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 {
if (!mimeType.equals(codecMimeType)) {
return false;
}
if (!codecMimeType.equals(MimeTypes.VIDEO_H265)) {
return true;
}
Pair<Integer, Integer> codecProfileAndLevel = MediaCodecUtil.getCodecProfileAndLevel(codec);
if (codecProfileAndLevel == null) {
// If we don't know any better, we assume that the profile and level are supported.
......
......@@ -29,7 +29,6 @@ import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
......@@ -58,16 +57,21 @@ public final class MediaCodecUtil {
private static final String TAG = "MediaCodecUtil";
private static final MediaCodecInfo PASSTHROUGH_DECODER_INFO =
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 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.
private static int maxH264DecodableFrameSize = -1;
......@@ -305,7 +309,7 @@ public final class MediaCodecUtil {
*
* @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
* supported, null otherwise.
* recognized, or null otherwise
*/
public static Pair<Integer, Integer> getCodecProfileAndLevel(String codec) {
if (codec == null) {
......@@ -360,25 +364,35 @@ public final class MediaCodecUtil {
Log.w(TAG, "Ignoring malformed AVC codec string: " + codec);
return null;
}
int profile;
String profileString = codecsParts[1].substring(0, 2).toUpperCase(Locale.US);
if ("42".equals(profileString)) {
profile = CodecProfileLevel.AVCProfileBaseline;
} else if ("4D".equals(profileString)) {
profile = CodecProfileLevel.AVCProfileMain;
} else if ("58".equals(profileString)) {
profile = CodecProfileLevel.AVCProfileExtended;
} else if ("64".equals(profileString)) {
profile = CodecProfileLevel.AVCProfileHigh;
} else {
Log.w(TAG, "Unknown AVC profile string: " + profileString);
Integer profileInteger = null;
Integer levelInteger = null;
try {
if (codecsParts[1].length() == 6) {
// Format: avc1.xxccyy, where xx is profile and yy level, both hexadecimal.
profileInteger = Integer.parseInt(codecsParts[1].substring(0, 2), 16);
levelInteger = Integer.parseInt(codecsParts[1].substring(4), 16);
} else if (codecsParts.length >= 3) {
// Format: avc1.xx.[y]yy where xx is profile and [y]yy level, both decimal.
profileInteger = Integer.parseInt(codecsParts[1]);
levelInteger = Integer.parseInt(codecsParts[2]);
} 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;
}
String levelString = codecsParts[1].substring(4).toUpperCase(Locale.US);
Integer level = AVC_CODEC_STRING_TO_PROFILE_LEVEL.get(levelString);
Integer profile = AVC_PROFILE_NUMBER_TO_CONST.get(profileInteger);
if (profile == null) {
Log.w(TAG, "Unknown AVC profile: " + profileInteger);
return null;
}
Integer level = AVC_LEVEL_NUMBER_TO_CONST.get(levelInteger);
if (level == null) {
Log.w(TAG, "Unknown AVC level string: " + levelString);
Log.w(TAG, "Unknown AVC level: " + levelInteger);
return null;
}
return new Pair<>(profile, level);
......@@ -541,24 +555,30 @@ public final class MediaCodecUtil {
}
static {
AVC_CODEC_STRING_TO_PROFILE_LEVEL = new HashMap<>();
AVC_CODEC_STRING_TO_PROFILE_LEVEL.put("01", CodecProfileLevel.AVCLevel1);
// TODO: Find string for CodecProfileLevel.AVCLevel1b.
AVC_CODEC_STRING_TO_PROFILE_LEVEL.put("0B", CodecProfileLevel.AVCLevel11);
AVC_CODEC_STRING_TO_PROFILE_LEVEL.put("0C", CodecProfileLevel.AVCLevel12);
AVC_CODEC_STRING_TO_PROFILE_LEVEL.put("0D", CodecProfileLevel.AVCLevel13);
AVC_CODEC_STRING_TO_PROFILE_LEVEL.put("14", CodecProfileLevel.AVCLevel2);
AVC_CODEC_STRING_TO_PROFILE_LEVEL.put("15", CodecProfileLevel.AVCLevel21);
AVC_CODEC_STRING_TO_PROFILE_LEVEL.put("16", CodecProfileLevel.AVCLevel22);
AVC_CODEC_STRING_TO_PROFILE_LEVEL.put("1E", CodecProfileLevel.AVCLevel3);
AVC_CODEC_STRING_TO_PROFILE_LEVEL.put("1F", CodecProfileLevel.AVCLevel31);
AVC_CODEC_STRING_TO_PROFILE_LEVEL.put("20", CodecProfileLevel.AVCLevel32);
AVC_CODEC_STRING_TO_PROFILE_LEVEL.put("32", CodecProfileLevel.AVCLevel4);
AVC_CODEC_STRING_TO_PROFILE_LEVEL.put("33", CodecProfileLevel.AVCLevel41);
AVC_CODEC_STRING_TO_PROFILE_LEVEL.put("34", CodecProfileLevel.AVCLevel42);
AVC_CODEC_STRING_TO_PROFILE_LEVEL.put("3C", CodecProfileLevel.AVCLevel5);
AVC_CODEC_STRING_TO_PROFILE_LEVEL.put("3D", CodecProfileLevel.AVCLevel51);
AVC_CODEC_STRING_TO_PROFILE_LEVEL.put("3E", CodecProfileLevel.AVCLevel52);
AVC_PROFILE_NUMBER_TO_CONST = new HashMap<>();
AVC_PROFILE_NUMBER_TO_CONST.put(66, CodecProfileLevel.AVCProfileBaseline);
AVC_PROFILE_NUMBER_TO_CONST.put(77, CodecProfileLevel.AVCProfileMain);
AVC_PROFILE_NUMBER_TO_CONST.put(88, CodecProfileLevel.AVCProfileExtended);
AVC_PROFILE_NUMBER_TO_CONST.put(100, CodecProfileLevel.AVCProfileHigh);
AVC_LEVEL_NUMBER_TO_CONST = new HashMap<>();
AVC_LEVEL_NUMBER_TO_CONST.put(10, CodecProfileLevel.AVCLevel1);
// TODO: Find int for CodecProfileLevel.AVCLevel1b.
AVC_LEVEL_NUMBER_TO_CONST.put(11, CodecProfileLevel.AVCLevel11);
AVC_LEVEL_NUMBER_TO_CONST.put(12, CodecProfileLevel.AVCLevel12);
AVC_LEVEL_NUMBER_TO_CONST.put(13, CodecProfileLevel.AVCLevel13);
AVC_LEVEL_NUMBER_TO_CONST.put(20, CodecProfileLevel.AVCLevel2);
AVC_LEVEL_NUMBER_TO_CONST.put(21, CodecProfileLevel.AVCLevel21);
AVC_LEVEL_NUMBER_TO_CONST.put(22, CodecProfileLevel.AVCLevel22);
AVC_LEVEL_NUMBER_TO_CONST.put(30, CodecProfileLevel.AVCLevel3);
AVC_LEVEL_NUMBER_TO_CONST.put(31, CodecProfileLevel.AVCLevel31);
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.put("L30", CodecProfileLevel.HEVCMainTierLevel1);
......
......@@ -187,8 +187,8 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer {
return FORMAT_UNSUPPORTED_SUBTYPE;
}
boolean decoderCapable;
if (format.width > 0 && format.height > 0) {
boolean decoderCapable = decoderInfo.isCodecSupported(format.codecs);
if (decoderCapable && format.width > 0 && format.height > 0) {
if (Util.SDK_INT >= 21) {
if (format.frameRate > 0) {
decoderCapable = decoderInfo.isVideoSizeAndRateSupportedV21(format.width, format.height,
......@@ -196,13 +196,9 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer {
} else {
decoderCapable = decoderInfo.isVideoSizeSupportedV21(format.width, format.height);
}
decoderCapable &= decoderInfo.isCodecSupported(format.codecs);
} else {
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;
......
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