ffmpeg_next/software/resampling/
context.rs1use 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 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 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 pub fn input(&self) -> &Definition {
142 &self.input
143 }
144
145 pub fn output(&self) -> &Definition {
147 &self.output
148 }
149
150 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 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 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}