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