void VP8CodeIntraModes(VP8Encoder* const enc) { VP8BitWriter* const bw = &enc->bw_; VP8EncIterator it; VP8IteratorInit(enc, &it); do { const VP8MBInfo* const mb = it.mb_; const uint8_t* preds = it.preds_; if (enc->segment_hdr_.update_map_) { PutSegment(bw, mb->segment_, enc->proba_.segments_); } if (enc->proba_.use_skip_proba_) { VP8PutBit(bw, mb->skip_, enc->proba_.skip_proba_); } if (VP8PutBit(bw, (mb->type_ != 0), 145)) { // i16x16 PutI16Mode(bw, preds[0]); } else { const int preds_w = enc->preds_w_; const uint8_t* top_pred = preds - preds_w; int x, y; for (y = 0; y < 4; ++y) { int left = preds[-1]; for (x = 0; x < 4; ++x) { const uint8_t* const probas = kBModesProba[top_pred[x]][left]; left = PutI4Mode(bw, preds[x], probas); } top_pred = preds; preds += preds_w; } } PutUVMode(bw, mb->uv_mode_); } while (VP8IteratorNext(&it)); }
static void PutUVMode(VP8BitWriter* const bw, int uv_mode) { if (VP8PutBit(bw, uv_mode != DC_PRED, 142)) { if (VP8PutBit(bw, uv_mode != V_PRED, 114)) { VP8PutBit(bw, uv_mode != H_PRED, 183); // else: TM_PRED } } }
static void PutI16Mode(VP8BitWriter* const bw, int mode) { if (VP8PutBit(bw, (mode == TM_PRED || mode == H_PRED), 156)) { VP8PutBit(bw, mode == TM_PRED, 128); // TM or HE } else { VP8PutBit(bw, mode == V_PRED, 163); // VE or DC } }
static int PutI4Mode(VP8BitWriter* const bw, int mode, const uint8_t* const prob) { if (VP8PutBit(bw, mode != B_DC_PRED, prob[0])) { if (VP8PutBit(bw, mode != B_TM_PRED, prob[1])) { if (VP8PutBit(bw, mode != B_VE_PRED, prob[2])) { if (!VP8PutBit(bw, mode >= B_LD_PRED, prob[3])) { if (VP8PutBit(bw, mode != B_HE_PRED, prob[4])) { VP8PutBit(bw, mode != B_RD_PRED, prob[5]); } } else { if (VP8PutBit(bw, mode != B_LD_PRED, prob[6])) { if (VP8PutBit(bw, mode != B_VL_PRED, prob[7])) { VP8PutBit(bw, mode != B_HD_PRED, prob[8]); } } } } } } return mode; }
void VP8WriteProbas(VP8BitWriter* const bw, const VP8Proba* const probas) { int t, b, c, p; for (t = 0; t < NUM_TYPES; ++t) { for (b = 0; b < NUM_BANDS; ++b) { for (c = 0; c < NUM_CTX; ++c) { for (p = 0; p < NUM_PROBAS; ++p) { const uint8_t p0 = probas->coeffs_[t][b][c][p]; const int update = (p0 != VP8CoeffsProba0[t][b][c][p]); if (VP8PutBit(bw, update, VP8CoeffsUpdateProba[t][b][c][p])) { VP8PutBits(bw, p0, 8); } } } } } if (VP8PutBitUniform(bw, probas->use_skip_proba_)) { VP8PutBits(bw, probas->skip_proba_, 8); } }
static int PutCoeffs(VP8BitWriter* const bw, int ctx, const VP8Residual* res) { int n = res->first; // should be prob[VP8EncBands[n]], but it's equivalent for n=0 or 1 const uint8_t* p = res->prob[n][ctx]; if (!VP8PutBit(bw, res->last >= 0, p[0])) { return 0; } while (n < 16) { const int c = res->coeffs[n++]; const int sign = c < 0; int v = sign ? -c : c; if (!VP8PutBit(bw, v != 0, p[1])) { p = res->prob[VP8EncBands[n]][0]; continue; } if (!VP8PutBit(bw, v > 1, p[2])) { p = res->prob[VP8EncBands[n]][1]; } else { if (!VP8PutBit(bw, v > 4, p[3])) { if (VP8PutBit(bw, v != 2, p[4])) VP8PutBit(bw, v == 4, p[5]); } else if (!VP8PutBit(bw, v > 10, p[6])) { if (!VP8PutBit(bw, v > 6, p[7])) { VP8PutBit(bw, v == 6, 159); } else { VP8PutBit(bw, v >= 9, 165); VP8PutBit(bw, !(v & 1), 145); } } else { int mask; const uint8_t* tab; if (v < 3 + (8 << 1)) { // VP8Cat3 (3b) VP8PutBit(bw, 0, p[8]); VP8PutBit(bw, 0, p[9]); v -= 3 + (8 << 0); mask = 1 << 2; tab = VP8Cat3; } else if (v < 3 + (8 << 2)) { // VP8Cat4 (4b) VP8PutBit(bw, 0, p[8]); VP8PutBit(bw, 1, p[9]); v -= 3 + (8 << 1); mask = 1 << 3; tab = VP8Cat4; } else if (v < 3 + (8 << 3)) { // VP8Cat5 (5b) VP8PutBit(bw, 1, p[8]); VP8PutBit(bw, 0, p[10]); v -= 3 + (8 << 2); mask = 1 << 4; tab = VP8Cat5; } else { // VP8Cat6 (11b) VP8PutBit(bw, 1, p[8]); VP8PutBit(bw, 1, p[10]); v -= 3 + (8 << 3); mask = 1 << 10; tab = VP8Cat6; } while (mask) { VP8PutBit(bw, !!(v & mask), *tab++); mask >>= 1; } } p = res->prob[VP8EncBands[n]][2]; } VP8PutBitUniform(bw, sign); if (n == 16 || !VP8PutBit(bw, n <= res->last, p[0])) { return 1; // EOB } } return 1; }
static void PutSegment(VP8BitWriter* const bw, int s, const uint8_t* p) { if (VP8PutBit(bw, s >= 2, p[0])) p += 1; VP8PutBit(bw, s & 1, p[1]); }