mirror of
https://github.com/androidx/media.git
synced 2025-05-03 21:57:46 +08:00
Cleanup codec init, flush and release
Issue: #2826 ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=218332277
This commit is contained in:
parent
2fc122745a
commit
66c508651a
@ -475,32 +475,10 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (!initCodecWithFallback(wrappedMediaCrypto, drmSessionRequiresSecureDecoder)) {
|
maybeInitCodecWithFallback(wrappedMediaCrypto, drmSessionRequiresSecureDecoder);
|
||||||
// We can't initialize a codec yet.
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
} catch (DecoderInitializationException e) {
|
} catch (DecoderInitializationException e) {
|
||||||
throw ExoPlaybackException.createForRenderer(e, getIndex());
|
throw ExoPlaybackException.createForRenderer(e, getIndex());
|
||||||
}
|
}
|
||||||
|
|
||||||
String codecName = codecInfo.name;
|
|
||||||
codecAdaptationWorkaroundMode = codecAdaptationWorkaroundMode(codecName);
|
|
||||||
codecNeedsReconfigureWorkaround = codecNeedsReconfigureWorkaround(codecName);
|
|
||||||
codecNeedsDiscardToSpsWorkaround = codecNeedsDiscardToSpsWorkaround(codecName, format);
|
|
||||||
codecNeedsFlushWorkaround = codecNeedsFlushWorkaround(codecName);
|
|
||||||
codecNeedsEosFlushWorkaround = codecNeedsEosFlushWorkaround(codecName);
|
|
||||||
codecNeedsEosOutputExceptionWorkaround = codecNeedsEosOutputExceptionWorkaround(codecName);
|
|
||||||
codecNeedsMonoChannelCountWorkaround = codecNeedsMonoChannelCountWorkaround(codecName, format);
|
|
||||||
codecNeedsEosPropagation =
|
|
||||||
codecNeedsEosPropagationWorkaround(codecInfo) || getCodecNeedsEosPropagation();
|
|
||||||
codecHotswapDeadlineMs =
|
|
||||||
getState() == STATE_STARTED
|
|
||||||
? (SystemClock.elapsedRealtime() + MAX_CODEC_HOTSWAP_TIME_MS)
|
|
||||||
: C.TIME_UNSET;
|
|
||||||
resetInputBuffer();
|
|
||||||
resetOutputBuffer();
|
|
||||||
waitingForFirstSyncFrame = true;
|
|
||||||
decoderCounters.decoderInitCount++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected boolean shouldInitCodec(MediaCodecInfo codecInfo) {
|
protected boolean shouldInitCodec(MediaCodecInfo codecInfo) {
|
||||||
@ -581,31 +559,17 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
|
|||||||
|
|
||||||
protected void releaseCodec() {
|
protected void releaseCodec() {
|
||||||
availableCodecInfos = null;
|
availableCodecInfos = null;
|
||||||
codecHotswapDeadlineMs = C.TIME_UNSET;
|
|
||||||
resetInputBuffer();
|
|
||||||
resetOutputBuffer();
|
|
||||||
waitingForKeys = false;
|
|
||||||
shouldSkipOutputBuffer = false;
|
|
||||||
decodeOnlyPresentationTimestamps.clear();
|
|
||||||
resetCodecBuffers();
|
|
||||||
codecInfo = null;
|
|
||||||
codecReconfigured = false;
|
|
||||||
codecReceivedBuffers = false;
|
|
||||||
codecNeedsDiscardToSpsWorkaround = false;
|
|
||||||
codecNeedsFlushWorkaround = false;
|
|
||||||
codecAdaptationWorkaroundMode = ADAPTATION_WORKAROUND_MODE_NEVER;
|
|
||||||
codecNeedsReconfigureWorkaround = false;
|
|
||||||
codecNeedsEosFlushWorkaround = false;
|
|
||||||
codecNeedsMonoChannelCountWorkaround = false;
|
|
||||||
codecNeedsAdaptationWorkaroundBuffer = false;
|
|
||||||
shouldSkipAdaptationWorkaroundOutputBuffer = false;
|
|
||||||
codecNeedsEosPropagation = false;
|
|
||||||
codecReceivedEos = false;
|
|
||||||
codecReconfigurationState = RECONFIGURATION_STATE_NONE;
|
|
||||||
codecReinitializationState = REINITIALIZATION_STATE_NONE;
|
|
||||||
codecReinitializationIsRelease = false;
|
|
||||||
codecConfiguredWithOperatingRate = false;
|
|
||||||
if (codec != null) {
|
if (codec != null) {
|
||||||
|
resetInputBuffer();
|
||||||
|
resetOutputBuffer();
|
||||||
|
resetCodecBuffers();
|
||||||
|
codecHotswapDeadlineMs = C.TIME_UNSET;
|
||||||
|
waitingForKeys = false;
|
||||||
|
decodeOnlyPresentationTimestamps.clear();
|
||||||
|
codecInfo = null;
|
||||||
|
codecReconfigured = false;
|
||||||
|
codecReconfigurationState = RECONFIGURATION_STATE_NONE;
|
||||||
|
codecReinitializationState = REINITIALIZATION_STATE_NONE;
|
||||||
decoderCounters.decoderReleaseCount++;
|
decoderCounters.decoderReleaseCount++;
|
||||||
try {
|
try {
|
||||||
codec.stop();
|
codec.stop();
|
||||||
@ -708,45 +672,40 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
|
|||||||
*/
|
*/
|
||||||
protected boolean flushOrReleaseCodec() {
|
protected boolean flushOrReleaseCodec() {
|
||||||
if (codec == null) {
|
if (codec == null) {
|
||||||
// Nothing to do.
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
codecHotswapDeadlineMs = C.TIME_UNSET;
|
if (codecNeedsFlushWorkaround
|
||||||
resetInputBuffer();
|
|| (codecNeedsEosFlushWorkaround && codecReceivedEos)
|
||||||
resetOutputBuffer();
|
|| (codecReinitializationState != REINITIALIZATION_STATE_NONE
|
||||||
codecReceivedBuffers = false;
|
&& codecReinitializationIsRelease)) {
|
||||||
waitingForFirstSyncFrame = true;
|
|
||||||
waitingForKeys = false;
|
|
||||||
shouldSkipOutputBuffer = false;
|
|
||||||
decodeOnlyPresentationTimestamps.clear();
|
|
||||||
codecNeedsAdaptationWorkaroundBuffer = false;
|
|
||||||
shouldSkipAdaptationWorkaroundOutputBuffer = false;
|
|
||||||
if (codecNeedsFlushWorkaround || (codecNeedsEosFlushWorkaround && codecReceivedEos)) {
|
|
||||||
releaseCodec();
|
releaseCodec();
|
||||||
return true;
|
return true;
|
||||||
} else if (codecReinitializationState != REINITIALIZATION_STATE_NONE) {
|
|
||||||
// We're already waiting to re-initialize the codec. Since we're now flushing, there's no need
|
|
||||||
// to wait any longer.
|
|
||||||
if (codecReinitializationIsRelease) {
|
|
||||||
releaseCodec();
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
codec.flush();
|
|
||||||
codecReinitializationState = REINITIALIZATION_STATE_NONE;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// We can flush and re-use the existing decoder.
|
|
||||||
codec.flush();
|
|
||||||
}
|
|
||||||
if (codecReconfigured && format != null) {
|
|
||||||
// Any reconfiguration data that we send shortly before the flush may be discarded. We
|
|
||||||
// avoid this issue by sending reconfiguration data following every flush.
|
|
||||||
codecReconfigurationState = RECONFIGURATION_STATE_WRITE_PENDING;
|
|
||||||
}
|
}
|
||||||
|
codec.flush();
|
||||||
|
|
||||||
|
resetInputBuffer();
|
||||||
|
resetOutputBuffer();
|
||||||
|
codecHotswapDeadlineMs = C.TIME_UNSET;
|
||||||
|
codecReceivedEos = false;
|
||||||
|
codecReceivedBuffers = false;
|
||||||
|
waitingForFirstSyncFrame = true;
|
||||||
|
codecNeedsAdaptationWorkaroundBuffer = false;
|
||||||
|
shouldSkipAdaptationWorkaroundOutputBuffer = false;
|
||||||
|
shouldSkipOutputBuffer = false;
|
||||||
|
|
||||||
|
waitingForKeys = false;
|
||||||
|
decodeOnlyPresentationTimestamps.clear();
|
||||||
|
codecReinitializationState = REINITIALIZATION_STATE_NONE;
|
||||||
|
// Reconfiguration data sent shortly before the flush may not have been processed by the
|
||||||
|
// decoder. If the codec has been reconfigured we always send reconfiguration data again to
|
||||||
|
// guarantee that it's processed.
|
||||||
|
codecReconfigurationState =
|
||||||
|
codecReconfigured ? RECONFIGURATION_STATE_WRITE_PENDING : RECONFIGURATION_STATE_NONE;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean initCodecWithFallback(MediaCrypto crypto, boolean drmSessionRequiresSecureDecoder)
|
private void maybeInitCodecWithFallback(
|
||||||
|
MediaCrypto crypto, boolean drmSessionRequiresSecureDecoder)
|
||||||
throws DecoderInitializationException {
|
throws DecoderInitializationException {
|
||||||
if (availableCodecInfos == null) {
|
if (availableCodecInfos == null) {
|
||||||
try {
|
try {
|
||||||
@ -770,14 +729,13 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
|
|||||||
DecoderInitializationException.NO_SUITABLE_DECODER_ERROR);
|
DecoderInitializationException.NO_SUITABLE_DECODER_ERROR);
|
||||||
}
|
}
|
||||||
|
|
||||||
while (true) {
|
while (codec == null) {
|
||||||
MediaCodecInfo codecInfo = availableCodecInfos.peekFirst();
|
MediaCodecInfo codecInfo = availableCodecInfos.peekFirst();
|
||||||
if (!shouldInitCodec(codecInfo)) {
|
if (!shouldInitCodec(codecInfo)) {
|
||||||
return false;
|
return;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
initCodec(codecInfo, crypto);
|
initCodec(codecInfo, crypto);
|
||||||
return true;
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
Log.w(TAG, "Failed to initialize decoder: " + codecInfo, e);
|
Log.w(TAG, "Failed to initialize decoder: " + codecInfo, e);
|
||||||
// This codec failed to initialize, so fall back to the next codec in the list (if any). We
|
// This codec failed to initialize, so fall back to the next codec in the list (if any). We
|
||||||
@ -798,6 +756,8 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
availableCodecInfos = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<MediaCodecInfo> getAvailableCodecInfos(boolean drmSessionRequiresSecureDecoder)
|
private List<MediaCodecInfo> getAvailableCodecInfos(boolean drmSessionRequiresSecureDecoder)
|
||||||
@ -827,13 +787,14 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
|
|||||||
long codecInitializingTimestamp;
|
long codecInitializingTimestamp;
|
||||||
long codecInitializedTimestamp;
|
long codecInitializedTimestamp;
|
||||||
MediaCodec codec = null;
|
MediaCodec codec = null;
|
||||||
String name = codecInfo.name;
|
String codecName = codecInfo.name;
|
||||||
|
|
||||||
updateCodecOperatingRate();
|
updateCodecOperatingRate();
|
||||||
boolean configureWithOperatingRate = codecOperatingRate > assumedMinimumCodecOperatingRate;
|
boolean configureWithOperatingRate = codecOperatingRate > assumedMinimumCodecOperatingRate;
|
||||||
try {
|
try {
|
||||||
codecInitializingTimestamp = SystemClock.elapsedRealtime();
|
codecInitializingTimestamp = SystemClock.elapsedRealtime();
|
||||||
TraceUtil.beginSection("createCodec:" + name);
|
TraceUtil.beginSection("createCodec:" + codecName);
|
||||||
codec = MediaCodec.createByCodecName(name);
|
codec = MediaCodec.createByCodecName(codecName);
|
||||||
TraceUtil.endSection();
|
TraceUtil.endSection();
|
||||||
TraceUtil.beginSection("configureCodec");
|
TraceUtil.beginSection("configureCodec");
|
||||||
configureCodec(
|
configureCodec(
|
||||||
@ -842,7 +803,6 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
|
|||||||
format,
|
format,
|
||||||
crypto,
|
crypto,
|
||||||
configureWithOperatingRate ? codecOperatingRate : CODEC_OPERATING_RATE_UNSET);
|
configureWithOperatingRate ? codecOperatingRate : CODEC_OPERATING_RATE_UNSET);
|
||||||
codecConfiguredWithOperatingRate = configureWithOperatingRate;
|
|
||||||
TraceUtil.endSection();
|
TraceUtil.endSection();
|
||||||
TraceUtil.beginSection("startCodec");
|
TraceUtil.beginSection("startCodec");
|
||||||
codec.start();
|
codec.start();
|
||||||
@ -856,10 +816,36 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
|
|||||||
}
|
}
|
||||||
throw e;
|
throw e;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.codec = codec;
|
this.codec = codec;
|
||||||
this.codecInfo = codecInfo;
|
this.codecInfo = codecInfo;
|
||||||
|
codecConfiguredWithOperatingRate = configureWithOperatingRate;
|
||||||
|
codecAdaptationWorkaroundMode = codecAdaptationWorkaroundMode(codecName);
|
||||||
|
codecNeedsReconfigureWorkaround = codecNeedsReconfigureWorkaround(codecName);
|
||||||
|
codecNeedsDiscardToSpsWorkaround = codecNeedsDiscardToSpsWorkaround(codecName, format);
|
||||||
|
codecNeedsFlushWorkaround = codecNeedsFlushWorkaround(codecName);
|
||||||
|
codecNeedsEosFlushWorkaround = codecNeedsEosFlushWorkaround(codecName);
|
||||||
|
codecNeedsEosOutputExceptionWorkaround = codecNeedsEosOutputExceptionWorkaround(codecName);
|
||||||
|
codecNeedsMonoChannelCountWorkaround = codecNeedsMonoChannelCountWorkaround(codecName, format);
|
||||||
|
codecNeedsEosPropagation =
|
||||||
|
codecNeedsEosPropagationWorkaround(codecInfo) || getCodecNeedsEosPropagation();
|
||||||
|
|
||||||
|
resetInputBuffer();
|
||||||
|
resetOutputBuffer();
|
||||||
|
codecHotswapDeadlineMs =
|
||||||
|
getState() == STATE_STARTED
|
||||||
|
? (SystemClock.elapsedRealtime() + MAX_CODEC_HOTSWAP_TIME_MS)
|
||||||
|
: C.TIME_UNSET;
|
||||||
|
codecReceivedEos = false;
|
||||||
|
codecReceivedBuffers = false;
|
||||||
|
waitingForFirstSyncFrame = true;
|
||||||
|
codecNeedsAdaptationWorkaroundBuffer = false;
|
||||||
|
shouldSkipAdaptationWorkaroundOutputBuffer = false;
|
||||||
|
shouldSkipOutputBuffer = false;
|
||||||
|
|
||||||
|
decoderCounters.decoderInitCount++;
|
||||||
long elapsed = codecInitializedTimestamp - codecInitializingTimestamp;
|
long elapsed = codecInitializedTimestamp - codecInitializingTimestamp;
|
||||||
onCodecInitialized(name, codecInitializedTimestamp, elapsed);
|
onCodecInitialized(codecName, codecInitializedTimestamp, elapsed);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void getCodecBuffers(MediaCodec codec) {
|
private void getCodecBuffers(MediaCodec codec) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user