Move adaptation disabling workaround into MediaCodecUtil
This is necessary to make sure that the correct thing happens where MediaCodecInfo.adaptive is queried directly (for example, MediaCodecVideoRenderer uses the field to determine how to size input buffers). Also disable adaptive on Nexus 10. Issue: #2806 ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=157583473
This commit is contained in:
parent
0f27efae44
commit
ea21af2ce9
@ -71,7 +71,7 @@ public final class MediaCodecInfo {
|
||||
* @return The created instance.
|
||||
*/
|
||||
public static MediaCodecInfo newPassthroughInstance(String name) {
|
||||
return new MediaCodecInfo(name, null, null);
|
||||
return new MediaCodecInfo(name, null, null, false);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -84,18 +84,29 @@ public final class MediaCodecInfo {
|
||||
*/
|
||||
public static MediaCodecInfo newInstance(String name, String mimeType,
|
||||
CodecCapabilities capabilities) {
|
||||
return new MediaCodecInfo(name, mimeType, capabilities);
|
||||
return new MediaCodecInfo(name, mimeType, capabilities, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param name The name of the decoder.
|
||||
* @param capabilities The capabilities of the decoder.
|
||||
* Creates an instance.
|
||||
*
|
||||
* @param name The name of the {@link MediaCodec}.
|
||||
* @param mimeType A mime type supported by the {@link MediaCodec}.
|
||||
* @param capabilities The capabilities of the {@link MediaCodec} for the specified mime type.
|
||||
* @param forceDisableAdaptive Whether {@link #adaptive} should be forced to {@code false}.
|
||||
* @return The created instance.
|
||||
*/
|
||||
private MediaCodecInfo(String name, String mimeType, CodecCapabilities capabilities) {
|
||||
public static MediaCodecInfo newInstance(String name, String mimeType,
|
||||
CodecCapabilities capabilities, boolean forceDisableAdaptive) {
|
||||
return new MediaCodecInfo(name, mimeType, capabilities, forceDisableAdaptive);
|
||||
}
|
||||
|
||||
private MediaCodecInfo(String name, String mimeType, CodecCapabilities capabilities,
|
||||
boolean forceDisableAdaptive) {
|
||||
this.name = Assertions.checkNotNull(name);
|
||||
this.mimeType = mimeType;
|
||||
this.capabilities = capabilities;
|
||||
adaptive = capabilities != null && isAdaptive(capabilities);
|
||||
adaptive = !forceDisableAdaptive && capabilities != null && isAdaptive(capabilities);
|
||||
tunneling = capabilities != null && isTunneling(capabilities);
|
||||
}
|
||||
|
||||
|
@ -339,7 +339,7 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
|
||||
}
|
||||
|
||||
String codecName = decoderInfo.name;
|
||||
codecIsAdaptive = decoderInfo.adaptive && !codecNeedsDisableAdaptationWorkaround(codecName);
|
||||
codecIsAdaptive = decoderInfo.adaptive;
|
||||
codecNeedsDiscardToSpsWorkaround = codecNeedsDiscardToSpsWorkaround(codecName, format);
|
||||
codecNeedsFlushWorkaround = codecNeedsFlushWorkaround(codecName);
|
||||
codecNeedsAdaptationWorkaround = codecNeedsAdaptationWorkaround(codecName);
|
||||
@ -1188,18 +1188,4 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
|
||||
&& "OMX.MTK.AUDIO.DECODER.MP3".equals(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the decoder is known to fail when adapting, despite advertising itself as an
|
||||
* adaptive decoder.
|
||||
* <p>
|
||||
* If true is returned then we explicitly disable adaptation for the decoder.
|
||||
*
|
||||
* @param name The decoder name.
|
||||
* @return True if the decoder is known to fail when adapting.
|
||||
*/
|
||||
private static boolean codecNeedsDisableAdaptationWorkaround(String name) {
|
||||
return Util.SDK_INT <= 19 && Util.MODEL.equals("ODROID-XU3")
|
||||
&& ("OMX.Exynos.AVC.Decoder".equals(name) || "OMX.Exynos.AVC.Decoder.secure".equals(name));
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -160,6 +160,55 @@ public final class MediaCodecUtil {
|
||||
return decoderInfos;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the maximum frame size supported by the default H264 decoder.
|
||||
*
|
||||
* @return The maximum frame size for an H264 stream that can be decoded on the device.
|
||||
*/
|
||||
public static int maxH264DecodableFrameSize() throws DecoderQueryException {
|
||||
if (maxH264DecodableFrameSize == -1) {
|
||||
int result = 0;
|
||||
MediaCodecInfo decoderInfo = getDecoderInfo(MimeTypes.VIDEO_H264, false);
|
||||
if (decoderInfo != null) {
|
||||
for (CodecProfileLevel profileLevel : decoderInfo.getProfileLevels()) {
|
||||
result = Math.max(avcLevelToMaxFrameSize(profileLevel.level), result);
|
||||
}
|
||||
// We assume support for at least 480p (SDK_INT >= 21) or 360p (SDK_INT < 21), which are
|
||||
// the levels mandated by the Android CDD.
|
||||
result = Math.max(result, Util.SDK_INT >= 21 ? (720 * 480) : (480 * 360));
|
||||
}
|
||||
maxH264DecodableFrameSize = result;
|
||||
}
|
||||
return maxH264DecodableFrameSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns profile and level (as defined by {@link CodecProfileLevel}) corresponding to the given
|
||||
* codec description string (as defined by RFC 6381).
|
||||
*
|
||||
* @param codec A codec description string, as defined by RFC 6381.
|
||||
* @return A pair (profile constant, level constant) if {@code codec} is well-formed and
|
||||
* recognized, or null otherwise
|
||||
*/
|
||||
public static Pair<Integer, Integer> getCodecProfileAndLevel(String codec) {
|
||||
if (codec == null) {
|
||||
return null;
|
||||
}
|
||||
String[] parts = codec.split("\\.");
|
||||
switch (parts[0]) {
|
||||
case CODEC_ID_HEV1:
|
||||
case CODEC_ID_HVC1:
|
||||
return getHevcProfileAndLevel(codec, parts);
|
||||
case CODEC_ID_AVC1:
|
||||
case CODEC_ID_AVC2:
|
||||
return getAvcProfileAndLevel(codec, parts);
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// Internal methods.
|
||||
|
||||
private static List<MediaCodecInfo> getDecoderInfosInternal(
|
||||
CodecKey key, MediaCodecListCompat mediaCodecList) throws DecoderQueryException {
|
||||
try {
|
||||
@ -177,12 +226,14 @@ public final class MediaCodecUtil {
|
||||
try {
|
||||
CodecCapabilities capabilities = codecInfo.getCapabilitiesForType(supportedType);
|
||||
boolean secure = mediaCodecList.isSecurePlaybackSupported(mimeType, capabilities);
|
||||
boolean forceDisableAdaptive = codecNeedsDisableAdaptationWorkaround(codecName);
|
||||
if ((secureDecodersExplicit && key.secure == secure)
|
||||
|| (!secureDecodersExplicit && !key.secure)) {
|
||||
decoderInfos.add(MediaCodecInfo.newInstance(codecName, mimeType, capabilities));
|
||||
decoderInfos.add(MediaCodecInfo.newInstance(codecName, mimeType, capabilities,
|
||||
forceDisableAdaptive));
|
||||
} else if (!secureDecodersExplicit && secure) {
|
||||
decoderInfos.add(MediaCodecInfo.newInstance(codecName + ".secure", mimeType,
|
||||
capabilities));
|
||||
capabilities, forceDisableAdaptive));
|
||||
// It only makes sense to have one synthesized secure decoder, return immediately.
|
||||
return decoderInfos;
|
||||
}
|
||||
@ -289,50 +340,16 @@ public final class MediaCodecUtil {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the maximum frame size supported by the default H264 decoder.
|
||||
* Returns whether the decoder is known to fail when adapting, despite advertising itself as an
|
||||
* adaptive decoder.
|
||||
*
|
||||
* @return The maximum frame size for an H264 stream that can be decoded on the device.
|
||||
* @param name The decoder name.
|
||||
* @return True if the decoder is known to fail when adapting.
|
||||
*/
|
||||
public static int maxH264DecodableFrameSize() throws DecoderQueryException {
|
||||
if (maxH264DecodableFrameSize == -1) {
|
||||
int result = 0;
|
||||
MediaCodecInfo decoderInfo = getDecoderInfo(MimeTypes.VIDEO_H264, false);
|
||||
if (decoderInfo != null) {
|
||||
for (CodecProfileLevel profileLevel : decoderInfo.getProfileLevels()) {
|
||||
result = Math.max(avcLevelToMaxFrameSize(profileLevel.level), result);
|
||||
}
|
||||
// We assume support for at least 480p (SDK_INT >= 21) or 360p (SDK_INT < 21), which are
|
||||
// the levels mandated by the Android CDD.
|
||||
result = Math.max(result, Util.SDK_INT >= 21 ? (720 * 480) : (480 * 360));
|
||||
}
|
||||
maxH264DecodableFrameSize = result;
|
||||
}
|
||||
return maxH264DecodableFrameSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns profile and level (as defined by {@link CodecProfileLevel}) corresponding to the given
|
||||
* codec description string (as defined by RFC 6381).
|
||||
*
|
||||
* @param codec A codec description string, as defined by RFC 6381.
|
||||
* @return A pair (profile constant, level constant) if {@code codec} is well-formed and
|
||||
* recognized, or null otherwise
|
||||
*/
|
||||
public static Pair<Integer, Integer> getCodecProfileAndLevel(String codec) {
|
||||
if (codec == null) {
|
||||
return null;
|
||||
}
|
||||
String[] parts = codec.split("\\.");
|
||||
switch (parts[0]) {
|
||||
case CODEC_ID_HEV1:
|
||||
case CODEC_ID_HVC1:
|
||||
return getHevcProfileAndLevel(codec, parts);
|
||||
case CODEC_ID_AVC1:
|
||||
case CODEC_ID_AVC2:
|
||||
return getAvcProfileAndLevel(codec, parts);
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
private static boolean codecNeedsDisableAdaptationWorkaround(String name) {
|
||||
return Util.SDK_INT <= 22
|
||||
&& (Util.MODEL.equals("ODROID-XU3") || Util.MODEL.equals("Nexus 10"))
|
||||
&& ("OMX.Exynos.AVC.Decoder".equals(name) || "OMX.Exynos.AVC.Decoder.secure".equals(name));
|
||||
}
|
||||
|
||||
private static Pair<Integer, Integer> getHevcProfileAndLevel(String codec, String[] parts) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user