Skip to content

Commit

Permalink
adts duration
Browse files Browse the repository at this point in the history
  • Loading branch information
dedobbin committed Mar 7, 2024
1 parent 335d960 commit 01b85f2
Showing 1 changed file with 80 additions and 1 deletion.
81 changes: 80 additions & 1 deletion symphonia-codec-aac/src/adts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down Expand Up @@ -258,3 +266,74 @@ impl FormatReader for AdtsReader {
self.reader
}
}

fn approximate_frame_count(mut source: &mut MediaSourceStream) -> Result<Option<u64>> {
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) as u64 * SAMPLES_PER_AAC_PACKET))
}
}
}

0 comments on commit 01b85f2

Please sign in to comment.