Skip to main content

ffmpeg_the_third/software/resampling/
context.rs

1use 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    /// Create a resampler with the given definitions.
44    #[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    /// Create a resampler with the given definitions and custom options dictionary.
65    #[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    /// Create a resampler with the given definitions.
124    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    /// Create a resampler with the given definitions and custom options dictionary.
144    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    /// Get the input definition.
207    pub fn input(&self) -> &Definition {
208        &self.input
209    }
210
211    /// Get the output definition.
212    pub fn output(&self) -> &Definition {
213        &self.output
214    }
215
216    /// Get the remaining delay.
217    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    /// Run the resampler from the given input to the given output.
227    ///
228    /// When there are internal frames to process it will return `Ok(Some(Delay { .. }))`.
229    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    /// Convert one of the remaining internal frames.
256    ///
257    /// When there are no more internal frames `Ok(None)` will be returned.
258    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}