diff --git a/library/core/src/main/java/com/google/android/exoplayer2/extractor/mkv/MatroskaExtractor.java b/library/core/src/main/java/com/google/android/exoplayer2/extractor/mkv/MatroskaExtractor.java index e53a25d0af..c785865f6a 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/extractor/mkv/MatroskaExtractor.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/extractor/mkv/MatroskaExtractor.java @@ -96,6 +96,7 @@ public class MatroskaExtractor implements Extractor { private static final String DOC_TYPE_WEBM = "webm"; private static final String CODEC_ID_VP8 = "V_VP8"; 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_MPEG4_SP = "V_MPEG4/ISO/SP"; 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) { return CODEC_ID_VP8.equals(codecId) || CODEC_ID_VP9.equals(codecId) + || CODEC_ID_AV1.equals(codecId) || CODEC_ID_MPEG2.equals(codecId) || CODEC_ID_MPEG4_SP.equals(codecId) || CODEC_ID_MPEG4_ASP.equals(codecId) @@ -1780,6 +1782,9 @@ public class MatroskaExtractor implements Extractor { case CODEC_ID_VP9: mimeType = MimeTypes.VIDEO_VP9; break; + case CODEC_ID_AV1: + mimeType = MimeTypes.VIDEO_AV1; + break; case CODEC_ID_MPEG2: mimeType = MimeTypes.VIDEO_MPEG2; break; diff --git a/library/core/src/main/java/com/google/android/exoplayer2/extractor/mp4/Atom.java b/library/core/src/main/java/com/google/android/exoplayer2/extractor/mp4/Atom.java index 8a004d2e99..f383305fcc 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/extractor/mp4/Atom.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/extractor/mp4/Atom.java @@ -57,6 +57,11 @@ import java.util.List; public static final int TYPE_hvc1 = Util.getIntegerCodeForString("hvc1"); public static final int TYPE_hev1 = Util.getIntegerCodeForString("hev1"); 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_dva1 = Util.getIntegerCodeForString("dva1"); 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_sv3d = Util.getIntegerCodeForString("sv3d"); 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_alac = Util.getIntegerCodeForString("alac"); public static final int TYPE_alaw = Util.getIntegerCodeForString("alaw"); diff --git a/library/core/src/main/java/com/google/android/exoplayer2/extractor/mp4/AtomParsers.java b/library/core/src/main/java/com/google/android/exoplayer2/extractor/mp4/AtomParsers.java index aad6530384..0a87ab92c4 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/extractor/mp4/AtomParsers.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/extractor/mp4/AtomParsers.java @@ -745,6 +745,7 @@ import java.util.List; || childAtomType == Atom.TYPE_s263 || childAtomType == Atom.TYPE_vp08 || childAtomType == Atom.TYPE_vp09 + || childAtomType == Atom.TYPE_av01 || childAtomType == Atom.TYPE_dvav || childAtomType == Atom.TYPE_dva1 || childAtomType == Atom.TYPE_dvhe @@ -902,6 +903,9 @@ import java.util.List; } else if (childAtomType == Atom.TYPE_vpcC) { Assertions.checkState(mimeType == null); 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) { Assertions.checkState(mimeType == null); mimeType = MimeTypes.VIDEO_H263; diff --git a/library/core/src/main/java/com/google/android/exoplayer2/extractor/mp4/Sniffer.java b/library/core/src/main/java/com/google/android/exoplayer2/extractor/mp4/Sniffer.java index b22c5203c3..5c5afe39a8 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/extractor/mp4/Sniffer.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/extractor/mp4/Sniffer.java @@ -41,6 +41,7 @@ import java.io.IOException; Util.getIntegerCodeForString("avc1"), Util.getIntegerCodeForString("hvc1"), Util.getIntegerCodeForString("hev1"), + Util.getIntegerCodeForString("av01"), Util.getIntegerCodeForString("mp41"), Util.getIntegerCodeForString("mp42"), Util.getIntegerCodeForString("3g2a"), diff --git a/library/core/src/main/java/com/google/android/exoplayer2/mediacodec/MediaCodecUtil.java b/library/core/src/main/java/com/google/android/exoplayer2/mediacodec/MediaCodecUtil.java index a7c6405c82..5a3179f110 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/mediacodec/MediaCodecUtil.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/mediacodec/MediaCodecUtil.java @@ -110,7 +110,8 @@ public final class MediaCodecUtil { * @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. */ - public static @Nullable MediaCodecInfo getPassthroughDecoderInfo() throws DecoderQueryException { + @Nullable + public static MediaCodecInfo getPassthroughDecoderInfo() throws DecoderQueryException { MediaCodecInfo decoderInfo = getDecoderInfo(MimeTypes.AUDIO_RAW, /* secure= */ false); 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. * @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 { List decoderInfos = getDecoderInfos(mimeType, secure); 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 * recognized, or null otherwise */ - public static @Nullable Pair getCodecProfileAndLevel(String codec) { + @Nullable + public static Pair getCodecProfileAndLevel(String codec) { if (codec == 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("\\."); switch (parts[0]) { + case CODEC_ID_AVC1: + case CODEC_ID_AVC2: + return getAvcProfileAndLevel(codec, parts); case CODEC_ID_HEV1: case CODEC_ID_HVC1: return getHevcProfileAndLevel(codec, parts); case CODEC_ID_DVHE: case CODEC_ID_DVH1: return getDolbyVisionProfileAndLevel(codec, parts); - case CODEC_ID_AVC1: - case CODEC_ID_AVC2: - return getAvcProfileAndLevel(codec, parts); case CODEC_ID_MP4A: return getAacCodecProfileAndLevel(codec, parts); default: @@ -536,8 +541,8 @@ public final class MediaCodecUtil { Log.w(TAG, "Ignoring malformed AVC codec string: " + codec); return null; } - Integer profileInteger; - Integer levelInteger; + int profileInteger; + int levelInteger; try { if (parts[1].length() == 6) { // Format: avc1.xxccyy, where xx is profile and yy level, both hexadecimal. @@ -610,8 +615,8 @@ public final class MediaCodecUtil { } } - private static @Nullable Pair getAacCodecProfileAndLevel( - String codec, String[] parts) { + @Nullable + private static Pair getAacCodecProfileAndLevel(String codec, String[] parts) { if (parts.length != 3) { Log.w(TAG, "Ignoring malformed MP4A codec string: " + codec); return null; diff --git a/library/core/src/main/java/com/google/android/exoplayer2/util/MimeTypes.java b/library/core/src/main/java/com/google/android/exoplayer2/util/MimeTypes.java index 01b4388eb4..5eaed8ad2f 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/util/MimeTypes.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/util/MimeTypes.java @@ -37,6 +37,7 @@ public final class MimeTypes { 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_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_MPEG = BASE_TYPE_VIDEO + "/mpeg"; public static final String VIDEO_MPEG2 = BASE_TYPE_VIDEO + "/mpeg2"; @@ -200,6 +201,8 @@ public final class MimeTypes { || codec.startsWith("dvhe") || codec.startsWith("dvh1")) { return MimeTypes.VIDEO_DOLBY_VISION; + } else if (codec.startsWith("av01")) { + return MimeTypes.VIDEO_AV1; } else if (codec.startsWith("vp9") || codec.startsWith("vp09")) { return MimeTypes.VIDEO_VP9; } else if (codec.startsWith("vp8") || codec.startsWith("vp08")) {