254cc372dce744ad1d8b2626c1d64f555264841c
[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.awidth { 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.awidth { 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.aheight { 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.aheight { 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 pu_type: PUType,
544 }
545
546 impl PUInfo {
547 fn is_intra(self) -> bool { self.cu_type == CUType::Intra }
548 }
549
550 const RV60_CANDIDATE_INTRA_ANGLES: [u8; 6] = [ 0, 1, 10, 26, 18, 2 ];
551
552 #[derive(Clone,Copy,Default)]
553 struct BlockInfo {
554 mv: MVInfo,
555 imode: u8,
556 }
557
558 struct DeblockInfo {
559 left_str: Vec<u8>,
560 top_str: Vec<u8>,
561 stride: usize,
562 }
563
564 impl DeblockInfo {
565 fn new() -> Self {
566 Self { left_str: Vec::new(), top_str: Vec::new(), stride: 0 }
567 }
568 fn reinit(&mut self, w: usize, h: usize) {
569 self.left_str.clear();
570 self.top_str.clear();
571 self.stride = w >> 2;
572 let size = self.stride * (h >> 2);
573 self.left_str.resize(size, 0);
574 self.top_str.resize(size, 0);
575 }
576 fn set_strength(&mut self, xpos: usize, ypos: usize, size: usize, q: u8, strength: u8) {
577 let pos = self.get_pos(xpos, ypos);
578 let dsize = size >> 2;
579 let dval = (q << 2) | strength;
580 for x in 0..dsize {
581 self.top_str[pos + x] = dval;
582 self.top_str[pos + (dsize - 1) * self.stride + x] = dval;
583 }
584 for y in 0..dsize {
585 self.left_str[pos + y * self.stride] = dval;
586 self.left_str[pos + y * self.stride + dsize - 1] = dval;
587 }
588 }
589 fn get_pos(&self, xpos: usize, ypos: usize) -> usize {
590 (xpos >> 2) + (ypos >> 2) * self.stride
591 }
592 fn get_top_strength(&self, pos: usize) -> u8 {
593 self.top_str[pos] & 3
594 }
595 fn get_left_strength(&self, pos: usize) -> u8 {
596 self.left_str[pos] & 3
597 }
598 fn set_top_strength(&mut self, pos: usize, str: u8) {
599 self.top_str[pos] |= str;
600 }
601 fn set_left_strength(&mut self, pos: usize, str: u8) {
602 self.left_str[pos] |= str;
603 }
604 }
605
606 struct RealVideo60Decoder {
607 info: NACodecInfoRef,
608 cbs: RV60Codebooks,
609 ipbs: IPBShuffler,
610 dsp: RV60DSP,
611 ipred: IntraPredContext,
612 skip_mode: FrameSkipMode,
613
614 avg_buf: NAVideoBufferRef<u8>,
615
616 y_coeffs: [i16; 16 * 16],
617 u_coeffs: [i16; 8 * 8],
618 v_coeffs: [i16; 8 * 8],
619 qp: u8,
620 sel_qp: u8,
621
622 cu_splits: Vec<bool>,
623 coded_blk: [bool; 64],
624 dblk: DeblockInfo,
625
626 pu_info: Vec<PUInfo>,
627 pu_stride: usize,
628 pu_pos: usize,
629
630 blk_info: Vec<BlockInfo>,
631 blk_stride: usize,
632 blk_pos: usize,
633
634 xpos: usize,
635 ypos: usize,
636
637 ts_scale: u64,
638 ref0_pts: u64,
639 ref1_pts: u64,
640 ref0_ts: u64,
641 ref1_ts: u64,
642 }
643
644 impl RealVideo60Decoder {
645 fn new() -> Self {
646 let tmp_vinfo = NAVideoInfo::new(64, 64, false, YUV420_FORMAT);
647 let vt = alloc_video_buffer(tmp_vinfo, 4).unwrap();
648 let vb = vt.get_vbuf();
649 let avg_buf = vb.unwrap();
650 RealVideo60Decoder{
651 info: NACodecInfoRef::default(),
652 cbs: RV60Codebooks::init(),
653 ipbs: IPBShuffler::new(),
654 ipred: IntraPredContext::new(),
655 skip_mode: FrameSkipMode::default(),
656 dsp: RV60DSP::new(),
657 avg_buf,
658 y_coeffs: [0; 16 * 16],
659 u_coeffs: [0; 8 * 8],
660 v_coeffs: [0; 8 * 8],
661 qp: 0,
662 sel_qp: 0,
663 cu_splits: Vec::with_capacity(24),
664 coded_blk: [false; 64],
665 dblk: DeblockInfo::new(),
666 pu_info: Vec::new(),
667 pu_stride: 0,
668 pu_pos: 0,
669 blk_info: Vec::new(),
670 blk_stride: 0,
671 blk_pos: 0,
672 xpos: 0,
673 ypos: 0,
674
675 ts_scale: 1,
676 ref0_pts: 0,
677 ref1_pts: 0,
678 ref0_ts: 0,
679 ref1_ts: 0,
680 }
681 }
682 fn decode_cu_line(&mut self, buf: &mut NASimpleVideoFrame<u8>, hdr: &FrameHeader, src: &[u8], cu_y: usize) -> DecoderResult<()> {
683 let mut br = BitReader::new(src, BitReaderMode::BE);
684 let cu_w = hdr.get_width_cu();
685 let dqp = hdr.read_line_qp_offset(&mut br)?;
686 let qps = (hdr.qp as i8) + dqp;
687 validate!((0..32).contains(&qps));
688 let qp = qps as u8;
689 self.qp = qp;
690 self.sel_qp = match hdr.osvquant {
691 0 => qp,
692 1 => {
693 if qp <= 25 {
694 qp + 5
695 } else {
696 qp
697 }
698 },
699 _ => {
700 if qp <= 18 {
701 qp + 10
702 } else if qp <= 25 {
703 qp + 5
704 } else {
705 qp
706 }
707 },
708 };
709
710 for cu_x in 0..cu_w {
711 self.cu_splits.clear();
712 self.coded_blk = [false; 64];
713 self.decode_cb_tree(buf, hdr, &mut br, cu_x << 6, cu_y << 6, 6)?;
714 if hdr.deblock {
715 self.cu_splits.reverse();
716 self.deblock_cb_tree(buf, hdr, cu_x << 6, cu_y << 6, 6);
717 }
718 }
719 if br.left() >= 8 {
720 println!(" left {} bits", br.left());
721 }
722 Ok(())
723 }
724 #[allow(clippy::cognitive_complexity)]
725 fn decode_cb_tree(&mut self, buf: &mut NASimpleVideoFrame<u8>, hdr: &FrameHeader, br: &mut BitReader, xpos: usize, ypos: usize, log_size: u8) -> DecoderResult<()> {
726 if (xpos >= hdr.awidth) || (ypos >= hdr.aheight) { return Ok(()); }
727
728 let size = 1 << log_size;
729 let split = (xpos + size > hdr.awidth) || (ypos + size > hdr.aheight) || (size > 8 && br.read_bool()?);
730 self.cu_splits.push(split);
731 if split {
732 let hsize = size >> 1;
733 self.decode_cb_tree(buf, hdr, br, xpos, ypos, log_size - 1)?;
734 self.decode_cb_tree(buf, hdr, br, xpos + hsize, ypos, log_size - 1)?;
735 self.decode_cb_tree(buf, hdr, br, xpos, ypos + hsize, log_size - 1)?;
736 self.decode_cb_tree(buf, hdr, br, xpos + hsize, ypos + hsize, log_size - 1)?;
737 } else {
738 let cbh = CBHeader::read(br, hdr.ftype, hdr.two_f_refs, size)?;
739 self.pu_pos = (xpos >> 3) + (ypos >> 3) * self.pu_stride;
740 self.blk_pos = (xpos >> 2) + (ypos >> 2) * self.blk_stride;
741 self.xpos = xpos;
742 self.ypos = ypos;
743 self.reconstruct_info(hdr, &cbh, size)?;
744
745 let split_i4x4 = (cbh.cu_type == CUType::Intra) && (size == 8) && (cbh.pu_type == PUType::Quarters);
746 match cbh.cu_type {
747 CUType::Intra => {
748 let itype = self.blk_info[self.blk_pos].imode;
749 if !split_i4x4 {
750 let dstride = buf.stride[0];
751 let off = xpos + ypos * dstride;
752 let dst = &mut buf.data;
753 self.populate_ipred(hdr, dst, 0, dstride, 0, 0, size, true);
754 self.ipred.pred_angle(dst, off, dstride, size, itype as usize, true);
755 }
756 for comp in 1..3 {
757 let dstride = buf.stride[comp];
758 let soff = buf.offset[comp];
759 let off = soff + (xpos >> 1) + (ypos >> 1) * dstride;
760 let dst = &mut buf.data;
761 self.populate_ipred(hdr, dst, soff, dstride, 0, 0, size >> 1, false);
762 self.ipred.pred_angle(dst, off, dstride, size >> 1, itype as usize, false);
763 }
764 },
765 _ => {
766 let mut mv_x = xpos >> 2;
767 let mut mv_y = ypos >> 2;
768 let mut mv_pos = mv_x + mv_y * self.blk_stride;
769 for part_no in 0..cbh.pu_type.get_num_mvs() {
770 let (mv_w, mv_h) = cbh.pu_type.get_mv_size(part_no, size);
771 let mv = self.blk_info[mv_pos].mv;
772 let bw = mv_w << 2;
773 let bh = mv_h << 2;
774 let bx = mv_x << 2;
775 let by = mv_y << 2;
776 match mv.mvref {
777 MVRef::Ref0 => {
778 if hdr.ftype != FrameType::B {
779 if let Some(ref prevbuf) = self.ipbs.get_lastref() {
780 self.dsp.do_mc(buf, prevbuf, bx, by, bw, bh, mv.f_mv, false);
781 }
782 } else {
783 if let Some(ref prevbuf) = self.ipbs.get_b_fwdref() {
784 self.dsp.do_mc(buf, prevbuf, bx, by, bw, bh, mv.f_mv, false);
785 }
786 }
787 },
788 MVRef::Ref1 => {
789 if let Some(ref prevbuf) = self.ipbs.get_nextref() {
790 self.dsp.do_mc(buf, prevbuf, bx, by, bw, bh, mv.f_mv, false);
791 }
792 },
793 MVRef::BRef => {
794 validate!(hdr.ftype == FrameType::B);
795 if let Some(ref prevbuf) = self.ipbs.get_b_bwdref() {
796 self.dsp.do_mc(buf, prevbuf, bx, by, bw, bh, mv.b_mv, false);
797 }
798 },
799 MVRef::Ref0AndBRef => {
800 validate!(hdr.ftype == FrameType::B);
801 if let (Some(ref prevbuf), Some(ref nextbuf)) = (self.ipbs.get_b_fwdref(), self.ipbs.get_b_bwdref()) {
802 self.dsp.do_mc(buf, prevbuf, bx, by, bw, bh, mv.f_mv, false);
803 {
804 let mut avg_buf = NASimpleVideoFrame::from_video_buf(&mut self.avg_buf).unwrap();
805 self.dsp.do_mc(&mut avg_buf, nextbuf, bx, by, bw, bh, mv.b_mv, true);
806 }
807 self.dsp.do_avg(buf, &self.avg_buf, bx, by, bw, bh);
808 }
809 },
810 _ => unreachable!(),
811 };
812 if cbh.pu_type == PUType::Quarters {
813 if part_no != 1 {
814 mv_pos += mv_w;
815 mv_x += mv_w;
816 } else {
817 mv_pos += mv_h * self.blk_stride - mv_w;
818 mv_x -= mv_w;
819 mv_y += mv_h;
820 }
821 } else if cbh.pu_type.has_hor_split() {
822 mv_pos += mv_h * self.blk_stride;
823 mv_y += mv_h;
824 } else if cbh.pu_type.has_ver_split() {
825 mv_pos += mv_w;
826 mv_x += mv_w;
827 }
828 }
829 },
830 };
831 if cbh.ttype != TransformType::None {
832 self.y_coeffs = [0; 16 * 16];
833 self.u_coeffs = [0; 8 * 8];
834 self.v_coeffs = [0; 8 * 8];
835 }
836 let is_intra = cbh.cu_type == CUType::Intra;
837 let cb_pos = ((xpos & 63) >> 3) + ((ypos & 63) >> 3) * 8;
838 match cbh.ttype {
839 TransformType::T4X4 => {
840 let subset = if is_intra { 0 } else { 2 };
841 if size == 16 {
842 let cbp16;
843 if br.read_bool()? {
844 cbp16 = rv6_decode_cbp16(br, &self.cbs, subset, self.sel_qp)?;
845 } else {
846 cbp16 = 0;
847 }
848 if cbp16 != 0 {
849 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)?;
850 for y in 0..4 {
851 for x in 0..4 {
852 let i = x + y * 4;
853 if ((cbp16 >> i) & 1) != 0 {
854 self.dsp.transform4x4(&mut self.y_coeffs[i * 16..][..16]);
855 let dstride = buf.stride[0];
856 let off = xpos + x * 4 + (ypos + y * 4) * dstride;
857 let dst = &mut buf.data;
858 self.dsp.add_block(dst, off, dstride, &self.y_coeffs[i*16..][..16], 4);
859 self.coded_blk[cb_pos + (y / 2) * 8 + (x / 2)] = true;
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 self.coded_blk[cb_pos + y * 8 + x] = true;
875 }
876 if ((cbp16 >> (20 + i)) & 1) != 0 {
877 self.dsp.transform4x4(&mut self.v_coeffs[i * 16..][..16]);
878 let dstride = buf.stride[2];
879 let off = buf.offset[2] + xoff + yoff * dstride;
880 let dst = &mut buf.data;
881 self.dsp.add_block(dst, off, dstride, &self.v_coeffs[i * 16..][..16], 4);
882 self.coded_blk[cb_pos + y * 8 + x] = true;
883 }
884 }
885 }
886 }
887 } else {
888 let cbp8 = rv6_decode_cbp8(br, &self.cbs, subset, self.sel_qp)?;
889 if cbp8 != 0 {
890 self.coded_blk[cb_pos] = true;
891 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)?;
892 }
893 for i in 0..4 {
894 let xoff = (i & 1) * 4;
895 let yoff = (i & 2) * 2;
896 if split_i4x4 {
897 let dstride = buf.stride[0];
898 let off = xpos + xoff + (ypos + yoff) * dstride;
899 let dst = &mut buf.data;
900 self.populate_ipred(hdr, dst, 0, dstride, xoff, yoff, 4, true);
901 let itype = self.blk_info[self.blk_pos + (i & 1) + (i >> 1) * self.blk_stride].imode;
902 self.ipred.pred_angle(dst, off, dstride, 4, itype as usize, true);
903 }
904 if ((cbp8 >> i) & 1) != 0 {
905 let blk = &mut self.y_coeffs[i * 16..][..16];
906 self.dsp.transform4x4(blk);
907 let dstride = buf.stride[0];
908 let soff = buf.offset[0];
909 let off = soff + xpos + xoff + (ypos + yoff) * dstride;
910 self.dsp.add_block(buf.data, off, dstride, blk, 4);
911 }
912 }
913 if ((cbp8 >> 4) & 1) != 0 {
914 self.dsp.transform4x4(&mut self.u_coeffs);
915 let dstride = buf.stride[1];
916 let soff = buf.offset[1];
917 let off = soff + (xpos >> 1) + (ypos >> 1) * dstride;
918 self.dsp.add_block(buf.data, off, dstride, &self.u_coeffs, 4);
919 }
920 if ((cbp8 >> 5) & 1) != 0 {
921 self.dsp.transform4x4(&mut self.v_coeffs);
922 let dstride = buf.stride[2];
923 let soff = buf.offset[2];
924 let off = soff + (xpos >> 1) + (ypos >> 1) * dstride;
925 self.dsp.add_block(buf.data, off, dstride, &self.v_coeffs, 4);
926 }
927 }
928 },
929 TransformType::T8X8 => {
930 let subset = if is_intra { 1 } else { 3 };
931 let cbp8 = rv6_decode_cbp8(br, &self.cbs, subset, self.sel_qp)?;
932 if cbp8 != 0 {
933 self.coded_blk[cb_pos] = true;
934 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)?;
935 if (cbp8 & 0xF) != 0 {
936 self.dsp.transform8x8(&mut self.y_coeffs);
937 let dstride = buf.stride[0];
938 let off = xpos + ypos * dstride;
939 self.dsp.add_block(buf.data, off, dstride, &self.y_coeffs, 8);
940 }
941 if ((cbp8 >> 4) & 1) != 0 {
942 self.dsp.transform4x4(&mut self.u_coeffs);
943 let dstride = buf.stride[1];
944 let soff = buf.offset[1];
945 let off = soff + (xpos >> 1) + (ypos >> 1) * dstride;
946 self.dsp.add_block(buf.data, off, dstride, &self.u_coeffs, 4);
947 }
948 if ((cbp8 >> 5) & 1) != 0 {
949 self.dsp.transform4x4(&mut self.v_coeffs);
950 let dstride = buf.stride[2];
951 let soff = buf.offset[2];
952 let off = soff + (xpos >> 1) + (ypos >> 1) * dstride;
953 self.dsp.add_block(buf.data, off, dstride, &self.v_coeffs, 4);
954 }
955 }
956 },
957 TransformType::T16X16 => {
958 let subset = if is_intra { 1 } else { 3 };
959 let num_clusters = size >> 4;
960 let cl_cbp = br.read((num_clusters * num_clusters) as u8)?;
961 for y in 0..num_clusters {
962 for x in 0..num_clusters {
963 if ((cl_cbp >> (x + y * num_clusters)) & 1) == 0 { continue; }
964 self.coded_blk[cb_pos + x * 2 + y * 2 * 8 + 0] = true;
965 self.coded_blk[cb_pos + x * 2 + y * 2 * 8 + 1] = true;
966 self.coded_blk[cb_pos + x * 2 + y * 2 * 8 + 8] = true;
967 self.coded_blk[cb_pos + x * 2 + y * 2 * 8 + 9] = true;
968 let super_cbp = rv6_decode_cbp16(br, &self.cbs, subset, self.sel_qp)?;
969 if super_cbp != 0 {
970 self.y_coeffs = [0; 16 * 16];
971 self.u_coeffs = [0; 8 * 8];
972 self.v_coeffs = [0; 8 * 8];
973 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)?;
974 if (super_cbp & 0xFFFF) != 0 {
975 self.dsp.transform16x16(&mut self.y_coeffs);
976 let dstride = buf.stride[0];
977 let off = xpos + x * 16 + (ypos + y * 16) * dstride;
978 self.dsp.add_block(buf.data, off, dstride, &self.y_coeffs, 16);
979 }
980 if ((super_cbp >> 16) & 0xF) != 0 {
981 self.dsp.transform8x8(&mut self.u_coeffs);
982 let dstride = buf.stride[1];
983 let soff = buf.offset[1];
984 let off = soff + (xpos >> 1) + x * 8 + ((ypos >> 1) + y * 8) * dstride;
985 self.dsp.add_block(buf.data, off, dstride, &self.u_coeffs, 8);
986 }
987 if ((super_cbp >> 20) & 0xF) != 0 {
988 self.dsp.transform8x8(&mut self.v_coeffs);
989 let dstride = buf.stride[2];
990 let soff = buf.offset[2];
991 let off = soff + (xpos >> 1) + x * 8 + ((ypos >> 1) + y * 8) * dstride;
992 self.dsp.add_block(buf.data, off, dstride, &self.v_coeffs, 8);
993 }
994 }
995 }
996 }
997 },
998 _ => {},
999 };
1000 }
1001 Ok(())
1002 }
1003 fn reconstruct_info(&mut self, hdr: &FrameHeader, cbh: &CBHeader, size: usize) -> DecoderResult<()>{
1004 let mut pui = PUInfo::default();
1005 let pu_size = size >> 3;
1006 pui.cu_type = cbh.cu_type;
1007 pui.ttype = cbh.ttype;
1008 pui.pu_type = cbh.pu_type;
1009 if (cbh.cu_type == CUType::Intra) && (cbh.pu_type == PUType::Quarters) { // very special case
1010 self.pu_info[self.pu_pos] = pui;
1011 for y in 0..2 {
1012 for x in 0..2 {
1013 let imode = self.reconstruct_intra(hdr, cbh, 4, x + y * 2);
1014 validate!(imode <= MAX_IMODE);
1015 self.blk_info[self.blk_pos + x + y * self.blk_stride].imode = imode;
1016 self.blk_info[self.blk_pos + x + y * self.blk_stride].mv = MVInfo::default();
1017 }
1018 }
1019 return Ok(());
1020 }
1021 match cbh.cu_type {
1022 CUType::Intra => {
1023 self.pu_info[self.pu_pos] = pui;
1024 let imode = self.reconstruct_intra(hdr, cbh, size, 0);
1025 validate!(imode <= MAX_IMODE);
1026 for y in 0..(size >> 2) {
1027 for x in 0..(size >> 2) {
1028 self.blk_info[self.blk_pos + x + y * self.blk_stride].imode = imode;
1029 }
1030 }
1031 },
1032 CUType::InterMV => {
1033 let mut mv_x = self.xpos >> 2;
1034 let mut mv_y = self.ypos >> 2;
1035 let mut mv_pos = self.blk_pos;
1036 let pu_type = cbh.pu_type;
1037 for part_no in 0..pu_type.get_num_mvs() {
1038 let (mv_w, mv_h) = pu_type.get_mv_size(part_no, size);
1039 let mv = self.predict_mv(hdr, mv_x, mv_y, mv_w, &cbh.mv[part_no]);
1040 for y in 0..mv_h {
1041 for x in 0..mv_w {
1042 self.blk_info[mv_pos + x + y * self.blk_stride].mv = mv;
1043 }
1044 }
1045 if pu_type == PUType::Quarters {
1046 if part_no != 1 {
1047 mv_pos += mv_w;
1048 mv_x += mv_w;
1049 } else {
1050 mv_pos += mv_h * self.blk_stride - mv_w;
1051 mv_x -= mv_w;
1052 mv_y += mv_h;
1053 }
1054 } else if pu_type.has_hor_split() {
1055 mv_pos += mv_h * self.blk_stride;
1056 mv_y += mv_h;
1057 } else if pu_type.has_ver_split() {
1058 mv_pos += mv_w;
1059 mv_x += mv_w;
1060 }
1061 }
1062 },
1063 _ => {
1064 let skip_idx = cbh.mv[0].mvref.get_skip_mv_num();
1065 let mut skip_cand: UniqueList<MVInfo> = UniqueList::new(4);
1066 self.fill_skip_cand(hdr, &mut skip_cand, size);
1067 let mv = skip_cand.list[skip_idx];
1068
1069 let mv_size = size >> 2;
1070 for y in 0..mv_size {
1071 for x in 0..mv_size {
1072 self.blk_info[self.blk_pos + x + y * self.blk_stride].mv = mv;
1073 }
1074 }
1075 },
1076 };
1077 for y in 0..pu_size {
1078 for x in 0..pu_size {
1079 self.pu_info[self.pu_pos + x + y * self.pu_stride] = pui;
1080 }
1081 }
1082 Ok(())
1083 }
1084 fn reconstruct_intra(&self, hdr: &FrameHeader, cbh: &CBHeader, size: usize, sub: usize) -> u8 {
1085 match cbh.imode[0] {
1086 IntraMode::DC64 => { return 1; },
1087 IntraMode::Plane64 => { return 0; },
1088 _ => {},
1089 };
1090 // form list of predictors
1091 let blk_pos = self.blk_pos + (sub & 1) + (sub >> 1) * self.blk_stride;
1092 let mut ipm_cand: UniqueList<u8> = UniqueList::new(3);
1093 if hdr.has_top_block(self.xpos, self.ypos, (sub & 1) * 4, 0, size) {
1094 let pu = &self.pu_info[self.pu_pos - self.pu_stride];
1095 if pu.is_intra() {
1096 ipm_cand.add(self.blk_info[self.blk_pos + (sub & 1) - self.blk_stride].imode);
1097 }
1098 }
1099 if hdr.has_left_block(self.xpos, self.ypos, 0, (sub & 2) * 2, size) {
1100 let pu = &self.pu_info[self.pu_pos - 1];
1101 if pu.is_intra() {
1102 ipm_cand.add(self.blk_info[blk_pos - 1 - (sub & 1)].imode);
1103 }
1104 }
1105 let tl_x = if (sub & 2) == 0 { self.xpos + (sub & 1) * 4 } else { self.xpos };
1106 let tl_y = self.ypos + (sub & 2) * 4;
1107 if (tl_x > 0) && (tl_y > 0) {
1108 let pu = match sub {
1109 0 => &self.pu_info[self.pu_pos - self.pu_stride - 1],
1110 1 => &self.pu_info[self.pu_pos - self.pu_stride],
1111 2 => &self.pu_info[self.pu_pos - 1],
1112 _ => &self.pu_info[self.pu_pos - 1],
1113 };
1114 if pu.is_intra() {
1115 if sub != 3 {
1116 ipm_cand.add(self.blk_info[blk_pos - self.blk_stride - 1].imode);
1117 } else {
1118 ipm_cand.add(self.blk_info[blk_pos - self.blk_stride - 2].imode);
1119 }
1120 }
1121 }
1122 for el in RV60_CANDIDATE_INTRA_ANGLES.iter() {
1123 ipm_cand.add(*el);
1124 }
1125 // actually decode prediction mode
1126 match cbh.imode[sub] {
1127 IntraMode::Index(idx) => {
1128 ipm_cand.list[idx as usize]
1129 },
1130 IntraMode::Mode(mode) => {
1131 let mut imode = mode;
1132 let mut ipm_cs: [u8; 3] = [ipm_cand.list[0], ipm_cand.list[1], ipm_cand.list[2]];
1133 ipm_cs.sort();
1134 for ic in ipm_cs.iter() {
1135 if imode >= *ic {
1136 imode += 1;
1137 }
1138 }
1139 imode
1140 },
1141 _ => unreachable!(),
1142 }
1143 }
1144 fn populate_ipred(&mut self, hdr: &FrameHeader, src: &[u8], soff: usize, stride: usize, xoff: usize, yoff: usize, size: usize, is_luma: bool) {
1145 let src_off = if is_luma {
1146 soff + self.xpos + xoff + (self.ypos + yoff) * stride
1147 } else {
1148 soff + (self.xpos >> 1) + (self.ypos >> 1) * stride
1149 };
1150 self.ipred = IntraPredContext::new();
1151 if (self.ypos + yoff) > 0 {
1152 self.ipred.has_t = true;
1153 for x in 0..size {
1154 self.ipred.t[x + 1] = src[src_off - stride + x];
1155 }
1156 if (is_luma && hdr.has_top_right_block(self.xpos, self.ypos, xoff, yoff, size)) ||
1157 (!is_luma && hdr.has_top_right_block(self.xpos, self.ypos, 0, 0, size << 1)) {
1158 self.ipred.has_tr = true;
1159 for x in size..size*2 {
1160 self.ipred.t[x + 1] = src[src_off - stride + x];
1161 }
1162 } else {
1163 for i in 0..size {
1164 self.ipred.t[size + i + 1] = self.ipred.t[size];
1165 }
1166 }
1167 if (self.xpos + xoff) > 0 {
1168 self.ipred.t[0] = src[src_off - stride - 1];
1169 }
1170 }
1171 if (self.xpos + xoff) > 0 {
1172 self.ipred.has_l = true;
1173 for y in 0..size {
1174 self.ipred.l[y + 1] = src[src_off - 1 + y * stride];
1175 }
1176 if (is_luma && hdr.has_left_down_block(self.xpos, self.ypos, xoff, yoff, size)) ||
1177 (!is_luma && hdr.has_left_down_block(self.xpos, self.ypos, 0, 0, size << 1)) {
1178 self.ipred.has_ld = true;
1179 for y in size..size*2 {
1180 self.ipred.l[y + 1] = src[src_off - 1 + y * stride];
1181 }
1182 } else {
1183 for i in 0..size {
1184 self.ipred.l[size + i + 1] = self.ipred.l[size];
1185 }
1186 }
1187 if (self.ypos + yoff) > 0 {
1188 self.ipred.l[0] = src[src_off - stride - 1];
1189 }
1190 }
1191 }
1192 fn predict_mv(&self, hdr: &FrameHeader, mv_x: usize, mv_y: usize, mv_w: usize, mvi: &MVInfo) -> MVInfo {
1193 let mv_pos = mv_x + mv_y * self.blk_stride;
1194 let f_mv: MV;
1195 let b_mv: MV;
1196 if mvi.mvref.is_fwd() {
1197 let mut mv_cand: [MV; 3] = [ZERO_MV; 3];
1198 let mut mv_cand_size: usize = 0;
1199 if mv_x > 0 {
1200 let ref_mv = &self.blk_info[mv_pos - 1].mv;
1201 if ref_mv.matches_fwd(mvi.mvref) {
1202 mv_cand[mv_cand_size] = ref_mv.f_mv;
1203 mv_cand_size += 1;
1204 }
1205 }
1206 if mv_y > 0 {
1207 let ref_mv = &self.blk_info[mv_pos - self.blk_stride].mv;
1208 if ref_mv.matches_fwd(mvi.mvref) {
1209 mv_cand[mv_cand_size] = ref_mv.f_mv;
1210 mv_cand_size += 1;
1211 }
1212 }
1213 if hdr.has_top_block(mv_x << 2, mv_y << 2, mv_w << 2, 0, 4) {
1214 let ref_mv = &self.blk_info[mv_pos - self.blk_stride + mv_w].mv;
1215 if ref_mv.matches_fwd(mvi.mvref) {
1216 mv_cand[mv_cand_size] = ref_mv.f_mv;
1217 mv_cand_size += 1;
1218 }
1219 }
1220 f_mv = match mv_cand_size {
1221 1 | 2 => {
1222 let x = mv_cand[0].x + mv_cand[1].x + mv_cand[2].x;
1223 let y = mv_cand[0].y + mv_cand[1].y + mv_cand[2].y;
1224 if mv_cand_size == 1 {
1225 MV { x, y }
1226 } else {
1227 MV { x: x >> 1, y: y >> 1 }
1228 }
1229 },
1230 3 => MV::pred(mv_cand[0], mv_cand[1], mv_cand[2]),
1231 _ => ZERO_MV,
1232 };
1233 } else {
1234 f_mv = ZERO_MV;
1235 }
1236 if mvi.mvref.is_bwd() {
1237 let mut mv_cand: [MV; 3] = [ZERO_MV; 3];
1238 let mut mv_cand_size: usize = 0;
1239 if mv_x > 0 {
1240 let ref_mv = &self.blk_info[mv_pos - 1].mv;
1241 if ref_mv.matches_bwd(mvi.mvref) {
1242 mv_cand[mv_cand_size] = ref_mv.b_mv;
1243 mv_cand_size += 1;
1244 }
1245 }
1246 if mv_y > 0 {
1247 let ref_mv = &self.blk_info[mv_pos - self.blk_stride].mv;
1248 if ref_mv.matches_bwd(mvi.mvref) {
1249 mv_cand[mv_cand_size] = ref_mv.b_mv;
1250 mv_cand_size += 1;
1251 }
1252 }
1253 if hdr.has_top_block(mv_x << 2, mv_y << 2, mv_w << 2, 0, 4) {
1254 let ref_mv = &self.blk_info[mv_pos - self.blk_stride + mv_w].mv;
1255 if ref_mv.matches_bwd(mvi.mvref) {
1256 mv_cand[mv_cand_size] = ref_mv.b_mv;
1257 mv_cand_size += 1;
1258 }
1259 }
1260 b_mv = match mv_cand_size {
1261 1 | 2 => {
1262 let x = mv_cand[0].x + mv_cand[1].x + mv_cand[2].x;
1263 let y = mv_cand[0].y + mv_cand[1].y + mv_cand[2].y;
1264 if mv_cand_size == 1 {
1265 MV { x, y }
1266 } else {
1267 MV { x: x >> 1, y: y >> 1 }
1268 }
1269 },
1270 3 => MV::pred(mv_cand[0], mv_cand[1], mv_cand[2]),
1271 _ => ZERO_MV,
1272 };
1273 } else {
1274 b_mv = ZERO_MV;
1275 }
1276
1277 MVInfo { f_mv: mvi.f_mv + f_mv, b_mv: mvi.b_mv + b_mv, mvref: mvi.mvref }
1278 }
1279 fn fill_skip_cand(&mut self, hdr: &FrameHeader, skip_cand: &mut UniqueList<MVInfo>, size: usize) {
1280 let mv_size = size >> 2;
1281
1282 if self.xpos > 0 {
1283 let mv = &self.blk_info[self.blk_pos - 1].mv;
1284 if mv.is_some() {
1285 skip_cand.add(*mv);
1286 }
1287 }
1288 if self.ypos > 0 {
1289 let mv = &self.blk_info[self.blk_pos - self.blk_stride].mv;
1290 if mv.is_some() {
1291 skip_cand.add(*mv);
1292 }
1293 }
1294 if hdr.has_top_right_block(self.xpos, self.ypos, 0, 0, size) {
1295 let mv = &self.blk_info[self.blk_pos - self.blk_stride + mv_size].mv;
1296 if mv.is_some() {
1297 skip_cand.add(*mv);
1298 }
1299 }
1300 if hdr.has_left_down_block(self.xpos, self.ypos, 0, 0, size) {
1301 let mv = &self.blk_info[self.blk_pos + self.blk_stride * mv_size - 1].mv;
1302 if mv.is_some() {
1303 skip_cand.add(*mv);
1304 }
1305 }
1306 if hdr.has_left_block(self.xpos, self.ypos, 0, 0, size) {
1307 let mv = &self.blk_info[self.blk_pos + self.blk_stride * (mv_size - 1) - 1].mv;
1308 if mv.is_some() {
1309 skip_cand.add(*mv);
1310 }
1311 }
1312 if hdr.has_top_block(self.xpos, self.ypos, 0, 0, size) {
1313 let mv = &self.blk_info[self.blk_pos - self.blk_stride + mv_size - 1].mv;
1314 if mv.is_some() {
1315 skip_cand.add(*mv);
1316 }
1317 }
1318 if (self.xpos > 0) && (self.ypos > 0) {
1319 let mv = &self.blk_info[self.blk_pos - self.blk_stride - 1].mv;
1320 if mv.is_some() {
1321 skip_cand.add(*mv);
1322 }
1323 }
1324 for i in skip_cand.fill..4 {
1325 skip_cand.list[i] = MVInfo { f_mv: ZERO_MV, b_mv: ZERO_MV, mvref: MVRef::Ref0 };
1326 }
1327 }
1328 fn calc_tile_size(&self, pu_pos: usize, cu_type: CUType, log_size: u8) -> u8 {
1329 match log_size {
1330 3 => 3,
1331 4 if (cu_type != CUType::Intra) && (self.pu_info[pu_pos].pu_type != PUType::Full) => 3,
1332 4 | 5 | 6 => 4,
1333 _ => unreachable!(),
1334 }
1335 }
1336 fn deblock_cb_tree(&mut self, buf: &mut NASimpleVideoFrame<u8>, hdr: &FrameHeader, xpos: usize, ypos: usize, log_size: u8) {
1337 if (xpos >= hdr.awidth) || (ypos >= hdr.aheight) { return; }
1338 let split = self.cu_splits.pop().unwrap();
1339 if split {
1340 let hsize = 1 << (log_size - 1);
1341 self.deblock_cb_tree(buf, hdr, xpos, ypos, log_size - 1);
1342 self.deblock_cb_tree(buf, hdr, xpos + hsize, ypos, log_size - 1);
1343 self.deblock_cb_tree(buf, hdr, xpos, ypos + hsize, log_size - 1);
1344 self.deblock_cb_tree(buf, hdr, xpos + hsize, ypos + hsize, log_size - 1);
1345 } else {
1346 let pu_pos = (xpos >> 3) + (ypos >> 3) * self.pu_stride;
1347 let cu_type = self.pu_info[pu_pos].cu_type;
1348 let tsize = self.calc_tile_size(pu_pos, cu_type, log_size);
1349 let ntiles = 1 << (log_size - tsize);
1350 let dparams = RV60DeblockParams {
1351 deblock_chroma: hdr.deblock_chroma,
1352 width: hdr.awidth,
1353 height: hdr.aheight,
1354 dblkstride: self.dblk.stride,
1355 };
1356 for ty in 0..ntiles {
1357 for tx in 0..ntiles {
1358 let x = xpos + (tx << tsize);
1359 let y = ypos + (ty << tsize);
1360 let cb_pos = ((x & 63) >> 3) + ((y & 63) >> 3) * 8;
1361 if cu_type == CUType::Intra {
1362 self.dblk.set_strength(x, y, 1 << tsize, self.qp, 2);
1363 } else if (cu_type != CUType::Skip) && self.coded_blk[cb_pos] {
1364 self.dblk.set_strength(x, y, 1 << tsize, self.qp, 1);
1365 } else {
1366 self.dblk.set_strength(x, y, 1 << tsize, self.qp, 0);
1367 self.derive_deblock_strength(x, y, 1 << (tsize - 2));
1368 }
1369 self.dsp.do_deblock(&dparams, buf, x, y, 1 << tsize,
1370 self.dblk.top_str.as_slice(),
1371 self.dblk.left_str.as_slice(),
1372 self.dblk.get_pos(x, y));
1373 }
1374 }
1375 }
1376 }
1377 fn derive_deblock_strength(&mut self, xpos: usize, ypos: usize, size4: usize) {
1378 let blk_pos = (xpos >> 2) + (ypos >> 2) * self.blk_stride;
1379 let mut dblk_pos = self.dblk.get_pos(xpos, ypos);
1380 if ypos > 0 {
1381 let top_blk_pos = blk_pos - self.blk_stride;
1382 for i in 0..size4 {
1383 if self.dblk.get_top_strength(dblk_pos - self.dblk.stride + i) == 0 {
1384 if self.blk_info[blk_pos + i].mv.is_deblock_cand(&self.blk_info[top_blk_pos + i].mv) {
1385 self.dblk.set_top_strength(dblk_pos + i, 1);
1386 }
1387 }
1388 }
1389 }
1390 if xpos > 0 {
1391 for i in 0..size4 {
1392 if self.dblk.get_left_strength(dblk_pos - 1) == 0 {
1393 if self.blk_info[blk_pos + i * self.blk_stride].mv.is_deblock_cand(&self.blk_info[blk_pos + i * self.blk_stride - 1].mv) {
1394 self.dblk.set_left_strength(dblk_pos, 1);
1395 }
1396 }
1397 dblk_pos += self.dblk.stride;
1398 }
1399 }
1400 }
1401 }
1402
1403 impl NADecoder for RealVideo60Decoder {
1404 fn init(&mut self, supp: &mut NADecoderSupport, info: NACodecInfoRef) -> DecoderResult<()> {
1405 if let NACodecTypeInfo::Video(vinfo) = info.get_properties() {
1406 let fmt = YUV420_FORMAT;
1407 let myinfo = NACodecTypeInfo::Video(NAVideoInfo::new(0, 0, false, fmt));
1408 self.info = NACodecInfo::new_ref(info.get_name(), myinfo, info.get_extradata()).into_ref();
1409
1410 let edata = info.get_extradata().unwrap();
1411 let src: &[u8] = &edata;
1412
1413 if src.len() < 8 { return Err(DecoderError::InvalidData); }
1414 let mut mr = MemoryReader::new_read(src);
1415 let mut br = ByteReader::new(&mut mr);
1416 let _flags = br.read_u32be()?;
1417 let version = br.read_u32be()?;
1418 let _unk = br.read_u16be()?;
1419 validate!((version >> 28) == 4);
1420 // then width and height again as 16be
1421
1422 //self.bd.width = vinfo.get_width();
1423 //self.bd.height = vinfo.get_height();
1424 //self.frmmgr.clear();
1425
1426 supp.pool_u8.set_dec_bufs(3);
1427 supp.pool_u8.prealloc_video(NAVideoInfo::new(vinfo.get_width(), vinfo.get_height(), false, fmt), 6)?;
1428
1429 Ok(())
1430 } else {
1431 println!("???");
1432 Err(DecoderError::InvalidData)
1433 }
1434 }
1435 fn decode(&mut self, supp: &mut NADecoderSupport, pkt: &NAPacket) -> DecoderResult<NAFrameRef> {
1436 let src = pkt.get_buffer();
1437
1438 validate!(src.len() > 9);
1439 let hsize = (src[0] as usize) * 8 + 9;
1440 let mut br = BitReader::new(&src[hsize..], BitReaderMode::BE);
1441 let hdr = FrameHeader::read(&mut br)?;
1442 match self.skip_mode {
1443 FrameSkipMode::None => {},
1444 FrameSkipMode::KeyframesOnly => {
1445 if hdr.ftype == FrameType::B {
1446 let mut frm = NAFrame::new_from_pkt(pkt, self.info.clone(), NABufferType::None);
1447 frm.set_frame_type(FrameType::Skip);
1448 return Ok(frm.into_ref());
1449 }
1450 },
1451 FrameSkipMode::IntraOnly => {
1452 if hdr.ftype != FrameType::I {
1453 let mut frm = NAFrame::new_from_pkt(pkt, self.info.clone(), NABufferType::None);
1454 frm.set_frame_type(FrameType::Skip);
1455 return Ok(frm.into_ref());
1456 }
1457 },
1458 };
1459
1460 let mut slices: Vec<usize> = Vec::new();
1461 hdr.parse_slice_sizes(&mut br, &mut slices)?;
1462 match hdr.ftype {
1463 FrameType::P => {
1464 if self.ipbs.get_lastref().is_none() {
1465 return Err(DecoderError::MissingReference);
1466 }
1467 },
1468 FrameType::B => {
1469 if self.ipbs.get_lastref().is_none() {
1470 return Err(DecoderError::MissingReference);
1471 }
1472 if self.ipbs.get_nextref().is_none() {
1473 return Err(DecoderError::MissingReference);
1474 }
1475 },
1476 _ => {},
1477 };
1478
1479 let tmp_vinfo = NAVideoInfo::new(hdr.width, hdr.height, false, YUV420_FORMAT);
1480 let ret = supp.pool_u8.get_free();
1481 if ret.is_none() {
1482 return Err(DecoderError::AllocError);
1483 }
1484 let mut buf = ret.unwrap();
1485 if buf.get_info() != tmp_vinfo {
1486 self.ipbs.clear();
1487 supp.pool_u8.reset();
1488 supp.pool_u8.prealloc_video(tmp_vinfo, 6)?;
1489 let ret = supp.pool_u8.get_free();
1490 if ret.is_none() {
1491 return Err(DecoderError::AllocError);
1492 }
1493 buf = ret.unwrap();
1494 }
1495
1496 let cu_w = hdr.get_width_cu();
1497 let cu_h = hdr.get_height_cu();
1498 self.pu_stride = cu_w << 3;
1499 self.pu_info.resize(self.pu_stride * (cu_h << 3), PUInfo::default());
1500 self.blk_stride = cu_w << 4;
1501 self.blk_info.clear();
1502 self.blk_info.resize(self.blk_stride * (cu_h << 4), BlockInfo::default());
1503 if hdr.deblock {
1504 self.dblk.reinit(hdr.awidth, hdr.aheight);
1505 }
1506 let mut off = hsize + ((br.tell() >> 3) as usize);
1507 let mut dframe = NASimpleVideoFrame::from_video_buf(&mut buf).unwrap();
1508 for (cu_y, size) in slices.into_iter().enumerate() {
1509 self.decode_cu_line(&mut dframe, &hdr, &src[off..][..size], cu_y)?;
1510 off += size;
1511 }
1512 if (hdr.ftype == FrameType::I) || (hdr.ftype == FrameType::P) {
1513 self.ipbs.add_frame(buf.clone());
1514 }
1515
1516 if hdr.ftype != FrameType::B {
1517 self.ref0_pts = self.ref1_pts;
1518 self.ref1_pts = pkt.get_pts().unwrap_or(0);
1519 self.ref0_ts = self.ref1_ts;
1520 self.ref1_ts = hdr.ts as u64;
1521 if (self.ref1_pts > self.ref0_pts) && (self.ref1_ts > self.ref0_ts) {
1522 self.ts_scale = (self.ref1_pts - self.ref0_pts) / (self.ref1_ts - self.ref0_ts);
1523 }
1524 }
1525 let mut frm = NAFrame::new_from_pkt(pkt, self.info.clone(), NABufferType::Video(buf));
1526 frm.set_keyframe(hdr.ftype == FrameType::I);
1527 if hdr.ftype == FrameType::B {
1528 let pts = self.ref0_pts + ((hdr.ts as u64) - self.ref0_ts) * self.ts_scale;
1529 frm.set_pts(Some(pts));
1530 }
1531 frm.set_frame_type(hdr.ftype);
1532 Ok(frm.into_ref())
1533 }
1534 fn flush(&mut self) {
1535 self.ipbs.clear();
1536 }
1537 }
1538
1539 const DECODER_OPTIONS: &[NAOptionDefinition] = &[
1540 NAOptionDefinition {
1541 name: FRAME_SKIP_OPTION, description: FRAME_SKIP_OPTION_DESC,
1542 opt_type: NAOptionDefinitionType::String(Some(&[
1543 FRAME_SKIP_OPTION_VAL_NONE,
1544 FRAME_SKIP_OPTION_VAL_KEYFRAME,
1545 FRAME_SKIP_OPTION_VAL_INTRA
1546 ])) },
1547 ];
1548
1549 impl NAOptionHandler for RealVideo60Decoder {
1550 fn get_supported_options(&self) -> &[NAOptionDefinition] { DECODER_OPTIONS }
1551 fn set_options(&mut self, options: &[NAOption]) {
1552 for option in options.iter() {
1553 for opt_def in DECODER_OPTIONS.iter() {
1554 if opt_def.check(option).is_ok() {
1555 match (option.name, &option.value) {
1556 (FRAME_SKIP_OPTION, NAValue::String(ref str)) => {
1557 if let Ok(smode) = FrameSkipMode::from_str(str) {
1558 self.skip_mode = smode;
1559 }
1560 },
1561 _ => {},
1562 }
1563 }
1564 }
1565 }
1566 }
1567 fn query_option_value(&self, name: &str) -> Option<NAValue> {
1568 match name {
1569 FRAME_SKIP_OPTION => Some(NAValue::String(self.skip_mode.to_string())),
1570 _ => None,
1571 }
1572 }
1573 }
1574
1575 pub fn get_decoder() -> Box<dyn NADecoder + Send> {
1576 Box::new(RealVideo60Decoder::new())
1577 }
1578
1579 #[cfg(test)]
1580 mod test {
1581 use nihav_core::codecs::RegisteredDecoders;
1582 use nihav_core::demuxers::RegisteredDemuxers;
1583 use nihav_codec_support::test::dec_video::*;
1584 use crate::realmedia_register_all_decoders;
1585 use crate::realmedia_register_all_demuxers;
1586 #[test]
1587 fn test_rv60() {
1588 let mut dmx_reg = RegisteredDemuxers::new();
1589 realmedia_register_all_demuxers(&mut dmx_reg);
1590 let mut dec_reg = RegisteredDecoders::new();
1591 realmedia_register_all_decoders(&mut dec_reg);
1592
1593 // sample from a private collection
1594 test_decoding("realmedia", "realvideo6", "assets/RV/RV60.rmhd", Some(1000), &dmx_reg, &dec_reg,
1595 ExpectedTestResult::MD5Frames(vec![
1596 [0x2b1f1807, 0x09edef33, 0x0e6c78c1, 0x3b3c8179],
1597 [0x76743a3b, 0x7dd4f196, 0x0193fe5a, 0x4f78c7cb],
1598 [0x2b1f1807, 0x09edef33, 0x0e6c78c1, 0x3b3c8179],
1599 [0xfee70206, 0x626f3bea, 0x7677ad4b, 0x1228f3b6],
1600 [0x7156cbc2, 0xf381bcb6, 0xe86531f2, 0xb311c3ea],
1601 [0x1742b5a1, 0x66252580, 0x242753de, 0x5215d732],
1602 [0xd357ebda, 0x6460dba6, 0xa93eb616, 0x63ee6d60],
1603 [0x4cd72275, 0x28e1e439, 0xad17dfca, 0x3fd7253f],
1604 [0xe389ce4f, 0x8f0891b3, 0x88639b23, 0x21ed114f],
1605 [0x5b2b2f1b, 0x17a7518b, 0x53806e6a, 0x4538bb00],
1606 [0xdca03c9a, 0x1a45d80c, 0x86141211, 0x79912ed4],
1607 [0x0bf66bf4, 0x46385620, 0xc6fa4796, 0xd8e16d56],
1608 [0x4671a7f0, 0x46f50649, 0x268df27b, 0x70b71ab3]]));
1609 }
1610 }