scuffle_transmuxer/codecs/
avc.rs

1use bytes::Bytes;
2use scuffle_flv::video::header::VideoFrameType;
3use scuffle_h264::{AVCDecoderConfigurationRecord, Sps};
4use scuffle_mp4::DynBox;
5use scuffle_mp4::types::avc1::Avc1;
6use scuffle_mp4::types::avcc::AvcC;
7use scuffle_mp4::types::colr::{ColorType, Colr};
8use scuffle_mp4::types::stsd::{SampleEntry, VisualSampleEntry};
9use scuffle_mp4::types::trun::{TrunSample, TrunSampleFlag};
10
11use crate::TransmuxError;
12
13pub(crate) fn stsd_entry(config: AVCDecoderConfigurationRecord, sps: &Sps) -> Result<DynBox, TransmuxError> {
14    if config.sps.is_empty() {
15        return Err(TransmuxError::InvalidAVCDecoderConfigurationRecord);
16    }
17
18    let colr = sps.color_config.as_ref().map(|color_config| {
19        Colr::new(ColorType::Nclx {
20            color_primaries: color_config.color_primaries as u16,
21            matrix_coefficients: color_config.matrix_coefficients as u16,
22            transfer_characteristics: color_config.transfer_characteristics as u16,
23            full_range_flag: color_config.video_full_range_flag,
24        })
25    });
26
27    Ok(Avc1::new(
28        SampleEntry::new(VisualSampleEntry::new(sps.width() as u16, sps.height() as u16, colr)),
29        AvcC::new(config),
30        None,
31    )
32    .into())
33}
34
35pub(crate) fn trun_sample(
36    frame_type: VideoFrameType,
37    composition_time: u32,
38    duration: u32,
39    data: &Bytes,
40) -> Result<TrunSample, TransmuxError> {
41    Ok(TrunSample {
42        composition_time_offset: Some(composition_time as i64),
43        duration: Some(duration),
44        flags: Some(TrunSampleFlag {
45            reserved: 0,
46            is_leading: 0,
47            sample_degradation_priority: 0,
48            sample_depends_on: if frame_type == VideoFrameType::KeyFrame { 2 } else { 1 },
49            sample_has_redundancy: 0,
50            sample_is_depended_on: 0,
51            sample_is_non_sync_sample: frame_type != VideoFrameType::KeyFrame,
52            sample_padding_value: 0,
53        }),
54        size: Some(data.len() as u32),
55    })
56}