1use std::ptr;
2
3use crate::{
4 FfmpegError, Result,
5 ffi::{self, AvFrame, sys},
6 format::{InputContext, Packet, Rational},
7};
8use sys::{
9 AVRounding::AV_ROUND_UP,
10 AVSampleFormat::{AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_NONE, AV_SAMPLE_FMT_S16},
11};
12
13#[derive(Debug, Clone, Copy, PartialEq, Eq)]
14pub enum SampleFormat {
15 F32,
16 I16,
17 Unknown,
18}
19
20#[derive(Debug, Clone)]
21pub struct AudioFrame {
22 pub sample_rate: u32,
23 pub channels: u16,
24 pub sample_format: SampleFormat,
25 pub pts: Option<i64>,
26 pub samples: usize,
27 pub interleaved_f32: Vec<f32>,
28}
29
30#[derive(Debug, Clone, Copy)]
31pub struct AudioResamplerConfig {
32 pub sample_rate: u32,
33 pub channels: u16,
34 pub sample_format: SampleFormat,
35}
36
37impl Default for AudioResamplerConfig {
38 fn default() -> Self {
39 Self {
40 sample_rate: 48_000,
41 channels: 2,
42 sample_format: SampleFormat::F32,
43 }
44 }
45}
46
47pub struct AudioDecoder {
48 stream_index: usize,
49 time_base: Rational,
50 context: *mut sys::AVCodecContext,
51}
52
53unsafe impl Send for AudioDecoder {}
54
55impl AudioDecoder {
56 pub fn open(input: &InputContext, stream_index: usize) -> Result<Self> {
57 let parameters = input.stream_parameters(stream_index)?;
58 let codec = unsafe { sys::avcodec_find_decoder((*parameters).codec_id) };
59 if codec.is_null() {
60 return Err(FfmpegError::new(
61 "avcodec_find_decoder",
62 "no audio decoder found",
63 ));
64 }
65 let context = unsafe { sys::avcodec_alloc_context3(codec) };
66 if context.is_null() {
67 return Err(FfmpegError::new(
68 "avcodec_alloc_context3",
69 "failed to allocate audio decoder context",
70 ));
71 }
72 unsafe {
73 ffi::check(
74 sys::avcodec_parameters_to_context(context, parameters),
75 "avcodec_parameters_to_context",
76 )?;
77 ffi::check(
78 sys::avcodec_open2(context, codec, ptr::null_mut()),
79 "avcodec_open2",
80 )?;
81 }
82 Ok(Self {
83 stream_index,
84 time_base: input.stream_time_base(stream_index)?.into(),
85 context,
86 })
87 }
88
89 pub fn stream_index(&self) -> usize {
90 self.stream_index
91 }
92
93 pub fn time_base(&self) -> Rational {
94 self.time_base
95 }
96
97 pub fn send_packet(&mut self, packet: &Packet) -> Result<()> {
98 if packet.stream_index() != self.stream_index {
99 return Ok(());
100 }
101 unsafe {
102 ffi::check(
103 sys::avcodec_send_packet(self.context, packet.inner.as_ptr()),
104 "avcodec_send_packet",
105 )
106 }
107 }
108
109 pub fn send_eof(&mut self) -> Result<()> {
110 unsafe {
111 ffi::check(
112 sys::avcodec_send_packet(self.context, ptr::null()),
113 "avcodec_send_packet",
114 )
115 }
116 }
117
118 pub fn flush(&mut self) {
119 unsafe { sys::avcodec_flush_buffers(self.context) };
120 }
121
122 pub fn receive_frame(&mut self) -> Result<Option<DecodedAudioFrame>> {
123 let mut frame = AvFrame::new()?;
124 let result = unsafe { sys::avcodec_receive_frame(self.context, frame.as_mut_ptr()) };
125 if result == sys::AVERROR(libc::EAGAIN) || result == sys::AVERROR_EOF {
126 return Ok(None);
127 }
128 if result < 0 {
129 return Err(ffi::error_from_code("avcodec_receive_frame", result));
130 }
131 Ok(Some(DecodedAudioFrame { frame }))
132 }
133}
134
135impl Drop for AudioDecoder {
136 fn drop(&mut self) {
137 unsafe { sys::avcodec_free_context(&mut self.context) };
138 }
139}
140
141pub struct DecodedAudioFrame {
142 frame: AvFrame,
143}
144
145impl DecodedAudioFrame {
146 pub fn samples(&self) -> usize {
147 self.frame.nb_samples()
148 }
149
150 pub fn pts(&self) -> Option<i64> {
151 self.frame.pts()
152 }
153}
154
155pub struct AudioResampler {
156 ptr: *mut sys::SwrContext,
157 config: AudioResamplerConfig,
158}
159
160unsafe impl Send for AudioResampler {}
161
162impl AudioResampler {
163 pub fn new(source: &DecodedAudioFrame, config: AudioResamplerConfig) -> Result<Self> {
164 let mut dst_layout = unsafe { std::mem::zeroed() };
165 let mut src_layout = unsafe { (*source.frame.as_ptr()).ch_layout };
166 unsafe {
167 sys::av_channel_layout_default(&mut dst_layout, config.channels as i32);
168 if src_layout.nb_channels == 0 {
169 sys::av_channel_layout_default(
170 &mut src_layout,
171 (*source.frame.as_ptr()).ch_layout.nb_channels,
172 );
173 }
174 }
175 let mut ptr = ptr::null_mut();
176 unsafe {
177 ffi::check(
178 sys::swr_alloc_set_opts2(
179 &mut ptr,
180 ptr::addr_of_mut!(dst_layout),
181 config.sample_format.to_av_sample_format(),
182 config.sample_rate as i32,
183 ptr::addr_of_mut!(src_layout),
184 source.frame.sample_format(),
185 (*source.frame.as_ptr()).sample_rate,
186 0,
187 ptr::null_mut(),
188 ),
189 "swr_alloc_set_opts2",
190 )?;
191 ffi::check(sys::swr_init(ptr), "swr_init")?;
192 }
193 Ok(Self { ptr, config })
194 }
195
196 pub fn convert(&mut self, source: &DecodedAudioFrame) -> Result<AudioFrame> {
197 if self.config.sample_format != SampleFormat::F32 {
198 return Err(FfmpegError::new(
199 "AudioResampler::convert",
200 "only interleaved f32 output is currently exposed",
201 ));
202 }
203 let input_samples = source.frame.nb_samples() as i64;
204 let delay =
205 unsafe { sys::swr_get_delay(self.ptr, (*source.frame.as_ptr()).sample_rate as i64) };
206 let output_capacity = unsafe {
207 sys::av_rescale_rnd(
208 delay + input_samples,
209 self.config.sample_rate as i64,
210 (*source.frame.as_ptr()).sample_rate as i64,
211 AV_ROUND_UP,
212 )
213 } as usize;
214 let channels = self.config.channels as usize;
215 let mut output = vec![0_f32; output_capacity.saturating_mul(channels)];
216 let mut output_ptr = output.as_mut_ptr() as *mut u8;
217 let converted = unsafe {
218 sys::swr_convert(
219 self.ptr,
220 ptr::addr_of_mut!(output_ptr),
221 output_capacity as i32,
222 (*source.frame.as_ptr()).data.as_ptr() as *mut *const u8,
223 source.frame.nb_samples() as i32,
224 )
225 };
226 if converted < 0 {
227 return Err(ffi::error_from_code("swr_convert", converted));
228 }
229 let samples = converted as usize;
230 output.truncate(samples.saturating_mul(channels));
231 Ok(AudioFrame {
232 sample_rate: self.config.sample_rate,
233 channels: self.config.channels,
234 sample_format: self.config.sample_format,
235 pts: source.pts(),
236 samples,
237 interleaved_f32: output,
238 })
239 }
240}
241
242impl Drop for AudioResampler {
243 fn drop(&mut self) {
244 unsafe { sys::swr_free(&mut self.ptr) };
245 }
246}
247
248impl SampleFormat {
249 fn to_av_sample_format(self) -> sys::AVSampleFormat {
250 match self {
251 Self::F32 => AV_SAMPLE_FMT_FLT,
252 Self::I16 => AV_SAMPLE_FMT_S16,
253 Self::Unknown => AV_SAMPLE_FMT_NONE,
254 }
255 }
256}