diff --git a/Cargo.toml b/Cargo.toml index 7b7fa6b..0e8d9af 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -15,7 +15,7 @@ claxon = { version = "0.4.2", optional = true } hound = { version = "3.3.1", optional = true } lewton = { version = "0.10", optional = true } minimp3_fixed = { version = "0.5.4", optional = true} -symphonia = { version = "0.5.2", optional = true, default-features = false } +symphonia = { version = "0.5.4", optional = true, default-features = false, features = ["all"] } crossbeam-channel = { version = "0.5.8", optional = true } thiserror = "1.0.49" diff --git a/assets/monkeys.mp4a b/assets/monkeys.mp4a new file mode 100644 index 0000000..bf13299 Binary files /dev/null and b/assets/monkeys.mp4a differ diff --git a/src/decoder/symphonia.rs b/src/decoder/symphonia.rs index 146ed21..02bcf46 100644 --- a/src/decoder/symphonia.rs +++ b/src/decoder/symphonia.rs @@ -2,7 +2,7 @@ use std::time::Duration; use symphonia::{ core::{ audio::{AudioBufferRef, SampleBuffer, SignalSpec}, - codecs::{Decoder, DecoderOptions}, + codecs::{Decoder, DecoderOptions, CODEC_TYPE_NULL}, errors::Error, formats::{FormatOptions, FormatReader, SeekedTo}, io::MediaSourceStream, @@ -76,8 +76,18 @@ impl SymphoniaDecoder { None => return Ok(None), }; + // Select the first supported track + let track_id = probed.format.tracks() + .iter() + .find(|t| t.codec_params.codec != CODEC_TYPE_NULL).unwrap().id; + + let decode_opts = + DecoderOptions { verify: false, ..Default::default() }; + + let track = probed.format.tracks().iter().find(|track| track.id == track_id).unwrap(); + let mut decoder = symphonia::default::get_codecs() - .make(&stream.codec_params, &DecoderOptions { verify: true })?; + .make(&track.codec_params, &decode_opts)?; let total_duration = stream .codec_params .time_base @@ -86,7 +96,16 @@ impl SymphoniaDecoder { let mut decode_errors: usize = 0; let decoded = loop { - let current_frame = probed.format.next_packet()?; + let current_frame = match probed.format.next_packet() { + Ok(packet) => packet, + Err(_) => break decoder.last_decoded() // IoError end of stream is expected + }; + + // If the packet does not belong to the selected track, skip over it + if current_frame.track_id() != track_id { + continue; + } + match decoder.decode(¤t_frame) { Ok(decoded) => break decoded, Err(e) => match e { diff --git a/tests/mp4a_test.rs b/tests/mp4a_test.rs new file mode 100644 index 0000000..0ef0632 --- /dev/null +++ b/tests/mp4a_test.rs @@ -0,0 +1,13 @@ +use std::io::BufReader; + +#[test] +fn test_mp4a_encodings() { + // mp4a codec downloaded from YouTube + // "Monkeys Spinning Monkeys" + // Kevin MacLeod (incompetech.com) + // Licensed under Creative Commons: By Attribution 3.0 + // http://creativecommons.org/licenses/by/3.0/ + let file = std::fs::File::open("assets/monkeys.mp4a").unwrap(); + let mut decoder = rodio::Decoder::new(BufReader::new(file)).unwrap(); + assert!(decoder.any(|x| x != 0)); // Assert not all zeros +} \ No newline at end of file diff --git a/tests/seek.rs b/tests/seek.rs index 27e2d0d..46df93d 100644 --- a/tests/seek.rs +++ b/tests/seek.rs @@ -24,7 +24,7 @@ use rstest_reuse::{self, *}; )] #[cfg_attr(feature = "symphonia-mp3", case("mp3", true, "symphonia"))] // note: disabled, broken decoder see issue: #577 -// #[cfg_attr(feature = "symphonia-isomp4", case("m4a", true, "symphonia"))] +#[cfg_attr(feature = "symphonia-isomp4", case("m4a", true, "symphonia"))] #[cfg_attr(feature = "symphonia-wav", case("wav", true, "symphonia"))] #[cfg_attr(feature = "symphonia-flac", case("flac", true, "symphonia"))] fn all_decoders( @@ -44,7 +44,7 @@ fn all_decoders( )] #[cfg_attr(feature = "symphonia-mp3", case("mp3", "symphonia"))] // note: disabled, broken decoder see issue: #577 -// #[cfg_attr(feature = "symphonia-isomp4", case("m4a", "symphonia"))] +#[cfg_attr(feature = "symphonia-isomp4", case("m4a", "symphonia"))] #[cfg_attr(feature = "symphonia-wav", case("wav", "symphonia"))] #[cfg_attr(feature = "symphonia-flac", case("flac", "symphonia"))] fn supported_decoders(#[case] format: &'static str, #[case] decoder_name: &'static str) {}