1
0
Fork 0
mirror of https://github.com/alfg/mp4-rust.git synced 2024-06-10 17:09:22 +00:00

Add necessary sub-boxes to stbl box

This commit is contained in:
Ian Jun 2020-07-30 14:01:09 +09:00
parent 34da7f9637
commit f09085f75e
9 changed files with 652 additions and 33 deletions

94
src/atoms/co64.rs Normal file
View file

@ -0,0 +1,94 @@
use std::io::{BufReader, Seek, Read, BufWriter, Write};
use byteorder::{BigEndian, ReadBytesExt, WriteBytesExt};
use crate::*;
#[derive(Debug, Default, PartialEq)]
pub struct Co64Box {
pub version: u8,
pub flags: u32,
pub entries: Vec<u64>,
}
impl Mp4Box for Co64Box {
fn box_type() -> BoxType {
BoxType::Co64Box
}
fn box_size(&self) -> u64 {
HEADER_SIZE + HEADER_EXT_SIZE + 4 + (8 * self.entries.len() as u64)
}
}
impl<R: Read + Seek> ReadBox<&mut BufReader<R>> for Co64Box {
fn read_box(reader: &mut BufReader<R>, size: u64) -> Result<Self> {
let start = get_box_start(reader)?;
let (version, flags) = read_box_header_ext(reader)?;
let entry_count = reader.read_u32::<BigEndian>()?;
let mut entries = Vec::with_capacity(entry_count as usize);
for _i in 0..entry_count {
let chunk_offset = reader.read_u64::<BigEndian>()?;
entries.push(chunk_offset);
}
skip_read_to(reader, start + size)?;
Ok(Co64Box {
version,
flags,
entries,
})
}
}
impl<W: Write> WriteBox<&mut BufWriter<W>> for Co64Box {
fn write_box(&self, writer: &mut BufWriter<W>) -> Result<u64> {
let size = self.box_size();
BoxHeader::new(Self::box_type(), size).write_box(writer)?;
write_box_header_ext(writer, self.version, self.flags)?;
writer.write_u32::<BigEndian>(self.entries.len() as u32)?;
for chunk_offset in self.entries.iter() {
writer.write_u64::<BigEndian>(*chunk_offset)?;
}
Ok(size)
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::read_box_header;
use std::io::Cursor;
#[test]
fn test_co64() {
let src_box = Co64Box {
version: 0,
flags: 0,
entries: vec![267, 1970, 2535, 2803, 11843, 22223, 33584],
};
let mut buf = Vec::new();
{
let mut writer = BufWriter::new(&mut buf);
src_box.write_box(&mut writer).unwrap();
}
assert_eq!(buf.len(), src_box.box_size() as usize);
{
let mut reader = BufReader::new(Cursor::new(&buf));
let header = read_box_header(&mut reader).unwrap();
assert_eq!(header.name, BoxType::Co64Box);
assert_eq!(src_box.box_size(), header.size);
let dst_box = Co64Box::read_box(&mut reader, header.size).unwrap();
assert_eq!(src_box, dst_box);
}
}
}

View file

@ -237,4 +237,10 @@ mod tests {
let ftyp_fcc2 = ftyp_value.into();
assert_eq!(ftyp_fcc, ftyp_fcc2);
}
// #[test]
// fn test_a() {
// let a: u32 = FourCC::from("co64").into();
// assert_eq!(a, 0);
// }
}

View file

