diff --git a/sdk/android/api/org/webrtc/FileVideoCapturer.java b/sdk/android/api/org/webrtc/FileVideoCapturer.java index 88a0d30090..4efed36a5f 100644 --- a/sdk/android/api/org/webrtc/FileVideoCapturer.java +++ b/sdk/android/api/org/webrtc/FileVideoCapturer.java @@ -15,6 +15,7 @@ import android.os.SystemClock; import java.io.IOException; import java.io.RandomAccessFile; import java.nio.ByteBuffer; +import java.nio.channels.FileChannel; import java.nio.charset.Charset; import java.util.Timer; import java.util.TimerTask; @@ -33,18 +34,21 @@ public class FileVideoCapturer implements VideoCapturer { private static class VideoReaderY4M implements VideoReader { private static final String TAG = "VideoReaderY4M"; private static final String Y4M_FRAME_DELIMETER = "FRAME"; + private static final int FRAME_DELIMETER_LENGTH = Y4M_FRAME_DELIMETER.length() + 1; private final int frameWidth; private final int frameHeight; // First char after header private final long videoStart; - private final RandomAccessFile mediaFileStream; + private final RandomAccessFile mediaFile; + private final FileChannel mediaFileChannel; public VideoReaderY4M(String file) throws IOException { - mediaFileStream = new RandomAccessFile(file, "r"); + mediaFile = new RandomAccessFile(file, "r"); + mediaFileChannel = mediaFile.getChannel(); StringBuilder builder = new StringBuilder(); for (;;) { - int c = mediaFileStream.read(); + int c = mediaFile.read(); if (c == -1) { // End of file reached. throw new RuntimeException("Found end of file before end of header for file: " + file); @@ -55,7 +59,7 @@ public class FileVideoCapturer implements VideoCapturer { } builder.append((char) c); } - videoStart = mediaFileStream.getFilePointer(); + videoStart = mediaFileChannel.position(); String header = builder.toString(); String[] headerTokens = header.split("[ ]"); int w = 0; @@ -101,24 +105,24 @@ public class FileVideoCapturer implements VideoCapturer { final int sizeV = chromaHeight * buffer.getStrideV(); try { - byte[] frameDelim = new byte[Y4M_FRAME_DELIMETER.length() + 1]; - if (mediaFileStream.read(frameDelim) < frameDelim.length) { + ByteBuffer frameDelim = ByteBuffer.allocate(FRAME_DELIMETER_LENGTH); + if (mediaFileChannel.read(frameDelim) < FRAME_DELIMETER_LENGTH) { // We reach end of file, loop - mediaFileStream.seek(videoStart); - if (mediaFileStream.read(frameDelim) < frameDelim.length) { + mediaFileChannel.position(videoStart); + if (mediaFileChannel.read(frameDelim) < FRAME_DELIMETER_LENGTH) { throw new RuntimeException("Error looping video"); } } - String frameDelimStr = new String(frameDelim, Charset.forName("US-ASCII")); + String frameDelimStr = new String(frameDelim.array(), Charset.forName("US-ASCII")); if (!frameDelimStr.equals(Y4M_FRAME_DELIMETER + "\n")) { throw new RuntimeException( "Frames should be delimited by FRAME plus newline, found delimter was: '" + frameDelimStr + "'"); } - mediaFileStream.readFully(dataY.array(), dataY.arrayOffset(), sizeY); - mediaFileStream.readFully(dataU.array(), dataU.arrayOffset(), sizeU); - mediaFileStream.readFully(dataV.array(), dataV.arrayOffset(), sizeV); + mediaFileChannel.read(dataY); + mediaFileChannel.read(dataU); + mediaFileChannel.read(dataV); } catch (IOException e) { throw new RuntimeException(e); } @@ -129,7 +133,8 @@ public class FileVideoCapturer implements VideoCapturer { @Override public void close() { try { - mediaFileStream.close(); + // Closing a file also closes the channel. + mediaFile.close(); } catch (IOException e) { Logging.e(TAG, "Problem closing file", e); } diff --git a/sdk/android/api/org/webrtc/JavaI420Buffer.java b/sdk/android/api/org/webrtc/JavaI420Buffer.java index 13ed63bf18..3498faf50e 100644 --- a/sdk/android/api/org/webrtc/JavaI420Buffer.java +++ b/sdk/android/api/org/webrtc/JavaI420Buffer.java @@ -85,7 +85,8 @@ public class JavaI420Buffer implements VideoFrame.I420Buffer { int uPos = yPos + width * height; int vPos = uPos + strideUV * chromaHeight; - ByteBuffer buffer = ByteBuffer.allocateDirect(width * height + 2 * strideUV * chromaHeight); + ByteBuffer buffer = + JniCommon.nativeAllocateByteBuffer(width * height + 2 * strideUV * chromaHeight); buffer.position(yPos); buffer.limit(uPos); @@ -99,8 +100,8 @@ public class JavaI420Buffer implements VideoFrame.I420Buffer { buffer.limit(vPos + strideUV * chromaHeight); ByteBuffer dataV = buffer.slice(); - return new JavaI420Buffer( - width, height, dataY, width, dataU, strideUV, dataV, strideUV, null /* releaseCallback */); + return new JavaI420Buffer(width, height, dataY, width, dataU, strideUV, dataV, strideUV, + () -> { JniCommon.nativeFreeByteBuffer(buffer); }); } @Override diff --git a/sdk/android/instrumentationtests/src/org/webrtc/FileVideoCapturerTest.java b/sdk/android/instrumentationtests/src/org/webrtc/FileVideoCapturerTest.java index a572b7e91f..667a343745 100644 --- a/sdk/android/instrumentationtests/src/org/webrtc/FileVideoCapturerTest.java +++ b/sdk/android/instrumentationtests/src/org/webrtc/FileVideoCapturerTest.java @@ -21,6 +21,7 @@ import java.nio.charset.Charset; import java.util.ArrayList; import java.util.Arrays; import org.chromium.base.test.BaseJUnit4ClassRunner; +import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -58,6 +59,11 @@ public class FileVideoCapturerTest { } } + @Before + public void setUp() { + NativeLibrary.initialize(new NativeLibrary.DefaultLoader()); + } + @Test @SmallTest public void testVideoCaptureFromFile() throws InterruptedException, IOException { diff --git a/sdk/android/instrumentationtests/src/org/webrtc/HardwareVideoDecoderTest.java b/sdk/android/instrumentationtests/src/org/webrtc/HardwareVideoDecoderTest.java index f680102a7c..09a8275fc1 100644 --- a/sdk/android/instrumentationtests/src/org/webrtc/HardwareVideoDecoderTest.java +++ b/sdk/android/instrumentationtests/src/org/webrtc/HardwareVideoDecoderTest.java @@ -59,7 +59,7 @@ public final class HardwareVideoDecoderTest { private static final int TEST_FRAME_COUNT = 10; private static final int TEST_FRAME_WIDTH = 640; private static final int TEST_FRAME_HEIGHT = 360; - private static final VideoFrame.I420Buffer[] TEST_FRAMES = generateTestFrames(); + private VideoFrame.I420Buffer[] TEST_FRAMES; private static final boolean ENABLE_INTEL_VP8_ENCODER = true; private static final boolean ENABLE_H264_HIGH_PROFILE = true; @@ -150,6 +150,8 @@ public final class HardwareVideoDecoderTest { public void setUp() { NativeLibrary.initialize(new NativeLibrary.DefaultLoader()); + TEST_FRAMES = generateTestFrames(); + eglBase = new EglBase14(null, EglBase.CONFIG_PLAIN); eglBase.createDummyPbufferSurface(); eglBase.makeCurrent(); diff --git a/sdk/android/instrumentationtests/src/org/webrtc/HardwareVideoEncoderTest.java b/sdk/android/instrumentationtests/src/org/webrtc/HardwareVideoEncoderTest.java index 2c45a4f16b..ef0be1427f 100644 --- a/sdk/android/instrumentationtests/src/org/webrtc/HardwareVideoEncoderTest.java +++ b/sdk/android/instrumentationtests/src/org/webrtc/HardwareVideoEncoderTest.java @@ -211,7 +211,6 @@ public class HardwareVideoEncoderTest { public MockI420Buffer(int width, int height, Runnable releaseCallback) { super(width, height, releaseCallback); - // We never release this but it is not a problem in practice because the release is a no-op. realBuffer = JavaI420Buffer.allocate(width, height); } @@ -251,6 +250,18 @@ public class HardwareVideoEncoderTest { return this; } + @Override + public void retain() { + super.retain(); + realBuffer.retain(); + } + + @Override + public void release() { + super.release(); + realBuffer.release(); + } + @Override public VideoFrame.Buffer cropAndScale( int cropX, int cropY, int cropWidth, int cropHeight, int scaleWidth, int scaleHeight) {