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