scuffle_transmuxer/codecs/
aac.rs

1use bytes::Bytes;
2use scuffle_aac::PartialAudioSpecificConfig;
3use scuffle_flv::audio::header::legacy::{SoundSize, SoundType};
4use scuffle_mp4::DynBox;
5use scuffle_mp4::types::esds::Esds;
6use scuffle_mp4::types::esds::descriptor::header::DescriptorHeader;
7use scuffle_mp4::types::esds::descriptor::traits::DescriptorType;
8use scuffle_mp4::types::esds::descriptor::types::decoder_config::DecoderConfigDescriptor;
9use scuffle_mp4::types::esds::descriptor::types::decoder_specific_info::DecoderSpecificInfoDescriptor;
10use scuffle_mp4::types::esds::descriptor::types::es::EsDescriptor;
11use scuffle_mp4::types::mp4a::Mp4a;
12use scuffle_mp4::types::stsd::{AudioSampleEntry, SampleEntry};
13use scuffle_mp4::types::trun::{TrunSample, TrunSampleFlag};
14
15use crate::TransmuxError;
16
17pub(crate) fn stsd_entry(
18    sound_size: SoundSize,
19    sound_type: SoundType,
20    data: Bytes,
21) -> Result<(DynBox, PartialAudioSpecificConfig), TransmuxError> {
22    let aac_config = scuffle_aac::PartialAudioSpecificConfig::parse(&data)?;
23
24    Ok((
25        Mp4a::new(
26            SampleEntry::new(AudioSampleEntry::new(
27                match sound_type {
28                    SoundType::Mono => 1,
29                    SoundType::Stereo => 2,
30                    _ => return Err(TransmuxError::InvalidAudioChannels),
31                },
32                match sound_size {
33                    SoundSize::Bit8 => 8,
34                    SoundSize::Bit16 => 16,
35                    _ => return Err(TransmuxError::InvalidAudioSampleSize),
36                },
37                aac_config.sampling_frequency,
38            )),
39            Esds::new(EsDescriptor::new(
40                2,
41                0,
42                Some(0),
43                None,
44                Some(0),
45                Some(DecoderConfigDescriptor::new(
46                    0x40, // aac
47                    0x05, // audio stream
48                    0,    // max bitrate
49                    0,    // avg bitrate
50                    Some(DecoderSpecificInfoDescriptor {
51                        header: DescriptorHeader::new(DecoderSpecificInfoDescriptor::TAG),
52                        data,
53                    }),
54                )),
55                None,
56            )),
57            None,
58        )
59        .into(),
60        aac_config,
61    ))
62}
63
64pub(crate) fn trun_sample(data: &Bytes) -> Result<(TrunSample, u32), TransmuxError> {
65    Ok((
66        TrunSample {
67            duration: Some(1024),
68            composition_time_offset: None,
69            flags: Some(TrunSampleFlag {
70                reserved: 0,
71                is_leading: 0,
72                sample_degradation_priority: 0,
73                sample_depends_on: 2,
74                sample_has_redundancy: 0,
75                sample_is_depended_on: 0,
76                sample_is_non_sync_sample: false,
77                sample_padding_value: 0,
78            }),
79            size: Some(data.len() as u32),
80        },
81        1024,
82    ))
83}