introduce a way for encoder to manifest its capabilities
[nihav.git] / nihav-ms / src / codecs / msvideo1enc.rs
index 3c89f7ae7e4721f694a72d342e55cf9b87ef8104..4507e08ec7bfff1f7d3251d4d059b29c494a2bc1 100644 (file)
@@ -201,9 +201,9 @@ macro_rules! quant_template {
             for clr in pix.iter() {
                 if clr[best_axis] > avg[best_axis] {
                     avg2.add(clr);
-                    mask |= mask_bit;
                 } else {
                     avg1.add(clr);
+                    mask |= mask_bit;
                 }
                 mask_bit <<= 1;
             }
@@ -338,8 +338,8 @@ impl BlockState {
             let src2 = [buf[off], buf[off + 1], buf[off + 4], buf[off + 5]];
             let (clrs, mask, dist) = quant2_4pix(&src2);
             self.clr8[i] = clrs;
-            let lo_bits = (mask & 0x3) ^ 0x3;
-            let hi_bits = ((mask & 0xC) ^ 0xC) << 2;
+            let lo_bits = mask & 0x3;
+            let hi_bits = (mask & 0xC) << 2;
             self.clr8_flags |= (hi_bits | lo_bits) << ((i & 1) * 2 + (i & 2) * 4);
             self.clr8_dist += dist;
         }
@@ -835,6 +835,7 @@ impl NAEncoder for MSVideo1Encoder {
             }
         }
     }
+    fn get_capabilities(&self) -> u64 { ENC_CAPS_SKIPFRAME }
     fn init(&mut self, stream_id: u32, encinfo: EncodeParameters) -> EncoderResult<NAStreamRef> {
         match encinfo.format {
             NACodecTypeInfo::None => Err(EncoderError::FormatError),
@@ -873,6 +874,31 @@ impl NAEncoder for MSVideo1Encoder {
     }
     fn encode(&mut self, frm: &NAFrame) -> EncoderResult<()> {
         let buf = frm.get_buffer();
+        if frm.frame_type == FrameType::Skip {
+            if let Some(ref stream) = self.stream {
+                let mut dbuf = Vec::with_capacity(4);
+                let mut gw   = GrowableMemoryWriter::new_write(&mut dbuf);
+                let mut bw   = ByteWriter::new(&mut gw);
+
+                let vinfo = stream.get_info().get_properties().get_video_info().unwrap();
+                let mut nskips = ((vinfo.get_width() + 3) / 4) * ((vinfo.get_height() + 3) / 4);
+                while nskips >= 1023 {
+                    Self::write_skips(&mut bw, 1023)?;
+                    nskips -= 1023;
+                }
+                if nskips > 0 {
+                    Self::write_skips(&mut bw, nskips)?;
+                }
+                self.pkt = Some(NAPacket::new(self.stream.clone().unwrap(), frm.ts, false, dbuf));
+                self.frmcount += 1;
+                if self.frmcount == self.key_int {
+                    self.frmcount = 0;
+                }
+                return Ok(());
+            } else {
+                return Err(EncoderError::Bug);
+            }
+        }
         if let Some(ref vbuf) = buf.get_vbuf16() {
             if self.pal_mode {
                 return Err(EncoderError::InvalidParameters);
@@ -1050,7 +1076,7 @@ mod test {
             };
         //test_encoding_to_file(&dec_config, &enc_config, enc_params, &[]);
         test_encoding_md5(&dec_config, &enc_config, enc_params, &[],
-                          &[0x27a9db38, 0x74f1000a, 0x38818c05, 0x99d692ba]);
+                          &[0x5afaf853, 0xd53ba9dd, 0x630f53e7, 0x41b33a36]);
     }
 
     #[test]
@@ -1096,6 +1122,6 @@ mod test {
             };
         //test_encoding_to_file(&dec_config, &enc_config, enc_params, &[]);
         test_encoding_md5(&dec_config, &enc_config, enc_params, &[],
-                          &[0xe570a206, 0xc223063f, 0x44a0b70e, 0xa71fed1f]);
+                          &[0xb3175a7b, 0x4a6cb45e, 0x526f3f5d, 0xaa1574cc]);
     }
 }