Handle alternative DV MIME types

Also detect ISOBMFF brand for DV when sniffing.

PiperOrigin-RevId: 233433449
This commit is contained in:
andrewlewis 2019-02-11 18:29:18 +00:00 committed by Andrew Lewis
parent a21572f0dd
commit ad69a93708
2 changed files with 96 additions and 54 deletions

View File

@ -30,7 +30,8 @@ import java.io.IOException;
/** The maximum number of bytes to peek when sniffing. */ /** The maximum number of bytes to peek when sniffing. */
private static final int SEARCH_LENGTH = 4 * 1024; private static final int SEARCH_LENGTH = 4 * 1024;
private static final int[] COMPATIBLE_BRANDS = new int[] { private static final int[] COMPATIBLE_BRANDS =
new int[] {
Util.getIntegerCodeForString("isom"), Util.getIntegerCodeForString("isom"),
Util.getIntegerCodeForString("iso2"), Util.getIntegerCodeForString("iso2"),
Util.getIntegerCodeForString("iso3"), Util.getIntegerCodeForString("iso3"),
@ -55,6 +56,7 @@ import java.io.IOException;
Util.getIntegerCodeForString("M4VP"), Util.getIntegerCodeForString("M4VP"),
Util.getIntegerCodeForString("qt "), // Apple QuickTime Util.getIntegerCodeForString("qt "), // Apple QuickTime
Util.getIntegerCodeForString("MSNV"), // Sony PSP Util.getIntegerCodeForString("MSNV"), // Sony PSP
Util.getIntegerCodeForString("dby1"), // Dolby Vision
}; };
/** /**

View File

@ -250,20 +250,22 @@ public final class MediaCodecUtil {
for (int i = 0; i < numberOfCodecs; i++) { for (int i = 0; i < numberOfCodecs; i++) {
android.media.MediaCodecInfo codecInfo = mediaCodecList.getCodecInfoAt(i); android.media.MediaCodecInfo codecInfo = mediaCodecList.getCodecInfoAt(i);
String codecName = codecInfo.getName(); String codecName = codecInfo.getName();
if (isCodecUsableDecoder(codecInfo, codecName, secureDecodersExplicit, requestedMimeType)) { String codecSupportedType =
for (String supportedType : codecInfo.getSupportedTypes()) { getCodecSupportedType(codecInfo, codecName, secureDecodersExplicit, requestedMimeType);
if (supportedType.equalsIgnoreCase(mimeType)) { if (codecSupportedType != null) {
try { try {
CodecCapabilities capabilities = codecInfo.getCapabilitiesForType(supportedType); CodecCapabilities capabilities = codecInfo.getCapabilitiesForType(codecSupportedType);
boolean secure = mediaCodecList.isSecurePlaybackSupported(mimeType, capabilities); boolean secure = mediaCodecList.isSecurePlaybackSupported(mimeType, capabilities);
boolean forceDisableAdaptive = codecNeedsDisableAdaptationWorkaround(codecName); boolean forceDisableAdaptive = codecNeedsDisableAdaptationWorkaround(codecName);
if ((secureDecodersExplicit && key.secure == secure) if ((secureDecodersExplicit && key.secure == secure)
|| (!secureDecodersExplicit && !key.secure)) { || (!secureDecodersExplicit && !key.secure)) {
decoderInfos.add(MediaCodecInfo.newInstance(codecName, mimeType, capabilities, decoderInfos.add(
forceDisableAdaptive, false)); MediaCodecInfo.newInstance(
codecName, mimeType, capabilities, forceDisableAdaptive, false));
} else if (!secureDecodersExplicit && secure) { } else if (!secureDecodersExplicit && secure) {
decoderInfos.add(MediaCodecInfo.newInstance(codecName + ".secure", mimeType, decoderInfos.add(
capabilities, forceDisableAdaptive, true)); MediaCodecInfo.newInstance(
codecName + ".secure", mimeType, capabilities, forceDisableAdaptive, true));
// 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;
} }
@ -274,14 +276,12 @@ public final class MediaCodecUtil {
} else { } else {
// Rethrow error querying primary codec capabilities, or secondary codec // Rethrow error querying primary codec capabilities, or secondary codec
// capabilities if API level is greater than 23. // capabilities if API level is greater than 23.
Log.e(TAG, "Failed to query codec " + codecName + " (" + supportedType + ")"); Log.e(TAG, "Failed to query codec " + codecName + " (" + codecSupportedType + ")");
throw e; throw e;
} }
} }
} }
} }
}
}
return decoderInfos; return decoderInfos;
} catch (Exception e) { } catch (Exception e) {
// If the underlying mediaserver is in a bad state, we may catch an IllegalStateException // If the underlying mediaserver is in a bad state, we may catch an IllegalStateException
@ -290,6 +290,46 @@ public final class MediaCodecUtil {
} }
} }
/**
* Returns the codec's supported type for decoding {@code requestedMimeType} on the current
* device, or {@code null} if the codec can't be used.
*
* @param info The codec information.
* @param name The name of the codec
* @param secureDecodersExplicit Whether secure decoders were explicitly listed, if present.
* @param requestedMimeType The originally requested MIME type, which may differ from the codec
* key MIME type if the codec key is being considered as a fallback.
* @return The codec's supported type for decoding {@code requestedMimeType}, or {@code null} if
* the codec can't be used.
*/
@Nullable
private static String getCodecSupportedType(
android.media.MediaCodecInfo info,
String name,
boolean secureDecodersExplicit,
String requestedMimeType) {
if (isCodecUsableDecoder(info, name, secureDecodersExplicit, requestedMimeType)) {
if (requestedMimeType.equals(MimeTypes.VIDEO_DOLBY_VISION)) {
// Handle decoders that declare support for DV via MIME types that aren't
// video/dolby-vision.
if ("OMX.MS.HEVCDV.Decoder".equals(name)) {
return "video/hevcdv";
} else if ("OMX.RTK.video.decoder".equals(name)
|| "OMX.realtek.video.decoder.tunneled".equals(name)) {
return "video/dv_hevc";
}
}
String[] supportedTypes = info.getSupportedTypes();
for (String supportedType : supportedTypes) {
if (supportedType.equalsIgnoreCase(requestedMimeType)) {
return supportedType;
}
}
}
return null;
}
/** /**
* Returns whether the specified codec is usable for decoding on the current device. * Returns whether the specified codec is usable for decoding on the current device.
* *