From 462533219d19fc1b24461b5e171582fa2b051395 Mon Sep 17 00:00:00 2001 From: sheenachhabra Date: Wed, 19 Feb 2025 05:09:18 -0800 Subject: [PATCH] Create muxer specific `BufferInfo` class Muxer does not use `offset` field, hence not added. PiperOrigin-RevId: 728625538 --- RELEASENOTES.md | 2 + .../androidx/media3/common/util/Util.java | 14 +++++ .../java/androidx/media3/muxer/Boxes.java | 12 ++--- .../androidx/media3/muxer/BufferInfo.java | 46 +++++++++++++++++ .../media3/muxer/FragmentedMp4Muxer.java | 1 - .../media3/muxer/FragmentedMp4Writer.java | 20 ++++---- .../java/androidx/media3/muxer/Mp4Muxer.java | 18 +++---- .../java/androidx/media3/muxer/Mp4Writer.java | 11 ++-- .../java/androidx/media3/muxer/MuxerUtil.java | 11 ++++ .../java/androidx/media3/muxer/Track.java | 15 ++---- .../java/androidx/media3/muxer/BoxesTest.java | 51 +++++++++---------- .../muxer/FragmentedMp4MuxerEndToEndTest.java | 12 ++--- .../Mp4MuxerEndToEndParameterizedTest.java | 12 ++--- .../media3/muxer/Mp4MuxerEndToEndTest.java | 24 ++++----- .../media3/muxer/Mp4MuxerMetadataTest.java | 1 - .../androidx/media3/muxer/MuxerTestUtil.java | 9 ++-- .../transformer/InAppFragmentedMp4Muxer.java | 10 ++-- .../media3/transformer/InAppMp4Muxer.java | 10 ++-- 18 files changed, 166 insertions(+), 113 deletions(-) create mode 100644 libraries/muxer/src/main/java/androidx/media3/muxer/BufferInfo.java diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 5d218776e3..812b61c354 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -20,6 +20,8 @@ * DRM: * Effect: * Muxers: + * `writeSampleData()` API now uses muxer specific `BufferInfo` class + instead of `MediaCodec.BufferInfo`. * IMA extension: * Session: * Make `MediaSession.setSessionActivity(PendingIntent)` accept null diff --git a/libraries/common/src/main/java/androidx/media3/common/util/Util.java b/libraries/common/src/main/java/androidx/media3/common/util/Util.java index 577082118d..bb85b79a49 100644 --- a/libraries/common/src/main/java/androidx/media3/common/util/Util.java +++ b/libraries/common/src/main/java/androidx/media3/common/util/Util.java @@ -3478,6 +3478,20 @@ public final class Util { } } + /** Returns {@link C.BufferFlags} corresponding to {@link MediaCodec} flags. */ + @UnstableApi + public static @C.BufferFlags int getBufferFlagsFromMediaCodecFlags(int mediaCodecFlags) { + @C.BufferFlags int flags = 0; + if ((mediaCodecFlags & MediaCodec.BUFFER_FLAG_KEY_FRAME) == MediaCodec.BUFFER_FLAG_KEY_FRAME) { + flags |= C.BUFFER_FLAG_KEY_FRAME; + } + if ((mediaCodecFlags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) + == MediaCodec.BUFFER_FLAG_END_OF_STREAM) { + flags |= C.BUFFER_FLAG_END_OF_STREAM; + } + return flags; + } + @UnstableApi public static boolean isFrameDropAllowedOnSurfaceInput(Context context) { // Prior to API 29, decoders may drop frames to keep their output surface from growing out of diff --git a/libraries/muxer/src/main/java/androidx/media3/muxer/Boxes.java b/libraries/muxer/src/main/java/androidx/media3/muxer/Boxes.java index c10324142c..29ab42fe09 100644 --- a/libraries/muxer/src/main/java/androidx/media3/muxer/Boxes.java +++ b/libraries/muxer/src/main/java/androidx/media3/muxer/Boxes.java @@ -24,8 +24,6 @@ import static java.lang.Math.max; import static java.lang.Math.min; import static java.nio.charset.StandardCharsets.UTF_8; -import android.media.MediaCodec; -import android.media.MediaCodec.BufferInfo; import android.media.MediaCodecInfo; import android.util.Pair; import androidx.annotation.Nullable; @@ -1045,7 +1043,7 @@ import org.checkerframework.checker.nullness.qual.PolyNull; } /** Returns the stsz (sample size) box. */ - public static ByteBuffer stsz(List writtenSamples) { + public static ByteBuffer stsz(List writtenSamples) { ByteBuffer contents = ByteBuffer.allocate(writtenSamples.size() * 4 + MAX_FIXED_LEAF_BOX_SIZE); contents.putInt(0x0); // version and flags @@ -1133,7 +1131,7 @@ import org.checkerframework.checker.nullness.qual.PolyNull; } /** Returns the stss (sync sample) box. */ - public static ByteBuffer stss(List writtenSamples) { + public static ByteBuffer stss(List writtenSamples) { ByteBuffer contents = ByteBuffer.allocate(writtenSamples.size() * 4 + MAX_FIXED_LEAF_BOX_SIZE); contents.putInt(0x0); // version and flags @@ -1146,8 +1144,8 @@ import org.checkerframework.checker.nullness.qual.PolyNull; int currentSampleNumber = 1; int totalKeyFrames = 0; for (int i = 0; i < writtenSamples.size(); i++) { - MediaCodec.BufferInfo info = writtenSamples.get(i); - if ((info.flags & MediaCodec.BUFFER_FLAG_KEY_FRAME) > 0) { + BufferInfo info = writtenSamples.get(i); + if ((info.flags & C.BUFFER_FLAG_KEY_FRAME) > 0) { contents.putInt(currentSampleNumber); totalKeyFrames++; } @@ -1258,7 +1256,7 @@ import org.checkerframework.checker.nullness.qual.PolyNull; contents.putInt(currentSampleMetadata.durationVu); // An unsigned int(32) contents.putInt(currentSampleMetadata.size); // An unsigned int(32) contents.putInt( - (currentSampleMetadata.flags & MediaCodec.BUFFER_FLAG_KEY_FRAME) != 0 + (currentSampleMetadata.flags & C.BUFFER_FLAG_KEY_FRAME) != 0 ? TRUN_BOX_SYNC_SAMPLE_FLAGS : TRUN_BOX_NON_SYNC_SAMPLE_FLAGS); if (hasBFrame) { diff --git a/libraries/muxer/src/main/java/androidx/media3/muxer/BufferInfo.java b/libraries/muxer/src/main/java/androidx/media3/muxer/BufferInfo.java new file mode 100644 index 0000000000..3dd43835a4 --- /dev/null +++ b/libraries/muxer/src/main/java/androidx/media3/muxer/BufferInfo.java @@ -0,0 +1,46 @@ +/* + * Copyright 2025 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 + * + * https://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.muxer; + +import androidx.media3.common.C; +import androidx.media3.common.util.UnstableApi; +import java.nio.ByteBuffer; + +/** Contains metadata of a sample {@link ByteBuffer}. */ +@UnstableApi +public final class BufferInfo { + /** The presentation timestamp of sample (in microseconds). */ + public final long presentationTimeUs; + + /** The amount of data (in bytes) in the buffer. */ + public final int size; + + /** The buffer flags, which should be a combination of the {@code C.BUFFER_FLAG_*}. */ + public final @C.BufferFlags int flags; + + /** + * Creates an instance. + * + * @param presentationTimeUs The presentation timestamp of sample (in microseconds). + * @param size The amount of data (in bytes) in the buffer. + * @param flags The buffer flags, which should be a combination of the {@code C.BUFFER_FLAG_*}. + */ + public BufferInfo(long presentationTimeUs, int size, @C.BufferFlags int flags) { + this.presentationTimeUs = presentationTimeUs; + this.size = size; + this.flags = flags; + } +} diff --git a/libraries/muxer/src/main/java/androidx/media3/muxer/FragmentedMp4Muxer.java b/libraries/muxer/src/main/java/androidx/media3/muxer/FragmentedMp4Muxer.java index d04eb57125..e7fed6c030 100644 --- a/libraries/muxer/src/main/java/androidx/media3/muxer/FragmentedMp4Muxer.java +++ b/libraries/muxer/src/main/java/androidx/media3/muxer/FragmentedMp4Muxer.java @@ -18,7 +18,6 @@ package androidx.media3.muxer; import static androidx.media3.common.util.Assertions.checkArgument; import static androidx.media3.common.util.Assertions.checkNotNull; -import android.media.MediaCodec.BufferInfo; import android.util.SparseArray; import androidx.media3.common.Format; import androidx.media3.common.Metadata; diff --git a/libraries/muxer/src/main/java/androidx/media3/muxer/FragmentedMp4Writer.java b/libraries/muxer/src/main/java/androidx/media3/muxer/FragmentedMp4Writer.java index c95d383801..119346b3eb 100644 --- a/libraries/muxer/src/main/java/androidx/media3/muxer/FragmentedMp4Writer.java +++ b/libraries/muxer/src/main/java/androidx/media3/muxer/FragmentedMp4Writer.java @@ -28,8 +28,7 @@ import static androidx.media3.muxer.MuxerUtil.UNSIGNED_INT_MAX_VALUE; import static java.lang.Math.max; import static java.lang.Math.min; -import android.media.MediaCodec; -import android.media.MediaCodec.BufferInfo; +import androidx.media3.common.C; import androidx.media3.common.Format; import androidx.media3.common.MimeTypes; import androidx.media3.common.util.Util; @@ -164,7 +163,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; return track; } - public void writeSampleData(Track track, ByteBuffer byteBuffer, MediaCodec.BufferInfo bufferInfo) + public void writeSampleData(Track track, ByteBuffer byteBuffer, BufferInfo bufferInfo) throws IOException { if (!headerCreated) { createHeader(); @@ -250,15 +249,14 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; tracks, metadataCollector, /* isFragmentedMp4= */ true, lastSampleDurationBehavior)); } - private boolean shouldFlushPendingSamples( - Track track, MediaCodec.BufferInfo nextSampleBufferInfo) { + private boolean shouldFlushPendingSamples(Track track, BufferInfo nextSampleBufferInfo) { // If video track is present then fragment will be created based on group of pictures and // track's duration so far. if (videoTrack != null) { // Video samples can be written only when complete group of pictures are present. if (track.equals(videoTrack) && track.hadKeyframe - && ((nextSampleBufferInfo.flags & MediaCodec.BUFFER_FLAG_KEY_FRAME) > 0)) { + && ((nextSampleBufferInfo.flags & C.BUFFER_FLAG_KEY_FRAME) > 0)) { BufferInfo firstPendingSample = checkNotNull(track.pendingSamplesBufferInfo.peekFirst()); BufferInfo lastPendingSample = checkNotNull(track.pendingSamplesBufferInfo.peekLast()); return lastPendingSample.presentationTimeUs - firstPendingSample.presentationTimeUs @@ -353,11 +351,11 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; annexBToAvccConverter.process(currentSampleByteBuffer, linearByteBufferAllocator); pendingSamplesByteBuffer.add(currentSampleByteBuffer); BufferInfo currentSampleBufferInfo = track.pendingSamplesBufferInfo.removeFirst(); - currentSampleBufferInfo.set( - currentSampleByteBuffer.position(), - currentSampleByteBuffer.remaining(), - currentSampleBufferInfo.presentationTimeUs, - currentSampleBufferInfo.flags); + currentSampleBufferInfo = + new BufferInfo( + currentSampleBufferInfo.presentationTimeUs, + currentSampleByteBuffer.remaining(), + currentSampleBufferInfo.flags); pendingSamplesBufferInfoBuilder.add(currentSampleBufferInfo); } } else { 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 5430c54add..cbca31ae69 100644 --- a/libraries/muxer/src/main/java/androidx/media3/muxer/Mp4Muxer.java +++ b/libraries/muxer/src/main/java/androidx/media3/muxer/Mp4Muxer.java @@ -27,8 +27,6 @@ import static androidx.media3.muxer.MuxerUtil.isMetadataSupported; import static androidx.media3.muxer.MuxerUtil.populateAuxiliaryTracksMetadata; import static java.lang.annotation.ElementType.TYPE_USE; -import android.media.MediaCodec; -import android.media.MediaCodec.BufferInfo; import androidx.annotation.IntDef; import androidx.annotation.Nullable; import androidx.media3.common.C; @@ -160,19 +158,19 @@ public final class Mp4Muxer implements AutoCloseable { public static final int LAST_SAMPLE_DURATION_BEHAVIOR_SET_TO_ZERO = 0; /** - * Use the {@link MediaCodec#BUFFER_FLAG_END_OF_STREAM end of stream sample} to set the duration - * of the last sample. + * Use the {@link C#BUFFER_FLAG_END_OF_STREAM end of stream sample} to set the duration of the + * last sample. * *

After {@linkplain #writeSampleData writing} all the samples for a track, the app must * {@linkplain #writeSampleData write} an empty sample with flag {@link - * MediaCodec#BUFFER_FLAG_END_OF_STREAM}. The timestamp of this sample should be equal to the - * desired track duration. + * C#BUFFER_FLAG_END_OF_STREAM}. The timestamp of this sample should be equal to the desired track + * duration. * - *

Once a sample with flag {@link MediaCodec#BUFFER_FLAG_END_OF_STREAM} is {@linkplain - * #writeSampleData written}, no more samples can be written for that track. + *

Once a sample with flag {@link C#BUFFER_FLAG_END_OF_STREAM} is {@linkplain #writeSampleData + * written}, no more samples can be written for that track. * - *

If no explicit {@link MediaCodec#BUFFER_FLAG_END_OF_STREAM} sample is passed, then the - * duration of the last sample will be same as that of the sample before that. + *

If no explicit {@link C#BUFFER_FLAG_END_OF_STREAM} sample is passed, then the duration of + * the last sample will be same as that of the sample before that. */ public static final int LAST_SAMPLE_DURATION_BEHAVIOR_SET_FROM_END_OF_STREAM_BUFFER_OR_DUPLICATE_PREVIOUS = 1; diff --git a/libraries/muxer/src/main/java/androidx/media3/muxer/Mp4Writer.java b/libraries/muxer/src/main/java/androidx/media3/muxer/Mp4Writer.java index c7d0419e8c..b8dec32424 100644 --- a/libraries/muxer/src/main/java/androidx/media3/muxer/Mp4Writer.java +++ b/libraries/muxer/src/main/java/androidx/media3/muxer/Mp4Writer.java @@ -27,7 +27,6 @@ import static androidx.media3.muxer.MuxerUtil.populateAuxiliaryTracksMetadata; import static java.lang.Math.max; import static java.lang.Math.min; -import android.media.MediaCodec.BufferInfo; import androidx.media3.common.Format; import androidx.media3.common.util.Util; import androidx.media3.container.MdtaMetadataEntry; @@ -463,11 +462,11 @@ import java.util.concurrent.atomic.AtomicBoolean; if (doesSampleContainAnnexBNalUnits(checkNotNull(track.format.sampleMimeType))) { currentSampleByteBuffer = annexBToAvccConverter.process(currentSampleByteBuffer, linearByteBufferAllocator); - currentSampleBufferInfo.set( - currentSampleByteBuffer.position(), - currentSampleByteBuffer.remaining(), - currentSampleBufferInfo.presentationTimeUs, - currentSampleBufferInfo.flags); + currentSampleBufferInfo = + new BufferInfo( + currentSampleBufferInfo.presentationTimeUs, + currentSampleByteBuffer.remaining(), + currentSampleBufferInfo.flags); } // If the original sample had 3 bytes NAL start code instead of 4 bytes, then after AnnexB to 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 efb52baaed..20198a8675 100644 --- a/libraries/muxer/src/main/java/androidx/media3/muxer/MuxerUtil.java +++ b/libraries/muxer/src/main/java/androidx/media3/muxer/MuxerUtil.java @@ -15,10 +15,12 @@ */ package androidx.media3.muxer; +import static androidx.media3.common.util.Util.getBufferFlagsFromMediaCodecFlags; 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 android.media.MediaCodec; import androidx.media3.common.C; import androidx.media3.common.Format; import androidx.media3.common.Metadata; @@ -50,6 +52,15 @@ public final class MuxerUtil { || metadata instanceof XmpData; } + /** Returns {@link BufferInfo} corresponding to the {@link MediaCodec.BufferInfo}. */ + public static BufferInfo getMuxerBufferInfoFromMediaCodecBufferInfo( + MediaCodec.BufferInfo mediaCodecBufferInfo) { + return new BufferInfo( + mediaCodecBufferInfo.presentationTimeUs, + mediaCodecBufferInfo.size, + getBufferFlagsFromMediaCodecFlags(mediaCodecBufferInfo.flags)); + } + /** * Returns whether the given {@linkplain Format track format} is an auxiliary track. * diff --git a/libraries/muxer/src/main/java/androidx/media3/muxer/Track.java b/libraries/muxer/src/main/java/androidx/media3/muxer/Track.java index 996267fddc..2da0b84d85 100644 --- a/libraries/muxer/src/main/java/androidx/media3/muxer/Track.java +++ b/libraries/muxer/src/main/java/androidx/media3/muxer/Track.java @@ -17,8 +17,6 @@ package androidx.media3.muxer; import static androidx.media3.common.util.Assertions.checkArgument; -import android.media.MediaCodec; -import android.media.MediaCodec.BufferInfo; import androidx.media3.common.C; import androidx.media3.common.Format; import androidx.media3.common.MimeTypes; @@ -76,13 +74,13 @@ import java.util.List; + " MediaCodec.BUFFER_FLAG_END_OF_STREAM flag"); // Skip empty samples. if (bufferInfo.size == 0 || byteBuffer.remaining() == 0) { - if ((bufferInfo.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0) { + if ((bufferInfo.flags & C.BUFFER_FLAG_END_OF_STREAM) != 0) { endOfStreamTimestampUs = bufferInfo.presentationTimeUs; } return; } - if ((bufferInfo.flags & MediaCodec.BUFFER_FLAG_KEY_FRAME) > 0) { + if ((bufferInfo.flags & C.BUFFER_FLAG_KEY_FRAME) > 0) { hadKeyframe = true; } @@ -100,12 +98,9 @@ import java.util.List; } // Always copy the buffer info as it is retained until the track is finalized. - BufferInfo bufferInfoToAdd = new BufferInfo(); - bufferInfoToAdd.set( - /* newOffset= */ byteBufferToAdd.position(), - /* newSize= */ byteBufferToAdd.remaining(), - bufferInfo.presentationTimeUs, - bufferInfo.flags); + BufferInfo bufferInfoToAdd = + new BufferInfo( + bufferInfo.presentationTimeUs, byteBufferToAdd.remaining(), bufferInfo.flags); pendingSamplesBufferInfo.addLast(bufferInfoToAdd); pendingSamplesByteBuffer.addLast(byteBufferToAdd); diff --git a/libraries/muxer/src/test/java/androidx/media3/muxer/BoxesTest.java b/libraries/muxer/src/test/java/androidx/media3/muxer/BoxesTest.java index 75a0a12ee0..b76f6c7ec0 100644 --- a/libraries/muxer/src/test/java/androidx/media3/muxer/BoxesTest.java +++ b/libraries/muxer/src/test/java/androidx/media3/muxer/BoxesTest.java @@ -517,8 +517,7 @@ public class BoxesTest { @Test public void convertPresentationTimestampsToDurationsVu_singleSampleAtZeroTimestamp_returnsSampleLengthEqualsZero() { - List sampleBufferInfos = - createBufferInfoListWithSamplePresentationTimestamps(0L); + List sampleBufferInfos = createBufferInfoListWithSamplePresentationTimestamps(0L); List durationsVu = Boxes.convertPresentationTimestampsToDurationsVu( @@ -533,7 +532,7 @@ public class BoxesTest { @Test public void convertPresentationTimestampsToDurationsVu_singleSampleAtNonZeroTimestamp_returnsSampleLengthEqualsZero() { - List sampleBufferInfos = + List sampleBufferInfos = createBufferInfoListWithSamplePresentationTimestamps(5_000L); List durationsVu = @@ -549,7 +548,7 @@ public class BoxesTest { @Test public void convertPresentationTimestampsToDurationsVu_differentSampleDurations_lastFrameDurationShort_returnsLastSampleOfZeroDuration() { - List sampleBufferInfos = + List sampleBufferInfos = createBufferInfoListWithSamplePresentationTimestamps(0L, 30_000L, 80_000L); List durationsVu = @@ -565,7 +564,7 @@ public class BoxesTest { @Test public void convertPresentationTimestampsToDurationsVu_differentSampleDurations_lastFrameDurationDuplicate_returnsLastSampleOfDuplicateDuration() { - List sampleBufferInfos = + List sampleBufferInfos = createBufferInfoListWithSamplePresentationTimestamps(0L, 30_000L, 80_000L); List durationsVu = @@ -581,7 +580,7 @@ public class BoxesTest { @Test public void convertPresentationTimestampsToDurationsVu_withOutOfOrderSampleTimestamps_returnsExpectedDurations() { - List sampleBufferInfos = + List sampleBufferInfos = createBufferInfoListWithSamplePresentationTimestamps(0L, 10_000L, 1_000L, 2_000L, 11_000L); List durationsVu = @@ -597,7 +596,7 @@ public class BoxesTest { @Test public void convertPresentationTimestampsToDurationsVu_withLastSampleDurationBehaviorUsingEndOfStreamFlag_returnsExpectedDurations() { - List sampleBufferInfos = + List sampleBufferInfos = createBufferInfoListWithSamplePresentationTimestamps(0L, 1_000L, 2_000L, 3_000L, 4_000L); List durationsVu = @@ -652,8 +651,7 @@ public class BoxesTest { @Test public void createCttsBox_withSingleSampleTimestamp_returnsEmptyBox() { - List sampleBufferInfos = - createBufferInfoListWithSamplePresentationTimestamps(400); + List sampleBufferInfos = createBufferInfoListWithSamplePresentationTimestamps(400); List durationsVu = Boxes.convertPresentationTimestampsToDurationsVu( sampleBufferInfos, @@ -669,7 +667,7 @@ public class BoxesTest { @Test public void createCttsBox_withNoBframesSampleTimestamps_returnsEmptyBox() throws IOException { - List sampleBufferInfos = + List sampleBufferInfos = createBufferInfoListWithSamplePresentationTimestamps(0L, 1000L, 2000L); List durationsVu = Boxes.convertPresentationTimestampsToDurationsVu( @@ -686,7 +684,7 @@ public class BoxesTest { @Test public void createCttsBox_withBFramesSampleTimestamps_matchesExpected() throws IOException { - List sampleBufferInfos = + List sampleBufferInfos = createBufferInfoListWithSamplePresentationTimestamps( 0, 400, 200, 100, 300, 800, 600, 500, 700); @@ -706,7 +704,7 @@ public class BoxesTest { @Test public void createCttsBox_withLargeSampleTimestamps_matchesExpected() throws IOException { - List sampleBufferInfos = + List sampleBufferInfos = createBufferInfoListWithSamplePresentationTimestamps( 23698215060L, 23698248252L, 23698347988L, 23698488968L, 23698547416L); @@ -724,8 +722,7 @@ public class BoxesTest { @Test public void createStszBox_matchesExpected() throws IOException { - List sampleBufferInfos = - createBufferInfoListWithSampleSizes(100, 200, 150, 200); + List sampleBufferInfos = createBufferInfoListWithSampleSizes(100, 200, 150, 200); ByteBuffer stszBox = Boxes.stsz(sampleBufferInfos); @@ -780,7 +777,7 @@ public class BoxesTest { @Test public void createStssBox_matchesExpected() throws IOException { - List sampleBufferInfos = createBufferInfoListWithSomeKeyFrames(); + List sampleBufferInfos = createBufferInfoListWithSomeKeyFrames(); ByteBuffer stssBox = Boxes.stss(sampleBufferInfos); @@ -867,37 +864,35 @@ public class BoxesTest { context, dumpableBox, MuxerTestUtil.getExpectedDumpFilePath("trex_box")); } - private static List createBufferInfoListWithSamplePresentationTimestamps( + private static List createBufferInfoListWithSamplePresentationTimestamps( long... timestampsUs) { - List bufferInfoList = new ArrayList<>(); + List bufferInfoList = new ArrayList<>(); for (long timestampUs : timestampsUs) { - MediaCodec.BufferInfo bufferInfo = new MediaCodec.BufferInfo(); - bufferInfo.presentationTimeUs = timestampUs; + BufferInfo bufferInfo = new BufferInfo(timestampUs, /* size= */ 0, /* flags= */ 0); bufferInfoList.add(bufferInfo); } return bufferInfoList; } - private static List createBufferInfoListWithSampleSizes(int... sizes) { - List bufferInfoList = new ArrayList<>(); + private static List createBufferInfoListWithSampleSizes(int... sizes) { + List bufferInfoList = new ArrayList<>(); for (int size : sizes) { - MediaCodec.BufferInfo bufferInfo = new MediaCodec.BufferInfo(); - bufferInfo.size = size; + BufferInfo bufferInfo = new BufferInfo(/* presentationTimeUs= */ 0, size, /* flags= */ 0); bufferInfoList.add(bufferInfo); } return bufferInfoList; } - private static List createBufferInfoListWithSomeKeyFrames() { - List bufferInfoList = new ArrayList<>(); + private static List createBufferInfoListWithSomeKeyFrames() { + List bufferInfoList = new ArrayList<>(); for (int i = 0; i < 30; i++) { - MediaCodec.BufferInfo bufferInfo = new MediaCodec.BufferInfo(); + @C.BufferFlags int flags = 0; if (i % 5 == 0) { // Make every 5th frame as key frame. - bufferInfo.flags = MediaCodec.BUFFER_FLAG_KEY_FRAME; + flags = C.BUFFER_FLAG_KEY_FRAME; } - bufferInfoList.add(bufferInfo); + bufferInfoList.add(new BufferInfo(/* presentationTimeUs= */ 0, /* size= */ 0, flags)); } return bufferInfoList; diff --git a/libraries/muxer/src/test/java/androidx/media3/muxer/FragmentedMp4MuxerEndToEndTest.java b/libraries/muxer/src/test/java/androidx/media3/muxer/FragmentedMp4MuxerEndToEndTest.java index 1c0e6c65f1..5417ca34a8 100644 --- a/libraries/muxer/src/test/java/androidx/media3/muxer/FragmentedMp4MuxerEndToEndTest.java +++ b/libraries/muxer/src/test/java/androidx/media3/muxer/FragmentedMp4MuxerEndToEndTest.java @@ -16,10 +16,10 @@ package androidx.media3.muxer; import static androidx.media3.common.util.Assertions.checkNotNull; +import static androidx.media3.common.util.Util.getBufferFlagsFromMediaCodecFlags; import static androidx.media3.muxer.MuxerTestUtil.MP4_FILE_ASSET_DIRECTORY; import android.content.Context; -import android.media.MediaCodec; import android.net.Uri; import androidx.annotation.Nullable; import androidx.media3.common.util.MediaFormatUtil; @@ -149,12 +149,12 @@ public class FragmentedMp4MuxerEndToEndTest { } do { - MediaCodec.BufferInfo bufferInfo = new MediaCodec.BufferInfo(); - bufferInfo.flags = extractor.getSampleFlags(); - bufferInfo.offset = 0; - bufferInfo.presentationTimeUs = extractor.getSampleTime(); int sampleSize = (int) extractor.getSampleSize(); - bufferInfo.size = sampleSize; + BufferInfo bufferInfo = + new BufferInfo( + extractor.getSampleTime(), + sampleSize, + getBufferFlagsFromMediaCodecFlags(extractor.getSampleFlags())); ByteBuffer sampleBuffer = ByteBuffer.allocateDirect(sampleSize); extractor.readSampleData(sampleBuffer, /* offset= */ 0); diff --git a/libraries/muxer/src/test/java/androidx/media3/muxer/Mp4MuxerEndToEndParameterizedTest.java b/libraries/muxer/src/test/java/androidx/media3/muxer/Mp4MuxerEndToEndParameterizedTest.java index f8c94ec0ab..6a06133d6e 100644 --- a/libraries/muxer/src/test/java/androidx/media3/muxer/Mp4MuxerEndToEndParameterizedTest.java +++ b/libraries/muxer/src/test/java/androidx/media3/muxer/Mp4MuxerEndToEndParameterizedTest.java @@ -16,10 +16,10 @@ package androidx.media3.muxer; import static androidx.media3.common.util.Assertions.checkNotNull; +import static androidx.media3.common.util.Util.getBufferFlagsFromMediaCodecFlags; import static androidx.media3.muxer.MuxerTestUtil.MP4_FILE_ASSET_DIRECTORY; import android.content.Context; -import android.media.MediaCodec; import android.net.Uri; import androidx.annotation.Nullable; import androidx.media3.common.util.MediaFormatUtil; @@ -153,12 +153,12 @@ public class Mp4MuxerEndToEndParameterizedTest { } do { - MediaCodec.BufferInfo bufferInfo = new MediaCodec.BufferInfo(); - bufferInfo.flags = extractor.getSampleFlags(); - bufferInfo.offset = 0; - bufferInfo.presentationTimeUs = extractor.getSampleTime(); int sampleSize = (int) extractor.getSampleSize(); - bufferInfo.size = sampleSize; + BufferInfo bufferInfo = + new BufferInfo( + extractor.getSampleTime(), + sampleSize, + getBufferFlagsFromMediaCodecFlags(extractor.getSampleFlags())); ByteBuffer sampleBuffer = ByteBuffer.allocateDirect(sampleSize); extractor.readSampleData(sampleBuffer, /* offset= */ 0); 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 9b232761e8..365e848253 100644 --- a/libraries/muxer/src/test/java/androidx/media3/muxer/Mp4MuxerEndToEndTest.java +++ b/libraries/muxer/src/test/java/androidx/media3/muxer/Mp4MuxerEndToEndTest.java @@ -16,6 +16,7 @@ package androidx.media3.muxer; import static androidx.media3.common.util.Assertions.checkNotNull; +import static androidx.media3.common.util.Util.getBufferFlagsFromMediaCodecFlags; import static androidx.media3.muxer.Mp4Muxer.LAST_SAMPLE_DURATION_BEHAVIOR_SET_FROM_END_OF_STREAM_BUFFER_OR_DUPLICATE_PREVIOUS; import static androidx.media3.muxer.MuxerTestUtil.FAKE_VIDEO_FORMAT; import static androidx.media3.muxer.MuxerTestUtil.MP4_FILE_ASSET_DIRECTORY; @@ -25,8 +26,6 @@ import static com.google.common.truth.Truth.assertThat; import static org.junit.Assert.assertThrows; import android.content.Context; -import android.media.MediaCodec; -import android.media.MediaCodec.BufferInfo; import android.net.Uri; import android.util.Pair; import androidx.media3.common.C; @@ -791,12 +790,11 @@ public class Mp4MuxerEndToEndTest { mp4Muxer.writeSampleData(track, sample3.first, sample3.second); mp4Muxer.writeSampleData(track, sample4.first, sample4.second); // Write end of stream sample. - BufferInfo endOfStreamBufferInfo = new BufferInfo(); - endOfStreamBufferInfo.set( - /* newOffset= */ 0, - /* newSize= */ 0, - /* newTimeUs= */ expectedDurationUs, - /* newFlags= */ MediaCodec.BUFFER_FLAG_END_OF_STREAM); + BufferInfo endOfStreamBufferInfo = + new BufferInfo( + /* presentationTimeUs= */ expectedDurationUs, + /* size= */ 0, + C.BUFFER_FLAG_END_OF_STREAM); mp4Muxer.writeSampleData(track, ByteBuffer.allocate(0), endOfStreamBufferInfo); } finally { mp4Muxer.close(); @@ -929,12 +927,12 @@ public class Mp4MuxerEndToEndTest { } do { - MediaCodec.BufferInfo bufferInfo = new MediaCodec.BufferInfo(); - bufferInfo.flags = extractor.getSampleFlags(); - bufferInfo.offset = 0; - bufferInfo.presentationTimeUs = extractor.getSampleTime(); int sampleSize = (int) extractor.getSampleSize(); - bufferInfo.size = sampleSize; + BufferInfo bufferInfo = + new BufferInfo( + extractor.getSampleTime(), + sampleSize, + getBufferFlagsFromMediaCodecFlags(extractor.getSampleFlags())); ByteBuffer sampleBuffer = ByteBuffer.allocateDirect(sampleSize); extractor.readSampleData(sampleBuffer, /* offset= */ 0); diff --git a/libraries/muxer/src/test/java/androidx/media3/muxer/Mp4MuxerMetadataTest.java b/libraries/muxer/src/test/java/androidx/media3/muxer/Mp4MuxerMetadataTest.java index 0c5b3da76b..36ef642601 100644 --- a/libraries/muxer/src/test/java/androidx/media3/muxer/Mp4MuxerMetadataTest.java +++ b/libraries/muxer/src/test/java/androidx/media3/muxer/Mp4MuxerMetadataTest.java @@ -22,7 +22,6 @@ import static androidx.media3.muxer.MuxerTestUtil.FAKE_VIDEO_FORMAT; import static androidx.media3.muxer.MuxerTestUtil.XMP_SAMPLE_DATA; import android.content.Context; -import android.media.MediaCodec.BufferInfo; import android.util.Pair; import androidx.media3.common.util.Util; import androidx.media3.container.MdtaMetadataEntry; diff --git a/libraries/muxer/src/test/java/androidx/media3/muxer/MuxerTestUtil.java b/libraries/muxer/src/test/java/androidx/media3/muxer/MuxerTestUtil.java index 8a251d71fb..ee6a7be764 100644 --- a/libraries/muxer/src/test/java/androidx/media3/muxer/MuxerTestUtil.java +++ b/libraries/muxer/src/test/java/androidx/media3/muxer/MuxerTestUtil.java @@ -18,9 +18,8 @@ package androidx.media3.muxer; import static androidx.media3.common.MimeTypes.AUDIO_AAC; import static androidx.media3.common.MimeTypes.VIDEO_H264; -import android.media.MediaCodec; -import android.media.MediaCodec.BufferInfo; import android.util.Pair; +import androidx.media3.common.C; import androidx.media3.common.Format; import com.google.common.collect.ImmutableList; import com.google.common.io.BaseEncoding; @@ -66,10 +65,8 @@ import java.nio.ByteBuffer; sampleDirectBuffer.put(FAKE_H264_SAMPLE); sampleDirectBuffer.rewind(); - BufferInfo bufferInfo = new BufferInfo(); - bufferInfo.presentationTimeUs = presentationTimeUs; - bufferInfo.flags = MediaCodec.BUFFER_FLAG_KEY_FRAME; - bufferInfo.size = FAKE_H264_SAMPLE.length; + BufferInfo bufferInfo = + new BufferInfo(presentationTimeUs, FAKE_H264_SAMPLE.length, C.BUFFER_FLAG_KEY_FRAME); return new Pair<>(sampleDirectBuffer, bufferInfo); } diff --git a/libraries/transformer/src/main/java/androidx/media3/transformer/InAppFragmentedMp4Muxer.java b/libraries/transformer/src/main/java/androidx/media3/transformer/InAppFragmentedMp4Muxer.java index f0db699d92..9b14ead8fd 100644 --- a/libraries/transformer/src/main/java/androidx/media3/transformer/InAppFragmentedMp4Muxer.java +++ b/libraries/transformer/src/main/java/androidx/media3/transformer/InAppFragmentedMp4Muxer.java @@ -15,8 +15,9 @@ */ package androidx.media3.transformer; +import static androidx.media3.muxer.MuxerUtil.getMuxerBufferInfoFromMediaCodecBufferInfo; + import android.media.MediaCodec; -import android.media.MediaCodec.BufferInfo; import androidx.media3.common.C; import androidx.media3.common.Format; import androidx.media3.common.MediaLibraryInfo; @@ -138,7 +139,7 @@ public final class InAppFragmentedMp4Muxer implements Muxer { } @Override - public void writeSampleData(int trackId, ByteBuffer byteBuffer, BufferInfo bufferInfo) + public void writeSampleData(int trackId, ByteBuffer byteBuffer, MediaCodec.BufferInfo bufferInfo) throws MuxerException { if (videoDurationUs != C.TIME_UNSET && trackId == videoTrackId @@ -152,7 +153,8 @@ public final class InAppFragmentedMp4Muxer implements Muxer { videoDurationUs)); return; } - muxer.writeSampleData(trackId, byteBuffer, bufferInfo); + muxer.writeSampleData( + trackId, byteBuffer, getMuxerBufferInfoFromMediaCodecBufferInfo(bufferInfo)); } @Override @@ -165,7 +167,7 @@ public final class InAppFragmentedMp4Muxer implements Muxer { @Override public void close() throws MuxerException { if (videoDurationUs != C.TIME_UNSET && videoTrackId != TRACK_ID_UNSET) { - BufferInfo bufferInfo = new BufferInfo(); + MediaCodec.BufferInfo bufferInfo = new MediaCodec.BufferInfo(); bufferInfo.set( /* newOffset= */ 0, /* newSize= */ 0, diff --git a/libraries/transformer/src/main/java/androidx/media3/transformer/InAppMp4Muxer.java b/libraries/transformer/src/main/java/androidx/media3/transformer/InAppMp4Muxer.java index b01ff1b202..1055e40d70 100644 --- a/libraries/transformer/src/main/java/androidx/media3/transformer/InAppMp4Muxer.java +++ b/libraries/transformer/src/main/java/androidx/media3/transformer/InAppMp4Muxer.java @@ -15,8 +15,9 @@ */ package androidx.media3.transformer; +import static androidx.media3.muxer.MuxerUtil.getMuxerBufferInfoFromMediaCodecBufferInfo; + import android.media.MediaCodec; -import android.media.MediaCodec.BufferInfo; import androidx.annotation.Nullable; import androidx.media3.common.C; import androidx.media3.common.Format; @@ -157,7 +158,7 @@ public final class InAppMp4Muxer implements Muxer { } @Override - public void writeSampleData(int trackId, ByteBuffer byteBuffer, BufferInfo bufferInfo) + public void writeSampleData(int trackId, ByteBuffer byteBuffer, MediaCodec.BufferInfo bufferInfo) throws MuxerException { if (videoDurationUs != C.TIME_UNSET && trackId == videoTrackId @@ -171,7 +172,8 @@ public final class InAppMp4Muxer implements Muxer { videoDurationUs)); return; } - muxer.writeSampleData(trackId, byteBuffer, bufferInfo); + muxer.writeSampleData( + trackId, byteBuffer, getMuxerBufferInfoFromMediaCodecBufferInfo(bufferInfo)); } @Override @@ -184,7 +186,7 @@ public final class InAppMp4Muxer implements Muxer { @Override public void close() throws MuxerException { if (videoDurationUs != C.TIME_UNSET && videoTrackId != TRACK_ID_UNSET) { - BufferInfo bufferInfo = new BufferInfo(); + MediaCodec.BufferInfo bufferInfo = new MediaCodec.BufferInfo(); bufferInfo.set( /* newOffset= */ 0, /* newSize= */ 0,