opus_codec/
repacketizer.rs

1//! Safe wrapper for `OpusRepacketizer` utilities
2
3use crate::bindings::{
4    OpusRepacketizer, opus_repacketizer_cat, opus_repacketizer_create, opus_repacketizer_destroy,
5    opus_repacketizer_get_nb_frames, opus_repacketizer_init, opus_repacketizer_out,
6    opus_repacketizer_out_range,
7};
8use crate::error::{Error, Result};
9
10/// Repackages Opus frames into packets.
11pub struct Repacketizer {
12    rp: *mut OpusRepacketizer,
13}
14
15unsafe impl Send for Repacketizer {}
16unsafe impl Sync for Repacketizer {}
17
18impl Repacketizer {
19    /// Create a new repacketizer.
20    ///
21    /// # Errors
22    /// Returns `AllocFail` if allocation fails.
23    pub fn new() -> Result<Self> {
24        let rp = unsafe { opus_repacketizer_create() };
25        if rp.is_null() {
26            return Err(Error::AllocFail);
27        }
28        Ok(Self { rp })
29    }
30
31    /// Reset internal state.
32    pub fn reset(&mut self) {
33        unsafe { opus_repacketizer_init(self.rp) };
34    }
35
36    /// Add a packet to the current state.
37    ///
38    /// # Errors
39    /// Returns an error if the packet is invalid for the current state.
40    pub fn push(&mut self, packet: &[u8]) -> Result<()> {
41        if packet.is_empty() {
42            return Err(Error::BadArg);
43        }
44        let len_i32 = i32::try_from(packet.len()).map_err(|_| Error::BadArg)?;
45        let r = unsafe { opus_repacketizer_cat(self.rp, packet.as_ptr(), len_i32) };
46        if r != 0 {
47            return Err(Error::from_code(r));
48        }
49        Ok(())
50    }
51
52    /// Number of frames currently queued.
53    #[must_use]
54    pub fn frames(&mut self) -> i32 {
55        unsafe { opus_repacketizer_get_nb_frames(self.rp) }
56    }
57
58    /// Emit a packet containing frames in range [begin, end).
59    ///
60    /// # Errors
61    /// Returns an error if range is invalid or output buffer is too small.
62    pub fn out_range(&mut self, begin: i32, end: i32, out: &mut [u8]) -> Result<usize> {
63        if out.is_empty() {
64            return Err(Error::BadArg);
65        }
66        if begin < 0 || end <= begin {
67            return Err(Error::BadArg);
68        }
69        let out_len_i32 = i32::try_from(out.len()).map_err(|_| Error::BadArg)?;
70        let n = unsafe {
71            opus_repacketizer_out_range(self.rp, begin, end, out.as_mut_ptr(), out_len_i32)
72        };
73        if n < 0 {
74            return Err(Error::from_code(n));
75        }
76        usize::try_from(n).map_err(|_| Error::InternalError)
77    }
78
79    /// Emit a packet with all queued frames.
80    ///
81    /// # Errors
82    /// Returns an error if the output buffer is too small.
83    pub fn out(&mut self, out: &mut [u8]) -> Result<usize> {
84        if out.is_empty() {
85            return Err(Error::BadArg);
86        }
87        let out_len_i32 = i32::try_from(out.len()).map_err(|_| Error::BadArg)?;
88        let n = unsafe { opus_repacketizer_out(self.rp, out.as_mut_ptr(), out_len_i32) };
89        if n < 0 {
90            return Err(Error::from_code(n));
91        }
92        usize::try_from(n).map_err(|_| Error::InternalError)
93    }
94}
95
96impl Drop for Repacketizer {
97    fn drop(&mut self) {
98        unsafe { opus_repacketizer_destroy(self.rp) };
99    }
100}