scuffle_transmuxer/codecs/
av1.rs1use bytes::{Buf, Bytes};
2use scuffle_av1::seq::SequenceHeaderObu;
3use scuffle_av1::{AV1CodecConfigurationRecord, ObuHeader, ObuType};
4use scuffle_bytes_util::BytesCursorExt;
5use scuffle_flv::video::header::VideoFrameType;
6use scuffle_mp4::DynBox;
7use scuffle_mp4::types::av01::Av01;
8use scuffle_mp4::types::av1c::Av1C;
9use scuffle_mp4::types::colr::{ColorType, Colr};
10use scuffle_mp4::types::stsd::{SampleEntry, VisualSampleEntry};
11use scuffle_mp4::types::trun::{TrunSample, TrunSampleFlag};
12
13use crate::TransmuxError;
14
15pub(crate) fn stsd_entry(config: AV1CodecConfigurationRecord) -> Result<(DynBox, SequenceHeaderObu), TransmuxError> {
16 let mut cursor = std::io::Cursor::new(config.config_obu.clone());
17 let header = ObuHeader::parse(&mut cursor)?;
18 let data = cursor.extract_bytes(header.size.unwrap_or(cursor.remaining() as u64) as usize)?;
19
20 if header.obu_type != ObuType::SequenceHeader {
21 return Err(TransmuxError::InvalidAv1DecoderConfigurationRecord);
22 }
23
24 let seq_obu = SequenceHeaderObu::parse(header, &mut std::io::Cursor::new(data))?;
25
26 Ok((
32 Av01::new(
33 SampleEntry::new(VisualSampleEntry::new(
34 seq_obu.max_frame_width as u16,
35 seq_obu.max_frame_height as u16,
36 Some(Colr::new(ColorType::Nclx {
37 color_primaries: seq_obu.color_config.color_primaries as u16,
38 matrix_coefficients: seq_obu.color_config.matrix_coefficients as u16,
39 transfer_characteristics: seq_obu.color_config.transfer_characteristics as u16,
40 full_range_flag: seq_obu.color_config.full_color_range,
41 })),
42 )),
43 Av1C::new(config),
44 None,
45 )
46 .into(),
47 seq_obu,
48 ))
49}
50
51pub(crate) fn trun_sample(frame_type: VideoFrameType, duration: u32, data: &Bytes) -> Result<TrunSample, TransmuxError> {
52 Ok(TrunSample {
53 composition_time_offset: None,
54 duration: Some(duration),
55 flags: Some(TrunSampleFlag {
56 reserved: 0,
57 is_leading: 0,
58 sample_degradation_priority: 0,
59 sample_depends_on: if frame_type == VideoFrameType::KeyFrame { 2 } else { 1 },
60 sample_has_redundancy: 0,
61 sample_is_depended_on: 0,
62 sample_is_non_sync_sample: frame_type != VideoFrameType::KeyFrame,
63 sample_padding_value: 0,
64 }),
65 size: Some(data.len() as u32),
66 })
67}