code wiki / (root) / nx_h264_bframe_reflist_gate.nx

nx_h264_bframe_reflist_gate.nx source

↩ module page · 121 lines · 5932 B

1// nx_h264_bframe_reflist_gate.nx -- B-R1: compute POC (display order) for every frame of bframe_test.264 2// and construct each B-slice's L0/L1 reference lists, verified against hand-derived ground truth: 3// POC (decode order) == 0,2,6,4,8,12,10,14,16,20,18,22 4// B@POC4 -> L0[0]=2 L1[0]=6 ; B@POC10 -> L0[0]=8 L1[0]=12 ; B@POC18 -> L0[0]=16 L1[0]=20 5// Exits 0/1. license_tier: ORIGINAL 6import "nx_syscalls.nx" 7import "nx_h264_bits.nx" 8import "nx_h264_sps.nx" 9import "nx_h264_pps.nx" 10import "nx_h264_nal.nx" 11import "nx_h264_slice.nx" 12import "nx_h264_poc.nx" 13import "nx_gate_verdict.nx" 14 15func gp(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } sys_write(1, s, n); return 0 } 16func gn(v: i64) -> i64 { 17 let bb: *u8 = sys_mmap(28); var m: i64 = v 18 if m < 0 { sys_write(1, "-\x00" as *u8, 1); m = 0 - m } 19 let t: *u8 = sys_mmap(28); var k: i64 = 0 20 if m == 0 { t[0] = 48 as u8; k = 1 } 21 while m > 0 { t[k] = (48 + (m % 10)) as u8; m = m / 10; k = k + 1 } 22 var i: i64 = 0 23 while i < k { bb[i] = t[k - 1 - i]; i = i + 1 } 24 sys_write(1, bb, k); return 0 25} 26 27func main() -> i64 { 28 let szp: *i64 = sys_mmap(16) as *i64 29 let b: *u8 = sys_read_file("knowledge/staging/media/bframe_test.264\x00" as *u8, szp) 30 if (b as i64) == 0 { gp("no bframe_test.264\n\x00" as *u8); sys_exit(1); return 1 } 31 let len: i64 = szp[0] 32 gp("B-FRAME-REFLIST-GATE (B-R1: POC + L0/L1)\n\x00" as *u8) 33 34 let offs: *i64 = sys_mmap(512 * 8) as *i64 35 let types: *i64 = sys_mmap(512 * 8) as *i64 36 let nc: i64 = nx_nal_split_annexb(b, 0, len, offs, types, 512) 37 let sps: *i64 = sys_mmap(128) as *i64 38 let pps: *i64 = sys_mmap(128) as *i64 39 var k: i64 = 0 40 while k < nc { 41 let noff: i64 = offs[k] 42 var nend: i64 = len 43 if k + 1 < nc { nend = offs[k + 1] - 3 } 44 if types[k] == 7 { let dst: *u8 = sys_mmap(nend - noff + 16); let rb: i64 = nx_h264_unescape_rbsp((b as i64 + noff + 1) as *u8, nend - noff - 1, dst); nx_h264_parse_sps(dst, rb, sps) } 45 if types[k] == 8 { let dst: *u8 = sys_mmap(nend - noff + 16); let rb: i64 = nx_h264_unescape_rbsp((b as i64 + noff + 1) as *u8, nend - noff - 1, dst); nx_h264_parse_pps(dst, rb, pps) } 46 k = k + 1 47 } 48 let max_poc_lsb: i64 = 1 << sps[11] 49 50 // expected POC (decode order) + expected B L0/L1[0] 51 let expPoc: *i64 = sys_mmap(16 * 8) as *i64 52 expPoc[0]=0; expPoc[1]=2; expPoc[2]=6; expPoc[3]=4; expPoc[4]=8; expPoc[5]=12 53 expPoc[6]=10; expPoc[7]=14; expPoc[8]=16; expPoc[9]=20; expPoc[10]=18; expPoc[11]=22 54 55 let state: *i64 = sys_mmap(16) as *i64 56 state[0] = 0; state[1] = 0 57 // DPB of reference pics (POC + decode idx), in decode order 58 let dpbPoc: *i64 = sys_mmap(64 * 8) as *i64 59 let dpbIdx: *i64 = sys_mmap(64 * 8) as *i64 60 var dpbN: i64 = 0 61 let l0: *i64 = sys_mmap(64 * 8) as *i64 62 let l0i: *i64 = sys_mmap(64 * 8) as *i64 63 let l1: *i64 = sys_mmap(64 * 8) as *i64 64 let l1i: *i64 = sys_mmap(64 * 8) as *i64 65 let sh: *i64 = sys_mmap(64) as *i64 66 67 var ok: i64 = 1 68 var di: i64 = 0 69 var nB: i64 = 0 70 var bmatch: i64 = 0 71 k = 0 72 while k < nc { 73 let isSlice: i64 = (types[k] == 1) as i64 + (types[k] == 5) as i64 74 if isSlice >= 1 { 75 let noff: i64 = offs[k] 76 let hdr: i64 = b[noff] as i64 77 let ntype: i64 = hdr & 31 78 let nref: i64 = (hdr >> 5) & 3 79 var nend: i64 = len 80 if k + 1 < nc { nend = offs[k + 1] - 3 } 81 let dst: *u8 = sys_mmap(nend - noff + 16) 82 let rb: i64 = nx_h264_unescape_rbsp((b as i64 + noff + 1) as *u8, nend - noff - 1, dst) 83 let br: *BitReader = sys_mmap(NX_BR_BYTES) as *BitReader 84 br_init(br, dst, rb) 85 nx_h264_parse_slice_header_br(br, ntype, nref, sps[9], sps[11], sps[10], sps[6], pps[3], pps[6], sh) 86 let is_idr: i64 = (ntype == 5) as i64 87 let poc: i64 = nx_h264_poc_type0(sh[5], max_poc_lsb, is_idr, nref, state) 88 gp(" dec\x00" as *u8); gn(di); gp(" type=\x00" as *u8); gn(sh[8]); gp(" POC=\x00" as *u8); gn(poc) 89 if poc != expPoc[di] { ok = 0; gp(" *POC-MISMATCH(exp \x00" as *u8); gn(expPoc[di]); gp(")\x00" as *u8) } 90 // B-slice: build + check ref lists from DPB so far 91 if sh[8] == 1 { 92 nB = nB + 1 93 nx_h264_build_blists(dpbPoc, dpbIdx, dpbN, poc, l0, l0i, l1, l1i) 94 gp(" L0[0]=\x00" as *u8); gn(l0[0]); gp(" L1[0]=\x00" as *u8); gn(l1[0]) 95 var expL0: i64 = 0 - 1 96 var expL1: i64 = 0 - 1 97 if poc == 4 { expL0 = 2; expL1 = 6 } 98 if poc == 10 { expL0 = 8; expL1 = 12 } 99 if poc == 18 { expL0 = 16; expL1 = 20 } 100 if l0[0] == expL0 { if l1[0] == expL1 { bmatch = bmatch + 1; gp(" OK\x00" as *u8) } } 101 if l0[0] != expL0 { ok = 0; gp(" *L0-BAD\x00" as *u8) } 102 if l1[0] != expL1 { ok = 0; gp(" *L1-BAD\x00" as *u8) } 103 } 104 gp("\n\x00" as *u8) 105 // reference pics (nal_ref_idc != 0) join the DPB 106 if nref != 0 { dpbPoc[dpbN] = poc; dpbIdx[dpbN] = di; dpbN = dpbN + 1 } 107 di = di + 1 108 } 109 k = k + 1 110 } 111 gp(" frames=\x00" as *u8); gn(di); gp(" B=\x00" as *u8); gn(nB); gp(" B-lists-correct=\x00" as *u8); gn(bmatch); gp("/\x00" as *u8); gn(nB); gp("\n\x00" as *u8) 112 // MIGRATED onto nx_gate_verdict by nx_gate_dry_apply (D001, minimal form): every check 113 // row above is untouched, so the PASS/FAIL vector cannot change; only the hand-rolled 114 // verdict emission is replaced by the ONE shared base class. Proven by nx_gate_migrate verify. 115 let ctr__dry: *i64 = gv_ctr() 116 ctr__dry[0] = ok 117 ctr__dry[1] = 1 118 let rc__dry: i64 = gv_verdict("H264-BFRAME-REFLIST-GATE" as *u8, ctr__dry, "POC + B L0/L1 correct)00" as *u8) 119 sys_exit(rc__dry) 120 return rc__dry 121}