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;
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.for_codec(CODEC_TYPE_AAC).with_sample_rate(header.sample_rate);
135
136 if let Some(channels) = header.channels {
137 params.with_channels(channels);
138 }
139
140 source.seek_buffered_rev(AdtsHeader::SIZE);
142
143 let first_frame_pos = source.pos();
144
145 Ok(AdtsReader {
146 reader: source,
147 tracks: vec![Track::new(0, params)],
148 cues: Vec::new(),
149 metadata: Default::default(),
150 first_frame_pos,
151 next_packet_ts: 0,
152 })
153 }
154
155 fn next_packet(&mut self) -> Result<Packet> {
156 let header = AdtsHeader::read(&mut self.reader)?;
158
159 let ts = self.next_packet_ts;
162
163 self.next_packet_ts += SAMPLES_PER_AAC_PACKET;
164
165 Ok(Packet::new_from_boxed_slice(
166 0,
167 ts,
168 SAMPLES_PER_AAC_PACKET,
169 self.reader.read_boxed_slice_exact(header.frame_len)?,
170 ))
171 }
172
173 fn metadata(&mut self) -> Metadata<'_> {
174 self.metadata.metadata()
175 }
176
177 fn cues(&self) -> &[Cue] {
178 &self.cues
179 }
180
181 fn tracks(&self) -> &[Track] {
182 &self.tracks
183 }
184
185 fn seek(&mut self, _mode: SeekMode, to: SeekTo) -> Result<SeekedTo> {
186 let required_ts = match to {
188 SeekTo::TimeStamp { ts, .. } => ts,
190 SeekTo::Time { time, .. } => {
192 if let Some(sample_rate) = self.tracks[0].codec_params.sample_rate {
195 TimeBase::new(1, sample_rate).calc_timestamp(time)
196 }
197 else {
198 return seek_error(SeekErrorKind::Unseekable);
199 }
200 }
201 };
202
203 debug!("seeking to ts={}", required_ts);
204
205 if required_ts < self.next_packet_ts {
208 if self.reader.is_seekable() {
210 let seeked_pos = self.reader.seek(SeekFrom::Start(self.first_frame_pos))?;
211
212 if seeked_pos != self.first_frame_pos {
215 return seek_error(SeekErrorKind::Unseekable);
216 }
217 }
218 else {
219 return seek_error(SeekErrorKind::ForwardOnly);
220 }
221
222 self.next_packet_ts = 0;
224 }
225
226 loop {
229 let header = AdtsHeader::read(&mut self.reader)?;
231
232 if self.next_packet_ts + SAMPLES_PER_AAC_PACKET > required_ts {
237 self.reader.seek_buffered_rev(AdtsHeader::SIZE);
238 break;
239 }
240
241 self.reader.ignore_bytes(header.frame_len as u64)?;
243
244 self.next_packet_ts += SAMPLES_PER_AAC_PACKET;
246 }
247
248 debug!(
249 "seeked to ts={} (delta={})",
250 self.next_packet_ts,
251 required_ts as i64 - self.next_packet_ts as i64
252 );
253
254 Ok(SeekedTo { track_id: 0, required_ts, actual_ts: self.next_packet_ts })
255 }
256
257 fn into_inner(self: Box<Self>) -> MediaSourceStream {
258 self.reader
259 }
260}