scuffle_transmuxer/codecs/
aac.rs1use bytes::Bytes;
2use fixed::FixedU32;
3use isobmff::boxes::{AudioSampleEntry, SampleEntry, SampleFlags, TrackRunBoxSample};
4use scuffle_aac::PartialAudioSpecificConfig;
5use scuffle_bytes_util::zero_copy::U24Be;
6use scuffle_flv::audio::header::legacy::{SoundSize, SoundType};
7use scuffle_mp4::boxes::{ESDBox, MP4AudioSampleEntry};
8use scuffle_mp4::object_description::{
9 DecoderConfigDescriptor, DescriptorTag, ESDescriptor, ObjectTypeIndication, StreamType, UnknownDescriptor,
10};
11
12use crate::TransmuxError;
13
14pub(crate) fn stsd_entry<'a>(
15 sound_size: SoundSize,
16 sound_type: SoundType,
17 data: Bytes,
18) -> Result<(MP4AudioSampleEntry<'a>, PartialAudioSpecificConfig), TransmuxError> {
19 let aac_config = scuffle_aac::PartialAudioSpecificConfig::parse(&data)?;
20
21 let channelcount = match sound_type {
22 SoundType::Mono => 1,
23 SoundType::Stereo => 2,
24 _ => return Err(TransmuxError::InvalidAudioChannels),
25 };
26
27 let samplesize = match sound_size {
28 SoundSize::Bit8 => 8,
29 SoundSize::Bit16 => 16,
30 _ => return Err(TransmuxError::InvalidAudioSampleSize),
31 };
32
33 let es = ESDescriptor {
34 es_id: 2,
35 stream_priority: 0,
36 depends_on_es_id: Some(0),
37 url_string: None,
38 ocr_es_id: Some(0),
39 dec_config_descr: DecoderConfigDescriptor {
40 object_type_indication: ObjectTypeIndication::Audio14496_3, stream_type: StreamType::AudioStream,
42 up_stream: false,
43 reserved: true,
44 buffer_size_db: U24Be(0),
45 max_bitrate: 0,
46 avg_bitrate: 0,
47 dec_specific_info: Some(UnknownDescriptor::new(DescriptorTag::DecSpecificInfoTag, data.into())),
48 profile_level_indication_index_descr: vec![],
49 unknown_descriptors: vec![],
50 },
51 sl_config_descr: None,
52 unknown_descriptors: vec![],
53 };
54 let mp4a = MP4AudioSampleEntry {
55 sample_entry: AudioSampleEntry::new(
56 SampleEntry::default(),
57 channelcount,
58 samplesize,
59 FixedU32::from_num(aac_config.sampling_frequency),
60 ),
61 es: ESDBox::new(es),
62 };
63
64 Ok((mp4a, aac_config))
65}
66
67pub(crate) fn trun_sample(data: &Bytes) -> Result<(TrackRunBoxSample, u32), TransmuxError> {
68 Ok((
69 TrackRunBoxSample {
70 sample_duration: Some(1024),
71 sample_composition_time_offset: None,
72 sample_flags: Some(SampleFlags {
73 reserved: 0,
74 is_leading: 0,
75 sample_degradation_priority: 0,
76 sample_depends_on: 2,
77 sample_has_redundancy: 0,
78 sample_is_depended_on: 0,
79 sample_is_non_sync_sample: false,
80 sample_padding_value: 0,
81 }),
82 sample_size: Some(data.len() as u32),
83 },
84 1024,
85 ))
86}