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:
parent
b1e1fa9031
commit
a33ba9b8af
@ -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");
|
||||
}
|
||||
|
||||
|
@ -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,
|
||||
},
|
||||
})
|
||||
|
@ -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()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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,
|
||||
|
Loading…
Reference in New Issue
Block a user