code wiki / (root) / nx_h264_colmv_gate.nx

nx_h264_colmv_gate.nx source

↩ module page · 125 lines · 5705 B

1// nx_h264_colmv_gate.nx -- verify the co-located MV-field decoder: decode the future-anchor P-slice 2// (POC 6 = RefPicList1[0] of the first B-slice) of bframe_test.264 via nx_h264_pslice_mvfield and confirm 3// the reader lands at the rbsp end (entropy sync) + report the per-4x4 MV field stats. Exit 0/1. 4import "nx_syscalls.nx" 5import "nx_h264_bits.nx" 6import "nx_h264_sps.nx" 7import "nx_h264_pps.nx" 8import "nx_h264_nal.nx" 9import "nx_h264_slice.nx" 10import "nx_h264_poc.nx" 11import "nx_h264_pmvfield.nx" 12 13func gp(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } sys_write(1, s, n); return 0 } 14func gn(v: i64) -> i64 { 15 let bb: *u8 = sys_mmap(28); var m: i64 = v 16 if m < 0 { sys_write(1, "-\x00" as *u8, 1); m = 0 - m } 17 let t: *u8 = sys_mmap(28); var k: i64 = 0 18 if m == 0 { t[0] = 48 as u8; k = 1 } 19 while m > 0 { t[k] = (48 + (m % 10)) as u8; m = m / 10; k = k + 1 } 20 var i: i64 = 0 21 while i < k { bb[i] = t[k - 1 - i]; i = i + 1 } 22 sys_write(1, bb, k); return 0 23} 24 25func main() -> i64 { 26 let szp: *i64 = sys_mmap(16) as *i64 27 let b: *u8 = sys_read_file("knowledge/staging/media/bframe_test.264\x00" as *u8, szp) 28 if (b as i64) == 0 { gp("no bframe_test.264\n\x00" as *u8); sys_exit(1); return 1 } 29 let len: i64 = szp[0] 30 gp("COLMV-GATE (decode future-anchor POC6 MV field)\n\x00" as *u8) 31 let offs: *i64 = sys_mmap(512 * 8) as *i64 32 let types: *i64 = sys_mmap(512 * 8) as *i64 33 let nc: i64 = nx_nal_split_annexb(b, 0, len, offs, types, 512) 34 let sps: *i64 = sys_mmap(128) as *i64 35 let pps: *i64 = sys_mmap(128) as *i64 36 var k: i64 = 0 37 while k < nc { 38 let noff: i64 = offs[k] 39 var nend: i64 = len 40 if k + 1 < nc { nend = offs[k + 1] - 3 } 41 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) } 42 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) } 43 k = k + 1 44 } 45 let mbW: i64 = sps[2] / 16 46 let mbH: i64 = sps[3] / 16 47 let lbW: i64 = mbW * 4 48 let lbH: i64 = mbH * 4 49 let max_poc_lsb: i64 = 1 << sps[11] 50 let sh: *i64 = sys_mmap(64) as *i64 51 let state: *i64 = sys_mmap(16) as *i64 52 state[0] = 0; state[1] = 0 53 54 // find the slice with POC==6 (the future anchor) 55 var ak: i64 = 0 - 1 56 var aRbsp: i64 = 0 57 let aDst: *u8 = sys_mmap(1) as *u8 58 k = 0 59 while k < nc { 60 let isSlice: i64 = (types[k] == 1) as i64 + (types[k] == 5) as i64 61 if isSlice >= 1 { 62 let noff: i64 = offs[k] 63 let hdr: i64 = b[noff] as i64 64 var nend: i64 = len 65 if k + 1 < nc { nend = offs[k + 1] - 3 } 66 let dst: *u8 = sys_mmap(nend - noff + 16) 67 let rb: i64 = nx_h264_unescape_rbsp((b as i64 + noff + 1) as *u8, nend - noff - 1, dst) 68 let br: *BitReader = sys_mmap(NX_BR_BYTES) as *BitReader 69 br_init(br, dst, rb) 70 nx_h264_parse_slice_header_br(br, hdr & 31, (hdr >> 5) & 3, sps[9], sps[11], sps[10], sps[6], pps[3], pps[6], sh) 71 let is_idr: i64 = (hdr & 31) == 5 72 let poc: i64 = nx_h264_poc_type0(sh[5], max_poc_lsb, is_idr, (hdr >> 5) & 3, state) 73 if poc == 6 { if ak < 0 { if sh[8] == 0 { ak = k } } } 74 } 75 k = k + 1 76 } 77 if ak < 0 { gp("no POC6 P-slice\n\x00" as *u8); sys_exit(1); return 1 } 78 79 let noff: i64 = offs[ak] 80 let hdr: i64 = b[noff] as i64 81 var nend: i64 = len 82 if ak + 1 < nc { nend = offs[ak + 1] - 3 } 83 let sl_dst: *u8 = sys_mmap(nend - noff + 16) 84 let sl_rbsp: i64 = nx_h264_unescape_rbsp((b as i64 + noff + 1) as *u8, nend - noff - 1, sl_dst) 85 let sbr: *BitReader = sys_mmap(NX_BR_BYTES) as *BitReader 86 br_init(sbr, sl_dst, sl_rbsp) 87 nx_h264_parse_slice_header_br(sbr, hdr & 31, (hdr >> 5) & 3, sps[9], sps[11], sps[10], sps[6], pps[3], pps[6], sh) 88 let num_ref: i64 = sh[12] + 1 89 90 let gref: *i64 = sys_mmap(lbW * lbH * 8) as *i64 91 let gmvx: *i64 = sys_mmap(lbW * lbH * 8) as *i64 92 let gmvy: *i64 = sys_mmap(lbW * lbH * 8) as *i64 93 var z: i64 = 0 94 while z < lbW * lbH { gref[z] = 0 - 2; gmvx[z] = 0; gmvy[z] = 0; z = z + 1 } 95 96 let endpos: i64 = nx_h264_pslice_mvfield(sbr, sh[7], num_ref, mbW, mbH, gref, gmvx, gmvy) 97 98 // stats 99 var ninter: i64 = 0 100 var nintra: i64 = 0 101 var nundec: i64 = 0 102 var maxabs: i64 = 0 103 z = 0 104 while z < lbW * lbH { 105 if gref[z] >= 0 { ninter = ninter + 1 } 106 if gref[z] == 0 - 1 { nintra = nintra + 1 } 107 if gref[z] == 0 - 2 { nundec = nundec + 1 } 108 var ax: i64 = gmvx[z]; if ax < 0 { ax = 0 - ax } 109 var ay: i64 = gmvy[z]; if ay < 0 { ay = 0 - ay } 110 if ax > maxabs { maxabs = ax } 111 if ay > maxabs { maxabs = ay } 112 z = z + 1 113 } 114 gp(" POC6 slice QP=\x00" as *u8); gn(sh[7]); gp(" num_ref=\x00" as *u8); gn(num_ref); gp(" rbsp=\x00" as *u8); gn(sl_rbsp); gp("\n\x00" as *u8) 115 gp(" reader end=\x00" as *u8); gn(endpos); gp("/\x00" as *u8); gn(sl_rbsp); gp("\n\x00" as *u8) 116 gp(" MV field: inter4x4=\x00" as *u8); gn(ninter); gp(" intra4x4=\x00" as *u8); gn(nintra); gp(" undecoded=\x00" as *u8); gn(nundec); gp(" max|mv|=\x00" as *u8); gn(maxabs); gp("\n\x00" as *u8) 117 if endpos >= sl_rbsp - 2 { if nundec == 0 { 118 gp(" *** co-located MV field decoded, reader at rbsp end, all 4x4 covered -> GREEN ***\n\x00" as *u8) 119 sys_exit(0) 120 return 0 121 } } 122 gp("COLMV-GATE result=FAIL verdict=RED\n\x00" as *u8) 123 sys_exit(1) 124 return 1 125}