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
if (allowPassthrough(mimeType) && mediaCodecSelector.getPassthroughDecoderInfo() != null) {
return ADAPTIVE_NOT_SEAMLESS | FORMAT_HANDLED;
}
MediaCodecInfo decoderInfo = mediaCodecSelector.getDecoderInfo(mimeType, false);
MediaCodecInfo decoderInfo = mediaCodecSelector.getDecoderInfo(mimeType, false, false);
if (decoderInfo == null) {
return FORMAT_UNSUPPORTED_SUBTYPE;
}
......
......@@ -51,6 +51,14 @@ public final class MediaCodecInfo {
*/
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 CodecCapabilities capabilities;
......@@ -86,6 +94,7 @@ public final class MediaCodecInfo {
this.mimeType = mimeType;
this.capabilities = capabilities;
adaptive = capabilities != null && isAdaptive(capabilities);
tunneling = capabilities != null && isTunneling(capabilities);
}
/**
......@@ -270,4 +279,13 @@ public final class MediaCodecInfo {
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 {
*/
protected MediaCodecInfo getDecoderInfo(MediaCodecSelector mediaCodecSelector,
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 {
return Util.SDK_INT < 24
&& ("OMX.Nvidia.h264.decode".equals(name) || "OMX.Nvidia.h264.decode.secure".equals(name))
&& ("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 {
MediaCodecSelector DEFAULT = new MediaCodecSelector() {
@Override
public MediaCodecInfo getDecoderInfo(String mimeType, boolean requiresSecureDecoder)
throws DecoderQueryException {
return MediaCodecUtil.getDecoderInfo(mimeType, requiresSecureDecoder);
public MediaCodecInfo getDecoderInfo(String mimeType, boolean requiresSecureDecoder,
boolean requiresTunneling) throws DecoderQueryException {
return MediaCodecUtil.getDecoderInfo(mimeType, requiresSecureDecoder, requiresTunneling);
}
@Override
......@@ -46,12 +46,13 @@ public interface MediaCodecSelector {
*
* @param mimeType The mime type for which a 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.
* @throws DecoderQueryException Thrown if there was an error querying decoders.
*/
MediaCodecInfo getDecoderInfo(String mimeType, boolean requiresSecureDecoder)
throws DecoderQueryException;
MediaCodecInfo getDecoderInfo(String mimeType, boolean requiresSecureDecoder,
boolean requiresTunneling) throws DecoderQueryException;
/**
* Selects a decoder to instantiate for audio passthrough.
......
......@@ -81,7 +81,9 @@ public final class MediaCodecUtil {
/**
* Optional call to warm the codec cache for a given mime type.
* <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 secure Whether the decoder is required to support secure decryption. Always pass false
......@@ -113,14 +115,26 @@ public final class MediaCodecUtil {
* @param mimeType The mime type.
* @param secure Whether the decoder is required to support secure decryption. Always pass false
* 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
* exists.
* @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 {
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 {
boolean secure = mediaCodecList.isSecurePlaybackSupported(mimeType, capabilities);
if ((secureDecodersExplicit && key.secure == secure)
|| (!secureDecodersExplicit && !key.secure)) {
decoderInfos.add(
MediaCodecInfo.newInstance(codecName, mimeType, capabilities));
decoderInfos.add(MediaCodecInfo.newInstance(codecName, mimeType, capabilities));
} else if (!secureDecodersExplicit && secure) {
decoderInfos.add(MediaCodecInfo.newInstance(codecName + ".secure",
mimeType, capabilities));
decoderInfos.add(MediaCodecInfo.newInstance(codecName + ".secure", mimeType,
capabilities));
// It only makes sense to have one synthesized secure decoder, return immediately.
return decoderInfos;
}
......@@ -292,7 +305,7 @@ public final class MediaCodecUtil {
public static int maxH264DecodableFrameSize() throws DecoderQueryException {
if (maxH264DecodableFrameSize == -1) {
int result = 0;
MediaCodecInfo decoderInfo = getDecoderInfo(MimeTypes.VIDEO_H264, false);
MediaCodecInfo decoderInfo = getDecoderInfo(MimeTypes.VIDEO_H264, false, false);
if (decoderInfo != null) {
for (CodecProfileLevel profileLevel : decoderInfo.getProfileLevels()) {
result = Math.max(avcLevelToMaxFrameSize(profileLevel.level), result);
......
......@@ -172,7 +172,7 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer {
}
}
MediaCodecInfo decoderInfo = mediaCodecSelector.getDecoderInfo(mimeType,
requiresSecureDecryption);
requiresSecureDecryption, false);
if (decoderInfo == null) {
return FORMAT_UNSUPPORTED_SUBTYPE;
}
......
......@@ -633,7 +633,7 @@ public final class DashTest extends ActivityInstrumentationTestCase2<HostActivit
}
private static boolean shouldSkipAdaptiveTest(String mimeType) throws DecoderQueryException {
MediaCodecInfo decoderInfo = MediaCodecUtil.getDecoderInfo(mimeType, false);
MediaCodecInfo decoderInfo = MediaCodecUtil.getDecoderInfo(mimeType, false, false);
assertNotNull(decoderInfo);
if (decoderInfo.adaptive) {
return false;
......@@ -706,7 +706,8 @@ public final class DashTest extends ActivityInstrumentationTestCase2<HostActivit
if (isWidevineEncrypted) {
try {
// 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);
String securityProperty = mediaDrm.getPropertyString(SECURITY_LEVEL_PROPERTY);
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