]> git.nihav.org Git - nihav.git/blobdiff - nihav-duck/src/codecs/vp8.rs
avimux: do not record palette change chunks in OpenDML index
[nihav.git] / nihav-duck / src / codecs / vp8.rs
index 2969bfa9e697021fced83f83f935181fa574b94c..83539b6aa6ea1bf16e1c2f095a2b2da8be768354 100644 (file)
@@ -7,18 +7,15 @@ use super::vp78data::*;
 use super::vp78dsp::*;
 use super::vp8dsp::*;
 
-#[derive(Clone,Copy,PartialEq,Debug)]
+#[derive(Clone,Copy,PartialEq,Debug,Default)]
 enum VP8Ref {
+    #[default]
     Intra,
     Last,
     Golden,
     AltRef,
 }
 
-impl Default for VP8Ref {
-    fn default() -> Self { VP8Ref::Intra }
-}
-
 #[derive(Default)]
 pub struct VP8Shuffler {
     lastframe: Option<NAVideoBufferRef<u8>>,
@@ -43,25 +40,13 @@ impl VP8Shuffler {
         self.altframe = Some(buf);
     }
     pub fn get_last(&mut self) -> Option<NAVideoBufferRef<u8>> {
-        if let Some(ref frm) = self.lastframe {
-            Some(frm.clone())
-        } else {
-            None
-        }
+        self.lastframe.as_ref().cloned()
     }
     pub fn get_golden(&mut self) -> Option<NAVideoBufferRef<u8>> {
-        if let Some(ref frm) = self.goldframe {
-            Some(frm.clone())
-        } else {
-            None
-        }
+        self.goldframe.as_ref().cloned()
     }
     pub fn get_altref(&mut self) -> Option<NAVideoBufferRef<u8>> {
-        if let Some(ref frm) = self.altframe {
-            Some(frm.clone())
-        } else {
-            None
-        }
+        self.altframe.as_ref().cloned()
     }
     pub fn has_refs(&self) -> bool {
         self.lastframe.is_some()
@@ -343,6 +328,7 @@ impl VP8Decoder {
         }
         Ok(())
     }
+    #[allow(clippy::collapsible_if)]
     fn mb_lf_adjustments(&mut self, bc: &mut BoolCoder) -> DecoderResult<()> {
         self.dstate.lf_delta                = bc.read_bool();
         if self.dstate.lf_delta {
@@ -389,12 +375,12 @@ impl VP8Decoder {
         Ok(())
     }
     fn read_dct_coef_prob_upd(&mut self, bc: &mut BoolCoder) -> DecoderResult<()> {
-        for i in 0..4 {
-            for j in 0..8 {
-                for k in 0..3 {
-                    for l in 0..11 {
-                        if bc.read_prob(DCT_UPDATE_PROBS[i][j][k][l]) {
-                            self.dstate.coef_probs[i][j][k][l]  = bc.read_byte();
+        for (probs, upd_probs) in self.dstate.coef_probs.iter_mut().zip(DCT_UPDATE_PROBS.iter()) {
+            for (probs, upd_probs) in probs.iter_mut().zip(upd_probs.iter()) {
+                for (probs, upd_probs) in probs.iter_mut().zip(upd_probs.iter()) {
+                    for (prob, &upd_prob) in probs.iter_mut().zip(upd_probs.iter()) {
+                        if bc.read_prob(upd_prob) {
+                            *prob = bc.read_byte();
                         }
                     }
                 }
@@ -407,10 +393,11 @@ impl VP8Decoder {
           [ 237, 246, 253, 253, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 250, 250, 252, 254, 254 ],
           [ 231, 243, 245, 253, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 251, 251, 254, 254, 254 ]
         ];
-        for comp in 0..2 {
-            for i in 0..19 {
-                if bc.read_prob(MV_UPDATE_PROBS[comp][i]) {
-                    self.dstate.mv_probs[comp][i]   = bc.read_probability();
+        for (prob_row, upd_row) in self.dstate.mv_probs.iter_mut()
+                .zip(MV_UPDATE_PROBS.iter()) {
+            for (prob, &upd_prob) in prob_row.iter_mut().zip(upd_row.iter()) {
+                if bc.read_prob(upd_prob) {
+                    *prob = bc.read_probability();
                 }
             }
         }
@@ -462,45 +449,48 @@ impl VP8Decoder {
             ytype = 3;
         }
         sbparams.qmat = &self.qmat[qmat_idx][0];
-        for i in 0..16 {
+        let (y_coeffs, c_coeffs) = self.coeffs.split_at_mut(16);
+        for (i, (coeffs, y_has_ac)) in y_coeffs.iter_mut().zip(has_ac.iter_mut()).enumerate() {
             let bx = i & 3;
             let by = i >> 2;
             let pred = &self.pcache.y_pred;
             let pidx = pred.xpos + mb_x * 4 + bx + by * pred.stride;
             let pctx = self.pcache.y_pred_left[by] + pred.data[pidx - pred.stride];
 
-            let has_nz = decode_subblock(bc, &mut self.coeffs[i], ytype, pctx, &sbparams);
+            let has_nz = decode_subblock(bc, coeffs, ytype, pctx, &sbparams);
             self.pcache.y_pred.data[pidx] = has_nz;
             self.pcache.y_pred_left[by]   = has_nz;
-            has_ac[i] = has_nz > 0;
-            coded |= has_ac[i] | (self.coeffs[i][0] != 0);
+            *y_has_ac = has_nz > 0;
+            coded |= *y_has_ac | (coeffs[0] != 0);
         }
         sbparams.qmat = &self.qmat[qmat_idx][1];
-        for i in 16..20 {
+        let (u_coeffs, v_coeffs) = c_coeffs.split_at_mut(4);
+        let (u_has_ac, v_has_ac) = has_ac[16..24].split_at_mut(4);
+        for (i, (coeffs, u_has_ac)) in u_coeffs.iter_mut().zip(u_has_ac.iter_mut()).enumerate() {
             let bx = i & 1;
             let by = (i >> 1) & 1;
             let pred = &self.pcache.u_pred;
             let pidx = pred.xpos + mb_x * 2 + bx + by * pred.stride;
             let pctx = self.pcache.u_pred_left[by] + pred.data[pidx - pred.stride];
 
-            let has_nz = decode_subblock(bc, &mut self.coeffs[i], 2, pctx, &sbparams);
+            let has_nz = decode_subblock(bc, coeffs, 2, pctx, &sbparams);
             self.pcache.u_pred.data[pidx] = has_nz;
             self.pcache.u_pred_left[by]   = has_nz;
-            has_ac[i] = has_nz > 0;
-            coded |= has_ac[i] | (self.coeffs[i][0] != 0);
+            *u_has_ac = has_nz > 0;
+            coded |= *u_has_ac | (coeffs[0] != 0);
         }
-        for i in 20..24 {
+        for (i, (coeffs, v_has_ac)) in v_coeffs.iter_mut().zip(v_has_ac.iter_mut()).enumerate() {
             let bx = i & 1;
             let by = (i >> 1) & 1;
             let pred = &self.pcache.v_pred;
             let pidx = pred.xpos + mb_x * 2 + bx + by * pred.stride;
             let pctx = self.pcache.v_pred_left[by] + pred.data[pidx - pred.stride];
 
-            let has_nz = decode_subblock(bc, &mut self.coeffs[i], 2, pctx, &sbparams);
+            let has_nz = decode_subblock(bc, coeffs, 2, pctx, &sbparams);
             self.pcache.v_pred.data[pidx] = has_nz;
             self.pcache.v_pred_left[by]   = has_nz;
-            has_ac[i] = has_nz > 0;
-            coded |= has_ac[i] | (self.coeffs[i][0] != 0);
+            *v_has_ac = has_nz > 0;
+            coded |= *v_has_ac | (coeffs[0] != 0);
         }
 
         if self.dstate.has_y2 {
@@ -514,11 +504,11 @@ impl VP8Decoder {
                 self.coeffs[i][0] = self.coeffs[24][i];
             }
         }
-        for i in 0..24 {
-            if has_ac[i] {
-                idct4x4(&mut self.coeffs[i]);
-            } else if self.coeffs[i][0] != 0 {
-                idct4x4_dc(&mut self.coeffs[i]);
+        for (&has_ac, coeffs) in has_ac.iter().zip(self.coeffs.iter_mut()).take(24) {
+            if has_ac {
+                idct4x4(coeffs);
+            } else if coeffs[0] != 0 {
+                idct4x4_dc(coeffs);
             }
         }
 
@@ -751,6 +741,7 @@ impl VP8Decoder {
             },
         }
     }
+    #[allow(clippy::identity_op)]
     fn do_split_mv(&mut self, bc: &mut BoolCoder, mb_x: usize, mb_y: usize, pred_mv: MV) -> DecoderResult<()> {
         let split_mode                  = bc.read_tree(MV_SPLIT_MODE_TREE, &MV_SPLIT_MODE_PROBS);
         let mut mvidx = mb_x * 4 + mb_y * 4 * self.mv_stride;
@@ -975,7 +966,7 @@ impl VP8Decoder {
             }.unwrap();
         let single_mv = self.mb_info[mb_x + mb_y * self.mb_w].mb_type != VPMBType::InterFourMV;
         let mut iidx = mb_x * 4 + mb_y * 4 * self.mv_stride;
-        let mut mc_buf = self.mc_buf.get_data_mut().unwrap();
+        let mc_buf = self.mc_buf.get_data_mut().unwrap();
 
         let dst = &mut dframe.data[0..];
         let ystride = dframe.stride[0];
@@ -983,20 +974,20 @@ impl VP8Decoder {
         if single_mv {
             if self.dstate.version == 0 {
                 mc_block16x16(dst, yoff, ystride, mb_x * 16, mb_y * 16,
-                              self.mvs[iidx].x * 2, self.mvs[iidx].y * 2, refframe.clone(), 0, &mut mc_buf);
+                              self.mvs[iidx].x * 2, self.mvs[iidx].y * 2, refframe.clone(), 0, mc_buf);
             } else {
                 mc_block16x16_bilin(dst, yoff, ystride, mb_x * 16, mb_y * 16,
-                              self.mvs[iidx].x * 2, self.mvs[iidx].y * 2, refframe.clone(), 0, &mut mc_buf);
+                              self.mvs[iidx].x * 2, self.mvs[iidx].y * 2, refframe.clone(), 0, mc_buf);
             }
         } else {
             for y in 0..4 {
                 for x in 0..4 {
                     if self.dstate.version == 0 {
                         mc_block4x4(dst, yoff + x * 4, ystride, mb_x * 16 + x * 4, mb_y * 16 + y * 4,
-                                    self.mvs[iidx + x].x * 2, self.mvs[iidx + x].y * 2, refframe.clone(), 0, &mut mc_buf);
+                                    self.mvs[iidx + x].x * 2, self.mvs[iidx + x].y * 2, refframe.clone(), 0, mc_buf);
                     } else {
                         mc_block4x4_bilin(dst, yoff + x * 4, ystride, mb_x * 16 + x * 4, mb_y * 16 + y * 4,
-                                          self.mvs[iidx + x].x * 2, self.mvs[iidx + x].y * 2, refframe.clone(), 0, &mut mc_buf);
+                                          self.mvs[iidx + x].x * 2, self.mvs[iidx + x].y * 2, refframe.clone(), 0, mc_buf);
                     }
                 }
                 yoff += 4 * ystride;
@@ -1013,15 +1004,15 @@ impl VP8Decoder {
             let mut chroma_mv = self.mvs[iidx];
 
             if self.dstate.version == 0 {
-                mc_block8x8(dst, uoff, ustride, mb_x * 8, mb_y * 8, chroma_mv.x, chroma_mv.y, refframe.clone(), 1, &mut mc_buf);
-                mc_block8x8(dst, voff, vstride, mb_x * 8, mb_y * 8, chroma_mv.x, chroma_mv.y, refframe,         2, &mut mc_buf);
+                mc_block8x8(dst, uoff, ustride, mb_x * 8, mb_y * 8, chroma_mv.x, chroma_mv.y, refframe.clone(), 1, mc_buf);
+                mc_block8x8(dst, voff, vstride, mb_x * 8, mb_y * 8, chroma_mv.x, chroma_mv.y, refframe,         2, mc_buf);
             } else {
                 if self.dstate.version == 3 {
                     chroma_mv.x &= !7;
                     chroma_mv.y &= !7;
                 }
-                mc_block8x8_bilin(dst, uoff, ustride, mb_x * 8, mb_y * 8, chroma_mv.x, chroma_mv.y, refframe.clone(), 1, &mut mc_buf);
-                mc_block8x8_bilin(dst, voff, vstride, mb_x * 8, mb_y * 8, chroma_mv.x, chroma_mv.y, refframe,         2, &mut mc_buf);
+                mc_block8x8_bilin(dst, uoff, ustride, mb_x * 8, mb_y * 8, chroma_mv.x, chroma_mv.y, refframe.clone(), 1, mc_buf);
+                mc_block8x8_bilin(dst, voff, vstride, mb_x * 8, mb_y * 8, chroma_mv.x, chroma_mv.y, refframe,         2, mc_buf);
             }
         } else {
             for y in 0..2 {
@@ -1049,14 +1040,14 @@ impl VP8Decoder {
 
                     if self.dstate.version == 0 {
                         mc_block4x4(dst, uoff + x * 4, ustride, mb_x * 8 + x * 4, mb_y * 8 + y * 4,
-                                    chroma_mv.x, chroma_mv.y, refframe.clone(), 1, &mut mc_buf);
+                                    chroma_mv.x, chroma_mv.y, refframe.clone(), 1, mc_buf);
                         mc_block4x4(dst, voff + x * 4, vstride, mb_x * 8 + x * 4, mb_y * 8 + y * 4,
-                                    chroma_mv.x, chroma_mv.y, refframe.clone(), 2, &mut mc_buf);
+                                    chroma_mv.x, chroma_mv.y, refframe.clone(), 2, mc_buf);
                     } else {
                         mc_block4x4_bilin(dst, uoff + x * 4, ustride, mb_x * 8 + x * 4, mb_y * 8 + y * 4,
-                                          chroma_mv.x, chroma_mv.y, refframe.clone(), 1, &mut mc_buf);
+                                          chroma_mv.x, chroma_mv.y, refframe.clone(), 1,  mc_buf);
                         mc_block4x4_bilin(dst, voff + x * 4, vstride, mb_x * 8 + x * 4, mb_y * 8 + y * 4,
-                                          chroma_mv.x, chroma_mv.y, refframe.clone(), 2, &mut mc_buf);
+                                          chroma_mv.x, chroma_mv.y, refframe.clone(), 2, mc_buf);
                     }
                 }
                 uoff += ustride * 4;
@@ -1159,6 +1150,7 @@ impl NADecoder for VP8Decoder {
         }
     }
     #[allow(clippy::cognitive_complexity)]
+    #[allow(clippy::collapsible_else_if)]
     fn decode(&mut self, supp: &mut NADecoderSupport, pkt: &NAPacket) -> DecoderResult<NAFrameRef> {
         let src = pkt.get_buffer();
         validate!(src.len() > 4);
@@ -1281,13 +1273,10 @@ impl NADecoder for VP8Decoder {
         for start in part_offs[num_partitions..].iter_mut() {
             *start = data_start;
         }
-        let mut bc_src = unsafe {
-                let mut arr: [BoolCoder; 8] = std::mem::MaybeUninit::uninit().assume_init();
-                for (bc, &off) in arr.iter_mut().zip(part_offs.iter()) {
-                    std::ptr::write(bc, BoolCoder::new(&src[off..]).unwrap());
-                }
-                arr
-            };
+        let mut bc_src = Vec::new();
+        for &off in part_offs.iter() {
+            bc_src.push(BoolCoder::new(&src[off..]).unwrap());
+        }
 
         let vinfo = NAVideoInfo::new(self.width, self.height, false, YUV420_FORMAT);
         let ret = supp.pool_u8.get_free();
@@ -1547,13 +1536,14 @@ mod test {
     use crate::duck_register_all_decoders;
     use crate::duck_register_all_demuxers;
 
+    // all samples are from the official VP8 test bitstreams set
     fn test_vp8_core(name: &str, hash: [u32; 4]) {
         let mut dmx_reg = RegisteredDemuxers::new();
         duck_register_all_demuxers(&mut dmx_reg);
         let mut dec_reg = RegisteredDecoders::new();
         duck_register_all_decoders(&mut dec_reg);
 
-        test_decoding("ivf", "vp8", name, None, &dmx_reg,
+        test_decoding("dkivf", "vp8", name, None, &dmx_reg,
                       &dec_reg, ExpectedTestResult::MD5(hash));
     }