symphonia_codec_aac/
adts.rs

1// Symphonia
2// Copyright (c) 2019-2022 The Project Symphonia Developers.
3//
4// This Source Code Form is subject to the terms of the Mozilla Public
5// License, v. 2.0. If a copy of the MPL was not distributed with this
6// file, You can obtain one at https://mozilla.org/MPL/2.0/.
7
8use 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
27/// Audio Data Transport Stream (ADTS) format reader.
28///
29/// `AdtsReader` implements a demuxer for ADTS (AAC native frames).
30pub 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        // The header may be 5 or 7 bytes (without or with protection).
81        let mut buf = [0u8; 7];
82        reader.read_buf_exact(&mut buf[..5])?;
83
84        let mut bs = BitReaderLtr::new(&buf);
85
86        // Profile
87        let profile = M4A_TYPES[bs.read_bits_leq32(2)? as usize + 1];
88
89        // Sample rate index.
90        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        // Private bit.
97        bs.ignore_bit()?;
98
99        // Channel configuration
100        let channels = match bs.read_bits_leq32(3)? {
101            0 => None,
102            idx => map_channels(idx),
103        };
104
105        // Originality, Home, Copyrighted ID bit, Copyright ID start bits. Only used for encoding.
106        bs.ignore_bits(4)?;
107
108        // Frame length = Header size (7) + AAC frame size
109        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        // TODO: Support multiple AAC packets per ADTS packet.
119        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        // Use the header to populate the codec parameters.
132        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        // Rewind back to the start of the frame.
141        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        // Parse the header to get the calculated frame size.
157        let header = AdtsHeader::read(&mut self.reader)?;
158
159        // TODO: Support multiple AAC packets per ADTS packet.
160
161        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        // Get the timestamp of the desired audio frame.
187        let required_ts = match to {
188            // Frame timestamp given.
189            SeekTo::TimeStamp { ts, .. } => ts,
190            // Time value given, calculate frame timestamp from sample rate.
191            SeekTo::Time { time, .. } => {
192                // Use the sample rate to calculate the frame timestamp. If sample rate is not
193                // known, the seek cannot be completed.
194                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 the desired timestamp is less-than the next packet timestamp, attempt to seek
206        // to the start of the stream.
207        if required_ts < self.next_packet_ts {
208            // If the reader is not seekable then only forward seeks are possible.
209            if self.reader.is_seekable() {
210                let seeked_pos = self.reader.seek(SeekFrom::Start(self.first_frame_pos))?;
211
212                // Since the elementary stream has no timestamp information, the position seeked
213                // to must be exactly as requested.
214                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            // Successfuly seeked to the start of the stream, reset the next packet timestamp.
223            self.next_packet_ts = 0;
224        }
225
226        // Parse frames from the stream until the frame containing the desired timestamp is
227        // reached.
228        loop {
229            // Parse the next frame header.
230            let header = AdtsHeader::read(&mut self.reader)?;
231
232            // TODO: Support multiple AAC packets per ADTS packet.
233
234            // If the next frame's timestamp would exceed the desired timestamp, rewind back to the
235            // start of this frame and end the search.
236            if self.next_packet_ts + SAMPLES_PER_AAC_PACKET > required_ts {
237                self.reader.seek_buffered_rev(AdtsHeader::SIZE);
238                break;
239            }
240
241            // Otherwise, ignore the frame body.
242            self.reader.ignore_bytes(header.frame_len as u64)?;
243
244            // Increment the timestamp for the next packet.
245            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}