1use bytes::{Bytes, BytesMut};
2
3pub fn is_aac(input: &[u8]) -> bool {
4 if input.len() < 7 {
6 return false;
7 }
8
9 if input[0] != 0xFF || (input[1] & 0xF0) != 0xF0 {
11 return false;
12 }
13
14 let layer = (input[1] & 0x06) >> 1;
15 if layer != 0 {
16 return false;
18 }
19
20 let profile = (input[2] & 0xC0) >> 6;
22 if profile == 3 {
23 return false;
25 }
26
27 let sampling_freq_index = (input[2] & 0x3C) >> 2;
29 if sampling_freq_index > 11 {
30 return false;
32 }
33
34 true
36}
37
38pub fn extract_aac_data(sound_data: &Bytes) -> Option<Bytes> {
39 if sound_data.len() < 7 {
40 return None;
41 }
42
43 if sound_data[0] != 0xFF || (sound_data[1] & 0xF0) != 0xF0 {
45 return None;
46 }
47
48 let protection_absent: bool = (sound_data[1] & 0x01) == 0x01;
50 let header_size: usize = if protection_absent { 7 } else { 9 };
51
52 if sound_data.len() < header_size {
53 return None;
54 }
55
56 let frame_length: usize = (((sound_data[3] as usize & 0x03) << 11)
57 | ((sound_data[4] as usize) << 3)
58 | ((sound_data[5] as usize) >> 5)) as usize;
59
60 if sound_data.len() < frame_length {
61 return None;
62 }
63
64 Some(sound_data.slice(header_size..frame_length))
65}
66
67pub fn ensure_adts_header(data: Bytes, channels: u8, sample_rate: u32) -> Bytes {
68 if extract_aac_data(&data).is_none() {
70 let audio_object_type = data[0] >> 3; let profile = match audio_object_type {
74 1 => 0x66, 2 => 0x67, 5 => 0x68, _ => 0x66, };
79
80 let header = create_adts_header(profile, channels, sample_rate, data.len() - 2, false);
81 let mut payload = BytesMut::from(&header[..]);
82 payload.extend_from_slice(&data[2..]); return payload.freeze();
85 }
86
87 return data;
88}
89
90pub fn create_adts_header(
91 codec_id: u8,
92 channels: u8,
93 sample_rate: u32,
94 aac_frame_length: usize,
95 has_crc: bool,
96) -> Vec<u8> {
97 let profile_object_type = match codec_id {
98 0x66 => 1, 0x67 => 2, 0x68 => 3, _ => 1, };
103
104 let sample_rate_index = sample_rate_index(sample_rate);
105 let channel_config = channels.min(7);
106 let header_length = if has_crc { 9 } else { 7 };
107 let frame_length = aac_frame_length + header_length;
108
109 let mut header = Vec::with_capacity(header_length);
110 let protection_absent = if has_crc { 0 } else { 1 };
111
112 header.push(0xFF);
113 header.push(0xF0 | protection_absent);
114
115 let profile_and_sampling =
116 (profile_object_type << 6) | (sample_rate_index << 2) | (channel_config >> 2);
117 header.push(profile_and_sampling);
118
119 let frame_length_high = ((frame_length >> 11) & 0x03) as u8;
120 let frame_length_mid = ((frame_length >> 3) & 0xFF) as u8;
121 header.push((channel_config & 3) << 6 | frame_length_high);
122 header.push(frame_length_mid);
123
124 let frame_length_low = ((frame_length & 0x07) << 5) | 0x1F;
125 header.push(frame_length_low as u8);
126 header.push(0xFC);
127
128 if has_crc {
129 header.extend_from_slice(&[0x00, 0x00]);
130 }
131
132 header
133}
134
135fn sample_rate_index(sample_rate: u32) -> u8 {
136 match sample_rate {
137 96000 => 0x0,
138 88200 => 0x1,
139 64000 => 0x2,
140 48000 => 0x3,
141 44100 => 0x4,
142 32000 => 0x5,
143 24000 => 0x6,
144 22050 => 0x7,
145 16000 => 0x8,
146 12000 => 0x9,
147 11025 => 0xA,
148 8000 => 0xB,
149 7350 => 0xC,
150 _ => 0xF, }
152}
153
154#[cfg(test)]
155mod tests {
156 use super::*;
157 use mse_fmp4::aac::{AdtsHeader, ChannelConfiguration, SamplingFrequency};
158
159 #[test]
160 fn test_adts_header_parsing() {
161 let data = vec![0u8; 200]; let channels = 2u8;
163 let sample_rate = 44100u32;
164 let adts_payload = create_adts_header(0x66, channels, sample_rate, data.len(), false);
165 let mut full_payload = adts_payload.clone();
166 full_payload.extend_from_slice(&data);
167
168 let adts = AdtsHeader::read_from(&full_payload[..]).unwrap();
169 assert_eq!(adts.frame_len, 207);
170 assert_eq!(adts.sampling_frequency, SamplingFrequency::Hz44100);
171 assert_eq!(
172 adts.channel_configuration,
173 ChannelConfiguration::TwoChannels
174 );
175 assert_eq!(adts.profile, mse_fmp4::aac::AacProfile::Lc);
176 }
177}