Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/tfdt box #90

Merged
merged 3 commits into from
Jan 12, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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