diff --git a/sdk/android/api/org/webrtc/VideoFileRenderer.java b/sdk/android/api/org/webrtc/VideoFileRenderer.java index 92cdeb4513..f88687150d 100644 --- a/sdk/android/api/org/webrtc/VideoFileRenderer.java +++ b/sdk/android/api/org/webrtc/VideoFileRenderer.java @@ -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,19 +114,21 @@ public class VideoFileRenderer implements VideoSink { 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 @@ 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 + "."); + } 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); } } }