shrink several large datastructures

*   Box the remaining Depacketizer variants. I already boxed the largest
    ones, which are also the most common. Might as well box the others
    and not have so much dead space in the common case...
*   Don't keep around a full codec::Parameters on all codecs. This
    shrinks several depacketizers. I also avoid some awkward
    destructuring.
*   Box VideoFrame::new_parameters, which is populated rarely.

```
sizes changes on 64-bit platforms:
type                               before  after
client::Stream                        512    312
codec::Depacketizer                   224     16
codec::aac::Depacketizer              232    208
codec::g723::Depacketizer             200    104
codec::h264::Depacketizer             560    552
codec::onvif::Depacketizer            216    128
codec::simple_audio::Depacketizer     208    112
codec::CodecItem                      240    160
codec::VideoFrame                     232    152
codec::AudioFrame                     104    104
codec::MessageFrame                   104    104
client::rtp::SenderReport              72     72
```
This commit is contained in:
Scott Lamb 2021-07-08 14:45:18 -07:00
parent f5b4c5a9b6
commit de6658961b
8 changed files with 218 additions and 144 deletions

View File

@ -1,7 +1,12 @@
## unreleased
* New opaque error type with more uniform, richer error messages. No more
`failure` dependency.
* BREAKING CHANGE: New opaque error type with more uniform, richer error
messages. No more `failure` dependency.
* BREAKING CHANGE: `retina::client::Stream::parameters` now returns parameters
by value. This allows shrinking depacketizer types.
* BREAKING CHANGE: `retina::codec::VideoFrame::new_parameters` is now boxed.
This allows shrinking `VideoFrame` and `CodecItem` by 80 bytes each (on
64-bit platforms). The box is only rarely populated.
## v0.0.4 (2021-06-28)

View File

@ -191,7 +191,7 @@ impl Stream {
///
/// Returns `None` on unknown codecs, bad parameters, or if parameters aren't specified
/// via SDP. Some codecs allow parameters to be specified in-band instead.
pub fn parameters(&self) -> Option<&crate::codec::Parameters> {
pub fn parameters(&self) -> Option<crate::codec::Parameters> {
self.depacketizer.as_ref().ok().and_then(|d| d.parameters())
}
}
@ -1071,3 +1071,31 @@ impl futures::Stream for Demuxed {
}
}
}
#[cfg(test)]
mod tests {
use super::*;
// See with: cargo test -- --nocapture client::tests::print_sizes
#[test]
fn print_sizes() {
for (name, size) in [
("RtspConnection", std::mem::size_of::<RtspConnection>()),
(
"Session<Described>",
std::mem::size_of::<Session<Described>>(),
),
("Session<Playing>", std::mem::size_of::<Session<Playing>>()),
("Demuxed", std::mem::size_of::<Demuxed>()),
("Stream", std::mem::size_of::<Stream>()),
("PacketItem", std::mem::size_of::<PacketItem>()),
("rtp::Packet", std::mem::size_of::<rtp::Packet>()),
(
"rtp::SenderReport",
std::mem::size_of::<rtp::SenderReport>(),
),
] {
println!("{:-40} {:4}", name, size);
}
}
}

View File

