Commit 09094461 by eguven Committed by Oliver Woodman

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
parent 68156ac7
...@@ -157,25 +157,29 @@ public final class LibvpxVideoRenderer extends BaseRenderer { ...@@ -157,25 +157,29 @@ public final class LibvpxVideoRenderer extends BaseRenderer {
return; return;
} }
try { if (isRendererAvailable()) {
if (decoder == null) { try {
// If we don't have a decoder yet, we need to instantiate one. if (decoder == null) {
long codecInitializingTimestamp = SystemClock.elapsedRealtime(); // If we don't have a decoder yet, we need to instantiate one.
TraceUtil.beginSection("createVpxDecoder"); long codecInitializingTimestamp = SystemClock.elapsedRealtime();
decoder = new VpxDecoder(NUM_BUFFERS, NUM_BUFFERS, INITIAL_INPUT_BUFFER_SIZE); TraceUtil.beginSection("createVpxDecoder");
decoder.setOutputMode(outputMode); 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(); TraceUtil.endSection();
long codecInitializedTimestamp = SystemClock.elapsedRealtime(); } catch (VpxDecoderException e) {
eventDispatcher.decoderInitialized(decoder.getName(), codecInitializedTimestamp, throw ExoPlaybackException.createForRenderer(e, getIndex());
codecInitializedTimestamp - codecInitializingTimestamp);
decoderCounters.codecInitCount++;
} }
TraceUtil.beginSection("drainAndFeed"); } else {
while (drainOutputBuffer(positionUs)) {} skipToKeyframeBefore(positionUs);
while (feedInputBuffer()) {}
TraceUtil.endSection();
} catch (VpxDecoderException e) {
throw ExoPlaybackException.createForRenderer(e, getIndex());
} }
decoderCounters.ensureUpdated(); decoderCounters.ensureUpdated();
} }
...@@ -331,7 +335,8 @@ public final class LibvpxVideoRenderer extends BaseRenderer { ...@@ -331,7 +335,8 @@ public final class LibvpxVideoRenderer extends BaseRenderer {
@Override @Override
public boolean isReady() { 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. // Ready. If we were joining then we've now joined, so clear the joining deadline.
joiningDeadlineMs = -1; joiningDeadlineMs = -1;
return true; return true;
...@@ -385,17 +390,21 @@ public final class LibvpxVideoRenderer extends BaseRenderer { ...@@ -385,17 +390,21 @@ public final class LibvpxVideoRenderer extends BaseRenderer {
outputBuffer = null; outputBuffer = null;
format = null; format = null;
try { try {
if (decoder != null) { releaseDecoder();
decoder.release();
decoder = null;
decoderCounters.codecReleaseCount++;
}
} finally { } finally {
decoderCounters.ensureUpdated(); decoderCounters.ensureUpdated();
eventDispatcher.disabled(decoderCounters); eventDispatcher.disabled(decoderCounters);
} }
} }
private void releaseDecoder() {
if (decoder != null) {
decoder.release();
decoder = null;
decoderCounters.codecReleaseCount++;
}
}
private boolean readFormat() { private boolean readFormat() {
int result = readSource(formatHolder, null); int result = readSource(formatHolder, null);
if (result == C.RESULT_FORMAT_READ) { if (result == C.RESULT_FORMAT_READ) {
...@@ -428,9 +437,7 @@ public final class LibvpxVideoRenderer extends BaseRenderer { ...@@ -428,9 +437,7 @@ public final class LibvpxVideoRenderer extends BaseRenderer {
this.surface = surface; this.surface = surface;
outputBufferRenderer = null; outputBufferRenderer = null;
outputMode = (surface != null) ? VpxDecoder.OUTPUT_MODE_RGB : VpxDecoder.OUTPUT_MODE_NONE; outputMode = (surface != null) ? VpxDecoder.OUTPUT_MODE_RGB : VpxDecoder.OUTPUT_MODE_NONE;
if (decoder != null) { updateDecoder();
decoder.setOutputMode(outputMode);
}
drawnToSurface = false; drawnToSurface = false;
} }
...@@ -442,11 +449,23 @@ public final class LibvpxVideoRenderer extends BaseRenderer { ...@@ -442,11 +449,23 @@ public final class LibvpxVideoRenderer extends BaseRenderer {
surface = null; surface = null;
outputMode = (outputBufferRenderer != null) ? VpxDecoder.OUTPUT_MODE_YUV outputMode = (outputBufferRenderer != null) ? VpxDecoder.OUTPUT_MODE_YUV
: VpxDecoder.OUTPUT_MODE_NONE; : VpxDecoder.OUTPUT_MODE_NONE;
updateDecoder();
}
private void updateDecoder() {
if (decoder != null) { 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) { private void maybeNotifyVideoSizeChanged(final int width, final int height) {
if (previousWidth != width || previousHeight != height) { if (previousWidth != width || previousHeight != height) {
previousWidth = width; previousWidth = width;
......
...@@ -263,4 +263,13 @@ public abstract class BaseRenderer implements Renderer, RendererCapabilities { ...@@ -263,4 +263,13 @@ public abstract class BaseRenderer implements Renderer, RendererCapabilities {
return readEndOfStream ? streamIsFinal : stream.isReady(); 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);
}
} }
...@@ -477,6 +477,8 @@ public abstract class MediaCodecRenderer extends BaseRenderer { ...@@ -477,6 +477,8 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
while (drainOutputBuffer(positionUs, elapsedRealtimeUs)) {} while (drainOutputBuffer(positionUs, elapsedRealtimeUs)) {}
while (feedInputBuffer()) {} while (feedInputBuffer()) {}
TraceUtil.endSection(); TraceUtil.endSection();
} else if (format != null) {
skipToKeyframeBefore(positionUs);
} }
decoderCounters.ensureUpdated(); decoderCounters.ensureUpdated();
} }
......
...@@ -610,6 +610,11 @@ public final class ExtractorMediaSource implements MediaPeriod, MediaSource, ...@@ -610,6 +610,11 @@ public final class ExtractorMediaSource implements MediaPeriod, MediaSource,
return ExtractorMediaSource.this.readData(track, formatHolder, buffer); return ExtractorMediaSource.this.readData(track, formatHolder, buffer);
} }
@Override
public void skipToKeyframeBefore(long timeUs) {
sampleQueues[track].skipToKeyframeBefore(timeUs);
}
} }
/** /**
......
...@@ -55,4 +55,11 @@ public interface SampleStream { ...@@ -55,4 +55,11 @@ public interface SampleStream {
*/ */
int readData(FormatHolder formatHolder, DecoderInputBuffer buffer); 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);
} }
...@@ -253,6 +253,11 @@ public final class SingleSampleMediaSource implements MediaPeriod, MediaSource, ...@@ -253,6 +253,11 @@ public final class SingleSampleMediaSource implements MediaPeriod, MediaSource,
} }
} }
@Override
public void skipToKeyframeBefore(long timeUs) {
// do nothing
}
// Loader.Callback implementation. // Loader.Callback implementation.
@Override @Override
......
...@@ -192,6 +192,11 @@ public class ChunkSampleStream<T extends ChunkSource> implements SampleStream, S ...@@ -192,6 +192,11 @@ public class ChunkSampleStream<T extends ChunkSource> implements SampleStream, S
return sampleQueue.readData(formatHolder, buffer, loadingFinished, lastSeekPositionUs); return sampleQueue.readData(formatHolder, buffer, loadingFinished, lastSeekPositionUs);
} }
@Override
public void skipToKeyframeBefore(long timeUs) {
sampleQueue.skipToKeyframeBefore(timeUs);
}
// Loader.Callback implementation. // Loader.Callback implementation.
@Override @Override
......
...@@ -619,6 +619,11 @@ import java.util.List; ...@@ -619,6 +619,11 @@ import java.util.List;
return HlsSampleStreamWrapper.this.readData(group, formatHolder, buffer); return HlsSampleStreamWrapper.this.readData(group, formatHolder, buffer);
} }
@Override
public void skipToKeyframeBefore(long timeUs) {
sampleQueues.valueAt(group).skipToKeyframeBefore(timeUs);
}
} }
} }
...@@ -240,7 +240,7 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer { ...@@ -240,7 +240,7 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer {
@Override @Override
public boolean isReady() { 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. // Ready. If we were joining then we've now joined, so clear the joining deadline.
joiningDeadlineMs = -1; joiningDeadlineMs = -1;
return true; return true;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment