| Index: webrtc/sdk/android/api/org/webrtc/VideoFileRenderer.java
|
| diff --git a/webrtc/sdk/android/api/org/webrtc/VideoFileRenderer.java b/webrtc/sdk/android/api/org/webrtc/VideoFileRenderer.java
|
| index f4ffbcace8b6b7c7f90b7fc8f38d47505088657a..02a4a3fd0f37488434935c966d18b1b2f7158628 100644
|
| --- a/webrtc/sdk/android/api/org/webrtc/VideoFileRenderer.java
|
| +++ b/webrtc/sdk/android/api/org/webrtc/VideoFileRenderer.java
|
| @@ -16,6 +16,7 @@ import java.io.FileOutputStream;
|
| import java.io.IOException;
|
| import java.nio.ByteBuffer;
|
| import java.util.concurrent.CountDownLatch;
|
| +import java.util.ArrayList;
|
|
|
| /**
|
| * Can be used to save the video frames to file.
|
| @@ -27,12 +28,14 @@ public class VideoFileRenderer implements VideoRenderer.Callbacks {
|
| private final Object handlerLock = new Object();
|
| private final Handler renderThreadHandler;
|
| private final FileOutputStream videoOutFile;
|
| + private final String outputFileName;
|
| private final int outputFileWidth;
|
| private final int outputFileHeight;
|
| private final int outputFrameSize;
|
| private final ByteBuffer outputFrameBuffer;
|
| private EglBase eglBase;
|
| private YuvConverter yuvConverter;
|
| + private ArrayList<ByteBuffer> rawFrames = new ArrayList<>();
|
|
|
| public VideoFileRenderer(String outputFile, int outputFileWidth, int outputFileHeight,
|
| final EglBase.Context sharedContext) throws IOException {
|
| @@ -40,6 +43,7 @@ public class VideoFileRenderer implements VideoRenderer.Callbacks {
|
| throw new IllegalArgumentException("Does not support uneven width or height");
|
| }
|
|
|
| + this.outputFileName = outputFile;
|
| this.outputFileWidth = outputFileWidth;
|
| this.outputFileHeight = outputFileHeight;
|
|
|
| @@ -86,7 +90,7 @@ public class VideoFileRenderer implements VideoRenderer.Callbacks {
|
| final float[] texMatrix = RendererCommon.multiplyMatrices(rotatedSamplingMatrix, layoutMatrix);
|
|
|
| try {
|
| - videoOutFile.write("FRAME\n".getBytes());
|
| + ByteBuffer buffer = nativeCreateNativeByteBuffer(outputFrameSize);
|
| if (!frame.yuvFrame) {
|
| yuvConverter.convert(outputFrameBuffer, outputFileWidth, outputFileHeight, outputFileWidth,
|
| frame.textureId, texMatrix);
|
| @@ -96,27 +100,26 @@ public class VideoFileRenderer implements VideoRenderer.Callbacks {
|
| int offset = outputFrameBuffer.arrayOffset();
|
|
|
| // Write Y
|
| - videoOutFile.write(data, offset, outputFileWidth * outputFileHeight);
|
| + buffer.put(data, offset, outputFileWidth * outputFileHeight);
|
|
|
| // Write U
|
| for (int r = outputFileHeight; r < outputFileHeight * 3 / 2; ++r) {
|
| - videoOutFile.write(data, offset + r * stride, stride / 2);
|
| + buffer.put(data, offset + r * stride, stride / 2);
|
| }
|
|
|
| // Write V
|
| for (int r = outputFileHeight; r < outputFileHeight * 3 / 2; ++r) {
|
| - videoOutFile.write(data, offset + r * stride + stride / 2, stride / 2);
|
| + buffer.put(data, offset + r * stride + stride / 2, stride / 2);
|
| }
|
| } else {
|
| nativeI420Scale(frame.yuvPlanes[0], frame.yuvStrides[0], frame.yuvPlanes[1],
|
| frame.yuvStrides[1], frame.yuvPlanes[2], frame.yuvStrides[2], frame.width, frame.height,
|
| outputFrameBuffer, outputFileWidth, outputFileHeight);
|
| - videoOutFile.write(
|
| - outputFrameBuffer.array(), outputFrameBuffer.arrayOffset(), outputFrameSize);
|
| +
|
| + buffer.put(outputFrameBuffer.array(), outputFrameBuffer.arrayOffset(), outputFrameSize);
|
| }
|
| - } catch (IOException e) {
|
| - Logging.e(TAG, "Failed to write to file for video out");
|
| - throw new RuntimeException(e);
|
| + buffer.rewind();
|
| + rawFrames.add(buffer);
|
| } finally {
|
| VideoRenderer.renderFrameDone(frame);
|
| }
|
| @@ -130,11 +133,6 @@ public class VideoFileRenderer implements VideoRenderer.Callbacks {
|
| renderThreadHandler.post(new Runnable() {
|
| @Override
|
| public void run() {
|
| - try {
|
| - videoOutFile.close();
|
| - } catch (IOException e) {
|
| - Logging.d(TAG, "Error closing output video file");
|
| - }
|
| yuvConverter.release();
|
| eglBase.release();
|
| renderThread.quit();
|
| @@ -142,9 +140,31 @@ public class VideoFileRenderer implements VideoRenderer.Callbacks {
|
| }
|
| });
|
| ThreadUtils.awaitUninterruptibly(cleanupBarrier);
|
| + try {
|
| + for (ByteBuffer buffer : rawFrames) {
|
| + videoOutFile.write("FRAME\n".getBytes());
|
| +
|
| + byte[] data = new byte[outputFrameSize];
|
| + buffer.get(data);
|
| +
|
| + videoOutFile.write(data);
|
| +
|
| + nativeFreeNativeByteBuffer(buffer);
|
| + }
|
| + videoOutFile.close();
|
| + Logging.d(TAG, "Video written to disk as " + outputFileName + ". Number frames are "
|
| + + rawFrames.size() + " and the dimension of the frames are " + outputFileWidth + "x"
|
| + + outputFileHeight + ".");
|
| + } catch (IOException e) {
|
| + Logging.e(TAG, "Error writing video to disk", e);
|
| + }
|
| }
|
|
|
| public static native void nativeI420Scale(ByteBuffer srcY, int strideY, ByteBuffer srcU,
|
| int strideU, ByteBuffer srcV, int strideV, int width, int height, ByteBuffer dst,
|
| int dstWidth, int dstHeight);
|
| +
|
| + public static native ByteBuffer nativeCreateNativeByteBuffer(int size);
|
| +
|
| + public static native void nativeFreeNativeByteBuffer(ByteBuffer buffer);
|
| }
|
|
|