Create muxer specific BufferInfo class

Muxer does not use `offset` field, hence not added.

PiperOrigin-RevId: 728625538
This commit is contained in:
sheenachhabra 2025-02-19 05:09:18 -08:00 committed by Copybara-Service
parent 1461e9e93a
commit 462533219d
18 changed files with 166 additions and 113 deletions

View File

@ -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

View File

@ -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

View File

@ -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<MediaCodec.BufferInfo> writtenSamples) {
public static ByteBuffer stsz(List<BufferInfo> 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<MediaCodec.BufferInfo> writtenSamples) {
public static ByteBuffer stss(List<BufferInfo> 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) {

View File

@ -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;
}
}

View File

@ -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;

View File

@ -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,10 +351,10 @@ 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 =
new BufferInfo(
currentSampleBufferInfo.presentationTimeUs,
currentSampleByteBuffer.remaining(),
currentSampleBufferInfo.flags);
pendingSamplesBufferInfoBuilder.add(currentSampleBufferInfo);
}

View File

@ -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.
*
* <p>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.
*
* <p>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.
* <p>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.
*
* <p>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.
* <p>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;

View File

@ -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,10 +462,10 @@ import java.util.concurrent.atomic.AtomicBoolean;
if (doesSampleContainAnnexBNalUnits(checkNotNull(track.format.sampleMimeType))) {
currentSampleByteBuffer =
annexBToAvccConverter.process(currentSampleByteBuffer, linearByteBufferAllocator);
currentSampleBufferInfo.set(
currentSampleByteBuffer.position(),
currentSampleByteBuffer.remaining(),
currentSampleBufferInfo =
new BufferInfo(
currentSampleBufferInfo.presentationTimeUs,
currentSampleByteBuffer.remaining(),
currentSampleBufferInfo.flags);
}

View File

@ -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.
*

View File

@ -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);

View File

