]> git.nihav.org Git - nihav.git/blob - nihav-indeo/src/codecs/indeo3.rs
msvideo1enc: handle skip frames
[nihav.git] / nihav-indeo / src / codecs / indeo3.rs
1 use nihav_core::formats;
2 use nihav_core::codecs::*;
3 use nihav_core::io::byteio::*;
4 use std::io::SeekFrom;
5 use std::mem;
6 use super::indeo3data::*;
7
8 #[derive(Clone, Copy)]
9 struct MV {
10 x: i8,
11 y: i8
12 }
13
14 struct Buffers {
15 width: usize,
16 height: usize,
17 cw: usize,
18 ch: usize,
19 sbuf: Vec<u8>,
20 dbuf: Vec<u8>,
21 }
22
23 const DEFAULT_PIXEL: u8 = 0x40;
24
25 impl Buffers {
26 fn new() -> Self { Buffers { width: 0, height: 0, cw: 0, ch: 0, sbuf: Vec::new(), dbuf: Vec::new() } }
27 fn reset(&mut self) {
28 self.width = 0;
29 self.height = 0;
30 self.sbuf.clear();
31 self.dbuf.clear();
32 }
33 fn alloc(&mut self, w: usize, h: usize) {
34 self.width = w;
35 self.height = h;
36 self.cw = ((w >> 2) + 3) & !3;
37 self.ch = ((h >> 2) + 3) & !3;
38 self.sbuf.resize(w * h + self.cw * self.ch * 2, DEFAULT_PIXEL);
39 self.dbuf.resize(w * h + self.cw * self.ch * 2, DEFAULT_PIXEL);
40 }
41 fn flip(&mut self) { std::mem::swap(&mut self.sbuf, &mut self.dbuf); }
42 fn get_stride(&mut self, planeno: usize) -> usize {
43 if planeno == 0 { self.width } else { self.cw }
44 }
45 fn get_offset(&mut self, planeno: usize) -> usize {
46 match planeno {
47 1 => self.width * self.height,
48 2 => self.width * self.height + self.cw * self.ch,
49 _ => 0,
50 }
51 }
52 fn fill_framebuf(&mut self, fbuf: &mut NAVideoBuffer<u8>) {
53 for planeno in 0..3 {
54 let mut soff = self.get_offset(planeno);
55 let mut doff = fbuf.get_offset(planeno);
56 let sstride = self.get_stride(planeno);
57 let dstride = fbuf.get_stride(planeno);
58 let width = if planeno == 0 { self.width } else { self.width >> 2 };
59 let height = if planeno == 0 { self.height } else { self.height >> 2 };
60 let src = self.dbuf.as_slice();
61 let dst = fbuf.get_data_mut().unwrap();
62 for _ in 0..height {
63 for x in 0..width {
64 dst[doff + x] = src[soff + x] * 2;
65 }
66 soff += sstride;
67 doff += dstride;
68 }
69 }
70 }
71 fn copy_block(&mut self, doff: usize, soff: usize, stride: usize, w: usize, h: usize) {
72 let mut sidx = soff;
73 let mut didx = doff;
74 for _ in 0..h {
75 self.dbuf[didx..][..w].copy_from_slice(&self.sbuf[sidx..][..w]);
76 sidx += stride;
77 didx += stride;
78 }
79 }
80 fn fill_block(&mut self, doff: usize, stride: usize, w: usize, h: usize, topline: bool) {
81 let mut didx = doff;
82 let mut buf: [u8; 8] = [0; 8];
83 if topline {
84 for _ in 0..h {
85 for i in 0..w { self.dbuf[didx + i] = DEFAULT_PIXEL; }
86 didx += stride;
87 }
88 } else {
89 for i in 0..w { buf[i] = self.dbuf[didx - stride + i]; }
90 for _ in 0..h {
91 self.dbuf[didx..][..w].copy_from_slice(&buf[..w]);
92 didx += stride;
93 }
94 }
95 }
96 }
97
98 #[allow(unused_variables)]
99 fn apply_delta4x4(bufs: &mut Buffers, off: usize, stride: usize,
100 deltas: &[u8], topline: bool, first_line: bool) {
101 let dst = &mut bufs.dbuf[off..][..4];
102 for i in 0..4 { dst[i] = dst[i].wrapping_add(deltas[i]) & 0x7F; }
103 }
104
105 #[allow(unused_variables)]
106 fn apply_delta4x8(bufs: &mut Buffers, off: usize, stride: usize,
107 deltas: &[u8], topline: bool, first_line: bool) {
108 let dst = &mut bufs.dbuf[off..][..stride + 4];
109 for i in 0..4 { dst[i + stride] = dst[i].wrapping_add(deltas[i]) & 0x7F; }
110 if !topline {
111 for i in 0..4 { dst[i] = (dst[i + stride] + dst[i]) >> 1; }
112 } else {
113 for i in 0..4 { dst[i] = dst[i + stride]; }
114 }
115 }
116
117 #[allow(unused_variables)]
118 fn apply_delta4x8m11(bufs: &mut Buffers, off: usize, stride: usize,
119 deltas: &[u8], topline: bool, first_line: bool) {
120 let dst = &mut bufs.dbuf[off..][..stride + 4];
121 for i in 0..4 { dst[i] = dst[i] .wrapping_add(deltas[i]) & 0x7F; }
122 for i in 0..4 { dst[i + stride] = dst[i + stride].wrapping_add(deltas[i]) & 0x7F; }
123 }
124
125 #[allow(unused_variables)]
126 fn apply_delta8x8p(bufs: &mut Buffers, off: usize, stride: usize,
127 deltas: &[u8], topline: bool, first_line: bool) {
128 let dst = &mut bufs.dbuf[off..][..stride + 8];
129 for i in 0..8 { dst[i] = dst[i] .wrapping_add(deltas[i >> 1]) & 0x7F; }
130 for i in 0..8 { dst[i + stride] = dst[i + stride].wrapping_add(deltas[i >> 1]) & 0x7F; }
131 }
132
133 fn apply_delta8x8i(bufs: &mut Buffers, off: usize, stride: usize,
134 deltas: &[u8], topline: bool, firstline: bool) {
135 let dst = &mut bufs.dbuf[off..][..stride + 8];
136 if !firstline {
137 for i in 0..8 { dst[i + stride] = dst[i ].wrapping_add(deltas[i >> 1]) & 0x7F; }
138 } else {
139 for i in 0..8 { dst[i + stride] = dst[i & !1].wrapping_add(deltas[i >> 1]) & 0x7F; }
140 }
141 if !topline {
142 for i in 0..8 { dst[i] = (dst[i + stride] + dst[i]) >> 1; }
143 } else {
144 for i in 0..8 { dst[i] = dst[i + stride]; }
145 }
146 }
147
148 fn copy_line_top(bufs: &mut Buffers, off: usize, stride: usize, bw: usize, topline: bool) {
149 let mut buf: [u8; 8] = [0; 8];
150 if !topline {
151 let src = &bufs.dbuf[(off - stride)..(off - stride + bw)];
152 buf[..bw].copy_from_slice(&src[..bw]);
153 } else {
154 for i in 0..bw { buf[i] = DEFAULT_PIXEL; }
155 }
156 let dst = &mut bufs.dbuf[off..][..bw];
157 dst.copy_from_slice(&buf[..bw]);
158 }
159
160 fn copy_line_top4x4(bufs: &mut Buffers, off: usize, stride: usize, topline: bool) {
161 copy_line_top(bufs, off, stride, 4, topline);
162 }
163
164 fn copy_line_top4x8(bufs: &mut Buffers, off: usize, stride: usize, topline: bool) {
165 copy_line_top(bufs, off, stride, 4, topline);
166 copy_line_top(bufs, off + stride, stride, 4, false);
167 }
168
169 fn copy_line_top8x8(bufs: &mut Buffers, off: usize, stride: usize, topline: bool) {
170 let mut buf: [u8; 8] = [0; 8];
171 if !topline {
172 let src = &bufs.dbuf[(off - stride)..(off - stride + 8)];
173 for i in 0..8 { buf[i] = src[i & !1]; }
174 } else {
175 for i in 0..8 { buf[i] = DEFAULT_PIXEL; }
176 }
177 let dst = &mut bufs.dbuf[off..][..8];
178 dst.copy_from_slice(&buf[..8]);
179 }
180
181 fn fill_block8x8(bufs: &mut Buffers, doff: usize, stride: usize, h: usize, topline: bool, firstline: bool) {
182 let mut didx = doff;
183 let mut buf: [u8; 8] = [0; 8];
184 if firstline {
185 for i in 0..8 { buf[i] = DEFAULT_PIXEL; }
186 } else {
187 for i in 0..8 { buf[i] = bufs.dbuf[doff - stride + i]; }
188 }
189 if topline && !firstline {
190 for i in 0..4 { buf[i * 2 + 1] = buf[i * 2]; }
191 for i in 0..8 { bufs.dbuf[doff + i] = (bufs.dbuf[doff - stride + i] + buf[i]) >> 1; }
192 }
193
194 let start = if !topline { 0 } else { 1 };
195 if topline {
196 didx += stride;
197 }
198 for _ in start..h {
199 bufs.dbuf[didx..][..8].copy_from_slice(&buf[..8]);
200 didx += stride;
201 }
202 }
203
204 struct Indeo3Decoder {
205 info: NACodecInfoRef,
206 bpos: u8,
207 bbuf: u8,
208 width: u16,
209 height: u16,
210 mvs: Vec<MV>,
211 altquant: [u8; 16],
212 vq_offset: u8,
213 bufs: Buffers,
214 requant_tab: [[u8; 128]; 8],
215 }
216
217 #[derive(Clone,Copy)]
218 struct IV3Cell {
219 x: u16,
220 y: u16,
221 w: u16,
222 h: u16,
223 d: u8,
224 vqt: bool,
225 mv: Option<MV>,
226 }
227
228 impl IV3Cell {
229 fn new(w: u16, h: u16) -> Self {
230 IV3Cell { x: 0, y: 0, w, h, d: 20, vqt: false, mv: None }
231 }
232 fn split_h(&self) -> (Self, Self) {
233 let h1 = if self.h > 2 { ((self.h + 2) >> 2) << 1 } else { 1 };
234 let h2 = self.h - h1;
235 let mut cell1 = *self;
236 cell1.h = h1;
237 cell1.d -= 1;
238 let mut cell2 = *self;
239 cell2.y += h1;
240 cell2.h = h2;
241 cell2.d -= 1;
242 (cell1, cell2)
243 }
244 fn split_w(&self, stripw: u16) -> (Self, Self) {
245 let w1 = if self.w > stripw {
246 if self.w > stripw * 2 { stripw * 2 } else { stripw }
247 } else {
248 if self.w > 2 { ((self.w + 2) >> 2) << 1 } else { 1 }
249 };
250 let w2 = self.w - w1;
251 let mut cell1 = *self;
252 cell1.w = w1;
253 cell1.d -= 1;
254 let mut cell2 = *self;
255 cell2.x += w1;
256 cell2.w = w2;
257 cell2.d -= 1;
258 (cell1, cell2)
259 }
260 fn no_mv(&self) -> bool { self.mv.is_none() }
261 }
262
263 struct CellDecParams {
264 tab: [usize; 2],
265 bw: u16,
266 bh: u16,
267 swap_q: [bool; 2],
268 hq: bool,
269 apply_delta: fn (&mut Buffers, usize, usize, &[u8], bool, bool),
270 copy_line_top: fn (&mut Buffers, usize, usize, bool),
271 }
272
273 const FRMH_TAG: u32 = ((b'F' as u32) << 24) | ((b'R' as u32) << 16)
274 | ((b'M' as u32) << 8) | (b'H' as u32);
275
276 const H_SPLIT: u8 = 0;
277 const V_SPLIT: u8 = 1;
278 const SKIP_OR_TREE: u8 = 2;
279
280 impl Indeo3Decoder {
281 fn new() -> Self {
282 const REQUANT_OFF: [i32; 8] = [ 0, 1, 0, 4, 4, 1, 0, 1 ];
283
284 let dummy_info = NACodecInfo::new_dummy();
285
286 let mut requant_tab = [[0u8; 128]; 8];
287 for i in 0..8 {
288 let step = (i as i32) + 2;
289 let start = if (i == 3) || (i == 4) { -3 } else { step / 2 };
290 let mut last = 0;
291 for j in 0..128 {
292 requant_tab[i][j] = (((j as i32) + start) / step * step + REQUANT_OFF[i]) as u8;
293 if requant_tab[i][j] < 128 {
294 last = requant_tab[i][j];
295 } else {
296 requant_tab[i][j] = last;
297 }
298 }
299 }
300 requant_tab[1][7] = 10;
301 requant_tab[1][119] = 118;
302 requant_tab[1][120] = 118;
303 requant_tab[4][8] = 10;
304
305 Indeo3Decoder { info: dummy_info, bpos: 0, bbuf: 0, width: 0, height: 0,
306 mvs: Vec::new(), altquant: [0; 16],
307 vq_offset: 0, bufs: Buffers::new(), requant_tab }
308 }
309
310 fn br_reset(&mut self) {
311 self.bpos = 0;
312 self.bbuf = 0;
313 }
314
315 fn get_2bits(&mut self, br: &mut ByteReader) -> DecoderResult<u8> {
316 if self.bpos == 0 {
317 self.bbuf = br.read_byte()?;
318 self.bpos = 8;
319 }
320 self.bpos -= 2;
321 Ok((self.bbuf >> self.bpos) & 0x3)
322 }
323
324 #[allow(clippy::cognitive_complexity)]
325 fn decode_cell_data(&mut self, br: &mut ByteReader, cell: IV3Cell,
326 off: usize, stride: usize, params: CellDecParams, vq_idx: u8) -> DecoderResult<()> {
327 let blk_w = cell.w * 4 / params.bw;
328 let blk_h = cell.h * 4 / params.bh;
329 let scale: usize = if params.bh == 4 { 1 } else { 2 };
330
331 validate!((((cell.w * 4) % params.bw) == 0) && (((cell.h * 4) % params.bh) == 0));
332
333 let mut run_blocks = 0;
334 let mut run_skip = false;
335
336 let mut didx: usize = ((cell.x*4) as usize) + ((cell.y * 4) as usize) * stride + off;
337 let mut sidx: usize;
338
339 if cell.no_mv() {
340 sidx = 0;
341 } else {
342 let mv = cell.mv.unwrap();
343 let mx = i16::from(mv.x);
344 let my = i16::from(mv.y);
345 let l = (cell.x as i16) * 4 + mx;
346 let t = (cell.y as i16) * 4 + my;
347 let r = ((cell.x + cell.w) as i16) * 4 + mx;
348 let b = ((cell.y + cell.h) as i16) * 4 + my;
349 validate!(l >= 0);
350 validate!(t >= 0);
351 validate!(r <= (self.width as i16));
352 validate!(b <= (self.height as i16));
353 sidx = (l as usize) + (t as usize) * stride + off;
354 }
355 if vq_idx >= 8 {
356 let requant_tab = &self.requant_tab[(vq_idx & 7) as usize];
357 if cell.no_mv() {
358 if cell.y > 0 {
359 for x in 0..(cell.w as usize) * 4 {
360 self.bufs.dbuf[didx + x - stride] = requant_tab[self.bufs.dbuf[didx + x - stride] as usize];
361 }
362 }
363 } else {
364 for x in 0..(cell.w as usize) * 4 {
365 self.bufs.sbuf[sidx + x] = requant_tab[self.bufs.sbuf[sidx + x] as usize];
366 }
367 }
368 }
369 for y in 0..blk_h {
370 let mut xoff: usize = 0;
371 for _ in 0..blk_w {
372 if run_blocks > 0 {
373 if !run_skip || !cell.no_mv() {
374 if !(params.bw == 8 && cell.no_mv()) {
375 if !cell.no_mv() {
376 self.bufs.copy_block(didx + xoff, sidx + xoff, stride,
377 params.bw as usize, params.bh as usize);
378 } else {
379 self.bufs.fill_block(didx + xoff, stride,
380 params.bw as usize, params.bh as usize,
381 (cell.y == 0) && (y == 0));
382 }
383 } else {
384 fill_block8x8(&mut self.bufs,
385 didx + xoff, stride, 8,
386 y == 0, (cell.y == 0) && (y == 0));
387 }
388 }
389 run_blocks -= 1;
390 } else {
391 let mut line: usize = 0;
392 while line < 4 {
393 let c = br.read_byte()?;
394 if c < 0xF8 {
395 let delta_tab = if params.hq {
396 IVI3_DELTA_CBS[params.tab[line & 1]]
397 } else {
398 IVI3_DELTA_CBS[params.tab[1]]
399 };
400 let mut idx1;
401 let mut idx2;
402 if (c as usize) < delta_tab.data.len()/2 {
403 idx1 = br.read_byte()? as usize;
404 validate!(idx1 < delta_tab.data.len() / 2);
405 idx2 = c as usize;
406 } else {
407 let tmp = (c as usize) - delta_tab.data.len()/2;
408 idx1 = tmp / (delta_tab.quad_radix as usize);
409 idx2 = tmp % (delta_tab.quad_radix as usize);
410 if params.swap_q[line & 1] {
411 mem::swap(&mut idx1, &mut idx2);
412 }
413 }
414 let deltas: [u8; 4] = [delta_tab.data[idx1 * 2] as u8,
415 delta_tab.data[idx1 * 2 + 1] as u8,
416 delta_tab.data[idx2 * 2 + 0] as u8,
417 delta_tab.data[idx2 * 2 + 1] as u8];
418 let topline = (cell.y == 0) && (y == 0) && (line == 0);
419 let first_line = (y == 0) && (line == 0);
420 if cell.no_mv() {
421 (params.copy_line_top)(&mut self.bufs,
422 didx + xoff + line * scale * stride,
423 stride, topline);
424 } else {
425 self.bufs.copy_block(didx + xoff + line * scale * stride,
426 sidx + xoff + line * scale * stride,
427 stride, params.bw as usize, scale);
428 }
429 (params.apply_delta)(&mut self.bufs,
430 didx + xoff + line * scale * stride,
431 stride, &deltas, topline, first_line);
432 line += 1;
433 } else {
434 let mut tocopy: usize = 0;
435 let mut do_copy = true;
436 if c == 0xF8 { return Err(DecoderError::InvalidData); }
437 if c == 0xF9 {
438 run_blocks = 1;
439 run_skip = true;
440 validate!(line == 0);
441 tocopy = 4;
442 do_copy = !cell.no_mv();
443 }
444 if c == 0xFA {
445 validate!(line == 0);
446 tocopy = 4;
447 do_copy = !cell.no_mv();
448 }
449 if c == 0xFB {
450 let c = br.read_byte()?;
451 validate!((c < 64) && ((c & 0x1F) != 0));
452 run_blocks = (c & 0x1F) - 1;
453 run_skip = (c & 0x20) != 0;
454 tocopy = 4 - line;
455 if params.bw == 4 && cell.no_mv() && run_skip {
456 do_copy = false;
457 }
458 }
459 if c == 0xFC {
460 run_skip = false;
461 run_blocks = 1;
462 tocopy = 4 - line;
463 }
464 if c >= 0xFD {
465 let nl = 257 - i16::from(c) - (line as i16);
466 validate!(nl > 0);
467 tocopy = nl as usize;
468 }
469 if do_copy {
470 if !(params.bh == 8 && cell.no_mv()) {
471 if !cell.no_mv() {
472 self.bufs.copy_block(didx + xoff + line * scale * stride,
473 sidx + xoff + line * scale * stride,
474 stride, params.bw as usize,
475 tocopy * scale);
476 } else {
477 self.bufs.fill_block(didx + xoff + line * scale * stride,
478 stride, params.bw as usize,
479 tocopy * scale,
480 (cell.y == 0) && (y == 0) && (line == 0));
481 }
482 } else {
483 fill_block8x8(&mut self.bufs,
484 didx + xoff + line * 2 * stride,
485 stride, tocopy * 2,
486 (y == 0) && (line == 0),
487 (cell.y == 0) && (y == 0) && (line == 0));
488 }
489 }
490 line += tocopy;
491 }
492 }
493 }
494 xoff += params.bw as usize;
495 }
496 didx += stride * (params.bh as usize);
497 sidx += stride * (params.bh as usize);
498 }
499 Ok(())
500 }
501
502 fn copy_cell(&mut self, cell: IV3Cell, off: usize, stride: usize) -> DecoderResult<()> {
503 if cell.no_mv() { return Err(DecoderError::InvalidData); }
504 let mv = cell.mv.unwrap();
505 let mx = i16::from(mv.x);
506 let my = i16::from(mv.y);
507 let l = (cell.x as i16) * 4 + mx;
508 let t = (cell.y as i16) * 4 + my;
509 let r = ((cell.x + cell.w) as i16) * 4 + mx;
510 let b = ((cell.y + cell.h) as i16) * 4 + my;
511 validate!(l >= 0);
512 validate!(t >= 0);
513 validate!(r <= (self.width as i16));
514 validate!(b <= (self.height as i16));
515 let sidx: usize = off + (l as usize) + (t as usize) * stride;
516 let didx: usize = off + ((cell.x * 4) as usize) + ((cell.y * 4) as usize) * stride;
517 self.bufs.copy_block(didx, sidx, stride, (cell.w * 4) as usize, (cell.h * 4) as usize);
518 Ok(())
519 }
520
521 fn decode_cell(&mut self, br: &mut ByteReader, cell: IV3Cell, off: usize,
522 stride: usize, intra: bool) -> DecoderResult<()> {
523 let code = br.read_byte()?;
524 let mode = code >> 4;
525 let vq_idx = code & 0xF;
526
527 let mut idx1: usize = vq_idx as usize;
528 let mut idx2: usize = vq_idx as usize;
529 if (mode == 1) || (mode == 4) {
530 let c = self.altquant[vq_idx as usize];
531 idx1 = (c >> 4) as usize;
532 idx2 = (c & 0xF) as usize;
533 } else {
534 idx1 += self.vq_offset as usize;
535 idx2 += self.vq_offset as usize;
536 }
537 validate!((idx1 < 24) && (idx2 < 24));
538
539 let mut cp = CellDecParams {
540 tab: [idx2, idx1],
541 bw: 0, bh: 0,
542 swap_q: [idx2 >= 16, idx1 >= 16],
543 hq: false,
544 apply_delta: apply_delta4x4,
545 copy_line_top: copy_line_top4x4,
546 };
547 if (mode == 0) || (mode == 1) {
548 cp.bw = 4;
549 cp.bh = 4;
550 cp.hq = true;
551 } else if (mode == 3) || (mode == 4) {
552 if !cell.no_mv() { return Err(DecoderError::InvalidData); }
553 cp.bw = 4;
554 cp.bh = 8;
555 cp.hq = true;
556 cp.apply_delta = apply_delta4x8;
557 cp.copy_line_top = copy_line_top4x8;
558 } else if mode == 10 {
559 if !cell.no_mv() {
560 validate!(!intra);
561 cp.apply_delta = apply_delta8x8p;
562 } else {
563 cp.apply_delta = apply_delta8x8i;
564 }
565 cp.bw = 8;
566 cp.bh = 8;
567 cp.copy_line_top = copy_line_top8x8;
568 } else if mode == 11 {
569 if cell.no_mv() { return Err(DecoderError::InvalidData); }
570 validate!(!intra);
571 cp.bw = 4;
572 cp.bh = 8;
573 cp.apply_delta = apply_delta4x8m11;
574 cp.copy_line_top = copy_line_top4x8;
575 } else {
576 return Err(DecoderError::InvalidData);
577 }
578 self.decode_cell_data(br, cell, off, stride, cp, vq_idx)
579 }
580
581 fn parse_tree(&mut self, br: &mut ByteReader, cell: IV3Cell, off: usize,
582 stride: usize, stripw: u16, intra: bool) -> DecoderResult<()> {
583 let op = self.get_2bits(br)?;
584 if op == H_SPLIT {
585 validate!(cell.h > 1);
586 validate!(cell.d > 0);
587 let (cell1, cell2) = cell.split_h();
588 self.parse_tree(br, cell1, off, stride, stripw, intra)?;
589 self.parse_tree(br, cell2, off, stride, stripw, intra)?;
590 Ok(())
591 } else if op == V_SPLIT {
592 validate!(cell.w > 1);
593 validate!(cell.d > 0);
594 let (cell1, cell2) = cell.split_w(stripw);
595 self.parse_tree(br, cell1, off, stride, stripw, intra)?;
596 self.parse_tree(br, cell2, off, stride, stripw, intra)?;
597 Ok(())
598 } else if op == SKIP_OR_TREE {
599 if !cell.vqt {
600 let mut newcell = cell;
601 newcell.vqt = true;
602 newcell.d -= 1;
603 self.parse_tree(br, newcell, off, stride, stripw, intra)
604 } else {
605 validate!(!intra);
606 let code = self.get_2bits(br)?;
607 validate!(code < 2);
608 if code == 1 { return Err(DecoderError::NotImplemented); }
609 self.copy_cell(cell, off, stride)
610 }
611 } else {
612 if !cell.vqt {
613 let mut newcell = cell;
614 newcell.vqt = true;
615 newcell.d -= 1;
616 let mv_idx = br.read_byte()? as usize;
617 validate!(mv_idx < self.mvs.len());
618 newcell.mv = Some(self.mvs[mv_idx]);
619 self.parse_tree(br, newcell, off, stride, stripw, intra)
620 } else {
621 self.decode_cell(br, cell, off, stride, intra)
622 }
623 }
624 }
625
626 fn decode_plane_intra(&mut self, br: &mut ByteReader, planeno: usize,
627 start: u64, end: u64) -> DecoderResult<()> {
628 let offs = self.bufs.get_offset(planeno);
629 let stride = self.bufs.get_stride(planeno);
630 br.seek(SeekFrom::Start(start))?;
631
632 let nvec = br.read_u32le()?;
633 validate!(nvec == 0); // for intra there should be no mc_vecs
634 self.mvs.clear();
635 for _ in 0..nvec {
636 let x = br.read_byte()? as i8;
637 let y = br.read_byte()? as i8;
638 self.mvs.push(MV{ x, y });
639 }
640
641 let (cellwidth, cellheight) = if planeno == 0 {
642 (self.bufs.width >> 2, self.bufs.height >> 2)
643 } else {
644 (((self.bufs.width >> 2) + 3) >> 2, ((self.bufs.height >> 2) + 3) >> 2)
645 };
646 let cell = IV3Cell::new(cellwidth as u16, cellheight as u16);
647 self.br_reset();
648 self.parse_tree(br, cell, offs, stride, if planeno > 0 { 10 } else { 40 }, true)?;
649 validate!(br.tell() <= end);
650 Ok(())
651 }
652
653 fn decode_plane_inter(&mut self, br: &mut ByteReader, planeno: usize,
654 start: u64, end: u64) -> DecoderResult<()> {
655 let offs = self.bufs.get_offset(planeno);
656 let stride = self.bufs.get_stride(planeno);
657 br.seek(SeekFrom::Start(start))?;
658
659 let nvec = br.read_u32le()?;
660 validate!(nvec <= 256); // for intra there should be no mc_vecs
661 self.mvs.clear();
662 for _ in 0..nvec {
663 let y = br.read_byte()? as i8;
664 let x = br.read_byte()? as i8;
665 self.mvs.push(MV{ x, y });
666 }
667
668 let (cellwidth, cellheight) = if planeno == 0 {
669 (self.bufs.width >> 2, self.bufs.height >> 2)
670 } else {
671 (((self.bufs.width >> 2) + 3) >> 2, ((self.bufs.height >> 2) + 3) >> 2)
672 };
673 let cell = IV3Cell::new(cellwidth as u16, cellheight as u16);
674 self.br_reset();
675 self.parse_tree(br, cell, offs, stride, if planeno > 0 { 10 } else { 40 }, false)?;
676 validate!(br.tell() <= end);
677 Ok(())
678 }
679 }
680
681 const FLAG_KEYFRAME: u16 = 1 << 2;
682 const FLAG_NONREF: u16 = 1 << 8;
683
684 impl NADecoder for Indeo3Decoder {
685 fn init(&mut self, _supp: &mut NADecoderSupport, info: NACodecInfoRef) -> DecoderResult<()> {
686 if let NACodecTypeInfo::Video(vinfo) = info.get_properties() {
687 let w = vinfo.get_width();
688 let h = vinfo.get_height();
689 let fmt = formats::YUV410_FORMAT;
690 let myinfo = NACodecTypeInfo::Video(NAVideoInfo::new(w, h, false, fmt));
691 self.info = NACodecInfo::new_ref(info.get_name(), myinfo, info.get_extradata()).into_ref();
692 self.bufs.reset();
693 Ok(())
694 } else {
695 Err(DecoderError::InvalidData)
696 }
697 }
698 fn decode(&mut self, _supp: &mut NADecoderSupport, pkt: &NAPacket) -> DecoderResult<NAFrameRef> {
699 let src = pkt.get_buffer();
700 let mut mr = MemoryReader::new_read(&src);
701 let mut br = ByteReader::new(&mut mr);
702 let frameno = br.read_u32le()?;
703 let hdr_2 = br.read_u32le()?;
704 let check = br.read_u32le()?;
705 let size = br.read_u32le()?;
706
707 let data_start = br.tell();
708
709 if (frameno ^ hdr_2 ^ size ^ FRMH_TAG) != check {
710 return Err(DecoderError::InvalidData);
711 }
712 if i64::from(size) > br.left() { return Err(DecoderError::InvalidData); }
713 let ver = br.read_u16le()?;
714 if ver != 32 { return Err(DecoderError::NotImplemented); }
715 let flags = br.read_u16le()?;
716 let size2 = br.read_u32le()?;
717 if size2 == 0x80 {
718 let mut frm = NAFrame::new_from_pkt(pkt, self.info.clone(), NABufferType::None);
719 frm.set_keyframe(false);
720 frm.set_frame_type(FrameType::Skip);
721 return Ok(frm.into_ref());
722 }
723 validate!(((size2 + 7) >> 3) <= size);
724 let cb = br.read_byte()?;
725 self.vq_offset = cb;
726 br.read_skip(3)?;
727 let height = br.read_u16le()?;
728 let width = br.read_u16le()?;
729 validate!((width >= 16) && (width <= 640));
730 validate!((height >= 16) && (height <= 640));
731 validate!(((width & 3) == 0) && ((height & 3) == 0));
732 let vinfo;
733 if (self.bufs.width != (width as usize)) || (self.bufs.height != (height as usize)) {
734 self.bufs.alloc(width as usize, height as usize);
735 vinfo = NAVideoInfo::new(width as usize, height as usize, false, formats::YUV410_FORMAT);
736 } else {
737 vinfo = self.info.get_properties().get_video_info().unwrap();
738 }
739 self.width = width;
740 self.height = height;
741
742 let yoff = br.read_u32le()?;
743 let uoff = br.read_u32le()?;
744 let voff = br.read_u32le()?;
745 if yoff > size { return Err(DecoderError::InvalidData); }
746 if uoff > size { return Err(DecoderError::InvalidData); }
747 if voff > size { return Err(DecoderError::InvalidData); }
748
749 br.read_skip(4)?;
750 br.read_buf(&mut self.altquant)?;
751
752 let mut yend = src.len() as u32;//size;
753 if (uoff < yend) && (uoff > yoff) { yend = uoff; }
754 if (voff < yend) && (voff > yoff) { yend = voff; }
755 let mut uend = size;
756 if (yoff < uend) && (yoff > uoff) { uend = yoff; }
757 if (voff < uend) && (voff > uoff) { uend = voff; }
758 let mut vend = size;
759 if (yoff < vend) && (yoff > voff) { vend = yoff; }
760 if (uoff < vend) && (uoff > voff) { vend = uoff; }
761
762 let intraframe = (flags & FLAG_KEYFRAME) != 0;
763 let bufinfo = alloc_video_buffer(vinfo, 4)?;
764 let mut buf = bufinfo.get_vbuf().unwrap();
765 let ystart = data_start + u64::from(yoff);
766 let ustart = data_start + u64::from(uoff);
767 let vstart = data_start + u64::from(voff);
768 let yendpos = data_start + u64::from(yend);
769 let uendpos = data_start + u64::from(uend);
770 let vendpos = data_start + u64::from(vend);
771 if intraframe {
772 self.decode_plane_intra(&mut br, 0, ystart, yendpos)?;
773 self.decode_plane_intra(&mut br, 1, vstart, vendpos)?;
774 self.decode_plane_intra(&mut br, 2, ustart, uendpos)?;
775 } else {
776 self.decode_plane_inter(&mut br, 0, ystart, yendpos)?;
777 self.decode_plane_inter(&mut br, 1, vstart, vendpos)?;
778 self.decode_plane_inter(&mut br, 2, ustart, uendpos)?;
779 }
780 self.bufs.fill_framebuf(&mut buf);
781 if (flags & FLAG_NONREF) == 0 { self.bufs.flip(); }
782 let mut frm = NAFrame::new_from_pkt(pkt, self.info.clone(), bufinfo);
783 frm.set_keyframe(intraframe);
784 frm.set_frame_type(if intraframe { FrameType::I } else { FrameType::P });
785 Ok(frm.into_ref())
786 }
787 fn flush(&mut self) {
788 self.bufs.reset();
789 }
790 }
791
792 impl NAOptionHandler for Indeo3Decoder {
793 fn get_supported_options(&self) -> &[NAOptionDefinition] { &[] }
794 fn set_options(&mut self, _options: &[NAOption]) { }
795 fn query_option_value(&self, _name: &str) -> Option<NAValue> { None }
796 }
797
798 pub fn get_decoder() -> Box<dyn NADecoder + Send> {
799 Box::new(Indeo3Decoder::new())
800 }
801
802 #[cfg(test)]
803 mod test {
804 use nihav_core::codecs::RegisteredDecoders;
805 use nihav_core::demuxers::RegisteredDemuxers;
806 use nihav_codec_support::test::dec_video::*;
807 use crate::indeo_register_all_decoders;
808 use nihav_commonfmt::generic_register_all_demuxers;
809 #[test]
810 fn test_indeo3() {
811 let mut dmx_reg = RegisteredDemuxers::new();
812 generic_register_all_demuxers(&mut dmx_reg);
813 let mut dec_reg = RegisteredDecoders::new();
814 indeo_register_all_decoders(&mut dec_reg);
815
816 // sample: https://samples.mplayerhq.hu/V-codecs/IV32/iv32_example.avi
817 test_decoding("avi", "indeo3", "assets/Indeo/iv32_example.avi", Some(10),
818 &dmx_reg, &dec_reg, ExpectedTestResult::MD5Frames(vec![
819 [0x90be698e, 0x326db071, 0x08e8c6a5, 0x39349acc],
820 [0x25d677fc, 0x63f96aaa, 0xd412ca98, 0x61416313],
821 [0xc4368250, 0x63e7b6bc, 0xffcff950, 0x11f13239],
822 [0x7e869758, 0x027abc2e, 0x25204bca, 0x93fbaa03],
823 [0x5a1e822c, 0x2b1a4cd5, 0x72059843, 0xe5689ad1],
824 [0x3a971cce, 0x5ec22135, 0x1a45f802, 0x0f5f9264],
825 [0x0a65f782, 0xd8767cf3, 0x878b4b8d, 0xfc94c88b],
826 [0x4ac70139, 0x3300eac1, 0xba84b068, 0x47f5ff29],
827 [0x3e8c8ec4, 0x9421b38c, 0x580abbbd, 0x92792d19],
828 [0x9096ee9b, 0x8dd9fb14, 0x981e31e3, 0x3ffd7d29],
829 [0x22dc71ec, 0x3d8f6f7e, 0x1a198982, 0x41d17ecc]]));
830 }
831 }