1 use nihav_core::formats::YUV420_FORMAT;
2 use nihav_core::frame::{NABufferType, NAVideoInfo, NAVideoBuffer, NAVideoBufferRef, FrameType, alloc_video_buffer};
3 use nihav_core::codecs::{NADecoderSupport, DecoderError, DecoderResult};
4 use nihav_codec_support::codecs::{MV, ZERO_MV, IPBShuffler};
5 use nihav_core::io::bitreader::{BitReader,BitReaderMode};
6 use nihav_core::io::intcode::*;
7 use nihav_codec_support::data::GenericCache;
10 use super::rv34codes::*;
11 use super::rv34dsp::*;
14 fn scale(&self, trd: u16, trb: u16) -> (MV, MV);
17 const TR_SHIFT: u8 = 14;
18 const TR_BIAS: i32 = 1 << (TR_SHIFT - 1);
20 impl RV34MVScale for MV {
21 fn scale(&self, trd: u16, trb: u16) -> (MV, MV) {
22 let ratio = ((trb as i32) << TR_SHIFT) / (trd as i32);
24 x: (((self.x as i32) * ratio + TR_BIAS) >> TR_SHIFT) as i16,
25 y: (((self.y as i32) * ratio + TR_BIAS) >> TR_SHIFT) as i16
27 let mv_b = mv_f - *self;
33 pub struct RV34SliceHeader {
45 impl RV34SliceHeader {
46 pub fn fits(&self, cmp: &RV34SliceHeader) -> bool {
47 (self.ftype == cmp.ftype) &&
48 (self.pts == cmp.pts) &&
49 (self.width == cmp.width) &&
50 (self.height == cmp.height)
55 #[derive(Debug,Clone,Copy,PartialEq)]
73 pub fn is_intra(self) -> bool {
74 (self == MBType::MBIntra) || (self == MBType::MBIntra16)
76 pub fn is_16(self) -> bool {
77 (self == MBType::MBIntra16) || (self == MBType::MBP16x16Mix)
79 pub fn is_intra_or_16(self) -> bool {
80 self.is_intra() || self.is_16()
82 pub fn get_num_mvs(self) -> usize {
84 MBType::MBIntra | MBType::MBIntra16 |
85 MBType::MBSkip | MBType::MBDirect => 0,
86 MBType::MBP16x16 | MBType::MBP16x16Mix |
87 MBType::MBForward | MBType::MBBackward => 1,
88 MBType::MBP16x8 | MBType::MBP8x16 | MBType::MBBidir => 2,
90 MBType::Invalid => unreachable!(),
93 pub fn is_fwd(self) -> bool {
95 MBType::MBP16x16 | MBType::MBP16x16Mix |
96 MBType::MBP16x8 | MBType::MBP8x16 | MBType::MBP8x8 |
99 pub fn is_bwd(self) -> bool {
100 matches!(self, MBType::MBBidir | MBType::MBBackward)
102 pub fn has_mv_dir(self, fwd: bool) -> bool {
104 MBType::MBBidir => true,
105 MBType::MBForward if fwd => true,
106 MBType::MBBackward if !fwd => true,
110 pub fn is_nomv(self) -> bool {
111 matches!(self, MBType::MBIntra | MBType::MBIntra16 | MBType::MBSkip | MBType::MBDirect)
113 /*pub fn is_16x16(self) -> bool {
115 MBType::MBP16x8 | MBType::MBP8x16 | MBType::MBP8x8 => false,
119 fn get_weight(self) -> usize {
121 MBType::MBIntra => 0,
122 MBType::MBIntra16 => 1,
123 MBType::MBSkip => unreachable!(),
124 MBType::MBP16x16 => 2,
125 MBType::MBP16x16Mix => 10,
126 MBType::MBP16x8 => 7,
127 MBType::MBP8x16 => 8,
129 MBType::MBDirect => 6,
130 MBType::MBBidir => 9,
131 MBType::MBForward => 4,
132 MBType::MBBackward => 5,
133 MBType::Invalid => unreachable!(),
138 const MBTYPE_FROM_WEIGHT: [MBType; 11] = [
139 MBType::MBIntra, MBType::MBIntra16, MBType::MBP16x16, MBType::MBP8x8,
140 MBType::MBForward, MBType::MBBackward, MBType::MBDirect, MBType::MBP16x8,
141 MBType::MBP8x16, MBType::MBBidir, MBType::MBP16x16Mix,
144 #[derive(Clone,Copy)]
151 #[derive(Clone,Copy)]
152 pub struct RV34MBInfo {
156 pub cbp_c: u8, // for deblocking purposes
160 struct IntraModeState {
161 cache: GenericCache<i8>,
164 const RV34_INTRA_PRED4: [PredType4x4; 9] = [
165 PredType4x4::DC, PredType4x4::Ver, PredType4x4::Hor,
166 PredType4x4::DiagDownRight, PredType4x4::DiagDownLeft,
167 PredType4x4::VerRight, PredType4x4::VerLeft,
168 PredType4x4::HorUp, PredType4x4::HorDown
171 const RV34_INTRA_PRED16: [PredType8x8; 4] = [
172 PredType8x8::DC, PredType8x8::Ver, PredType8x8::Hor, PredType8x8::Plane
175 impl IntraModeState {
176 fn new(mb_w: usize) -> Self {
177 let stride = 1 + mb_w * 4 + 1;
178 IntraModeState { cache: GenericCache::new(4, stride, -1) }
180 fn reset(&mut self) { self.cache.reset(); }
181 fn update(&mut self) { self.cache.update_row(); }
182 fn get_pos(&self, xpos: usize) -> usize {
183 self.cache.stride + 1 + xpos * 4
185 fn set_mb_x(&mut self, mb_x: usize) {
186 self.cache.xpos = self.get_pos(mb_x);
188 fn fill_block(&mut self, val: i8) {
189 let mut pos = self.cache.xpos;
192 self.cache.data[pos + j] = val;
194 pos += self.cache.stride;
197 fn get_pred16_type(&self, has_top: bool, has_left: bool) -> PredType8x8 {
198 if !has_top && !has_left { return PredType8x8::DC128; }
199 let mut im = RV34_INTRA_PRED16[self.cache.data[self.cache.xpos] as usize];
202 PredType8x8::Plane | PredType8x8::Ver => PredType8x8::Hor,
203 PredType8x8::DC => PredType8x8::LeftDC,
206 } else if !has_left {
208 PredType8x8::Plane | PredType8x8::Hor => PredType8x8::Ver,
209 PredType8x8::DC => PredType8x8::TopDC,
215 fn get_pred8_type(&self, has_top: bool, has_left: bool) -> PredType8x8 {
216 if !has_top && !has_left { return PredType8x8::DC128; }
217 let mut im = RV34_INTRA_PRED16[self.cache.data[self.cache.xpos] as usize];
218 im = match im { PredType8x8::Plane => PredType8x8::DC, _ => im };
221 PredType8x8::Plane | PredType8x8::Ver => PredType8x8::Hor,
222 PredType8x8::DC => PredType8x8::LeftDC,
225 } else if !has_left {
227 PredType8x8::Plane | PredType8x8::Hor => PredType8x8::Ver,
228 PredType8x8::DC => PredType8x8::TopDC,
234 fn get_pred4_type(&self, x: usize, y: usize, has_top: bool, has_left: bool) -> PredType4x4 {
235 let no_up = !has_top && (y == 0);
236 let no_left = !has_left && (x == 0);
237 if no_up && no_left { return PredType4x4::DC128; }
238 let no_down = !has_left || (x != 0) || (y == 3);
240 let mut im = RV34_INTRA_PRED4[self.cache.data[self.cache.xpos + x + y * self.cache.stride] as usize];
244 PredType4x4::Ver => PredType4x4::Hor,
245 PredType4x4::DC => PredType4x4::LeftDC,
250 PredType4x4::Hor => PredType4x4::Ver,
251 PredType4x4::DC => PredType4x4::TopDC,
252 PredType4x4::DiagDownLeft => PredType4x4::DiagDownLeftNoDown,
258 PredType4x4::DiagDownLeft => PredType4x4::DiagDownLeftNoDown,
259 PredType4x4::HorUp => PredType4x4::HorUpNoDown,
260 PredType4x4::VerLeft => PredType4x4::VerLeftNoDown,
267 fn get_pred4_type_chroma(&self, x: usize, y: usize, has_top: bool, has_left: bool) -> PredType4x4 {
268 let no_up = !has_top && (y == 0);
269 let no_left = !has_left && (x == 0);
270 if no_up && no_left { return PredType4x4::DC128; }
271 let no_down = !has_left || (x != 0) || (y == 1);
273 let mut im = RV34_INTRA_PRED4[self.cache.data[self.cache.xpos + x * 2 + y * 2 * self.cache.stride] as usize];
277 PredType4x4::Ver => PredType4x4::Hor,
278 PredType4x4::DC => PredType4x4::LeftDC,
283 PredType4x4::Hor => PredType4x4::Ver,
284 PredType4x4::DC => PredType4x4::TopDC,
285 PredType4x4::DiagDownLeft => PredType4x4::DiagDownLeftNoDown,
291 PredType4x4::DiagDownLeft => PredType4x4::DiagDownLeftNoDown,
292 PredType4x4::HorUp => PredType4x4::HorUpNoDown,
293 PredType4x4::VerLeft => PredType4x4::VerLeftNoDown,
306 pub has_b: Vec<bool>,
307 pub has_f: Vec<bool>,
312 Self { mv_b: Vec::new(), mv_f: Vec::new(), w: 0, h: 0, has_b: Vec::new(), has_f: Vec::new() }
314 fn resize(&mut self, mb_w: usize, mb_h: usize) {
319 fn reset(&mut self) {
320 let size = self.w * self.h;
322 self.mv_f.resize(size, ZERO_MV);
324 self.mv_b.resize(size, ZERO_MV);
326 self.has_f.resize(size >> 2, false);
328 self.has_b.resize(size >> 2, false);
330 fn fill(&mut self, mb_x: usize, mb_y: usize, fwd: bool, mv: MV) {
331 let idx = mb_x * 2 + mb_y * 2 * self.w;
333 self.mv_f[idx + 0] = mv;
334 self.mv_f[idx + 1] = mv;
335 self.mv_f[idx + self.w + 0] = mv;
336 self.mv_f[idx + self.w + 1] = mv;
338 self.mv_b[idx + 0] = mv;
339 self.mv_b[idx + 1] = mv;
340 self.mv_b[idx + self.w + 0] = mv;
341 self.mv_b[idx + self.w + 1] = mv;
344 fn get_mv_by_idx(&self, idx: usize, fwd: bool) -> MV {
345 if fwd { self.mv_f[idx] } else { self.mv_b[idx] }
347 fn pred_mv(&self, idx: usize, fwd: bool, has_top: bool, has_left: bool, has_tr: bool, has_tl: bool, is16: bool) -> MV {
348 if !has_top && !has_left { return ZERO_MV; }
349 let left_mv = if has_left { self.get_mv_by_idx(idx - 1, fwd) } else { ZERO_MV };
350 let top_mv = if has_top { self.get_mv_by_idx(idx - self.w, fwd) } else { left_mv };
351 let tr_add = if is16 { 2 } else { 1 };
354 tr_mv = self.get_mv_by_idx(idx - self.w + tr_add, fwd);
356 tr_mv = self.get_mv_by_idx(idx - self.w - 1, fwd);
360 MV::pred(left_mv, top_mv, tr_mv)
362 pub fn pred_mb_mv(&self, mb_x: usize, mb_y: usize, fwd: bool, has_top: bool, has_left: bool, has_tr: bool, has_tl: bool) -> MV {
363 self.pred_mv(mb_x * 2 + mb_y * 2 * self.w, fwd, has_top, has_left, has_tr, has_tl, true)
365 fn set_mb(&mut self, mb_x: usize, mb_y: usize, mbtype: MBType, ref_mvi: &Self, mvs: &[MV], sstate: &SState) {
366 let mb_idx = mb_x + mb_y * (self.w >> 1);
367 self.has_f[mb_idx] = mbtype.is_fwd();
368 self.has_b[mb_idx] = mbtype.is_bwd();
369 if mbtype.is_nomv() {
370 self.fill(mb_x, mb_y, true, ZERO_MV);
371 self.fill(mb_x, mb_y, false, ZERO_MV);
375 self.fill(mb_x, mb_y, false, ZERO_MV);
376 } else if mbtype.is_bwd() {
377 self.fill(mb_x, mb_y, true, ZERO_MV);
379 let idx = mb_x * 2 + mb_y * 2 * self.w;
383 self.fill(mb_x, mb_y, true, ZERO_MV/*pred_mv*/);
386 MBType::MBP16x16Mix => {
387 let pred_mv = self.pred_mv(idx, mbtype.is_fwd(), sstate.has_top, sstate.has_left, sstate.has_tr, sstate.has_tl, true);
388 let new_mv = mvs[0] + pred_mv;
389 self.fill(mb_x, mb_y, true, new_mv);
392 let pred_mv = self.pred_mv(idx, mbtype.is_fwd(), sstate.has_top, sstate.has_left, sstate.has_tr, sstate.has_tl, true);
393 let new_mv = mvs[0] + pred_mv;
394 self.mv_f[idx + 0] = new_mv;
395 self.mv_f[idx + 1] = new_mv;
397 let idx2 = idx + self.w;
398 let pred_mv = self.pred_mv(idx2, true, true, sstate.has_left, false, sstate.has_left, true);
399 let new_mv = mvs[1] + pred_mv;
400 self.mv_f[idx2 + 0] = new_mv;
401 self.mv_f[idx2 + 1] = new_mv;
404 let pred_mv = self.pred_mv(idx, true, sstate.has_top, sstate.has_left, sstate.has_top, sstate.has_tl, false);
405 let new_mv = mvs[0] + pred_mv;
406 self.mv_f[idx] = new_mv;
407 self.mv_f[idx + self.w] = new_mv;
409 let pred_mv = self.pred_mv(idx + 1, true, sstate.has_top, true, sstate.has_tr, sstate.has_top, false);
410 let new_mv = mvs[1] + pred_mv;
411 self.mv_f[idx + 1] = new_mv;
412 self.mv_f[idx + self.w + 1] = new_mv;
416 let mut has_top = sstate.has_top;
419 let has_left = (x > 0) || sstate.has_left;
420 let has_tr = if y > 0 { x == 0 } else if x == 0 { sstate.has_top } else { sstate.has_tr };
423 has_tl = if x == 0 { sstate.has_tl } else { sstate.has_top };
425 has_tl = if x == 0 { sstate.has_left } else { true };
427 let pred_mv = self.pred_mv(idx8 + x, true, has_top, has_left, has_tr, has_tl, false);
428 let new_mv = mvs[x + y * 2] + pred_mv;
429 self.mv_f[idx8 + x] = new_mv;
435 MBType::MBDirect => {
436 let mut cum_mv_f = ZERO_MV;
437 let mut cum_mv_b = ZERO_MV;
441 let (mv_f, mv_b) = ref_mvi.mv_f[idx8 + x].scale(sstate.trd, sstate.trb);
451 self.fill(mb_x, mb_y, true, cum_mv_f);
452 self.fill(mb_x, mb_y, false, cum_mv_b);
455 let pred_mv_f = ZERO_MV;
456 let new_mv = pred_mv_f + mvs[0];
457 self.fill(mb_x, mb_y, true, new_mv);
458 let pred_mv_b = ZERO_MV;
459 let new_mv = pred_mv_b + mvs[1];
460 self.fill(mb_x, mb_y, false, new_mv);
462 MBType::MBForward => {
463 let pred_mv = self.pred_mv(idx, mbtype.is_fwd(), sstate.has_top, sstate.has_left, sstate.has_tr, sstate.has_tl, true);
464 let new_mv = mvs[0] + pred_mv;
465 self.fill(mb_x, mb_y, true, new_mv);
467 MBType::MBBackward => {
468 let pred_mv = self.pred_mv(idx, mbtype.is_fwd(), sstate.has_top, sstate.has_left, sstate.has_tr, sstate.has_tl, true);
469 let new_mv = mvs[0] + pred_mv;
470 self.fill(mb_x, mb_y, false, new_mv);
475 pub fn get_mv(&self, mb_x: usize, mb_y: usize, x: usize, y: usize, fwd: bool) -> MV {
476 let idx = mb_x * 2 + x + (mb_y * 2 + y) * self.w;
477 if fwd { self.mv_f[idx] }
478 else { self.mv_b[idx] }
480 fn mv_gt_3(&self, mb_x: usize, mb_y: usize, x: usize, y: usize, vert: bool) -> bool {
481 let idx = mb_x * 2 + x + (mb_y * 2 + y) * self.w;
482 let off = if vert { self.w } else { 1 };
483 let diffx = self.mv_f[idx].x - self.mv_f[idx - off].x;
484 let diffy = self.mv_f[idx].y - self.mv_f[idx - off].y;
485 (diffx < -3) || (diffx > 3) || (diffy < -3) || (diffy > 3)
489 pub trait RV34BitstreamDecoder {
490 fn decode_slice_header(&mut self, br: &mut BitReader, old_w: usize, old_h: usize) -> DecoderResult<RV34SliceHeader>;
491 fn decode_intra_pred(&mut self, br: &mut BitReader, types: &mut [i8], pos: usize, tstride: usize, has_top: bool) -> DecoderResult<()>;
492 fn quant_dc(&self, is_intra: bool, q: u8) -> u8;
493 fn decode_inter_mb_hdr(&mut self, br: &mut BitReader, ftype: FrameType, mbtype: MBType) -> DecoderResult<MBInfo>;
494 fn predict_b_mv(&self, sstate: &SState, mvi: &MVInfo, mbtype: MBType, mvs: &[MV], mbinfo: &[RV34MBInfo]) -> (MV, MV);
498 fn loop_filter(&self, frame: &mut NAVideoBuffer<u8>, ftype: FrameType, mbinfo: &[RV34MBInfo], mb_w: usize, mb_h: usize, row: usize);
499 fn do_luma_mc(&self, frame: &mut NAVideoBuffer<u8>, prev_frame: &NAVideoBuffer<u8>, x: usize, y: usize, mv: MV, use16: bool, avg: bool);
500 fn do_chroma_mc(&self, frame: &mut NAVideoBuffer<u8>, prev_frame: &NAVideoBuffer<u8>, x: usize, y: usize, comp: usize, mv: MV, use8: bool, avg: bool);
503 fn parse_slice_offsets(src: &[u8], offsets: &mut Vec<usize>) -> DecoderResult<()> {
504 let num_slices = (src[0] as usize) + 1;
505 let ini_off = num_slices * 8 + 1;
508 if ini_off >= src.len() { return Err(DecoderError::ShortData); }
510 let mut br = BitReader::new(&src[1..ini_off], BitReaderMode::BE);
512 for i in 0..num_slices {
514 let off = br.read(32)? as usize;
515 if (i == 0) && (off != 0) {
516 return Err(DecoderError::InvalidData);
518 if (i > 0) && (off <= offsets[i - 1]) {
519 return Err(DecoderError::InvalidData);
527 fn decode_slice_header(br: &mut BitReader, bd: &mut dyn RV34BitstreamDecoder, slice_no: usize, slice_offs: &[usize], old_width: usize, old_height: usize) -> DecoderResult<RV34SliceHeader> {
528 validate!(slice_no < slice_offs.len());
529 br.seek((slice_offs[slice_no] * 8) as u32)?;
530 let mut shdr = bd.decode_slice_header(br, old_width, old_height)?;
531 if ((shdr.width == 0) || (shdr.height == 0)) && (shdr.ftype != FrameType::I) {
532 return Err(DecoderError::MissingReference);
534 if slice_no < slice_offs.len() - 1 {
535 let cur_pos = br.tell() as u32;
536 br.seek((slice_offs[slice_no + 1] * 8) as u32)?;
537 if let Ok(nhdr) = bd.decode_slice_header(br, shdr.width, shdr.height) {
538 validate!(nhdr.start > shdr.start);
539 shdr.end = nhdr.start;
541 if slice_no + 2 < slice_offs.len() {
542 br.seek((slice_offs[slice_no + 2] * 8) as u32)?;
543 if let Ok(nhdr) = bd.decode_slice_header(br, shdr.width, shdr.height) {
544 validate!(nhdr.start > shdr.start);
545 shdr.end = nhdr.start;
547 shdr.end = ((shdr.width + 15) >> 4) * ((shdr.height + 15) >> 4);
550 shdr.end = ((shdr.width + 15) >> 4) * ((shdr.height + 15) >> 4);
555 shdr.end = ((shdr.width + 15) >> 4) * ((shdr.height + 15) >> 4);
560 const RV34_MB_MAX_SIZES: [usize; 6] = [ 0x2F, 0x62, 0x18B, 0x62F, 0x18BF, 0x23FF ];
561 const RV34_SLICE_START_BITS: [u8; 6] = [ 6, 7, 9, 11, 13, 14 ];
563 pub fn get_slice_start_offset_bits(w: usize, h: usize) -> u8 {
564 if (w == 0) || (h == 0) {
567 let mb_size = ((w + 15) >> 4) * ((h + 15) >> 4) - 1;
568 let mut idx: usize = 0;
569 while (idx < 5) && (RV34_MB_MAX_SIZES[idx] < mb_size) { idx += 1; }
570 RV34_SLICE_START_BITS[idx]
573 const RV34_DQUANT_TAB: [[i8; 2]; 32] = [
574 [ 0, 0 ], [ 2, 1 ], [ -1, 1 ], [ -1, 1 ], [ -1, 1 ], [ -1, 1 ], [ -1, 1 ], [ -1, 1 ],
575 [ -1, 1 ], [ -1, 1 ], [ -1, 1 ], [ -2, 2 ], [ -2, 2 ], [ -2, 2 ], [ -2, 2 ], [ -2, 2 ],
576 [ -2, 2 ], [ -2, 2 ], [ -2, 2 ], [ -2, 2 ], [ -2, 2 ], [ -3, 3 ], [ -3, 3 ], [ -3, 3 ],
577 [ -3, 3 ], [ -3, 3 ], [ -3, 3 ], [ -3, 3 ], [ -3, 3 ], [ -3, 2 ], [ -3, 1 ], [ -3,-5 ]
580 const RV34_QUANT_TAB: [u16; 32] = [
581 60, 67, 76, 85, 96, 108, 121, 136,
582 152, 171, 192, 216, 242, 272, 305, 341,
583 383, 432, 481, 544, 606, 683, 767, 854,
584 963, 1074, 1212, 1392, 1566, 1708, 1978, 2211
587 const RV34_CHROMA_QUANT_DC: [u8; 32] = [
588 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13,
589 14, 15, 15, 16, 17, 18, 18, 19, 20, 20, 21, 21, 22, 22, 23, 23
591 const RV34_CHROMA_QUANT_AC: [u8; 32] = [
592 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
593 16, 17, 17, 18, 19, 20, 20, 21, 22, 22, 23, 23, 24, 24, 25, 25
596 fn decode_dquant(br: &mut BitReader, q: u8) -> DecoderResult<u8> {
598 let diff = RV34_DQUANT_TAB[q as usize][br.read(1)? as usize];
599 let qp = (q as i8) + diff;
600 validate!((qp > 0) && (qp < 32));
603 let qp = br.read(5)? as u8;
653 fn new(ftype: FrameType) -> Self { Self { is_p: ftype == FrameType::P, hist: [MBType::Invalid; 4], count: 0 } }
654 fn add(&mut self, mbt: MBType) {
655 let mbt2 = match mbt {
656 MBType::MBSkip if self.is_p => MBType::MBP16x16,
657 MBType::MBSkip if !self.is_p => MBType::MBDirect,
660 self.hist[self.count] = mbt2;
663 fn get_mbtype(&self) -> MBType {
666 } else if self.count == 1 {
668 } else if self.count == 2 {
669 if self.hist[0].get_weight() <= self.hist[1].get_weight() {
675 let mut w: [usize; 12] = [0; 12];
676 for i in 0..self.count { w[self.hist[i].get_weight()] += 1; }
679 if w[i] == self.count { return MBTYPE_FROM_WEIGHT[i]; }
680 if (w[i] > w[nz_idx]) || (w[nz_idx] == 0) { nz_idx = i; }
683 MBTYPE_FROM_WEIGHT[nz_idx]
688 fn decode_mv(br: &mut BitReader) -> DecoderResult<MV> {
689 let x = br.read_code_signed(IntCodeType::Gamma)? as i16;
690 let y = br.read_code_signed(IntCodeType::Gamma)? as i16;
694 fn do_mc_16x16(dsp: &mut dyn RV34DSP, buf: &mut NAVideoBuffer<u8>, prevbuf: &NAVideoBuffer<u8>, mb_x: usize, mb_y: usize, mv: MV, avg: bool) {
695 dsp.do_luma_mc (buf, prevbuf, mb_x * 16, mb_y * 16, mv, true, avg);
696 dsp.do_chroma_mc(buf, prevbuf, mb_x * 8, mb_y * 8, 1, mv, true, avg);
697 dsp.do_chroma_mc(buf, prevbuf, mb_x * 8, mb_y * 8, 2, mv, true, avg);
700 fn do_mc_8x8(dsp: &mut dyn RV34DSP, buf: &mut NAVideoBuffer<u8>, prevbuf: &NAVideoBuffer<u8>, mb_x: usize, xoff: usize, mb_y: usize, yoff: usize, mv: MV, avg: bool) {
701 dsp.do_luma_mc (buf, prevbuf, mb_x * 16 + xoff * 8, mb_y * 16 + yoff * 8, mv, false, avg);
702 dsp.do_chroma_mc(buf, prevbuf, mb_x * 8 + xoff * 4, mb_y * 8 + yoff * 4, 1, mv, false, avg);
703 dsp.do_chroma_mc(buf, prevbuf, mb_x * 8 + xoff * 4, mb_y * 8 + yoff * 4, 2, mv, false, avg);
706 fn do_avg(cdsp: &RV34CommonDSP, buf: &mut NAVideoBuffer<u8>, avg_buf: &NAVideoBuffer<u8>, mb_x: usize, xb: usize, mb_y: usize, yb: usize, size: usize, ratio1: u32, ratio2: u32) {
708 let xoff = if comp == 0 { mb_x * 16 + xb * 8 } else { mb_x * 8 + xb * 4 };
709 let yoff = if comp == 0 { mb_y * 16 + yb * 8 } else { mb_y * 8 + yb * 4 };
710 let csize = if comp == 0 { size } else { size >> 1 };
711 let dstride = buf.get_stride(comp);
712 let doffset = buf.get_offset(comp) + xoff + yoff * dstride;
713 let data = buf.get_data_mut().unwrap();
714 let dst: &mut [u8] = data.as_mut_slice();
716 let sstride = avg_buf.get_stride(comp);
717 let soffset = avg_buf.get_offset(comp);
718 let data = avg_buf.get_data();
719 let src: &[u8] = data.as_slice();
721 if ratio1 == ratio2 {
722 cdsp.avg(dst, doffset, dstride, src, soffset, sstride, csize);
724 cdsp.weight(dst, doffset, dstride, src, soffset, sstride, ratio2, ratio1, csize);
729 pub struct RV34Decoder {
732 dsp: Box<dyn RV34DSP + Send>,
744 mbinfo: Vec<RV34MBInfo>,
745 avg_buf: NAVideoBufferRef<u8>,
750 pub fn new(is_rv30: bool, dsp: Box<dyn RV34DSP + Send>) -> Self {
751 let tmp_vinfo = NAVideoInfo::new(16, 16, false, YUV420_FORMAT);
752 let vt = alloc_video_buffer(tmp_vinfo, 4).unwrap();
753 let vb = vt.get_vbuf();
754 let avg_buf = vb.unwrap();
757 coderead: RV34Codes::new(),
759 cdsp: RV34CommonDSP::new(),
760 ipbs: IPBShuffler::new(),
762 ref_mvi: MVInfo::new(),
765 last_ts: 0, next_ts: 0,
766 ratio1: 0, ratio2: 0,
772 fn decode_mb_header_intra(&mut self, bd: &mut dyn RV34BitstreamDecoder, br: &mut BitReader, is_i16: bool, im: &mut IntraModeState, q: u8, has_top: bool, has_dq: bool) -> DecoderResult<MBInfo> {
774 let imode = br.read(2)? as i8;
775 im.fill_block(imode);
776 Ok(MBInfo { mbtype: MBType::MBIntra16, skip_run: 0, dquant: false })
778 let dq = if !has_dq {
779 if !self.is_rv30 { !br.read_bool()? } else { false }
782 decode_dquant(br, q)?;
784 bd.decode_intra_pred(br, im.cache.data.as_mut_slice(), im.cache.xpos, im.cache.stride, has_top)?;
785 Ok(MBInfo { mbtype: MBType::MBIntra, skip_run: 0, dquant: dq })
788 fn decode_mb_header_inter(&mut self, bd: &mut dyn RV34BitstreamDecoder, br: &mut BitReader, ftype: FrameType, mbtype: MBType, im: &mut IntraModeState, q: u8, has_top: bool) -> DecoderResult<MBInfo> {
789 let hdr = bd.decode_inter_mb_hdr(br, ftype, mbtype)?;
790 validate!(hdr.mbtype != MBType::Invalid);
792 decode_dquant(br, q)?;
794 if hdr.mbtype.is_intra() {
795 return self.decode_mb_header_intra(bd, br, hdr.mbtype.is_16(), im, q, has_top, true);
800 fn decode_mb_intra(&mut self, sstate: &SState, imode: &IntraModeState, buf: &mut NAVideoBuffer<u8>, br: &mut BitReader, is_16: bool) -> DecoderResult<()> {
801 let mut cur_cbp = sstate.cbp;
803 let q_dc = RV34_QUANT_TAB[sstate.q_dc as usize];
804 let q_ac = RV34_QUANT_TAB[sstate.q as usize];
805 let luma_set = if is_16 { 2 } else { 1 };
806 let mut coeffs16: [i16; 16] = [0; 16];
808 let has_ac = self.coderead.decode_block(br, &mut coeffs16, 3, 0, q_dc, q_dc, q_ac)?;
810 self.cdsp.transform16(&mut coeffs16);
812 self.cdsp.transform16_dc(&mut coeffs16);
815 let stride = buf.get_stride(0);
816 let mut offset = buf.get_offset(0) + sstate.mb_x * 16 + sstate.mb_y * 16 * stride;
817 let data = buf.get_data_mut().unwrap();
818 let framebuf: &mut [u8] = data.as_mut_slice();
821 let im16 = imode.get_pred16_type(sstate.has_top, sstate.has_left);
822 self.cdsp.ipred16x16[im16 as usize](framebuf, offset, stride);
827 let mut coeffs: [i16; 16] = [0; 16];
829 if (cur_cbp & 1) != 0 {
830 has_ac = self.coderead.decode_block(br, &mut coeffs, luma_set, 0, q_ac, q_ac, q_ac)?;
835 coeffs[0] = coeffs16[x + y * 4];
837 let noright = (sstate.mb_x == sstate.mb_w - 1) && (x == 3);
838 let has_top = sstate.has_top || (y > 0);
839 let im = imode.get_pred4_type(x, y, sstate.has_top, sstate.has_left);
840 let topright: [u8; 4] = if (noright && sstate.has_top && y == 0) || (x == 3 && y > 0) {
841 let i = offset + x * 4 - stride;
842 [framebuf[i + 3], framebuf[i + 3], framebuf[i + 3], framebuf[i + 3]]
844 let i = offset + x * 4 - stride;
845 [framebuf[i + 4], framebuf[i + 5], framebuf[i + 6], framebuf[i + 7]]
849 self.cdsp.ipred4x4[im as usize](framebuf, offset + x*4, stride, &topright);
852 self.cdsp.transform(&mut coeffs);
854 self.cdsp.transform_dc(&mut coeffs);
856 self.cdsp.add_coeffs(framebuf, offset + x * 4, stride, &coeffs);
859 offset += stride * 4;
862 let q_dc = RV34_QUANT_TAB[RV34_CHROMA_QUANT_DC[sstate.q as usize] as usize];
863 let q_ac = RV34_QUANT_TAB[RV34_CHROMA_QUANT_AC[sstate.q as usize] as usize];
866 let stride = buf.get_stride(comp);
867 let mut offset = buf.get_offset(comp) + sstate.mb_x * 8 + sstate.mb_y * 8 * stride;
868 let data = buf.get_data_mut().unwrap();
869 let framebuf: &mut [u8] = data.as_mut_slice();
871 let im8 = imode.get_pred8_type(sstate.has_top, sstate.has_left);
872 self.cdsp.ipred8x8[im8 as usize](framebuf, offset, stride);
876 let mut coeffs: [i16; 16] = [0; 16];
878 if (cur_cbp & 1) != 0 {
879 has_ac = self.coderead.decode_block(br, &mut coeffs, chroma_set, 1, q_dc, q_ac, q_ac)?;
884 let noright = (sstate.mb_x == sstate.mb_w - 1) && (x == 1);
885 let has_top = sstate.has_top || (y > 0);
886 let im = imode.get_pred4_type_chroma(x, y, sstate.has_top, sstate.has_left);
887 let topright: [u8; 4] = if (noright && sstate.has_top && y == 0) || (x == 1 && y > 0) {
888 let i = offset + x * 4 - stride;
889 [framebuf[i + 3], framebuf[i + 3], framebuf[i + 3], framebuf[i + 3]]
891 let i = offset + x * 4 - stride;
892 [framebuf[i + 4], framebuf[i + 5], framebuf[i + 6], framebuf[i + 7]]
896 self.cdsp.ipred4x4[im as usize](framebuf, offset + x*4, stride, &topright);
899 self.cdsp.transform(&mut coeffs);
901 self.cdsp.transform_dc(&mut coeffs);
903 self.cdsp.add_coeffs(framebuf, offset + x * 4, stride, &coeffs);
906 offset += stride * 4;
912 fn do_mc(&mut self, buf: &mut NAVideoBuffer<u8>, mbh: &MBInfo, sstate: &SState) {
913 let mb_x = sstate.mb_x;
914 let mb_y = sstate.mb_y;
916 MBType::MBP16x16 | MBType::MBP16x16Mix => {
917 if let Some(ref prevbuf) = self.ipbs.get_lastref() {
918 let mv = self.mvi.get_mv(mb_x, mb_y, 0, 0, true);
919 do_mc_16x16(self.dsp.as_mut(), buf, prevbuf, mb_x, mb_y, mv, false);
922 MBType::MBForward => {
923 if let Some(ref fwdbuf) = self.ipbs.get_b_fwdref() {
924 let mv = self.mvi.get_mv(mb_x, mb_y, 0, 0, true);
925 do_mc_16x16(self.dsp.as_mut(), buf, fwdbuf, mb_x, mb_y, mv, false);
928 MBType::MBBackward => {
929 if let Some(ref bwdbuf) = self.ipbs.get_b_bwdref() {
930 let mv = self.mvi.get_mv(mb_x, mb_y, 0, 0, false);
931 do_mc_16x16(self.dsp.as_mut(), buf, bwdbuf, mb_x, mb_y, mv, false);
934 MBType::MBP8x8 | MBType::MBP8x16 | MBType::MBP16x8 => {
935 if let Some(ref prevbuf) = self.ipbs.get_lastref() {
938 let mv = self.mvi.get_mv(mb_x, mb_y, x, y, true);
939 do_mc_8x8(self.dsp.as_mut(), buf, prevbuf, mb_x, x, mb_y, y, mv, false);
944 MBType::MBSkip if !self.is_b => {
945 if let Some(ref prevbuf) = self.ipbs.get_lastref() {
946 do_mc_16x16(self.dsp.as_mut(), buf, prevbuf, mb_x, mb_y, ZERO_MV, false);
949 MBType::MBSkip | MBType::MBDirect => {
950 if let (Some(ref fwdbuf), Some(ref bwdbuf)) = (self.ipbs.get_b_fwdref(), self.ipbs.get_b_bwdref()) {
953 let (mv_f, mv_b) = self.ref_mvi.get_mv(mb_x, mb_y, x, y, true).scale(sstate.trd, sstate.trb);
954 do_mc_8x8(self.dsp.as_mut(), buf, fwdbuf, mb_x, x, mb_y, y, mv_f, false);
955 do_mc_8x8(self.dsp.as_mut(), &mut self.avg_buf, bwdbuf, mb_x, x, mb_y, y, mv_b, true);
956 do_avg(&self.cdsp, buf, &self.avg_buf, mb_x, x, mb_y, y, 8, self.ratio1, self.ratio2);
962 if let (Some(ref fwdbuf), Some(ref bwdbuf)) = (self.ipbs.get_b_fwdref(), self.ipbs.get_b_bwdref()) {
963 let mv_f = self.mvi.get_mv(mb_x, mb_y, 0, 0, true);
964 let mv_b = self.mvi.get_mv(mb_x, mb_y, 0, 0, false);
965 do_mc_16x16(self.dsp.as_mut(), buf, fwdbuf, mb_x, mb_y, mv_f, false);
966 do_mc_16x16(self.dsp.as_mut(), &mut self.avg_buf, bwdbuf, mb_x, mb_y, mv_b, true);
967 do_avg(&self.cdsp, buf, &self.avg_buf, mb_x, 0, mb_y, 0, 16, self.ratio1, self.ratio2);
973 fn decode_mb_inter(&mut self, sstate: &SState, mbh: &MBInfo, buf: &mut NAVideoBuffer<u8>, br: &mut BitReader, is_16: bool) -> DecoderResult<()> {
974 self.do_mc(buf, mbh, sstate);
976 let mut cur_cbp = sstate.cbp;
979 let q_dc = RV34_QUANT_TAB[sstate.q_dc as usize];
980 let q_ac = RV34_QUANT_TAB[sstate.q as usize];
981 let luma_set = if is_16 { 2 } else { 0 };
982 let mut coeffs16: [i16; 16] = [0; 16];
984 let has_ac = self.coderead.decode_block(br, &mut coeffs16, 3, 0, q_dc, q_dc, q_ac)?;
986 self.cdsp.transform16(&mut coeffs16);
988 self.cdsp.transform16_dc(&mut coeffs16);
991 let stride = buf.get_stride(0);
992 let mut offset = buf.get_offset(0) + sstate.mb_x * 16 + sstate.mb_y * 16 * stride;
993 let data = buf.get_data_mut().unwrap();
994 let framebuf: &mut [u8] = data.as_mut_slice();
998 let mut coeffs: [i16; 16] = [0; 16];
1000 if (cur_cbp & 1) != 0 {
1001 has_ac = self.coderead.decode_block(br, &mut coeffs, luma_set, 0, q_ac, q_ac, q_ac)?;
1006 coeffs[0] = coeffs16[x + y * 4];
1009 self.cdsp.transform(&mut coeffs);
1011 self.cdsp.transform_dc(&mut coeffs);
1013 self.cdsp.add_coeffs(framebuf, offset + x * 4, stride, &coeffs);
1016 offset += stride * 4;
1020 self.coderead.select_codes(false, sstate.q, sstate.set_idx, false);
1022 let q_dc = RV34_QUANT_TAB[RV34_CHROMA_QUANT_DC[sstate.q as usize] as usize];
1023 let q_ac = RV34_QUANT_TAB[RV34_CHROMA_QUANT_AC[sstate.q as usize] as usize];
1026 let stride = buf.get_stride(comp);
1027 let mut offset = buf.get_offset(comp) + sstate.mb_x * 8 + sstate.mb_y * 8 * stride;
1028 let data = buf.get_data_mut().unwrap();
1029 let framebuf: &mut [u8] = data.as_mut_slice();
1032 let mut coeffs: [i16; 16] = [0; 16];
1034 if (cur_cbp & 1) != 0 {
1035 has_ac = self.coderead.decode_block(br, &mut coeffs, chroma_set, 1, q_dc, q_ac, q_ac)?;
1040 self.cdsp.transform(&mut coeffs);
1042 self.cdsp.transform_dc(&mut coeffs);
1044 self.cdsp.add_coeffs(framebuf, offset + x * 4, stride, &coeffs);
1047 offset += stride * 4;
1052 fn fill_deblock_flags(&self, sstate: &SState, mb_pos: usize, mbinfo: &mut [RV34MBInfo]) {
1053 let mbt = mbinfo[mb_pos].mbtype;
1054 let mut hmvmask = 0;
1055 let mut vmvmask = 0;
1059 let shift = x * 2 + y * 8;
1060 if ((x > 0) || (sstate.mb_x > 0)) && self.mvi.mv_gt_3(sstate.mb_x, sstate.mb_y, x, y, false) {
1061 vmvmask |= 0x11 << shift;
1063 if ((y > 0) || sstate.has_top) && self.mvi.mv_gt_3(sstate.mb_x, sstate.mb_y, x, y, true) {
1064 hmvmask |= 0x03 << shift;
1068 if !sstate.has_top { hmvmask &= !0x000F; }
1069 if sstate.mb_x == 0 { vmvmask &= !0x1111; }
1071 vmvmask |= (vmvmask & 0x4444) >> 1;
1072 hmvmask |= (hmvmask & 0x0F00) >> 4;
1073 if sstate.mb_x > 0 {
1074 mbinfo[mb_pos - 1].deblock |= (vmvmask & 0x1111) << 3;
1078 mbinfo[mb_pos - sstate.mb_w].deblock |= (hmvmask & 0xF) << 12;
1081 if mbt.is_intra_or_16() {
1082 mbinfo[mb_pos].deblock = 0xFFFF;
1083 mbinfo[mb_pos].cbp_c = 0xFF;
1085 mbinfo[mb_pos].deblock = (mbinfo[mb_pos].cbp as u16) | hmvmask | vmvmask;
1086 mbinfo[mb_pos].cbp_c = (mbinfo[mb_pos].cbp >> 16) as u8;
1090 #[allow(clippy::cognitive_complexity)]
1091 pub fn parse_frame(&mut self, supp: &mut NADecoderSupport, src: &[u8], bd: &mut dyn RV34BitstreamDecoder) -> DecoderResult<(NABufferType, FrameType, u64)> {
1092 let mut slice_offs: Vec<usize> = Vec::new();
1093 parse_slice_offsets(src, &mut slice_offs)?;
1094 let ini_off = slice_offs.len() * 8 + 1;
1096 let mut br = BitReader::new(&src[ini_off..], BitReaderMode::BE);
1097 let hdr0 = decode_slice_header(&mut br, bd, 0, slice_offs.as_slice(), self.width, self.height)?;
1098 validate!((hdr0.width != 0) && (hdr0.height != 0));
1099 self.width = hdr0.width;
1100 self.height = hdr0.height;
1101 let mb_w = (hdr0.width + 15) >> 4;
1102 let mb_h = (hdr0.height + 15) >> 4;
1103 let mut mb_pos: usize = 0;
1104 let mut slice = hdr0;
1105 let mut slice_no: usize = 1;
1106 let is_intra = hdr0.ftype == FrameType::I;
1107 let mut skip_run: usize = 0;
1108 let mut imode = IntraModeState::new(mb_w);
1109 let mut q = hdr0.quant;
1111 let mut sstate = SState::new();
1112 let mut mbinfo: Vec<RV34MBInfo> = Vec::with_capacity(mb_w * mb_h);
1114 self.is_b = hdr0.ftype == FrameType::B;
1115 if hdr0.ftype != FrameType::B {
1116 self.last_ts = self.next_ts;
1117 self.next_ts = hdr0.pts;
1118 if self.last_ts > self.next_ts {
1119 self.base_ts += 1 << 13;
1124 if self.ipbs.get_lastref().is_none() {
1125 return Err(DecoderError::MissingReference);
1129 if self.ipbs.get_lastref().is_none() {
1130 return Err(DecoderError::MissingReference);
1132 if self.ipbs.get_nextref().is_none() {
1133 return Err(DecoderError::MissingReference);
1138 let ts_diff = (self.next_ts << 3).wrapping_sub(hdr0.pts << 3) >> 3;
1139 let ts = self.base_ts + (self.next_ts as u64) - (ts_diff as u64);
1140 sstate.trd = (self.next_ts << 3).wrapping_sub(self.last_ts << 3) >> 3;
1141 sstate.trb = (hdr0.pts << 3).wrapping_sub(self.last_ts << 3) >> 3;
1142 if sstate.trb != 0 {
1143 self.ratio1 = ((sstate.trb as u32) << 14) / (sstate.trd as u32);
1144 self.ratio2 = (((sstate.trd as u32) - (sstate.trb as u32)) << 14) / (sstate.trd as u32);
1146 self.ratio1 = 1 << 14 >> 1;
1147 self.ratio2 = 1 << 14 >> 1;
1149 //todo validate against ref frame
1151 let vinfo = NAVideoInfo::new(hdr0.width, hdr0.height, false, YUV420_FORMAT);
1152 let ret = supp.pool_u8.get_free();
1154 return Err(DecoderError::AllocError);
1156 let mut buf = ret.unwrap();
1157 if buf.get_info() != vinfo {
1159 supp.pool_u8.reset();
1160 supp.pool_u8.prealloc_video(vinfo, 4)?;
1161 let ret = supp.pool_u8.get_free();
1163 return Err(DecoderError::AllocError);
1169 sstate.has_top = false;
1172 sstate.set_idx = hdr0.set_idx;
1174 self.mvi.resize(mb_w, mb_h);
1175 for mb_y in 0..mb_h {
1177 sstate.has_left = false;
1178 for mb_x in 0..mb_w {
1180 if mb_pos == slice.end {
1181 slice = decode_slice_header(&mut br, bd, slice_no, &slice_offs, self.width, self.height)?;
1182 validate!(slice.fits(&hdr0));
1187 sstate.has_top = false;
1188 sstate.has_left = false;
1189 sstate.set_idx = slice.set_idx;
1191 sstate.has_top = (mb_pos - slice.start) >= mb_w;
1192 sstate.has_tl = sstate.has_top && (mb_x > 0) && (mb_pos > slice.start + mb_w);
1193 sstate.has_tr = (mb_x < mb_w - 1) && (mb_pos - slice.start >= mb_w - 1);
1194 imode.set_mb_x(mb_x);
1195 let mbh = if is_intra {
1196 let is_i16 = br.read_bool()?;
1197 self.decode_mb_header_intra(bd, &mut br, is_i16, &mut imode, q, sstate.has_top, false)?
1202 mbtype = MBType::Invalid;
1204 let mut hist = MBHist::new(hdr0.ftype);
1206 hist.add(mbinfo[mb_pos - mb_w].mbtype);
1207 if sstate.has_tr { hist.add(mbinfo[mb_pos - mb_w + 1].mbtype); }
1209 if sstate.has_left { hist.add(mbinfo[mb_pos - 1].mbtype); }
1210 if sstate.has_tl { hist.add(mbinfo[mb_pos - mb_w - 1].mbtype); }
1211 mbtype = hist.get_mbtype();
1213 self.decode_mb_header_inter(bd, &mut br, hdr0.ftype, mbtype, &mut imode, q, sstate.has_top)?
1216 MBInfo { mbtype: MBType::MBSkip, skip_run: 0, dquant: false }
1219 if !mbh.mbtype.is_intra() {
1220 let mut mvs: [MV; 4] = [ZERO_MV; 4];
1221 for i in 0..mbh.mbtype.get_num_mvs() {
1222 mvs[i] = decode_mv(&mut br)?;
1225 self.mvi.set_mb(mb_x, mb_y, mbh.mbtype, &self.ref_mvi, &mvs, &sstate);
1227 let (mv_f, mv_b) = bd.predict_b_mv(&sstate, &self.mvi, mbh.mbtype, &mvs, mbinfo.as_slice());
1228 self.mvi.fill(mb_x, mb_y, true, mv_f);
1229 self.mvi.fill(mb_x, mb_y, false, mv_b);
1233 let is_16 = (mbh.mbtype == MBType::MBIntra16) || (mbh.mbtype == MBType::MBP16x16Mix);
1234 if mbh.mbtype == MBType::MBSkip {
1236 if mbh.skip_run > 0 {
1237 skip_run = mbh.skip_run;
1240 self.coderead.select_codes(mbh.mbtype.is_intra(), q, slice.set_idx, is_16);
1241 if mbh.mbtype == MBType::MBP16x16Mix {
1242 self.coderead.select_codes(true, q, slice.set_idx, true);
1244 cbp = self.coderead.decode_cbp(&mut br)?;
1247 if is_intra || mbh.mbtype.is_intra() {
1248 sstate.q_dc = bd.quant_dc(true, q);
1249 self.decode_mb_intra(&sstate, &imode, &mut buf, &mut br, is_16)?;
1251 sstate.q_dc = bd.quant_dc(false, q);
1252 imode.fill_block(0);
1253 self.decode_mb_inter(&sstate, &mbh, &mut buf, &mut br, is_16)?;
1256 let mi = RV34MBInfo { cbp, q, mbtype: mbh.mbtype, deblock: 0, cbp_c: 0 };
1259 mbinfo[mb_pos].deblock = 0xFFFF;
1260 mbinfo[mb_pos].cbp_c = 0xFF;
1262 self.fill_deblock_flags(&sstate, mb_pos, &mut mbinfo);
1264 sstate.has_left = true;
1267 if hdr0.deblock && (mb_y >= 1) {
1268 self.dsp.loop_filter(&mut buf, hdr0.ftype, &mbinfo, mb_w, mb_h, mb_y - 1);
1273 self.dsp.loop_filter(&mut buf, hdr0.ftype, &mbinfo, mb_w, mb_h, mb_h - 1);
1276 self.ipbs.add_frame(buf.clone());
1277 mem::swap(&mut self.mvi, &mut self.ref_mvi);
1278 mem::swap(&mut self.mbinfo, &mut mbinfo);
1281 Ok((NABufferType::Video(buf), hdr0.ftype, ts))
1283 pub fn flush(&mut self) {