Skip to main content

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::*;
7use crate::utils;
8use libc::{c_int, c_void};
9#[cfg(feature = "serialize")]
10use serde::{Deserialize, Serialize};
11
12#[derive(Eq, PartialEq, Copy, Clone, Debug)]
13#[cfg_attr(feature = "serialize", derive(Serialize, Deserialize))]
14pub enum Sample {
15    None,
16
17    U8(Type),
18    I16(Type),
19    I32(Type),
20    I64(Type),
21    F32(Type),
22    F64(Type),
23}
24
25#[derive(Eq, PartialEq, Copy, Clone, Debug)]
26#[cfg_attr(feature = "serialize", derive(Serialize, Deserialize))]
27pub enum Type {
28    Packed,
29    Planar,
30}
31
32impl Sample {
33    #[inline]
34    pub fn name(&self) -> &'static str {
35        unsafe { utils::str_from_c_ptr(av_get_sample_fmt_name((*self).into())) }
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        use AVSampleFormat as AV;
73
74        match value {
75            AV::NONE => Sample::None,
76
77            AV::U8 => Sample::U8(Type::Packed),
78            AV::S16 => Sample::I16(Type::Packed),
79            AV::S32 => Sample::I32(Type::Packed),
80            AV::S64 => Sample::I64(Type::Packed),
81            AV::FLT => Sample::F32(Type::Packed),
82            AV::DBL => Sample::F64(Type::Packed),
83
84            AV::U8P => Sample::U8(Type::Planar),
85            AV::S16P => Sample::I16(Type::Planar),
86            AV::S32P => Sample::I32(Type::Planar),
87            AV::S64P => Sample::I64(Type::Planar),
88            AV::FLTP => Sample::F32(Type::Planar),
89            AV::DBLP => Sample::F64(Type::Planar),
90
91            AV::NB => unreachable!(),
92
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        use AVSampleFormat as AV;
113
114        match value {
115            Sample::None => AV::NONE,
116
117            Sample::U8(Type::Packed) => AV::U8,
118            Sample::I16(Type::Packed) => AV::S16,
119            Sample::I32(Type::Packed) => AV::S32,
120            Sample::I64(Type::Packed) => AV::S64,
121            Sample::F32(Type::Packed) => AV::FLT,
122            Sample::F64(Type::Packed) => AV::DBL,
123
124            Sample::U8(Type::Planar) => AV::U8P,
125            Sample::I16(Type::Planar) => AV::S16P,
126            Sample::I32(Type::Planar) => AV::S32P,
127            Sample::I64(Type::Planar) => AV::S64P,
128            Sample::F32(Type::Planar) => AV::FLTP,
129            Sample::F64(Type::Planar) => AV::DBLP,
130        }
131    }
132}
133
134pub struct Buffer {
135    pub format: Sample,
136    pub channels: u16,
137    pub samples: usize,
138    pub align: bool,
139
140    buffer: *mut *mut u8,
141    size: c_int,
142}
143
144impl Buffer {
145    #[inline]
146    pub fn size(format: Sample, channels: u16, samples: usize, align: bool) -> usize {
147        unsafe {
148            av_samples_get_buffer_size(
149                ptr::null_mut(),
150                i32::from(channels),
151                samples as c_int,
152                format.into(),
153                !align as c_int,
154            ) as usize
155        }
156    }
157
158    #[inline]
159    pub fn new(format: Sample, channels: u16, samples: usize, align: bool) -> Self {
160        unsafe {
161            let mut buf = Buffer {
162                format,
163                channels,
164                samples,
165                align,
166
167                buffer: ptr::null_mut(),
168                size: 0,
169            };
170
171            av_samples_alloc_array_and_samples(
172                &mut buf.buffer,
173                &mut buf.size,
174                i32::from(channels),
175                samples as c_int,
176                format.into(),
177                !align as c_int,
178            );
179
180            buf
181        }
182    }
183}
184
185impl Index<usize> for Buffer {
186    type Output = [u8];
187
188    #[inline]
189    fn index(&self, index: usize) -> &[u8] {
190        if index >= self.samples {
191            panic!("out of bounds");
192        }
193
194        unsafe { slice::from_raw_parts(*self.buffer.add(index), self.size as usize) }
195    }
196}
197
198impl Clone for Buffer {
199    #[inline]
200    fn clone(&self) -> Self {
201        let mut buf = Buffer::new(self.format, self.channels, self.samples, self.align);
202        buf.clone_from(self);
203
204        buf
205    }
206
207    #[inline]
208    fn clone_from(&mut self, source: &Self) {
209        unsafe {
210            av_samples_copy(
211                self.buffer,
212                source.buffer as *const *mut u8,
213                0,
214                0,
215                source.samples as c_int,
216                i32::from(source.channels),
217                source.format.into(),
218            );
219        }
220    }
221}
222
223impl Drop for Buffer {
224    #[inline]
225    fn drop(&mut self) {
226        unsafe {
227            av_freep(self.buffer as *mut c_void);
228        }
229    }
230}