mirror of
https://github.com/alfg/mp4-rust.git
synced 2024-05-20 01:08:06 +00:00
ace2799c75
This introduces the 'Metadata' trait to enable access to common video metadata such title, year, cover art and more. Reading 'title', 'description', 'poster' and 'year' metadata is implemented here.
120 lines
3 KiB
Rust
120 lines
3 KiB
Rust
use serde::Serialize;
|
|
use std::io::{Read, Seek, SeekFrom, Write};
|
|
|
|
use crate::mp4box::*;
|
|
use crate::mp4box::{mvex::MvexBox, mvhd::MvhdBox, trak::TrakBox, udta::UdtaBox};
|
|
|
|
#[derive(Debug, Clone, PartialEq, Default, Serialize)]
|
|
pub struct MoovBox {
|
|
pub mvhd: MvhdBox,
|
|
|
|
#[serde(skip_serializing_if = "Option::is_none")]
|
|
pub mvex: Option<MvexBox>,
|
|
|
|
#[serde(rename = "trak")]
|
|
pub traks: Vec<TrakBox>,
|
|
|
|
#[serde(skip_serializing_if = "Option::is_none")]
|
|
pub udta: Option<UdtaBox>,
|
|
}
|
|
|
|
impl MoovBox {
|
|
pub fn get_type(&self) -> BoxType {
|
|
BoxType::MoovBox
|
|
}
|
|
|
|
pub fn get_size(&self) -> u64 {
|
|
let mut size = HEADER_SIZE + self.mvhd.box_size();
|
|
for trak in self.traks.iter() {
|
|
size += trak.box_size();
|
|
}
|
|
size
|
|
}
|
|
}
|
|
|
|
impl Mp4Box for MoovBox {
|
|
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!("traks={}", self.traks.len());
|
|
Ok(s)
|
|
}
|
|
}
|
|
|
|
impl<R: Read + Seek> ReadBox<&mut R> for MoovBox {
|
|
fn read_box(reader: &mut R, size: u64) -> Result<Self> {
|
|
let start = box_start(reader)?;
|
|
|
|
let mut mvhd = None;
|
|
let mut udta = None;
|
|
let mut mvex = None;
|
|
let mut traks = Vec::new();
|
|
|
|
let mut current = reader.seek(SeekFrom::Current(0))?;
|
|
let end = start + size;
|
|
while current < end {
|
|
// Get box header.
|
|
let header = BoxHeader::read(reader)?;
|
|
let BoxHeader { name, size: s } = header;
|
|
|
|
match name {
|
|
BoxType::MvhdBox => {
|
|
mvhd = Some(MvhdBox::read_box(reader, s)?);
|
|
}
|
|
BoxType::MvexBox => {
|
|
mvex = Some(MvexBox::read_box(reader, s)?);
|
|
}
|
|
BoxType::TrakBox => {
|
|
let trak = TrakBox::read_box(reader, s)?;
|
|
traks.push(trak);
|
|
}
|
|
BoxType::UdtaBox => {
|
|
udta = Some(UdtaBox::read_box(reader, s)?);
|
|
}
|
|
_ => {
|
|
// XXX warn!()
|
|
skip_box(reader, s)?;
|
|
}
|
|
}
|
|
|
|
current = reader.seek(SeekFrom::Current(0))?;
|
|
}
|
|
|
|
if mvhd.is_none() {
|
|
return Err(Error::BoxNotFound(BoxType::MvhdBox));
|
|
}
|
|
|
|
skip_bytes_to(reader, start + size)?;
|
|
|
|
Ok(MoovBox {
|
|
mvhd: mvhd.unwrap(),
|
|
udta,
|
|
mvex,
|
|
traks,
|
|
})
|
|
}
|
|
}
|
|
|
|
impl<W: Write> WriteBox<&mut W> for MoovBox {
|
|
fn write_box(&self, writer: &mut W) -> Result<u64> {
|
|
let size = self.box_size();
|
|
BoxHeader::new(self.box_type(), size).write(writer)?;
|
|
|
|
self.mvhd.write_box(writer)?;
|
|
for trak in self.traks.iter() {
|
|
trak.write_box(writer)?;
|
|
}
|
|
Ok(0)
|
|
}
|
|
}
|