Skip to content

Commit 8803014

Browse files
author
Andrey Tkachenko
committed
refactoring: split off Mp4Header from Mp4Reader
1 parent 35560e9 commit 8803014

File tree

4 files changed

+114
-39
lines changed

4 files changed

+114
-39
lines changed

examples/mp4dump.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -46,12 +46,12 @@ fn get_boxes(file: File) -> Result<Vec<Box>> {
4646

4747
// collect known boxes
4848
let mut boxes = vec![
49-
build_box(&mp4.ftyp),
50-
build_box(&mp4.moov),
51-
build_box(&mp4.moov.mvhd),
49+
build_box(&mp4.header.ftyp),
50+
build_box(&mp4.header.moov),
51+
build_box(&mp4.header.moov.mvhd),
5252
];
5353

54-
if let Some(ref mvex) = &mp4.moov.mvex {
54+
if let Some(ref mvex) = &mp4.header.moov.mvex {
5555
boxes.push(build_box(mvex));
5656
if let Some(mehd) = &mvex.mehd {
5757
boxes.push(build_box(mehd));
@@ -117,7 +117,7 @@ fn get_boxes(file: File) -> Result<Vec<Box>> {
117117
}
118118

119119
// If fragmented, add moof boxes.
120-
for moof in mp4.moofs.iter() {
120+
for moof in mp4.header.moofs.iter() {
121121
boxes.push(build_box(moof));
122122
boxes.push(build_box(&moof.mfhd));
123123
for traf in moof.trafs.iter() {

examples/mp4info.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,10 +37,10 @@ fn info<P: AsRef<Path>>(filename: &P) -> Result<()> {
3737
println!(" compatible_brands: {}\n", compatible_brands);
3838

3939
println!("Movie:");
40-
println!(" version: {}", mp4.moov.mvhd.version);
40+
println!(" version: {}", mp4.header.moov.mvhd.version);
4141
println!(
4242
" creation time: {}",
43-
creation_time(mp4.moov.mvhd.creation_time)
43+
creation_time(mp4.header.moov.mvhd.creation_time)
4444
);
4545
println!(" duration: {:?}", mp4.duration());
4646
println!(" fragments: {:?}", mp4.is_fragmented());

src/lib.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,8 @@
2222
//! let mp4 = mp4::Mp4Reader::read_header(reader, size)?;
2323
//!
2424
//! // Print boxes.
25-
//! println!("major brand: {}", mp4.ftyp.major_brand);
26-
//! println!("timescale: {}", mp4.moov.mvhd.timescale);
25+
//! println!("major brand: {}", mp4.header.ftyp.major_brand);
26+
//! println!("timescale: {}", mp4.header.moov.mvhd.timescale);
2727
//!
2828
//! // Use available methods.
2929
//! println!("size: {}", mp4.size());
@@ -83,7 +83,7 @@ mod track;
8383
pub use track::{Mp4Track, TrackConfig};
8484

8585
mod reader;
86-
pub use reader::Mp4Reader;
86+
pub use reader::{Mp4Header, Mp4Reader};
8787

8888
mod writer;
8989
pub use writer::{Mp4Config, Mp4Writer};

src/reader.rs

Lines changed: 104 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,7 @@ use crate::meta::MetaBox;
66
use crate::*;
77

88
#[derive(Debug)]
9-
pub struct Mp4Reader<R> {
10-
reader: R,
9+
pub struct Mp4Header {
1110
pub ftyp: FtypBox,
1211
pub moov: MoovBox,
1312
pub moofs: Vec<MoofBox>,
@@ -17,8 +16,8 @@ pub struct Mp4Reader<R> {
1716
size: u64,
1817
}
1918

20-
impl<R: Read + Seek> Mp4Reader<R> {
21-
pub fn read_header(mut reader: R, size: u64) -> Result<Self> {
19+
impl Mp4Header {
20+
pub fn read<R: Read + Seek>(reader: &mut R, size: u64) -> Result<Self> {
2221
let start = reader.stream_position()?;
2322

2423
let mut ftyp = None;
@@ -30,7 +29,7 @@ impl<R: Read + Seek> Mp4Reader<R> {
3029
let mut current = start;
3130
while current < size {
3231
// Get box header.
33-
let header = BoxHeader::read(&mut reader)?;
32+
let header = BoxHeader::read(reader)?;
3433
let BoxHeader { name, size: s } = header;
3534
if s > size {
3635
return Err(Error::InvalidData(
@@ -46,30 +45,30 @@ impl<R: Read + Seek> Mp4Reader<R> {
4645
// Match and parse the atom boxes.
4746
match name {
4847
BoxType::FtypBox => {
49-
ftyp = Some(FtypBox::read_box(&mut reader, s)?);
48+
ftyp = Some(FtypBox::read_box(reader, s)?);
5049
}
5150
BoxType::FreeBox => {
52-
skip_box(&mut reader, s)?;
51+
skip_box(reader, s)?;
5352
}
5453
BoxType::MdatBox => {
55-
skip_box(&mut reader, s)?;
54+
skip_box(reader, s)?;
5655
}
5756
BoxType::MoovBox => {
58-
moov = Some(MoovBox::read_box(&mut reader, s)?);
57+
moov = Some(MoovBox::read_box(reader, s)?);
5958
}
6059
BoxType::MoofBox => {
6160
let moof_offset = reader.stream_position()? - 8;
62-
let moof = MoofBox::read_box(&mut reader, s)?;
61+
let moof = MoofBox::read_box(reader, s)?;
6362
moofs.push(moof);
6463
moof_offsets.push(moof_offset);
6564
}
6665
BoxType::EmsgBox => {
67-
let emsg = EmsgBox::read_box(&mut reader, s)?;
66+
let emsg = EmsgBox::read_box(reader, s)?;
6867
emsgs.push(emsg);
6968
}
7069
_ => {
7170
// XXX warn!()
72-
skip_box(&mut reader, s)?;
71+
skip_box(reader, s)?;
7372
}
7473
}
7574
current = reader.stream_position()?;
@@ -118,8 +117,7 @@ impl<R: Read + Seek> Mp4Reader<R> {
118117
}
119118
}
120119

121-
Ok(Mp4Reader {
122-
reader,
120+
Ok(Mp4Header {
123121
ftyp: ftyp.unwrap(),
124122
moov: moov.unwrap(),
125123
moofs,
@@ -129,11 +127,7 @@ impl<R: Read + Seek> Mp4Reader<R> {
129127
})
130128
}
131129

132-
pub fn read_fragment_header<FR: Read + Seek>(
133-
&self,
134-
mut reader: FR,
135-
size: u64,
136-
) -> Result<Mp4Reader<FR>> {
130+
pub fn read_fragment<R: Read + Seek>(&self, reader: &mut R, size: u64) -> Result<Self> {
137131
let start = reader.stream_position()?;
138132

139133
let mut moofs = Vec::new();
@@ -142,7 +136,7 @@ impl<R: Read + Seek> Mp4Reader<R> {
142136
let mut current = start;
143137
while current < size {
144138
// Get box header.
145-
let header = BoxHeader::read(&mut reader)?;
139+
let header = BoxHeader::read(reader)?;
146140
let BoxHeader { name, size: s } = header;
147141
if s > size {
148142
return Err(Error::InvalidData(
@@ -158,17 +152,17 @@ impl<R: Read + Seek> Mp4Reader<R> {
158152
// Match and parse the atom boxes.
159153
match name {
160154
BoxType::MdatBox => {
161-
skip_box(&mut reader, s)?;
155+
skip_box(reader, s)?;
162156
}
163157
BoxType::MoofBox => {
164158
let moof_offset = reader.stream_position()? - 8;
165-
let moof = MoofBox::read_box(&mut reader, s)?;
159+
let moof = MoofBox::read_box(reader, s)?;
166160
moofs.push(moof);
167161
moof_offsets.push(moof_offset);
168162
}
169163
_ => {
170164
// XXX warn!()
171-
skip_box(&mut reader, s)?;
165+
skip_box(reader, s)?;
172166
}
173167
}
174168
current = reader.stream_position()?;
@@ -204,8 +198,7 @@ impl<R: Read + Seek> Mp4Reader<R> {
204198
}
205199
}
206200

207-
Ok(Mp4Reader {
208-
reader,
201+
Ok(Mp4Header {
209202
ftyp: self.ftyp.clone(),
210203
moov: self.moov.clone(),
211204
moofs,
@@ -215,10 +208,12 @@ impl<R: Read + Seek> Mp4Reader<R> {
215208
})
216209
}
217210

211+
#[inline]
218212
pub fn size(&self) -> u64 {
219213
self.size
220214
}
221215

216+
#[inline]
222217
pub fn major_brand(&self) -> &FourCC {
223218
&self.ftyp.major_brand
224219
}
@@ -255,9 +250,14 @@ impl<R: Read + Seek> Mp4Reader<R> {
255250
}
256251
}
257252

258-
pub fn read_sample(&mut self, track_id: u32, sample_id: u32) -> Result<Option<Mp4Sample>> {
253+
pub fn read_sample<R: Read + Seek>(
254+
&mut self,
255+
reader: &mut R,
256+
track_id: u32,
257+
sample_id: u32,
258+
) -> Result<Option<Mp4Sample>> {
259259
if let Some(track) = self.tracks.get(&track_id) {
260-
track.read_sample(&mut self.reader, sample_id)
260+
track.read_sample(reader, sample_id)
261261
} else {
262262
Err(Error::TrakNotFound(track_id))
263263
}
@@ -270,9 +270,7 @@ impl<R: Read + Seek> Mp4Reader<R> {
270270
Err(Error::TrakNotFound(track_id))
271271
}
272272
}
273-
}
274273

275-
impl<R> Mp4Reader<R> {
276274
pub fn metadata(&self) -> impl Metadata<'_> {
277275
self.moov.udta.as_ref().and_then(|udta| {
278276
udta.meta.as_ref().and_then(|meta| match meta {
@@ -282,3 +280,80 @@ impl<R> Mp4Reader<R> {
282280
})
283281
}
284282
}
283+
284+
#[derive(Debug)]
285+
pub struct Mp4Reader<R> {
286+
reader: R,
287+
pub header: Mp4Header,
288+
}
289+
290+
impl<R: Read + Seek> Mp4Reader<R> {
291+
pub fn read_header(mut reader: R, size: u64) -> Result<Self> {
292+
Ok(Mp4Reader {
293+
header: Mp4Header::read(&mut reader, size)?,
294+
reader,
295+
})
296+
}
297+
298+
pub fn read_fragment_header<FR: Read + Seek>(
299+
&self,
300+
mut reader: FR,
301+
size: u64,
302+
) -> Result<Mp4Reader<FR>> {
303+
Ok(Mp4Reader {
304+
header: self.header.read_fragment(&mut reader, size)?,
305+
reader,
306+
})
307+
}
308+
309+
pub fn size(&self) -> u64 {
310+
self.header.size()
311+
}
312+
313+
pub fn major_brand(&self) -> &FourCC {
314+
self.header.major_brand()
315+
}
316+
317+
pub fn minor_version(&self) -> u32 {
318+
self.header.minor_version()
319+
}
320+
321+
pub fn compatible_brands(&self) -> &[FourCC] {
322+
self.header.compatible_brands()
323+
}
324+
325+
pub fn duration(&self) -> Duration {
326+
self.header.duration()
327+
}
328+
329+
pub fn timescale(&self) -> u32 {
330+
self.header.timescale()
331+
}
332+
333+
pub fn is_fragmented(&self) -> bool {
334+
self.header.is_fragmented()
335+
}
336+
337+
pub fn tracks(&self) -> &HashMap<u32, Mp4Track> {
338+
self.header.tracks()
339+
}
340+
341+
pub fn sample_count(&self, track_id: u32) -> Result<u32> {
342+
self.header.sample_count(track_id)
343+
}
344+
345+
pub fn read_sample(&mut self, track_id: u32, sample_id: u32) -> Result<Option<Mp4Sample>> {
346+
self.header
347+
.read_sample(&mut self.reader, track_id, sample_id)
348+
}
349+
350+
pub fn sample_offset(&mut self, track_id: u32, sample_id: u32) -> Result<u64> {
351+
self.header.sample_offset(track_id, sample_id)
352+
}
353+
}
354+
355+
impl<R> Mp4Reader<R> {
356+
pub fn metadata(&self) -> impl Metadata<'_> {
357+
self.header.metadata()
358+
}
359+
}

0 commit comments

Comments
 (0)