]> git.nihav.org Git - nihav.git/blob - nihav-realmedia/src/codecs/rv3040.rs
msvideo1enc: switch to faster 2-colour quantiser
[nihav.git] / nihav-realmedia / src / codecs / rv3040.rs
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;
8 use std::mem;
9
10 use super::rv34codes::*;
11 use super::rv34dsp::*;
12
13 trait RV34MVScale {
14 fn scale(&self, trd: u16, trb: u16) -> (MV, MV);
15 }
16
17 const TR_SHIFT: u8 = 14;
18 const TR_BIAS: i32 = 1 << (TR_SHIFT - 1);
19
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);
23 let mv_f = MV {
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
26 };
27 let mv_b = mv_f - *self;
28 (mv_f, mv_b)
29 }
30 }
31
32 #[derive(Clone,Copy)]
33 pub struct RV34SliceHeader {
34 pub ftype: FrameType,
35 pub quant: u8,
36 pub pts: u16,
37 pub width: usize,
38 pub height: usize,
39 pub start: usize,
40 pub end: usize,
41 pub set_idx: usize,
42 pub deblock: bool,
43 }
44
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)
51 }
52 }
53
54 #[allow(dead_code)]
55 #[derive(Debug,Clone,Copy,PartialEq)]
56 pub enum MBType {
57 MBIntra,
58 MBIntra16,
59 MBSkip,
60 MBP16x16,
61 MBP16x16Mix,
62 MBP16x8,
63 MBP8x16,
64 MBP8x8,
65 MBDirect,
66 MBBidir,
67 MBForward,
68 MBBackward,
69 Invalid,
70 }
71
72 impl MBType {
73 pub fn is_intra(self) -> bool {
74 (self == MBType::MBIntra) || (self == MBType::MBIntra16)
75 }
76 pub fn is_16(self) -> bool {
77 (self == MBType::MBIntra16) || (self == MBType::MBP16x16Mix)
78 }
79 pub fn is_intra_or_16(self) -> bool {
80 self.is_intra() || self.is_16()
81 }
82 pub fn get_num_mvs(self) -> usize {
83 match self {
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,
89 MBType::MBP8x8 => 4,
90 MBType::Invalid => unreachable!(),
91 }
92 }
93 pub fn is_fwd(self) -> bool {
94 matches!(self,
95 MBType::MBP16x16 | MBType::MBP16x16Mix |
96 MBType::MBP16x8 | MBType::MBP8x16 | MBType::MBP8x8 |
97 MBType::MBForward)
98 }
99 pub fn is_bwd(self) -> bool {
100 matches!(self, MBType::MBBidir | MBType::MBBackward)
101 }
102 pub fn has_mv_dir(self, fwd: bool) -> bool {
103 match self {
104 MBType::MBBidir => true,
105 MBType::MBForward if fwd => true,
106 MBType::MBBackward if !fwd => true,
107 _ => false,
108 }
109 }
110 pub fn is_nomv(self) -> bool {
111 matches!(self, MBType::MBIntra | MBType::MBIntra16 | MBType::MBSkip | MBType::MBDirect)
112 }
113 /*pub fn is_16x16(self) -> bool {
114 match self {
115 MBType::MBP16x8 | MBType::MBP8x16 | MBType::MBP8x8 => false,
116 _ => true,
117 }
118 }*/
119 fn get_weight(self) -> usize {
120 match self {
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,
128 MBType::MBP8x8 => 3,
129 MBType::MBDirect => 6,
130 MBType::MBBidir => 9,
131 MBType::MBForward => 4,
132 MBType::MBBackward => 5,
133 MBType::Invalid => unreachable!(),
134 }
135 }
136 }
137
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,
142 ];
143
144 #[derive(Clone,Copy)]
145 pub struct MBInfo {
146 pub mbtype: MBType,
147 pub skip_run: usize,
148 pub dquant: bool,
149 }
150
151 #[derive(Clone,Copy)]
152 pub struct RV34MBInfo {
153 pub mbtype: MBType,
154 pub cbp: u32,
155 pub deblock:u16,
156 pub cbp_c: u8, // for deblocking purposes
157 pub q: u8,
158 }
159
160 struct IntraModeState {
161 cache: GenericCache<i8>,
162 }
163
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
169 ];
170
171 const RV34_INTRA_PRED16: [PredType8x8; 4] = [
172 PredType8x8::DC, PredType8x8::Ver, PredType8x8::Hor, PredType8x8::Plane
173 ];
174
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) }
179 }
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
184 }
185 fn set_mb_x(&mut self, mb_x: usize) {
186 self.cache.xpos = self.get_pos(mb_x);
187 }
188 fn fill_block(&mut self, val: i8) {
189 let mut pos = self.cache.xpos;
190 for _ in 0..4 {
191 for j in 0..4 {
192 self.cache.data[pos + j] = val;
193 }
194 pos += self.cache.stride;
195 }
196 }
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];
200 if !has_top {
201 im = match im {
202 PredType8x8::Plane | PredType8x8::Ver => PredType8x8::Hor,
203 PredType8x8::DC => PredType8x8::LeftDC,
204 _ => im,
205 };
206 } else if !has_left {
207 im = match im {
208 PredType8x8::Plane | PredType8x8::Hor => PredType8x8::Ver,
209 PredType8x8::DC => PredType8x8::TopDC,
210 _ => im,
211 };
212 }
213 im
214 }
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 };
219 if !has_top {
220 im = match im {
221 PredType8x8::Plane | PredType8x8::Ver => PredType8x8::Hor,
222 PredType8x8::DC => PredType8x8::LeftDC,
223 _ => im,
224 };
225 } else if !has_left {
226 im = match im {
227 PredType8x8::Plane | PredType8x8::Hor => PredType8x8::Ver,
228 PredType8x8::DC => PredType8x8::TopDC,
229 _ => im,
230 };
231 }
232 im
233 }
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);
239
240 let mut im = RV34_INTRA_PRED4[self.cache.data[self.cache.xpos + x + y * self.cache.stride] as usize];
241
242 if no_up {
243 im = match im {
244 PredType4x4::Ver => PredType4x4::Hor,
245 PredType4x4::DC => PredType4x4::LeftDC,
246 _ => im,
247 };
248 } else if no_left {
249 im = match im {
250 PredType4x4::Hor => PredType4x4::Ver,
251 PredType4x4::DC => PredType4x4::TopDC,
252 PredType4x4::DiagDownLeft => PredType4x4::DiagDownLeftNoDown,
253 _ => im,
254 };
255 }
256 if no_down {
257 im = match im {
258 PredType4x4::DiagDownLeft => PredType4x4::DiagDownLeftNoDown,
259 PredType4x4::HorUp => PredType4x4::HorUpNoDown,
260 PredType4x4::VerLeft => PredType4x4::VerLeftNoDown,
261 _ => im,
262 };
263 }
264 im
265 }
266 //todo merge
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);
272
273 let mut im = RV34_INTRA_PRED4[self.cache.data[self.cache.xpos + x * 2 + y * 2 * self.cache.stride] as usize];
274
275 if no_up {
276 im = match im {
277 PredType4x4::Ver => PredType4x4::Hor,
278 PredType4x4::DC => PredType4x4::LeftDC,
279 _ => im,
280 };
281 } else if no_left {
282 im = match im {
283 PredType4x4::Hor => PredType4x4::Ver,
284 PredType4x4::DC => PredType4x4::TopDC,
285 PredType4x4::DiagDownLeft => PredType4x4::DiagDownLeftNoDown,
286 _ => im,
287 };
288 }
289 if no_down {
290 im = match im {
291 PredType4x4::DiagDownLeft => PredType4x4::DiagDownLeftNoDown,
292 PredType4x4::HorUp => PredType4x4::HorUpNoDown,
293 PredType4x4::VerLeft => PredType4x4::VerLeftNoDown,
294 _ => im,
295 };
296 }
297 im
298 }
299 }
300
301 pub struct MVInfo {
302 pub mv_b: Vec<MV>,
303 pub mv_f: Vec<MV>,
304 pub w: usize,
305 pub h: usize,
306 pub has_b: Vec<bool>,
307 pub has_f: Vec<bool>,
308 }
309
310 impl MVInfo {
311 fn new() -> Self {
312 Self { mv_b: Vec::new(), mv_f: Vec::new(), w: 0, h: 0, has_b: Vec::new(), has_f: Vec::new() }
313 }
314 fn resize(&mut self, mb_w: usize, mb_h: usize) {
315 self.w = mb_w * 2;
316 self.h = mb_h * 2;
317 self.reset();
318 }
319 fn reset(&mut self) {
320 let size = self.w * self.h;
321 self.mv_f.clear();
322 self.mv_f.resize(size, ZERO_MV);
323 self.mv_b.clear();
324 self.mv_b.resize(size, ZERO_MV);
325 self.has_f.clear();
326 self.has_f.resize(size >> 2, false);
327 self.has_b.clear();
328 self.has_b.resize(size >> 2, false);
329 }
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;
332 if fwd {
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;
337 } else {
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;
342 }
343 }
344 fn get_mv_by_idx(&self, idx: usize, fwd: bool) -> MV {
345 if fwd { self.mv_f[idx] } else { self.mv_b[idx] }
346 }
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 };
352 let tr_mv;
353 if has_tr {
354 tr_mv = self.get_mv_by_idx(idx - self.w + tr_add, fwd);
355 } else if has_tl {
356 tr_mv = self.get_mv_by_idx(idx - self.w - 1, fwd);
357 } else {
358 tr_mv = left_mv;
359 }
360 MV::pred(left_mv, top_mv, tr_mv)
361 }
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)
364 }
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);
372 return;
373 }
374 if mbtype.is_fwd() {
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);
378 }
379 let idx = mb_x * 2 + mb_y * 2 * self.w;
380
381 match mbtype {
382 MBType::MBSkip => {
383 self.fill(mb_x, mb_y, true, ZERO_MV/*pred_mv*/);
384 },
385 MBType::MBP16x16 |
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);
390 },
391 MBType::MBP16x8 => {
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;
396
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;
402 },
403 MBType::MBP8x16 => {
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;
408
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;
413 },
414 MBType::MBP8x8 => {
415 let mut idx8 = idx;
416 let mut has_top = sstate.has_top;
417 for y in 0..2 {
418 for x in 0..2 {
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 };
421 let has_tl;
422 if y == 0 {
423 has_tl = if x == 0 { sstate.has_tl } else { sstate.has_top };
424 } else {
425 has_tl = if x == 0 { sstate.has_left } else { true };
426 }
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;
430 }
431 has_top = true;
432 idx8 += self.w;
433 }
434 },
435 MBType::MBDirect => {
436 let mut cum_mv_f = ZERO_MV;
437 let mut cum_mv_b = ZERO_MV;
438 let mut idx8 = idx;
439 for _ in 0..2 {
440 for x in 0..2 {
441 let (mv_f, mv_b) = ref_mvi.mv_f[idx8 + x].scale(sstate.trd, sstate.trb);
442 cum_mv_f += mv_f;
443 cum_mv_b += mv_b;
444 }
445 idx8 += self.w;
446 }
447 cum_mv_f.x >>= 2;
448 cum_mv_f.y >>= 2;
449 cum_mv_b.x >>= 2;
450 cum_mv_b.y >>= 2;
451 self.fill(mb_x, mb_y, true, cum_mv_f);
452 self.fill(mb_x, mb_y, false, cum_mv_b);
453 },
454 MBType::MBBidir => {
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);
461 },
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);
466 },
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);
471 },
472 _ => {},
473 }
474 }
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] }
479 }
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)
486 }
487 }
488
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);
495 }
496
497 pub trait RV34DSP {
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);
501 }
502
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;
506 offsets.clear();
507
508 if ini_off >= src.len() { return Err(DecoderError::ShortData); }
509
510 let mut br = BitReader::new(&src[1..ini_off], BitReaderMode::BE);
511
512 for i in 0..num_slices {
513 br.skip(32)?;
514 let off = br.read(32)? as usize;
515 if (i == 0) && (off != 0) {
516 return Err(DecoderError::InvalidData);
517 }
518 if (i > 0) && (off <= offsets[i - 1]) {
519 return Err(DecoderError::InvalidData);
520 }
521 offsets.push(off);
522 }
523
524 Ok(())
525 }
526
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);
533 }
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;
540 } else {
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;
546 } else {
547 shdr.end = ((shdr.width + 15) >> 4) * ((shdr.height + 15) >> 4);
548 }
549 } else {
550 shdr.end = ((shdr.width + 15) >> 4) * ((shdr.height + 15) >> 4);
551 }
552 }
553 br.seek(cur_pos)?;
554 } else {
555 shdr.end = ((shdr.width + 15) >> 4) * ((shdr.height + 15) >> 4);
556 }
557 Ok(shdr)
558 }
559
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 ];
562
563 pub fn get_slice_start_offset_bits(w: usize, h: usize) -> u8 {
564 if (w == 0) || (h == 0) {
565 return 0;
566 }
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]
571 }
572
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 ]
578 ];
579
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
585 ];
586
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
590 ];
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
594 ];
595
596 fn decode_dquant(br: &mut BitReader, q: u8) -> DecoderResult<u8> {
597 if br.read_bool()? {
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));
601 Ok(qp as u8)
602 } else {
603 let qp = br.read(5)? as u8;
604 Ok(qp)
605 }
606 }
607
608 pub struct SState {
609 pub mb_x: usize,
610 pub mb_y: usize,
611 pub mb_w: usize,
612 pub mb_h: usize,
613 pub cbp: u32,
614 pub q: u8,
615 pub q_dc: u8,
616 pub set_idx: usize,
617 pub has_left: bool,
618 pub has_top: bool,
619 pub has_tl: bool,
620 pub has_tr: bool,
621 pub trd: u16,
622 pub trb: u16,
623 }
624
625 impl SState {
626 fn new() -> Self {
627 Self {
628 mb_x: 0,
629 mb_y: 0,
630 mb_w: 0,
631 mb_h: 0,
632 cbp: 0,
633 q: 0,
634 q_dc: 0,
635 set_idx: 0,
636 has_left: false,
637 has_top: false,
638 has_tl: false,
639 has_tr: false,
640 trd: 0,
641 trb: 0,
642 }
643 }
644 }
645
646 struct MBHist {
647 is_p: bool,
648 hist: [MBType; 4],
649 count: usize,
650 }
651
652 impl MBHist {
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,
658 _ => mbt,
659 };
660 self.hist[self.count] = mbt2;
661 self.count += 1;
662 }
663 fn get_mbtype(&self) -> MBType {
664 if self.count == 0 {
665 MBType::MBIntra
666 } else if self.count == 1 {
667 self.hist[0]
668 } else if self.count == 2 {
669 if self.hist[0].get_weight() <= self.hist[1].get_weight() {
670 self.hist[0]
671 } else {
672 self.hist[1]
673 }
674 } else {
675 let mut w: [usize; 12] = [0; 12];
676 for i in 0..self.count { w[self.hist[i].get_weight()] += 1; }
677 let mut nz_idx = 0;
678 for i in 0..12 {
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; }
681 }
682
683 MBTYPE_FROM_WEIGHT[nz_idx]
684 }
685 }
686 }
687
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;
691 Ok(MV{ x, y })
692 }
693
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);
698 }
699
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);
704 }
705
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) {
707 for comp in 0..3 {
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();
715
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();
720
721 if ratio1 == ratio2 {
722 cdsp.avg(dst, doffset, dstride, src, soffset, sstride, csize);
723 } else {
724 cdsp.weight(dst, doffset, dstride, src, soffset, sstride, ratio2, ratio1, csize);
725 }
726 }
727 }
728
729 pub struct RV34Decoder {
730 is_rv30: bool,
731 coderead: RV34Codes,
732 dsp: Box<dyn RV34DSP + Send>,
733 cdsp: RV34CommonDSP,
734 width: usize,
735 height: usize,
736 ipbs: IPBShuffler,
737 mvi: MVInfo,
738 ref_mvi: MVInfo,
739 last_ts: u16,
740 next_ts: u16,
741 ratio1: u32,
742 ratio2: u32,
743 is_b: bool,
744 mbinfo: Vec<RV34MBInfo>,
745 avg_buf: NAVideoBufferRef<u8>,
746 base_ts: u64,
747 }
748
749 impl RV34Decoder {
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();
755 RV34Decoder {
756 is_rv30,
757 coderead: RV34Codes::new(),
758 dsp,
759 cdsp: RV34CommonDSP::new(),
760 ipbs: IPBShuffler::new(),
761 mvi: MVInfo::new(),
762 ref_mvi: MVInfo::new(),
763 mbinfo: Vec::new(),
764 width: 0, height: 0,
765 last_ts: 0, next_ts: 0,
766 ratio1: 0, ratio2: 0,
767 is_b: false,
768 avg_buf,
769 base_ts: 0,
770 }
771 }
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> {
773 if is_i16 {
774 let imode = br.read(2)? as i8;
775 im.fill_block(imode);
776 Ok(MBInfo { mbtype: MBType::MBIntra16, skip_run: 0, dquant: false })
777 } else {
778 let dq = if !has_dq {
779 if !self.is_rv30 { !br.read_bool()? } else { false }
780 } else { false };
781 if dq {
782 decode_dquant(br, q)?;
783 }
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 })
786 }
787 }
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);
791 if hdr.dquant {
792 decode_dquant(br, q)?;
793 }
794 if hdr.mbtype.is_intra() {
795 return self.decode_mb_header_intra(bd, br, hdr.mbtype.is_16(), im, q, has_top, true);
796 }
797 Ok(hdr)
798 }
799
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;
802 {
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];
807 if is_16 {
808 let has_ac = self.coderead.decode_block(br, &mut coeffs16, 3, 0, q_dc, q_dc, q_ac)?;
809 if has_ac {
810 self.cdsp.transform16(&mut coeffs16);
811 } else {
812 self.cdsp.transform16_dc(&mut coeffs16);
813 }
814 }
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();
819
820 if is_16 {
821 let im16 = imode.get_pred16_type(sstate.has_top, sstate.has_left);
822 self.cdsp.ipred16x16[im16 as usize](framebuf, offset, stride);
823 }
824
825 for y in 0..4 {
826 for x in 0..4 {
827 let mut coeffs: [i16; 16] = [0; 16];
828 let has_ac;
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)?;
831 } else {
832 has_ac = false;
833 }
834 if is_16 {
835 coeffs[0] = coeffs16[x + y * 4];
836 } else {
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]]
843 } else if has_top {
844 let i = offset + x * 4 - stride;
845 [framebuf[i + 4], framebuf[i + 5], framebuf[i + 6], framebuf[i + 7]]
846 } else {
847 [0; 4]
848 };
849 self.cdsp.ipred4x4[im as usize](framebuf, offset + x*4, stride, &topright);
850 }
851 if has_ac {
852 self.cdsp.transform(&mut coeffs);
853 } else {
854 self.cdsp.transform_dc(&mut coeffs);
855 }
856 self.cdsp.add_coeffs(framebuf, offset + x * 4, stride, &coeffs);
857 cur_cbp >>= 1;
858 }
859 offset += stride * 4;
860 }
861 }
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];
864 let chroma_set = 0;
865 for comp in 1..3 {
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();
870 if is_16 {
871 let im8 = imode.get_pred8_type(sstate.has_top, sstate.has_left);
872 self.cdsp.ipred8x8[im8 as usize](framebuf, offset, stride);
873 }
874 for y in 0..2 {
875 for x in 0..2 {
876 let mut coeffs: [i16; 16] = [0; 16];
877 let has_ac;
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)?;
880 } else {
881 has_ac = false;
882 }
883 if !is_16 {
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]]
890 } else if has_top {
891 let i = offset + x * 4 - stride;
892 [framebuf[i + 4], framebuf[i + 5], framebuf[i + 6], framebuf[i + 7]]
893 } else {
894 [0; 4]
895 };
896 self.cdsp.ipred4x4[im as usize](framebuf, offset + x*4, stride, &topright);
897 }
898 if has_ac {
899 self.cdsp.transform(&mut coeffs);
900 } else {
901 self.cdsp.transform_dc(&mut coeffs);
902 }
903 self.cdsp.add_coeffs(framebuf, offset + x * 4, stride, &coeffs);
904 cur_cbp >>= 1;
905 }
906 offset += stride * 4;
907 }
908 }
909 Ok(())
910 }
911
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;
915 match mbh.mbtype {
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);
920 }
921 },
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);
926 }
927 },
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);
932 }
933 },
934 MBType::MBP8x8 | MBType::MBP8x16 | MBType::MBP16x8 => {
935 if let Some(ref prevbuf) = self.ipbs.get_lastref() {
936 for y in 0..2 {
937 for x in 0..2 {
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);
940 }
941 }
942 }
943 },
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);
947 }
948 },
949 MBType::MBSkip | MBType::MBDirect => {
950 if let (Some(ref fwdbuf), Some(ref bwdbuf)) = (self.ipbs.get_b_fwdref(), self.ipbs.get_b_bwdref()) {
951 for y in 0..2 {
952 for x in 0..2 {
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);
957 }
958 }
959 }
960 },
961 MBType::MBBidir => {
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);
968 }
969 },
970 _ => {},
971 };
972 }
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);
975
976 let mut cur_cbp = sstate.cbp;
977
978 {
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];
983 if is_16 {
984 let has_ac = self.coderead.decode_block(br, &mut coeffs16, 3, 0, q_dc, q_dc, q_ac)?;
985 if has_ac {
986 self.cdsp.transform16(&mut coeffs16);
987 } else {
988 self.cdsp.transform16_dc(&mut coeffs16);
989 }
990 }
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();
995
996 for y in 0..4 {
997 for x in 0..4 {
998 let mut coeffs: [i16; 16] = [0; 16];
999 let has_ac;
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)?;
1002 } else {
1003 has_ac = false;
1004 }
1005 if is_16 {
1006 coeffs[0] = coeffs16[x + y * 4];
1007 }
1008 if has_ac {
1009 self.cdsp.transform(&mut coeffs);
1010 } else {
1011 self.cdsp.transform_dc(&mut coeffs);
1012 }
1013 self.cdsp.add_coeffs(framebuf, offset + x * 4, stride, &coeffs);
1014 cur_cbp >>= 1;
1015 }
1016 offset += stride * 4;
1017 }
1018 }
1019 if is_16 {
1020 self.coderead.select_codes(false, sstate.q, sstate.set_idx, false);
1021 }
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];
1024 let chroma_set = 1;
1025 for comp in 1..3 {
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();
1030 for _ in 0..2 {
1031 for x in 0..2 {
1032 let mut coeffs: [i16; 16] = [0; 16];
1033 let has_ac;
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)?;
1036 } else {
1037 has_ac = false;
1038 }
1039 if has_ac {
1040 self.cdsp.transform(&mut coeffs);
1041 } else {
1042 self.cdsp.transform_dc(&mut coeffs);
1043 }
1044 self.cdsp.add_coeffs(framebuf, offset + x * 4, stride, &coeffs);
1045 cur_cbp >>= 1;
1046 }
1047 offset += stride * 4;
1048 }
1049 }
1050 Ok(())
1051 }
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;
1056
1057 for y in 0..2 {
1058 for x in 0..2 {
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;
1062 }
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;
1065 }
1066 }
1067 }
1068 if !sstate.has_top { hmvmask &= !0x000F; }
1069 if sstate.mb_x == 0 { vmvmask &= !0x1111; }
1070 if self.is_rv30 {
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;
1075 }
1076 if sstate.has_top {
1077
1078 mbinfo[mb_pos - sstate.mb_w].deblock |= (hmvmask & 0xF) << 12;
1079 }
1080 }
1081 if mbt.is_intra_or_16() {
1082 mbinfo[mb_pos].deblock = 0xFFFF;
1083 mbinfo[mb_pos].cbp_c = 0xFF;
1084 } else {
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;
1087 }
1088 }
1089
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;
1095
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;
1110
1111 let mut sstate = SState::new();
1112 let mut mbinfo: Vec<RV34MBInfo> = Vec::with_capacity(mb_w * mb_h);
1113
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;
1120 }
1121 }
1122 match hdr0.ftype {
1123 FrameType::P => {
1124 if self.ipbs.get_lastref().is_none() {
1125 return Err(DecoderError::MissingReference);
1126 }
1127 },
1128 FrameType::B => {
1129 if self.ipbs.get_lastref().is_none() {
1130 return Err(DecoderError::MissingReference);
1131 }
1132 if self.ipbs.get_nextref().is_none() {
1133 return Err(DecoderError::MissingReference);
1134 }
1135 },
1136 _ => {},
1137 };
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);
1145 } else {
1146 self.ratio1 = 1 << 14 >> 1;
1147 self.ratio2 = 1 << 14 >> 1;
1148 }
1149 //todo validate against ref frame
1150
1151 let vinfo = NAVideoInfo::new(hdr0.width, hdr0.height, false, YUV420_FORMAT);
1152 let ret = supp.pool_u8.get_free();
1153 if ret.is_none() {
1154 return Err(DecoderError::AllocError);
1155 }
1156 let mut buf = ret.unwrap();
1157 if buf.get_info() != vinfo {
1158 self.ipbs.clear();
1159 supp.pool_u8.reset();
1160 supp.pool_u8.prealloc_video(vinfo, 4)?;
1161 let ret = supp.pool_u8.get_free();
1162 if ret.is_none() {
1163 return Err(DecoderError::AllocError);
1164 }
1165 buf = ret.unwrap();
1166 }
1167
1168 sstate.q = q;
1169 sstate.has_top = false;
1170 sstate.mb_w = mb_w;
1171 sstate.mb_h = mb_h;
1172 sstate.set_idx = hdr0.set_idx;
1173
1174 self.mvi.resize(mb_w, mb_h);
1175 for mb_y in 0..mb_h {
1176 sstate.mb_y = mb_y;
1177 sstate.has_left = false;
1178 for mb_x in 0..mb_w {
1179 sstate.mb_x = mb_x;
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));
1183 q = slice.quant;
1184 slice_no += 1;
1185 imode.reset();
1186 sstate.q = q;
1187 sstate.has_top = false;
1188 sstate.has_left = false;
1189 sstate.set_idx = slice.set_idx;
1190 }
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)?
1198 } else {
1199 if skip_run == 0 {
1200 let mbtype;
1201 if self.is_rv30 {
1202 mbtype = MBType::Invalid;
1203 } else {
1204 let mut hist = MBHist::new(hdr0.ftype);
1205 if sstate.has_top {
1206 hist.add(mbinfo[mb_pos - mb_w].mbtype);
1207 if sstate.has_tr { hist.add(mbinfo[mb_pos - mb_w + 1].mbtype); }
1208 }
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();
1212 }
1213 self.decode_mb_header_inter(bd, &mut br, hdr0.ftype, mbtype, &mut imode, q, sstate.has_top)?
1214 } else {
1215 skip_run -= 1;
1216 MBInfo { mbtype: MBType::MBSkip, skip_run: 0, dquant: false }
1217 }
1218 };
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)?;
1223 }
1224 if !self.is_b {
1225 self.mvi.set_mb(mb_x, mb_y, mbh.mbtype, &self.ref_mvi, &mvs, &sstate);
1226 } else {
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);
1230 }
1231 }
1232 let cbp;
1233 let is_16 = (mbh.mbtype == MBType::MBIntra16) || (mbh.mbtype == MBType::MBP16x16Mix);
1234 if mbh.mbtype == MBType::MBSkip {
1235 cbp = 0;
1236 if mbh.skip_run > 0 {
1237 skip_run = mbh.skip_run;
1238 }
1239 } else {
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);
1243 }
1244 cbp = self.coderead.decode_cbp(&mut br)?;
1245 }
1246 sstate.cbp = cbp;
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)?;
1250 } else {
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)?;
1254 }
1255
1256 let mi = RV34MBInfo { cbp, q, mbtype: mbh.mbtype, deblock: 0, cbp_c: 0 };
1257 mbinfo.push(mi);
1258 if is_intra {
1259 mbinfo[mb_pos].deblock = 0xFFFF;
1260 mbinfo[mb_pos].cbp_c = 0xFF;
1261 } else {
1262 self.fill_deblock_flags(&sstate, mb_pos, &mut mbinfo);
1263 }
1264 sstate.has_left = true;
1265 mb_pos += 1;
1266 }
1267 if hdr0.deblock && (mb_y >= 1) {
1268 self.dsp.loop_filter(&mut buf, hdr0.ftype, &mbinfo, mb_w, mb_h, mb_y - 1);
1269 }
1270 imode.update();
1271 }
1272 if hdr0.deblock {
1273 self.dsp.loop_filter(&mut buf, hdr0.ftype, &mbinfo, mb_w, mb_h, mb_h - 1);
1274 }
1275 if !self.is_b {
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);
1279 }
1280
1281 Ok((NABufferType::Video(buf), hdr0.ftype, ts))
1282 }
1283 pub fn flush(&mut self) {
1284 self.ipbs.clear();
1285 }
1286 }