ffmpeg_next/software/resampling/
context.rs1use std::ptr;
2
3use super::Delay;
4use crate::Dictionary;
5use crate::ffi::*;
6use crate::util::format;
7use crate::{ChannelLayout, Error, frame};
8use libc::c_int;
9use std::ffi::c_void;
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 Some(Delay::from(self)).filter(|d| d.output > 0)
153 }
154
155 pub fn run(
159 &mut self,
160 input: &frame::Audio,
161 output: &mut frame::Audio,
162 ) -> Result<Option<Delay>, Error> {
163 unsafe {
164 (*output.as_mut_ptr()).sample_rate = self.output.rate as i32;
165 }
166
167 unsafe {
168 if output.is_empty() {
169 output.alloc(
170 self.output.format,
171 input.samples(),
172 self.output.channel_layout,
173 );
174 }
175
176 match swr_convert_frame(self.as_mut_ptr(), output.as_mut_ptr(), input.as_ptr()) {
177 0 => Ok(self.delay()),
178
179 e => Err(Error::from(e)),
180 }
181 }
182 }
183
184 pub fn flush(&mut self, output: &mut frame::Audio) -> Result<Option<Delay>, Error> {
188 unsafe {
189 (*output.as_mut_ptr()).sample_rate = self.output.rate as i32;
190 }
191
192 unsafe {
193 match swr_convert_frame(self.as_mut_ptr(), output.as_mut_ptr(), ptr::null()) {
194 0 => Ok(self.delay()),
195
196 e => Err(Error::from(e)),
197 }
198 }
199 }
200}
201
202impl Drop for Context {
203 fn drop(&mut self) {
204 unsafe {
205 swr_free(&mut self.as_mut_ptr());
206 }
207 }
208}