use std::{borrow::Cow, ops::Range};
use log::trace;
use super::{
comment_header_copy::CommentHeaderCopy, comment_header_parse::VorbisCommentData,
setup_header_parse::VorbisSetupData, VorbisIdentificationHeaderData, VorbisOptimizerError
};
pub(super) struct IdentificationHeaderCopy {
pub(super) comment_data: Option<VorbisCommentData>,
pub(super) codec_setup: Option<VorbisSetupData>
}
impl IdentificationHeaderCopy {
#[allow(clippy::type_complexity)]
pub(super) fn optimize_packet<'packet>(
&mut self,
mut packet: Cow<'packet, [u8]>,
identification_data: &VorbisIdentificationHeaderData
) -> Result<
(
Option<(Cow<'packet, [u8]>, Option<u16>)>,
Option<CommentHeaderCopy>
),
VorbisOptimizerError
> {
trace!("Optimizing identification header Vorbis packet");
const SAMPLING_FREQUENCY_BYTE_RANGE: Range<usize> = 7 + 5..7 + 9;
const MAXIMUM_BITRATE_BYTE_RANGE: Range<usize> = 7 + 9..7 + 13;
const NOMINAL_BITRATE_BYTE_RANGE: Range<usize> = 7 + 13..7 + 17;
const MINIMUM_BITRATE_BYTE_RANGE: Range<usize> = 7 + 17..7 + 21;
const FRAMING_BYTE_OFFSET: usize = 7 + 22;
const EXPECTED_PACKET_LENGTH: usize = 7 + 23;
let sampling_frequency =
u32::from_le_bytes(packet[SAMPLING_FREQUENCY_BYTE_RANGE].try_into().unwrap());
let maximum_bitrate =
i32::from_le_bytes(packet[MAXIMUM_BITRATE_BYTE_RANGE].try_into().unwrap());
let nominal_bitrate =
i32::from_le_bytes(packet[NOMINAL_BITRATE_BYTE_RANGE].try_into().unwrap());
let minimum_bitrate =
i32::from_le_bytes(packet[MINIMUM_BITRATE_BYTE_RANGE].try_into().unwrap());
let target_sampling_frequency = identification_data.sampling_frequency.get();
let target_maximum_bitrate = identification_data.maximum_bitrate;
let target_nominal_bitrate = identification_data.nominal_bitrate;
let target_minimum_bitrate = identification_data.minimum_bitrate;
if target_sampling_frequency != sampling_frequency
|| target_maximum_bitrate != maximum_bitrate
|| target_nominal_bitrate != nominal_bitrate
|| target_minimum_bitrate != minimum_bitrate
{
packet.to_mut()[SAMPLING_FREQUENCY_BYTE_RANGE]
.copy_from_slice(&target_sampling_frequency.to_le_bytes());
packet.to_mut()[MAXIMUM_BITRATE_BYTE_RANGE]
.copy_from_slice(&target_maximum_bitrate.to_le_bytes());
packet.to_mut()[NOMINAL_BITRATE_BYTE_RANGE]
.copy_from_slice(&target_nominal_bitrate.to_le_bytes());
packet.to_mut()[MINIMUM_BITRATE_BYTE_RANGE]
.copy_from_slice(&target_minimum_bitrate.to_le_bytes());
}
if packet[FRAMING_BYTE_OFFSET] != 1 {
trace!("Fixing framing bit");
packet.to_mut()[FRAMING_BYTE_OFFSET] = 1;
}
if packet.len() > EXPECTED_PACKET_LENGTH {
trace!("Removing trailing bytes at end of packet");
packet.to_mut().truncate(EXPECTED_PACKET_LENGTH);
}
Ok((
Some((packet, None)),
Some(CommentHeaderCopy {
comment_data: self.comment_data.take(),
codec_setup: self.codec_setup.take()
})
))
}
}