initial seeking support
authorKostya Shishkov <kostya.shishkov@gmail.com>
Wed, 13 Nov 2019 18:41:45 +0000 (19:41 +0100)
committerKostya Shishkov <kostya.shishkov@gmail.com>
Wed, 13 Nov 2019 18:41:45 +0000 (19:41 +0100)
nihav-commonfmt/src/demuxers/avi.rs
nihav-core/src/demuxers/mod.rs
nihav-game/src/demuxers/bmv.rs
nihav-game/src/demuxers/gdv.rs
nihav-game/src/demuxers/vmd.rs
nihav-rad/src/demuxers/bink.rs
nihav-rad/src/demuxers/smacker.rs
nihav-realmedia/src/demuxers/realmedia.rs

index cf66f36885438d1052c8c83bb2f967956d86e2ce..6603b5705a1f32691378eacb4bfcad0004e48171 100644 (file)
@@ -41,6 +41,8 @@ struct AVIDemuxer<'a> {
     num_streams:    u8,
     size:           usize,
     movi_size:      usize,
+    movi_pos:       u64,
+    movi_orig:      usize,
     sstate:         StreamState,
     tb_num:         u32,
     tb_den:         u32,
@@ -59,7 +61,7 @@ struct RIFFParser {
 
 impl<'a> DemuxCore<'a> for AVIDemuxer<'a> {
     #[allow(unused_variables)]
-    fn open(&mut self, strmgr: &mut StreamManager) -> DemuxerResult<()> {
+    fn open(&mut self, strmgr: &mut StreamManager, seek_index: &mut SeekIndex) -> DemuxerResult<()> {
         self.read_header(strmgr)?;
         Ok(())
     }
@@ -112,9 +114,21 @@ impl<'a> DemuxCore<'a> for AVIDemuxer<'a> {
         }
     }
 
-    #[allow(unused_variables)]
-    fn seek(&mut self, time: u64) -> DemuxerResult<()> {
-        Err(NotImplemented)
+    fn seek(&mut self, time: u64, seek_index: &SeekIndex) -> DemuxerResult<()> {
+        let ret = seek_index.find_pos(time);
+        if ret.is_none() {
+            return Err(DemuxerError::SeekError);
+        }
+        let pos = ret.unwrap().pos;
+        self.src.seek(SeekFrom::Start(pos))?;
+
+        let cur_pos = self.src.tell();
+        if cur_pos < self.movi_pos { return Err(DemuxerError::SeekError); }
+        let skip_size = (cur_pos - self.movi_pos) as usize;
+        if skip_size > self.movi_size { return Err(DemuxerError::SeekError); }
+        self.movi_size = self.movi_orig - skip_size;
+
+        Ok(())
     }
 }
 
