symphonia_codec_aac/
adts.rs1use symphonia_core::errors::unsupported_error;
9use symphonia_core::support_format;
10
11use symphonia_core::audio::Channels;
12use symphonia_core::codecs::{CodecParameters, CODEC_TYPE_AAC};
13use symphonia_core::errors::{decode_error, seek_error, Result, SeekErrorKind};
14use symphonia_core::formats::prelude::*;
15use symphonia_core::io::*;
16use symphonia_core::meta::{Metadata, MetadataLog};
17use symphonia_core::probe::{Descriptor, Instantiate, QueryDescriptor};
18
19use std::io::{Seek, SeekFrom};
20
21use super::common::{map_channels, M4AType, AAC_SAMPLE_RATES, M4A_TYPES};
22
23use log::{debug, info};
24
25const SAMPLES_PER_AAC_PACKET: u64 = 1024;
26
27pub struct AdtsReader {
31 reader: MediaSourceStream,
32 tracks: Vec<Track>,
33 cues: Vec<Cue>,
34 metadata: MetadataLog,
35 first_frame_pos: u64,
36 next_packet_ts: u64,
37}
38
39impl QueryDescriptor for AdtsReader {
40 fn query() -> &'static [Descriptor] {
41 &[support_format!(
42 "aac",
43 "Audio Data Transport Stream (native AAC)",
44 &["aac"],
45 &["audio/aac"],
46 &[&[0xff, 0xf1]]
47 )]
48 }
49
50 fn score(_context: &[u8]) -> u8 {
51 255
52 }
53}
54
55#[derive(Debug)]
56#[allow(dead_code)]
57struct AdtsHeader {
58 profile: M4AType,
59 channels: Option<Channels>,
60 sample_rate: u32,
61 frame_len: usize,
62}
63
64impl AdtsHeader {
65 const SIZE: usize = 7;
66
67 fn sync<B: ReadBytes>(reader: &mut B) -> Result<()> {
68 let mut sync = 0u16;
69
70 while sync != 0xfff1 {
71 sync = (sync << 8) | u16::from(reader.read_u8()?);
72 }
73
74 Ok(())
75 }
76
77 fn read<B: ReadBytes>(reader: &mut B) -> Result<Self> {
78 AdtsHeader::sync(reader)?;
79
80 let mut buf = [0u8; 7];
82 reader.read_buf_exact(&mut buf[..5])?;
83
84 let mut bs = BitReaderLtr::new(&buf);
85
86 let profile = M4A_TYPES[bs.read_bits_leq32(2)? as usize + 1];
88
89 let sample_rate = match bs.read_bits_leq32(4)? as usize {
91 15 => return decode_error("adts: forbidden sample rate"),
92 13 | 14 => return decode_error("adts: reserved sample rate"),
93 idx => AAC_SAMPLE_RATES[idx],
94 };
95
96 bs.ignore_bit()?;
98
99 let channels = match bs.read_bits_leq32(3)? {
101 0 => None,
102 idx => map_channels(idx),
103 };
104
105 bs.ignore_bits(4)?;
107
108 let frame_len = bs.read_bits_leq32(13)? as usize;
110
111 if frame_len < AdtsHeader::SIZE {
112 return decode_error("adts: invalid adts frame length");
113 }
114
115 let _fullness = bs.read_bits_leq32(11)?;
116 let num_aac_frames = bs.read_bits_leq32(2)? + 1;
117
118 if num_aac_frames > 1 {
120 return unsupported_error("adts: only 1 aac frame per adts packet is supported");
121 }
122
123 Ok(AdtsHeader { profile, channels, sample_rate, frame_len: frame_len - AdtsHeader::SIZE })
124 }
125}
126
127impl FormatReader for AdtsReader {
128 fn try_new(mut source: MediaSourceStream, _options: &FormatOptions) -> Result<Self> {
129 let header = AdtsHeader::read(&mut source)?;
130
131 let mut params = CodecParameters::new();
133
134 params
135 .for_codec(CODEC_TYPE_AAC)
136 .with_sample_rate(header.sample_rate)
137 .with_time_base(TimeBase::new(1, header.sample_rate));
138
139 if let Some(channels) = header.channels {
140 params.with_channels(channels);
141 }
142
143 source.seek_buffered_rev(AdtsHeader::SIZE);
145
146 let first_frame_pos = source.pos();
147
148 let n_frames = approximate_frame_count(&mut source)?;
149 if let Some(n_frames) = n_frames {
150 info!("estimating duration from bitrate, may be inaccurate for vbr files");
151 params.with_n_frames(n_frames);
152 }
153
154 Ok(AdtsReader {
155 reader: source,
156 tracks: vec![Track::new(0, params)],
157 cues: Vec::new(),
158 metadata: Default::default(),
159 first_frame_pos,
160 next_packet_ts: 0,
161 })
162 }
163
164 fn next_packet(&mut self) -> Result<Packet> {
165 let header = AdtsHeader::read(&mut self.reader)?;
167
168 let ts = self.next_packet_ts;
171
172 self.next_packet_ts += SAMPLES_PER_AAC_PACKET;
173
174 Ok(Packet::new_from_boxed_slice(
175 0,
176 ts,
177 SAMPLES_PER_AAC_PACKET,
178 self.reader.read_boxed_slice_exact(header.frame_len)?,
179 ))
180 }
181
182 fn metadata(&mut self) -> Metadata<'_> {
183 self.metadata.metadata()
184 }
185
186 fn cues(&self) -> &[Cue] {
187 &self.cues
188 }
189
190 fn tracks(&self) -> &[Track] {
191 &self.tracks
192 }
193
194 fn seek(&mut self, _mode: SeekMode, to: SeekTo) -> Result<SeekedTo> {
195 let required_ts = match to {
197 SeekTo::TimeStamp { ts, .. } => ts,
199 SeekTo::Time { time, .. } => {
201 if let Some(sample_rate) = self.tracks[0].codec_params.sample_rate {
204 TimeBase::new(1, sample_rate).calc_timestamp(time)
205 }
206 else {
207 return seek_error(SeekErrorKind::Unseekable);
208 }
209 }
210 };
211
212 debug!("seeking to ts={}", required_ts);
213
214 if required_ts < self.next_packet_ts {
217 if self.reader.is_seekable() {
219 let seeked_pos = self.reader.seek(SeekFrom::Start(self.first_frame_pos))?;
220
221 if seeked_pos != self.first_frame_pos {
224 return seek_error(SeekErrorKind::Unseekable);
225 }
226 }
227 else {
228 return seek_error(SeekErrorKind::ForwardOnly);
229 }
230
231 self.next_packet_ts = 0;
233 }
234
235 loop {
238 let header = AdtsHeader::read(&mut self.reader)?;
240
241 if self.next_packet_ts + SAMPLES_PER_AAC_PACKET > required_ts {
246 self.reader.seek_buffered_rev(AdtsHeader::SIZE);
247 break;
248 }
249
250 self.reader.ignore_bytes(header.frame_len as u64)?;
252
253 self.next_packet_ts += SAMPLES_PER_AAC_PACKET;
255 }
256
257 debug!(
258 "seeked to ts={} (delta={})",
259 self.next_packet_ts,
260 required_ts as i64 - self.next_packet_ts as i64
261 );
262
263 Ok(SeekedTo { track_id: 0, required_ts, actual_ts: self.next_packet_ts })
264 }
265
266 fn into_inner(self: Box<Self>) -> MediaSourceStream {
267 self.reader
268 }
269}
270
271fn approximate_frame_count(mut source: &mut MediaSourceStream) -> Result<Option<u64>> {
272 let original_pos = source.pos();
273 let total_len = match source.byte_len() {
274 Some(len) => len - original_pos,
275 _ => return Ok(None),
276 };
277
278 let mut parsed_n_frames = 0;
279 let mut n_bytes = 0;
280
281 if !source.is_seekable() {
282 const MAX_LEN: u64 = 16 * 1024;
284
285 source.ensure_seekback_buffer(MAX_LEN as usize);
286 let mut scoped_stream = ScopedStream::new(&mut source, MAX_LEN);
287
288 while let Ok(header) = AdtsHeader::read(&mut scoped_stream) {
289 if scoped_stream.ignore_bytes(header.frame_len as u64).is_err() {
290 break;
291 }
292
293 parsed_n_frames += 1;
294 n_bytes += header.frame_len + AdtsHeader::SIZE;
295 }
296
297 let _ = source.seek_buffered(original_pos);
298 }
299 else {
300 const NUM_SAMPLE_POINTS: u64 = 4;
302
303 let step = (total_len - original_pos) / NUM_SAMPLE_POINTS;
304
305 for new_pos in (original_pos..total_len - step).step_by(step as usize).skip(1) {
307 let res = source.seek(SeekFrom::Start(new_pos));
308 if res.is_err() {
309 break;
310 }
311
312 for _ in 0..=100 {
313 let header = match AdtsHeader::read(&mut source) {
314 Ok(header) => header,
315 _ => break,
316 };
317
318 if source.ignore_bytes(header.frame_len as u64).is_err() {
319 break;
320 }
321
322 parsed_n_frames += 1;
323 n_bytes += header.frame_len + AdtsHeader::SIZE;
324 }
325 }
326
327 let _ = source.seek(SeekFrom::Start(original_pos))?;
328 }
329
330 debug!("adts: Parsed {} of {} bytes to approximate duration", n_bytes, total_len);
331
332 match parsed_n_frames {
333 0 => Ok(None),
334 _ => Ok(Some(total_len / (n_bytes as u64 / parsed_n_frames) * SAMPLES_PER_AAC_PACKET)),
335 }
336}