@ -517,8 +517,7 @@ public class BoxesTest {
@Test
public void
convertPresentationTimestampsToDurationsVu_singleSampleAtZeroTimestamp_returnsSampleLengthEqualsZero() {
List<MediaCodec.BufferInfo> sampleBufferInfos =
createBufferInfoListWithSamplePresentationTimestamps(0L);
List<BufferInfo> sampleBufferInfos = createBufferInfoListWithSamplePresentationTimestamps(0L);
List<Integer> durationsVu =
Boxes.convertPresentationTimestampsToDurationsVu(
@ -533,7 +532,7 @@ public class BoxesTest {
@Test
public void
convertPresentationTimestampsToDurationsVu_singleSampleAtNonZeroTimestamp_returnsSampleLengthEqualsZero() {
List<MediaCodec.BufferInfo> sampleBufferInfos =
List<BufferInfo> sampleBufferInfos =
createBufferInfoListWithSamplePresentationTimestamps(5_000L);
List<Integer> durationsVu =
@ -549,7 +548,7 @@ public class BoxesTest {
@Test
public void
convertPresentationTimestampsToDurationsVu_differentSampleDurations_lastFrameDurationShort_returnsLastSampleOfZeroDuration() {
List<MediaCodec.BufferInfo> sampleBufferInfos =
List<BufferInfo> sampleBufferInfos =
createBufferInfoListWithSamplePresentationTimestamps(0L, 30_000L, 80_000L);
List<Integer> durationsVu =
@ -565,7 +564,7 @@ public class BoxesTest {
@Test
public void
convertPresentationTimestampsToDurationsVu_differentSampleDurations_lastFrameDurationDuplicate_returnsLastSampleOfDuplicateDuration() {
List<MediaCodec.BufferInfo> sampleBufferInfos =
List<BufferInfo> sampleBufferInfos =
createBufferInfoListWithSamplePresentationTimestamps(0L, 30_000L, 80_000L);
List<Integer> durationsVu =
@ -581,7 +580,7 @@ public class BoxesTest {
@Test
public void
convertPresentationTimestampsToDurationsVu_withOutOfOrderSampleTimestamps_returnsExpectedDurations() {
List<MediaCodec.BufferInfo> sampleBufferInfos =
List<BufferInfo> sampleBufferInfos =
createBufferInfoListWithSamplePresentationTimestamps(0L, 10_000L, 1_000L, 2_000L, 11_000L);
List<Integer> durationsVu =
@ -597,7 +596,7 @@ public class BoxesTest {
@Test
public void
convertPresentationTimestampsToDurationsVu_withLastSampleDurationBehaviorUsingEndOfStreamFlag_returnsExpectedDurations() {
List<MediaCodec.BufferInfo> sampleBufferInfos =
List<BufferInfo> sampleBufferInfos =
createBufferInfoListWithSamplePresentationTimestamps(0L, 1_000L, 2_000L, 3_000L, 4_000L);
List<Integer> durationsVu =
@ -652,8 +651,7 @@ public class BoxesTest {
@Test
public void createCttsBox_withSingleSampleTimestamp_returnsEmptyBox() {
List<MediaCodec.BufferInfo> sampleBufferInfos =
createBufferInfoListWithSamplePresentationTimestamps(400);
List<BufferInfo> sampleBufferInfos = createBufferInfoListWithSamplePresentationTimestamps(400);
List<Integer> durationsVu =
Boxes.convertPresentationTimestampsToDurationsVu(
sampleBufferInfos,
@ -669,7 +667,7 @@ public class BoxesTest {
@Test
public void createCttsBox_withNoBframesSampleTimestamps_returnsEmptyBox() throws IOException {
List<MediaCodec.BufferInfo> sampleBufferInfos =
List<BufferInfo> sampleBufferInfos =
createBufferInfoListWithSamplePresentationTimestamps(0L, 1000L, 2000L);
List<Integer> durationsVu =
Boxes.convertPresentationTimestampsToDurationsVu(
@ -686,7 +684,7 @@ public class BoxesTest {
@Test
public void createCttsBox_withBFramesSampleTimestamps_matchesExpected() throws IOException {
List<MediaCodec.BufferInfo> sampleBufferInfos =
List<BufferInfo> 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<MediaCodec.BufferInfo> sampleBufferInfos =
List<BufferInfo> sampleBufferInfos =
createBufferInfoListWithSamplePresentationTimestamps(
23698215060L, 23698248252L, 23698347988L, 23698488968L, 23698547416L);
@ -724,8 +722,7 @@ public class BoxesTest {
@Test
public void createStszBox_matchesExpected() throws IOException {
List<MediaCodec.BufferInfo> sampleBufferInfos =
createBufferInfoListWithSampleSizes(100, 200, 150, 200);
List<BufferInfo> 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<MediaCodec.BufferInfo> sampleBufferInfos = createBufferInfoListWithSomeKeyFrames();
List<BufferInfo> sampleBufferInfos = createBufferInfoListWithSomeKeyFrames();
ByteBuffer stssBox = Boxes.stss(sampleBufferInfos);
@ -867,37 +864,35 @@ public class BoxesTest {
context, dumpableBox, MuxerTestUtil.getExpectedDumpFilePath("trex_box"));
}
private static List<MediaCodec.BufferInfo> createBufferInfoListWithSamplePresentationTimestamps(
private static List<BufferInfo> createBufferInfoListWithSamplePresentationTimestamps(
long... timestampsUs) {
List<MediaCodec.BufferInfo> bufferInfoList = new ArrayList<>();
List<BufferInfo> 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<MediaCodec.BufferInfo> createBufferInfoListWithSampleSizes(int... sizes) {
List<MediaCodec.BufferInfo> bufferInfoList = new ArrayList<>();
private static List<BufferInfo> createBufferInfoListWithSampleSizes(int... sizes) {
List<BufferInfo> 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<MediaCodec.BufferInfo> createBufferInfoListWithSomeKeyFrames() {
List<MediaCodec.BufferInfo> bufferInfoList = new ArrayList<>();
private static List<BufferInfo> createBufferInfoListWithSomeKeyFrames() {
List<BufferInfo> 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;

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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;

View File

@ -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);
}

View File

@ -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,

View File

@ -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,