1use crate::bindings::{
4 OpusRepacketizer, opus_repacketizer_cat, opus_repacketizer_create, opus_repacketizer_destroy,
5 opus_repacketizer_get_nb_frames, opus_repacketizer_get_size, opus_repacketizer_init,
6 opus_repacketizer_out, opus_repacketizer_out_range,
7};
8use crate::error::{Error, Result};
9#[cfg(opus_codec_rust_packet_ops)]
10use crate::packet;
11use crate::{AlignedBuffer, Ownership, RawHandle};
12use std::marker::PhantomData;
13use std::ops::Deref;
14use std::ptr::NonNull;
15
16pub struct Repacketizer {
18 rp: RawHandle<OpusRepacketizer>,
19 packets: Vec<RetainedPacket>,
20}
21
22struct RetainedPacket {
23 data: Vec<u8>,
24 #[cfg(opus_codec_rust_packet_ops)]
25 layout: Result<packet::PacketRepacketizerLayout>,
26}
27
28unsafe impl Send for Repacketizer {}
29
30pub struct RepacketizerRef<'a> {
41 inner: Repacketizer,
42 _marker: PhantomData<&'a mut OpusRepacketizer>,
43}
44
45unsafe impl Send for RepacketizerRef<'_> {}
46
47impl Repacketizer {
48 fn from_raw(ptr: NonNull<OpusRepacketizer>, ownership: Ownership) -> Self {
49 Self {
50 rp: RawHandle::new(ptr, ownership, opus_repacketizer_destroy),
51 packets: Vec::new(),
52 }
53 }
54
55 pub fn new() -> Result<Self> {
60 let rp = unsafe { opus_repacketizer_create() };
61 let rp = NonNull::new(rp).ok_or(Error::AllocFail)?;
62 Ok(Self::from_raw(rp, Ownership::Owned))
63 }
64
65 pub fn reset(&mut self) {
67 unsafe { opus_repacketizer_init(self.rp.as_ptr()) };
68 self.packets.clear();
69 }
70
71 pub fn push(&mut self, packet: &[u8]) -> Result<()> {
78 if packet.is_empty() || i32::try_from(packet.len()).is_err() {
79 return Err(Error::BadArg);
80 }
81 self.push_owned(packet.to_vec())
82 }
83
84 pub fn push_owned(&mut self, packet: Vec<u8>) -> Result<()> {
91 if packet.is_empty() {
92 return Err(Error::BadArg);
93 }
94 let len_i32 = i32::try_from(packet.len()).map_err(|_| Error::BadArg)?;
95 #[cfg(opus_codec_rust_packet_ops)]
96 let layout = packet::packet_repacketizer_layout(&packet);
97 let r = unsafe { opus_repacketizer_cat(self.rp.as_ptr(), packet.as_ptr(), len_i32) };
98 if r != 0 {
99 return Err(Error::from_code(r));
100 }
101 self.packets.push(RetainedPacket {
103 data: packet,
104 #[cfg(opus_codec_rust_packet_ops)]
105 layout,
106 });
107 Ok(())
108 }
109
110 #[must_use]
112 pub fn frame_count(&self) -> i32 {
113 unsafe { opus_repacketizer_get_nb_frames(self.rp.as_ptr()) }
114 }
115
116 #[must_use]
118 pub fn len(&self) -> usize {
119 let frames = self.frame_count();
120 debug_assert!(
121 frames >= 0,
122 "repacketizer frame count should be non-negative"
123 );
124 usize::try_from(frames).unwrap_or(0)
125 }
126
127 #[must_use]
129 pub fn is_empty(&self) -> bool {
130 self.len() == 0
131 }
132
133 pub fn emit_range(&mut self, begin: i32, end: i32, out: &mut [u8]) -> Result<usize> {
139 if out.is_empty() {
140 return Err(Error::BadArg);
141 }
142 if begin < 0 || end <= begin {
143 return Err(Error::BadArg);
144 }
145 #[cfg(opus_codec_rust_packet_ops)]
146 let begin_index = usize::try_from(begin).map_err(|_| Error::BadArg)?;
147 #[cfg(opus_codec_rust_packet_ops)]
148 let end_index = usize::try_from(end).map_err(|_| Error::BadArg)?;
149 #[cfg(not(opus_codec_rust_packet_ops))]
150 {
151 self.emit_range_via_c(begin, end, out)
152 }
153 #[cfg(opus_codec_rust_packet_ops)]
154 {
155 let mut frames = [&[][..]; packet::MAX_FRAMES_PER_PACKET];
156 let mut paddings = [packet::PacketPadding::EMPTY; packet::MAX_FRAMES_PER_PACKET];
157 if let Some((toc, frame_count)) =
158 self.repacketizer_inputs(&mut frames, &mut paddings)?
159 {
160 if end_index > frame_count {
161 return Err(Error::BadArg);
162 }
163 return packet::repacketize_frames_range(
164 toc,
165 &frames[..frame_count],
166 &paddings[..frame_count],
167 begin_index,
168 end_index,
169 out,
170 );
171 }
172 self.emit_range_via_c(begin, end, out)
173 }
174 }
175
176 pub fn emit(&mut self, out: &mut [u8]) -> Result<usize> {
182 if out.is_empty() {
183 return Err(Error::BadArg);
184 }
185 #[cfg(not(opus_codec_rust_packet_ops))]
186 {
187 self.emit_via_c(out)
188 }
189 #[cfg(opus_codec_rust_packet_ops)]
190 {
191 let mut frames = [&[][..]; packet::MAX_FRAMES_PER_PACKET];
192 let mut paddings = [packet::PacketPadding::EMPTY; packet::MAX_FRAMES_PER_PACKET];
193 if let Some((toc, frame_count)) =
194 self.repacketizer_inputs(&mut frames, &mut paddings)?
195 {
196 return packet::repacketize_frames(
197 toc,
198 &frames[..frame_count],
199 &paddings[..frame_count],
200 out,
201 );
202 }
203 self.emit_via_c(out)
204 }
205 }
206
207 pub fn size() -> Result<usize> {
212 let raw = unsafe { opus_repacketizer_get_size() };
213 if raw <= 0 {
214 return Err(Error::InternalError);
215 }
216 usize::try_from(raw).map_err(|_| Error::InternalError)
217 }
218
219 pub unsafe fn init_in_place(ptr: *mut OpusRepacketizer) -> Result<()> {
228 if ptr.is_null() {
229 return Err(Error::BadArg);
230 }
231 if !crate::opus_ptr_is_aligned(ptr.cast()) {
232 return Err(Error::BadArg);
233 }
234 unsafe { opus_repacketizer_init(ptr) };
235 Ok(())
236 }
237
238 #[cfg(opus_codec_rust_packet_ops)]
239 fn repacketizer_inputs<'a>(
240 &'a self,
241 frames: &mut [&'a [u8]; packet::MAX_FRAMES_PER_PACKET],
242 paddings: &mut [packet::PacketPadding<'a>; packet::MAX_FRAMES_PER_PACKET],
243 ) -> Result<Option<(u8, usize)>> {
244 let c_frame_count = self.len();
245 if self.packets.is_empty() {
246 return if c_frame_count == 0 {
247 Err(Error::BadArg)
248 } else {
249 Ok(None)
250 };
251 }
252
253 let mut toc = None;
254 let mut frame_count = 0usize;
255 for packet in &self.packets {
256 let layout = match &packet.layout {
257 Ok(layout) => layout,
258 Err(Error::InvalidPacket) => return Ok(None),
262 Err(err) => return Err(err.clone()),
263 };
264 toc.get_or_insert(layout.toc);
265 let packet_frame_count = layout.frames().len();
266 if frame_count + packet_frame_count > packet::MAX_FRAMES_PER_PACKET {
267 return Ok(None);
268 }
269 for (packet_frame, frame) in layout.frames().iter().enumerate() {
270 frames[frame_count] = frame.slice(&packet.data)?;
271 paddings[frame_count] = if packet_frame == 0 {
272 layout.packet_padding(&packet.data)
273 } else {
274 packet::PacketPadding::EMPTY
275 };
276 frame_count += 1;
277 }
278 }
279
280 if frame_count != c_frame_count {
281 return Ok(None);
282 }
283
284 let toc = toc.ok_or(Error::BadArg)?;
285 Ok(Some((toc, frame_count)))
286 }
287
288 fn emit_range_via_c(&self, begin: i32, end: i32, out: &mut [u8]) -> Result<usize> {
289 if out.is_empty() {
290 return Err(Error::BadArg);
291 }
292 let out_len_i32 = i32::try_from(out.len()).map_err(|_| Error::BadArg)?;
293 let n = unsafe {
294 opus_repacketizer_out_range(self.rp.as_ptr(), begin, end, out.as_mut_ptr(), out_len_i32)
295 };
296 if n < 0 {
297 return Err(Error::from_code(n));
298 }
299 usize::try_from(n).map_err(|_| Error::InternalError)
300 }
301
302 fn emit_via_c(&self, out: &mut [u8]) -> Result<usize> {
303 if out.is_empty() {
304 return Err(Error::BadArg);
305 }
306 let out_len_i32 = i32::try_from(out.len()).map_err(|_| Error::BadArg)?;
307 let n = unsafe { opus_repacketizer_out(self.rp.as_ptr(), out.as_mut_ptr(), out_len_i32) };
308 if n < 0 {
309 return Err(Error::from_code(n));
310 }
311 usize::try_from(n).map_err(|_| Error::InternalError)
312 }
313}
314
315impl<'a> RepacketizerRef<'a> {
316 #[must_use]
333 pub unsafe fn from_raw(ptr: *mut OpusRepacketizer) -> Self {
334 let repacketizer = Repacketizer::from_raw(
335 crate::checked_non_null(ptr, "RepacketizerRef::from_raw"),
336 Ownership::Borrowed,
337 );
338 Self {
339 inner: repacketizer,
340 _marker: PhantomData,
341 }
342 }
343
344 pub fn init_in(buf: &'a mut AlignedBuffer) -> Result<Self> {
349 let required = Repacketizer::size()?;
350 if buf.capacity_bytes() < required {
351 return Err(Error::BadArg);
352 }
353 let ptr = buf.as_mut_ptr::<OpusRepacketizer>();
354 unsafe { Repacketizer::init_in_place(ptr)? };
355 Ok(unsafe { Self::from_raw(ptr) })
356 }
357
358 delegate_ref_mut_methods! {
359 fn reset() -> ();
360 fn push(packet: &[u8]) -> Result<()>;
361 fn push_owned(packet: Vec<u8>) -> Result<()>;
362 fn emit_range(begin: i32, end: i32, out: &mut [u8]) -> Result<usize>;
363 fn emit(out: &mut [u8]) -> Result<usize>;
364 }
365}
366
367impl Drop for RepacketizerRef<'_> {
368 fn drop(&mut self) {
369 if !self.inner.packets.is_empty() {
370 unsafe { opus_repacketizer_init(self.inner.rp.as_ptr()) };
375 }
376 }
377}
378
379impl Deref for RepacketizerRef<'_> {
380 type Target = Repacketizer;
381
382 fn deref(&self) -> &Self::Target {
383 &self.inner
384 }
385}
386
387#[cfg(all(test, opus_codec_rust_packet_ops))]
388mod tests {
389 use super::*;
390
391 #[test]
392 fn invalid_cached_layout_falls_back_to_c_emit() {
393 let packet = vec![0x78, b'a'];
394 let mut rp = Repacketizer::new().unwrap();
395 rp.push_owned(packet.clone()).unwrap();
396 rp.packets[0].layout = Err(Error::InvalidPacket);
397
398 let mut out = [0u8; 8];
399 let out_len = rp.emit(&mut out).unwrap();
400 assert_eq!(&out[..out_len], packet);
401
402 let out_len = rp.emit_range(0, 1, &mut out).unwrap();
403 assert_eq!(&out[..out_len], packet);
404 }
405
406 #[test]
407 fn unexpected_cached_layout_error_is_not_hidden() {
408 let packet = vec![0x78, b'a'];
409 let mut rp = Repacketizer::new().unwrap();
410 rp.push_owned(packet).unwrap();
411 rp.packets[0].layout = Err(Error::InternalError);
412
413 let mut out = [0u8; 8];
414 assert_eq!(rp.emit(&mut out).unwrap_err(), Error::InternalError);
415 assert_eq!(
416 rp.emit_range(0, 1, &mut out).unwrap_err(),
417 Error::InternalError
418 );
419 }
420}