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}