Skip to content
Draft
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
2 changes: 1 addition & 1 deletion src/any.rs
Original file line number Diff line number Diff line change
Expand Up @@ -281,7 +281,7 @@ any! {
Fiel,
Hev1, Hvc1,
Hvcc,
Mp4a,
Mp4a, Mp4v,
Esds,
Tx3g,
Ftab,
Expand Down
7 changes: 7 additions & 0 deletions src/moov/trak/mdia/minf/stbl/stsd/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ mod ftab;
mod h264;
mod hevc;
mod mp4a;
mod mp4v;
mod opus;
mod pasp;
mod pcm;
Expand All @@ -35,6 +36,7 @@ pub use ftab::*;
pub use h264::*;
pub use hevc::*;
pub use mp4a::*;
pub use mp4v::*;
pub use opus::*;
pub use pasp::*;
pub use pcm::*;
Expand Down Expand Up @@ -78,6 +80,9 @@ pub enum Codec {
// AAC
Mp4a(Mp4a),

// MPEG video
Mp4v(Mp4v),

// Text
Tx3g(Tx3g),

Expand Down Expand Up @@ -125,6 +130,7 @@ impl Decode for Codec {
Any::Vp08(atom) => atom.into(),
Any::Vp09(atom) => atom.into(),
Any::Mp4a(atom) => atom.into(),
Any::Mp4v(atom) => atom.into(),
Any::Tx3g(atom) => atom.into(),
Any::Av01(atom) => atom.into(),
Any::Opus(atom) => atom.into(),
Expand Down Expand Up @@ -160,6 +166,7 @@ impl Encode for Codec {
Self::Vp08(atom) => atom.encode(buf),
Self::Vp09(atom) => atom.encode(buf),
Self::Mp4a(atom) => atom.encode(buf),
Self::Mp4v(atom) => atom.encode(buf),
Self::Tx3g(atom) => atom.encode(buf),
Self::Av01(atom) => atom.encode(buf),
Self::Opus(atom) => atom.encode(buf),
Expand Down
100 changes: 100 additions & 0 deletions src/moov/trak/mdia/minf/stbl/stsd/mp4v.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
use crate::*;

#[derive(Debug, Clone, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct Mp4v {
pub visual: Visual,
pub esds: Esds,
pub btrt: Option<Btrt>,
pub taic: Option<Taic>,
}

impl Atom for Mp4v {
const KIND: FourCC = FourCC::new(b"mp4v");

fn decode_body<B: Buf>(buf: &mut B) -> Result<Self> {
let visual = Visual::decode(buf)?;

let mut btrt = None;
let mut esds = None;
let mut taic = None;

while let Some(atom) = Any::decode_maybe(buf)? {
match atom {
Any::Btrt(atom) => btrt = atom.into(),
Any::Esds(atom) => esds = atom.into(),
Any::Taic(atom) => taic = atom.into(),
unknown => Self::decode_unknown(&unknown)?,
}
}

Ok(Mp4v {
visual,
esds: esds.ok_or(Error::MissingBox(Esds::KIND))?,
btrt,
taic,
})
}

fn encode_body<B: BufMut>(&self, buf: &mut B) -> Result<()> {
self.visual.encode(buf)?;
self.esds.encode(buf)?;
self.btrt.encode(buf)?;
self.taic.encode(buf)?;

Ok(())
}
}

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn test_mp4v() {
let expected = Mp4v {
visual: Visual {
data_reference_index: 0,
width: 100,
height: 80,
horizresolution: 72.into(),
vertresolution: 48.into(),
frame_count: 3,
compressor: "test".into(),
depth: 10,
},
esds: Esds {
es_desc: esds::EsDescriptor {
es_id: 2,
dec_config: esds::DecoderConfig {
object_type_indication: 0x20,
stream_type: 0x04,
up_stream: 0,
buffer_size_db: Default::default(),
max_bitrate: 4000000,
avg_bitrate: 2000000,
// TODO: rework this to be a video version
dec_specific: esds::DecoderSpecific {
profile: 2,
freq_index: 4,
chan_conf: 2,
},
},
sl_config: esds::SLConfig::default(),
},
},
btrt: Some(Btrt {
buffer_size_db: 1,
max_bitrate: 2,
avg_bitrate: 3,
}),
taic: None,
};
let mut buf = Vec::new();
expected.encode(&mut buf).unwrap();

let mut buf = buf.as_ref();
let decoded = Mp4v::decode(&mut buf).unwrap();
assert_eq!(decoded, expected);
}
}