int VP8GetCostLuma16(VP8EncIterator* const it, const VP8ModeScore* const rd) { VP8Residual res; VP8Encoder* const enc = it->enc_; int x, y; int R = 0; VP8IteratorNzToBytes(it); // re-import the non-zero context // DC VP8InitResidual(0, 1, enc, &res); VP8SetResidualCoeffs(rd->y_dc_levels, &res); R += VP8GetResidualCost(it->top_nz_[8] + it->left_nz_[8], &res); // AC VP8InitResidual(1, 0, enc, &res); for (y = 0; y < 4; ++y) { for (x = 0; x < 4; ++x) { const int ctx = it->top_nz_[x] + it->left_nz_[y]; VP8SetResidualCoeffs(rd->y_ac_levels[x + y * 4], &res); R += VP8GetResidualCost(ctx, &res); it->top_nz_[x] = it->left_nz_[y] = (res.last >= 0); } } return R; }
static void CodeResiduals(VP8BitWriter* const bw, VP8EncIterator* const it, const VP8ModeScore* const rd) { int x, y, ch; VP8Residual res; uint64_t pos1, pos2, pos3; const int i16 = (it->mb_->type_ == 1); const int segment = it->mb_->segment_; VP8Encoder* const enc = it->enc_; VP8IteratorNzToBytes(it); pos1 = VP8BitWriterPos(bw); if (i16) { VP8InitResidual(0, 1, enc, &res); VP8SetResidualCoeffs(rd->y_dc_levels, &res); it->top_nz_[8] = it->left_nz_[8] = PutCoeffs(bw, it->top_nz_[8] + it->left_nz_[8], &res); VP8InitResidual(1, 0, enc, &res); } else { VP8InitResidual(0, 3, enc, &res); } // luma-AC for (y = 0; y < 4; ++y) { for (x = 0; x < 4; ++x) { const int ctx = it->top_nz_[x] + it->left_nz_[y]; VP8SetResidualCoeffs(rd->y_ac_levels[x + y * 4], &res); it->top_nz_[x] = it->left_nz_[y] = PutCoeffs(bw, ctx, &res); } } pos2 = VP8BitWriterPos(bw); // U/V VP8InitResidual(0, 2, enc, &res); for (ch = 0; ch <= 2; ch += 2) { for (y = 0; y < 2; ++y) { for (x = 0; x < 2; ++x) { const int ctx = it->top_nz_[4 + ch + x] + it->left_nz_[4 + ch + y]; VP8SetResidualCoeffs(rd->uv_levels[ch * 2 + x + y * 2], &res); it->top_nz_[4 + ch + x] = it->left_nz_[4 + ch + y] = PutCoeffs(bw, ctx, &res); } } } pos3 = VP8BitWriterPos(bw); it->luma_bits_ = pos2 - pos1; it->uv_bits_ = pos3 - pos2; it->bit_count_[segment][i16] += it->luma_bits_; it->bit_count_[segment][2] += it->uv_bits_; VP8IteratorBytesToNz(it); }
static int RecordTokens(VP8EncIterator* const it, const VP8ModeScore* const rd, VP8TBuffer* const tokens) { int x, y, ch; VP8Residual res; VP8Encoder* const enc = it->enc_; VP8IteratorNzToBytes(it); if (it->mb_->type_ == 1) { // i16x16 const int ctx = it->top_nz_[8] + it->left_nz_[8]; VP8InitResidual(0, 1, enc, &res); VP8SetResidualCoeffs(rd->y_dc_levels, &res); it->top_nz_[8] = it->left_nz_[8] = VP8RecordCoeffTokens(ctx, 1, res.first, res.last, res.coeffs, tokens); VP8RecordCoeffs(ctx, &res); VP8InitResidual(1, 0, enc, &res); } else { VP8InitResidual(0, 3, enc, &res); } // luma-AC for (y = 0; y < 4; ++y) { for (x = 0; x < 4; ++x) { const int ctx = it->top_nz_[x] + it->left_nz_[y]; VP8SetResidualCoeffs(rd->y_ac_levels[x + y * 4], &res); it->top_nz_[x] = it->left_nz_[y] = VP8RecordCoeffTokens(ctx, res.coeff_type, res.first, res.last, res.coeffs, tokens); VP8RecordCoeffs(ctx, &res); } } // U/V VP8InitResidual(0, 2, enc, &res); for (ch = 0; ch <= 2; ch += 2) { for (y = 0; y < 2; ++y) { for (x = 0; x < 2; ++x) { const int ctx = it->top_nz_[4 + ch + x] + it->left_nz_[4 + ch + y]; VP8SetResidualCoeffs(rd->uv_levels[ch * 2 + x + y * 2], &res); it->top_nz_[4 + ch + x] = it->left_nz_[4 + ch + y] = VP8RecordCoeffTokens(ctx, 2, res.first, res.last, res.coeffs, tokens); VP8RecordCoeffs(ctx, &res); } } } VP8IteratorBytesToNz(it); return !tokens->error_; }
// Same as CodeResiduals, but doesn't actually write anything. // Instead, it just records the event distribution. static void RecordResiduals(VP8EncIterator* const it, const VP8ModeScore* const rd) { int x, y, ch; VP8Residual res; VP8Encoder* const enc = it->enc_; VP8IteratorNzToBytes(it); if (it->mb_->type_ == 1) { // i16x16 VP8InitResidual(0, 1, enc, &res); VP8SetResidualCoeffs(rd->y_dc_levels, &res); it->top_nz_[8] = it->left_nz_[8] = VP8RecordCoeffs(it->top_nz_[8] + it->left_nz_[8], &res); VP8InitResidual(1, 0, enc, &res); } else { VP8InitResidual(0, 3, enc, &res); } // luma-AC for (y = 0; y < 4; ++y) { for (x = 0; x < 4; ++x) { const int ctx = it->top_nz_[x] + it->left_nz_[y]; VP8SetResidualCoeffs(rd->y_ac_levels[x + y * 4], &res); it->top_nz_[x] = it->left_nz_[y] = VP8RecordCoeffs(ctx, &res); } } // U/V VP8InitResidual(0, 2, enc, &res); for (ch = 0; ch <= 2; ch += 2) { for (y = 0; y < 2; ++y) { for (x = 0; x < 2; ++x) { const int ctx = it->top_nz_[4 + ch + x] + it->left_nz_[4 + ch + y]; VP8SetResidualCoeffs(rd->uv_levels[ch * 2 + x + y * 2], &res); it->top_nz_[4 + ch + x] = it->left_nz_[4 + ch + y] = VP8RecordCoeffs(ctx, &res); } } } VP8IteratorBytesToNz(it); }
int VP8GetCostLuma4(VP8EncIterator* const it, const int16_t levels[16]) { const int x = (it->i4_ & 3), y = (it->i4_ >> 2); VP8Residual res; VP8Encoder* const enc = it->enc_; int R = 0; int ctx; VP8InitResidual(0, 3, enc, &res); ctx = it->top_nz_[x] + it->left_nz_[y]; VP8SetResidualCoeffs(levels, &res); R += VP8GetResidualCost(ctx, &res); return R; }
int VP8GetCostUV(VP8EncIterator* const it, const VP8ModeScore* const rd) { VP8Residual res; VP8Encoder* const enc = it->enc_; int ch, x, y; int R = 0; VP8IteratorNzToBytes(it); // re-import the non-zero context VP8InitResidual(0, 2, enc, &res); for (ch = 0; ch <= 2; ch += 2) { for (y = 0; y < 2; ++y) { for (x = 0; x < 2; ++x) { const int ctx = it->top_nz_[4 + ch + x] + it->left_nz_[4 + ch + y]; VP8SetResidualCoeffs(rd->uv_levels[ch * 2 + x + y * 2], &res); R += VP8GetResidualCost(ctx, &res); it->top_nz_[4 + ch + x] = it->left_nz_[4 + ch + y] = (res.last >= 0); } } } return R; }