nx_h264_intra.nx source
↩ module page · 111 lines · 5458 B
1// nx_h264_intra.nx -- H.264 Intra_4x4 spatial prediction (core modes), the last
2// reconstruction DSP kernel (spec 8.3.1.2). Produces a 4x4 prediction block
3// from neighbour samples; the decoded residual (dequant->idct) is then added and
4// clipped (nx_idct_add_clip) to form the final pixels.
5//
6// mode 0 Vertical : pred[y][x] = top[x] (needs top)
7// mode 1 Horizontal : pred[y][x] = left[y] (needs left)
8// mode 2 DC : both avail -> (sum top + sum left + 4) >> 3
9// top only -> (sum top + 2) >> 2
10// left only -> (sum left + 2) >> 2
11// neither -> 128
12//
13// HONEST scope: the 6 directional modes (3..8: diag-down-left/right, vertical-
14// right, horizontal-down, vertical-left, horizontal-up) are NOT yet implemented
15// (they need top-right + corner + filtered neighbours) -- flagged for a follow-up
16// rung. DC/Vertical/Horizontal are the most common and are exactly gated here.
17//
18// genealogy_id: itu_t_h264_sec8_3_1_2_intra4x4 + spatial_intra_prediction
19// lineage_id: intra4x4_dc_vertical_horizontal
20// license_tier: ORIGINAL
21import "nx_syscalls.nx"
22
23// top[0..3] = samples above, left[0..3] = samples to the left. pred = i64[16].
24func nx_intra4x4_pred(mode: i64, top: *i64, left: *i64, avail_top: i64, avail_left: i64, pred: *i64) -> i64 {
25 if mode == 0 {
26 var y: i64 = 0
27 while y < 4 { var x: i64 = 0; while x < 4 { pred[y * 4 + x] = top[x]; x = x + 1 } y = y + 1 }
28 }
29 if mode == 1 {
30 var y: i64 = 0
31 while y < 4 { var x: i64 = 0; while x < 4 { pred[y * 4 + x] = left[y]; x = x + 1 } y = y + 1 }
32 }
33 if mode == 2 {
34 var dc: i64 = 128
35 let st: i64 = top[0] + top[1] + top[2] + top[3]
36 let sl: i64 = left[0] + left[1] + left[2] + left[3]
37 if avail_top == 1 { if avail_left == 1 { dc = (st + sl + 4) >> 3 } }
38 if avail_top == 1 { if avail_left == 0 { dc = (st + 2) >> 2 } }
39 if avail_top == 0 { if avail_left == 1 { dc = (sl + 2) >> 2 } }
40 var i: i64 = 0
41 while i < 16 { pred[i] = dc; i = i + 1 }
42 }
43 return 0
44}
45
46// neighbour accessors: p[k,-1] (k=-1 -> top-left), p[-1,k] (k=-1 -> top-left)
47func p4_topx(t: *i64, tl: i64, k: i64) -> i64 { if k < 0 { return tl } return t[k] }
48func p4_left(l: *i64, tl: i64, k: i64) -> i64 { if k < 0 { return tl } return l[k] }
49
50// FULL Intra_4x4 predictor, all 9 modes (spec 8.3.1.2.1-9).
51// t[0..7] = p[0..7,-1] (top + top-right; caller substitutes t[4..7]=t[3] when TR
52// unavailable). l[0..3] = p[-1,0..3]. tl = p[-1,-1].
53// All taps are weighted averages of non-negative samples -> plain >> is exact.
54func nx_intra4x4_pred_full(mode: i64, t: *i64, l: *i64, tl: i64, avail_top: i64, avail_left: i64, pred: *i64) -> i64 {
55 if mode < 3 { return nx_intra4x4_pred(mode, t, l, avail_top, avail_left, pred) }
56 var y: i64 = 0
57 while y < 4 {
58 var x: i64 = 0
59 while x < 4 {
60 var v: i64 = 0
61 if mode == 3 {
62 v = (t[x+y] + 2*t[x+y+1] + t[x+y+2] + 2) >> 2
63 if x == 3 { if y == 3 { v = (t[6] + 3*t[7] + 2) >> 2 } }
64 }
65 if mode == 4 {
66 if x > y { v = (p4_topx(t,tl,x-y-2) + 2*p4_topx(t,tl,x-y-1) + p4_topx(t,tl,x-y) + 2) >> 2 }
67 if x < y { v = (p4_left(l,tl,y-x-2) + 2*p4_left(l,tl,y-x-1) + p4_left(l,tl,y-x) + 2) >> 2 }
68 if x == y { v = (t[0] + 2*tl + l[0] + 2) >> 2 }
69 }
70 if mode == 5 {
71 let zVR: i64 = 2*x - y
72 if zVR == 0 - 1 { v = (l[0] + 2*tl + t[0] + 2) >> 2 }
73 if zVR < 0 - 1 { v = (p4_left(l,tl,y-1) + 2*p4_left(l,tl,y-2) + p4_left(l,tl,y-3) + 2) >> 2 }
74 if zVR >= 0 {
75 let ix: i64 = x - (y >> 1)
76 if (zVR % 2) == 0 { v = (p4_topx(t,tl,ix-1) + p4_topx(t,tl,ix) + 1) >> 1 }
77 if (zVR % 2) == 1 { v = (p4_topx(t,tl,ix-2) + 2*p4_topx(t,tl,ix-1) + p4_topx(t,tl,ix) + 2) >> 2 }
78 }
79 }
80 if mode == 6 {
81 let zHD: i64 = 2*y - x
82 if zHD == 0 - 1 { v = (l[0] + 2*tl + t[0] + 2) >> 2 }
83 if zHD < 0 - 1 { v = (p4_topx(t,tl,x-1) + 2*p4_topx(t,tl,x-2) + p4_topx(t,tl,x-3) + 2) >> 2 }
84 if zHD >= 0 {
85 let iy: i64 = y - (x >> 1)
86 if (zHD % 2) == 0 { v = (p4_left(l,tl,iy-1) + p4_left(l,tl,iy) + 1) >> 1 }
87 if (zHD % 2) == 1 { v = (p4_left(l,tl,iy-2) + 2*p4_left(l,tl,iy-1) + p4_left(l,tl,iy) + 2) >> 2 }
88 }
89 }
90 if mode == 7 {
91 let ix: i64 = x + (y >> 1)
92 if (y % 2) == 0 { v = (t[ix] + t[ix+1] + 1) >> 1 }
93 if (y % 2) == 1 { v = (t[ix] + 2*t[ix+1] + t[ix+2] + 2) >> 2 }
94 }
95 if mode == 8 {
96 let zHU: i64 = x + 2*y
97 if zHU > 5 { v = l[3] }
98 if zHU == 5 { v = (l[2] + 3*l[3] + 2) >> 2 }
99 if zHU < 5 {
100 let iy: i64 = y + (x >> 1)
101 if (zHU % 2) == 0 { v = (p4_left(l,tl,iy) + p4_left(l,tl,iy+1) + 1) >> 1 }
102 if (zHU % 2) == 1 { v = (p4_left(l,tl,iy) + 2*p4_left(l,tl,iy+1) + p4_left(l,tl,iy+2) + 2) >> 2 }
103 }
104 }
105 pred[y * 4 + x] = v
106 x = x + 1
107 }
108 y = y + 1
109 }
110 return 0
111}