| 1 | use std::ffi::{CStr, CString}; |
| 2 | use std::ops::Index; |
| 3 | use std::ptr; |
| 4 | use std::slice; |
| 5 | use std::str::from_utf8_unchecked; |
| 6 | |
| 7 | use ffi::AVSampleFormat::*; |
| 8 | use ffi::*; |
| 9 | use libc::{c_int, c_void}; |
| 10 | |
| 11 | #[derive (Eq, PartialEq, Copy, Clone, Debug)] |
| 12 | pub 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)] |
| 24 | pub enum Type { |
| 25 | Packed, |
| 26 | Planar, |
| 27 | } |
| 28 | |
| 29 | impl 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 | |
| 68 | impl 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 | |
| 93 | impl From<&'static str> for Sample { |
| 94 | #[inline ] |
| 95 | fn from(value: &'static str) -> Self { |
| 96 | unsafe { |
| 97 | let value: CString = CString::new(value).unwrap(); |
| 98 | |
| 99 | Sample::from(av_get_sample_fmt(value.as_ptr())) |
| 100 | } |
| 101 | } |
| 102 | } |
| 103 | |
| 104 | impl 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 | |
| 127 | pub 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 | |
| 137 | impl 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 | |
| 178 | impl 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 | |
| 191 | impl Clone for Buffer { |
| 192 | #[inline ] |
| 193 | fn clone(&self) -> Self { |
| 194 | let mut buf: Buffer = 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 | |
| 216 | impl Drop for Buffer { |
| 217 | #[inline ] |
| 218 | fn drop(&mut self) { |
| 219 | unsafe { |
| 220 | av_freep(self.buffer as *mut c_void); |
| 221 | } |
| 222 | } |
| 223 | } |
| 224 | |