]> git.nihav.org Git - nihav.git/blame - nihav-realmedia/src/codecs/rv60.rs
add NASimpleVideoFrame and try it in RV60 decoder
[nihav.git] / nihav-realmedia / src / codecs / rv60.rs
CommitLineData
52aad9fe
KS
1use std::rc::Rc;
2use std::cell::RefCell;
5641dccf
KS
3use nihav_core::formats::YUV420_FORMAT;
4use nihav_core::frame::*;
5use nihav_core::codecs::{NADecoder, MV, ZERO_MV, DecoderError, DecoderResult, IPBShuffler};
6use nihav_core::io::byteio::{MemoryReader,ByteReader};
7use nihav_core::io::bitreader::{BitReader,BitReaderMode};
8use nihav_core::io::intcode::*;
52aad9fe
KS
9
10use super::rv60codes::*;
11use super::rv60dsp::*;
12
13struct UniqueList<A> {
14 list: [A; 4],
15 fill: usize,
16 max_size: usize,
17}
18
19impl<A:Copy+Default+PartialEq> UniqueList<A> {
20 fn new(max_size: usize) -> Self {
21 Self { list: [A::default(); 4], fill: 0, max_size }
22 }
23 fn add(&mut self, cand: A) {
24 if self.fill == self.max_size { return; }
25 let mut unique = true;
26 for el in self.list.into_iter().take(self.fill) {
27 if *el == cand {
28 unique = false;
29 break;
30 }
31 }
32 if unique {
33 self.list[self.fill] = cand;
34 self.fill += 1;
35 }
36 }
37}
38
39const RV60_FRAME_TYPES: [FrameType; 4] = [ FrameType::I, FrameType::P, FrameType::B, FrameType::Other ];
40const MAX_IMODE: u8 = 34;
41
42#[derive(Clone,Copy,Debug)]
43struct FrameHeader {
44 profile: u8,
45 ftype: FrameType,
46 qp: u8,
47 osvquant: u8,
48 ts: u32,
49 width: usize,
50 height: usize,
51 two_f_refs: bool,
52 qp_off_type: u8,
53 deblock: bool,
54 deblock_chroma: bool,
55}
56
57const RV60_CUSTOM_MSG_LENS: [u32; 4] = [ 2, 4, 16, 32 ];
58impl FrameHeader {
59 fn read(br: &mut BitReader) -> DecoderResult<Self> {
60 let marker = br.read(2)?;
61 validate!(marker == 3);
62 let profile = br.read(2)? as u8;
63 validate!(profile == 0);
64 let _someval = br.read(4)?;
65 let ftypeid = br.read(2)? as usize;
66 let ftype = RV60_FRAME_TYPES[ftypeid];
67 let qp = br.read(6)? as u8;
68 let marker = br.read(1)?;
69 validate!(marker == 0);
70 let toolset = br.read(2)?;
71 validate!(toolset == 0);
72 let osvquant = br.read(2)? as u8;
73 let _some_flag = br.read_bool()?;
74 let _some_val = br.read(2)?;
75 let ts = br.read(24)?;
76 let width = ((br.read(11)? as usize) + 1) * 4;
77 let height = ((br.read(11)? as usize) + 0) * 4;
78 validate!(height > 0);
79 let _some_flag = br.read_bool()?;
80 let two_f_refs;
81 if ftype == FrameType::I {
82//byte17 = 0
83 two_f_refs = false;
84 } else {
85 let flag = br.read_bool()?;
86 if flag { // untested
87 br.skip(1)?;
88 br.skip(1)?;
89 br.skip(1)?;
90 }
91//byte17 = flag?
92 two_f_refs = br.read_bool()?;
93 }
94// if byte17 { dw40 = 2; dw3C = 2; } else { dw40 = 1; dw3C = 1; }
95 let _some_val = br.read_code(UintCodeType::Unary012)?; // luma_qp_diff?
96 let chroma_qp_diff = br.read(1)?;
97 validate!(chroma_qp_diff == 0);
98 let qp_off_type = br.read_code(UintCodeType::Unary012)? as u8;
99 let deblock = br.read_bool()?;
100 let deblock_chroma = deblock && !br.read_bool()?;
101 if br.read_bool()? {
102 let custom_msg_hdr_len = br.read(2)? as usize;
103 if custom_msg_hdr_len != 0 {
104 for i in 0..custom_msg_hdr_len {
105 br.skip(RV60_CUSTOM_MSG_LENS[i] * 8)?;
106 }
107 }
108 }
109
110 Ok(FrameHeader {
111 profile, ftype, qp, osvquant, ts, width, height, two_f_refs, qp_off_type,
112 deblock, deblock_chroma,
113 })
114 }
115 fn parse_slice_sizes(&self, br: &mut BitReader, sizes: &mut Vec<usize>) -> DecoderResult<()> {
116 let nslices = self.get_height_cu();
117 let nbits = (br.read(5)? as u8) + 1;
118 validate!(nbits < 32);
119 let mut signs: Vec<bool> = Vec::with_capacity(nslices);
120 for _ in 0..nslices {
121 let sign = br.read_bool()?;
122 signs.push(sign);
123 }
124 validate!(signs[0]);
125 sizes.truncate(0);
126 let mut sum = 0;
127 let first_size = br.read(nbits)? as usize;
128 validate!(first_size > 0);
129 sum += first_size;
130 let mut lastsize = first_size;
131 sizes.push(first_size);
132 for i in 1..nslices {
133 let diff = br.read(nbits)? as isize;
134 let size;
135 if signs[i] {
136 let sum = (lastsize as isize).checked_add(diff);
137 validate!(sum.is_some());
138 size = sum.unwrap() as usize;
139 } else {
140 let sum = (lastsize as isize).checked_sub(diff);
141 validate!(sum.is_some());
142 size = sum.unwrap() as usize;
143 }
144 sizes.push(size);
145 sum += size;
146 lastsize = size;
147 }
148 br.align();
149if ((br.left() >> 3) as usize) != sum {
150println!(" left {} / {}", br.left() >> 3, sum);
151}
152 validate!((br.left() >> 3) >= (sum as isize));
153 Ok(())
154 }
155 fn read_line_qp_offset(&self, br: &mut BitReader) -> DecoderResult<i8> {
156 match self.qp_off_type {
157 0 => Ok(0),
158 1 => {
159 let val = br.read_code(UintCodeType::Unary012)?;
160 if val != 2 {
161 Ok(val as i8)
162 } else {
163 Ok(-1)
164 }
165 },
166 _ => {
167 if br.read(1)? == 0 {
168 Ok(0)
169 } else {
170 let val = br.read(2)? as i8;
171 if (val & 2) == 0 {
172 Ok(val + 1)
173 } else {
174 Ok(-((val & 1) + 1))
175 }
176 }
177 },
178 }
179 }
180 fn get_width_cu(&self) -> usize {
181 (self.width + 63) >> 6
182 }
183 fn get_height_cu(&self) -> usize {
184 (self.height + 63) >> 6
185 }
186 fn has_top_block(&self, xpos: usize, ypos: usize, dx: usize, dy: usize, size: usize) -> bool {
187 if (ypos + dy) == 0 { return false; }
188 let xpos2 = xpos + dx;
189 if (xpos2 + size) > self.width { return false; }
190 true
191 }
192 fn has_top_right_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 * 2) > self.width { return false; }
196 let cxpos = ((xpos + dx) & 63) >> RV60_BLOCK_LOG2[size];
197 let cypos = ((ypos + dy) & 63) >> RV60_BLOCK_LOG2[size];
198 ((cypos as u8) & RV60_AVAIL_MASK[cxpos]) == 0
199 }
200 fn has_left_block(&self, xpos: usize, ypos: usize, dx: usize, dy: usize, size: usize) -> bool {
201 if (xpos + dx) == 0 { return false; }
202 let ypos2 = ypos + dy;
203 if (ypos2 + size) > self.height { return false; }
204 true
205 }
206 fn has_left_down_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 * 2) > self.height { return false; }
210 let cxpos = (!(xpos + dx) & 63) >> RV60_BLOCK_LOG2[size];
211 let cypos = (!(ypos + dy) & 63) >> RV60_BLOCK_LOG2[size];
212 ((cypos as u8) & RV60_AVAIL_MASK[cxpos]) >= 1
213 }
214}
215
216const RV60_BLOCK_LOG2: [u8; 65] = [
217 0,
218 0, 1, 0, 2, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 4,
219 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5,
220 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
221 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6
222];
223const RV60_AVAIL_MASK: [u8; 64] = [
224 0, 1, 0, 3, 0, 1, 0, 7, 0, 1, 0, 3, 0, 1, 0, 0,
225 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
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, 0
228];
229
230#[derive(Clone,Copy,PartialEq,Debug)]
231enum CUType {
232 Intra,
233 InterMV,
234 Skip,
235 InterNoMV,
236}
237
238impl Default for CUType {
239 fn default() -> Self { CUType::Intra }
240}
241
242const RV60_CU_TYPES: [CUType; 4] = [ CUType::Intra, CUType::InterMV, CUType::Skip, CUType::InterNoMV ];
243
244#[derive(Clone,Copy,PartialEq,Debug)]
245enum PUType {
246 Full,
247 N2Hor,
248 N2Ver,
249 Quarters,
250 N4Hor,
251 N34Hor,
252 N4Ver,
253 N34Ver,
254}
255
256const RV60_PU_TYPES: [PUType; 8] = [
257 PUType::Full, PUType::N2Hor, PUType::N2Ver, PUType::Quarters,
258 PUType::N4Hor, PUType::N34Hor, PUType::N4Ver, PUType::N34Ver,
259];
260
261impl PUType {
262 fn get_num_mvs(&self) -> usize {
263 match *self {
264 PUType::Full => 1,
265 PUType::Quarters => 4,
266 _ => 2,
267 }
268 }
269 fn get_mv_size(&self, part_no: usize, size: usize) -> (usize, usize) {
270 let mv_size = size >> 2;
271 match *self {
272 PUType::Full => (mv_size, mv_size),
273 PUType::N2Hor => (mv_size, mv_size >> 1),
274 PUType::N2Ver => (mv_size >> 1, mv_size),
275 PUType::Quarters => (mv_size >> 1, mv_size >> 1),
276 PUType::N4Hor => {
277 if part_no == 0 {
278 (mv_size, mv_size >> 2)
279 } else {
280 (mv_size, 3 * mv_size >> 2)
281 }
282 },
283 PUType::N34Hor => {
284 if part_no == 0 {
285 (mv_size, 3 * mv_size >> 2)
286 } else {
287 (mv_size, mv_size >> 2)
288 }
289 },
290 PUType::N4Ver => {
291 if part_no == 0 {
292 ( mv_size >> 2, mv_size)
293 } else {
294 (3 * mv_size >> 2, mv_size)
295 }
296 },
297 PUType::N34Ver => {
298 if part_no == 0 {
299 (3 * mv_size >> 2, mv_size)
300 } else {
301 ( mv_size >> 2, mv_size)
302 }
303 },
304 }
305 }
306 fn has_hor_split(&self) -> bool {
307 match *self {
308 PUType::N2Hor | PUType::N4Hor | PUType::N34Hor | PUType::Quarters => true,
309 _ => false,
310 }
311 }
312 fn has_ver_split(&self) -> bool {
313 match *self {
314 PUType::N2Ver | PUType::N4Ver | PUType::N34Ver | PUType::Quarters => true,
315 _ => false,
316 }
317 }
318}
319
320impl Default for PUType {
321 fn default() -> Self { PUType::Full }
322}
323
324#[derive(Clone,Copy,Debug)]
325enum IntraMode {
326 Index(u8),
327 Mode(u8),
328 DC64,
329 Plane64,
330}
331
332#[derive(Clone,Copy,PartialEq,Debug)]
333enum TransformType {
334 None,
335 T4X4,
336 T8X8,
337 T16X16,
338}
339
340impl Default for TransformType {
341 fn default() -> Self { TransformType::None }
342}
343
344#[derive(Clone,Copy,PartialEq,Debug)]
345enum MVRef {
346 None,
347 Ref0,
348 Ref1,
349 BRef,
350 Ref0AndBRef,
351 Skip0,
352 Skip1,
353 Skip2,
354 Skip3,
355}
356
357const SKIP_MV_REF: [MVRef; 4] = [ MVRef::Skip0, MVRef::Skip1, MVRef::Skip2, MVRef::Skip3 ];
358
359impl 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 match *self {
370 MVRef::Ref0 | MVRef::Ref0AndBRef => true,
371 _ => false,
372 }
373 }
374 fn is_fwd(&self) -> bool {
375 match *self {
376 MVRef::Ref0 | MVRef::Ref1 | MVRef::Ref0AndBRef => true,
377 _ => false,
378 }
379 }
380 fn is_bwd(&self) -> bool {
381 match *self {
382 MVRef::BRef | MVRef::Ref0AndBRef => true,
383 _ => false,
384 }
385 }
386}
387
388#[derive(Clone,Copy,PartialEq,Debug)]
389struct MVInfo {
390 f_mv: MV,
391 b_mv: MV,
392 mvref: MVRef,
393}
394
395impl MVInfo {
396 fn is_some(&self) -> bool { self.mvref != MVRef::None }
397 fn matches_fwd(&self, mvref: MVRef) -> bool {
398 (self.mvref == mvref) || (self.mvref.is_ref0() && mvref.is_ref0())
399 }
400 fn matches_bwd(&self, mvref: MVRef) -> bool {
401 self.mvref.is_bwd() && mvref.is_bwd()
402 }
403 fn is_deblock_cand(&self, other: &MVInfo) -> bool {
404 if self.mvref != other.mvref { return true; }
405 let mut mvdiff = 0;
406 if self.mvref.is_fwd() {
407 let diff = self.f_mv - other.f_mv;
408 mvdiff += diff.x.abs() + diff.y.abs();
409 }
410 if self.mvref.is_bwd() {
411 let diff = self.b_mv - other.b_mv;
412 mvdiff += diff.x.abs() + diff.y.abs();
413 }
414 mvdiff > 4
415 }
416}
417
418impl Default for MVInfo {
419 fn default() -> Self { Self { f_mv: ZERO_MV, b_mv: ZERO_MV, mvref: MVRef::None } }
420}
421
422#[derive(Clone,Copy,Debug)]
423struct CBHeader {
424 cu_type: CUType,
425 pu_type: PUType,
426 ttype: TransformType,
427 imode: [IntraMode; 4],
428 mv: [MVInfo; 4],
429}
430
431impl CBHeader {
432 fn read(br: &mut BitReader, ftype: FrameType, two_f_refs: bool, size: usize) -> DecoderResult<Self> {
433 let cu_type;
434 let pu_type;
435 let mut imode: [IntraMode; 4] = [IntraMode::Index(0); 4];
436 let mut mv: [MVInfo; 4] = [MVInfo::default(); 4];
437 if ftype == FrameType::I {
438 cu_type = CUType::Intra;
439 } else {
440 cu_type = RV60_CU_TYPES[br.read(2)? as usize];
441 }
442 match cu_type {
443 CUType::Intra => {
444 if (size == 8) && br.read_bool()? {
445 pu_type = PUType::Quarters;
446 } else {
447 pu_type = PUType::Full;
448 }
449 if pu_type == PUType::Quarters {
450 for i in 0..4 {
451 imode[i] = CBHeader::read_intra_mode(br)?;
452 }
453 } else if size <= 32 {
454 imode[0] = CBHeader::read_intra_mode(br)?;
455 } else {
456 if !br.read_bool()? {
457 imode[0] = IntraMode::DC64;
458 } else {
459 imode[0] = IntraMode::Plane64;
460 }
461 }
462 },
463 CUType::InterMV => {
464 let bits = if size == 8 { 2 } else { 3 };
465 pu_type = RV60_PU_TYPES[br.read(bits)? as usize];
466 CBHeader::read_mv_data(br, ftype, two_f_refs, size, pu_type, &mut mv)?;
467 },
468 _ => {
469 pu_type = PUType::Full;
470 let skip_mv_no = br.read_code(UintCodeType::LimitedUnary(3, 0))?;
471 mv[0].mvref = SKIP_MV_REF[skip_mv_no as usize];
472 },
473 };
474 let ttype;
475 if cu_type == CUType::Skip {
476 ttype = TransformType::None;
477 } else if size >= 32 {
478 ttype = TransformType::T16X16;
479 } else if size == 16 {
480 if (cu_type == CUType::Intra) || (pu_type == PUType::Full) {
481 ttype = TransformType::T16X16;
482 } else {
483 ttype = TransformType::T4X4;
484 }
485 } else {
486 if pu_type == PUType::Full {
487 ttype = TransformType::T8X8;
488 } else {
489 ttype = TransformType::T4X4;
490 }
491 }
492 Ok(Self {
493 cu_type, pu_type, ttype, imode, mv,
494 })
495 }
496 fn read_intra_mode(br: &mut BitReader) -> DecoderResult<IntraMode> {
497 if br.read_bool()? {
498 let idx = br.read_code(UintCodeType::Unary012)? as u8;
499 Ok(IntraMode::Index(idx))
500 } else {
501 let mode = br.read(5)? as u8;
502 Ok(IntraMode::Mode(mode))
503 }
504 }
505 fn read_mv_data(br: &mut BitReader, ftype: FrameType, two_f_refs: bool, size: usize, pu_type: PUType, mv: &mut [MVInfo; 4]) -> DecoderResult<()> {
506 let mv_count = pu_type.get_num_mvs();
507 for i in 0..mv_count {
508 mv[i] = CBHeader::read_mv_info(br, ftype, two_f_refs, size, pu_type)?;
509 }
510 Ok(())
511 }
512 fn read_mv_info(br: &mut BitReader, ftype: FrameType, two_f_refs: bool, size: usize, pu_type: PUType) -> DecoderResult<MVInfo> {
513 let mut f_mv = ZERO_MV;
514 let mut b_mv = ZERO_MV;
515 let mvref;
516 if ftype != FrameType::B {
517 if two_f_refs && br.read_bool()? {
518 mvref = MVRef::Ref1;
519 } else {
520 mvref = MVRef::Ref0;
521 }
522 f_mv = CBHeader::read_mv(br)?;
523 Ok(MVInfo { f_mv, b_mv: ZERO_MV, mvref })
524 } else {
525 if ((size <= 8) && ((size != 8) || (pu_type != PUType::Full))) || br.read_bool()? {
526 if !br.read_bool()? {
527 mvref = MVRef::Ref0;
528 f_mv = CBHeader::read_mv(br)?;
529 } else {
530 mvref = MVRef::BRef;
531 b_mv = CBHeader::read_mv(br)?;
532 }
533 } else {
534 mvref = MVRef::Ref0AndBRef;
535 f_mv = CBHeader::read_mv(br)?;
536 b_mv = CBHeader::read_mv(br)?;
537 }
538 Ok(MVInfo { f_mv, b_mv, mvref })
539 }
540 }
541 fn read_mv(br: &mut BitReader) -> DecoderResult<MV> {
542 let x = br.read_code_signed(IntCodeType::Gamma)? as i16;
543 let y = br.read_code_signed(IntCodeType::Gamma)? as i16;
544 Ok(MV { x, y })
545 }
546}
547
548#[derive(Clone,Copy,Default)]
549struct PUInfo {
550 cu_type: CUType,
551 ttype: TransformType,
552}
553
554impl PUInfo {
555 fn is_intra(&self) -> bool { self.cu_type == CUType::Intra }
556}
557
558const RV60_CANDIDATE_INTRA_ANGLES: [u8; 6] = [ 0, 1, 10, 26, 18, 2 ];
559
560#[derive(Clone,Copy,Default)]
561struct BlockInfo {
562 mv: MVInfo,
563 imode: u8,
564}
565
566struct DeblockInfo {
567 left_str: Vec<u8>,
568 top_str: Vec<u8>,
569 stride: usize,
570}
571
572impl DeblockInfo {
573 fn new() -> Self {
574 Self { left_str: Vec::new(), top_str: Vec::new(), stride: 0 }
575 }
576 fn reinit(&mut self, w: usize, h: usize) {
577 self.left_str.clear();
578 self.top_str.clear();
579 self.stride = w >> 2;
580 let size = self.stride * (h >> 2);
581 self.left_str.resize(size, 0);
582 self.top_str.resize(size, 0);
583 }
584 fn set_strength(&mut self, xpos: usize, ypos: usize, size: usize, q: u8, strength: u8) {
585 let pos = self.get_pos(xpos, ypos);
586 let dsize = size >> 2;
587 let dval = (q << 2) | strength;
588 for x in 0..dsize {
589 self.top_str[pos + x] = dval;
590 }
591 for y in 0..dsize {
592 self.left_str[pos + y * self.stride] = dval;
593 }
594 }
595 fn get_pos(&self, xpos: usize, ypos: usize) -> usize {
596 (xpos >> 2) + (ypos >> 2) * self.stride
597 }
598 fn get_top_strength(&self, pos: usize) -> u8 {
599 self.top_str[pos] & 3
600 }
601 fn get_left_strength(&self, pos: usize) -> u8 {
602 self.left_str[pos] & 3
603 }
604 fn set_top_strength(&mut self, pos: usize, str: u8) {
605 self.top_str[pos] |= str;
606 }
607 fn set_left_strength(&mut self, pos: usize, str: u8) {
608 self.left_str[pos] |= str;
609 }
610}
611
612struct RealVideo60Decoder {
613 info: Rc<NACodecInfo>,
614 cbs: RV60Codebooks,
615 ipbs: IPBShuffler,
616 dsp: RV60DSP,
617 ipred: IntraPredContext,
618
619 avg_buf: NAVideoBuffer<u8>,
620
621 y_coeffs: [i16; 16 * 16],
622 u_coeffs: [i16; 8 * 8],
623 v_coeffs: [i16; 8 * 8],
624 qp: u8,
625 sel_qp: u8,
626
627 cu_splits: Vec<bool>,
628 coded_blk: [bool; 64],
629 dblk: DeblockInfo,
630
631 pu_info: Vec<PUInfo>,
632 pu_stride: usize,
633 pu_pos: usize,
634
635 blk_info: Vec<BlockInfo>,
636 blk_stride: usize,
637 blk_pos: usize,
638
639 xpos: usize,
640 ypos: usize,
641}
642
643impl RealVideo60Decoder {
644 fn new() -> Self {
645 let tmp_vinfo = NAVideoInfo::new(64, 64, false, YUV420_FORMAT);
b70cc006 646 let vt = alloc_video_buffer(tmp_vinfo, 4).unwrap();
52aad9fe
KS
647 let vb = vt.get_vbuf();
648 let avg_buf = vb.unwrap();
649 RealVideo60Decoder{
650 info: Rc::new(DUMMY_CODEC_INFO),
651 cbs: RV60Codebooks::init(),
652 ipbs: IPBShuffler::new(),
653 ipred: IntraPredContext::new(),
654 dsp: RV60DSP::new(),
655 avg_buf: avg_buf,
656 y_coeffs: [0; 16 * 16],
657 u_coeffs: [0; 8 * 8],
658 v_coeffs: [0; 8 * 8],
659 qp: 0,
660 sel_qp: 0,
661 cu_splits: Vec::with_capacity(24),
662 coded_blk: [false; 64],
663 dblk: DeblockInfo::new(),
664 pu_info: Vec::new(),
665 pu_stride: 0,
666 pu_pos: 0,
667 blk_info: Vec::new(),
668 blk_stride: 0,
669 blk_pos: 0,
670 xpos: 0,
671 ypos: 0,
672 }
673 }
cd830591 674 fn decode_cu_line(&mut self, buf: &mut NASimpleVideoFrame<u8>, hdr: &FrameHeader, src: &[u8], cu_y: usize) -> DecoderResult<()> {
52aad9fe
KS
675 let mut br = BitReader::new(src, src.len(), BitReaderMode::BE);
676 let cu_w = hdr.get_width_cu();
677 let dqp = hdr.read_line_qp_offset(&mut br)?;
678 let qps = (hdr.qp as i8) + dqp;
679 validate!((qps >= 0) && (qps < 32));
680 let qp = qps as u8;
681 self.qp = qp;
682 self.sel_qp = match hdr.osvquant {
683 0 => qp,
684 1 => {
685 if qp <= 25 {
686 qp + 5
687 } else {
688 qp
689 }
690 },
691 _ => {
692 if qp <= 18 {
693 qp + 10
694 } else if qp <= 25 {
695 qp + 5
696 } else {
697 qp
698 }
699 },
700 };
701
702 for cu_x in 0..cu_w {
703 self.cu_splits.clear();
704 self.coded_blk = [false; 64];
705 self.decode_cb_tree(buf, hdr, &mut br, cu_x << 6, cu_y << 6, 6)?;
706 if hdr.deblock {
707 self.cu_splits.reverse();
708 self.deblock_cb_tree(buf, hdr, cu_x << 6, cu_y << 6, 6);
709 }
710 }
711if br.left() >= 8 {
712println!(" left {} bits", br.left());
713}
714 Ok(())
715 }
cd830591 716 fn decode_cb_tree(&mut self, buf: &mut NASimpleVideoFrame<u8>, hdr: &FrameHeader, br: &mut BitReader, xpos: usize, ypos: usize, log_size: u8) -> DecoderResult<()> {
52aad9fe
KS
717 if (xpos >= hdr.width) || (ypos >= hdr.height) { return Ok(()); }
718
719 let size = 1 << log_size;
720 let split = (xpos + size > hdr.width) || (ypos + size > hdr.height) || (size > 8 && br.read_bool()?);
721 self.cu_splits.push(split);
722 if split {
723 let hsize = size >> 1;
724 self.decode_cb_tree(buf, hdr, br, xpos, ypos, log_size - 1)?;
725 self.decode_cb_tree(buf, hdr, br, xpos + hsize, ypos, log_size - 1)?;
726 self.decode_cb_tree(buf, hdr, br, xpos, ypos + hsize, log_size - 1)?;
727 self.decode_cb_tree(buf, hdr, br, xpos + hsize, ypos + hsize, log_size - 1)?;
728 } else {
729 let cbh = CBHeader::read(br, hdr.ftype, hdr.two_f_refs, size)?;
730 self.pu_pos = (xpos >> 3) + (ypos >> 3) * self.pu_stride;
731 self.blk_pos = (xpos >> 2) + (ypos >> 2) * self.blk_stride;
732 self.xpos = xpos;
733 self.ypos = ypos;
734 self.reconstruct_info(hdr, &cbh, size)?;
735
736 let split_i4x4 = (cbh.cu_type == CUType::Intra) && (size == 8) && (cbh.pu_type == PUType::Quarters);
737 match cbh.cu_type {
738 CUType::Intra => {
739 let itype = self.blk_info[self.blk_pos].imode;
740 if !split_i4x4 {
cd830591 741 let dstride = buf.stride[0];
52aad9fe 742 let off = xpos + ypos * dstride;
cd830591 743 let dst = &mut buf.data;
52aad9fe
KS
744 self.populate_ipred(hdr, dst, 0, dstride, 0, 0, size, true);
745 self.ipred.pred_angle(dst, off, dstride, size, itype as usize, true);
746 }
747 for comp in 1..3 {
cd830591
KS
748 let dstride = buf.stride[comp];
749 let soff = buf.offset[comp];
52aad9fe 750 let off = soff + (xpos >> 1) + (ypos >> 1) * dstride;
cd830591 751 let mut dst = &mut buf.data;
52aad9fe
KS
752 self.populate_ipred(hdr, dst, soff, dstride, 0, 0, size >> 1, false);
753 self.ipred.pred_angle(&mut dst, off, dstride, size >> 1, itype as usize, false);
754 }
755 },
756 _ => {
757 let mut mv_x = xpos >> 2;
758 let mut mv_y = ypos >> 2;
759 let mut mv_pos = mv_x + mv_y * self.blk_stride;
760 for part_no in 0..cbh.pu_type.get_num_mvs() {
761 let (mv_w, mv_h) = cbh.pu_type.get_mv_size(part_no, size);
762 let mv = self.blk_info[mv_pos].mv;
763 let bw = mv_w << 2;
764 let bh = mv_h << 2;
765 let bx = mv_x << 2;
766 let by = mv_y << 2;
767 match mv.mvref {
768 MVRef::Ref0 => {
769 if hdr.ftype != FrameType::B {
770 if let Some(ref prevbuf) = self.ipbs.get_lastref() {
771 self.dsp.do_mc(buf, prevbuf, bx, by, bw, bh, mv.f_mv, false);
772 }
773 } else {
774 if let Some(ref prevbuf) = self.ipbs.get_b_fwdref() {
775 self.dsp.do_mc(buf, prevbuf, bx, by, bw, bh, mv.f_mv, false);
776 }
777 }
778 },
779 MVRef::Ref1 => {
780 if let Some(ref prevbuf) = self.ipbs.get_nextref() {
781 self.dsp.do_mc(buf, prevbuf, bx, by, bw, bh, mv.f_mv, false);
782 }
783 },
784 MVRef::BRef => {
785 validate!(hdr.ftype == FrameType::B);
786 if let Some(ref prevbuf) = self.ipbs.get_b_bwdref() {
787 self.dsp.do_mc(buf, prevbuf, bx, by, bw, bh, mv.b_mv, false);
788 }
789 },
790 MVRef::Ref0AndBRef => {
791 validate!(hdr.ftype == FrameType::B);
792 if let (Some(ref prevbuf), Some(ref nextbuf)) = (self.ipbs.get_b_fwdref(), self.ipbs.get_b_bwdref()) {
793 self.dsp.do_mc(buf, prevbuf, bx, by, bw, bh, mv.f_mv, false);
cd830591
KS
794 {
795 let mut avg_buf = NASimpleVideoFrame::from_video_buf(&mut self.avg_buf).unwrap();
796 self.dsp.do_mc(&mut avg_buf, nextbuf, bx, by, bw, bh, mv.b_mv, true);
797 }
52aad9fe
KS
798 self.dsp.do_avg(buf, &self.avg_buf, bx, by, bw, bh);
799 }
800 },
801 _ => unreachable!(),
802 };
803 if cbh.pu_type == PUType::Quarters {
804 if part_no != 1 {
805 mv_pos += mv_w;
806 mv_x += mv_w;
807 } else {
808 mv_pos += mv_h * self.blk_stride - mv_w;
809 mv_x -= mv_w;
810 mv_y += mv_h;
811 }
812 } else if cbh.pu_type.has_hor_split() {
813 mv_pos += mv_h * self.blk_stride;
814 mv_y += mv_h;
815 } else if cbh.pu_type.has_ver_split() {
816 mv_pos += mv_w;
817 mv_x += mv_w;
818 }
819 }
820 },
821 };
822 if cbh.ttype != TransformType::None {
823 self.y_coeffs = [0; 16 * 16];
824 self.u_coeffs = [0; 8 * 8];
825 self.v_coeffs = [0; 8 * 8];
826 }
827 let is_intra = cbh.cu_type == CUType::Intra;
828 let cb_pos = ((xpos & 63) >> 3) + ((ypos & 63) >> 3) * 8;
829 match cbh.ttype {
830 TransformType::T4X4 => {
831 let subset = if is_intra { 0 } else { 2 };
832 if size == 16 {
833 let cbp16;
834 if br.read_bool()? {
835 cbp16 = rv6_decode_cbp16(br, &self.cbs, subset, self.sel_qp)?;
836 } else {
837 cbp16 = 0;
838 }
839 if cbp16 != 0 {
840 self.coded_blk[cb_pos + 0] = true;
841 self.coded_blk[cb_pos + 1] = true;
842 self.coded_blk[cb_pos + 8] = true;
843 self.coded_blk[cb_pos + 9] = true;
844 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)?;
845 for y in 0..4 {
846 for x in 0..4 {
847 let i = x + y * 4;
848 if ((cbp16 >> i) & 1) != 0 {
849 self.dsp.transform4x4(&mut self.y_coeffs[i * 16..][..16]);
cd830591 850 let dstride = buf.stride[0];
52aad9fe 851 let off = xpos + x * 4 + (ypos + y * 4) * dstride;
cd830591 852 let mut dst = &mut buf.data;
52aad9fe
KS
853 self.dsp.add_block(&mut dst, off, dstride, &self.y_coeffs[i*16..][..16], 4);
854 }
855 }
856 }
857 for y in 0..2 {
858 for x in 0..2 {
859 let i = x + y * 2;
860 let xoff = (xpos >> 1) + x * 4;
861 let yoff = (ypos >> 1) + y * 4;
862 if ((cbp16 >> (16 + i)) & 1) != 0 {
863 self.dsp.transform4x4(&mut self.u_coeffs[i * 16..][..16]);
cd830591
KS
864 let dstride = buf.stride[1];
865 let off = buf.offset[1] + xoff + yoff * dstride;
866 let mut dst = &mut buf.data;
52aad9fe
KS
867 self.dsp.add_block(&mut dst, off, dstride, &self.u_coeffs[i * 16..][..16], 4);
868 }
869 if ((cbp16 >> (20 + i)) & 1) != 0 {
870 self.dsp.transform4x4(&mut self.v_coeffs[i * 16..][..16]);
cd830591
KS
871 let dstride = buf.stride[2];
872 let off = buf.offset[2] + xoff + yoff * dstride;
873 let mut dst = &mut buf.data;
52aad9fe
KS
874 self.dsp.add_block(&mut dst, off, dstride, &self.v_coeffs[i * 16..][..16], 4);
875 }
876 }
877 }
878 }
879 } else {
880 let cbp8 = rv6_decode_cbp8(br, &self.cbs, subset, self.sel_qp)?;
881 if cbp8 != 0 {
882 self.coded_blk[cb_pos] = true;
883 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)?;
884 }
885 for i in 0..4 {
886 let xoff = (i & 1) * 4;
887 let yoff = (i & 2) * 2;
888 if split_i4x4 {
cd830591 889 let dstride = buf.stride[0];
52aad9fe 890 let off = xpos + xoff + (ypos + yoff) * dstride;
cd830591 891 let mut dst = &mut buf.data;
52aad9fe
KS
892 self.populate_ipred(hdr, dst, 0, dstride, xoff, yoff, 4, true);
893 let itype = self.blk_info[self.blk_pos + (i & 1) + (i >> 1) * self.blk_stride].imode;
894 self.ipred.pred_angle(&mut dst, off, dstride, 4, itype as usize, false);
895 }
896 if ((cbp8 >> i) & 1) != 0 {
897 let blk = &mut self.y_coeffs[i * 16..][..16];
898 self.dsp.transform4x4(blk);
cd830591
KS
899 let dstride = buf.stride[0];
900 let soff = buf.offset[0];
52aad9fe 901 let off = soff + xpos + xoff + (ypos + yoff) * dstride;
cd830591 902 let mut dst = &mut buf.data;
52aad9fe
KS
903 self.dsp.add_block(&mut dst, off, dstride, blk, 4);
904 }
905 }
906 if ((cbp8 >> 4) & 1) != 0 {
907 self.dsp.transform4x4(&mut self.u_coeffs);
cd830591
KS
908 let dstride = buf.stride[1];
909 let soff = buf.offset[1];
52aad9fe 910 let off = soff + (xpos >> 1) + (ypos >> 1) * dstride;
cd830591 911 let mut dst = &mut buf.data;
52aad9fe
KS
912 self.dsp.add_block(&mut dst, off, dstride, &self.u_coeffs, 4);
913 }
914 if ((cbp8 >> 5) & 1) != 0 {
915 self.dsp.transform4x4(&mut self.v_coeffs);
cd830591
KS
916 let dstride = buf.stride[2];
917 let soff = buf.offset[2];
52aad9fe 918 let off = soff + (xpos >> 1) + (ypos >> 1) * dstride;
cd830591 919 let mut dst = &mut buf.data;
52aad9fe
KS
920 self.dsp.add_block(&mut dst, off, dstride, &self.v_coeffs, 4);
921 }
922 }
923 },
924 TransformType::T8X8 => {
925 let subset = if is_intra { 1 } else { 3 };
926 let cbp8 = rv6_decode_cbp8(br, &self.cbs, subset, self.sel_qp)?;
927 if cbp8 != 0 {
928 self.coded_blk[cb_pos] = true;
929 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)?;
930 if (cbp8 & 0xF) != 0 {
931 self.dsp.transform8x8(&mut self.y_coeffs);
cd830591 932 let dstride = buf.stride[0];
52aad9fe 933 let off = xpos + ypos * dstride;
cd830591 934 let mut dst = &mut buf.data;
52aad9fe
KS
935 self.dsp.add_block(&mut dst, off, dstride, &self.y_coeffs, 8);
936 }
937 if ((cbp8 >> 4) & 1) != 0 {
938 self.dsp.transform4x4(&mut self.u_coeffs);
cd830591
KS
939 let dstride = buf.stride[1];
940 let soff = buf.offset[1];
52aad9fe 941 let off = soff + (xpos >> 1) + (ypos >> 1) * dstride;
cd830591 942 let mut dst = &mut buf.data;
52aad9fe
KS
943 self.dsp.add_block(&mut dst, off, dstride, &self.u_coeffs, 4);
944 }
945 if ((cbp8 >> 5) & 1) != 0 {
946 self.dsp.transform4x4(&mut self.v_coeffs);
cd830591
KS
947 let dstride = buf.stride[2];
948 let soff = buf.offset[2];
52aad9fe 949 let off = soff + (xpos >> 1) + (ypos >> 1) * dstride;
cd830591 950 let mut dst = &mut buf.data;
52aad9fe
KS
951 self.dsp.add_block(&mut dst, 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);
cd830591 974 let dstride = buf.stride[0];
52aad9fe 975 let off = xpos + x * 16 + (ypos + y * 16) * dstride;
cd830591 976 let mut dst = &mut buf.data;
52aad9fe
KS
977 self.dsp.add_block(&mut dst, off, dstride, &self.y_coeffs, 16);
978 }
979 if ((super_cbp >> 16) & 0xF) != 0 {
980 self.dsp.transform8x8(&mut self.u_coeffs);
cd830591
KS
981 let dstride = buf.stride[1];
982 let soff = buf.offset[1];
52aad9fe 983 let off = soff + (xpos >> 1) + x * 8 + ((ypos >> 1) + y * 8) * dstride;
cd830591 984 let mut dst = &mut buf.data;
52aad9fe
KS
985 self.dsp.add_block(&mut dst, off, dstride, &self.u_coeffs, 8);
986 }
987 if ((super_cbp >> 20) & 0xF) != 0 {
988 self.dsp.transform8x8(&mut self.v_coeffs);
cd830591
KS
989 let dstride = buf.stride[2];
990 let soff = buf.offset[2];
52aad9fe 991 let off = soff + (xpos >> 1) + x * 8 + ((ypos >> 1) + y * 8) * dstride;
cd830591 992 let mut dst = &mut buf.data;
52aad9fe
KS
993 self.dsp.add_block(&mut dst, off, dstride, &self.v_coeffs, 8);
994 }
995 }
996 }
997 }
998 },
999 _ => {},
1000 };
1001 }
1002 Ok(())
1003 }
1004 fn reconstruct_info(&mut self, hdr: &FrameHeader, cbh: &CBHeader, size: usize) -> DecoderResult<()>{
1005 let mut pui = PUInfo::default();
1006 let pu_size = size >> 3;
1007 pui.cu_type = cbh.cu_type;
1008 pui.ttype = cbh.ttype;
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.into_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.into_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 }
cd830591 1328 fn deblock_cb_tree(&mut self, buf: &mut NASimpleVideoFrame<u8>, hdr: &FrameHeader, xpos: usize, ypos: usize, log_size: u8) {
52aad9fe
KS
1329 if (xpos >= hdr.width) || (ypos >= hdr.height) { return; }
1330 let split = (log_size > 3) && self.cu_splits.pop().unwrap();
1331 if split {
1332 let hsize = 1 << (log_size - 1);
1333 self.deblock_cb_tree(buf, hdr, xpos, ypos, log_size - 1);
1334 self.deblock_cb_tree(buf, hdr, xpos + hsize, ypos, log_size - 1);
1335 self.deblock_cb_tree(buf, hdr, xpos, ypos + hsize, log_size - 1);
1336 self.deblock_cb_tree(buf, hdr, xpos + hsize, ypos + hsize, log_size - 1);
1337 } else {
1338 let pu_pos = (xpos >> 3) + (ypos >> 3) * self.pu_stride;
1339 let cu_type = self.pu_info[pu_pos].cu_type;
1340 let tsize = if self.pu_info[pu_pos].ttype == TransformType::T16X16 { 4 } else { 3 };
1341 let ntiles = 1 << (log_size - tsize);
1342 let dparams = RV60DeblockParams {
1343 deblock_chroma: hdr.deblock_chroma,
1344 width: hdr.width,
1345 height: hdr.height,
1346 dblkstride: self.dblk.stride,
1347 };
1348 for ty in 0..ntiles {
1349 for tx in 0..ntiles {
1350 let x = xpos + (tx << tsize);
1351 let y = ypos + (ty << tsize);
1352 let cb_pos = ((x & 63) >> 3) + ((y & 63) >> 3) * 8;
1353 if cu_type == CUType::Intra {
1354 self.dblk.set_strength(x, y, 1 << tsize, self.qp, 2);
1355 } else if (cu_type != CUType::Skip) && self.coded_blk[cb_pos] {
1356 self.dblk.set_strength(x, y, 1 << tsize, self.qp, 1);
1357 } else {
1358 self.dblk.set_strength(x, y, 1 << tsize, self.qp, 0);
1359 self.derive_deblock_strength(x, y, 1 << (tsize - 2));
1360 }
1361 self.dsp.do_deblock(&dparams, buf, x, y, 1 << tsize,
1362 self.dblk.top_str.as_slice(),
1363 self.dblk.left_str.as_slice(),
1364 self.dblk.get_pos(x, y));
1365 }
1366 }
1367 }
1368 }
1369 fn derive_deblock_strength(&mut self, xpos: usize, ypos: usize, size4: usize) {
1370 let blk_pos = (xpos >> 2) + (ypos >> 2) * self.blk_stride;
1371 let mut dblk_pos = self.dblk.get_pos(xpos, ypos);
1372 if ypos > 0 {
1373 let top_blk_pos = blk_pos - self.blk_stride;
1374 for i in 0..size4 {
1375 if self.dblk.get_top_strength(dblk_pos + i) == 0 {
1376 if self.blk_info[blk_pos + i].mv.is_deblock_cand(&self.blk_info[top_blk_pos + i].mv) {
1377 self.dblk.set_top_strength(dblk_pos + i, 1);
1378 }
1379 }
1380 }
1381 }
1382 if xpos > 0 {
1383 for i in 0..size4 {
1384 if self.dblk.get_left_strength(dblk_pos) == 0 {
1385 if self.blk_info[blk_pos + i].mv.is_deblock_cand(&self.blk_info[blk_pos + i - 1].mv) {
1386 self.dblk.set_left_strength(dblk_pos, 1);
1387 }
1388 }
1389 dblk_pos += self.dblk.stride;
1390 }
1391 }
1392 }
1393}
1394
1395impl NADecoder for RealVideo60Decoder {
1396 fn init(&mut self, info: Rc<NACodecInfo>) -> DecoderResult<()> {
1397 if let NACodecTypeInfo::Video(_vinfo) = info.get_properties() {
1398 let fmt = YUV420_FORMAT;
1399 let myinfo = NACodecTypeInfo::Video(NAVideoInfo::new(0, 0, false, fmt));
1400 self.info = Rc::new(NACodecInfo::new_ref(info.get_name(), myinfo, info.get_extradata()));
1401
1402 let edata = info.get_extradata().unwrap();
1403 let src: &[u8] = &edata;
1404
1405 if src.len() < 8 { return Err(DecoderError::InvalidData); }
1406 let mut mr = MemoryReader::new_read(src);
1407 let mut br = ByteReader::new(&mut mr);
1408 let _flags = br.read_u32be()?;
1409 let version = br.read_u32be()?;
1410 let _unk = br.read_u16be()?;
1411 validate!((version >> 28) == 4);
1412 // then width and height again as 16be
1413
1414 //self.bd.width = vinfo.get_width();
1415 //self.bd.height = vinfo.get_height();
1416 //self.frmmgr.clear();
1417 Ok(())
1418 } else {
1419println!("???");
1420 Err(DecoderError::InvalidData)
1421 }
1422 }
1423 fn decode(&mut self, pkt: &NAPacket) -> DecoderResult<NAFrameRef> {
1424 let src = pkt.get_buffer();
1425
1426 validate!(src.len() > 9);
1427 let hsize = (src[0] as usize) * 8 + 9;
1428 let mut br = BitReader::new(&src[hsize..], src.len() - hsize, BitReaderMode::BE);
1429 let hdr = FrameHeader::read(&mut br)?;
1430 let mut slices: Vec<usize> = Vec::new();
1431 hdr.parse_slice_sizes(&mut br, &mut slices)?;
1432
1433 let tmp_vinfo = NAVideoInfo::new(hdr.width, hdr.height, false, YUV420_FORMAT);
1434 let res = alloc_video_buffer(tmp_vinfo, 6);
1435 if !res.is_ok() { return Err(DecoderError::InvalidData); }
b70cc006 1436 let bufinfo = res.unwrap();
52aad9fe
KS
1437 let mut buf = bufinfo.get_vbuf().unwrap();
1438
1439 let cu_w = hdr.get_width_cu();
1440 let cu_h = hdr.get_height_cu();
1441 self.pu_stride = cu_w << 3;
1442 self.pu_info.resize(self.pu_stride * (cu_h << 3), PUInfo::default());
1443 self.blk_stride = cu_w << 4;
1444 self.blk_info.truncate(0);
1445 self.blk_info.resize(self.blk_stride * (cu_h << 4), BlockInfo::default());
1446 if hdr.deblock {
1447 self.dblk.reinit(hdr.width, hdr.height);
1448 }
1449 let mut off = hsize + ((br.tell() >> 3) as usize);
cd830591 1450 let mut dframe = NASimpleVideoFrame::from_video_buf(&mut buf).unwrap();
52aad9fe 1451 for (cu_y, size) in slices.into_iter().enumerate() {
cd830591 1452 self.decode_cu_line(&mut dframe, &hdr, &src[off..][..size], cu_y)?;
52aad9fe
KS
1453 off += size;
1454 }
1455 if (hdr.ftype == FrameType::I) || (hdr.ftype == FrameType::P) {
1456 self.ipbs.add_frame(buf);
1457 }
1458
1459 let mut frm = NAFrame::new_from_pkt(pkt, self.info.clone(), bufinfo);
1460 frm.set_keyframe(hdr.ftype == FrameType::I);
1461 frm.set_pts(Some(hdr.ts as u64));
1462 frm.set_frame_type(hdr.ftype);
1463 Ok(Rc::new(RefCell::new(frm)))
1464 }
1465}
1466
1467pub fn get_decoder() -> Box<NADecoder> {
1468 Box::new(RealVideo60Decoder::new())
1469}
1470
1471#[cfg(test)]
1472mod test {
3167c45c
KS
1473 use nihav_core::codecs::RegisteredDecoders;
1474 use nihav_core::demuxers::RegisteredDemuxers;
1475 use nihav_core::test::dec_video::*;
1476 use crate::codecs::realmedia_register_all_codecs;
1477 use crate::demuxers::realmedia_register_all_demuxers;
52aad9fe
KS
1478 #[test]
1479 fn test_rv60() {
3167c45c
KS
1480 let mut dmx_reg = RegisteredDemuxers::new();
1481 realmedia_register_all_demuxers(&mut dmx_reg);
1482 let mut dec_reg = RegisteredDecoders::new();
1483 realmedia_register_all_codecs(&mut dec_reg);
1484
1485 test_file_decoding("realmedia", "assets/RV/RV60.rmhd", Some(4000), true, false, None/*Some("rv60")*/, &dmx_reg, &dec_reg);
1f7e9371 1486//panic!("end");
52aad9fe
KS
1487 }
1488}