ffmpeg_next/software/resampling/
context.rs

1use std::ptr;
2
3use super::Delay;
4use ffi::*;
5use libc::c_int;
6use std::ffi::c_void;
7use util::format;
8use Dictionary;
9use {frame, ChannelLayout, Error};
10
11#[derive(Eq, PartialEq, Copy, Clone)]
12pub struct Definition {
13    pub format: format::Sample,
14    pub channel_layout: ChannelLayout,
15    pub rate: u32,
16}
17
18pub struct Context {
19    ptr: *mut SwrContext,
20
21    input: Definition,
22    output: Definition,
23}
24
25unsafe impl Send for Context {}
26
27impl 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
39impl 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
207impl Drop for Context {
208    fn drop(&mut self) {
209        unsafe {
210            swr_free(&mut self.as_mut_ptr());
211        }
212    }
213}