Change the default value of lastSampleDurationBehavior

to
LAST_SAMPLE_DURATION_BEHAVIOR_SET_FROM_END_OF_STREAM_BUFFER_OR_DUPLICATE_PREVIOUS

This CL also combines LAST_SAMPLE_DURATION_BEHAVIOR_SET_FROM_END_OF_STREAM_BUFFER
and LAST_SAMPLE_DURATION_BEHAVIOR_DUPLICATE_PREVIOUS.

The reason for combining the two enums is that, when the option
to use END_OF_STREAM_BUFFER is selected and if the EOS buffer is
not provided then the muxer anyways fallbacks to duplicate
duration behavior.

The last sample with 0 durations seems less useful so
change the default behavior to non-zero duration.
This will also match the behavior with MediaMuxer.

PiperOrigin-RevId: 675189932
This commit is contained in:
sheenachhabra 2024-09-16 09:58:37 -07:00 committed by Copybara-Service
parent 0ce6d9620e
commit 47d45a82ca
34 changed files with 134 additions and 136 deletions

View File

@ -821,7 +821,7 @@ import org.checkerframework.checker.nullness.qual.PolyNull;
currentSampleTimeUs = nextSampleTimeUs;
}
long lastSampleDurationVuFromEndOfStream = 0;
long lastSampleDurationVuFromEndOfStream = C.LENGTH_UNSET;
if (endOfStreamTimestampUs != C.TIME_UNSET) {
lastSampleDurationVuFromEndOfStream =
vuFromUs(endOfStreamTimestampUs, videoUnitTimescale)
@ -1244,16 +1244,18 @@ import org.checkerframework.checker.nullness.qual.PolyNull;
@Mp4Muxer.LastSampleDurationBehavior int lastSampleDurationBehavior,
int lastSampleDurationVuFromEndOfStream) {
switch (lastSampleDurationBehavior) {
case Mp4Muxer.LAST_SAMPLE_DURATION_BEHAVIOR_DUPLICATE_PREVIOUS:
case Mp4Muxer.LAST_SAMPLE_DURATION_BEHAVIOR_SET_TO_ZERO:
return 0;
case Mp4Muxer
.LAST_SAMPLE_DURATION_BEHAVIOR_SET_FROM_END_OF_STREAM_BUFFER_OR_DUPLICATE_PREVIOUS:
if (lastSampleDurationVuFromEndOfStream != C.LENGTH_UNSET) {
return lastSampleDurationVuFromEndOfStream;
}
// For a track having less than 3 samples, duplicating the last frame duration will
// significantly increase the overall track duration, so avoid that.
return sampleDurationsExceptLast.size() < 2
? 0
: Iterables.getLast(sampleDurationsExceptLast);
case Mp4Muxer.LAST_SAMPLE_DURATION_BEHAVIOR_SET_TO_ZERO:
return 0;
case Mp4Muxer.LAST_SAMPLE_DURATION_BEHAVIOR_SET_FROM_END_OF_STREAM_BUFFER:
return lastSampleDurationVuFromEndOfStream;
default:
throw new IllegalArgumentException(
"Unexpected value for the last frame duration behavior " + lastSampleDurationBehavior);

View File

@ -23,7 +23,7 @@ import static androidx.media3.muxer.Boxes.BOX_HEADER_SIZE;
import static androidx.media3.muxer.Boxes.MFHD_BOX_CONTENT_SIZE;
import static androidx.media3.muxer.Boxes.TFHD_BOX_CONTENT_SIZE;
import static androidx.media3.muxer.Boxes.getTrunBoxContentSize;
import static androidx.media3.muxer.Mp4Muxer.LAST_SAMPLE_DURATION_BEHAVIOR_DUPLICATE_PREVIOUS;
import static androidx.media3.muxer.Mp4Muxer.LAST_SAMPLE_DURATION_BEHAVIOR_SET_FROM_END_OF_STREAM_BUFFER_OR_DUPLICATE_PREVIOUS;
import static androidx.media3.muxer.MuxerUtil.UNSIGNED_INT_MAX_VALUE;
import static java.lang.Math.max;
import static java.lang.Math.min;
@ -101,7 +101,8 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
this.annexBToAvccConverter = annexBToAvccConverter;
this.fragmentDurationUs = fragmentDurationMs * 1_000;
this.sampleCopyEnabled = sampleCopyEnabled;
lastSampleDurationBehavior = LAST_SAMPLE_DURATION_BEHAVIOR_DUPLICATE_PREVIOUS;
lastSampleDurationBehavior =
LAST_SAMPLE_DURATION_BEHAVIOR_SET_FROM_END_OF_STREAM_BUFFER_OR_DUPLICATE_PREVIOUS;
tracks = new ArrayList<>();
minInputPresentationTimeUs = Long.MAX_VALUE;
currentFragmentSequenceNumber = 1;
@ -334,7 +335,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
? minInputPresentationTimeUs
: pendingSamplesBufferInfo.get(0).presentationTimeUs,
track.videoUnitTimebase(),
LAST_SAMPLE_DURATION_BEHAVIOR_DUPLICATE_PREVIOUS,
LAST_SAMPLE_DURATION_BEHAVIOR_SET_FROM_END_OF_STREAM_BUFFER_OR_DUPLICATE_PREVIOUS,
track.endOfStreamTimestampUs);
List<Integer> sampleCompositionTimeOffsets =

View File

@ -147,20 +147,13 @@ public final class Mp4Muxer implements Muxer {
@Target(TYPE_USE)
@IntDef({
LAST_SAMPLE_DURATION_BEHAVIOR_SET_TO_ZERO,
LAST_SAMPLE_DURATION_BEHAVIOR_DUPLICATE_PREVIOUS,
LAST_SAMPLE_DURATION_BEHAVIOR_SET_FROM_END_OF_STREAM_BUFFER
LAST_SAMPLE_DURATION_BEHAVIOR_SET_FROM_END_OF_STREAM_BUFFER_OR_DUPLICATE_PREVIOUS
})
public @interface LastSampleDurationBehavior {}
/** The duration of the last sample is set to 0. */
public static final int LAST_SAMPLE_DURATION_BEHAVIOR_SET_TO_ZERO = 0;
/**
* Use the difference between the last timestamp and the one before that as the duration of the
* last sample.
*/
public static final int LAST_SAMPLE_DURATION_BEHAVIOR_DUPLICATE_PREVIOUS = 1;
/**
* Use the {@link MediaCodec#BUFFER_FLAG_END_OF_STREAM end of stream sample} to set the duration
* of the last sample.
@ -174,9 +167,10 @@ public final class Mp4Muxer implements Muxer {
* #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 set to 0.
* 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 = 2;
public static final int
LAST_SAMPLE_DURATION_BEHAVIOR_SET_FROM_END_OF_STREAM_BUFFER_OR_DUPLICATE_PREVIOUS = 1;
/** The specific MP4 file format. */
@Documented
@ -216,7 +210,8 @@ public final class Mp4Muxer implements Muxer {
*/
public Builder(FileOutputStream outputStream) {
this.outputStream = outputStream;
lastSampleDurationBehavior = LAST_SAMPLE_DURATION_BEHAVIOR_SET_TO_ZERO;
lastSampleDurationBehavior =
LAST_SAMPLE_DURATION_BEHAVIOR_SET_FROM_END_OF_STREAM_BUFFER_OR_DUPLICATE_PREVIOUS;
sampleCopyEnabled = true;
attemptStreamableOutputEnabled = true;
outputFileFormat = FILE_FORMAT_DEFAULT;
@ -225,7 +220,8 @@ public final class Mp4Muxer implements Muxer {
/**
* Sets the {@link LastSampleDurationBehavior}.
*
* <p>The default value is {@link #LAST_SAMPLE_DURATION_BEHAVIOR_SET_TO_ZERO}.
* <p>The default value is {@link
* #LAST_SAMPLE_DURATION_BEHAVIOR_SET_FROM_END_OF_STREAM_BUFFER_OR_DUPLICATE_PREVIOUS}.
*/
@CanIgnoreReturnValue
public Mp4Muxer.Builder setLastSampleDurationBehavior(

View File

@ -15,8 +15,7 @@
*/
package androidx.media3.muxer;
import static androidx.media3.muxer.Mp4Muxer.LAST_SAMPLE_DURATION_BEHAVIOR_DUPLICATE_PREVIOUS;
import static androidx.media3.muxer.Mp4Muxer.LAST_SAMPLE_DURATION_BEHAVIOR_SET_FROM_END_OF_STREAM_BUFFER;
import static androidx.media3.muxer.Mp4Muxer.LAST_SAMPLE_DURATION_BEHAVIOR_SET_FROM_END_OF_STREAM_BUFFER_OR_DUPLICATE_PREVIOUS;
import static androidx.media3.muxer.Mp4Muxer.LAST_SAMPLE_DURATION_BEHAVIOR_SET_TO_ZERO;
import static androidx.media3.muxer.MuxerTestUtil.FAKE_AUDIO_FORMAT;
import static androidx.media3.muxer.MuxerTestUtil.FAKE_CSD_0;
@ -534,7 +533,7 @@ public class BoxesTest {
sampleBufferInfos,
/* firstSamplePresentationTimeUs= */ 0L,
VU_TIMEBASE,
LAST_SAMPLE_DURATION_BEHAVIOR_DUPLICATE_PREVIOUS,
LAST_SAMPLE_DURATION_BEHAVIOR_SET_FROM_END_OF_STREAM_BUFFER_OR_DUPLICATE_PREVIOUS,
C.TIME_UNSET);
assertThat(durationsVu).containsExactly(3_000, 5_000, 5_000);
@ -568,7 +567,7 @@ public class BoxesTest {
sampleBufferInfos,
/* firstSamplePresentationTimeUs= */ 0L,
VU_TIMEBASE,
LAST_SAMPLE_DURATION_BEHAVIOR_SET_FROM_END_OF_STREAM_BUFFER,
LAST_SAMPLE_DURATION_BEHAVIOR_SET_FROM_END_OF_STREAM_BUFFER_OR_DUPLICATE_PREVIOUS,
/* endOfStreamTimestampUs= */ 10_000);
assertThat(durationsVu).containsExactly(100, 100, 100, 100, 600);

View File

@ -15,7 +15,7 @@
*/
package androidx.media3.muxer;
import static androidx.media3.muxer.Mp4Muxer.LAST_SAMPLE_DURATION_BEHAVIOR_SET_FROM_END_OF_STREAM_BUFFER;
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.XMP_SAMPLE_DATA;
import static androidx.media3.muxer.MuxerTestUtil.getFakeSampleAndSampleInfo;
@ -683,7 +683,7 @@ public class Mp4MuxerEndToEndTest {
Mp4Muxer mp4Muxer =
new Mp4Muxer.Builder(new FileOutputStream(outputFilePath))
.setLastSampleDurationBehavior(
LAST_SAMPLE_DURATION_BEHAVIOR_SET_FROM_END_OF_STREAM_BUFFER)
LAST_SAMPLE_DURATION_BEHAVIOR_SET_FROM_END_OF_STREAM_BUFFER_OR_DUPLICATE_PREVIOUS)
.build();
mp4Muxer.addMetadataEntry(
new Mp4TimestampData(
@ -725,13 +725,13 @@ public class Mp4MuxerEndToEndTest {
@Test
public void
createMp4File_withLastSampleDurationBehaviorUsingEndOfStreamFlagButNoEndOfStreamSample_outputsDurationEqualsToLastSampleTimestamp()
createMp4File_withLastSampleDurationBehaviorUsingEndOfStreamFlagButNoEndOfStreamSample_writesExpectedDurationForTheLastSample()
throws Exception {
String outputFilePath = temporaryFolder.newFile().getPath();
Mp4Muxer mp4Muxer =
new Mp4Muxer.Builder(new FileOutputStream(outputFilePath))
.setLastSampleDurationBehavior(
LAST_SAMPLE_DURATION_BEHAVIOR_SET_FROM_END_OF_STREAM_BUFFER)
LAST_SAMPLE_DURATION_BEHAVIOR_SET_FROM_END_OF_STREAM_BUFFER_OR_DUPLICATE_PREVIOUS)
.build();
mp4Muxer.addMetadataEntry(
new Mp4TimestampData(
@ -742,8 +742,8 @@ public class Mp4MuxerEndToEndTest {
getFakeSampleAndSampleInfo(/* presentationTimeUs= */ 100L);
Pair<ByteBuffer, BufferInfo> sample3 =
getFakeSampleAndSampleInfo(/* presentationTimeUs= */ 200L);
long lastSampleTimestampUs = 300L;
Pair<ByteBuffer, BufferInfo> sample4 = getFakeSampleAndSampleInfo(lastSampleTimestampUs);
Pair<ByteBuffer, BufferInfo> sample4 =
getFakeSampleAndSampleInfo(/* presentationTimeUs= */ 300L);
try {
TrackToken track = mp4Muxer.addTrack(FAKE_VIDEO_FORMAT);
@ -759,7 +759,7 @@ public class Mp4MuxerEndToEndTest {
TestUtil.extractAllSamplesFromFilePath(
new Mp4Extractor(new DefaultSubtitleParserFactory()), outputFilePath);
fakeExtractorOutput.track(/* id= */ 0, C.TRACK_TYPE_VIDEO).assertSampleCount(4);
assertThat(fakeExtractorOutput.seekMap.getDurationUs()).isEqualTo(lastSampleTimestampUs);
assertThat(fakeExtractorOutput.seekMap.getDurationUs()).isEqualTo(400L);
}
private static void writeFakeSamples(Mp4Muxer muxer, TrackToken trackToken, int sampleCount)

View File

@ -1,10 +1,10 @@
seekMap:
isSeekable = true
duration = 933300
duration = 999900
getPosition(0) = [[timeUs=0, position=400052]]
getPosition(1) = [[timeUs=0, position=400052], [timeUs=533322, position=428455]]
getPosition(466650) = [[timeUs=0, position=400052], [timeUs=533322, position=428455]]
getPosition(933300) = [[timeUs=533322, position=428455]]
getPosition(499950) = [[timeUs=0, position=400052], [timeUs=533322, position=428455]]
getPosition(999900) = [[timeUs=533322, position=428455]]
numberOfTracks = 1
track 0:
total output bytes = 50100
@ -15,7 +15,7 @@ track 0:
maxInputSize = 10464
width = 176
height = 144
frameRate = 16.072002
frameRate = 15.0015
colorInfo:
lumaBitdepth = 8
chromaBitdepth = 8

View File

@ -1,10 +1,10 @@
seekMap:
isSeekable = true
duration = 933300
duration = 999900
getPosition(0) = [[timeUs=0, position=400052]]
getPosition(1) = [[timeUs=0, position=400052]]
getPosition(466650) = [[timeUs=0, position=400052]]
getPosition(933300) = [[timeUs=0, position=400052]]
getPosition(499950) = [[timeUs=0, position=400052]]
getPosition(999900) = [[timeUs=0, position=400052]]
numberOfTracks = 1
track 0:
total output bytes = 45694
@ -17,7 +17,7 @@ track 0:
maxInputSize = 9256
width = 176
height = 144
frameRate = 16.072002
frameRate = 15.0015
colorInfo:
lumaBitdepth = 8
chromaBitdepth = 8

View File

@ -1,10 +1,10 @@
seekMap:
isSeekable = true
duration = 2992000
duration = 3008000
getPosition(0) = [[timeUs=0, position=400052]]
getPosition(1) = [[timeUs=1, position=400241]]
getPosition(1496000) = [[timeUs=1496000, position=412467]]
getPosition(2992000) = [[timeUs=2992000, position=424658]]
getPosition(1504000) = [[timeUs=1504000, position=412467]]
getPosition(3008000) = [[timeUs=3008000, position=424658]]
numberOfTracks = 1
track 0:
total output bytes = 24785

View File

@ -1,10 +1,10 @@
seekMap:
isSeekable = true
duration = 2966600
duration = 3000000
getPosition(0) = [[timeUs=0, position=400052]]
getPosition(1) = [[timeUs=0, position=400052], [timeUs=1000000, position=578564]]
getPosition(1483300) = [[timeUs=1000000, position=578564], [timeUs=2000000, position=671623]]
getPosition(2966600) = [[timeUs=2000000, position=671623]]
getPosition(1500000) = [[timeUs=1000000, position=578564], [timeUs=2000000, position=671623]]
getPosition(3000000) = [[timeUs=2000000, position=671623]]
numberOfTracks = 1
track 0:
total output bytes = 378802
@ -15,7 +15,7 @@ track 0:
maxInputSize = 115022
width = 642
height = 642
frameRate = 30.33776
frameRate = 30.0
colorInfo:
colorSpace = 1
colorRange = 2

View File

@ -1,10 +1,10 @@
seekMap:
isSeekable = true
duration = 2993500
duration = 3013500
getPosition(0) = [[timeUs=0, position=400052]]
getPosition(1) = [[timeUs=1, position=400052]]
getPosition(1496750) = [[timeUs=1496750, position=449844]]
getPosition(2993500) = [[timeUs=2993500, position=499769]]
getPosition(1506750) = [[timeUs=1506750, position=449844]]
getPosition(3013500) = [[timeUs=3013500, position=499769]]
numberOfTracks = 1
track 0:
total output bytes = 100872

View File

@ -1,10 +1,10 @@
seekMap:
isSeekable = true
duration = 3966600
duration = 3999900
getPosition(0) = [[timeUs=0, position=400052]]
getPosition(1) = [[timeUs=0, position=400052], [timeUs=1000000, position=552554]]
getPosition(1983300) = [[timeUs=1000000, position=552554], [timeUs=2000000, position=638317]]
getPosition(3966600) = [[timeUs=3000000, position=753611]]
getPosition(1999950) = [[timeUs=1000000, position=552554], [timeUs=2000000, position=638317]]
getPosition(3999900) = [[timeUs=3000000, position=753611]]
numberOfTracks = 1
track 0:
total output bytes = 416333
@ -17,7 +17,7 @@ track 0:
maxNumReorderSamples = 1
width = 800
height = 640
frameRate = 30.25261
frameRate = 30.00075
colorInfo:
lumaBitdepth = 8
chromaBitdepth = 8

View File

@ -1,10 +1,10 @@
seekMap:
isSeekable = true
duration = 3966600
duration = 3999900
getPosition(0) = [[timeUs=0, position=400052]]
getPosition(1) = [[timeUs=0, position=400052], [timeUs=1000000, position=547447]]
getPosition(1983300) = [[timeUs=1000000, position=547447], [timeUs=2000000, position=631674]]
getPosition(3966600) = [[timeUs=3000000, position=744000]]
getPosition(1999950) = [[timeUs=1000000, position=547447], [timeUs=2000000, position=631674]]
getPosition(3999900) = [[timeUs=3000000, position=744000]]
numberOfTracks = 1
track 0:
total output bytes = 406132
@ -17,7 +17,7 @@ track 0:
maxNumReorderSamples = 2
width = 800
height = 640
frameRate = 30.25261
frameRate = 30.00075
colorInfo:
lumaBitdepth = 8
chromaBitdepth = 8

View File

@ -1,10 +1,10 @@
seekMap:
isSeekable = true
duration = 3966600
duration = 3999900
getPosition(0) = [[timeUs=0, position=400052]]
getPosition(1) = [[timeUs=0, position=400052]]
getPosition(1983300) = [[timeUs=0, position=400052]]
getPosition(3966600) = [[timeUs=0, position=400052]]
getPosition(1999950) = [[timeUs=0, position=400052]]
getPosition(3999900) = [[timeUs=0, position=400052]]
numberOfTracks = 1
track 0:
total output bytes = 305806
@ -15,7 +15,7 @@ track 0:
maxInputSize = 100600
width = 800
height = 640
frameRate = 30.25261
frameRate = 30.00075
colorInfo:
colorRange = 2
lumaBitdepth = 8

View File

@ -1,10 +1,10 @@
seekMap:
isSeekable = true
duration = 2980000
duration = 3000000
getPosition(0) = [[timeUs=0, position=400052]]
getPosition(1) = [[timeUs=1, position=400052]]
getPosition(1490000) = [[timeUs=1490000, position=404418]]
getPosition(2980000) = [[timeUs=2980000, position=408843]]
getPosition(1500000) = [[timeUs=1500000, position=404477]]
getPosition(3000000) = [[timeUs=3000000, position=408843]]
numberOfTracks = 1
track 0:
total output bytes = 8850

View File

@ -1,10 +1,10 @@
seekMap:
isSeekable = true
duration = 3000000
duration = 3020000
getPosition(0) = [[timeUs=0, position=400052]]
getPosition(1) = [[timeUs=1, position=400052]]
getPosition(1500000) = [[timeUs=1500000, position=402452]]
getPosition(3000000) = [[timeUs=3000000, position=404852]]
getPosition(1510000) = [[timeUs=1510000, position=402452]]
getPosition(3020000) = [[timeUs=3020000, position=404852]]
numberOfTracks = 1
track 0:
total output bytes = 4832

View File

@ -1,10 +1,10 @@
seekMap:
isSeekable = true
duration = 66700
duration = 100000
getPosition(0) = [[timeUs=0, position=400052]]
getPosition(1) = [[timeUs=0, position=400052]]
getPosition(33350) = [[timeUs=0, position=400052]]
getPosition(66700) = [[timeUs=0, position=400052]]
getPosition(50000) = [[timeUs=0, position=400052]]
getPosition(100000) = [[timeUs=0, position=400052]]
numberOfTracks = 3
track 0:
total output bytes = 387
@ -65,7 +65,7 @@ track 2:
maxNumReorderSamples = 0
width = 1920
height = 1080
frameRate = 44.977512
frameRate = 30.0
colorInfo:
colorSpace = 2
colorRange = 1

View File

@ -1,10 +1,10 @@
seekMap:
isSeekable = true
duration = 4203200
duration = 4236500
getPosition(0) = [[timeUs=0, position=400052]]
getPosition(1) = [[timeUs=0, position=400052], [timeUs=1002944, position=2283470]]
getPosition(2101600) = [[timeUs=2003555, position=4184649], [timeUs=3003433, position=4426916]]
getPosition(4203200) = [[timeUs=4003266, position=6438541]]
getPosition(2118250) = [[timeUs=2003555, position=4184649], [timeUs=3003433, position=4426916]]
getPosition(4236500) = [[timeUs=4003266, position=6438541]]
numberOfTracks = 2
track 0:
total output bytes = 7944083
@ -17,7 +17,7 @@ track 0:
maxNumReorderSamples = 0
width = 1280
height = 720
frameRate = 30.215075
frameRate = 29.977577
colorInfo:
colorSpace = 6
colorRange = 2

View File

@ -1,10 +1,10 @@
seekMap:
isSeekable = true
duration = 3000
duration = 4000
getPosition(0) = [[timeUs=0, position=400052]]
getPosition(1) = [[timeUs=0, position=400052], [timeUs=3000, position=400108]]
getPosition(1500) = [[timeUs=0, position=400052], [timeUs=3000, position=400108]]
getPosition(3000) = [[timeUs=3000, position=400108]]
getPosition(2000) = [[timeUs=0, position=400052], [timeUs=3000, position=400108]]
getPosition(4000) = [[timeUs=2000, position=400220]]
numberOfTracks = 1
track 0:
total output bytes = 224
@ -17,7 +17,7 @@ track 0:
maxNumReorderSamples = 2
width = 12
height = 10
frameRate = 1333.3334
frameRate = 999.99994
colorInfo:
colorRange = 1
lumaBitdepth = 8

View File

@ -1,10 +1,10 @@
seekMap:
isSeekable = true
duration = 273900
duration = 414800
getPosition(0) = [[timeUs=0, position=400052]]
getPosition(1) = [[timeUs=0, position=400052], [timeUs=273900, position=400108]]
getPosition(136950) = [[timeUs=0, position=400052], [timeUs=273900, position=400108]]
getPosition(273900) = [[timeUs=273900, position=400108]]
getPosition(207400) = [[timeUs=0, position=400052], [timeUs=273900, position=400108]]
getPosition(414800) = [[timeUs=33188, position=400220]]
numberOfTracks = 1
track 0:
total output bytes = 224
@ -17,7 +17,7 @@ track 0:
maxNumReorderSamples = 2
width = 12
height = 10
frameRate = 14.603869
frameRate = 9.643202
colorInfo:
colorRange = 1
lumaBitdepth = 8

View File

@ -1,10 +1,10 @@
seekMap:
isSeekable = true
duration = 4137400
duration = 4171600
getPosition(0) = [[timeUs=0, position=400052]]
getPosition(1) = [[timeUs=0, position=400052], [timeUs=1002944, position=2283470]]
getPosition(2068700) = [[timeUs=2003555, position=4184649], [timeUs=3003433, position=4426916]]
getPosition(4137400) = [[timeUs=4003266, position=6438541]]
getPosition(2085800) = [[timeUs=2003555, position=4184649], [timeUs=3003433, position=4426916]]
getPosition(4171600) = [[timeUs=4003266, position=6438541]]
numberOfTracks = 2
track 0:
total output bytes = 7822354
@ -17,7 +17,7 @@ track 0:
maxNumReorderSamples = 0
width = 1280
height = 720
frameRate = 30.21221
frameRate = 29.964523
colorInfo:
colorSpace = 6
colorRange = 2

View File

@ -1,10 +1,10 @@
seekMap:
isSeekable = true
duration = 1064600
duration = 1087800
getPosition(0) = [[timeUs=0, position=400052]]
getPosition(1) = [[timeUs=0, position=400052]]
getPosition(532300) = [[timeUs=0, position=400052]]
getPosition(1064600) = [[timeUs=0, position=400052]]
getPosition(543900) = [[timeUs=0, position=400052]]
getPosition(1087800) = [[timeUs=0, position=400052]]
numberOfTracks = 2
track 0:
total output bytes = 69084
@ -15,7 +15,7 @@ track 0:
maxInputSize = 46460
width = 1080
height = 720
frameRate = 31.004547
frameRate = 29.973022
colorInfo:
lumaBitdepth = 8
chromaBitdepth = 8

View File

@ -1,10 +1,10 @@
seekMap:
isSeekable = true
duration = 1065600
duration = 1088800
getPosition(0) = [[timeUs=0, position=400052]]
getPosition(1) = [[timeUs=0, position=400052]]
getPosition(532800) = [[timeUs=0, position=400052]]
getPosition(1065600) = [[timeUs=0, position=400052]]
getPosition(544400) = [[timeUs=0, position=400052]]
getPosition(1088800) = [[timeUs=0, position=400052]]
numberOfTracks = 2
track 0:
total output bytes = 9529
@ -211,7 +211,7 @@ track 1:
maxNumReorderSamples = 0
width = 1080
height = 720
frameRate = 31.004547
frameRate = 29.973022
colorInfo:
colorSpace = 1
colorRange = 2

View File

@ -1,10 +1,10 @@
seekMap:
isSeekable = true
duration = 933300
duration = 999900
getPosition(0) = [[timeUs=0, position=400052]]
getPosition(1) = [[timeUs=0, position=400052], [timeUs=533322, position=428455]]
getPosition(466650) = [[timeUs=0, position=400052], [timeUs=533322, position=428455]]
getPosition(933300) = [[timeUs=533322, position=428455]]
getPosition(499950) = [[timeUs=0, position=400052], [timeUs=533322, position=428455]]
getPosition(999900) = [[timeUs=533322, position=428455]]
numberOfTracks = 1
track 0:
total output bytes = 50100
@ -15,7 +15,7 @@ track 0:
maxInputSize = 10464
width = 176
height = 144
frameRate = 16.072002
frameRate = 15.0015
colorInfo:
colorRange = 2
lumaBitdepth = 8

View File

@ -1,10 +1,10 @@
seekMap:
isSeekable = true
duration = 933300
duration = 999900
getPosition(0) = [[timeUs=0, position=400052]]
getPosition(1) = [[timeUs=0, position=400052]]
getPosition(466650) = [[timeUs=0, position=400052]]
getPosition(933300) = [[timeUs=0, position=400052]]
getPosition(499950) = [[timeUs=0, position=400052]]
getPosition(999900) = [[timeUs=0, position=400052]]
numberOfTracks = 1
track 0:
total output bytes = 45694
@ -17,7 +17,7 @@ track 0:
maxInputSize = 9256
width = 176
height = 144
frameRate = 16.072002
frameRate = 15.0015
colorInfo:
colorRange = 2
lumaBitdepth = 8

View File

@ -1,10 +1,10 @@
seekMap:
isSeekable = true
duration = 2992000
duration = 3008000
getPosition(0) = [[timeUs=0, position=400052]]
getPosition(1) = [[timeUs=1, position=400241]]
getPosition(1496000) = [[timeUs=1496000, position=412467]]
getPosition(2992000) = [[timeUs=2992000, position=424658]]
getPosition(1504000) = [[timeUs=1504000, position=412467]]
getPosition(3008000) = [[timeUs=3008000, position=424658]]
numberOfTracks = 1
track 0:
total output bytes = 24785

View File

@ -1,10 +1,10 @@
seekMap:
isSeekable = true
duration = 3000000
duration = 3020000
getPosition(0) = [[timeUs=0, position=400052]]
getPosition(1) = [[timeUs=1, position=400052]]
getPosition(1500000) = [[timeUs=1500000, position=449844]]
getPosition(3000000) = [[timeUs=3000000, position=499769]]
getPosition(1510000) = [[timeUs=1510000, position=449844]]
getPosition(3020000) = [[timeUs=3020000, position=499769]]
numberOfTracks = 1
track 0:
total output bytes = 100872

View File

@ -1,10 +1,10 @@
seekMap:
isSeekable = true
duration = 2980000
duration = 3000000
getPosition(0) = [[timeUs=0, position=400052]]
getPosition(1) = [[timeUs=1, position=400052]]
getPosition(1490000) = [[timeUs=1490000, position=404418]]
getPosition(2980000) = [[timeUs=2980000, position=408843]]
getPosition(1500000) = [[timeUs=1500000, position=404477]]
getPosition(3000000) = [[timeUs=3000000, position=408843]]
numberOfTracks = 1
track 0:
total output bytes = 8850

View File

@ -1,10 +1,10 @@
seekMap:
isSeekable = true
duration = 3000000
duration = 3020000
getPosition(0) = [[timeUs=0, position=400052]]
getPosition(1) = [[timeUs=1, position=400052]]
getPosition(1500000) = [[timeUs=1500000, position=402452]]
getPosition(3000000) = [[timeUs=3000000, position=404852]]
getPosition(1510000) = [[timeUs=1510000, position=402452]]
getPosition(3020000) = [[timeUs=3020000, position=404852]]
numberOfTracks = 1
track 0:
total output bytes = 4832

View File

@ -1,10 +1,10 @@
seekMap:
isSeekable = true
duration = 66700
duration = 100000
getPosition(0) = [[timeUs=0, position=400052]]
getPosition(1) = [[timeUs=0, position=400052]]
getPosition(33350) = [[timeUs=0, position=400052]]
getPosition(66700) = [[timeUs=0, position=400052]]
getPosition(50000) = [[timeUs=0, position=400052]]
getPosition(100000) = [[timeUs=0, position=400052]]
numberOfTracks = 2
track 0:
total output bytes = 678996
@ -17,7 +17,7 @@ track 0:
maxNumReorderSamples = 0
width = 1920
height = 1080
frameRate = 44.977512
frameRate = 30.0
rotationDegrees = 90
colorInfo:
colorSpace = 2

View File

@ -1,10 +1,10 @@
seekMap:
isSeekable = true
duration = 1064600
duration = 1087800
getPosition(0) = [[timeUs=0, position=400052]]
getPosition(1) = [[timeUs=0, position=400052]]
getPosition(532300) = [[timeUs=0, position=400052]]
getPosition(1064600) = [[timeUs=0, position=400052]]
getPosition(543900) = [[timeUs=0, position=400052]]
getPosition(1087800) = [[timeUs=0, position=400052]]
numberOfTracks = 2
track 0:
total output bytes = 69084
@ -15,7 +15,7 @@ track 0:
maxInputSize = 46460
width = 1080
height = 720
frameRate = 31.004547
frameRate = 29.973022
colorInfo:
colorRange = 2
lumaBitdepth = 8

View File

@ -1,10 +1,10 @@
seekMap:
isSeekable = true
duration = 1065600
duration = 1088800
getPosition(0) = [[timeUs=0, position=400052]]
getPosition(1) = [[timeUs=0, position=400052]]
getPosition(532800) = [[timeUs=0, position=400052]]
getPosition(1065600) = [[timeUs=0, position=400052]]
getPosition(544400) = [[timeUs=0, position=400052]]
getPosition(1088800) = [[timeUs=0, position=400052]]
numberOfTracks = 2
track 0:
total output bytes = 301213
@ -17,7 +17,7 @@ track 0:
maxNumReorderSamples = 0
width = 1080
height = 720
frameRate = 31.004547
frameRate = 29.973022
colorInfo:
colorSpace = 1
colorRange = 2

View File

@ -1,10 +1,10 @@
seekMap:
isSeekable = true
duration = 966600
duration = 999900
getPosition(0) = [[timeUs=0, position=400052]]
getPosition(1) = [[timeUs=0, position=400052], [timeUs=333333, position=416043]]
getPosition(483300) = [[timeUs=333333, position=416043], [timeUs=666666, position=428793]]
getPosition(966600) = [[timeUs=666666, position=428793]]
getPosition(499950) = [[timeUs=333333, position=416043], [timeUs=666666, position=428793]]
getPosition(999900) = [[timeUs=666666, position=428793]]
numberOfTracks = 1
track 0:
total output bytes = 41647
@ -17,7 +17,7 @@ track 0:
maxNumReorderSamples = 2
width = 854
height = 480
frameRate = 31.036623
frameRate = 30.003
colorInfo:
colorRange = 2
lumaBitdepth = 8

View File

@ -1813,7 +1813,7 @@ public class TransformerEndToEndTest {
FakeExtractorOutput fakeExtractorOutput =
TestUtil.extractAllSamplesFromFilePath(mp4Extractor, exportTestResult.filePath);
// TODO: b/324903070 - The generated output file has incorrect duration.
assertThat(fakeExtractorOutput.seekMap.getDurationUs()).isEqualTo(1_555_700);
assertThat(fakeExtractorOutput.seekMap.getDurationUs()).isEqualTo(1_578_900);
assertThat(fakeExtractorOutput.numberOfTracks).isEqualTo(1);
FakeTrackOutput audioTrack = fakeExtractorOutput.trackOutputs.get(0);
int expectedSampleCount = 68;

View File

@ -16,7 +16,7 @@
package androidx.media3.transformer;
import static androidx.media3.common.util.Assertions.checkNotNull;
import static androidx.media3.muxer.Mp4Muxer.LAST_SAMPLE_DURATION_BEHAVIOR_SET_FROM_END_OF_STREAM_BUFFER;
import static androidx.media3.muxer.Mp4Muxer.LAST_SAMPLE_DURATION_BEHAVIOR_SET_FROM_END_OF_STREAM_BUFFER_OR_DUPLICATE_PREVIOUS;
import android.media.MediaCodec;
import android.media.MediaCodec.BufferInfo;
@ -153,7 +153,7 @@ public final class InAppMuxer implements Muxer {
*
* <p>The default is {@link C#TIME_UNSET} to not set any duration in the output. In this case
* the video track duration is determined by the samples written to it and the duration of the
* last sample is set to 0.
* last sample will be same as that of the sample before that.
*
* @param videoDurationUs The duration of the video track (in microseconds) in the output, or
* {@link C#TIME_UNSET} to not set any duration. Only applicable when a video track is
@ -186,7 +186,7 @@ public final class InAppMuxer implements Muxer {
Mp4Muxer.Builder builder = new Mp4Muxer.Builder(outputStream);
if (videoDurationUs != C.TIME_UNSET) {
builder.setLastSampleDurationBehavior(
LAST_SAMPLE_DURATION_BEHAVIOR_SET_FROM_END_OF_STREAM_BUFFER);
LAST_SAMPLE_DURATION_BEHAVIOR_SET_FROM_END_OF_STREAM_BUFFER_OR_DUPLICATE_PREVIOUS);
}
muxer = builder.build();
}