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