Commit 53934c13 by andrewlewis Committed by Oliver Woodman

Select non-primary tunneling decoder

Issue: #3100
Issue: #5547
PiperOrigin-RevId: 243181217
parent b84c5143
......@@ -61,6 +61,14 @@
present or newly absent.
* Add support for reading AC-4 streams
([#5303](https://github.com/google/ExoPlayer/pull/5303)).
* Video:
* 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.
* Support video tunneling when the decoder is not listed first for the MIME
type ([#3100](https://github.com/google/ExoPlayer/issues/3100)).
* Query `MediaCodecList.ALL_CODECS` when selecting a tunneling decoder
([#5547](https://github.com/google/ExoPlayer/issues/5547)).
* Add support for SHOUTcast ICY metadata
([#3735](https://github.com/google/ExoPlayer/issues/3735)).
* CEA-608: Improved conformance to the specification
......@@ -102,9 +110,6 @@
([#5698](https://github.com/google/ExoPlayer/issues/5698),
[#5694](https://github.com/google/ExoPlayer/issues/5694)).
* 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 ###
......
......@@ -289,11 +289,15 @@ public class MediaCodecAudioRenderer extends MediaCodecRenderer implements Media
}
}
List<MediaCodecInfo> decoderInfos =
mediaCodecSelector.getDecoderInfos(format.sampleMimeType, requiresSecureDecryption);
mediaCodecSelector.getDecoderInfos(
format.sampleMimeType, requiresSecureDecryption, /* requiresTunnelingDecoder= */ false);
if (decoderInfos.isEmpty()) {
return requiresSecureDecryption
&& !mediaCodecSelector
.getDecoderInfos(format.sampleMimeType, /* requiresSecureDecoder= */ false)
.getDecoderInfos(
format.sampleMimeType,
/* requiresSecureDecoder= */ false,
/* requiresTunnelingDecoder= */ false)
.isEmpty()
? FORMAT_UNSUPPORTED_DRM
: FORMAT_UNSUPPORTED_SUBTYPE;
......@@ -322,7 +326,8 @@ public class MediaCodecAudioRenderer extends MediaCodecRenderer implements Media
return Collections.singletonList(passthroughDecoderInfo);
}
}
return super.getDecoderInfos(mediaCodecSelector, format, requiresSecureDecoder);
return mediaCodecSelector.getDecoderInfos(
format.sampleMimeType, requiresSecureDecoder, /* requiresTunnelingDecoder= */ false);
}
/**
......
......@@ -441,11 +441,9 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
* @return A list of {@link MediaCodecInfo}s corresponding to decoders. May be empty.
* @throws DecoderQueryException Thrown if there was an error querying decoders.
*/
protected List<MediaCodecInfo> getDecoderInfos(
protected abstract List<MediaCodecInfo> getDecoderInfos(
MediaCodecSelector mediaCodecSelector, Format format, boolean requiresSecureDecoder)
throws DecoderQueryException {
return mediaCodecSelector.getDecoderInfos(format.sampleMimeType, requiresSecureDecoder);
}
throws DecoderQueryException;
/**
* Configures a newly created {@link MediaCodec}.
......
......@@ -32,9 +32,11 @@ public interface MediaCodecSelector {
MediaCodecSelector DEFAULT =
new MediaCodecSelector() {
@Override
public List<MediaCodecInfo> getDecoderInfos(String mimeType, boolean requiresSecureDecoder)
public List<MediaCodecInfo> getDecoderInfos(
String mimeType, boolean requiresSecureDecoder, boolean requiresTunnelingDecoder)
throws DecoderQueryException {
return MediaCodecUtil.getDecoderInfos(mimeType, requiresSecureDecoder);
return MediaCodecUtil.getDecoderInfos(
mimeType, requiresSecureDecoder, requiresTunnelingDecoder);
}
@Override
......@@ -48,10 +50,12 @@ public interface MediaCodecSelector {
*
* @param mimeType The MIME type for which a decoder is required.
* @param requiresSecureDecoder Whether a secure decoder is required.
* @param requiresTunnelingDecoder Whether a tunneling decoder is required.
* @return A list of {@link MediaCodecInfo}s corresponding to decoders. May be empty.
* @throws DecoderQueryException Thrown if there was an error querying decoders.
*/
List<MediaCodecInfo> getDecoderInfos(String mimeType, boolean requiresSecureDecoder)
List<MediaCodecInfo> getDecoderInfos(
String mimeType, boolean requiresSecureDecoder, boolean requiresTunnelingDecoder)
throws DecoderQueryException;
/**
......
......@@ -52,6 +52,7 @@ import com.google.android.exoplayer2.util.TraceUtil;
import com.google.android.exoplayer2.util.Util;
import com.google.android.exoplayer2.video.VideoRendererEventListener.EventDispatcher;
import java.nio.ByteBuffer;
import java.util.Collections;
import java.util.List;
/**
......@@ -304,11 +305,14 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer {
}
}
List<MediaCodecInfo> decoderInfos =
mediaCodecSelector.getDecoderInfos(format.sampleMimeType, requiresSecureDecryption);
getDecoderInfos(mediaCodecSelector, format, requiresSecureDecryption);
if (decoderInfos.isEmpty()) {
return requiresSecureDecryption
&& !mediaCodecSelector
.getDecoderInfos(format.sampleMimeType, /* requiresSecureDecoder= */ false)
.getDecoderInfos(
format.sampleMimeType,
/* requiresSecureDecoder= */ false,
/* requiresTunnelingDecoder= */ false)
.isEmpty()
? FORMAT_UNSUPPORTED_DRM
: FORMAT_UNSUPPORTED_SUBTYPE;
......@@ -323,12 +327,35 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer {
decoderInfo.isSeamlessAdaptationSupported(format)
? ADAPTIVE_SEAMLESS
: ADAPTIVE_NOT_SEAMLESS;
int tunnelingSupport = decoderInfo.tunneling ? TUNNELING_SUPPORTED : TUNNELING_NOT_SUPPORTED;
int tunnelingSupport = TUNNELING_NOT_SUPPORTED;
if (isFormatSupported) {
List<MediaCodecInfo> tunnelingDecoderInfos =
mediaCodecSelector.getDecoderInfos(
format.sampleMimeType,
requiresSecureDecryption,
/* requiresTunnelingDecoder= */ true);
if (!tunnelingDecoderInfos.isEmpty()) {
MediaCodecInfo tunnelingDecoderInfo = tunnelingDecoderInfos.get(0);
if (tunnelingDecoderInfo.isFormatSupported(format)
&& tunnelingDecoderInfo.isSeamlessAdaptationSupported(format)) {
tunnelingSupport = TUNNELING_SUPPORTED;
}
}
}
int formatSupport = isFormatSupported ? FORMAT_HANDLED : FORMAT_EXCEEDS_CAPABILITIES;
return adaptiveSupport | tunnelingSupport | formatSupport;
}
@Override
protected List<MediaCodecInfo> getDecoderInfos(
MediaCodecSelector mediaCodecSelector, Format format, boolean requiresSecureDecoder)
throws DecoderQueryException {
List<MediaCodecInfo> decoderInfos =
mediaCodecSelector.getDecoderInfos(format.sampleMimeType, requiresSecureDecoder, tunneling);
return Collections.unmodifiableList(decoderInfos);
}
@Override
protected void onEnabled(boolean joining) throws ExoPlaybackException {
super.onEnabled(joining);
int oldTunnelingAudioSessionId = tunnelingAudioSessionId;
......
......@@ -628,7 +628,9 @@ public final class DashStreamingTest {
@Test
public void testDecoderInfoH264() throws DecoderQueryException {
MediaCodecInfo decoderInfo = MediaCodecUtil.getDecoderInfo(MimeTypes.VIDEO_H264, false);
MediaCodecInfo decoderInfo =
MediaCodecUtil.getDecoderInfo(
MimeTypes.VIDEO_H264, /* secure= */ false, /* tunneling= */ false);
assertThat(decoderInfo).isNotNull();
assertThat(Util.SDK_INT < 21 || decoderInfo.adaptive).isTrue();
}
......@@ -639,7 +641,11 @@ public final class DashStreamingTest {
// Pass.
return;
}
assertThat(MediaCodecUtil.getDecoderInfo(MimeTypes.VIDEO_H265, false).adaptive).isTrue();
assertThat(
MediaCodecUtil.getDecoderInfo(
MimeTypes.VIDEO_H265, /* secure= */ false, /* tunneling= */ false)
.adaptive)
.isTrue();
}
@Test
......@@ -648,13 +654,18 @@ public final class DashStreamingTest {
// Pass.
return;
}
assertThat(MediaCodecUtil.getDecoderInfo(MimeTypes.VIDEO_VP9, false).adaptive).isTrue();
assertThat(
MediaCodecUtil.getDecoderInfo(
MimeTypes.VIDEO_VP9, /* secure= */ false, /* tunneling= */ false)
.adaptive)
.isTrue();
}
// Internal.
private static boolean shouldSkipAdaptiveTest(String mimeType) throws DecoderQueryException {
MediaCodecInfo decoderInfo = MediaCodecUtil.getDecoderInfo(mimeType, false);
MediaCodecInfo decoderInfo =
MediaCodecUtil.getDecoderInfo(mimeType, /* secure= */ false, /* tunneling= */ false);
return decoderInfo == null || !decoderInfo.adaptive;
}
......
......@@ -106,7 +106,8 @@ public final class DashTestRunner {
if (Util.SDK_INT >= 18) {
try {
// Force L3 if secure decoder is not available.
if (MediaCodecUtil.getDecoderInfo(mimeType, true) == null) {
if (MediaCodecUtil.getDecoderInfo(mimeType, /* secure= */ true, /* tunneling= */ false)
== null) {
return false;
}
MediaDrm mediaDrm = MediaDrmBuilder.build();
......
......@@ -82,12 +82,16 @@ public class EnumerateDecodersTest {
}
private void enumerateDecoders(String mimeType) throws DecoderQueryException {
logDecoderInfos(mimeType, /* secure= */ false);
logDecoderInfos(mimeType, /* secure= */ true);
logDecoderInfos(mimeType, /* secure= */ false, /* tunneling= */ false);
logDecoderInfos(mimeType, /* secure= */ true, /* tunneling= */ false);
logDecoderInfos(mimeType, /* secure= */ false, /* tunneling= */ true);
logDecoderInfos(mimeType, /* secure= */ true, /* tunneling= */ true);
}
private void logDecoderInfos(String mimeType, boolean secure) throws DecoderQueryException {
List<MediaCodecInfo> mediaCodecInfos = MediaCodecUtil.getDecoderInfos(mimeType, secure);
private void logDecoderInfos(String mimeType, boolean secure, boolean tunneling)
throws DecoderQueryException {
List<MediaCodecInfo> mediaCodecInfos =
MediaCodecUtil.getDecoderInfos(mimeType, secure, tunneling);
for (MediaCodecInfo mediaCodecInfo : mediaCodecInfos) {
CodecCapabilities capabilities = Assertions.checkNotNull(mediaCodecInfo.capabilities);
metricsLogger.logMetric(
......
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