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}
191