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