1
0
Fork 0
mirror of https://github.com/alfg/mp4-rust.git synced 2024-06-11 01:19:21 +00:00

refactoring: split off Mp4Header from Mp4Reader

This commit is contained in:
Andrey Tkachenko 2023-09-22 14:25:53 +04:00
parent 35560e94f5
commit 045677e56e
4 changed files with 118 additions and 39 deletions

View file

@ -46,12 +46,12 @@ fn get_boxes(file: File) -> Result<Vec<Box>> {
// collect known boxes // collect known boxes
let mut boxes = vec![ let mut boxes = vec![
build_box(&mp4.ftyp), build_box(&mp4.header.ftyp),
build_box(&mp4.moov), build_box(&mp4.header.moov),
build_box(&mp4.moov.mvhd), build_box(&mp4.header.moov.mvhd),
]; ];
if let Some(ref mvex) = &mp4.moov.mvex { if let Some(ref mvex) = &mp4.header.moov.mvex {
boxes.push(build_box(mvex)); boxes.push(build_box(mvex));
if let Some(mehd) = &mvex.mehd { if let Some(mehd) = &mvex.mehd {
boxes.push(build_box(mehd)); boxes.push(build_box(mehd));
@ -117,7 +117,7 @@ fn get_boxes(file: File) -> Result<Vec<Box>> {
} }
// If fragmented, add moof boxes. // If fragmented, add moof boxes.
for moof in mp4.moofs.iter() { for moof in mp4.header.moofs.iter() {
boxes.push(build_box(moof)); boxes.push(build_box(moof));
boxes.push(build_box(&moof.mfhd)); boxes.push(build_box(&moof.mfhd));
for traf in moof.trafs.iter() { for traf in moof.trafs.iter() {

View file

@ -37,10 +37,10 @@ fn info<P: AsRef<Path>>(filename: &P) -> Result<()> {
println!(" compatible_brands: {}\n", compatible_brands); println!(" compatible_brands: {}\n", compatible_brands);
println!("Movie:"); println!("Movie:");
println!(" version: {}", mp4.moov.mvhd.version); println!(" version: {}", mp4.header.moov.mvhd.version);
println!( println!(
" creation time: {}", " creation time: {}",
creation_time(mp4.moov.mvhd.creation_time) creation_time(mp4.header.moov.mvhd.creation_time)
); );
println!(" duration: {:?}", mp4.duration()); println!(" duration: {:?}", mp4.duration());
println!(" fragments: {:?}", mp4.is_fragmented()); println!(" fragments: {:?}", mp4.is_fragmented());

View file

@ -22,8 +22,8 @@
//! let mp4 = mp4::Mp4Reader::read_header(reader, size)?; //! let mp4 = mp4::Mp4Reader::read_header(reader, size)?;
//! //!
//! // Print boxes. //! // Print boxes.
//! println!("major brand: {}", mp4.ftyp.major_brand); //! println!("major brand: {}", mp4.header.ftyp.major_brand);
//! println!("timescale: {}", mp4.moov.mvhd.timescale); //! println!("timescale: {}", mp4.header.moov.mvhd.timescale);
//! //!
//! // Use available methods. //! // Use available methods.
//! println!("size: {}", mp4.size()); //! println!("size: {}", mp4.size());
@ -83,7 +83,7 @@ mod track;
pub use track::{Mp4Track, TrackConfig}; pub use track::{Mp4Track, TrackConfig};
mod reader; mod reader;
pub use reader::Mp4Reader; pub use reader::{Mp4Header, Mp4Reader};
mod writer; mod writer;
pub use writer::{Mp4Config, Mp4Writer}; pub use writer::{Mp4Config, Mp4Writer};

View file

@ -6,8 +6,7 @@ use crate::meta::MetaBox;
use crate::*; use crate::*;
#[derive(Debug)] #[derive(Debug)]
pub struct Mp4Reader<R> { pub struct Mp4Header {
reader: R,
pub ftyp: FtypBox, pub ftyp: FtypBox,
pub moov: MoovBox, pub moov: MoovBox,
pub moofs: Vec<MoofBox>, pub moofs: Vec<MoofBox>,
@ -17,8 +16,8 @@ pub struct Mp4Reader<R> {
size: u64, size: u64,
} }
impl<R: Read + Seek> Mp4Reader<R> { impl Mp4Header {
pub fn read_header(mut reader: R, size: u64) -> Result<Self> { pub fn read<R: Read + Seek>(reader: &mut R, size: u64) -> Result<Self> {
let start = reader.stream_position()?; let start = reader.stream_position()?;
let mut ftyp = None; let mut ftyp = None;
@ -30,7 +29,7 @@ impl<R: Read + Seek> Mp4Reader<R> {
let mut current = start; let mut current = start;
while current < size { while current < size {
// Get box header. // Get box header.
let header = BoxHeader::read(&mut reader)?; let header = BoxHeader::read(reader)?;
let BoxHeader { name, size: s } = header; let BoxHeader { name, size: s } = header;
if s > size { if s > size {
return Err(Error::InvalidData( return Err(Error::InvalidData(
@ -46,30 +45,30 @@ impl<R: Read + Seek> Mp4Reader<R> {
// Match and parse the atom boxes. // Match and parse the atom boxes.
match name { match name {
BoxType::FtypBox => { BoxType::FtypBox => {
ftyp = Some(FtypBox::read_box(&mut reader, s)?); ftyp = Some(FtypBox::read_box(reader, s)?);
} }
BoxType::FreeBox => { BoxType::FreeBox => {
skip_box(&mut reader, s)?; skip_box(reader, s)?;
} }
BoxType::MdatBox => { BoxType::MdatBox => {
skip_box(&mut reader, s)?; skip_box(reader, s)?;
} }
BoxType::MoovBox => { BoxType::MoovBox => {
moov = Some(MoovBox::read_box(&mut reader, s)?); moov = Some(MoovBox::read_box(reader, s)?);
} }
BoxType::MoofBox => { BoxType::MoofBox => {
let moof_offset = reader.stream_position()? - 8; let moof_offset = reader.stream_position()? - 8;
let moof = MoofBox::read_box(&mut reader, s)?; let moof = MoofBox::read_box(reader, s)?;
moofs.push(moof); moofs.push(moof);
moof_offsets.push(moof_offset); moof_offsets.push(moof_offset);
} }
BoxType::EmsgBox => { BoxType::EmsgBox => {
let emsg = EmsgBox::read_box(&mut reader, s)?; let emsg = EmsgBox::read_box(reader, s)?;
emsgs.push(emsg); emsgs.push(emsg);
} }
_ => { _ => {
// XXX warn!() // XXX warn!()
skip_box(&mut reader, s)?; skip_box(reader, s)?;
} }
} }
current = reader.stream_position()?; current = reader.stream_position()?;
@ -118,8 +117,7 @@ impl<R: Read + Seek> Mp4Reader<R> {
} }
} }
Ok(Mp4Reader { Ok(Mp4Header {
reader,
ftyp: ftyp.unwrap(), ftyp: ftyp.unwrap(),
moov: moov.unwrap(), moov: moov.unwrap(),
moofs, moofs,
@ -129,11 +127,7 @@ impl<R: Read + Seek> Mp4Reader<R> {
}) })
} }
pub fn read_fragment_header<FR: Read + Seek>( pub fn read_fragment<R: Read + Seek>(&self, reader: &mut R, size: u64) -> Result<Self> {
&self,
mut reader: FR,
size: u64,
) -> Result<Mp4Reader<FR>> {
let start = reader.stream_position()?; let start = reader.stream_position()?;
let mut moofs = Vec::new(); let mut moofs = Vec::new();
@ -142,7 +136,7 @@ impl<R: Read + Seek> Mp4Reader<R> {
let mut current = start; let mut current = start;
while current < size { while current < size {
// Get box header. // Get box header.
let header = BoxHeader::read(&mut reader)?; let header = BoxHeader::read(reader)?;
let BoxHeader { name, size: s } = header; let BoxHeader { name, size: s } = header;
if s > size { if s > size {
return Err(Error::InvalidData( return Err(Error::InvalidData(
@ -158,17 +152,17 @@ impl<R: Read + Seek> Mp4Reader<R> {
// Match and parse the atom boxes. // Match and parse the atom boxes.
match name { match name {
BoxType::MdatBox => { BoxType::MdatBox => {
skip_box(&mut reader, s)?; skip_box(reader, s)?;
} }
BoxType::MoofBox => { BoxType::MoofBox => {
let moof_offset = reader.stream_position()? - 8; let moof_offset = reader.stream_position()? - 8;
let moof = MoofBox::read_box(&mut reader, s)?; let moof = MoofBox::read_box(reader, s)?;
moofs.push(moof); moofs.push(moof);
moof_offsets.push(moof_offset); moof_offsets.push(moof_offset);
} }
_ => { _ => {
// XXX warn!() // XXX warn!()
skip_box(&mut reader, s)?; skip_box(reader, s)?;
} }
} }
current = reader.stream_position()?; current = reader.stream_position()?;
@ -204,8 +198,7 @@ impl<R: Read + Seek> Mp4Reader<R> {
} }
} }
Ok(Mp4Reader { Ok(Mp4Header {
reader,
ftyp: self.ftyp.clone(), ftyp: self.ftyp.clone(),
moov: self.moov.clone(), moov: self.moov.clone(),
moofs, moofs,
@ -215,10 +208,12 @@ impl<R: Read + Seek> Mp4Reader<R> {
}) })
} }
#[inline]
pub fn size(&self) -> u64 { pub fn size(&self) -> u64 {
self.size self.size
} }
#[inline]
pub fn major_brand(&self) -> &FourCC { pub fn major_brand(&self) -> &FourCC {
&self.ftyp.major_brand &self.ftyp.major_brand
} }
@ -255,9 +250,14 @@ impl<R: Read + Seek> Mp4Reader<R> {
} }
} }
pub fn read_sample(&mut self, track_id: u32, sample_id: u32) -> Result<Option<Mp4Sample>> { pub fn read_sample<R: Read + Seek>(
&mut self,
reader: &mut R,
track_id: u32,
sample_id: u32,
) -> Result<Option<Mp4Sample>> {
if let Some(track) = self.tracks.get(&track_id) { if let Some(track) = self.tracks.get(&track_id) {
track.read_sample(&mut self.reader, sample_id) track.read_sample(reader, sample_id)
} else { } else {
Err(Error::TrakNotFound(track_id)) Err(Error::TrakNotFound(track_id))
} }
@ -270,9 +270,7 @@ impl<R: Read + Seek> Mp4Reader<R> {
Err(Error::TrakNotFound(track_id)) Err(Error::TrakNotFound(track_id))
} }
} }
}
impl<R> Mp4Reader<R> {
pub fn metadata(&self) -> impl Metadata<'_> { pub fn metadata(&self) -> impl Metadata<'_> {
self.moov.udta.as_ref().and_then(|udta| { self.moov.udta.as_ref().and_then(|udta| {
udta.meta.as_ref().and_then(|meta| match meta { udta.meta.as_ref().and_then(|meta| match meta {
@ -282,3 +280,84 @@ impl<R> Mp4Reader<R> {
}) })
} }
} }
#[derive(Debug)]
pub struct Mp4Reader<R> {
reader: R,
pub header: Mp4Header,
}
impl<R: Read + Seek> Mp4Reader<R> {
pub fn from_reader(reader: R, header: Mp4Header) -> Self {
Self { reader, header }
}
pub fn read_header(mut reader: R, size: u64) -> Result<Self> {
Ok(Mp4Reader {
header: Mp4Header::read(&mut reader, size)?,
reader,
})
}
pub fn read_fragment_header<FR: Read + Seek>(
&self,
mut reader: FR,
size: u64,
) -> Result<Mp4Reader<FR>> {
Ok(Mp4Reader {
header: self.header.read_fragment(&mut reader, size)?,
reader,
})
}
pub fn size(&self) -> u64 {
self.header.size()
}
pub fn major_brand(&self) -> &FourCC {
self.header.major_brand()
}
pub fn minor_version(&self) -> u32 {
self.header.minor_version()
}
pub fn compatible_brands(&self) -> &[FourCC] {
self.header.compatible_brands()
}
pub fn duration(&self) -> Duration {
self.header.duration()
}
pub fn timescale(&self) -> u32 {
self.header.timescale()
}
pub fn is_fragmented(&self) -> bool {
self.header.is_fragmented()
}
pub fn tracks(&self) -> &HashMap<u32, Mp4Track> {
self.header.tracks()
}
pub fn sample_count(&self, track_id: u32) -> Result<u32> {
self.header.sample_count(track_id)
}
pub fn read_sample(&mut self, track_id: u32, sample_id: u32) -> Result<Option<Mp4Sample>> {
self.header
.read_sample(&mut self.reader, track_id, sample_id)
}
pub fn sample_offset(&mut self, track_id: u32, sample_id: u32) -> Result<u64> {
self.header.sample_offset(track_id, sample_id)
}
}
impl<R> Mp4Reader<R> {
pub fn metadata(&self) -> impl Metadata<'_> {
self.header.metadata()
}
}