ffmpeg_the_third/software/resampling/
context.rs

1use std::ptr;
2
3use super::Delay;
4use crate::ffi::*;
5use crate::util::format;
6use crate::Dictionary;
7use crate::{frame, ChannelLayoutMask, Error};
8use libc::c_int;
9use std::ffi::c_void;
10
11#[cfg(feature = "ffmpeg_5_1")]
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(
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        options: Dictionary,
74    ) -> Result<Self, Error> {
75        unsafe {
76            let 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            let mut opts = options.disown();
89            let res = av_opt_set_dict(ptr as *mut c_void, &mut opts);
90            Dictionary::own(opts);
91
92            if res != 0 {
93                return Err(Error::from(res));
94            }
95
96            if !ptr.is_null() {
97                match swr_init(ptr) {
98                    e if e < 0 => Err(Error::from(e)),
99
100                    _ => Ok(Context {
101                        ptr,
102
103                        input: Definition {
104                            format: src_format,
105                            channel_layout: src_channel_layout,
106                            rate: src_rate,
107                        },
108
109                        output: Definition {
110                            format: dst_format,
111                            channel_layout: dst_channel_layout,
112                            rate: dst_rate,
113                        },
114                    }),
115                }
116            } else {
117                Err(Error::InvalidData)
118            }
119        }
120    }
121
122    /// Create a resampler with the given definitions.
123    #[cfg(feature = "ffmpeg_5_1")]
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    #[cfg(feature = "ffmpeg_5_1")]
145    pub fn get_with2(
146        src_format: format::Sample,
147        src_channel_layout: ChannelLayout,
148        src_rate: u32,
149        dst_format: format::Sample,
150        dst_channel_layout: ChannelLayout,
151        dst_rate: u32,
152        options: Dictionary,
153    ) -> Result<Self, Error> {
154        unsafe {
155            let mut context_ptr = ptr::null_mut();
156            let res = swr_alloc_set_opts2(
157                ptr::addr_of_mut!(context_ptr),
158                dst_channel_layout.as_ptr() as _,
159                dst_format.into(),
160                dst_rate as c_int,
161                src_channel_layout.as_ptr() as _,
162                src_format.into(),
163                src_rate as c_int,
164                0,
165                ptr::null_mut(),
166            );
167
168            if res < 0 {
169                return Err(Error::from(res));
170            }
171
172            let mut opts = options.disown();
173            let res = av_opt_set_dict(context_ptr as *mut c_void, &mut opts);
174            Dictionary::own(opts);
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}