code wiki / (root) / nx_h264_cabac_mb.nx

nx_h264_cabac_mb.nx source

↩ module page · 158 lines · 7973 B

1// nx_h264_cabac_mb.nx -- H.264 CABAC I-slice macroblock syntax (clauses 9.3.2.5, 9.3.3.1.1, Table 9-36). 2// STEP 3, on the KAT-verified engine (nx_h264_cabac.nx, clause 9.3.1) and the residual layer 3// (nx_h264_cabac_residual.nx, gate 8/8). I-slices only: an I-frame poster needs no motion vectors 4// and no inter prediction, which removes most of full CABAC from scope. 5// 6// All ctxIdxOffsets are NAMED (rule 11) and carry their spec table reference, so a wrong constant is 7// reviewable against the standard instead of being a bare number. 8// license_tier: ORIGINAL 9import "nx_syscalls.nx" 10import "nx_h264_cabac.nx" 11import "nx_h264_cabac_ctxinc.nx" 12 13const CMB_OFF_MBTYPE_I: i64 = 3 // Table 9-34: mb_type, I slices 14const CMB_CTX_TERMINATE: i64 = 276 // clause 9.3.3.2.2.3: the end-of-slice / I_PCM terminate context 15const CMB_OFF_CHROMA_PRED: i64 = 64 // Table 9-34: intra_chroma_pred_mode 16const CMB_OFF_PREV_I4: i64 = 68 // Table 9-34: prev_intra4x4_pred_mode_flag 17const CMB_OFF_REM_I4: i64 = 69 // Table 9-34: rem_intra4x4_pred_mode 18const CMB_OFF_CBP_LUMA: i64 = 73 // Table 9-34: coded_block_pattern, luma prefix 19const CMB_OFF_CBP_CHROMA: i64 = 77 // Table 9-34: coded_block_pattern, chroma suffix 20const CMB_MBTYPE_I_NXN: i64 = 0 21const CMB_MBTYPE_I_PCM: i64 = 25 22const CMB_REM_I4_BITS: i64 = 3 // FL binarization, cMax=7 23 24// mb_type for an I slice (Table 9-36 binarization + Table 9-39 ctxIdxInc). 25// condA/condB are condTermFlagA/B: 1 when that neighbour exists and is NOT I_NxN. 26// Returns 0 for I_NxN, 25 for I_PCM, else 1..24 encoding predMode/cbpChroma/cbpLuma. 27func cmb_mbtype_i(cab: *i64, ctx: *i64, rlps: *i64, tlps: *i64, tmps: *i64, condA: i64, condB: i64) -> i64 { 28 let b0: i64 = cab_decision(cab, ctx, CMB_OFF_MBTYPE_I + condA + condB, rlps, tlps, tmps) 29 if b0 == 0 { return CMB_MBTYPE_I_NXN } 30 if cab_terminate(cab) == 1 { return CMB_MBTYPE_I_PCM } 31 let cbpLuma: i64 = cab_decision(cab, ctx, CMB_OFF_MBTYPE_I + 3, rlps, tlps, tmps) 32 let b3: i64 = cab_decision(cab, ctx, CMB_OFF_MBTYPE_I + 4, rlps, tlps, tmps) 33 var cbpChroma: i64 = 0 34 if b3 != 0 { 35 // second chroma bin uses ctxIdxInc 5 ONLY on this branch (Table 9-39 "5,6") 36 let b4: i64 = cab_decision(cab, ctx, CMB_OFF_MBTYPE_I + 5, rlps, tlps, tmps) 37 cbpChroma = 1 + b4 38 } 39 let p0: i64 = cab_decision(cab, ctx, CMB_OFF_MBTYPE_I + 6, rlps, tlps, tmps) 40 let p1: i64 = cab_decision(cab, ctx, CMB_OFF_MBTYPE_I + 7, rlps, tlps, tmps) 41 let predMode: i64 = 2 * p0 + p1 42 return 1 + predMode + 4 * cbpChroma + 12 * cbpLuma 43} 44 45// Does this mb_type mean Intra_16x16? (1..24 are the I_16x16 family) 46func cmb_is_i16x16(mbt: i64) -> i64 { 47 if mbt < 1 { return 0 } 48 if mbt > 24 { return 0 } 49 return 1 50} 51// Decompose an I_16x16 mb_type back into its three fields. 52func cmb_i16_predmode(mbt: i64) -> i64 { if cmb_is_i16x16(mbt) == 0 { return 0 - 1 } return (mbt - 1) % 4 } 53func cmb_i16_cbpchroma(mbt: i64) -> i64 { if cmb_is_i16x16(mbt) == 0 { return 0 - 1 } return ((mbt - 1) / 4) % 3 } 54func cmb_i16_cbpluma(mbt: i64) -> i64 { 55 if cmb_is_i16x16(mbt) == 0 { return 0 - 1 } 56 if (mbt - 1) >= 12 { return 15 } 57 return 0 58} 59 60// prev_intra4x4_pred_mode_flag (single bin, ctxIdxInc 0) 61func cmb_prev_i4(cab: *i64, ctx: *i64, rlps: *i64, tlps: *i64, tmps: *i64) -> i64 { 62 return cab_decision(cab, ctx, CMB_OFF_PREV_I4, rlps, tlps, tmps) 63} 64// rem_intra4x4_pred_mode: FL binarization, 3 bins, all ctxIdxInc 0, LSB first (9.3.2.5) 65func cmb_rem_i4(cab: *i64, ctx: *i64, rlps: *i64, tlps: *i64, tmps: *i64) -> i64 { 66 var v: i64 = 0 67 var i: i64 = 0 68 while i < CMB_REM_I4_BITS { 69 let b: i64 = cab_decision(cab, ctx, CMB_OFF_REM_I4, rlps, tlps, tmps) 70 v = v | (b << i) 71 i = i + 1 72 } 73 return v 74} 75// intra_chroma_pred_mode: TU cMax=3. bin0 ctxIdxInc = condA+condB, bins 1..2 ctxIdxInc = 3. 76func cmb_chroma_pred(cab: *i64, ctx: *i64, rlps: *i64, tlps: *i64, tmps: *i64, condA: i64, condB: i64) -> i64 { 77 if cab_decision(cab, ctx, CMB_OFF_CHROMA_PRED + condA + condB, rlps, tlps, tmps) == 0 { return 0 } 78 if cab_decision(cab, ctx, CMB_OFF_CHROMA_PRED + 3, rlps, tlps, tmps) == 0 { return 1 } 79 if cab_decision(cab, ctx, CMB_OFF_CHROMA_PRED + 3, rlps, tlps, tmps) == 0 { return 2 } 80 return 3 81} 82// coded_block_pattern luma: 4 bins, ctxIdxInc from the two neighbouring cbp bits (9.3.3.1.1.4). 83// condA[i]/condB[i] are 1 when that neighbouring 8x8 has NO coefficients. 84func cmb_cbp_luma(cab: *i64, ctx: *i64, rlps: *i64, tlps: *i64, tmps: *i64, condA: *i64, condB: *i64) -> i64 { 85 var cbp: i64 = 0 86 var i: i64 = 0 87 while i < 4 { 88 let inc: i64 = condA[i] + 2 * condB[i] 89 let b: i64 = cab_decision(cab, ctx, CMB_OFF_CBP_LUMA + inc, rlps, tlps, tmps) 90 cbp = cbp | (b << i) 91 i = i + 1 92 } 93 return cbp 94} 95// coded_block_pattern chroma: bin0 inc = condA+2*condB; if set, bin1 inc = 4 + condA2+2*condB2. 96func cmb_cbp_chroma(cab: *i64, ctx: *i64, rlps: *i64, tlps: *i64, tmps: *i64, 97 condA0: i64, condB0: i64, condA1: i64, condB1: i64) -> i64 { 98 if cab_decision(cab, ctx, CMB_OFF_CBP_CHROMA + condA0 + 2 * condB0, rlps, tlps, tmps) == 0 { return 0 } 99 if cab_decision(cab, ctx, CMB_OFF_CBP_CHROMA + 4 + condA1 + 2 * condB1, rlps, tlps, tmps) == 0 { return 1 } 100 return 2 101} 102 103// ---- ctxBlockCat plumbing (Table 9-34 offsets + clause 9.3.3.1.1.9) ------------------------- 104// These are the BASES the residual layer takes as parameters, so the whole CABAC decoder-side 105// contract lives here and integration is only "call these from the macroblock loop". 106const CMB_OFF_CBF: i64 = 85 // Table 9-34: coded_block_flag base 107const CMB_OFF_SIG: i64 = 105 // significant_coeff_flag base (frame-coded) 108const CMB_OFF_LAST: i64 = 166 // last_significant_coeff_flag base (frame-coded) 109const CMB_OFF_ABS: i64 = 227 // coeff_abs_level_minus1 base 110const CMB_CAT_MAX: i64 = 4 // ctxBlockCat 0..4 for non-8x8 I-slice residual 111 112// ctxBlockCat -> per-category offsets. Cat 0=Intra16x16DC 1=Intra16x16AC 2=Luma4x4 3=ChromaDC 4=ChromaAC 113func cmb_cbf_catoff(cat: i64) -> i64 { 114 if cat < 0 { return 0 - 1 } 115 if cat > CMB_CAT_MAX { return 0 - 1 } 116 return cat * 4 117} 118func cmb_sig_catoff(cat: i64) -> i64 { 119 if cat < 0 { return 0 - 1 } 120 if cat == 0 { return 0 } 121 if cat == 1 { return 15 } 122 if cat == 2 { return 29 } 123 if cat == 3 { return 44 } 124 if cat == 4 { return 47 } 125 return 0 - 1 126} 127func cmb_abs_catoff(cat: i64) -> i64 { 128 if cat < 0 { return 0 - 1 } 129 if cat == 0 { return 0 } 130 if cat == 1 { return 10 } 131 if cat == 2 { return 20 } 132 if cat == 3 { return 30 } 133 if cat == 4 { return 39 } 134 return 0 - 1 135} 136// number of coefficients carried by each category 137func cmb_cat_maxcoeff(cat: i64) -> i64 { 138 if cat == 0 { return 16 } 139 if cat == 1 { return 15 } 140 if cat == 2 { return 16 } 141 if cat == 3 { return 4 } 142 if cat == 4 { return 15 } 143 return 0 - 1 144} 145// absolute context bases to hand to the residual layer 146func cmb_sig_base(cat: i64) -> i64 { let o: i64 = cmb_sig_catoff(cat); if o < 0 { return 0 - 1 } return CMB_OFF_SIG + o } 147func cmb_last_base(cat: i64) -> i64 { let o: i64 = cmb_sig_catoff(cat); if o < 0 { return 0 - 1 } return CMB_OFF_LAST + o } 148func cmb_abs_base(cat: i64) -> i64 { let o: i64 = cmb_abs_catoff(cat); if o < 0 { return 0 - 1 } return CMB_OFF_ABS + o } 149 150// coded_block_flag (9.3.3.1.1.9). condA/condB are 1 when that neighbour block has coefficients; 151// an UNAVAILABLE neighbour contributes 0 for an intra block, which is why the first macroblock of 152// a frame is decodable with condA=condB=0. 153func cmb_coded_block_flag(cab: *i64, ctx: *i64, rlps: *i64, tlps: *i64, tmps: *i64, 154 cat: i64, condA: i64, condB: i64) -> i64 { 155 let o: i64 = cmb_cbf_catoff(cat) 156 if o < 0 { return 0 - 1 } 157 return cab_decision(cab, ctx, CMB_OFF_CBF + o + cci_cbf(condA, condB), rlps, tlps, tmps) 158}