ffmpeg/util/format/
sample.rs

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}