Skip to content
Closed
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
4 changes: 2 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,15 @@ license = "MIT"
include = ["src", "benches", "Cargo.toml", "README", "LICENSE"]

[dependencies]
thiserror = "^1.0"
thiserror = "2.0"
byteorder = "1"
bytes = "1.1.0"
num-rational = { version = "0.4.0", features = ["serde"] }
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"

[dev-dependencies]
criterion = "0.3"
criterion = "0.7"

[[bench]]
name = "bench_main"
Expand Down
94 changes: 94 additions & 0 deletions examples/fragdump.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
use std::io::prelude::*;
use std::io;
use std::io::BufReader;
use std::env;
use std::path::Path;
use std::fs::File;
use std::io::SeekFrom;

use mp4::Result;
use mp4::mp4box::*;

fn main() {
let args: Vec<String> = env::args().collect();

if args.len() < 3 {
println!("Usage: fragdump <filename_in> <filename_out>");
std::process::exit(1);
}

if let Err(err) = dump(&args[1], &args[2]) {
let _ = writeln!(io::stderr(), "{}", err);
}
}

fn dump<P: AsRef<Path>>(filename: &P, out: &P) -> Result<()> {
let f = File::open(filename)?;
let size = f.metadata()?.len();
let mut reader = BufReader::new(f);

let start = reader.seek(SeekFrom::Current(0))?;

let mut styp = None;
let mut sidx = None;
let mut moof = None;
let mut mdat = None;

let mut current = start;
while current < size {
let header = BoxHeader::read(&mut reader)?;
let BoxHeader { name, size: s } = header;

match name {
BoxType::SidxBox => {
println!(" sidx in len {}", s);
sidx = Some(SidxBox::read_box(&mut reader, s)?);
}
BoxType::MoofBox => {
println!(" moof in len {}", s);
moof = Some(MoofBox::read_box(&mut reader, s)?);
}
BoxType::MdatBox => {
println!(" mdat in len {}", s);
let mut vec_mdat = vec![0; (s - 8) as usize];
reader.read_exact(&mut vec_mdat)?;
mdat = Some(vec_mdat);
}
BoxType::StypBox => {
println!(" styp in len {}", s);
styp = Some(FtypBox::read_box(&mut reader, s)?);
}
b => {
println!("WARN: got unexpected box {:?}", b);
skip_box(&mut reader, s)?;
}
}

current = reader.seek(SeekFrom::Current(0))?;
}

let styp = styp.unwrap();
let sidx = sidx.unwrap();
let mut moof = moof.unwrap();
let tfdt = moof.trafs[0].tfdt.as_mut().unwrap();
tfdt.base_media_decode_time = sidx.earliest_presentation_time + 5;
let mdat = mdat.unwrap();

let mut vec = File::create(out)?;
// let mut vec = Vec::new();
let t = styp.write_box(&mut vec)?;
// println!(" styp out len {} vs {}", t, vec.len());
// let mut vec = Vec::new();
let t = sidx.write_box(&mut vec)?;
// println!(" sidx out len {} vs {}", t, vec.len());
// let mut vec = Vec::new();
let t = moof.write_box(&mut vec)?;
// println!(" moof out len {} vs {}", t, vec.len());
let mdat_hdr = BoxHeader::new(BoxType::MdatBox, mdat.len() as u64 + 8);
// let mut vec = Vec::new();
let t = mdat_hdr.write(&mut vec)?;
let t = t + vec.write(&mdat)? as u64;
// println!(" mdat out len {} vs {}", t, vec.len());

Ok(())
}
7 changes: 5 additions & 2 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -76,8 +76,11 @@ pub type Result<T> = std::result::Result<T, Error>;
mod types;
pub use types::*;

mod mp4box;
pub use mp4box::*;
// TODO
// mod mp4box;
// pub use mp4box::*;
pub mod mp4box;
pub use mp4box::Mp4Box;

