From 6a7e9132fde6e71992cc38c03d4f9712d76a1b82 Mon Sep 17 00:00:00 2001 From: sheenachhabra Date: Fri, 2 Aug 2024 08:01:01 -0700 Subject: [PATCH] Write sample location key when muxing editable tracks There are two ways to write editable tracks samples. 1. In the embedded edit data MP4. 2. Interleaved with primary tracks samples. Initial plan was to support only option 1 but then the decision is to support both ways. To identify between these two an additional key will be required. Option 2 is yet to be implemented in Mp4Muxer. PiperOrigin-RevId: 658791214 --- .../media3/container/MdtaMetadataEntry.java | 24 +++++++++++++++++++ .../java/androidx/media3/muxer/Mp4Muxer.java | 7 ++++++ .../mp4_with_editable_video_tracks.mp4.dump | 4 ++-- ...ith_editable_video_tracks_in_edvd.box.dump | 16 ++++++------- 4 files changed, 41 insertions(+), 10 deletions(-) diff --git a/libraries/container/src/main/java/androidx/media3/container/MdtaMetadataEntry.java b/libraries/container/src/main/java/androidx/media3/container/MdtaMetadataEntry.java index 6daf669c5e..5a3c68bed2 100644 --- a/libraries/container/src/main/java/androidx/media3/container/MdtaMetadataEntry.java +++ b/libraries/container/src/main/java/androidx/media3/container/MdtaMetadataEntry.java @@ -40,6 +40,7 @@ public final class MdtaMetadataEntry implements Metadata.Entry { /** Key for the capture frame rate (in frames per second). */ public static final String KEY_ANDROID_CAPTURE_FPS = "com.android.capture.fps"; + // TODO: b/345219017 - Add depth/editing file format spec link after its published. /** Key for editable tracks box (edvd) offset. */ public static final String KEY_EDITABLE_TRACKS_OFFSET = "editable.tracks.offset"; @@ -49,6 +50,16 @@ public final class MdtaMetadataEntry implements Metadata.Entry { /** Key for editable tracks map. */ public static final String KEY_EDITABLE_TRACKS_MAP = "editable.tracks.map"; + /** Key for editable tracks samples location. */ + public static final String KEY_EDITABLE_TRACKS_SAMPLES_LOCATION = + "editable.tracks.samples.location"; + + /** The editable tracks samples are in edit data MP4. */ + public static final byte EDITABLE_TRACKS_SAMPLES_LOCATION_IN_EDIT_DATA_MP4 = 0; + + /** The editable tracks samples are interleaved with the primary tracks samples. */ + public static final byte EDITABLE_TRACKS_SAMPLES_LOCATION_INTERLEAVED = 1; + /** The default locale indicator which implies all speakers in all countries. */ public static final int DEFAULT_LOCALE_INDICATOR = 0; @@ -64,6 +75,9 @@ public final class MdtaMetadataEntry implements Metadata.Entry { /** The type indicator for 32-bit signed integer. */ public static final int TYPE_INDICATOR_INT32 = 67; + /** The type indicator for an 8-bit unsigned integer. */ + public static final int TYPE_INDICATOR_8_BIT_UNSIGNED_INT = 75; + /** The type indicator for 64-bit unsigned integer. */ public static final int TYPE_INDICATOR_UNSIGNED_INT64 = 78; @@ -116,6 +130,13 @@ public final class MdtaMetadataEntry implements Metadata.Entry { case KEY_EDITABLE_TRACKS_MAP: checkArgument(typeIndicator == TYPE_INDICATOR_RESERVED); break; + case KEY_EDITABLE_TRACKS_SAMPLES_LOCATION: + checkArgument( + typeIndicator == TYPE_INDICATOR_8_BIT_UNSIGNED_INT + && value.length == 1 + && (value[0] == EDITABLE_TRACKS_SAMPLES_LOCATION_IN_EDIT_DATA_MP4 + || value[0] == EDITABLE_TRACKS_SAMPLES_LOCATION_INTERLEAVED)); + break; default: // Ignore custom keys. } @@ -159,6 +180,9 @@ public final class MdtaMetadataEntry implements Metadata.Entry { case TYPE_INDICATOR_INT32: formattedValue = String.valueOf(Ints.fromByteArray(value)); break; + case TYPE_INDICATOR_8_BIT_UNSIGNED_INT: + formattedValue = String.valueOf(Byte.toUnsignedInt(value[0])); + break; case TYPE_INDICATOR_UNSIGNED_INT64: formattedValue = String.valueOf(new ParsableByteArray(value).readUnsignedLongToLong()); break; diff --git a/libraries/muxer/src/main/java/androidx/media3/muxer/Mp4Muxer.java b/libraries/muxer/src/main/java/androidx/media3/muxer/Mp4Muxer.java index be35e7fd06..26206eda27 100644 --- a/libraries/muxer/src/main/java/androidx/media3/muxer/Mp4Muxer.java +++ b/libraries/muxer/src/main/java/androidx/media3/muxer/Mp4Muxer.java @@ -18,6 +18,8 @@ package androidx.media3.muxer; import static androidx.media3.common.util.Assertions.checkArgument; import static androidx.media3.common.util.Assertions.checkNotNull; import static androidx.media3.common.util.Assertions.checkState; +import static androidx.media3.container.MdtaMetadataEntry.EDITABLE_TRACKS_SAMPLES_LOCATION_IN_EDIT_DATA_MP4; +import static androidx.media3.container.MdtaMetadataEntry.TYPE_INDICATOR_8_BIT_UNSIGNED_INT; import static androidx.media3.container.Mp4Util.EDITABLE_TRACK_TYPE_DEPTH_INVERSE; import static androidx.media3.container.Mp4Util.EDITABLE_TRACK_TYPE_DEPTH_LINEAR; import static androidx.media3.container.Mp4Util.EDITABLE_TRACK_TYPE_DEPTH_METADATA; @@ -531,6 +533,11 @@ public final class Mp4Muxer implements Muxer { } checkNotNull(editableVideoMetadataCollector); + editableVideoMetadataCollector.addMetadata( + new MdtaMetadataEntry( + MdtaMetadataEntry.KEY_EDITABLE_TRACKS_SAMPLES_LOCATION, + new byte[] {EDITABLE_TRACKS_SAMPLES_LOCATION_IN_EDIT_DATA_MP4}, + TYPE_INDICATOR_8_BIT_UNSIGNED_INT)); editableVideoMetadataCollector.addMetadata( new MdtaMetadataEntry( MdtaMetadataEntry.KEY_EDITABLE_TRACKS_MAP, diff --git a/libraries/test_data/src/test/assets/muxerdumps/mp4_with_editable_video_tracks.mp4.dump b/libraries/test_data/src/test/assets/muxerdumps/mp4_with_editable_video_tracks.mp4.dump index dea103df36..e39598de1d 100644 --- a/libraries/test_data/src/test/assets/muxerdumps/mp4_with_editable_video_tracks.mp4.dump +++ b/libraries/test_data/src/test/assets/muxerdumps/mp4_with_editable_video_tracks.mp4.dump @@ -21,7 +21,7 @@ track 0: colorRange = 1 lumaBitdepth = 8 chromaBitdepth = 8 - metadata = entries=[mdta: key=editable.tracks.map, value=track types = 0,1, Mp4Timestamp: creation time=1000000, modification time=5000000, timescale=10000] + metadata = entries=[mdta: key=editable.tracks.map, value=track types = 0,1, mdta: key=editable.tracks.samples.location, value=0, Mp4Timestamp: creation time=1000000, modification time=5000000, timescale=10000] initializationData: data = length 28, hash 410B510 data = length 9, hash FBADD682 @@ -60,7 +60,7 @@ track 1: colorRange = 1 lumaBitdepth = 8 chromaBitdepth = 8 - metadata = entries=[mdta: key=editable.tracks.map, value=track types = 0,1, Mp4Timestamp: creation time=1000000, modification time=5000000, timescale=10000] + metadata = entries=[mdta: key=editable.tracks.map, value=track types = 0,1, mdta: key=editable.tracks.samples.location, value=0, Mp4Timestamp: creation time=1000000, modification time=5000000, timescale=10000] initializationData: data = length 28, hash 410B510 data = length 9, hash FBADD682 diff --git a/libraries/test_data/src/test/assets/muxerdumps/mp4_with_editable_video_tracks_in_edvd.box.dump b/libraries/test_data/src/test/assets/muxerdumps/mp4_with_editable_video_tracks_in_edvd.box.dump index 142fa15025..54ed10b089 100644 --- a/libraries/test_data/src/test/assets/muxerdumps/mp4_with_editable_video_tracks_in_edvd.box.dump +++ b/libraries/test_data/src/test/assets/muxerdumps/mp4_with_editable_video_tracks_in_edvd.box.dump @@ -43,16 +43,16 @@ mdat (296 bytes): edvd (400628 bytes): ftyp (28 bytes): Data = length 20, hash EF896440 - moov (1384 bytes): + moov (1449 bytes): mvhd (108 bytes): Data = length 100, hash 2613A5D - meta (120 bytes): + meta (185 bytes): hdlr (33 bytes): Data = length 25, hash C39D0F5B - keys (43 bytes): - Data = length 35, hash 1CD3D3F - ilst (36 bytes): - Data = length 28, hash D9B9DABE + keys (83 bytes): + Data = length 75, hash 951DA420 + ilst (61 bytes): + Data = length 53, hash 1156FE81 trak (574 bytes): tkhd (92 bytes): Data = length 84, hash 3D79758F @@ -105,7 +105,7 @@ edvd (400628 bytes): Data = length 16, hash E4EE6699 stss (36 bytes): Data = length 28, hash 53024615 - free (398624 bytes): - Data = length 398616, hash 25A3AD01 + free (398559 bytes): + Data = length 398551, hash D08A6DF mdat (576 bytes): Data = length 560, hash 9E0D5FC5