ffmpeg_next/util/format/
sample.rs

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}