mod track;
pub use track::{Mp4Track, TrackConfig};
Expand Down
2 changes: 1 addition & 1 deletion src/mp4box/dinf.rs
Original file line number Diff line number Diff line change
Expand Up @@ -232,7 +232,7 @@ impl UrlBox {
let mut size = HEADER_SIZE + HEADER_EXT_SIZE;

if !self.location.is_empty() {
size += self.location.bytes().len() as u64 + 1;
size += self.location.len() as u64 + 1;
}

size
Expand Down
5 changes: 4 additions & 1 deletion src/mp4box/ftyp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,12 @@ pub struct FtypBox {
pub major_brand: FourCC,
pub minor_version: u32,
pub compatible_brands: Vec<FourCC>,
pub box_type: BoxType,
}

impl FtypBox {
pub fn get_type(&self) -> BoxType {
BoxType::FtypBox
self.box_type
}

pub fn get_size(&self) -> u64 {
Expand Down Expand Up @@ -72,6 +73,7 @@ impl<R: Read + Seek> ReadBox<&mut R> for FtypBox {
major_brand: From::from(major),
minor_version: minor,
compatible_brands: brands,
box_type: BoxType::FtypBox,
})
}
}
Expand Down Expand Up @@ -107,6 +109,7 @@ mod tests {
str::parse("avc1").unwrap(),
str::parse("mp41").unwrap(),
],
box_type: BoxType::FtypBox,
};
let mut buf = Vec::new();
src_box.write_box(&mut buf).unwrap();
Expand Down
6 changes: 3 additions & 3 deletions src/mp4box/ilst.rs
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,7 @@ impl<R: Read + Seek> ReadBox<&mut R> for IlstItemBox {
}

impl<'a> Metadata<'a> for IlstBox {
fn title(&self) -> Option<Cow<str>> {
fn title(&'_ self) -> Option<Cow<'_, str>> {
self.items.get(&MetadataKey::Title).map(item_to_str)
}

Expand All @@ -178,7 +178,7 @@ impl<'a> Metadata<'a> for IlstBox {
self.items.get(&MetadataKey::Poster).map(item_to_bytes)
}

fn summary(&self) -> Option<Cow<str>> {
fn summary(&'_ self) -> Option<Cow<'_, str>> {
self.items.get(&MetadataKey::Summary).map(item_to_str)
}
}
Expand All @@ -187,7 +187,7 @@ fn item_to_bytes(item: &IlstItemBox) -> &[u8] {
&item.data.data
}

fn item_to_str(item: &IlstItemBox) -> Cow<str> {
fn item_to_str(item: &'_ IlstItemBox) -> Cow<'_, str> {
String::from_utf8_lossy(&item.data.data)
}

Expand Down
83 changes: 83 additions & 0 deletions src/mp4box/mdat.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
use crate::mp4box::*;

#[derive(Debug, Clone, PartialEq, Default, serde::Serialize)]
pub struct MdatBox {
pub data: Vec<u8>,
}

impl Mp4Box for MdatBox {
fn box_type(&self) -> BoxType {
BoxType::MdatBox
}

fn box_size(&self) -> u64 {
HEADER_SIZE + self.data.len() as u64
}

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

fn summary(&self) -> Result<String> {
Ok(String::new())
}
}

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

let mut data = vec![0; size as usize - 8];
reader.read_exact(&mut data)?;

skip_bytes_to(reader, start + size)?;

Ok(Self { data })
}
}

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

writer.write_all(&self.data)?;

Ok(size)
}
}

#[derive(Debug, Clone, PartialEq, Default, serde::Serialize)]
pub struct AnyBox {
pub box_type: BoxType,
pub data: Vec<u8>,
}

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

fn box_size(&self) -> u64 {
HEADER_SIZE + self.data.len() as u64
}

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

fn summary(&self) -> Result<String> {
Ok(String::new())
}
}

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

writer.write_all(&self.data)?;

Ok(size)
}
}
19 changes: 17 additions & 2 deletions src/mp4box/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ pub(crate) mod ftyp;
pub(crate) mod hdlr;
pub(crate) mod hev1;
pub(crate) mod ilst;
pub mod mdat;
pub(crate) mod mdhd;
pub(crate) mod mdia;
pub(crate) mod mehd;
Expand All @@ -85,6 +86,7 @@ pub(crate) mod moov;
pub(crate) mod mp4a;
pub(crate) mod mvex;
pub(crate) mod mvhd;
pub mod sidx;
pub(crate) mod smhd;
pub(crate) mod stbl;
pub(crate) mod stco;
Expand Down Expand Up @@ -115,9 +117,12 @@ pub use edts::EdtsBox;
pub use elst::ElstBox;
pub use emsg::EmsgBox;
pub use ftyp::FtypBox;
// TODO
pub use hdlr::HdlrBox;
pub use hev1::Hev1Box;
pub use ilst::IlstBox;
pub use mdat::AnyBox;
pub use mdat::MdatBox;
pub use mdhd::MdhdBox;
pub use mdia::MdiaBox;
pub use mehd::MehdBox;
Expand All @@ -129,6 +134,7 @@ pub use moov::MoovBox;
pub use mp4a::Mp4aBox;
pub use mvex::MvexBox;
pub use mvhd::MvhdBox;
pub use sidx::SidxBox;
pub use smhd::SmhdBox;
pub use stbl::StblBox;
pub use stco::StcoBox;
Expand Down Expand Up @@ -156,12 +162,18 @@ pub const HEADER_EXT_SIZE: u64 = 4;

