ffmpeg_the_third/util/format/
sample.rs

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