Align Decoder(Audio|Video)Renderer decoder re-use logic

- Fix DecoderAudioRenderer to re-init codec if the DRM session changes.
- Add canKeepCodec to DecoderVideoRenderer. Previously it was assumed
  that the decoder could be re-used, but this will not be true in all
  cases for FfmpegVideoRenderer.

Issue: #7079
PiperOrigin-RevId: 309935278
This commit is contained in:
olly 2020-05-05 14:37:41 +01:00 committed by Oliver Woodman
parent 2e81186a33
commit ee14fe7adf
6 changed files with 40 additions and 7 deletions

View File

@ -162,4 +162,9 @@ public class Libgav1VideoRenderer extends DecoderVideoRenderer {
decoder.setOutputMode(outputMode);
}
}
@Override
protected boolean canKeepCodec(Format oldFormat, Format newFormat) {
return true;
}
}

View File

@ -56,7 +56,8 @@ public final class FfmpegLibrary {
}
/** Returns the version of the underlying library if available, or null otherwise. */
public static @Nullable String getVersion() {
@Nullable
public static String getVersion() {
return isAvailable() ? ffmpegGetVersion() : null;
}
@ -69,7 +70,7 @@ public final class FfmpegLibrary {
if (!isAvailable()) {
return false;
}
String codecName = getCodecName(mimeType);
@Nullable String codecName = getCodecName(mimeType);
if (codecName == null) {
return false;
}
@ -84,7 +85,8 @@ public final class FfmpegLibrary {
* Returns the name of the FFmpeg decoder that could be used to decode the format, or {@code null}
* if it's unsupported.
*/
/* package */ static @Nullable String getCodecName(String mimeType) {
@Nullable
/* package */ static String getCodecName(String mimeType) {
switch (mimeType) {
case MimeTypes.AUDIO_AAC:
return "aac";

View File

@ -24,6 +24,7 @@ import com.google.android.exoplayer2.RendererCapabilities;
import com.google.android.exoplayer2.decoder.Decoder;
import com.google.android.exoplayer2.drm.ExoMediaCrypto;
import com.google.android.exoplayer2.util.TraceUtil;
import com.google.android.exoplayer2.util.Util;
import com.google.android.exoplayer2.video.DecoderVideoRenderer;
import com.google.android.exoplayer2.video.VideoDecoderInputBuffer;
import com.google.android.exoplayer2.video.VideoDecoderOutputBuffer;
@ -113,4 +114,9 @@ public final class FfmpegVideoRenderer extends DecoderVideoRenderer {
}
*/
}
@Override
protected boolean canKeepCodec(Format oldFormat, Format newFormat) {
return Util.areEqual(oldFormat.sampleMimeType, newFormat.sampleMimeType);
}
}

View File

@ -168,4 +168,9 @@ public class LibvpxVideoRenderer extends DecoderVideoRenderer {
decoder.setOutputMode(outputMode);
}
}
@Override
protected boolean canKeepCodec(Format oldFormat, Format newFormat) {
return true;
}
}

View File

@ -323,7 +323,7 @@ public abstract class DecoderAudioRenderer extends BaseRenderer implements Media
*
* @param oldFormat The previous format.
* @param newFormat The new format.
* @return True if the existing decoder can be kept.
* @return Whether the existing decoder can be kept.
*/
protected boolean canKeepCodec(Format oldFormat, Format newFormat) {
return false;
@ -643,7 +643,9 @@ public abstract class DecoderAudioRenderer extends BaseRenderer implements Media
Format oldFormat = inputFormat;
inputFormat = newFormat;
if (!canKeepCodec(oldFormat, inputFormat)) {
if (decoder == null) {
maybeInitDecoder();
} else if (sourceDrmSession != decoderDrmSession || !canKeepCodec(oldFormat, inputFormat)) {
if (decoderReceivedBuffers) {
// Signal end of stream and wait for any final output buffers before re-initialization.
decoderReinitializationState = REINITIALIZATION_STATE_SIGNAL_END_OF_STREAM;
@ -657,7 +659,6 @@ public abstract class DecoderAudioRenderer extends BaseRenderer implements Media
encoderDelay = inputFormat.encoderDelay;
encoderPadding = inputFormat.encoderPadding;
eventDispatcher.inputFormatChanged(inputFormat);
}

View File

@ -379,9 +379,12 @@ public abstract class DecoderVideoRenderer extends BaseRenderer {
waitingForFirstSampleInFormat = true;
Format newFormat = Assertions.checkNotNull(formatHolder.format);
setSourceDrmSession(formatHolder.drmSession);
Format oldFormat = inputFormat;
inputFormat = newFormat;
if (sourceDrmSession != decoderDrmSession) {
if (decoder == null) {
maybeInitDecoder();
} else if (sourceDrmSession != decoderDrmSession || !canKeepCodec(oldFormat, inputFormat)) {
if (decoderReceivedBuffers) {
// Signal end of stream and wait for any final output buffers before re-initialization.
decoderReinitializationState = REINITIALIZATION_STATE_SIGNAL_END_OF_STREAM;
@ -640,6 +643,17 @@ public abstract class DecoderVideoRenderer extends BaseRenderer {
*/
protected abstract void setDecoderOutputMode(@C.VideoOutputMode int outputMode);
/**
* Returns whether the existing decoder can be kept for a new format.
*
* @param oldFormat The previous format.
* @param newFormat The new format.
* @return Whether the existing decoder can be kept.
*/
protected boolean canKeepCodec(Format oldFormat, Format newFormat) {
return false;
}
// Internal methods.
private void setSourceDrmSession(@Nullable DrmSession session) {