code wiki / (root) / nx_h264_mc_luma.nx

nx_h264_mc_luma.nx source

↩ module page · 83 lines · 4644 B

1// nx_h264_mc_luma.nx -- H.264 luma quarter-pel motion-compensated interpolation (spec 8.4.2.2.1). 2// Half-pel = 6-tap (1,-5,20,20,-5,1); quarter-pel = bilinear average of integer/half-pel samples; 3// center (2,2) = 6-tap on the UNROUNDED horizontal half-pel intermediates ((.+512)>>10). Edge 4// samples are clamped (full-sample padding). Given a reference plane + integer pos (x,y) + frac 5// (xf,yf in 0..3), returns one predicted luma sample. 6// genealogy_id: itu_t_h264_sec8_4_2_2_1_luma_interp 7// lineage_id: sixtap_halfpel + bilinear_quarterpel + center_2pass 8// license_tier: ORIGINAL 9import "nx_syscalls.nx" 10 11func mc_clip1(v: i64) -> i64 { if v < 0 { return 0 } if v > 255 { return 255 } return v } 12func mc_tap6(a: i64, b: i64, c: i64, d: i64, e: i64, f: i64) -> i64 { 13 return a - 5 * b + 20 * c + 20 * d - 5 * e + f 14} 15// clamped integer sample access 16func mc_rc(ref: *u8, W: i64, H: i64, x: i64, y: i64) -> i64 { 17 var xx: i64 = x 18 if xx < 0 { xx = 0 } 19 if xx > W - 1 { xx = W - 1 } 20 var yy: i64 = y 21 if yy < 0 { yy = 0 } 22 if yy > H - 1 { yy = H - 1 } 23 return ref[yy * W + xx] as i64 24} 25// unrounded horizontal 6-tap at (x,y): half-pel between (x,y) and (x+1,y) 26func mc_hc(ref: *u8, W: i64, H: i64, x: i64, y: i64) -> i64 { 27 return mc_tap6(mc_rc(ref,W,H,x-2,y), mc_rc(ref,W,H,x-1,y), mc_rc(ref,W,H,x,y), 28 mc_rc(ref,W,H,x+1,y), mc_rc(ref,W,H,x+2,y), mc_rc(ref,W,H,x+3,y)) 29} 30// unrounded vertical 6-tap at (x,y): half-pel between (x,y) and (x,y+1) 31func mc_vc(ref: *u8, W: i64, H: i64, x: i64, y: i64) -> i64 { 32 return mc_tap6(mc_rc(ref,W,H,x,y-2), mc_rc(ref,W,H,x,y-1), mc_rc(ref,W,H,x,y), 33 mc_rc(ref,W,H,x,y+1), mc_rc(ref,W,H,x,y+2), mc_rc(ref,W,H,x,y+3)) 34} 35func mc_halfH(ref: *u8, W: i64, H: i64, x: i64, y: i64) -> i64 { return mc_clip1((mc_hc(ref,W,H,x,y) + 16) >> 5) } 36func mc_halfV(ref: *u8, W: i64, H: i64, x: i64, y: i64) -> i64 { return mc_clip1((mc_vc(ref,W,H,x,y) + 16) >> 5) } 37// center half-pel (2,2): 6-tap (vertical) on unrounded horizontal intermediates 38func mc_halfHV(ref: *u8, W: i64, H: i64, x: i64, y: i64) -> i64 { 39 let j1: i64 = mc_tap6(mc_hc(ref,W,H,x,y-2), mc_hc(ref,W,H,x,y-1), mc_hc(ref,W,H,x,y), 40 mc_hc(ref,W,H,x,y+1), mc_hc(ref,W,H,x,y+2), mc_hc(ref,W,H,x,y+3)) 41 return mc_clip1((j1 + 512) >> 10) 42} 43 44// one luma sample at integer (x,y) + quarter-pel frac (xf,yf), each 0..3. 45func nx_h264_mc_luma_sample(ref: *u8, W: i64, H: i64, x: i64, y: i64, xf: i64, yf: i64) -> i64 { 46 if xf == 0 { if yf == 0 { return mc_rc(ref,W,H,x,y) } } // G 47 // pure horizontal row (yf==0) 48 if yf == 0 { 49 let bb: i64 = mc_halfH(ref,W,H,x,y) 50 if xf == 2 { return bb } // b 51 if xf == 1 { return (mc_rc(ref,W,H,x,y) + bb + 1) >> 1 } // a 52 return (mc_rc(ref,W,H,x+1,y) + bb + 1) >> 1 // c (xf==3) 53 } 54 // pure vertical col (xf==0) 55 if xf == 0 { 56 let hh: i64 = mc_halfV(ref,W,H,x,y) 57 if yf == 2 { return hh } // h 58 if yf == 1 { return (mc_rc(ref,W,H,x,y) + hh + 1) >> 1 } // d 59 return (mc_rc(ref,W,H,x,y+1) + hh + 1) >> 1 // n (yf==3) 60 } 61 // center column (xf==2) 62 if xf == 2 { 63 let j: i64 = mc_halfHV(ref,W,H,x,y) 64 if yf == 2 { return j } // j 65 if yf == 1 { return (mc_halfH(ref,W,H,x,y) + j + 1) >> 1 } // f 66 return (j + mc_halfH(ref,W,H,x,y+1) + 1) >> 1 // q (yf==3) 67 } 68 // center row (yf==2) 69 if yf == 2 { 70 let j: i64 = mc_halfHV(ref,W,H,x,y) 71 if xf == 1 { return (mc_halfV(ref,W,H,x,y) + j + 1) >> 1 } // i 72 return (j + mc_halfV(ref,W,H,x+1,y) + 1) >> 1 // k (xf==3) 73 } 74 // true diagonals (xf in {1,3}, yf in {1,3}) 75 let bxy: i64 = mc_halfH(ref,W,H,x,y) // b (x+0.5, y) 76 let bxy1: i64 = mc_halfH(ref,W,H,x,y+1) // s (x+0.5, y+1) 77 let vxy: i64 = mc_halfV(ref,W,H,x,y) // h (x, y+0.5) 78 let vx1y: i64 = mc_halfV(ref,W,H,x+1,y) // m (x+1, y+0.5) 79 if xf == 1 { if yf == 1 { return (bxy + vxy + 1) >> 1 } } // e 80 if xf == 3 { if yf == 1 { return (bxy + vx1y + 1) >> 1 } } // g 81 if xf == 1 { if yf == 3 { return (vxy + bxy1 + 1) >> 1 } } // p 82 return (vx1y + bxy1 + 1) >> 1 // r (3,3) 83}