]> git.nihav.org Git - nihav.git/blobdiff - nihav-indeo/src/codecs/ivibr.rs
avimux: do not record palette change chunks in OpenDML index
[nihav.git] / nihav-indeo / src / codecs / ivibr.rs
index 8ccd3b0278b078e9a0a9d2845aa5550d49e872da..c3722a1bf493e9d88f691360507d91368813a50a 100644 (file)
@@ -144,23 +144,22 @@ pub const IVI_BLK_CB: &[IVICodebook; 8] = &[
     IVICodebook { len:  9, bits: [ 3, 4, 4, 5, 5, 5, 6, 5, 5, 0, 0, 0, 0, 0, 0, 0 ], offs: [0; 16] }
 ];
 
-#[allow(unused_variables)]
 #[allow(clippy::many_single_char_names)]
 fn read_trans_band_header(br: &mut BitReader, w: usize, h: usize, dst: &mut [i16], dstride: usize) -> DecoderResult<()> {
-    let color_plane     = br.read(2)?;
-    let bit_depth       = br.read(3)?;
+    let _color_plane    = br.read(2)?;
+    let _bit_depth      = br.read(3)?;
     let dirty_rects     = br.read(8)? as usize;
-    for i in 0..dirty_rects {
-        let x = br.read(16)?;
-        let y = br.read(16)?;
-        let l = br.read(16)?;
-        let r = br.read(16)?;
+    for _ in 0..dirty_rects {
+        let _x = br.read(16)?;
+        let _y = br.read(16)?;
+        let _l = br.read(16)?;
+        let _r = br.read(16)?;
     }
     let has_trans_color = br.read_bool()?;
     if has_trans_color {
-        let r = br.read(8)?;
-        let g = br.read(8)?;
-        let b = br.read(8)?;
+        let _r = br.read(8)?;
+        let _g = br.read(8)?;
+        let _b = br.read(8)?;
     }
 
     br.skip(1)?;
@@ -187,7 +186,7 @@ let tile_end = tile_start + len * 8;
 
         let first_val = br.read_bool()?;
 
-        let mut dec_size = 0;
+        let mut _dec_size = 0;
         let mut x = 0;
         let mut y = 0;
         let mut fill = if !first_val { 255-128 } else { 0-128 };
@@ -195,7 +194,7 @@ let tile_end = tile_start + len * 8;
         while br.tell() < tile_end {
             let code = br.read_ivi_cb(&cb)? as usize;
             if code == 0 {
-                dec_size += 255;
+                _dec_size += 255;
                 for _ in 0..255 {
                     if (x < w) && (y < h) {
                         dst[x + y * dstride] = fill;
@@ -207,7 +206,7 @@ let tile_end = tile_start + len * 8;
                     }
                 }
             } else {
-                dec_size += code;
+                _dec_size += code;
                 for _ in 0..code {
                     if (x < w) && (y < h) {
                         dst[x + y * dstride] = fill;
@@ -228,7 +227,8 @@ let tile_end = tile_start + len * 8;
     Ok(())
 }
 
-fn decode_block8x8(br: &mut BitReader, blk_cb: &IVICodebook, rvmap: &RVMap, tables: &TxParams8x8, is_intra: bool, is_2d: bool, prev_dc: &mut i32, quant: u8, coeffs: &mut [i32; 64], transform: &TrFunc) -> DecoderResult<()> {
+#[allow(clippy::collapsible_else_if)]
+fn decode_block8x8(br: &mut BitReader, blk_cb: &IVICodebook, rvmap: &RVMap, tables: &TxParams8x8, is_intra: bool, is_2d: bool, prev_dc: &mut i32, quant: u8, coeffs: &mut [i32; 64], transform: TrFunc) -> DecoderResult<()> {
     let mut idx: isize = -1;
     let quant_mat = if is_intra { tables.quant_intra } else { tables.quant_inter };
     while idx <= 64 {
@@ -257,7 +257,7 @@ fn decode_block8x8(br: &mut BitReader, blk_cb: &IVICodebook, rvmap: &RVMap, tabl
             }
         }
         idx += run;
-        validate!((idx >= 0) && (idx < 64));
+        validate!((0..64).contains(&idx));
 
         let spos = tables.scan[idx as usize];
         let q = (u32::from(quant_mat[spos]) * u32::from(quant)) >> 9;
@@ -278,7 +278,9 @@ fn decode_block8x8(br: &mut BitReader, blk_cb: &IVICodebook, rvmap: &RVMap, tabl
     (transform)(coeffs);
     Ok(())
 }
-fn decode_block4x4(br: &mut BitReader, blk_cb: &IVICodebook, rvmap: &RVMap, tables: &TxParams4x4, is_intra: bool, is_2d: bool, prev_dc: &mut i32, quant: u8, coeffs: &mut [i32; 64], transform: &TrFunc) -> DecoderResult<()> {
+
+#[allow(clippy::collapsible_else_if)]
+fn decode_block4x4(br: &mut BitReader, blk_cb: &IVICodebook, rvmap: &RVMap, tables: &TxParams4x4, is_intra: bool, is_2d: bool, prev_dc: &mut i32, quant: u8, coeffs: &mut [i32; 64], transform: TrFunc) -> DecoderResult<()> {
     let mut idx: isize = -1;
     let quant_mat = if is_intra { tables.quant_intra } else { tables.quant_inter };
     while idx <= 64 {
@@ -306,7 +308,7 @@ fn decode_block4x4(br: &mut BitReader, blk_cb: &IVICodebook, rvmap: &RVMap, tabl
             }
         }
         idx += run;
-        validate!((idx >= 0) && (idx < 16));
+        validate!((0..16).contains(&idx));
 
         let spos = tables.scan[idx as usize];
         let q = (u32::from(quant_mat[spos]) * u32::from(quant)) >> 9;
@@ -482,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 {
@@ -501,15 +506,18 @@ impl IVIDecoder {
             bref: None,
 
             bands,
+            band_tiles: 0,
             tiles: Vec::new(), tile_start: [[0; 4]; 4], num_tiles: [[0; 4]; 4],
+
+            scalable,
         }
     }
 
     fn realloc(&mut self, pic_hdr: &PictureHeader) -> DecoderResult<()> {
         let planes = if pic_hdr.transparent { 4 } else { 3 };
 
-        //self.bands.truncate(0);
-        self.tiles.truncate(0);
+        //self.bands.clear();
+        self.tiles.clear();
         self.num_tiles  = [[0; 4]; 4];
         self.tile_start = [[0; 4]; 4];
         let mut tstart: usize = 0;
@@ -528,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 };
@@ -550,7 +561,7 @@ impl IVIDecoder {
         }
         Ok(())
     }
-    fn decode_band(&mut self, pic_hdr: &PictureHeader, dec: &mut IndeoXParser, br: &mut BitReader, plane_no: usize, band_no: usize) -> DecoderResult<()> {
+    fn decode_band(&mut self, pic_hdr: &PictureHeader, dec: &mut dyn IndeoXParser, br: &mut BitReader, plane_no: usize, band_no: usize) -> DecoderResult<()> {
         let bidx = match plane_no {
             0 => { band_no },
             _ => { pic_hdr.luma_bands + plane_no - 1 },
@@ -580,7 +591,7 @@ impl IVIDecoder {
                 let mb_h = (tile.h + mb_size - 1) / mb_size;
                 tile.mb_w = mb_w;
                 tile.mb_h = mb_h;
-                tile.mb.truncate(0);
+                tile.mb.clear();
                 tile.mb.resize(mb_w * mb_h, MB::new(0, 0));
             }
 
@@ -594,21 +605,18 @@ 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));
                 {
                     let ref_tile: Option<&IVITile>;
-                    let mv_scale;
-                    if (plane_no == 0) && (band_no == 0) {
-                        mv_scale = 0;
-                    } else {
-                        mv_scale = (((self.bands[0].mb_size >> 3) as i8) - ((band.mb_size >> 3) as i8)) as u8;
-                    }
+                    let mv_scale = if (plane_no == 0) && (band_no == 0) { 0 } else {
+                            (((self.bands[0].mb_size >> 3) as i8) - ((band.mb_size >> 3) as i8)) as u8
+                        };
                     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 {
@@ -620,18 +628,16 @@ impl IVIDecoder {
                     dec.decode_mb_info(br, pic_hdr, &band, tile, ref_tile, mv_scale)?;
                 }
 
-                self.decode_tile(br, &band, tile_no, &tr, &tr_dc)?;
+                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 {
                 {
                     let ref_tile: Option<&IVITile>;
-                    let mv_scale;
-                    if (plane_no == 0) && (band_no == 0) {
-                        mv_scale = 0;
-                    } else {
-                        mv_scale = (((self.bands[0].mb_size >> 3) as i8) - ((band.mb_size >> 3) as i8)) as u8;
-                    }
+                    let mv_scale = if (plane_no == 0) && (band_no == 0) { 0 } else {
+                            (((self.bands[0].mb_size >> 3) as i8) - ((band.mb_size >> 3) as i8)) as u8
+                        };
                     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 {
@@ -651,7 +657,7 @@ br.skip(skip_part as u32)?;
                             mb.mtype = MBType::Inter;
                             mb.cbp   = 0;
                             if band.inherit_mv {
-                                if let Some(ref tileref) = ref_tile {
+                                if let Some(tileref) = ref_tile {
                                     let mx = tileref.mb[mb_idx].mv_x;
                                     let my = tileref.mb[mb_idx].mv_y;
                                     mb.mv_x = scale_mv(mx, mv_scale);
@@ -663,14 +669,15 @@ br.skip(skip_part as u32)?;
                         }
                     }
                 }
-                self.decode_tile(br, &band, tile_no, &tr, &tr_dc)?;
+                self.decode_tile(br, &band, tile_no, tr, tr_dc)?;
             }
         }
         self.bands[bidx] = band;
         br.align();
         Ok(())
     }
-    fn decode_tile(&mut self, br: &mut BitReader, band: &BandHeader, tile_no: usize, tr: &TrFunc, transform_dc: &TrFuncDC) -> DecoderResult<()> {
+    #[allow(clippy::collapsible_else_if)]
+    fn decode_tile(&mut self, br: &mut BitReader, band: &BandHeader, tile_no: usize, tr: TrFunc, transform_dc: TrFuncDC) -> DecoderResult<()> {
         let mut mb_idx = 0;
         let mut prev_dc: i32 = 0;
         let tile = &mut self.tiles[tile_no];
@@ -678,7 +685,7 @@ br.skip(skip_part as u32)?;
 
         let stride = frame.plane_stride[band.plane_no];
         let mut dstidx = tile.pos_x + tile.pos_y * stride;
-        let mut dst = &mut frame.plane_buf[band.plane_no];
+        let dst = &mut frame.plane_buf[band.plane_no];
         let pos_x = tile.pos_x;
         let pos_y = tile.pos_y;
         let tile_w = (tile.w + 15) & !15;
@@ -696,12 +703,7 @@ br.skip(skip_part as u32)?;
                         let boff = (blk_no & 1) * band.blk_size + (blk_no >> 1) * band.blk_size * stride + mb_x * band.mb_size;
                         if !is_intra {
                             if mb.mtype != MBType::Bidir {
-                                let idx;
-                                if mb.mtype != MBType::Backward {
-                                    idx = self.prev_frame;
-                                } else {
-                                    idx = self.next_frame;
-                                }
+                                let idx = if mb.mtype != MBType::Backward { self.prev_frame } else { self.next_frame };
                                 let pf = &self.frames[idx];
                                 do_mc(&mut dst[dstidx + boff..], stride,
                                       &pf.plane_buf[band.plane_no], pf.plane_stride[band.plane_no],
@@ -726,23 +728,23 @@ br.skip(skip_part as u32)?;
                             if let TxType::Transform8(ref params) = band.ttype {
                                 decode_block8x8(br, &band.blk_cb, &band.rvmap, params, is_intra, band.tr.is_2d(), &mut prev_dc, mb.q, &mut blk, tr)?;
                                 if is_intra {
-                                    put_block(&mut dst, dstidx + boff, stride, &blk, 8);
+                                    put_block(dst, dstidx + boff, stride, &blk, 8);
                                 } else {
-                                    add_block(&mut dst, dstidx + boff, stride, &blk, 8);
+                                    add_block(dst, dstidx + boff, stride, &blk, 8);
                                 }
                             }
                             if let TxType::Transform4(ref params) = band.ttype {
                                 decode_block4x4(br, &band.blk_cb, &band.rvmap, params, is_intra, band.tr.is_2d(), &mut prev_dc, mb.q, &mut blk, tr)?;
                                 if is_intra {
-                                    put_block(&mut dst, dstidx + boff, stride, &blk, 4);
+                                    put_block(dst, dstidx + boff, stride, &blk, 4);
                                 } else {
-                                    add_block(&mut dst, dstidx + boff, stride, &blk, 4);
+                                    add_block(dst, dstidx + boff, stride, &blk, 4);
                                 }
                             }
                         } else {
                             if is_intra {
                                 (transform_dc)(&mut blk, prev_dc);
-                                put_block(&mut dst, dstidx + boff, stride, &blk, band.blk_size);
+                                put_block(dst, dstidx + boff, stride, &blk, band.blk_size);
                             }
                         }
                         cbp >>= 1;
@@ -751,12 +753,7 @@ br.skip(skip_part as u32)?;
                     let mut blk: [i32; 64] = [0; 64];
                     if !is_intra {
                         if mb.mtype != MBType::Bidir {
-                            let idx;
-                            if mb.mtype != MBType::Backward {
-                                idx = self.prev_frame;
-                            } else {
-                                idx = self.next_frame;
-                            }
+                            let idx = if mb.mtype != MBType::Backward { self.prev_frame } else { self.next_frame };
                             let pf = &self.frames[idx];
                             do_mc(&mut dst[dstidx + mb_x * band.blk_size..], stride,
                                   &pf.plane_buf[band.plane_no], pf.plane_stride[band.plane_no],
@@ -786,24 +783,24 @@ br.skip(skip_part as u32)?;
                         }
                         if is_intra {
                             if band.blk_size == 8 {
-                                put_block(&mut dst, dstidx + mb_x * band.blk_size, stride, &blk, 8);
+                                put_block(dst, dstidx + mb_x * band.blk_size, stride, &blk, 8);
                             } else {
-                                put_block(&mut dst, dstidx + mb_x * band.blk_size, stride, &blk, 4);
+                                put_block(dst, dstidx + mb_x * band.blk_size, stride, &blk, 4);
                             }
                         } else {
                             if band.blk_size == 8 {
-                                add_block(&mut dst, dstidx + mb_x * band.blk_size, stride, &blk, 8);
+                                add_block(dst, dstidx + mb_x * band.blk_size, stride, &blk, 8);
                             } else {
-                                add_block(&mut dst, dstidx + mb_x * band.blk_size, stride, &blk, 4);
+                                add_block(dst, dstidx + mb_x * band.blk_size, stride, &blk, 4);
                             }
                         }
                     } else {
                         if is_intra {
                             (transform_dc)(&mut blk, prev_dc);
                             if band.blk_size == 8 {
-                                put_block(&mut dst, dstidx + mb_x * band.blk_size, stride, &blk, 8);
+                                put_block(dst, dstidx + mb_x * band.blk_size, stride, &blk, 8);
                             } else {
-                                put_block(&mut dst, dstidx + mb_x * band.blk_size, stride, &blk, 4);
+                                put_block(dst, dstidx + mb_x * band.blk_size, stride, &blk, 4);
                             }
                         }
                     }
@@ -812,7 +809,6 @@ br.skip(skip_part as u32)?;
             }
             dstidx += stride * band.mb_size;
         }
-        br.align();
         Ok(())
     }
 
@@ -825,7 +821,7 @@ br.skip(skip_part as u32)?;
         unreachable!();
     }
 
-    fn decode_single_frame<'a>(&mut self, dec: &mut IndeoXParser, br: &mut BitReader<'a>) -> DecoderResult<NABufferType> {
+    fn decode_single_frame(&mut self, dec: &mut dyn IndeoXParser, br: &mut BitReader) -> DecoderResult<NABufferType> {
         let pic_hdr = dec.decode_picture_header(br)?;
         self.ftype = pic_hdr.ftype;
         if pic_hdr.ftype.is_null() {
@@ -869,22 +865,77 @@ br.skip(skip_part as u32)?;
         self.realloc(&pic_hdr)?;
         self.frames[self.cur_frame].realloc(&pic_hdr)?;
 
-        for plane in 0..3 {
-            let num_bands = if plane == 0 { pic_hdr.luma_bands } else { pic_hdr.chroma_bands };
-            for band in 0..num_bands {
-                self.decode_band(&pic_hdr, dec, br, plane, band)?;
+        if !self.scalable {
+            for plane in 0..3 {
+                let num_bands = if plane == 0 { pic_hdr.luma_bands } else { pic_hdr.chroma_bands };
+                for band in 0..num_bands {
+                    self.decode_band(&pic_hdr, dec, br, plane, band)?;
+                }
+                if let NABufferType::Video(ref mut vb) = buftype {
+                    let mut frame = self.frames[self.cur_frame].clone();
+                    if num_bands == 1 {
+                        frame.fill_plane(vb, plane);
+                    } else {
+                        let dplane = if (plane == 1) || (plane == 2) { plane ^ 3 } else { plane };
+                        let (w, h)  = vb.get_dimensions(dplane);
+                        let dstride = vb.get_stride(dplane);
+                        let off     = vb.get_offset(dplane);
+                        let dst = vb.get_data_mut().unwrap();
+                        dec.recombine_plane(&frame.plane_buf[plane], frame.plane_stride[plane], &mut dst[off..], dstride, w, h);
+                    }
+                }
             }
+        } else {
+            let mut bands_decoded = [[false; 10]; 3];
+            let mut num_decoded = 0;
+
+            let num_bands = [ pic_hdr.luma_bands, pic_hdr.chroma_bands, pic_hdr.chroma_bands ];
+
+            for plane in 0..3 {
+                for band in 0..num_bands[plane] {
+                    if br.peek(8) == 0x01 { // skipped scalable bands
+                        br.skip(8)?;
+                        continue;
+                    }
+                    self.decode_band(&pic_hdr, dec, br, plane, band)?;
+                    bands_decoded[plane][band] = true;
+                    num_decoded += 1;
+                }
+            }
+            if (num_decoded < num_bands[0] + num_bands[1] + num_bands[2]) && (br.left() > 0) {
+                validate!(br.read(8)? == 0x00);
+                while br.peek(8) == 0x00 {
+                    if br.skip(8).is_err() { // happens at the end of data
+                        break;
+                    }
+                }
+                validate!((br.tell() & 31) == 0);
+
+                for (plane, &nbands) in num_bands.iter().enumerate() {
+                    for (band, band_decoded) in bands_decoded[plane][..nbands].iter_mut().enumerate() {
+                        if *band_decoded || br.left() == 0 {
+                            continue;
+                        }
+                        self.decode_band(&pic_hdr, dec, br, plane, band)?;
+                        *band_decoded = true;
+                        num_decoded += 1;
+                    }
+                }
+            }
+
             if let NABufferType::Video(ref mut vb) = buftype {
-                let mut frame = self.frames[self.cur_frame].clone();
-                if num_bands == 1 {
-                    frame.fill_plane(vb, plane);
-                } else {
-                    let dplane = if (plane == 1) || (plane == 2) { plane ^ 3 } else { plane };
-                    let (w, h)  = vb.get_dimensions(dplane);
-                    let dstride = vb.get_stride(dplane);
-                    let off     = vb.get_offset(dplane);
-                    let dst = vb.get_data_mut().unwrap();
-                    dec.recombine_plane(&frame.plane_buf[plane], frame.plane_stride[plane], &mut dst[off..], dstride, w, h);
+                for (plane, &nbands) in num_bands.iter().enumerate() {
+                    let mut frame = self.frames[self.cur_frame].clone();
+                    if nbands == 1 {
+                        frame.fill_plane(vb, plane);
+                    } else {
+                        let dplane = if (plane == 1) || (plane == 2) { plane ^ 3 } else { plane };
+                        let (w, h)  = vb.get_dimensions(dplane);
+                        let dstride = vb.get_stride(dplane);
+                        let off     = vb.get_offset(dplane);
+                        let dst = vb.get_data_mut().unwrap();
+                        dec.recombine_plane(&frame.plane_buf[plane], frame.plane_stride[plane], &mut dst[off..], dstride, w, h);
+                    }
                 }
             }
         }
@@ -912,9 +963,8 @@ br.skip(skip_part as u32)?;
         Ok(buftype)
     }
 
-    pub fn decode_frame<'a>(&mut self, dec: &mut IndeoXParser, br: &mut BitReader<'a>) -> DecoderResult<NABufferType> {
-        let res = self.decode_single_frame(dec, br);
-        if res.is_err() { return res; }
+    pub fn decode_frame(&mut self, dec: &mut dyn IndeoXParser, br: &mut BitReader) -> DecoderResult<NABufferType> {
+        let res = self.decode_single_frame(dec, br)?;
         if (self.ftype == IVIFrameType::Intra) && (br.left() > 16) {
             loop {
                 if br.left() < 8 { break; }
@@ -929,14 +979,19 @@ br.skip(skip_part as u32)?;
                 let seq = br.peek(21);
                 if seq == 0xBFFF8 {
                     let res2 = self.decode_single_frame(dec, br);
-                    if res2.is_ok() {
-                        self.bref = Some(res2.unwrap());
+                    if let Ok(res) = res2 {
+                        self.bref = Some(res);
                     }
                 }
                 self.ftype = IVIFrameType::Intra;
             }
         }
-        if let Ok(NABufferType::None) = res {
+        if self.bref.is_some() && self.ftype == IVIFrameType::Inter {
+            let mut bref: Option<NABufferType> = Some(res);
+            mem::swap(&mut bref, &mut self.bref);
+            return Ok(bref.unwrap());
+        }
+        if let NABufferType::None = res {
             if self.bref.is_some() {
                 let mut bref: Option<NABufferType> = None;
                 mem::swap(&mut bref, &mut self.bref);
@@ -944,7 +999,7 @@ br.skip(skip_part as u32)?;
                 return Ok(bref.unwrap());
             }
         }
-        res
+        Ok(res)
     }
 
     pub fn flush(&mut self) {