From a58f231018bcd8162bb2662c7234ddefd0998a98 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sami=20Kalliom=C3=A4ki?= Date: Mon, 2 Oct 2017 13:12:17 +0200 Subject: [PATCH] Fix a crash in HardwareVideoDecoder on reinitialization. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Do not post releasing the texture output buffer. Bug: webrtc:7760 Change-Id: Ie4d7165a24c791a406be75688c814e2b9d9cde8f Reviewed-on: https://webrtc-review.googlesource.com/5440 Commit-Queue: Sami Kalliomäki Reviewed-by: Magnus Jedvert Cr-Commit-Position: refs/heads/master@{#20072} --- .../java/org/webrtc/HardwareVideoDecoder.java | 43 ++++++++++++------- 1 file changed, 28 insertions(+), 15 deletions(-) diff --git a/sdk/android/src/java/org/webrtc/HardwareVideoDecoder.java b/sdk/android/src/java/org/webrtc/HardwareVideoDecoder.java index 7f7d5383b4..2330dd83d5 100644 --- a/sdk/android/src/java/org/webrtc/HardwareVideoDecoder.java +++ b/sdk/android/src/java/org/webrtc/HardwareVideoDecoder.java @@ -125,8 +125,8 @@ class HardwareVideoDecoder } } - // Metadata for the last frame rendered to the texture. Only accessed on the texture helper's - // thread. + // Metadata for the last frame rendered to the texture. + private Object renderedTextureMetadataLock = new Object(); private DecodedTextureMetadata renderedTextureMetadata; // Decoding proceeds asynchronously. This callback returns decoded frames to the caller. Valid @@ -320,6 +320,9 @@ class HardwareVideoDecoder surfaceTextureHelper.dispose(); surfaceTextureHelper = null; } + synchronized (renderedTextureMetadataLock) { + renderedTextureMetadata = null; + } callback = null; frameInfos.clear(); return status; @@ -424,25 +427,35 @@ class HardwareVideoDecoder height = this.height; } - surfaceTextureHelper.getHandler().post(new Runnable() { - @Override - public void run() { - renderedTextureMetadata = new DecodedTextureMetadata( - width, height, rotation, info.presentationTimeUs, decodeTimeMs); - codec.releaseOutputBuffer(index, true); + synchronized (renderedTextureMetadataLock) { + if (renderedTextureMetadata != null) { + return; // We are still waiting for texture for the previous frame, drop this one. } - }); + renderedTextureMetadata = new DecodedTextureMetadata( + width, height, rotation, info.presentationTimeUs, decodeTimeMs); + codec.releaseOutputBuffer(index, true); + } } @Override public void onTextureFrameAvailable(int oesTextureId, float[] transformMatrix, long timestampNs) { - VideoFrame.TextureBuffer oesBuffer = surfaceTextureHelper.createTextureBuffer( - renderedTextureMetadata.width, renderedTextureMetadata.height, - RendererCommon.convertMatrixToAndroidGraphicsMatrix(transformMatrix)); + final VideoFrame frame; + final int decodeTimeMs; + synchronized (renderedTextureMetadataLock) { + if (renderedTextureMetadata == null) { + throw new IllegalStateException( + "Rendered texture metadata was null in onTextureFrameAvailable."); + } + VideoFrame.TextureBuffer oesBuffer = surfaceTextureHelper.createTextureBuffer( + renderedTextureMetadata.width, renderedTextureMetadata.height, + RendererCommon.convertMatrixToAndroidGraphicsMatrix(transformMatrix)); + frame = new VideoFrame(oesBuffer, renderedTextureMetadata.rotation, + renderedTextureMetadata.presentationTimestampUs * 1000); + decodeTimeMs = renderedTextureMetadata.decodeTimeMs; + renderedTextureMetadata = null; + } - VideoFrame frame = new VideoFrame(oesBuffer, renderedTextureMetadata.rotation, - renderedTextureMetadata.presentationTimestampUs * 1000); - callback.onDecodedFrame(frame, renderedTextureMetadata.decodeTimeMs, null /* qp */); + callback.onDecodedFrame(frame, decodeTimeMs, null /* qp */); frame.release(); }