ac_ffmpeg/codec/audio/
mod.rs

1//! Audio decoder/encoder.
2
3pub mod frame;
4pub mod resampler;
5pub mod transcoder;
6
7use std::{ffi::CString, os::raw::c_void, ptr};
8
9use crate::{
10    codec::{AudioCodecParameters, CodecError, CodecParameters, CodecTag, Decoder, Encoder},
11    format::stream::Stream,
12    packet::Packet,
13    time::TimeBase,
14    Error,
15};
16
17pub use self::{
18    frame::{AudioFrame, AudioFrameMut, ChannelLayout, ChannelLayoutRef, SampleFormat},
19    resampler::AudioResampler,
20    transcoder::AudioTranscoder,
21};
22
23/// Builder for the audio decoder.
24pub struct AudioDecoderBuilder {
25    ptr: *mut c_void,
26    time_base: TimeBase,
27}
28
29impl AudioDecoderBuilder {
30    /// Create a new decoder builder from a given raw representation.
31    unsafe fn from_raw_ptr(ptr: *mut c_void) -> Self {
32        let time_base = TimeBase::MICROSECONDS;
33
34        super::ffw_decoder_set_pkt_timebase(ptr, time_base.num() as _, time_base.den() as _);
35
36        Self { ptr, time_base }
37    }
38
39    /// Create a new builder for a given codec.
40    fn new(codec: &str) -> Result<Self, Error> {
41        let codec = CString::new(codec).expect("invalid codec name");
42
43        let ptr = unsafe { super::ffw_decoder_new(codec.as_ptr() as _) };
44
45        if ptr.is_null() {
46            return Err(Error::new("unknown codec"));
47        }
48
49        unsafe { Ok(Self::from_raw_ptr(ptr)) }
50    }
51
52    /// Create a new builder from given codec parameters.
53    fn from_codec_parameters(codec_parameters: &AudioCodecParameters) -> Result<Self, Error> {
54        let ptr = unsafe { super::ffw_decoder_from_codec_parameters(codec_parameters.as_ptr()) };
55
56        if ptr.is_null() {
57            return Err(Error::new("unable to create a decoder"));
58        }
59
60        unsafe { Ok(Self::from_raw_ptr(ptr)) }
61    }
62
63    /// Set a decoder option.
64    pub fn set_option<V>(self, name: &str, value: V) -> Self
65    where
66        V: ToString,
67    {
68        let name = CString::new(name).expect("invalid option name");
69        let value = CString::new(value.to_string()).expect("invalid option value");
70
71        let ret = unsafe {
72            super::ffw_decoder_set_initial_option(self.ptr, name.as_ptr() as _, value.as_ptr() as _)
73        };
74
75        if ret < 0 {
76            panic!("unable to allocate an option");
77        }
78
79        self
80    }
81
82    /// Set decoder time base (all input packets will be rescaled into this
83    /// time base). The default time base is in microseconds.
84    pub fn time_base(mut self, time_base: TimeBase) -> Self {
85        self.time_base = time_base;
86
87        unsafe {
88            super::ffw_decoder_set_pkt_timebase(
89                self.ptr,
90                time_base.num() as _,
91                time_base.den() as _,
92            );
93        }
94
95        self
96    }
97
98    /// Set codec extradata.
99    pub fn extradata<T>(self, data: Option<T>) -> Self
100    where
101        T: AsRef<[u8]>,
102    {
103        let data = data.as_ref().map(|d| d.as_ref());
104
105        let ptr;
106        let size;
107
108        if let Some(data) = data {
109            ptr = data.as_ptr();
110            size = data.len();
111        } else {
112            ptr = ptr::null();
113            size = 0;
114        }
115
116        let res = unsafe { super::ffw_decoder_set_extradata(self.ptr, ptr, size as _) };
117
118        if res < 0 {
119            panic!("unable to allocate extradata");
120        }
121
122        self
123    }
124
125    /// Build the decoder.
126    pub fn build(mut self) -> Result<AudioDecoder, Error> {
127        unsafe {
128            if super::ffw_decoder_open(self.ptr) != 0 {
129                return Err(Error::new("unable to build the decoder"));
130            }
131        }
132
133        let ptr = self.ptr;
134
135        self.ptr = ptr::null_mut();
136
137        let res = AudioDecoder {
138            ptr,
139            time_base: self.time_base,
140        };
141
142        Ok(res)
143    }
144}
145
146impl Drop for AudioDecoderBuilder {
147    fn drop(&mut self) {
148        unsafe { super::ffw_decoder_free(self.ptr) }
149    }
150}
151
152unsafe impl Send for AudioDecoderBuilder {}
153unsafe impl Sync for AudioDecoderBuilder {}
154
155/// Audio decoder.
156pub struct AudioDecoder {
157    ptr: *mut c_void,
158    time_base: TimeBase,
159}
160
161impl AudioDecoder {
162    /// Create a new audio decoder for a given codec.
163    pub fn new(codec: &str) -> Result<Self, Error> {
164        AudioDecoderBuilder::new(codec).and_then(|builder| builder.build())
165    }
166
167    /// Create a new decoder from given codec parameters.
168    pub fn from_codec_parameters(
169        codec_parameters: &AudioCodecParameters,
170    ) -> Result<AudioDecoderBuilder, Error> {
171        AudioDecoderBuilder::from_codec_parameters(codec_parameters)
172    }
173
174    /// Create a new decoder for a given stream.
175    ///
176    /// # Panics
177    /// The method panics if the stream is not an audio stream.
178    pub fn from_stream(stream: &Stream) -> Result<AudioDecoderBuilder, Error> {
179        let codec_parameters = stream
180            .codec_parameters()
181            .into_audio_codec_parameters()
182            .unwrap();
183
184        let builder = AudioDecoderBuilder::from_codec_parameters(&codec_parameters)?
185            .time_base(stream.time_base());
186
187        Ok(builder)
188    }
189
190    /// Get decoder builder for a given codec.
191    pub fn builder(codec: &str) -> Result<AudioDecoderBuilder, Error> {
192        AudioDecoderBuilder::new(codec)
193    }
194}
195
196impl Decoder for AudioDecoder {
197    type CodecParameters = AudioCodecParameters;
198    type Frame = AudioFrame;
199
200    fn codec_parameters(&self) -> Self::CodecParameters {
201        let ptr = unsafe { super::ffw_decoder_get_codec_parameters(self.ptr) };
202
203        if ptr.is_null() {
204            panic!("unable to allocate codec parameters");
205        }
206
207        let params = unsafe { CodecParameters::from_raw_ptr(ptr) };
208
209        params.into_audio_codec_parameters().unwrap()
210    }
211
212    fn try_push(&mut self, packet: Packet) -> Result<(), CodecError> {
213        let packet = packet.with_time_base(self.time_base);
214
215        unsafe {
216            match super::ffw_decoder_push_packet(self.ptr, packet.as_ptr()) {
217                1 => Ok(()),
218                0 => Err(CodecError::again(
219                    "all frames must be consumed before pushing a new packet",
220                )),
221                e => Err(CodecError::from_raw_error_code(e)),
222            }
223        }
224    }
225
226    fn try_flush(&mut self) -> Result<(), CodecError> {
227        unsafe {
228            match super::ffw_decoder_push_packet(self.ptr, ptr::null()) {
229                1 => Ok(()),
230                0 => Err(CodecError::again(
231                    "all frames must be consumed before flushing",
232                )),
233                e => Err(CodecError::from_raw_error_code(e)),
234            }
235        }
236    }
237
238    fn take(&mut self) -> Result<Option<AudioFrame>, Error> {
239        let mut fptr = ptr::null_mut();
240
241        unsafe {
242            match super::ffw_decoder_take_frame(self.ptr, &mut fptr) {
243                1 => {
244                    if fptr.is_null() {
245                        panic!("no frame received")
246                    } else {
247                        Ok(Some(AudioFrame::from_raw_ptr(fptr, self.time_base)))
248                    }
249                }
250                0 => Ok(None),
251                e => Err(Error::from_raw_error_code(e)),
252            }
253        }
254    }
255}
256
257impl Drop for AudioDecoder {
258    fn drop(&mut self) {
259        unsafe { super::ffw_decoder_free(self.ptr) }
260    }
261}
262
263unsafe impl Send for AudioDecoder {}
264unsafe impl Sync for AudioDecoder {}
265
266/// Wrapper for the raw audio encoder.
267struct RawAudioEncoder {
268    ptr: *mut c_void,
269}
270
271impl RawAudioEncoder {
272    /// Create a new encoder wrapper.
273    fn from_raw_ptr(ptr: *mut c_void) -> Self {
274        Self { ptr }
275    }
276}
277
278impl Drop for RawAudioEncoder {
279    fn drop(&mut self) {
280        unsafe { super::ffw_encoder_free(self.ptr) }
281    }
282}
283
284unsafe impl Send for RawAudioEncoder {}
285unsafe impl Sync for RawAudioEncoder {}
286
287/// Builder for the audio encoder.
288pub struct AudioEncoderBuilder {
289    raw: RawAudioEncoder,
290
291    time_base: TimeBase,
292
293    sample_format: Option<SampleFormat>,
294    sample_rate: Option<u32>,
295    channel_layout: Option<ChannelLayout>,
296}
297
298impl AudioEncoderBuilder {
299    /// Create a new encoder builder for a given codec.
300    fn new(codec: &str) -> Result<Self, Error> {
301        let codec = CString::new(codec).expect("invalid codec name");
302
303        let ptr = unsafe { super::ffw_encoder_new(codec.as_ptr() as _) };
304
305        if ptr.is_null() {
306            return Err(Error::new("unknown codec"));
307        }
308
309        unsafe {
310            super::ffw_encoder_set_bit_rate(ptr, 0);
311        }
312
313        let res = Self {
314            raw: RawAudioEncoder::from_raw_ptr(ptr),
315
316            time_base: TimeBase::MICROSECONDS,
317
318            sample_format: None,
319            sample_rate: None,
320            channel_layout: None,
321        };
322
323        Ok(res)
324    }
325
326    /// Create a new encoder builder from given codec parameters.
327    fn from_codec_parameters(codec_parameters: &AudioCodecParameters) -> Result<Self, Error> {
328        let ptr = unsafe { super::ffw_encoder_from_codec_parameters(codec_parameters.as_ptr()) };
329
330        if ptr.is_null() {
331            return Err(Error::new("unable to create an encoder"));
332        }
333
334        let sample_format;
335        let sample_rate;
336        let channel_layout;
337
338        unsafe {
339            sample_format = SampleFormat::from_raw(super::ffw_encoder_get_sample_format(ptr));
340            sample_rate = super::ffw_encoder_get_sample_rate(ptr) as _;
341            channel_layout =
342                ChannelLayoutRef::from_raw_ptr(super::ffw_encoder_get_channel_layout(ptr));
343        }
344
345        let channel_layout = channel_layout.to_owned();
346
347        let res = Self {
348            raw: RawAudioEncoder::from_raw_ptr(ptr),
349
350            time_base: TimeBase::MICROSECONDS,
351
352            sample_format: Some(sample_format),
353            sample_rate: Some(sample_rate),
354            channel_layout: Some(channel_layout),
355        };
356
357        Ok(res)
358    }
359
360    /// Set an encoder option.
361    pub fn set_option<V>(self, name: &str, value: V) -> Self
362    where
363        V: ToString,
364    {
365        let name = CString::new(name).expect("invalid option name");
366        let value = CString::new(value.to_string()).expect("invalid option value");
367
368        let ret = unsafe {
369            super::ffw_encoder_set_initial_option(
370                self.raw.ptr,
371                name.as_ptr() as _,
372                value.as_ptr() as _,
373            )
374        };
375
376        if ret < 0 {
377            panic!("unable to allocate an option");
378        }
379
380        self
381    }
382
383    /// Set encoder bit rate. The default is 0 (i.e. automatic).
384    pub fn bit_rate(self, bit_rate: u64) -> Self {
385        unsafe {
386            super::ffw_encoder_set_bit_rate(self.raw.ptr, bit_rate as _);
387        }
388
389        self
390    }
391
392    /// Set encoder time base. The default time base is in microseconds.
393    #[inline]
394    pub fn time_base(mut self, time_base: TimeBase) -> Self {
395        self.time_base = time_base;
396        self
397    }
398
399    /// Set audio sample format.
400    #[inline]
401    pub fn sample_format(mut self, format: SampleFormat) -> Self {
402        self.sample_format = Some(format);
403        self
404    }
405
406    /// Set sampling rate.
407    #[inline]
408    pub fn sample_rate(mut self, rate: u32) -> Self {
409        self.sample_rate = Some(rate);
410        self
411    }
412
413    /// Set channel layout.
414    #[inline]
415    pub fn channel_layout(mut self, layout: ChannelLayout) -> Self {
416        self.channel_layout = Some(layout);
417        self
418    }
419
420    /// Set codec tag.
421    pub fn codec_tag(self, codec_tag: impl Into<CodecTag>) -> Self {
422        unsafe {
423            super::ffw_encoder_set_codec_tag(self.raw.ptr, codec_tag.into().into());
424        }
425
426        self
427    }
428
429    /// Build the encoder.
430    pub fn build(self) -> Result<AudioEncoder, Error> {
431        let sample_format = self
432            .sample_format
433            .ok_or_else(|| Error::new("sample format not set"))?;
434
435        let sample_rate = self
436            .sample_rate
437            .ok_or_else(|| Error::new("sample rate not set"))?;
438
439        let channel_layout = self
440            .channel_layout
441            .ok_or_else(|| Error::new("channel layout not set"))?;
442
443        let tb = self.time_base;
444
445        unsafe {
446            super::ffw_encoder_set_time_base(self.raw.ptr, tb.num() as _, tb.den() as _);
447            super::ffw_encoder_set_sample_format(self.raw.ptr, sample_format.into_raw());
448            super::ffw_encoder_set_sample_rate(self.raw.ptr, sample_rate as _);
449
450            if super::ffw_encoder_set_channel_layout(self.raw.ptr, channel_layout.as_ptr()) != 0 {
451                panic!("unable to copy channel layout");
452            }
453
454            if super::ffw_encoder_open(self.raw.ptr) != 0 {
455                return Err(Error::new("unable to build the encoder"));
456            }
457        }
458
459        let res = AudioEncoder {
460            raw: self.raw,
461            time_base: tb,
462        };
463
464        Ok(res)
465    }
466}
467
468/// Audio encoder.
469pub struct AudioEncoder {
470    raw: RawAudioEncoder,
471    time_base: TimeBase,
472}
473
474impl AudioEncoder {
475    /// Create a new encoder builder from given codec parameters.
476    pub fn from_codec_parameters(
477        codec_parameters: &AudioCodecParameters,
478    ) -> Result<AudioEncoderBuilder, Error> {
479        AudioEncoderBuilder::from_codec_parameters(codec_parameters)
480    }
481
482    /// Get encoder builder for a given codec.
483    pub fn builder(codec: &str) -> Result<AudioEncoderBuilder, Error> {
484        AudioEncoderBuilder::new(codec)
485    }
486
487    /// Number of samples per audio channel in an audio frame. Each encoded
488    /// frame except the last one must contain exactly this number of samples.
489    /// The method returns None if the number of samples per frame is not
490    /// restricted.
491    pub fn samples_per_frame(&self) -> Option<usize> {
492        let res = unsafe { super::ffw_encoder_get_frame_size(self.raw.ptr) as _ };
493
494        if res == 0 {
495            None
496        } else {
497            Some(res)
498        }
499    }
500}
501
502impl Encoder for AudioEncoder {
503    type CodecParameters = AudioCodecParameters;
504    type Frame = AudioFrame;
505
506    fn codec_parameters(&self) -> Self::CodecParameters {
507        let ptr = unsafe { super::ffw_encoder_get_codec_parameters(self.raw.ptr) };
508
509        if ptr.is_null() {
510            panic!("unable to allocate codec parameters");
511        }
512
513        let params = unsafe { CodecParameters::from_raw_ptr(ptr) };
514
515        params.into_audio_codec_parameters().unwrap()
516    }
517
518    fn try_push(&mut self, frame: AudioFrame) -> Result<(), CodecError> {
519        let frame = frame.with_time_base(self.time_base);
520
521        unsafe {
522            match super::ffw_encoder_push_frame(self.raw.ptr, frame.as_ptr()) {
523                1 => Ok(()),
524                0 => Err(CodecError::again(
525                    "all packets must be consumed before pushing a new frame",
526                )),
527                e => Err(CodecError::from_raw_error_code(e)),
528            }
529        }
530    }
531
532    fn try_flush(&mut self) -> Result<(), CodecError> {
533        unsafe {
534            match super::ffw_encoder_push_frame(self.raw.ptr, ptr::null()) {
535                1 => Ok(()),
536                0 => Err(CodecError::again(
537                    "all packets must be consumed before flushing",
538                )),
539                e => Err(CodecError::from_raw_error_code(e)),
540            }
541        }
542    }
543
544    fn take(&mut self) -> Result<Option<Packet>, Error> {
545        let mut pptr = ptr::null_mut();
546
547        unsafe {
548            match super::ffw_encoder_take_packet(self.raw.ptr, &mut pptr) {
549                1 => {
550                    if pptr.is_null() {
551                        panic!("no packet received")
552                    } else {
553                        Ok(Some(Packet::from_raw_ptr(pptr, self.time_base)))
554                    }
555                }
556                0 => Ok(None),
557                e => Err(Error::from_raw_error_code(e)),
558            }
559        }
560    }
561}