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