Skip to content
Open
Show file tree
Hide file tree
Changes from 3 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 @@ -268,7 +268,7 @@ any! {
Minf,
Stbl,
Stsd,
Avc1,
Avc1, Avc3,
Avcc,
Btrt,
Ccst,
Expand Down
12 changes: 8 additions & 4 deletions src/moov/trak/mdia/minf/stbl/stsd/h264/avc1.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
use crate::*;

const AVC1_CODE: u32 = u32::from_be_bytes(*b"avc1");

#[derive(Debug, Clone, PartialEq, Eq, Default)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct Avc1 {
pub struct AvcSampleEntry<const KIND_CODE: u32> {
pub visual: Visual,
pub avcc: Avcc,
pub btrt: Option<Btrt>,
Expand All @@ -11,8 +13,10 @@ pub struct Avc1 {
pub taic: Option<Taic>,
}

impl Atom for Avc1 {
const KIND: FourCC = FourCC::new(b"avc1");
pub type Avc1 = AvcSampleEntry<{ AVC1_CODE }>;

impl<const KIND_CODE: u32> Atom for AvcSampleEntry<KIND_CODE> {
const KIND: FourCC = FourCC::from_u32(KIND_CODE);

fn decode_body<B: Buf>(buf: &mut B) -> Result<Self> {
let visual = Visual::decode(buf)?;
Expand All @@ -33,7 +37,7 @@ impl Atom for Avc1 {
}
}

Ok(Avc1 {
Ok(Self {
visual,
avcc: avcc.ok_or(Error::MissingBox(Avcc::KIND))?,
btrt,
Expand Down
76 changes: 76 additions & 0 deletions src/moov/trak/mdia/minf/stbl/stsd/h264/avc3.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
use super::avc1::AvcSampleEntry;

const AVC3_CODE: u32 = u32::from_be_bytes(*b"avc3");

pub type Avc3 = AvcSampleEntry<{ AVC3_CODE }>;

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

fn base(compressor: &str) -> Avc3 {
Avc3 {
visual: Visual {
data_reference_index: 1,
width: 320,
height: 240,
horizresolution: 0x48.into(),
vertresolution: 0x48.into(),
frame_count: 1,
compressor: compressor.into(),
depth: 24,
},
avcc: Avcc {
configuration_version: 1,
avc_profile_indication: 100,
profile_compatibility: 0,
avc_level_indication: 13,
length_size: 4,
sequence_parameter_sets: vec![vec![
0x67, 0x64, 0x00, 0x0D, 0xAC, 0xD9, 0x41, 0x41, 0xFA, 0x10, 0x00, 0x00, 0x03,
0x00, 0x10, 0x00, 0x00, 0x03, 0x03, 0x20, 0xF1, 0x42, 0x99, 0x60,
]],
picture_parameter_sets: vec![vec![0x68, 0xEB, 0xE3, 0xCB, 0x22, 0xC0]],
..Default::default()
},
..Default::default()
}
}

fn roundtrip(expected: Avc3) {
let mut buf = Vec::new();
expected.encode(&mut buf).unwrap();

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

#[test]
fn test_avc3() {
roundtrip(base("ya boy"));
}

#[test]
fn test_avc3_with_extras() {
let mut avc3 = base("they");
avc3.btrt = Some(Btrt {
buffer_size_db: 14075,
max_bitrate: 374288,
avg_bitrate: 240976,
});
avc3.colr = Some(Colr::default());
avc3.pasp = Some(Pasp {
h_spacing: 4,
v_spacing: 3,
});
avc3.taic = Some(Taic {
time_uncertainty: u64::MAX,
clock_resolution: 1000,
clock_drift_rate: i32::MAX,
clock_type: ClockType::CanSync,
});
roundtrip(avc3);
}
}
2 changes: 2 additions & 0 deletions src/moov/trak/mdia/minf/stbl/stsd/h264/mod.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
mod avc1;
mod avc3;
mod avcc;

// Incomplete H264 decoder, saved for possible future use
Expand All @@ -7,4 +8,5 @@ mod avcc;
//mod sps;

pub use avc1::*;
pub use avc3::*;
pub use avcc::*;
5 changes: 5 additions & 0 deletions src/moov/trak/mdia/minf/stbl/stsd/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,9 @@ pub enum Codec {
// H264
Avc1(Avc1),

// H264: SPS/PPS/VPS is inline
Avc3(Avc3),

// HEVC: SPS/PPS/VPS is inline
Hev1(Hev1),

Expand Down Expand Up @@ -97,6 +100,7 @@ impl Decode for Codec {
let atom = Any::decode(buf)?;
Ok(match atom {
Any::Avc1(atom) => atom.into(),
Any::Avc3(atom) => atom.into(),
Any::Hev1(atom) => atom.into(),
Any::Hvc1(atom) => atom.into(),
Any::Vp08(atom) => atom.into(),
Expand All @@ -120,6 +124,7 @@ impl Encode for Codec {
match self {
Self::Unknown(kind) => kind.encode(buf),
Self::Avc1(atom) => atom.encode(buf),
Self::Avc3(atom) => atom.encode(buf),
Self::Hev1(atom) => atom.encode(buf),
Self::Hvc1(atom) => atom.encode(buf),
Self::Vp08(atom) => atom.encode(buf),
Expand Down
4 changes: 4 additions & 0 deletions src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@ impl FourCC {
pub const fn new(value: &[u8; 4]) -> Self {
FourCC(*value)
}

pub const fn from_u32(value: u32) -> Self {
FourCC(value.to_be_bytes())
}
}

impl From<u32> for FourCC {
Expand Down