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