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}
diff --git a/sdk/android/api/org/webrtc/VideoFileRenderer.java b/sdk/android/api/org/webrtc/VideoFileRenderer.java
index 92cdeb4..f886871 100644
--- a/sdk/android/api/org/webrtc/VideoFileRenderer.java
+++ b/sdk/android/api/org/webrtc/VideoFileRenderer.java
@@ -29,6 +29,8 @@
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 @@
("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,19 +114,21 @@
final VideoFrame.I420Buffer i420 = scaledBuffer.toI420();
scaledBuffer.release();
- YuvHelper.I420Rotate(i420.getDataY(), i420.getStrideY(), i420.getDataU(), i420.getStrideU(),
- i420.getDataV(), i420.getStrideV(), outputFrameBuffer, i420.getWidth(), i420.getHeight(),
- frame.getRotation());
- i420.release();
+ fileThreadHandler.post(() -> {
+ YuvHelper.I420Rotate(i420.getDataY(), i420.getStrideY(), i420.getDataU(), i420.getStrideU(),
+ i420.getDataV(), i420.getStrideV(), outputFrameBuffer, i420.getWidth(), i420.getHeight(),
+ frame.getRotation());
+ i420.release();
- try {
- videoOutFile.write("FRAME\n".getBytes(Charset.forName("US-ASCII")));
- videoOutFile.write(
- outputFrameBuffer.array(), outputFrameBuffer.arrayOffset(), outputFrameSize);
- } catch (IOException e) {
- throw new RuntimeException("Error writing video to disk", e);
- }
- frameCount++;
+ try {
+ videoOutFile.write("FRAME\n".getBytes(Charset.forName("US-ASCII")));
+ videoOutFile.write(
+ outputFrameBuffer.array(), outputFrameBuffer.arrayOffset(), outputFrameSize);
+ } catch (IOException e) {
+ throw new RuntimeException("Error writing video to disk", e);
+ }
+ frameCount++;
+ });
}
/**
@@ -135,14 +143,23 @@
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 + ".");
+ } catch (IOException e) {
+ throw new RuntimeException("Error closing output file", e);
+ }
+ fileThread.quit();
+ });
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
- + ".");
- } catch (IOException e) {
- throw new RuntimeException("Error closing output file", e);
+ fileThread.join();
+ } catch (InterruptedException e) {
+ Thread.currentThread().interrupt();
+ Logging.e(TAG, "Interrupted while waiting for the write to disk to complete.", e);
}
}
}