ffmpeg_the_third/util/format/
sample.rs1use 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}