mirror of
https://github.com/alfg/mp4-rust.git
synced 2025-02-22 07:56:16 +00:00
Merge pull request #2 from maestrolix/fix_tests
Correction of unit tests and writing an integration test
This commit is contained in:
commit
ca6760af8e
47 changed files with 296 additions and 517 deletions
|
@ -30,6 +30,8 @@ anyhow = "1.0"
|
|||
criterion = "0.5.1"
|
||||
tokio = { version = "1.37.0", features = ["full"] }
|
||||
tokio-util = "0.7.10"
|
||||
glob = "0.3.2"
|
||||
|
||||
|
||||
[[bench]]
|
||||
name = "bench_main"
|
||||
|
|
Binary file not shown.
BIN
assets/videos/cosmoc.mp4f
Normal file
BIN
assets/videos/cosmoc.mp4f
Normal file
Binary file not shown.
|
@ -42,7 +42,7 @@ async fn samples<P: AsRef<Path>>(filename: &P) -> Result<(), mp4::Error<MemorySt
|
|||
let data = mp4_file
|
||||
.read_sample_data(track_id, idx)
|
||||
.await?
|
||||
.map(|x| x.slice(0..32));
|
||||
.map(|x| x.slice(0..16));
|
||||
|
||||
println!(
|
||||
"[{} {} {}] {} - <{}> {} +{} {:?}",
|
||||
|
|
54
src/file.rs
54
src/file.rs
|
@ -6,8 +6,8 @@ use std::ops::Range;
|
|||
use tokio::io::{AsyncRead, AsyncReadExt, AsyncSeek, AsyncSeekExt, SeekFrom};
|
||||
|
||||
use crate::error::{BoxError, MemoryStorageError};
|
||||
use crate::Mp4Track;
|
||||
use crate::{BlockReader, BoxHeader, BoxType, EmsgBox, FtypBox, MoofBox, MoovBox};
|
||||
use crate::{Mp4Track, HEADER_SIZE};
|
||||
|
||||
pub trait DataStorage {
|
||||
type Error;
|
||||
|
@ -107,9 +107,12 @@ where
|
|||
let mut got_moov = false;
|
||||
let mut offset = 0u64;
|
||||
|
||||
while let Some(BoxHeader { kind, size: s }) =
|
||||
while let Some(BoxHeader { kind, size: mut s }) =
|
||||
BoxHeader::read(&mut self.reader, &mut offset).await?
|
||||
{
|
||||
if s >= HEADER_SIZE {
|
||||
s -= HEADER_SIZE; // size without header
|
||||
}
|
||||
match kind {
|
||||
BoxType::FtypBox => {
|
||||
println!("ftyp");
|
||||
|
@ -125,6 +128,7 @@ where
|
|||
|
||||
BoxType::MoovBox => {
|
||||
println!("moov");
|
||||
|
||||
if buff.len() < s as usize {
|
||||
buff.resize(s as usize, 0);
|
||||
}
|
||||
|
@ -180,6 +184,7 @@ where
|
|||
offset += s;
|
||||
}
|
||||
}
|
||||
println!("\n");
|
||||
}
|
||||
|
||||
Ok(got_moov)
|
||||
|
@ -187,7 +192,7 @@ where
|
|||
|
||||
async fn skip_box(&mut self, bt: BoxType, size: u64) -> Result<(), BoxError> {
|
||||
println!("skip {:?}", bt);
|
||||
tokio::io::copy(&mut (&mut self.reader).take(size), &mut tokio::io::empty()).await?;
|
||||
self.reader.seek(SeekFrom::Current(size as _)).await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
@ -204,6 +209,7 @@ where
|
|||
buffer: DataBlockBody::Memory(buffer.into()),
|
||||
});
|
||||
} else {
|
||||
self.skip_box(kind, size).await?;
|
||||
self.data_blocks.push(DataBlock {
|
||||
kind,
|
||||
offset,
|
||||
|
@ -273,46 +279,4 @@ where
|
|||
|
||||
Ok(None)
|
||||
}
|
||||
|
||||
// pub fn into_streams<T: AsRef<[u32]>>(
|
||||
// self,
|
||||
// tracks: T,
|
||||
// ) -> impl Iterator<
|
||||
// Item = (
|
||||
// u32,
|
||||
// impl futures::Stream<Item = Result<Mp4Sample, Error<S::Error>>> + 'a,
|
||||
// ),
|
||||
// >
|
||||
// where
|
||||
// S::Error: 'a,
|
||||
// {
|
||||
// let storage = Arc::new(self.data_storage);
|
||||
// let data_blocks = Arc::new(self.data_blocks);
|
||||
|
||||
// self.tracks
|
||||
// .into_iter()
|
||||
// .filter_map(move |(track_id, track)| {
|
||||
// if !tracks.as_ref().contains(&track_id) {
|
||||
// return None;
|
||||
// }
|
||||
|
||||
// let storage = storage.clone();
|
||||
// let data_blocks = data_blocks.clone();
|
||||
|
||||
// Some((
|
||||
// track_id,
|
||||
// async_stream::stream! {
|
||||
// for samp_offset in track.samples {
|
||||
// yield Ok(Mp4Sample {
|
||||
// start_time: samp_offset.start_time,
|
||||
// duration: samp_offset.duration,
|
||||
// rendering_offset: samp_offset.rendering_offset,
|
||||
// is_sync: samp_offset.is_sync,
|
||||
// bytes: Bytes::new(),
|
||||
// })
|
||||
// }
|
||||
// },
|
||||
// ))
|
||||
// })
|
||||
// }
|
||||
}
|
||||
|
|
67
src/lib.rs
67
src/lib.rs
|
@ -1,70 +1,3 @@
|
|||
//! `mp4` is a Rust library to read and write ISO-MP4 files.
|
||||
//!
|
||||
//! This package contains MPEG-4 specifications defined in parts:
|
||||
//! * ISO/IEC 14496-12 - ISO Base Media File Format (QuickTime, MPEG-4, etc)
|
||||
//! * ISO/IEC 14496-14 - MP4 file format
|
||||
//! * ISO/IEC 14496-17 - Streaming text format
|
||||
//!
|
||||
//! See: [mp4box] for supported MP4 atoms.
|
||||
//!
|
||||
//! ### Example
|
||||
//!
|
||||
//! ```
|
||||
//! use std::fs::File;
|
||||
//! use std::io::{BufReader};
|
||||
//! use mp4::{Result};
|
||||
//!
|
||||
//! fn main() -> Result<()> {
|
||||
//! let f = File::open("tests/samples/minimal.mp4").unwrap();
|
||||
//! let size = f.metadata()?.len();
|
||||
//! let reader = BufReader::new(f);
|
||||
//!
|
||||
//! let mp4 = mp4::Mp4Reader::read_header(reader, size)?;
|
||||
//!
|
||||
//! // Print boxes.
|
||||
//! println!("major brand: {}", mp4.header.ftyp.major_brand);
|
||||
//! println!("timescale: {}", mp4.header.moov.mvhd.timescale);
|
||||
//!
|
||||
//! // Use available methods.
|
||||
//! println!("size: {}", mp4.size());
|
||||
//!
|
||||
//! let mut compatible_brands = String::new();
|
||||
//! for brand in mp4.compatible_brands().iter() {
|
||||
//! compatible_brands.push_str(&brand.to_string());
|
||||
//! compatible_brands.push_str(",");
|
||||
//! }
|
||||
//! println!("compatible brands: {}", compatible_brands);
|
||||
//! println!("duration: {:?}", mp4.duration());
|
||||
//!
|
||||
//! // Track info.
|
||||
//! for track in mp4.tracks().values() {
|
||||
//! println!(
|
||||
//! "track: #{}({}) {} : {}",
|
||||
//! track.track_id(),
|
||||
//! track.language(),
|
||||
//! track.track_type()?,
|
||||
//! track.box_type()?,
|
||||
//! );
|
||||
//! }
|
||||
//! Ok(())
|
||||
//! }
|
||||
//! ```
|
||||
//!
|
||||
//! See [examples] for more examples.
|
||||
//!
|
||||
//! # Installation
|
||||
//!
|
||||
//! Add the following to your `Cargo.toml` file:
|
||||
//!
|
||||
//! ```toml
|
||||
//! [dependencies]
|
||||
//! mp4 = "0.7.0"
|
||||
//! ```
|
||||
//!
|
||||
//! [mp4box]: https://github.com/alfg/mp4-rust/blob/master/src/mp4box/mod.rs
|
||||
//! [examples]: https://github.com/alfg/mp4-rust/tree/master/examples
|
||||
#![doc(html_root_url = "https://docs.rs/mp4/*")]
|
||||
|
||||
pub mod error;
|
||||
use error::BoxError;
|
||||
pub use error::Error;
|
||||
|
|
|
@ -299,8 +299,8 @@ mod tests {
|
|||
use super::*;
|
||||
use crate::mp4box::BoxHeader;
|
||||
|
||||
#[test]
|
||||
fn test_avc1() {
|
||||
#[tokio::test]
|
||||
async fn test_avc1() {
|
||||
let src_box = Avc1Box {
|
||||
data_reference_index: 1,
|
||||
width: 320,
|
||||
|
@ -330,11 +330,14 @@ mod tests {
|
|||
src_box.write_box(&mut buf).unwrap();
|
||||
assert_eq!(buf.len(), src_box.box_size() as usize);
|
||||
|
||||
let header = BoxHeader::read_sync(&mut buf.as_slice()).unwrap().unwrap();
|
||||
let header = BoxHeader::read(&mut buf.as_slice(), &mut 0)
|
||||
.await
|
||||
.unwrap()
|
||||
.unwrap();
|
||||
assert_eq!(header.kind, BoxType::Avc1Box);
|
||||
assert_eq!(src_box.box_size(), header.size);
|
||||
|
||||
let dst_box = Avc1Box::read_block(&mut buf.as_slice()).unwrap();
|
||||
let dst_box = Avc1Box::read_block(&mut &buf[8..]).unwrap();
|
||||
assert_eq!(src_box, dst_box);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -67,6 +67,8 @@ impl BlockReader for Co64Box {
|
|||
|
||||
let entry_size = size_of::<u64>(); // chunk_offset
|
||||
let entry_count = reader.get_u32();
|
||||
println!("{}", reader.remaining() / entry_size);
|
||||
println!("entry_count: {}", entry_count);
|
||||
if entry_count as usize > reader.remaining() / entry_size {
|
||||
return Err(BoxError::InvalidData(
|
||||
"co64 entry_count indicates more entries than could fit in the box",
|
||||
|
@ -112,8 +114,8 @@ mod tests {
|
|||
use super::*;
|
||||
use crate::mp4box::BoxHeader;
|
||||
|
||||
#[test]
|
||||
fn test_co64() {
|
||||
#[tokio::test]
|
||||
async fn test_co64() {
|
||||
let src_box = Co64Box {
|
||||
version: 0,
|
||||
flags: 0,
|
||||
|
@ -123,11 +125,12 @@ mod tests {
|
|||
src_box.write_box(&mut buf).unwrap();
|
||||
assert_eq!(buf.len(), src_box.box_size() as usize);
|
||||
|
||||
let header = BoxHeader::read_sync(&mut buf.as_slice()).unwrap().unwrap();
|
||||
let mut reader = buf.as_slice();
|
||||
let header = BoxHeader::read(&mut reader, &mut 0).await.unwrap().unwrap();
|
||||
assert_eq!(header.kind, BoxType::Co64Box);
|
||||
assert_eq!(src_box.box_size(), header.size);
|
||||
|
||||
let dst_box = Co64Box::read_block(&mut buf.as_slice()).unwrap();
|
||||
let dst_box = Co64Box::read_block(&mut reader).unwrap();
|
||||
assert_eq!(src_box, dst_box);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -104,8 +104,8 @@ mod tests {
|
|||
use super::*;
|
||||
use crate::mp4box::BoxHeader;
|
||||
|
||||
#[test]
|
||||
fn test_ctts() {
|
||||
#[tokio::test]
|
||||
async fn test_ctts() {
|
||||
let src_box = CttsBox {
|
||||
version: 0,
|
||||
flags: 0,
|
||||
|
@ -125,7 +125,7 @@ mod tests {
|
|||
assert_eq!(buf.len(), src_box.box_size() as usize);
|
||||
|
||||
let mut reader = buf.as_slice();
|
||||
let header = BoxHeader::read_sync(&mut reader).unwrap().unwrap();
|
||||
let header = BoxHeader::read(&mut reader, &mut 0).await.unwrap().unwrap();
|
||||
assert_eq!(header.kind, BoxType::CttsBox);
|
||||
assert_eq!(src_box.box_size(), header.size);
|
||||
|
||||
|
|
|
@ -74,8 +74,8 @@ mod tests {
|
|||
use super::*;
|
||||
use crate::mp4box::BoxHeader;
|
||||
|
||||
#[test]
|
||||
fn test_data() {
|
||||
#[tokio::test]
|
||||
async fn test_data() {
|
||||
let src_box = DataBox {
|
||||
data_type: DataType::Text,
|
||||
data: b"test_data".to_vec(),
|
||||
|
@ -85,7 +85,7 @@ mod tests {
|
|||
assert_eq!(buf.len(), src_box.box_size() as usize);
|
||||
|
||||
let mut reader = buf.as_slice();
|
||||
let header = BoxHeader::read_sync(&mut reader).unwrap().unwrap();
|
||||
let header = BoxHeader::read(&mut reader, &mut 0).await.unwrap().unwrap();
|
||||
assert_eq!(header.kind, BoxType::DataBox);
|
||||
assert_eq!(src_box.box_size(), header.size);
|
||||
|
||||
|
@ -93,15 +93,15 @@ mod tests {
|
|||
assert_eq!(src_box, dst_box);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_data_empty() {
|
||||
#[tokio::test]
|
||||
async fn test_data_empty() {
|
||||
let src_box = DataBox::default();
|
||||
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 = buf.as_slice();
|
||||
let header = BoxHeader::read_sync(&mut reader).unwrap().unwrap();
|
||||
let header = BoxHeader::read(&mut reader, &mut 0).await.unwrap().unwrap();
|
||||
assert_eq!(header.kind, BoxType::DataBox);
|
||||
assert_eq!(src_box.box_size(), header.size);
|
||||
|
||||
|
|
|
@ -135,8 +135,8 @@ mod tests {
|
|||
use super::*;
|
||||
use crate::mp4box::BoxHeader;
|
||||
|
||||
#[test]
|
||||
fn test_elst32() {
|
||||
#[tokio::test]
|
||||
async fn test_elst32() {
|
||||
let src_box = ElstBox {
|
||||
version: 0,
|
||||
flags: 0,
|
||||
|
@ -152,7 +152,7 @@ mod tests {
|
|||
assert_eq!(buf.len(), src_box.box_size() as usize);
|
||||
|
||||
let mut reader = buf.as_slice();
|
||||
let header = BoxHeader::read_sync(&mut reader).unwrap().unwrap();
|
||||
let header = BoxHeader::read(&mut reader, &mut 0).await.unwrap().unwrap();
|
||||
assert_eq!(header.kind, BoxType::ElstBox);
|
||||
assert_eq!(src_box.box_size(), header.size);
|
||||
|
||||
|
@ -160,8 +160,8 @@ mod tests {
|
|||
assert_eq!(src_box, dst_box);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_elst64() {
|
||||
#[tokio::test]
|
||||
async fn test_elst64() {
|
||||
let src_box = ElstBox {
|
||||
version: 1,
|
||||
flags: 0,
|
||||
|
@ -177,7 +177,7 @@ mod tests {
|
|||
assert_eq!(buf.len(), src_box.box_size() as usize);
|
||||
|
||||
let mut reader = buf.as_slice();
|
||||
let header = BoxHeader::read_sync(&mut reader).unwrap().unwrap();
|
||||
let header = BoxHeader::read(&mut reader, &mut 0).await.unwrap().unwrap();
|
||||
assert_eq!(header.kind, BoxType::ElstBox);
|
||||
assert_eq!(src_box.box_size(), header.size);
|
||||
|
||||
|
|
|
@ -162,8 +162,8 @@ mod tests {
|
|||
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_emsg_version0() {
|
||||
#[tokio::test]
|
||||
async fn test_emsg_version0() {
|
||||
let src_box = EmsgBox {
|
||||
version: 0,
|
||||
flags: 0,
|
||||
|
@ -181,7 +181,7 @@ mod tests {
|
|||
assert_eq!(buf.len(), src_box.box_size() as usize);
|
||||
|
||||
let mut reader = buf.as_slice();
|
||||
let header = BoxHeader::read_sync(&mut reader).unwrap().unwrap();
|
||||
let header = BoxHeader::read(&mut reader, &mut 0).await.unwrap().unwrap();
|
||||
assert_eq!(header.kind, BoxType::EmsgBox);
|
||||
assert_eq!(src_box.box_size(), header.size);
|
||||
|
||||
|
@ -189,8 +189,8 @@ mod tests {
|
|||
assert_eq!(src_box, dst_box);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_emsg_version1() {
|
||||
#[tokio::test]
|
||||
async fn test_emsg_version1() {
|
||||
let src_box = EmsgBox {
|
||||
version: 1,
|
||||
flags: 0,
|
||||
|
@ -208,7 +208,7 @@ mod tests {
|
|||
assert_eq!(buf.len(), src_box.box_size() as usize);
|
||||
|
||||
let mut reader = buf.as_slice();
|
||||
let header = BoxHeader::read_sync(&mut reader).unwrap().unwrap();
|
||||
let header = BoxHeader::read(&mut reader, &mut 0).await.unwrap().unwrap();
|
||||
assert_eq!(header.kind, BoxType::EmsgBox);
|
||||
assert_eq!(src_box.box_size(), header.size);
|
||||
|
||||
|
|
|
@ -49,7 +49,7 @@ impl Mp4Box for FtypBox {
|
|||
|
||||
impl BlockReader for FtypBox {
|
||||
fn read_block<'a>(reader: &mut impl Reader<'a>) -> Result<Self> {
|
||||
let brand_count = (reader.remaining() - 16) / 4; // header + major + minor
|
||||
let brand_count = (reader.remaining() - 8) / 4; // major + minor
|
||||
|
||||
let major = reader.get_u32();
|
||||
let minor = reader.get_u32();
|
||||
|
@ -91,8 +91,8 @@ mod tests {
|
|||
use super::*;
|
||||
use crate::mp4box::BoxHeader;
|
||||
|
||||
#[test]
|
||||
fn test_ftyp() {
|
||||
#[tokio::test]
|
||||
async fn test_ftyp() {
|
||||
let src_box = FtypBox {
|
||||
major_brand: str::parse("isom").unwrap(),
|
||||
minor_version: 0,
|
||||
|
@ -108,7 +108,7 @@ mod tests {
|
|||
assert_eq!(buf.len(), src_box.box_size() as usize);
|
||||
|
||||
let mut reader = buf.as_slice();
|
||||
let header = BoxHeader::read_sync(&mut reader).unwrap().unwrap();
|
||||
let header = BoxHeader::read(&mut reader, &mut 0).await.unwrap().unwrap();
|
||||
assert_eq!(header.kind, BoxType::FtypBox);
|
||||
assert_eq!(src_box.box_size(), header.size);
|
||||
|
||||
|
|
|
@ -89,8 +89,8 @@ mod tests {
|
|||
use super::*;
|
||||
use crate::mp4box::BoxHeader;
|
||||
|
||||
#[test]
|
||||
fn test_hdlr() {
|
||||
#[tokio::test]
|
||||
async fn test_hdlr() {
|
||||
let src_box = HdlrBox {
|
||||
version: 0,
|
||||
flags: 0,
|
||||
|
@ -102,7 +102,7 @@ mod tests {
|
|||
assert_eq!(buf.len(), src_box.box_size() as usize);
|
||||
|
||||
let mut reader = buf.as_slice();
|
||||
let header = BoxHeader::read_sync(&mut reader).unwrap().unwrap();
|
||||
let header = BoxHeader::read(&mut reader, &mut 0).await.unwrap().unwrap();
|
||||
assert_eq!(header.kind, BoxType::HdlrBox);
|
||||
assert_eq!(src_box.box_size(), header.size);
|
||||
|
||||
|
@ -110,8 +110,8 @@ mod tests {
|
|||
assert_eq!(src_box, dst_box);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_hdlr_empty() {
|
||||
#[tokio::test]
|
||||
async fn test_hdlr_empty() {
|
||||
let src_box = HdlrBox {
|
||||
version: 0,
|
||||
flags: 0,
|
||||
|
@ -123,7 +123,7 @@ mod tests {
|
|||
assert_eq!(buf.len(), src_box.box_size() as usize);
|
||||
|
||||
let mut reader = buf.as_slice();
|
||||
let header = BoxHeader::read_sync(&mut reader).unwrap().unwrap();
|
||||
let header = BoxHeader::read(&mut reader, &mut 0).await.unwrap().unwrap();
|
||||
assert_eq!(header.kind, BoxType::HdlrBox);
|
||||
assert_eq!(src_box.box_size(), header.size);
|
||||
|
||||
|
@ -131,8 +131,8 @@ mod tests {
|
|||
assert_eq!(src_box, dst_box);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_hdlr_extra() {
|
||||
#[tokio::test]
|
||||
async fn test_hdlr_extra() {
|
||||
let real_src_box = HdlrBox {
|
||||
version: 0,
|
||||
flags: 0,
|
||||
|
@ -150,7 +150,7 @@ mod tests {
|
|||
assert_eq!(buf.len(), src_box.box_size() as usize);
|
||||
|
||||
let mut reader = buf.as_slice();
|
||||
let header = BoxHeader::read_sync(&mut reader).unwrap().unwrap();
|
||||
let header = BoxHeader::read(&mut reader, &mut 0).await.unwrap().unwrap();
|
||||
assert_eq!(header.kind, BoxType::HdlrBox);
|
||||
assert_eq!(src_box.box_size(), header.size);
|
||||
|
||||
|
|
|
@ -200,7 +200,7 @@ impl Mp4Box for HvcCBox {
|
|||
}
|
||||
|
||||
fn summary(&self) -> Result<String> {
|
||||
Ok(format!("configuration_version={} general_profile_space={} general_tier_flag={} general_profile_idc={} general_profile_compatibility_flags={} general_constraint_indicator_flag={} general_level_idc={} min_spatial_segmentation_idc={} parallelism_type={} chroma_format_idc={} bit_depth_luma_minus8={} bit_depth_chroma_minus8={} avg_frame_rate={} constant_frame_rate={} num_temporal_layers={} temporal_id_nested={} length_size_minus_one={}",
|
||||
Ok(format!("configuration_version={} general_profile_space={} general_tier_flag={} general_profile_idc={} general_profile_compatibility_flags={} general_constraint_indicator_flag={} general_level_idc={} min_spatial_segmentation_idc={} parallelism_type={} chroma_format_idc={} bit_depth_luma_minus8={} bit_depth_chroma_minus8={} avg_frame_rate={} constant_frame_rate={} num_temporal_layers={} temporal_id_nested={} length_size_minus_one={}",
|
||||
self.configuration_version,
|
||||
self.general_profile_space,
|
||||
self.general_tier_flag,
|
||||
|
@ -370,8 +370,8 @@ mod tests {
|
|||
use super::*;
|
||||
use crate::mp4box::BoxHeader;
|
||||
|
||||
#[test]
|
||||
fn test_hev1() {
|
||||
#[tokio::test]
|
||||
async fn test_hev1() {
|
||||
let src_box = Hev1Box {
|
||||
data_reference_index: 1,
|
||||
width: 320,
|
||||
|
@ -390,7 +390,7 @@ mod tests {
|
|||
assert_eq!(buf.len(), src_box.box_size() as usize);
|
||||
|
||||
let mut reader = buf.as_slice();
|
||||
let header = BoxHeader::read_sync(&mut reader).unwrap().unwrap();
|
||||
let header = BoxHeader::read(&mut reader, &mut 0).await.unwrap().unwrap();
|
||||
assert_eq!(header.kind, BoxType::Hev1Box);
|
||||
assert_eq!(src_box.box_size(), header.size);
|
||||
|
||||
|
|
|
@ -19,8 +19,9 @@ impl IlstBox {
|
|||
|
||||
pub fn get_size(&self) -> u64 {
|
||||
let mut size = HEADER_SIZE;
|
||||
let ilst_item_header_size = HEADER_SIZE;
|
||||
for item in self.items.values() {
|
||||
size += item.get_size();
|
||||
size += ilst_item_header_size + item.get_size();
|
||||
}
|
||||
size
|
||||
}
|
||||
|
@ -76,7 +77,7 @@ impl BlockReader for IlstBox {
|
|||
_ => continue,
|
||||
}
|
||||
}
|
||||
|
||||
// dbg!(&items);
|
||||
Ok(IlstBox { items })
|
||||
}
|
||||
|
||||
|
@ -98,7 +99,9 @@ impl<W: Write> WriteBox<&mut W> for IlstBox {
|
|||
MetadataKey::Summary => BoxType::DescBox,
|
||||
};
|
||||
|
||||
BoxHeader::new(name, value.get_size()).write(writer)?;
|
||||
let size = HEADER_SIZE + value.box_size(); // Size of IlstItem + DataBox
|
||||
|
||||
BoxHeader::new(name, size).write(writer)?;
|
||||
value.write_box(writer)?;
|
||||
}
|
||||
Ok(size)
|
||||
|
@ -144,8 +147,8 @@ mod tests {
|
|||
use super::*;
|
||||
use crate::mp4box::BoxHeader;
|
||||
|
||||
#[test]
|
||||
fn test_ilst() {
|
||||
#[tokio::test]
|
||||
async fn test_ilst() {
|
||||
let src_year = DataBox {
|
||||
data_type: DataType::Text,
|
||||
data: b"test_year".to_vec(),
|
||||
|
@ -165,7 +168,7 @@ mod tests {
|
|||
assert_eq!(buf.len(), src_box.box_size() as usize);
|
||||
|
||||
let mut reader = buf.as_slice();
|
||||
let header = BoxHeader::read_sync(&mut reader).unwrap().unwrap();
|
||||
let header = BoxHeader::read(&mut reader, &mut 0).await.unwrap().unwrap();
|
||||
assert_eq!(header.kind, BoxType::IlstBox);
|
||||
assert_eq!(src_box.box_size(), header.size);
|
||||
|
||||
|
@ -173,15 +176,15 @@ mod tests {
|
|||
assert_eq!(src_box, dst_box);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_ilst_empty() {
|
||||
#[tokio::test]
|
||||
async fn test_ilst_empty() {
|
||||
let src_box = IlstBox::default();
|
||||
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 = buf.as_slice();
|
||||
let header = BoxHeader::read_sync(&mut reader).unwrap().unwrap();
|
||||
let header = BoxHeader::read(&mut reader, &mut 0).await.unwrap().unwrap();
|
||||
assert_eq!(header.kind, BoxType::IlstBox);
|
||||
assert_eq!(src_box.box_size(), header.size);
|
||||
|
||||
|
|
|
@ -179,8 +179,8 @@ mod tests {
|
|||
test_language_code("kor");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_mdhd32() {
|
||||
#[tokio::test]
|
||||
async fn test_mdhd32() {
|
||||
let src_box = MdhdBox {
|
||||
version: 0,
|
||||
flags: 0,
|
||||
|
@ -195,7 +195,7 @@ mod tests {
|
|||
assert_eq!(buf.len(), src_box.box_size() as usize);
|
||||
|
||||
let mut reader = buf.as_slice();
|
||||
let header = BoxHeader::read_sync(&mut reader).unwrap().unwrap();
|
||||
let header = BoxHeader::read(&mut reader, &mut 0).await.unwrap().unwrap();
|
||||
assert_eq!(header.kind, BoxType::MdhdBox);
|
||||
assert_eq!(src_box.box_size(), header.size);
|
||||
|
||||
|
@ -203,8 +203,8 @@ mod tests {
|
|||
assert_eq!(src_box, dst_box);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_mdhd64() {
|
||||
#[tokio::test]
|
||||
async fn test_mdhd64() {
|
||||
let src_box = MdhdBox {
|
||||
version: 0,
|
||||
flags: 0,
|
||||
|
@ -219,7 +219,7 @@ mod tests {
|
|||
assert_eq!(buf.len(), src_box.box_size() as usize);
|
||||
|
||||
let mut reader = buf.as_slice();
|
||||
let header = BoxHeader::read_sync(&mut reader).unwrap().unwrap();
|
||||
let header = BoxHeader::read(&mut reader, &mut 0).await.unwrap().unwrap();
|
||||
assert_eq!(header.kind, BoxType::MdhdBox);
|
||||
assert_eq!(src_box.box_size(), header.size);
|
||||
|
||||
|
|
|
@ -93,8 +93,8 @@ mod tests {
|
|||
use super::*;
|
||||
use crate::mp4box::BoxHeader;
|
||||
|
||||
#[test]
|
||||
fn test_mehd32() {
|
||||
#[tokio::test]
|
||||
async fn test_mehd32() {
|
||||
let src_box = MehdBox {
|
||||
version: 0,
|
||||
flags: 0,
|
||||
|
@ -105,7 +105,7 @@ mod tests {
|
|||
assert_eq!(buf.len(), src_box.box_size() as usize);
|
||||
|
||||
let mut reader = buf.as_slice();
|
||||
let header = BoxHeader::read_sync(&mut reader).unwrap().unwrap();
|
||||
let header = BoxHeader::read(&mut reader, &mut 0).await.unwrap().unwrap();
|
||||
assert_eq!(header.kind, BoxType::MehdBox);
|
||||
assert_eq!(src_box.box_size(), header.size);
|
||||
|
||||
|
@ -113,8 +113,8 @@ mod tests {
|
|||
assert_eq!(src_box, dst_box);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_mehd64() {
|
||||
#[tokio::test]
|
||||
async fn test_mehd64() {
|
||||
let src_box = MehdBox {
|
||||
version: 0,
|
||||
flags: 0,
|
||||
|
@ -125,7 +125,7 @@ mod tests {
|
|||
assert_eq!(buf.len(), src_box.box_size() as usize);
|
||||
|
||||
let mut reader = buf.as_slice();
|
||||
let header = BoxHeader::read_sync(&mut reader).unwrap().unwrap();
|
||||
let header = BoxHeader::read(&mut reader, &mut 0).await.unwrap().unwrap();
|
||||
assert_eq!(header.kind, BoxType::MehdBox);
|
||||
assert_eq!(src_box.box_size(), header.size);
|
||||
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
use std::collections::HashMap;
|
||||
|
||||
use serde::Serialize;
|
||||
|
||||
use crate::mp4box::hdlr::HdlrBox;
|
||||
|
@ -90,22 +92,29 @@ impl BlockReader for MetaBox {
|
|||
reader.skip(4);
|
||||
}
|
||||
|
||||
let mut boxes = HashMap::new();
|
||||
while let Some(mut bx) = reader.get_box()? {
|
||||
boxes.insert(bx.kind, bx.inner.collect_remaining());
|
||||
}
|
||||
|
||||
// find the hdlr box
|
||||
let hdlr = reader.find_box::<HdlrBox>()?;
|
||||
let hdlr = HdlrBox::read_block(&mut boxes.remove(&BoxType::HdlrBox).unwrap().as_slice())?;
|
||||
|
||||
Ok(match hdlr.handler_type {
|
||||
MDIR => MetaBox::Mdir {
|
||||
ilst: reader.try_find_box::<IlstBox>()?,
|
||||
ilst: if let Some(inner) = boxes.remove(&BoxType::IlstBox) {
|
||||
Some(IlstBox::read_block(&mut inner.as_slice())?)
|
||||
} else {
|
||||
None
|
||||
},
|
||||
},
|
||||
_ => MetaBox::Unknown {
|
||||
hdlr: hdlr.clone(),
|
||||
data: boxes
|
||||
.into_iter()
|
||||
.map(|(k, v)| (k, v))
|
||||
.collect::<Vec<(BoxType, Vec<u8>)>>(),
|
||||
},
|
||||
_ => {
|
||||
let mut data = Vec::new();
|
||||
|
||||
while let Some(mut bx) = reader.get_box()? {
|
||||
data.push((bx.kind, bx.inner.collect_remaining()))
|
||||
}
|
||||
|
||||
MetaBox::Unknown { hdlr, data }
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -152,8 +161,8 @@ mod tests {
|
|||
use super::*;
|
||||
use crate::mp4box::BoxHeader;
|
||||
|
||||
#[test]
|
||||
fn test_meta_mdir_empty() {
|
||||
#[tokio::test]
|
||||
async fn test_meta_mdir_empty() {
|
||||
let src_box = MetaBox::Mdir { ilst: None };
|
||||
|
||||
let mut buf = Vec::new();
|
||||
|
@ -161,7 +170,7 @@ mod tests {
|
|||
assert_eq!(buf.len(), src_box.box_size() as usize);
|
||||
|
||||
let mut reader = buf.as_slice();
|
||||
let header = BoxHeader::read_sync(&mut reader).unwrap().unwrap();
|
||||
let header = BoxHeader::read(&mut reader, &mut 0).await.unwrap().unwrap();
|
||||
assert_eq!(header.kind, BoxType::MetaBox);
|
||||
assert_eq!(header.size, src_box.box_size());
|
||||
|
||||
|
@ -169,8 +178,8 @@ mod tests {
|
|||
assert_eq!(dst_box, src_box);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_meta_mdir() {
|
||||
#[tokio::test]
|
||||
async fn test_meta_mdir() {
|
||||
let src_box = MetaBox::Mdir {
|
||||
ilst: Some(IlstBox::default()),
|
||||
};
|
||||
|
@ -180,7 +189,7 @@ mod tests {
|
|||
assert_eq!(buf.len(), src_box.box_size() as usize);
|
||||
|
||||
let mut reader = buf.as_slice();
|
||||
let header = BoxHeader::read_sync(&mut reader).unwrap().unwrap();
|
||||
let header = BoxHeader::read(&mut reader, &mut 0).await.unwrap().unwrap();
|
||||
assert_eq!(header.kind, BoxType::MetaBox);
|
||||
assert_eq!(header.size, src_box.box_size());
|
||||
|
||||
|
@ -188,12 +197,13 @@ mod tests {
|
|||
assert_eq!(dst_box, src_box);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_meta_hdrl_non_first() {
|
||||
#[tokio::test]
|
||||
async fn test_meta_hdrl_non_first() {
|
||||
let data = b"\x00\x00\x00\x7fmeta\x00\x00\x00\x00\x00\x00\x00Qilst\x00\x00\x00I\xa9too\x00\x00\x00Adata\x00\x00\x00\x01\x00\x00\x00\x00TMPGEnc Video Mastering Works 7 Version 7.0.15.17\x00\x00\x00\"hdlr\x00\x00\x00\x00\x00\x00\x00\x00mdirappl\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00";
|
||||
|
||||
let mut reader = data.as_slice();
|
||||
let header = BoxHeader::read_sync(&mut reader).unwrap().unwrap();
|
||||
|
||||
let header = BoxHeader::read(&mut reader, &mut 0).await.unwrap().unwrap();
|
||||
assert_eq!(header.kind, BoxType::MetaBox);
|
||||
|
||||
let meta_box = MetaBox::read_block(&mut reader).unwrap();
|
||||
|
@ -208,8 +218,8 @@ mod tests {
|
|||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_meta_unknown() {
|
||||
#[tokio::test]
|
||||
async fn test_meta_unknown() {
|
||||
let src_hdlr = HdlrBox {
|
||||
handler_type: FourCC::from(*b"test"),
|
||||
..Default::default()
|
||||
|
@ -225,7 +235,7 @@ mod tests {
|
|||
assert_eq!(buf.len(), src_box.box_size() as usize);
|
||||
|
||||
let mut reader = buf.as_slice();
|
||||
let header = BoxHeader::read_sync(&mut reader).unwrap().unwrap();
|
||||
let header = BoxHeader::read(&mut reader, &mut 0).await.unwrap().unwrap();
|
||||
assert_eq!(header.kind, BoxType::MetaBox);
|
||||
assert_eq!(header.size, src_box.box_size());
|
||||
|
||||
|
|
|
@ -81,8 +81,8 @@ mod tests {
|
|||
use super::*;
|
||||
use crate::mp4box::BoxHeader;
|
||||
|
||||
#[test]
|
||||
fn test_mfhd() {
|
||||
#[tokio::test]
|
||||
async fn test_mfhd() {
|
||||
let src_box = MfhdBox {
|
||||
version: 0,
|
||||
flags: 0,
|
||||
|
@ -93,7 +93,7 @@ mod tests {
|
|||
assert_eq!(buf.len(), src_box.box_size() as usize);
|
||||
|
||||
let mut reader = buf.as_slice();
|
||||
let header = BoxHeader::read_sync(&mut reader).unwrap().unwrap();
|
||||
let header = BoxHeader::read(&mut reader, &mut 0).await.unwrap().unwrap();
|
||||
assert_eq!(header.kind, BoxType::MfhdBox);
|
||||
assert_eq!(src_box.box_size(), header.size);
|
||||
|
||||
|
|
|
@ -158,7 +158,7 @@ pub const HEADER_EXT_SIZE: u64 = 4;
|
|||
|
||||
macro_rules! boxtype {
|
||||
($( $name:ident => $value:expr ),*) => {
|
||||
#[derive(Clone, Copy, PartialEq, Eq)]
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Hash)]
|
||||
pub enum BoxType {
|
||||
$( $name, )*
|
||||
UnknownBox(u32),
|
||||
|
@ -699,13 +699,14 @@ impl<'a> Reader<'a> for &'a [u8] {
|
|||
|
||||
#[inline]
|
||||
fn get_box(&mut self) -> Result<Option<BoxReader<'a, impl Reader<'a> + '_>>> {
|
||||
let Some(BoxHeader { kind, size }) = BoxHeader::read_sync(self)? else {
|
||||
let mut offset = 0;
|
||||
let Some(BoxHeader { kind, size }) = BoxHeader::read_sync(self, &mut offset)? else {
|
||||
return Ok(None);
|
||||
};
|
||||
|
||||
Ok(Some(BoxReader {
|
||||
kind,
|
||||
inner: Reader::take(self, size as _)?,
|
||||
inner: Reader::take(self, (size - offset) as _)?,
|
||||
m: PhantomData,
|
||||
}))
|
||||
}
|
||||
|
@ -731,7 +732,7 @@ impl BoxHeader {
|
|||
Self { kind: name, size }
|
||||
}
|
||||
|
||||
pub fn read_sync<'a>(reader: &mut impl Reader<'a>) -> Result<Option<Self>> {
|
||||
pub fn read_sync<'a>(reader: &mut impl Reader<'a>, offset: &mut u64) -> Result<Option<Self>> {
|
||||
if reader.remaining() < 8 {
|
||||
return Ok(None);
|
||||
}
|
||||
|
@ -739,12 +740,16 @@ impl BoxHeader {
|
|||
let sz = reader.get_u32();
|
||||
let typ = reader.get_u32();
|
||||
|
||||
*offset += 8;
|
||||
|
||||
// Get largesize if size is 1
|
||||
let size = if sz == 1 {
|
||||
if reader.remaining() < 8 {
|
||||
return Err(BoxError::InvalidData("expected 8 bytes more"));
|
||||
}
|
||||
|
||||
*offset += 8;
|
||||
|
||||
let largesize = reader.get_u64();
|
||||
// Subtract the length of the serialized largesize, as callers assume `size - HEADER_SIZE` is the length
|
||||
// of the box data. Disallow `largesize < 16`, or else a largesize of 8 will result in a BoxHeader::size
|
||||
|
@ -767,7 +772,7 @@ impl BoxHeader {
|
|||
|
||||
Ok(Some(BoxHeader {
|
||||
kind: BoxType::from(typ),
|
||||
size: size.saturating_sub(HEADER_SIZE),
|
||||
size,
|
||||
}))
|
||||
}
|
||||
|
||||
|
@ -829,7 +834,7 @@ impl BoxHeader {
|
|||
|
||||
Ok(Some(BoxHeader {
|
||||
kind: BoxType::from(typ),
|
||||
size: size.saturating_sub(HEADER_SIZE),
|
||||
size,
|
||||
}))
|
||||
}
|
||||
|
||||
|
@ -837,10 +842,10 @@ impl BoxHeader {
|
|||
if self.size > u32::MAX as u64 {
|
||||
writer.write_u32::<BigEndian>(1)?;
|
||||
writer.write_u32::<BigEndian>(self.kind.into())?;
|
||||
writer.write_u64::<BigEndian>(self.size + HEADER_SIZE)?;
|
||||
writer.write_u64::<BigEndian>(self.size)?;
|
||||
Ok(16)
|
||||
} else {
|
||||
writer.write_u32::<BigEndian>((self.size + HEADER_SIZE) as u32)?;
|
||||
writer.write_u32::<BigEndian>(self.size as u32)?;
|
||||
writer.write_u32::<BigEndian>(self.kind.into())?;
|
||||
Ok(8)
|
||||
}
|
||||
|
@ -914,31 +919,43 @@ mod tests {
|
|||
assert_eq!(ftyp_fcc, ftyp_fcc2);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_largesize_too_small() {
|
||||
let error =
|
||||
BoxHeader::read_sync(&mut &[0, 0, 0, 1, 1, 2, 3, 4, 0, 0, 0, 0, 0, 0, 0, 7][..]);
|
||||
#[tokio::test]
|
||||
async fn test_largesize_too_small() {
|
||||
let error = BoxHeader::read(
|
||||
&mut &[0, 0, 0, 1, 1, 2, 3, 4, 0, 0, 0, 0, 0, 0, 0, 7][..],
|
||||
&mut 0,
|
||||
)
|
||||
.await;
|
||||
assert!(matches!(error, Err(BoxError::InvalidData(_))));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_zero_largesize() {
|
||||
let error =
|
||||
BoxHeader::read_sync(&mut &[0, 0, 0, 1, 1, 2, 3, 4, 0, 0, 0, 0, 0, 0, 0, 8][..]);
|
||||
#[tokio::test]
|
||||
async fn test_zero_largesize() {
|
||||
let error = BoxHeader::read(
|
||||
&mut &[0, 0, 0, 1, 1, 2, 3, 4, 0, 0, 0, 0, 0, 0, 0, 8][..],
|
||||
&mut 0,
|
||||
)
|
||||
.await;
|
||||
assert!(matches!(error, Err(BoxError::InvalidData(_))));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_nonzero_largesize_too_small() {
|
||||
let error =
|
||||
BoxHeader::read_sync(&mut &[0, 0, 0, 1, 1, 2, 3, 4, 0, 0, 0, 0, 0, 0, 0, 15][..]);
|
||||
#[tokio::test]
|
||||
async fn test_nonzero_largesize_too_small() {
|
||||
let error = BoxHeader::read(
|
||||
&mut &[0, 0, 0, 1, 1, 2, 3, 4, 0, 0, 0, 0, 0, 0, 0, 15][..],
|
||||
&mut 0,
|
||||
)
|
||||
.await;
|
||||
assert!(matches!(error, Err(BoxError::InvalidData(_))));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_valid_largesize() {
|
||||
let header =
|
||||
BoxHeader::read_sync(&mut &[0, 0, 0, 1, 1, 2, 3, 4, 0, 0, 0, 0, 0, 0, 0, 16][..]);
|
||||
#[tokio::test]
|
||||
async fn test_valid_largesize() {
|
||||
let header = BoxHeader::read(
|
||||
&mut &[0, 0, 0, 1, 1, 2, 3, 4, 0, 0, 0, 0, 0, 0, 0, 16][..],
|
||||
&mut 0,
|
||||
)
|
||||
.await;
|
||||
assert!(matches!(header, Ok(Some(BoxHeader { size: 8, .. }))));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -135,8 +135,8 @@ mod tests {
|
|||
use super::*;
|
||||
use crate::mp4box::BoxHeader;
|
||||
|
||||
#[test]
|
||||
fn test_moov() {
|
||||
#[tokio::test]
|
||||
async fn test_moov() {
|
||||
let src_box = MoovBox {
|
||||
mvhd: MvhdBox::default(),
|
||||
mvex: None, // XXX mvex is not written currently
|
||||
|
@ -150,7 +150,7 @@ mod tests {
|
|||
assert_eq!(buf.len(), src_box.box_size() as usize);
|
||||
|
||||
let mut reader = buf.as_slice();
|
||||
let header = BoxHeader::read_sync(&mut reader).unwrap().unwrap();
|
||||
let header = BoxHeader::read(&mut reader, &mut 0).await.unwrap().unwrap();
|
||||
assert_eq!(header.kind, BoxType::MoovBox);
|
||||
assert_eq!(header.size, src_box.box_size());
|
||||
|
||||
|
@ -158,8 +158,8 @@ mod tests {
|
|||
assert_eq!(dst_box, src_box);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_moov_empty() {
|
||||
#[tokio::test]
|
||||
async fn test_moov_empty() {
|
||||
let src_box = MoovBox::default();
|
||||
|
||||
let mut buf = Vec::new();
|
||||
|
@ -167,7 +167,7 @@ mod tests {
|
|||
assert_eq!(buf.len(), src_box.box_size() as usize);
|
||||
|
||||
let mut reader = buf.as_slice();
|
||||
let header = BoxHeader::read_sync(&mut reader).unwrap().unwrap();
|
||||
let header = BoxHeader::read(&mut reader, &mut 0).await.unwrap().unwrap();
|
||||
assert_eq!(header.kind, BoxType::MoovBox);
|
||||
assert_eq!(header.size, src_box.box_size());
|
||||
|
||||
|
|
|
@ -595,8 +595,8 @@ mod tests {
|
|||
use super::*;
|
||||
use crate::mp4box::BoxHeader;
|
||||
|
||||
#[test]
|
||||
fn test_mp4a() {
|
||||
#[tokio::test]
|
||||
async fn test_mp4a() {
|
||||
let src_box = Mp4aBox {
|
||||
data_reference_index: 1,
|
||||
channelcount: 2,
|
||||
|
@ -629,7 +629,7 @@ mod tests {
|
|||
assert_eq!(buf.len(), src_box.box_size() as usize);
|
||||
|
||||
let mut reader = buf.as_slice();
|
||||
let header = BoxHeader::read_sync(&mut reader).unwrap().unwrap();
|
||||
let header = BoxHeader::read(&mut reader, &mut 0).await.unwrap().unwrap();
|
||||
assert_eq!(header.kind, BoxType::Mp4aBox);
|
||||
assert_eq!(src_box.box_size(), header.size);
|
||||
|
||||
|
@ -637,8 +637,8 @@ mod tests {
|
|||
assert_eq!(src_box, dst_box);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_mp4a_no_esds() {
|
||||
#[tokio::test]
|
||||
async fn test_mp4a_no_esds() {
|
||||
let src_box = Mp4aBox {
|
||||
data_reference_index: 1,
|
||||
channelcount: 2,
|
||||
|
@ -651,7 +651,7 @@ mod tests {
|
|||
assert_eq!(buf.len(), src_box.box_size() as usize);
|
||||
|
||||
let mut reader = buf.as_slice();
|
||||
let header = BoxHeader::read_sync(&mut reader).unwrap().unwrap();
|
||||
let header = BoxHeader::read(&mut reader, &mut 0).await.unwrap().unwrap();
|
||||
assert_eq!(header.kind, BoxType::Mp4aBox);
|
||||
assert_eq!(src_box.box_size(), header.size);
|
||||
|
||||
|
|
|
@ -201,8 +201,8 @@ mod tests {
|
|||
use super::*;
|
||||
use crate::mp4box::BoxHeader;
|
||||
|
||||
#[test]
|
||||
fn test_mvhd32() {
|
||||
#[tokio::test]
|
||||
async fn test_mvhd32() {
|
||||
let src_box = MvhdBox {
|
||||
version: 0,
|
||||
flags: 0,
|
||||
|
@ -220,7 +220,7 @@ mod tests {
|
|||
assert_eq!(buf.len(), src_box.box_size() as usize);
|
||||
|
||||
let mut reader = buf.as_slice();
|
||||
let header = BoxHeader::read_sync(&mut reader).unwrap().unwrap();
|
||||
let header = BoxHeader::read(&mut reader, &mut 0).await.unwrap().unwrap();
|
||||
assert_eq!(header.kind, BoxType::MvhdBox);
|
||||
assert_eq!(src_box.box_size(), header.size);
|
||||
|
||||
|
@ -228,8 +228,8 @@ mod tests {
|
|||
assert_eq!(src_box, dst_box);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_mvhd64() {
|
||||
#[tokio::test]
|
||||
async fn test_mvhd64() {
|
||||
let src_box = MvhdBox {
|
||||
version: 1,
|
||||
flags: 0,
|
||||
|
@ -247,7 +247,7 @@ mod tests {
|
|||
assert_eq!(buf.len(), src_box.box_size() as usize);
|
||||
|
||||
let mut reader = buf.as_slice();
|
||||
let header = BoxHeader::read_sync(&mut reader).unwrap().unwrap();
|
||||
let header = BoxHeader::read(&mut reader, &mut 0).await.unwrap().unwrap();
|
||||
assert_eq!(header.kind, BoxType::MvhdBox);
|
||||
assert_eq!(src_box.box_size(), header.size);
|
||||
|
||||
|
|
|
@ -85,8 +85,8 @@ mod tests {
|
|||
use super::*;
|
||||
use crate::mp4box::BoxHeader;
|
||||
|
||||
#[test]
|
||||
fn test_smhd() {
|
||||
#[tokio::test]
|
||||
async fn test_smhd() {
|
||||
let src_box = SmhdBox {
|
||||
version: 0,
|
||||
flags: 0,
|
||||
|
@ -97,7 +97,7 @@ mod tests {
|
|||
assert_eq!(buf.len(), src_box.box_size() as usize);
|
||||
|
||||
let mut reader = buf.as_slice();
|
||||
let header = BoxHeader::read_sync(&mut reader).unwrap().unwrap();
|
||||
let header = BoxHeader::read(&mut reader, &mut 0).await.unwrap().unwrap();
|
||||
assert_eq!(header.kind, BoxType::SmhdBox);
|
||||
assert_eq!(src_box.box_size(), header.size);
|
||||
|
||||
|
|
|
@ -130,8 +130,8 @@ mod tests {
|
|||
use super::*;
|
||||
use crate::mp4box::BoxHeader;
|
||||
|
||||
#[test]
|
||||
fn test_stco() {
|
||||
#[tokio::test]
|
||||
async fn test_stco() {
|
||||
let src_box = StcoBox {
|
||||
version: 0,
|
||||
flags: 0,
|
||||
|
@ -142,7 +142,7 @@ mod tests {
|
|||
assert_eq!(buf.len(), src_box.box_size() as usize);
|
||||
|
||||
let mut reader = buf.as_slice();
|
||||
let header = BoxHeader::read_sync(&mut reader).unwrap().unwrap();
|
||||
let header = BoxHeader::read(&mut reader, &mut 0).await.unwrap().unwrap();
|
||||
assert_eq!(header.kind, BoxType::StcoBox);
|
||||
assert_eq!(src_box.box_size(), header.size);
|
||||
|
||||
|
|
|
@ -126,8 +126,8 @@ mod tests {
|
|||
use super::*;
|
||||
use crate::mp4box::BoxHeader;
|
||||
|
||||
#[test]
|
||||
fn test_stsc() {
|
||||
#[tokio::test]
|
||||
async fn test_stsc() {
|
||||
let src_box = StscBox {
|
||||
version: 0,
|
||||
flags: 0,
|
||||
|
@ -151,7 +151,7 @@ mod tests {
|
|||
assert_eq!(buf.len(), src_box.box_size() as usize);
|
||||
|
||||
let mut reader = buf.as_slice();
|
||||
let header = BoxHeader::read_sync(&mut reader).unwrap().unwrap();
|
||||
let header = BoxHeader::read(&mut reader, &mut 0).await.unwrap().unwrap();
|
||||
assert_eq!(header.kind, BoxType::StscBox);
|
||||
assert_eq!(src_box.box_size(), header.size);
|
||||
|
||||
|
|
|
@ -92,8 +92,8 @@ mod tests {
|
|||
use super::*;
|
||||
use crate::mp4box::BoxHeader;
|
||||
|
||||
#[test]
|
||||
fn test_stss() {
|
||||
#[tokio::test]
|
||||
async fn test_stss() {
|
||||
let src_box = StssBox {
|
||||
version: 0,
|
||||
flags: 0,
|
||||
|
@ -104,7 +104,7 @@ mod tests {
|
|||
assert_eq!(buf.len(), src_box.box_size() as usize);
|
||||
|
||||
let mut reader = buf.as_slice();
|
||||
let header = BoxHeader::read_sync(&mut reader).unwrap().unwrap();
|
||||
let header = BoxHeader::read(&mut reader, &mut 0).await.unwrap().unwrap();
|
||||
assert_eq!(header.kind, BoxType::StssBox);
|
||||
assert_eq!(src_box.box_size(), header.size);
|
||||
|
||||
|
|
|
@ -114,8 +114,8 @@ mod tests {
|
|||
use super::*;
|
||||
use crate::mp4box::BoxHeader;
|
||||
|
||||
#[test]
|
||||
fn test_stsz_same_size() {
|
||||
#[tokio::test]
|
||||
async fn test_stsz_same_size() {
|
||||
let src_box = StszBox {
|
||||
version: 0,
|
||||
flags: 0,
|
||||
|
@ -128,7 +128,7 @@ mod tests {
|
|||
assert_eq!(buf.len(), src_box.box_size() as usize);
|
||||
|
||||
let mut reader = buf.as_slice();
|
||||
let header = BoxHeader::read_sync(&mut reader).unwrap().unwrap();
|
||||
let header = BoxHeader::read(&mut reader, &mut 0).await.unwrap().unwrap();
|
||||
assert_eq!(header.kind, BoxType::StszBox);
|
||||
assert_eq!(src_box.box_size(), header.size);
|
||||
|
||||
|
@ -136,8 +136,8 @@ mod tests {
|
|||
assert_eq!(src_box, dst_box);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_stsz_many_sizes() {
|
||||
#[tokio::test]
|
||||
async fn test_stsz_many_sizes() {
|
||||
let src_box = StszBox {
|
||||
version: 0,
|
||||
flags: 0,
|
||||
|
@ -150,7 +150,7 @@ mod tests {
|
|||
assert_eq!(buf.len(), src_box.box_size() as usize);
|
||||
|
||||
let mut reader = buf.as_slice();
|
||||
let header = BoxHeader::read_sync(&mut reader).unwrap().unwrap();
|
||||
let header = BoxHeader::read(&mut reader, &mut 0).await.unwrap().unwrap();
|
||||
assert_eq!(header.kind, BoxType::StszBox);
|
||||
assert_eq!(src_box.box_size(), header.size);
|
||||
|
||||
|
|
|
@ -103,8 +103,8 @@ mod tests {
|
|||
use super::*;
|
||||
use crate::mp4box::BoxHeader;
|
||||
|
||||
#[test]
|
||||
fn test_stts() {
|
||||
#[tokio::test]
|
||||
async fn test_stts() {
|
||||
let src_box = SttsBox {
|
||||
version: 0,
|
||||
flags: 0,
|
||||
|
@ -124,7 +124,7 @@ mod tests {
|
|||
assert_eq!(buf.len(), src_box.box_size() as usize);
|
||||
|
||||
let mut reader = buf.as_slice();
|
||||
let header = BoxHeader::read_sync(&mut reader).unwrap().unwrap();
|
||||
let header = BoxHeader::read(&mut reader, &mut 0).await.unwrap().unwrap();
|
||||
assert_eq!(header.kind, BoxType::SttsBox);
|
||||
assert_eq!(src_box.box_size(), header.size);
|
||||
|
||||
|
|
|
@ -92,8 +92,8 @@ mod tests {
|
|||
use super::*;
|
||||
use crate::mp4box::BoxHeader;
|
||||
|
||||
#[test]
|
||||
fn test_tfdt32() {
|
||||
#[tokio::test]
|
||||
async fn test_tfdt32() {
|
||||
let src_box = TfdtBox {
|
||||
version: 0,
|
||||
flags: 0,
|
||||
|
@ -104,7 +104,7 @@ mod tests {
|
|||
assert_eq!(buf.len(), src_box.box_size() as usize);
|
||||
|
||||
let mut reader = buf.as_slice();
|
||||
let header = BoxHeader::read_sync(&mut reader).unwrap().unwrap();
|
||||
let header = BoxHeader::read(&mut reader, &mut 0).await.unwrap().unwrap();
|
||||
assert_eq!(header.kind, BoxType::TfdtBox);
|
||||
assert_eq!(src_box.box_size(), header.size);
|
||||
|
||||
|
@ -112,8 +112,8 @@ mod tests {
|
|||
assert_eq!(src_box, dst_box);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_tfdt64() {
|
||||
#[tokio::test]
|
||||
async fn test_tfdt64() {
|
||||
let src_box = TfdtBox {
|
||||
version: 1,
|
||||
flags: 0,
|
||||
|
@ -124,7 +124,7 @@ mod tests {
|
|||
assert_eq!(buf.len(), src_box.box_size() as usize);
|
||||
|
||||
let mut reader = buf.as_slice();
|
||||
let header = BoxHeader::read_sync(&mut reader).unwrap().unwrap();
|
||||
let header = BoxHeader::read(&mut reader, &mut 0).await.unwrap().unwrap();
|
||||
assert_eq!(header.kind, BoxType::TfdtBox);
|
||||
assert_eq!(src_box.box_size(), header.size);
|
||||
|
||||
|
|
|
@ -151,8 +151,8 @@ mod tests {
|
|||
use super::*;
|
||||
use crate::mp4box::BoxHeader;
|
||||
|
||||
#[test]
|
||||
fn test_tfhd() {
|
||||
#[tokio::test]
|
||||
async fn test_tfhd() {
|
||||
let src_box = TfhdBox {
|
||||
version: 0,
|
||||
flags: 0,
|
||||
|
@ -168,7 +168,7 @@ mod tests {
|
|||
assert_eq!(buf.len(), src_box.box_size() as usize);
|
||||
|
||||
let mut reader = buf.as_slice();
|
||||
let header = BoxHeader::read_sync(&mut reader).unwrap().unwrap();
|
||||
let header = BoxHeader::read(&mut reader, &mut 0).await.unwrap().unwrap();
|
||||
assert_eq!(header.kind, BoxType::TfhdBox);
|
||||
assert_eq!(src_box.box_size(), header.size);
|
||||
|
||||
|
@ -176,8 +176,8 @@ mod tests {
|
|||
assert_eq!(src_box, dst_box);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_tfhd_with_flags() {
|
||||
#[tokio::test]
|
||||
async fn test_tfhd_with_flags() {
|
||||
let src_box = TfhdBox {
|
||||
version: 0,
|
||||
flags: TfhdBox::FLAG_SAMPLE_DESCRIPTION_INDEX
|
||||
|
@ -195,7 +195,7 @@ mod tests {
|
|||
assert_eq!(buf.len(), src_box.box_size() as usize);
|
||||
|
||||
let mut reader = buf.as_slice();
|
||||
let header = BoxHeader::read_sync(&mut reader).unwrap().unwrap();
|
||||
let header = BoxHeader::read(&mut reader, &mut 0).await.unwrap().unwrap();
|
||||
assert_eq!(header.kind, BoxType::TfhdBox);
|
||||
assert_eq!(src_box.box_size(), header.size);
|
||||
|
||||
|
|
|
@ -263,8 +263,8 @@ mod tests {
|
|||
use super::*;
|
||||
use crate::mp4box::BoxHeader;
|
||||
|
||||
#[test]
|
||||
fn test_tkhd32() {
|
||||
#[tokio::test]
|
||||
async fn test_tkhd32() {
|
||||
let src_box = TkhdBox {
|
||||
version: 0,
|
||||
flags: TrackFlag::TrackEnabled as u32,
|
||||
|
@ -284,7 +284,7 @@ mod tests {
|
|||
assert_eq!(buf.len(), src_box.box_size() as usize);
|
||||
|
||||
let mut reader = buf.as_slice();
|
||||
let header = BoxHeader::read_sync(&mut reader).unwrap().unwrap();
|
||||
let header = BoxHeader::read(&mut reader, &mut 0).await.unwrap().unwrap();
|
||||
assert_eq!(header.kind, BoxType::TkhdBox);
|
||||
assert_eq!(src_box.box_size(), header.size);
|
||||
|
||||
|
@ -292,8 +292,8 @@ mod tests {
|
|||
assert_eq!(src_box, dst_box);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_tkhd64() {
|
||||
#[tokio::test]
|
||||
async fn test_tkhd64() {
|
||||
let src_box = TkhdBox {
|
||||
version: 1,
|
||||
flags: TrackFlag::TrackEnabled as u32,
|
||||
|
@ -313,7 +313,7 @@ mod tests {
|
|||
assert_eq!(buf.len(), src_box.box_size() as usize);
|
||||
|
||||
let mut reader = buf.as_slice();
|
||||
let header = BoxHeader::read_sync(&mut reader).unwrap().unwrap();
|
||||
let header = BoxHeader::read(&mut reader, &mut 0).await.unwrap().unwrap();
|
||||
assert_eq!(header.kind, BoxType::TkhdBox);
|
||||
assert_eq!(src_box.box_size(), header.size);
|
||||
|
||||
|
|
|
@ -93,8 +93,8 @@ mod tests {
|
|||
use super::*;
|
||||
use crate::mp4box::BoxHeader;
|
||||
|
||||
#[test]
|
||||
fn test_trex() {
|
||||
#[tokio::test]
|
||||
async fn test_trex() {
|
||||
let src_box = TrexBox {
|
||||
version: 0,
|
||||
flags: 0,
|
||||
|
@ -109,7 +109,7 @@ mod tests {
|
|||
assert_eq!(buf.len(), src_box.box_size() as usize);
|
||||
|
||||
let mut reader = buf.as_slice();
|
||||
let header = BoxHeader::read_sync(&mut reader).unwrap().unwrap();
|
||||
let header = BoxHeader::read(&mut reader, &mut 0).await.unwrap().unwrap();
|
||||
assert_eq!(header.kind, BoxType::TrexBox);
|
||||
assert_eq!(src_box.box_size(), header.size);
|
||||
|
||||
|
|
|
@ -210,8 +210,8 @@ mod tests {
|
|||
use super::*;
|
||||
use crate::mp4box::BoxHeader;
|
||||
|
||||
#[test]
|
||||
fn test_trun_same_size() {
|
||||
#[tokio::test]
|
||||
async fn test_trun_same_size() {
|
||||
let src_box = TrunBox {
|
||||
version: 0,
|
||||
flags: 0,
|
||||
|
@ -228,7 +228,7 @@ mod tests {
|
|||
assert_eq!(buf.len(), src_box.box_size() as usize);
|
||||
|
||||
let mut reader = buf.as_slice();
|
||||
let header = BoxHeader::read_sync(&mut reader).unwrap().unwrap();
|
||||
let header = BoxHeader::read(&mut reader, &mut 0).await.unwrap().unwrap();
|
||||
assert_eq!(header.kind, BoxType::TrunBox);
|
||||
assert_eq!(src_box.box_size(), header.size);
|
||||
|
||||
|
@ -236,8 +236,8 @@ mod tests {
|
|||
assert_eq!(src_box, dst_box);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_trun_many_sizes() {
|
||||
#[tokio::test]
|
||||
async fn test_trun_many_sizes() {
|
||||
let src_box = TrunBox {
|
||||
version: 0,
|
||||
flags: TrunBox::FLAG_SAMPLE_DURATION
|
||||
|
@ -257,7 +257,7 @@ mod tests {
|
|||
assert_eq!(buf.len(), src_box.box_size() as usize);
|
||||
|
||||
let mut reader = buf.as_slice();
|
||||
let header = BoxHeader::read_sync(&mut reader).unwrap().unwrap();
|
||||
let header = BoxHeader::read(&mut reader, &mut 0).await.unwrap().unwrap();
|
||||
assert_eq!(header.kind, BoxType::TrunBox);
|
||||
assert_eq!(src_box.box_size(), header.size);
|
||||
|
||||
|
|
|
@ -155,8 +155,8 @@ mod tests {
|
|||
use super::*;
|
||||
use crate::mp4box::BoxHeader;
|
||||
|
||||
#[test]
|
||||
fn test_tx3g() {
|
||||
#[tokio::test]
|
||||
async fn test_tx3g() {
|
||||
let src_box = Tx3gBox {
|
||||
data_reference_index: 1,
|
||||
display_flags: 0,
|
||||
|
@ -176,7 +176,7 @@ mod tests {
|
|||
assert_eq!(buf.len(), src_box.box_size() as usize);
|
||||
|
||||
let mut reader = buf.as_slice();
|
||||
let header = BoxHeader::read_sync(&mut reader).unwrap().unwrap();
|
||||
let header = BoxHeader::read(&mut reader, &mut 0).await.unwrap().unwrap();
|
||||
assert_eq!(header.kind, BoxType::Tx3gBox);
|
||||
assert_eq!(src_box.box_size(), header.size);
|
||||
|
||||
|
|
|
@ -68,8 +68,8 @@ mod tests {
|
|||
use super::*;
|
||||
use crate::mp4box::BoxHeader;
|
||||
|
||||
#[test]
|
||||
fn test_udta_empty() {
|
||||
#[tokio::test]
|
||||
async fn test_udta_empty() {
|
||||
let src_box = UdtaBox { meta: None };
|
||||
|
||||
let mut buf = Vec::new();
|
||||
|
@ -77,7 +77,7 @@ mod tests {
|
|||
assert_eq!(buf.len(), src_box.box_size() as usize);
|
||||
|
||||
let mut reader = buf.as_slice();
|
||||
let header = BoxHeader::read_sync(&mut reader).unwrap().unwrap();
|
||||
let header = BoxHeader::read(&mut reader, &mut 0).await.unwrap().unwrap();
|
||||
assert_eq!(header.kind, BoxType::UdtaBox);
|
||||
assert_eq!(header.size, src_box.box_size());
|
||||
|
||||
|
@ -85,8 +85,8 @@ mod tests {
|
|||
assert_eq!(dst_box, src_box);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_udta() {
|
||||
#[tokio::test]
|
||||
async fn test_udta() {
|
||||
let src_box = UdtaBox {
|
||||
meta: Some(MetaBox::default()),
|
||||
};
|
||||
|
@ -96,7 +96,7 @@ mod tests {
|
|||
assert_eq!(buf.len(), src_box.box_size() as usize);
|
||||
|
||||
let mut reader = buf.as_slice();
|
||||
let header = BoxHeader::read_sync(&mut reader).unwrap().unwrap();
|
||||
let header = BoxHeader::read(&mut reader, &mut 0).await.unwrap().unwrap();
|
||||
assert_eq!(header.kind, BoxType::UdtaBox);
|
||||
assert_eq!(header.size, src_box.box_size());
|
||||
|
||||
|
|
|
@ -93,8 +93,8 @@ mod tests {
|
|||
use super::*;
|
||||
use crate::mp4box::BoxHeader;
|
||||
|
||||
#[test]
|
||||
fn test_vmhd() {
|
||||
#[tokio::test]
|
||||
async fn test_vmhd() {
|
||||
let src_box = VmhdBox {
|
||||
version: 0,
|
||||
flags: 1,
|
||||
|
@ -110,7 +110,7 @@ mod tests {
|
|||
assert_eq!(buf.len(), src_box.box_size() as usize);
|
||||
|
||||
let mut reader = buf.as_slice();
|
||||
let header = BoxHeader::read_sync(&mut reader).unwrap().unwrap();
|
||||
let header = BoxHeader::read(&mut reader, &mut 0).await.unwrap().unwrap();
|
||||
assert_eq!(header.kind, BoxType::VmhdBox);
|
||||
assert_eq!(src_box.box_size(), header.size);
|
||||
|
||||
|
|
|
@ -169,8 +169,8 @@ mod tests {
|
|||
use super::*;
|
||||
use crate::mp4box::BoxHeader;
|
||||
|
||||
#[test]
|
||||
fn test_vpcc() {
|
||||
#[tokio::test]
|
||||
async fn test_vpcc() {
|
||||
let src_box = Vp09Box::new(&Vp9Config {
|
||||
width: 1920,
|
||||
height: 1080,
|
||||
|
@ -180,7 +180,7 @@ mod tests {
|
|||
assert_eq!(buf.len(), src_box.box_size() as usize);
|
||||
|
||||
let mut reader = buf.as_slice();
|
||||
let header = BoxHeader::read_sync(&mut reader).unwrap().unwrap();
|
||||
let header = BoxHeader::read(&mut reader, &mut 0).await.unwrap().unwrap();
|
||||
assert_eq!(header.kind, BoxType::Vp09Box);
|
||||
assert_eq!(src_box.box_size(), header.size);
|
||||
|
||||
|
|
|
@ -101,8 +101,8 @@ mod tests {
|
|||
use super::*;
|
||||
use crate::mp4box::BoxHeader;
|
||||
|
||||
#[test]
|
||||
fn test_vpcc() {
|
||||
#[tokio::test]
|
||||
async fn test_vpcc() {
|
||||
let src_box = VpccBox {
|
||||
version: VpccBox::DEFAULT_VERSION,
|
||||
flags: 0,
|
||||
|
@ -121,7 +121,7 @@ mod tests {
|
|||
assert_eq!(buf.len(), src_box.box_size() as usize);
|
||||
|
||||
let mut reader = buf.as_slice();
|
||||
let header = BoxHeader::read_sync(&mut reader).unwrap().unwrap();
|
||||
let header = BoxHeader::read(&mut reader, &mut 0).await.unwrap().unwrap();
|
||||
assert_eq!(header.kind, BoxType::VpccBox);
|
||||
assert_eq!(src_box.box_size(), header.size);
|
||||
|
||||
|
|
250
tests/lib.rs
250
tests/lib.rs
|
@ -1,210 +1,54 @@
|
|||
use mp4::{AudioObjectType, AvcProfile, ChannelConfig, MediaType, SampleFreqIndex, TrackType};
|
||||
use std::fs::{self, File};
|
||||
use std::io::BufReader;
|
||||
use std::time::Duration;
|
||||
use glob::glob;
|
||||
use mp4::TrackType;
|
||||
use tokio::fs::File;
|
||||
use tokio::io::BufReader;
|
||||
|
||||
#[test]
|
||||
fn test_read_mp4() {
|
||||
let mut mp4 = get_reader("tests/samples/minimal.mp4");
|
||||
#[tokio::test]
|
||||
async fn test_read_mp4() {
|
||||
let paths = glob("./assets/videos/*.mp4").expect("Failed to read glob pattern");
|
||||
|
||||
assert_eq!(2591, mp4.size());
|
||||
for path in paths {
|
||||
if let Ok(path) = path {
|
||||
println!("\n{}", path.display());
|
||||
let f = File::open(path).await.unwrap();
|
||||
let mut reader = BufReader::new(f);
|
||||
|
||||
// ftyp.
|
||||
assert_eq!(4, mp4.compatible_brands().len());
|
||||
let mut mp4_file = mp4::Mp4File::new(&mut reader);
|
||||
println!(
|
||||
"streaming possible: {}",
|
||||
mp4_file.read_header().await.unwrap()
|
||||
);
|
||||
|
||||
// Check compatible_brands.
|
||||
let brands = vec![
|
||||
String::from("isom"),
|
||||
String::from("iso2"),
|
||||
String::from("avc1"),
|
||||
String::from("mp41"),
|
||||
];
|
||||
let mut keys = mp4_file
|
||||
.tracks
|
||||
.iter()
|
||||
.filter(|&(_, v)| v.track_type() == TrackType::Video)
|
||||
.map(|(k, _)| *k);
|
||||
|
||||
for b in brands {
|
||||
let t = mp4.compatible_brands().iter().any(|x| x.to_string() == b);
|
||||
assert!(t);
|
||||
let track_id = keys.next().unwrap();
|
||||
let samples_len = mp4_file.tracks.get(&track_id).unwrap().samples.len();
|
||||
|
||||
for idx in 0..samples_len {
|
||||
let samp = mp4_file.tracks.get(&track_id).unwrap().samples[idx].clone();
|
||||
|
||||
let data = mp4_file
|
||||
.read_sample_data(track_id, idx)
|
||||
.await
|
||||
.unwrap()
|
||||
.map(|x| x.slice(0..10));
|
||||
|
||||
// println!(
|
||||
// "[{} {} {}] {} - <{}> {} +{} {:?}",
|
||||
// idx + 1,
|
||||
// samp.chunk_id,
|
||||
// samp.offset,
|
||||
// samp.is_sync,
|
||||
// samp.size,
|
||||
// samp.start_time,
|
||||
// samp.rendering_offset,
|
||||
// data.as_deref()
|
||||
// );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
assert_eq!(mp4.duration(), Duration::from_millis(62));
|
||||
assert_eq!(mp4.timescale(), 1000);
|
||||
assert_eq!(mp4.tracks().len(), 2);
|
||||
|
||||
let sample_count = mp4.sample_count(1).unwrap();
|
||||
assert_eq!(sample_count, 1);
|
||||
let sample_1_1 = mp4.read_sample(1, 1).unwrap().unwrap();
|
||||
assert_eq!(sample_1_1.bytes.len(), 751);
|
||||
assert_eq!(
|
||||
sample_1_1,
|
||||
mp4::Mp4Sample {
|
||||
start_time: 0,
|
||||
duration: 512,
|
||||
rendering_offset: 0,
|
||||
is_sync: true,
|
||||
bytes: mp4::Bytes::from(vec![0x0u8; 751]),
|
||||
}
|
||||
);
|
||||
let eos = mp4.read_sample(1, 2).unwrap();
|
||||
assert!(eos.is_none());
|
||||
|
||||
let sample_count = mp4.sample_count(2).unwrap();
|
||||
assert_eq!(sample_count, 3);
|
||||
let sample_2_1 = mp4.read_sample(2, 1).unwrap().unwrap();
|
||||
assert_eq!(sample_2_1.bytes.len(), 179);
|
||||
assert_eq!(
|
||||
sample_2_1,
|
||||
mp4::Mp4Sample {
|
||||
start_time: 0,
|
||||
duration: 1024,
|
||||
rendering_offset: 0,
|
||||
is_sync: true,
|
||||
bytes: mp4::Bytes::from(vec![0x0u8; 179]),
|
||||
}
|
||||
);
|
||||
|
||||
let sample_2_2 = mp4.read_sample(2, 2).unwrap().unwrap();
|
||||
assert_eq!(
|
||||
sample_2_2,
|
||||
mp4::Mp4Sample {
|
||||
start_time: 1024,
|
||||
duration: 1024,
|
||||
rendering_offset: 0,
|
||||
is_sync: true,
|
||||
bytes: mp4::Bytes::from(vec![0x0u8; 180]),
|
||||
}
|
||||
);
|
||||
|
||||
let sample_2_3 = mp4.read_sample(2, 3).unwrap().unwrap();
|
||||
assert_eq!(
|
||||
sample_2_3,
|
||||
mp4::Mp4Sample {
|
||||
start_time: 2048,
|
||||
duration: 896,
|
||||
rendering_offset: 0,
|
||||
is_sync: true,
|
||||
bytes: mp4::Bytes::from(vec![0x0u8; 160]),
|
||||
}
|
||||
);
|
||||
|
||||
let eos = mp4.read_sample(2, 4).unwrap();
|
||||
assert!(eos.is_none());
|
||||
|
||||
// track #1
|
||||
let track1 = mp4.tracks().get(&1).unwrap();
|
||||
assert_eq!(track1.track_id(), 1);
|
||||
assert_eq!(track1.track_type().unwrap(), TrackType::Video);
|
||||
assert_eq!(track1.media_type().unwrap(), MediaType::H264);
|
||||
assert_eq!(track1.video_profile().unwrap(), AvcProfile::AvcHigh);
|
||||
assert_eq!(track1.width(), 320);
|
||||
assert_eq!(track1.height(), 240);
|
||||
assert_eq!(track1.bitrate(), 150200);
|
||||
assert_eq!(track1.frame_rate(), 25.00);
|
||||
|
||||
// track #2
|
||||
let track2 = mp4.tracks().get(&2).unwrap();
|
||||
assert_eq!(track2.track_type().unwrap(), TrackType::Audio);
|
||||
assert_eq!(track2.media_type().unwrap(), MediaType::AAC);
|
||||
assert_eq!(
|
||||
track2.audio_profile().unwrap(),
|
||||
AudioObjectType::AacLowComplexity
|
||||
);
|
||||
assert_eq!(
|
||||
track2.sample_freq_index().unwrap(),
|
||||
SampleFreqIndex::Freq48000
|
||||
);
|
||||
assert_eq!(track2.channel_config().unwrap(), ChannelConfig::Mono);
|
||||
assert_eq!(track2.bitrate(), 67695);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_read_extended_audio_object_type() {
|
||||
// Extended audio object type and sample rate index of 15
|
||||
let mp4 = get_reader("tests/samples/extended_audio_object_type.mp4");
|
||||
|
||||
let track = mp4.tracks().get(&1).unwrap();
|
||||
assert_eq!(track.track_type().unwrap(), TrackType::Audio);
|
||||
assert_eq!(track.media_type().unwrap(), MediaType::AAC);
|
||||
assert_eq!(
|
||||
track.audio_profile().unwrap(),
|
||||
AudioObjectType::AudioLosslessCoding
|
||||
);
|
||||
assert_eq!(
|
||||
track
|
||||
.trak
|
||||
.mdia
|
||||
.minf
|
||||
.stbl
|
||||
.stsd
|
||||
.mp4a
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.esds
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.es_desc
|
||||
.dec_config
|
||||
.dec_specific
|
||||
.freq_index,
|
||||
15
|
||||
);
|
||||
assert_eq!(track.channel_config().unwrap(), ChannelConfig::Stereo);
|
||||
assert_eq!(track.bitrate(), 839250);
|
||||
}
|
||||
|
||||
fn get_reader(path: &str) -> Mp4Reader<BufReader<File>> {
|
||||
let f = File::open(path).unwrap();
|
||||
let f_size = f.metadata().unwrap().len();
|
||||
let mut reader = BufReader::new(f);
|
||||
|
||||
let mp4_file = mp4::Mp4File::new(&mut reader);
|
||||
|
||||
mp4::Mp4File::read_header(reader, f_size).unwrap()
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_read_metadata() {
|
||||
let want_poster = fs::read("tests/samples/big_buck_bunny.jpg").unwrap();
|
||||
let want_summary = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed non risus. Suspendisse lectus tortor, dignissim sit amet, adipiscing nec, ultricies sed, dolor. Cras elementum ultrices diam. Maecenas ligula massa, varius a, semper congue, euismod non, mi. Proin porttitor, orci nec nonummy molestie, enim est eleifend mi, non fermentum diam nisl sit amet erat. Duis semper. Duis arcu massa, scelerisque vitae, consequat in, pretium a, enim. Pellentesque congue. Ut in risus volutpat libero pharetra tempor. Cras vestibulum bibendum augue.";
|
||||
let mp4 = get_reader("tests/samples/big_buck_bunny_metadata.m4v");
|
||||
let metadata = mp4.metadata();
|
||||
assert_eq!(metadata.title(), Some("Big Buck Bunny".into()));
|
||||
assert_eq!(metadata.year(), Some(2008));
|
||||
assert_eq!(metadata.summary(), Some(want_summary.into()));
|
||||
|
||||
assert!(metadata.poster().is_some());
|
||||
let poster = metadata.poster().unwrap();
|
||||
assert_eq!(poster.len(), want_poster.len());
|
||||
assert_eq!(poster, want_poster.as_slice());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_read_fragments() {
|
||||
let mp4 = get_reader("tests/samples/minimal_init.mp4");
|
||||
|
||||
assert_eq!(692, mp4.size());
|
||||
assert_eq!(5, mp4.compatible_brands().len());
|
||||
|
||||
let sample_count = mp4.sample_count(1).unwrap();
|
||||
assert_eq!(sample_count, 0);
|
||||
|
||||
let f = File::open("tests/samples/minimal_fragment.m4s").unwrap();
|
||||
let f_size = f.metadata().unwrap().len();
|
||||
let frag_reader = BufReader::new(f);
|
||||
|
||||
let mut mp4_fragment = mp4.read_fragment_header(frag_reader, f_size).unwrap();
|
||||
let sample_count = mp4_fragment.sample_count(1).unwrap();
|
||||
assert_eq!(sample_count, 1);
|
||||
let sample_1_1 = mp4_fragment.read_sample(1, 1).unwrap().unwrap();
|
||||
assert_eq!(sample_1_1.bytes.len(), 751);
|
||||
assert_eq!(
|
||||
sample_1_1,
|
||||
mp4::Mp4Sample {
|
||||
start_time: 0,
|
||||
duration: 512,
|
||||
rendering_offset: 0,
|
||||
is_sync: true,
|
||||
bytes: mp4::Bytes::from(vec![0x0u8; 751]),
|
||||
}
|
||||
);
|
||||
let eos = mp4_fragment.read_sample(1, 2);
|
||||
assert!(eos.is_err());
|
||||
}
|
||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 132 KiB |
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Loading…
Reference in a new issue