Extract AV1 streams in DASH (fMP4/Matroska)

PiperOrigin-RevId: 238983394
This commit is contained in:
andrewlewis 2019-03-18 14:41:44 +00:00 committed by Oliver Woodman
parent 3e4c15aa15
commit a5616cb552
6 changed files with 33 additions and 13 deletions

View File

@ -96,6 +96,7 @@ public class MatroskaExtractor implements Extractor {
private static final String DOC_TYPE_WEBM = "webm"; private static final String DOC_TYPE_WEBM = "webm";
private static final String CODEC_ID_VP8 = "V_VP8"; private static final String CODEC_ID_VP8 = "V_VP8";
private static final String CODEC_ID_VP9 = "V_VP9"; private static final String CODEC_ID_VP9 = "V_VP9";
private static final String CODEC_ID_AV1 = "V_AV1";
private static final String CODEC_ID_MPEG2 = "V_MPEG2"; private static final String CODEC_ID_MPEG2 = "V_MPEG2";
private static final String CODEC_ID_MPEG4_SP = "V_MPEG4/ISO/SP"; private static final String CODEC_ID_MPEG4_SP = "V_MPEG4/ISO/SP";
private static final String CODEC_ID_MPEG4_ASP = "V_MPEG4/ISO/ASP"; private static final String CODEC_ID_MPEG4_ASP = "V_MPEG4/ISO/ASP";
@ -1536,6 +1537,7 @@ public class MatroskaExtractor implements Extractor {
private static boolean isCodecSupported(String codecId) { private static boolean isCodecSupported(String codecId) {
return CODEC_ID_VP8.equals(codecId) return CODEC_ID_VP8.equals(codecId)
|| CODEC_ID_VP9.equals(codecId) || CODEC_ID_VP9.equals(codecId)
|| CODEC_ID_AV1.equals(codecId)
|| CODEC_ID_MPEG2.equals(codecId) || CODEC_ID_MPEG2.equals(codecId)
|| CODEC_ID_MPEG4_SP.equals(codecId) || CODEC_ID_MPEG4_SP.equals(codecId)
|| CODEC_ID_MPEG4_ASP.equals(codecId) || CODEC_ID_MPEG4_ASP.equals(codecId)
@ -1780,6 +1782,9 @@ public class MatroskaExtractor implements Extractor {
case CODEC_ID_VP9: case CODEC_ID_VP9:
mimeType = MimeTypes.VIDEO_VP9; mimeType = MimeTypes.VIDEO_VP9;
break; break;
case CODEC_ID_AV1:
mimeType = MimeTypes.VIDEO_AV1;
break;
case CODEC_ID_MPEG2: case CODEC_ID_MPEG2:
mimeType = MimeTypes.VIDEO_MPEG2; mimeType = MimeTypes.VIDEO_MPEG2;
break; break;

View File

@ -57,6 +57,11 @@ import java.util.List;
public static final int TYPE_hvc1 = Util.getIntegerCodeForString("hvc1"); public static final int TYPE_hvc1 = Util.getIntegerCodeForString("hvc1");
public static final int TYPE_hev1 = Util.getIntegerCodeForString("hev1"); public static final int TYPE_hev1 = Util.getIntegerCodeForString("hev1");
public static final int TYPE_hvcC = Util.getIntegerCodeForString("hvcC"); public static final int TYPE_hvcC = Util.getIntegerCodeForString("hvcC");
public static final int TYPE_vp08 = Util.getIntegerCodeForString("vp08");
public static final int TYPE_vp09 = Util.getIntegerCodeForString("vp09");
public static final int TYPE_vpcC = Util.getIntegerCodeForString("vpcC");
public static final int TYPE_av01 = Util.getIntegerCodeForString("av01");
public static final int TYPE_av1C = Util.getIntegerCodeForString("av1C");
public static final int TYPE_dvav = Util.getIntegerCodeForString("dvav"); public static final int TYPE_dvav = Util.getIntegerCodeForString("dvav");
public static final int TYPE_dva1 = Util.getIntegerCodeForString("dva1"); public static final int TYPE_dva1 = Util.getIntegerCodeForString("dva1");
public static final int TYPE_dvhe = Util.getIntegerCodeForString("dvhe"); public static final int TYPE_dvhe = Util.getIntegerCodeForString("dvhe");
@ -145,9 +150,6 @@ import java.util.List;
public static final int TYPE_st3d = Util.getIntegerCodeForString("st3d"); public static final int TYPE_st3d = Util.getIntegerCodeForString("st3d");
public static final int TYPE_sv3d = Util.getIntegerCodeForString("sv3d"); public static final int TYPE_sv3d = Util.getIntegerCodeForString("sv3d");
public static final int TYPE_proj = Util.getIntegerCodeForString("proj"); public static final int TYPE_proj = Util.getIntegerCodeForString("proj");
public static final int TYPE_vp08 = Util.getIntegerCodeForString("vp08");
public static final int TYPE_vp09 = Util.getIntegerCodeForString("vp09");
public static final int TYPE_vpcC = Util.getIntegerCodeForString("vpcC");
public static final int TYPE_camm = Util.getIntegerCodeForString("camm"); public static final int TYPE_camm = Util.getIntegerCodeForString("camm");
public static final int TYPE_alac = Util.getIntegerCodeForString("alac"); public static final int TYPE_alac = Util.getIntegerCodeForString("alac");
public static final int TYPE_alaw = Util.getIntegerCodeForString("alaw"); public static final int TYPE_alaw = Util.getIntegerCodeForString("alaw");

View File

@ -745,6 +745,7 @@ import java.util.List;
|| childAtomType == Atom.TYPE_s263 || childAtomType == Atom.TYPE_s263
|| childAtomType == Atom.TYPE_vp08 || childAtomType == Atom.TYPE_vp08
|| childAtomType == Atom.TYPE_vp09 || childAtomType == Atom.TYPE_vp09
|| childAtomType == Atom.TYPE_av01
|| childAtomType == Atom.TYPE_dvav || childAtomType == Atom.TYPE_dvav
|| childAtomType == Atom.TYPE_dva1 || childAtomType == Atom.TYPE_dva1
|| childAtomType == Atom.TYPE_dvhe || childAtomType == Atom.TYPE_dvhe
@ -902,6 +903,9 @@ import java.util.List;
} else if (childAtomType == Atom.TYPE_vpcC) { } else if (childAtomType == Atom.TYPE_vpcC) {
Assertions.checkState(mimeType == null); Assertions.checkState(mimeType == null);
mimeType = (atomType == Atom.TYPE_vp08) ? MimeTypes.VIDEO_VP8 : MimeTypes.VIDEO_VP9; mimeType = (atomType == Atom.TYPE_vp08) ? MimeTypes.VIDEO_VP8 : MimeTypes.VIDEO_VP9;
} else if (childAtomType == Atom.TYPE_av1C) {
Assertions.checkState(mimeType == null);
mimeType = MimeTypes.VIDEO_AV1;
} else if (childAtomType == Atom.TYPE_d263) { } else if (childAtomType == Atom.TYPE_d263) {
Assertions.checkState(mimeType == null); Assertions.checkState(mimeType == null);
mimeType = MimeTypes.VIDEO_H263; mimeType = MimeTypes.VIDEO_H263;

View File

@ -41,6 +41,7 @@ import java.io.IOException;
Util.getIntegerCodeForString("avc1"), Util.getIntegerCodeForString("avc1"),
Util.getIntegerCodeForString("hvc1"), Util.getIntegerCodeForString("hvc1"),
Util.getIntegerCodeForString("hev1"), Util.getIntegerCodeForString("hev1"),
Util.getIntegerCodeForString("av01"),
Util.getIntegerCodeForString("mp41"), Util.getIntegerCodeForString("mp41"),
Util.getIntegerCodeForString("mp42"), Util.getIntegerCodeForString("mp42"),
Util.getIntegerCodeForString("3g2a"), Util.getIntegerCodeForString("3g2a"),

View File

@ -110,7 +110,8 @@ public final class MediaCodecUtil {
* @return A {@link MediaCodecInfo} describing the decoder, or null if no suitable decoder exists. * @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. * @throws DecoderQueryException If there was an error querying the available decoders.
*/ */
public static @Nullable MediaCodecInfo getPassthroughDecoderInfo() throws DecoderQueryException { @Nullable
public static MediaCodecInfo getPassthroughDecoderInfo() throws DecoderQueryException {
MediaCodecInfo decoderInfo = getDecoderInfo(MimeTypes.AUDIO_RAW, /* secure= */ false); MediaCodecInfo decoderInfo = getDecoderInfo(MimeTypes.AUDIO_RAW, /* secure= */ false);
return decoderInfo == null ? null : MediaCodecInfo.newPassthroughInstance(decoderInfo.name); return decoderInfo == null ? null : MediaCodecInfo.newPassthroughInstance(decoderInfo.name);
} }
@ -124,7 +125,8 @@ public final class MediaCodecUtil {
* @return A {@link MediaCodecInfo} describing the decoder, or null if no suitable decoder exists. * @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. * @throws DecoderQueryException If there was an error querying the available decoders.
*/ */
public static @Nullable MediaCodecInfo getDecoderInfo(String mimeType, boolean secure) @Nullable
public static MediaCodecInfo getDecoderInfo(String mimeType, boolean secure)
throws DecoderQueryException { throws DecoderQueryException {
List<MediaCodecInfo> decoderInfos = getDecoderInfos(mimeType, secure); List<MediaCodecInfo> decoderInfos = getDecoderInfos(mimeType, secure);
return decoderInfos.isEmpty() ? null : decoderInfos.get(0); return decoderInfos.isEmpty() ? null : decoderInfos.get(0);
@ -204,21 +206,24 @@ public final class MediaCodecUtil {
* @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
* recognized, or null otherwise * recognized, or null otherwise
*/ */
public static @Nullable Pair<Integer, Integer> getCodecProfileAndLevel(String codec) { @Nullable
public static Pair<Integer, Integer> getCodecProfileAndLevel(String codec) {
if (codec == null) { if (codec == null) {
return null; return null;
} }
// TODO: Check codec profile/level for AV1 once targeting Android Q and [Internal: b/128552878]
// has been fixed.
String[] parts = codec.split("\\."); String[] parts = codec.split("\\.");
switch (parts[0]) { switch (parts[0]) {
case CODEC_ID_AVC1:
case CODEC_ID_AVC2:
return getAvcProfileAndLevel(codec, parts);
case CODEC_ID_HEV1: case CODEC_ID_HEV1:
case CODEC_ID_HVC1: case CODEC_ID_HVC1:
return getHevcProfileAndLevel(codec, parts); return getHevcProfileAndLevel(codec, parts);
case CODEC_ID_DVHE: case CODEC_ID_DVHE:
case CODEC_ID_DVH1: case CODEC_ID_DVH1:
return getDolbyVisionProfileAndLevel(codec, parts); return getDolbyVisionProfileAndLevel(codec, parts);
case CODEC_ID_AVC1:
case CODEC_ID_AVC2:
return getAvcProfileAndLevel(codec, parts);
case CODEC_ID_MP4A: case CODEC_ID_MP4A:
return getAacCodecProfileAndLevel(codec, parts); return getAacCodecProfileAndLevel(codec, parts);
default: default:
@ -536,8 +541,8 @@ 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;
} }
Integer profileInteger; int profileInteger;
Integer levelInteger; int levelInteger;
try { try {
if (parts[1].length() == 6) { if (parts[1].length() == 6) {
// Format: avc1.xxccyy, where xx is profile and yy level, both hexadecimal. // Format: avc1.xxccyy, where xx is profile and yy level, both hexadecimal.
@ -610,8 +615,8 @@ public final class MediaCodecUtil {
} }
} }
private static @Nullable Pair<Integer, Integer> getAacCodecProfileAndLevel( @Nullable
String codec, String[] parts) { private static Pair<Integer, Integer> getAacCodecProfileAndLevel(String codec, String[] parts) {
if (parts.length != 3) { if (parts.length != 3) {
Log.w(TAG, "Ignoring malformed MP4A codec string: " + codec); Log.w(TAG, "Ignoring malformed MP4A codec string: " + codec);
return null; return null;

View File

@ -37,6 +37,7 @@ public final class MimeTypes {
public static final String VIDEO_H265 = BASE_TYPE_VIDEO + "/hevc"; public static final String VIDEO_H265 = BASE_TYPE_VIDEO + "/hevc";
public static final String VIDEO_VP8 = BASE_TYPE_VIDEO + "/x-vnd.on2.vp8"; public static final String VIDEO_VP8 = BASE_TYPE_VIDEO + "/x-vnd.on2.vp8";
public static final String VIDEO_VP9 = BASE_TYPE_VIDEO + "/x-vnd.on2.vp9"; public static final String VIDEO_VP9 = BASE_TYPE_VIDEO + "/x-vnd.on2.vp9";
public static final String VIDEO_AV1 = BASE_TYPE_VIDEO + "/av01";
public static final String VIDEO_MP4V = BASE_TYPE_VIDEO + "/mp4v-es"; public static final String VIDEO_MP4V = BASE_TYPE_VIDEO + "/mp4v-es";
public static final String VIDEO_MPEG = BASE_TYPE_VIDEO + "/mpeg"; public static final String VIDEO_MPEG = BASE_TYPE_VIDEO + "/mpeg";
public static final String VIDEO_MPEG2 = BASE_TYPE_VIDEO + "/mpeg2"; public static final String VIDEO_MPEG2 = BASE_TYPE_VIDEO + "/mpeg2";
@ -200,6 +201,8 @@ public final class MimeTypes {
|| codec.startsWith("dvhe") || codec.startsWith("dvhe")
|| codec.startsWith("dvh1")) { || codec.startsWith("dvh1")) {
return MimeTypes.VIDEO_DOLBY_VISION; return MimeTypes.VIDEO_DOLBY_VISION;
} else if (codec.startsWith("av01")) {
return MimeTypes.VIDEO_AV1;
} else if (codec.startsWith("vp9") || codec.startsWith("vp09")) { } else if (codec.startsWith("vp9") || codec.startsWith("vp09")) {
return MimeTypes.VIDEO_VP9; return MimeTypes.VIDEO_VP9;
} else if (codec.startsWith("vp8") || codec.startsWith("vp08")) { } else if (codec.startsWith("vp8") || codec.startsWith("vp08")) {