ac_ffmpeg/codec/audio/frame/
mod.rs

1//! Audio frame.
2
3#[cfg(not(channel_layout_v2))]
4mod channels_v1;
5
6#[cfg(channel_layout_v2)]
7mod channels_v2;
8
9use std::{
10    ffi::{CStr, CString},
11    fmt::{self, Display, Formatter},
12    marker::PhantomData,
13    ops::{Deref, DerefMut},
14    os::raw::{c_char, c_int, c_void},
15    ptr, slice,
16    str::FromStr,
17};
18
19use crate::time::{TimeBase, Timestamp};
20
21#[cfg(not(channel_layout_v2))]
22pub use channels_v1::{ChannelLayout, ChannelLayoutRef};
23
24#[cfg(channel_layout_v2)]
25pub use channels_v2::{ChannelLayout, ChannelLayoutRef};
26
27extern "C" {
28    fn ffw_get_sample_format_by_name(name: *const c_char) -> c_int;
29    fn ffw_get_sample_format_name(format: c_int) -> *const c_char;
30    fn ffw_sample_format_is_planar(format: c_int) -> c_int;
31    fn ffw_sample_format_is_none(format: c_int) -> c_int;
32
33    fn ffw_frame_new_silence(
34        channel_layout: *const c_void,
35        sample_fmt: c_int,
36        sample_rate: c_int,
37        nb_samples: c_int,
38    ) -> *mut c_void;
39    fn ffw_frame_get_format(frame: *const c_void) -> c_int;
40    fn ffw_frame_get_nb_samples(frame: *const c_void) -> c_int;
41    fn ffw_frame_get_sample_rate(frame: *const c_void) -> c_int;
42    fn ffw_frame_get_channel_layout(frame: *const c_void) -> *const c_void;
43    fn ffw_frame_get_pts(frame: *const c_void) -> i64;
44    fn ffw_frame_set_pts(frame: *mut c_void, pts: i64);
45    fn ffw_frame_get_plane_data(frame: *mut c_void, index: usize) -> *mut u8;
46    fn ffw_frame_get_line_size(frame: *const c_void, plane: usize) -> usize;
47    fn ffw_frame_clone(frame: *const c_void) -> *mut c_void;
48    fn ffw_frame_free(frame: *mut c_void);
49    fn ffw_frame_is_writable(frame: *const c_void) -> c_int;
50    fn ffw_frame_make_writable(frame: *mut c_void) -> c_int;
51}
52
53/// An error indicating an unknown channel layout.
54#[derive(Debug, Copy, Clone)]
55pub struct UnknownChannelLayout;
56
57impl Display for UnknownChannelLayout {
58    fn fmt(&self, f: &mut Formatter) -> Result<(), fmt::Error> {
59        f.write_str("unknown channel layout")
60    }
61}
62
63impl std::error::Error for UnknownChannelLayout {}
64
65/// Get channel layout with a given name.
66pub fn get_channel_layout(name: &str) -> ChannelLayout {
67    ChannelLayout::from_str(name).unwrap()
68}
69
70/// An error indicating an unknown sample format.
71#[derive(Debug, Copy, Clone)]
72pub struct UnknownSampleFormat;
73
74/// Audio sample format.
75#[derive(Copy, Clone, Eq, PartialEq)]
76pub struct SampleFormat(c_int);
77
78impl SampleFormat {
79    /// Create a sample format value from a given raw representation.
80    pub(crate) fn from_raw(v: c_int) -> Self {
81        Self(v)
82    }
83
84    /// Get the raw value.
85    pub(crate) fn into_raw(self) -> c_int {
86        let Self(format) = self;
87
88        format
89    }
90
91    /// Get name of the sample format.
92    pub fn name(self) -> &'static str {
93        unsafe {
94            let ptr = ffw_get_sample_format_name(self.into_raw());
95
96            if ptr.is_null() {
97                panic!("invalid sample format");
98            }
99
100            let name = CStr::from_ptr(ptr as _);
101
102            name.to_str().unwrap()
103        }
104    }
105
106    /// Check if the sample format is planar (i.e. each channel has its own
107    /// plane).
108    pub fn is_planar(self) -> bool {
109        unsafe { ffw_sample_format_is_planar(self.into_raw()) != 0 }
110    }
111}
112
113impl FromStr for SampleFormat {
114    type Err = UnknownSampleFormat;
115
116    fn from_str(s: &str) -> Result<Self, Self::Err> {
117        let name = CString::new(s).expect("invalid sample format name");
118
119        unsafe {
120            let format = ffw_get_sample_format_by_name(name.as_ptr() as _);
121
122            if ffw_sample_format_is_none(format) == 0 {
123                Ok(Self(format))
124            } else {
125                Err(UnknownSampleFormat)
126            }
127        }
128    }
129}
130
131/// Get audio sample format with a given name.
132pub fn get_sample_format(name: &str) -> SampleFormat {
133    SampleFormat::from_str(name).unwrap()
134}
135
136/// Audio plane. This is an array of audio sample data. Depending on the
137/// sample format, this can either be samples for a single channel, or
138/// for all channels multiplexed together.
139pub struct Plane<'a> {
140    frame: *mut c_void,
141    index: usize,
142    line_size: usize,
143    phantom: PhantomData<&'a ()>,
144}
145
146impl Plane<'_> {
147    /// Create a new plane.
148    fn new(frame: *mut c_void, index: usize, line_size: usize) -> Self {
149        Self {
150            frame,
151            index,
152            line_size,
153            phantom: PhantomData,
154        }
155    }
156
157    /// Get plane data.
158    pub fn data(&self) -> &[u8] {
159        unsafe {
160            let data = ffw_frame_get_plane_data(self.frame, self.index as _);
161            slice::from_raw_parts(data, self.line_size)
162        }
163    }
164
165    /// Get mutable plane data.
166    pub fn data_mut(&mut self) -> &mut [u8] {
167        unsafe {
168            let data = ffw_frame_get_plane_data(self.frame, self.index as _);
169            slice::from_raw_parts_mut(data, self.line_size)
170        }
171    }
172}
173
174/// Get sample data planes from a given audio frame.
175fn get_audio_planes<'a>(
176    frame: *mut c_void,
177    sample_format: SampleFormat,
178    channels: usize,
179) -> Vec<Plane<'a>> {
180    let line_size = unsafe { ffw_frame_get_line_size(frame, 0) as _ };
181
182    let mut inner = Vec::new();
183
184    if sample_format.is_planar() {
185        for i in 0..channels {
186            inner.push(Plane::new(frame, i, line_size));
187        }
188    } else {
189        inner.push(Plane::new(frame, 0, line_size));
190    }
191
192    inner
193}
194
195/// A collection of audio planes. This type can be dereferenced into a slice of
196///  `Plane`. If the sample data is planar, you will get the same number of
197/// `Plane`'s as you have channels. If the sample data is packed (or interleaved),
198/// there will be a single plane containing data for all channels.
199pub struct Planes<'a> {
200    inner: Vec<Plane<'a>>,
201}
202
203impl<'a> From<&'a AudioFrame> for Planes<'a> {
204    fn from(frame: &'a AudioFrame) -> Self {
205        let sample_format = frame.sample_format();
206        let channel_layout = frame.channel_layout();
207
208        Self {
209            inner: get_audio_planes(frame.ptr, sample_format, channel_layout.channels() as _),
210        }
211    }
212}
213
214impl<'a> From<&'a AudioFrameMut> for Planes<'a> {
215    fn from(frame: &'a AudioFrameMut) -> Self {
216        let sample_format = frame.sample_format();
217        let channel_layout = frame.channel_layout();
218
219        Self {
220            inner: get_audio_planes(frame.ptr, sample_format, channel_layout.channels() as _),
221        }
222    }
223}
224
225impl<'a> Deref for Planes<'a> {
226    type Target = [Plane<'a>];
227
228    #[inline]
229    fn deref(&self) -> &Self::Target {
230        &self.inner
231    }
232}
233
234/// A collection of mutable audio planes.
235pub struct PlanesMut<'a> {
236    inner: Vec<Plane<'a>>,
237}
238
239impl<'a> From<&'a mut AudioFrameMut> for PlanesMut<'a> {
240    fn from(frame: &'a mut AudioFrameMut) -> Self {
241        let sample_format = frame.sample_format();
242        let channel_layout = frame.channel_layout();
243
244        Self {
245            inner: get_audio_planes(frame.ptr, sample_format, channel_layout.channels() as _),
246        }
247    }
248}
249
250impl<'a> Deref for PlanesMut<'a> {
251    type Target = [Plane<'a>];
252
253    #[inline]
254    fn deref(&self) -> &Self::Target {
255        &self.inner
256    }
257}
258
259impl DerefMut for PlanesMut<'_> {
260    #[inline]
261    fn deref_mut(&mut self) -> &mut Self::Target {
262        &mut self.inner
263    }
264}
265
266/// An audio frame with mutable data.
267pub struct AudioFrameMut {
268    ptr: *mut c_void,
269    time_base: TimeBase,
270}
271
272impl AudioFrameMut {
273    /// Create an audio frame containing silence. The time base of the frame
274    /// will be in microseconds.
275    pub fn silence(
276        channel_layout: &ChannelLayoutRef,
277        sample_format: SampleFormat,
278        sample_rate: u32,
279        samples: usize,
280    ) -> Self {
281        let ptr = unsafe {
282            ffw_frame_new_silence(
283                channel_layout.as_ptr(),
284                sample_format.into_raw(),
285                sample_rate as _,
286                samples as _,
287            )
288        };
289
290        if ptr.is_null() {
291            panic!("unable to allocate an audio frame");
292        }
293
294        Self {
295            ptr,
296            time_base: TimeBase::MICROSECONDS,
297        }
298    }
299
300    /// Get frame sample format.
301    pub fn sample_format(&self) -> SampleFormat {
302        unsafe { SampleFormat::from_raw(ffw_frame_get_format(self.ptr)) }
303    }
304
305    /// Get frame sample rate.
306    pub fn sample_rate(&self) -> u32 {
307        unsafe { ffw_frame_get_sample_rate(self.ptr) as _ }
308    }
309
310    /// Get number of samples (per channel) in this frame.
311    pub fn samples(&self) -> usize {
312        unsafe { ffw_frame_get_nb_samples(self.ptr) as _ }
313    }
314
315    /// Get sample data planes for this frame.
316    #[inline]
317    pub fn planes(&self) -> Planes {
318        Planes::from(self)
319    }
320
321    /// Get mutable sample data planes for this frame.
322    #[inline]
323    pub fn planes_mut(&mut self) -> PlanesMut {
324        PlanesMut::from(self)
325    }
326
327    /// Get channel layout.
328    pub fn channel_layout(&self) -> &ChannelLayoutRef {
329        unsafe { ChannelLayoutRef::from_raw_ptr(ffw_frame_get_channel_layout(self.ptr)) }
330    }
331
332    /// Get frame time base.
333    #[inline]
334    pub fn time_base(&self) -> TimeBase {
335        self.time_base
336    }
337
338    /// Set frame time base. (This will rescale the current timestamp into a
339    /// given time base.)
340    pub fn with_time_base(mut self, time_base: TimeBase) -> Self {
341        let new_pts = self.pts().with_time_base(time_base);
342
343        unsafe {
344            ffw_frame_set_pts(self.ptr, new_pts.timestamp());
345        }
346
347        self.time_base = time_base;
348
349        self
350    }
351
352    /// Get presentation timestamp.
353    pub fn pts(&self) -> Timestamp {
354        let pts = unsafe { ffw_frame_get_pts(self.ptr) };
355
356        Timestamp::new(pts, self.time_base)
357    }
358
359    /// Set presentation timestamp.
360    pub fn with_pts(self, pts: Timestamp) -> Self {
361        let pts = pts.with_time_base(self.time_base);
362
363        unsafe { ffw_frame_set_pts(self.ptr, pts.timestamp()) }
364
365        self
366    }
367
368    /// Make the frame immutable.
369    #[inline]
370    pub fn freeze(mut self) -> AudioFrame {
371        let ptr = self.ptr;
372
373        self.ptr = ptr::null_mut();
374
375        AudioFrame {
376            ptr,
377            time_base: self.time_base,
378        }
379    }
380}
381
382impl Drop for AudioFrameMut {
383    fn drop(&mut self) {
384        unsafe { ffw_frame_free(self.ptr) }
385    }
386}
387
388unsafe impl Send for AudioFrameMut {}
389unsafe impl Sync for AudioFrameMut {}
390
391/// An audio frame with immutable data.
392pub struct AudioFrame {
393    ptr: *mut c_void,
394    time_base: TimeBase,
395}
396
397impl AudioFrame {
398    /// Create a new audio frame from its raw representation.
399    pub(crate) unsafe fn from_raw_ptr(ptr: *mut c_void, time_base: TimeBase) -> Self {
400        AudioFrame { ptr, time_base }
401    }
402
403    /// Get frame sample format.
404    pub fn sample_format(&self) -> SampleFormat {
405        unsafe { SampleFormat::from_raw(ffw_frame_get_format(self.ptr)) }
406    }
407
408    /// Get frame sample rate.
409    pub fn sample_rate(&self) -> u32 {
410        unsafe { ffw_frame_get_sample_rate(self.ptr) as _ }
411    }
412
413    /// Get number of samples (per channel) in this frame.
414    pub fn samples(&self) -> usize {
415        unsafe { ffw_frame_get_nb_samples(self.ptr) as _ }
416    }
417
418    /// Get sample data planes for this frame.
419    #[inline]
420    pub fn planes(&self) -> Planes {
421        Planes::from(self)
422    }
423
424    /// Get channel layout.
425    pub fn channel_layout(&self) -> &ChannelLayoutRef {
426        unsafe { ChannelLayoutRef::from_raw_ptr(ffw_frame_get_channel_layout(self.ptr)) }
427    }
428
429    /// Get frame time base.
430    #[inline]
431    pub fn time_base(&self) -> TimeBase {
432        self.time_base
433    }
434
435    /// Set frame time base. (This will rescale the current timestamp into a
436    /// given time base.)
437    pub fn with_time_base(mut self, time_base: TimeBase) -> Self {
438        let new_pts = self.pts().with_time_base(time_base);
439
440        unsafe {
441            ffw_frame_set_pts(self.ptr, new_pts.timestamp());
442        }
443
444        self.time_base = time_base;
445
446        self
447    }
448
449    /// Get presentation timestamp.
450    pub fn pts(&self) -> Timestamp {
451        let pts = unsafe { ffw_frame_get_pts(self.ptr) };
452
453        Timestamp::new(pts, self.time_base)
454    }
455
456    /// Set presentation timestamp.
457    pub fn with_pts(self, pts: Timestamp) -> Self {
458        let pts = pts.with_time_base(self.time_base);
459
460        unsafe { ffw_frame_set_pts(self.ptr, pts.timestamp()) }
461
462        self
463    }
464
465    /// Get raw pointer.
466    pub(crate) fn as_ptr(&self) -> *const c_void {
467        self.ptr
468    }
469
470    /// Try to make this frame mutable. Returns AudioFrameMut if it can be made
471    /// into mutable without copying the data, otherwise returns AudioFrame.
472    pub fn try_into_mut(self) -> Result<AudioFrameMut, AudioFrame> {
473        let res = unsafe { ffw_frame_is_writable(self.ptr) };
474        if res > 0 {
475            Ok(self.into_mut())
476        } else {
477            Err(self)
478        }
479    }
480
481    /// Make this frame mutable. This will copy the data if it is not already
482    /// mutable.
483    pub fn into_mut(mut self) -> AudioFrameMut {
484        let res = unsafe { ffw_frame_make_writable(self.ptr) };
485
486        if res < 0 {
487            panic!("unable to make the frame mutable");
488        }
489
490        let ptr = self.ptr;
491
492        self.ptr = ptr::null_mut();
493
494        AudioFrameMut {
495            ptr,
496            time_base: self.time_base,
497        }
498    }
499}
500
501impl Clone for AudioFrame {
502    fn clone(&self) -> Self {
503        let ptr = unsafe { ffw_frame_clone(self.ptr) };
504
505        if ptr.is_null() {
506            panic!("unable to clone a frame");
507        }
508
509        Self {
510            ptr,
511            time_base: self.time_base,
512        }
513    }
514}
515
516impl Drop for AudioFrame {
517    fn drop(&mut self) {
518        unsafe { ffw_frame_free(self.ptr) }
519    }
520}
521
522unsafe impl Send for AudioFrame {}
523unsafe impl Sync for AudioFrame {}