Allow codec flushing without re-initialization
For decoder reuse, we want disable() to flush the decoder. However, if the flush needs to release the decoder for some reason, it seems non-ideal to immediately re-initialize it. Re-initialization can also throw ExoPlaybackException, which we don't want for disabling. This change allows a variant of flush that wont re-initialize the decoder if it has to be released, which will be used from disable(). Issue: #2826 ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=216834862
This commit is contained in:
parent
42c3ff3934
commit
842f622d29
@ -546,9 +546,7 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
|
|||||||
protected void onPositionReset(long positionUs, boolean joining) throws ExoPlaybackException {
|
protected void onPositionReset(long positionUs, boolean joining) throws ExoPlaybackException {
|
||||||
inputStreamEnded = false;
|
inputStreamEnded = false;
|
||||||
outputStreamEnded = false;
|
outputStreamEnded = false;
|
||||||
if (codec != null) {
|
flushOrReinitCodec();
|
||||||
flushCodec();
|
|
||||||
}
|
|
||||||
formatQueue.clear();
|
formatQueue.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -687,10 +685,36 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
|
|||||||
decoderCounters.ensureUpdated();
|
decoderCounters.ensureUpdated();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void flushCodec() throws ExoPlaybackException {
|
/**
|
||||||
|
* Flushes the codec. If flushing is not possible, the codec will be released and re-instantiated.
|
||||||
|
* This method is a no-op if the codec is {@code null}.
|
||||||
|
*
|
||||||
|
* <p>The implementation of this method calls {@link #flushOrReleaseCodec()}, and {@link
|
||||||
|
* #maybeInitCodec()} if the codec needs to be re-instantiated.
|
||||||
|
*
|
||||||
|
* @throws ExoPlaybackException If an error occurs re-instantiating the codec.
|
||||||
|
*/
|
||||||
|
protected final void flushOrReinitCodec() throws ExoPlaybackException {
|
||||||
|
if (flushOrReleaseCodec()) {
|
||||||
|
maybeInitCodec();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Flushes the codec. If flushing is not possible, the codec will be released. This method is a
|
||||||
|
* no-op if the codec is {@code null}.
|
||||||
|
*
|
||||||
|
* @return Whether the codec was released.
|
||||||
|
*/
|
||||||
|
protected boolean flushOrReleaseCodec() {
|
||||||
|
if (codec == null) {
|
||||||
|
// Nothing to do.
|
||||||
|
return false;
|
||||||
|
}
|
||||||
codecHotswapDeadlineMs = C.TIME_UNSET;
|
codecHotswapDeadlineMs = C.TIME_UNSET;
|
||||||
resetInputBuffer();
|
resetInputBuffer();
|
||||||
resetOutputBuffer();
|
resetOutputBuffer();
|
||||||
|
codecReceivedBuffers = false;
|
||||||
waitingForFirstSyncFrame = true;
|
waitingForFirstSyncFrame = true;
|
||||||
waitingForKeys = false;
|
waitingForKeys = false;
|
||||||
shouldSkipOutputBuffer = false;
|
shouldSkipOutputBuffer = false;
|
||||||
@ -699,28 +723,27 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
|
|||||||
shouldSkipAdaptationWorkaroundOutputBuffer = false;
|
shouldSkipAdaptationWorkaroundOutputBuffer = false;
|
||||||
if (codecNeedsFlushWorkaround || (codecNeedsEosFlushWorkaround && codecReceivedEos)) {
|
if (codecNeedsFlushWorkaround || (codecNeedsEosFlushWorkaround && codecReceivedEos)) {
|
||||||
releaseCodec();
|
releaseCodec();
|
||||||
maybeInitCodec();
|
return true;
|
||||||
} else if (codecReinitializationState != REINITIALIZATION_STATE_NONE) {
|
} else if (codecReinitializationState != REINITIALIZATION_STATE_NONE) {
|
||||||
// We're already waiting to re-initialize the codec. Since we're now flushing, there's no need
|
// We're already waiting to re-initialize the codec. Since we're now flushing, there's no need
|
||||||
// to wait any longer.
|
// to wait any longer.
|
||||||
if (codecReinitializationIsRelease) {
|
if (codecReinitializationIsRelease) {
|
||||||
releaseCodec();
|
releaseCodec();
|
||||||
maybeInitCodec();
|
return true;
|
||||||
} else {
|
} else {
|
||||||
codec.flush();
|
codec.flush();
|
||||||
codecReceivedBuffers = false;
|
|
||||||
codecReinitializationState = REINITIALIZATION_STATE_NONE;
|
codecReinitializationState = REINITIALIZATION_STATE_NONE;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// We can flush and re-use the existing decoder.
|
// We can flush and re-use the existing decoder.
|
||||||
codec.flush();
|
codec.flush();
|
||||||
codecReceivedBuffers = false;
|
|
||||||
}
|
}
|
||||||
if (codecReconfigured && format != null) {
|
if (codecReconfigured && format != null) {
|
||||||
// Any reconfiguration data that we send shortly before the flush may be discarded. We
|
// Any reconfiguration data that we send shortly before the flush may be discarded. We
|
||||||
// avoid this issue by sending reconfiguration data following every flush.
|
// avoid this issue by sending reconfiguration data following every flush.
|
||||||
codecReconfigurationState = RECONFIGURATION_STATE_WRITE_PENDING;
|
codecReconfigurationState = RECONFIGURATION_STATE_WRITE_PENDING;
|
||||||
}
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean initCodecWithFallback(MediaCrypto crypto, boolean drmSessionRequiresSecureDecoder)
|
private boolean initCodecWithFallback(MediaCrypto crypto, boolean drmSessionRequiresSecureDecoder)
|
||||||
@ -1496,7 +1519,7 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
|
|||||||
releaseCodec();
|
releaseCodec();
|
||||||
maybeInitCodec();
|
maybeInitCodec();
|
||||||
} else {
|
} else {
|
||||||
flushCodec();
|
flushOrReinitCodec();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
outputStreamEnded = true;
|
outputStreamEnded = true;
|
||||||
|
@ -520,9 +520,12 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer {
|
|||||||
|
|
||||||
@CallSuper
|
@CallSuper
|
||||||
@Override
|
@Override
|
||||||
protected void flushCodec() throws ExoPlaybackException {
|
protected boolean flushOrReleaseCodec() {
|
||||||
super.flushCodec();
|
try {
|
||||||
buffersInCodecCount = 0;
|
return super.flushOrReleaseCodec();
|
||||||
|
} finally {
|
||||||
|
buffersInCodecCount = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -859,7 +862,7 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer {
|
|||||||
// We dropped some buffers to catch up, so update the decoder counters and flush the codec,
|
// We dropped some buffers to catch up, so update the decoder counters and flush the codec,
|
||||||
// which releases all pending buffers buffers including the current output buffer.
|
// which releases all pending buffers buffers including the current output buffer.
|
||||||
updateDroppedBufferCounters(buffersInCodecCount + droppedSourceBufferCount);
|
updateDroppedBufferCounters(buffersInCodecCount + droppedSourceBufferCount);
|
||||||
flushCodec();
|
flushOrReinitCodec();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -105,9 +105,12 @@ public class DebugRenderersFactory extends DefaultRenderersFactory {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void flushCodec() throws ExoPlaybackException {
|
protected boolean flushOrReleaseCodec() {
|
||||||
super.flushCodec();
|
try {
|
||||||
clearTimestamps();
|
return super.flushOrReleaseCodec();
|
||||||
|
} finally {
|
||||||
|
clearTimestamps();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
Loading…
x
Reference in New Issue
Block a user