From: Kostya Shishkov Date: Tue, 10 Feb 2026 17:38:00 +0000 (+0100) Subject: videoplayer: (hopefully) fix near-end seek issues X-Git-Url: https://git.nihav.org/?a=commitdiff_plain;h=57f57a5860b3fd34d0422e334676ee17b49da452;p=nihav-player.git videoplayer: (hopefully) fix near-end seek issues The original design was simple: get last frames, end decoding. Unfortunately, this did not take into account that user may want to rewind video at the last moment. In such case playback would either end or lock up waiting for the video decoding thread (that has finished by this point) to send a reply. Hence the need to reset "at the end" state in various places of the player. --- diff --git a/videoplayer/src/main.rs b/videoplayer/src/main.rs index 8b1bbaa..bcc210b 100644 --- a/videoplayer/src/main.rs +++ b/videoplayer/src/main.rs @@ -464,6 +464,7 @@ struct Player { mute: bool, volume: usize, end: bool, + seeked: bool, tkeep: TimeKeep, @@ -513,6 +514,7 @@ impl Player { mute: false, volume: 100, end: false, + seeked: false, tkeep: TimeKeep::new(), @@ -537,6 +539,8 @@ impl Player { return Ok(()); //TODO: not ignore some of seek errors? } + self.seeked = true; + self.acontrol.flush(); self.vcontrol.flush(); disp_queue.flush(); @@ -576,7 +580,11 @@ impl Player { } if try_send { match dmx.get_frame() { - Err(DemuxerError::EOF) => break, + 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(); @@ -1010,6 +1018,7 @@ impl Player { let mut last_disp = Instant::now(); let mut has_data = true; 'main: loop { + self.seeked = false; let ret = self.handle_events(&mut event_pump, &mut canvas, &mut dmx, &mut disp_q); if matches!(ret, Ok(true) | Err(_)) { if !self.quiet { @@ -1017,6 +1026,9 @@ impl Player { } break 'main; } + if self.seeked { + has_data = true; + } if !self.paused { let mut try_send = self.acontrol.get_queue_size() < FRAME_QUEUE_LEN && self.vcontrol.get_queue_size() < FRAME_QUEUE_LEN; if !self.vcontrol.try_send_queued() && self.vcontrol.is_filled(FRAME_QUEUE_LEN) { diff --git a/videoplayer/src/videodec.rs b/videoplayer/src/videodec.rs index ea6ca72..b8add27 100644 --- a/videoplayer/src/videodec.rs +++ b/videoplayer/src/videodec.rs @@ -282,7 +282,9 @@ fn start_video_decoding(width: usize, height: usize, tb_num: u32, tb_den: u32, v while let Some((buf, time)) = vdec.more_frames(false) { vfsend.send((buf, time)).expect("video frame should be sent"); } - VDEC_STATE.set_state(DecodingState::Waiting); + if VDEC_STATE.get_state() != DecodingState::End { + VDEC_STATE.set_state(DecodingState::Waiting); + } }, Ok(PktSendEvent::Flush) => { vdec.flush(); @@ -297,7 +299,6 @@ fn start_video_decoding(width: usize, height: usize, tb_num: u32, tb_den: u32, v } } VDEC_STATE.set_state(DecodingState::End); - break; }, Ok(PktSendEvent::ImmediateEnd) => { VDEC_STATE.set_state(DecodingState::End); @@ -433,6 +434,9 @@ impl VideoControl { matches!(VDEC_STATE.get_state(), DecodingState::End | DecodingState::Error) } pub fn wait_for_frames(&mut self) -> Result<(), ()> { + if self.is_video_end() { + return Ok(()); + } VDEC_STATE.set_state(DecodingState::Prefetch); self.try_send_event(PktSendEvent::GetFrames); while !self.try_send_queued() {