ffmpeg_rs/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            let ptr = swr_alloc_set_opts(
72                ptr::null_mut(),
73                dst_channel_layout.bits() as i64,
74                dst_format.into(),
75                dst_rate as c_int,
76                src_channel_layout.bits() as i64,
77                src_format.into(),
78                src_rate as c_int,
79                0,
80                ptr::null_mut(),
81            );
82
83            let mut opts = options.disown();
84            let res = av_opt_set_dict(ptr as *mut c_void, &mut opts);
85            Dictionary::own(opts);
86
87            if res != 0 {
88                return Err(Error::from(res));
89            }
90
91            if !ptr.is_null() {
92                match swr_init(ptr) {
93                    e if e < 0 => Err(Error::from(e)),
94
95                    _ => Ok(Context {
96                        ptr,
97
98                        input: Definition {
99                            format: src_format,
100                            channel_layout: src_channel_layout,
101                            rate: src_rate,
102                        },
103
104                        output: Definition {
105                            format: dst_format,
106                            channel_layout: dst_channel_layout,
107                            rate: dst_rate,
108                        },
109                    }),
110                }
111            } else {
112                Err(Error::InvalidData)
113            }
114        }
115    }
116
117    /// Get the input definition.
118    pub fn input(&self) -> &Definition {
119        &self.input
120    }
121
122    /// Get the output definition.
123    pub fn output(&self) -> &Definition {
124        &self.output
125    }
126
127    /// Get the remaining delay.
128    pub fn delay(&self) -> Option<Delay> {
129        unsafe {
130            match swr_get_delay(self.as_ptr() as *mut _, 1) {
131                0 => None,
132                _ => Some(Delay::from(self)),
133            }
134        }
135    }
136
137    /// Run the resampler from the given input to the given output.
138    ///
139    /// When there are internal frames to process it will return `Ok(Some(Delay { .. }))`.
140    pub fn run(
141        &mut self,
142        input: &frame::Audio,
143        output: &mut frame::Audio,
144    ) -> Result<Option<Delay>, Error> {
145        unsafe {
146            (*output.as_mut_ptr()).sample_rate = self.output.rate as i32;
147        }
148
149        unsafe {
150            if output.is_empty() {
151                output.alloc(
152                    self.output.format,
153                    input.samples(),
154                    self.output.channel_layout,
155                );
156            }
157
158            match swr_convert_frame(self.as_mut_ptr(), output.as_mut_ptr(), input.as_ptr()) {
159                0 => Ok(self.delay()),
160
161                e => Err(Error::from(e)),
162            }
163        }
164    }
165
166    /// Convert one of the remaining internal frames.
167    ///
168    /// When there are no more internal frames `Ok(None)` will be returned.
169    pub fn flush(&mut self, output: &mut frame::Audio) -> Result<Option<Delay>, Error> {
170        unsafe {
171            (*output.as_mut_ptr()).sample_rate = self.output.rate as i32;
172        }
173
174        unsafe {
175            match swr_convert_frame(self.as_mut_ptr(), output.as_mut_ptr(), ptr::null()) {
176                0 => Ok(self.delay()),
177
178                e => Err(Error::from(e)),
179            }
180        }
181    }
182}
183
184impl Drop for Context {
185    fn drop(&mut self) {
186        unsafe {
187            swr_free(&mut self.as_mut_ptr());
188        }
189    }
190}