Commit 401e20d9 by andrewlewis Committed by Oliver Woodman

Signal fallback via renderer constructor

Remove MediaCodecSelector.DEFAULT_WITH_FALLBACK, as codec selectors
will need to be able to return a list of decoder infos even when not
using fallback in a later change. Instead signal that fallback should
be used via a renderer constructor.

Fallback is always disabled for audio.

PiperOrigin-RevId: 242454172
parent baf00406
...@@ -102,6 +102,9 @@ ...@@ -102,6 +102,9 @@
([#5698](https://github.com/google/ExoPlayer/issues/5698), ([#5698](https://github.com/google/ExoPlayer/issues/5698),
[#5694](https://github.com/google/ExoPlayer/issues/5694)). [#5694](https://github.com/google/ExoPlayer/issues/5694)).
* Move `PriorityTaskManager` from `DefaultLoadControl` to `SimpleExoPlayer`. * Move `PriorityTaskManager` from `DefaultLoadControl` to `SimpleExoPlayer`.
* Remove `MediaCodecSelector.DEFAULT_WITH_FALLBACK`. Apps should instead signal
that fallback should be used by passing `true` as the `enableDecoderFallback`
parameter when instantiating the video renderer.
### 2.9.6 ### ### 2.9.6 ###
......
...@@ -250,6 +250,7 @@ public class MediaCodecAudioRenderer extends MediaCodecRenderer implements Media ...@@ -250,6 +250,7 @@ public class MediaCodecAudioRenderer extends MediaCodecRenderer implements Media
mediaCodecSelector, mediaCodecSelector,
drmSessionManager, drmSessionManager,
playClearSamplesWithoutKeys, playClearSamplesWithoutKeys,
/* enableDecoderFallback= */ false,
/* assumedMinimumCodecOperatingRate= */ 44100); /* assumedMinimumCodecOperatingRate= */ 44100);
this.context = context.getApplicationContext(); this.context = context.getApplicationContext();
this.audioSink = audioSink; this.audioSink = audioSink;
......
...@@ -53,6 +53,7 @@ import java.lang.annotation.RetentionPolicy; ...@@ -53,6 +53,7 @@ import java.lang.annotation.RetentionPolicy;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.util.ArrayDeque; import java.util.ArrayDeque;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections;
import java.util.List; import java.util.List;
/** /**
...@@ -289,6 +290,7 @@ public abstract class MediaCodecRenderer extends BaseRenderer { ...@@ -289,6 +290,7 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
private final MediaCodecSelector mediaCodecSelector; private final MediaCodecSelector mediaCodecSelector;
@Nullable private final DrmSessionManager<FrameworkMediaCrypto> drmSessionManager; @Nullable private final DrmSessionManager<FrameworkMediaCrypto> drmSessionManager;
private final boolean playClearSamplesWithoutKeys; private final boolean playClearSamplesWithoutKeys;
private final boolean enableDecoderFallback;
private final float assumedMinimumCodecOperatingRate; private final float assumedMinimumCodecOperatingRate;
private final DecoderInputBuffer buffer; private final DecoderInputBuffer buffer;
private final DecoderInputBuffer flagsOnlyBuffer; private final DecoderInputBuffer flagsOnlyBuffer;
...@@ -354,6 +356,9 @@ public abstract class MediaCodecRenderer extends BaseRenderer { ...@@ -354,6 +356,9 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
* begin in parallel with key acquisition. This parameter specifies whether the renderer is * begin in parallel with key acquisition. This parameter specifies whether the renderer is
* permitted to play clear regions of encrypted media files before {@code drmSessionManager} * permitted to play clear regions of encrypted media files before {@code drmSessionManager}
* has obtained the keys necessary to decrypt encrypted regions of the media. * has obtained the keys necessary to decrypt encrypted regions of the media.
* @param enableDecoderFallback Whether to enable fallback to lower-priority decoders if decoder
* initialization fails. This may result in using a decoder that is less efficient or slower
* than the primary decoder.
* @param assumedMinimumCodecOperatingRate A codec operating rate that all codecs instantiated by * @param assumedMinimumCodecOperatingRate A codec operating rate that all codecs instantiated by
* this renderer are assumed to meet implicitly (i.e. without the operating rate being set * this renderer are assumed to meet implicitly (i.e. without the operating rate being set
* explicitly using {@link MediaFormat#KEY_OPERATING_RATE}). * explicitly using {@link MediaFormat#KEY_OPERATING_RATE}).
...@@ -363,11 +368,13 @@ public abstract class MediaCodecRenderer extends BaseRenderer { ...@@ -363,11 +368,13 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
MediaCodecSelector mediaCodecSelector, MediaCodecSelector mediaCodecSelector,
@Nullable DrmSessionManager<FrameworkMediaCrypto> drmSessionManager, @Nullable DrmSessionManager<FrameworkMediaCrypto> drmSessionManager,
boolean playClearSamplesWithoutKeys, boolean playClearSamplesWithoutKeys,
boolean enableDecoderFallback,
float assumedMinimumCodecOperatingRate) { float assumedMinimumCodecOperatingRate) {
super(trackType); super(trackType);
this.mediaCodecSelector = Assertions.checkNotNull(mediaCodecSelector); this.mediaCodecSelector = Assertions.checkNotNull(mediaCodecSelector);
this.drmSessionManager = drmSessionManager; this.drmSessionManager = drmSessionManager;
this.playClearSamplesWithoutKeys = playClearSamplesWithoutKeys; this.playClearSamplesWithoutKeys = playClearSamplesWithoutKeys;
this.enableDecoderFallback = enableDecoderFallback;
this.assumedMinimumCodecOperatingRate = assumedMinimumCodecOperatingRate; this.assumedMinimumCodecOperatingRate = assumedMinimumCodecOperatingRate;
buffer = new DecoderInputBuffer(DecoderInputBuffer.BUFFER_REPLACEMENT_MODE_DISABLED); buffer = new DecoderInputBuffer(DecoderInputBuffer.BUFFER_REPLACEMENT_MODE_DISABLED);
flagsOnlyBuffer = DecoderInputBuffer.newFlagsOnlyInstance(); flagsOnlyBuffer = DecoderInputBuffer.newFlagsOnlyInstance();
...@@ -735,8 +742,14 @@ public abstract class MediaCodecRenderer extends BaseRenderer { ...@@ -735,8 +742,14 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
throws DecoderInitializationException { throws DecoderInitializationException {
if (availableCodecInfos == null) { if (availableCodecInfos == null) {
try { try {
List<MediaCodecInfo> allAvailableCodecInfos =
getAvailableCodecInfos(mediaCryptoRequiresSecureDecoder);
if (enableDecoderFallback) {
availableCodecInfos = new ArrayDeque<>(allAvailableCodecInfos);
} else {
availableCodecInfos = availableCodecInfos =
new ArrayDeque<>(getAvailableCodecInfos(mediaCryptoRequiresSecureDecoder)); new ArrayDeque<>(Collections.singletonList(allAvailableCodecInfos.get(0)));
}
preferredDecoderInitializationException = null; preferredDecoderInitializationException = null;
} catch (DecoderQueryException e) { } catch (DecoderQueryException e) {
throw new DecoderInitializationException( throw new DecoderInitializationException(
......
...@@ -18,7 +18,6 @@ package com.google.android.exoplayer2.mediacodec; ...@@ -18,7 +18,6 @@ package com.google.android.exoplayer2.mediacodec;
import android.media.MediaCodec; import android.media.MediaCodec;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import com.google.android.exoplayer2.mediacodec.MediaCodecUtil.DecoderQueryException; import com.google.android.exoplayer2.mediacodec.MediaCodecUtil.DecoderQueryException;
import java.util.Collections;
import java.util.List; import java.util.List;
/** /**
...@@ -35,32 +34,6 @@ public interface MediaCodecSelector { ...@@ -35,32 +34,6 @@ public interface MediaCodecSelector {
@Override @Override
public List<MediaCodecInfo> getDecoderInfos(String mimeType, boolean requiresSecureDecoder) public List<MediaCodecInfo> getDecoderInfos(String mimeType, boolean requiresSecureDecoder)
throws DecoderQueryException { throws DecoderQueryException {
List<MediaCodecInfo> decoderInfos =
MediaCodecUtil.getDecoderInfos(mimeType, requiresSecureDecoder);
return decoderInfos.isEmpty()
? Collections.emptyList()
: Collections.singletonList(decoderInfos.get(0));
}
@Override
public @Nullable MediaCodecInfo getPassthroughDecoderInfo() throws DecoderQueryException {
return MediaCodecUtil.getPassthroughDecoderInfo();
}
};
/**
* A {@link MediaCodecSelector} that returns a list of decoders in priority order, allowing
* fallback to less preferred decoders if initialization fails.
*
* <p>Note: if a hardware-accelerated video decoder fails to initialize, this selector may provide
* a software video decoder to use as a fallback. Using software decoding can be inefficient, and
* the decoder may be too slow to keep up with the playback position.
*/
MediaCodecSelector DEFAULT_WITH_FALLBACK =
new MediaCodecSelector() {
@Override
public List<MediaCodecInfo> getDecoderInfos(String mimeType, boolean requiresSecureDecoder)
throws DecoderQueryException {
return MediaCodecUtil.getDecoderInfos(mimeType, requiresSecureDecoder); return MediaCodecUtil.getDecoderInfos(mimeType, requiresSecureDecoder);
} }
......
...@@ -210,16 +210,64 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer { ...@@ -210,16 +210,64 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer {
* @param maxDroppedFramesToNotify The maximum number of frames that can be dropped between * @param maxDroppedFramesToNotify The maximum number of frames that can be dropped between
* invocations of {@link VideoRendererEventListener#onDroppedFrames(int, long)}. * invocations of {@link VideoRendererEventListener#onDroppedFrames(int, long)}.
*/ */
public MediaCodecVideoRenderer(Context context, MediaCodecSelector mediaCodecSelector, public MediaCodecVideoRenderer(
Context context,
MediaCodecSelector mediaCodecSelector,
long allowedJoiningTimeMs,
@Nullable DrmSessionManager<FrameworkMediaCrypto> drmSessionManager,
boolean playClearSamplesWithoutKeys,
@Nullable Handler eventHandler,
@Nullable VideoRendererEventListener eventListener,
int maxDroppedFramesToNotify) {
this(
context,
mediaCodecSelector,
allowedJoiningTimeMs,
drmSessionManager,
playClearSamplesWithoutKeys,
/* enableDecoderFallback= */ false,
eventHandler,
eventListener,
maxDroppedFramesToNotify);
}
/**
* @param context A context.
* @param mediaCodecSelector A decoder selector.
* @param allowedJoiningTimeMs The maximum duration in milliseconds for which this video renderer
* can attempt to seamlessly join an ongoing playback.
* @param drmSessionManager For use with encrypted content. May be null if support for encrypted
* content is not required.
* @param playClearSamplesWithoutKeys Encrypted media may contain clear (un-encrypted) regions.
* For example a media file may start with a short clear region so as to allow playback to
* begin in parallel with key acquisition. This parameter specifies whether the renderer is
* permitted to play clear regions of encrypted media files before {@code drmSessionManager}
* has obtained the keys necessary to decrypt encrypted regions of the media.
* @param enableDecoderFallback Whether to enable fallback to lower-priority decoders if decoder
* initialization fails. This may result in using a decoder that is slower/less efficient than
* the primary decoder.
* @param eventHandler A handler to use when delivering events to {@code eventListener}. May be
* null if delivery of events is not required.
* @param eventListener A listener of events. May be null if delivery of events is not required.
* @param maxDroppedFramesToNotify The maximum number of frames that can be dropped between
* invocations of {@link VideoRendererEventListener#onDroppedFrames(int, long)}.
*/
public MediaCodecVideoRenderer(
Context context,
MediaCodecSelector mediaCodecSelector,
long allowedJoiningTimeMs, long allowedJoiningTimeMs,
@Nullable DrmSessionManager<FrameworkMediaCrypto> drmSessionManager, @Nullable DrmSessionManager<FrameworkMediaCrypto> drmSessionManager,
boolean playClearSamplesWithoutKeys, @Nullable Handler eventHandler, boolean playClearSamplesWithoutKeys,
@Nullable VideoRendererEventListener eventListener, int maxDroppedFramesToNotify) { boolean enableDecoderFallback,
@Nullable Handler eventHandler,
@Nullable VideoRendererEventListener eventListener,
int maxDroppedFramesToNotify) {
super( super(
C.TRACK_TYPE_VIDEO, C.TRACK_TYPE_VIDEO,
mediaCodecSelector, mediaCodecSelector,
drmSessionManager, drmSessionManager,
playClearSamplesWithoutKeys, playClearSamplesWithoutKeys,
enableDecoderFallback,
/* assumedMinimumCodecOperatingRate= */ 30); /* assumedMinimumCodecOperatingRate= */ 30);
this.allowedJoiningTimeMs = allowedJoiningTimeMs; this.allowedJoiningTimeMs = allowedJoiningTimeMs;
this.maxDroppedFramesToNotify = maxDroppedFramesToNotify; this.maxDroppedFramesToNotify = maxDroppedFramesToNotify;
......
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