Reset maxTrackDurationUs when a new fragment is written

When there is both audio and video track, then fragment
creation is driven by video track (a combination of duration
so far + next key frame). But if there is no video track, then
the duration so far drives the fragment creation.

Due to bug, when there is only audio track, only first
fragment was created as expected and then a new fragment is
created for every audio sample.

#cherrypick

PiperOrigin-RevId: 731257696
This commit is contained in:
sheenachhabra 2025-02-26 04:15:31 -08:00 committed by Copybara-Service
parent 20ea05063b
commit d16fdcb8cc
5 changed files with 144 additions and 0 deletions

View File

@ -34,6 +34,8 @@
* Muxers: * Muxers:
* `writeSampleData()` API now uses muxer specific `BufferInfo` class * `writeSampleData()` API now uses muxer specific `BufferInfo` class
instead of `MediaCodec.BufferInfo`. instead of `MediaCodec.BufferInfo`.
* Fix a bug in `FragmentedMp4Muxer` that creates a lot of fragments when
only audio track is written.
* IMA extension: * IMA extension:
* Session: * Session:
* Make `MediaSession.setSessionActivity(PendingIntent)` accept null * Make `MediaSession.setSessionActivity(PendingIntent)` accept null

View File

@ -291,6 +291,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
writeMdatBox(trackInfos); writeMdatBox(trackInfos);
currentFragmentSequenceNumber++; currentFragmentSequenceNumber++;
maxTrackDurationUs = 0;
} }
private void writeMdatBox(List<ProcessedTrackInfo> trackInfos) throws IOException { private void writeMdatBox(List<ProcessedTrackInfo> trackInfos) throws IOException {

View File

@ -55,6 +55,7 @@ public class FragmentedMp4MuxerEndToEndTest {
private static final String H264_WITH_PYRAMID_B_FRAMES_MP4 = private static final String H264_WITH_PYRAMID_B_FRAMES_MP4 =
"bbb_800x640_768kbps_30fps_avc_pyramid_3b.mp4"; "bbb_800x640_768kbps_30fps_avc_pyramid_3b.mp4";
private static final String H265_HDR10_MP4 = "hdr10-720p.mp4"; private static final String H265_HDR10_MP4 = "hdr10-720p.mp4";
private static final String AUDIO_ONLY_MP4 = "sample_audio_only_15s.mp4";
@Parameters(name = "{0}") @Parameters(name = "{0}")
public static ImmutableList<String> mediaSamples() { public static ImmutableList<String> mediaSamples() {
@ -133,6 +134,34 @@ public class FragmentedMp4MuxerEndToEndTest {
MuxerTestUtil.getExpectedDumpFilePath(H265_HDR10_MP4 + "_fragmented_box_structure")); MuxerTestUtil.getExpectedDumpFilePath(H265_HDR10_MP4 + "_fragmented_box_structure"));
} }
@Test
public void createFragmentedMp4File_fromAudioOnlyInputFile_writesExpectedFragments()
throws Exception {
@Nullable FragmentedMp4Muxer fragmentedMp4Muxer = null;
try {
fragmentedMp4Muxer = new FragmentedMp4Muxer.Builder(checkNotNull(outputStream)).build();
fragmentedMp4Muxer.addMetadataEntry(
new Mp4TimestampData(
/* creationTimestampSeconds= */ 100_000_000L,
/* modificationTimestampSeconds= */ 500_000_000L));
feedInputDataToMuxer(context, fragmentedMp4Muxer, AUDIO_ONLY_MP4);
} finally {
if (fragmentedMp4Muxer != null) {
fragmentedMp4Muxer.close();
}
}
DumpableMp4Box dumpableMp4Box =
new DumpableMp4Box(
ByteBuffer.wrap(TestUtil.getByteArrayFromFilePath(checkNotNull(outputPath))));
// For a 15 sec audio, there should be 8 fragments (2 sec fragment duration).
DumpFileAsserts.assertOutput(
context,
dumpableMp4Box,
MuxerTestUtil.getExpectedDumpFilePath(AUDIO_ONLY_MP4 + "_fragmented_box_structure"));
}
private static void feedInputDataToMuxer( private static void feedInputDataToMuxer(
Context context, FragmentedMp4Muxer muxer, String inputFileName) Context context, FragmentedMp4Muxer muxer, String inputFileName)
throws IOException, MuxerException { throws IOException, MuxerException {

View File

@ -0,0 +1,112 @@
ftyp (28 bytes):
Data = length 20, hash EF896440
moov (570 bytes):
mvhd (108 bytes):
Data = length 100, hash 2FE65288
trak (414 bytes):
tkhd (92 bytes):
Data = length 84, hash B0AC1B04
mdia (314 bytes):
mdhd (32 bytes):
Data = length 24, hash 2FD02F4F
hdlr (44 bytes):
Data = length 36, hash 49FC755F
minf (230 bytes):
smhd (16 bytes):
Data = length 8, hash 94446F01
dinf (36 bytes):
Data = length 28, hash D535436B
stbl (170 bytes):
stsd (94 bytes):
Data = length 86, hash 8D20FFFF
stts (16 bytes):
Data = length 8, hash 94446F01
stsz (20 bytes):
Data = length 12, hash EE830681
stsc (16 bytes):
Data = length 8, hash 94446F01
stco (16 bytes):
Data = length 8, hash 94446F01
mvex (40 bytes):
trex (32 bytes):
Data = length 24, hash C35D3183
moof (1216 bytes):
mfhd (16 bytes):
Data = length 8, hash 94446F02
traf (1192 bytes):
tfhd (24 bytes):
Data = length 16, hash D3715417
trun (1160 bytes):
Data = length 1152, hash 1DBC5FAE
mdat (595 bytes):
Data = length 587, hash 5606AB27
moof (1216 bytes):
mfhd (16 bytes):
Data = length 8, hash 94446F03
traf (1192 bytes):
tfhd (24 bytes):
Data = length 16, hash D3715503
trun (1160 bytes):
Data = length 1152, hash D7BCFD1D
mdat (578 bytes):
Data = length 570, hash 82739626
moof (1216 bytes):
mfhd (16 bytes):
Data = length 8, hash 94446F04
traf (1192 bytes):
tfhd (24 bytes):
Data = length 16, hash D37155DE
trun (1160 bytes):
Data = length 1152, hash 4B1C22AE
mdat (595 bytes):
Data = length 587, hash 5925807B
moof (1216 bytes):
mfhd (16 bytes):
Data = length 8, hash 94446F05
traf (1192 bytes):
tfhd (24 bytes):
Data = length 16, hash D37156CA
trun (1160 bytes):
Data = length 1152, hash D7BCFD1D
mdat (578 bytes):
Data = length 570, hash 82739626
moof (1216 bytes):
mfhd (16 bytes):
Data = length 8, hash 94446F06
traf (1192 bytes):
tfhd (24 bytes):
Data = length 16, hash D37156A5
trun (1160 bytes):
Data = length 1152, hash D7BCFD1D
mdat (578 bytes):
Data = length 570, hash 82739626
moof (1216 bytes):
mfhd (16 bytes):
Data = length 8, hash 94446F07
traf (1192 bytes):
tfhd (24 bytes):
Data = length 16, hash D3715780
trun (1160 bytes):
Data = length 1152, hash B425E72E
mdat (595 bytes):
Data = length 587, hash 310213B9
moof (1216 bytes):
mfhd (16 bytes):
Data = length 8, hash 94446F08
traf (1192 bytes):
tfhd (24 bytes):
Data = length 16, hash D371586C
trun (1160 bytes):
Data = length 1152, hash D7BCFD1D
mdat (578 bytes):
Data = length 570, hash 82739626
moof (556 bytes):
mfhd (16 bytes):
Data = length 8, hash 94446F09
traf (532 bytes):
tfhd (24 bytes):
Data = length 16, hash D3715947
trun (500 bytes):
Data = length 492, hash EC9CC954
mdat (248 bytes):
Data = length 240, hash BD3FF239