Write to file on a dedicated thread in VideoFileRenderer.

The disk cannot always keep up to with the frames produced. To solve
this, write to disk on a dedicated thread so we don't block rendering.

Bug: b/80409365
Change-Id: If9ef3eb6948d81deebb987420599fef446b082d6
Reviewed-on: https://webrtc-review.googlesource.com/79800
Reviewed-by: Paulina Hensman <phensman@webrtc.org>
Commit-Queue: Sami Kalliomäki <sakal@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#23483}
This commit is contained in:
Sami Kalliomäki 2018-05-30 09:24:19 +02:00 committed by Commit Bot
parent d45b345700
commit aa35aeaa66

View file

@ -29,6 +29,8 @@ public class VideoFileRenderer implements VideoSink {
private final HandlerThread renderThread;
private final Handler renderThreadHandler;
private final HandlerThread fileThread;
private final Handler fileThreadHandler;
private final FileOutputStream videoOutFile;
private final String outputFileName;
private final int outputFileWidth;
@ -57,10 +59,14 @@ public class VideoFileRenderer implements VideoSink {
("YUV4MPEG2 C420 W" + outputFileWidth + " H" + outputFileHeight + " Ip F30:1 A1:1\n")
.getBytes(Charset.forName("US-ASCII")));
renderThread = new HandlerThread(TAG);
renderThread = new HandlerThread(TAG + "RenderThread");
renderThread.start();
renderThreadHandler = new Handler(renderThread.getLooper());
fileThread = new HandlerThread(TAG + "FileThread");
fileThread.start();
fileThreadHandler = new Handler(fileThread.getLooper());
ThreadUtils.invokeAtFrontUninterruptibly(renderThreadHandler, new Runnable() {
@Override
public void run() {
@ -108,6 +114,7 @@ public class VideoFileRenderer implements VideoSink {
final VideoFrame.I420Buffer i420 = scaledBuffer.toI420();
scaledBuffer.release();
fileThreadHandler.post(() -> {
YuvHelper.I420Rotate(i420.getDataY(), i420.getStrideY(), i420.getDataU(), i420.getStrideU(),
i420.getDataV(), i420.getStrideV(), outputFrameBuffer, i420.getWidth(), i420.getHeight(),
frame.getRotation());
@ -121,6 +128,7 @@ public class VideoFileRenderer implements VideoSink {
throw new RuntimeException("Error writing video to disk", e);
}
frameCount++;
});
}
/**
@ -135,14 +143,23 @@ public class VideoFileRenderer implements VideoSink {
cleanupBarrier.countDown();
});
ThreadUtils.awaitUninterruptibly(cleanupBarrier);
fileThreadHandler.post(() -> {
try {
videoOutFile.close();
Logging.d(TAG,
"Video written to disk as " + outputFileName + ". The number of frames is " + frameCount
+ " and the dimensions of the frames are " + outputFileWidth + "x" + outputFileHeight
+ ".");
+ " and the dimensions of the frames are " + outputFileWidth + "x"
+ outputFileHeight + ".");
} catch (IOException e) {
throw new RuntimeException("Error closing output file", e);
}
fileThread.quit();
});
try {
fileThread.join();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
Logging.e(TAG, "Interrupted while waiting for the write to disk to complete.", e);
}
}
}