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