rv6: fix typo in chroma filtering loop
[nihav.git] / nihav-realmedia / src / codecs / rv60.rs
CommitLineData
5641dccf
KS
1use nihav_core::formats::YUV420_FORMAT;
2use nihav_core::frame::*;
54d2b09a 3use nihav_core::codecs::{NADecoder, NADecoderSupport, DecoderError, DecoderResult, FrameSkipMode};
7d57ae2f 4use nihav_core::options::*;
b4d5b851 5use nihav_codec_support::codecs::{MV, ZERO_MV, IPBShuffler};
5641dccf
KS
6use nihav_core::io::byteio::{MemoryReader,ByteReader};
7use nihav_core::io::bitreader::{BitReader,BitReaderMode};
8use nihav_core::io::intcode::*;
54d2b09a 9use std::str::FromStr;
52aad9fe
KS
10
11use super::rv60codes::*;
12use super::rv60dsp::*;
13
14struct UniqueList<A> {
15 list: [A; 4],
16 fill: usize,
17 max_size: usize,
18}
19
20impl<A:Copy+Default+PartialEq> UniqueList<A> {
21 fn new(max_size: usize) -> Self {
22 Self { list: [A::default(); 4], fill: 0, max_size }
23 }
24 fn add(&mut self, cand: A) {
25 if self.fill == self.max_size { return; }
26 let mut unique = true;
61d3e294 27 for el in self.list.iter().take(self.fill) {
52aad9fe
KS
28 if *el == cand {
29 unique = false;
30 break;
31 }
32 }
33 if unique {
34 self.list[self.fill] = cand;
35 self.fill += 1;
36 }
37 }
38}
39
40const RV60_FRAME_TYPES: [FrameType; 4] = [ FrameType::I, FrameType::P, FrameType::B, FrameType::Other ];
41const MAX_IMODE: u8 = 34;
42
43#[derive(Clone,Copy,Debug)]
3518aa85 44#[allow(dead_code)]
52aad9fe
KS
45struct FrameHeader {
46 profile: u8,
47 ftype: FrameType,
48 qp: u8,
49 osvquant: u8,
50 ts: u32,
51 width: usize,
52 height: usize,
53 two_f_refs: bool,
54 qp_off_type: u8,
55 deblock: bool,
56 deblock_chroma: bool,
57}
58
59const RV60_CUSTOM_MSG_LENS: [u32; 4] = [ 2, 4, 16, 32 ];
60impl FrameHeader {
61 fn read(br: &mut BitReader) -> DecoderResult<Self> {
62 let marker = br.read(2)?;
63 validate!(marker == 3);
64 let profile = br.read(2)? as u8;
65 validate!(profile == 0);
66 let _someval = br.read(4)?;
67 let ftypeid = br.read(2)? as usize;
68 let ftype = RV60_FRAME_TYPES[ftypeid];
69 let qp = br.read(6)? as u8;
70 let marker = br.read(1)?;
71 validate!(marker == 0);
72 let toolset = br.read(2)?;
73 validate!(toolset == 0);
74 let osvquant = br.read(2)? as u8;
75 let _some_flag = br.read_bool()?;
76 let _some_val = br.read(2)?;
77 let ts = br.read(24)?;
78 let width = ((br.read(11)? as usize) + 1) * 4;
79 let height = ((br.read(11)? as usize) + 0) * 4;
80 validate!(height > 0);
81 let _some_flag = br.read_bool()?;
82 let two_f_refs;
83 if ftype == FrameType::I {
84//byte17 = 0
85 two_f_refs = false;
86 } else {
87 let flag = br.read_bool()?;
88 if flag { // untested
89 br.skip(1)?;
90 br.skip(1)?;
91 br.skip(1)?;
92 }
93//byte17 = flag?
94 two_f_refs = br.read_bool()?;
95 }
96// if byte17 { dw40 = 2; dw3C = 2; } else { dw40 = 1; dw3C = 1; }
97 let _some_val = br.read_code(UintCodeType::Unary012)?; // luma_qp_diff?
98 let chroma_qp_diff = br.read(1)?;
99 validate!(chroma_qp_diff == 0);
100 let qp_off_type = br.read_code(UintCodeType::Unary012)? as u8;
101 let deblock = br.read_bool()?;
102 let deblock_chroma = deblock && !br.read_bool()?;
103 if br.read_bool()? {
104 let custom_msg_hdr_len = br.read(2)? as usize;
105 if custom_msg_hdr_len != 0 {
106 for i in 0..custom_msg_hdr_len {
107 br.skip(RV60_CUSTOM_MSG_LENS[i] * 8)?;
108 }
109 }
110 }
111
112 Ok(FrameHeader {
113 profile, ftype, qp, osvquant, ts, width, height, two_f_refs, qp_off_type,
114 deblock, deblock_chroma,
115 })
116 }
117 fn parse_slice_sizes(&self, br: &mut BitReader, sizes: &mut Vec<usize>) -> DecoderResult<()> {
118 let nslices = self.get_height_cu();
119 let nbits = (br.read(5)? as u8) + 1;
120 validate!(nbits < 32);
121 let mut signs: Vec<bool> = Vec::with_capacity(nslices);
122 for _ in 0..nslices {
123 let sign = br.read_bool()?;
124 signs.push(sign);
125 }
126 validate!(signs[0]);
37952415 127 sizes.clear();
52aad9fe
KS
128 let mut sum = 0;
129 let first_size = br.read(nbits)? as usize;
130 validate!(first_size > 0);
131 sum += first_size;
132 let mut lastsize = first_size;
133 sizes.push(first_size);
134 for i in 1..nslices {
135 let diff = br.read(nbits)? as isize;
136 let size;
137 if signs[i] {
138 let sum = (lastsize as isize).checked_add(diff);
139 validate!(sum.is_some());
140 size = sum.unwrap() as usize;
141 } else {
142 let sum = (lastsize as isize).checked_sub(diff);
143 validate!(sum.is_some());
144 size = sum.unwrap() as usize;
145 }
146 sizes.push(size);
147 sum += size;
148 lastsize = size;
149 }
150 br.align();
151if ((br.left() >> 3) as usize) != sum {
152println!(" left {} / {}", br.left() >> 3, sum);
153}
154 validate!((br.left() >> 3) >= (sum as isize));
155 Ok(())
156 }
157 fn read_line_qp_offset(&self, br: &mut BitReader) -> DecoderResult<i8> {
158 match self.qp_off_type {
159 0 => Ok(0),
160 1 => {
161 let val = br.read_code(UintCodeType::Unary012)?;
162 if val != 2 {
163 Ok(val as i8)
164 } else {
165 Ok(-1)
166 }
167 },
168 _ => {
169 if br.read(1)? == 0 {
170 Ok(0)
171 } else {
172 let val = br.read(2)? as i8;
173 if (val & 2) == 0 {
174 Ok(val + 1)
175 } else {
176 Ok(-((val & 1) + 1))
177 }
178 }
179 },
180 }
181 }
182 fn get_width_cu(&self) -> usize {
183 (self.width + 63) >> 6
184 }
185 fn get_height_cu(&self) -> usize {
186 (self.height + 63) >> 6
187 }
188 fn has_top_block(&self, xpos: usize, ypos: usize, dx: usize, dy: usize, size: usize) -> bool {
189 if (ypos + dy) == 0 { return false; }
190 let xpos2 = xpos + dx;
191 if (xpos2 + size) > self.width { return false; }
192 true
193 }
194 fn has_top_right_block(&self, xpos: usize, ypos: usize, dx: usize, dy: usize, size: usize) -> bool {
195 if (ypos + dy) == 0 { return false; }
196 let xpos2 = xpos + dx;
197 if (xpos2 + size * 2) > self.width { return false; }
198 let cxpos = ((xpos + dx) & 63) >> RV60_BLOCK_LOG2[size];
199 let cypos = ((ypos + dy) & 63) >> RV60_BLOCK_LOG2[size];
200 ((cypos as u8) & RV60_AVAIL_MASK[cxpos]) == 0
201 }
202 fn has_left_block(&self, xpos: usize, ypos: usize, dx: usize, dy: usize, size: usize) -> bool {
203 if (xpos + dx) == 0 { return false; }
204 let ypos2 = ypos + dy;
205 if (ypos2 + size) > self.height { return false; }
206 true
207 }
208 fn has_left_down_block(&self, xpos: usize, ypos: usize, dx: usize, dy: usize, size: usize) -> bool {
209 if (xpos + dx) == 0 { return false; }
210 let ypos2 = ypos + dy;
211 if (ypos2 + size * 2) > self.height { return false; }
212 let cxpos = (!(xpos + dx) & 63) >> RV60_BLOCK_LOG2[size];
213 let cypos = (!(ypos + dy) & 63) >> RV60_BLOCK_LOG2[size];
214 ((cypos as u8) & RV60_AVAIL_MASK[cxpos]) >= 1
215 }
216}
217
218const RV60_BLOCK_LOG2: [u8; 65] = [
219 0,
220 0, 1, 0, 2, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 4,
221 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5,
222 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
223 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6
224];
225const RV60_AVAIL_MASK: [u8; 64] = [
5536ee65 226 0, 1, 0, 3, 0, 1, 0, 7, 0, 1, 0, 3, 0, 1, 0, 0xF,
52aad9fe
KS
227 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
228 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
229 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
230];
231
232#[derive(Clone,Copy,PartialEq,Debug)]
233enum CUType {
234 Intra,
235 InterMV,
236 Skip,
237 InterNoMV,
238}
239
240impl Default for CUType {
241 fn default() -> Self { CUType::Intra }
242}
243
244const RV60_CU_TYPES: [CUType; 4] = [ CUType::Intra, CUType::InterMV, CUType::Skip, CUType::InterNoMV ];
245
246#[derive(Clone,Copy,PartialEq,Debug)]
247enum PUType {
248 Full,
249 N2Hor,
250 N2Ver,
251 Quarters,
252 N4Hor,
253 N34Hor,
254 N4Ver,
255 N34Ver,
256}
257
258const RV60_PU_TYPES: [PUType; 8] = [
259 PUType::Full, PUType::N2Hor, PUType::N2Ver, PUType::Quarters,
d24468d9 260 PUType::N4Hor, PUType::N34Hor, PUType::N4Ver, PUType::N34Ver,
52aad9fe
KS
261];
262
263impl PUType {
e07387c7
KS
264 fn get_num_mvs(self) -> usize {
265 match self {
52aad9fe
KS
266 PUType::Full => 1,
267 PUType::Quarters => 4,
268 _ => 2,
269 }
270 }
e07387c7 271 fn get_mv_size(self, part_no: usize, size: usize) -> (usize, usize) {
52aad9fe 272 let mv_size = size >> 2;
e07387c7 273 match self {
52aad9fe
KS
274 PUType::Full => (mv_size, mv_size),
275 PUType::N2Hor => (mv_size, mv_size >> 1),
276 PUType::N2Ver => (mv_size >> 1, mv_size),
277 PUType::Quarters => (mv_size >> 1, mv_size >> 1),
278 PUType::N4Hor => {
279 if part_no == 0 {
e07387c7 280 (mv_size, mv_size >> 2)
52aad9fe 281 } else {
e07387c7 282 (mv_size, (3 * mv_size) >> 2)
52aad9fe
KS
283 }
284 },
285 PUType::N34Hor => {
286 if part_no == 0 {
e07387c7 287 (mv_size, (3 * mv_size) >> 2)
52aad9fe 288 } else {
e07387c7 289 (mv_size, mv_size >> 2)
52aad9fe
KS
290 }
291 },
292 PUType::N4Ver => {
293 if part_no == 0 {
e07387c7 294 ( mv_size >> 2, mv_size)
52aad9fe 295 } else {
e07387c7 296 ((3 * mv_size) >> 2, mv_size)
52aad9fe
KS
297 }
298 },
299 PUType::N34Ver => {
300 if part_no == 0 {
e07387c7 301 ((3 * mv_size) >> 2, mv_size)
52aad9fe 302 } else {
e07387c7 303 ( mv_size >> 2, mv_size)
52aad9fe
KS
304 }
305 },
306 }
307 }
e07387c7 308 fn has_hor_split(self) -> bool {
6f263099 309 matches!(self, PUType::N2Hor | PUType::N4Hor | PUType::N34Hor | PUType::Quarters)
52aad9fe 310 }
e07387c7 311 fn has_ver_split(self) -> bool {
6f263099 312 matches!(self, PUType::N2Ver | PUType::N4Ver | PUType::N34Ver | PUType::Quarters)
52aad9fe
KS
313 }
314}
315
316impl Default for PUType {
317 fn default() -> Self { PUType::Full }
318}
319
320#[derive(Clone,Copy,Debug)]
321enum IntraMode {
322 Index(u8),
323 Mode(u8),
324 DC64,
325 Plane64,
326}
327
328#[derive(Clone,Copy,PartialEq,Debug)]
329enum TransformType {
330 None,
331 T4X4,
332 T8X8,
333 T16X16,
334}
335
336impl Default for TransformType {
337 fn default() -> Self { TransformType::None }
338}
339
340#[derive(Clone,Copy,PartialEq,Debug)]
341enum MVRef {
342 None,
343 Ref0,
344 Ref1,
345 BRef,
346 Ref0AndBRef,
347 Skip0,
348 Skip1,
349 Skip2,
350 Skip3,
351}
352
353const SKIP_MV_REF: [MVRef; 4] = [ MVRef::Skip0, MVRef::Skip1, MVRef::Skip2, MVRef::Skip3 ];
354
355impl MVRef {
e07387c7
KS
356 fn get_skip_mv_num(self) -> usize {
357 match self {
52aad9fe
KS
358 MVRef::Skip1 => 1,
359 MVRef::Skip2 => 2,
360 MVRef::Skip3 => 3,
361 _ => 0,
362 }
363 }
e07387c7 364 fn is_ref0(self) -> bool {
6f263099 365 matches!(self, MVRef::Ref0 | MVRef::Ref0AndBRef)
52aad9fe 366 }
e07387c7 367 fn is_fwd(self) -> bool {
6f263099 368 matches!(self, MVRef::Ref0 | MVRef::Ref1 | MVRef::Ref0AndBRef)
52aad9fe 369 }
e07387c7 370 fn is_bwd(self) -> bool {
6f263099 371 matches!(self, MVRef::BRef | MVRef::Ref0AndBRef)
52aad9fe
KS
372 }
373}
374
375#[derive(Clone,Copy,PartialEq,Debug)]
376struct MVInfo {
377 f_mv: MV,
378 b_mv: MV,
379 mvref: MVRef,
380}
381
382impl MVInfo {
383 fn is_some(&self) -> bool { self.mvref != MVRef::None }
384 fn matches_fwd(&self, mvref: MVRef) -> bool {
385 (self.mvref == mvref) || (self.mvref.is_ref0() && mvref.is_ref0())
386 }
387 fn matches_bwd(&self, mvref: MVRef) -> bool {
388 self.mvref.is_bwd() && mvref.is_bwd()
389 }
390 fn is_deblock_cand(&self, other: &MVInfo) -> bool {
391 if self.mvref != other.mvref { return true; }
392 let mut mvdiff = 0;
393 if self.mvref.is_fwd() {
394 let diff = self.f_mv - other.f_mv;
395 mvdiff += diff.x.abs() + diff.y.abs();
396 }
397 if self.mvref.is_bwd() {
398 let diff = self.b_mv - other.b_mv;
399 mvdiff += diff.x.abs() + diff.y.abs();
400 }
401 mvdiff > 4
402 }
403}
404
405impl Default for MVInfo {
406 fn default() -> Self { Self { f_mv: ZERO_MV, b_mv: ZERO_MV, mvref: MVRef::None } }
407}
408
409#[derive(Clone,Copy,Debug)]
410struct CBHeader {
411 cu_type: CUType,
412 pu_type: PUType,
413 ttype: TransformType,
414 imode: [IntraMode; 4],
415 mv: [MVInfo; 4],
416}
417
418impl CBHeader {
419 fn read(br: &mut BitReader, ftype: FrameType, two_f_refs: bool, size: usize) -> DecoderResult<Self> {
420 let cu_type;
421 let pu_type;
422 let mut imode: [IntraMode; 4] = [IntraMode::Index(0); 4];
423 let mut mv: [MVInfo; 4] = [MVInfo::default(); 4];
424 if ftype == FrameType::I {
425 cu_type = CUType::Intra;
426 } else {
427 cu_type = RV60_CU_TYPES[br.read(2)? as usize];
428 }
429 match cu_type {
430 CUType::Intra => {
431 if (size == 8) && br.read_bool()? {
432 pu_type = PUType::Quarters;
433 } else {
434 pu_type = PUType::Full;
435 }
436 if pu_type == PUType::Quarters {
437 for i in 0..4 {
438 imode[i] = CBHeader::read_intra_mode(br)?;
439 }
440 } else if size <= 32 {
441 imode[0] = CBHeader::read_intra_mode(br)?;
442 } else {
443 if !br.read_bool()? {
444 imode[0] = IntraMode::DC64;
445 } else {
446 imode[0] = IntraMode::Plane64;
447 }
448 }
449 },
450 CUType::InterMV => {
451 let bits = if size == 8 { 2 } else { 3 };
452 pu_type = RV60_PU_TYPES[br.read(bits)? as usize];
453 CBHeader::read_mv_data(br, ftype, two_f_refs, size, pu_type, &mut mv)?;
454 },
455 _ => {
456 pu_type = PUType::Full;
457 let skip_mv_no = br.read_code(UintCodeType::LimitedUnary(3, 0))?;
458 mv[0].mvref = SKIP_MV_REF[skip_mv_no as usize];
459 },
460 };
461 let ttype;
462 if cu_type == CUType::Skip {
463 ttype = TransformType::None;
464 } else if size >= 32 {
465 ttype = TransformType::T16X16;
466 } else if size == 16 {
467 if (cu_type == CUType::Intra) || (pu_type == PUType::Full) {
468 ttype = TransformType::T16X16;
469 } else {
470 ttype = TransformType::T4X4;
471 }
472 } else {
473 if pu_type == PUType::Full {
474 ttype = TransformType::T8X8;
475 } else {
476 ttype = TransformType::T4X4;
477 }
478 }
479 Ok(Self {
480 cu_type, pu_type, ttype, imode, mv,
481 })
482 }
483 fn read_intra_mode(br: &mut BitReader) -> DecoderResult<IntraMode> {
484 if br.read_bool()? {
485 let idx = br.read_code(UintCodeType::Unary012)? as u8;
486 Ok(IntraMode::Index(idx))
487 } else {
488 let mode = br.read(5)? as u8;
489 Ok(IntraMode::Mode(mode))
490 }
491 }
492 fn read_mv_data(br: &mut BitReader, ftype: FrameType, two_f_refs: bool, size: usize, pu_type: PUType, mv: &mut [MVInfo; 4]) -> DecoderResult<()> {
493 let mv_count = pu_type.get_num_mvs();
494 for i in 0..mv_count {
495 mv[i] = CBHeader::read_mv_info(br, ftype, two_f_refs, size, pu_type)?;
496 }
497 Ok(())
498 }
499 fn read_mv_info(br: &mut BitReader, ftype: FrameType, two_f_refs: bool, size: usize, pu_type: PUType) -> DecoderResult<MVInfo> {
500 let mut f_mv = ZERO_MV;
501 let mut b_mv = ZERO_MV;
502 let mvref;
503 if ftype != FrameType::B {
504 if two_f_refs && br.read_bool()? {
505 mvref = MVRef::Ref1;
506 } else {
507 mvref = MVRef::Ref0;
508 }
509 f_mv = CBHeader::read_mv(br)?;
510 Ok(MVInfo { f_mv, b_mv: ZERO_MV, mvref })
511 } else {
512 if ((size <= 8) && ((size != 8) || (pu_type != PUType::Full))) || br.read_bool()? {
513 if !br.read_bool()? {
514 mvref = MVRef::Ref0;
515 f_mv = CBHeader::read_mv(br)?;
516 } else {
517 mvref = MVRef::BRef;
518 b_mv = CBHeader::read_mv(br)?;
519 }
520 } else {
521 mvref = MVRef::Ref0AndBRef;
522 f_mv = CBHeader::read_mv(br)?;
523 b_mv = CBHeader::read_mv(br)?;
524 }
525 Ok(MVInfo { f_mv, b_mv, mvref })
526 }
527 }
528 fn read_mv(br: &mut BitReader) -> DecoderResult<MV> {
529 let x = br.read_code_signed(IntCodeType::Gamma)? as i16;
530 let y = br.read_code_signed(IntCodeType::Gamma)? as i16;
531 Ok(MV { x, y })
532 }
533}
534
535#[derive(Clone,Copy,Default)]
536struct PUInfo {
537 cu_type: CUType,
538 ttype: TransformType,
539}
540
541impl PUInfo {
e07387c7 542 fn is_intra(self) -> bool { self.cu_type == CUType::Intra }
52aad9fe
KS
543}
544
545const RV60_CANDIDATE_INTRA_ANGLES: [u8; 6] = [ 0, 1, 10, 26, 18, 2 ];
546
547#[derive(Clone,Copy,Default)]
548struct BlockInfo {
549 mv: MVInfo,
550 imode: u8,
551}
552
553struct DeblockInfo {
554 left_str: Vec<u8>,
555 top_str: Vec<u8>,
556 stride: usize,
557}
558
559impl DeblockInfo {
560 fn new() -> Self {
561 Self { left_str: Vec::new(), top_str: Vec::new(), stride: 0 }
562 }
563 fn reinit(&mut self, w: usize, h: usize) {
564 self.left_str.clear();
565 self.top_str.clear();
566 self.stride = w >> 2;
567 let size = self.stride * (h >> 2);
568 self.left_str.resize(size, 0);
569 self.top_str.resize(size, 0);
570 }
571 fn set_strength(&mut self, xpos: usize, ypos: usize, size: usize, q: u8, strength: u8) {
572 let pos = self.get_pos(xpos, ypos);
573 let dsize = size >> 2;
574 let dval = (q << 2) | strength;
575 for x in 0..dsize {
576 self.top_str[pos + x] = dval;
577 }
578 for y in 0..dsize {
579 self.left_str[pos + y * self.stride] = dval;
580 }
581 }
582 fn get_pos(&self, xpos: usize, ypos: usize) -> usize {
583 (xpos >> 2) + (ypos >> 2) * self.stride
584 }
585 fn get_top_strength(&self, pos: usize) -> u8 {
586 self.top_str[pos] & 3
587 }
588 fn get_left_strength(&self, pos: usize) -> u8 {
589 self.left_str[pos] & 3
590 }
591 fn set_top_strength(&mut self, pos: usize, str: u8) {
592 self.top_str[pos] |= str;
593 }
594 fn set_left_strength(&mut self, pos: usize, str: u8) {
595 self.left_str[pos] |= str;
596 }
597}
598
599struct RealVideo60Decoder {
2422d969 600 info: NACodecInfoRef,
52aad9fe
KS
601 cbs: RV60Codebooks,
602 ipbs: IPBShuffler,
603 dsp: RV60DSP,
604 ipred: IntraPredContext,
54d2b09a 605 skip_mode: FrameSkipMode,
52aad9fe 606
3fc28ece 607 avg_buf: NAVideoBufferRef<u8>,
52aad9fe
KS
608
609 y_coeffs: [i16; 16 * 16],
610 u_coeffs: [i16; 8 * 8],
611 v_coeffs: [i16; 8 * 8],
612 qp: u8,
613 sel_qp: u8,
614
615 cu_splits: Vec<bool>,
616 coded_blk: [bool; 64],
617 dblk: DeblockInfo,
618
619 pu_info: Vec<PUInfo>,
620 pu_stride: usize,
621 pu_pos: usize,
622
623 blk_info: Vec<BlockInfo>,
624 blk_stride: usize,
625 blk_pos: usize,
626
627 xpos: usize,
628 ypos: usize,
d32c444b
KS
629
630 ts_scale: u64,
631 ref0_pts: u64,
632 ref1_pts: u64,
633 ref0_ts: u64,
634 ref1_ts: u64,
52aad9fe
KS
635}
636
637impl RealVideo60Decoder {
638 fn new() -> Self {
639 let tmp_vinfo = NAVideoInfo::new(64, 64, false, YUV420_FORMAT);
b70cc006 640 let vt = alloc_video_buffer(tmp_vinfo, 4).unwrap();
52aad9fe
KS
641 let vb = vt.get_vbuf();
642 let avg_buf = vb.unwrap();
643 RealVideo60Decoder{
2422d969 644 info: NACodecInfoRef::default(),
52aad9fe
KS
645 cbs: RV60Codebooks::init(),
646 ipbs: IPBShuffler::new(),
647 ipred: IntraPredContext::new(),
54d2b09a 648 skip_mode: FrameSkipMode::default(),
52aad9fe 649 dsp: RV60DSP::new(),
e07387c7 650 avg_buf,
52aad9fe
KS
651 y_coeffs: [0; 16 * 16],
652 u_coeffs: [0; 8 * 8],
653 v_coeffs: [0; 8 * 8],
654 qp: 0,
655 sel_qp: 0,
656 cu_splits: Vec::with_capacity(24),
657 coded_blk: [false; 64],
658 dblk: DeblockInfo::new(),
659 pu_info: Vec::new(),
660 pu_stride: 0,
661 pu_pos: 0,
662 blk_info: Vec::new(),
663 blk_stride: 0,
664 blk_pos: 0,
665 xpos: 0,
666 ypos: 0,
d32c444b
KS
667
668 ts_scale: 1,
669 ref0_pts: 0,
670 ref1_pts: 0,
671 ref0_ts: 0,
672 ref1_ts: 0,
52aad9fe
KS
673 }
674 }
cd830591 675 fn decode_cu_line(&mut self, buf: &mut NASimpleVideoFrame<u8>, hdr: &FrameHeader, src: &[u8], cu_y: usize) -> DecoderResult<()> {
fa90ccfb 676 let mut br = BitReader::new(src, BitReaderMode::BE);
52aad9fe
KS
677 let cu_w = hdr.get_width_cu();
678 let dqp = hdr.read_line_qp_offset(&mut br)?;
679 let qps = (hdr.qp as i8) + dqp;
6f263099 680 validate!((0..32).contains(&qps));
52aad9fe
KS
681 let qp = qps as u8;
682 self.qp = qp;
683 self.sel_qp = match hdr.osvquant {
684 0 => qp,
685 1 => {
686 if qp <= 25 {
687 qp + 5
688 } else {
689 qp
690 }
691 },
692 _ => {
693 if qp <= 18 {
694 qp + 10
695 } else if qp <= 25 {
696 qp + 5
697 } else {
698 qp
699 }
700 },
701 };
702
703 for cu_x in 0..cu_w {
704 self.cu_splits.clear();
705 self.coded_blk = [false; 64];
706 self.decode_cb_tree(buf, hdr, &mut br, cu_x << 6, cu_y << 6, 6)?;
707 if hdr.deblock {
708 self.cu_splits.reverse();
709 self.deblock_cb_tree(buf, hdr, cu_x << 6, cu_y << 6, 6);
710 }
711 }
712if br.left() >= 8 {
713println!(" left {} bits", br.left());
714}
715 Ok(())
716 }
b7c882c1 717 #[allow(clippy::cognitive_complexity)]
cd830591 718 fn decode_cb_tree(&mut self, buf: &mut NASimpleVideoFrame<u8>, hdr: &FrameHeader, br: &mut BitReader, xpos: usize, ypos: usize, log_size: u8) -> DecoderResult<()> {
52aad9fe
KS
719 if (xpos >= hdr.width) || (ypos >= hdr.height) { return Ok(()); }
720
721 let size = 1 << log_size;
722 let split = (xpos + size > hdr.width) || (ypos + size > hdr.height) || (size > 8 && br.read_bool()?);
723 self.cu_splits.push(split);
724 if split {
725 let hsize = size >> 1;
726 self.decode_cb_tree(buf, hdr, br, xpos, ypos, log_size - 1)?;
727 self.decode_cb_tree(buf, hdr, br, xpos + hsize, ypos, log_size - 1)?;
728 self.decode_cb_tree(buf, hdr, br, xpos, ypos + hsize, log_size - 1)?;
729 self.decode_cb_tree(buf, hdr, br, xpos + hsize, ypos + hsize, log_size - 1)?;
730 } else {
731 let cbh = CBHeader::read(br, hdr.ftype, hdr.two_f_refs, size)?;
732 self.pu_pos = (xpos >> 3) + (ypos >> 3) * self.pu_stride;
733 self.blk_pos = (xpos >> 2) + (ypos >> 2) * self.blk_stride;
734 self.xpos = xpos;
735 self.ypos = ypos;
736 self.reconstruct_info(hdr, &cbh, size)?;
737
738 let split_i4x4 = (cbh.cu_type == CUType::Intra) && (size == 8) && (cbh.pu_type == PUType::Quarters);
739 match cbh.cu_type {
740 CUType::Intra => {
741 let itype = self.blk_info[self.blk_pos].imode;
742 if !split_i4x4 {
cd830591 743 let dstride = buf.stride[0];
52aad9fe 744 let off = xpos + ypos * dstride;
cd830591 745 let dst = &mut buf.data;
52aad9fe
KS
746 self.populate_ipred(hdr, dst, 0, dstride, 0, 0, size, true);
747 self.ipred.pred_angle(dst, off, dstride, size, itype as usize, true);
748 }
749 for comp in 1..3 {
cd830591
KS
750 let dstride = buf.stride[comp];
751 let soff = buf.offset[comp];
52aad9fe 752 let off = soff + (xpos >> 1) + (ypos >> 1) * dstride;
6f263099 753 let dst = &mut buf.data;
52aad9fe 754 self.populate_ipred(hdr, dst, soff, dstride, 0, 0, size >> 1, false);
6f263099 755 self.ipred.pred_angle(dst, off, dstride, size >> 1, itype as usize, false);
52aad9fe
KS
756 }
757 },
758 _ => {
759 let mut mv_x = xpos >> 2;
760 let mut mv_y = ypos >> 2;
761 let mut mv_pos = mv_x + mv_y * self.blk_stride;
762 for part_no in 0..cbh.pu_type.get_num_mvs() {
763 let (mv_w, mv_h) = cbh.pu_type.get_mv_size(part_no, size);
764 let mv = self.blk_info[mv_pos].mv;
765 let bw = mv_w << 2;
766 let bh = mv_h << 2;
767 let bx = mv_x << 2;
768 let by = mv_y << 2;
769 match mv.mvref {
770 MVRef::Ref0 => {
771 if hdr.ftype != FrameType::B {
772 if let Some(ref prevbuf) = self.ipbs.get_lastref() {
773 self.dsp.do_mc(buf, prevbuf, bx, by, bw, bh, mv.f_mv, false);
774 }
775 } else {
776 if let Some(ref prevbuf) = self.ipbs.get_b_fwdref() {
777 self.dsp.do_mc(buf, prevbuf, bx, by, bw, bh, mv.f_mv, false);
778 }
779 }
780 },
781 MVRef::Ref1 => {
782 if let Some(ref prevbuf) = self.ipbs.get_nextref() {
783 self.dsp.do_mc(buf, prevbuf, bx, by, bw, bh, mv.f_mv, false);
784 }
785 },
786 MVRef::BRef => {
787 validate!(hdr.ftype == FrameType::B);
788 if let Some(ref prevbuf) = self.ipbs.get_b_bwdref() {
789 self.dsp.do_mc(buf, prevbuf, bx, by, bw, bh, mv.b_mv, false);
790 }
791 },
792 MVRef::Ref0AndBRef => {
793 validate!(hdr.ftype == FrameType::B);
794 if let (Some(ref prevbuf), Some(ref nextbuf)) = (self.ipbs.get_b_fwdref(), self.ipbs.get_b_bwdref()) {
795 self.dsp.do_mc(buf, prevbuf, bx, by, bw, bh, mv.f_mv, false);
cd830591
KS
796 {
797 let mut avg_buf = NASimpleVideoFrame::from_video_buf(&mut self.avg_buf).unwrap();
798 self.dsp.do_mc(&mut avg_buf, nextbuf, bx, by, bw, bh, mv.b_mv, true);
799 }
52aad9fe
KS
800 self.dsp.do_avg(buf, &self.avg_buf, bx, by, bw, bh);
801 }
802 },
803 _ => unreachable!(),
804 };
805 if cbh.pu_type == PUType::Quarters {
806 if part_no != 1 {
807 mv_pos += mv_w;
808 mv_x += mv_w;
809 } else {
810 mv_pos += mv_h * self.blk_stride - mv_w;
811 mv_x -= mv_w;
812 mv_y += mv_h;
813 }
814 } else if cbh.pu_type.has_hor_split() {
815 mv_pos += mv_h * self.blk_stride;
816 mv_y += mv_h;
817 } else if cbh.pu_type.has_ver_split() {
818 mv_pos += mv_w;
819 mv_x += mv_w;
820 }
821 }
822 },
823 };
824 if cbh.ttype != TransformType::None {
825 self.y_coeffs = [0; 16 * 16];
826 self.u_coeffs = [0; 8 * 8];
827 self.v_coeffs = [0; 8 * 8];
828 }
829 let is_intra = cbh.cu_type == CUType::Intra;
830 let cb_pos = ((xpos & 63) >> 3) + ((ypos & 63) >> 3) * 8;
831 match cbh.ttype {
832 TransformType::T4X4 => {
833 let subset = if is_intra { 0 } else { 2 };
834 if size == 16 {
835 let cbp16;
836 if br.read_bool()? {
837 cbp16 = rv6_decode_cbp16(br, &self.cbs, subset, self.sel_qp)?;
838 } else {
839 cbp16 = 0;
840 }
841 if cbp16 != 0 {
842 self.coded_blk[cb_pos + 0] = true;
843 self.coded_blk[cb_pos + 1] = true;
844 self.coded_blk[cb_pos + 8] = true;
845 self.coded_blk[cb_pos + 9] = true;
846 rv6_decode_cu_4x4in16x16(br, &self.cbs, is_intra, self.qp, self.sel_qp, &mut self.y_coeffs, &mut self.u_coeffs, &mut self.v_coeffs, cbp16)?;
847 for y in 0..4 {
848 for x in 0..4 {
849 let i = x + y * 4;
850 if ((cbp16 >> i) & 1) != 0 {
851 self.dsp.transform4x4(&mut self.y_coeffs[i * 16..][..16]);
cd830591 852 let dstride = buf.stride[0];
52aad9fe 853 let off = xpos + x * 4 + (ypos + y * 4) * dstride;
6f263099
KS
854 let dst = &mut buf.data;
855 self.dsp.add_block(dst, off, dstride, &self.y_coeffs[i*16..][..16], 4);
52aad9fe
KS
856 }
857 }
858 }
859 for y in 0..2 {
860 for x in 0..2 {
861 let i = x + y * 2;
862 let xoff = (xpos >> 1) + x * 4;
863 let yoff = (ypos >> 1) + y * 4;
864 if ((cbp16 >> (16 + i)) & 1) != 0 {
865 self.dsp.transform4x4(&mut self.u_coeffs[i * 16..][..16]);
cd830591
KS
866 let dstride = buf.stride[1];
867 let off = buf.offset[1] + xoff + yoff * dstride;
6f263099
KS
868 let dst = &mut buf.data;
869 self.dsp.add_block(dst, off, dstride, &self.u_coeffs[i * 16..][..16], 4);
52aad9fe
KS
870 }
871 if ((cbp16 >> (20 + i)) & 1) != 0 {
872 self.dsp.transform4x4(&mut self.v_coeffs[i * 16..][..16]);
cd830591
KS
873 let dstride = buf.stride[2];
874 let off = buf.offset[2] + xoff + yoff * dstride;
6f263099
KS
875 let dst = &mut buf.data;
876 self.dsp.add_block(dst, off, dstride, &self.v_coeffs[i * 16..][..16], 4);
52aad9fe
KS
877 }
878 }
879 }
880 }
881 } else {
882 let cbp8 = rv6_decode_cbp8(br, &self.cbs, subset, self.sel_qp)?;
883 if cbp8 != 0 {
884 self.coded_blk[cb_pos] = true;
885 rv6_decode_cu_8x8(br, &self.cbs, is_intra, self.qp, self.sel_qp, &mut self.y_coeffs, &mut self.u_coeffs, &mut self.v_coeffs, cbp8, true)?;
886 }
887 for i in 0..4 {
888 let xoff = (i & 1) * 4;
889 let yoff = (i & 2) * 2;
890 if split_i4x4 {
cd830591 891 let dstride = buf.stride[0];
52aad9fe 892 let off = xpos + xoff + (ypos + yoff) * dstride;
6f263099 893 let dst = &mut buf.data;
52aad9fe
KS
894 self.populate_ipred(hdr, dst, 0, dstride, xoff, yoff, 4, true);
895 let itype = self.blk_info[self.blk_pos + (i & 1) + (i >> 1) * self.blk_stride].imode;
6f263099 896 self.ipred.pred_angle(dst, off, dstride, 4, itype as usize, false);
52aad9fe
KS
897 }
898 if ((cbp8 >> i) & 1) != 0 {
899 let blk = &mut self.y_coeffs[i * 16..][..16];
900 self.dsp.transform4x4(blk);
cd830591
KS
901 let dstride = buf.stride[0];
902 let soff = buf.offset[0];
52aad9fe 903 let off = soff + xpos + xoff + (ypos + yoff) * dstride;
6f263099 904 self.dsp.add_block(buf.data, off, dstride, blk, 4);
52aad9fe
KS
905 }
906 }
907 if ((cbp8 >> 4) & 1) != 0 {
908 self.dsp.transform4x4(&mut self.u_coeffs);
cd830591
KS
909 let dstride = buf.stride[1];
910 let soff = buf.offset[1];
52aad9fe 911 let off = soff + (xpos >> 1) + (ypos >> 1) * dstride;
6f263099 912 self.dsp.add_block(buf.data, off, dstride, &self.u_coeffs, 4);
52aad9fe
KS
913 }
914 if ((cbp8 >> 5) & 1) != 0 {
915 self.dsp.transform4x4(&mut self.v_coeffs);
cd830591
KS
916 let dstride = buf.stride[2];
917 let soff = buf.offset[2];
52aad9fe 918 let off = soff + (xpos >> 1) + (ypos >> 1) * dstride;
6f263099 919 self.dsp.add_block(buf.data, off, dstride, &self.v_coeffs, 4);
52aad9fe
KS
920 }
921 }
922 },
923 TransformType::T8X8 => {
924 let subset = if is_intra { 1 } else { 3 };
925 let cbp8 = rv6_decode_cbp8(br, &self.cbs, subset, self.sel_qp)?;
926 if cbp8 != 0 {
927 self.coded_blk[cb_pos] = true;
928 rv6_decode_cu_8x8(br, &self.cbs, is_intra, self.qp, self.sel_qp, &mut self.y_coeffs, &mut self.u_coeffs, &mut self.v_coeffs, cbp8, false)?;
929 if (cbp8 & 0xF) != 0 {
930 self.dsp.transform8x8(&mut self.y_coeffs);
cd830591 931 let dstride = buf.stride[0];
52aad9fe 932 let off = xpos + ypos * dstride;
6f263099 933 self.dsp.add_block(buf.data, off, dstride, &self.y_coeffs, 8);
52aad9fe
KS
934 }
935 if ((cbp8 >> 4) & 1) != 0 {
936 self.dsp.transform4x4(&mut self.u_coeffs);
cd830591
KS
937 let dstride = buf.stride[1];
938 let soff = buf.offset[1];
52aad9fe 939 let off = soff + (xpos >> 1) + (ypos >> 1) * dstride;
6f263099 940 self.dsp.add_block(buf.data, off, dstride, &self.u_coeffs, 4);
52aad9fe
KS
941 }
942 if ((cbp8 >> 5) & 1) != 0 {
943 self.dsp.transform4x4(&mut self.v_coeffs);
cd830591
KS
944 let dstride = buf.stride[2];
945 let soff = buf.offset[2];
52aad9fe 946 let off = soff + (xpos >> 1) + (ypos >> 1) * dstride;
6f263099 947 self.dsp.add_block(buf.data, off, dstride, &self.v_coeffs, 4);
52aad9fe
KS
948 }
949 }
950 },
951 TransformType::T16X16 => {
952 let subset = if is_intra { 1 } else { 3 };
953 let num_clusters = size >> 4;
954 let cl_cbp = br.read((num_clusters * num_clusters) as u8)?;
955 for y in 0..num_clusters {
956 for x in 0..num_clusters {
957 if ((cl_cbp >> (x + y * num_clusters)) & 1) == 0 { continue; }
958 self.coded_blk[cb_pos + x * 2 + y * 2 * 8 + 0] = true;
959 self.coded_blk[cb_pos + x * 2 + y * 2 * 8 + 1] = true;
960 self.coded_blk[cb_pos + x * 2 + y * 2 * 8 + 8] = true;
961 self.coded_blk[cb_pos + x * 2 + y * 2 * 8 + 9] = true;
962 let super_cbp = rv6_decode_cbp16(br, &self.cbs, subset, self.sel_qp)?;
963 if super_cbp != 0 {
964 self.y_coeffs = [0; 16 * 16];
965 self.u_coeffs = [0; 8 * 8];
966 self.v_coeffs = [0; 8 * 8];
967 rv6_decode_cu_16x16(br, &self.cbs, is_intra, self.qp, self.sel_qp, &mut self.y_coeffs, &mut self.u_coeffs, &mut self.v_coeffs, super_cbp)?;
968 if (super_cbp & 0xFFFF) != 0 {
969 self.dsp.transform16x16(&mut self.y_coeffs);
cd830591 970 let dstride = buf.stride[0];
52aad9fe 971 let off = xpos + x * 16 + (ypos + y * 16) * dstride;
6f263099 972 self.dsp.add_block(buf.data, off, dstride, &self.y_coeffs, 16);
52aad9fe
KS
973 }
974 if ((super_cbp >> 16) & 0xF) != 0 {
975 self.dsp.transform8x8(&mut self.u_coeffs);
cd830591
KS
976 let dstride = buf.stride[1];
977 let soff = buf.offset[1];
52aad9fe 978 let off = soff + (xpos >> 1) + x * 8 + ((ypos >> 1) + y * 8) * dstride;
6f263099 979 self.dsp.add_block(buf.data, off, dstride, &self.u_coeffs, 8);
52aad9fe
KS
980 }
981 if ((super_cbp >> 20) & 0xF) != 0 {
982 self.dsp.transform8x8(&mut self.v_coeffs);
cd830591
KS
983 let dstride = buf.stride[2];
984 let soff = buf.offset[2];
52aad9fe 985 let off = soff + (xpos >> 1) + x * 8 + ((ypos >> 1) + y * 8) * dstride;
6f263099 986 self.dsp.add_block(buf.data, off, dstride, &self.v_coeffs, 8);
52aad9fe
KS
987 }
988 }
989 }
990 }
991 },
992 _ => {},
993 };
994 }
995 Ok(())
996 }
997 fn reconstruct_info(&mut self, hdr: &FrameHeader, cbh: &CBHeader, size: usize) -> DecoderResult<()>{
998 let mut pui = PUInfo::default();
999 let pu_size = size >> 3;
1000 pui.cu_type = cbh.cu_type;
1001 pui.ttype = cbh.ttype;
1002 if (cbh.cu_type == CUType::Intra) && (cbh.pu_type == PUType::Quarters) { // very special case
1003 self.pu_info[self.pu_pos] = pui;
1004 for y in 0..2 {
1005 for x in 0..2 {
1006 let imode = self.reconstruct_intra(hdr, cbh, 4, x + y * 2);
1007 validate!(imode <= MAX_IMODE);
1008 self.blk_info[self.blk_pos + x + y * self.blk_stride].imode = imode;
1009 self.blk_info[self.blk_pos + x + y * self.blk_stride].mv = MVInfo::default();
1010 }
1011 }
1012 return Ok(());
1013 }
1014 match cbh.cu_type {
1015 CUType::Intra => {
1016 self.pu_info[self.pu_pos] = pui;
1017 let imode = self.reconstruct_intra(hdr, cbh, size, 0);
1018 validate!(imode <= MAX_IMODE);
1019 for y in 0..(size >> 2) {
1020 for x in 0..(size >> 2) {
1021 self.blk_info[self.blk_pos + x + y * self.blk_stride].imode = imode;
1022 }
1023 }
1024 },
1025 CUType::InterMV => {
1026 let mut mv_x = self.xpos >> 2;
1027 let mut mv_y = self.ypos >> 2;
1028 let mut mv_pos = self.blk_pos;
1029 let pu_type = cbh.pu_type;
1030 for part_no in 0..pu_type.get_num_mvs() {
1031 let (mv_w, mv_h) = pu_type.get_mv_size(part_no, size);
1032 let mv = self.predict_mv(hdr, mv_x, mv_y, mv_w, &cbh.mv[part_no]);
1033 for y in 0..mv_h {
1034 for x in 0..mv_w {
1035 self.blk_info[mv_pos + x + y * self.blk_stride].mv = mv;
1036 }
1037 }
1038 if pu_type == PUType::Quarters {
1039 if part_no != 1 {
1040 mv_pos += mv_w;
1041 mv_x += mv_w;
1042 } else {
1043 mv_pos += mv_h * self.blk_stride - mv_w;
1044 mv_x -= mv_w;
1045 mv_y += mv_h;
1046 }
1047 } else if pu_type.has_hor_split() {
1048 mv_pos += mv_h * self.blk_stride;
1049 mv_y += mv_h;
1050 } else if pu_type.has_ver_split() {
1051 mv_pos += mv_w;
1052 mv_x += mv_w;
1053 }
1054 }
1055 },
1056 _ => {
1057 let skip_idx = cbh.mv[0].mvref.get_skip_mv_num();
1058 let mut skip_cand: UniqueList<MVInfo> = UniqueList::new(4);
1059 self.fill_skip_cand(hdr, &mut skip_cand, size);
1060 let mv = skip_cand.list[skip_idx];
1061
1062 let mv_size = size >> 2;
1063 for y in 0..mv_size {
1064 for x in 0..mv_size {
1065 self.blk_info[self.blk_pos + x + y * self.blk_stride].mv = mv;
1066 }
1067 }
1068 },
1069 };
1070 for y in 0..pu_size {
1071 for x in 0..pu_size {
1072 self.pu_info[self.pu_pos + x + y * self.pu_stride] = pui;
1073 }
1074 }
1075 Ok(())
1076 }
1077 fn reconstruct_intra(&self, hdr: &FrameHeader, cbh: &CBHeader, size: usize, sub: usize) -> u8 {
1078 match cbh.imode[0] {
1079 IntraMode::DC64 => { return 1; },
1080 IntraMode::Plane64 => { return 0; },
1081 _ => {},
1082 };
1083 // form list of predictors
1084 let blk_pos = self.blk_pos + (sub & 1) + (sub >> 1) * self.blk_stride;
1085 let mut ipm_cand: UniqueList<u8> = UniqueList::new(3);
1086 if hdr.has_top_block(self.xpos, self.ypos, (sub & 1) * 4, 0, size) {
1087 let pu = &self.pu_info[self.pu_pos - self.pu_stride];
1088 if pu.is_intra() {
1089 ipm_cand.add(self.blk_info[self.blk_pos + (sub & 1) - self.blk_stride].imode);
1090 }
1091 }
1092 if hdr.has_left_block(self.xpos, self.ypos, 0, (sub & 2) * 2, size) {
1093 let pu = &self.pu_info[self.pu_pos - 1];
1094 if pu.is_intra() {
1095 ipm_cand.add(self.blk_info[blk_pos - 1 - (sub & 1)].imode);
1096 }
1097 }
1098 let tl_x = if (sub & 2) == 0 { self.xpos + (sub & 1) * 4 } else { self.xpos };
1099 let tl_y = self.ypos + (sub & 2) * 4;
1100 if (tl_x > 0) && (tl_y > 0) {
1101 let pu = match sub {
1102 0 => &self.pu_info[self.pu_pos - self.pu_stride - 1],
1103 1 => &self.pu_info[self.pu_pos - self.pu_stride],
1104 2 => &self.pu_info[self.pu_pos - 1],
1105 _ => &self.pu_info[self.pu_pos - 1],
1106 };
1107 if pu.is_intra() {
1108 if sub != 3 {
1109 ipm_cand.add(self.blk_info[blk_pos - self.blk_stride - 1].imode);
1110 } else {
1111 ipm_cand.add(self.blk_info[blk_pos - self.blk_stride - 2].imode);
1112 }
1113 }
1114 }
61d3e294 1115 for el in RV60_CANDIDATE_INTRA_ANGLES.iter() {
52aad9fe
KS
1116 ipm_cand.add(*el);
1117 }
1118 // actually decode prediction mode
1119 match cbh.imode[sub] {
1120 IntraMode::Index(idx) => {
1121 ipm_cand.list[idx as usize]
1122 },
1123 IntraMode::Mode(mode) => {
1124 let mut imode = mode;
1125 let mut ipm_cs: [u8; 3] = [ipm_cand.list[0], ipm_cand.list[1], ipm_cand.list[2]];
1126 ipm_cs.sort();
61d3e294 1127 for ic in ipm_cs.iter() {
52aad9fe
KS
1128 if imode >= *ic {
1129 imode += 1;
1130 }
1131 }
1132 imode
1133 },
1134 _ => unreachable!(),
1135 }
1136 }
1137 fn populate_ipred(&mut self, hdr: &FrameHeader, src: &[u8], soff: usize, stride: usize, xoff: usize, yoff: usize, size: usize, is_luma: bool) {
1138 let src_off = if is_luma {
1139 soff + self.xpos + xoff + (self.ypos + yoff) * stride
1140 } else {
1141 soff + (self.xpos >> 1) + (self.ypos >> 1) * stride
1142 };
1143 self.ipred = IntraPredContext::new();
1144 if (self.ypos + yoff) > 0 {
1145 self.ipred.has_t = true;
1146 for x in 0..size {
1147 self.ipred.t[x + 1] = src[src_off - stride + x];
1148 }
1149 if (is_luma && hdr.has_top_right_block(self.xpos, self.ypos, xoff, yoff, size)) ||
1150 (!is_luma && hdr.has_top_right_block(self.xpos, self.ypos, 0, 0, size << 1)) {
1151 self.ipred.has_tr = true;
1152 for x in size..size*2 {
1153 self.ipred.t[x + 1] = src[src_off - stride + x];
1154 }
1155 } else {
1156 for i in 0..size {
1157 self.ipred.t[size + i + 1] = self.ipred.t[size];
1158 }
1159 }
1160 if (self.xpos + xoff) > 0 {
1161 self.ipred.t[0] = src[src_off - stride - 1];
1162 }
1163 }
1164 if (self.xpos + xoff) > 0 {
1165 self.ipred.has_l = true;
1166 for y in 0..size {
1167 self.ipred.l[y + 1] = src[src_off - 1 + y * stride];
1168 }
1169 if (is_luma && hdr.has_left_down_block(self.xpos, self.ypos, xoff, yoff, size)) ||
1170 (!is_luma && hdr.has_left_down_block(self.xpos, self.ypos, 0, 0, size << 1)) {
1171 self.ipred.has_ld = true;
1172 for y in size..size*2 {
1173 self.ipred.l[y + 1] = src[src_off - 1 + y * stride];
1174 }
1175 } else {
1176 for i in 0..size {
1177 self.ipred.l[size + i + 1] = self.ipred.l[size];
1178 }
1179 }
1180 if (self.ypos + yoff) > 0 {
1181 self.ipred.l[0] = src[src_off - stride - 1];
1182 }
1183 }
1184 }
1185 fn predict_mv(&self, hdr: &FrameHeader, mv_x: usize, mv_y: usize, mv_w: usize, mvi: &MVInfo) -> MVInfo {
1186 let mv_pos = mv_x + mv_y * self.blk_stride;
1187 let f_mv: MV;
1188 let b_mv: MV;
1189 if mvi.mvref.is_fwd() {
1190 let mut mv_cand: [MV; 3] = [ZERO_MV; 3];
1191 let mut mv_cand_size: usize = 0;
1192 if mv_x > 0 {
1193 let ref_mv = &self.blk_info[mv_pos - 1].mv;
1194 if ref_mv.matches_fwd(mvi.mvref) {
1195 mv_cand[mv_cand_size] = ref_mv.f_mv;
1196 mv_cand_size += 1;
1197 }
1198 }
1199 if mv_y > 0 {
1200 let ref_mv = &self.blk_info[mv_pos - self.blk_stride].mv;
1201 if ref_mv.matches_fwd(mvi.mvref) {
1202 mv_cand[mv_cand_size] = ref_mv.f_mv;
1203 mv_cand_size += 1;
1204 }
1205 }
1206 if hdr.has_top_block(mv_x << 2, mv_y << 2, mv_w << 2, 0, 4) {
1207 let ref_mv = &self.blk_info[mv_pos - self.blk_stride + mv_w].mv;
1208 if ref_mv.matches_fwd(mvi.mvref) {
1209 mv_cand[mv_cand_size] = ref_mv.f_mv;
1210 mv_cand_size += 1;
1211 }
1212 }
1213 f_mv = match mv_cand_size {
1214 1 | 2 => {
1215 let x = mv_cand[0].x + mv_cand[1].x + mv_cand[2].x;
1216 let y = mv_cand[0].y + mv_cand[1].y + mv_cand[2].y;
1217 if mv_cand_size == 1 {
1218 MV { x, y }
1219 } else {
1220 MV { x: x >> 1, y: y >> 1 }
1221 }
1222 },
1223 3 => MV::pred(mv_cand[0], mv_cand[1], mv_cand[2]),
1224 _ => ZERO_MV,
1225 };
1226 } else {
1227 f_mv = ZERO_MV;
1228 }
1229 if mvi.mvref.is_bwd() {
1230 let mut mv_cand: [MV; 3] = [ZERO_MV; 3];
1231 let mut mv_cand_size: usize = 0;
1232 if mv_x > 0 {
1233 let ref_mv = &self.blk_info[mv_pos - 1].mv;
1234 if ref_mv.matches_bwd(mvi.mvref) {
1235 mv_cand[mv_cand_size] = ref_mv.b_mv;
1236 mv_cand_size += 1;
1237 }
1238 }
1239 if mv_y > 0 {
1240 let ref_mv = &self.blk_info[mv_pos - self.blk_stride].mv;
1241 if ref_mv.matches_bwd(mvi.mvref) {
1242 mv_cand[mv_cand_size] = ref_mv.b_mv;
1243 mv_cand_size += 1;
1244 }
1245 }
1246 if hdr.has_top_block(mv_x << 2, mv_y << 2, mv_w << 2, 0, 4) {
1247 let ref_mv = &self.blk_info[mv_pos - self.blk_stride + mv_w].mv;
1248 if ref_mv.matches_bwd(mvi.mvref) {
1249 mv_cand[mv_cand_size] = ref_mv.b_mv;
1250 mv_cand_size += 1;
1251 }
1252 }
1253 b_mv = match mv_cand_size {
1254 1 | 2 => {
1255 let x = mv_cand[0].x + mv_cand[1].x + mv_cand[2].x;
1256 let y = mv_cand[0].y + mv_cand[1].y + mv_cand[2].y;
1257 if mv_cand_size == 1 {
1258 MV { x, y }
1259 } else {
1260 MV { x: x >> 1, y: y >> 1 }
1261 }
1262 },
1263 3 => MV::pred(mv_cand[0], mv_cand[1], mv_cand[2]),
1264 _ => ZERO_MV,
1265 };
1266 } else {
1267 b_mv = ZERO_MV;
1268 }
d24468d9 1269
52aad9fe
KS
1270 MVInfo { f_mv: mvi.f_mv + f_mv, b_mv: mvi.b_mv + b_mv, mvref: mvi.mvref }
1271 }
1272 fn fill_skip_cand(&mut self, hdr: &FrameHeader, skip_cand: &mut UniqueList<MVInfo>, size: usize) {
1273 let mv_size = size >> 2;
1274
1275 if self.xpos > 0 {
1276 let mv = &self.blk_info[self.blk_pos - 1].mv;
1277 if mv.is_some() {
1278 skip_cand.add(*mv);
1279 }
1280 }
1281 if self.ypos > 0 {
1282 let mv = &self.blk_info[self.blk_pos - self.blk_stride].mv;
1283 if mv.is_some() {
1284 skip_cand.add(*mv);
1285 }
1286 }
1287 if hdr.has_top_right_block(self.xpos, self.ypos, 0, 0, size) {
1288 let mv = &self.blk_info[self.blk_pos - self.blk_stride + mv_size].mv;
1289 if mv.is_some() {
1290 skip_cand.add(*mv);
1291 }
1292 }
1293 if hdr.has_left_down_block(self.xpos, self.ypos, 0, 0, size) {
1294 let mv = &self.blk_info[self.blk_pos + self.blk_stride * mv_size - 1].mv;
1295 if mv.is_some() {
1296 skip_cand.add(*mv);
1297 }
1298 }
1299 if hdr.has_left_block(self.xpos, self.ypos, 0, 0, size) {
1300 let mv = &self.blk_info[self.blk_pos + self.blk_stride * (mv_size - 1) - 1].mv;
1301 if mv.is_some() {
1302 skip_cand.add(*mv);
1303 }
1304 }
1305 if hdr.has_top_block(self.xpos, self.ypos, 0, 0, size) {
1306 let mv = &self.blk_info[self.blk_pos - self.blk_stride + mv_size - 1].mv;
1307 if mv.is_some() {
1308 skip_cand.add(*mv);
1309 }
1310 }
1311 if (self.xpos > 0) && (self.ypos > 0) {
1312 let mv = &self.blk_info[self.blk_pos - self.blk_stride - 1].mv;
1313 if mv.is_some() {
1314 skip_cand.add(*mv);
1315 }
1316 }
1317 for i in skip_cand.fill..4 {
1318 skip_cand.list[i] = MVInfo { f_mv: ZERO_MV, b_mv: ZERO_MV, mvref: MVRef::Ref0 };
1319 }
1320 }
cd830591 1321 fn deblock_cb_tree(&mut self, buf: &mut NASimpleVideoFrame<u8>, hdr: &FrameHeader, xpos: usize, ypos: usize, log_size: u8) {
52aad9fe
KS
1322 if (xpos >= hdr.width) || (ypos >= hdr.height) { return; }
1323 let split = (log_size > 3) && self.cu_splits.pop().unwrap();
1324 if split {
1325 let hsize = 1 << (log_size - 1);
1326 self.deblock_cb_tree(buf, hdr, xpos, ypos, log_size - 1);
1327 self.deblock_cb_tree(buf, hdr, xpos + hsize, ypos, log_size - 1);
1328 self.deblock_cb_tree(buf, hdr, xpos, ypos + hsize, log_size - 1);
1329 self.deblock_cb_tree(buf, hdr, xpos + hsize, ypos + hsize, log_size - 1);
1330 } else {
1331 let pu_pos = (xpos >> 3) + (ypos >> 3) * self.pu_stride;
1332 let cu_type = self.pu_info[pu_pos].cu_type;
1333 let tsize = if self.pu_info[pu_pos].ttype == TransformType::T16X16 { 4 } else { 3 };
1334 let ntiles = 1 << (log_size - tsize);
1335 let dparams = RV60DeblockParams {
1336 deblock_chroma: hdr.deblock_chroma,
1337 width: hdr.width,
1338 height: hdr.height,
1339 dblkstride: self.dblk.stride,
1340 };
1341 for ty in 0..ntiles {
1342 for tx in 0..ntiles {
1343 let x = xpos + (tx << tsize);
1344 let y = ypos + (ty << tsize);
1345 let cb_pos = ((x & 63) >> 3) + ((y & 63) >> 3) * 8;
1346 if cu_type == CUType::Intra {
1347 self.dblk.set_strength(x, y, 1 << tsize, self.qp, 2);
1348 } else if (cu_type != CUType::Skip) && self.coded_blk[cb_pos] {
1349 self.dblk.set_strength(x, y, 1 << tsize, self.qp, 1);
1350 } else {
1351 self.dblk.set_strength(x, y, 1 << tsize, self.qp, 0);
1352 self.derive_deblock_strength(x, y, 1 << (tsize - 2));
1353 }
1354 self.dsp.do_deblock(&dparams, buf, x, y, 1 << tsize,
1355 self.dblk.top_str.as_slice(),
1356 self.dblk.left_str.as_slice(),
1357 self.dblk.get_pos(x, y));
1358 }
1359 }
1360 }
1361 }
1362 fn derive_deblock_strength(&mut self, xpos: usize, ypos: usize, size4: usize) {
1363 let blk_pos = (xpos >> 2) + (ypos >> 2) * self.blk_stride;
1364 let mut dblk_pos = self.dblk.get_pos(xpos, ypos);
1365 if ypos > 0 {
1366 let top_blk_pos = blk_pos - self.blk_stride;
1367 for i in 0..size4 {
1368 if self.dblk.get_top_strength(dblk_pos + i) == 0 {
1369 if self.blk_info[blk_pos + i].mv.is_deblock_cand(&self.blk_info[top_blk_pos + i].mv) {
1370 self.dblk.set_top_strength(dblk_pos + i, 1);
1371 }
1372 }
1373 }
1374 }
1375 if xpos > 0 {
1376 for i in 0..size4 {
1377 if self.dblk.get_left_strength(dblk_pos) == 0 {
1378 if self.blk_info[blk_pos + i].mv.is_deblock_cand(&self.blk_info[blk_pos + i - 1].mv) {
1379 self.dblk.set_left_strength(dblk_pos, 1);
1380 }
1381 }
1382 dblk_pos += self.dblk.stride;
1383 }
1384 }
1385 }
1386}
1387
1388impl NADecoder for RealVideo60Decoder {
3c69ce1b
KS
1389 fn init(&mut self, supp: &mut NADecoderSupport, info: NACodecInfoRef) -> DecoderResult<()> {
1390 if let NACodecTypeInfo::Video(vinfo) = info.get_properties() {
52aad9fe
KS
1391 let fmt = YUV420_FORMAT;
1392 let myinfo = NACodecTypeInfo::Video(NAVideoInfo::new(0, 0, false, fmt));
2422d969 1393 self.info = NACodecInfo::new_ref(info.get_name(), myinfo, info.get_extradata()).into_ref();
52aad9fe
KS
1394
1395 let edata = info.get_extradata().unwrap();
1396 let src: &[u8] = &edata;
1397
1398 if src.len() < 8 { return Err(DecoderError::InvalidData); }
1399 let mut mr = MemoryReader::new_read(src);
1400 let mut br = ByteReader::new(&mut mr);
1401 let _flags = br.read_u32be()?;
1402 let version = br.read_u32be()?;
1403 let _unk = br.read_u16be()?;
1404 validate!((version >> 28) == 4);
1405 // then width and height again as 16be
1406
1407 //self.bd.width = vinfo.get_width();
1408 //self.bd.height = vinfo.get_height();
1409 //self.frmmgr.clear();
3c69ce1b
KS
1410
1411 supp.pool_u8.set_dec_bufs(3);
1412 supp.pool_u8.prealloc_video(NAVideoInfo::new(vinfo.get_width(), vinfo.get_height(), false, fmt), 6)?;
1413
52aad9fe
KS
1414 Ok(())
1415 } else {
1416println!("???");
1417 Err(DecoderError::InvalidData)
1418 }
1419 }
3c69ce1b 1420 fn decode(&mut self, supp: &mut NADecoderSupport, pkt: &NAPacket) -> DecoderResult<NAFrameRef> {
52aad9fe
KS
1421 let src = pkt.get_buffer();
1422
1423 validate!(src.len() > 9);
1424 let hsize = (src[0] as usize) * 8 + 9;
fa90ccfb 1425 let mut br = BitReader::new(&src[hsize..], BitReaderMode::BE);
52aad9fe 1426 let hdr = FrameHeader::read(&mut br)?;
54d2b09a
KS
1427 match self.skip_mode {
1428 FrameSkipMode::None => {},
1429 FrameSkipMode::KeyframesOnly => {
1430 if hdr.ftype == FrameType::B {
1431 let mut frm = NAFrame::new_from_pkt(pkt, self.info.clone(), NABufferType::None);
1432 frm.set_frame_type(FrameType::Skip);
1433 return Ok(frm.into_ref());
1434 }
1435 },
1436 FrameSkipMode::IntraOnly => {
1437 if hdr.ftype != FrameType::I {
1438 let mut frm = NAFrame::new_from_pkt(pkt, self.info.clone(), NABufferType::None);
1439 frm.set_frame_type(FrameType::Skip);
1440 return Ok(frm.into_ref());
1441 }
1442 },
1443 };
1444
52aad9fe
KS
1445 let mut slices: Vec<usize> = Vec::new();
1446 hdr.parse_slice_sizes(&mut br, &mut slices)?;
6e24ec0b
KS
1447 match hdr.ftype {
1448 FrameType::P => {
1449 if self.ipbs.get_lastref().is_none() {
1450 return Err(DecoderError::MissingReference);
1451 }
1452 },
1453 FrameType::B => {
1454 if self.ipbs.get_lastref().is_none() {
1455 return Err(DecoderError::MissingReference);
1456 }
1457 if self.ipbs.get_nextref().is_none() {
1458 return Err(DecoderError::MissingReference);
1459 }
1460 },
1461 _ => {},
1462 };
52aad9fe
KS
1463
1464 let tmp_vinfo = NAVideoInfo::new(hdr.width, hdr.height, false, YUV420_FORMAT);
3c69ce1b
KS
1465 let ret = supp.pool_u8.get_free();
1466 if ret.is_none() {
1467 return Err(DecoderError::AllocError);
1468 }
1469 let mut buf = ret.unwrap();
1470 if buf.get_info() != tmp_vinfo {
1471 self.ipbs.clear();
1472 supp.pool_u8.reset();
1473 supp.pool_u8.prealloc_video(tmp_vinfo, 6)?;
1474 let ret = supp.pool_u8.get_free();
1475 if ret.is_none() {
1476 return Err(DecoderError::AllocError);
1477 }
1478 buf = ret.unwrap();
1479 }
52aad9fe
KS
1480
1481 let cu_w = hdr.get_width_cu();
1482 let cu_h = hdr.get_height_cu();
1483 self.pu_stride = cu_w << 3;
1484 self.pu_info.resize(self.pu_stride * (cu_h << 3), PUInfo::default());
1485 self.blk_stride = cu_w << 4;
37952415 1486 self.blk_info.clear();
52aad9fe
KS
1487 self.blk_info.resize(self.blk_stride * (cu_h << 4), BlockInfo::default());
1488 if hdr.deblock {
1489 self.dblk.reinit(hdr.width, hdr.height);
1490 }
1491 let mut off = hsize + ((br.tell() >> 3) as usize);
cd830591 1492 let mut dframe = NASimpleVideoFrame::from_video_buf(&mut buf).unwrap();
52aad9fe 1493 for (cu_y, size) in slices.into_iter().enumerate() {
cd830591 1494 self.decode_cu_line(&mut dframe, &hdr, &src[off..][..size], cu_y)?;
52aad9fe
KS
1495 off += size;
1496 }
1497 if (hdr.ftype == FrameType::I) || (hdr.ftype == FrameType::P) {
3c69ce1b 1498 self.ipbs.add_frame(buf.clone());
52aad9fe
KS
1499 }
1500
d32c444b
KS
1501 if hdr.ftype != FrameType::B {
1502 self.ref0_pts = self.ref1_pts;
1503 self.ref1_pts = pkt.get_pts().unwrap_or(0);
1504 self.ref0_ts = self.ref1_ts;
1505 self.ref1_ts = hdr.ts as u64;
1506 if (self.ref1_pts > self.ref0_pts) && (self.ref1_ts > self.ref0_ts) {
1507 self.ts_scale = (self.ref1_pts - self.ref0_pts) / (self.ref1_ts - self.ref0_ts);
1508 }
1509 }
3c69ce1b 1510 let mut frm = NAFrame::new_from_pkt(pkt, self.info.clone(), NABufferType::Video(buf));
52aad9fe 1511 frm.set_keyframe(hdr.ftype == FrameType::I);
d32c444b
KS
1512 if hdr.ftype == FrameType::B {
1513 let pts = self.ref0_pts + ((hdr.ts as u64) - self.ref0_ts) * self.ts_scale;
1514 frm.set_pts(Some(pts));
1515 }
52aad9fe 1516 frm.set_frame_type(hdr.ftype);
171860fc 1517 Ok(frm.into_ref())
52aad9fe 1518 }
f9be4e75
KS
1519 fn flush(&mut self) {
1520 self.ipbs.clear();
1521 }
52aad9fe
KS
1522}
1523
54d2b09a
KS
1524const DECODER_OPTIONS: &[NAOptionDefinition] = &[
1525 NAOptionDefinition {
1526 name: FRAME_SKIP_OPTION, description: FRAME_SKIP_OPTION_DESC,
1527 opt_type: NAOptionDefinitionType::String(Some(&[
1528 FRAME_SKIP_OPTION_VAL_NONE,
1529 FRAME_SKIP_OPTION_VAL_KEYFRAME,
1530 FRAME_SKIP_OPTION_VAL_INTRA
1531 ])) },
1532];
1533
7d57ae2f 1534impl NAOptionHandler for RealVideo60Decoder {
54d2b09a
KS
1535 fn get_supported_options(&self) -> &[NAOptionDefinition] { DECODER_OPTIONS }
1536 fn set_options(&mut self, options: &[NAOption]) {
1537 for option in options.iter() {
1538 for opt_def in DECODER_OPTIONS.iter() {
1539 if opt_def.check(option).is_ok() {
1540 match (option.name, &option.value) {
1541 (FRAME_SKIP_OPTION, NAValue::String(ref str)) => {
1542 if let Ok(smode) = FrameSkipMode::from_str(str) {
1543 self.skip_mode = smode;
1544 }
1545 },
1546 _ => {},
1547 }
1548 }
1549 }
1550 }
1551 }
1552 fn query_option_value(&self, name: &str) -> Option<NAValue> {
1553 match name {
1554 FRAME_SKIP_OPTION => Some(NAValue::String(self.skip_mode.to_string())),
1555 _ => None,
1556 }
1557 }
7d57ae2f
KS
1558}
1559
08a1fab7 1560pub fn get_decoder() -> Box<dyn NADecoder + Send> {
52aad9fe
KS
1561 Box::new(RealVideo60Decoder::new())
1562}
1563
1564#[cfg(test)]
1565mod test {
3167c45c
KS
1566 use nihav_core::codecs::RegisteredDecoders;
1567 use nihav_core::demuxers::RegisteredDemuxers;
ce742854 1568 use nihav_codec_support::test::dec_video::*;
78fb6560 1569 use crate::realmedia_register_all_decoders;
e64739f8 1570 use crate::realmedia_register_all_demuxers;
52aad9fe
KS
1571 #[test]
1572 fn test_rv60() {
3167c45c
KS
1573 let mut dmx_reg = RegisteredDemuxers::new();
1574 realmedia_register_all_demuxers(&mut dmx_reg);
1575 let mut dec_reg = RegisteredDecoders::new();
78fb6560 1576 realmedia_register_all_decoders(&mut dec_reg);
3167c45c 1577
886cde48 1578 // sample from a private collection
c5123998
KS
1579 test_decoding("realmedia", "realvideo6", "assets/RV/RV60.rmhd", Some(1000), &dmx_reg, &dec_reg,
1580 ExpectedTestResult::MD5Frames(vec![
1581 [0x2b1f1807, 0x09edef33, 0x0e6c78c1, 0x3b3c8179],
1582 [0xea406850, 0x400802b8, 0xac106fb6, 0xe1e2e766],
1583 [0x2b1f1807, 0x09edef33, 0x0e6c78c1, 0x3b3c8179],
1584 [0xb04e2626, 0x976e16f5, 0xc41a7a78, 0x2d8765da],
1585 [0xf4f30d97, 0x7f2876eb, 0x265ffad4, 0x3542a7c4],
a15d97ad
KS
1586 [0x7fd46b65, 0x9e56b770, 0xffa13e3b, 0x73d47eb6],
1587 [0xa3ec74e1, 0xc33617ab, 0xb49c744b, 0x7d1c8127],
1588 [0x830d85c2, 0x1df398c3, 0x40f33a4f, 0x445d95b3],
1589 [0xa5471116, 0x9299e39f, 0x98da1680, 0x1aabeed5],
1590 [0xd89ef645, 0x66c684fe, 0x6d5e4207, 0x5e480550],
1591 [0xdf434d0c, 0xf0018799, 0x935aa650, 0xcfc702fc],
1592 [0x9770cae6, 0x8a7caa6a, 0x87b6438d, 0x7b161519],
1593 [0x9a2dfade, 0x3ff56dbe, 0x5fbc6999, 0x827770e9]]));
52aad9fe
KS
1594 }
1595}