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 5474162ccf..a2a9b4cd9a 100644 --- a/libraries/container/src/main/java/androidx/media3/container/MdtaMetadataEntry.java +++ b/libraries/container/src/main/java/androidx/media3/container/MdtaMetadataEntry.java @@ -41,7 +41,8 @@ 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. + // See the MP4 With Auxiliary Tracks Extension (MP4-AT) file format at + // https://developer.android.com/media/platform/mp4-at-file-format. /** Key for auxiliary tracks extension box (axte) offset. */ public static final String KEY_AUXILIARY_TRACKS_OFFSET = "auxiliary.tracks.offset"; diff --git a/libraries/container/src/main/java/androidx/media3/container/Mp4Util.java b/libraries/container/src/main/java/androidx/media3/container/Mp4Util.java deleted file mode 100644 index e076d3ab21..0000000000 --- a/libraries/container/src/main/java/androidx/media3/container/Mp4Util.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright 2024 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package androidx.media3.container; - -import androidx.media3.common.util.UnstableApi; - -/** Utility methods for MP4 containers. */ -@UnstableApi -public final class Mp4Util { - /** The original video track without any depth based effects applied. */ - public static final int MP4_AT_AUXILIARY_TRACK_TYPE_SHARP = 0; - - /** - * A linear encoded depth video track. - * - *

See https://developer.android.com/static/media/camera/camera2/Dynamic-depth-v1.0.pdf for - * linear depth encoding. - */ - public static final int MP4_AT_AUXILIARY_TRACK_TYPE_DEPTH_LINEAR = 1; - - /** - * An inverse encoded depth video track. - * - *

See https://developer.android.com/static/media/camera/camera2/Dynamic-depth-v1.0.pdf for - * inverse depth encoding. - */ - public static final int MP4_AT_AUXILIARY_TRACK_TYPE_DEPTH_INVERSE = 2; - - /** A timed metadata of depth video track. */ - public static final int MP4_AT_AUXILIARY_TRACK_TYPE_DEPTH_METADATA = 3; - - private Mp4Util() {} -} diff --git a/libraries/extractor/src/main/java/androidx/media3/extractor/mp4/Mp4Extractor.java b/libraries/extractor/src/main/java/androidx/media3/extractor/mp4/Mp4Extractor.java index 4874977c3d..2a221b78a3 100644 --- a/libraries/extractor/src/main/java/androidx/media3/extractor/mp4/Mp4Extractor.java +++ b/libraries/extractor/src/main/java/androidx/media3/extractor/mp4/Mp4Extractor.java @@ -24,10 +24,6 @@ import static androidx.media3.common.util.Assertions.checkState; import static androidx.media3.common.util.Assertions.checkStateNotNull; import static androidx.media3.common.util.Util.castNonNull; import static androidx.media3.container.MdtaMetadataEntry.AUXILIARY_TRACKS_SAMPLES_NOT_INTERLEAVED; -import static androidx.media3.container.Mp4Util.MP4_AT_AUXILIARY_TRACK_TYPE_DEPTH_INVERSE; -import static androidx.media3.container.Mp4Util.MP4_AT_AUXILIARY_TRACK_TYPE_DEPTH_LINEAR; -import static androidx.media3.container.Mp4Util.MP4_AT_AUXILIARY_TRACK_TYPE_DEPTH_METADATA; -import static androidx.media3.container.Mp4Util.MP4_AT_AUXILIARY_TRACK_TYPE_SHARP; import static androidx.media3.extractor.mp4.BoxParser.parseTraks; import static androidx.media3.extractor.mp4.MetadataUtil.findMdtaMetadataEntryWithKey; import static androidx.media3.extractor.mp4.MimeTypeResolver.getContainerMimeType; @@ -160,15 +156,17 @@ public final class Mp4Extractor implements Extractor, SeekMap { */ public static final int FLAG_READ_WITHIN_GOP_SAMPLE_DEPENDENCIES = 1 << 5; - // TODO: b/345219017 - Add depth/editing file format spec link after its published. /** - * Flag to extract the auxiliary tracks. + * Flag to extract the auxiliary tracks from the MP4 With Auxiliary Tracks Extension (MP4-AT) file + * format. * *

