]> git.nihav.org Git - nihav.git/blobdiff - nihav-indeo/src/codecs/ivibr.rs
core/io: allow skipping right to the bitstream end
[nihav.git] / nihav-indeo / src / codecs / ivibr.rs
index e023bdb77e1a3f08edd1acc8845d11afde457bd1..5831f801693d23181716b4ecc4e00c7f305432e5 100644 (file)
@@ -484,13 +484,16 @@ pub struct IVIDecoder {
     bref:       Option<NABufferType>,
 
     bands:      Vec<BandHeader>,
+    band_tiles: usize,
     tiles:      Vec<IVITile>,
     num_tiles:  [[usize; 4]; 4],
     tile_start: [[usize; 4]; 4],
+
+    scalable:   bool,
 }
 
 impl IVIDecoder {
-    pub fn new() -> Self {
+    pub fn new(scalable: bool) -> Self {
         let mut bands: Vec<BandHeader> = Vec::with_capacity(12);
         bands.resize(12, BandHeader::new_empty(42, 42));
         IVIDecoder {
@@ -503,7 +506,10 @@ impl IVIDecoder {
             bref: None,
 
             bands,
+            band_tiles: 0,
             tiles: Vec::new(), tile_start: [[0; 4]; 4], num_tiles: [[0; 4]; 4],
+
+            scalable,
         }
     }
 
@@ -530,6 +536,9 @@ impl IVIDecoder {
                     tile_h = (tile_h + 1) >> 1;
                 }
             }
+            if plane == 0 {
+                self.band_tiles = ((band_w + tile_w - 1) / tile_w) * ((band_h + tile_h - 1) / tile_h);
+            }
             for band in 0..bands {
                 self.tile_start[plane][band] = tstart;
                 let band_xoff = if (band & 1) == 1 { band_w } else { 0 };
@@ -596,7 +605,7 @@ impl IVIDecoder {
                 }
                 br.align();
                 validate!(len > 0);
-                let tile_end = tile_start + len * 8;
+                let tile_end = (tile_start & !7) + len * 8;
                 validate!(tile_end > br.tell());
                 validate!(tile_end <= br.tell() + (br.left() as usize));
                 {
@@ -610,7 +619,7 @@ impl IVIDecoder {
                     let (ref_tiles, cur_tiles) = self.tiles.split_at_mut(tile_no);
                     let tile = &mut cur_tiles[0];
                     if plane_no != 0 || band_no != 0 {
-                        let rtile = &ref_tiles[0];
+                        let rtile = &ref_tiles[tile_no % self.band_tiles];
                         if (tile.mb_w != rtile.mb_w) || (tile.mb_h != rtile.mb_h) {
                             ref_tile = None;
                         } else {
@@ -623,6 +632,7 @@ impl IVIDecoder {
                 }
 
                 self.decode_tile(br, &band, tile_no, tr, tr_dc)?;
+                br.align();
 let skip_part = tile_end - br.tell();
 br.skip(skip_part as u32)?;
             } else {
@@ -814,7 +824,6 @@ br.skip(skip_part as u32)?;
             }
             dstidx += stride * band.mb_size;
         }
-        br.align();
         Ok(())
     }
 
@@ -938,6 +947,11 @@ br.skip(skip_part as u32)?;
                 self.ftype = IVIFrameType::Intra;
             }
         }
+        if self.bref.is_some() && self.ftype == IVIFrameType::Inter {
+            let mut bref: Option<NABufferType> = Some(res.unwrap());
+            mem::swap(&mut bref, &mut self.bref);
+            return Ok(bref.unwrap());
+        }
         if let Ok(NABufferType::None) = res {
             if self.bref.is_some() {
                 let mut bref: Option<NABufferType> = None;