ffmpeg_the_third/software/resampling/
context.rs1use std::ptr;
2
3use super::Delay;
4use crate::ffi::*;
5use crate::util::format;
6use crate::AsMutPtr;
7use crate::Dictionary;
8use crate::{frame, ChannelLayoutMask, Error};
9use libc::c_int;
10use std::ffi::c_void;
11
12use crate::ChannelLayout;
13
14#[derive(Eq, PartialEq, Copy, Clone)]
15pub struct Definition {
16 pub format: format::Sample,
17 pub channel_layout: ChannelLayoutMask,
18 pub rate: u32,
19}
20
21pub struct Context {
22 ptr: *mut SwrContext,
23
24 input: Definition,
25 output: Definition,
26}
27
28unsafe impl Send for Context {}
29
30impl Context {
31 #[doc(hidden)]
32 pub unsafe fn as_ptr(&self) -> *const SwrContext {
33 self.ptr as *const _
34 }
35
36 #[doc(hidden)]
37 pub unsafe fn as_mut_ptr(&mut self) -> *mut SwrContext {
38 self.ptr
39 }
40}
41
42impl Context {
43 #[cfg(not(feature = "ffmpeg_7_0"))]
45 pub fn get(
46 src_format: format::Sample,
47 src_channel_layout: ChannelLayoutMask,
48 src_rate: u32,
49 dst_format: format::Sample,
50 dst_channel_layout: ChannelLayoutMask,
51 dst_rate: u32,
52 ) -> Result<Self, Error> {
53 Self::get_with(
54 src_format,
55 src_channel_layout,
56 src_rate,
57 dst_format,
58 dst_channel_layout,
59 dst_rate,
60 Dictionary::new(),
61 )
62 }
63
64 #[cfg(not(feature = "ffmpeg_7_0"))]
66 pub fn get_with<Dict>(
67 src_format: format::Sample,
68 src_channel_layout: ChannelLayoutMask,
69 src_rate: u32,
70 dst_format: format::Sample,
71 dst_channel_layout: ChannelLayoutMask,
72 dst_rate: u32,
73 mut options: Dict,
74 ) -> Result<Self, Error>
75 where
76 Dict: AsMutPtr<*mut AVDictionary>,
77 {
78 unsafe {
79 let ptr = swr_alloc_set_opts(
80 ptr::null_mut(),
81 dst_channel_layout.bits() as i64,
82 dst_format.into(),
83 dst_rate as c_int,
84 src_channel_layout.bits() as i64,
85 src_format.into(),
86 src_rate as c_int,
87 0,
88 ptr::null_mut(),
89 );
90
91 let res = av_opt_set_dict(ptr as *mut c_void, options.as_mut_ptr());
92
93 if res != 0 {
94 return Err(Error::from(res));
95 }
96
97 if !ptr.is_null() {
98 match swr_init(ptr) {
99 e if e < 0 => Err(Error::from(e)),
100
101 _ => Ok(Context {
102 ptr,
103
104 input: Definition {
105 format: src_format,
106 channel_layout: src_channel_layout,
107 rate: src_rate,
108 },
109
110 output: Definition {
111 format: dst_format,
112 channel_layout: dst_channel_layout,
113 rate: dst_rate,
114 },
115 }),
116 }
117 } else {
118 Err(Error::InvalidData)
119 }
120 }
121 }
122
123 pub fn get2(
125 src_format: format::Sample,
126 src_channel_layout: ChannelLayout,
127 src_rate: u32,
128 dst_format: format::Sample,
129 dst_channel_layout: ChannelLayout,
130 dst_rate: u32,
131 ) -> Result<Self, Error> {
132 Self::get_with2(
133 src_format,
134 src_channel_layout,
135 src_rate,
136 dst_format,
137 dst_channel_layout,
138 dst_rate,
139 Dictionary::new(),
140 )
141 }
142
143 pub fn get_with2<Dict>(
145 src_format: format::Sample,
146 src_channel_layout: ChannelLayout,
147 src_rate: u32,
148 dst_format: format::Sample,
149 dst_channel_layout: ChannelLayout,
150 dst_rate: u32,
151 mut options: Dict,
152 ) -> Result<Self, Error>
153 where
154 Dict: AsMutPtr<*mut AVDictionary>,
155 {
156 unsafe {
157 let mut context_ptr = ptr::null_mut();
158 let res = swr_alloc_set_opts2(
159 ptr::addr_of_mut!(context_ptr),
160 dst_channel_layout.as_ptr() as _,
161 dst_format.into(),
162 dst_rate as c_int,
163 src_channel_layout.as_ptr() as _,
164 src_format.into(),
165 src_rate as c_int,
166 0,
167 ptr::null_mut(),
168 );
169
170 if res < 0 {
171 return Err(Error::from(res));
172 }
173
174 let res = av_opt_set_dict(context_ptr as *mut c_void, options.as_mut_ptr());
175
176 if res != 0 {
177 return Err(Error::from(res));
178 }
179
180 if !context_ptr.is_null() {
181 match swr_init(context_ptr) {
182 e if e < 0 => Err(Error::from(e)),
183
184 _ => Ok(Context {
185 ptr: context_ptr,
186
187 input: Definition {
188 format: src_format,
189 channel_layout: src_channel_layout.mask().unwrap(),
190 rate: src_rate,
191 },
192
193 output: Definition {
194 format: dst_format,
195 channel_layout: dst_channel_layout.mask().unwrap(),
196 rate: dst_rate,
197 },
198 }),
199 }
200 } else {
201 Err(Error::InvalidData)
202 }
203 }
204 }
205
206 pub fn input(&self) -> &Definition {
208 &self.input
209 }
210
211 pub fn output(&self) -> &Definition {
213 &self.output
214 }
215
216 pub fn delay(&self) -> Option<Delay> {
218 unsafe {
219 match swr_get_delay(self.as_ptr() as *mut _, 1) {
220 0 => None,
221 _ => Some(Delay::from(self)),
222 }
223 }
224 }
225
226 pub fn run(
230 &mut self,
231 input: &frame::Audio,
232 output: &mut frame::Audio,
233 ) -> Result<Option<Delay>, Error> {
234 unsafe {
235 (*output.as_mut_ptr()).sample_rate = self.output.rate as i32;
236 }
237
238 unsafe {
239 if output.is_empty() {
240 output.alloc(
241 self.output.format,
242 input.samples(),
243 self.output.channel_layout,
244 );
245 }
246
247 match swr_convert_frame(self.as_mut_ptr(), output.as_mut_ptr(), input.as_ptr()) {
248 0 => Ok(self.delay()),
249
250 e => Err(Error::from(e)),
251 }
252 }
253 }
254
255 pub fn flush(&mut self, output: &mut frame::Audio) -> Result<Option<Delay>, Error> {
259 unsafe {
260 (*output.as_mut_ptr()).sample_rate = self.output.rate as i32;
261 }
262
263 unsafe {
264 match swr_convert_frame(self.as_mut_ptr(), output.as_mut_ptr(), ptr::null()) {
265 0 => Ok(self.delay()),
266
267 e => Err(Error::from(e)),
268 }
269 }
270 }
271}
272
273impl Drop for Context {
274 fn drop(&mut self) {
275 unsafe {
276 swr_free(&mut self.as_mut_ptr());
277 }
278 }
279}