Either primary video tracks or auxiliary tracks (but not both) will be extracted based on * the flag. * *

If the flag is set but the auxiliary tracks are not present, then it fallbacks to extract * primary tracks instead. + * + *

See the file format at https://developer.android.com/media/platform/mp4-at-file-format. */ public static final int FLAG_READ_AUXILIARY_TRACKS = 1 << 6; @@ -824,16 +822,16 @@ public final class Mp4Extractor implements Extractor, SeekMap { for (int i = 0; i < auxiliaryTrackTypesFromMap.size(); i++) { @C.AuxiliaryTrackType int auxiliaryTrackType; switch (auxiliaryTrackTypesFromMap.get(i)) { - case MP4_AT_AUXILIARY_TRACK_TYPE_SHARP: + case 0: auxiliaryTrackType = AUXILIARY_TRACK_TYPE_ORIGINAL; break; - case MP4_AT_AUXILIARY_TRACK_TYPE_DEPTH_LINEAR: + case 1: auxiliaryTrackType = AUXILIARY_TRACK_TYPE_DEPTH_LINEAR; break; - case MP4_AT_AUXILIARY_TRACK_TYPE_DEPTH_INVERSE: + case 2: auxiliaryTrackType = AUXILIARY_TRACK_TYPE_DEPTH_INVERSE; break; - case MP4_AT_AUXILIARY_TRACK_TYPE_DEPTH_METADATA: + case 3: auxiliaryTrackType = C.AUXILIARY_TRACK_TYPE_DEPTH_METADATA; break; default: 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 71b13fccb3..92297f60d5 100644 --- a/libraries/muxer/src/main/java/androidx/media3/muxer/Mp4Muxer.java +++ b/libraries/muxer/src/main/java/androidx/media3/muxer/Mp4Muxer.java @@ -107,7 +107,7 @@ import org.checkerframework.checker.nullness.qual.EnsuresNonNull; */ @UnstableApi public final class Mp4Muxer implements Muxer { - /** Parameters for {@link #FILE_FORMAT_MP4_AT}. */ + /** Parameters for {@link #FILE_FORMAT_MP4_WITH_AUXILIARY_TRACKS_EXTENSION}. */ public static final class Mp4AtFileParameters { /** Provides temporary cache files to be used by the muxer. */ public interface CacheFileProvider { @@ -177,21 +177,22 @@ public final class Mp4Muxer implements Muxer { @Documented @Retention(RetentionPolicy.SOURCE) @Target(TYPE_USE) - @IntDef({FILE_FORMAT_DEFAULT, FILE_FORMAT_MP4_AT}) + @IntDef({FILE_FORMAT_DEFAULT, FILE_FORMAT_MP4_WITH_AUXILIARY_TRACKS_EXTENSION}) public @interface FileFormat {} /** The default MP4 format. */ public static final int FILE_FORMAT_DEFAULT = 0; - // TODO: b/345219017 - Add spec details. /** - * The MP4-AT (MP4 With Auxiliary Tracks Extension) file format. In this file format all the + * The MP4 With Auxiliary Tracks Extension (MP4-AT) file format. In this file format all the * tracks with {@linkplain Format#auxiliaryTrackType} set to {@link * C#AUXILIARY_TRACK_TYPE_ORIGINAL}, {@link C#AUXILIARY_TRACK_TYPE_DEPTH_LINEAR}, {@link * C#AUXILIARY_TRACK_TYPE_DEPTH_INVERSE}, or {@link C#AUXILIARY_TRACK_TYPE_DEPTH_METADATA} are * written in the Auxiliary Tracks MP4 (axte box). The rest of the tracks are written as usual. + * + *

