Commit 32867217 by aquilescanta Committed by Santiago Seifert

Improve profile/level check support for AVC

Issue:#1772

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=132078273
parent da0bc332
...@@ -113,9 +113,6 @@ public final class MediaCodecInfo { ...@@ -113,9 +113,6 @@ public final class MediaCodecInfo {
if (!mimeType.equals(codecMimeType)) { if (!mimeType.equals(codecMimeType)) {
return false; return false;
} }
if (!codecMimeType.equals(MimeTypes.VIDEO_H265)) {
return true;
}
Pair<Integer, Integer> codecProfileAndLevel = MediaCodecUtil.getCodecProfileAndLevel(codec); Pair<Integer, Integer> codecProfileAndLevel = MediaCodecUtil.getCodecProfileAndLevel(codec);
if (codecProfileAndLevel == null) { if (codecProfileAndLevel == null) {
// If we don't know any better, we assume that the profile and level are supported. // If we don't know any better, we assume that the profile and level are supported.
......
...@@ -29,7 +29,6 @@ import java.util.ArrayList; ...@@ -29,7 +29,6 @@ import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Locale;
import java.util.Map; import java.util.Map;
import java.util.regex.Matcher; import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
...@@ -58,16 +57,21 @@ public final class MediaCodecUtil { ...@@ -58,16 +57,21 @@ public final class MediaCodecUtil {
private static final String TAG = "MediaCodecUtil"; private static final String TAG = "MediaCodecUtil";
private static final MediaCodecInfo PASSTHROUGH_DECODER_INFO = private static final MediaCodecInfo PASSTHROUGH_DECODER_INFO =
MediaCodecInfo.newPassthroughInstance("OMX.google.raw.decoder"); MediaCodecInfo.newPassthroughInstance("OMX.google.raw.decoder");
private static final Map<String, Integer> HEVC_CODEC_STRING_TO_PROFILE_LEVEL;
private static final Map<String, Integer> AVC_CODEC_STRING_TO_PROFILE_LEVEL;
private static final String CODEC_ID_HEV1 = "hev1";
private static final String CODEC_ID_HVC1 = "hvc1";
private static final String CODEC_ID_AVC1 = "avc1";
private static final String CODEC_ID_AVC2 = "avc2";
private static final Pattern PROFILE_PATTERN = Pattern.compile("^\\D?(\\d+)$"); private static final Pattern PROFILE_PATTERN = Pattern.compile("^\\D?(\\d+)$");
private static final HashMap<CodecKey, List<MediaCodecInfo>> decoderInfosCache = new HashMap<>(); private static final HashMap<CodecKey, List<MediaCodecInfo>> decoderInfosCache = new HashMap<>();
// Codecs to constant mappings.
// AVC.
private static final Map<Integer, Integer> AVC_PROFILE_NUMBER_TO_CONST;
private static final Map<Integer, Integer> AVC_LEVEL_NUMBER_TO_CONST;
private static final String CODEC_ID_AVC1 = "avc1";
private static final String CODEC_ID_AVC2 = "avc2";
// HEVC.
private static final Map<String, Integer> HEVC_CODEC_STRING_TO_PROFILE_LEVEL;
private static final String CODEC_ID_HEV1 = "hev1";
private static final String CODEC_ID_HVC1 = "hvc1";
// Lazily initialized. // Lazily initialized.
private static int maxH264DecodableFrameSize = -1; private static int maxH264DecodableFrameSize = -1;
...@@ -305,7 +309,7 @@ public final class MediaCodecUtil { ...@@ -305,7 +309,7 @@ public final class MediaCodecUtil {
* *
* @param codec A 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 * @return A pair (profile constant, level constant) if {@code codec} is well-formed and
* supported, null otherwise. * recognized, or null otherwise
*/ */
public static Pair<Integer, Integer> getCodecProfileAndLevel(String codec) { public static Pair<Integer, Integer> getCodecProfileAndLevel(String codec) {
if (codec == null) { if (codec == null) {
...@@ -360,25 +364,35 @@ public final class MediaCodecUtil { ...@@ -360,25 +364,35 @@ public final class MediaCodecUtil {
Log.w(TAG, "Ignoring malformed AVC codec string: " + codec); Log.w(TAG, "Ignoring malformed AVC codec string: " + codec);
return null; return null;
} }
int profile; Integer profileInteger = null;
String profileString = codecsParts[1].substring(0, 2).toUpperCase(Locale.US); Integer levelInteger = null;
if ("42".equals(profileString)) { try {
profile = CodecProfileLevel.AVCProfileBaseline; if (codecsParts[1].length() == 6) {
} else if ("4D".equals(profileString)) { // Format: avc1.xxccyy, where xx is profile and yy level, both hexadecimal.
profile = CodecProfileLevel.AVCProfileMain; profileInteger = Integer.parseInt(codecsParts[1].substring(0, 2), 16);
} else if ("58".equals(profileString)) { levelInteger = Integer.parseInt(codecsParts[1].substring(4), 16);
profile = CodecProfileLevel.AVCProfileExtended; } else if (codecsParts.length >= 3) {
} else if ("64".equals(profileString)) { // Format: avc1.xx.[y]yy where xx is profile and [y]yy level, both decimal.
profile = CodecProfileLevel.AVCProfileHigh; profileInteger = Integer.parseInt(codecsParts[1]);
} else { levelInteger = Integer.parseInt(codecsParts[2]);
Log.w(TAG, "Unknown AVC profile string: " + profileString); } else {
// We don't recognize the format.
Log.w(TAG, "Ignoring malformed AVC codec string: " + codec);
return null;
}
} catch (NumberFormatException e) {
Log.w(TAG, "Ignoring malformed AVC codec string: " + codec);
return null; return null;
} }
String levelString = codecsParts[1].substring(4).toUpperCase(Locale.US); Integer profile = AVC_PROFILE_NUMBER_TO_CONST.get(profileInteger);
Integer level = AVC_CODEC_STRING_TO_PROFILE_LEVEL.get(levelString); if (profile == null) {
Log.w(TAG, "Unknown AVC profile: " + profileInteger);
return null;
}
Integer level = AVC_LEVEL_NUMBER_TO_CONST.get(levelInteger);
if (level == null) { if (level == null) {
Log.w(TAG, "Unknown AVC level string: " + levelString); Log.w(TAG, "Unknown AVC level: " + levelInteger);
return null; return null;
} }
return new Pair<>(profile, level); return new Pair<>(profile, level);
...@@ -541,24 +555,30 @@ public final class MediaCodecUtil { ...@@ -541,24 +555,30 @@ public final class MediaCodecUtil {
} }
static { static {
AVC_CODEC_STRING_TO_PROFILE_LEVEL = new HashMap<>(); AVC_PROFILE_NUMBER_TO_CONST = new HashMap<>();
AVC_CODEC_STRING_TO_PROFILE_LEVEL.put("01", CodecProfileLevel.AVCLevel1); AVC_PROFILE_NUMBER_TO_CONST.put(66, CodecProfileLevel.AVCProfileBaseline);
// TODO: Find string for CodecProfileLevel.AVCLevel1b. AVC_PROFILE_NUMBER_TO_CONST.put(77, CodecProfileLevel.AVCProfileMain);
AVC_CODEC_STRING_TO_PROFILE_LEVEL.put("0B", CodecProfileLevel.AVCLevel11); AVC_PROFILE_NUMBER_TO_CONST.put(88, CodecProfileLevel.AVCProfileExtended);
AVC_CODEC_STRING_TO_PROFILE_LEVEL.put("0C", CodecProfileLevel.AVCLevel12); AVC_PROFILE_NUMBER_TO_CONST.put(100, CodecProfileLevel.AVCProfileHigh);
AVC_CODEC_STRING_TO_PROFILE_LEVEL.put("0D", CodecProfileLevel.AVCLevel13);
AVC_CODEC_STRING_TO_PROFILE_LEVEL.put("14", CodecProfileLevel.AVCLevel2); AVC_LEVEL_NUMBER_TO_CONST = new HashMap<>();
AVC_CODEC_STRING_TO_PROFILE_LEVEL.put("15", CodecProfileLevel.AVCLevel21); AVC_LEVEL_NUMBER_TO_CONST.put(10, CodecProfileLevel.AVCLevel1);
AVC_CODEC_STRING_TO_PROFILE_LEVEL.put("16", CodecProfileLevel.AVCLevel22); // TODO: Find int for CodecProfileLevel.AVCLevel1b.
AVC_CODEC_STRING_TO_PROFILE_LEVEL.put("1E", CodecProfileLevel.AVCLevel3); AVC_LEVEL_NUMBER_TO_CONST.put(11, CodecProfileLevel.AVCLevel11);
AVC_CODEC_STRING_TO_PROFILE_LEVEL.put("1F", CodecProfileLevel.AVCLevel31); AVC_LEVEL_NUMBER_TO_CONST.put(12, CodecProfileLevel.AVCLevel12);
AVC_CODEC_STRING_TO_PROFILE_LEVEL.put("20", CodecProfileLevel.AVCLevel32); AVC_LEVEL_NUMBER_TO_CONST.put(13, CodecProfileLevel.AVCLevel13);
AVC_CODEC_STRING_TO_PROFILE_LEVEL.put("32", CodecProfileLevel.AVCLevel4); AVC_LEVEL_NUMBER_TO_CONST.put(20, CodecProfileLevel.AVCLevel2);
AVC_CODEC_STRING_TO_PROFILE_LEVEL.put("33", CodecProfileLevel.AVCLevel41); AVC_LEVEL_NUMBER_TO_CONST.put(21, CodecProfileLevel.AVCLevel21);
AVC_CODEC_STRING_TO_PROFILE_LEVEL.put("34", CodecProfileLevel.AVCLevel42); AVC_LEVEL_NUMBER_TO_CONST.put(22, CodecProfileLevel.AVCLevel22);
AVC_CODEC_STRING_TO_PROFILE_LEVEL.put("3C", CodecProfileLevel.AVCLevel5); AVC_LEVEL_NUMBER_TO_CONST.put(30, CodecProfileLevel.AVCLevel3);
AVC_CODEC_STRING_TO_PROFILE_LEVEL.put("3D", CodecProfileLevel.AVCLevel51); AVC_LEVEL_NUMBER_TO_CONST.put(31, CodecProfileLevel.AVCLevel31);
AVC_CODEC_STRING_TO_PROFILE_LEVEL.put("3E", CodecProfileLevel.AVCLevel52); AVC_LEVEL_NUMBER_TO_CONST.put(32, CodecProfileLevel.AVCLevel32);
AVC_LEVEL_NUMBER_TO_CONST.put(40, CodecProfileLevel.AVCLevel4);
AVC_LEVEL_NUMBER_TO_CONST.put(41, CodecProfileLevel.AVCLevel41);
AVC_LEVEL_NUMBER_TO_CONST.put(42, CodecProfileLevel.AVCLevel42);
AVC_LEVEL_NUMBER_TO_CONST.put(50, CodecProfileLevel.AVCLevel5);
AVC_LEVEL_NUMBER_TO_CONST.put(51, CodecProfileLevel.AVCLevel51);
AVC_LEVEL_NUMBER_TO_CONST.put(52, CodecProfileLevel.AVCLevel52);
HEVC_CODEC_STRING_TO_PROFILE_LEVEL = new HashMap<>(); HEVC_CODEC_STRING_TO_PROFILE_LEVEL = new HashMap<>();
HEVC_CODEC_STRING_TO_PROFILE_LEVEL.put("L30", CodecProfileLevel.HEVCMainTierLevel1); HEVC_CODEC_STRING_TO_PROFILE_LEVEL.put("L30", CodecProfileLevel.HEVCMainTierLevel1);
......
...@@ -187,8 +187,8 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer { ...@@ -187,8 +187,8 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer {
return FORMAT_UNSUPPORTED_SUBTYPE; return FORMAT_UNSUPPORTED_SUBTYPE;
} }
boolean decoderCapable; boolean decoderCapable = decoderInfo.isCodecSupported(format.codecs);
if (format.width > 0 && format.height > 0) { if (decoderCapable && format.width > 0 && format.height > 0) {
if (Util.SDK_INT >= 21) { if (Util.SDK_INT >= 21) {
if (format.frameRate > 0) { if (format.frameRate > 0) {
decoderCapable = decoderInfo.isVideoSizeAndRateSupportedV21(format.width, format.height, decoderCapable = decoderInfo.isVideoSizeAndRateSupportedV21(format.width, format.height,
...@@ -196,13 +196,9 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer { ...@@ -196,13 +196,9 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer {
} else { } else {
decoderCapable = decoderInfo.isVideoSizeSupportedV21(format.width, format.height); decoderCapable = decoderInfo.isVideoSizeSupportedV21(format.width, format.height);
} }
decoderCapable &= decoderInfo.isCodecSupported(format.codecs);
} else { } else {
decoderCapable = format.width * format.height <= MediaCodecUtil.maxH264DecodableFrameSize(); decoderCapable = format.width * format.height <= MediaCodecUtil.maxH264DecodableFrameSize();
} }
} else {
// We don't know any better, so assume true.
decoderCapable = true;
} }
int adaptiveSupport = decoderInfo.adaptive ? ADAPTIVE_SEAMLESS : ADAPTIVE_NOT_SEAMLESS; int adaptiveSupport = decoderInfo.adaptive ? ADAPTIVE_SEAMLESS : ADAPTIVE_NOT_SEAMLESS;
......
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