opusic_c/
repacketizer.rs

1//! Opus packet manipulation
2use crate::{sys, mem, ErrorCode};
3
4use core::marker;
5use core::convert::TryInto;
6
7///Pads a given Opus packet to a larger size (possibly changing the TOC sequence).
8///
9///Returns `ErrorCode::BadArg` if size cannot fit `u32` or new size is less than `input.len()`
10pub fn pad_packet(input: &mut [u8], new_len: usize) -> Result<(), ErrorCode> {
11    let len = match input.len().try_into() {
12        Ok(data_len) => data_len,
13        Err(_) => return Err(ErrorCode::bad_arg()),
14    };
15    let new_len = match new_len.try_into() {
16        Ok(data_len) => data_len,
17        Err(_) => return Err(ErrorCode::bad_arg()),
18    };
19    let data = input.as_mut_ptr();
20
21    let result = unsafe {
22        sys::opus_packet_pad(data, len, new_len)
23    };
24
25    map_sys_error!(result => ())
26}
27
28///Remove all padding from a given Opus packet and rewrite the TOC sequence to minimize space usage.
29///
30///Returns `ErrorCode::BadArg` if size cannot fit `u32`
31///
32///On success returns new size of the `input` data
33pub fn unpad_packet(input: &mut [u8]) -> Result<usize, ErrorCode> {
34    let len = match input.len().try_into() {
35        Ok(data_len) => data_len,
36        Err(_) => return Err(ErrorCode::bad_arg()),
37    };
38    let data = input.as_mut_ptr();
39
40    let result = unsafe {
41        sys::opus_packet_unpad(data, len)
42    };
43
44    map_sys_error!(result => result as usize)
45}
46
47#[repr(transparent)]
48///Repacketizer can be used to merge multiple Opus packets into a single packet or alternatively to split Opus packets that have previously been merged
49pub struct Repacketizer {
50    inner: mem::Unique<sys::OpusRepacketizer>
51}
52
53impl Repacketizer {
54    ///Creates new instance, allocating necessary memory
55    pub fn new() -> Result<Self, ErrorCode> {
56        let size = unsafe {
57            sys::opus_repacketizer_get_size()
58        };
59
60        if size == 0 {
61            return Err(ErrorCode::Internal);
62        }
63
64        let mut this = match mem::Unique::new(size as _) {
65            Some(inner) => Self {
66                inner,
67            },
68            None => return Err(ErrorCode::AllocFail)
69        };
70
71        this.reset();
72
73        Ok(this)
74    }
75
76    #[inline(always)]
77    ///Re-initializes this Repacketizer state, resetting ongoing progress, if any.
78    pub fn reset(&mut self) {
79        unsafe {
80            sys::opus_repacketizer_init(self.inner.as_mut());
81        }
82    }
83
84    #[inline(always)]
85    ///Starts new repacketizer process, resetting `self` in the process.
86    pub fn start<'a, 'buf>(&'a mut self) -> OngoingRepacketizer<'a, 'buf> {
87        OngoingRepacketizer {
88            inner: self,
89            _buf_lifetime: marker::PhantomData
90        }
91    }
92
93    ///Takes all `bufs` combining it into single packet
94    ///
95    ///This is shortcut to using [start](struct.Repacketizer.html#method.start).
96    pub fn combine_all(&mut self, bufs: &[&[u8]], out: &mut [mem::MaybeUninit<u8>]) -> Result<usize, ErrorCode> {
97        let mut state = self.start();
98        for buf in bufs {
99            state.add_packet(buf)?;
100        }
101        state.create_full_packet(out)
102    }
103}
104
105unsafe impl Send for Repacketizer {}
106
107#[repr(transparent)]
108///Ongoing repacketizer process
109///
110///Lifetime parameters:
111///
112///- `a` - Depends on original instance of [Repacketizer](struct.Repacketizer.html)
113///- `buf` - Lifetime of the last buffer added to the state. Note that all previous lifetimes must fit it too
114///
115///Dropping state will reset [Repacketizer](struct.Repacketizer.html)
116pub struct OngoingRepacketizer<'a, 'buf> {
117    inner: &'a mut Repacketizer,
118    _buf_lifetime: marker::PhantomData<&'buf [u8]>
119}
120
121impl<'a, 'buf> OngoingRepacketizer<'a, 'buf> {
122    #[inline(always)]
123    fn as_state(&self) -> &mem::Unique<sys::OpusRepacketizer> {
124        &self.inner.inner
125    }
126
127    #[inline(always)]
128    fn as_state_mut(&mut self) -> &mut mem::Unique<sys::OpusRepacketizer> {
129        &mut self.inner.inner
130    }
131
132    #[inline(always)]
133    ///Re-initializes this Repacketizer state, resetting ongoing progress, if any.
134    pub fn reset(&mut self) {
135        self.inner.reset();
136    }
137
138    #[inline(always)]
139    ///Return the total number of frames contained in packet data submitted to the repacketizer state
140    ///since the last time `reset` has been called
141    pub fn get_nb_frames(&self) -> u32 {
142        unsafe {
143            sys::opus_repacketizer_get_nb_frames(self.as_state().as_pseudo_mut()) as _
144        }
145    }
146
147    ///Add a packet to the current repacketizer state.
148    ///
149    ///This packet must match the configuration of any packets already submitted for
150    ///repacketization since the last call to `reset()`. This means that it must
151    ///have the same coding mode, audio bandwidth, frame size, and channel count. This can be
152    ///checked in advance by examining the top 6 bits of the first byte of the packet, and ensuring
153    ///they match the top 6 bits of the first byte of any previously submitted packet. The total
154    ///duration of audio in the repacketizer state also must not exceed 120 ms, the maximum
155    ///duration of a single packet, after adding this packet.
156    ///
157    ///In order to add a packet with a different configuration or to add more audio beyond 120 ms,
158    ///you must clear the repacketizer state by calling `reset()`. If a packet is
159    ///too large to add to the current repacketizer state, no part of it is added, even if it
160    ///contains multiple frames, some of which might fit. If you wish to be able to add parts of
161    ///such packets, you should first use another repacketizer to split the packet into pieces and
162    ///add them individually.
163    pub fn add_packet(&mut self, input: &'buf [u8]) -> Result<(), ErrorCode> {
164        let len = match input.len().try_into() {
165            Ok(data_len) => data_len,
166            Err(_) => return Err(ErrorCode::bad_arg()),
167        };
168        let data = input.as_ptr();
169
170        let result = unsafe {
171            sys::opus_repacketizer_cat(self.as_state_mut().as_mut(), data, len)
172        };
173
174        map_sys_error!(result => ())
175    }
176
177    #[inline(always)]
178    ///Adds packet to the ongoing state, returning `Self` with modified lifetime
179    ///
180    ///Refers to [add_packet](struct.OngoingRepacketizer.html#method.add_packet) for details
181    pub fn with_packet<'new_buf>(self, input: &'new_buf [u8]) -> Result<OngoingRepacketizer<'a, 'new_buf>, ErrorCode> where 'buf: 'new_buf {
182        let mut new = self;
183        new.add_packet(input)?;
184        Ok(new)
185    }
186
187    ///Construct a new packet from data previously submitted to the repacketizer state
188    ///
189    ///## Parameters
190    ///
191    ///- `range` - Should contain range of frames to encode in range `0..=get_nb_frames()`
192    ///- `out` - Output buffer to store new packet. Max required size can be calculated as `1277*(range.1 - range.0)`. Optimal required size is `(range.1 - range.0) + [packet1 length]...`
193    ///
194    ///## Return value
195    ///
196    ///Number of bytes written in `out` buffer
197    pub fn create_packet(&self, range: (u32, u32), out: &mut [mem::MaybeUninit<u8>]) -> Result<usize, ErrorCode> {
198        let begin = match range.0.try_into() {
199            Ok(begin) => begin,
200            Err(_) => return Err(ErrorCode::bad_arg()),
201        };
202        let end = match range.1.try_into() {
203            Ok(end) => end,
204            Err(_) => return Err(ErrorCode::bad_arg()),
205        };
206
207        let out_len = match out.len().try_into() {
208            Ok(out_len) => out_len,
209            Err(_) => return Err(ErrorCode::bad_arg()),
210        };
211
212        let result = unsafe {
213            sys::opus_repacketizer_out_range(self.as_state().as_pseudo_mut(), begin, end, out.as_mut_ptr() as _, out_len)
214        };
215
216        map_sys_error!(result => result as _)
217    }
218
219    #[inline(always)]
220    ///Construct a new packet from data previously submitted to the repacketizer state using all frames available
221    ///
222    ///This is the same as calling `create_packet((0, nb_frames), ...)`
223    pub fn create_full_packet(&self, out: &mut [mem::MaybeUninit<u8>]) -> Result<usize, ErrorCode> {
224        let out_len = match out.len().try_into() {
225            Ok(out_len) => out_len,
226            Err(_) => return Err(ErrorCode::bad_arg()),
227        };
228
229        let result = unsafe {
230            sys::opus_repacketizer_out(self.as_state().as_pseudo_mut(), out.as_mut_ptr() as _, out_len)
231        };
232
233        map_sys_error!(result => result as _)
234    }
235}
236
237impl<'a, 'buf> Drop for OngoingRepacketizer<'a, 'buf> {
238    #[inline(always)]
239    fn drop(&mut self) {
240        self.inner.reset();
241    }
242}