code wiki / (root) / nx_hevc_pred.nx

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}