code wiki / (root) / nx_hevc_ctx.nx

nx_hevc_ctx.nx source

↩ module page · 44 lines · 4678 B

1// nx_hevc_ctx.nx -- SOVEREIGN HEVC CABAC context-model set, RUNG 3b-1 of the HEVC decoder. 2// The per-syntax-element context models for an I-slice (initType 0): normative initValues (H.265 Tables 3// 9-5..9-37) laid out with named offsets, initialized to (pStateIdx,valMps) via the R2 formula at SliceQpY. 4// These feed R3b-2..5 (coding_quadtree / coding_unit / residual_coding). Self-test: init at QP26, confirm 5// every state in [0,62] and mps in {0,1}. NOTE: the initValue numbers are the normative tables; their exact 6// correctness is proven end-to-end at R6 (first reconstructed frame). No third party. license_tier: ORIGINAL 7import "nx_syscalls.nx" 8 9func pe(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} return sys_write(1,s,n) } 10func 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) } 11func parse_nums(s: *u8, out: *i64) -> i64 { var n: i64=0; var i: i64=0; var cur: i64=0; var has: i64=0; while s[i]!=(0 as u8){ let c: i64=s[i] as i64; if c>=48 { if c<=57 { cur=cur*10+(c-48); has=1 } else { if has==1{out[n]=cur;n=n+1;cur=0;has=0} } } else { if has==1{out[n]=cur;n=n+1;cur=0;has=0} } i=i+1 } if has==1{out[n]=cur;n=n+1} return n } 12func clip3(lo: i64, hi: i64, v: i64) -> i64 { if v<lo {return lo} if v>hi {return hi} return v } 13// init one context model (ctx[2k]=pState ctx[2k+1]=mps) from initValue + SliceQpY (H.265 9.3.2.2) 14func ctx_init1(ctx: *i64, k: i64, iv: i64, qp: i64) -> i64 { 15 let slope: i64=(iv>>4)*5-45; let offs: i64=((iv&15)<<3)-16 16 let pre: i64=clip3(1,126,((slope*clip3(0,51,qp))>>4)+offs) 17 if pre<=63 { ctx[2*k]=63-pre; ctx[2*k+1]=0 } else { ctx[2*k]=pre-64; ctx[2*k+1]=1 } 18 return 0 19} 20 21func main(argc: i64, argv: *i64) -> i64 { 22 var qp: i64=26 23 if argc>=2 { let s: *u8=argv[1] as *u8; var v: i64=0; var i: i64=0; while s[i]!=(0 as u8){ if s[i]>=(48 as u8){ if s[i]<=(57 as u8){ v=v*10+((s[i]-(48 as u8)) as i64) } } i=i+1 } qp=v } 24 // initType-0 (I-slice) initValues in syntax-element order; offsets below index into this. 25 let iv: *i64=sys_mmap(8*256) as *i64 26 let nIv: i64=parse_nums("153 200 139 141 157 154 184 184 63 153 138 138 111 141 94 138 182 154 154 154 154 139 139 110 110 124 125 140 153 125 127 140 109 111 143 127 111 79 108 123 63 110 110 124 125 140 153 125 127 140 109 111 143 127 111 79 108 123 63 91 171 134 141 111 111 125 110 110 94 124 108 124 107 125 141 179 153 125 107 125 141 179 153 125 107 125 141 179 153 125 140 139 182 182 152 136 152 136 153 136 139 111 136 139 111 141 111 140 92 137 138 140 152 138 139 153 74 149 92 139 107 122 152 140 179 166 182 140 227 122 197 138 153 136 167 152 152" as *u8, iv) 27 // named offsets (must match the order above) 28 let OFF_SAO_MERGE: i64=0; let OFF_SAO_TYPE: i64=1; let OFF_SPLIT_CU: i64=2; let OFF_TQ_BYPASS: i64=5 29 let OFF_PART_MODE: i64=6; let OFF_PREV_INTRA: i64=7; let OFF_INTRA_CHROMA: i64=8; let OFF_SPLIT_TF: i64=9 30 let OFF_CBF_LUMA: i64=12; let OFF_CBF_CHROMA: i64=14; let OFF_CU_QP_DELTA: i64=19; let OFF_TSKIP: i64=21 31 let OFF_LAST_X: i64=23; let OFF_LAST_Y: i64=41; let OFF_CODED_SUB: i64=59; let OFF_SIG: i64=63 32 let OFF_G1: i64=107; let OFF_G2: i64=131; let NCTX: i64=137 33 pe("initValues parsed=" as *u8); pn(nIv); pe(" expected NCTX=" as *u8); pn(NCTX); pe("\n" as *u8) 34 if nIv!=NCTX { pe("MISMATCH: initValue count != NCTX -> table layout wrong\n" as *u8); return 1 } 35 let ctx: *i64=sys_mmap(8*2*NCTX) as *i64 36 var k: i64=0; while k<NCTX { ctx_init1(ctx, k, iv[k], qp); k=k+1 } 37 // verify all states valid 38 var bad: i64=0; k=0; while k<NCTX { if ctx[2*k]<0 {bad=bad+1} if ctx[2*k]>62 {bad=bad+1} if ctx[2*k+1]<0 {bad=bad+1} if ctx[2*k+1]>1 {bad=bad+1} k=k+1 } 39 pe("init at QP=" as *u8); pn(qp); pe(": split_cu[0] state=" as *u8); pn(ctx[2*OFF_SPLIT_CU]); pe("/mps=" as *u8); pn(ctx[2*OFF_SPLIT_CU+1]) 40 pe(" sig[0] state=" as *u8); pn(ctx[2*OFF_SIG]); pe(" g1[0] state=" as *u8); pn(ctx[2*OFF_G1]); pe(" prev_intra state=" as *u8); pn(ctx[2*OFF_PREV_INTRA]); pe("\n" as *u8) 41 pe("offsets: SAO_MERGE=" as *u8); pn(OFF_SAO_MERGE); pe(" SPLIT_CU=" as *u8); pn(OFF_SPLIT_CU); pe(" PREV_INTRA=" as *u8); pn(OFF_PREV_INTRA); pe(" LAST_X=" as *u8); pn(OFF_LAST_X); pe(" SIG=" as *u8); pn(OFF_SIG); pe(" G1=" as *u8); pn(OFF_G1); pe(" G2=" as *u8); pn(OFF_G2); pe("\n" as *u8) 42 if bad==0 { pe("R3b-1 OK: " as *u8); pn(NCTX); pe(" contexts initialized, all states valid\n" as *u8) } else { pe("BAD: " as *u8); pn(bad); pe(" invalid states\n" as *u8) } 43 return 0 44}