From 9292f0767e68fbab99d79271a668fe336db67ea8 Mon Sep 17 00:00:00 2001 From: _ <> Date: Sat, 13 Nov 2021 02:42:31 +0000 Subject: [PATCH] :construction: still trying to debug the popping. I've narrowed it down. --- src/decoder.rs | 81 +++++++++++++++++++++++++++++++++++++++----------- src/main.rs | 58 +++++++++++++++++------------------- 2 files changed, 90 insertions(+), 49 deletions(-) diff --git a/src/decoder.rs b/src/decoder.rs index e90884b..64825b6 100644 --- a/src/decoder.rs +++ b/src/decoder.rs @@ -86,6 +86,7 @@ pub struct Decoder { best_stream_idx: usize, pub decoder: DecodeContext, pub resampler: ResamplingContext, + resampler_flushed: bool, } impl Decoder { @@ -109,38 +110,40 @@ impl Decoder { best_stream_idx, decoder, resampler, + resampler_flushed: false, }) } pub fn fill_buffer (&mut self, pcm_buffers: &mut PcmBuffers) -> Result { - match self.resampler.delay () { - Some (x) => { - tracing::trace! ("flushing resampler ({} ms)", x.milliseconds); - let mut frame_resampled = ffmpeg_next::util::frame::Audio::empty (); - frame_resampled.set_channel_layout (ChannelLayout::STEREO); - frame_resampled.set_format (Sample::F32 (sample::Type::Packed)); - frame_resampled.set_rate (48000); + if ! self.resampler_flushed && self.resampler.delay ().is_some () { + let mut frame_resampled = ffmpeg_next::util::frame::Audio::empty (); + frame_resampled.set_channel_layout (ChannelLayout::STEREO); + frame_resampled.set_format (Sample::F32 (sample::Type::Packed)); + frame_resampled.set_rate (48000); + + let rc = self.resampler.flush (&mut frame_resampled)?; + if rc.is_none () { + self.resampler_flushed = true; + } + + if ! frame_resampled.data (0).is_empty () { + tracing::trace! ("flushing resampler... {}", frame_resampled.data (0).len ()); + pcm_buffers.produce_bytes (frame_resampled.data (0)); - if self.resampler.flush (&mut frame_resampled).is_ok () { - pcm_buffers.produce_bytes (frame_resampled.data (0)); - return Ok (true); - } - else { - tracing::error! ("resampler flushed out a zero-length frame?"); - } - }, - _ => {}, + return Ok (true); + } } let mut frame_src = ffmpeg_next::util::frame::Audio::empty (); if self.decoder.receive_frame (&mut frame_src).is_ok () { - //eprintln! ("decoder.receive_frame"); + // tracing::trace! ("decoded frame"); let mut frame_resampled = ffmpeg_next::util::frame::Audio::empty (); frame_resampled.set_channel_layout (ChannelLayout::STEREO); frame_resampled.set_format (Sample::F32 (sample::Type::Packed)); frame_resampled.set_rate (48000); self.resampler.run (&frame_src, &mut frame_resampled)?; + self.resampler_flushed = false; pcm_buffers.produce_bytes (frame_resampled.data (0)); return Ok (true); } @@ -149,12 +152,54 @@ impl Decoder { while let Some ((stream, packet)) = self.input_ctx.packets ().next () { if stream.index () == self.best_stream_idx { - //eprintln! ("decoder.send_packet"); + // tracing::trace! ("demuxed packet"); self.decoder.send_packet (&packet)?; return Ok (true); } } + if self.resampler_flushed { + return Ok (false); + } + + let mut frame_resampled = ffmpeg_next::util::frame::Audio::empty (); + frame_resampled.set_channel_layout (ChannelLayout::STEREO); + frame_resampled.set_format (Sample::F32 (sample::Type::Packed)); + frame_resampled.set_rate (48000); + + let rc = self.resampler.flush (&mut frame_resampled)?; + if rc.is_none () { + self.resampler_flushed = true; + } + + if ! frame_resampled.data (0).is_empty () { + tracing::trace! ("flushing resampler... {}", frame_resampled.data (0).len ()); + pcm_buffers.produce_bytes (frame_resampled.data (0)); + + return Ok (true); + } + Ok (false) } } + +#[cfg (test)] +mod test { + use super::*; + + #[test] + fn pcm_buffer () { + let mut x = PcmBuffers::default (); + + x.produce (vec! [0.0, 1.0, 2.0, 3.0]); + x.produce (vec! [4.0, 5.0, 6.0, 7.0]); + + let mut data = vec! [0.0; 3]; + + assert! (x.consume_exact (&mut data)); + assert_eq! (&data, &[0.0, 1.0, 2.0]); + + assert! (x.consume_exact (&mut data)); + assert_eq! (&data, &[3.0, 4.0, 5.0]); + } +} diff --git a/src/main.rs b/src/main.rs index 4b0a14e..1fbc5d0 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,4 +1,6 @@ use std::{ + fs::File, + io::Write, sync::{ Arc, Condvar, @@ -8,7 +10,7 @@ use std::{ self, sleep, }, - time::Duration, + time::{Duration, Instant}, }; use anyhow::{ @@ -17,6 +19,11 @@ use anyhow::{ Result, }; +use byteorder::{ + ByteOrder, + LittleEndian, +}; + use cpal::traits::{ DeviceTrait, HostTrait, @@ -45,14 +52,12 @@ fn cmd_debug (args: &[String]) -> Result <()> { let mut decoder = decoder::Decoder::new (&filename)?; let mut pcm_buffers = decoder::PcmBuffers::default (); - tracing::debug! ("Constructed decoder"); - - sleep (Duration::from_secs (3)); - tracing::debug! ("Decoding..."); + let mut f = File::create ("pcm-dump.data")?; + 'decoding: loop { - while pcm_buffers.samples_available () < 48_000 { + while pcm_buffers.samples_available () < 12_000 { if ! decoder.fill_buffer (&mut pcm_buffers)? { tracing::info! ("Decoder finished"); break 'decoding; @@ -60,29 +65,16 @@ fn cmd_debug (args: &[String]) -> Result <()> { } while pcm_buffers.samples_available () > 0 { - let mut buf = vec! [0.0f32; pcm_buffers.samples_available ()]; - pcm_buffers.consume_exact (&mut buf); + let mut src = vec! [0.0f32; pcm_buffers.samples_available ()]; + // dbg! (src.len ()); + pcm_buffers.consume_exact (&mut src); + let mut dest = vec! [0; src.len () * 4]; + LittleEndian::write_f32_into (&src, &mut dest); + + f.write_all (&dest)?; } } - sleep (Duration::from_secs (3)); - - tracing::debug! ("Dropping resampler..."); - dbg! (decoder.resampler.delay ()); - - drop (decoder.resampler); - sleep (Duration::from_secs (3)); - - tracing::debug! ("Dropping decoder..."); - - drop (decoder.decoder); - sleep (Duration::from_secs (3)); - - tracing::debug! ("Dropping input_ctx..."); - - drop (decoder.input_ctx); - sleep (Duration::from_secs (3)); - Ok (()) } @@ -108,7 +100,7 @@ fn cmd_play (args: &[String]) -> Result <()> { // tracing::trace! ("decode thread parking"); let mut decoder_state = cvar.wait_while (lock.lock ().unwrap (), |decoder_state| { - decoder_state.pcm_buffers.samples_available () >= 48_000 && + decoder_state.pcm_buffers.samples_available () >= 12_000 && ! decoder_state.quit }).unwrap (); @@ -120,7 +112,7 @@ fn cmd_play (args: &[String]) -> Result <()> { let pcm_buffers = &mut decoder_state.pcm_buffers; - while pcm_buffers.samples_available () < 96_000 { + while pcm_buffers.samples_available () < 12_000 { // tracing::trace! ("Decoder is trying to work..."); if ! decoder.fill_buffer (pcm_buffers)? { tracing::info! ("Finished decoding file"); @@ -152,10 +144,16 @@ fn cmd_play (args: &[String]) -> Result <()> { move |data: &mut [f32], _: &cpal::OutputCallbackInfo| { let (lock, cvar) = &*pair; + let time_start = Instant::now (); let mut decoder_state = match lock.lock () { Ok (x) => x, Err (_) => return, }; + let time_stop = Instant::now (); + let dur = time_stop - time_start; + if dur.as_micros () > 1 { + dbg! (dur.as_micros ()); + } let pcm_buffers = &mut decoder_state.pcm_buffers; @@ -167,6 +165,7 @@ fn cmd_play (args: &[String]) -> Result <()> { } let (lock, cvar) = &*pcm_quit; + let mut pcm_quit = lock.lock ().unwrap (); *pcm_quit = true; cvar.notify_one (); @@ -251,9 +250,6 @@ mod test { } } - assert_eq! (packet_count, 5496); - assert_eq! (frame_count, 5496); - Ok (()) } }