nx_h264_chroma_pred.nx source
↩ module page · 102 lines · 3624 B
1// nx_h264_chroma_pred.nx -- Intra chroma 8x8 prediction (4:2:0), spec 8.3.4.
2// mode 0 DC : per-quadrant (TL/TR/BL/BR) DC with the spec's availability fallbacks
3// mode 1 Horiz: pred[y][x] = left[y]
4// mode 2 Vert : pred[y][x] = top[x]
5// mode 3 Plane: 8x8 plane fit (multiplier 34), Clip1 to [0,255]
6// top[0..7]=p[x,-1], left[0..7]=p[-1,y], tl=p[-1,-1]. pred = 64 i64 raster.
7//
8// genealogy_id: itu_t_h264_sec8_3_4_intra_chroma
9// lineage_id: intra_chroma_dc_quadrant + plane8x8
10// license_tier: ORIGINAL
11import "nx_syscalls.nx"
12import "nx_h264_idct.nx"
13
14func sum4(a: *i64, off: i64) -> i64 { return a[off] + a[off+1] + a[off+2] + a[off+3] }
15
16// fill one 4x4 quadrant at (qx,qy) in {0,4} with constant dc.
17func fill_quad(pred: *i64, qx: i64, qy: i64, dc: i64) -> i64 {
18 var y: i64 = 0
19 while y < 4 {
20 var x: i64 = 0
21 while x < 4 { pred[(qy + y) * 8 + (qx + x)] = dc; x = x + 1 }
22 y = y + 1
23 }
24 return 0
25}
26
27func nx_intra_chroma_pred(mode: i64, top: *i64, left: *i64, tl: i64, avail_top: i64, avail_left: i64, pred: *i64) -> i64 {
28 if mode == 1 {
29 var y: i64 = 0
30 while y < 8 { var x: i64 = 0; while x < 8 { pred[y*8+x] = left[y]; x = x + 1 } y = y + 1 }
31 return 0
32 }
33 if mode == 2 {
34 var y: i64 = 0
35 while y < 8 { var x: i64 = 0; while x < 8 { pred[y*8+x] = top[x]; x = x + 1 } y = y + 1 }
36 return 0
37 }
38 if mode == 0 {
39 let st0: i64 = sum4(top, 0)
40 let st1: i64 = sum4(top, 4)
41 let sl0: i64 = sum4(left, 0)
42 let sl1: i64 = sum4(left, 4)
43 // TL quadrant
44 var dc: i64 = 128
45 if avail_top == 1 { if avail_left == 1 { dc = (st0 + sl0 + 4) >> 3 } }
46 if avail_top == 1 { if avail_left == 0 { dc = (st0 + 2) >> 2 } }
47 if avail_top == 0 { if avail_left == 1 { dc = (sl0 + 2) >> 2 } }
48 fill_quad(pred, 0, 0, dc)
49 // TR quadrant (prefers top)
50 dc = 128
51 if avail_top == 1 { dc = (st1 + 2) >> 2 }
52 if avail_top == 0 { if avail_left == 1 { dc = (sl0 + 2) >> 2 } }
53 fill_quad(pred, 4, 0, dc)
54 // BL quadrant (prefers left)
55 dc = 128
56 if avail_left == 1 { dc = (sl1 + 2) >> 2 }
57 if avail_left == 0 { if avail_top == 1 { dc = (st0 + 2) >> 2 } }
58 fill_quad(pred, 0, 4, dc)
59 // BR quadrant
60 dc = 128
61 if avail_top == 1 { if avail_left == 1 { dc = (st1 + sl1 + 4) >> 3 } }
62 if avail_top == 1 { if avail_left == 0 { dc = (st1 + 2) >> 2 } }
63 if avail_top == 0 { if avail_left == 1 { dc = (sl1 + 2) >> 2 } }
64 fill_quad(pred, 4, 4, dc)
65 return 0
66 }
67 if mode == 3 {
68 var H: i64 = 0
69 var xp: i64 = 0
70 while xp < 4 {
71 var t2: i64 = tl
72 if 2 - xp >= 0 { t2 = top[2 - xp] }
73 H = H + (xp + 1) * (top[4 + xp] - t2)
74 xp = xp + 1
75 }
76 var V: i64 = 0
77 var yp: i64 = 0
78 while yp < 4 {
79 var l2: i64 = tl
80 if 2 - yp >= 0 { l2 = left[2 - yp] }
81 V = V + (yp + 1) * (left[4 + yp] - l2)
82 yp = yp + 1
83 }
84 let a: i64 = 16 * (left[7] + top[7])
85 let b: i64 = asr(34 * H + 32, 6)
86 let c: i64 = asr(34 * V + 32, 6)
87 var y: i64 = 0
88 while y < 8 {
89 var x: i64 = 0
90 while x < 8 {
91 var v: i64 = asr(a + b * (x - 3) + c * (y - 3) + 16, 5)
92 if v < 0 { v = 0 }
93 if v > 255 { v = 255 }
94 pred[y * 8 + x] = v
95 x = x + 1
96 }
97 y = y + 1
98 }
99 return 0
100 }
101 return 0
102}