From 6b56f12f15b1c02d813db7f9a31e8acb7a70fdc1 Mon Sep 17 00:00:00 2001 From: Googler Date: Wed, 21 Aug 2024 22:31:10 -0700 Subject: [PATCH] AtomParser: Update initialization data to CodecPrivate format for Vp9 PiperOrigin-RevId: 666188937 --- .../common/util/CodecSpecificDataUtil.java | 30 +++++++++++++++++++ .../media3/extractor/mp4/BoxParser.java | 10 ++++++- .../bbb_642x642_768kbps_30fps_vp9.webm.dump | 2 ++ .../bbb_800x640_768kbps_30fps_vp9.mp4.dump | 2 ++ 4 files changed, 43 insertions(+), 1 deletion(-) diff --git a/libraries/common/src/main/java/androidx/media3/common/util/CodecSpecificDataUtil.java b/libraries/common/src/main/java/androidx/media3/common/util/CodecSpecificDataUtil.java index d05a123346..eca8dac931 100644 --- a/libraries/common/src/main/java/androidx/media3/common/util/CodecSpecificDataUtil.java +++ b/libraries/common/src/main/java/androidx/media3/common/util/CodecSpecificDataUtil.java @@ -21,6 +21,7 @@ import android.util.Pair; import androidx.annotation.Nullable; import androidx.media3.common.C; import androidx.media3.common.MimeTypes; +import com.google.common.collect.ImmutableList; import java.util.ArrayList; import java.util.Collections; import java.util.List; @@ -80,6 +81,35 @@ public final class CodecSpecificDataUtil { && initializationData.get(0)[0] == 1; } + /** + * Returns initialization data in CodecPrivate format of VP9. + * + *

Each feature of VP9 CodecPrivate is defined by the binary format of ID (1 byte), length (1 + * byte), and data (1 byte). See + * href="https://www.webmproject.org/docs/container/#vp9-codec-feature-metadata-codecprivate">CodecPrivate + * format of VP9 for more details. + * + * @param profile The VP9 codec profile. + * @param level The VP9 codec level. + * @param bitDepth The bit depth of the luma and color components. + * @param chromaSubsampling The chroma subsampling. + */ + public static ImmutableList buildVp9CodecPrivateInitializationData( + byte profile, byte level, byte bitDepth, byte chromaSubsampling) { + byte profileId = 0x01; + byte levelId = 0x02; + byte bitDepthId = 0x03; + byte chromaSubsamplingId = 0x04; + byte length = 0x01; + return ImmutableList.of( + new byte[] { + profileId, length, profile, + levelId, length, level, + bitDepthId, length, bitDepth, + chromaSubsamplingId, length, chromaSubsampling + }); + } + /** * Parses an MPEG-4 Visual configuration information, as defined in ISO/IEC14496-2. * diff --git a/libraries/extractor/src/main/java/androidx/media3/extractor/mp4/BoxParser.java b/libraries/extractor/src/main/java/androidx/media3/extractor/mp4/BoxParser.java index a4eb4b5adb..3c1e4433bf 100644 --- a/libraries/extractor/src/main/java/androidx/media3/extractor/mp4/BoxParser.java +++ b/libraries/extractor/src/main/java/androidx/media3/extractor/mp4/BoxParser.java @@ -1306,10 +1306,18 @@ public final class BoxParser { mimeType = (atomType == Mp4Box.TYPE_vp08) ? MimeTypes.VIDEO_VP8 : MimeTypes.VIDEO_VP9; parent.setPosition(childStartPosition + Mp4Box.FULL_HEADER_SIZE); // See vpcC atom syntax: https://www.webmproject.org/vp9/mp4/#syntax_1 - parent.skipBytes(2); // profile(8), level(8) + byte profile = (byte) parent.readUnsignedByte(); + byte level = (byte) parent.readUnsignedByte(); int byte3 = parent.readUnsignedByte(); bitdepthLuma = byte3 >> 4; bitdepthChroma = bitdepthLuma; + byte chromaSubsampling = (byte) ((byte3 >> 1) & 0b111); + if (mimeType.equals(MimeTypes.VIDEO_VP9)) { + // CSD should be in CodecPrivate format according to VP9 Codec spec. + initializationData = + CodecSpecificDataUtil.buildVp9CodecPrivateInitializationData( + profile, level, (byte) bitdepthLuma, chromaSubsampling); + } boolean fullRangeFlag = (byte3 & 0b1) != 0; int colorPrimaries = parent.readUnsignedByte(); int transferCharacteristics = parent.readUnsignedByte(); diff --git a/libraries/test_data/src/test/assets/muxerdumps/bbb_642x642_768kbps_30fps_vp9.webm.dump b/libraries/test_data/src/test/assets/muxerdumps/bbb_642x642_768kbps_30fps_vp9.webm.dump index 01563094d7..a7d961c2d0 100644 --- a/libraries/test_data/src/test/assets/muxerdumps/bbb_642x642_768kbps_30fps_vp9.webm.dump +++ b/libraries/test_data/src/test/assets/muxerdumps/bbb_642x642_768kbps_30fps_vp9.webm.dump @@ -23,6 +23,8 @@ track 0: lumaBitdepth = 8 chromaBitdepth = 8 metadata = entries=[Mp4Timestamp: creation time=100000000, modification time=500000000, timescale=10000] + initializationData: + data = length 12, hash 31B20D86 sample 0: time = 0 flags = 1 diff --git a/libraries/test_data/src/test/assets/muxerdumps/bbb_800x640_768kbps_30fps_vp9.mp4.dump b/libraries/test_data/src/test/assets/muxerdumps/bbb_800x640_768kbps_30fps_vp9.mp4.dump index 2196db2751..767fecd5c8 100644 --- a/libraries/test_data/src/test/assets/muxerdumps/bbb_800x640_768kbps_30fps_vp9.mp4.dump +++ b/libraries/test_data/src/test/assets/muxerdumps/bbb_800x640_768kbps_30fps_vp9.mp4.dump @@ -21,6 +21,8 @@ track 0: lumaBitdepth = 8 chromaBitdepth = 8 metadata = entries=[Mp4Timestamp: creation time=100000000, modification time=500000000, timescale=10000] + initializationData: + data = length 12, hash 53AEAE99 sample 0: time = 0 flags = 1