From 0909446133e50e5bc111afe6a93ea8a7cb40d828 Mon Sep 17 00:00:00 2001 From: eguven Date: Thu, 21 Jul 2016 11:14:43 -0700 Subject: [PATCH] Don't let renderer input buffer get too big if codec not available. ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=128082468 --- .../ext/vp9/LibvpxVideoRenderer.java | 73 ++++++++++++------- .../android/exoplayer2/BaseRenderer.java | 9 +++ .../mediacodec/MediaCodecRenderer.java | 2 + .../source/ExtractorMediaSource.java | 5 ++ .../exoplayer2/source/SampleStream.java | 7 ++ .../source/SingleSampleMediaSource.java | 5 ++ .../source/chunk/ChunkSampleStream.java | 5 ++ .../source/hls/HlsSampleStreamWrapper.java | 5 ++ .../video/MediaCodecVideoRenderer.java | 2 +- 9 files changed, 85 insertions(+), 28 deletions(-) diff --git a/extensions/vp9/src/main/java/com/google/android/exoplayer2/ext/vp9/LibvpxVideoRenderer.java b/extensions/vp9/src/main/java/com/google/android/exoplayer2/ext/vp9/LibvpxVideoRenderer.java index 68bc2e9a2b..da8a868475 100644 --- a/extensions/vp9/src/main/java/com/google/android/exoplayer2/ext/vp9/LibvpxVideoRenderer.java +++ b/extensions/vp9/src/main/java/com/google/android/exoplayer2/ext/vp9/LibvpxVideoRenderer.java @@ -157,25 +157,29 @@ public final class LibvpxVideoRenderer extends BaseRenderer { return; } - try { - if (decoder == null) { - // If we don't have a decoder yet, we need to instantiate one. - long codecInitializingTimestamp = SystemClock.elapsedRealtime(); - TraceUtil.beginSection("createVpxDecoder"); - decoder = new VpxDecoder(NUM_BUFFERS, NUM_BUFFERS, INITIAL_INPUT_BUFFER_SIZE); - decoder.setOutputMode(outputMode); + if (isRendererAvailable()) { + try { + if (decoder == null) { + // If we don't have a decoder yet, we need to instantiate one. + long codecInitializingTimestamp = SystemClock.elapsedRealtime(); + TraceUtil.beginSection("createVpxDecoder"); + decoder = new VpxDecoder(NUM_BUFFERS, NUM_BUFFERS, INITIAL_INPUT_BUFFER_SIZE); + decoder.setOutputMode(outputMode); + TraceUtil.endSection(); + long codecInitializedTimestamp = SystemClock.elapsedRealtime(); + eventDispatcher.decoderInitialized(decoder.getName(), codecInitializedTimestamp, + codecInitializedTimestamp - codecInitializingTimestamp); + decoderCounters.codecInitCount++; + } + TraceUtil.beginSection("drainAndFeed"); + while (drainOutputBuffer(positionUs)) {} + while (feedInputBuffer()) {} TraceUtil.endSection(); - long codecInitializedTimestamp = SystemClock.elapsedRealtime(); - eventDispatcher.decoderInitialized(decoder.getName(), codecInitializedTimestamp, - codecInitializedTimestamp - codecInitializingTimestamp); - decoderCounters.codecInitCount++; + } catch (VpxDecoderException e) { + throw ExoPlaybackException.createForRenderer(e, getIndex()); } - TraceUtil.beginSection("drainAndFeed"); - while (drainOutputBuffer(positionUs)) {} - while (feedInputBuffer()) {} - TraceUtil.endSection(); - } catch (VpxDecoderException e) { - throw ExoPlaybackException.createForRenderer(e, getIndex()); + } else { + skipToKeyframeBefore(positionUs); } decoderCounters.ensureUpdated(); } @@ -331,7 +335,8 @@ public final class LibvpxVideoRenderer extends BaseRenderer { @Override public boolean isReady() { - if (format != null && (isSourceReady() || outputBuffer != null) && renderedFirstFrame) { + if (format != null && (isSourceReady() || outputBuffer != null) + && (renderedFirstFrame || !isRendererAvailable())) { // Ready. If we were joining then we've now joined, so clear the joining deadline. joiningDeadlineMs = -1; return true; @@ -385,17 +390,21 @@ public final class LibvpxVideoRenderer extends BaseRenderer { outputBuffer = null; format = null; try { - if (decoder != null) { - decoder.release(); - decoder = null; - decoderCounters.codecReleaseCount++; - } + releaseDecoder(); } finally { decoderCounters.ensureUpdated(); eventDispatcher.disabled(decoderCounters); } } + private void releaseDecoder() { + if (decoder != null) { + decoder.release(); + decoder = null; + decoderCounters.codecReleaseCount++; + } + } + private boolean readFormat() { int result = readSource(formatHolder, null); if (result == C.RESULT_FORMAT_READ) { @@ -428,9 +437,7 @@ public final class LibvpxVideoRenderer extends BaseRenderer { this.surface = surface; outputBufferRenderer = null; outputMode = (surface != null) ? VpxDecoder.OUTPUT_MODE_RGB : VpxDecoder.OUTPUT_MODE_NONE; - if (decoder != null) { - decoder.setOutputMode(outputMode); - } + updateDecoder(); drawnToSurface = false; } @@ -442,11 +449,23 @@ public final class LibvpxVideoRenderer extends BaseRenderer { surface = null; outputMode = (outputBufferRenderer != null) ? VpxDecoder.OUTPUT_MODE_YUV : VpxDecoder.OUTPUT_MODE_NONE; + updateDecoder(); + } + + private void updateDecoder() { if (decoder != null) { - decoder.setOutputMode(outputMode); + if (outputMode == VpxDecoder.OUTPUT_MODE_NONE) { + releaseDecoder(); + } else { + decoder.setOutputMode(outputMode); + } } } + private boolean isRendererAvailable() { + return surface != null || outputBufferRenderer != null; + } + private void maybeNotifyVideoSizeChanged(final int width, final int height) { if (previousWidth != width || previousHeight != height) { previousWidth = width; diff --git a/library/src/main/java/com/google/android/exoplayer2/BaseRenderer.java b/library/src/main/java/com/google/android/exoplayer2/BaseRenderer.java index fe1e0837c4..96051cd746 100644 --- a/library/src/main/java/com/google/android/exoplayer2/BaseRenderer.java +++ b/library/src/main/java/com/google/android/exoplayer2/BaseRenderer.java @@ -263,4 +263,13 @@ public abstract class BaseRenderer implements Renderer, RendererCapabilities { return readEndOfStream ? streamIsFinal : stream.isReady(); } + /** + * Attempts to skip to the keyframe before the specified time. + * + * @param timeUs The specified time. + */ + protected void skipToKeyframeBefore(long timeUs) { + stream.skipToKeyframeBefore(timeUs); + } + } diff --git a/library/src/main/java/com/google/android/exoplayer2/mediacodec/MediaCodecRenderer.java b/library/src/main/java/com/google/android/exoplayer2/mediacodec/MediaCodecRenderer.java index 4f91c966e3..fbd3883071 100644 --- a/library/src/main/java/com/google/android/exoplayer2/mediacodec/MediaCodecRenderer.java +++ b/library/src/main/java/com/google/android/exoplayer2/mediacodec/MediaCodecRenderer.java @@ -477,6 +477,8 @@ public abstract class MediaCodecRenderer extends BaseRenderer { while (drainOutputBuffer(positionUs, elapsedRealtimeUs)) {} while (feedInputBuffer()) {} TraceUtil.endSection(); + } else if (format != null) { + skipToKeyframeBefore(positionUs); } decoderCounters.ensureUpdated(); } diff --git a/library/src/main/java/com/google/android/exoplayer2/source/ExtractorMediaSource.java b/library/src/main/java/com/google/android/exoplayer2/source/ExtractorMediaSource.java index 738671efb0..0928173645 100644 --- a/library/src/main/java/com/google/android/exoplayer2/source/ExtractorMediaSource.java +++ b/library/src/main/java/com/google/android/exoplayer2/source/ExtractorMediaSource.java @@ -610,6 +610,11 @@ public final class ExtractorMediaSource implements MediaPeriod, MediaSource, return ExtractorMediaSource.this.readData(track, formatHolder, buffer); } + @Override + public void skipToKeyframeBefore(long timeUs) { + sampleQueues[track].skipToKeyframeBefore(timeUs); + } + } /** diff --git a/library/src/main/java/com/google/android/exoplayer2/source/SampleStream.java b/library/src/main/java/com/google/android/exoplayer2/source/SampleStream.java index f539b44942..c385de73a8 100644 --- a/library/src/main/java/com/google/android/exoplayer2/source/SampleStream.java +++ b/library/src/main/java/com/google/android/exoplayer2/source/SampleStream.java @@ -55,4 +55,11 @@ public interface SampleStream { */ int readData(FormatHolder formatHolder, DecoderInputBuffer buffer); + /** + * Attempts to skip to the keyframe before the specified time. + * + * @param timeUs The specified time. + */ + void skipToKeyframeBefore(long timeUs); + } diff --git a/library/src/main/java/com/google/android/exoplayer2/source/SingleSampleMediaSource.java b/library/src/main/java/com/google/android/exoplayer2/source/SingleSampleMediaSource.java index beca9dc831..ca9526c4f3 100644 --- a/library/src/main/java/com/google/android/exoplayer2/source/SingleSampleMediaSource.java +++ b/library/src/main/java/com/google/android/exoplayer2/source/SingleSampleMediaSource.java @@ -253,6 +253,11 @@ public final class SingleSampleMediaSource implements MediaPeriod, MediaSource, } } + @Override + public void skipToKeyframeBefore(long timeUs) { + // do nothing + } + // Loader.Callback implementation. @Override diff --git a/library/src/main/java/com/google/android/exoplayer2/source/chunk/ChunkSampleStream.java b/library/src/main/java/com/google/android/exoplayer2/source/chunk/ChunkSampleStream.java index bfec990f35..e48a98f11f 100644 --- a/library/src/main/java/com/google/android/exoplayer2/source/chunk/ChunkSampleStream.java +++ b/library/src/main/java/com/google/android/exoplayer2/source/chunk/ChunkSampleStream.java @@ -192,6 +192,11 @@ public class ChunkSampleStream implements SampleStream, S return sampleQueue.readData(formatHolder, buffer, loadingFinished, lastSeekPositionUs); } + @Override + public void skipToKeyframeBefore(long timeUs) { + sampleQueue.skipToKeyframeBefore(timeUs); + } + // Loader.Callback implementation. @Override diff --git a/library/src/main/java/com/google/android/exoplayer2/source/hls/HlsSampleStreamWrapper.java b/library/src/main/java/com/google/android/exoplayer2/source/hls/HlsSampleStreamWrapper.java index 871e12a2fc..bbce69708b 100644 --- a/library/src/main/java/com/google/android/exoplayer2/source/hls/HlsSampleStreamWrapper.java +++ b/library/src/main/java/com/google/android/exoplayer2/source/hls/HlsSampleStreamWrapper.java @@ -619,6 +619,11 @@ import java.util.List; return HlsSampleStreamWrapper.this.readData(group, formatHolder, buffer); } + @Override + public void skipToKeyframeBefore(long timeUs) { + sampleQueues.valueAt(group).skipToKeyframeBefore(timeUs); + } + } } diff --git a/library/src/main/java/com/google/android/exoplayer2/video/MediaCodecVideoRenderer.java b/library/src/main/java/com/google/android/exoplayer2/video/MediaCodecVideoRenderer.java index ba9dd7d1ef..9a8c21116f 100644 --- a/library/src/main/java/com/google/android/exoplayer2/video/MediaCodecVideoRenderer.java +++ b/library/src/main/java/com/google/android/exoplayer2/video/MediaCodecVideoRenderer.java @@ -240,7 +240,7 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer { @Override public boolean isReady() { - if (renderedFirstFrame && super.isReady()) { + if ((renderedFirstFrame || super.shouldInitCodec()) && super.isReady()) { // Ready. If we were joining then we've now joined, so clear the joining deadline. joiningDeadlineMs = -1; return true;