macro_rules! boxtype {
($( $name:ident => $value:expr ),*) => {
#[derive(Clone, Copy, PartialEq, Eq)]
#[derive(Clone, Copy, PartialEq, Eq, serde::Serialize)]
pub enum BoxType {
$( $name, )*
UnknownBox(u32),
}

impl Default for BoxType {
fn default() -> BoxType {
BoxType::FreeBox
}
}

impl From<u32> for BoxType {
fn from(t: u32) -> BoxType {
match t {
Expand Down Expand Up @@ -231,14 +243,17 @@ boxtype! {
Tx3gBox => 0x74783367,
VpccBox => 0x76706343,
Vp09Box => 0x76703039,
// TODO
DataBox => 0x64617461,
IlstBox => 0x696c7374,
NameBox => 0xa96e616d,
DayBox => 0xa9646179,
CovrBox => 0x636f7672,
DescBox => 0x64657363,
WideBox => 0x77696465,
WaveBox => 0x77617665
WaveBox => 0x77617665,
SidxBox => 0x73696478,
StypBox => 0x73747970
}

pub trait Mp4Box: Sized {
Expand Down
2 changes: 1 addition & 1 deletion src/mp4box/moof.rs
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,6 @@ impl<W: Write> WriteBox<&mut W> for MoofBox {
for traf in self.trafs.iter() {
traf.write_box(writer)?;
}
Ok(0)
Ok(size)
}
}
1 change: 0 additions & 1 deletion src/mp4box/moov.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
use serde::Serialize;
use std::io::{Read, Seek, Write};

use crate::meta::MetaBox;
use crate::mp4box::*;
use crate::mp4box::{mvex::MvexBox, mvhd::MvhdBox, trak::TrakBox, udta::UdtaBox};

Expand Down
2 changes: 1 addition & 1 deletion src/mp4box/mp4a.rs
Original file line number Diff line number Diff line change
Expand Up @@ -285,7 +285,7 @@ fn size_of_length(size: u32) -> u32 {
fn write_desc<W: Write>(writer: &mut W, tag: u8, size: u32) -> Result<u64> {
writer.write_u8(tag)?;

if size as u64 > std::u32::MAX as u64 {
if size as u64 > u32::MAX as u64 {
return Err(Error::InvalidData("invalid descriptor length range"));
}

Expand Down
Loading
Loading