adts_reader/
lib.rs

1//! A Rust parser for the [Audio Data Transport Stream](https://wiki.multimedia.cx/index.php/ADTS)
2//! framing format often used to carry encoded AAC audio data.
3//!
4//! [`AdtsHeader`](struct.AdtsHeader.html) is the primary type provided by this crate.
5//!
6//! Given a buffer containing some number of ADTS frames, the first frame may be inspected by
7//! constructing a header instance with,
8//!
9//! ```rust
10//! use adts_reader::AdtsHeader;
11//! # let buf: Vec<u8> = vec!(0xff, 0xf0, 0, 0, 1, 0x20, 0, 0, 0);
12//! // let buf = ...;
13//! match AdtsHeader::from_bytes(&buf) {
14//!     Ok(header) => println!("length (headers+payload) is {}", header.frame_length()),
15//!     Err(e) => panic!("failed to read header: {:?}", e),
16//! }
17//! ```
18//!
19//! # Unsupported
20//!
21//!  - Resynchronising `AdtsParser` after encountering bitstream error (we could search for
22//!    sync-word)
23//!  - Copyright identifiers (I don't have any example bitstreams to try)
24//!  - CRC handling (probably needs to be implemented as part of AAC bitstream parsing)
25
26#![forbid(unsafe_code)]
27#![deny(rust_2018_idioms, future_incompatible)]
28
29// TODO: might be better to implement AdtsParser as an iterator, rather then doing callbacks into a
30// trait implementation -- it looked hard to implement though!
31
32use std::fmt;
33
34#[derive(Debug)]
35pub enum AdtsHeaderError {
36    /// Indicates that the given buffer did not start with the required sequence of 12 '1'-bits
37    /// (`0xfff`).
38    BadSyncWord(u16),
39    NotEnoughData {
40        expected: usize,
41        actual: usize,
42    },
43    /// The frame_length field stored in the ADTS header is invalid as it holds a value smaller
44    /// than the size of the header fields
45    BadFrameLength {
46        minimum: usize,
47        actual: usize,
48    },
49}
50
51/// Error indicating that not enough data was provided to `AdtsHeader` to be able to extract the
52/// whole ADTS payload following the header fields.
53#[derive(Debug, PartialEq)]
54pub struct PayloadError {
55    pub expected: usize,
56    pub actual: usize,
57}
58
59#[derive(Debug, PartialEq)]
60pub enum MpegVersion {
61    Mpeg2,
62    Mpeg4,
63}
64
65#[derive(Debug, PartialEq, Clone, Copy)]
66pub enum AudioObjectType {
67    /// 'Main' profile
68    AacMain,
69    /// 'Low Complexity' profile
70    AacLC,
71    /// 'Scalable Sample Rate' profile
72    AacSSR,
73    /// 'Long Term Prediction' profile
74    AacLTP,
75}
76
77#[derive(Debug, PartialEq)]
78pub enum ProtectionIndicator {
79    CrcPresent,
80    CrcAbsent,
81}
82
83#[derive(Debug, PartialEq, Clone, Copy)]
84pub enum SamplingFrequency {
85    /// 96kHz
86    Freq96000 = 0x0,
87    /// 88.2kHz
88    Freq88200 = 0x1,
89    /// 64kHz
90    Freq64000 = 0x2,
91    /// 48kHz
92    Freq48000 = 0x3,
93    /// 44.1kHz
94    Freq44100 = 0x4,
95    /// 32kHz
96    Freq32000 = 0x5,
97    /// 24kHz
98    Freq24000 = 0x6,
99    /// 22.05kHz
100    Freq22050 = 0x7,
101    /// 16kHz
102    Freq16000 = 0x8,
103    /// 12kHz
104    Freq12000 = 0x9,
105    /// 11.025kHz
106    Freq11025 = 0xa,
107    /// 8kHz
108    Freq8000 = 0xb,
109    FreqReserved0xc = 0xc,
110    FreqReserved0xd = 0xd,
111    FreqReserved0xe = 0xe,
112    FreqReserved0xf = 0xf,
113}
114
115impl SamplingFrequency {
116    fn from(value: u8) -> SamplingFrequency {
117        match value {
118            0x0 => SamplingFrequency::Freq96000,
119            0x1 => SamplingFrequency::Freq88200,
120            0x2 => SamplingFrequency::Freq64000,
121            0x3 => SamplingFrequency::Freq48000,
122            0x4 => SamplingFrequency::Freq44100,
123            0x5 => SamplingFrequency::Freq32000,
124            0x6 => SamplingFrequency::Freq24000,
125            0x7 => SamplingFrequency::Freq22050,
126            0x8 => SamplingFrequency::Freq16000,
127            0x9 => SamplingFrequency::Freq12000,
128            0xa => SamplingFrequency::Freq11025,
129            0xb => SamplingFrequency::Freq8000,
130            0xc => SamplingFrequency::FreqReserved0xc,
131            0xd => SamplingFrequency::FreqReserved0xd,
132            0xe => SamplingFrequency::FreqReserved0xe,
133            0xf => SamplingFrequency::FreqReserved0xf,
134            _ => panic!("invalud value {:x}", value),
135        }
136    }
137
138    pub fn freq(&self) -> Option<u32> {
139        match self {
140            &SamplingFrequency::Freq96000 => Some(96000),
141            &SamplingFrequency::Freq88200 => Some(88200),
142            &SamplingFrequency::Freq64000 => Some(64000),
143            &SamplingFrequency::Freq48000 => Some(48000),
144            &SamplingFrequency::Freq44100 => Some(44100),
145            &SamplingFrequency::Freq32000 => Some(32000),
146            &SamplingFrequency::Freq24000 => Some(24000),
147            &SamplingFrequency::Freq22050 => Some(22050),
148            &SamplingFrequency::Freq16000 => Some(16000),
149            &SamplingFrequency::Freq12000 => Some(12000),
150            &SamplingFrequency::Freq11025 => Some(11025),
151            &SamplingFrequency::Freq8000 => Some(8000),
152            &SamplingFrequency::FreqReserved0xc => None,
153            &SamplingFrequency::FreqReserved0xd => None,
154            &SamplingFrequency::FreqReserved0xe => None,
155            &SamplingFrequency::FreqReserved0xf => None,
156        }
157    }
158}
159
160#[derive(Debug, PartialEq, Clone, Copy)]
161pub enum ChannelConfiguration {
162    ObjectTypeSpecificConfig = 0x0,
163    Mono = 0x1,
164    Stereo = 0x2,
165    Three = 0x3,
166    Four = 0x4,
167    Five = 0x5,
168    FiveOne = 0x6,
169    SevenOne = 0x7,
170}
171impl ChannelConfiguration {
172    fn from(value: u8) -> ChannelConfiguration {
173        match value {
174            0x0 => ChannelConfiguration::ObjectTypeSpecificConfig,
175            0x1 => ChannelConfiguration::Mono,
176            0x2 => ChannelConfiguration::Stereo,
177            0x3 => ChannelConfiguration::Three,
178            0x4 => ChannelConfiguration::Four,
179            0x5 => ChannelConfiguration::Five,
180            0x6 => ChannelConfiguration::FiveOne,
181            0x7 => ChannelConfiguration::SevenOne,
182            _ => panic!("invalid value {}", value),
183        }
184    }
185}
186
187#[derive(Debug, PartialEq)]
188pub enum Originality {
189    Original,
190    Copy,
191}
192
193#[derive(Debug, PartialEq)]
194pub enum CopyrightIdentificationStart {
195    Start,
196    Other,
197}
198
199/// Extract information for a single ADTS frame from the start of the given byte buffer .
200pub struct AdtsHeader<'buf> {
201    buf: &'buf [u8],
202}
203impl<'buf> AdtsHeader<'buf> {
204    /// Construct an instance by borrowing the given byte buffer.  The given buffer may be longer
205    /// then the ADTS frame, in which case the rest of the buffer is ignored.
206    ///
207    ///
208    /// Note that this function returns `Err` if there is not enough data to parse the whole
209    /// header, but it can return `Ok` even if there is not enough data in the given buffer to hold
210    /// the whole of the payload that the header indicates should be present (however _if_ there is
211    /// not enough data to hold the payload, then [`payload()`](#method.payload) will return
212    /// `None`).
213    pub fn from_bytes(buf: &'buf [u8]) -> Result<AdtsHeader<'_>, AdtsHeaderError> {
214        assert!(!buf.is_empty());
215        let header_len = 7;
216        Self::check_len(header_len, buf.len())?;
217        let header = AdtsHeader { buf };
218        if header.sync_word() != 0xfff {
219            return Err(AdtsHeaderError::BadSyncWord(header.sync_word()));
220        }
221        let crc_len = 2;
222        if header.protection() == ProtectionIndicator::CrcPresent {
223            Self::check_len(header_len + crc_len, buf.len())?;
224        }
225        if header.frame_length() < header.header_length() {
226            return Err(AdtsHeaderError::BadFrameLength {
227                actual: header.frame_length() as usize,
228                minimum: header.header_length() as usize,
229            });
230        }
231        Ok(header)
232    }
233
234    fn check_len(expected: usize, actual: usize) -> Result<(), AdtsHeaderError> {
235        if actual < expected {
236            Err(AdtsHeaderError::NotEnoughData { expected, actual })
237        } else {
238            Ok(())
239        }
240    }
241
242    fn header_length(&self) -> u16 {
243        let fixed_len = 7;
244        if self.protection() == ProtectionIndicator::CrcPresent {
245            fixed_len + 2
246        } else {
247            fixed_len
248        }
249    }
250
251    fn sync_word(&self) -> u16 {
252        u16::from(self.buf[0]) << 4 | u16::from(self.buf[1] >> 4)
253    }
254
255    pub fn mpeg_version(&self) -> MpegVersion {
256        if self.buf[1] & 0b0000_1000 != 0 {
257            MpegVersion::Mpeg2
258        } else {
259            MpegVersion::Mpeg4
260        }
261    }
262
263    pub fn protection(&self) -> ProtectionIndicator {
264        if self.buf[1] & 0b0000_0001 != 0 {
265            ProtectionIndicator::CrcAbsent
266        } else {
267            ProtectionIndicator::CrcPresent
268        }
269    }
270
271    // Indicates what type of AAC data this stream contains
272    pub fn audio_object_type(&self) -> AudioObjectType {
273        match self.buf[2] & 0b1100_0000 {
274            0b0000_0000 => AudioObjectType::AacMain,
275            0b0100_0000 => AudioObjectType::AacLC,
276            0b1000_0000 => AudioObjectType::AacSSR,
277            0b1100_0000 => AudioObjectType::AacLTP,
278            v => panic!("impossible value {:#b}", v),
279        }
280    }
281
282    pub fn sampling_frequency(&self) -> SamplingFrequency {
283        SamplingFrequency::from(self.buf[2] >> 2 & 0b1111)
284    }
285
286    /// either 1 or 0
287    pub fn private_bit(&self) -> u8 {
288        self.buf[2] & 1
289    }
290
291    pub fn channel_configuration(&self) -> ChannelConfiguration {
292        ChannelConfiguration::from(self.buf[2] << 2 & 0b0100 | self.buf[3] >> 6)
293    }
294
295    pub fn originality(&self) -> Originality {
296        if self.buf[3] & 0b0010_0000 != 0 {
297            Originality::Copy
298        } else {
299            Originality::Original
300        }
301    }
302
303    /// either 1 or 0
304    pub fn home(&self) -> u8 {
305        self.buf[3] >> 4 & 1
306    }
307
308    /// either 1 or 0
309    pub fn copyright_identification_bit(&self) -> u8 {
310        self.buf[3] >> 3 & 1
311    }
312
313    pub fn copyright_identification_start(&self) -> CopyrightIdentificationStart {
314        if self.buf[3] & 0b0000_0100 != 0 {
315            CopyrightIdentificationStart::Start
316        } else {
317            CopyrightIdentificationStart::Other
318        }
319    }
320
321    /// length of this frame, including the length of the header.
322    pub fn frame_length(&self) -> u16 {
323        u16::from(self.buf[3] & 0b11) << 11
324            | u16::from(self.buf[4]) << 3
325            | u16::from(self.buf[5]) >> 5
326    }
327
328    /// Calculates the length of the frame payload from the `frame_length` header value, and the
329    /// total size of headers in this frame -- returning `None` if the `frame_length` header had a
330    /// value too small to even include the headers
331    pub fn payload_length(&self) -> Option<u16> {
332        let diff = self.frame_length() as i16 - self.header_length() as i16;
333        if diff >= 0 {
334            Some(diff as u16)
335        } else {
336            None
337        }
338    }
339
340    pub fn adts_buffer_fullness(&self) -> u16 {
341        u16::from(self.buf[5] & 0b00000011) << 6 | u16::from(self.buf[6]) >> 2
342    }
343
344    /// Gives the 16-bit cyclic redundancy check value stored in this frame header, or `None` if
345    /// the header does not supply a CRC.
346    ///
347    /// NB the implementation doesn't currently check that the CRC is correct
348    pub fn crc(&self) -> Option<u16> {
349        match self.protection() {
350            ProtectionIndicator::CrcAbsent => None,
351            ProtectionIndicator::CrcPresent => {
352                Some(u16::from(self.buf[7]) << 8 | u16::from(self.buf[8]))
353            }
354        }
355    }
356
357    /// The number of data blocks in the frame, a value between 1 and 4 inclusive.
358    ///
359    /// (Note that in the serialised ADTS data stores the _number of blocks - 1_.  This method
360    /// returns the actual number of blocks by adding one to the serialised value.)
361    ///
362    /// Most streams store a single block per ADTS frame
363    pub fn number_of_raw_data_blocks_in_frame(&self) -> u8 {
364        (self.buf[6] & 0b11) + 1
365    }
366
367    /// The payload AAC data inside this ADTS frame
368    pub fn payload(&self) -> Result<&'buf [u8], PayloadError> {
369        let len = self.frame_length() as usize;
370        if self.buf.len() < len {
371            Err(PayloadError {
372                expected: len,
373                actual: self.buf.len(),
374            })
375        } else {
376            Ok(&self.buf[self.header_length() as usize..len])
377        }
378    }
379}
380impl<'buf> fmt::Debug for AdtsHeader<'buf> {
381    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
382        f.debug_struct("AdtsHeader")
383            .field("mpeg_version", &self.mpeg_version())
384            .field("protection", &self.protection())
385            .field("audio_object_type", &self.audio_object_type())
386            .field("sampling_frequency", &self.sampling_frequency())
387            .field("private_bit", &self.private_bit())
388            .field("channel_configuration", &self.channel_configuration())
389            .field("originality", &self.originality())
390            .field("home", &self.home())
391            .field(
392                "copyright_identification_bit",
393                &self.copyright_identification_bit(),
394            )
395            .field(
396                "copyright_identification_start",
397                &self.copyright_identification_start(),
398            )
399            .field("frame_length", &self.frame_length())
400            .field("adts_buffer_fullness", &self.adts_buffer_fullness())
401            .field("crc", &self.crc())
402            .field(
403                "number_of_raw_data_blocks_in_frame",
404                &self.number_of_raw_data_blocks_in_frame(),
405            )
406            .finish()
407    }
408}
409
410#[derive(Debug, PartialEq)]
411pub enum CopyrightIdErr {
412    TooFewBits,
413    TooManyBits,
414}
415
416#[derive(Debug, PartialEq)]
417pub struct CopyrightIdentification {
418    pub copyright_identifier: u8,
419    pub copyright_number: u64,
420}
421
422#[derive(PartialEq)]
423enum AdtsState {
424    Start,
425    Incomplete,
426    Error,
427}
428
429#[derive(Debug, PartialEq)]
430pub enum AdtsParseError {
431    BadSyncWord,
432    BadFrameLength,
433}
434
435/// Trait to be implemented by types that wish to consume the ADTS data produced by [`AdtsParser`](struct.AdtsParser.html).
436///
437/// # Example
438///
439/// ```rust
440/// use adts_reader::*;
441///
442/// struct MyConsumer { }
443/// impl AdtsConsumer for MyConsumer {
444///     fn new_config(&mut self, mpeg_version: MpegVersion, protection: ProtectionIndicator, aot: AudioObjectType, freq: SamplingFrequency, private_bit: u8, channels: ChannelConfiguration, originality: Originality, home: u8) {
445///         println!("Configuration {:?} {:?} {:?}", aot, freq, channels);
446///     }
447///     fn payload(&mut self, buffer_fullness: u16, number_of_blocks: u8, buf: &[u8]) {
448///         println!(" - frame of {} bytes", buf.len());
449///     }
450///     fn error(&mut self, err: AdtsParseError) {
451///         println!(" - oops: {:?}", err);
452///     }
453/// }
454///
455/// let consumer = MyConsumer { };
456/// let parser = AdtsParser::new(consumer);
457/// ```
458pub trait AdtsConsumer {
459    /// Called when a new configuration is found within the ADTS bitstream
460    ///
461    /// An ADTS bitstream should have the same configuration throughout, so this would usually just
462    /// be called once at the beginning of the stream.  The audio configuration header values do
463    /// however appear in every frame (so that the bitstream format can support seeking, not that
464    /// this implementation helps there) and so it would be possible for a malformed bitstream to
465    /// signal a configuration change part way through.
466    fn new_config(
467        &mut self,
468        mpeg_version: MpegVersion,
469        protection: ProtectionIndicator,
470        aot: AudioObjectType,
471        freq: SamplingFrequency,
472        private_bit: u8,
473        channels: ChannelConfiguration,
474        originality: Originality,
475        home: u8,
476    );
477
478    /// called with the ADTS frame payload, and frame-specific header values
479    fn payload(&mut self, buffer_fullness: u16, number_of_blocks: u8, buf: &[u8]);
480
481    /// called if AdtsParser encounters an error in the ADTS bitstream.
482    fn error(&mut self, err: AdtsParseError);
483}
484
485/// Find ADTS frames within provided buffers of data, announcing audio configuration as it is
486/// discovered (normally just once at the start, but possibly changing during the stream if the
487/// stream is malformed).
488///
489/// Does not currently try to handle re-synchronise with the ADTS bitstream on encountering bad
490/// data.
491pub struct AdtsParser<C>
492where
493    C: AdtsConsumer,
494{
495    pub consumer: C,
496    current_config: [u8; 3],
497    state: AdtsState,
498    incomplete_frame: Vec<u8>,
499    desired_data_len: Option<usize>,
500}
501impl<C> AdtsParser<C>
502where
503    C: AdtsConsumer,
504{
505    pub fn new(consumer: C) -> AdtsParser<C> {
506        AdtsParser {
507            consumer,
508            current_config: [0; 3],
509            state: AdtsState::Start,
510            incomplete_frame: vec![],
511            desired_data_len: None,
512        }
513    }
514
515    fn is_new_config(&self, header_data: &[u8]) -> bool {
516        self.current_config != header_data[0..3]
517    }
518
519    fn remember(&mut self, remaining_data: &[u8], desired_data_len: usize) {
520        self.state = AdtsState::Incomplete;
521        self.incomplete_frame.clear();
522        self.incomplete_frame.extend_from_slice(remaining_data);
523        self.desired_data_len = Some(desired_data_len);
524    }
525
526    /// Initialize or re-initialize parser state.  Call this function before processing a group of
527    /// ADTS frames to ensure that any error state due to processing an earlier group of ADTS
528    /// frames is cleared.
529    pub fn start(&mut self) {
530        if self.state == AdtsState::Incomplete {
531            self.incomplete_frame.clear();
532            self.desired_data_len = None;
533            eprintln!("ADTS: incomplete data buffer dropped by call to start()");
534        }
535        self.state = AdtsState::Start;
536    }
537
538    /// Extracts information about each ADTS frame in the given buffer, which is passed to the
539    /// `AdtsConsumer` implementation supplied at construction time.
540    ///
541    /// If the given buffer ends part-way through an ADTS frame, the remaining unconsumed data
542    /// will be buffered inside this AdtsParser instance, and the rest of the ADTS frame may be
543    /// passed in another buffer in the next call to this method.
544    pub fn push(&mut self, adts_buf: &[u8]) {
545        let mut buf = adts_buf;
546        match self.state {
547            AdtsState::Error => return, // TODO: resync to recover from bitstream errors
548            AdtsState::Incomplete => {
549                // on last call to push(), the end of the adts_buf held the start of an ADTS
550                // frame, and we copied that data into incomplete_buffer, so now lets try to add
551                // enough initial bytes from the adts_buf given to this call to get a complete
552                // frame
553                loop {
554                    let bytes_needed_to_complete_frame = self.desired_data_len.unwrap() - self.incomplete_frame.len();
555                    if buf.len() < bytes_needed_to_complete_frame {
556                        self.incomplete_frame.extend_from_slice(buf);
557                        return;
558                    }
559                    self.incomplete_frame
560                        .extend_from_slice(&buf[..bytes_needed_to_complete_frame]);
561                    buf = &buf[bytes_needed_to_complete_frame..];
562                    let mut still_more = false; // TODO: this is horrible
563                    match AdtsHeader::from_bytes(&self.incomplete_frame[..]) {
564                        Ok(header) => {
565                            if (header.frame_length() as usize) > self.incomplete_frame.len() {
566                                self.desired_data_len = Some(header.frame_length() as usize);
567                                still_more = true;
568                            } else {
569                                if self.is_new_config(&self.incomplete_frame[..]) {
570                                    Self::push_config(
571                                        &mut self.current_config,
572                                        &mut self.consumer,
573                                        &header,
574                                        &self.incomplete_frame[..],
575                                    );
576                                }
577                                Self::push_payload(&mut self.consumer, header);
578                                self.state = AdtsState::Start;
579                            }
580                        }
581                        Err(e) => {
582                            self.state = AdtsState::Error;
583                            match e {
584                                AdtsHeaderError::BadSyncWord { .. } => {
585                                    self.consumer.error(AdtsParseError::BadSyncWord);
586                                    return;
587                                }
588                                AdtsHeaderError::BadFrameLength { .. } => {
589                                    self.consumer.error(AdtsParseError::BadFrameLength);
590                                    return;
591                                }
592                                AdtsHeaderError::NotEnoughData { expected, .. } => {
593                                    self.desired_data_len = Some(expected);
594                                    still_more = true;
595                                }
596                            }
597                        }
598                    }
599                    if !still_more {
600                        break;
601                    }
602                }
603            }
604            AdtsState::Start => (),
605        };
606        let mut pos = 0;
607        while pos < buf.len() {
608            let remaining_data = &buf[pos..];
609            let h = match AdtsHeader::from_bytes(remaining_data) {
610                Ok(header) => header,
611                Err(e) => {
612                    self.state = AdtsState::Error;
613                    match e {
614                        AdtsHeaderError::BadSyncWord { .. } => {
615                            self.consumer.error(AdtsParseError::BadSyncWord)
616                        }
617                        AdtsHeaderError::BadFrameLength { .. } => {
618                            self.consumer.error(AdtsParseError::BadFrameLength);
619                            return;
620                        }
621                        AdtsHeaderError::NotEnoughData { expected, .. } => {
622                            self.remember(remaining_data, expected);
623                            return;
624                        }
625                    }
626                    return;
627                }
628            };
629            let new_pos = pos + h.frame_length() as usize;
630            if new_pos > buf.len() {
631                self.remember(remaining_data, h.frame_length() as usize);
632                return;
633            }
634            if self.is_new_config(remaining_data) {
635                Self::push_config(
636                    &mut self.current_config,
637                    &mut self.consumer,
638                    &h,
639                    remaining_data,
640                );
641            }
642            Self::push_payload(&mut self.consumer, h);
643            self.state = AdtsState::Start;
644            pos = new_pos;
645        }
646    }
647
648    fn push_config(
649        current_config: &mut [u8; 3],
650        consumer: &mut C,
651        h: &AdtsHeader<'_>,
652        frame_buffer: &[u8],
653    ) {
654        current_config.copy_from_slice(&frame_buffer[0..3]);
655        consumer.new_config(
656            h.mpeg_version(),
657            h.protection(),
658            h.audio_object_type(),
659            h.sampling_frequency(),
660            h.private_bit(),
661            h.channel_configuration(),
662            h.originality(),
663            h.home(),
664        );
665    }
666
667    fn push_payload(consumer: &mut C, h: AdtsHeader<'_>) {
668        match h.payload() {
669            Ok(payload) => {
670                consumer.payload(
671                    h.adts_buffer_fullness(),
672                    h.number_of_raw_data_blocks_in_frame(),
673                    payload,
674                );
675            }
676            Err(PayloadError { expected, actual }) => {
677                // since we checked we had enough data for the whole frame above, this must be
678                // a bug,
679                panic!(
680                    "Unexpected payload size mismatch: expected {}, actual size {}",
681                    expected, actual
682                );
683            }
684        }
685    }
686}
687
688#[cfg(test)]
689mod tests {
690    use bitstream_io::{BitWriter, BE};
691    use std::io;
692    use super::*;
693
694    fn make_test_data<F>(builder: F) -> Vec<u8>
695    where
696        F: Fn(BitWriter<'_, BE>) -> Result<(), io::Error>,
697    {
698        let mut data: Vec<u8> = Vec::new();
699        builder(BitWriter::<BE>::new(&mut data)).unwrap();
700        data
701    }
702
703    fn write_frame(w: &mut BitWriter<'_, BE>) -> Result<(), io::Error> {
704        w.write(12, 0xfff)?; // sync_word
705        w.write(1, 0)?; // mpeg_version
706        w.write(2, 0)?; // layer
707        w.write(1, 1)?; // protection_absent
708        w.write(2, 0)?; // object_type
709        w.write(4, 0b0011)?; // sampling_frequency_index
710        w.write(1, 1)?; // private_bit
711        w.write(3, 2)?; // channel_configuration
712        w.write(1, 1)?; // original_copy
713        w.write(1, 0)?; // home
714        w.write(1, 0)?; // copyright_identification_bit
715        w.write(1, 1)?; // copyright_identification_start
716        w.write(13, 8)?; // frame_length
717        w.write(11, 123)?; // adts_buffer_fullness
718        w.write(2, 0)?; // number_of_raw_data_blocks_in_frame
719        w.write(8, 0b10000001) // 1 byte of payload data
720    }
721
722    #[test]
723    fn no_crc() {
724        let header_data = make_test_data(|mut w| write_frame(&mut w));
725        let header = AdtsHeader::from_bytes(&header_data[..]).unwrap();
726        assert_eq!(header.mpeg_version(), MpegVersion::Mpeg4);
727        assert_eq!(header.protection(), ProtectionIndicator::CrcAbsent);
728        assert_eq!(header.audio_object_type(), AudioObjectType::AacMain);
729        assert_eq!(header.sampling_frequency(), SamplingFrequency::Freq48000);
730        assert_eq!(header.sampling_frequency().freq(), Some(48000));
731        assert_eq!(header.channel_configuration(), ChannelConfiguration::Stereo);
732        assert_eq!(header.originality(), Originality::Copy);
733        assert_eq!(header.home(), 0);
734        assert_eq!(header.copyright_identification_bit(), 0);
735        assert_eq!(
736            header.copyright_identification_start(),
737            CopyrightIdentificationStart::Start
738        );
739        assert_eq!(header.frame_length(), 8);
740        assert_eq!(header.payload_length(), Some(8 - 7));
741        assert_eq!(header.adts_buffer_fullness(), 123);
742        assert_eq!(header.number_of_raw_data_blocks_in_frame(), 1);
743        assert_eq!(header.payload(), Ok(&[0b10000001][..]));
744    }
745
746    struct MockConsumer {
747        seq: usize,
748        payload_seq: usize,
749        payload_size: Option<usize>,
750    }
751    impl MockConsumer {
752        pub fn new() -> MockConsumer {
753            MockConsumer {
754                seq: 0,
755                payload_seq: 0,
756                payload_size: None
757            }
758        }
759        pub fn assert_seq(&mut self, expected: usize) {
760            assert_eq!(expected, self.seq);
761            self.seq += 1;
762        }
763    }
764    impl AdtsConsumer for MockConsumer {
765        // TODO: assertions are terribly brittle
766        fn new_config(
767            &mut self,
768            mpeg_version: MpegVersion,
769            _protection: ProtectionIndicator,
770            _aot: AudioObjectType,
771            _freq: SamplingFrequency,
772            _private_bit: u8,
773            _channels: ChannelConfiguration,
774            _originality: Originality,
775            _home: u8,
776        ) {
777            self.assert_seq(0);
778            assert_eq!(mpeg_version, MpegVersion::Mpeg4);
779        }
780        fn payload(&mut self, _buffer_fullness: u16, _number_of_blocks: u8, buf: &[u8]) {
781            self.payload_seq += 1;
782            let new_payload_seq = self.payload_seq;
783            self.assert_seq(new_payload_seq);
784            self.payload_size = Some(buf.len());
785        }
786        fn error(&mut self, err: AdtsParseError) {
787            panic!("no errors expected in bitstream: {:?}", err);
788        }
789    }
790
791    #[test]
792    fn parser() {
793        let header_data = make_test_data(|mut w| {
794            write_frame(&mut w)?;
795            write_frame(&mut w)
796        });
797        for split in 0..header_data.len() {
798            let mut parser = AdtsParser::new(MockConsumer::new());
799            let (head, tail) = header_data.split_at(split);
800            parser.push(head);
801            parser.push(tail);
802            assert_eq!(2, parser.consumer.payload_seq);
803            assert_eq!(Some(1), parser.consumer.payload_size);
804        }
805    }
806
807    #[test]
808    fn too_short() {
809        let header_data = make_test_data(|mut w| write_frame(&mut w));
810        let mut parser = AdtsParser::new(MockConsumer::new());
811        parser.push(&header_data[..5]);
812        parser.push(&header_data[5..7]);
813    }
814}