Commit 4db6f1e4 by olly Committed by Oliver Woodman

Expose whether decoders support tunneling

This is a first step toward supporting tunneled playback

Issue: #1688

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=141167501
parent 99957bba
...@@ -144,7 +144,7 @@ public class MediaCodecAudioRenderer extends MediaCodecRenderer implements Media ...@@ -144,7 +144,7 @@ public class MediaCodecAudioRenderer extends MediaCodecRenderer implements Media
if (allowPassthrough(mimeType) && mediaCodecSelector.getPassthroughDecoderInfo() != null) { if (allowPassthrough(mimeType) && mediaCodecSelector.getPassthroughDecoderInfo() != null) {
return ADAPTIVE_NOT_SEAMLESS | FORMAT_HANDLED; return ADAPTIVE_NOT_SEAMLESS | FORMAT_HANDLED;
} }
MediaCodecInfo decoderInfo = mediaCodecSelector.getDecoderInfo(mimeType, false); MediaCodecInfo decoderInfo = mediaCodecSelector.getDecoderInfo(mimeType, false, false);
if (decoderInfo == null) { if (decoderInfo == null) {
return FORMAT_UNSUPPORTED_SUBTYPE; return FORMAT_UNSUPPORTED_SUBTYPE;
} }
......
...@@ -51,6 +51,14 @@ public final class MediaCodecInfo { ...@@ -51,6 +51,14 @@ public final class MediaCodecInfo {
*/ */
public final boolean adaptive; public final boolean adaptive;
/**
* Whether the decoder supports tunneling.
*
* @see CodecCapabilities#isFeatureSupported(String)
* @see CodecCapabilities#FEATURE_TunneledPlayback
*/
public final boolean tunneling;
private final String mimeType; private final String mimeType;
private final CodecCapabilities capabilities; private final CodecCapabilities capabilities;
...@@ -86,6 +94,7 @@ public final class MediaCodecInfo { ...@@ -86,6 +94,7 @@ public final class MediaCodecInfo {
this.mimeType = mimeType; this.mimeType = mimeType;
this.capabilities = capabilities; this.capabilities = capabilities;
adaptive = capabilities != null && isAdaptive(capabilities); adaptive = capabilities != null && isAdaptive(capabilities);
tunneling = capabilities != null && isTunneling(capabilities);
} }
/** /**
...@@ -270,4 +279,13 @@ public final class MediaCodecInfo { ...@@ -270,4 +279,13 @@ public final class MediaCodecInfo {
return capabilities.isFeatureSupported(CodecCapabilities.FEATURE_AdaptivePlayback); return capabilities.isFeatureSupported(CodecCapabilities.FEATURE_AdaptivePlayback);
} }
private static boolean isTunneling(CodecCapabilities capabilities) {
return Util.SDK_INT >= 21 && isTunnelingV21(capabilities);
}
@TargetApi(21)
private static boolean isTunnelingV21(CodecCapabilities capabilities) {
return capabilities.isFeatureSupported(CodecCapabilities.FEATURE_TunneledPlayback);
}
} }
...@@ -270,7 +270,7 @@ public abstract class MediaCodecRenderer extends BaseRenderer { ...@@ -270,7 +270,7 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
*/ */
protected MediaCodecInfo getDecoderInfo(MediaCodecSelector mediaCodecSelector, protected MediaCodecInfo getDecoderInfo(MediaCodecSelector mediaCodecSelector,
Format format, boolean requiresSecureDecoder) throws DecoderQueryException { Format format, boolean requiresSecureDecoder) throws DecoderQueryException {
return mediaCodecSelector.getDecoderInfo(format.sampleMimeType, requiresSecureDecoder); return mediaCodecSelector.getDecoderInfo(format.sampleMimeType, requiresSecureDecoder, false);
} }
/** /**
...@@ -1020,7 +1020,7 @@ public abstract class MediaCodecRenderer extends BaseRenderer { ...@@ -1020,7 +1020,7 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
return Util.SDK_INT < 24 return Util.SDK_INT < 24
&& ("OMX.Nvidia.h264.decode".equals(name) || "OMX.Nvidia.h264.decode.secure".equals(name)) && ("OMX.Nvidia.h264.decode".equals(name) || "OMX.Nvidia.h264.decode.secure".equals(name))
&& ("flounder".equals(Util.DEVICE) || "flounder_lte".equals(Util.DEVICE) && ("flounder".equals(Util.DEVICE) || "flounder_lte".equals(Util.DEVICE)
|| "grouper".equals(Util.DEVICE) || "tilapia".equals(Util.DEVICE)); || "grouper".equals(Util.DEVICE) || "tilapia".equals(Util.DEVICE));
} }
/** /**
......
...@@ -29,9 +29,9 @@ public interface MediaCodecSelector { ...@@ -29,9 +29,9 @@ public interface MediaCodecSelector {
MediaCodecSelector DEFAULT = new MediaCodecSelector() { MediaCodecSelector DEFAULT = new MediaCodecSelector() {
@Override @Override
public MediaCodecInfo getDecoderInfo(String mimeType, boolean requiresSecureDecoder) public MediaCodecInfo getDecoderInfo(String mimeType, boolean requiresSecureDecoder,
throws DecoderQueryException { boolean requiresTunneling) throws DecoderQueryException {
return MediaCodecUtil.getDecoderInfo(mimeType, requiresSecureDecoder); return MediaCodecUtil.getDecoderInfo(mimeType, requiresSecureDecoder, requiresTunneling);
} }
@Override @Override
...@@ -46,12 +46,13 @@ public interface MediaCodecSelector { ...@@ -46,12 +46,13 @@ public interface MediaCodecSelector {
* *
* @param mimeType The mime type for which a decoder is required. * @param mimeType The mime type for which a decoder is required.
* @param requiresSecureDecoder Whether a secure decoder is required. * @param requiresSecureDecoder Whether a secure decoder is required.
* @param requiresTunneling Whether a decoder that supports tunneling is required.
* @return A {@link MediaCodecInfo} describing the decoder, or null if no suitable decoder * @return A {@link MediaCodecInfo} describing the decoder, or null if no suitable decoder
* exists. * exists.
* @throws DecoderQueryException Thrown if there was an error querying decoders. * @throws DecoderQueryException Thrown if there was an error querying decoders.
*/ */
MediaCodecInfo getDecoderInfo(String mimeType, boolean requiresSecureDecoder) MediaCodecInfo getDecoderInfo(String mimeType, boolean requiresSecureDecoder,
throws DecoderQueryException; boolean requiresTunneling) throws DecoderQueryException;
/** /**
* Selects a decoder to instantiate for audio passthrough. * Selects a decoder to instantiate for audio passthrough.
......
...@@ -81,7 +81,9 @@ public final class MediaCodecUtil { ...@@ -81,7 +81,9 @@ public final class MediaCodecUtil {
/** /**
* Optional call to warm the codec cache for a given mime type. * Optional call to warm the codec cache for a given mime type.
* <p> * <p>
* Calling this method may speed up subsequent calls to {@link #getDecoderInfo(String, boolean)}. * Calling this method may speed up subsequent calls to
* {@link #getDecoderInfo(String, boolean, boolean)} and
* {@link #getDecoderInfos(String, boolean)}.
* *
* @param mimeType The mime type. * @param mimeType The mime type.
* @param secure Whether the decoder is required to support secure decryption. Always pass false * @param secure Whether the decoder is required to support secure decryption. Always pass false
...@@ -113,14 +115,26 @@ public final class MediaCodecUtil { ...@@ -113,14 +115,26 @@ public final class MediaCodecUtil {
* @param mimeType The mime type. * @param mimeType The mime type.
* @param secure Whether the decoder is required to support secure decryption. Always pass false * @param secure Whether the decoder is required to support secure decryption. Always pass false
* unless secure decryption really is required. * unless secure decryption really is required.
* @param tunneling Whether the decoder is required to support tunneling. Always pass false unless
* tunneling really is required.
* @return A {@link MediaCodecInfo} describing the decoder, or null if no suitable decoder * @return A {@link MediaCodecInfo} describing the decoder, or null if no suitable decoder
* exists. * exists.
* @throws DecoderQueryException If there was an error querying the available decoders. * @throws DecoderQueryException If there was an error querying the available decoders.
*/ */
public static MediaCodecInfo getDecoderInfo(String mimeType, boolean secure) public static MediaCodecInfo getDecoderInfo(String mimeType, boolean secure, boolean tunneling)
throws DecoderQueryException { throws DecoderQueryException {
List<MediaCodecInfo> decoderInfos = getDecoderInfos(mimeType, secure); List<MediaCodecInfo> decoderInfos = getDecoderInfos(mimeType, secure);
return decoderInfos.isEmpty() ? null : decoderInfos.get(0); if (tunneling) {
for (int i = 0; i < decoderInfos.size(); i++) {
MediaCodecInfo decoderInfo = decoderInfos.get(i);
if (decoderInfo.tunneling) {
return decoderInfo;
}
}
return null;
} else {
return decoderInfos.isEmpty() ? null : decoderInfos.get(0);
}
} }
/** /**
...@@ -178,11 +192,10 @@ public final class MediaCodecUtil { ...@@ -178,11 +192,10 @@ public final class MediaCodecUtil {
boolean secure = mediaCodecList.isSecurePlaybackSupported(mimeType, capabilities); boolean secure = mediaCodecList.isSecurePlaybackSupported(mimeType, capabilities);
if ((secureDecodersExplicit && key.secure == secure) if ((secureDecodersExplicit && key.secure == secure)
|| (!secureDecodersExplicit && !key.secure)) { || (!secureDecodersExplicit && !key.secure)) {
decoderInfos.add( decoderInfos.add(MediaCodecInfo.newInstance(codecName, mimeType, capabilities));
MediaCodecInfo.newInstance(codecName, mimeType, capabilities));
} else if (!secureDecodersExplicit && secure) { } else if (!secureDecodersExplicit && secure) {
decoderInfos.add(MediaCodecInfo.newInstance(codecName + ".secure", decoderInfos.add(MediaCodecInfo.newInstance(codecName + ".secure", mimeType,
mimeType, capabilities)); capabilities));
// It only makes sense to have one synthesized secure decoder, return immediately. // It only makes sense to have one synthesized secure decoder, return immediately.
return decoderInfos; return decoderInfos;
} }
...@@ -292,7 +305,7 @@ public final class MediaCodecUtil { ...@@ -292,7 +305,7 @@ public final class MediaCodecUtil {
public static int maxH264DecodableFrameSize() throws DecoderQueryException { public static int maxH264DecodableFrameSize() throws DecoderQueryException {
if (maxH264DecodableFrameSize == -1) { if (maxH264DecodableFrameSize == -1) {
int result = 0; int result = 0;
MediaCodecInfo decoderInfo = getDecoderInfo(MimeTypes.VIDEO_H264, false); MediaCodecInfo decoderInfo = getDecoderInfo(MimeTypes.VIDEO_H264, false, false);
if (decoderInfo != null) { if (decoderInfo != null) {
for (CodecProfileLevel profileLevel : decoderInfo.getProfileLevels()) { for (CodecProfileLevel profileLevel : decoderInfo.getProfileLevels()) {
result = Math.max(avcLevelToMaxFrameSize(profileLevel.level), result); result = Math.max(avcLevelToMaxFrameSize(profileLevel.level), result);
......
...@@ -172,7 +172,7 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer { ...@@ -172,7 +172,7 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer {
} }
} }
MediaCodecInfo decoderInfo = mediaCodecSelector.getDecoderInfo(mimeType, MediaCodecInfo decoderInfo = mediaCodecSelector.getDecoderInfo(mimeType,
requiresSecureDecryption); requiresSecureDecryption, false);
if (decoderInfo == null) { if (decoderInfo == null) {
return FORMAT_UNSUPPORTED_SUBTYPE; return FORMAT_UNSUPPORTED_SUBTYPE;
} }
......
...@@ -633,7 +633,7 @@ public final class DashTest extends ActivityInstrumentationTestCase2<HostActivit ...@@ -633,7 +633,7 @@ public final class DashTest extends ActivityInstrumentationTestCase2<HostActivit
} }
private static boolean shouldSkipAdaptiveTest(String mimeType) throws DecoderQueryException { private static boolean shouldSkipAdaptiveTest(String mimeType) throws DecoderQueryException {
MediaCodecInfo decoderInfo = MediaCodecUtil.getDecoderInfo(mimeType, false); MediaCodecInfo decoderInfo = MediaCodecUtil.getDecoderInfo(mimeType, false, false);
assertNotNull(decoderInfo); assertNotNull(decoderInfo);
if (decoderInfo.adaptive) { if (decoderInfo.adaptive) {
return false; return false;
...@@ -706,7 +706,8 @@ public final class DashTest extends ActivityInstrumentationTestCase2<HostActivit ...@@ -706,7 +706,8 @@ public final class DashTest extends ActivityInstrumentationTestCase2<HostActivit
if (isWidevineEncrypted) { if (isWidevineEncrypted) {
try { try {
// Force L3 if secure decoder is not available. // Force L3 if secure decoder is not available.
boolean forceL3Widevine = MediaCodecUtil.getDecoderInfo(videoMimeType, true) == null; boolean forceL3Widevine =
MediaCodecUtil.getDecoderInfo(videoMimeType, true, false) == null;
MediaDrm mediaDrm = new MediaDrm(WIDEVINE_UUID); MediaDrm mediaDrm = new MediaDrm(WIDEVINE_UUID);
String securityProperty = mediaDrm.getPropertyString(SECURITY_LEVEL_PROPERTY); String securityProperty = mediaDrm.getPropertyString(SECURITY_LEVEL_PROPERTY);
String widevineContentId = forceL3Widevine ? WIDEVINE_SW_CRYPTO_CONTENT_ID String widevineContentId = forceL3Widevine ? WIDEVINE_SW_CRYPTO_CONTENT_ID
......
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