1
0
Fork 0
mirror of https://github.com/alfg/mp4-rust.git synced 2024-06-02 13:39:54 +00:00

Add a function to the reader to read in fragments from a different reader

This commit is contained in:
Jensenn 2023-05-26 13:48:27 -06:00
parent a730bcd00c
commit d6debae211
4 changed files with 119 additions and 0 deletions

View file

@ -129,6 +129,92 @@ impl<R: Read + Seek> Mp4Reader<R> {
})
}
pub fn read_fragment_header<FR: Read + Seek>(
&self,
mut reader: FR,
size: u64,
) -> Result<Mp4Reader<FR>> {
let start = reader.stream_position()?;
let mut moofs = Vec::new();
let mut moof_offsets = Vec::new();
let mut current = start;
while current < size {
// Get box header.
let header = BoxHeader::read(&mut reader)?;
let BoxHeader { name, size: s } = header;
if s > size {
return Err(Error::InvalidData(
"file contains a box with a larger size than it",
));
}
// Break if size zero BoxHeader, which can result in dead-loop.
if s == 0 {
break;
}
// Match and parse the atom boxes.
match name {
BoxType::MdatBox => {
skip_box(&mut reader, s)?;
}
BoxType::MoofBox => {
let moof_offset = reader.stream_position()? - 8;
let moof = MoofBox::read_box(&mut reader, s)?;
moofs.push(moof);
moof_offsets.push(moof_offset);
}
_ => {
// XXX warn!()
skip_box(&mut reader, s)?;
}
}
current = reader.stream_position()?;
}
if moofs.is_empty() {
return Err(Error::BoxNotFound(BoxType::MoofBox));
}
let size = current - start;
let mut tracks: HashMap<u32, Mp4Track> = self
.moov
.traks
.iter()
.map(|trak| (trak.tkhd.track_id, Mp4Track::from(trak)))
.collect();
let mut default_sample_duration = 0;
if let Some(ref mvex) = &self.moov.mvex {
default_sample_duration = mvex.trex.default_sample_duration
}
for (moof, moof_offset) in moofs.iter().zip(moof_offsets) {
for traf in moof.trafs.iter() {
let track_id = traf.tfhd.track_id;
if let Some(track) = tracks.get_mut(&track_id) {
track.default_sample_duration = default_sample_duration;
track.moof_offsets.push(moof_offset);
track.trafs.push(traf.clone())
} else {
return Err(Error::TrakNotFound(track_id));
}
}
}
Ok(Mp4Reader {
reader,
ftyp: self.ftyp.clone(),
moov: self.moov.clone(),
moofs,
emsgs: Vec::new(),
tracks,
size,
})
}
pub fn size(&self) -> u64 {
self.size
}

View file

@ -176,3 +176,36 @@ fn test_read_metadata() {
assert_eq!(poster.len(), want_poster.len());
assert_eq!(poster, want_poster.as_slice());
}
#[test]
fn test_read_fragments() {
let mp4 = get_reader("tests/samples/minimal_init.mp4");
assert_eq!(692, mp4.size());
assert_eq!(5, mp4.compatible_brands().len());
let sample_count = mp4.sample_count(1).unwrap();
assert_eq!(sample_count, 0);
let f = File::open("tests/samples/minimal_fragment.m4s").unwrap();
let f_size = f.metadata().unwrap().len();
let frag_reader = BufReader::new(f);
let mut mp4_fragment = mp4.read_fragment_header(frag_reader, f_size).unwrap();
let sample_count = mp4_fragment.sample_count(1).unwrap();
assert_eq!(sample_count, 1);
let sample_1_1 = mp4_fragment.read_sample(1, 1).unwrap().unwrap();
assert_eq!(sample_1_1.bytes.len(), 751);
assert_eq!(
sample_1_1,
mp4::Mp4Sample {
start_time: 0,
duration: 512,
rendering_offset: 0,
is_sync: true,
bytes: mp4::Bytes::from(vec![0x0u8; 751]),
}
);
let eos = mp4_fragment.read_sample(1, 2);
assert!(eos.is_err());
}

Binary file not shown.

Binary file not shown.