From 1e86e4edabcbc1e29f5d9ec970b127ab53fa0e65 Mon Sep 17 00:00:00 2001 From: Ian Jun <40660047+ian-spoonradio@users.noreply.github.com> Date: Sun, 26 Jul 2020 12:11:47 +0900 Subject: [PATCH] Remove deprecated codes (#9) * Add ReadBox trait * Add boxtype macro * Remove offset in BoxHeader * Fix parsing error when box has largesize * Remove duplicated codes reading version and flags Co-authored-by: Byungwan Jun --- src/atoms.rs | 262 +++++++++++++++++++++------------------------------ src/lib.rs | 35 +++---- 2 files changed, 125 insertions(+), 172 deletions(-) diff --git a/src/atoms.rs b/src/atoms.rs index 0276d0c..bf35bca 100644 --- a/src/atoms.rs +++ b/src/atoms.rs @@ -6,99 +6,70 @@ use crate::{Error, read_box_header, BoxHeader, HEADER_SIZE}; pub type Result = std::result::Result; -#[derive(Clone, Copy, PartialEq)] -pub enum BoxType { - FtypBox, - MvhdBox, - FreeBox, - MdatBox, - MoovBox, - MoofBox, - TkhdBox, - EdtsBox, - MdiaBox, - ElstBox, - MdhdBox, - HdlrBox, - MinfBox, - VmhdBox, - StblBox, - StsdBox, - SttsBox, - TrakBox, - UdtaBox, - DinfBox, - SmhdBox, - Avc1Box, - Mp4aBox, - UnknownBox(u32), -} +macro_rules! boxtype { + ($( $name:ident => $value:expr ),*) => { + #[derive(Clone, Copy, PartialEq)] + pub enum BoxType { + $( $name, )* + UnknownBox(u32), + } -impl From for BoxType { - fn from(t: u32) -> BoxType { - use self::BoxType::*; - match t { - 0x66747970 => FtypBox, - 0x6d766864 => MvhdBox, - 0x66726565 => FreeBox, - 0x6d646174 => MdatBox, - 0x6d6f6f76 => MoovBox, - 0x6d6f6f66 => MoofBox , - 0x746b6864 => TkhdBox, - 0x65647473 => EdtsBox, - 0x6d646961 => MdiaBox, - 0x656c7374 => ElstBox, - 0x6d646864 => MdhdBox, - 0x68646c72 => HdlrBox, - 0x6d696e66 => MinfBox, - 0x766d6864 => VmhdBox, - 0x7374626c => StblBox, - 0x73747364 => StsdBox, - 0x73747473 => SttsBox, - 0x7472616b => TrakBox, - 0x75647461 => UdtaBox, - 0x64696e66 => DinfBox, - 0x736d6864 => SmhdBox, - 0x61766331 => Avc1Box, - 0x6d703461 => Mp4aBox, - _ => UnknownBox(t), + impl From for BoxType { + fn from(t: u32) -> BoxType { + match t { + $( $value => BoxType::$name, )* + _ => BoxType::UnknownBox(t), + } + } + } + + impl Into for BoxType { + fn into(self) -> u32 { + match self { + $( BoxType::$name => $value, )* + BoxType::UnknownBox(t) => t, + } + } } } } -impl Into for BoxType { - fn into(self) -> u32 { - use self::BoxType::*; - match self { - FtypBox => 0x66747970, - MvhdBox => 0x6d766864, - FreeBox => 0x66726565, - MdatBox => 0x6d646174, - MoovBox => 0x6d6f6f76, - MoofBox => 0x6d6f6f66, - TkhdBox => 0x746b6864, - EdtsBox => 0x65647473, - MdiaBox => 0x6d646961, - ElstBox => 0x656c7374, - MdhdBox => 0x6d646864, - HdlrBox => 0x68646c72, - MinfBox => 0x6d696e66, - VmhdBox => 0x766d6864, - StblBox => 0x7374626c, - StsdBox => 0x73747364, - SttsBox => 0x73747473, - TrakBox => 0x7472616b, - UdtaBox => 0x75647461, - DinfBox => 0x64696e66, - SmhdBox => 0x736d6864, - Avc1Box => 0x61766331, - Mp4aBox => 0x6d703461, - - UnknownBox(t) => t, - } +macro_rules! read_box_header_ext { + ($r:ident, $v:ident, $ f:ident) => { + let $v = $r.read_u8().unwrap(); + let flags_a = $r.read_u8().unwrap(); + let flags_b = $r.read_u8().unwrap(); + let flags_c = $r.read_u8().unwrap(); + let $f = u32::from(flags_a) << 16 | u32::from(flags_b) << 8 | u32::from(flags_c); } } +boxtype!{ + FtypBox => 0x66747970, + MvhdBox => 0x6d766864, + FreeBox => 0x66726565, + MdatBox => 0x6d646174, + MoovBox => 0x6d6f6f76, + MoofBox => 0x6d6f6f66, + TkhdBox => 0x746b6864, + EdtsBox => 0x65647473, + MdiaBox => 0x6d646961, + ElstBox => 0x656c7374, + MdhdBox => 0x6d646864, + HdlrBox => 0x68646c72, + MinfBox => 0x6d696e66, + VmhdBox => 0x766d6864, + StblBox => 0x7374626c, + StsdBox => 0x73747364, + SttsBox => 0x73747473, + TrakBox => 0x7472616b, + UdtaBox => 0x75647461, + DinfBox => 0x64696e66, + SmhdBox => 0x736d6864, + Avc1Box => 0x61766331, + Mp4aBox => 0x6d703461 +} + impl fmt::Debug for BoxType { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { let fourcc: FourCC = From::from(self.clone()); @@ -151,7 +122,7 @@ impl fmt::Display for FourCC { } pub trait ReadBox: Sized { - fn read_box(_: T, offset: u64, size: u32) -> Result; + fn read_box(_: T, size: u32) -> Result; } #[derive(Debug, Default)] @@ -333,7 +304,7 @@ pub struct StsdBox { } impl ReadBox<&mut BufReader> for FtypBox { - fn read_box(reader: &mut BufReader, _offset: u64, size: u32) -> Result { + fn read_box(reader: &mut BufReader, size: u32) -> Result { let major = reader.read_u32::().unwrap(); let minor = reader.read_u32::().unwrap(); if size % 4 != 0 { @@ -356,7 +327,7 @@ impl ReadBox<&mut BufReader> for FtypBox { } impl ReadBox<&mut BufReader> for MoovBox { - fn read_box(reader: &mut BufReader, _offset: u64, size: u32) -> Result { + fn read_box(reader: &mut BufReader, size: u32) -> Result { let mut moov = MoovBox::new(); let mut start = 0u64; @@ -364,14 +335,14 @@ impl ReadBox<&mut BufReader> for MoovBox { // Get box header. let header = read_box_header(reader, start).unwrap(); - let BoxHeader{ name, size: s, offset: _ } = header; + let BoxHeader{ name, size: s } = header; match name { BoxType::MvhdBox => { - moov.mvhd = MvhdBox::read_box(reader, 0, s as u32).unwrap(); + moov.mvhd = MvhdBox::read_box(reader, s as u32).unwrap(); } BoxType::TrakBox => { - let trak = TrakBox::read_box(reader, 0, s as u32).unwrap(); + let trak = TrakBox::read_box(reader, s as u32).unwrap(); moov.traks.push(trak); } BoxType::UdtaBox => { @@ -385,14 +356,11 @@ impl ReadBox<&mut BufReader> for MoovBox { } impl ReadBox<&mut BufReader> for MvhdBox { - fn read_box(reader: &mut BufReader, _offset: u64, size: u32) -> Result { + fn read_box(reader: &mut BufReader, size: u32) -> Result { let current = reader.seek(SeekFrom::Current(0)).unwrap(); // Current cursor position. - let version = reader.read_u8().unwrap(); - let flags_a = reader.read_u8().unwrap(); - let flags_b = reader.read_u8().unwrap(); - let flags_c = reader.read_u8().unwrap(); - let flags = u32::from(flags_a) << 16 | u32::from(flags_b) << 8 | u32::from(flags_c); + read_box_header_ext!(reader, version, flags); + let creation_time = reader.read_u32::().unwrap(); let modification_time = reader.read_u32::().unwrap(); let timescale = reader.read_u32::().unwrap(); @@ -413,7 +381,7 @@ impl ReadBox<&mut BufReader> for MvhdBox { } impl ReadBox<&mut BufReader> for TrakBox { - fn read_box(reader: &mut BufReader, _offset: u64, size: u32) -> Result { + fn read_box(reader: &mut BufReader, size: u32) -> Result { let current = reader.seek(SeekFrom::Current(0)).unwrap(); // Current cursor position. let mut trak = TrakBox::new(); @@ -421,19 +389,19 @@ impl ReadBox<&mut BufReader> for TrakBox { while start < size as u64 { // Get box header. let header = read_box_header(reader, start).unwrap(); - let BoxHeader{ name, size: s, offset: _ } = header; + let BoxHeader{ name, size: s } = header; match name { BoxType::TkhdBox => { - let tkhd = TkhdBox::read_box(reader, 0, s as u32).unwrap(); + let tkhd = TkhdBox::read_box(reader, s as u32).unwrap(); trak.tkhd = Some(tkhd); } BoxType::EdtsBox => { - let edts = EdtsBox::read_box(reader, 0, s as u32).unwrap(); + let edts = EdtsBox::read_box(reader, s as u32).unwrap(); trak.edts = Some(edts); } BoxType::MdiaBox => { - let mdia = MdiaBox::read_box(reader, 0, s as u32).unwrap(); + let mdia = MdiaBox::read_box(reader, s as u32).unwrap(); trak.mdia = Some(mdia); } _ => break @@ -446,14 +414,11 @@ impl ReadBox<&mut BufReader> for TrakBox { } impl ReadBox<&mut BufReader> for TkhdBox { - fn read_box(reader: &mut BufReader, _offset: u64, size: u32) -> Result { + fn read_box(reader: &mut BufReader, size: u32) -> Result { let current = reader.seek(SeekFrom::Current(0)).unwrap(); // Current cursor position. - let version = reader.read_u8().unwrap(); - let flags_a = reader.read_u8().unwrap(); - let flags_b = reader.read_u8().unwrap(); - let flags_c = reader.read_u8().unwrap(); - let flags = u32::from(flags_a) << 16 | u32::from(flags_b) << 8 | u32::from(flags_c); + read_box_header_ext!(reader, version, flags); + let creation_time = reader.read_u32::().unwrap(); let modification_time = reader.read_u32::().unwrap(); let track_id = reader.read_u32::().unwrap(); @@ -498,7 +463,7 @@ impl ReadBox<&mut BufReader> for TkhdBox { } impl ReadBox<&mut BufReader> for EdtsBox { - fn read_box(reader: &mut BufReader, _offset: u64, size: u32) -> Result { + fn read_box(reader: &mut BufReader, size: u32) -> Result { let current = reader.seek(SeekFrom::Current(0)).unwrap(); // Current cursor position. let mut edts = EdtsBox::new(); @@ -506,11 +471,11 @@ impl ReadBox<&mut BufReader> for EdtsBox { while start < size as u64 { // Get box header. let header = read_box_header(reader, start).unwrap(); - let BoxHeader{ name, size: s, offset: _ } = header; + let BoxHeader{ name, size: s } = header; match name { BoxType::ElstBox => { - let elst = ElstBox::read_box(reader, 0, s as u32).unwrap(); + let elst = ElstBox::read_box(reader, s as u32).unwrap(); edts.elst = Some(elst); } _ => break @@ -523,7 +488,7 @@ impl ReadBox<&mut BufReader> for EdtsBox { } impl ReadBox<&mut BufReader> for ElstBox { - fn read_box(reader: &mut BufReader, _offset: u64, size: u32) -> Result { + fn read_box(reader: &mut BufReader, size: u32) -> Result { let current = reader.seek(SeekFrom::Current(0)).unwrap(); // Current cursor position. let version = reader.read_u32::().unwrap(); @@ -551,7 +516,7 @@ impl ReadBox<&mut BufReader> for ElstBox { } impl ReadBox<&mut BufReader> for MdiaBox { - fn read_box(reader: &mut BufReader, _offset: u64, size: u32) -> Result { + fn read_box(reader: &mut BufReader, size: u32) -> Result { let current = reader.seek(SeekFrom::Current(0)).unwrap(); // Current cursor position. let mut mdia = MdiaBox::new(); @@ -559,19 +524,19 @@ impl ReadBox<&mut BufReader> for MdiaBox { while start < size as u64 { // Get box header. let header = read_box_header(reader, start).unwrap(); - let BoxHeader{ name, size: s, offset: _ } = header; + let BoxHeader{ name, size: s } = header; match name { BoxType::MdhdBox => { - let mdhd = MdhdBox::read_box(reader, 0, s as u32).unwrap(); + let mdhd = MdhdBox::read_box(reader, s as u32).unwrap(); mdia.mdhd = Some(mdhd); } BoxType::HdlrBox => { - let hdlr = HdlrBox::read_box(reader, 0, s as u32).unwrap(); + let hdlr = HdlrBox::read_box(reader, s as u32).unwrap(); mdia.hdlr = Some(hdlr); } BoxType::MinfBox => { - let minf = MinfBox::read_box(reader, 0, s as u32).unwrap(); + let minf = MinfBox::read_box(reader, s as u32).unwrap(); mdia.minf = Some(minf); } _ => break @@ -584,14 +549,11 @@ impl ReadBox<&mut BufReader> for MdiaBox { } impl ReadBox<&mut BufReader> for MdhdBox { - fn read_box(reader: &mut BufReader, _offset: u64, size: u32) -> Result { + fn read_box(reader: &mut BufReader, size: u32) -> Result { let current = reader.seek(SeekFrom::Current(0)).unwrap(); // Current cursor position. - let version = reader.read_u8().unwrap(); - let flags_a = reader.read_u8().unwrap(); - let flags_b = reader.read_u8().unwrap(); - let flags_c = reader.read_u8().unwrap(); - let flags = u32::from(flags_a) << 16 | u32::from(flags_b) << 8 | u32::from(flags_c); + read_box_header_ext!(reader, version, flags); + let creation_time = reader.read_u32::().unwrap(); let modification_time = reader.read_u32::().unwrap(); let timescale = reader.read_u32::().unwrap(); @@ -629,14 +591,11 @@ fn get_language_string(language: u16) -> String { } impl ReadBox<&mut BufReader> for HdlrBox { - fn read_box(reader: &mut BufReader, _offset: u64, size: u32) -> Result { + fn read_box(reader: &mut BufReader, size: u32) -> Result { let current = reader.seek(SeekFrom::Current(0)).unwrap(); // Current cursor position. - let version = reader.read_u8().unwrap(); - let flags_a = reader.read_u8().unwrap(); - let flags_b = reader.read_u8().unwrap(); - let flags_c = reader.read_u8().unwrap(); - let flags = u32::from(flags_a) << 16 | u32::from(flags_b) << 8 | u32::from(flags_c); + read_box_header_ext!(reader, version, flags); + reader.read_u32::().unwrap(); // skip. let handler = reader.read_u32::().unwrap(); @@ -661,7 +620,7 @@ impl ReadBox<&mut BufReader> for HdlrBox { } impl ReadBox<&mut BufReader> for MinfBox { - fn read_box(reader: &mut BufReader, _offset: u64, size: u32) -> Result { + fn read_box(reader: &mut BufReader, size: u32) -> Result { let current = reader.seek(SeekFrom::Current(0)).unwrap(); // Current cursor position. let mut minf = MinfBox::new(); @@ -669,11 +628,11 @@ impl ReadBox<&mut BufReader> for MinfBox { while start < size as u64 { // Get box header. let header = read_box_header(reader, start).unwrap(); - let BoxHeader{ name, size: s, offset: _ } = header; + let BoxHeader{ name, size: s } = header; match name { BoxType::VmhdBox => { - let vmhd = VmhdBox::read_box(reader, 0, s as u32).unwrap(); + let vmhd = VmhdBox::read_box(reader, s as u32).unwrap(); minf.vmhd = Some(vmhd); } BoxType::SmhdBox => { @@ -683,7 +642,7 @@ impl ReadBox<&mut BufReader> for MinfBox { start = (s as u32 - HEADER_SIZE) as u64; } BoxType::StblBox => { - let stbl = StblBox::read_box(reader, 0, s as u32).unwrap(); + let stbl = StblBox::read_box(reader, s as u32).unwrap(); minf.stbl = Some(stbl); } _ => break @@ -696,14 +655,11 @@ impl ReadBox<&mut BufReader> for MinfBox { } impl ReadBox<&mut BufReader> for VmhdBox { - fn read_box(reader: &mut BufReader, _offset: u64, size: u32) -> Result { + fn read_box(reader: &mut BufReader, size: u32) -> Result { let current = reader.seek(SeekFrom::Current(0)).unwrap(); // Current cursor position. - let version = reader.read_u8().unwrap(); - let flags_a = reader.read_u8().unwrap(); - let flags_b = reader.read_u8().unwrap(); - let flags_c = reader.read_u8().unwrap(); - let flags = u32::from(flags_a) << 16 | u32::from(flags_b) << 8 | u32::from(flags_c); + read_box_header_ext!(reader, version, flags); + let graphics_mode = reader.read_u16::().unwrap(); let op_color = reader.read_u16::().unwrap(); skip(reader, current, size); @@ -718,22 +674,22 @@ impl ReadBox<&mut BufReader> for VmhdBox { } impl ReadBox<&mut BufReader> for StblBox { - fn read_box(reader: &mut BufReader, _offset: u64, size: u32) -> Result { + fn read_box(reader: &mut BufReader, size: u32) -> Result { let mut stbl = StblBox::new(); let start = 0u64; while start < size as u64 { // Get box header. let header = read_box_header(reader, start).unwrap(); - let BoxHeader{ name, size: s, offset: _ } = header; + let BoxHeader{ name, size: s } = header; match name { BoxType::StsdBox => { - let stsd = StsdBox::read_box(reader, 0, s as u32).unwrap(); + let stsd = StsdBox::read_box(reader, s as u32).unwrap(); stbl.stsd = Some(stsd); } BoxType::SttsBox => { - let stts = SttsBox::read_box(reader, 0, s as u32).unwrap(); + let stts = SttsBox::read_box(reader, s as u32).unwrap(); stbl.stts = Some(stts); } _ => break @@ -744,14 +700,11 @@ impl ReadBox<&mut BufReader> for StblBox { } impl ReadBox<&mut BufReader> for SttsBox { - fn read_box(reader: &mut BufReader, _offset: u64, size: u32) -> Result { + fn read_box(reader: &mut BufReader, size: u32) -> Result { let current = reader.seek(SeekFrom::Current(0)).unwrap(); // Current cursor position. - let version = reader.read_u8().unwrap(); - let flags_a = reader.read_u8().unwrap(); - let flags_b = reader.read_u8().unwrap(); - let flags_c = reader.read_u8().unwrap(); - let flags = u32::from(flags_a) << 16 | u32::from(flags_b) << 8 | u32::from(flags_c); + read_box_header_ext!(reader, version, flags); + let entry_count = reader.read_u32::().unwrap(); let mut sample_counts = Vec::new(); let mut sample_deltas = Vec::new(); @@ -775,21 +728,18 @@ impl ReadBox<&mut BufReader> for SttsBox { } impl ReadBox<&mut BufReader> for StsdBox { - fn read_box(reader: &mut BufReader, _offset: u64, size: u32) -> Result { + fn read_box(reader: &mut BufReader, size: u32) -> Result { let current = reader.seek(SeekFrom::Current(0)).unwrap(); // Current cursor position. - let version = reader.read_u8().unwrap(); - let flags_a = reader.read_u8().unwrap(); - let flags_b = reader.read_u8().unwrap(); - let flags_c = reader.read_u8().unwrap(); - let flags = u32::from(flags_a) << 16 | u32::from(flags_b) << 8 | u32::from(flags_c); + read_box_header_ext!(reader, version, flags); + reader.read_u32::().unwrap(); // skip. let mut start = 0u64; while start < size as u64 { // Get box header. let header = read_box_header(reader, start).unwrap(); - let BoxHeader{ name, size: s, offset: _ } = header; + let BoxHeader{ name, size: s } = header; match name { BoxType::Avc1Box => { diff --git a/src/lib.rs b/src/lib.rs index 2a46de6..9af5436 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -40,7 +40,6 @@ impl BMFF { struct BoxHeader { name: BoxType, size: u64, - offset: u64, } pub fn read_mp4(f: File) -> Result { @@ -62,12 +61,12 @@ fn read_boxes(f: File) -> Result { // Get box header. let header = read_box_header(&mut reader, start).unwrap(); - let BoxHeader{ name, size, offset: _ } = header; + let BoxHeader{ name, size } = header; // Match and parse the atom boxes. match name { BoxType::FtypBox => { - let ftyp = FtypBox::read_box(&mut reader, 0, size as u32).unwrap(); + let ftyp = FtypBox::read_box(&mut reader, size as u32).unwrap(); bmff.ftyp = ftyp; } BoxType::FreeBox => { @@ -77,7 +76,7 @@ fn read_boxes(f: File) -> Result { start = (size as u32 - HEADER_SIZE) as u64; } BoxType::MoovBox => { - let moov = MoovBox::read_box(&mut reader, 0, size as u32).unwrap(); + let moov = MoovBox::read_box(&mut reader, size as u32).unwrap(); bmff.moov = Some(moov); } BoxType::MoofBox => { @@ -97,6 +96,7 @@ fn read_boxes(f: File) -> Result { Ok(bmff) } +// TODO: if size is 0, then this box is the last one in the file fn read_box_header(reader: &mut BufReader, start: u64) -> Result { // Seek to offset. let _r = reader.seek(SeekFrom::Current(start as i64)); @@ -108,24 +108,27 @@ fn read_box_header(reader: &mut BufReader, start: u64) -> Res // Get size. let s = buf[0..4].try_into().unwrap(); let size = u32::from_be_bytes(s); - - // TODO: Err if size is 0. - // if size == 0 { break; } // Get box type string. let t = buf[4..8].try_into().unwrap(); let typ = u32::from_be_bytes(t); - let offset = match size { - 1 => 4 + 4 + 8, - _ => 4 + 4, - }; + // Get largesize if size is 1 + if size == 1 { + reader.read(&mut buf).unwrap(); + let s = buf.try_into().unwrap(); + let largesize = u64::from_be_bytes(s); - Ok(BoxHeader { - name: BoxType::from(typ), - size: size as u64, - offset: offset as u64, - }) + Ok(BoxHeader { + name: BoxType::from(typ), + size: largesize, + }) + } else { + Ok(BoxHeader { + name: BoxType::from(typ), + size: size as u64, + }) + } }