See the file format at https://developer.android.com/media/platform/mp4-at-file-format. */ - public static final int FILE_FORMAT_MP4_AT = 1; + public static final int FILE_FORMAT_MP4_WITH_AUXILIARY_TRACKS_EXTENSION = 1; /** A builder for {@link Mp4Muxer} instances. */ public static final class Builder { @@ -297,8 +298,8 @@ public final class Mp4Muxer implements Muxer { * *

The default value is {@link #FILE_FORMAT_DEFAULT}. * - *

For {@link #FILE_FORMAT_MP4_AT}, {@link Mp4AtFileParameters} must also be {@linkplain - * #setMp4AtFileParameters(Mp4AtFileParameters)} set}. + *

For {@link #FILE_FORMAT_MP4_WITH_AUXILIARY_TRACKS_EXTENSION}, {@link Mp4AtFileParameters} + * must also be {@linkplain #setMp4AtFileParameters(Mp4AtFileParameters)} set}. */ @CanIgnoreReturnValue public Mp4Muxer.Builder setOutputFileFormat(@FileFormat int fileFormat) { @@ -316,10 +317,10 @@ public final class Mp4Muxer implements Muxer { /** Builds an {@link Mp4Muxer} instance. */ public Mp4Muxer build() { checkArgument( - outputFileFormat == FILE_FORMAT_MP4_AT + outputFileFormat == FILE_FORMAT_MP4_WITH_AUXILIARY_TRACKS_EXTENSION ? mp4AtFileParameters != null : mp4AtFileParameters == null, - "Mp4AtFileParameters must be set for FILE_FORMAT_MP4_AT"); + "Mp4AtFileParameters must be set for FILE_FORMAT_MP4_WITH_AUXILIARY_TRACKS_EXTENSION"); return new Mp4Muxer( outputStream, lastSampleDurationBehavior, @@ -416,7 +417,8 @@ public final class Mp4Muxer implements Muxer { * @throws MuxerException If an error occurs while adding track. */ public TrackToken addTrack(int sortKey, Format format) throws MuxerException { - if (outputFileFormat == FILE_FORMAT_MP4_AT && isAuxiliaryTrack(format)) { + if (outputFileFormat == FILE_FORMAT_MP4_WITH_AUXILIARY_TRACKS_EXTENSION + && isAuxiliaryTrack(format)) { if (checkNotNull(mp4AtFileParameters).shouldInterleaveSamples) { // Auxiliary tracks are handled by the primary Mp4Writer. return mp4Writer.addAuxiliaryTrack(sortKey, format); diff --git a/libraries/muxer/src/main/java/androidx/media3/muxer/MuxerUtil.java b/libraries/muxer/src/main/java/androidx/media3/muxer/MuxerUtil.java index 4fd8b2c22b..efb52baaed 100644 --- a/libraries/muxer/src/main/java/androidx/media3/muxer/MuxerUtil.java +++ b/libraries/muxer/src/main/java/androidx/media3/muxer/MuxerUtil.java @@ -18,10 +18,6 @@ package androidx.media3.muxer; import static androidx.media3.container.MdtaMetadataEntry.AUXILIARY_TRACKS_SAMPLES_INTERLEAVED; import static androidx.media3.container.MdtaMetadataEntry.AUXILIARY_TRACKS_SAMPLES_NOT_INTERLEAVED; import static androidx.media3.container.MdtaMetadataEntry.TYPE_INDICATOR_8_BIT_UNSIGNED_INT; -import static androidx.media3.container.Mp4Util.MP4_AT_AUXILIARY_TRACK_TYPE_DEPTH_INVERSE; -import static androidx.media3.container.Mp4Util.MP4_AT_AUXILIARY_TRACK_TYPE_DEPTH_LINEAR; -import static androidx.media3.container.Mp4Util.MP4_AT_AUXILIARY_TRACK_TYPE_DEPTH_METADATA; -import static androidx.media3.container.Mp4Util.MP4_AT_AUXILIARY_TRACK_TYPE_SHARP; import androidx.media3.common.C; import androidx.media3.common.Format; @@ -134,16 +130,16 @@ public final class MuxerUtil { int trackType; switch (track.format.auxiliaryTrackType) { case C.AUXILIARY_TRACK_TYPE_ORIGINAL: - trackType = MP4_AT_AUXILIARY_TRACK_TYPE_SHARP; + trackType = 0; break; case C.AUXILIARY_TRACK_TYPE_DEPTH_LINEAR: - trackType = MP4_AT_AUXILIARY_TRACK_TYPE_DEPTH_LINEAR; + trackType = 1; break; case C.AUXILIARY_TRACK_TYPE_DEPTH_INVERSE: - trackType = MP4_AT_AUXILIARY_TRACK_TYPE_DEPTH_INVERSE; + trackType = 2; break; case C.AUXILIARY_TRACK_TYPE_DEPTH_METADATA: - trackType = MP4_AT_AUXILIARY_TRACK_TYPE_DEPTH_METADATA; + trackType = 3; break; default: throw new IllegalArgumentException( diff --git a/libraries/muxer/src/test/java/androidx/media3/muxer/Mp4MuxerEndToEndTest.java b/libraries/muxer/src/test/java/androidx/media3/muxer/Mp4MuxerEndToEndTest.java index 6e42612b92..06fdf22307 100644 --- a/libraries/muxer/src/test/java/androidx/media3/muxer/Mp4MuxerEndToEndTest.java +++ b/libraries/muxer/src/test/java/androidx/media3/muxer/Mp4MuxerEndToEndTest.java @@ -416,25 +416,28 @@ public class Mp4MuxerEndToEndTest { } @Test - public void createMp4Muxer_withFileFormatMp4AtButWithoutCacheFileProvider_throws() - throws Exception { + public void + createMp4Muxer_withMp4WithAuxiliaryTracksExtensionFileFormatButWithoutCacheFileProvider_throws() + throws Exception { String outputFilePath = temporaryFolder.newFile().getPath(); assertThrows( IllegalArgumentException.class, () -> new Mp4Muxer.Builder(new FileOutputStream(outputFilePath)) - .setOutputFileFormat(Mp4Muxer.FILE_FORMAT_MP4_AT) + .setOutputFileFormat(Mp4Muxer.FILE_FORMAT_MP4_WITH_AUXILIARY_TRACKS_EXTENSION) .build()); } @Test - public void writeMp4File_withFileFormatMp4AtAndAuxiliaryTracks_writesAxteBox() throws Exception { + public void + writeMp4File_withMp4WithAuxiliaryTracksExtensionFileFormatAndAuxiliaryTracks_writesAxteBox() + throws Exception { String outputFilePath = temporaryFolder.newFile().getPath(); String cacheFilePath = temporaryFolder.newFile().getPath(); Mp4Muxer muxer = new Mp4Muxer.Builder(new FileOutputStream(outputFilePath)) - .setOutputFileFormat(Mp4Muxer.FILE_FORMAT_MP4_AT) + .setOutputFileFormat(Mp4Muxer.FILE_FORMAT_MP4_WITH_AUXILIARY_TRACKS_EXTENSION) .setMp4AtFileParameters( new Mp4Muxer.Mp4AtFileParameters( /* shouldInterleaveSamples= */ false, () -> cacheFilePath)) @@ -477,7 +480,7 @@ public class Mp4MuxerEndToEndTest { } @Test - public void writeMp4File_withFileFormatDefaultAndAuxiliaryTracks_doesNotWriteAxteBox() + public void writeMp4File_withDefaultFileFormatAndAuxiliaryTracks_doesNotWriteAxteBox() throws Exception { String outputFilePath = temporaryFolder.newFile().getPath(); Mp4Muxer muxer = new Mp4Muxer.Builder(new FileOutputStream(outputFilePath)).build(); @@ -520,13 +523,13 @@ public class Mp4MuxerEndToEndTest { @Test public void - writeMp4File_withFileFormatMp4AtAndAuxiliaryVideoTracks_primaryVideoTracksMatchesExpected() + writeMp4File_withMp4WithAuxiliaryTracksExtensionFileFormatAndAuxiliaryVideoTracks_primaryVideoTracksMatchesExpected() throws Exception { String outputFilePath = temporaryFolder.newFile().getPath(); String cacheFilePath = temporaryFolder.newFile().getPath(); Mp4Muxer muxer = new Mp4Muxer.Builder(new FileOutputStream(outputFilePath)) - .setOutputFileFormat(Mp4Muxer.FILE_FORMAT_MP4_AT) + .setOutputFileFormat(Mp4Muxer.FILE_FORMAT_MP4_WITH_AUXILIARY_TRACKS_EXTENSION) .setMp4AtFileParameters( new Mp4Muxer.Mp4AtFileParameters( /* shouldInterleaveSamples= */ false, () -> cacheFilePath)) @@ -570,13 +573,14 @@ public class Mp4MuxerEndToEndTest { } @Test - public void writeMp4File_withFileFormatMp4AtAndAuxiliaryTracks_auxiliaryTracksMatchesExpected() - throws Exception { + public void + writeMp4File_withMp4WithAuxiliaryTracksExtensionFileFormatAndAuxiliaryTracks_auxiliaryTracksMatchesExpected() + throws Exception { String outputFilePath = temporaryFolder.newFile().getPath(); String cacheFilePath = temporaryFolder.newFile().getPath(); Mp4Muxer muxer = new Mp4Muxer.Builder(new FileOutputStream(outputFilePath)) - .setOutputFileFormat(Mp4Muxer.FILE_FORMAT_MP4_AT) + .setOutputFileFormat(Mp4Muxer.FILE_FORMAT_MP4_WITH_AUXILIARY_TRACKS_EXTENSION) .setMp4AtFileParameters( new Mp4Muxer.Mp4AtFileParameters( /* shouldInterleaveSamples= */ false, () -> cacheFilePath)) @@ -622,12 +626,12 @@ public class Mp4MuxerEndToEndTest { @Test public void - writeMp4File_withFileFormatMp4AtAndAuxiliaryTracksAndShouldInterleaveSamples_primaryVideoTracksMatchesExpected() + writeMp4File_withMp4WithAuxiliaryTracksExtensionFileFormatAndAuxiliaryTracksAndShouldInterleaveSamples_primaryVideoTracksMatchesExpected() throws Exception { String outputFilePath = temporaryFolder.newFile().getPath(); Mp4Muxer muxer = new Mp4Muxer.Builder(new FileOutputStream(outputFilePath)) - .setOutputFileFormat(Mp4Muxer.FILE_FORMAT_MP4_AT) + .setOutputFileFormat(Mp4Muxer.FILE_FORMAT_MP4_WITH_AUXILIARY_TRACKS_EXTENSION) .setMp4AtFileParameters( new Mp4Muxer.Mp4AtFileParameters( /* shouldInterleaveSamples= */ true, /* cacheFileProvider= */ null)) @@ -673,12 +677,12 @@ public class Mp4MuxerEndToEndTest { @Test public void - writeMp4File_withFileFormatMp4AtAndAuxiliaryTracksAndShouldInterleaveSamples_auxiliaryTracksMatchesExpected() + writeMp4File_withMp4WithAuxiliaryTracksExtensionFileFormatAndAuxiliaryTracksAndShouldInterleaveSamples_auxiliaryTracksMatchesExpected() throws Exception { String outputFilePath = temporaryFolder.newFile().getPath(); Mp4Muxer muxer = new Mp4Muxer.Builder(new FileOutputStream(outputFilePath)) - .setOutputFileFormat(Mp4Muxer.FILE_FORMAT_MP4_AT) + .setOutputFileFormat(Mp4Muxer.FILE_FORMAT_MP4_WITH_AUXILIARY_TRACKS_EXTENSION) .setMp4AtFileParameters( new Mp4Muxer.Mp4AtFileParameters( /* shouldInterleaveSamples= */ true, /* cacheFileProvider= */ null))