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 |
97 MBType::MBForward => true,
101 pub fn is_bwd(self) -> bool {
103 MBType::MBBidir | MBType::MBBackward => true,
107 pub fn has_mv_dir(self, fwd: bool) -> bool {
109 MBType::MBBidir => true,
110 MBType::MBForward if fwd => true,
111 MBType::MBBackward if !fwd => true,
115 pub fn is_nomv(self) -> bool {
117 MBType::MBIntra | MBType::MBIntra16 | MBType::MBSkip | MBType::MBDirect => true,
121 /*pub fn is_16x16(self) -> bool {
123 MBType::MBP16x8 | MBType::MBP8x16 | MBType::MBP8x8 => false,
127 fn get_weight(self) -> usize {
129 MBType::MBIntra => 0,
130 MBType::MBIntra16 => 1,
131 MBType::MBSkip => unreachable!(),
132 MBType::MBP16x16 => 2,
133 MBType::MBP16x16Mix => 10,
134 MBType::MBP16x8 => 7,
135 MBType::MBP8x16 => 8,
137 MBType::MBDirect => 6,
138 MBType::MBBidir => 9,
139 MBType::MBForward => 4,
140 MBType::MBBackward => 5,
141 MBType::Invalid => unreachable!(),
146 const MBTYPE_FROM_WEIGHT: [MBType; 11] = [
147 MBType::MBIntra, MBType::MBIntra16, MBType::MBP16x16, MBType::MBP8x8,
148 MBType::MBForward, MBType::MBBackward, MBType::MBDirect, MBType::MBP16x8,
149 MBType::MBP8x16, MBType::MBBidir, MBType::MBP16x16Mix,
152 #[derive(Clone,Copy)]
159 #[derive(Clone,Copy)]
160 pub struct RV34MBInfo {
164 pub cbp_c: u8, // for deblocking purposes
168 struct IntraModeState {
169 cache: GenericCache<i8>,
172 const RV34_INTRA_PRED4: [PredType4x4; 9] = [
173 PredType4x4::DC, PredType4x4::Ver, PredType4x4::Hor,
174 PredType4x4::DiagDownRight, PredType4x4::DiagDownLeft,
175 PredType4x4::VerRight, PredType4x4::VerLeft,
176 PredType4x4::HorUp, PredType4x4::HorDown
179 const RV34_INTRA_PRED16: [PredType8x8; 4] = [
180 PredType8x8::DC, PredType8x8::Ver, PredType8x8::Hor, PredType8x8::Plane
183 impl IntraModeState {
184 fn new(mb_w: usize) -> Self {
185 let stride = 1 + mb_w * 4 + 1;
186 IntraModeState { cache: GenericCache::new(4, stride, -1) }
188 fn reset(&mut self) { self.cache.reset(); }
189 fn update(&mut self) { self.cache.update_row(); }
190 fn get_pos(&self, xpos: usize) -> usize {
191 self.cache.stride + 1 + xpos * 4
193 fn set_mb_x(&mut self, mb_x: usize) {
194 self.cache.xpos = self.get_pos(mb_x);
196 fn fill_block(&mut self, val: i8) {
197 let mut pos = self.cache.xpos;
200 self.cache.data[pos + j] = val;
202 pos += self.cache.stride;
205 fn get_pred16_type(&self, has_top: bool, has_left: bool) -> PredType8x8 {
206 if !has_top && !has_left { return PredType8x8::DC128; }
207 let mut im = RV34_INTRA_PRED16[self.cache.data[self.cache.xpos] as usize];
210 PredType8x8::Plane | PredType8x8::Ver => PredType8x8::Hor,
211 PredType8x8::DC => PredType8x8::LeftDC,
214 } else if !has_left {
216 PredType8x8::Plane | PredType8x8::Hor => PredType8x8::Ver,
217 PredType8x8::DC => PredType8x8::TopDC,
223 fn get_pred8_type(&self, has_top: bool, has_left: bool) -> PredType8x8 {
224 if !has_top && !has_left { return PredType8x8::DC128; }
225 let mut im = RV34_INTRA_PRED16[self.cache.data[self.cache.xpos] as usize];
226 im = match im { PredType8x8::Plane => PredType8x8::DC, _ => im };
229 PredType8x8::Plane | PredType8x8::Ver => PredType8x8::Hor,
230 PredType8x8::DC => PredType8x8::LeftDC,
233 } else if !has_left {
235 PredType8x8::Plane | PredType8x8::Hor => PredType8x8::Ver,
236 PredType8x8::DC => PredType8x8::TopDC,
242 fn get_pred4_type(&self, x: usize, y: usize, has_top: bool, has_left: bool) -> PredType4x4 {
243 let no_up = !has_top && (y == 0);
244 let no_left = !has_left && (x == 0);
245 if no_up && no_left { return PredType4x4::DC128; }
246 let no_down = !has_left || (x != 0) || (y == 3);
248 let mut im = RV34_INTRA_PRED4[self.cache.data[self.cache.xpos + x + y * self.cache.stride] as usize];
252 PredType4x4::Ver => PredType4x4::Hor,
253 PredType4x4::DC => PredType4x4::LeftDC,
258 PredType4x4::Hor => PredType4x4::Ver,
259 PredType4x4::DC => PredType4x4::TopDC,
260 PredType4x4::DiagDownLeft => PredType4x4::DiagDownLeftNoDown,
266 PredType4x4::DiagDownLeft => PredType4x4::DiagDownLeftNoDown,
267 PredType4x4::HorUp => PredType4x4::HorUpNoDown,
268 PredType4x4::VerLeft => PredType4x4::VerLeftNoDown,
275 fn get_pred4_type_chroma(&self, x: usize, y: usize, has_top: bool, has_left: bool) -> PredType4x4 {
276 let no_up = !has_top && (y == 0);
277 let no_left = !has_left && (x == 0);
278 if no_up && no_left { return PredType4x4::DC128; }
279 let no_down = !has_left || (x != 0) || (y == 1);
281 let mut im = RV34_INTRA_PRED4[self.cache.data[self.cache.xpos + x * 2 + y * 2 * self.cache.stride] as usize];
285 PredType4x4::Ver => PredType4x4::Hor,
286 PredType4x4::DC => PredType4x4::LeftDC,
291 PredType4x4::Hor => PredType4x4::Ver,
292 PredType4x4::DC => PredType4x4::TopDC,
293 PredType4x4::DiagDownLeft => PredType4x4::DiagDownLeftNoDown,
299 PredType4x4::DiagDownLeft => PredType4x4::DiagDownLeftNoDown,
300 PredType4x4::HorUp => PredType4x4::HorUpNoDown,
301 PredType4x4::VerLeft => PredType4x4::VerLeftNoDown,
314 pub has_b: Vec<bool>,
315 pub has_f: Vec<bool>,
320 Self { mv_b: Vec::new(), mv_f: Vec::new(), w: 0, h: 0, has_b: Vec::new(), has_f: Vec::new() }
322 fn resize(&mut self, mb_w: usize, mb_h: usize) {
327 fn reset(&mut self) {
328 let size = self.w * self.h;
329 self.mv_f.truncate(0);
330 self.mv_f.resize(size, ZERO_MV);
331 self.mv_b.truncate(0);
332 self.mv_b.resize(size, ZERO_MV);
333 self.has_f.truncate(0);
334 self.has_f.resize(size >> 2, false);
335 self.has_b.truncate(0);
336 self.has_b.resize(size >> 2, false);
338 fn fill(&mut self, mb_x: usize, mb_y: usize, fwd: bool, mv: MV) {
339 let idx = mb_x * 2 + mb_y * 2 * self.w;
341 self.mv_f[idx + 0] = mv;
342 self.mv_f[idx + 1] = mv;
343 self.mv_f[idx + self.w + 0] = mv;
344 self.mv_f[idx + self.w + 1] = mv;
346 self.mv_b[idx + 0] = mv;
347 self.mv_b[idx + 1] = mv;
348 self.mv_b[idx + self.w + 0] = mv;
349 self.mv_b[idx + self.w + 1] = mv;
352 fn get_mv_by_idx(&self, idx: usize, fwd: bool) -> MV {
353 if fwd { self.mv_f[idx] } else { self.mv_b[idx] }
355 fn pred_mv(&self, idx: usize, fwd: bool, has_top: bool, has_left: bool, has_tr: bool, has_tl: bool, is16: bool) -> MV {
356 if !has_top && !has_left { return ZERO_MV; }
357 let left_mv = if has_left { self.get_mv_by_idx(idx - 1, fwd) } else { ZERO_MV };
358 let top_mv = if has_top { self.get_mv_by_idx(idx - self.w, fwd) } else { left_mv };
359 let tr_add = if is16 { 2 } else { 1 };
362 tr_mv = self.get_mv_by_idx(idx - self.w + tr_add, fwd);
364 tr_mv = self.get_mv_by_idx(idx - self.w - 1, fwd);
368 MV::pred(left_mv, top_mv, tr_mv)
370 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 {
371 self.pred_mv(mb_x * 2 + mb_y * 2 * self.w, fwd, has_top, has_left, has_tr, has_tl, true)
373 fn set_mb(&mut self, mb_x: usize, mb_y: usize, mbtype: MBType, ref_mvi: &Self, mvs: &[MV], sstate: &SState) {
374 let mb_idx = mb_x + mb_y * (self.w >> 1);
375 self.has_f[mb_idx] = mbtype.is_fwd();
376 self.has_b[mb_idx] = mbtype.is_bwd();
377 if mbtype.is_nomv() {
378 self.fill(mb_x, mb_y, true, ZERO_MV);
379 self.fill(mb_x, mb_y, false, ZERO_MV);
383 self.fill(mb_x, mb_y, false, ZERO_MV);
384 } else if mbtype.is_bwd() {
385 self.fill(mb_x, mb_y, true, ZERO_MV);
387 let idx = mb_x * 2 + mb_y * 2 * self.w;
391 self.fill(mb_x, mb_y, true, ZERO_MV/*pred_mv*/);
394 MBType::MBP16x16Mix => {
395 let pred_mv = self.pred_mv(idx, mbtype.is_fwd(), sstate.has_top, sstate.has_left, sstate.has_tr, sstate.has_tl, true);
396 let new_mv = mvs[0] + pred_mv;
397 self.fill(mb_x, mb_y, true, new_mv);
400 let pred_mv = self.pred_mv(idx, mbtype.is_fwd(), sstate.has_top, sstate.has_left, sstate.has_tr, sstate.has_tl, true);
401 let new_mv = mvs[0] + pred_mv;
402 self.mv_f[idx + 0] = new_mv;
403 self.mv_f[idx + 1] = new_mv;
405 let idx2 = idx + self.w;
406 let pred_mv = self.pred_mv(idx2, true, true, sstate.has_left, false, sstate.has_left, true);
407 let new_mv = mvs[1] + pred_mv;
408 self.mv_f[idx2 + 0] = new_mv;
409 self.mv_f[idx2 + 1] = new_mv;
412 let pred_mv = self.pred_mv(idx, true, sstate.has_top, sstate.has_left, sstate.has_top, sstate.has_tl, false);
413 let new_mv = mvs[0] + pred_mv;
414 self.mv_f[idx] = new_mv;
415 self.mv_f[idx + self.w] = new_mv;
417 let pred_mv = self.pred_mv(idx + 1, true, sstate.has_top, true, sstate.has_tr, sstate.has_top, false);
418 let new_mv = mvs[1] + pred_mv;
419 self.mv_f[idx + 1] = new_mv;
420 self.mv_f[idx + self.w + 1] = new_mv;
424 let mut has_top = sstate.has_top;
427 let has_left = (x > 0) || sstate.has_left;
428 let has_tr = if y > 0 { x == 0 } else if x == 0 { sstate.has_top } else { sstate.has_tr };
431 has_tl = if x == 0 { sstate.has_tl } else { sstate.has_top };
433 has_tl = if x == 0 { sstate.has_left } else { true };
435 let pred_mv = self.pred_mv(idx8 + x, true, has_top, has_left, has_tr, has_tl, false);
436 let new_mv = mvs[x + y * 2] + pred_mv;
437 self.mv_f[idx8 + x] = new_mv;
443 MBType::MBDirect => {
444 let mut cum_mv_f = ZERO_MV;
445 let mut cum_mv_b = ZERO_MV;
449 let (mv_f, mv_b) = ref_mvi.mv_f[idx8 + x].scale(sstate.trd, sstate.trb);
459 self.fill(mb_x, mb_y, true, cum_mv_f);
460 self.fill(mb_x, mb_y, false, cum_mv_b);
463 let pred_mv_f = ZERO_MV;
464 let new_mv = pred_mv_f + mvs[0];
465 self.fill(mb_x, mb_y, true, new_mv);
466 let pred_mv_b = ZERO_MV;
467 let new_mv = pred_mv_b + mvs[1];
468 self.fill(mb_x, mb_y, false, new_mv);
470 MBType::MBForward => {
471 let pred_mv = self.pred_mv(idx, mbtype.is_fwd(), sstate.has_top, sstate.has_left, sstate.has_tr, sstate.has_tl, true);
472 let new_mv = mvs[0] + pred_mv;
473 self.fill(mb_x, mb_y, true, new_mv);
475 MBType::MBBackward => {
476 let pred_mv = self.pred_mv(idx, mbtype.is_fwd(), sstate.has_top, sstate.has_left, sstate.has_tr, sstate.has_tl, true);
477 let new_mv = mvs[0] + pred_mv;
478 self.fill(mb_x, mb_y, false, new_mv);
483 pub fn get_mv(&self, mb_x: usize, mb_y: usize, x: usize, y: usize, fwd: bool) -> MV {
484 let idx = mb_x * 2 + x + (mb_y * 2 + y) * self.w;
485 if fwd { self.mv_f[idx] }
486 else { self.mv_b[idx] }
488 fn mv_gt_3(&self, mb_x: usize, mb_y: usize, x: usize, y: usize, vert: bool) -> bool {
489 let idx = mb_x * 2 + x + (mb_y * 2 + y) * self.w;
490 let off = if vert { self.w } else { 1 };
491 let diffx = self.mv_f[idx].x - self.mv_f[idx - off].x;
492 let diffy = self.mv_f[idx].y - self.mv_f[idx - off].y;
493 (diffx < -3) || (diffx > 3) || (diffy < -3) || (diffy > 3)
497 pub trait RV34BitstreamDecoder {
498 fn decode_slice_header(&mut self, br: &mut BitReader, old_w: usize, old_h: usize) -> DecoderResult<RV34SliceHeader>;
499 fn decode_intra_pred(&mut self, br: &mut BitReader, types: &mut [i8], pos: usize, tstride: usize, has_top: bool) -> DecoderResult<()>;
500 fn quant_dc(&self, is_intra: bool, q: u8) -> u8;
501 fn decode_inter_mb_hdr(&mut self, br: &mut BitReader, ftype: FrameType, mbtype: MBType) -> DecoderResult<MBInfo>;
502 fn predict_b_mv(&self, sstate: &SState, mvi: &MVInfo, mbtype: MBType, mvs: &[MV], mbinfo: &[RV34MBInfo]) -> (MV, MV);
506 fn loop_filter(&self, frame: &mut NAVideoBuffer<u8>, ftype: FrameType, mbinfo: &[RV34MBInfo], mb_w: usize, mb_h: usize, row: usize);
507 fn do_luma_mc(&self, frame: &mut NAVideoBuffer<u8>, prev_frame: &NAVideoBuffer<u8>, x: usize, y: usize, mv: MV, use16: bool, avg: bool);
508 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);
511 fn parse_slice_offsets(src: &[u8], offsets: &mut Vec<usize>) -> DecoderResult<()> {
512 let num_slices = (src[0] as usize) + 1;
513 let ini_off = num_slices * 8 + 1;
516 if ini_off >= src.len() { return Err(DecoderError::ShortData); }
518 let mut br = BitReader::new(&src[1..ini_off], BitReaderMode::BE);
520 for i in 0..num_slices {
522 let off = br.read(32)? as usize;
523 if (i == 0) && (off != 0) {
524 return Err(DecoderError::InvalidData);
526 if (i > 0) && (off <= offsets[i - 1]) {
527 return Err(DecoderError::InvalidData);
535 fn decode_slice_header(br: &mut BitReader, bd: &mut RV34BitstreamDecoder, slice_no: usize, slice_offs: &[usize], old_width: usize, old_height: usize) -> DecoderResult<RV34SliceHeader> {
536 validate!(slice_no < slice_offs.len());
537 br.seek((slice_offs[slice_no] * 8) as u32)?;
538 let mut shdr = bd.decode_slice_header(br, old_width, old_height)?;
539 if ((shdr.width == 0) || (shdr.height == 0)) && (shdr.ftype != FrameType::I) {
540 return Err(DecoderError::MissingReference);
542 if slice_no < slice_offs.len() - 1 {
543 let cur_pos = br.tell() as u32;
544 br.seek((slice_offs[slice_no + 1] * 8) as u32)?;
545 if let Ok(nhdr) = bd.decode_slice_header(br, shdr.width, shdr.height) {
546 validate!(nhdr.start > shdr.start);
547 shdr.end = nhdr.start;
549 if slice_no + 2 < slice_offs.len() {
550 br.seek((slice_offs[slice_no + 2] * 8) as u32)?;
551 if let Ok(nhdr) = bd.decode_slice_header(br, shdr.width, shdr.height) {
552 validate!(nhdr.start > shdr.start);
553 shdr.end = nhdr.start;
555 shdr.end = ((shdr.width + 15) >> 4) * ((shdr.height + 15) >> 4);
558 shdr.end = ((shdr.width + 15) >> 4) * ((shdr.height + 15) >> 4);
563 shdr.end = ((shdr.width + 15) >> 4) * ((shdr.height + 15) >> 4);
568 const RV34_MB_MAX_SIZES: [usize; 6] = [ 0x2F, 0x62, 0x18B, 0x62F, 0x18BF, 0x23FF ];
569 const RV34_SLICE_START_BITS: [u8; 6] = [ 6, 7, 9, 11, 13, 14 ];
571 pub fn get_slice_start_offset_bits(w: usize, h: usize) -> u8 {
572 if (w == 0) || (h == 0) {
575 let mb_size = ((w + 15) >> 4) * ((h + 15) >> 4) - 1;
576 let mut idx: usize = 0;
577 while (idx < 5) && (RV34_MB_MAX_SIZES[idx] < mb_size) { idx += 1; }
578 RV34_SLICE_START_BITS[idx]
581 const RV34_DQUANT_TAB: [[i8; 2]; 32] = [
582 [ 0, 0 ], [ 2, 1 ], [ -1, 1 ], [ -1, 1 ], [ -1, 1 ], [ -1, 1 ], [ -1, 1 ], [ -1, 1 ],
583 [ -1, 1 ], [ -1, 1 ], [ -1, 1 ], [ -2, 2 ], [ -2, 2 ], [ -2, 2 ], [ -2, 2 ], [ -2, 2 ],
584 [ -2, 2 ], [ -2, 2 ], [ -2, 2 ], [ -2, 2 ], [ -2, 2 ], [ -3, 3 ], [ -3, 3 ], [ -3, 3 ],
585 [ -3, 3 ], [ -3, 3 ], [ -3, 3 ], [ -3, 3 ], [ -3, 3 ], [ -3, 2 ], [ -3, 1 ], [ -3,-5 ]
588 const RV34_QUANT_TAB: [u16; 32] = [
589 60, 67, 76, 85, 96, 108, 121, 136,
590 152, 171, 192, 216, 242, 272, 305, 341,
591 383, 432, 481, 544, 606, 683, 767, 854,
592 963, 1074, 1212, 1392, 1566, 1708, 1978, 2211
595 const RV34_CHROMA_QUANT_DC: [u8; 32] = [
596 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13,
597 14, 15, 15, 16, 17, 18, 18, 19, 20, 20, 21, 21, 22, 22, 23, 23
599 const RV34_CHROMA_QUANT_AC: [u8; 32] = [
600 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
601 16, 17, 17, 18, 19, 20, 20, 21, 22, 22, 23, 23, 24, 24, 25, 25
604 fn decode_dquant(br: &mut BitReader, q: u8) -> DecoderResult<u8> {
606 let diff = RV34_DQUANT_TAB[q as usize][br.read(1)? as usize];
607 let qp = (q as i8) + diff;
608 validate!((qp > 0) && (qp < 32));
611 let qp = br.read(5)? as u8;
661 fn new(ftype: FrameType) -> Self { Self { is_p: ftype == FrameType::P, hist: [MBType::Invalid; 4], count: 0 } }
662 fn add(&mut self, mbt: MBType) {
663 let mbt2 = match mbt {
664 MBType::MBSkip if self.is_p => MBType::MBP16x16,
665 MBType::MBSkip if !self.is_p => MBType::MBDirect,
668 self.hist[self.count] = mbt2;
671 fn get_mbtype(&self) -> MBType {
674 } else if self.count == 1 {
676 } else if self.count == 2 {
677 if self.hist[0].get_weight() <= self.hist[1].get_weight() {
683 let mut w: [usize; 12] = [0; 12];
684 for i in 0..self.count { w[self.hist[i].get_weight()] += 1; }
687 if w[i] == self.count { return MBTYPE_FROM_WEIGHT[i]; }
688 if (w[i] > w[nz_idx]) || (w[nz_idx] == 0) { nz_idx = i; }
691 MBTYPE_FROM_WEIGHT[nz_idx]
696 fn decode_mv(br: &mut BitReader) -> DecoderResult<MV> {
697 let x = br.read_code_signed(IntCodeType::Gamma)? as i16;
698 let y = br.read_code_signed(IntCodeType::Gamma)? as i16;
702 fn do_mc_16x16(dsp: &Box<dyn RV34DSP + Send>, buf: &mut NAVideoBuffer<u8>, prevbuf: &NAVideoBuffer<u8>, mb_x: usize, mb_y: usize, mv: MV, avg: bool) {
703 dsp.do_luma_mc (buf, prevbuf, mb_x * 16, mb_y * 16, mv, true, avg);
704 dsp.do_chroma_mc(buf, prevbuf, mb_x * 8, mb_y * 8, 1, mv, true, avg);
705 dsp.do_chroma_mc(buf, prevbuf, mb_x * 8, mb_y * 8, 2, mv, true, avg);
708 fn do_mc_8x8(dsp: &Box<dyn RV34DSP + Send>, buf: &mut NAVideoBuffer<u8>, prevbuf: &NAVideoBuffer<u8>, mb_x: usize, xoff: usize, mb_y: usize, yoff: usize, mv: MV, avg: bool) {
709 dsp.do_luma_mc (buf, prevbuf, mb_x * 16 + xoff * 8, mb_y * 16 + yoff * 8, mv, false, avg);
710 dsp.do_chroma_mc(buf, prevbuf, mb_x * 8 + xoff * 4, mb_y * 8 + yoff * 4, 1, mv, false, avg);
711 dsp.do_chroma_mc(buf, prevbuf, mb_x * 8 + xoff * 4, mb_y * 8 + yoff * 4, 2, mv, false, avg);
714 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) {
716 let xoff = if comp == 0 { mb_x * 16 + xb * 8 } else { mb_x * 8 + xb * 4 };
717 let yoff = if comp == 0 { mb_y * 16 + yb * 8 } else { mb_y * 8 + yb * 4 };
718 let csize = if comp == 0 { size } else { size >> 1 };
719 let dstride = buf.get_stride(comp);
720 let doffset = buf.get_offset(comp) + xoff + yoff * dstride;
721 let data = buf.get_data_mut().unwrap();
722 let dst: &mut [u8] = data.as_mut_slice();
724 let sstride = avg_buf.get_stride(comp);
725 let soffset = avg_buf.get_offset(comp);
726 let data = avg_buf.get_data();
727 let src: &[u8] = data.as_slice();
729 if ratio1 == ratio2 {
730 cdsp.avg(dst, doffset, dstride, src, soffset, sstride, csize);
732 cdsp.weight(dst, doffset, dstride, src, soffset, sstride, ratio2, ratio1, csize);
737 pub struct RV34Decoder {
740 dsp: Box<dyn RV34DSP + Send>,
752 mbinfo: Vec<RV34MBInfo>,
753 avg_buf: NAVideoBufferRef<u8>,
758 pub fn new(is_rv30: bool, dsp: Box<dyn RV34DSP + Send>) -> Self {
759 let tmp_vinfo = NAVideoInfo::new(16, 16, false, YUV420_FORMAT);
760 let vt = alloc_video_buffer(tmp_vinfo, 4).unwrap();
761 let vb = vt.get_vbuf();
762 let avg_buf = vb.unwrap();
765 coderead: RV34Codes::new(),
767 cdsp: RV34CommonDSP::new(),
768 ipbs: IPBShuffler::new(),
770 ref_mvi: MVInfo::new(),
773 last_ts: 0, next_ts: 0,
774 ratio1: 0, ratio2: 0,
780 fn decode_mb_header_intra(&mut self, bd: &mut RV34BitstreamDecoder, br: &mut BitReader, is_i16: bool, im: &mut IntraModeState, q: u8, has_top: bool, has_dq: bool) -> DecoderResult<MBInfo> {
782 let imode = br.read(2)? as i8;
783 im.fill_block(imode);
784 Ok(MBInfo { mbtype: MBType::MBIntra16, skip_run: 0, dquant: false })
786 let dq = if !has_dq {
787 if !self.is_rv30 { !br.read_bool()? } else { false }
790 decode_dquant(br, q)?;
792 bd.decode_intra_pred(br, im.cache.data.as_mut_slice(), im.cache.xpos, im.cache.stride, has_top)?;
793 Ok(MBInfo { mbtype: MBType::MBIntra, skip_run: 0, dquant: dq })
796 fn decode_mb_header_inter(&mut self, bd: &mut RV34BitstreamDecoder, br: &mut BitReader, ftype: FrameType, mbtype: MBType, im: &mut IntraModeState, q: u8, has_top: bool) -> DecoderResult<MBInfo> {
797 let hdr = bd.decode_inter_mb_hdr(br, ftype, mbtype)?;
798 validate!(hdr.mbtype != MBType::Invalid);
800 decode_dquant(br, q)?;
802 if hdr.mbtype.is_intra() {
803 return self.decode_mb_header_intra(bd, br, hdr.mbtype.is_16(), im, q, has_top, true);
808 fn decode_mb_intra(&mut self, sstate: &SState, imode: &IntraModeState, buf: &mut NAVideoBuffer<u8>, br: &mut BitReader, is_16: bool) -> DecoderResult<()> {
809 let mut cur_cbp = sstate.cbp;
811 let q_dc = RV34_QUANT_TAB[sstate.q_dc as usize];
812 let q_ac = RV34_QUANT_TAB[sstate.q as usize];
813 let luma_set = if is_16 { 2 } else { 1 };
814 let mut coeffs16: [i16; 16] = [0; 16];
816 let has_ac = self.coderead.decode_block(br, &mut coeffs16, 3, 0, q_dc, q_dc, q_ac)?;
818 self.cdsp.transform16(&mut coeffs16);
820 self.cdsp.transform16_dc(&mut coeffs16);
823 let stride = buf.get_stride(0);
824 let mut offset = buf.get_offset(0) + sstate.mb_x * 16 + sstate.mb_y * 16 * stride;
825 let data = buf.get_data_mut().unwrap();
826 let framebuf: &mut [u8] = data.as_mut_slice();
829 let im16 = imode.get_pred16_type(sstate.has_top, sstate.has_left);
830 self.cdsp.ipred16x16[im16 as usize](framebuf, offset, stride);
835 let mut coeffs: [i16; 16] = [0; 16];
837 if (cur_cbp & 1) != 0 {
838 has_ac = self.coderead.decode_block(br, &mut coeffs, luma_set, 0, q_ac, q_ac, q_ac)?;
843 coeffs[0] = coeffs16[x + y * 4];
845 let noright = (sstate.mb_x == sstate.mb_w - 1) && (x == 3);
846 let has_top = sstate.has_top || (y > 0);
847 let im = imode.get_pred4_type(x, y, sstate.has_top, sstate.has_left);
848 let topright: [u8; 4] = if (noright && sstate.has_top && y == 0) || (x == 3 && y > 0) {
849 let i = offset + x * 4 - stride;
850 [framebuf[i + 3], framebuf[i + 3], framebuf[i + 3], framebuf[i + 3]]
852 let i = offset + x * 4 - stride;
853 [framebuf[i + 4], framebuf[i + 5], framebuf[i + 6], framebuf[i + 7]]
857 self.cdsp.ipred4x4[im as usize](framebuf, offset + x*4, stride, &topright);
860 self.cdsp.transform(&mut coeffs);
862 self.cdsp.transform_dc(&mut coeffs);
864 self.cdsp.add_coeffs(framebuf, offset + x * 4, stride, &coeffs);
867 offset += stride * 4;
870 let q_dc = RV34_QUANT_TAB[RV34_CHROMA_QUANT_DC[sstate.q as usize] as usize];
871 let q_ac = RV34_QUANT_TAB[RV34_CHROMA_QUANT_AC[sstate.q as usize] as usize];
874 let stride = buf.get_stride(comp);
875 let mut offset = buf.get_offset(comp) + sstate.mb_x * 8 + sstate.mb_y * 8 * stride;
876 let data = buf.get_data_mut().unwrap();
877 let framebuf: &mut [u8] = data.as_mut_slice();
879 let im8 = imode.get_pred8_type(sstate.has_top, sstate.has_left);
880 self.cdsp.ipred8x8[im8 as usize](framebuf, offset, stride);
884 let mut coeffs: [i16; 16] = [0; 16];
886 if (cur_cbp & 1) != 0 {
887 has_ac = self.coderead.decode_block(br, &mut coeffs, chroma_set, 1, q_dc, q_ac, q_ac)?;
892 let noright = (sstate.mb_x == sstate.mb_w - 1) && (x == 1);
893 let has_top = sstate.has_top || (y > 0);
894 let im = imode.get_pred4_type_chroma(x, y, sstate.has_top, sstate.has_left);
895 let topright: [u8; 4] = if (noright && sstate.has_top && y == 0) || (x == 1 && y > 0) {
896 let i = offset + x * 4 - stride;
897 [framebuf[i + 3], framebuf[i + 3], framebuf[i + 3], framebuf[i + 3]]
899 let i = offset + x * 4 - stride;
900 [framebuf[i + 4], framebuf[i + 5], framebuf[i + 6], framebuf[i + 7]]
904 self.cdsp.ipred4x4[im as usize](framebuf, offset + x*4, stride, &topright);
907 self.cdsp.transform(&mut coeffs);
909 self.cdsp.transform_dc(&mut coeffs);
911 self.cdsp.add_coeffs(framebuf, offset + x * 4, stride, &coeffs);
914 offset += stride * 4;
920 fn do_mc(&mut self, buf: &mut NAVideoBuffer<u8>, mbh: &MBInfo, sstate: &SState) {
921 let mb_x = sstate.mb_x;
922 let mb_y = sstate.mb_y;
924 MBType::MBP16x16 | MBType::MBP16x16Mix => {
925 if let Some(ref prevbuf) = self.ipbs.get_lastref() {
926 let mv = self.mvi.get_mv(mb_x, mb_y, 0, 0, true);
927 do_mc_16x16(&self.dsp, buf, prevbuf, mb_x, mb_y, mv, false);
930 MBType::MBForward => {
931 if let Some(ref fwdbuf) = self.ipbs.get_b_fwdref() {
932 let mv = self.mvi.get_mv(mb_x, mb_y, 0, 0, true);
933 do_mc_16x16(&self.dsp, buf, fwdbuf, mb_x, mb_y, mv, false);
936 MBType::MBBackward => {
937 if let Some(ref bwdbuf) = self.ipbs.get_b_bwdref() {
938 let mv = self.mvi.get_mv(mb_x, mb_y, 0, 0, false);
939 do_mc_16x16(&self.dsp, buf, bwdbuf, mb_x, mb_y, mv, false);
942 MBType::MBP8x8 | MBType::MBP8x16 | MBType::MBP16x8 => {
943 if let Some(ref prevbuf) = self.ipbs.get_lastref() {
946 let mv = self.mvi.get_mv(mb_x, mb_y, x, y, true);
947 do_mc_8x8(&self.dsp, buf, prevbuf, mb_x, x, mb_y, y, mv, false);
952 MBType::MBSkip if !self.is_b => {
953 if let Some(ref prevbuf) = self.ipbs.get_lastref() {
954 do_mc_16x16(&self.dsp, buf, prevbuf, mb_x, mb_y, ZERO_MV, false);
957 MBType::MBSkip | MBType::MBDirect => {
958 if let (Some(ref fwdbuf), Some(ref bwdbuf)) = (self.ipbs.get_b_fwdref(), self.ipbs.get_b_bwdref()) {
961 let (mv_f, mv_b) = self.ref_mvi.get_mv(mb_x, mb_y, x, y, true).scale(sstate.trd, sstate.trb);
962 do_mc_8x8(&self.dsp, buf, fwdbuf, mb_x, x, mb_y, y, mv_f, false);
963 do_mc_8x8(&self.dsp, &mut self.avg_buf, bwdbuf, mb_x, x, mb_y, y, mv_b, true);
964 do_avg(&self.cdsp, buf, &self.avg_buf, mb_x, x, mb_y, y, 8, self.ratio1, self.ratio2);
970 if let (Some(ref fwdbuf), Some(ref bwdbuf)) = (self.ipbs.get_b_fwdref(), self.ipbs.get_b_bwdref()) {
971 let mv_f = self.mvi.get_mv(mb_x, mb_y, 0, 0, true);
972 let mv_b = self.mvi.get_mv(mb_x, mb_y, 0, 0, false);
973 do_mc_16x16(&self.dsp, buf, fwdbuf, mb_x, mb_y, mv_f, false);
974 do_mc_16x16(&self.dsp, &mut self.avg_buf, bwdbuf, mb_x, mb_y, mv_b, true);
975 do_avg(&self.cdsp, buf, &self.avg_buf, mb_x, 0, mb_y, 0, 16, self.ratio1, self.ratio2);
981 fn decode_mb_inter(&mut self, sstate: &SState, mbh: &MBInfo, buf: &mut NAVideoBuffer<u8>, br: &mut BitReader, is_16: bool) -> DecoderResult<()> {
982 self.do_mc(buf, mbh, sstate);
984 let mut cur_cbp = sstate.cbp;
987 let q_dc = RV34_QUANT_TAB[sstate.q_dc as usize];
988 let q_ac = RV34_QUANT_TAB[sstate.q as usize];
989 let luma_set = if is_16 { 2 } else { 0 };
990 let mut coeffs16: [i16; 16] = [0; 16];
992 let has_ac = self.coderead.decode_block(br, &mut coeffs16, 3, 0, q_dc, q_dc, q_ac)?;
994 self.cdsp.transform16(&mut coeffs16);
996 self.cdsp.transform16_dc(&mut coeffs16);
999 let stride = buf.get_stride(0);
1000 let mut offset = buf.get_offset(0) + sstate.mb_x * 16 + sstate.mb_y * 16 * stride;
1001 let data = buf.get_data_mut().unwrap();
1002 let framebuf: &mut [u8] = data.as_mut_slice();
1006 let mut coeffs: [i16; 16] = [0; 16];
1008 if (cur_cbp & 1) != 0 {
1009 has_ac = self.coderead.decode_block(br, &mut coeffs, luma_set, 0, q_ac, q_ac, q_ac)?;
1014 coeffs[0] = coeffs16[x + y * 4];
1017 self.cdsp.transform(&mut coeffs);
1019 self.cdsp.transform_dc(&mut coeffs);
1021 self.cdsp.add_coeffs(framebuf, offset + x * 4, stride, &coeffs);
1024 offset += stride * 4;
1028 self.coderead.select_codes(false, sstate.q, sstate.set_idx, false);
1030 let q_dc = RV34_QUANT_TAB[RV34_CHROMA_QUANT_DC[sstate.q as usize] as usize];
1031 let q_ac = RV34_QUANT_TAB[RV34_CHROMA_QUANT_AC[sstate.q as usize] as usize];
1034 let stride = buf.get_stride(comp);
1035 let mut offset = buf.get_offset(comp) + sstate.mb_x * 8 + sstate.mb_y * 8 * stride;
1036 let data = buf.get_data_mut().unwrap();
1037 let framebuf: &mut [u8] = data.as_mut_slice();
1040 let mut coeffs: [i16; 16] = [0; 16];
1042 if (cur_cbp & 1) != 0 {
1043 has_ac = self.coderead.decode_block(br, &mut coeffs, chroma_set, 1, q_dc, q_ac, q_ac)?;
1048 self.cdsp.transform(&mut coeffs);
1050 self.cdsp.transform_dc(&mut coeffs);
1052 self.cdsp.add_coeffs(framebuf, offset + x * 4, stride, &coeffs);
1055 offset += stride * 4;
1060 fn fill_deblock_flags(&self, sstate: &SState, mb_pos: usize, mbinfo: &mut Vec<RV34MBInfo>) {
1061 let mbt = mbinfo[mb_pos].mbtype;
1062 let mut hmvmask = 0;
1063 let mut vmvmask = 0;
1067 let shift = x * 2 + y * 8;
1068 if ((x > 0) || (sstate.mb_x > 0)) && self.mvi.mv_gt_3(sstate.mb_x, sstate.mb_y, x, y, false) {
1069 vmvmask |= 0x11 << shift;
1071 if ((y > 0) || sstate.has_top) && self.mvi.mv_gt_3(sstate.mb_x, sstate.mb_y, x, y, true) {
1072 hmvmask |= 0x03 << shift;
1076 if !sstate.has_top { hmvmask &= !0x000F; }
1077 if sstate.mb_x == 0 { vmvmask &= !0x1111; }
1079 vmvmask |= (vmvmask & 0x4444) >> 1;
1080 hmvmask |= (hmvmask & 0x0F00) >> 4;
1081 if sstate.mb_x > 0 {
1082 mbinfo[mb_pos - 1].deblock |= (vmvmask & 0x1111) << 3;
1086 mbinfo[mb_pos - sstate.mb_w].deblock |= (hmvmask & 0xF) << 12;
1089 if mbt.is_intra_or_16() {
1090 mbinfo[mb_pos].deblock = 0xFFFF;
1091 mbinfo[mb_pos].cbp_c = 0xFF;
1093 mbinfo[mb_pos].deblock = (mbinfo[mb_pos].cbp as u16) | hmvmask | vmvmask;
1094 mbinfo[mb_pos].cbp_c = (mbinfo[mb_pos].cbp >> 16) as u8;
1098 pub fn parse_frame(&mut self, supp: &mut NADecoderSupport, src: &[u8], bd: &mut RV34BitstreamDecoder) -> DecoderResult<(NABufferType, FrameType, u64)> {
1099 let mut slice_offs: Vec<usize> = Vec::new();
1100 parse_slice_offsets(src, &mut slice_offs)?;
1101 let ini_off = slice_offs.len() * 8 + 1;
1103 let mut br = BitReader::new(&src[ini_off..], BitReaderMode::BE);
1104 let hdr0 = decode_slice_header(&mut br, bd, 0, slice_offs.as_slice(), self.width, self.height)?;
1105 validate!((hdr0.width != 0) && (hdr0.height != 0));
1106 self.width = hdr0.width;
1107 self.height = hdr0.height;
1108 let mb_w = (hdr0.width + 15) >> 4;
1109 let mb_h = (hdr0.height + 15) >> 4;
1110 let mut mb_pos: usize = 0;
1111 let mut slice = hdr0;
1112 let mut slice_no: usize = 1;
1113 let is_intra = hdr0.ftype == FrameType::I;
1114 let mut skip_run: usize = 0;
1115 let mut imode = IntraModeState::new(mb_w);
1116 let mut q = hdr0.quant;
1118 let mut sstate = SState::new();
1119 let mut mbinfo: Vec<RV34MBInfo> = Vec::with_capacity(mb_w * mb_h);
1121 self.is_b = hdr0.ftype == FrameType::B;
1122 if hdr0.ftype != FrameType::B {
1123 self.last_ts = self.next_ts;
1124 self.next_ts = hdr0.pts;
1125 if self.last_ts > self.next_ts {
1126 self.base_ts += 1 << 13;
1131 if self.ipbs.get_lastref().is_none() {
1132 return Err(DecoderError::MissingReference);
1136 if self.ipbs.get_lastref().is_none() {
1137 return Err(DecoderError::MissingReference);
1139 if self.ipbs.get_nextref().is_none() {
1140 return Err(DecoderError::MissingReference);
1145 let ts_diff = (self.next_ts << 3).wrapping_sub(hdr0.pts << 3) >> 3;
1146 let ts = self.base_ts + (self.next_ts as u64) - (ts_diff as u64);
1147 sstate.trd = (self.next_ts << 3).wrapping_sub(self.last_ts << 3) >> 3;
1148 sstate.trb = (hdr0.pts << 3).wrapping_sub(self.last_ts << 3) >> 3;
1149 if sstate.trb != 0 {
1150 self.ratio1 = ((sstate.trb as u32) << 14) / (sstate.trd as u32);
1151 self.ratio2 = (((sstate.trd as u32) - (sstate.trb as u32)) << 14) / (sstate.trd as u32);
1153 self.ratio1 = 1 << 14 >> 1;
1154 self.ratio2 = 1 << 14 >> 1;
1156 //todo validate against ref frame
1158 let vinfo = NAVideoInfo::new(hdr0.width, hdr0.height, false, YUV420_FORMAT);
1159 let ret = supp.pool_u8.get_free();
1161 return Err(DecoderError::AllocError);
1163 let mut buf = ret.unwrap();
1164 if buf.get_info() != vinfo {
1166 supp.pool_u8.reset();
1167 supp.pool_u8.prealloc_video(vinfo, 4)?;
1168 let ret = supp.pool_u8.get_free();
1170 return Err(DecoderError::AllocError);
1176 sstate.has_top = false;
1179 sstate.set_idx = hdr0.set_idx;
1181 self.mvi.resize(mb_w, mb_h);
1182 for mb_y in 0..mb_h {
1184 sstate.has_left = false;
1185 for mb_x in 0..mb_w {
1187 if mb_pos == slice.end {
1188 slice = decode_slice_header(&mut br, bd, slice_no, &slice_offs, self.width, self.height)?;
1189 validate!(slice.fits(&hdr0));
1194 sstate.has_top = false;
1195 sstate.has_left = false;
1196 sstate.set_idx = slice.set_idx;
1198 sstate.has_top = (mb_pos - slice.start) >= mb_w;
1199 sstate.has_tl = sstate.has_top && (mb_x > 0) && (mb_pos > slice.start + mb_w);
1200 sstate.has_tr = (mb_x < mb_w - 1) && (mb_pos - slice.start >= mb_w - 1);
1201 imode.set_mb_x(mb_x);
1202 let mbh = if is_intra {
1203 let is_i16 = br.read_bool()?;
1204 self.decode_mb_header_intra(bd, &mut br, is_i16, &mut imode, q, sstate.has_top, false)?
1209 mbtype = MBType::Invalid;
1211 let mut hist = MBHist::new(hdr0.ftype);
1213 hist.add(mbinfo[mb_pos - mb_w].mbtype);
1214 if sstate.has_tr { hist.add(mbinfo[mb_pos - mb_w + 1].mbtype); }
1216 if sstate.has_left { hist.add(mbinfo[mb_pos - 1].mbtype); }
1217 if sstate.has_tl { hist.add(mbinfo[mb_pos - mb_w - 1].mbtype); }
1218 mbtype = hist.get_mbtype();
1220 self.decode_mb_header_inter(bd, &mut br, hdr0.ftype, mbtype, &mut imode, q, sstate.has_top)?
1223 MBInfo { mbtype: MBType::MBSkip, skip_run: 0, dquant: false }
1226 if !mbh.mbtype.is_intra() {
1227 let mut mvs: [MV; 4] = [ZERO_MV; 4];
1228 for i in 0..mbh.mbtype.get_num_mvs() {
1229 mvs[i] = decode_mv(&mut br)?;
1232 self.mvi.set_mb(mb_x, mb_y, mbh.mbtype, &self.ref_mvi, &mvs, &sstate);
1234 let (mv_f, mv_b) = bd.predict_b_mv(&sstate, &self.mvi, mbh.mbtype, &mvs, mbinfo.as_slice());
1235 self.mvi.fill(mb_x, mb_y, true, mv_f);
1236 self.mvi.fill(mb_x, mb_y, false, mv_b);
1240 let is_16 = (mbh.mbtype == MBType::MBIntra16) || (mbh.mbtype == MBType::MBP16x16Mix);
1241 if mbh.mbtype == MBType::MBSkip {
1243 if mbh.skip_run > 0 {
1244 skip_run = mbh.skip_run;
1247 self.coderead.select_codes(mbh.mbtype.is_intra(), q, slice.set_idx, is_16);
1248 if mbh.mbtype == MBType::MBP16x16Mix {
1249 self.coderead.select_codes(true, q, slice.set_idx, true);
1251 cbp = self.coderead.decode_cbp(&mut br)?;
1254 if is_intra || mbh.mbtype.is_intra() {
1255 sstate.q_dc = bd.quant_dc(true, q);
1256 self.decode_mb_intra(&sstate, &imode, &mut buf, &mut br, is_16)?;
1258 sstate.q_dc = bd.quant_dc(false, q);
1259 imode.fill_block(0);
1260 self.decode_mb_inter(&sstate, &mbh, &mut buf, &mut br, is_16)?;
1263 let mi = RV34MBInfo { cbp, q, mbtype: mbh.mbtype, deblock: 0, cbp_c: 0 };
1266 mbinfo[mb_pos].deblock = 0xFFFF;
1267 mbinfo[mb_pos].cbp_c = 0xFF;
1269 self.fill_deblock_flags(&sstate, mb_pos, &mut mbinfo);
1271 sstate.has_left = true;
1274 if hdr0.deblock && (mb_y >= 1) {
1275 self.dsp.loop_filter(&mut buf, hdr0.ftype, &mbinfo, mb_w, mb_h, mb_y - 1);
1280 self.dsp.loop_filter(&mut buf, hdr0.ftype, &mbinfo, mb_w, mb_h, mb_h - 1);
1283 self.ipbs.add_frame(buf.clone());
1284 mem::swap(&mut self.mvi, &mut self.ref_mvi);
1285 mem::swap(&mut self.mbinfo, &mut mbinfo);
1288 Ok((NABufferType::Video(buf), hdr0.ftype, ts))
1290 pub fn flush(&mut self) {