Commit e125ed70 by olly Committed by Oliver Woodman

Report tunneling support via RendererCapabilities API

Also revert ability to query for a decoder that explicitly
supports tunneling, since in the new design we'll just be
querying the first decoder provided by the MediaCodecSelector
and then reporting what it supports. This is in line with
what we do when reporting support for adaptive switching.

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=144315746
parent 57525244
...@@ -80,6 +80,20 @@ public interface RendererCapabilities { ...@@ -80,6 +80,20 @@ public interface RendererCapabilities {
int ADAPTIVE_NOT_SUPPORTED = 0b0000; int ADAPTIVE_NOT_SUPPORTED = 0b0000;
/** /**
* A mask to apply to the result of {@link #supportsFormat(Format)} to obtain one of
* {@link #TUNNELING_SUPPORTED} and {@link #TUNNELING_NOT_SUPPORTED}.
*/
int TUNNELING_SUPPORT_MASK = 0b10000;
/**
* The {@link Renderer} supports tunneled output.
*/
int TUNNELING_SUPPORTED = 0b10000;
/**
* The {@link Renderer} does not support tunneled output.
*/
int TUNNELING_NOT_SUPPORTED = 0b00000;
/**
* Returns the track type that the {@link Renderer} handles. For example, a video renderer will * Returns the track type that the {@link Renderer} handles. For example, a video renderer will
* return {@link C#TRACK_TYPE_VIDEO}, an audio renderer will return {@link C#TRACK_TYPE_AUDIO}, a * return {@link C#TRACK_TYPE_VIDEO}, an audio renderer will return {@link C#TRACK_TYPE_AUDIO}, a
* text renderer will return {@link C#TRACK_TYPE_TEXT}, and so on. * text renderer will return {@link C#TRACK_TYPE_TEXT}, and so on.
...@@ -91,7 +105,7 @@ public interface RendererCapabilities { ...@@ -91,7 +105,7 @@ public interface RendererCapabilities {
/** /**
* Returns the extent to which the {@link Renderer} supports a given format. The returned value is * Returns the extent to which the {@link Renderer} supports a given format. The returned value is
* the bitwise OR of two properties: * the bitwise OR of three properties:
* <ul> * <ul>
* <li>The level of support for the format itself. One of {@link #FORMAT_HANDLED}, * <li>The level of support for the format itself. One of {@link #FORMAT_HANDLED},
* {@link #FORMAT_EXCEEDS_CAPABILITIES}, {@link #FORMAT_UNSUPPORTED_SUBTYPE} and * {@link #FORMAT_EXCEEDS_CAPABILITIES}, {@link #FORMAT_UNSUPPORTED_SUBTYPE} and
...@@ -99,9 +113,12 @@ public interface RendererCapabilities { ...@@ -99,9 +113,12 @@ public interface RendererCapabilities {
* <li>The level of support for adapting from the format to another format of the same mime type. * <li>The level of support for adapting from the format to another format of the same mime type.
* One of {@link #ADAPTIVE_SEAMLESS}, {@link #ADAPTIVE_NOT_SEAMLESS} and * One of {@link #ADAPTIVE_SEAMLESS}, {@link #ADAPTIVE_NOT_SEAMLESS} and
* {@link #ADAPTIVE_NOT_SUPPORTED}.</li> * {@link #ADAPTIVE_NOT_SUPPORTED}.</li>
* <li>The level of support for tunneling. One of {@link #TUNNELING_SUPPORTED} and
* {@link #TUNNELING_NOT_SUPPORTED}.</li>
* </ul> * </ul>
* The individual properties can be retrieved by performing a bitwise AND with * The individual properties can be retrieved by performing a bitwise AND with
* {@link #FORMAT_SUPPORT_MASK} and {@link #ADAPTIVE_SUPPORT_MASK} respectively. * {@link #FORMAT_SUPPORT_MASK}, {@link #ADAPTIVE_SUPPORT_MASK} and
* {@link #TUNNELING_SUPPORT_MASK} respectively.
* *
* @param format The format. * @param format The format.
* @return The extent to which the renderer is capable of supporting the given format. * @return The extent to which the renderer is capable of supporting the given format.
......
...@@ -138,10 +138,11 @@ public class MediaCodecAudioRenderer extends MediaCodecRenderer implements Media ...@@ -138,10 +138,11 @@ public class MediaCodecAudioRenderer extends MediaCodecRenderer implements Media
if (!MimeTypes.isAudio(mimeType)) { if (!MimeTypes.isAudio(mimeType)) {
return FORMAT_UNSUPPORTED_TYPE; return FORMAT_UNSUPPORTED_TYPE;
} }
int tunnelingSupport = Util.SDK_INT >= 21 ? TUNNELING_SUPPORTED : TUNNELING_NOT_SUPPORTED;
if (allowPassthrough(mimeType) && mediaCodecSelector.getPassthroughDecoderInfo() != null) { if (allowPassthrough(mimeType) && mediaCodecSelector.getPassthroughDecoderInfo() != null) {
return ADAPTIVE_NOT_SEAMLESS | FORMAT_HANDLED; return ADAPTIVE_NOT_SEAMLESS | tunnelingSupport | FORMAT_HANDLED;
} }
MediaCodecInfo decoderInfo = mediaCodecSelector.getDecoderInfo(mimeType, false, false); MediaCodecInfo decoderInfo = mediaCodecSelector.getDecoderInfo(mimeType, false);
if (decoderInfo == null) { if (decoderInfo == null) {
return FORMAT_UNSUPPORTED_SUBTYPE; return FORMAT_UNSUPPORTED_SUBTYPE;
} }
...@@ -152,7 +153,7 @@ public class MediaCodecAudioRenderer extends MediaCodecRenderer implements Media ...@@ -152,7 +153,7 @@ public class MediaCodecAudioRenderer extends MediaCodecRenderer implements Media
&& (format.channelCount == Format.NO_VALUE && (format.channelCount == Format.NO_VALUE
|| decoderInfo.isAudioChannelCountSupportedV21(format.channelCount))); || decoderInfo.isAudioChannelCountSupportedV21(format.channelCount)));
int formatSupport = decoderCapable ? FORMAT_HANDLED : FORMAT_EXCEEDS_CAPABILITIES; int formatSupport = decoderCapable ? FORMAT_HANDLED : FORMAT_EXCEEDS_CAPABILITIES;
return ADAPTIVE_NOT_SEAMLESS | formatSupport; return ADAPTIVE_NOT_SEAMLESS | tunnelingSupport | formatSupport;
} }
@Override @Override
......
...@@ -158,7 +158,8 @@ public abstract class SimpleDecoderAudioRenderer extends BaseRenderer implements ...@@ -158,7 +158,8 @@ public abstract class SimpleDecoderAudioRenderer extends BaseRenderer implements
if (formatSupport == FORMAT_UNSUPPORTED_TYPE || formatSupport == FORMAT_UNSUPPORTED_SUBTYPE) { if (formatSupport == FORMAT_UNSUPPORTED_TYPE || formatSupport == FORMAT_UNSUPPORTED_SUBTYPE) {
return formatSupport; return formatSupport;
} }
return ADAPTIVE_NOT_SEAMLESS | formatSupport; int tunnelingSupport = Util.SDK_INT >= 21 ? TUNNELING_SUPPORTED : TUNNELING_NOT_SUPPORTED;
return ADAPTIVE_NOT_SEAMLESS | tunnelingSupport | formatSupport;
} }
/** /**
......
...@@ -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, false); return mediaCodecSelector.getDecoderInfo(format.sampleMimeType, requiresSecureDecoder);
} }
/** /**
......
...@@ -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)
boolean requiresTunneling) throws DecoderQueryException { throws DecoderQueryException {
return MediaCodecUtil.getDecoderInfo(mimeType, requiresSecureDecoder, requiresTunneling); return MediaCodecUtil.getDecoderInfo(mimeType, requiresSecureDecoder);
} }
@Override @Override
...@@ -46,13 +46,11 @@ public interface MediaCodecSelector { ...@@ -46,13 +46,11 @@ 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 exists.
* @return A {@link MediaCodecInfo} describing the decoder, or null if no suitable decoder
* 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)
boolean requiresTunneling) throws DecoderQueryException; throws DecoderQueryException;
/** /**
* Selects a decoder to instantiate for audio passthrough. * Selects a decoder to instantiate for audio passthrough.
......
...@@ -81,9 +81,8 @@ public final class MediaCodecUtil { ...@@ -81,9 +81,8 @@ 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 * Calling this method may speed up subsequent calls to {@link #getDecoderInfo(String, boolean)}
* {@link #getDecoderInfo(String, boolean, boolean)} and * and {@link #getDecoderInfos(String, boolean)}.
* {@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
...@@ -115,26 +114,14 @@ public final class MediaCodecUtil { ...@@ -115,26 +114,14 @@ 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, boolean tunneling) public static MediaCodecInfo getDecoderInfo(String mimeType, boolean secure)
throws DecoderQueryException { throws DecoderQueryException {
List<MediaCodecInfo> decoderInfos = getDecoderInfos(mimeType, secure); List<MediaCodecInfo> decoderInfos = getDecoderInfos(mimeType, secure);
if (tunneling) { return decoderInfos.isEmpty() ? null : decoderInfos.get(0);
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);
}
} }
/** /**
...@@ -305,7 +292,7 @@ public final class MediaCodecUtil { ...@@ -305,7 +292,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, false); MediaCodecInfo decoderInfo = getDecoderInfo(MimeTypes.VIDEO_H264, 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, false); requiresSecureDecryption);
if (decoderInfo == null) { if (decoderInfo == null) {
return FORMAT_UNSUPPORTED_SUBTYPE; return FORMAT_UNSUPPORTED_SUBTYPE;
} }
...@@ -196,8 +196,9 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer { ...@@ -196,8 +196,9 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer {
} }
int adaptiveSupport = decoderInfo.adaptive ? ADAPTIVE_SEAMLESS : ADAPTIVE_NOT_SEAMLESS; int adaptiveSupport = decoderInfo.adaptive ? ADAPTIVE_SEAMLESS : ADAPTIVE_NOT_SEAMLESS;
int tunnelingSupport = decoderInfo.tunneling ? TUNNELING_SUPPORTED : TUNNELING_NOT_SUPPORTED;
int formatSupport = decoderCapable ? FORMAT_HANDLED : FORMAT_EXCEEDS_CAPABILITIES; int formatSupport = decoderCapable ? FORMAT_HANDLED : FORMAT_EXCEEDS_CAPABILITIES;
return adaptiveSupport | formatSupport; return adaptiveSupport | tunnelingSupport | formatSupport;
} }
@Override @Override
......
...@@ -634,7 +634,7 @@ public final class DashTest extends ActivityInstrumentationTestCase2<HostActivit ...@@ -634,7 +634,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, false); MediaCodecInfo decoderInfo = MediaCodecUtil.getDecoderInfo(mimeType, false);
assertNotNull(decoderInfo); assertNotNull(decoderInfo);
if (decoderInfo.adaptive) { if (decoderInfo.adaptive) {
return false; return false;
...@@ -707,8 +707,7 @@ public final class DashTest extends ActivityInstrumentationTestCase2<HostActivit ...@@ -707,8 +707,7 @@ 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 = boolean forceL3Widevine = MediaCodecUtil.getDecoderInfo(videoMimeType, true) == null;
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