@@ -126,6 +140,8 @@ impl<'a> AVIDemuxer<'a> {
             src: io,
             size: 0,
             movi_size: 0,
+            movi_pos:  0,
+            movi_orig: 0,
             sstate: StreamState::new(),
             tb_num: 0,
             tb_den: 0,
@@ -200,9 +216,15 @@ impl<'a> AVIDemuxer<'a> {
         let mut rest_size = size;
         loop {
             let (csz, end) = self.parse_chunk(strmgr, RIFFTag::List(mktag!(b"LIST"), mktag!(b"movi")), rest_size,0)?;
-            if end { self.movi_size = csz - 4; break; }
+            if end {
+                self.movi_size = csz - 4;
+                self.movi_orig = self.movi_size;
+                self.movi_pos = self.src.tell();
+                break;
+            }
             rest_size -= csz;
         }
+//todo read index
         if !self.sstate.valid_state() || self.sstate.strm_no != self.num_streams {
             return Err(InvalidData);
         }
index 902fbba4db578fd74bc05e3e2a32fed22fb41012..405d88d6f4e528a446e13389d64adbdda0aa0f7d 100644 (file)
@@ -11,14 +11,16 @@ pub enum DemuxerError {
     NotImplemented,
     MemoryError,
     TryAgain,
+    SeekError,
+    NotPossible,
 }
 
 pub type DemuxerResult<T> = Result<T, DemuxerError>;
 
 pub trait DemuxCore<'a> {
-    fn open(&mut self, strmgr: &mut StreamManager) -> DemuxerResult<()>;
+    fn open(&mut self, strmgr: &mut StreamManager, seek_idx: &mut SeekIndex) -> DemuxerResult<()>;
     fn get_frame(&mut self, strmgr: &mut StreamManager) -> DemuxerResult<NAPacket>;
-    fn seek(&mut self, time: u64) -> DemuxerResult<()>;
+    fn seek(&mut self, time: u64, seek_idx: &SeekIndex) -> DemuxerResult<()>;
 }
 
 pub trait NAPacketReader {
@@ -136,16 +138,121 @@ impl<'a> Iterator for StreamIter<'a> {
     }
 }
 
+#[derive(Clone,Copy,PartialEq)]
+pub enum SeekIndexMode {
+    None,
+    Present,
+    Automatic,
+}
+
+impl Default for SeekIndexMode {
+    fn default() -> Self { SeekIndexMode::None }
+}
+
+#[derive(Clone,Copy,Default)]
+pub struct SeekEntry {
+    pub pts:    u64,
+    pub pos:    u64,
+}
+
+#[derive(Clone)]
+pub struct StreamSeekInfo {
+    pub id:         u32,
+    pub tb_num:     u32,
+    pub tb_den:     u32,
+    pub filled:     bool,
+    pub entries:    Vec<SeekEntry>,
+}
+
+impl StreamSeekInfo {
+    pub fn new(id: u32, tb_num: u32, tb_den: u32) -> Self {
+        Self {
+            id, tb_num, tb_den,
+            filled:     false,
+            entries:    Vec::new(),
+        }
+    }
+    pub fn add_entry(&mut self, entry: SeekEntry) {
+        self.entries.push(entry);
+    }
+    pub fn find_pos(&self, pts: u64) -> Option<u64> {
+        if !self.entries.is_empty() {
+// todo something faster like binary search
+            let mut cand = 0;
+            for (idx, entry) in self.entries.iter().enumerate() {
+                if entry.pts <= pts {
+                    cand = idx;
+                } else {
+                    break;
+                }
+            }
+            Some(self.entries[cand].pos)
+        } else {
+            None
+        }
+    }
+}
+
+#[derive(Clone,Copy,Default)]
+pub struct SeekIndexResult {
+    pub pts:        u64,
+    pub pos:        u64,
+    pub str_id:     u32,
+}
+
+#[derive(Default)]
+pub struct SeekIndex {
+    pub seek_info:  Vec<StreamSeekInfo>,
+    pub mode:       SeekIndexMode,
+}
+
+impl SeekIndex {
+    pub fn new() -> Self { Self::default() }
+    pub fn add_stream(&mut self, id: u32, tb_num: u32, tb_den: u32) {
+        if self.stream_id_to_index(id).is_none() {
+            self.seek_info.push(StreamSeekInfo::new(id, tb_num, tb_den));
+        }
+    }
+    pub fn stream_id_to_index(&self, id: u32) -> Option<usize> {
+        for (idx, str) in self.seek_info.iter().enumerate() {
+            if str.id == id {
+                return Some(idx);
+            }
+        }
+        None
+    }
+    pub fn find_pos(&self, time: u64) -> Option<SeekIndexResult> {
+        let mut cand = None;
+        for str in self.seek_info.iter() {
+            if !str.filled { continue; }
+            let pts = NATimeInfo::time_to_ts(time, 1000, str.tb_num, str.tb_den);
+            let pos = str.find_pos(pts);
+            if pos.is_none() { continue; }
+            let pos = pos.unwrap();
+            if cand.is_none() {
+                cand = Some(SeekIndexResult { pts, pos, str_id: str.id });
+            } else if let Some(entry) = cand {
+                if pos < entry.pos {
+                    cand = Some(SeekIndexResult { pts, pos, str_id: str.id });
+                }
+            }
+        }
+        cand
+    }
+}
+
 pub struct Demuxer<'a> {
     dmx:        Box<dyn DemuxCore<'a> + 'a>,
     streams:    StreamManager,
+    seek_idx:   SeekIndex,
 }
 
 impl<'a> Demuxer<'a> {
-    fn new(dmx: Box<dyn DemuxCore<'a> + 'a>, str: StreamManager) -> Self {
+    fn new(dmx: Box<dyn DemuxCore<'a> + 'a>, str: StreamManager, seek_idx: SeekIndex) -> Self {
         Demuxer {
             dmx,
             streams:    str,
+            seek_idx,
         }
     }
     pub fn get_stream(&self, idx: usize) -> Option<NAStreamRef> {
@@ -182,7 +289,10 @@ impl<'a> Demuxer<'a> {
         }
     }
     pub fn seek(&mut self, time: u64) -> DemuxerResult<()> {
-        self.dmx.seek(time)
+        self.dmx.seek(time, &self.seek_idx)
+    }
+    pub fn get_seek_index(&self) -> &SeekIndex {
+        &self.seek_idx
     }
 }
 
@@ -201,8 +311,9 @@ pub trait DemuxerCreator {
 pub fn create_demuxer<'a>(dmxcr: &DemuxerCreator, br: &'a mut ByteReader<'a>) -> DemuxerResult<Demuxer<'a>> {
     let mut dmx = dmxcr.new_demuxer(br);
     let mut str = StreamManager::new();
-    dmx.open(&mut str)?;
-    Ok(Demuxer::new(dmx, str))
+    let mut seek_idx = SeekIndex::new();
+    dmx.open(&mut str, &mut seek_idx)?;
+    Ok(Demuxer::new(dmx, str, seek_idx))
 }
 
 #[derive(Default)]
index afb17317c152da7a6d7c816ff595968f7cd622c5..44e9193998c9d43c2cb98d1a845ca6003f701428 100644 (file)
@@ -12,7 +12,7 @@ struct BMVDemuxer<'a> {
 
 impl<'a> DemuxCore<'a> for BMVDemuxer<'a> {
     #[allow(unused_variables)]
-    fn open(&mut self, strmgr: &mut StreamManager) -> DemuxerResult<()> {
+    fn open(&mut self, strmgr: &mut StreamManager, _seek_index: &mut SeekIndex) -> DemuxerResult<()> {
         let src = &mut self.src;
 
         let vhdr = NAVideoInfo::new(640, 429, false, PAL8_FORMAT);
@@ -70,9 +70,8 @@ impl<'a> DemuxCore<'a> for BMVDemuxer<'a> {
         }
     }
 
-    #[allow(unused_variables)]
-    fn seek(&mut self, time: u64) -> DemuxerResult<()> {
-        Err(DemuxerError::NotImplemented)
+    fn seek(&mut self, _time: u64, _seek_index: &SeekIndex) -> DemuxerResult<()> {
+        Err(DemuxerError::NotPossible)
     }
 }
 
@@ -111,7 +110,7 @@ struct BMV3Demuxer<'a> {
 
 impl<'a> DemuxCore<'a> for BMV3Demuxer<'a> {
     #[allow(unused_variables)]
-    fn open(&mut self, strmgr: &mut StreamManager) -> DemuxerResult<()> {
+    fn open(&mut self, strmgr: &mut StreamManager, _seek_index: &mut SeekIndex) -> DemuxerResult<()> {
         let src = &mut self.src;
 
         let mut magic = [0u8; 4];
@@ -212,9 +211,8 @@ impl<'a> DemuxCore<'a> for BMV3Demuxer<'a> {
         }
     }
 
-    #[allow(unused_variables)]
-    fn seek(&mut self, time: u64) -> DemuxerResult<()> {
-        Err(DemuxerError::NotImplemented)
+    fn seek(&mut self, _time: u64, _seek_index: &SeekIndex) -> DemuxerResult<()> {
+        Err(DemuxerError::NotPossible)
     }
 }
 
index 6f27cc4f8119ec278caee605c272a32ca3a43e96..b70e344a8782a0eea7a69db695347184356df60b 100644 (file)
@@ -48,7 +48,7 @@ const GDV_SIZE_TABLE: &[GDVFixedSizes] = &[
 
 impl<'a> DemuxCore<'a> for GremlinVideoDemuxer<'a> {
     #[allow(unused_variables)]
-    fn open(&mut self, strmgr: &mut StreamManager) -> DemuxerResult<()> {
+    fn open(&mut self, strmgr: &mut StreamManager, _seek_index: &mut SeekIndex) -> DemuxerResult<()> {
         let src = &mut self.src;
         let magic = src.read_u32le()?;
         if magic != 0x29111994 { return Err(DemuxerError::InvalidData); }
@@ -110,9 +110,8 @@ impl<'a> DemuxCore<'a> for GremlinVideoDemuxer<'a> {
         }
     }
 
-    #[allow(unused_variables)]
-    fn seek(&mut self, time: u64) -> DemuxerResult<()> {
-        Err(DemuxerError::NotImplemented)
+    fn seek(&mut self, _time: u64, _seek_index: &SeekIndex) -> DemuxerResult<()> {
+        Err(DemuxerError::NotPossible)
     }
 }
 /*impl<'a> Drop for GremlinVideoDemuxer<'a> {
index cc4ac0ee8707d3ae3ed0eadd540837cd003b0105..0c47f89cf5600438a28b360fca0c2739640bc9ab 100644 (file)
@@ -28,7 +28,7 @@ struct VMDDemuxer<'a> {
 
 impl<'a> DemuxCore<'a> for VMDDemuxer<'a> {
     #[allow(unused_variables)]
-    fn open(&mut self, strmgr: &mut StreamManager) -> DemuxerResult<()> {
+    fn open(&mut self, strmgr: &mut StreamManager, _seek_index: &mut SeekIndex) -> DemuxerResult<()> {
         let src = &mut self.src;
 
         let mut header: [u8; HEADER_SIZE] = [0; HEADER_SIZE];
@@ -149,9 +149,8 @@ impl<'a> DemuxCore<'a> for VMDDemuxer<'a> {
         Ok(pkt)
     }
 
-    #[allow(unused_variables)]
-    fn seek(&mut self, time: u64) -> DemuxerResult<()> {
-        Err(DemuxerError::NotImplemented)
+    fn seek(&mut self, _time: u64, _seek_index: &SeekIndex) -> DemuxerResult<()> {
+        Err(DemuxerError::NotPossible)
     }
 }
 
index 29427af1bab54b6df777cca6b2c9e1801cb58641..bdbf0c5b99ef30525b9f795b42c91c945ef09328 100644 (file)
@@ -49,7 +49,7 @@ macro_rules! mktag {
 }
 
 impl<'a> DemuxCore<'a> for BinkDemuxer<'a> {
-    fn open(&mut self, strmgr: &mut StreamManager) -> DemuxerResult<()> {
+    fn open(&mut self, strmgr: &mut StreamManager, seek_idx: &mut SeekIndex) -> DemuxerResult<()> {
         let src = &mut self.src;
         let mut magic: [u8; 4] = [0; 4];
                                               src.read_buf(&mut magic)?;
@@ -97,12 +97,18 @@ impl<'a> DemuxCore<'a> for BinkDemuxer<'a> {
             let _trk_id                     = src.read_u32le()?;
         }
 
+        seek_idx.mode = SeekIndexMode::Present;
+        seek_idx.add_stream(0, tb_num, tb_den);
         self.frame_pos = Vec::with_capacity(self.frames + 1);
-        for _ in 0..=self.frames {
+        for fno in 0..=self.frames {
             let pos                         = src.read_u32le()?;
             self.frame_pos.push(pos);
+            if (pos & 1) != 0 {
+                seek_idx.seek_info[0].add_entry(SeekEntry { pts: fno as u64, pos: (pos & !1) as u64 });
+            }
         }
         validate!((src.tell() as u32) == (self.frame_pos[0] & !1));
+        seek_idx.seek_info[0].filled = true;
 
         self.cur_frame = 0;
         
@@ -143,9 +149,16 @@ impl<'a> DemuxCore<'a> for BinkDemuxer<'a> {
 
         Ok(pkt)
     }
-    #[allow(unused_variables)]
-    fn seek(&mut self, time: u64) -> DemuxerResult<()> {
-        Err(DemuxerError::NotImplemented)
+    fn seek(&mut self, time: u64, seek_idx: &SeekIndex) -> DemuxerResult<()> {
+        let ret = seek_idx.find_pos(time);
+        if ret.is_none() {
+            return Err(DemuxerError::SeekError);
+        }
+        let seek_info = ret.unwrap();
+        self.src.seek(SeekFrom::Start(seek_info.pos))?;
+        self.queued_packets.clear();
+        self.cur_frame = seek_info.pts as usize;
+        Ok(())
     }
 }
 
index 3e612efca146fab51264130ec9ba7712b91f21b9..902be430fa7aef8915e4b10e39a3fd1a0e62182f 100644 (file)
@@ -95,7 +95,7 @@ fn get_pts_inc(val: i32) -> u64 {
 }
 
 impl<'a> DemuxCore<'a> for SmackerVideoDemuxer<'a> {
-    fn open(&mut self, strmgr: &mut StreamManager) -> DemuxerResult<()> {
+    fn open(&mut self, strmgr: &mut StreamManager, _seek_idx: &mut SeekIndex) -> DemuxerResult<()> {
         let src = &mut self.src;
         let mut magic: [u8; 4] = [0; 4];
                                               src.read_buf(&mut magic)?;
@@ -245,8 +245,7 @@ impl<'a> DemuxCore<'a> for SmackerVideoDemuxer<'a> {
 
         Ok(pkt)
     }
-    #[allow(unused_variables)]
-    fn seek(&mut self, time: u64) -> DemuxerResult<()> {
+    fn seek(&mut self, time: u64, _seek_idx: &SeekIndex) -> DemuxerResult<()> {
         if time == 0 {
             let start = self.start;
             self.src.seek(SeekFrom::Start(start))?;
index 6a30f1055fb5773e9018f227049de48e02c768ff..b9eb9c741530636bacf58bc2f57366d89036e5c7 100644 (file)
@@ -647,7 +647,7 @@ println!(" got ainfo {:?}", ainfo);
 
 impl<'a> DemuxCore<'a> for RealMediaDemuxer<'a> {
     #[allow(unused_variables)]
-    fn open(&mut self, strmgr: &mut StreamManager) -> DemuxerResult<()> {
+    fn open(&mut self, strmgr: &mut StreamManager, _seek_idx: &mut SeekIndex) -> DemuxerResult<()> {
         self.read_header(strmgr)?;
         Ok(())
     }
@@ -731,7 +731,7 @@ impl<'a> DemuxCore<'a> for RealMediaDemuxer<'a> {
     }
 
     #[allow(unused_variables)]
-    fn seek(&mut self, time: u64) -> DemuxerResult<()> {
+    fn seek(&mut self, time: u64, seek_idx: &SeekIndex) -> DemuxerResult<()> {
         Err(NotImplemented)
     }
 }
@@ -1110,7 +1110,7 @@ struct RealAudioDemuxer<'a> {
 
 impl<'a> DemuxCore<'a> for RealAudioDemuxer<'a> {
     #[allow(unused_variables)]
-    fn open(&mut self, strmgr: &mut StreamManager) -> DemuxerResult<()> {
+    fn open(&mut self, strmgr: &mut StreamManager, _seek_idx: &mut SeekIndex) -> DemuxerResult<()> {
         let magic                                       = self.src.read_u32be()?;
         validate!(magic == mktag!(b".ra\xFD"));
         let ver         = self.src.read_u16be()?;
@@ -1183,7 +1183,7 @@ println!(" got ainfo {:?}", ainfo);
     }
 
     #[allow(unused_variables)]
-    fn seek(&mut self, time: u64) -> DemuxerResult<()> {
+    fn seek(&mut self, time: u64, seek_idx: &SeekIndex) -> DemuxerResult<()> {
         Err(NotImplemented)
     }
 }
@@ -1450,7 +1450,7 @@ struct RealIVRDemuxer<'a> {
 
 impl<'a> DemuxCore<'a> for RealIVRDemuxer<'a> {
     #[allow(unused_variables)]
-    fn open(&mut self, strmgr: &mut StreamManager) -> DemuxerResult<()> {
+    fn open(&mut self, strmgr: &mut StreamManager, seek_idx: &mut SeekIndex) -> DemuxerResult<()> {
         let magic                                       = self.src.peek_u32be()?;
         if magic == mktag!(b".REC") {
             let mut rec = RecordDemuxer::new(0, 0);
@@ -1522,7 +1522,7 @@ println!("R1M kind");
     }
 
     #[allow(unused_variables)]
-    fn seek(&mut self, time: u64) -> DemuxerResult<()> {
+    fn seek(&mut self, time: u64, seek_idx: &SeekIndex) -> DemuxerResult<()> {
         Err(NotImplemented)
     }
 }