code wiki / (root) / nx_h264_intra.nx

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}