From: Kostya Shishkov Date: Thu, 2 Oct 2025 16:33:23 +0000 (+0200) Subject: vmd: implement optional seeking to arbitrary position X-Git-Url: https://git.nihav.org/?a=commitdiff_plain;h=69a08d7e4bf875bfa9c5200d51dbae796ac80aa9;p=nihav.git vmd: implement optional seeking to arbitrary position --- diff --git a/nihav-game/src/codecs/vmd.rs b/nihav-game/src/codecs/vmd.rs index 02c76dd..82da8da 100644 --- a/nihav-game/src/codecs/vmd.rs +++ b/nihav-game/src/codecs/vmd.rs @@ -329,6 +329,9 @@ impl NADecoder for VMDVideoDecoder { Ok(frm.into_ref()) } fn flush(&mut self) { + for el in self.framebuf.iter_mut() { + *el = 0; + } } } diff --git a/nihav-game/src/demuxers/vmd.rs b/nihav-game/src/demuxers/vmd.rs index fd48a66..41c14aa 100644 --- a/nihav-game/src/demuxers/vmd.rs +++ b/nihav-game/src/demuxers/vmd.rs @@ -28,6 +28,7 @@ struct VMDDemuxer<'a> { is_indeo: bool, is_lhaud: bool, frames: Vec, + force_seek: bool, } impl<'a> DemuxCore<'a> for VMDDemuxer<'a> { @@ -178,17 +179,55 @@ impl<'a> DemuxCore<'a> for VMDDemuxer<'a> { Ok(pkt) } - fn seek(&mut self, _time: NATimePoint, _seek_index: &SeekIndex) -> DemuxerResult<()> { - Err(DemuxerError::NotPossible) + fn seek(&mut self, time: NATimePoint, _seek_index: &SeekIndex) -> DemuxerResult<()> { + if !self.force_seek { + Err(DemuxerError::NotPossible) + } else { + let seek_ts = match time { + NATimePoint::Milliseconds(ms) => ms * 12 / 1000, + NATimePoint::PTS(ts) => ts, + _ => return Err(DemuxerError::SeekError), + }; + let mut fno = 0; + for frame in self.frames.iter() { + if frame.chtype == CHTYPE_VIDEO && u64::from(frame.ts) >= seek_ts { + break; + } + fno += 1; + } + if fno >= self.frames.len() { + return Err(DemuxerError::SeekError); + } + self.fno = fno; + Ok(()) + } } fn get_duration(&self) -> u64 { 0 } } +const DEMUXER_OPTS: &[NAOptionDefinition] = &[ + NAOptionDefinition { + name: FORCE_SEEK_OPTION, description: FORCE_SEEK_OPTION_DESC, + opt_type: NAOptionDefinitionType::Bool }, +]; + impl<'a> NAOptionHandler for VMDDemuxer<'a> { - fn get_supported_options(&self) -> &[NAOptionDefinition] { &[] } - fn set_options(&mut self, _options: &[NAOption]) { } - fn query_option_value(&self, _name: &str) -> Option { None } + fn get_supported_options(&self) -> &[NAOptionDefinition] { DEMUXER_OPTS } + fn set_options(&mut self, options: &[NAOption]) { + for option in options.iter() { + if let NAOption { name: FORCE_SEEK_OPTION, value: NAValue::Bool(ref bval) } = option { + self.force_seek = *bval; + } + } + } + fn query_option_value(&self, name: &str) -> Option { + if name == FORCE_SEEK_OPTION { + Some(NAValue::Bool(self.force_seek)) + } else { + None + } + } } impl<'a> VMDDemuxer<'a> { @@ -201,6 +240,7 @@ impl<'a> VMDDemuxer<'a> { is_indeo: false, is_lhaud: false, frames: Vec::new(), + force_seek: false, } } }