ffmpeg_the_third/util/frame/
audio.rs

1use std::mem;
2use std::ops::{Deref, DerefMut};
3use std::slice;
4
5use super::Frame;
6use crate::ffi::*;
7use crate::util::format;
8use crate::ChannelLayoutMask;
9use libc::c_int;
10
11#[cfg(feature = "ffmpeg_5_1")]
12use crate::ChannelLayout;
13
14#[cfg(not(feature = "ffmpeg_7_0"))]
15use libc::c_ulonglong;
16
17#[derive(PartialEq, Eq)]
18pub struct Audio(Frame);
19
20impl Audio {
21    #[inline(always)]
22    pub unsafe fn wrap(ptr: *mut AVFrame) -> Self {
23        Audio(Frame::wrap(ptr))
24    }
25
26    #[inline]
27    pub unsafe fn alloc(
28        &mut self,
29        format: format::Sample,
30        samples: usize,
31        layout: ChannelLayoutMask,
32    ) {
33        self.set_format(format);
34        self.set_samples(samples);
35        #[cfg(not(feature = "ffmpeg_7_0"))]
36        self.set_channel_layout(layout);
37        #[cfg(feature = "ffmpeg_7_0")]
38        self.set_ch_layout(ChannelLayout::from_mask(layout).unwrap());
39
40        av_frame_get_buffer(self.as_mut_ptr(), 0);
41    }
42}
43
44impl Audio {
45    #[inline(always)]
46    pub fn empty() -> Self {
47        unsafe { Audio(Frame::empty()) }
48    }
49
50    #[inline]
51    pub fn new(format: format::Sample, samples: usize, layout: ChannelLayoutMask) -> Self {
52        unsafe {
53            let mut frame = Audio::empty();
54            frame.alloc(format, samples, layout);
55
56            frame
57        }
58    }
59
60    #[inline]
61    pub fn format(&self) -> format::Sample {
62        unsafe {
63            if (*self.as_ptr()).format == -1 {
64                format::Sample::None
65            } else {
66                format::Sample::from(mem::transmute::<c_int, AVSampleFormat>(
67                    (*self.as_ptr()).format,
68                ))
69            }
70        }
71    }
72
73    #[inline]
74    pub fn set_format(&mut self, value: format::Sample) {
75        unsafe {
76            (*self.as_mut_ptr()).format = mem::transmute::<AVSampleFormat, c_int>(value.into());
77        }
78    }
79
80    #[cfg(not(feature = "ffmpeg_7_0"))]
81    #[inline]
82    pub fn channel_layout(&self) -> ChannelLayoutMask {
83        unsafe {
84            ChannelLayoutMask::from_bits_truncate((*self.as_ptr()).channel_layout as c_ulonglong)
85        }
86    }
87
88    #[cfg(not(feature = "ffmpeg_7_0"))]
89    #[inline]
90    pub fn set_channel_layout(&mut self, value: ChannelLayoutMask) {
91        unsafe {
92            (*self.as_mut_ptr()).channel_layout = value.bits() as u64;
93        }
94    }
95
96    #[cfg(feature = "ffmpeg_5_1")]
97    #[inline]
98    pub fn ch_layout(&self) -> ChannelLayout<'_> {
99        unsafe { ChannelLayout::from(&self.as_ref().unwrap().ch_layout) }
100    }
101
102    #[cfg(feature = "ffmpeg_5_1")]
103    #[inline]
104    pub fn set_ch_layout(&mut self, value: ChannelLayout) {
105        unsafe {
106            self.as_mut().unwrap().ch_layout = value.into_owned();
107        }
108    }
109
110    #[cfg(not(feature = "ffmpeg_7_0"))]
111    #[inline]
112    pub fn channels(&self) -> u16 {
113        unsafe { (*self.as_ptr()).channels as u16 }
114    }
115
116    #[cfg(not(feature = "ffmpeg_7_0"))]
117    #[inline]
118    pub fn set_channels(&mut self, value: u16) {
119        unsafe {
120            (*self.as_mut_ptr()).channels = i32::from(value);
121        }
122    }
123
124    #[inline]
125    pub fn rate(&self) -> u32 {
126        unsafe { (*self.as_ptr()).sample_rate as u32 }
127    }
128
129    #[inline]
130    pub fn set_rate(&mut self, value: u32) {
131        unsafe {
132            (*self.as_mut_ptr()).sample_rate = value as c_int;
133        }
134    }
135
136    #[inline]
137    pub fn samples(&self) -> usize {
138        unsafe { (*self.as_ptr()).nb_samples as usize }
139    }
140
141    #[inline]
142    pub fn set_samples(&mut self, value: usize) {
143        unsafe {
144            (*self.as_mut_ptr()).nb_samples = value as c_int;
145        }
146    }
147
148    #[inline]
149    pub fn is_planar(&self) -> bool {
150        self.format().is_planar()
151    }
152
153    #[inline]
154    pub fn is_packed(&self) -> bool {
155        self.format().is_packed()
156    }
157
158    #[inline]
159    pub fn planes(&self) -> usize {
160        unsafe {
161            if (*self.as_ptr()).linesize[0] == 0 {
162                return 0;
163            }
164        }
165
166        if self.is_packed() {
167            1
168        } else {
169            #[cfg(not(feature = "ffmpeg_5_1"))]
170            let channels = self.channels() as usize;
171            #[cfg(feature = "ffmpeg_5_1")]
172            let channels = self.ch_layout().channels() as usize;
173
174            channels
175        }
176    }
177
178    #[inline]
179    pub fn plane<T: Sample>(&self, index: usize) -> &[T] {
180        if index >= self.planes() {
181            panic!("out of bounds");
182        }
183
184        #[cfg(not(feature = "ffmpeg_5_1"))]
185        let channels = self.channels() as u16;
186        #[cfg(feature = "ffmpeg_5_1")]
187        let channels = self.ch_layout().channels() as u16;
188
189        if !<T as Sample>::is_valid(self.format(), channels) {
190            panic!("unsupported type");
191        }
192
193        unsafe { slice::from_raw_parts((*self.as_ptr()).data[index] as *const T, self.samples()) }
194    }
195
196    #[inline]
197    pub fn plane_mut<T: Sample>(&mut self, index: usize) -> &mut [T] {
198        if index >= self.planes() {
199            panic!("out of bounds");
200        }
201
202        #[cfg(not(feature = "ffmpeg_5_1"))]
203        let channels = self.channels() as u16;
204        #[cfg(feature = "ffmpeg_5_1")]
205        let channels = self.ch_layout().channels() as u16;
206
207        if !<T as Sample>::is_valid(self.format(), channels) {
208            panic!("unsupported type");
209        }
210
211        unsafe {
212            slice::from_raw_parts_mut((*self.as_mut_ptr()).data[index] as *mut T, self.samples())
213        }
214    }
215
216    #[inline]
217    pub fn data(&self, index: usize) -> &[u8] {
218        if index >= self.planes() {
219            panic!("out of bounds");
220        }
221
222        unsafe {
223            slice::from_raw_parts(
224                (*self.as_ptr()).data[index],
225                (*self.as_ptr()).linesize[index] as usize,
226            )
227        }
228    }
229
230    #[inline]
231    pub fn data_mut(&mut self, index: usize) -> &mut [u8] {
232        if index >= self.planes() {
233            panic!("out of bounds");
234        }
235
236        unsafe {
237            slice::from_raw_parts_mut(
238                (*self.as_mut_ptr()).data[index],
239                (*self.as_ptr()).linesize[index] as usize,
240            )
241        }
242    }
243}
244
245impl Deref for Audio {
246    type Target = Frame;
247
248    fn deref(&self) -> &<Self as Deref>::Target {
249        &self.0
250    }
251}
252
253impl DerefMut for Audio {
254    fn deref_mut(&mut self) -> &mut <Self as Deref>::Target {
255        &mut self.0
256    }
257}
258
259impl ::std::fmt::Debug for Audio {
260    fn fmt(&self, f: &mut ::std::fmt::Formatter) -> Result<(), ::std::fmt::Error> {
261        #[cfg(not(feature = "ffmpeg_5_1"))]
262        let channels = self.channels() as u16;
263        #[cfg(feature = "ffmpeg_5_1")]
264        let channels = self.ch_layout().channels() as u16;
265
266        f.write_str("ffmpeg::frame::Audio { ")?;
267        f.write_str(&format!("format: {:?}, ", self.format()))?;
268        f.write_str(&format!("channels: {channels}, "))?;
269        f.write_str(&format!("rate: {:?}, ", self.rate()))?;
270        f.write_str(&format!("samples: {:?} ", self.samples()))?;
271        f.write_str("}")
272    }
273}
274
275impl Clone for Audio {
276    fn clone(&self) -> Self {
277        #[cfg(not(feature = "ffmpeg_5_1"))]
278        let mask = self.channel_layout();
279        #[cfg(feature = "ffmpeg_5_1")]
280        let mask = self.ch_layout().mask().unwrap();
281
282        let mut cloned = Audio::new(self.format(), self.samples(), mask);
283        cloned.clone_from(self);
284
285        cloned
286    }
287
288    fn clone_from(&mut self, source: &Self) {
289        unsafe {
290            av_frame_copy(self.as_mut_ptr(), source.as_ptr());
291            av_frame_copy_props(self.as_mut_ptr(), source.as_ptr());
292        }
293    }
294}
295
296impl From<Frame> for Audio {
297    fn from(frame: Frame) -> Self {
298        Audio(frame)
299    }
300}
301
302pub unsafe trait Sample {
303    fn is_valid(format: format::Sample, channels: u16) -> bool;
304}
305
306unsafe impl Sample for u8 {
307    #[inline(always)]
308    fn is_valid(format: format::Sample, _channels: u16) -> bool {
309        matches!(format, format::Sample::U8(..))
310    }
311}
312
313unsafe impl Sample for (u8, u8) {
314    #[inline(always)]
315    fn is_valid(format: format::Sample, channels: u16) -> bool {
316        channels == 2 && format == format::Sample::U8(format::sample::Type::Packed)
317    }
318}
319
320unsafe impl Sample for (u8, u8, u8) {
321    #[inline(always)]
322    fn is_valid(format: format::Sample, channels: u16) -> bool {
323        channels == 3 && format == format::Sample::U8(format::sample::Type::Packed)
324    }
325}
326
327unsafe impl Sample for (u8, u8, u8, u8) {
328    #[inline(always)]
329    fn is_valid(format: format::Sample, channels: u16) -> bool {
330        channels == 4 && format == format::Sample::U8(format::sample::Type::Packed)
331    }
332}
333
334unsafe impl Sample for (u8, u8, u8, u8, u8) {
335    #[inline(always)]
336    fn is_valid(format: format::Sample, channels: u16) -> bool {
337        channels == 5 && format == format::Sample::U8(format::sample::Type::Packed)
338    }
339}
340
341unsafe impl Sample for (u8, u8, u8, u8, u8, u8) {
342    #[inline(always)]
343    fn is_valid(format: format::Sample, channels: u16) -> bool {
344        channels == 6 && format == format::Sample::U8(format::sample::Type::Packed)
345    }
346}
347
348unsafe impl Sample for (u8, u8, u8, u8, u8, u8, u8) {
349    #[inline(always)]
350    fn is_valid(format: format::Sample, channels: u16) -> bool {
351        channels == 7 && format == format::Sample::U8(format::sample::Type::Packed)
352    }
353}
354
355unsafe impl Sample for i16 {
356    #[inline(always)]
357    fn is_valid(format: format::Sample, _channels: u16) -> bool {
358        matches!(format, format::Sample::I16(..))
359    }
360}
361
362unsafe impl Sample for (i16, i16) {
363    #[inline(always)]
364    fn is_valid(format: format::Sample, channels: u16) -> bool {
365        channels == 2 && format == format::Sample::I16(format::sample::Type::Packed)
366    }
367}
368
369unsafe impl Sample for (i16, i16, i16) {
370    #[inline(always)]
371    fn is_valid(format: format::Sample, channels: u16) -> bool {
372        channels == 3 && format == format::Sample::I16(format::sample::Type::Packed)
373    }
374}
375
376unsafe impl Sample for (i16, i16, i16, i16) {
377    #[inline(always)]
378    fn is_valid(format: format::Sample, channels: u16) -> bool {
379        channels == 4 && format == format::Sample::I16(format::sample::Type::Packed)
380    }
381}
382
383unsafe impl Sample for (i16, i16, i16, i16, i16) {
384    #[inline(always)]
385    fn is_valid(format: format::Sample, channels: u16) -> bool {
386        channels == 5 && format == format::Sample::I16(format::sample::Type::Packed)
387    }
388}
389
390unsafe impl Sample for (i16, i16, i16, i16, i16, i16) {
391    #[inline(always)]
392    fn is_valid(format: format::Sample, channels: u16) -> bool {
393        channels == 6 && format == format::Sample::I16(format::sample::Type::Packed)
394    }
395}
396
397unsafe impl Sample for (i16, i16, i16, i16, i16, i16, i16) {
398    #[inline(always)]
399    fn is_valid(format: format::Sample, channels: u16) -> bool {
400        channels == 7 && format == format::Sample::I16(format::sample::Type::Packed)
401    }
402}
403
404unsafe impl Sample for i32 {
405    #[inline(always)]
406    fn is_valid(format: format::Sample, _channels: u16) -> bool {
407        matches!(format, format::Sample::I32(..))
408    }
409}
410
411unsafe impl Sample for (i32, i32) {
412    #[inline(always)]
413    fn is_valid(format: format::Sample, channels: u16) -> bool {
414        channels == 2 && format == format::Sample::I32(format::sample::Type::Packed)
415    }
416}
417
418unsafe impl Sample for (i32, i32, i32) {
419    #[inline(always)]
420    fn is_valid(format: format::Sample, channels: u16) -> bool {
421        channels == 3 && format == format::Sample::I32(format::sample::Type::Packed)
422    }
423}
424
425unsafe impl Sample for (i32, i32, i32, i32) {
426    #[inline(always)]
427    fn is_valid(format: format::Sample, channels: u16) -> bool {
428        channels == 4 && format == format::Sample::I32(format::sample::Type::Packed)
429    }
430}
431
432unsafe impl Sample for (i32, i32, i32, i32, i32) {
433    #[inline(always)]
434    fn is_valid(format: format::Sample, channels: u16) -> bool {
435        channels == 5 && format == format::Sample::I32(format::sample::Type::Packed)
436    }
437}
438
439unsafe impl Sample for (i32, i32, i32, i32, i32, i32) {
440    #[inline(always)]
441    fn is_valid(format: format::Sample, channels: u16) -> bool {
442        channels == 6 && format == format::Sample::I32(format::sample::Type::Packed)
443    }
444}
445
446unsafe impl Sample for (i32, i32, i32, i32, i32, i32, i32) {
447    #[inline(always)]
448    fn is_valid(format: format::Sample, channels: u16) -> bool {
449        channels == 7 && format == format::Sample::I32(format::sample::Type::Packed)
450    }
451}
452
453unsafe impl Sample for f32 {
454    #[inline(always)]
455    fn is_valid(format: format::Sample, _channels: u16) -> bool {
456        matches!(format, format::Sample::F32(..))
457    }
458}
459
460unsafe impl Sample for (f32, f32) {
461    #[inline(always)]
462    fn is_valid(format: format::Sample, channels: u16) -> bool {
463        channels == 2 && format == format::Sample::F32(format::sample::Type::Packed)
464    }
465}
466
467unsafe impl Sample for (f32, f32, f32) {
468    #[inline(always)]
469    fn is_valid(format: format::Sample, channels: u16) -> bool {
470        channels == 3 && format == format::Sample::F32(format::sample::Type::Packed)
471    }
472}
473
474unsafe impl Sample for (f32, f32, f32, f32) {
475    #[inline(always)]
476    fn is_valid(format: format::Sample, channels: u16) -> bool {
477        channels == 4 && format == format::Sample::F32(format::sample::Type::Packed)
478    }
479}
480
481unsafe impl Sample for (f32, f32, f32, f32, f32) {
482    #[inline(always)]
483    fn is_valid(format: format::Sample, channels: u16) -> bool {
484        channels == 5 && format == format::Sample::F32(format::sample::Type::Packed)
485    }
486}
487
488unsafe impl Sample for (f32, f32, f32, f32, f32, f32) {
489    #[inline(always)]
490    fn is_valid(format: format::Sample, channels: u16) -> bool {
491        channels == 6 && format == format::Sample::F32(format::sample::Type::Packed)
492    }
493}
494
495unsafe impl Sample for (f32, f32, f32, f32, f32, f32, f32) {
496    #[inline(always)]
497    fn is_valid(format: format::Sample, channels: u16) -> bool {
498        channels == 7 && format == format::Sample::F32(format::sample::Type::Packed)
499    }
500}
501
502unsafe impl Sample for f64 {
503    #[inline(always)]
504    fn is_valid(format: format::Sample, _channels: u16) -> bool {
505        matches!(format, format::Sample::F64(..))
506    }
507}
508
509unsafe impl Sample for (f64, f64) {
510    #[inline(always)]
511    fn is_valid(format: format::Sample, channels: u16) -> bool {
512        channels == 2 && format == format::Sample::F64(format::sample::Type::Packed)
513    }
514}
515
516unsafe impl Sample for (f64, f64, f64) {
517    #[inline(always)]
518    fn is_valid(format: format::Sample, channels: u16) -> bool {
519        channels == 3 && format == format::Sample::F64(format::sample::Type::Packed)
520    }
521}
522
523unsafe impl Sample for (f64, f64, f64, f64) {
524    #[inline(always)]
525    fn is_valid(format: format::Sample, channels: u16) -> bool {
526        channels == 4 && format == format::Sample::F64(format::sample::Type::Packed)
527    }
528}
529
530unsafe impl Sample for (f64, f64, f64, f64, f64) {
531    #[inline(always)]
532    fn is_valid(format: format::Sample, channels: u16) -> bool {
533        channels == 5 && format == format::Sample::F64(format::sample::Type::Packed)
534    }
535}
536
537unsafe impl Sample for (f64, f64, f64, f64, f64, f64) {
538    #[inline(always)]
539    fn is_valid(format: format::Sample, channels: u16) -> bool {
540        channels == 6 && format == format::Sample::F64(format::sample::Type::Packed)
541    }
542}
543
544unsafe impl Sample for (f64, f64, f64, f64, f64, f64, f64) {
545    #[inline(always)]
546    fn is_valid(format: format::Sample, channels: u16) -> bool {
547        channels == 7 && format == format::Sample::F64(format::sample::Type::Packed)
548    }
549}