@ -1,13 +1,26 @@
use std::io::{BufReader, Seek, Read, BufWriter, Write};
use crate::*;
use crate::atoms::{stts::SttsBox, stsd::StsdBox};
use crate::atoms::{
stsd::StsdBox,
stts::SttsBox,
stss::StssBox,
stsc::StscBox,
stsz::StszBox,
stco::StcoBox,
co64::Co64Box,
};
#[derive(Debug, Default)]
pub struct StblBox {
pub stts: Option<SttsBox>,
pub stsd: Option<StsdBox>,
pub stts: Option<SttsBox>,
pub stss: Option<StssBox>,
pub stsc: Option<StscBox>,
pub stsz: Option<StszBox>,
pub stco: Option<StcoBox>,
pub co64: Option<Co64Box>,
}
impl StblBox {
@ -17,17 +30,32 @@ impl StblBox {
}
impl Mp4Box for StblBox {
fn box_type(&self) -> BoxType {
fn box_type() -> BoxType {
BoxType::StblBox
}
fn box_size(&self) -> u64 {
let mut size = HEADER_SIZE;
if let Some(stsd) = &self.stsd {
size += stsd.box_size();
}
if let Some(stts) = &self.stts {
size += stts.box_size();
}
if let Some(stsd) = &self.stsd {
size += stsd.box_size();
if let Some(stss) = &self.stss {
size += stss.box_size();
}
if let Some(stsc) = &self.stsc {
size += stsc.box_size();
}
if let Some(stsz) = &self.stsz {
size += stsz.box_size();
}
if let Some(stco) = &self.stco {
size += stco.box_size();
}
if let Some(co64) = &self.co64 {
size += co64.box_size();
}
size
}
@ -35,26 +63,53 @@ impl Mp4Box for StblBox {
impl<R: Read + Seek> ReadBox<&mut BufReader<R>> for StblBox {
fn read_box(reader: &mut BufReader<R>, size: u64) -> Result<Self> {
let start = get_box_start(reader)?;
let mut stbl = StblBox::new();
let start = 0u64;
while start < size {
let mut current = reader.seek(SeekFrom::Current(0))?;
let end = start + size;
while current < end {
// Get box header.
let header = read_box_header(reader, start)?;
let header = read_box_header(reader)?;
let BoxHeader{ name, size: s } = header;
match name {
BoxType::SttsBox => {
let stts = SttsBox::read_box(reader, s)?;
stbl.stts = Some(stts);
}
BoxType::StsdBox => {
let stsd = StsdBox::read_box(reader, s)?;
stbl.stsd = Some(stsd);
}
_ => break
BoxType::SttsBox => {
let stts = SttsBox::read_box(reader, s)?;
stbl.stts = Some(stts);
}
BoxType::StssBox => {
let stss = StssBox::read_box(reader, s)?;
stbl.stss = Some(stss);
}
BoxType::StscBox => {
let stsc = StscBox::read_box(reader, s)?;
stbl.stsc = Some(stsc);
}
BoxType::StszBox => {
let stsz = StszBox::read_box(reader, s)?;
stbl.stsz = Some(stsz);
}
BoxType::StcoBox => {
let stco = StcoBox::read_box(reader, s)?;
stbl.stco = Some(stco);
}
BoxType::Co64Box => {
let co64 = Co64Box::read_box(reader, s)?;
stbl.co64 = Some(co64);
}
_ => {}
}
current = reader.seek(SeekFrom::Current(0))?;
}
skip_read_to(reader, start + size)?;
Ok(stbl)
}
}
@ -62,13 +117,28 @@ impl<R: Read + Seek> ReadBox<&mut BufReader<R>> for StblBox {
impl<W: Write> WriteBox<&mut BufWriter<W>> for StblBox {
fn write_box(&self, writer: &mut BufWriter<W>) -> Result<u64> {
let size = self.box_size();
BoxHeader::new(self.box_type(), size).write_box(writer)?;
BoxHeader::new(Self::box_type(), size).write_box(writer)?;
if let Some(stsd) = &self.stsd {
stsd.write_box(writer)?;
}
if let Some(stts) = &self.stts {
stts.write_box(writer)?;
}
if let Some(stsd) = &self.stsd {
stsd.write_box(writer)?;
if let Some(stss) = &self.stss {
stss.write_box(writer)?;
}
if let Some(stsc) = &self.stsc {
stsc.write_box(writer)?;
}
if let Some(stsz) = &self.stsz {
stsz.write_box(writer)?;
}
if let Some(stco) = &self.stco {
stco.write_box(writer)?;
}
if let Some(co64) = &self.co64 {
co64.write_box(writer)?;
}
Ok(size)

94
src/atoms/stco.rs Normal file
View file

@ -0,0 +1,94 @@
use std::io::{BufReader, Seek, Read, BufWriter, Write};
use byteorder::{BigEndian, ReadBytesExt, WriteBytesExt};
use crate::*;
#[derive(Debug, Default, PartialEq)]
pub struct StcoBox {
pub version: u8,
pub flags: u32,
pub entries: Vec<u32>,
}
impl Mp4Box for StcoBox {
fn box_type() -> BoxType {
BoxType::StcoBox
}
fn box_size(&self) -> u64 {
HEADER_SIZE + HEADER_EXT_SIZE + 4 + (4 * self.entries.len() as u64)
}
}
impl<R: Read + Seek> ReadBox<&mut BufReader<R>> for StcoBox {
fn read_box(reader: &mut BufReader<R>, size: u64) -> Result<Self> {
let start = get_box_start(reader)?;
let (version, flags) = read_box_header_ext(reader)?;
let entry_count = reader.read_u32::<BigEndian>()?;
let mut entries = Vec::with_capacity(entry_count as usize);
for _i in 0..entry_count {
let chunk_offset = reader.read_u32::<BigEndian>()?;
entries.push(chunk_offset);
}
skip_read_to(reader, start + size)?;
Ok(StcoBox {
version,
flags,
entries,
})
}
}
impl<W: Write> WriteBox<&mut BufWriter<W>> for StcoBox {
fn write_box(&self, writer: &mut BufWriter<W>) -> Result<u64> {
let size = self.box_size();
BoxHeader::new(Self::box_type(), size).write_box(writer)?;
write_box_header_ext(writer, self.version, self.flags)?;
writer.write_u32::<BigEndian>(self.entries.len() as u32)?;
for chunk_offset in self.entries.iter() {
writer.write_u32::<BigEndian>(*chunk_offset)?;
}
Ok(size)
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::read_box_header;
use std::io::Cursor;
#[test]
fn test_stco() {
let src_box = StcoBox {
version: 0,
flags: 0,
entries: vec![267, 1970, 2535, 2803, 11843, 22223, 33584],
};
let mut buf = Vec::new();
{
let mut writer = BufWriter::new(&mut buf);
src_box.write_box(&mut writer).unwrap();
}
assert_eq!(buf.len(), src_box.box_size() as usize);
{
let mut reader = BufReader::new(Cursor::new(&buf));
let header = read_box_header(&mut reader).unwrap();
assert_eq!(header.name, BoxType::StcoBox);
assert_eq!(src_box.box_size(), header.size);
let dst_box = StcoBox::read_box(&mut reader, header.size).unwrap();
assert_eq!(src_box, dst_box);
}
}
}

118
src/atoms/stsc.rs Normal file
View file

@ -0,0 +1,118 @@
use std::io::{BufReader, Seek, Read, BufWriter, Write};
use byteorder::{BigEndian, ReadBytesExt, WriteBytesExt};
use crate::*;
#[derive(Debug, Default, PartialEq)]
pub struct StscBox {
pub version: u8,
pub flags: u32,
pub entries: Vec<StscEntry>,
}
#[derive(Debug, Default, PartialEq)]
pub struct StscEntry {
pub first_chunk: u32,
pub samples_per_chunk: u32,
pub sample_description_index: u32,
}
impl Mp4Box for StscBox {
fn box_type() -> BoxType {
BoxType::StscBox
}
fn box_size(&self) -> u64 {
HEADER_SIZE + HEADER_EXT_SIZE + 4 + (12 * self.entries.len() as u64)
}
}
impl<R: Read + Seek> ReadBox<&mut BufReader<R>> for StscBox {
fn read_box(reader: &mut BufReader<R>, size: u64) -> Result<Self> {
let start = get_box_start(reader)?;
let (version, flags) = read_box_header_ext(reader)?;
let entry_count = reader.read_u32::<BigEndian>()?;
let mut entries = Vec::with_capacity(entry_count as usize);
for _i in 0..entry_count {
let entry = StscEntry {
first_chunk: reader.read_u32::<BigEndian>()?,
samples_per_chunk: reader.read_u32::<BigEndian>()?,
sample_description_index: reader.read_u32::<BigEndian>()?,
};
entries.push(entry);
}
skip_read_to(reader, start + size)?;
Ok(StscBox {
version,
flags,
entries,
})
}
}
impl<W: Write> WriteBox<&mut BufWriter<W>> for StscBox {
fn write_box(&self, writer: &mut BufWriter<W>) -> Result<u64> {
let size = self.box_size();
BoxHeader::new(Self::box_type(), size).write_box(writer)?;
write_box_header_ext(writer, self.version, self.flags)?;
writer.write_u32::<BigEndian>(self.entries.len() as u32)?;
for entry in self.entries.iter() {
writer.write_u32::<BigEndian>(entry.first_chunk)?;
writer.write_u32::<BigEndian>(entry.samples_per_chunk)?;
writer.write_u32::<BigEndian>(entry.sample_description_index)?;
}
Ok(size)
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::read_box_header;
use std::io::Cursor;
#[test]
fn test_stsc() {
let src_box = StscBox {
version: 0,
flags: 0,
entries: vec![
StscEntry {
first_chunk: 1,
samples_per_chunk: 1,
sample_description_index: 1,
},
StscEntry {
first_chunk: 19026,
samples_per_chunk: 14,
sample_description_index: 1
},
],
};
let mut buf = Vec::new();
{
let mut writer = BufWriter::new(&mut buf);
src_box.write_box(&mut writer).unwrap();
}
assert_eq!(buf.len(), src_box.box_size() as usize);
{
let mut reader = BufReader::new(Cursor::new(&buf));
let header = read_box_header(&mut reader).unwrap();
assert_eq!(header.name, BoxType::StscBox);
assert_eq!(src_box.box_size(), header.size);
let dst_box = StscBox::read_box(&mut reader, header.size).unwrap();
assert_eq!(src_box, dst_box);
}
}
}

View file

@ -1,5 +1,5 @@
use std::io::{BufReader, SeekFrom, Seek, Read, BufWriter, Write};
use byteorder::{BigEndian, ReadBytesExt};
use std::io::{BufReader, Seek, Read, BufWriter, Write};
use byteorder::{BigEndian, ReadBytesExt, WriteBytesExt};
use crate::*;
use crate::atoms::{avc::Avc1Box, mp4a::Mp4aBox};
@ -14,7 +14,7 @@ pub struct StsdBox {
}
impl Mp4Box for StsdBox {
fn box_type(&self) -> BoxType {
fn box_type() -> BoxType {
BoxType::StsdBox
}
@ -31,17 +31,17 @@ impl Mp4Box for StsdBox {
impl<R: Read + Seek> ReadBox<&mut BufReader<R>> for StsdBox {
fn read_box(reader: &mut BufReader<R>, size: u64) -> Result<Self> {
let current = reader.seek(SeekFrom::Current(0))?; // Current cursor position.
let start = get_box_start(reader)?;
let (version, flags) = read_box_header_ext(reader)?;
let _entry_count = reader.read_u32::<BigEndian>()?;
reader.read_u32::<BigEndian>()?; // XXX entry_count
let mut avc1 = None;
let mut mp4a = None;
// Get box header.
let header = read_box_header(reader, 0)?;
let header = read_box_header(reader)?;
let BoxHeader{ name, size: s } = header;
match name {
@ -54,7 +54,7 @@ impl<R: Read + Seek> ReadBox<&mut BufReader<R>> for StsdBox {
_ => {}
}
skip_read(reader, current, size)?;
skip_read_to(reader, start + size)?;
Ok(StsdBox {
version,
@ -66,8 +66,20 @@ impl<R: Read + Seek> ReadBox<&mut BufReader<R>> for StsdBox {
}
impl<W: Write> WriteBox<&mut BufWriter<W>> for StsdBox {
fn write_box(&self, _writer: &mut BufWriter<W>) -> Result<u64> {
// TODO
Ok(0)
fn write_box(&self, writer: &mut BufWriter<W>) -> Result<u64> {
let size = self.box_size();
BoxHeader::new(Self::box_type(), size).write_box(writer)?;
write_box_header_ext(writer, self.version, self.flags)?;
writer.write_u32::<BigEndian>(1)?; // entry_count
if let Some(avc1) = &self.avc1 {
avc1.write_box(writer)?;
} else if let Some(mp4a) = &self.mp4a {
mp4a.write_box(writer)?;
}
Ok(size)
}
}

94
src/atoms/stss.rs Normal file
View file

@ -0,0 +1,94 @@
use std::io::{BufReader, Seek, Read, BufWriter, Write};
use byteorder::{BigEndian, ReadBytesExt, WriteBytesExt};
use crate::*;
#[derive(Debug, Default, PartialEq)]
pub struct StssBox {
pub version: u8,
pub flags: u32,
pub entries: Vec<u32>,
}
impl Mp4Box for StssBox {
fn box_type() -> BoxType {
BoxType::StssBox
}
fn box_size(&self) -> u64 {
HEADER_SIZE + HEADER_EXT_SIZE + 4 + (4 * self.entries.len() as u64)
}
}
impl<R: Read + Seek> ReadBox<&mut BufReader<R>> for StssBox {
fn read_box(reader: &mut BufReader<R>, size: u64) -> Result<Self> {
let start = get_box_start(reader)?;
let (version, flags) = read_box_header_ext(reader)?;
let entry_count = reader.read_u32::<BigEndian>()?;
let mut entries = Vec::with_capacity(entry_count as usize);
for _i in 0..entry_count {
let sample_number = reader.read_u32::<BigEndian>()?;
entries.push(sample_number);
}
skip_read_to(reader, start + size)?;
Ok(StssBox {
version,
flags,
entries,
})
}
}
impl<W: Write> WriteBox<&mut BufWriter<W>> for StssBox {
fn write_box(&self, writer: &mut BufWriter<W>) -> Result<u64> {
let size = self.box_size();
BoxHeader::new(Self::box_type(), size).write_box(writer)?;
write_box_header_ext(writer, self.version, self.flags)?;
writer.write_u32::<BigEndian>(self.entries.len() as u32)?;
for sample_number in self.entries.iter() {
writer.write_u32::<BigEndian>(*sample_number)?;
}
Ok(size)
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::read_box_header;
use std::io::Cursor;
#[test]
fn test_stss() {
let src_box = StssBox {
version: 0,
flags: 0,
entries: vec![1, 61, 121, 181, 241, 301, 361, 421, 481],
};
let mut buf = Vec::new();
{
let mut writer = BufWriter::new(&mut buf);
src_box.write_box(&mut writer).unwrap();
}
assert_eq!(buf.len(), src_box.box_size() as usize);
{
let mut reader = BufReader::new(Cursor::new(&buf));
let header = read_box_header(&mut reader).unwrap();
assert_eq!(header.name, BoxType::StssBox);
assert_eq!(src_box.box_size(), header.size);
let dst_box = StssBox::read_box(&mut reader, header.size).unwrap();
assert_eq!(src_box, dst_box);
}
}
}

130
src/atoms/stsz.rs Normal file
View file

@ -0,0 +1,130 @@
use std::io::{BufReader, Seek, Read, BufWriter, Write};
use byteorder::{BigEndian, ReadBytesExt, WriteBytesExt};
use crate::*;
#[derive(Debug, Default, PartialEq)]
pub struct StszBox {
pub version: u8,
pub flags: u32,
pub sample_size: u32,
pub sample_sizes: Vec<u32>,
}
impl Mp4Box for StszBox {
fn box_type() -> BoxType {
BoxType::StszBox
}
fn box_size(&self) -> u64 {
HEADER_SIZE + HEADER_EXT_SIZE + 8 + (4 * self.sample_sizes.len() as u64)
}
}
impl<R: Read + Seek> ReadBox<&mut BufReader<R>> for StszBox {
fn read_box(reader: &mut BufReader<R>, size: u64) -> Result<Self> {
let start = get_box_start(reader)?;
let (version, flags) = read_box_header_ext(reader)?;
let sample_size = reader.read_u32::<BigEndian>()?;
let sample_count = reader.read_u32::<BigEndian>()?;
let mut sample_sizes = Vec::with_capacity(sample_count as usize);
if sample_size == 0 {
for _i in 0..sample_count {
let sample_number = reader.read_u32::<BigEndian>()?;
sample_sizes.push(sample_number);
}
}
skip_read_to(reader, start + size)?;
Ok(StszBox {
version,
flags,
sample_size,
sample_sizes,
})
}
}
impl<W: Write> WriteBox<&mut BufWriter<W>> for StszBox {
fn write_box(&self, writer: &mut BufWriter<W>) -> Result<u64> {
let size = self.box_size();
BoxHeader::new(Self::box_type(), size).write_box(writer)?;
write_box_header_ext(writer, self.version, self.flags)?;
writer.write_u32::<BigEndian>(self.sample_size)?;
writer.write_u32::<BigEndian>(self.sample_sizes.len() as u32)?;
if self.sample_size == 0 {
for sample_number in self.sample_sizes.iter() {
writer.write_u32::<BigEndian>(*sample_number)?;
}
}
Ok(size)
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::read_box_header;
use std::io::Cursor;
#[test]
fn test_stsz_same_size() {
let src_box = StszBox {
version: 0,
flags: 0,
sample_size: 1165,
sample_sizes: vec![],
};
let mut buf = Vec::new();
{
let mut writer = BufWriter::new(&mut buf);
src_box.write_box(&mut writer).unwrap();
}
assert_eq!(buf.len(), src_box.box_size() as usize);
{
let mut reader = BufReader::new(Cursor::new(&buf));
let header = read_box_header(&mut reader).unwrap();
assert_eq!(header.name, BoxType::StszBox);
assert_eq!(src_box.box_size(), header.size);
let dst_box = StszBox::read_box(&mut reader, header.size).unwrap();
assert_eq!(src_box, dst_box);
}
}
#[test]
fn test_stsz_many_sizes() {
let src_box = StszBox {
version: 0,
flags: 0,
sample_size: 0,
sample_sizes: vec![1165, 11, 11, 8545, 10126, 10866, 9643, 9351, 7730],
};
let mut buf = Vec::new();
{
let mut writer = BufWriter::new(&mut buf);
src_box.write_box(&mut writer).unwrap();
}
assert_eq!(buf.len(), src_box.box_size() as usize);
{
let mut reader = BufReader::new(Cursor::new(&buf));
let header = read_box_header(&mut reader).unwrap();
assert_eq!(header.name, BoxType::StszBox);
assert_eq!(src_box.box_size(), header.size);
let dst_box = StszBox::read_box(&mut reader, header.size).unwrap();
assert_eq!(src_box, dst_box);
}
}
}

View file

@ -1,4 +1,4 @@
use std::io::{BufReader, SeekFrom, Seek, Read, BufWriter, Write};
use std::io::{BufReader, Seek, Read, BufWriter, Write};
use byteorder::{BigEndian, ReadBytesExt, WriteBytesExt};
use crate::*;
@ -18,7 +18,7 @@ pub struct SttsEntry {
}
impl Mp4Box for SttsBox {
fn box_type(&self) -> BoxType {
fn box_type() -> BoxType {
BoxType::SttsBox
}
@ -29,7 +29,7 @@ impl Mp4Box for SttsBox {
impl<R: Read + Seek> ReadBox<&mut BufReader<R>> for SttsBox {
fn read_box(reader: &mut BufReader<R>, size: u64) -> Result<Self> {
let current = reader.seek(SeekFrom::Current(0))?; // Current cursor position.
let start = get_box_start(reader)?;
let (version, flags) = read_box_header_ext(reader)?;
@ -42,7 +42,8 @@ impl<R: Read + Seek> ReadBox<&mut BufReader<R>> for SttsBox {
};
entries.push(entry);
}
skip_read(reader, current, size)?;
skip_read_to(reader, start + size)?;
Ok(SttsBox {
version,
@ -55,7 +56,7 @@ impl<R: Read + Seek> ReadBox<&mut BufReader<R>> for SttsBox {
impl<W: Write> WriteBox<&mut BufWriter<W>> for SttsBox {
fn write_box(&self, writer: &mut BufWriter<W>) -> Result<u64> {
let size = self.box_size();
BoxHeader::new(self.box_type(), size).write_box(writer)?;
BoxHeader::new(Self::box_type(), size).write_box(writer)?;
write_box_header_ext(writer, self.version, self.flags)?;
@ -94,7 +95,7 @@ mod tests {
{
let mut reader = BufReader::new(Cursor::new(&buf));
let header = read_box_header(&mut reader, 0).unwrap();
let header = read_box_header(&mut reader).unwrap();
assert_eq!(header.name, BoxType::SttsBox);
assert_eq!(src_box.box_size(), header.size);
@ -123,7 +124,7 @@ mod tests {
{
let mut reader = BufReader::new(Cursor::new(&buf));
let header = read_box_header(&mut reader, 0).unwrap();
let header = read_box_header(&mut reader).unwrap();
assert_eq!(header.name, BoxType::SttsBox);
assert_eq!(src_box.box_size(), header.size);