retina/codec/
simple_audio.rs1use std::num::NonZeroU32;
8
9use super::{AudioParameters, CodecItem};
10
11#[derive(Debug)]
12pub(crate) struct Depacketizer {
13 parameters: AudioParameters,
14 pending: Option<super::AudioFrame>,
15 bits_per_sample: u32,
16}
17
18impl Depacketizer {
19 pub(super) fn new(clock_rate: u32, bits_per_sample: u32) -> Self {
21 Self {
22 parameters: AudioParameters {
23 rfc6381_codec: None,
24 frame_length: None, clock_rate,
26 extra_data: Vec::new(),
27 codec: super::AudioParametersCodec::Other,
28 },
29 bits_per_sample,
30 pending: None,
31 }
32 }
33
34 pub(super) fn parameters(&self) -> Option<super::ParametersRef<'_>> {
35 Some(super::ParametersRef::Audio(&self.parameters))
36 }
37
38 fn frame_length(&self, payload_len: usize) -> Option<NonZeroU32> {
39 assert!(payload_len < usize::from(u16::MAX));
42 let bits = (payload_len) as u32 * 8;
43 match bits.is_multiple_of(self.bits_per_sample) {
44 true => None,
45 false => NonZeroU32::new(bits / self.bits_per_sample),
46 }
47 }
48
49 pub(super) fn push(&mut self, pkt: crate::rtp::ReceivedPacket) -> Result<(), String> {
50 assert!(self.pending.is_none());
51 let payload = pkt.payload();
52 let frame_length = self.frame_length(payload.len()).ok_or_else(|| {
53 format!(
54 "invalid length {} for payload of {}-bit audio samples",
55 payload.len(),
56 self.bits_per_sample
57 )
58 })?;
59 self.pending = Some(super::AudioFrame {
60 loss: pkt.loss(),
61 ctx: *pkt.ctx(),
62 stream_id: pkt.stream_id(),
63 timestamp: pkt.timestamp(),
64 frame_length,
65 data: pkt.into_payload_bytes(),
66 });
67 Ok(())
68 }
69
70 pub(super) fn pull(&mut self) -> Option<super::CodecItem> {
71 self.pending.take().map(CodecItem::AudioFrame)
72 }
73}