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