mirror of
https://github.com/androidx/media.git
synced 2025-04-30 06:46:50 +08:00
Fix some MP4-AT file format related naming
Also add spec link in the code. PiperOrigin-RevId: 704329143
This commit is contained in:
parent
459162c692
commit
e017213ee8
@ -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";
|
||||
|
||||
|
@ -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.
|
||||
*
|
||||
* <p>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.
|
||||
*
|
||||
* <p>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() {}
|
||||
}
|
@ -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.
|
||||
*
|
||||
* <p>Either primary video tracks or auxiliary tracks (but not both) will be extracted based on
|
||||
* the flag.
|
||||
*
|
||||
* <p>If the flag is set but the auxiliary tracks are not present, then it fallbacks to extract
|
||||
* primary tracks instead.
|
||||
*
|
||||
* <p>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:
|
||||
|
@ -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.
|
||||
*
|
||||
* <p>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 {
|
||||
*
|
||||
* <p>The default value is {@link #FILE_FORMAT_DEFAULT}.
|
||||
*
|
||||
* <p>For {@link #FILE_FORMAT_MP4_AT}, {@link Mp4AtFileParameters} must also be {@linkplain
|
||||
* #setMp4AtFileParameters(Mp4AtFileParameters)} set}.
|
||||
* <p>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);
|
||||
|
@ -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(
|
||||
|
@ -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))
|
||||
|
Loading…
x
Reference in New Issue
Block a user