Skip to content

Commit

Permalink
Feature/tfdt box (alfg#90)
Browse files Browse the repository at this point in the history
* Add Tfdt box parsing

* Derive Default for TfdtBox

* Derive Eq for TfdtBox
  • Loading branch information
jensenn authored Jan 12, 2023
1 parent 2b5ea45 commit d7d2c69
Show file tree
Hide file tree
Showing 3 changed files with 147 additions and 1 deletion.
3 changes: 3 additions & 0 deletions src/mp4box/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@
//! mfhd
//! traf
//! tfhd
//! tfdt
//! trun
//! mdat
//! free
Expand Down Expand Up @@ -92,6 +93,7 @@ pub(crate) mod stsd;
pub(crate) mod stss;
pub(crate) mod stsz;
pub(crate) mod stts;
pub(crate) mod tfdt;
pub(crate) mod tfhd;
pub(crate) mod tkhd;
pub(crate) mod traf;
Expand Down Expand Up @@ -155,6 +157,7 @@ boxtype! {
MoofBox => 0x6d6f6f66,
TkhdBox => 0x746b6864,
TfhdBox => 0x74666864,
TfdtBox => 0x74666474,
EdtsBox => 0x65647473,
MdiaBox => 0x6d646961,
ElstBox => 0x656c7374,
Expand Down
137 changes: 137 additions & 0 deletions src/mp4box/tfdt.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
use byteorder::{BigEndian, ReadBytesExt, WriteBytesExt};
use serde::Serialize;
use std::io::{Read, Seek, Write};

use crate::mp4box::*;

#[derive(Debug, Clone, PartialEq, Eq, Default, Serialize)]
pub struct TfdtBox {
pub version: u8,
pub flags: u32,
pub base_media_decode_time: u64,
}

impl TfdtBox {
pub fn get_type(&self) -> BoxType {
BoxType::TfdtBox
}

pub fn get_size(&self) -> u64 {
let mut sum = HEADER_SIZE + HEADER_EXT_SIZE;
if self.version == 1 {
sum += 8;
} else {
sum += 4;
}
sum
}
}

impl Mp4Box for TfdtBox {
fn box_type(&self) -> BoxType {
self.get_type()
}

fn box_size(&self) -> u64 {
self.get_size()
}

fn to_json(&self) -> Result<String> {
Ok(serde_json::to_string(&self).unwrap())
}

fn summary(&self) -> Result<String> {
let s = format!("base_media_decode_time={}", self.base_media_decode_time);
Ok(s)
}
}

impl<R: Read + Seek> ReadBox<&mut R> for TfdtBox {
fn read_box(reader: &mut R, size: u64) -> Result<Self> {
let start = box_start(reader)?;

let (version, flags) = read_box_header_ext(reader)?;

let base_media_decode_time = if version == 1 {
reader.read_u64::<BigEndian>()?
} else if version == 0 {
reader.read_u32::<BigEndian>()? as u64
} else {
return Err(Error::InvalidData("version must be 0 or 1"));
};

skip_bytes_to(reader, start + size)?;

Ok(TfdtBox {
version,
flags,
base_media_decode_time,
})
}
}

impl<W: Write> WriteBox<&mut W> for TfdtBox {
fn write_box(&self, writer: &mut W) -> Result<u64> {
let size = self.box_size();
BoxHeader::new(self.box_type(), size).write(writer)?;

write_box_header_ext(writer, self.version, self.flags)?;

if self.version == 1 {
writer.write_u64::<BigEndian>(self.base_media_decode_time)?;
} else if self.version == 0 {
writer.write_u32::<BigEndian>(self.base_media_decode_time as u32)?;
} else {
return Err(Error::InvalidData("version must be 0 or 1"));
}

Ok(size)
}
}

#[cfg(test)]
mod tests {
use super::*;
use crate::mp4box::BoxHeader;
use std::io::Cursor;

#[test]
fn test_tfdt32() {
let src_box = TfdtBox {
version: 0,
flags: 0,
base_media_decode_time: 0,
};
let mut buf = Vec::new();
src_box.write_box(&mut buf).unwrap();
assert_eq!(buf.len(), src_box.box_size() as usize);

let mut reader = Cursor::new(&buf);
let header = BoxHeader::read(&mut reader).unwrap();
assert_eq!(header.name, BoxType::TfdtBox);
assert_eq!(src_box.box_size(), header.size);

let dst_box = TfdtBox::read_box(&mut reader, header.size).unwrap();
assert_eq!(src_box, dst_box);
}

#[test]
fn test_tfdt64() {
let src_box = TfdtBox {
version: 1,
flags: 0,
base_media_decode_time: 0,
};
let mut buf = Vec::new();
src_box.write_box(&mut buf).unwrap();
assert_eq!(buf.len(), src_box.box_size() as usize);

let mut reader = Cursor::new(&buf);
let header = BoxHeader::read(&mut reader).unwrap();
assert_eq!(header.name, BoxType::TfdtBox);
assert_eq!(src_box.box_size(), header.size);

let dst_box = TfdtBox::read_box(&mut reader, header.size).unwrap();
assert_eq!(src_box, dst_box);
}
}
8 changes: 7 additions & 1 deletion src/mp4box/traf.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,12 @@ use serde::Serialize;
use std::io::{Read, Seek, SeekFrom, Write};

use crate::mp4box::*;
use crate::mp4box::{tfhd::TfhdBox, trun::TrunBox};
use crate::mp4box::{tfdt::TfdtBox, tfhd::TfhdBox, trun::TrunBox};

#[derive(Debug, Clone, PartialEq, Eq, Default, Serialize)]
pub struct TrafBox {
pub tfhd: TfhdBox,
pub tfdt: Option<TfdtBox>,
pub trun: Option<TrunBox>,
}

Expand Down Expand Up @@ -49,6 +50,7 @@ impl<R: Read + Seek> ReadBox<&mut R> for TrafBox {
let start = box_start(reader)?;

let mut tfhd = None;
let mut tfdt = None;
let mut trun = None;

let mut current = reader.seek(SeekFrom::Current(0))?;
Expand All @@ -62,6 +64,9 @@ impl<R: Read + Seek> ReadBox<&mut R> for TrafBox {
BoxType::TfhdBox => {
tfhd = Some(TfhdBox::read_box(reader, s)?);
}
BoxType::TfdtBox => {
tfdt = Some(TfdtBox::read_box(reader, s)?);
}
BoxType::TrunBox => {
trun = Some(TrunBox::read_box(reader, s)?);
}
Expand All @@ -82,6 +87,7 @@ impl<R: Read + Seek> ReadBox<&mut R> for TrafBox {

Ok(TrafBox {
tfhd: tfhd.unwrap(),
tfdt,
trun,
})
}
Expand Down

0 comments on commit d7d2c69

Please sign in to comment.