1
0
Fork 0
mirror of https://github.com/alfg/mp4-rust.git synced 2024-05-19 16:58:04 +00:00

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 <unipro.kr@gmail.com>
This commit is contained in:
Ian Jun 2020-07-26 12:11:47 +09:00 committed by GitHub
parent a4fd45b3e8
commit 1e86e4edab
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 125 additions and 172 deletions

View file

@ -6,99 +6,70 @@ use crate::{Error, read_box_header, BoxHeader, HEADER_SIZE};
pub type Result<T> = std::result::Result<T, Error>;
#[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<u32> 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<u32> for BoxType {
fn from(t: u32) -> BoxType {
match t {
$( $value => BoxType::$name, )*
_ => BoxType::UnknownBox(t),
}
}
}
impl Into<u32> for BoxType {
fn into(self) -> u32 {
match self {
$( BoxType::$name => $value, )*
BoxType::UnknownBox(t) => t,
}
}
}
}
}
impl Into<u32> 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<T>: Sized {
fn read_box(_: T, offset: u64, size: u32) -> Result<Self>;
fn read_box(_: T, size: u32) -> Result<Self>;
}
#[derive(Debug, Default)]
@ -333,7 +304,7 @@ pub struct StsdBox {
}
impl<R: Read + Seek> ReadBox<&mut BufReader<R>> for FtypBox {
fn read_box(reader: &mut BufReader<R>, _offset: u64, size: u32) -> Result<Self> {
fn read_box(reader: &mut BufReader<R>, size: u32) -> Result<Self> {
let major = reader.read_u32::<BigEndian>().unwrap();
let minor = reader.read_u32::<BigEndian>().unwrap();
if size % 4 != 0 {
@ -356,7 +327,7 @@ impl<R: Read + Seek> ReadBox<&mut BufReader<R>> for FtypBox {
}
impl<R: Read + Seek> ReadBox<&mut BufReader<R>> for MoovBox {
fn read_box(reader: &mut BufReader<R>, _offset: u64, size: u32) -> Result<Self> {
fn read_box(reader: &mut BufReader<R>, size: u32) -> Result<Self> {
let mut moov = MoovBox::new();
let mut start = 0u64;
@ -364,14 +335,14 @@ impl<R: Read + Seek> ReadBox<&mut BufReader<R>> 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<R: Read + Seek> ReadBox<&mut BufReader<R>> for MoovBox {
}
impl<R: Read + Seek> ReadBox<&mut BufReader<R>> for MvhdBox {
fn read_box(reader: &mut BufReader<R>, _offset: u64, size: u32) -> Result<Self> {
fn read_box(reader: &mut BufReader<R>, size: u32) -> Result<Self> {
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::<BigEndian>().unwrap();
let modification_time = reader.read_u32::<BigEndian>().unwrap();
let timescale = reader.read_u32::<BigEndian>().unwrap();
@ -413,7 +381,7 @@ impl<R: Read + Seek> ReadBox<&mut BufReader<R>> for MvhdBox {
}
impl<R: Read + Seek> ReadBox<&mut BufReader<R>> for TrakBox {
fn read_box(reader: &mut BufReader<R>, _offset: u64, size: u32) -> Result<Self> {
fn read_box(reader: &mut BufReader<R>, size: u32) -> Result<Self> {
let current = reader.seek(SeekFrom::Current(0)).unwrap(); // Current cursor position.
let mut trak = TrakBox::new();
@ -421,19 +389,19 @@ impl<R: Read + Seek> ReadBox<&mut BufReader<R>> 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<R: Read + Seek> ReadBox<&mut BufReader<R>> for TrakBox {
}
impl<R: Read + Seek> ReadBox<&mut BufReader<R>> for TkhdBox {
fn read_box(reader: &mut BufReader<R>, _offset: u64, size: u32) -> Result<Self> {
fn read_box(reader: &mut BufReader<R>, size: u32) -> Result<Self> {
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::<BigEndian>().unwrap();
let modification_time = reader.read_u32::<BigEndian>().unwrap();
let track_id = reader.read_u32::<BigEndian>().unwrap();
@ -498,7 +463,7 @@ impl<R: Read + Seek> ReadBox<&mut BufReader<R>> for TkhdBox {
}
impl<R: Read + Seek> ReadBox<&mut BufReader<R>> for EdtsBox {
fn read_box(reader: &mut BufReader<R>, _offset: u64, size: u32) -> Result<Self> {
fn read_box(reader: &mut BufReader<R>, size: u32) -> Result<Self> {
let current = reader.seek(SeekFrom::Current(0)).unwrap(); // Current cursor position.
let mut edts = EdtsBox::new();
@ -506,11 +471,11 @@ impl<R: Read + Seek> ReadBox<&mut BufReader<R>> 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<R: Read + Seek> ReadBox<&mut BufReader<R>> for EdtsBox {
}
impl<R: Read + Seek> ReadBox<&mut BufReader<R>> for ElstBox {
fn read_box(reader: &mut BufReader<R>, _offset: u64, size: u32) -> Result<Self> {
fn read_box(reader: &mut BufReader<R>, size: u32) -> Result<Self> {
let current = reader.seek(SeekFrom::Current(0)).unwrap(); // Current cursor position.
let version = reader.read_u32::<BigEndian>().unwrap();
@ -551,7 +516,7 @@ impl<R: Read + Seek> ReadBox<&mut BufReader<R>> for ElstBox {
}
impl<R: Read + Seek> ReadBox<&mut BufReader<R>> for MdiaBox {
fn read_box(reader: &mut BufReader<R>, _offset: u64, size: u32) -> Result<Self> {
fn read_box(reader: &mut BufReader<R>, size: u32) -> Result<Self> {
let current = reader.seek(SeekFrom::Current(0)).unwrap(); // Current cursor position.
let mut mdia = MdiaBox::new();
@ -559,19 +524,19 @@ impl<R: Read + Seek> ReadBox<&mut BufReader<R>> 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<R: Read + Seek> ReadBox<&mut BufReader<R>> for MdiaBox {
}
impl<R: Read + Seek> ReadBox<&mut BufReader<R>> for MdhdBox {
fn read_box(reader: &mut BufReader<R>, _offset: u64, size: u32) -> Result<Self> {
fn read_box(reader: &mut BufReader<R>, size: u32) -> Result<Self> {
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::<BigEndian>().unwrap();
let modification_time = reader.read_u32::<BigEndian>().unwrap();
let timescale = reader.read_u32::<BigEndian>().unwrap();
@ -629,14 +591,11 @@ fn get_language_string(language: u16) -> String {
}
impl<R: Read + Seek> ReadBox<&mut BufReader<R>> for HdlrBox {
fn read_box(reader: &mut BufReader<R>, _offset: u64, size: u32) -> Result<Self> {
fn read_box(reader: &mut BufReader<R>, size: u32) -> Result<Self> {
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::<BigEndian>().unwrap(); // skip.
let handler = reader.read_u32::<BigEndian>().unwrap();
@ -661,7 +620,7 @@ impl<R: Read + Seek> ReadBox<&mut BufReader<R>> for HdlrBox {
}
impl<R: Read + Seek> ReadBox<&mut BufReader<R>> for MinfBox {
fn read_box(reader: &mut BufReader<R>, _offset: u64, size: u32) -> Result<Self> {
fn read_box(reader: &mut BufReader<R>, size: u32) -> Result<Self> {
let current = reader.seek(SeekFrom::Current(0)).unwrap(); // Current cursor position.
let mut minf = MinfBox::new();
@ -669,11 +628,11 @@ impl<R: Read + Seek> ReadBox<&mut BufReader<R>> 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<R: Read + Seek> ReadBox<&mut BufReader<R>> 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<R: Read + Seek> ReadBox<&mut BufReader<R>> for MinfBox {
}
impl<R: Read + Seek> ReadBox<&mut BufReader<R>> for VmhdBox {
fn read_box(reader: &mut BufReader<R>, _offset: u64, size: u32) -> Result<Self> {
fn read_box(reader: &mut BufReader<R>, size: u32) -> Result<Self> {
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::<BigEndian>().unwrap();
let op_color = reader.read_u16::<BigEndian>().unwrap();
skip(reader, current, size);
@ -718,22 +674,22 @@ impl<R: Read + Seek> ReadBox<&mut BufReader<R>> for VmhdBox {
}
impl<R: Read + Seek> ReadBox<&mut BufReader<R>> for StblBox {
fn read_box(reader: &mut BufReader<R>, _offset: u64, size: u32) -> Result<Self> {
fn read_box(reader: &mut BufReader<R>, size: u32) -> Result<Self> {
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<R: Read + Seek> ReadBox<&mut BufReader<R>> for StblBox {
}
impl<R: Read + Seek> ReadBox<&mut BufReader<R>> for SttsBox {
fn read_box(reader: &mut BufReader<R>, _offset: u64, size: u32) -> Result<Self> {
fn read_box(reader: &mut BufReader<R>, size: u32) -> Result<Self> {
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::<BigEndian>().unwrap();
let mut sample_counts = Vec::new();
let mut sample_deltas = Vec::new();
@ -775,21 +728,18 @@ impl<R: Read + Seek> ReadBox<&mut BufReader<R>> for SttsBox {
}
impl<R: Read + Seek> ReadBox<&mut BufReader<R>> for StsdBox {
fn read_box(reader: &mut BufReader<R>, _offset: u64, size: u32) -> Result<Self> {
fn read_box(reader: &mut BufReader<R>, size: u32) -> Result<Self> {
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::<BigEndian>().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 => {

View file

@ -40,7 +40,6 @@ impl BMFF {
struct BoxHeader {
name: BoxType,
size: u64,
offset: u64,
}
pub fn read_mp4(f: File) -> Result<BMFF> {
@ -62,12 +61,12 @@ fn read_boxes(f: File) -> Result<BMFF> {
// 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<BMFF> {
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<BMFF> {
Ok(bmff)
}
// TODO: if size is 0, then this box is the last one in the file
fn read_box_header<R: Read + Seek>(reader: &mut BufReader<R>, start: u64) -> Result<BoxHeader> {
// Seek to offset.
let _r = reader.seek(SeekFrom::Current(start as i64));
@ -108,24 +108,27 @@ fn read_box_header<R: Read + Seek>(reader: &mut BufReader<R>, 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,
})
}
}