no Bytes in AudioParameters interface either

For #47.

Along the way, I simplified `aac::Depacketizer` impl a bit, eliminating
a clone and some redundancy.
This commit is contained in:
Scott Lamb 2022-05-11 11:56:42 -07:00
parent b1e1fa9031
commit a33ba9b8af
4 changed files with 32 additions and 48 deletions

View File

@ -30,13 +30,9 @@ use super::{AudioParameters, CodecItem};
/// Currently stores the raw form and a few fields of interest.
#[derive(Clone, Debug)]
struct AudioSpecificConfig {
raw: Bytes,
sample_entry: Bytes,
parameters: AudioParameters,
/// See ISO/IEC 14496-3 Table 1.3.
audio_object_type: u8,
frame_length: NonZeroU16,
sampling_frequency: u32,
channels: &'static ChannelConfig,
}
@ -159,28 +155,22 @@ impl AudioSpecificConfig {
(_, true) => NonZeroU16::new(960).expect("non-zero"),
};
// https://datatracker.ietf.org/doc/html/rfc6381#section-3.3
let rfc6381_codec = Some(format!("mp4a.40.{}", audio_object_type));
Ok(AudioSpecificConfig {
raw: Bytes::copy_from_slice(raw),
sample_entry: make_sample_entry(channels, sampling_frequency, raw)?,
audio_object_type,
parameters: AudioParameters {
// See also TODO asking if clock_rate and sampling_frequency must match.
clock_rate: sampling_frequency,
rfc6381_codec,
frame_length: Some(NonZeroU32::from(frame_length)),
extra_data: raw.to_owned(),
sample_entry: Some(make_sample_entry(channels, sampling_frequency, raw)?),
},
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.
@ -220,7 +210,7 @@ macro_rules! write_box {
// is expected to reference `$buf` via the original name.
#[allow(clippy::unnecessary_mut_passed)]
{
let _: &mut BytesMut = $buf; // type-check.
let _: &mut Vec<u8> = $buf; // type-check.
let pos_start = $buf.len();
let fourcc: &[u8; 4] = $fourcc;
@ -244,7 +234,7 @@ macro_rules! write_box {
/// scope. See ISO/IEC 14496-1 Table 1 for the `tag`.
macro_rules! write_descriptor {
($buf:expr, $tag:expr, $b:block) => {{
let _: &mut BytesMut = $buf; // type-check.
let _: &mut Vec<u8> = $buf; // type-check.
let _: u8 = $tag;
let pos_start = $buf.len();
@ -274,8 +264,8 @@ fn make_sample_entry(
channels: &ChannelConfig,
sampling_frequency: u32,
config: &[u8],
) -> Result<Bytes, String> {
let mut buf = BytesMut::new();
) -> Result<Vec<u8>, String> {
let mut buf = Vec::new();
// Write an MP4AudioSampleEntry (`mp4a`), as in ISO/IEC 14496-14 section 5.6.1.
// It's based on AudioSampleEntry, ISO/IEC 14496-12 section 12.2.3.2,
@ -354,7 +344,7 @@ fn make_sample_entry(
});
});
});
Ok(buf.freeze())
Ok(buf)
}
/// Parses metadata from the `format-specific-params` of a SDP `fmtp` media attribute.
@ -418,11 +408,12 @@ fn parse_format_specific_params(
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 != config.sampling_frequency {
// TODO: is this a requirement? I might have read somewhere that the RTP clock rate can be
// a multiple of the AudioSpecificConfig sampling_frequency or vice versa.
if clock_rate != config.parameters.clock_rate {
return Err(format!(
"Expected RTP clock rate {} and AAC sampling frequency {} to match",
clock_rate, config.sampling_frequency
clock_rate, config.parameters.clock_rate,
));
}
@ -432,7 +423,6 @@ fn parse_format_specific_params(
#[derive(Debug)]
pub(crate) struct Depacketizer {
config: AudioSpecificConfig,
parameters: AudioParameters,
state: DepacketizerState,
}
@ -528,16 +518,14 @@ impl Depacketizer {
channels, config.channels
));
}
let parameters = config.to_parameters();
Ok(Self {
config,
parameters,
state: DepacketizerState::default(),
})
}
pub(super) fn parameters(&self) -> Option<super::ParametersRef> {
Some(super::ParametersRef::Audio(&self.parameters))
Some(super::ParametersRef::Audio(&self.config.parameters))
}
pub(super) fn push(&mut self, pkt: ReceivedPacket) -> Result<(), String> {
@ -797,15 +785,15 @@ mod tests {
#[test]
fn parse_audio_specific_config() {
let dahua = AudioSpecificConfig::parse(&[0x11, 0x88]).unwrap();
assert_eq!(dahua.sampling_frequency, 48_000);
assert_eq!(dahua.parameters.clock_rate, 48_000);
assert_eq!(dahua.channels.name, "mono");
let bunny = AudioSpecificConfig::parse(&[0x14, 0x90]).unwrap();
assert_eq!(bunny.sampling_frequency, 12_000);
assert_eq!(bunny.parameters.clock_rate, 12_000);
assert_eq!(bunny.channels.name, "stereo");
let rfc3640 = AudioSpecificConfig::parse(&[0x11, 0xB0]).unwrap();
assert_eq!(rfc3640.sampling_frequency, 48_000);
assert_eq!(rfc3640.parameters.clock_rate, 48_000);
assert_eq!(rfc3640.channels.name, "5.1");
}

View File

@ -5,8 +5,6 @@
use std::num::NonZeroU32;
use bytes::Bytes;
use super::AudioParameters;
const FIXED_CLOCK_RATE: u32 = 8_000;
@ -32,7 +30,7 @@ impl Depacketizer {
rfc6381_codec: None,
frame_length: NonZeroU32::new(240),
clock_rate: FIXED_CLOCK_RATE,
extra_data: Bytes::new(),
extra_data: Vec::new(),
sample_entry: None,
},
})

View File

@ -139,8 +139,8 @@ pub struct AudioParameters {
rfc6381_codec: Option<String>,
frame_length: Option<NonZeroU32>,
clock_rate: u32,
extra_data: Bytes,
sample_entry: Option<Bytes>,
extra_data: Vec<u8>,
sample_entry: Option<Vec<u8>>,
}
impl std::fmt::Debug for AudioParameters {
@ -172,7 +172,7 @@ impl AudioParameters {
/// The codec-specific "extra data" to feed to eg ffmpeg to decode the audio.
/// * AAC: a serialized `AudioSpecificConfig`.
pub fn extra_data(&self) -> &Bytes {
pub fn extra_data(&self) -> &[u8] {
&self.extra_data
}
@ -180,8 +180,8 @@ impl AudioParameters {
///
/// 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) -> Option<&Bytes> {
self.sample_entry.as_ref()
pub fn sample_entry(&self) -> Option<&[u8]> {
self.sample_entry.as_deref()
}
}

View File

@ -6,8 +6,6 @@
use std::num::NonZeroU32;
use bytes::Bytes;
use super::{AudioParameters, CodecItem};
#[derive(Debug)]
@ -25,7 +23,7 @@ impl Depacketizer {
rfc6381_codec: None,
frame_length: None, // variable
clock_rate,
extra_data: Bytes::new(),
extra_data: Vec::new(),
sample_entry: None,
},
bits_per_sample,