1use crate::bindings::{
4 OPUS_AUTO, OPUS_BANDWIDTH_FULLBAND, OPUS_BITRATE_MAX, OPUS_GET_BANDWIDTH_REQUEST,
5 OPUS_GET_BITRATE_REQUEST, OPUS_GET_COMPLEXITY_REQUEST, OPUS_GET_DTX_REQUEST,
6 OPUS_GET_EXPERT_FRAME_DURATION_REQUEST, OPUS_GET_FINAL_RANGE_REQUEST,
7 OPUS_GET_FORCE_CHANNELS_REQUEST, OPUS_GET_IN_DTX_REQUEST, OPUS_GET_INBAND_FEC_REQUEST,
8 OPUS_GET_LOOKAHEAD_REQUEST, OPUS_GET_LSB_DEPTH_REQUEST, OPUS_GET_MAX_BANDWIDTH_REQUEST,
9 OPUS_GET_PACKET_LOSS_PERC_REQUEST, OPUS_GET_PHASE_INVERSION_DISABLED_REQUEST,
10 OPUS_GET_PREDICTION_DISABLED_REQUEST, OPUS_GET_SIGNAL_REQUEST, OPUS_GET_VBR_CONSTRAINT_REQUEST,
11 OPUS_GET_VBR_REQUEST, OPUS_SET_BANDWIDTH_REQUEST, OPUS_SET_BITRATE_REQUEST,
12 OPUS_SET_COMPLEXITY_REQUEST, OPUS_SET_DTX_REQUEST, OPUS_SET_EXPERT_FRAME_DURATION_REQUEST,
13 OPUS_SET_FORCE_CHANNELS_REQUEST, OPUS_SET_INBAND_FEC_REQUEST, OPUS_SET_LSB_DEPTH_REQUEST,
14 OPUS_SET_MAX_BANDWIDTH_REQUEST, OPUS_SET_PACKET_LOSS_PERC_REQUEST,
15 OPUS_SET_PHASE_INVERSION_DISABLED_REQUEST, OPUS_SET_PREDICTION_DISABLED_REQUEST,
16 OPUS_SET_SIGNAL_REQUEST, OPUS_SET_VBR_CONSTRAINT_REQUEST, OPUS_SET_VBR_REQUEST, OpusEncoder,
17 opus_encode, opus_encode_float, opus_encoder_create, opus_encoder_ctl, opus_encoder_destroy,
18 opus_encoder_get_size, opus_encoder_init,
19};
20#[cfg(feature = "dred")]
21use crate::bindings::{
22 OPUS_GET_DRED_DURATION_REQUEST, OPUS_SET_DNN_BLOB_REQUEST, OPUS_SET_DRED_DURATION_REQUEST,
23};
24use crate::constants::max_frame_samples_for;
25use crate::error::{Error, Result};
26use crate::types::{
27 Application, Bandwidth, Bitrate, Channels, Complexity, ExpertFrameDuration, SampleRate, Signal,
28};
29use crate::{AlignedBuffer, Ownership, RawHandle};
30use std::marker::PhantomData;
31use std::num::NonZeroUsize;
32use std::ops::Deref;
33use std::ptr::NonNull;
34
35#[cfg(feature = "dred")]
36struct RetainedDnnBlob {
37 data: Box<[u32]>,
38 len: i32,
39}
40
41#[cfg(feature = "dred")]
42impl RetainedDnnBlob {
43 fn parts(&self) -> (*const u8, i32) {
44 (self.data.as_ptr().cast::<u8>(), self.len)
45 }
46}
47
48pub struct Encoder {
50 raw: RawHandle<OpusEncoder>,
51 sample_rate: SampleRate,
52 channels: Channels,
53 #[cfg(feature = "dred")]
58 dnn_blobs: Vec<RetainedDnnBlob>,
59 #[cfg(feature = "dred")]
60 active_dnn_blob: Option<usize>,
61}
62
63unsafe impl Send for Encoder {}
64
65pub struct EncoderRef<'a> {
77 inner: Encoder,
78 #[cfg(feature = "dred")]
79 active_dnn_blob: Option<(*const u8, i32)>,
80 _marker: PhantomData<&'a mut OpusEncoder>,
81}
82
83unsafe impl Send for EncoderRef<'_> {}
84
85impl Encoder {
86 fn from_raw(
87 ptr: NonNull<OpusEncoder>,
88 sample_rate: SampleRate,
89 channels: Channels,
90 ownership: Ownership,
91 ) -> Self {
92 Self {
93 raw: RawHandle::new(ptr, ownership, opus_encoder_destroy),
94 sample_rate,
95 channels,
96 #[cfg(feature = "dred")]
97 dnn_blobs: Vec::new(),
98 #[cfg(feature = "dred")]
99 active_dnn_blob: None,
100 }
101 }
102
103 pub fn size(channels: Channels) -> Result<usize> {
109 let raw = unsafe { opus_encoder_get_size(channels.as_i32()) };
110 if raw <= 0 {
111 return Err(Error::BadArg);
112 }
113 usize::try_from(raw).map_err(|_| Error::InternalError)
114 }
115
116 pub unsafe fn init_in_place(
125 ptr: *mut OpusEncoder,
126 sample_rate: SampleRate,
127 channels: Channels,
128 application: Application,
129 ) -> Result<()> {
130 if ptr.is_null() {
131 return Err(Error::BadArg);
132 }
133 if !crate::opus_ptr_is_aligned(ptr.cast()) {
134 return Err(Error::BadArg);
135 }
136 let r = unsafe {
137 opus_encoder_init(
138 ptr,
139 sample_rate.as_i32(),
140 channels.as_i32(),
141 application as i32,
142 )
143 };
144 if r != 0 {
145 return Err(Error::from_code(r));
146 }
147 Ok(())
148 }
149
150 pub fn new(
155 sample_rate: SampleRate,
156 channels: Channels,
157 application: Application,
158 ) -> Result<Self> {
159 if !sample_rate.is_valid() {
161 return Err(Error::BadArg);
162 }
163
164 let mut error = 0i32;
165 let encoder = unsafe {
166 opus_encoder_create(
167 sample_rate.as_i32(),
168 channels.as_i32(),
169 application as i32,
170 std::ptr::addr_of_mut!(error),
171 )
172 };
173
174 if error != 0 {
175 return Err(Error::from_code(error));
176 }
177
178 let encoder = NonNull::new(encoder).ok_or(Error::AllocFail)?;
179
180 Ok(Self::from_raw(
181 encoder,
182 sample_rate,
183 channels,
184 Ownership::Owned,
185 ))
186 }
187
188 pub fn encode(&mut self, input: &[i16], output: &mut [u8]) -> Result<usize> {
194 if input.is_empty() {
196 return Err(Error::BadArg);
197 }
198
199 if !input.len().is_multiple_of(self.channels.as_usize()) {
201 return Err(Error::BadArg);
202 }
203
204 let frame_size = input.len() / self.channels.as_usize();
205 let frame_size = NonZeroUsize::new(frame_size).ok_or(Error::BadArg)?;
206 if frame_size.get() > max_frame_samples_for(self.sample_rate) {
208 return Err(Error::BadArg);
209 }
210
211 if output.is_empty() {
213 return Err(Error::BadArg);
214 }
215 if output.len() > i32::MAX as usize {
216 return Err(Error::BadArg);
217 }
218
219 let frame_size_i32 = i32::try_from(frame_size.get()).map_err(|_| Error::BadArg)?;
220 let out_len_i32 = i32::try_from(output.len()).map_err(|_| Error::BadArg)?;
221 let result = unsafe {
222 opus_encode(
223 self.raw.as_ptr(),
224 input.as_ptr(),
225 frame_size_i32,
226 output.as_mut_ptr(),
227 out_len_i32,
228 )
229 };
230
231 if result < 0 {
232 return Err(Error::from_code(result));
233 }
234
235 usize::try_from(result).map_err(|_| Error::InternalError)
236 }
237
238 pub fn encode_limited(
249 &mut self,
250 input: &[i16],
251 output: &mut [u8],
252 max_data_bytes: usize,
253 ) -> Result<usize> {
254 if input.is_empty() {
256 return Err(Error::BadArg);
257 }
258
259 if !input.len().is_multiple_of(self.channels.as_usize()) {
261 return Err(Error::BadArg);
262 }
263
264 let frame_size = input.len() / self.channels.as_usize();
265 let frame_size = NonZeroUsize::new(frame_size).ok_or(Error::BadArg)?;
266 if frame_size.get() > max_frame_samples_for(self.sample_rate) {
268 return Err(Error::BadArg);
269 }
270
271 if output.is_empty() {
273 return Err(Error::BadArg);
274 }
275 if output.len() > i32::MAX as usize {
276 return Err(Error::BadArg);
277 }
278 if max_data_bytes == 0 || max_data_bytes > output.len() {
280 return Err(Error::BadArg);
281 }
282
283 let frame_size_i32 = i32::try_from(frame_size.get()).map_err(|_| Error::BadArg)?;
284 let max_bytes_i32 = i32::try_from(max_data_bytes).map_err(|_| Error::BadArg)?;
285 let result = unsafe {
286 opus_encode(
287 self.raw.as_ptr(),
288 input.as_ptr(),
289 frame_size_i32,
290 output.as_mut_ptr(),
291 max_bytes_i32,
292 )
293 };
294
295 if result < 0 {
296 return Err(Error::from_code(result));
297 }
298
299 usize::try_from(result).map_err(|_| Error::InternalError)
300 }
301
302 pub fn encode_float(&mut self, input: &[f32], output: &mut [u8]) -> Result<usize> {
308 if input.is_empty() {
309 return Err(Error::BadArg);
310 }
311 if !input.len().is_multiple_of(self.channels.as_usize()) {
312 return Err(Error::BadArg);
313 }
314 let frame_size = input.len() / self.channels.as_usize();
315 let frame_size = NonZeroUsize::new(frame_size).ok_or(Error::BadArg)?;
316 if frame_size.get() > max_frame_samples_for(self.sample_rate) {
317 return Err(Error::BadArg);
318 }
319 if output.is_empty() || output.len() > i32::MAX as usize {
320 return Err(Error::BadArg);
321 }
322 let frame_i32 = i32::try_from(frame_size.get()).map_err(|_| Error::BadArg)?;
323 let out_len_i32 = i32::try_from(output.len()).map_err(|_| Error::BadArg)?;
324 let n = unsafe {
325 opus_encode_float(
326 self.raw.as_ptr(),
327 input.as_ptr(),
328 frame_i32,
329 output.as_mut_ptr(),
330 out_len_i32,
331 )
332 };
333 if n < 0 {
334 return Err(Error::from_code(n));
335 }
336 usize::try_from(n).map_err(|_| Error::InternalError)
337 }
338
339 pub fn set_inband_fec(&mut self, enabled: bool) -> Result<()> {
346 self.simple_ctl(OPUS_SET_INBAND_FEC_REQUEST as i32, i32::from(enabled))
347 }
348 pub fn inband_fec(&mut self) -> Result<bool> {
353 self.get_bool_ctl(OPUS_GET_INBAND_FEC_REQUEST as i32)
354 }
355
356 pub fn set_packet_loss_perc(&mut self, perc: i32) -> Result<()> {
362 if !(0..=100).contains(&perc) {
363 return Err(Error::BadArg);
364 }
365 self.simple_ctl(OPUS_SET_PACKET_LOSS_PERC_REQUEST as i32, perc)
366 }
367 pub fn packet_loss_perc(&mut self) -> Result<i32> {
372 self.get_int_ctl(OPUS_GET_PACKET_LOSS_PERC_REQUEST as i32)
373 }
374
375 pub fn set_dtx(&mut self, enabled: bool) -> Result<()> {
380 self.simple_ctl(OPUS_SET_DTX_REQUEST as i32, i32::from(enabled))
381 }
382 pub fn dtx(&mut self) -> Result<bool> {
387 self.get_bool_ctl(OPUS_GET_DTX_REQUEST as i32)
388 }
389 pub fn in_dtx(&mut self) -> Result<bool> {
394 self.get_bool_ctl(OPUS_GET_IN_DTX_REQUEST as i32)
395 }
396
397 pub fn set_vbr_constraint(&mut self, constrained: bool) -> Result<()> {
402 self.simple_ctl(
403 OPUS_SET_VBR_CONSTRAINT_REQUEST as i32,
404 i32::from(constrained),
405 )
406 }
407 pub fn vbr_constraint(&mut self) -> Result<bool> {
412 self.get_bool_ctl(OPUS_GET_VBR_CONSTRAINT_REQUEST as i32)
413 }
414
415 pub fn set_max_bandwidth(&mut self, bw: Bandwidth) -> Result<()> {
420 self.simple_ctl(OPUS_SET_MAX_BANDWIDTH_REQUEST as i32, bw as i32)
421 }
422 pub fn max_bandwidth(&mut self) -> Result<Bandwidth> {
427 self.get_bandwidth_ctl(OPUS_GET_MAX_BANDWIDTH_REQUEST as i32)
428 }
429
430 pub fn set_bandwidth(&mut self, bw: Bandwidth) -> Result<()> {
435 self.simple_ctl(OPUS_SET_BANDWIDTH_REQUEST as i32, bw as i32)
436 }
437 pub fn bandwidth(&mut self) -> Result<Bandwidth> {
442 self.get_bandwidth_ctl(OPUS_GET_BANDWIDTH_REQUEST as i32)
443 }
444
445 pub fn set_force_channels(&mut self, channels: Option<Channels>) -> Result<()> {
450 let val = match channels {
451 Some(Channels::Mono) => 1,
452 Some(Channels::Stereo) => 2,
453 None => crate::bindings::OPUS_AUTO,
454 };
455 self.simple_ctl(OPUS_SET_FORCE_CHANNELS_REQUEST as i32, val)
456 }
457 pub fn force_channels(&mut self) -> Result<Option<Channels>> {
462 let v = self.get_int_ctl(OPUS_GET_FORCE_CHANNELS_REQUEST as i32)?;
463 Ok(match v {
464 1 => Some(Channels::Mono),
465 2 => Some(Channels::Stereo),
466 _ => None,
467 })
468 }
469
470 pub fn set_signal(&mut self, signal: Signal) -> Result<()> {
475 self.simple_ctl(OPUS_SET_SIGNAL_REQUEST as i32, signal as i32)
476 }
477 pub fn signal(&mut self) -> Result<Signal> {
483 let v = self.get_int_ctl(OPUS_GET_SIGNAL_REQUEST as i32)?;
484 match v {
485 x if x == OPUS_AUTO => Ok(Signal::Auto),
486 x if x == crate::bindings::OPUS_SIGNAL_VOICE as i32 => Ok(Signal::Voice),
487 x if x == crate::bindings::OPUS_SIGNAL_MUSIC as i32 => Ok(Signal::Music),
488 _ => Err(Error::InternalError),
489 }
490 }
491
492 pub fn lookahead(&mut self) -> Result<i32> {
497 self.get_int_ctl(OPUS_GET_LOOKAHEAD_REQUEST as i32)
498 }
499 pub fn final_range(&mut self) -> Result<u32> {
504 let mut val: u32 = 0;
505 let r = unsafe {
506 opus_encoder_ctl(
507 self.raw.as_ptr(),
508 OPUS_GET_FINAL_RANGE_REQUEST as i32,
509 &mut val,
510 )
511 };
512 if r != 0 {
513 return Err(Error::from_code(r));
514 }
515 Ok(val)
516 }
517
518 pub fn set_lsb_depth(&mut self, bits: i32) -> Result<()> {
524 if !(8..=24).contains(&bits) {
525 return Err(Error::BadArg);
526 }
527 self.simple_ctl(OPUS_SET_LSB_DEPTH_REQUEST as i32, bits)
528 }
529 pub fn lsb_depth(&mut self) -> Result<i32> {
534 self.get_int_ctl(OPUS_GET_LSB_DEPTH_REQUEST as i32)
535 }
536
537 pub fn set_expert_frame_duration(&mut self, dur: ExpertFrameDuration) -> Result<()> {
542 self.simple_ctl(OPUS_SET_EXPERT_FRAME_DURATION_REQUEST as i32, dur as i32)
543 }
544 pub fn expert_frame_duration(&mut self) -> Result<ExpertFrameDuration> {
550 let v = self.get_int_ctl(OPUS_GET_EXPERT_FRAME_DURATION_REQUEST as i32)?;
551 let vu = u32::try_from(v).map_err(|_| Error::InternalError)?;
552 match vu {
553 x if x == crate::bindings::OPUS_FRAMESIZE_ARG => Ok(ExpertFrameDuration::Auto),
554 x if x == crate::bindings::OPUS_FRAMESIZE_2_5_MS => Ok(ExpertFrameDuration::Ms2_5),
555 x if x == crate::bindings::OPUS_FRAMESIZE_5_MS => Ok(ExpertFrameDuration::Ms5),
556 x if x == crate::bindings::OPUS_FRAMESIZE_10_MS => Ok(ExpertFrameDuration::Ms10),
557 x if x == crate::bindings::OPUS_FRAMESIZE_20_MS => Ok(ExpertFrameDuration::Ms20),
558 x if x == crate::bindings::OPUS_FRAMESIZE_40_MS => Ok(ExpertFrameDuration::Ms40),
559 x if x == crate::bindings::OPUS_FRAMESIZE_60_MS => Ok(ExpertFrameDuration::Ms60),
560 x if x == crate::bindings::OPUS_FRAMESIZE_80_MS => Ok(ExpertFrameDuration::Ms80),
561 x if x == crate::bindings::OPUS_FRAMESIZE_100_MS => Ok(ExpertFrameDuration::Ms100),
562 x if x == crate::bindings::OPUS_FRAMESIZE_120_MS => Ok(ExpertFrameDuration::Ms120),
563 _ => Err(Error::InternalError),
564 }
565 }
566
567 pub fn set_prediction_disabled(&mut self, disabled: bool) -> Result<()> {
572 self.simple_ctl(
573 OPUS_SET_PREDICTION_DISABLED_REQUEST as i32,
574 i32::from(disabled),
575 )
576 }
577 pub fn prediction_disabled(&mut self) -> Result<bool> {
582 self.get_bool_ctl(OPUS_GET_PREDICTION_DISABLED_REQUEST as i32)
583 }
584
585 pub fn set_phase_inversion_disabled(&mut self, disabled: bool) -> Result<()> {
590 self.simple_ctl(
591 OPUS_SET_PHASE_INVERSION_DISABLED_REQUEST as i32,
592 i32::from(disabled),
593 )
594 }
595 pub fn phase_inversion_disabled(&mut self) -> Result<bool> {
600 self.get_bool_ctl(OPUS_GET_PHASE_INVERSION_DISABLED_REQUEST as i32)
601 }
602
603 #[cfg(feature = "dred")]
604 pub fn set_dred_duration(&mut self, frames_10ms: i32) -> Result<()> {
612 self.simple_ctl(OPUS_SET_DRED_DURATION_REQUEST as i32, frames_10ms)
613 }
614
615 #[cfg(feature = "dred")]
616 pub fn dred_duration(&mut self) -> Result<i32> {
621 self.get_int_ctl(OPUS_GET_DRED_DURATION_REQUEST as i32)
622 }
623
624 #[cfg(feature = "dred")]
625 pub unsafe fn set_dnn_blob(&mut self, ptr: *const u8, len: i32) -> Result<()> {
637 let blob_index = unsafe { self.retain_dnn_blob_copy(ptr, len)? };
638 let (owned_ptr, owned_len) = self.dnn_blobs[blob_index].parts();
639 if let Err(error) = unsafe { self.apply_dnn_blob(owned_ptr, owned_len) } {
640 if error == Error::Unimplemented {
641 let removed = self.dnn_blobs.pop();
644 debug_assert!(removed.is_some());
645 }
646 return Err(error);
647 }
648 self.active_dnn_blob = Some(blob_index);
649 Ok(())
650 }
651
652 #[cfg(feature = "dred")]
653 unsafe fn retain_dnn_blob_copy(&mut self, ptr: *const u8, len: i32) -> Result<usize> {
654 if ptr.is_null() || len <= 0 {
655 return Err(Error::BadArg);
656 }
657 let byte_len = usize::try_from(len).map_err(|_| Error::BadArg)?;
658 let word_len = byte_len.div_ceil(std::mem::size_of::<u32>());
659 let mut blob = vec![0u32; word_len].into_boxed_slice();
660 unsafe {
661 std::ptr::copy_nonoverlapping(ptr, blob.as_mut_ptr().cast::<u8>(), byte_len);
662 }
663 let index = self.dnn_blobs.len();
664 self.dnn_blobs.push(RetainedDnnBlob { data: blob, len });
665 Ok(index)
666 }
667
668 #[cfg(feature = "dred")]
669 unsafe fn apply_dnn_blob(&mut self, ptr: *const u8, len: i32) -> Result<()> {
670 let r = unsafe {
671 opus_encoder_ctl(
672 self.raw.as_ptr(),
673 OPUS_SET_DNN_BLOB_REQUEST as i32,
674 ptr,
675 len,
676 )
677 };
678 if r != 0 {
679 return Err(Error::from_code(r));
680 }
681 Ok(())
682 }
683
684 #[cfg(feature = "dred")]
685 fn reload_active_dnn_blob(&mut self) -> Result<()> {
686 let Some(index) = self.active_dnn_blob else {
687 return Ok(());
688 };
689 let (ptr, len) = self.dnn_blobs[index].parts();
690 unsafe { self.apply_dnn_blob(ptr, len) }
691 }
692
693 fn simple_ctl(&mut self, req: i32, val: i32) -> Result<()> {
695 let r = unsafe { opus_encoder_ctl(self.raw.as_ptr(), req, val) };
696 if r != 0 {
697 return Err(Error::from_code(r));
698 }
699 Ok(())
700 }
701 fn get_bool_ctl(&mut self, req: i32) -> Result<bool> {
702 Ok(self.get_int_ctl(req)? != 0)
703 }
704 fn get_int_ctl(&mut self, req: i32) -> Result<i32> {
705 let mut v: i32 = 0;
706 let r = unsafe { opus_encoder_ctl(self.raw.as_ptr(), req, &mut v) };
707 if r != 0 {
708 return Err(Error::from_code(r));
709 }
710 Ok(v)
711 }
712 fn get_bandwidth_ctl(&mut self, req: i32) -> Result<Bandwidth> {
713 let v = self.get_int_ctl(req)?;
714 let vu = u32::try_from(v).map_err(|_| Error::InternalError)?;
715 match vu {
716 x if x == crate::bindings::OPUS_BANDWIDTH_NARROWBAND => Ok(Bandwidth::Narrowband),
717 x if x == crate::bindings::OPUS_BANDWIDTH_MEDIUMBAND => Ok(Bandwidth::Mediumband),
718 x if x == crate::bindings::OPUS_BANDWIDTH_WIDEBAND => Ok(Bandwidth::Wideband),
719 x if x == crate::bindings::OPUS_BANDWIDTH_SUPERWIDEBAND => Ok(Bandwidth::SuperWideband),
720 x if x == OPUS_BANDWIDTH_FULLBAND => Ok(Bandwidth::Fullband),
721 _ => Err(Error::InternalError),
722 }
723 }
724
725 pub fn set_bitrate(&mut self, bitrate: Bitrate) -> Result<()> {
730 let result = unsafe {
731 opus_encoder_ctl(
732 self.raw.as_ptr(),
733 OPUS_SET_BITRATE_REQUEST as i32,
734 bitrate.value(),
735 )
736 };
737
738 if result != 0 {
739 return Err(Error::from_code(result));
740 }
741
742 Ok(())
743 }
744
745 pub fn bitrate(&mut self) -> Result<Bitrate> {
750 let mut bitrate = 0i32;
751 let result = unsafe {
752 opus_encoder_ctl(
753 self.raw.as_ptr(),
754 OPUS_GET_BITRATE_REQUEST as i32,
755 &mut bitrate,
756 )
757 };
758
759 if result != 0 {
760 return Err(Error::from_code(result));
761 }
762
763 match bitrate {
764 OPUS_AUTO => Ok(Bitrate::Auto),
765 OPUS_BITRATE_MAX => Ok(Bitrate::Max),
766 bps => Ok(Bitrate::Custom(bps)),
767 }
768 }
769
770 pub fn set_complexity(&mut self, complexity: Complexity) -> Result<()> {
775 let result = unsafe {
776 opus_encoder_ctl(
777 self.raw.as_ptr(),
778 OPUS_SET_COMPLEXITY_REQUEST as i32,
779 complexity.value() as i32,
780 )
781 };
782
783 if result != 0 {
784 return Err(Error::from_code(result));
785 }
786
787 Ok(())
788 }
789
790 pub fn complexity(&mut self) -> Result<Complexity> {
795 let mut complexity = 0i32;
796 let result = unsafe {
797 opus_encoder_ctl(
798 self.raw.as_ptr(),
799 OPUS_GET_COMPLEXITY_REQUEST as i32,
800 &mut complexity,
801 )
802 };
803
804 if result != 0 {
805 return Err(Error::from_code(result));
806 }
807
808 let complexity = u32::try_from(complexity).map_err(|_| Error::InternalError)?;
809 Complexity::try_new(complexity).ok_or(Error::InternalError)
810 }
811
812 pub fn set_vbr(&mut self, enabled: bool) -> Result<()> {
817 let vbr = i32::from(enabled);
818 let result =
819 unsafe { opus_encoder_ctl(self.raw.as_ptr(), OPUS_SET_VBR_REQUEST as i32, vbr) };
820
821 if result != 0 {
822 return Err(Error::from_code(result));
823 }
824
825 Ok(())
826 }
827
828 pub fn vbr(&mut self) -> Result<bool> {
833 let mut vbr = 0i32;
834 let result =
835 unsafe { opus_encoder_ctl(self.raw.as_ptr(), OPUS_GET_VBR_REQUEST as i32, &mut vbr) };
836
837 if result != 0 {
838 return Err(Error::from_code(result));
839 }
840
841 Ok(vbr != 0)
842 }
843
844 #[must_use]
846 pub const fn sample_rate(&self) -> SampleRate {
847 self.sample_rate
848 }
849
850 #[must_use]
852 pub const fn channels(&self) -> Channels {
853 self.channels
854 }
855
856 pub fn reset(&mut self) -> Result<()> {
861 let r = unsafe {
862 opus_encoder_ctl(self.raw.as_ptr(), crate::bindings::OPUS_RESET_STATE as i32)
863 };
864 if r != 0 {
865 return Err(Error::from_code(r));
866 }
867 #[cfg(feature = "dred")]
868 self.reload_active_dnn_blob()?;
869 Ok(())
870 }
871}
872
873impl<'a> EncoderRef<'a> {
874 #[must_use]
893 pub unsafe fn from_raw(
894 ptr: *mut OpusEncoder,
895 sample_rate: SampleRate,
896 channels: Channels,
897 ) -> Self {
898 let encoder = Encoder::from_raw(
899 crate::checked_non_null(ptr, "EncoderRef::from_raw"),
900 sample_rate,
901 channels,
902 Ownership::Borrowed,
903 );
904 Self {
905 inner: encoder,
906 #[cfg(feature = "dred")]
907 active_dnn_blob: None,
908 _marker: PhantomData,
909 }
910 }
911
912 pub fn init_in(
917 buf: &'a mut AlignedBuffer,
918 sample_rate: SampleRate,
919 channels: Channels,
920 application: Application,
921 ) -> Result<Self> {
922 let required = Encoder::size(channels)?;
923 if buf.capacity_bytes() < required {
924 return Err(Error::BadArg);
925 }
926 let ptr = buf.as_mut_ptr::<OpusEncoder>();
927 unsafe { Encoder::init_in_place(ptr, sample_rate, channels, application)? };
928 Ok(unsafe { Self::from_raw(ptr, sample_rate, channels) })
929 }
930
931 delegate_ref_mut_methods! {
932 fn encode(input: &[i16], output: &mut [u8]) -> Result<usize>;
933 fn encode_limited(input: &[i16], output: &mut [u8], max_data_bytes: usize) -> Result<usize>;
934 fn encode_float(input: &[f32], output: &mut [u8]) -> Result<usize>;
935 fn set_inband_fec(enabled: bool) -> Result<()>;
936 fn inband_fec() -> Result<bool>;
937 fn set_packet_loss_perc(perc: i32) -> Result<()>;
938 fn packet_loss_perc() -> Result<i32>;
939 fn set_dtx(enabled: bool) -> Result<()>;
940 fn dtx() -> Result<bool>;
941 fn in_dtx() -> Result<bool>;
942 fn set_vbr_constraint(constrained: bool) -> Result<()>;
943 fn vbr_constraint() -> Result<bool>;
944 fn set_max_bandwidth(bw: Bandwidth) -> Result<()>;
945 fn max_bandwidth() -> Result<Bandwidth>;
946 fn set_bandwidth(bw: Bandwidth) -> Result<()>;
947 fn bandwidth() -> Result<Bandwidth>;
948 fn set_force_channels(channels: Option<Channels>) -> Result<()>;
949 fn force_channels() -> Result<Option<Channels>>;
950 fn set_signal(signal: Signal) -> Result<()>;
951 fn signal() -> Result<Signal>;
952 fn lookahead() -> Result<i32>;
953 fn final_range() -> Result<u32>;
954 fn set_lsb_depth(bits: i32) -> Result<()>;
955 fn lsb_depth() -> Result<i32>;
956 fn set_expert_frame_duration(dur: ExpertFrameDuration) -> Result<()>;
957 fn expert_frame_duration() -> Result<ExpertFrameDuration>;
958 fn set_prediction_disabled(disabled: bool) -> Result<()>;
959 fn prediction_disabled() -> Result<bool>;
960 fn set_phase_inversion_disabled(disabled: bool) -> Result<()>;
961 fn phase_inversion_disabled() -> Result<bool>;
962 #[cfg(feature = "dred")]
963 fn set_dred_duration(frames_10ms: i32) -> Result<()>;
964 #[cfg(feature = "dred")]
965 fn dred_duration() -> Result<i32>;
966 fn set_bitrate(bitrate: Bitrate) -> Result<()>;
967 fn bitrate() -> Result<Bitrate>;
968 fn set_complexity(complexity: Complexity) -> Result<()>;
969 fn complexity() -> Result<Complexity>;
970 fn set_vbr(enabled: bool) -> Result<()>;
971 fn vbr() -> Result<bool>;
972 }
973
974 pub fn reset(&mut self) -> Result<()> {
979 self.inner.reset()?;
980 #[cfg(feature = "dred")]
981 if let Some((ptr, len)) = self.active_dnn_blob {
982 unsafe { self.inner.apply_dnn_blob(ptr, len)? };
983 }
984 Ok(())
985 }
986
987 #[cfg(feature = "dred")]
988 pub unsafe fn set_dnn_blob(&mut self, ptr: *const u8, len: i32) -> Result<()> {
1004 if ptr.is_null() || len <= 0 || !ptr.addr().is_multiple_of(std::mem::align_of::<u32>()) {
1005 return Err(Error::BadArg);
1006 }
1007 unsafe { self.inner.apply_dnn_blob(ptr, len)? };
1008 self.active_dnn_blob = Some((ptr, len));
1009 Ok(())
1010 }
1011}
1012
1013impl Deref for EncoderRef<'_> {
1014 type Target = Encoder;
1015
1016 fn deref(&self) -> &Self::Target {
1017 &self.inner
1018 }
1019}
1020
1021#[cfg(all(test, feature = "dred"))]
1022mod tests {
1023 use super::*;
1024
1025 #[test]
1026 fn dnn_blob_is_copied_into_retained_aligned_storage() {
1027 let mut encoder =
1028 Encoder::new(SampleRate::Hz48000, Channels::Mono, Application::Audio).unwrap();
1029 let source = [0u8, 1, 2, 3, 4];
1030 let unaligned = unsafe { source.as_ptr().add(1) };
1031
1032 let index = unsafe { encoder.retain_dnn_blob_copy(unaligned, 4) }.unwrap();
1033 let (retained, len) = encoder.dnn_blobs[index].parts();
1034
1035 assert_eq!(len, 4);
1036 assert_eq!((retained as usize) % std::mem::align_of::<u32>(), 0);
1037 assert_eq!(
1038 unsafe { std::slice::from_raw_parts(retained, 4) },
1039 &source[1..]
1040 );
1041 assert_eq!(encoder.dnn_blobs.len(), 1);
1042 }
1043}