scuffle_flv/
audio.rs

1use std::io;
2
3use byteorder::ReadBytesExt;
4use bytes::Bytes;
5use nutype_enum::nutype_enum;
6use scuffle_bytes_util::BytesCursorExt;
7
8use super::aac::{AacPacket, AacPacketType};
9
10/// FLV Tag Audio Data
11///
12/// This is the container for the audio data.
13///
14/// Defined by:
15/// - video_file_format_spec_v10.pdf (Chapter 1 - The FLV File Format - Audio tags)
16/// - video_file_format_spec_v10_1.pdf (Annex E.4.2.1 - AUDIODATA)
17#[derive(Debug, Clone, PartialEq)]
18pub struct AudioData {
19    /// The sound rate of the audio data. (2 bits)
20    pub sound_rate: SoundRate,
21    /// The sound size of the audio data. (1 bit)
22    pub sound_size: SoundSize,
23    /// The sound type of the audio data. (1 bit)
24    pub sound_type: SoundType,
25    /// The body of the audio data.
26    pub body: AudioDataBody,
27}
28
29impl AudioData {
30    pub fn demux(reader: &mut io::Cursor<Bytes>) -> io::Result<Self> {
31        let byte = reader.read_u8()?;
32        // SoundFormat is the first 4 bits of the byte
33        let sound_format = SoundFormat::from(byte >> 4);
34        // SoundRate is the next 2 bits of the byte
35        let sound_rate = SoundRate::from((byte >> 2) & 0b11);
36        // SoundSize is the next bit of the byte
37        let sound_size = SoundSize::from((byte >> 1) & 0b1);
38        // SoundType is the last bit of the byte
39        let sound_type = SoundType::from(byte & 0b1);
40
41        // Now we can demux the body of the audio data
42        let body = AudioDataBody::demux(sound_format, reader)?;
43
44        Ok(AudioData {
45            sound_rate,
46            sound_size,
47            sound_type,
48            body,
49        })
50    }
51}
52
53nutype_enum! {
54    /// FLV Sound Format
55    ///
56    /// Denotes the type of the underlying data packet
57    ///
58    /// Defined by:
59    /// - video_file_format_spec_v10.pdf (Chapter 1 - The FLV File Format - Audio tags)
60    /// - video_file_format_spec_v10_1.pdf (Annex E.4.2.1 - AUDIODATA)
61    pub enum SoundFormat(u8) {
62        /// Linear PCM, platform endian
63        LinearPcmPlatformEndian = 0,
64        /// ADPCM
65        Adpcm = 1,
66        /// MP3
67        Mp3 = 2,
68        /// Linear PCM, little endian
69        LinearPcmLittleEndian = 3,
70        /// Nellymoser 16Khz Mono
71        Nellymoser16KhzMono = 4,
72        /// Nellymoser 8Khz Mono
73        Nellymoser8KhzMono = 5,
74        /// Nellymoser
75        Nellymoser = 6,
76        /// G.711 A-Law logarithmic PCM
77        G711ALaw = 7,
78        /// G.711 Mu-Law logarithmic PCM
79        G711MuLaw = 8,
80        /// AAC
81        Aac = 10,
82        /// Speex
83        Speex = 11,
84        /// Mp3 8Khz
85        Mp38Khz = 14,
86        /// Device specific sound
87        DeviceSpecificSound = 15,
88    }
89}
90
91/// FLV Tag Audio Data Body
92///
93/// This is the container for the audio data body.
94///
95/// Defined by:
96/// - video_file_format_spec_v10.pdf (Chapter 1 - The FLV File Format - Audio tags)
97/// - video_file_format_spec_v10_1.pdf (Annex E.4.2.1 - AUDIODATA)
98#[derive(Debug, Clone, PartialEq)]
99pub enum AudioDataBody {
100    /// AAC Audio Packet
101    Aac(AacPacket),
102    /// Some other audio format we don't know how to parse
103    Unknown { sound_format: SoundFormat, data: Bytes },
104}
105
106impl AudioDataBody {
107    /// Demux the audio data body from the given reader
108    ///
109    /// The reader will be entirely consumed.
110    pub fn demux(sound_format: SoundFormat, reader: &mut io::Cursor<Bytes>) -> io::Result<Self> {
111        match sound_format {
112            SoundFormat::Aac => {
113                // For some reason the spec adds a specific byte before the AAC data.
114                // This byte is the AAC packet type.
115                let aac_packet_type = AacPacketType::from(reader.read_u8()?);
116                Ok(Self::Aac(AacPacket::new(aac_packet_type, reader.extract_remaining())))
117            }
118            _ => Ok(Self::Unknown {
119                sound_format,
120                data: reader.extract_remaining(),
121            }),
122        }
123    }
124}
125
126nutype_enum! {
127    /// FLV Sound Rate
128    ///
129    /// Denotes the sampling rate of the audio data.
130    ///
131    /// Defined by:
132    /// - video_file_format_spec_v10.pdf (Chapter 1 - The FLV File Format - Audio tags)
133    /// - video_file_format_spec_v10_1.pdf (Annex E.4.2.1 - AUDIODATA)
134    pub enum SoundRate(u8) {
135        /// 5.5 KHz
136        Hz5500 = 0,
137        /// 11 KHz
138        Hz11000 = 1,
139        /// 22 KHz
140        Hz22000 = 2,
141        /// 44 KHz
142        Hz44000 = 3,
143    }
144}
145
146nutype_enum! {
147    /// FLV Sound Size
148    ///
149    /// Denotes the size of each sample in the audio data.
150    ///
151    /// Defined by:
152    /// - video_file_format_spec_v10.pdf (Chapter 1 - The FLV File Format - Audio tags)
153    /// - video_file_format_spec_v10_1.pdf (Annex E.4.2.1 - AUDIODATA)
154    pub enum SoundSize(u8) {
155        /// 8 bit
156        Bit8 = 0,
157        /// 16 bit
158        Bit16 = 1,
159    }
160}
161
162nutype_enum! {
163    /// FLV Sound Type
164    ///
165    /// Denotes the number of channels in the audio data.
166    ///
167    /// Defined by:
168    /// - video_file_format_spec_v10.pdf (Chapter 1 - The FLV File Format - Audio tags)
169    /// - video_file_format_spec_v10_1.pdf (Annex E.4.2.1 - AUDIODATA)
170    pub enum SoundType(u8) {
171        /// Mono
172        Mono = 0,
173        /// Stereo
174        Stereo = 1,
175    }
176}
177
178#[cfg(test)]
179#[cfg_attr(all(test, coverage_nightly), coverage(off))]
180mod tests {
181    use super::*;
182
183    #[test]
184    fn test_sound_format() {
185        let cases = [
186            (
187                0x00,
188                SoundFormat::LinearPcmPlatformEndian,
189                "SoundFormat::LinearPcmPlatformEndian",
190            ),
191            (0x01, SoundFormat::Adpcm, "SoundFormat::Adpcm"),
192            (0x02, SoundFormat::Mp3, "SoundFormat::Mp3"),
193            (0x03, SoundFormat::LinearPcmLittleEndian, "SoundFormat::LinearPcmLittleEndian"),
194            (0x04, SoundFormat::Nellymoser16KhzMono, "SoundFormat::Nellymoser16KhzMono"),
195            (0x05, SoundFormat::Nellymoser8KhzMono, "SoundFormat::Nellymoser8KhzMono"),
196            (0x06, SoundFormat::Nellymoser, "SoundFormat::Nellymoser"),
197            (0x07, SoundFormat::G711ALaw, "SoundFormat::G711ALaw"),
198            (0x08, SoundFormat::G711MuLaw, "SoundFormat::G711MuLaw"),
199            (0x0A, SoundFormat::Aac, "SoundFormat::Aac"),
200            (0x0B, SoundFormat::Speex, "SoundFormat::Speex"),
201            (0x0E, SoundFormat::Mp38Khz, "SoundFormat::Mp38Khz"),
202            (0x0F, SoundFormat::DeviceSpecificSound, "SoundFormat::DeviceSpecificSound"),
203        ];
204
205        for (value, expected, name) in cases {
206            let sound_format = SoundFormat::from(value);
207            assert_eq!(sound_format, expected);
208            assert_eq!(format!("{:?}", sound_format), name);
209        }
210    }
211
212    #[test]
213    fn test_sound_rate() {
214        let cases = [
215            (0x00, SoundRate::Hz5500, "SoundRate::Hz5500"),
216            (0x01, SoundRate::Hz11000, "SoundRate::Hz11000"),
217            (0x02, SoundRate::Hz22000, "SoundRate::Hz22000"),
218            (0x03, SoundRate::Hz44000, "SoundRate::Hz44000"),
219        ];
220
221        for (value, expected, name) in cases {
222            let sound_rate = SoundRate::from(value);
223            assert_eq!(sound_rate, expected);
224            assert_eq!(format!("{:?}", sound_rate), name);
225        }
226    }
227
228    #[test]
229    fn test_sound_size() {
230        let cases = [
231            (0x00, SoundSize::Bit8, "SoundSize::Bit8"),
232            (0x01, SoundSize::Bit16, "SoundSize::Bit16"),
233        ];
234
235        for (value, expected, name) in cases {
236            let sound_size = SoundSize::from(value);
237            assert_eq!(sound_size, expected);
238            assert_eq!(format!("{:?}", sound_size), name);
239        }
240    }
241
242    #[test]
243    fn test_sound_type() {
244        let cases = [
245            (0x00, SoundType::Mono, "SoundType::Mono"),
246            (0x01, SoundType::Stereo, "SoundType::Stereo"),
247        ];
248
249        for (value, expected, name) in cases {
250            let sound_type = SoundType::from(value);
251            assert_eq!(sound_type, expected);
252            assert_eq!(format!("{:?}", sound_type), name);
253        }
254    }
255
256    #[test]
257    fn test_audio_data_demux() {
258        let mut reader = io::Cursor::new(Bytes::from(vec![0b10101101, 0b00000000, 1, 2, 3]));
259
260        let audio_data = AudioData::demux(&mut reader).unwrap();
261        assert_eq!(audio_data.sound_rate, SoundRate::Hz44000);
262        assert_eq!(audio_data.sound_size, SoundSize::Bit8);
263        assert_eq!(audio_data.sound_type, SoundType::Stereo);
264        assert_eq!(
265            audio_data.body,
266            AudioDataBody::Aac(AacPacket::SequenceHeader(Bytes::from(vec![1, 2, 3])))
267        );
268
269        let mut reader = io::Cursor::new(Bytes::from(vec![0b10101101, 0b00100000, 1, 2, 3]));
270
271        let audio_data = AudioData::demux(&mut reader).unwrap();
272        assert_eq!(audio_data.sound_rate, SoundRate::Hz44000);
273        assert_eq!(audio_data.sound_size, SoundSize::Bit8);
274        assert_eq!(audio_data.sound_type, SoundType::Stereo);
275        assert_eq!(
276            audio_data.body,
277            AudioDataBody::Aac(AacPacket::Unknown {
278                aac_packet_type: AacPacketType(0b00100000),
279                data: Bytes::from(vec![1, 2, 3])
280            })
281        );
282
283        let mut reader = io::Cursor::new(Bytes::from(vec![0b10001101, 0b00000000, 1, 2, 3]));
284
285        let audio_data = AudioData::demux(&mut reader).unwrap();
286        assert_eq!(
287            audio_data.body,
288            AudioDataBody::Unknown {
289                sound_format: SoundFormat(8),
290                data: Bytes::from(vec![0, 1, 2, 3])
291            }
292        );
293    }
294}