| 1 | use std::ptr; |
| 2 | |
| 3 | use super::Delay; |
| 4 | use ffi::*; |
| 5 | use libc::c_int; |
| 6 | use std::ffi::c_void; |
| 7 | use util::format; |
| 8 | use Dictionary; |
| 9 | use {frame, ChannelLayout, Error}; |
| 10 | |
| 11 | #[derive (Eq, PartialEq, Copy, Clone)] |
| 12 | pub struct Definition { |
| 13 | pub format: format::Sample, |
| 14 | pub channel_layout: ChannelLayout, |
| 15 | pub rate: u32, |
| 16 | } |
| 17 | |
| 18 | pub struct Context { |
| 19 | ptr: *mut SwrContext, |
| 20 | |
| 21 | input: Definition, |
| 22 | output: Definition, |
| 23 | } |
| 24 | |
| 25 | unsafe impl Send for Context {} |
| 26 | |
| 27 | impl Context { |
| 28 | #[doc (hidden)] |
| 29 | pub unsafe fn as_ptr(&self) -> *const SwrContext { |
| 30 | self.ptr as *const _ |
| 31 | } |
| 32 | |
| 33 | #[doc (hidden)] |
| 34 | pub unsafe fn as_mut_ptr(&mut self) -> *mut SwrContext { |
| 35 | self.ptr |
| 36 | } |
| 37 | } |
| 38 | |
| 39 | impl Context { |
| 40 | /// Create a resampler with the given definitions. |
| 41 | pub fn get( |
| 42 | src_format: format::Sample, |
| 43 | src_channel_layout: ChannelLayout, |
| 44 | src_rate: u32, |
| 45 | dst_format: format::Sample, |
| 46 | dst_channel_layout: ChannelLayout, |
| 47 | dst_rate: u32, |
| 48 | ) -> Result<Self, Error> { |
| 49 | Self::get_with( |
| 50 | src_format, |
| 51 | src_channel_layout, |
| 52 | src_rate, |
| 53 | dst_format, |
| 54 | dst_channel_layout, |
| 55 | dst_rate, |
| 56 | Dictionary::new(), |
| 57 | ) |
| 58 | } |
| 59 | |
| 60 | /// Create a resampler with the given definitions and custom options dictionary. |
| 61 | pub fn get_with( |
| 62 | src_format: format::Sample, |
| 63 | src_channel_layout: ChannelLayout, |
| 64 | src_rate: u32, |
| 65 | dst_format: format::Sample, |
| 66 | dst_channel_layout: ChannelLayout, |
| 67 | dst_rate: u32, |
| 68 | options: Dictionary, |
| 69 | ) -> Result<Self, Error> { |
| 70 | unsafe { |
| 71 | #[allow (unused_assignments)] |
| 72 | let mut ptr = std::ptr::null_mut(); |
| 73 | |
| 74 | #[cfg (not(feature = "ffmpeg_7_0" ))] |
| 75 | { |
| 76 | ptr = swr_alloc_set_opts( |
| 77 | ptr::null_mut(), |
| 78 | dst_channel_layout.bits() as i64, |
| 79 | dst_format.into(), |
| 80 | dst_rate as c_int, |
| 81 | src_channel_layout.bits() as i64, |
| 82 | src_format.into(), |
| 83 | src_rate as c_int, |
| 84 | 0, |
| 85 | ptr::null_mut(), |
| 86 | ); |
| 87 | } |
| 88 | #[cfg (feature = "ffmpeg_7_0" )] |
| 89 | { |
| 90 | let e = swr_alloc_set_opts2( |
| 91 | &mut ptr, |
| 92 | &dst_channel_layout.into(), |
| 93 | dst_format.into(), |
| 94 | dst_rate as c_int, |
| 95 | &src_channel_layout.into(), |
| 96 | src_format.into(), |
| 97 | src_rate as c_int, |
| 98 | 0, |
| 99 | ptr::null_mut(), |
| 100 | ); |
| 101 | if e != 0 { |
| 102 | return Err(Error::from(e)); |
| 103 | } |
| 104 | } |
| 105 | |
| 106 | let mut opts = options.disown(); |
| 107 | let res = av_opt_set_dict(ptr as *mut c_void, &mut opts); |
| 108 | Dictionary::own(opts); |
| 109 | |
| 110 | if res != 0 { |
| 111 | return Err(Error::from(res)); |
| 112 | } |
| 113 | |
| 114 | if !ptr.is_null() { |
| 115 | match swr_init(ptr) { |
| 116 | e if e < 0 => Err(Error::from(e)), |
| 117 | |
| 118 | _ => Ok(Context { |
| 119 | ptr, |
| 120 | |
| 121 | input: Definition { |
| 122 | format: src_format, |
| 123 | channel_layout: src_channel_layout, |
| 124 | rate: src_rate, |
| 125 | }, |
| 126 | |
| 127 | output: Definition { |
| 128 | format: dst_format, |
| 129 | channel_layout: dst_channel_layout, |
| 130 | rate: dst_rate, |
| 131 | }, |
| 132 | }), |
| 133 | } |
| 134 | } else { |
| 135 | Err(Error::InvalidData) |
| 136 | } |
| 137 | } |
| 138 | } |
| 139 | |
| 140 | /// Get the input definition. |
| 141 | pub fn input(&self) -> &Definition { |
| 142 | &self.input |
| 143 | } |
| 144 | |
| 145 | /// Get the output definition. |
| 146 | pub fn output(&self) -> &Definition { |
| 147 | &self.output |
| 148 | } |
| 149 | |
| 150 | /// Get the remaining delay. |
| 151 | pub fn delay(&self) -> Option<Delay> { |
| 152 | unsafe { |
| 153 | match swr_get_delay(self.as_ptr() as *mut _, 1) { |
| 154 | 0 => None, |
| 155 | _ => Some(Delay::from(self)), |
| 156 | } |
| 157 | } |
| 158 | } |
| 159 | |
| 160 | /// Run the resampler from the given input to the given output. |
| 161 | /// |
| 162 | /// When there are internal frames to process it will return `Ok(Some(Delay { .. }))`. |
| 163 | pub fn run( |
| 164 | &mut self, |
| 165 | input: &frame::Audio, |
| 166 | output: &mut frame::Audio, |
| 167 | ) -> Result<Option<Delay>, Error> { |
| 168 | unsafe { |
| 169 | (*output.as_mut_ptr()).sample_rate = self.output.rate as i32; |
| 170 | } |
| 171 | |
| 172 | unsafe { |
| 173 | if output.is_empty() { |
| 174 | output.alloc( |
| 175 | self.output.format, |
| 176 | input.samples(), |
| 177 | self.output.channel_layout, |
| 178 | ); |
| 179 | } |
| 180 | |
| 181 | match swr_convert_frame(self.as_mut_ptr(), output.as_mut_ptr(), input.as_ptr()) { |
| 182 | 0 => Ok(self.delay()), |
| 183 | |
| 184 | e => Err(Error::from(e)), |
| 185 | } |
| 186 | } |
| 187 | } |
| 188 | |
| 189 | /// Convert one of the remaining internal frames. |
| 190 | /// |
| 191 | /// When there are no more internal frames `Ok(None)` will be returned. |
| 192 | pub fn flush(&mut self, output: &mut frame::Audio) -> Result<Option<Delay>, Error> { |
| 193 | unsafe { |
| 194 | (*output.as_mut_ptr()).sample_rate = self.output.rate as i32; |
| 195 | } |
| 196 | |
| 197 | unsafe { |
| 198 | match swr_convert_frame(self.as_mut_ptr(), output.as_mut_ptr(), ptr::null()) { |
| 199 | 0 => Ok(self.delay()), |
| 200 | |
| 201 | e => Err(Error::from(e)), |
| 202 | } |
| 203 | } |
| 204 | } |
| 205 | } |
| 206 | |
| 207 | impl Drop for Context { |
| 208 | fn drop(&mut self) { |
| 209 | unsafe { |
| 210 | swr_free(&mut self.as_mut_ptr()); |
| 211 | } |
| 212 | } |
| 213 | } |
| 214 | |