🐛 bug: popping is gone

It was a combination of two bugs:

1. For some reason, libswresample sometimes returns more data than you need.
Like, it'll return X samples but _more than_ 8X bytes, for f32 stereo.

2. I wasn't supposed to be calling `flush`. I should have been calling
`run` with a dummy frame. This isn't intuitive to me, and it required
me to construct a dummy frame and keep it around in my code. I think
this is pretty inelegant. And looking at the ffmpeg code, I think it's
a flaw in the API design of the `ffmpeg_next` crate. I may ask them
about it in the future.
main
_ 2021-11-13 11:23:10 -06:00
parent 9c3368f28b
commit 68461866d8
2 changed files with 33 additions and 36 deletions

View File

@ -84,9 +84,11 @@ pub struct SharedState {
pub struct Decoder { pub struct Decoder {
pub input_ctx: DemuxContext, pub input_ctx: DemuxContext,
best_stream_idx: usize,
pub decoder: DecodeContext, pub decoder: DecodeContext,
pub resampler: ResamplingContext, pub resampler: ResamplingContext,
best_stream_idx: usize,
dummy_frame: Option <AudioFrame>,
} }
impl Decoder { impl Decoder {
@ -107,9 +109,11 @@ impl Decoder {
Ok (Self { Ok (Self {
input_ctx, input_ctx,
best_stream_idx,
decoder, decoder,
resampler, resampler,
best_stream_idx,
dummy_frame: None,
}) })
} }
@ -133,8 +137,8 @@ impl Decoder {
if actual_bytes > expected_bytes { if actual_bytes > expected_bytes {
let extra_bytes = actual_bytes - expected_bytes; let extra_bytes = actual_bytes - expected_bytes;
let extra_samples = extra_bytes / 4 / 2; let extra_samples = extra_bytes / 4 / 2;
tracing::debug! ("Extra bytes: {}", extra_bytes); // tracing::debug! ("Extra bytes: {}", extra_bytes);
tracing::debug! ("Extra samples: {}", extra_samples); // tracing::debug! ("Extra samples: {}", extra_samples);
} }
Some (frame) Some (frame)
@ -175,26 +179,18 @@ impl Decoder {
} }
pub fn pump_resampler (&mut self) -> Result <Option <AudioFrame>> { pub fn pump_resampler (&mut self) -> Result <Option <AudioFrame>> {
let delay = match self.resampler.delay () { let frame_src = match self.dummy_frame.as_ref () {
None => return Ok (None), None => return Ok (None),
Some (x) => x, Some (x) => x,
}; };
let mut frame_src = AudioFrame::new (
Sample::F32 (sample::Type::Planar),
0,
ChannelLayout::STEREO
);
let mut frame_resampled = Self::new_frame (); let mut frame_resampled = Self::new_frame ();
frame_src.set_rate (44100);
tracing::trace! ("Flushing resampler");
tracing::trace! ("delay: {:?}", delay);
let _rc = self.resampler.run (&frame_src, &mut frame_resampled)?; let _rc = self.resampler.run (&frame_src, &mut frame_resampled)?;
// dbg! (&frame_resampled, rc); // dbg! (&frame_resampled, rc);
Ok (if frame_resampled.samples () > 0 { Ok (if frame_resampled.samples () > 0 {
// tracing::trace! ("Pulled from resampler FIFO");
Some (frame_resampled) Some (frame_resampled)
} }
else { else {
@ -203,28 +199,31 @@ impl Decoder {
} }
pub fn pump_decoder (&mut self) -> Result <Option <AudioFrame>> { pub fn pump_decoder (&mut self) -> Result <Option <AudioFrame>> {
let mut frame_src = ffmpeg_next::util::frame::Audio::empty (); let mut frame_src = AudioFrame::empty ();
let rc = self.decoder.receive_frame (&mut frame_src); if let Err (_) = self.decoder.receive_frame (&mut frame_src) {
// dbg! (&rc); return Ok (None);
Ok (if rc.is_ok () { };
// dbg! (&frame_src);
if self.dummy_frame.is_none () {
//let nb_output_samples = frame_src.samples () * SAMPLE_RATE as usize / frame_src.rate () as usize; let mut dummy_frame = AudioFrame::new (
frame_src.format (),
let nb_output_samples = frame_src.samples (); 0,
frame_src.channel_layout (),
let mut frame_resampled = AudioFrame::new (
Sample::F32 (sample::Type::Packed),
nb_output_samples,
ChannelLayout::STEREO
); );
dummy_frame.set_rate (frame_src.rate ());
self.resampler.run (&frame_src, &mut frame_resampled)?; self.dummy_frame = Some (dummy_frame);
Some (frame_resampled)
} }
else {
None let nb_output_samples = frame_src.samples ();
})
let mut frame_resampled = AudioFrame::new (
Sample::F32 (sample::Type::Packed),
nb_output_samples,
ChannelLayout::STEREO
);
self.resampler.run (&frame_src, &mut frame_resampled)?;
Ok (Some (frame_resampled))
} }
pub fn pump_demuxer (&mut self) -> Result <bool> { pub fn pump_demuxer (&mut self) -> Result <bool> {

View File

@ -1,3 +1 @@
# Critical # Critical
- Popping every 1-3 seconds-ish