code wiki / (root) / nx_h264_fdct.nx

nx_h264_fdct.nx source

↩ module page · 97 lines · 4347 B

1// nx_h264_fdct.nx -- H.264 FORWARD 4x4 integer transform + forward quantization (the ENCODE counterpart of 2// the existing decode-side nx_h264_idct + nx_h264_dequant). This is the core rung of the sovereign H.264 3// ENCODER (R6, for HEVC->H.264 transcode): residual -> coefficients -> quantized levels, validated by 4// round-tripping back through the proven inverse pieces. The core transform Cf (rows then cols): 5// [1 1 1 1; 2 1 -1 -2; 1 -1 -1 1; 1 -2 2 -1], in butterfly form (no floats). Forward quant uses the 6// standard MF[qp%6][posClass] multiplier matrix + dead-zone f, matching the inverse normAdjust/V table so the 7// pair round-trips. Reuses nx_dq_posclass for the position class (DRY, identical to the dequant). ITU-T H.264 8// transform is public -> patent-clean for the integer math. license_tier: ORIGINAL 9import "nx_syscalls.nx" 10import "nx_h264_dequant.nx" // reuse nx_dq_posclass (position class 0/1/2) 11const K_MAGIC_13107: i64 = 13107 12const K_MAGIC_5243: i64 = 5243 13const K_MAGIC_8066: i64 = 8066 14const K_MAGIC_11916: i64 = 11916 15const K_MAGIC_4660: i64 = 4660 16const K_MAGIC_7490: i64 = 7490 17const K_MAGIC_10082: i64 = 10082 18const K_MAGIC_4194: i64 = 4194 19const K_MAGIC_6554: i64 = 6554 20const K_MAGIC_9362: i64 = 9362 21const K_MAGIC_3647: i64 = 3647 22const K_MAGIC_5825: i64 = 5825 23const K_MAGIC_8192: i64 = 8192 24const K_MAGIC_3355: i64 = 3355 25const K_MAGIC_7282: i64 = 7282 26const K_MAGIC_2893: i64 = 2893 27const K_MAGIC_4559: i64 = 4559 28 29// In-place forward core 4x4 transform on d[16] (raster order). Y = Cf * X * Cf^T. 30func nx_h264_fdct4x4(d: *i64) -> i64 { 31 let t: *i64 = sys_mmap(16 * 8) as *i64 32 var i: i64 = 0 33 while i < 4 { 34 let a: i64 = d[i*4+0]; let b: i64 = d[i*4+1]; let c: i64 = d[i*4+2]; let e: i64 = d[i*4+3] 35 let s0: i64 = a + e; let s1: i64 = b + c; let s2: i64 = b - c; let s3: i64 = a - e 36 t[i*4+0] = s0 + s1; t[i*4+1] = 2*s3 + s2; t[i*4+2] = s0 - s1; t[i*4+3] = s3 - 2*s2 37 i = i + 1 38 } 39 var j: i64 = 0 40 while j < 4 { 41 let a: i64 = t[0*4+j]; let b: i64 = t[1*4+j]; let c: i64 = t[2*4+j]; let e: i64 = t[3*4+j] 42 let s0: i64 = a + e; let s1: i64 = b + c; let s2: i64 = b - c; let s3: i64 = a - e 43 d[0*4+j] = s0 + s1; d[1*4+j] = 2*s3 + s2; d[2*4+j] = s0 - s1; d[3*4+j] = s3 - 2*s2 44 j = j + 1 45 } 46 return 0 47} 48 49// forward quant multiplier MF[m][posClass] (m = qp % 6), the spec's standard matrix. 50func nx_h264_fq_mf(m: i64, pc: i64) -> i64 { 51 let tab: *i64 = sys_mmap(18 * 8) as *i64 52 tab[0]=K_MAGIC_13107; tab[1]=K_MAGIC_5243; tab[2]=K_MAGIC_8066 53 tab[3]=K_MAGIC_11916; tab[4]=K_MAGIC_4660; tab[5]=K_MAGIC_7490 54 tab[6]=K_MAGIC_10082; tab[7]=K_MAGIC_4194; tab[8]=K_MAGIC_6554 55 tab[9]=K_MAGIC_9362; tab[10]=K_MAGIC_3647; tab[11]=K_MAGIC_5825 56 tab[12]=K_MAGIC_8192; tab[13]=K_MAGIC_3355; tab[14]=K_MAGIC_5243 57 tab[15]=K_MAGIC_7282; tab[16]=K_MAGIC_2893; tab[17]=K_MAGIC_4559 58 return tab[m * 3 + pc] 59} 60 61// Forward quantize the 16 core-transformed coeffs c[] at qp into out[] (levels). Dead-zone f = (1<<qbits)/3 62// (intra). |Z| = (|W|*MF + f) >> qbits ; qbits = 15 + qp/6. Sign preserved. 63func nx_h264_fquant4x4(c: *i64, qp: i64, out: *i64) -> i64 { 64 let m: i64 = qp % 6 65 let qbits: i64 = 15 + qp / 6 66 let f: i64 = (1 << qbits) / 3 67 var i: i64 = 0 68 while i < 4 { 69 var j: i64 = 0 70 while j < 4 { 71 let pc: i64 = nx_dq_posclass(i, j) 72 let mf: i64 = nx_h264_fq_mf(m, pc) 73 let idx: i64 = i * 4 + j 74 let w: i64 = c[idx] 75 var a: i64 = w; if a < 0 { a = 0 - a } 76 var z: i64 = (a * mf + f) >> qbits 77 if w < 0 { z = 0 - z } 78 out[idx] = z 79 j = j + 1 80 } 81 i = i + 1 82 } 83 return 0 84} 85 86// Forward 4x4 zig-zag scan: scan[i] = raster[ZZ[i]] (raster -> CAVLC scan order; the inverse permutation of 87// nx_h264_inv_zigzag4x4, ZZ = spec Table 8-12). The encoder feeds these scan-order levels to the CAVLC encoder. 88func nx_h264_fwd_zigzag4x4(raster: *i64, scan: *i64) -> i64 { 89 let zz: *i64 = sys_mmap(16 * 8) as *i64 90 zz[0]=0; zz[1]=1; zz[2]=4; zz[3]=8 91 zz[4]=5; zz[5]=2; zz[6]=3; zz[7]=6 92 zz[8]=9; zz[9]=12; zz[10]=13; zz[11]=10 93 zz[12]=7; zz[13]=11; zz[14]=14; zz[15]=15 94 var i: i64 = 0 95 while i < 16 { scan[i] = raster[zz[i]]; i = i + 1 } 96 return 0 97}