avimux: write palette in stream header and palette change chunks
[nihav.git] / nihav-commonfmt / src / codecs / zmbvenc.rs
CommitLineData
f1787005
KS
1use nihav_core::codecs::*;
2use nihav_core::compr::deflate::{Deflate, DeflateMode, DeflateWriter};
3use nihav_core::io::byteio::*;
4
5const RGB555_FORMAT: NAPixelFormaton = NAPixelFormaton { model: ColorModel::RGB(RGBSubmodel::RGB), components: 3,
6 comp_info: [
7 Some(NAPixelChromaton{ h_ss: 0, v_ss: 0, packed: true, depth: 5, shift: 10, comp_offs: 0, next_elem: 2 }),
8 Some(NAPixelChromaton{ h_ss: 0, v_ss: 0, packed: true, depth: 5, shift: 5, comp_offs: 0, next_elem: 2 }),
9 Some(NAPixelChromaton{ h_ss: 0, v_ss: 0, packed: true, depth: 5, shift: 0, comp_offs: 0, next_elem: 2 }),
10 None, None],
11 elem_size: 2, be: false, alpha: false, palette: false };
12const RGB24_0_FORMAT: NAPixelFormaton = NAPixelFormaton { model: ColorModel::RGB(RGBSubmodel::RGB), components: 3,
13 comp_info: [
14 Some(NAPixelChromaton{ h_ss: 0, v_ss: 0, packed: true, depth: 8, shift: 0, comp_offs: 2, next_elem: 4 }),
15 Some(NAPixelChromaton{ h_ss: 0, v_ss: 0, packed: true, depth: 8, shift: 0, comp_offs: 1, next_elem: 4 }),
16 Some(NAPixelChromaton{ h_ss: 0, v_ss: 0, packed: true, depth: 8, shift: 0, comp_offs: 0, next_elem: 4 }),
17 None, None],
18 elem_size: 4, be: false, alpha: false, palette: false };
19
20struct ZMBVEncoder {
21 stream: Option<NAStreamRef>,
22 frm1: Vec<u8>,
23 frm2: Vec<u8>,
24 tmp_buf: Vec<u8>,
25 zbuf: Vec<u8>,
26 pal: [u8; 768],
27 pkt: Option<NAPacket>,
28 frmcount: u8,
29 key_int: u8,
30 tile_w: usize,
31 tile_h: usize,
32 cmode: DeflateMode,
33 compr: Deflate,
34 bpp: u8,
35 width: usize,
36 height: usize,
37 range: usize,
38}
39
40fn buf_type_to_bpp(buf: &NABufferType) -> u8 {
41 match buf {
42 NABufferType::Video(ref vbuf) => {
43 let vinfo = vbuf.get_info();
44 if vinfo.get_format().is_paletted() {
45 8
46 } else {
47 vinfo.get_format().get_total_depth()
48 }
49 },
50 NABufferType::VideoPacked(ref vbuf) => {
51 let vinfo = vbuf.get_info();
52 vinfo.get_format().elem_size * 8
53 },
54 NABufferType::Video16(ref vbuf) => {
55 let vinfo = vbuf.get_info();
56 vinfo.get_format().get_total_depth()
57 },
58 _ => 0,
59 }
60}
61
62fn copy_frame(buf: NABufferType, dst: &mut [u8], bpp: u8) -> EncoderResult<()> {
63 match buf {
64 NABufferType::Video(ref vbuf) => {
65 if bpp != 8 {
66 return Err(EncoderError::FormatError);
67 }
68 let off = vbuf.get_offset(0);
69 let stride = vbuf.get_stride(0);
70 let data = vbuf.get_data();
71 let w = vbuf.get_info().get_width();
72 let h = vbuf.get_info().get_height();
73
74 for (dline, sline) in dst.chunks_mut(w).zip(data[off..].chunks(stride)).take(h) {
75 dline[..w].copy_from_slice(&sline[..w]);
76 }
77 },
78 NABufferType::Video16(ref vbuf) => {
79 let off = vbuf.get_offset(0);
80 let stride = vbuf.get_stride(0);
81 let data = vbuf.get_data();
82 let w = vbuf.get_info().get_width();
83 let h = vbuf.get_info().get_height();
84
85 for (dline, sline) in dst.chunks_mut(w * 2).zip(data[off..].chunks(stride)).take(h) {
86 for (dst, &src) in dline[..w * 2].chunks_exact_mut(2).zip(sline.iter()) {
87 dst[0] = src as u8;
88 dst[1] = (src >> 8) as u8;
89 }
90 }
91 },
92 NABufferType::VideoPacked(ref vbuf) => {
93 let off = vbuf.get_offset(0);
94 let stride = vbuf.get_stride(0);
95 let data = vbuf.get_data();
96 let w = vbuf.get_info().get_width();
97 let h = vbuf.get_info().get_height();
98 let w = w * (((bpp as usize) + 7) / 8);
99
100 for (dline, sline) in dst.chunks_mut(w).zip(data[off..].chunks(stride)).take(h) {
101 dline[..w].copy_from_slice(&sline[..w]);
102 }
103 },
104 _ => return Err(EncoderError::FormatError),
105 };
106 Ok(())
107}
108
109fn to_signed(val: usize) -> isize {
110 if (val & 1) == 0 {
111 (val >> 1) as isize
112 } else {
113 -((val >> 1) as isize) - 1
114 }
115}
116
117impl ZMBVEncoder {
118 fn new() -> Self {
119 Self {
120 stream: None,
121 pkt: None,
122 frm1: Vec::new(),
123 frm2: Vec::new(),
124 pal: [0; 768],
125 tmp_buf: Vec::new(),
126 zbuf: Vec::new(),
127 frmcount: 0,
128 key_int: 25,
129 tile_w: 16,
130 tile_h: 16,
131 cmode: DeflateMode::default(),
132 compr: Deflate::new(DeflateMode::default()),
133 bpp: 0,
134 width: 0,
135 height: 0,
136 range: 128,
137 }
138 }
139 fn encode_intra(&mut self, bw: &mut ByteWriter, buf: NABufferType) -> EncoderResult<()> {
140 let bpp = buf_type_to_bpp(&buf);
141
142 if let NABufferType::None = buf {
143 if self.bpp == 0 {
144 return Err(EncoderError::FormatError);
145 }
146 self.frm1.copy_from_slice(&self.frm2);
147 } else {
148 if bpp == 0 {
149 return Err(EncoderError::FormatError);
150 }
151 self.bpp = bpp;
152
153 if let (NABufferType::Video(ref vbuf), true) = (&buf, bpp == 8) {
154 let off = vbuf.get_offset(1);
155 let data = vbuf.get_data();
156 self.pal.copy_from_slice(&data[off..][..768]);
157 }
158
159 copy_frame(buf, &mut self.frm1, self.bpp)?;
160 }
161
162 bw.write_byte(1)?; // intra flag
163 bw.write_byte(0)?; // high version
164 bw.write_byte(1)?; // low version
165 bw.write_byte(if self.cmode == DeflateMode::NoCompr { 0 } else { 1 })?;
166 let fmt = match self.bpp {
167 8 => 4,
168 15 => 5,
169 16 => 6,
170 24 => 7,
171 32 => 8,
172 _ => unreachable!(),
173 };
174 bw.write_byte(fmt)?;
175 bw.write_byte(self.tile_w as u8)?;
176 bw.write_byte(self.tile_h as u8)?;
177
178 let bm = ((bpp as usize) + 7) / 8;
179 if self.cmode == DeflateMode::NoCompr {
180 if bpp == 8 {
181 bw.write_buf(&self.pal)?;
182 }
183 bw.write_buf(&self.frm1[..self.width * self.height * bm])?;
184 } else {
185 self.tmp_buf.truncate(0);
186 if bpp == 8 {
187 self.tmp_buf.extend_from_slice(&self.pal);
188 }
189 self.tmp_buf.extend_from_slice(&self.frm1[..self.width * self.height * bm]);
190 self.compr = Deflate::new(self.cmode);
191
192 let mut db = Vec::new();
193 std::mem::swap(&mut db, &mut self.zbuf);
194 db.truncate(0);
195 let mut wr = DeflateWriter::new(db);
196 self.compr.write_zlib_header(&mut wr);
197 self.compr.compress(&self.tmp_buf, &mut wr);
198 self.compr.compress_flush(&mut wr);
199 let mut db = wr.end();
200 std::mem::swap(&mut db, &mut self.zbuf);
201
202 bw.write_buf(&self.zbuf)?;
203 }
204
205 Ok(())
206 }
207 fn encode_inter(&mut self, bw: &mut ByteWriter, buf: NABufferType) -> EncoderResult<()> {
208 if let NABufferType::None = buf {
209 self.frm1.copy_from_slice(&self.frm2);
210
211 bw.write_byte(0)?;
212 self.tmp_buf.truncate(0);
213 let tile_w = (self.width + self.tile_w - 1) / self.tile_w;
214 let tile_h = (self.height + self.tile_h - 1) / self.tile_h;
215 let mv_size = (tile_w * tile_h * 2 + 3) & !3;
216 for _ in 0..mv_size {
217 self.tmp_buf.push(0);
218 }
219 if self.cmode == DeflateMode::NoCompr {
220 bw.write_buf(&self.tmp_buf)?;
221 } else {
222 let mut db = Vec::new();
223
224 std::mem::swap(&mut db, &mut self.zbuf);
225 db.truncate(0);
226 let mut wr = DeflateWriter::new(db);
227 self.compr.compress(&self.tmp_buf, &mut wr);
228 self.compr.compress_flush(&mut wr);
229 let mut db = wr.end();
230 std::mem::swap(&mut db, &mut self.zbuf);
231
232 bw.write_buf(&self.zbuf)?;
233 }
234 return Ok(());
235 }
236 let bpp = buf_type_to_bpp(&buf);
237 if bpp == 0 || bpp != self.bpp {
238 return Err(EncoderError::FormatError);
239 }
240
241 self.tmp_buf.truncate(0);
242 if let (NABufferType::Video(ref vbuf), true) = (&buf, bpp == 8) {
243 let mut npal = [0; 768];
244 let off = vbuf.get_offset(1);
245 let data = vbuf.get_data();
246 npal.copy_from_slice(&data[off..][..768]);
247 let mut cmp = true;
248 for (&a, &b) in self.pal.iter().zip(npal.iter()) {
249 if a != b {
250 cmp = false;
251 break;
252 }
253 }
254 if !cmp {
255 for (&a, &b) in self.pal.iter().zip(npal.iter()) {
256 self.tmp_buf.push(a ^ b);
257 }
258 self.pal = npal;
259
260 bw.write_byte(2)?;
261 } else {
262 bw.write_byte(0)?;
263 }
264 } else {
265 bw.write_byte(0)?;
266 }
267 copy_frame(buf, &mut self.frm1, self.bpp)?;
268
269 let tile_w = (self.width + self.tile_w - 1) / self.tile_w;
270 let tile_h = (self.height + self.tile_h - 1) / self.tile_h;
271 let mut mv_start = self.tmp_buf.len();
272 let mv_size = (tile_w * tile_h * 2 + 3) & !3;
273 for _ in 0..mv_size {
274 self.tmp_buf.push(0);
275 }
276
277 let bpp = ((self.bpp as usize) + 7) / 8;
278 let stride = self.width * bpp;
279 let mut off = 0;
280 for y in (0..self.height).step_by(self.tile_h) {
281 let cur_h = (self.height - y).min(self.tile_h);
282 for x in (0..self.width).step_by(self.tile_w) {
283 let cur_w = (self.width - x).min(self.tile_w);
284
285 let mut best_dist = std::u32::MAX;
286 let mut best_x = x;
287 let mut best_y = y;
288
289 'search: for yoff in 0..self.range {
290 let ypos = (y as isize) + to_signed(yoff);
291 if ypos < 0 {
292 continue;
293 }
294 let ypos = ypos as usize;
295 if ypos + cur_h > self.height {
296 break;
297 }
298 for xoff in 0..self.range {
299 let xpos = (x as isize) + to_signed(xoff);
300 if xpos < 0 {
301 continue;
302 }
303 let xpos = xpos as usize;
304 if xpos + cur_w > self.width {
305 break;
306 }
307
308 let mut diff = 0;
309 let roff = xpos * bpp + ypos * stride;
310 for (line0, line1) in self.frm1[off..].chunks(stride).take(cur_h).zip(self.frm2[roff..].chunks(stride)) {
311 for (&a, &b) in line0[..cur_w * bpp].iter().zip(line1[..cur_w * bpp].iter()) {
312 diff += u32::from(a ^ b);
313 }
314 }
315
316 if best_dist > diff {
317 best_dist = diff;
318 best_x = xpos;
319 best_y = ypos;
320 if diff == 0 {
321 break 'search;
322 }
323 }
324 }
325 }
326
327 let has_delta = best_dist != 0;
328 self.tmp_buf[mv_start] = (best_x.wrapping_sub(x) << 1) as u8;
329 if has_delta {
330 self.tmp_buf[mv_start] |= 1;
331 }
332 self.tmp_buf[mv_start + 1] = (best_y.wrapping_sub(y) << 1) as u8;
333 mv_start += 2;
334 if has_delta {
335 let rpos = best_x * bpp + best_y * stride;
336 for (line0, line1) in self.frm1[off..].chunks(stride).take(cur_h).zip(self.frm2[rpos..].chunks(stride)) {
337 for (&a, &b) in line0[..cur_w * bpp].iter().zip(line1[..cur_w * bpp].iter()) {
338 self.tmp_buf.push(a ^ b);
339 }
340 }
341 }
342
343 off += self.tile_w * bpp;
344 }
345 off -= tile_w * self.tile_w * bpp;
346 off += stride * self.tile_h;
347 }
348
349 if self.cmode == DeflateMode::NoCompr {
350 bw.write_buf(&self.tmp_buf)?;
351 } else {
352 let mut db = Vec::new();
353
354 std::mem::swap(&mut db, &mut self.zbuf);
355 db.truncate(0);
356 let mut wr = DeflateWriter::new(db);
357 self.compr.compress(&self.tmp_buf, &mut wr);
358 self.compr.compress_flush(&mut wr);
359 let mut db = wr.end();
360 std::mem::swap(&mut db, &mut self.zbuf);
361
362 bw.write_buf(&self.zbuf)?;
363 }
364
365 Ok(())
366 }
367}
368
369impl NAEncoder for ZMBVEncoder {
370 fn negotiate_format(&self, encinfo: &EncodeParameters) -> EncoderResult<EncodeParameters> {
371 match encinfo.format {
372 NACodecTypeInfo::None => {
373 let mut ofmt = EncodeParameters::default();
374 ofmt.format = NACodecTypeInfo::Video(NAVideoInfo::new(0, 0, true, YUV420_FORMAT));
375 Ok(ofmt)
376 },
377 NACodecTypeInfo::Audio(_) => Err(EncoderError::FormatError),
378 NACodecTypeInfo::Video(vinfo) => {
379 let depth = vinfo.format.get_total_depth();
380 let pix_fmt = if vinfo.format.is_paletted() {
381 PAL8_FORMAT
382 } else if !vinfo.format.model.is_rgb() || depth > 16 {
383 RGB24_0_FORMAT
384 } else if depth < 16 {
385 RGB555_FORMAT
386 } else {
387 RGB565_FORMAT
388 };
389 let outinfo = NAVideoInfo::new(vinfo.width, vinfo.height, false, pix_fmt);
390 let mut ofmt = *encinfo;
391 ofmt.format = NACodecTypeInfo::Video(outinfo);
392 Ok(ofmt)
393 }
394 }
395 }
396 fn init(&mut self, stream_id: u32, encinfo: EncodeParameters) -> EncoderResult<NAStreamRef> {
397 match encinfo.format {
398 NACodecTypeInfo::None => Err(EncoderError::FormatError),
399 NACodecTypeInfo::Audio(_) => Err(EncoderError::FormatError),
400 NACodecTypeInfo::Video(vinfo) => {
401 self.width = vinfo.width;
402 self.height = vinfo.height;
403
404 let out_info = NAVideoInfo::new(vinfo.width, vinfo.height, false, vinfo.format);
405 let info = NACodecInfo::new("zmbv", NACodecTypeInfo::Video(out_info), None);
406 let mut stream = NAStream::new(StreamType::Video, stream_id, info, encinfo.tb_num, encinfo.tb_den, 0);
407 stream.set_num(stream_id as usize);
408 let stream = stream.into_ref();
409
410 self.stream = Some(stream.clone());
411
412 self.frm1 = vec![0; vinfo.width * vinfo.height * 4];
413 self.frm2 = vec![0; vinfo.width * vinfo.height * 4];
414
415 Ok(stream)
416 },
417 }
418 }
419 fn encode(&mut self, frm: &NAFrame) -> EncoderResult<()> {
420 let buf = frm.get_buffer();
421 let mut dbuf = Vec::with_capacity(4);
422 let mut gw = GrowableMemoryWriter::new_write(&mut dbuf);
423 let mut bw = ByteWriter::new(&mut gw);
424 let is_intra = if self.frmcount == 0 {
425 self.encode_intra(&mut bw, buf)?;
426 true
427 } else {
428 self.encode_inter(&mut bw, buf)?;
429 false
430 };
431 self.pkt = Some(NAPacket::new(self.stream.clone().unwrap(), frm.ts, is_intra, dbuf));
432 self.frmcount += 1;
433 if self.frmcount == self.key_int {
434 self.frmcount = 0;
435 }
436 std::mem::swap(&mut self.frm1, &mut self.frm2);
437 Ok(())
438 }
439 fn get_packet(&mut self) -> EncoderResult<Option<NAPacket>> {
440 let mut npkt = None;
441 std::mem::swap(&mut self.pkt, &mut npkt);
442 Ok(npkt)
443 }
444 fn flush(&mut self) -> EncoderResult<()> {
445 self.frmcount = 0;
446 Ok(())
447 }
448}
449
450const ENCODER_OPTS: &[NAOptionDefinition] = &[
451 NAOptionDefinition {
452 name: KEYFRAME_OPTION, description: KEYFRAME_OPTION_DESC,
453 opt_type: NAOptionDefinitionType::Int(Some(0), Some(128)) },
454 NAOptionDefinition {
455 name: "range", description: "Block search range (0-128)",
456 opt_type: NAOptionDefinitionType::Int(Some(0), Some(128)) },
457 NAOptionDefinition {
458 name: "tile_width", description: "Block width (1-255)",
459 opt_type: NAOptionDefinitionType::Int(Some(1), Some(255)) },
460 NAOptionDefinition {
461 name: "tile_height", description: "Block width (1-255)",
462 opt_type: NAOptionDefinitionType::Int(Some(1), Some(255)) },
463 NAOptionDefinition {
464 name: "compr_level", description: "Compression level",
465 opt_type: DEFLATE_OPTION_VALUES },
466];
467
468impl NAOptionHandler for ZMBVEncoder {
469 fn get_supported_options(&self) -> &[NAOptionDefinition] { ENCODER_OPTS }
470 fn set_options(&mut self, options: &[NAOption]) {
471 for option in options.iter() {
472 for opt_def in ENCODER_OPTS.iter() {
473 if opt_def.check(option).is_ok() {
474 match option.name {
475 "compr_level" => {
476 if let NAValue::String(ref s) = option.value {
477 if let Ok(val) = s.parse::<DeflateMode>() {
478 self.cmode = val;
479 }
480 }
481 },
482 KEYFRAME_OPTION => {
483 if let NAValue::Int(intval) = option.value {
484 self.key_int = intval as u8;
485 }
486 },
487 "range" => {
488 if let NAValue::Int(intval) = option.value {
489 self.range = intval as usize;
490 }
491 },
492 "tile_width" => {
493 if let NAValue::Int(intval) = option.value {
494 self.tile_w = intval as usize;
495 }
496 },
497 "tile_height" => {
498 if let NAValue::Int(intval) = option.value {
499 self.tile_h = intval as usize;
500 }
501 },
502 _ => {},
503 };
504 }
505 }
506 }
507 }
508 fn query_option_value(&self, name: &str) -> Option<NAValue> {
509 match name {
510 "compr_level" => Some(NAValue::String(self.cmode.to_string())),
511 KEYFRAME_OPTION => Some(NAValue::Int(i64::from(self.key_int))),
512 "range" => Some(NAValue::Int(self.range as i64)),
513 "tile_width" => Some(NAValue::Int(self.tile_w as i64)),
514 "tile_height" => Some(NAValue::Int(self.tile_h as i64)),
515 _ => None,
516 }
517 }
518}
519
520pub fn get_encoder() -> Box<dyn NAEncoder + Send> {
521 Box::new(ZMBVEncoder::new())
522}
523
524#[cfg(test)]
525mod test {
526 use nihav_core::codecs::*;
527 use nihav_core::demuxers::*;
528 use nihav_core::muxers::*;
529 use crate::*;
530 use nihav_codec_support::test::enc_video::*;
531 use super::{RGB555_FORMAT, RGB24_0_FORMAT};
532
533 #[test]
534 fn test_zmbv_encoder_8bit() {
535 let mut dmx_reg = RegisteredDemuxers::new();
536 generic_register_all_demuxers(&mut dmx_reg);
537 let mut dec_reg = RegisteredDecoders::new();
538 generic_register_all_decoders(&mut dec_reg);
539 let mut mux_reg = RegisteredMuxers::new();
540 generic_register_all_muxers(&mut mux_reg);
541 let mut enc_reg = RegisteredEncoders::new();
542 generic_register_all_encoders(&mut enc_reg);
543
544 let dec_config = DecoderTestParams {
545 demuxer: "avi",
546 in_name: "assets/Misc/td3_000.avi",
547 stream_type: StreamType::Video,
548 limit: Some(20),
549 dmx_reg, dec_reg,
550 };
551 let enc_config = EncoderTestParams {
552 muxer: "avi",
553 enc_name: "zmbv",
554 out_name: "zmbv8.avi",
555 mux_reg, enc_reg,
556 };
557 let dst_vinfo = NAVideoInfo {
558 width: 0,
559 height: 0,
560 format: PAL8_FORMAT,
561 flipped: false,
562 bits: 8,
563 };
564 let enc_params = EncodeParameters {
565 format: NACodecTypeInfo::Video(dst_vinfo),
566 quality: 0,
567 bitrate: 0,
568 tb_num: 0,
569 tb_den: 0,
570 flags: 0,
571 };
572 //test_encoding_to_file(&dec_config, &enc_config, enc_params);
573 test_encoding_md5(&dec_config, &enc_config, enc_params,
574 &[0x50df10e2, 0x606f3268, 0xdd4bc2ff, 0x844e7d87]);
575 }
576
577 #[test]
578 fn test_zmbv_encoder_15bit() {
579 let mut dmx_reg = RegisteredDemuxers::new();
580 generic_register_all_demuxers(&mut dmx_reg);
581 let mut dec_reg = RegisteredDecoders::new();
582 generic_register_all_decoders(&mut dec_reg);
583 let mut mux_reg = RegisteredMuxers::new();
584 generic_register_all_muxers(&mut mux_reg);
585 let mut enc_reg = RegisteredEncoders::new();
586 generic_register_all_encoders(&mut enc_reg);
587
588 let dec_config = DecoderTestParams {
589 demuxer: "avi",
590 in_name: "assets/Misc/zmbv_15bit.avi",
591 stream_type: StreamType::Video,
592 limit: Some(4),
593 dmx_reg, dec_reg,
594 };
595 let enc_config = EncoderTestParams {
596 muxer: "avi",
597 enc_name: "zmbv",
598 out_name: "zmbv15.avi",
599 mux_reg, enc_reg,
600 };
601 let dst_vinfo = NAVideoInfo {
602 width: 0,
603 height: 0,
604 format: RGB555_FORMAT,
605 flipped: false,
606 bits: 8,
607 };
608 let enc_params = EncodeParameters {
609 format: NACodecTypeInfo::Video(dst_vinfo),
610 quality: 0,
611 bitrate: 0,
612 tb_num: 0,
613 tb_den: 0,
614 flags: 0,
615 };
616 //test_encoding_to_file(&dec_config, &enc_config, enc_params);
617 test_encoding_md5(&dec_config, &enc_config, enc_params,
618 &[0x0b4cb528, 0x66c91f6c, 0x1c2187a5, 0x2723a08d]);
619 }
620
621 #[test]
622 fn test_zmbv_encoder_16bit() {
623 let mut dmx_reg = RegisteredDemuxers::new();
624 generic_register_all_demuxers(&mut dmx_reg);
625 let mut dec_reg = RegisteredDecoders::new();
626 generic_register_all_decoders(&mut dec_reg);
627 let mut mux_reg = RegisteredMuxers::new();
628 generic_register_all_muxers(&mut mux_reg);
629 let mut enc_reg = RegisteredEncoders::new();
630 generic_register_all_encoders(&mut enc_reg);
631
632 let dec_config = DecoderTestParams {
633 demuxer: "avi",
634 in_name: "assets/Misc/zmbv_16bit.avi",
635 stream_type: StreamType::Video,
636 limit: Some(4),
637 dmx_reg, dec_reg,
638 };
639 let enc_config = EncoderTestParams {
640 muxer: "avi",
641 enc_name: "zmbv",
642 out_name: "zmbv16.avi",
643 mux_reg, enc_reg,
644 };
645 let dst_vinfo = NAVideoInfo {
646 width: 0,
647 height: 0,
648 format: RGB565_FORMAT,
649 flipped: false,
650 bits: 8,
651 };
652 let enc_params = EncodeParameters {
653 format: NACodecTypeInfo::Video(dst_vinfo),
654 quality: 0,
655 bitrate: 0,
656 tb_num: 0,
657 tb_den: 0,
658 flags: 0,
659 };
660 //test_encoding_to_file(&dec_config, &enc_config, enc_params);
661 test_encoding_md5(&dec_config, &enc_config, enc_params,
662 &[0x1a522743, 0x6c320a6e, 0xd08539e1, 0x03fc17ea]);
663 }
664
665 #[test]
666 fn test_zmbv_encoder_32bit() {
667 let mut dmx_reg = RegisteredDemuxers::new();
668 generic_register_all_demuxers(&mut dmx_reg);
669 let mut dec_reg = RegisteredDecoders::new();
670 generic_register_all_decoders(&mut dec_reg);
671 let mut mux_reg = RegisteredMuxers::new();
672 generic_register_all_muxers(&mut mux_reg);
673 let mut enc_reg = RegisteredEncoders::new();
674 generic_register_all_encoders(&mut enc_reg);
675
676 let dec_config = DecoderTestParams {
677 demuxer: "avi",
678 in_name: "assets/Misc/zmbv_32bit.avi",
679 stream_type: StreamType::Video,
680 limit: Some(4),
681 dmx_reg, dec_reg,
682 };
683 let enc_config = EncoderTestParams {
684 muxer: "avi",
685 enc_name: "zmbv",
686 out_name: "zmbv32.avi",
687 mux_reg, enc_reg,
688 };
689 let dst_vinfo = NAVideoInfo {
690 width: 0,
691 height: 0,
692 format: RGB24_0_FORMAT,
693 flipped: false,
694 bits: 8,
695 };
696 let enc_params = EncodeParameters {
697 format: NACodecTypeInfo::Video(dst_vinfo),
698 quality: 0,
699 bitrate: 0,
700 tb_num: 0,
701 tb_den: 0,
702 flags: 0,
703 };
704 //test_encoding_to_file(&dec_config, &enc_config, enc_params);
705 test_encoding_md5(&dec_config, &enc_config, enc_params,
706 &[0x3880e045, 0xe6c88dc7, 0x21066058, 0xc789f1e9]);
707 }
708}