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