1#[cfg(feature = "dred")]
4use crate::bindings::OPUS_SET_DNN_BLOB_REQUEST;
5use crate::bindings::{
6 OPUS_GET_FINAL_RANGE_REQUEST, OPUS_GET_GAIN_REQUEST, OPUS_GET_LAST_PACKET_DURATION_REQUEST,
7 OPUS_GET_PHASE_INVERSION_DISABLED_REQUEST, OPUS_GET_PITCH_REQUEST,
8 OPUS_GET_SAMPLE_RATE_REQUEST, OPUS_RESET_STATE, OPUS_SET_GAIN_REQUEST,
9 OPUS_SET_PHASE_INVERSION_DISABLED_REQUEST, OpusDecoder, opus_decode, opus_decode_float,
10 opus_decoder_create, opus_decoder_ctl, opus_decoder_destroy, opus_decoder_get_nb_samples,
11 opus_decoder_get_size, opus_decoder_init,
12};
13use crate::constants::{is_frame_size_2_5ms_aligned, max_frame_samples_for};
14use crate::error::{Error, Result};
15use crate::packet;
16use crate::types::{Bandwidth, Channels, SampleRate};
17use crate::{AlignedBuffer, Ownership, RawHandle};
18use std::marker::PhantomData;
19use std::num::NonZeroUsize;
20use std::ops::Deref;
21use std::ptr::{self, NonNull};
22
23#[cfg(feature = "dred")]
24struct RetainedDnnBlob {
25 data: Box<[u32]>,
26 len: i32,
27}
28
29#[cfg(feature = "dred")]
30impl RetainedDnnBlob {
31 fn parts(&self) -> (*const u8, i32) {
32 (self.data.as_ptr().cast::<u8>(), self.len)
33 }
34}
35
36pub struct Decoder {
38 raw: RawHandle<OpusDecoder>,
39 sample_rate: SampleRate,
40 channels: Channels,
41 #[cfg(feature = "dred")]
46 dnn_blobs: Vec<RetainedDnnBlob>,
47 #[cfg(feature = "dred")]
48 active_dnn_blob: Option<usize>,
49}
50
51unsafe impl Send for Decoder {}
52
53pub struct DecoderRef<'a> {
65 inner: Decoder,
66 #[cfg(feature = "dred")]
67 active_dnn_blob: Option<(*const u8, i32)>,
68 _marker: PhantomData<&'a mut OpusDecoder>,
69}
70
71unsafe impl Send for DecoderRef<'_> {}
72
73impl Decoder {
74 fn from_raw(
75 ptr: NonNull<OpusDecoder>,
76 sample_rate: SampleRate,
77 channels: Channels,
78 ownership: Ownership,
79 ) -> Self {
80 Self {
81 raw: RawHandle::new(ptr, ownership, opus_decoder_destroy),
82 sample_rate,
83 channels,
84 #[cfg(feature = "dred")]
85 dnn_blobs: Vec::new(),
86 #[cfg(feature = "dred")]
87 active_dnn_blob: None,
88 }
89 }
90
91 pub fn size(channels: Channels) -> Result<usize> {
97 let raw = unsafe { opus_decoder_get_size(channels.as_i32()) };
98 if raw <= 0 {
99 return Err(Error::BadArg);
100 }
101 usize::try_from(raw).map_err(|_| Error::InternalError)
102 }
103
104 pub unsafe fn init_in_place(
113 ptr: *mut OpusDecoder,
114 sample_rate: SampleRate,
115 channels: Channels,
116 ) -> Result<()> {
117 if ptr.is_null() {
118 return Err(Error::BadArg);
119 }
120 if !crate::opus_ptr_is_aligned(ptr.cast()) {
121 return Err(Error::BadArg);
122 }
123 let r = unsafe { opus_decoder_init(ptr, sample_rate.as_i32(), channels.as_i32()) };
124 if r != 0 {
125 return Err(Error::from_code(r));
126 }
127 Ok(())
128 }
129
130 pub fn new(sample_rate: SampleRate, channels: Channels) -> Result<Self> {
135 if !sample_rate.is_valid() {
137 return Err(Error::BadArg);
138 }
139
140 let mut error = 0i32;
141 let decoder = unsafe {
142 opus_decoder_create(
143 sample_rate.as_i32(),
144 channels.as_i32(),
145 std::ptr::addr_of_mut!(error),
146 )
147 };
148
149 if error != 0 {
150 return Err(Error::from_code(error));
151 }
152
153 let decoder = NonNull::new(decoder).ok_or(Error::AllocFail)?;
154
155 Ok(Self::from_raw(
156 decoder,
157 sample_rate,
158 channels,
159 Ownership::Owned,
160 ))
161 }
162
163 pub fn decode(&mut self, input: &[u8], output: &mut [i16], fec: bool) -> Result<usize> {
174 if !input.is_empty() && input.len() > i32::MAX as usize {
177 return Err(Error::BadArg);
178 }
179 if output.is_empty() {
180 return Err(Error::BadArg);
181 }
182 if !output.len().is_multiple_of(self.channels.as_usize()) {
183 return Err(Error::BadArg);
184 }
185 let frame_size = output.len() / self.channels.as_usize();
186 let frame_size = NonZeroUsize::new(frame_size).ok_or(Error::BadArg)?;
187 let max_frame = max_frame_samples_for(self.sample_rate);
188 if frame_size.get() > max_frame {
189 return Err(Error::BadArg);
190 }
191 if (input.is_empty() || fec)
193 && !is_frame_size_2_5ms_aligned(frame_size.get(), self.sample_rate)
194 {
195 return Err(Error::BadArg);
196 }
197
198 let input_len_i32 = if input.is_empty() {
199 0
200 } else {
201 i32::try_from(input.len()).map_err(|_| Error::BadArg)?
202 };
203 let frame_size_i32 = i32::try_from(frame_size.get()).map_err(|_| Error::BadArg)?;
204
205 let result = unsafe {
206 opus_decode(
207 self.raw.as_ptr(),
208 if input.is_empty() {
209 ptr::null()
210 } else {
211 input.as_ptr()
212 },
213 input_len_i32,
214 output.as_mut_ptr(),
215 frame_size_i32,
216 i32::from(fec),
217 )
218 };
219
220 if result < 0 {
221 return Err(Error::from_code(result));
222 }
223
224 usize::try_from(result).map_err(|_| Error::InternalError)
225 }
226
227 pub fn decode_float(&mut self, input: &[u8], output: &mut [f32], fec: bool) -> Result<usize> {
236 if !input.is_empty() && input.len() > i32::MAX as usize {
238 return Err(Error::BadArg);
239 }
240 if output.is_empty() {
241 return Err(Error::BadArg);
242 }
243 if !output.len().is_multiple_of(self.channels.as_usize()) {
244 return Err(Error::BadArg);
245 }
246 let frame_size = output.len() / self.channels.as_usize();
247 let frame_size = NonZeroUsize::new(frame_size).ok_or(Error::BadArg)?;
248 let max_frame = max_frame_samples_for(self.sample_rate);
249 if frame_size.get() > max_frame {
250 return Err(Error::BadArg);
251 }
252 if (input.is_empty() || fec)
254 && !is_frame_size_2_5ms_aligned(frame_size.get(), self.sample_rate)
255 {
256 return Err(Error::BadArg);
257 }
258
259 let input_len_i32 = if input.is_empty() {
260 0
261 } else {
262 i32::try_from(input.len()).map_err(|_| Error::BadArg)?
263 };
264 let frame_size_i32 = i32::try_from(frame_size.get()).map_err(|_| Error::BadArg)?;
265
266 let result = unsafe {
267 opus_decode_float(
268 self.raw.as_ptr(),
269 if input.is_empty() {
270 ptr::null()
271 } else {
272 input.as_ptr()
273 },
274 input_len_i32,
275 output.as_mut_ptr(),
276 frame_size_i32,
277 i32::from(fec),
278 )
279 };
280
281 if result < 0 {
282 return Err(Error::from_code(result));
283 }
284
285 usize::try_from(result).map_err(|_| Error::InternalError)
286 }
287
288 pub fn packet_samples(&self, packet: &[u8]) -> Result<usize> {
294 if packet.is_empty() {
296 return Err(Error::BadArg);
297 }
298 if packet.len() > i32::MAX as usize {
299 return Err(Error::BadArg);
300 }
301 let len_i32 = i32::try_from(packet.len()).map_err(|_| Error::BadArg)?;
302 let result =
303 unsafe { opus_decoder_get_nb_samples(self.raw.as_ptr(), packet.as_ptr(), len_i32) };
304
305 if result < 0 {
306 return Err(Error::from_code(result));
307 }
308
309 usize::try_from(result).map_err(|_| Error::InternalError)
310 }
311
312 pub fn packet_bandwidth(&self, packet: &[u8]) -> Result<Bandwidth> {
318 packet::packet_bandwidth(packet)
320 }
321
322 pub fn packet_channels(&self, packet: &[u8]) -> Result<Channels> {
328 packet::packet_channels(packet)
330 }
331
332 pub fn reset(&mut self) -> Result<()> {
338 let result = unsafe { opus_decoder_ctl(self.raw.as_ptr(), OPUS_RESET_STATE as i32) };
341
342 if result != 0 {
343 return Err(Error::from_code(result));
344 }
345
346 #[cfg(feature = "dred")]
347 self.reload_active_dnn_blob()?;
348 Ok(())
349 }
350
351 #[must_use]
353 pub const fn sample_rate(&self) -> SampleRate {
354 self.sample_rate
355 }
356
357 #[must_use]
359 pub const fn channels(&self) -> Channels {
360 self.channels
361 }
362
363 #[cfg_attr(not(feature = "dred"), allow(dead_code))]
364 pub(crate) fn as_mut_ptr(&mut self) -> *mut OpusDecoder {
365 self.raw.as_ptr()
366 }
367
368 pub fn get_sample_rate(&mut self) -> Result<i32> {
373 self.get_int_ctl(OPUS_GET_SAMPLE_RATE_REQUEST as i32)
374 }
375
376 pub fn get_pitch(&mut self) -> Result<i32> {
381 self.get_int_ctl(OPUS_GET_PITCH_REQUEST as i32)
382 }
383
384 pub fn get_last_packet_duration(&mut self) -> Result<i32> {
389 self.get_int_ctl(OPUS_GET_LAST_PACKET_DURATION_REQUEST as i32)
390 }
391
392 pub fn final_range(&mut self) -> Result<u32> {
397 let mut v: u32 = 0;
398 let r = unsafe {
399 opus_decoder_ctl(
400 self.raw.as_ptr(),
401 OPUS_GET_FINAL_RANGE_REQUEST as i32,
402 &mut v,
403 )
404 };
405 if r != 0 {
406 return Err(Error::from_code(r));
407 }
408 Ok(v)
409 }
410
411 pub fn set_gain(&mut self, q8_db: i32) -> Result<()> {
416 self.simple_ctl(OPUS_SET_GAIN_REQUEST as i32, q8_db)
417 }
418 pub fn gain(&mut self) -> Result<i32> {
423 self.get_int_ctl(OPUS_GET_GAIN_REQUEST as i32)
424 }
425
426 pub fn phase_inversion_disabled(&mut self) -> Result<bool> {
431 Ok(self.get_int_ctl(OPUS_GET_PHASE_INVERSION_DISABLED_REQUEST as i32)? != 0)
432 }
433
434 pub fn set_phase_inversion_disabled(&mut self, disabled: bool) -> Result<()> {
439 self.simple_ctl(
440 OPUS_SET_PHASE_INVERSION_DISABLED_REQUEST as i32,
441 i32::from(disabled),
442 )
443 }
444
445 #[cfg(feature = "dred")]
446 pub unsafe fn set_dnn_blob(&mut self, ptr: *const u8, len: i32) -> Result<()> {
458 let blob_index = unsafe { self.retain_dnn_blob_copy(ptr, len)? };
459 let (owned_ptr, owned_len) = self.dnn_blobs[blob_index].parts();
460 if let Err(error) = unsafe { self.apply_dnn_blob(owned_ptr, owned_len) } {
461 if error == Error::Unimplemented {
462 let removed = self.dnn_blobs.pop();
465 debug_assert!(removed.is_some());
466 }
467 return Err(error);
468 }
469 self.active_dnn_blob = Some(blob_index);
470 Ok(())
471 }
472
473 #[cfg(feature = "dred")]
474 unsafe fn retain_dnn_blob_copy(&mut self, ptr: *const u8, len: i32) -> Result<usize> {
475 if ptr.is_null() || len <= 0 {
476 return Err(Error::BadArg);
477 }
478 let byte_len = usize::try_from(len).map_err(|_| Error::BadArg)?;
479 let word_len = byte_len.div_ceil(std::mem::size_of::<u32>());
480 let mut blob = vec![0u32; word_len].into_boxed_slice();
481 unsafe {
482 std::ptr::copy_nonoverlapping(ptr, blob.as_mut_ptr().cast::<u8>(), byte_len);
483 }
484 let index = self.dnn_blobs.len();
485 self.dnn_blobs.push(RetainedDnnBlob { data: blob, len });
486 Ok(index)
487 }
488
489 #[cfg(feature = "dred")]
490 unsafe fn apply_dnn_blob(&mut self, ptr: *const u8, len: i32) -> Result<()> {
491 let r = unsafe {
492 opus_decoder_ctl(
493 self.raw.as_ptr(),
494 OPUS_SET_DNN_BLOB_REQUEST as i32,
495 ptr,
496 len,
497 )
498 };
499 if r != 0 {
500 return Err(Error::from_code(r));
501 }
502 Ok(())
503 }
504
505 #[cfg(feature = "dred")]
506 fn reload_active_dnn_blob(&mut self) -> Result<()> {
507 let Some(index) = self.active_dnn_blob else {
508 return Ok(());
509 };
510 let (ptr, len) = self.dnn_blobs[index].parts();
511 unsafe { self.apply_dnn_blob(ptr, len) }
512 }
513
514 fn simple_ctl(&mut self, req: i32, val: i32) -> Result<()> {
516 let r = unsafe { opus_decoder_ctl(self.raw.as_ptr(), req, val) };
517 if r != 0 {
518 return Err(Error::from_code(r));
519 }
520 Ok(())
521 }
522 fn get_int_ctl(&mut self, req: i32) -> Result<i32> {
523 let mut v: i32 = 0;
524 let r = unsafe { opus_decoder_ctl(self.raw.as_ptr(), req, &mut v) };
525 if r != 0 {
526 return Err(Error::from_code(r));
527 }
528 Ok(v)
529 }
530}
531
532impl<'a> DecoderRef<'a> {
533 #[must_use]
552 pub unsafe fn from_raw(
553 ptr: *mut OpusDecoder,
554 sample_rate: SampleRate,
555 channels: Channels,
556 ) -> Self {
557 let decoder = Decoder::from_raw(
558 crate::checked_non_null(ptr, "DecoderRef::from_raw"),
559 sample_rate,
560 channels,
561 Ownership::Borrowed,
562 );
563 Self {
564 inner: decoder,
565 #[cfg(feature = "dred")]
566 active_dnn_blob: None,
567 _marker: PhantomData,
568 }
569 }
570
571 pub fn init_in(
576 buf: &'a mut AlignedBuffer,
577 sample_rate: SampleRate,
578 channels: Channels,
579 ) -> Result<Self> {
580 let required = Decoder::size(channels)?;
581 if buf.capacity_bytes() < required {
582 return Err(Error::BadArg);
583 }
584 let ptr = buf.as_mut_ptr::<OpusDecoder>();
585 unsafe { Decoder::init_in_place(ptr, sample_rate, channels)? };
586 Ok(unsafe { Self::from_raw(ptr, sample_rate, channels) })
587 }
588
589 delegate_ref_mut_methods! {
590 fn decode(input: &[u8], output: &mut [i16], fec: bool) -> Result<usize>;
591 fn decode_float(input: &[u8], output: &mut [f32], fec: bool) -> Result<usize>;
592 fn get_sample_rate() -> Result<i32>;
593 fn get_pitch() -> Result<i32>;
594 fn get_last_packet_duration() -> Result<i32>;
595 fn final_range() -> Result<u32>;
596 fn set_gain(q8_db: i32) -> Result<()>;
597 fn gain() -> Result<i32>;
598 fn phase_inversion_disabled() -> Result<bool>;
599 fn set_phase_inversion_disabled(disabled: bool) -> Result<()>;
600 }
601
602 pub fn reset(&mut self) -> Result<()> {
607 self.inner.reset()?;
608 #[cfg(feature = "dred")]
609 if let Some((ptr, len)) = self.active_dnn_blob {
610 unsafe { self.inner.apply_dnn_blob(ptr, len)? };
611 }
612 Ok(())
613 }
614
615 #[cfg(feature = "dred")]
616 pub unsafe fn set_dnn_blob(&mut self, ptr: *const u8, len: i32) -> Result<()> {
632 if ptr.is_null() || len <= 0 || !ptr.addr().is_multiple_of(std::mem::align_of::<u32>()) {
633 return Err(Error::BadArg);
634 }
635 unsafe { self.inner.apply_dnn_blob(ptr, len)? };
636 self.active_dnn_blob = Some((ptr, len));
637 Ok(())
638 }
639}
640
641impl Deref for DecoderRef<'_> {
642 type Target = Decoder;
643
644 fn deref(&self) -> &Self::Target {
645 &self.inner
646 }
647}
648
649#[cfg(all(test, feature = "dred"))]
650mod tests {
651 use super::*;
652 use crate::types::{Channels, SampleRate};
653
654 #[test]
655 fn dnn_blob_is_copied_into_retained_aligned_storage() {
656 let mut decoder = Decoder::new(SampleRate::Hz48000, Channels::Mono).unwrap();
657 let source = [0u8, 1, 2, 3, 4];
658 let unaligned = unsafe { source.as_ptr().add(1) };
659
660 let index = unsafe { decoder.retain_dnn_blob_copy(unaligned, 4) }.unwrap();
661 let (retained, len) = decoder.dnn_blobs[index].parts();
662
663 assert_eq!(len, 4);
664 assert_eq!((retained as usize) % std::mem::align_of::<u32>(), 0);
665 assert_eq!(
666 unsafe { std::slice::from_raw_parts(retained, 4) },
667 &source[1..]
668 );
669 assert_eq!(decoder.dnn_blobs.len(), 1);
670 }
671}