@ -26,9 +26,13 @@ use crate::{client::rtp::Packet, error::ErrorInt, ConnectionContext, Error};
use super::CodecItem;
/// An AudioSpecificConfig as in ISO/IEC 14496-3 section 1.6.2.1.
/// Currently just a few fields of interest.
///
/// Currently stores the raw form and a few fields of interest.
#[derive(Clone, Debug)]
pub(super) struct AudioSpecificConfig {
struct AudioSpecificConfig {
raw: Bytes,
sample_entry: Bytes,
/// See ISO/IEC 14496-3 Table 1.3.
audio_object_type: u8,
frame_length: NonZeroU16,
@ -63,8 +67,8 @@ const CHANNEL_CONFIGS: [Option<ChannelConfig>; 8] = [
impl AudioSpecificConfig {
/// Parses from raw bytes.
fn parse(config: &[u8]) -> Result<Self, String> {
let mut r = bitreader::BitReader::new(config);
fn parse(raw: &[u8]) -> Result<Self, String> {
let mut r = bitreader::BitReader::new(&raw[..]);
let audio_object_type = match r
.read_u8(5)
.map_err(|e| format!("unable to read audio_object_type: {}", e))?
@ -153,12 +157,27 @@ impl AudioSpecificConfig {
};
Ok(AudioSpecificConfig {
raw: Bytes::copy_from_slice(raw),
sample_entry: make_sample_entry(channels, sampling_frequency, raw)?,
audio_object_type,
frame_length,
sampling_frequency,
channels,
})
}
fn to_parameters(&self) -> super::AudioParameters {
// https://datatracker.ietf.org/doc/html/rfc6381#section-3.3
let rfc6381_codec = Some(format!("mp4a.40.{}", self.audio_object_type));
super::AudioParameters {
// See also TODO asking if clock_rate and sampling_frequency must match.
clock_rate: self.sampling_frequency,
rfc6381_codec,
frame_length: Some(NonZeroU32::from(self.frame_length)),
extra_data: self.raw.clone(),
sample_entry: Some(self.sample_entry.clone()),
}
}
}
/// Overwrites a buffer with a varint length, returning the length of the length.
@ -239,13 +258,12 @@ macro_rules! write_descriptor {
}
/// Returns an MP4AudioSampleEntry (`mp4a`) box as in ISO/IEC 14496-14 section 5.6.1.
/// `config` should be a raw AudioSpecificConfig (matching `parsed`).
pub(super) fn get_mp4a_box(parameters: &super::AudioParameters) -> Result<Bytes, String> {
let parsed = match parameters.config {
super::AudioCodecConfig::Aac(ref c) => c,
_ => unreachable!(),
};
let config = &parameters.extra_data[..];
/// `config` should be a raw AudioSpecificConfig.
fn make_sample_entry(
channels: &ChannelConfig,
sampling_frequency: u32,
config: &[u8],
) -> Result<Bytes, String> {
let mut buf = BytesMut::new();
// Write an MP4AudioSampleEntry (`mp4a`), as in ISO/IEC 14496-14 section 5.6.1.
@ -258,7 +276,7 @@ pub(super) fn get_mp4a_box(parameters: &super::AudioParameters) -> Result<Bytes,
0, 0, 0, 0, // AudioSampleEntry.reserved
0, 0, 0, 0, // AudioSampleEntry.reserved
]);
buf.put_u16(parsed.channels.channels);
buf.put_u16(channels.channels);
buf.extend_from_slice(&[
0x00, 0x10, // AudioSampleEntry.samplesize
0x00, 0x00, 0x00, 0x00, // AudioSampleEntry.pre_defined, AudioSampleEntry.reserved
@ -269,12 +287,8 @@ pub(super) fn get_mp4a_box(parameters: &super::AudioParameters) -> Result<Bytes,
// use a SamplingRateBox. The latter also requires changing the
// version/structure of the AudioSampleEntryBox and the version of the
// stsd box. Just support the former for now.
let sampling_frequency = u16::try_from(parsed.sampling_frequency).map_err(|_| {
format!(
"aac sampling_frequency={} unsupported",
parsed.sampling_frequency
)
})?;
let sampling_frequency = u16::try_from(sampling_frequency)
.map_err(|_| format!("aac sampling_frequency={} unsupported", sampling_frequency))?;
buf.put_u32(u32::from(sampling_frequency) << 16);
// Write the embedded ESDBox (`esds`), as in ISO/IEC 14496-14 section 5.6.1.
@ -301,16 +315,15 @@ pub(super) fn get_mp4a_box(parameters: &super::AudioParameters) -> Result<Bytes,
// elementary stream in byte". ISO/IEC 13818-7 section
// 8.2.2.1 defines the total decoder input buffer size as
// 6144 bits per NCC.
let buffer_size_bytes = (6144 / 8) * u32::from(parsed.channels.ncc);
let buffer_size_bytes = (6144 / 8) * u32::from(channels.ncc);
debug_assert!(buffer_size_bytes <= 0xFF_FFFF);
// buffer_size_bytes as a 24-bit number
buf.put_u8((buffer_size_bytes >> 16) as u8);
buf.put_u16(buffer_size_bytes as u16);
let max_bitrate = (6144 / 1024)
* u32::from(parsed.channels.ncc)
* u32::from(sampling_frequency);
let max_bitrate =
(6144 / 1024) * u32::from(channels.ncc) * u32::from(sampling_frequency);
buf.put_u32(max_bitrate);
// avg_bitrate. ISO/IEC 14496-1 section 7.2.6.6 says "for streams with
@ -339,7 +352,7 @@ pub(super) fn get_mp4a_box(parameters: &super::AudioParameters) -> Result<Bytes,
fn parse_format_specific_params(
clock_rate: u32,
format_specific_params: &str,
) -> Result<super::AudioParameters, String> {
) -> Result<AudioSpecificConfig, String> {
let mut mode = None;
let mut config = None;
let mut size_length = None;
@ -392,34 +405,22 @@ fn parse_format_specific_params(
));
}
let parsed = AudioSpecificConfig::parse(&config[..])?;
let config = AudioSpecificConfig::parse(&config[..])?;
// TODO: is this a requirement? I might have read somewhere one can be a multiple of the other.
if clock_rate != parsed.sampling_frequency {
if clock_rate != config.sampling_frequency {
return Err(format!(
"Expected RTP clock rate {} and AAC sampling frequency {} to match",
clock_rate, parsed.sampling_frequency
clock_rate, config.sampling_frequency
));
}
// https://datatracker.ietf.org/doc/html/rfc6381#section-3.3
let rfc6381_codec = Some(format!("mp4a.40.{}", parsed.audio_object_type));
let frame_length = Some(parsed.frame_length);
Ok(super::AudioParameters {
config: super::AudioCodecConfig::Aac(parsed),
clock_rate,
rfc6381_codec,
frame_length: frame_length.map(NonZeroU32::from),
extra_data: Bytes::from(config),
})
Ok(config)
}
#[derive(Debug)]
pub(crate) struct Depacketizer {
parameters: super::Parameters,
/// This is in parameters but duplicated here to avoid destructuring.
frame_length: NonZeroU16,
config: AudioSpecificConfig,
state: DepacketizerState,
}
@ -497,27 +498,21 @@ impl Depacketizer {
) -> Result<Self, String> {
let format_specific_params = format_specific_params
.ok_or_else(|| "AAC requires format specific params".to_string())?;
let parameters = parse_format_specific_params(clock_rate, format_specific_params)?;
let parsed = match parameters.config {
super::AudioCodecConfig::Aac(ref c) => c,
_ => unreachable!(),
};
if matches!(channels, Some(c) if c.get() != parsed.channels.channels) {
let config = parse_format_specific_params(clock_rate, format_specific_params)?;
if matches!(channels, Some(c) if c.get() != config.channels.channels) {
return Err(format!(
"Expected RTP channels {:?} and AAC channels {:?} to match",
channels, parsed.channels
channels, config.channels
));
}
let frame_length = parsed.frame_length;
Ok(Self {
parameters: super::Parameters::Audio(parameters),
frame_length,
config,
state: DepacketizerState::Idle { prev_loss: 0 },
})
}
pub(super) fn parameters(&self) -> Option<&super::Parameters> {
Some(&self.parameters)
pub(super) fn parameters(&self) -> Option<super::Parameters> {
Some(super::Parameters::Audio(self.config.to_parameters()))
}
pub(super) fn push(&mut self, mut pkt: Packet) -> Result<(), String> {
@ -592,7 +587,7 @@ impl Depacketizer {
self.state = DepacketizerState::Ready(super::AudioFrame {
ctx: pkt.ctx,
loss: frag.loss,
frame_length: NonZeroU32::from(self.frame_length),
frame_length: NonZeroU32::from(self.config.frame_length),
stream_id: pkt.stream_id,
timestamp: pkt.timestamp,
data: std::mem::take(&mut frag.buf).freeze(),
@ -691,13 +686,13 @@ impl Depacketizer {
));
}
let delta = u32::from(agg.frame_i) * u32::from(self.frame_length.get());
let delta = u32::from(agg.frame_i) * u32::from(self.config.frame_length.get());
let agg_timestamp = agg.timestamp;
let frame = super::AudioFrame {
ctx: agg.ctx,
loss: agg.loss,
stream_id: agg.stream_id,
frame_length: NonZeroU32::from(self.frame_length),
frame_length: NonZeroU32::from(self.config.frame_length),
// u16 * u16 can't overflow u32, but i64 + u32 can overflow i64.
timestamp: match agg_timestamp.try_add(delta) {

View File

@ -8,35 +8,33 @@ use std::num::NonZeroU32;
use bytes::Bytes;
use pretty_hex::PrettyHex;
const FIXED_CLOCK_RATE: u32 = 8_000;
#[derive(Debug)]
pub(crate) struct Depacketizer {
parameters: super::Parameters,
pending: Option<super::AudioFrame>,
}
impl Depacketizer {
/// Creates a new Depacketizer.
pub(super) fn new(clock_rate: u32) -> Result<Self, String> {
if clock_rate != 8_000 {
if clock_rate != FIXED_CLOCK_RATE {
return Err(format!(
"Expected clock rate of 8000 for G.723, got {}",
clock_rate
"Expected clock rate of {} for G.723, got {}",
FIXED_CLOCK_RATE, clock_rate
));
}
Ok(Self {
parameters: super::Parameters::Audio(super::AudioParameters {
rfc6381_codec: None,
frame_length: NonZeroU32::new(240),
clock_rate,
extra_data: Bytes::new(),
config: super::AudioCodecConfig::Other,
}),
pending: None,
})
Ok(Self { pending: None })
}
pub(super) fn parameters(&self) -> Option<&super::Parameters> {
Some(&self.parameters)
pub(super) fn parameters(&self) -> Option<super::Parameters> {
Some(super::Parameters::Audio(super::AudioParameters {
rfc6381_codec: None,
frame_length: NonZeroU32::new(240),
clock_rate: FIXED_CLOCK_RATE,
extra_data: Bytes::new(),
sample_entry: None,
}))
}
fn validate(pkt: &crate::client::rtp::Packet) -> bool {

View File

@ -114,8 +114,10 @@ impl Depacketizer {
})
}
pub(super) fn parameters(&self) -> Option<&super::Parameters> {
Some(&self.parameters.generic_parameters)
pub(super) fn parameters(&self) -> Option<super::Parameters> {
Some(super::Parameters::Video(
self.parameters.generic_parameters.clone(),
))
}
pub(super) fn push(&mut self, pkt: Packet) -> Result<(), String> {
@ -419,10 +421,7 @@ impl Depacketizer {
let pps_nal = new_pps.as_deref().unwrap_or(&self.parameters.pps_nal);
// TODO: could map this to a RtpPacketError more accurately.
self.parameters = InternalParameters::parse_sps_and_pps(sps_nal, pps_nal)?;
match self.parameters.generic_parameters {
super::Parameters::Video(ref p) => Some(p.clone()),
_ => unreachable!(),
}
Some(Box::new(self.parameters.generic_parameters.clone()))
} else {
None
};
@ -457,7 +456,7 @@ impl AccessUnit {
#[derive(Clone, Debug)]
struct InternalParameters {
generic_parameters: super::Parameters,
generic_parameters: super::VideoParameters,
/// The (single) SPS NAL.
sps_nal: Bytes,
@ -599,13 +598,13 @@ impl InternalParameters {
let sps_nal = avc_decoder_config.slice(sps_nal_start..sps_nal_end);
let pps_nal = avc_decoder_config.slice(pps_nal_start..pps_nal_end);
Ok(InternalParameters {
generic_parameters: super::Parameters::Video(super::VideoParameters {
generic_parameters: super::VideoParameters {
rfc6381_codec,
pixel_dimensions,
pixel_aspect_ratio,
frame_rate,
extra_data: avc_decoder_config,
}),
},
sps_nal,
pps_nal,
})

View File

@ -10,7 +10,6 @@
use std::num::{NonZeroU16, NonZeroU32};
use crate::client::rtp;
use crate::error::ErrorInt;
use crate::ConnectionContext;
use crate::Error;
use bytes::{Buf, Bytes};
@ -114,13 +113,7 @@ pub struct AudioParameters {
frame_length: Option<NonZeroU32>,
clock_rate: u32,
extra_data: Bytes,
config: AudioCodecConfig,
}
#[derive(Clone)]
enum AudioCodecConfig {
Aac(aac::AudioSpecificConfig),
Other,
sample_entry: Option<Bytes>,
}
impl std::fmt::Debug for AudioParameters {
@ -153,13 +146,12 @@ impl AudioParameters {
&self.extra_data
}
/// Builds an `.mp4` `SimpleAudioEntry` box (as defined in ISO/IEC 14496-12) if possible.
/// An `.mp4` `SimpleAudioEntry` box (as defined in ISO/IEC 14496-12), if possible.
///
/// Not all codecs can be placed into a `.mp4` file, and even for supported codecs there
/// may be unsupported edge cases.
pub fn sample_entry(&self) -> Result<Bytes, Error> {
// TODO: InvalidArgument doesn't seem quite right. We probably should
// produce the mp4a eagerly anyway.
aac::get_mp4a_box(self).map_err(|description| wrap!(ErrorInt::InvalidArgument(description)))
pub fn sample_entry(&self) -> Option<&Bytes> {
self.sample_entry.as_ref()
}
}
@ -240,7 +232,8 @@ impl std::fmt::Debug for MessageFrame {
/// specified here; they can be calculated from the timestamp of a following
/// picture, or approximated via the frame rate.
pub struct VideoFrame {
pub new_parameters: Option<VideoParameters>,
// New video parameters. Rarely populated and large, so boxed to reduce bloat.
pub new_parameters: Option<Box<VideoParameters>>,
/// Number of lost RTP packets before this video frame. See [crate::client::rtp::Packet::loss].
/// Note that if loss occurs during a fragmented frame, more than this number of packets' worth
@ -318,10 +311,10 @@ pub struct Depacketizer(DepacketizerInner);
#[derive(Debug)]
enum DepacketizerInner {
Aac(Box<aac::Depacketizer>),
SimpleAudio(simple_audio::Depacketizer),
G723(g723::Depacketizer),
SimpleAudio(Box<simple_audio::Depacketizer>),
G723(Box<g723::Depacketizer>),
H264(Box<h264::Depacketizer>),
Onvif(onvif::Depacketizer),
Onvif(Box<onvif::Depacketizer>),
}
impl Depacketizer {
@ -346,40 +339,44 @@ impl Depacketizer {
channels,
format_specific_params,
)?)),
("audio", "g726-16") => {
DepacketizerInner::SimpleAudio(simple_audio::Depacketizer::new(clock_rate, 2))
}
("audio", "g726-24") => {
DepacketizerInner::SimpleAudio(simple_audio::Depacketizer::new(clock_rate, 3))
}
("audio", "dvi4") | ("audio", "g726-32") => {
DepacketizerInner::SimpleAudio(simple_audio::Depacketizer::new(clock_rate, 4))
}
("audio", "g726-40") => {
DepacketizerInner::SimpleAudio(simple_audio::Depacketizer::new(clock_rate, 5))
}
("audio", "g726-16") => DepacketizerInner::SimpleAudio(Box::new(
simple_audio::Depacketizer::new(clock_rate, 2),
)),
("audio", "g726-24") => DepacketizerInner::SimpleAudio(Box::new(
simple_audio::Depacketizer::new(clock_rate, 3),
)),
("audio", "dvi4") | ("audio", "g726-32") => DepacketizerInner::SimpleAudio(Box::new(
simple_audio::Depacketizer::new(clock_rate, 4),
)),
("audio", "g726-40") => DepacketizerInner::SimpleAudio(Box::new(
simple_audio::Depacketizer::new(clock_rate, 5),
)),
("audio", "pcma") | ("audio", "pcmu") | ("audio", "u8") | ("audio", "g722") => {
DepacketizerInner::SimpleAudio(simple_audio::Depacketizer::new(clock_rate, 8))
}
("audio", "l16") => {
DepacketizerInner::SimpleAudio(simple_audio::Depacketizer::new(clock_rate, 16))
DepacketizerInner::SimpleAudio(Box::new(simple_audio::Depacketizer::new(
clock_rate, 8,
)))
}
("audio", "l16") => DepacketizerInner::SimpleAudio(Box::new(
simple_audio::Depacketizer::new(clock_rate, 16),
)),
// Dahua cameras when configured with G723 send packets with a
// non-standard encoding-name "G723.1" and length 40, which doesn't
// make sense. Don't try to depacketize these.
("audio", "g723") => DepacketizerInner::G723(g723::Depacketizer::new(clock_rate)?),
("application", "vnd.onvif.metadata") => {
DepacketizerInner::Onvif(onvif::Depacketizer::new(CompressionType::Uncompressed))
}
("application", "vnd.onvif.metadata.gzip") => {
DepacketizerInner::Onvif(onvif::Depacketizer::new(CompressionType::GzipCompressed))
}
("application", "vnd.onvif.metadata.exi.onvif") => {
DepacketizerInner::Onvif(onvif::Depacketizer::new(CompressionType::ExiDefault))
}
("application", "vnd.onvif.metadata.exi.ext") => {
DepacketizerInner::Onvif(onvif::Depacketizer::new(CompressionType::ExiInBand))
("audio", "g723") => {
DepacketizerInner::G723(Box::new(g723::Depacketizer::new(clock_rate)?))
}
("application", "vnd.onvif.metadata") => DepacketizerInner::Onvif(Box::new(
onvif::Depacketizer::new(CompressionType::Uncompressed),
)),
("application", "vnd.onvif.metadata.gzip") => DepacketizerInner::Onvif(Box::new(
onvif::Depacketizer::new(CompressionType::GzipCompressed),
)),
("application", "vnd.onvif.metadata.exi.onvif") => DepacketizerInner::Onvif(Box::new(
onvif::Depacketizer::new(CompressionType::ExiDefault),
)),
("application", "vnd.onvif.metadata.exi.ext") => DepacketizerInner::Onvif(Box::new(
onvif::Depacketizer::new(CompressionType::ExiInBand),
)),
(_, _) => {
log::info!(
"no depacketizer for media/encoding_name {}/{}",
@ -394,7 +391,7 @@ impl Depacketizer {
}))
}
pub fn parameters(&self) -> Option<&Parameters> {
pub fn parameters(&self) -> Option<Parameters> {
match &self.0 {
DepacketizerInner::Aac(d) => d.parameters(),
DepacketizerInner::G723(d) => d.parameters(),
@ -424,3 +421,53 @@ impl Depacketizer {
}
}
}
#[cfg(test)]
mod tests {
use super::*;
// See with: cargo test -- --nocapture codec::tests::print_sizes
#[test]
fn print_sizes() {
for (name, size) in [
("Depacketizer", std::mem::size_of::<Depacketizer>()),
(
"aac::Depacketizer",
std::mem::size_of::<aac::Depacketizer>(),
),
(
"g723::Depacketizer",
std::mem::size_of::<g723::Depacketizer>(),
),
(
"h264::Depacketizer",
std::mem::size_of::<h264::Depacketizer>(),
),
(
"onvif::Depacketizer",
std::mem::size_of::<onvif::Depacketizer>(),
),
(
"simple_audio::Depacketizer",
std::mem::size_of::<simple_audio::Depacketizer>(),
),
("CodecItem", std::mem::size_of::<CodecItem>()),
("VideoFrame", std::mem::size_of::<VideoFrame>()),
("AudioFrame", std::mem::size_of::<AudioFrame>()),
("MessageFrame", std::mem::size_of::<MessageFrame>()),
(
"SenderReport",
std::mem::size_of::<crate::client::rtp::SenderReport>(),
),
("Parameters", std::mem::size_of::<Parameters>()),
("VideoParameters", std::mem::size_of::<VideoParameters>()),
("AudioParameters", std::mem::size_of::<AudioParameters>()),
(
"MessageParameters",
std::mem::size_of::<MessageParameters>(),
),
] {
println!("{:-40} {:4}", name, size);
}
}
}

View File

@ -12,7 +12,7 @@ use bytes::{Buf, BufMut, BytesMut};
use super::CodecItem;
#[derive(Clone, Debug)]
#[derive(Copy, Clone, Debug)]
pub enum CompressionType {
Uncompressed,
GzipCompressed,
@ -22,7 +22,7 @@ pub enum CompressionType {
#[derive(Debug)]
pub(crate) struct Depacketizer {
parameters: super::Parameters,
compression_type: CompressionType,
state: State,
high_water_size: usize,
}
@ -45,14 +45,16 @@ struct InProgress {
impl Depacketizer {
pub(super) fn new(compression_type: CompressionType) -> Self {
Depacketizer {
parameters: super::Parameters::Message(super::MessageParameters(compression_type)),
compression_type,
state: State::Idle,
high_water_size: 0,
}
}
pub(super) fn parameters(&self) -> Option<&super::Parameters> {
Some(&self.parameters)
pub(super) fn parameters(&self) -> Option<super::Parameters> {
Some(super::Parameters::Message(super::MessageParameters(
self.compression_type,
)))
}
pub(super) fn push(&mut self, pkt: crate::client::rtp::Packet) -> Result<(), String> {

View File

@ -12,7 +12,7 @@ use super::CodecItem;
#[derive(Debug)]
pub(crate) struct Depacketizer {
parameters: super::Parameters,
clock_rate: u32,
pending: Option<super::AudioFrame>,
bits_per_sample: u32,
}
@ -21,20 +21,20 @@ impl Depacketizer {
/// Creates a new Depacketizer.
pub(super) fn new(clock_rate: u32, bits_per_sample: u32) -> Self {
Self {
parameters: super::Parameters::Audio(super::AudioParameters {
rfc6381_codec: None,
frame_length: None, // variable
clock_rate,
extra_data: Bytes::new(),
config: super::AudioCodecConfig::Other,
}),
bits_per_sample,
pending: None,
}
}
pub(super) fn parameters(&self) -> Option<&super::Parameters> {
Some(&self.parameters)
pub(super) fn parameters(&self) -> Option<super::Parameters> {
Some(super::Parameters::Audio(super::AudioParameters {
rfc6381_codec: None,
frame_length: None, // variable
clock_rate: self.clock_rate,
extra_data: Bytes::new(),
sample_entry: None,
}))
}
fn frame_length(&self, payload_len: usize) -> Option<NonZeroU32> {