From e5bf23008ea53cee3efa716627062302143ba215 Mon Sep 17 00:00:00 2001 From: Kostya Shishkov Date: Sat, 14 Feb 2026 20:16:29 +0100 Subject: [PATCH] videoplayer: improve prefill code Previously prefill would fail with hardware-accelerated H.264 decoder since it starts output after 16 frames and prefill gives up after sending fewer packets. Repeating the cycle of sending packets and collecting frames should fix that. --- videoplayer/src/main.rs | 84 +++++++++++++++++++++++------------------ 1 file changed, 48 insertions(+), 36 deletions(-) diff --git a/videoplayer/src/main.rs b/videoplayer/src/main.rs index 96b4531..83e162b 100644 --- a/videoplayer/src/main.rs +++ b/videoplayer/src/main.rs @@ -569,47 +569,59 @@ impl Player { } fn prefill(&mut self, dmx: &mut DemuxerObject, disp_queue: &mut DispQueue) -> Result<(), ()> { debug_log!(self; {" prefilling"}); - while self.vcontrol.get_queue_size() < FRAME_QUEUE_LEN { - let mut try_send = self.acontrol.get_queue_size() < FRAME_QUEUE_LEN && (!self.has_video || (!self.vcontrol.is_filled(FRAME_QUEUE_LEN) && !disp_queue.is_full())); - - if !self.vcontrol.try_send_queued() && self.vcontrol.get_queue_size() > FRAME_QUEUE_LEN / 2 { - try_send = false; - } - if !self.acontrol.try_send_queued() && self.acontrol.get_queue_size() > FRAME_QUEUE_LEN / 2 { - try_send = false; - } - if try_send { - match dmx.get_frame() { - Err(DemuxerError::EOF) => { - self.vcontrol.try_send_video(PktSendEvent::End); - self.acontrol.try_send_audio(PktSendEvent::End); - break; - }, - Err(_) => break, - Ok(pkt) => { - let streamno = pkt.get_stream().get_id(); - if self.has_video && streamno == self.video_str { - self.vcontrol.try_send_video(PktSendEvent::Packet(pkt)); - } else if self.has_audio && streamno == self.audio_str { - self.acontrol.try_send_audio(PktSendEvent::Packet(pkt)); + let mut got_video = !self.has_video; + let mut got_audio = !self.has_audio; + while !(got_video && got_audio) { + // phase 1 - try to send packets for decoding + loop { + let mut try_send = self.acontrol.get_queue_size() < FRAME_QUEUE_LEN && (!self.has_video || (!self.vcontrol.is_filled(FRAME_QUEUE_LEN) && !disp_queue.is_full())); + + if !self.vcontrol.try_send_queued() && self.vcontrol.get_queue_size() > FRAME_QUEUE_LEN / 2 { + try_send = false; + } + if !self.acontrol.try_send_queued() && self.acontrol.get_queue_size() > FRAME_QUEUE_LEN / 2 { + try_send = false; + } + if try_send { + match dmx.get_frame() { + Err(DemuxerError::EOF) => { + self.vcontrol.try_send_video(PktSendEvent::End); + self.acontrol.try_send_audio(PktSendEvent::End); + break; + }, + Err(_) => break, + Ok(pkt) => { + let streamno = pkt.get_stream().get_id(); + if self.has_video && streamno == self.video_str { + self.vcontrol.try_send_video(PktSendEvent::Packet(pkt)); + } else if self.has_audio && streamno == self.audio_str { + self.acontrol.try_send_audio(PktSendEvent::Packet(pkt)); + } } - } - }; - } - self.vcontrol.fill(disp_queue); + }; + } + self.vcontrol.fill(disp_queue); - if !try_send { - break; + if !try_send { + break; + } } - } - if self.has_video { - while self.vcontrol.get_queue_size() > 0 && !disp_queue.is_full() { - self.vcontrol.try_send_queued(); + // phase 2 - retrieve available data + if self.has_video { + while self.vcontrol.get_queue_size() > 0 && !disp_queue.is_full() { + self.vcontrol.try_send_queued(); + self.vcontrol.fill(disp_queue); + std::thread::sleep(Duration::from_millis(5)); + } + self.vcontrol.wait_for_frames()?; self.vcontrol.fill(disp_queue); - std::thread::sleep(Duration::from_millis(10)); + if disp_queue.is_full() { + got_video = true; + } + } + if self.has_audio && self.acontrol.get_fill() > 0 { + got_audio = true; } - self.vcontrol.wait_for_frames()?; - self.vcontrol.fill(disp_queue); } debug_log!(self; {format!(" prefilling done, frames {}-{} audio {}", disp_queue.start, disp_queue.end, self.acontrol.get_fill())}); Ok(()) -- 2.39.5