1use std::ffi::{CStr, CString};
2use std::ops::Index;
3use std::ptr;
4use std::slice;
5use std::str::from_utf8_unchecked;
6
7use ffi::AVSampleFormat::*;
8use ffi::*;
9use libc::{c_int, c_void};
10
11#[derive(Eq, PartialEq, Copy, Clone, Debug)]
12pub enum Sample {
13 None,
14
15 U8(Type),
16 I16(Type),
17 I32(Type),
18 I64(Type),
19 F32(Type),
20 F64(Type),
21}
22
23#[derive(Eq, PartialEq, Copy, Clone, Debug)]
24pub enum Type {
25 Packed,
26 Planar,
27}
28
29impl Sample {
30 #[inline]
31 pub fn name(&self) -> &'static str {
32 unsafe {
33 from_utf8_unchecked(CStr::from_ptr(av_get_sample_fmt_name((*self).into())).to_bytes())
34 }
35 }
36
37 #[inline]
38 pub fn packed(&self) -> Self {
39 unsafe { Sample::from(av_get_packed_sample_fmt((*self).into())) }
40 }
41
42 #[inline]
43 pub fn planar(&self) -> Self {
44 unsafe { Sample::from(av_get_planar_sample_fmt((*self).into())) }
45 }
46
47 #[inline]
48 pub fn is_planar(&self) -> bool {
49 unsafe { av_sample_fmt_is_planar((*self).into()) == 1 }
50 }
51
52 #[inline]
53 pub fn is_packed(&self) -> bool {
54 !self.is_planar()
55 }
56
57 #[inline]
58 pub fn bytes(&self) -> usize {
59 unsafe { av_get_bytes_per_sample((*self).into()) as usize }
60 }
61
62 #[inline]
63 pub fn buffer(&self, channels: u16, samples: usize, align: bool) -> Buffer {
64 Buffer::new(*self, channels, samples, align)
65 }
66}
67
68impl From<AVSampleFormat> for Sample {
69 #[inline]
70 fn from(value: AVSampleFormat) -> Self {
71 match value {
72 AV_SAMPLE_FMT_NONE => Sample::None,
73
74 AV_SAMPLE_FMT_U8 => Sample::U8(Type::Packed),
75 AV_SAMPLE_FMT_S16 => Sample::I16(Type::Packed),
76 AV_SAMPLE_FMT_S32 => Sample::I32(Type::Packed),
77 AV_SAMPLE_FMT_S64 => Sample::I64(Type::Packed),
78 AV_SAMPLE_FMT_FLT => Sample::F32(Type::Packed),
79 AV_SAMPLE_FMT_DBL => Sample::F64(Type::Packed),
80
81 AV_SAMPLE_FMT_U8P => Sample::U8(Type::Planar),
82 AV_SAMPLE_FMT_S16P => Sample::I16(Type::Planar),
83 AV_SAMPLE_FMT_S32P => Sample::I32(Type::Planar),
84 AV_SAMPLE_FMT_S64P => Sample::I64(Type::Planar),
85 AV_SAMPLE_FMT_FLTP => Sample::F32(Type::Planar),
86 AV_SAMPLE_FMT_DBLP => Sample::F64(Type::Planar),
87
88 AV_SAMPLE_FMT_NB => Sample::None,
89 }
90 }
91}
92
93impl From<&'static str> for Sample {
94 #[inline]
95 fn from(value: &'static str) -> Self {
96 unsafe {
97 let value = CString::new(value).unwrap();
98
99 Sample::from(av_get_sample_fmt(value.as_ptr()))
100 }
101 }
102}
103
104impl From<Sample> for AVSampleFormat {
105 #[inline]
106 fn from(value: Sample) -> AVSampleFormat {
107 match value {
108 Sample::None => AV_SAMPLE_FMT_NONE,
109
110 Sample::U8(Type::Packed) => AV_SAMPLE_FMT_U8,
111 Sample::I16(Type::Packed) => AV_SAMPLE_FMT_S16,
112 Sample::I32(Type::Packed) => AV_SAMPLE_FMT_S32,
113 Sample::I64(Type::Packed) => AV_SAMPLE_FMT_S64,
114 Sample::F32(Type::Packed) => AV_SAMPLE_FMT_FLT,
115 Sample::F64(Type::Packed) => AV_SAMPLE_FMT_DBL,
116
117 Sample::U8(Type::Planar) => AV_SAMPLE_FMT_U8P,
118 Sample::I16(Type::Planar) => AV_SAMPLE_FMT_S16P,
119 Sample::I32(Type::Planar) => AV_SAMPLE_FMT_S32P,
120 Sample::I64(Type::Planar) => AV_SAMPLE_FMT_S64P,
121 Sample::F32(Type::Planar) => AV_SAMPLE_FMT_FLTP,
122 Sample::F64(Type::Planar) => AV_SAMPLE_FMT_DBLP,
123 }
124 }
125}
126
127pub struct Buffer {
128 pub format: Sample,
129 pub channels: u16,
130 pub samples: usize,
131 pub align: bool,
132
133 buffer: *mut *mut u8,
134 size: c_int,
135}
136
137impl Buffer {
138 #[inline]
139 pub fn size(format: Sample, channels: u16, samples: usize, align: bool) -> usize {
140 unsafe {
141 av_samples_get_buffer_size(
142 ptr::null_mut(),
143 i32::from(channels),
144 samples as c_int,
145 format.into(),
146 !align as c_int,
147 ) as usize
148 }
149 }
150
151 #[inline]
152 pub fn new(format: Sample, channels: u16, samples: usize, align: bool) -> Self {
153 unsafe {
154 let mut buf = Buffer {
155 format,
156 channels,
157 samples,
158 align,
159
160 buffer: ptr::null_mut(),
161 size: 0,
162 };
163
164 av_samples_alloc_array_and_samples(
165 &mut buf.buffer,
166 &mut buf.size,
167 i32::from(channels),
168 samples as c_int,
169 format.into(),
170 !align as c_int,
171 );
172
173 buf
174 }
175 }
176}
177
178impl Index<usize> for Buffer {
179 type Output = [u8];
180
181 #[inline]
182 fn index(&self, index: usize) -> &[u8] {
183 if index >= self.samples {
184 panic!("out of bounds");
185 }
186
187 unsafe { slice::from_raw_parts(*self.buffer.add(index), self.size as usize) }
188 }
189}
190
191impl Clone for Buffer {
192 #[inline]
193 fn clone(&self) -> Self {
194 let mut buf = Buffer::new(self.format, self.channels, self.samples, self.align);
195 buf.clone_from(self);
196
197 buf
198 }
199
200 #[inline]
201 fn clone_from(&mut self, source: &Self) {
202 unsafe {
203 av_samples_copy(
204 self.buffer,
205 source.buffer as *const *mut u8,
206 0,
207 0,
208 source.samples as c_int,
209 i32::from(source.channels),
210 source.format.into(),
211 );
212 }
213 }
214}
215
216impl Drop for Buffer {
217 #[inline]
218 fn drop(&mut self) {
219 unsafe {
220 av_freep(self.buffer as *mut c_void);
221 }
222 }
223}