scuffle_transmuxer/codecs/
avc.rs1use bytes::Bytes;
2use isobmff::UnknownBox;
3use isobmff::boxes::{
4 ColourInformation, ColourInformationBox, NclxColourInformation, PixelAspectRatioBox, SampleEntry, SampleFlags,
5 TrackRunBoxSample, VisualSampleEntry,
6};
7use scuffle_flv::video::header::VideoFrameType;
8use scuffle_h264::boxes::{AVCConfigurationBox, AVCSampleEntry1};
9use scuffle_h264::{AVCDecoderConfigurationRecord, Sps};
10
11use crate::TransmuxError;
12
13pub(crate) fn stsd_entry<'a>(
14 config: AVCDecoderConfigurationRecord<'a>,
15 sps: &'a Sps,
16) -> Result<AVCSampleEntry1<'a>, TransmuxError> {
17 if config.sps.is_empty() {
18 return Err(TransmuxError::InvalidAVCDecoderConfigurationRecord);
19 }
20
21 let mut sub_boxes = vec![UnknownBox::try_from_box(PixelAspectRatioBox::default())?];
22
23 if let Some(cc) = sps.color_config.as_ref() {
24 let colr = ColourInformationBox {
25 colour_info: ColourInformation::Nclx(NclxColourInformation {
26 colour_primaries: cc.color_primaries as u16,
27 matrix_coefficients: cc.matrix_coefficients as u16,
28 transfer_characteristics: cc.transfer_characteristics as u16,
29 full_range_flag: cc.video_full_range_flag,
30 }),
31 };
32 sub_boxes.push(UnknownBox::try_from_box(colr)?);
33 }
34
35 let visual_sample_entry =
36 VisualSampleEntry::new(SampleEntry::default(), sps.width() as u16, sps.height() as u16, [0; 32]);
37
38 Ok(AVCSampleEntry1 {
39 visual_sample_entry,
40 config: AVCConfigurationBox::new(config),
41 mpeg4_extension: None,
42 sub_boxes,
43 })
44}
45
46pub(crate) fn trun_sample(
47 frame_type: VideoFrameType,
48 composition_time: u32,
49 duration: u32,
50 data: &Bytes,
51) -> Result<TrackRunBoxSample, TransmuxError> {
52 Ok(TrackRunBoxSample {
53 sample_duration: Some(duration),
54 sample_size: Some(data.len() as u32),
55 sample_flags: Some(SampleFlags {
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 sample_composition_time_offset: Some(composition_time as i64),
66 })
67}