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    fn deref(&self) -> &Self::Target {
229        &self.inner
230    }
231}
232
233/// A collection of mutable audio planes.
234pub struct PlanesMut<'a> {
235    inner: Vec<Plane<'a>>,
236}
237
238impl<'a> From<&'a mut AudioFrameMut> for PlanesMut<'a> {
239    fn from(frame: &'a mut AudioFrameMut) -> Self {
240        let sample_format = frame.sample_format();
241        let channel_layout = frame.channel_layout();
242
243        Self {
244            inner: get_audio_planes(frame.ptr, sample_format, channel_layout.channels() as _),
245        }
246    }
247}
248
249impl<'a> Deref for PlanesMut<'a> {
250    type Target = [Plane<'a>];
251
252    fn deref(&self) -> &Self::Target {
253        &self.inner
254    }
255}
256
257impl<'a> DerefMut for PlanesMut<'a> {
258    fn deref_mut(&mut self) -> &mut Self::Target {
259        &mut self.inner
260    }
261}
262
263/// An audio frame with mutable data.
264pub struct AudioFrameMut {
265    ptr: *mut c_void,
266    time_base: TimeBase,
267}
268
269impl AudioFrameMut {
270    /// Create an audio frame containing silence. The time base of the frame
271    /// will be in microseconds.
272    pub fn silence(
273        channel_layout: &ChannelLayoutRef,
274        sample_format: SampleFormat,
275        sample_rate: u32,
276        samples: usize,
277    ) -> Self {
278        let ptr = unsafe {
279            ffw_frame_new_silence(
280                channel_layout.as_ptr(),
281                sample_format.into_raw(),
282                sample_rate as _,
283                samples as _,
284            )
285        };
286
287        if ptr.is_null() {
288            panic!("unable to allocate an audio frame");
289        }
290
291        Self {
292            ptr,
293            time_base: TimeBase::MICROSECONDS,
294        }
295    }
296
297    /// Get frame sample format.
298    pub fn sample_format(&self) -> SampleFormat {
299        unsafe { SampleFormat::from_raw(ffw_frame_get_format(self.ptr)) }
300    }
301
302    /// Get frame sample rate.
303    pub fn sample_rate(&self) -> u32 {
304        unsafe { ffw_frame_get_sample_rate(self.ptr) as _ }
305    }
306
307    /// Get number of samples (per channel) in this frame.
308    pub fn samples(&self) -> usize {
309        unsafe { ffw_frame_get_nb_samples(self.ptr) as _ }
310    }
311
312    /// Get sample data planes for this frame.
313    pub fn planes(&self) -> Planes {
314        Planes::from(self)
315    }
316
317    /// Get mutable sample data planes for this frame.
318    pub fn planes_mut(&mut self) -> PlanesMut {
319        PlanesMut::from(self)
320    }
321
322    /// Get channel layout.
323    pub fn channel_layout(&self) -> &ChannelLayoutRef {
324        unsafe { ChannelLayoutRef::from_raw_ptr(ffw_frame_get_channel_layout(self.ptr)) }
325    }
326
327    /// Get frame time base.
328    pub fn time_base(&self) -> TimeBase {
329        self.time_base
330    }
331
332    /// Set frame time base. (This will rescale the current timestamp into a
333    /// given time base.)
334    pub fn with_time_base(mut self, time_base: TimeBase) -> Self {
335        let new_pts = self.pts().with_time_base(time_base);
336
337        unsafe {
338            ffw_frame_set_pts(self.ptr, new_pts.timestamp());
339        }
340
341        self.time_base = time_base;
342
343        self
344    }
345
346    /// Get presentation timestamp.
347    pub fn pts(&self) -> Timestamp {
348        let pts = unsafe { ffw_frame_get_pts(self.ptr) };
349
350        Timestamp::new(pts, self.time_base)
351    }
352
353    /// Set presentation timestamp.
354    pub fn with_pts(self, pts: Timestamp) -> Self {
355        let pts = pts.with_time_base(self.time_base);
356
357        unsafe { ffw_frame_set_pts(self.ptr, pts.timestamp()) }
358
359        self
360    }
361
362    /// Make the frame immutable.
363    pub fn freeze(mut self) -> AudioFrame {
364        let ptr = self.ptr;
365
366        self.ptr = ptr::null_mut();
367
368        AudioFrame {
369            ptr,
370            time_base: self.time_base,
371        }
372    }
373}
374
375impl Drop for AudioFrameMut {
376    fn drop(&mut self) {
377        unsafe { ffw_frame_free(self.ptr) }
378    }
379}
380
381unsafe impl Send for AudioFrameMut {}
382unsafe impl Sync for AudioFrameMut {}
383
384/// An audio frame with immutable data.
385pub struct AudioFrame {
386    ptr: *mut c_void,
387    time_base: TimeBase,
388}
389
390impl AudioFrame {
391    /// Create a new audio frame from its raw representation.
392    pub(crate) unsafe fn from_raw_ptr(ptr: *mut c_void, time_base: TimeBase) -> Self {
393        AudioFrame { ptr, time_base }
394    }
395
396    /// Get frame sample format.
397    pub fn sample_format(&self) -> SampleFormat {
398        unsafe { SampleFormat::from_raw(ffw_frame_get_format(self.ptr)) }
399    }
400
401    /// Get frame sample rate.
402    pub fn sample_rate(&self) -> u32 {
403        unsafe { ffw_frame_get_sample_rate(self.ptr) as _ }
404    }
405
406    /// Get number of samples (per channel) in this frame.
407    pub fn samples(&self) -> usize {
408        unsafe { ffw_frame_get_nb_samples(self.ptr) as _ }
409    }
410
411    /// Get sample data planes for this frame.
412    pub fn planes(&self) -> Planes {
413        Planes::from(self)
414    }
415
416    /// Get channel layout.
417    pub fn channel_layout(&self) -> &ChannelLayoutRef {
418        unsafe { ChannelLayoutRef::from_raw_ptr(ffw_frame_get_channel_layout(self.ptr)) }
419    }
420
421    /// Get frame time base.
422    pub fn time_base(&self) -> TimeBase {
423        self.time_base
424    }
425
426    /// Set frame time base. (This will rescale the current timestamp into a
427    /// given time base.)
428    pub fn with_time_base(mut self, time_base: TimeBase) -> Self {
429        let new_pts = self.pts().with_time_base(time_base);
430
431        unsafe {
432            ffw_frame_set_pts(self.ptr, new_pts.timestamp());
433        }
434
435        self.time_base = time_base;
436
437        self
438    }
439
440    /// Get presentation timestamp.
441    pub fn pts(&self) -> Timestamp {
442        let pts = unsafe { ffw_frame_get_pts(self.ptr) };
443
444        Timestamp::new(pts, self.time_base)
445    }
446
447    /// Set presentation timestamp.
448    pub fn with_pts(self, pts: Timestamp) -> Self {
449        let pts = pts.with_time_base(self.time_base);
450
451        unsafe { ffw_frame_set_pts(self.ptr, pts.timestamp()) }
452
453        self
454    }
455
456    /// Get raw pointer.
457    pub(crate) fn as_ptr(&self) -> *const c_void {
458        self.ptr
459    }
460
461    /// Try to make this frame mutable. Returns AudioFrameMut if it can be made
462    /// into mutable without copying the data, otherwise returns AudioFrame.
463    pub fn try_into_mut(self) -> Result<AudioFrameMut, AudioFrame> {
464        let res = unsafe { ffw_frame_is_writable(self.ptr) };
465        if res > 0 {
466            Ok(self.into_mut())
467        } else {
468            Err(self)
469        }
470    }
471
472    /// Make this frame mutable. This will copy the data if it is not already
473    /// mutable.
474    pub fn into_mut(mut self) -> AudioFrameMut {
475        let res = unsafe { ffw_frame_make_writable(self.ptr) };
476
477        if res < 0 {
478            panic!("unable to make the frame mutable");
479        }
480
481        let ptr = self.ptr;
482
483        self.ptr = ptr::null_mut();
484
485        AudioFrameMut {
486            ptr,
487            time_base: self.time_base,
488        }
489    }
490}
491
492impl Clone for AudioFrame {
493    fn clone(&self) -> Self {
494        let ptr = unsafe { ffw_frame_clone(self.ptr) };
495
496        if ptr.is_null() {
497            panic!("unable to clone a frame");
498        }
499
500        Self {
501            ptr,
502            time_base: self.time_base,
503        }
504    }
505}
506
507impl Drop for AudioFrame {
508    fn drop(&mut self) {
509        unsafe { ffw_frame_free(self.ptr) }
510    }
511}
512
513unsafe impl Send for AudioFrame {}
514unsafe impl Sync for AudioFrame {}