diff options
author | Kostya Shishkov <kostya.shishkov@gmail.com> | 2024-07-27 15:58:56 +0200 |
---|---|---|
committer | Kostya Shishkov <kostya.shishkov@gmail.com> | 2024-07-27 15:58:56 +0200 |
commit | 6abff179ae3058d41de917738e52a1d42295e0e0 (patch) | |
tree | 69abd8b5d9dfdddb673a9561b0b5bf136f724637 | |
parent | b3085ea9e5a22776e5bbc9a948a7fbfdda8d3520 (diff) | |
download | nihav-6abff179ae3058d41de917738e52a1d42295e0e0.tar.gz |
vx demuxer: implement seeking
-rw-r--r-- | nihav-game/src/demuxers/vx.rs | 56 |
1 files changed, 42 insertions, 14 deletions
diff --git a/nihav-game/src/demuxers/vx.rs b/nihav-game/src/demuxers/vx.rs index d6830c6..4a47298 100644 --- a/nihav-game/src/demuxers/vx.rs +++ b/nihav-game/src/demuxers/vx.rs @@ -8,13 +8,14 @@ struct VXDemuxer<'a> { src: &'a mut ByteReader<'a>, vid_id: usize, aud_id: usize, + fps: u32, video_pos: u64, - num_vid: usize, vno: u64, num_vfrm: u64, num_aud: usize, ano: u64, num_afrm: u64, + seektab: Vec<(u32, u32)>, } impl<'a> DemuxCore<'a> for VXDemuxer<'a> { @@ -40,10 +41,7 @@ impl<'a> DemuxCore<'a> for VXDemuxer<'a> { validate!(audio_off == 0 || audio_off >= 0x30); let vinfo_off = src.read_u32le()? as u64; validate!(vinfo_off == 0 || vinfo_off >= 0x30); - let num_vstreams = src.read_u32le()? as usize; - if num_vstreams != 1 || num_audio_tracks > 2 { - return Err(DemuxerError::NotImplemented); - } + let num_keypos = src.read_u32le()? as usize; let vhdr = NAVideoInfo::new(width, height, false, YUV420_FORMAT); let vci = NACodecTypeInfo::Video(vhdr); @@ -64,16 +62,25 @@ impl<'a> DemuxCore<'a> for VXDemuxer<'a> { self.num_aud = num_audio_tracks; } - if num_vstreams > 0 { + if num_keypos > 0 { src.seek(SeekFrom::Start(vinfo_off))?; - for _ in 0..num_vstreams { - let _smth = src.read_u32le()?; - let offset = src.read_u32le()? as u64; - self.video_pos = offset; + let mut last_frame = src.read_u32le()?; + let mut last_offset = src.read_u32le()?; + validate!(last_frame == 0 && last_offset == 0x30); + self.seektab.clear(); + self.seektab.push((last_frame, last_offset)); + for _ in 1..num_keypos { + let frameno = src.read_u32le()?; + let offset = src.read_u32le()?; + validate!(frameno > last_frame && offset > last_offset); + self.seektab.push((frameno, offset)); + last_frame = frameno; + last_offset = offset; } } - self.num_vid = num_vstreams; + self.fps = fps; + self.video_pos = 0x30; self.vno = 0; self.num_vfrm = nframes as u64; Ok(()) @@ -99,8 +106,28 @@ impl<'a> DemuxCore<'a> for VXDemuxer<'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.seektab.len() < 2 { + Err(DemuxerError::NotPossible) + } else { + let fno = match time { + NATimePoint::Milliseconds(ms) => { + NATimeInfo::time_to_ts(ms, 1000, 65536, self.fps) + }, + NATimePoint::PTS(ts) => ts, + NATimePoint::None => return Err(DemuxerError::NotPossible) + }; + if fno >= self.num_vfrm { + return Err(DemuxerError::SeekError); + } + let idx = match self.seektab.binary_search_by_key(&fno, |&(frm, _)| u64::from(frm)) { + Ok(val) => val, + Err(val) => val - 1, + }; + self.vno = u64::from(self.seektab[idx].0); + self.video_pos = u64::from(self.seektab[idx].1); + Ok(()) + } } fn get_duration(&self) -> u64 { 0 } @@ -117,14 +144,15 @@ impl<'a> VXDemuxer<'a> { Self { vid_id: 0, aud_id: 0, + fps: 0, video_pos: 0, - num_vid: 0, num_aud: 0, vno: 0, ano: 0, num_vfrm: 0, num_afrm: 0, src: io, + seektab: Vec::new(), } } } |