nx_hevc_pred.nx source
↩ module page · 89 lines · 6941 B
1// nx_hevc_pred.nx -- SOVEREIGN HEVC intra prediction, RUNG 4a of the HEVC decoder (Planar + DC).
2// Given reference samples (reconstructed left column + top row + corners), produce the NxN predicted block
3// per H.265 8.4.4.2.4 (Planar) and 8.4.4.2.5 (DC, with the luma edge filter). Angular (modes 2-34) = R4b.
4// Self-test: flat refs -> flat pred; a top gradient -> Planar interpolates. No third party. license_tier: ORIGINAL
5import "nx_syscalls.nx"
6
7func pe(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} return sys_write(1,s,n) }
8func pn(v: i64) -> i64 { var m: i64=v; if m<0{m=0-m} let b: *u8=sys_mmap(32); var i: i64=32; if m==0{i=i-1;b[i]=(48 as u8)} while m>0{let q: i64=m/10; i=i-1; b[i]=((48+(m-q*10)) as u8); m=q} if v<0{i=i-1;b[i]=(45 as u8)} return sys_write(1,((b as i64)+i) as *u8,32-i) }
9func ilog2(n: i64) -> i64 { var l: i64=0; var v: i64=n; while v>1 {v=v>>1; l=l+1} return l }
10
11// Planar: pred[y*N+x] = ((N-1-x)*refL[y] + (x+1)*refTR + (N-1-y)*refT[x] + (y+1)*refBL + N) >> (log2N+1)
12// refL[0..N-1]=left column, refT[0..N-1]=top row, refTR=p[N][-1] (above-right), refBL=p[-1][N] (left-below).
13func predict_planar(pred: *i64, N: i64, refL: *i64, refT: *i64, refTR: i64, refBL: i64) -> i64 {
14 let log2N: i64=ilog2(N); let sh: i64=log2N+1
15 var y: i64=0
16 while y<N { var x: i64=0; while x<N {
17 pred[y*N+x] = ((N-1-x)*refL[y] + (x+1)*refTR + (N-1-y)*refT[x] + (y+1)*refBL + N) >> sh
18 x=x+1 } y=y+1 }
19 return 0
20}
21// DC: dc = (sum top + sum left + N) >> (log2N+1); pred = dc; luma N<32 -> filter row0/col0/corner.
22func predict_dc(pred: *i64, N: i64, refL: *i64, refT: *i64, cIdx: i64) -> i64 {
23 let log2N: i64=ilog2(N)
24 var s: i64=0; var k: i64=0; while k<N {s=s+refT[k]+refL[k]; k=k+1}
25 let dc: i64=(s+N) >> (log2N+1)
26 var y: i64=0; while y<N { var x: i64=0; while x<N {pred[y*N+x]=dc; x=x+1} y=y+1 }
27 if cIdx==0 { if N<32 {
28 pred[0]=(refL[0]+2*dc+refT[0]+2)>>2
29 var x2: i64=1; while x2<N {pred[x2]=(refT[x2]+3*dc+2)>>2; x2=x2+1}
30 var y2: i64=1; while y2<N {pred[y2*N]=(refL[y2]+3*dc+2)>>2; y2=y2+1}
31 } }
32 return 0
33}
34
35// Angular intra prediction (H.265 8.4.4.2.6). angT=intraPredAngle[mode-2], invT=invAngle[mode-11].
36// refL/refT are the 2N-length extended left/top references; corner=p[-1][-1].
37func predict_angular(pred: *i64, N: i64, mode: i64, refL: *i64, refT: *i64, corner: i64, angT: *i64, invT: *i64) -> i64 {
38 let angle: i64=angT[mode-2]; let B: i64=2*N
39 let ref: *i64=sys_mmap(8*(4*N+16)) as *i64
40 if mode>=18 {
41 ref[B]=corner; var x: i64=0; while x<2*N {ref[B+1+x]=refT[x]; x=x+1}
42 if angle<0 { let inv: i64=invT[mode-11]; let lim: i64=(N*angle)>>5; var xx: i64=0-1; while xx>=lim { let idx: i64=(0-1)+((xx*inv+128)>>8); if idx<0 {ref[B+xx]=corner} else {ref[B+xx]=refL[idx]} xx=xx-1 } }
43 var y: i64=0
44 while y<N { let iIdx: i64=((y+1)*angle)>>5; let iFact: i64=((y+1)*angle)&31; var x2: i64=0
45 while x2<N { if iFact!=0 {pred[y*N+x2]=((32-iFact)*ref[B+x2+iIdx+1]+iFact*ref[B+x2+iIdx+2]+16)>>5} else {pred[y*N+x2]=ref[B+x2+iIdx+1]} x2=x2+1 }
46 y=y+1 }
47 } else {
48 ref[B]=corner; var x: i64=0; while x<2*N {ref[B+1+x]=refL[x]; x=x+1}
49 if angle<0 { let inv: i64=invT[mode-11]; let lim: i64=(N*angle)>>5; var xx: i64=0-1; while xx>=lim { let idx: i64=(0-1)+((xx*inv+128)>>8); if idx<0 {ref[B+xx]=corner} else {ref[B+xx]=refT[idx]} xx=xx-1 } }
50 var x3: i64=0
51 while x3<N { let iIdx: i64=((x3+1)*angle)>>5; let iFact: i64=((x3+1)*angle)&31; var y3: i64=0
52 while y3<N { if iFact!=0 {pred[y3*N+x3]=((32-iFact)*ref[B+y3+iIdx+1]+iFact*ref[B+y3+iIdx+2]+16)>>5} else {pred[y3*N+x3]=ref[B+y3+iIdx+1]} y3=y3+1 }
53 x3=x3+1 }
54 }
55 return 0
56}
57func parse_nums(s: *u8, out: *i64) -> i64 { var n: i64=0; var i: i64=0; var cur: i64=0; var neg: i64=0; var has: i64=0; while s[i]!=(0 as u8){ let c: i64=s[i] as i64; if c==45 {neg=1} else { if c>=48 { if c<=57 {cur=cur*10+(c-48); has=1} else { if has==1{ if neg==1{out[n]=0-cur}else{out[n]=cur} n=n+1; cur=0; has=0; neg=0} } } else { if has==1{ if neg==1{out[n]=0-cur}else{out[n]=cur} n=n+1; cur=0; has=0; neg=0} } } i=i+1 } if has==1{ if neg==1{out[n]=0-cur}else{out[n]=cur} n=n+1} return n }
58
59func main(argc: i64, argv: *i64) -> i64 {
60 let N: i64=8; let pred: *i64=sys_mmap(8*N*N) as *i64
61 let refL: *i64=sys_mmap(8*64) as *i64; let refT: *i64=sys_mmap(8*64) as *i64
62 // test 1: flat refs (512, the 10-bit mid value)
63 var k: i64=0; while k<64 {refL[k]=512; refT[k]=512; k=k+1}
64 predict_planar(pred, N, refL, refT, 512, 512)
65 var flat: i64=1; var j: i64=0; while j<N*N {if pred[j]!=512 {flat=0} j=j+1}
66 pe("Planar flat-ref: pred[0]=" as *u8); pn(pred[0]); pe(" pred[last]=" as *u8); pn(pred[N*N-1]); pe(" all512=" as *u8); pn(flat); pe("\n" as *u8)
67 predict_dc(pred, N, refL, refT, 0)
68 pe("DC flat-ref: dc-interior pred[N+1]=" as *u8); pn(pred[N+1]); pe(" filtered corner pred[0]=" as *u8); pn(pred[0]); pe("\n" as *u8)
69 // test 2: top gradient (refT = 100,200,...,800), left = 100. Planar should interpolate top->bottom.
70 k=0; while k<64 {refT[k]=100*(k+1); refL[k]=100; k=k+1}
71 predict_planar(pred, N, refL, refT, 800, 100)
72 pe("Planar gradient: top row pred[0..2]=" as *u8); pn(pred[0]); pe("," as *u8); pn(pred[1]); pe("," as *u8); pn(pred[2]); pe(" bottom-left pred[(N-1)*N]=" as *u8); pn(pred[(N-1)*N]); pe("\n" as *u8)
73 // ---- R4b: angular ----
74 let angT: *i64=sys_mmap(8*40) as *i64; parse_nums("32 26 21 17 13 9 5 2 0 -2 -5 -9 -13 -17 -21 -26 -32 -26 -21 -17 -13 -9 -5 -2 0 2 5 9 13 17 21 26 32" as *u8, angT)
75 let invT: *i64=sys_mmap(8*20) as *i64; parse_nums("-4096 -1638 -910 -630 -482 -390 -315 -256 -315 -390 -482 -630 -910 -1638 -4096" as *u8, invT)
76 k=0; while k<64 {refT[k]=10*((k%8)+1); refL[k]=100+10*(k%8); k=k+1}
77 predict_angular(pred, N, 26, refL, refT, 0, angT, invT)
78 pe("mode26 vert: pred[0]=" as *u8); pn(pred[0]); pe(" pred[N]=" as *u8); pn(pred[N]); pe(" pred[1]=" as *u8); pn(pred[1]); pe(" (expect 10,10,20)\n" as *u8)
79 var av: i64=1; if pred[0]!=10 {av=0} if pred[N]!=10 {av=0} if pred[1]!=20 {av=0}
80 predict_angular(pred, N, 10, refL, refT, 0, angT, invT)
81 pe("mode10 horiz: pred[0]=" as *u8); pn(pred[0]); pe(" pred[1]=" as *u8); pn(pred[1]); pe(" pred[N]=" as *u8); pn(pred[N]); pe(" (expect 100,100,110)\n" as *u8)
82 if pred[0]!=100 {av=0} if pred[1]!=100 {av=0} if pred[N]!=110 {av=0}
83 predict_angular(pred, N, 34, refL, refT, 0, angT, invT)
84 pe("mode34 diag: pred[0]=" as *u8); pn(pred[0]); pe(" pred[1]=" as *u8); pn(pred[1]); pe(" (expect 20,30)\n" as *u8)
85 if pred[0]!=20 {av=0} if pred[1]!=30 {av=0}
86 var ok: i64=1; if flat==0 {ok=0} if av==0 {ok=0}
87 if ok==1 { pe("R4b OK: Planar+DC+angular intra prediction all match hand-computed values\n" as *u8) } else { pe("R4 BAD (flat=" as *u8); pn(flat); pe(" angular=" as *u8); pn(av); pe(")\n" as *u8) }
88 return 0
89}