diff options
| author | metamuffin <metamuffin@disroot.org> | 2026-03-05 16:35:00 +0100 |
|---|---|---|
| committer | metamuffin <metamuffin@disroot.org> | 2026-03-05 16:35:00 +0100 |
| commit | 1184539329ee82f2e82b3261953ebc87e7b855e0 (patch) | |
| tree | 508673a16178c18b41df19d63d1a7421d00d70f3 | |
| parent | 3fd3df27b1611867d8a2a224a7849bd4505406fa (diff) | |
| download | jellything-1184539329ee82f2e82b3261953ebc87e7b855e0.tar jellything-1184539329ee82f2e82b3261953ebc87e7b855e0.tar.bz2 jellything-1184539329ee82f2e82b3261953ebc87e7b855e0.tar.zst | |
more boxes
| -rw-r--r-- | remuxer/mp4/src/boxes.rs | 93 | ||||
| -rw-r--r-- | remuxer/src/muxers/mp4.rs | 22 |
2 files changed, 111 insertions, 4 deletions
diff --git a/remuxer/mp4/src/boxes.rs b/remuxer/mp4/src/boxes.rs index d2c3918..4c14eb1 100644 --- a/remuxer/mp4/src/boxes.rs +++ b/remuxer/mp4/src/boxes.rs @@ -44,6 +44,22 @@ impl WriteBox for FileType<'_> { } } +pub struct SegmentType<'a> { + pub major_brand: [u8; 4], + pub minor_version: u32, + pub compatible_brands: &'a [[u8; 4]], +} +impl WriteBox for SegmentType<'_> { + const BOXTYPE: [u8; 4] = *b"styp"; + fn write(&self, buf: &mut Vec<u8>) { + buf.extend(self.major_brand); + buf.extend(self.minor_version.to_be_bytes()); + for cb in self.compatible_brands { + buf.extend(cb); + } + } +} + pub struct MovieHeader { pub creation_time: u64, pub modification_time: u64, @@ -135,6 +151,7 @@ pub struct EditListEntry { } impl WriteBox for EditList<'_> { const BOXTYPE: [u8; 4] = *b"elst"; + const VERSION: Option<u8> = Some(1); fn write(&self, buf: &mut Vec<u8>) { buf.extend((self.entries.len() as u32).to_be_bytes()); for e in self.entries { @@ -242,6 +259,7 @@ pub struct TrackFragmentHeader { } impl WriteBox for TrackFragmentHeader { const BOXTYPE: [u8; 4] = *b"tfhd"; + const VERSION: Option<u8> = Some(0); fn write(&self, buf: &mut Vec<u8>) { buf.extend(self.track_id.to_be_bytes()); } @@ -252,6 +270,7 @@ pub struct TrackFragmentBaseMediaDecodeTime { } impl WriteBox for TrackFragmentBaseMediaDecodeTime { const BOXTYPE: [u8; 4] = *b"tfdt"; + const VERSION: Option<u8> = Some(1); fn write(&self, buf: &mut Vec<u8>) { buf.extend(self.base_media_decode_time.to_be_bytes()); } @@ -262,7 +281,81 @@ pub struct TrackRun { } impl WriteBox for TrackRun { const BOXTYPE: [u8; 4] = *b"trun"; + const VERSION: Option<u8> = Some(1); fn write(&self, buf: &mut Vec<u8>) { buf.extend(self.data_offset.to_be_bytes()); } } + +pub struct TimeToSample<'a>(pub &'a [TimeToSampleEntry]); +pub struct TimeToSampleEntry { + pub sample_count: u32, + pub sample_delta: u32, +} +impl WriteBox for TimeToSample<'_> { + const BOXTYPE: [u8; 4] = *b"stts"; + const VERSION: Option<u8> = Some(0); + fn write(&self, buf: &mut Vec<u8>) { + buf.extend((self.0.len() as u32).to_be_bytes()); + for e in self.0 { + buf.extend(e.sample_count.to_be_bytes()); + buf.extend(e.sample_delta.to_be_bytes()); + } + } +} + +pub struct TimeToChunk<'a>(pub &'a [TimeToChunkEntry]); +pub struct TimeToChunkEntry { + pub first_chunk: u32, + pub samples_per_chunk: u32, + pub sample_description_index: u32, +} +impl WriteBox for TimeToChunk<'_> { + const BOXTYPE: [u8; 4] = *b"stsc"; + const VERSION: Option<u8> = Some(0); + fn write(&self, buf: &mut Vec<u8>) { + buf.extend((self.0.len() as u32).to_be_bytes()); + for e in self.0 { + buf.extend(e.first_chunk.to_be_bytes()); + buf.extend(e.samples_per_chunk.to_be_bytes()); + buf.extend(e.sample_description_index.to_be_bytes()); + } + } +} + +pub struct SampleSize<'a> { + pub sample_size: u32, + pub entries: &'a [u32], +} +impl WriteBox for SampleSize<'_> { + const BOXTYPE: [u8; 4] = *b"stts"; + const VERSION: Option<u8> = Some(0); + fn write(&self, buf: &mut Vec<u8>) { + buf.extend(self.sample_size.to_be_bytes()); + buf.extend((self.entries.len() as u32).to_be_bytes()); + if self.sample_size == 0 { + for e in self.entries { + buf.extend(e.to_be_bytes()); + } + } + } +} + +pub struct ChunkOffset<'a>(pub &'a [u32]); +impl WriteBox for ChunkOffset<'_> { + const BOXTYPE: [u8; 4] = *b"stco"; + const VERSION: Option<u8> = Some(0); + fn write(&self, buf: &mut Vec<u8>) { + buf.extend((self.0.len() as u32).to_be_bytes()); + for e in self.0 { + buf.extend(e.to_be_bytes()); + } + } +} + +pub struct SampleDescription; +impl WriteBox for SampleDescription { + const BOXTYPE: [u8; 4] = *b"stsd"; + const VERSION: Option<u8> = Some(0); + fn write(&self, _buf: &mut Vec<u8>) {} +} diff --git a/remuxer/src/muxers/mp4.rs b/remuxer/src/muxers/mp4.rs index c3191d1..5975921 100644 --- a/remuxer/src/muxers/mp4.rs +++ b/remuxer/src/muxers/mp4.rs @@ -14,9 +14,9 @@ impl FragmentMuxer for MP4FragmentMuxer { fn write_init(out: &mut Vec<u8>, segment: Segment) -> Result<()> { let mut out = BoxW::new(out); out.write(FileType { - major_brand: *b"mp41", - minor_version: 0, - compatible_brands: &[*b"iso6"], + major_brand: *b"iso5", + minor_version: 512, + compatible_brands: &[*b"iso5", *b"iso6", *b"mp41"], }); out.write(Movie(|moov| { moov.write(MovieHeader { @@ -41,7 +41,16 @@ impl FragmentMuxer for MP4FragmentMuxer { minf.write(DataInformation(|dinf| { dinf.write(DataReference { entries: &[] }); })); - minf.write(SampleTable(|stbl| {})); + minf.write(SampleTable(|stbl| { + stbl.write(SampleDescription); + stbl.write(TimeToSample(&[])); + stbl.write(TimeToChunk(&[])); + stbl.write(ChunkOffset(&[])); + stbl.write(SampleSize { + sample_size: 0, + entries: &[], + }); + })); })); })); })); @@ -52,6 +61,11 @@ impl FragmentMuxer for MP4FragmentMuxer { fn write_frag(out: &mut Vec<u8>, segment: Segment) -> Result<()> { let mut out = BoxW::new(out); + out.write(SegmentType { + major_brand: *b"msdh", + minor_version: 0, + compatible_brands: &[*b"msdh", *b"msix"], + }); out.write(MovieFragment(|moof| { moof.write(MovieFragmentHeader { sequence_number: 0 }); moof.write(TrackFragment(|traf| { |