From e93994b2853efbef0b4ad2da68fde822f4e8054b Mon Sep 17 00:00:00 2001 From: dedobbin Date: Sun, 27 Aug 2023 21:05:40 +0200 Subject: [PATCH] adts duration --- symphonia-codec-aac/src/adts.rs | 79 ++++++++++++++++++++++++++++++++- 1 file changed, 78 insertions(+), 1 deletion(-) diff --git a/symphonia-codec-aac/src/adts.rs b/symphonia-codec-aac/src/adts.rs index 596c41dc..86b28a5e 100644 --- a/symphonia-codec-aac/src/adts.rs +++ b/symphonia-codec-aac/src/adts.rs @@ -131,12 +131,20 @@ impl FormatReader for AdtsReader { // Use the header to populate the codec parameters. let mut params = CodecParameters::new(); - params.for_codec(CODEC_TYPE_AAC).with_sample_rate(header.sample_rate); + params + .for_codec(CODEC_TYPE_AAC) + .with_sample_rate(header.sample_rate) + .with_time_base(TimeBase::new(1, header.sample_rate)); if let Some(channels) = header.channels { params.with_channels(channels); } + let n_frames = approximate_frame_count(&mut source)?; + if let Some(n_frames) = n_frames { + params.with_n_frames(n_frames); + } + // Rewind back to the start of the frame. source.seek_buffered_rev(AdtsHeader::SIZE); @@ -258,3 +266,72 @@ impl FormatReader for AdtsReader { self.reader } } + +fn approximate_frame_count(mut source: &mut MediaSourceStream) -> Result> { + let original_pos = source.pos(); + let total_len = match source.byte_len() { + Some(len) => len - original_pos, + _ => return Ok(None), + }; + + const ENSURED_SEEK_LEN: u64 = 1000; + source.ensure_seekback_buffer(ENSURED_SEEK_LEN as usize); + let mut scoped_stream = ScopedStream::new(&mut source, ENSURED_SEEK_LEN); + + let mut parsed_n_frames = 0; + let mut n_bytes = 0; + + loop { + let header = match AdtsHeader::read(&mut scoped_stream) { + Ok(header) => header, + _ => break, + }; + + if scoped_stream.ignore_bytes(header.frame_len as u64).is_err() { + break; + } + + parsed_n_frames += 1; + n_bytes += header.frame_len + AdtsHeader::SIZE; + } + source.seek_buffered_rev((source.pos() - original_pos) as usize); + + let step = total_len / 3; + if source.is_seekable() { + let mut new_pos = total_len / 2; + + loop { + if new_pos >= total_len { + break; + } + + let res = source.seek(SeekFrom::Start(new_pos)); + if res.is_err() { + break; + } + + for _ in 0..=500 { + let header = match AdtsHeader::read(&mut source) { + Ok(header) => header, + _ => break, + }; + + if source.ignore_bytes(header.frame_len as u64).is_err() { + break; + } + + parsed_n_frames += 1; + n_bytes += header.frame_len + AdtsHeader::SIZE; + } + new_pos += step; + } + + let _ = source.seek(SeekFrom::Start(original_pos))?; + } + debug!("adts: Parsed {} of {} bytes to approximate duration", n_bytes, total_len); + + match parsed_n_frames { + n if n == 0 => Ok(None), + _ => Ok(Some(total_len / (n_bytes as u64 / parsed_n_frames) * SAMPLES_PER_AAC_PACKET)), + } +}