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