An error occurred while loading the file. Please try again.
-
Paul Wilkins authored
Added switches and code to skip/breakout from doing SB32 and SB64 tests based on whether the 16x16 MB tests used split modes. Also to optionally skip 64x64 if 16x16 was chosen over 32x32. Impact varies depending on clip from a few % up to almost 50% on encode speed. Only the split mode breakout is currently enabled. Change-Id: Ib5836140b064b350ffa3057778ed2cadcc495cf8
29731308
/*
* Copyright (c) 2010 The WebM project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include "vpx_ports/config.h"
#include "vp9/encoder/vp9_encodeframe.h"
#include "vp9/encoder/vp9_encodemb.h"
#include "vp9/encoder/vp9_encodemv.h"
#include "vp9/common/vp9_common.h"
#include "vp9/encoder/vp9_onyx_int.h"
#include "vp9/common/vp9_extend.h"
#include "vp9/common/vp9_entropy.h"
#include "vp9/common/vp9_entropymode.h"
#include "vp9/common/vp9_quant_common.h"
#include "vp9/encoder/vp9_segmentation.h"
#include "vp9/common/vp9_setupintrarecon.h"
#include "vp9/common/vp9_reconintra4x4.h"
#include "vp9/encoder/vp9_encodeintra.h"
#include "vp9/common/vp9_reconinter.h"
#include "vp9/common/vp9_invtrans.h"
#include "vp9/encoder/vp9_rdopt.h"
#include "vp9/common/vp9_findnearmv.h"
#include "vp9/common/vp9_reconintra.h"
#include "vp9/common/vp9_seg_common.h"
#include "vp9/encoder/vp9_tokenize.h"
#include "vp9_rtcd.h"
#include <stdio.h>
#include <math.h>
#include <limits.h>
#include "vpx_ports/vpx_timer.h"
#include "vp9/common/vp9_pred_common.h"
#include "vp9/common/vp9_mvref_common.h"
#define DBG_PRNT_SEGMAP 0
// #define ENC_DEBUG
#ifdef ENC_DEBUG
int enc_debug = 0;
#endif
static void encode_macroblock(VP9_COMP *cpi, MACROBLOCK *x,
TOKENEXTRA **t, int recon_yoffset,
int recon_uvoffset, int output_enabled,
int mb_col, int mb_row);
static void encode_superblock(VP9_COMP *cpi, MACROBLOCK *x,
TOKENEXTRA **t, int recon_yoffset,
int recon_uvoffset, int mb_col, int mb_row);
static void adjust_act_zbin(VP9_COMP *cpi, MACROBLOCK *x);
#ifdef MODE_STATS
unsigned int inter_y_modes[MB_MODE_COUNT];
unsigned int inter_uv_modes[VP9_UV_MODES];
unsigned int inter_b_modes[B_MODE_COUNT];
unsigned int y_modes[VP9_YMODES];
unsigned int i8x8_modes[VP9_I8X8_MODES];
unsigned int uv_modes[VP9_UV_MODES];
unsigned int uv_modes_y[VP9_YMODES][VP9_UV_MODES];
unsigned int b_modes[B_MODE_COUNT];
#endif
7172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
/* activity_avg must be positive, or flat regions could get a zero weight
* (infinite lambda), which confounds analysis.
* This also avoids the need for divide by zero checks in
* vp9_activity_masking().
*/
#define VP9_ACTIVITY_AVG_MIN (64)
/* This is used as a reference when computing the source variance for the
* purposes of activity masking.
* Eventually this should be replaced by custom no-reference routines,
* which will be faster.
*/
static const uint8_t VP9_VAR_OFFS[16] = {
128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128
};
// Original activity measure from Tim T's code.
static unsigned int tt_activity_measure(VP9_COMP *cpi, MACROBLOCK *x) {
unsigned int act;
unsigned int sse;
/* TODO: This could also be done over smaller areas (8x8), but that would
* require extensive changes elsewhere, as lambda is assumed to be fixed
* over an entire MB in most of the code.
* Another option is to compute four 8x8 variances, and pick a single
* lambda using a non-linear combination (e.g., the smallest, or second
* smallest, etc.).
*/
act = vp9_variance16x16(x->src.y_buffer, x->src.y_stride, VP9_VAR_OFFS, 0,
&sse);
act = act << 4;
/* If the region is flat, lower the activity some more. */
if (act < 8 << 12)
act = act < 5 << 12 ? act : 5 << 12;
return act;
}
// Stub for alternative experimental activity measures.
static unsigned int alt_activity_measure(VP9_COMP *cpi,
MACROBLOCK *x, int use_dc_pred) {
return vp9_encode_intra(cpi, x, use_dc_pred);
}
// Measure the activity of the current macroblock
// What we measure here is TBD so abstracted to this function
#define ALT_ACT_MEASURE 1
static unsigned int mb_activity_measure(VP9_COMP *cpi, MACROBLOCK *x,
int mb_row, int mb_col) {
unsigned int mb_activity;
if (ALT_ACT_MEASURE) {
int use_dc_pred = (mb_col || mb_row) && (!mb_col || !mb_row);
// Or use and alternative.
mb_activity = alt_activity_measure(cpi, x, use_dc_pred);
} else {
// Original activity measure from Tim T's code.
mb_activity = tt_activity_measure(cpi, x);
}
if (mb_activity < VP9_ACTIVITY_AVG_MIN)
mb_activity = VP9_ACTIVITY_AVG_MIN;
return mb_activity;
}
// Calculate an "average" mb activity value for the frame
141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
#define ACT_MEDIAN 0
static void calc_av_activity(VP9_COMP *cpi, int64_t activity_sum) {
#if ACT_MEDIAN
// Find median: Simple n^2 algorithm for experimentation
{
unsigned int median;
unsigned int i, j;
unsigned int *sortlist;
unsigned int tmp;
// Create a list to sort to
CHECK_MEM_ERROR(sortlist,
vpx_calloc(sizeof(unsigned int),
cpi->common.MBs));
// Copy map to sort list
vpx_memcpy(sortlist, cpi->mb_activity_map,
sizeof(unsigned int) * cpi->common.MBs);
// Ripple each value down to its correct position
for (i = 1; i < cpi->common.MBs; i ++) {
for (j = i; j > 0; j --) {
if (sortlist[j] < sortlist[j - 1]) {
// Swap values
tmp = sortlist[j - 1];
sortlist[j - 1] = sortlist[j];
sortlist[j] = tmp;
} else
break;
}
}
// Even number MBs so estimate median as mean of two either side.
median = (1 + sortlist[cpi->common.MBs >> 1] +
sortlist[(cpi->common.MBs >> 1) + 1]) >> 1;
cpi->activity_avg = median;
vpx_free(sortlist);
}
#else
// Simple mean for now
cpi->activity_avg = (unsigned int)(activity_sum / cpi->common.MBs);
#endif
if (cpi->activity_avg < VP9_ACTIVITY_AVG_MIN)
cpi->activity_avg = VP9_ACTIVITY_AVG_MIN;
// Experimental code: return fixed value normalized for several clips
if (ALT_ACT_MEASURE)
cpi->activity_avg = 100000;
}
#define USE_ACT_INDEX 0
#define OUTPUT_NORM_ACT_STATS 0
#if USE_ACT_INDEX
// Calculate and activity index for each mb
static void calc_activity_index(VP9_COMP *cpi, MACROBLOCK *x) {
VP9_COMMON *const cm = &cpi->common;
int mb_row, mb_col;
int64_t act;
int64_t a;
int64_t b;
#if OUTPUT_NORM_ACT_STATS
FILE *f = fopen("norm_act.stt", "a");
fprintf(f, "\n%12d\n", cpi->activity_avg);
211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280
#endif
// Reset pointers to start of activity map
x->mb_activity_ptr = cpi->mb_activity_map;
// Calculate normalized mb activity number.
for (mb_row = 0; mb_row < cm->mb_rows; mb_row++) {
// for each macroblock col in image
for (mb_col = 0; mb_col < cm->mb_cols; mb_col++) {
// Read activity from the map
act = *(x->mb_activity_ptr);
// Calculate a normalized activity number
a = act + 4 * cpi->activity_avg;
b = 4 * act + cpi->activity_avg;
if (b >= a)
*(x->activity_ptr) = (int)((b + (a >> 1)) / a) - 1;
else
*(x->activity_ptr) = 1 - (int)((a + (b >> 1)) / b);
#if OUTPUT_NORM_ACT_STATS
fprintf(f, " %6d", *(x->mb_activity_ptr));
#endif
// Increment activity map pointers
x->mb_activity_ptr++;
}
#if OUTPUT_NORM_ACT_STATS
fprintf(f, "\n");
#endif
}
#if OUTPUT_NORM_ACT_STATS
fclose(f);
#endif
}
#endif
// Loop through all MBs. Note activity of each, average activity and
// calculate a normalized activity for each
static void build_activity_map(VP9_COMP *cpi) {
MACROBLOCK *const x = &cpi->mb;
MACROBLOCKD *xd = &x->e_mbd;
VP9_COMMON *const cm = &cpi->common;
#if ALT_ACT_MEASURE
YV12_BUFFER_CONFIG *new_yv12 = &cm->yv12_fb[cm->new_fb_idx];
int recon_yoffset;
int recon_y_stride = new_yv12->y_stride;
#endif
int mb_row, mb_col;
unsigned int mb_activity;
int64_t activity_sum = 0;
// for each macroblock row in image
for (mb_row = 0; mb_row < cm->mb_rows; mb_row++) {
#if ALT_ACT_MEASURE
// reset above block coeffs
xd->up_available = (mb_row != 0);
recon_yoffset = (mb_row * recon_y_stride * 16);
#endif
// for each macroblock col in image
for (mb_col = 0; mb_col < cm->mb_cols; mb_col++) {
#if ALT_ACT_MEASURE
xd->dst.y_buffer = new_yv12->y_buffer + recon_yoffset;
xd->left_available = (mb_col != 0);
281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350
recon_yoffset += 16;
#endif
#if !CONFIG_SUPERBLOCKS
// Copy current mb to a buffer
vp9_copy_mem16x16(x->src.y_buffer, x->src.y_stride, x->thismb, 16);
#endif
// measure activity
mb_activity = mb_activity_measure(cpi, x, mb_row, mb_col);
// Keep frame sum
activity_sum += mb_activity;
// Store MB level activity details.
*x->mb_activity_ptr = mb_activity;
// Increment activity map pointer
x->mb_activity_ptr++;
// adjust to the next column of source macroblocks
x->src.y_buffer += 16;
}
// adjust to the next row of mbs
x->src.y_buffer += 16 * x->src.y_stride - 16 * cm->mb_cols;
#if ALT_ACT_MEASURE
// extend the recon for intra prediction
vp9_extend_mb_row(new_yv12, xd->dst.y_buffer + 16,
xd->dst.u_buffer + 8, xd->dst.v_buffer + 8);
#endif
}
// Calculate an "average" MB activity
calc_av_activity(cpi, activity_sum);
#if USE_ACT_INDEX
// Calculate an activity index number of each mb
calc_activity_index(cpi, x);
#endif
}
// Macroblock activity masking
void vp9_activity_masking(VP9_COMP *cpi, MACROBLOCK *x) {
#if USE_ACT_INDEX
x->rdmult += *(x->mb_activity_ptr) * (x->rdmult >> 2);
x->errorperbit = x->rdmult * 100 / (110 * x->rddiv);
x->errorperbit += (x->errorperbit == 0);
#else
int64_t a;
int64_t b;
int64_t act = *(x->mb_activity_ptr);
// Apply the masking to the RD multiplier.
a = act + (2 * cpi->activity_avg);
b = (2 * act) + cpi->activity_avg;
x->rdmult = (unsigned int)(((int64_t)x->rdmult * b + (a >> 1)) / a);
x->errorperbit = x->rdmult * 100 / (110 * x->rddiv);
x->errorperbit += (x->errorperbit == 0);
#endif
// Activity based Zbin adjustment
adjust_act_zbin(cpi, x);
}
#if CONFIG_NEW_MVREF
351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420
static int vp9_cost_mv_ref_id(vp9_prob * ref_id_probs, int mv_ref_id) {
int cost;
// Encode the index for the MV reference.
switch (mv_ref_id) {
case 0:
cost = vp9_cost_zero(ref_id_probs[0]);
break;
case 1:
cost = vp9_cost_one(ref_id_probs[0]);
cost += vp9_cost_zero(ref_id_probs[1]);
break;
case 2:
cost = vp9_cost_one(ref_id_probs[0]);
cost += vp9_cost_one(ref_id_probs[1]);
cost += vp9_cost_zero(ref_id_probs[2]);
break;
case 3:
cost = vp9_cost_one(ref_id_probs[0]);
cost += vp9_cost_one(ref_id_probs[1]);
cost += vp9_cost_one(ref_id_probs[2]);
break;
// TRAP.. This should not happen
default:
assert(0);
break;
}
return cost;
}
// Estimate the cost of each coding the vector using each reference candidate
static unsigned int pick_best_mv_ref(MACROBLOCK *x,
MV_REFERENCE_FRAME ref_frame,
int_mv target_mv,
int_mv * mv_ref_list,
int_mv * best_ref) {
int i;
int best_index = 0;
int cost, cost2;
int zero_seen = (mv_ref_list[0].as_int) ? FALSE : TRUE;
MACROBLOCKD *xd = &x->e_mbd;
int max_mv = MV_MAX;
cost = vp9_cost_mv_ref_id(xd->mb_mv_ref_probs[ref_frame], 0) +
vp9_mv_bit_cost(&target_mv, &mv_ref_list[0], x->nmvjointcost,
x->mvcost, 96, xd->allow_high_precision_mv);
for (i = 1; i < MAX_MV_REF_CANDIDATES; ++i) {
// If we see a 0,0 reference vector for a second time we have reached
// the end of the list of valid candidate vectors.
if (!mv_ref_list[i].as_int) {
if (zero_seen)
break;
else
zero_seen = TRUE;
}
// Check for cases where the reference choice would give rise to an
// uncodable/out of range residual for row or col.
if ((abs(target_mv.as_mv.row - mv_ref_list[i].as_mv.row) > max_mv) ||
(abs(target_mv.as_mv.col - mv_ref_list[i].as_mv.col) > max_mv)) {
continue;
}
cost2 = vp9_cost_mv_ref_id(xd->mb_mv_ref_probs[ref_frame], i) +
vp9_mv_bit_cost(&target_mv, &mv_ref_list[i], x->nmvjointcost,
x->mvcost, 96, xd->allow_high_precision_mv);
if (cost2 < cost) {
421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490
cost = cost2;
best_index = i;
}
}
best_ref->as_int = mv_ref_list[best_index].as_int;
return best_index;
}
#endif
static void update_state(VP9_COMP *cpi, MACROBLOCK *x,
PICK_MODE_CONTEXT *ctx) {
int i;
MACROBLOCKD *xd = &x->e_mbd;
MODE_INFO *mi = &ctx->mic;
MB_MODE_INFO * mbmi = &xd->mode_info_context->mbmi;
int mb_mode = mi->mbmi.mode;
int mb_mode_index = ctx->best_mode_index;
#if CONFIG_DEBUG
assert(mb_mode < MB_MODE_COUNT);
assert(mb_mode_index < MAX_MODES);
assert(mi->mbmi.ref_frame < MAX_REF_FRAMES);
#endif
// Restore the coding context of the MB to that that was in place
// when the mode was picked for it
vpx_memcpy(xd->mode_info_context, mi, sizeof(MODE_INFO));
#if CONFIG_SUPERBLOCKS
if (mi->mbmi.encoded_as_sb) {
const int mis = cpi->common.mode_info_stride;
if (xd->mb_to_right_edge >= 0)
vpx_memcpy(xd->mode_info_context + 1, mi, sizeof(MODE_INFO));
if (xd->mb_to_bottom_edge >= 0) {
vpx_memcpy(xd->mode_info_context + mis, mi, sizeof(MODE_INFO));
if (xd->mb_to_right_edge >= 0)
vpx_memcpy(xd->mode_info_context + mis + 1, mi, sizeof(MODE_INFO));
}
#if CONFIG_TX32X32 && CONFIG_SUPERBLOCKS
} else {
ctx->txfm_rd_diff[ALLOW_32X32] = ctx->txfm_rd_diff[ALLOW_16X16];
#endif
}
#endif
if (mb_mode == B_PRED) {
for (i = 0; i < 16; i++) {
xd->block[i].bmi.as_mode = xd->mode_info_context->bmi[i].as_mode;
assert(xd->block[i].bmi.as_mode.first < B_MODE_COUNT);
}
} else if (mb_mode == I8X8_PRED) {
for (i = 0; i < 16; i++) {
xd->block[i].bmi = xd->mode_info_context->bmi[i];
}
} else if (mb_mode == SPLITMV) {
vpx_memcpy(x->partition_info, &ctx->partition_info,
sizeof(PARTITION_INFO));
mbmi->mv[0].as_int = x->partition_info->bmi[15].mv.as_int;
mbmi->mv[1].as_int = x->partition_info->bmi[15].second_mv.as_int;
}
{
int segment_id = mbmi->segment_id;
if (!vp9_segfeature_active(xd, segment_id, SEG_LVL_EOB) ||
vp9_get_segdata(xd, segment_id, SEG_LVL_EOB)) {
for (i = 0; i < NB_TXFM_MODES; i++) {
cpi->rd_tx_select_diff[i] += ctx->txfm_rd_diff[i];
}
}
491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560
}
if (cpi->common.frame_type == KEY_FRAME) {
// Restore the coding modes to that held in the coding context
// if (mb_mode == B_PRED)
// for (i = 0; i < 16; i++)
// {
// xd->block[i].bmi.as_mode =
// xd->mode_info_context->bmi[i].as_mode;
// assert(xd->mode_info_context->bmi[i].as_mode < MB_MODE_COUNT);
// }
#if CONFIG_INTERNAL_STATS
static const int kf_mode_index[] = {
THR_DC /*DC_PRED*/,
THR_V_PRED /*V_PRED*/,
THR_H_PRED /*H_PRED*/,
THR_D45_PRED /*D45_PRED*/,
THR_D135_PRED /*D135_PRED*/,
THR_D117_PRED /*D117_PRED*/,
THR_D153_PRED /*D153_PRED*/,
THR_D27_PRED /*D27_PRED*/,
THR_D63_PRED /*D63_PRED*/,
THR_TM /*TM_PRED*/,
THR_I8X8_PRED /*I8X8_PRED*/,
THR_B_PRED /*B_PRED*/,
};
cpi->mode_chosen_counts[kf_mode_index[mb_mode]]++;
#endif
} else {
/*
// Reduce the activation RD thresholds for the best choice mode
if ((cpi->rd_baseline_thresh[mb_mode_index] > 0) &&
(cpi->rd_baseline_thresh[mb_mode_index] < (INT_MAX >> 2)))
{
int best_adjustment = (cpi->rd_thresh_mult[mb_mode_index] >> 2);
cpi->rd_thresh_mult[mb_mode_index] =
(cpi->rd_thresh_mult[mb_mode_index]
>= (MIN_THRESHMULT + best_adjustment)) ?
cpi->rd_thresh_mult[mb_mode_index] - best_adjustment :
MIN_THRESHMULT;
cpi->rd_threshes[mb_mode_index] =
(cpi->rd_baseline_thresh[mb_mode_index] >> 7)
* cpi->rd_thresh_mult[mb_mode_index];
}
*/
// Note how often each mode chosen as best
cpi->mode_chosen_counts[mb_mode_index]++;
if (mbmi->mode == SPLITMV || mbmi->mode == NEWMV) {
int_mv best_mv, best_second_mv;
MV_REFERENCE_FRAME rf = mbmi->ref_frame;
#if CONFIG_NEW_MVREF
unsigned int best_index;
MV_REFERENCE_FRAME sec_ref_frame = mbmi->second_ref_frame;
#endif
best_mv.as_int = ctx->best_ref_mv.as_int;
best_second_mv.as_int = ctx->second_best_ref_mv.as_int;
if (mbmi->mode == NEWMV) {
best_mv.as_int = mbmi->ref_mvs[rf][0].as_int;
best_second_mv.as_int = mbmi->ref_mvs[mbmi->second_ref_frame][0].as_int;
#if CONFIG_NEW_MVREF
best_index = pick_best_mv_ref(x, rf, mbmi->mv[0],
mbmi->ref_mvs[rf], &best_mv);
mbmi->best_index = best_index;
++cpi->mb_mv_ref_count[rf][best_index];
if (mbmi->second_ref_frame > 0) {
unsigned int best_index;
best_index =
561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630
pick_best_mv_ref(x, sec_ref_frame, mbmi->mv[1],
mbmi->ref_mvs[sec_ref_frame],
&best_second_mv);
mbmi->best_second_index = best_index;
++cpi->mb_mv_ref_count[sec_ref_frame][best_index];
}
#endif
}
mbmi->best_mv.as_int = best_mv.as_int;
mbmi->best_second_mv.as_int = best_second_mv.as_int;
vp9_update_nmv_count(cpi, x, &best_mv, &best_second_mv);
}
#if CONFIG_COMP_INTERINTRA_PRED
if (mbmi->mode >= NEARESTMV && mbmi->mode < SPLITMV &&
mbmi->second_ref_frame <= INTRA_FRAME) {
if (mbmi->second_ref_frame == INTRA_FRAME) {
++cpi->interintra_count[1];
++cpi->ymode_count[mbmi->interintra_mode];
#if SEPARATE_INTERINTRA_UV
++cpi->y_uv_mode_count[mbmi->interintra_mode][mbmi->interintra_uv_mode];
#endif
} else {
++cpi->interintra_count[0];
}
}
#endif
if (cpi->common.mcomp_filter_type == SWITCHABLE &&
mbmi->mode >= NEARESTMV &&
mbmi->mode <= SPLITMV) {
++cpi->switchable_interp_count
[vp9_get_pred_context(&cpi->common, xd, PRED_SWITCHABLE_INTERP)]
[vp9_switchable_interp_map[mbmi->interp_filter]];
}
cpi->prediction_error += ctx->distortion;
cpi->intra_error += ctx->intra_error;
cpi->rd_comp_pred_diff[SINGLE_PREDICTION_ONLY] += ctx->single_pred_diff;
cpi->rd_comp_pred_diff[COMP_PREDICTION_ONLY] += ctx->comp_pred_diff;
cpi->rd_comp_pred_diff[HYBRID_PREDICTION] += ctx->hybrid_pred_diff;
}
}
static void pick_mb_modes(VP9_COMP *cpi,
VP9_COMMON *cm,
int mb_row,
int mb_col,
MACROBLOCK *x,
MACROBLOCKD *xd,
TOKENEXTRA **tp,
int *totalrate,
int *totaldist) {
int i;
int map_index;
int recon_yoffset, recon_uvoffset;
int ref_fb_idx = cm->lst_fb_idx;
int dst_fb_idx = cm->new_fb_idx;
int recon_y_stride = cm->yv12_fb[ref_fb_idx].y_stride;
int recon_uv_stride = cm->yv12_fb[ref_fb_idx].uv_stride;
ENTROPY_CONTEXT_PLANES left_context[2];
ENTROPY_CONTEXT_PLANES above_context[2];
ENTROPY_CONTEXT_PLANES *initial_above_context_ptr = cm->above_context
+ mb_col;
// Offsets to move pointers from MB to MB within a SB in raster order
int row_delta[4] = { 0, +1, 0, -1};
int col_delta[4] = { +1, -1, +1, +1};
/* Function should not modify L & A contexts; save and restore on exit */
vpx_memcpy(left_context,
631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700
cm->left_context,
sizeof(left_context));
vpx_memcpy(above_context,
initial_above_context_ptr,
sizeof(above_context));
/* Encode MBs in raster order within the SB */
for (i = 0; i < 4; i++) {
int dy = row_delta[i];
int dx = col_delta[i];
int offset_unextended = dy * cm->mb_cols + dx;
int offset_extended = dy * xd->mode_info_stride + dx;
MB_MODE_INFO * mbmi = &xd->mode_info_context->mbmi;
// TODO Many of the index items here can be computed more efficiently!
if ((mb_row >= cm->mb_rows) || (mb_col >= cm->mb_cols)) {
// MB lies outside frame, move on
mb_row += dy;
mb_col += dx;
// Update pointers
x->src.y_buffer += 16 * (dx + dy * x->src.y_stride);
x->src.u_buffer += 8 * (dx + dy * x->src.uv_stride);
x->src.v_buffer += 8 * (dx + dy * x->src.uv_stride);
x->gf_active_ptr += offset_unextended;
x->partition_info += offset_extended;
xd->mode_info_context += offset_extended;
xd->prev_mode_info_context += offset_extended;
#if CONFIG_DEBUG
assert((xd->prev_mode_info_context - cpi->common.prev_mip) ==
(xd->mode_info_context - cpi->common.mip));
#endif
continue;
}
// Index of the MB in the SB 0..3
xd->mb_index = i;
map_index = (mb_row * cpi->common.mb_cols) + mb_col;
x->mb_activity_ptr = &cpi->mb_activity_map[map_index];
// set above context pointer
xd->above_context = cm->above_context + mb_col;
// Restore the appropriate left context depending on which
// row in the SB the MB is situated
xd->left_context = cm->left_context + (i >> 1);
// Set up distance of MB to edge of frame in 1/8th pel units
xd->mb_to_top_edge = -((mb_row * 16) << 3);
xd->mb_to_left_edge = -((mb_col * 16) << 3);
xd->mb_to_bottom_edge = ((cm->mb_rows - 1 - mb_row) * 16) << 3;
xd->mb_to_right_edge = ((cm->mb_cols - 1 - mb_col) * 16) << 3;
// Set up limit values for MV components to prevent them from
// extending beyond the UMV borders assuming 16x16 block size
x->mv_row_min = -((mb_row * 16) + VP9BORDERINPIXELS - VP9_INTERP_EXTEND);
x->mv_col_min = -((mb_col * 16) + VP9BORDERINPIXELS - VP9_INTERP_EXTEND);
x->mv_row_max = ((cm->mb_rows - mb_row) * 16 +
(VP9BORDERINPIXELS - 16 - VP9_INTERP_EXTEND));
x->mv_col_max = ((cm->mb_cols - mb_col) * 16 +
(VP9BORDERINPIXELS - 16 - VP9_INTERP_EXTEND));
xd->up_available = (mb_row != 0);
xd->left_available = (mb_col != 0);
recon_yoffset = (mb_row * recon_y_stride * 16) + (mb_col * 16);
recon_uvoffset = (mb_row * recon_uv_stride * 8) + (mb_col * 8);
701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770
xd->dst.y_buffer = cm->yv12_fb[dst_fb_idx].y_buffer + recon_yoffset;
xd->dst.u_buffer = cm->yv12_fb[dst_fb_idx].u_buffer + recon_uvoffset;
xd->dst.v_buffer = cm->yv12_fb[dst_fb_idx].v_buffer + recon_uvoffset;
#if !CONFIG_SUPERBLOCKS
// Copy current MB to a work buffer
vp9_copy_mem16x16(x->src.y_buffer, x->src.y_stride, x->thismb, 16);
#endif
x->rddiv = cpi->RDDIV;
x->rdmult = cpi->RDMULT;
if (cpi->oxcf.tuning == VP8_TUNE_SSIM)
vp9_activity_masking(cpi, x);
// Is segmentation enabled
if (xd->segmentation_enabled) {
// Code to set segment id in xd->mbmi.segment_id
if (xd->update_mb_segmentation_map)
mbmi->segment_id = cpi->segmentation_map[map_index];
else
mbmi->segment_id = cm->last_frame_seg_map[map_index];
if (mbmi->segment_id > 3)
mbmi->segment_id = 0;
vp9_mb_init_quantizer(cpi, x);
} else
// Set to Segment 0 by default
mbmi->segment_id = 0;
x->active_ptr = cpi->active_map + map_index;
#if CONFIG_SUPERBLOCKS
xd->mode_info_context->mbmi.encoded_as_sb = 0;
#endif
cpi->update_context = 0; // TODO Do we need this now??
vp9_intra_prediction_down_copy(xd);
#ifdef ENC_DEBUG
enc_debug = (cpi->common.current_video_frame == 46 &&
mb_row == 5 && mb_col == 2);
#endif
// Find best coding mode & reconstruct the MB so it is available
// as a predictor for MBs that follow in the SB
if (cm->frame_type == KEY_FRAME) {
int r, d;
#ifdef ENC_DEBUG
if (enc_debug)
printf("intra pick_mb_modes %d %d\n", mb_row, mb_col);
#endif
vp9_rd_pick_intra_mode(cpi, x, &r, &d);
*totalrate += r;
*totaldist += d;
// Dummy encode, do not do the tokenization
encode_macroblock(cpi, x, tp,
recon_yoffset, recon_uvoffset, 0, mb_col, mb_row);
// Note the encoder may have changed the segment_id
// Save the coding context
vpx_memcpy(&x->mb_context[i].mic, xd->mode_info_context,
sizeof(MODE_INFO));
} else {
int seg_id, r, d;
if (xd->segmentation_enabled && cpi->seg0_cnt > 0 &&
!vp9_segfeature_active(xd, 0, SEG_LVL_REF_FRAME) &&
771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840
vp9_segfeature_active(xd, 1, SEG_LVL_REF_FRAME) &&
vp9_check_segref(xd, 1, INTRA_FRAME) +
vp9_check_segref(xd, 1, LAST_FRAME) +
vp9_check_segref(xd, 1, GOLDEN_FRAME) +
vp9_check_segref(xd, 1, ALTREF_FRAME) == 1) {
cpi->seg0_progress = (cpi->seg0_idx << 16) / cpi->seg0_cnt;
} else {
cpi->seg0_progress = (((mb_col & ~1) * 2 + (mb_row & ~1) * cm->mb_cols + i) << 16) / cm->MBs;
}
#ifdef ENC_DEBUG
if (enc_debug)
printf("inter pick_mb_modes %d %d\n", mb_row, mb_col);
#endif
vp9_pick_mode_inter_macroblock(cpi, x, recon_yoffset,
recon_uvoffset, &r, &d);
*totalrate += r;
*totaldist += d;
// Dummy encode, do not do the tokenization
encode_macroblock(cpi, x, tp,
recon_yoffset, recon_uvoffset, 0, mb_col, mb_row);
seg_id = mbmi->segment_id;
if (cpi->mb.e_mbd.segmentation_enabled && seg_id == 0) {
cpi->seg0_idx++;
}
if (!xd->segmentation_enabled ||
!vp9_segfeature_active(xd, seg_id, SEG_LVL_REF_FRAME) ||
vp9_check_segref(xd, seg_id, INTRA_FRAME) +
vp9_check_segref(xd, seg_id, LAST_FRAME) +
vp9_check_segref(xd, seg_id, GOLDEN_FRAME) +
vp9_check_segref(xd, seg_id, ALTREF_FRAME) > 1) {
// Get the prediction context and status
int pred_flag = vp9_get_pred_flag(xd, PRED_REF);
int pred_context = vp9_get_pred_context(cm, xd, PRED_REF);
// Count prediction success
cpi->ref_pred_count[pred_context][pred_flag]++;
}
}
// Next MB
mb_row += dy;
mb_col += dx;
x->src.y_buffer += 16 * (dx + dy * x->src.y_stride);
x->src.u_buffer += 8 * (dx + dy * x->src.uv_stride);
x->src.v_buffer += 8 * (dx + dy * x->src.uv_stride);
x->gf_active_ptr += offset_unextended;
x->partition_info += offset_extended;
xd->mode_info_context += offset_extended;
xd->prev_mode_info_context += offset_extended;
#if CONFIG_DEBUG
assert((xd->prev_mode_info_context - cpi->common.prev_mip) ==
(xd->mode_info_context - cpi->common.mip));
#endif
}
/* Restore L & A coding context to those in place on entry */
vpx_memcpy(cm->left_context,
left_context,
sizeof(left_context));
vpx_memcpy(initial_above_context_ptr,
above_context,
sizeof(above_context));
}
841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910
#if CONFIG_SUPERBLOCKS
static void pick_sb_modes (VP9_COMP *cpi,
VP9_COMMON *cm,
int mb_row,
int mb_col,
MACROBLOCK *x,
MACROBLOCKD *xd,
TOKENEXTRA **tp,
int *totalrate,
int *totaldist)
{
int map_index;
int recon_yoffset, recon_uvoffset;
int ref_fb_idx = cm->lst_fb_idx;
int dst_fb_idx = cm->new_fb_idx;
int recon_y_stride = cm->yv12_fb[ref_fb_idx].y_stride;
int recon_uv_stride = cm->yv12_fb[ref_fb_idx].uv_stride;
ENTROPY_CONTEXT_PLANES left_context[2];
ENTROPY_CONTEXT_PLANES above_context[2];
ENTROPY_CONTEXT_PLANES *initial_above_context_ptr = cm->above_context
+ mb_col;
/* Function should not modify L & A contexts; save and restore on exit */
vpx_memcpy (left_context,
cm->left_context,
sizeof(left_context));
vpx_memcpy (above_context,
initial_above_context_ptr,
sizeof(above_context));
map_index = (mb_row * cpi->common.mb_cols) + mb_col;
x->mb_activity_ptr = &cpi->mb_activity_map[map_index];
/* set above context pointer */
xd->above_context = cm->above_context + mb_col;
/* Restore the appropriate left context depending on which
* row in the SB the MB is situated */
xd->left_context = cm->left_context;
// Set up distance of MB to edge of frame in 1/8th pel units
xd->mb_to_top_edge = -((mb_row * 16) << 3);
xd->mb_to_left_edge = -((mb_col * 16) << 3);
xd->mb_to_bottom_edge = ((cm->mb_rows - 2 - mb_row) * 16) << 3;
xd->mb_to_right_edge = ((cm->mb_cols - 2 - mb_col) * 16) << 3;
/* Set up limit values for MV components to prevent them from
* extending beyond the UMV borders assuming 16x16 block size */
x->mv_row_min = -((mb_row * 16) + VP9BORDERINPIXELS - VP9_INTERP_EXTEND);
x->mv_col_min = -((mb_col * 16) + VP9BORDERINPIXELS - VP9_INTERP_EXTEND);
x->mv_row_max = ((cm->mb_rows - mb_row) * 16 +
(VP9BORDERINPIXELS - 32 - VP9_INTERP_EXTEND));
x->mv_col_max = ((cm->mb_cols - mb_col) * 16 +
(VP9BORDERINPIXELS - 32 - VP9_INTERP_EXTEND));
xd->up_available = (mb_row != 0);
xd->left_available = (mb_col != 0);
recon_yoffset = (mb_row * recon_y_stride * 16) + (mb_col * 16);
recon_uvoffset = (mb_row * recon_uv_stride * 8) + (mb_col * 8);
xd->dst.y_buffer = cm->yv12_fb[dst_fb_idx].y_buffer + recon_yoffset;
xd->dst.u_buffer = cm->yv12_fb[dst_fb_idx].u_buffer + recon_uvoffset;
xd->dst.v_buffer = cm->yv12_fb[dst_fb_idx].v_buffer + recon_uvoffset;
#if 0 // FIXME
/* Copy current MB to a work buffer */
vp9_copy_mem16x16(x->src.y_buffer, x->src.y_stride, x->thismb, 16);
#endif
x->rddiv = cpi->RDDIV;
x->rdmult = cpi->RDMULT;
911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980
if(cpi->oxcf.tuning == VP8_TUNE_SSIM)
vp9_activity_masking(cpi, x);
/* Is segmentation enabled */
if (xd->segmentation_enabled)
{
/* Code to set segment id in xd->mbmi.segment_id */
if (xd->update_mb_segmentation_map)
xd->mode_info_context->mbmi.segment_id =
cpi->segmentation_map[map_index] &&
cpi->segmentation_map[map_index + 1] &&
cpi->segmentation_map[map_index + cm->mb_cols] &&
cpi->segmentation_map[map_index + cm->mb_cols + 1];
else
xd->mode_info_context->mbmi.segment_id =
cm->last_frame_seg_map[map_index] &&
cm->last_frame_seg_map[map_index + 1] &&
cm->last_frame_seg_map[map_index + cm->mb_cols] &&
cm->last_frame_seg_map[map_index + cm->mb_cols + 1];
if (xd->mode_info_context->mbmi.segment_id > 3)
xd->mode_info_context->mbmi.segment_id = 0;
vp9_mb_init_quantizer(cpi, x);
}
else
/* Set to Segment 0 by default */
xd->mode_info_context->mbmi.segment_id = 0;
x->active_ptr = cpi->active_map + map_index;
cpi->update_context = 0; // TODO Do we need this now??
/* Find best coding mode & reconstruct the MB so it is available
* as a predictor for MBs that follow in the SB */
if (cm->frame_type == KEY_FRAME)
{
vp9_rd_pick_intra_mode_sb(cpi, x,
totalrate,
totaldist);
/* Save the coding context */
vpx_memcpy(&x->sb_context[0].mic, xd->mode_info_context,
sizeof(MODE_INFO));
} else {
if (xd->segmentation_enabled && cpi->seg0_cnt > 0 &&
!vp9_segfeature_active(xd, 0, SEG_LVL_REF_FRAME) &&
vp9_segfeature_active(xd, 1, SEG_LVL_REF_FRAME) &&
vp9_check_segref(xd, 1, INTRA_FRAME) +
vp9_check_segref(xd, 1, LAST_FRAME) +
vp9_check_segref(xd, 1, GOLDEN_FRAME) +
vp9_check_segref(xd, 1, ALTREF_FRAME) == 1) {
cpi->seg0_progress = (cpi->seg0_idx << 16) / cpi->seg0_cnt;
} else {
cpi->seg0_progress =
(((mb_col & ~1) * 2 + (mb_row & ~1) * cm->mb_cols) << 16) / cm->MBs;
}
vp9_rd_pick_inter_mode_sb(cpi, x,
recon_yoffset,
recon_uvoffset,
totalrate,
totaldist);
}
/* Restore L & A coding context to those in place on entry */
vpx_memcpy (cm->left_context,
left_context,
sizeof(left_context));
vpx_memcpy (initial_above_context_ptr,
above_context,
sizeof(above_context));
981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050
}
#endif
static void encode_sb(VP9_COMP *cpi,
VP9_COMMON *cm,
int mbrow,
int mbcol,
MACROBLOCK *x,
MACROBLOCKD *xd,
TOKENEXTRA **tp) {
int i;
int map_index;
int mb_row, mb_col;
int recon_yoffset, recon_uvoffset;
int ref_fb_idx = cm->lst_fb_idx;
int dst_fb_idx = cm->new_fb_idx;
int recon_y_stride = cm->yv12_fb[ref_fb_idx].y_stride;
int recon_uv_stride = cm->yv12_fb[ref_fb_idx].uv_stride;
int row_delta[4] = { 0, +1, 0, -1};
int col_delta[4] = { +1, -1, +1, +1};
mb_row = mbrow;
mb_col = mbcol;
/* Encode MBs in raster order within the SB */
for (i = 0; i < 4; i++) {
int dy = row_delta[i];
int dx = col_delta[i];
int offset_extended = dy * xd->mode_info_stride + dx;
int offset_unextended = dy * cm->mb_cols + dx;
MB_MODE_INFO * mbmi = &xd->mode_info_context->mbmi;
if ((mb_row >= cm->mb_rows) || (mb_col >= cm->mb_cols)) {
// MB lies outside frame, move on
mb_row += dy;
mb_col += dx;
x->src.y_buffer += 16 * (dx + dy * x->src.y_stride);
x->src.u_buffer += 8 * (dx + dy * x->src.uv_stride);
x->src.v_buffer += 8 * (dx + dy * x->src.uv_stride);
x->gf_active_ptr += offset_unextended;
x->partition_info += offset_extended;
xd->mode_info_context += offset_extended;
xd->prev_mode_info_context += offset_extended;
#if CONFIG_DEBUG
assert((xd->prev_mode_info_context - cpi->common.prev_mip) ==
(xd->mode_info_context - cpi->common.mip));
#endif
continue;
}
xd->mb_index = i;
// Restore MB state to that when it was picked
#if CONFIG_SUPERBLOCKS
if (xd->mode_info_context->mbmi.encoded_as_sb) {
update_state(cpi, x, &x->sb_context[i]);
cpi->sb_count++;
} else
#endif
update_state(cpi, x, &x->mb_context[i]);
map_index = (mb_row * cpi->common.mb_cols) + mb_col;
x->mb_activity_ptr = &cpi->mb_activity_map[map_index];
// reset above block coeffs
xd->above_context = cm->above_context + mb_col;
xd->left_context = cm->left_context + (i >> 1);
1051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120
// Set up distance of MB to edge of the frame in 1/8th pel units
// Set up limit values for MV components to prevent them from
// extending beyond the UMV borders assuming 32x32 block size
x->mv_row_min = -((mb_row * 16) + VP9BORDERINPIXELS - VP9_INTERP_EXTEND);
x->mv_col_min = -((mb_col * 16) + VP9BORDERINPIXELS - VP9_INTERP_EXTEND);
xd->mb_to_top_edge = -((mb_row * 16) << 3);
xd->mb_to_left_edge = -((mb_col * 16) << 3);
#if CONFIG_SUPERBLOCKS
if (xd->mode_info_context->mbmi.encoded_as_sb) {
x->mv_row_max = ((cm->mb_rows - mb_row) * 16 +
(VP9BORDERINPIXELS - 32 - VP9_INTERP_EXTEND));
x->mv_col_max = ((cm->mb_cols - mb_col) * 16 +
(VP9BORDERINPIXELS - 32 - VP9_INTERP_EXTEND));
xd->mb_to_bottom_edge = ((cm->mb_rows - 2 - mb_row) * 16) << 3;
xd->mb_to_right_edge = ((cm->mb_cols - 2 - mb_col) * 16) << 3;
} else {
#endif
x->mv_row_max = ((cm->mb_rows - mb_row) * 16 +
(VP9BORDERINPIXELS - 16 - VP9_INTERP_EXTEND));
x->mv_col_max = ((cm->mb_cols - mb_col) * 16 +
(VP9BORDERINPIXELS - 16 - VP9_INTERP_EXTEND));
xd->mb_to_bottom_edge = ((cm->mb_rows - 1 - mb_row) * 16) << 3;
xd->mb_to_right_edge = ((cm->mb_cols - 1 - mb_col) * 16) << 3;
#if CONFIG_SUPERBLOCKS
}
#endif
xd->up_available = (mb_row != 0);
xd->left_available = (mb_col != 0);
recon_yoffset = (mb_row * recon_y_stride * 16) + (mb_col * 16);
recon_uvoffset = (mb_row * recon_uv_stride * 8) + (mb_col * 8);
xd->dst.y_buffer = cm->yv12_fb[dst_fb_idx].y_buffer + recon_yoffset;
xd->dst.u_buffer = cm->yv12_fb[dst_fb_idx].u_buffer + recon_uvoffset;
xd->dst.v_buffer = cm->yv12_fb[dst_fb_idx].v_buffer + recon_uvoffset;
#if !CONFIG_SUPERBLOCKS
// Copy current MB to a work buffer
vp9_copy_mem16x16(x->src.y_buffer, x->src.y_stride, x->thismb, 16);
#endif
if (cpi->oxcf.tuning == VP8_TUNE_SSIM)
vp9_activity_masking(cpi, x);
// Is segmentation enabled
if (xd->segmentation_enabled) {
vp9_mb_init_quantizer(cpi, x);
}
x->active_ptr = cpi->active_map + map_index;
cpi->update_context = 0;
#if CONFIG_SUPERBLOCKS
if (!xd->mode_info_context->mbmi.encoded_as_sb)
#endif
vp9_intra_prediction_down_copy(xd);
if (cm->frame_type == KEY_FRAME) {
#if CONFIG_SUPERBLOCKS
if (xd->mode_info_context->mbmi.encoded_as_sb)
encode_superblock(cpi, x, tp, recon_yoffset, recon_uvoffset,
mb_col, mb_row);
else
1121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190
#endif
encode_macroblock(cpi, x, tp, recon_yoffset, recon_uvoffset, 1,
mb_col, mb_row);
// Note the encoder may have changed the segment_id
#ifdef MODE_STATS
y_modes[mbmi->mode]++;
#endif
} else {
unsigned char *segment_id;
int seg_ref_active;
if (xd->mode_info_context->mbmi.ref_frame) {
unsigned char pred_context;
pred_context = vp9_get_pred_context(cm, xd, PRED_COMP);
if (xd->mode_info_context->mbmi.second_ref_frame <= INTRA_FRAME)
cpi->single_pred_count[pred_context]++;
else
cpi->comp_pred_count[pred_context]++;
}
#if CONFIG_SUPERBLOCKS
if (xd->mode_info_context->mbmi.encoded_as_sb)
encode_superblock(cpi, x, tp, recon_yoffset, recon_uvoffset,
mb_col, mb_row);
else
#endif
encode_macroblock(cpi, x, tp, recon_yoffset, recon_uvoffset, 1,
mb_col, mb_row);
// Note the encoder may have changed the segment_id
#ifdef MODE_STATS
inter_y_modes[mbmi->mode]++;
if (mbmi->mode == SPLITMV) {
int b;
for (b = 0; b < x->partition_info->count; b++) {
inter_b_modes[x->partition_info->bmi[b].mode]++;
}
}
#endif
// If we have just a single reference frame coded for a segment then
// exclude from the reference frame counts used to work out
// probabilities. NOTE: At the moment we dont support custom trees
// for the reference frame coding for each segment but this is a
// possible future action.
segment_id = &mbmi->segment_id;
seg_ref_active = vp9_segfeature_active(xd, *segment_id,
SEG_LVL_REF_FRAME);
if (!seg_ref_active ||
((vp9_check_segref(xd, *segment_id, INTRA_FRAME) +
vp9_check_segref(xd, *segment_id, LAST_FRAME) +
vp9_check_segref(xd, *segment_id, GOLDEN_FRAME) +
vp9_check_segref(xd, *segment_id, ALTREF_FRAME)) > 1)) {
{
cpi->count_mb_ref_frame_usage[mbmi->ref_frame]++;
}
}
// Count of last ref frame 0,0 usage
if ((mbmi->mode == ZEROMV) && (mbmi->ref_frame == LAST_FRAME))
cpi->inter_zz_count++;
}
#if CONFIG_SUPERBLOCKS
1191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260
if (xd->mode_info_context->mbmi.encoded_as_sb) {
x->src.y_buffer += 32;
x->src.u_buffer += 16;
x->src.v_buffer += 16;
x->gf_active_ptr += 2;
x->partition_info += 2;
xd->mode_info_context += 2;
xd->prev_mode_info_context += 2;
(*tp)->Token = EOSB_TOKEN;
(*tp)++;
if (mb_row < cm->mb_rows) cpi->tplist[mb_row].stop = *tp;
break;
}
#endif
// Next MB
mb_row += dy;
mb_col += dx;
x->src.y_buffer += 16 * (dx + dy * x->src.y_stride);
x->src.u_buffer += 8 * (dx + dy * x->src.uv_stride);
x->src.v_buffer += 8 * (dx + dy * x->src.uv_stride);
x->gf_active_ptr += offset_unextended;
x->partition_info += offset_extended;
xd->mode_info_context += offset_extended;
xd->prev_mode_info_context += offset_extended;
#if CONFIG_DEBUG
assert((xd->prev_mode_info_context - cpi->common.prev_mip) ==
(xd->mode_info_context - cpi->common.mip));
#endif
(*tp)->Token = EOSB_TOKEN;
(*tp)++;
if (mb_row < cm->mb_rows) cpi->tplist[mb_row].stop = *tp;
}
// debug output
#if DBG_PRNT_SEGMAP
{
FILE *statsfile;
statsfile = fopen("segmap2.stt", "a");
fprintf(statsfile, "\n");
fclose(statsfile);
}
#endif
}
static
void encode_sb_row(VP9_COMP *cpi,
VP9_COMMON *cm,
int mb_row,
MACROBLOCK *x,
MACROBLOCKD *xd,
TOKENEXTRA **tp,
int *totalrate) {
int mb_col;
int mb_cols = cm->mb_cols;
// Initialize the left context for the new SB row
vpx_memset(cm->left_context, 0, sizeof(cm->left_context));
// Code each SB in the row
for (mb_col = 0; mb_col < mb_cols; mb_col += 2) {
int mb_rate = 0, mb_dist = 0;
#if CONFIG_SUPERBLOCKS
int sb_rate = INT_MAX, sb_dist;
#endif
1261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330
#if CONFIG_DEBUG
MODE_INFO *mic = xd->mode_info_context;
PARTITION_INFO *pi = x->partition_info;
signed char *gfa = x->gf_active_ptr;
uint8_t *yb = x->src.y_buffer;
uint8_t *ub = x->src.u_buffer;
uint8_t *vb = x->src.v_buffer;
#endif
#if CONFIG_SUPERBLOCKS
// Pick modes assuming the SB is coded as 4 independent MBs
xd->mode_info_context->mbmi.encoded_as_sb = 0;
#endif
pick_mb_modes(cpi, cm, mb_row, mb_col, x, xd, tp, &mb_rate, &mb_dist);
#if CONFIG_SUPERBLOCKS
mb_rate += vp9_cost_bit(cm->sb_coded, 0);
#endif
x->src.y_buffer -= 32;
x->src.u_buffer -= 16;
x->src.v_buffer -= 16;
x->gf_active_ptr -= 2;
x->partition_info -= 2;
xd->mode_info_context -= 2;
xd->prev_mode_info_context -= 2;
#if CONFIG_DEBUG
assert(x->gf_active_ptr == gfa);
assert(x->partition_info == pi);
assert(xd->mode_info_context == mic);
assert(x->src.y_buffer == yb);
assert(x->src.u_buffer == ub);
assert(x->src.v_buffer == vb);
#endif
#if CONFIG_SUPERBLOCKS
if (!((( mb_cols & 1) && mb_col == mb_cols - 1) ||
((cm->mb_rows & 1) && mb_row == cm->mb_rows - 1))) {
/* Pick a mode assuming that it applies to all 4 of the MBs in the SB */
xd->mode_info_context->mbmi.encoded_as_sb = 1;
pick_sb_modes(cpi, cm, mb_row, mb_col, x, xd, tp, &sb_rate, &sb_dist);
sb_rate += vp9_cost_bit(cm->sb_coded, 1);
}
/* Decide whether to encode as a SB or 4xMBs */
if (sb_rate < INT_MAX &&
RDCOST(x->rdmult, x->rddiv, sb_rate, sb_dist) <
RDCOST(x->rdmult, x->rddiv, mb_rate, mb_dist)) {
xd->mode_info_context->mbmi.encoded_as_sb = 1;
xd->mode_info_context[1].mbmi.encoded_as_sb = 1;
xd->mode_info_context[cm->mode_info_stride].mbmi.encoded_as_sb = 1;
xd->mode_info_context[1 + cm->mode_info_stride].mbmi.encoded_as_sb = 1;
*totalrate += sb_rate;
} else
#endif
{
#if CONFIG_SUPERBLOCKS
xd->mode_info_context->mbmi.encoded_as_sb = 0;
if (cm->mb_cols - 1 > mb_col)
xd->mode_info_context[1].mbmi.encoded_as_sb = 0;
if (cm->mb_rows - 1 > mb_row) {
xd->mode_info_context[cm->mode_info_stride].mbmi.encoded_as_sb = 0;
if (cm->mb_cols - 1 > mb_col)
xd->mode_info_context[1 + cm->mode_info_stride].mbmi.encoded_as_sb = 0;
}
#endif
*totalrate += mb_rate;
}
1331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400
/* Encode SB using best computed mode(s) */
encode_sb(cpi, cm, mb_row, mb_col, x, xd, tp);
#if CONFIG_DEBUG
assert(x->gf_active_ptr == gfa + 2);
assert(x->partition_info == pi + 2);
assert(xd->mode_info_context == mic + 2);
assert(x->src.y_buffer == yb + 32);
assert(x->src.u_buffer == ub + 16);
assert(x->src.v_buffer == vb + 16);
#endif
}
// this is to account for the border
x->gf_active_ptr += mb_cols - (mb_cols & 0x1);
x->partition_info += xd->mode_info_stride + 1 - (mb_cols & 0x1);
xd->mode_info_context += xd->mode_info_stride + 1 - (mb_cols & 0x1);
xd->prev_mode_info_context += xd->mode_info_stride + 1 - (mb_cols & 0x1);
#if CONFIG_DEBUG
assert((xd->prev_mode_info_context - cpi->common.prev_mip) ==
(xd->mode_info_context - cpi->common.mip));
#endif
}
static void init_encode_frame_mb_context(VP9_COMP *cpi) {
MACROBLOCK *const x = &cpi->mb;
VP9_COMMON *const cm = &cpi->common;
MACROBLOCKD *const xd = &x->e_mbd;
// GF active flags data structure
x->gf_active_ptr = (signed char *)cpi->gf_active_flags;
// Activity map pointer
x->mb_activity_ptr = cpi->mb_activity_map;
x->act_zbin_adj = 0;
cpi->seg0_idx = 0;
vpx_memset(cpi->ref_pred_count, 0, sizeof(cpi->ref_pred_count));
x->partition_info = x->pi;
xd->mode_info_context = cm->mi;
xd->mode_info_stride = cm->mode_info_stride;
xd->prev_mode_info_context = cm->prev_mi;
xd->frame_type = cm->frame_type;
xd->frames_since_golden = cm->frames_since_golden;
xd->frames_till_alt_ref_frame = cm->frames_till_alt_ref_frame;
// reset intra mode contexts
if (cm->frame_type == KEY_FRAME)
vp9_init_mbmode_probs(cm);
// Copy data over into macro block data structures.
x->src = * cpi->Source;
xd->pre = cm->yv12_fb[cm->lst_fb_idx];
xd->dst = cm->yv12_fb[cm->new_fb_idx];
// set up frame for intra coded blocks
vp9_setup_intra_recon(&cm->yv12_fb[cm->new_fb_idx]);
vp9_build_block_offsets(x);
vp9_setup_block_dptrs(&x->e_mbd);
vp9_setup_block_ptrs(x);
1401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470
xd->mode_info_context->mbmi.mode = DC_PRED;
xd->mode_info_context->mbmi.uv_mode = DC_PRED;
vp9_zero(cpi->count_mb_ref_frame_usage)
vp9_zero(cpi->bmode_count)
vp9_zero(cpi->ymode_count)
vp9_zero(cpi->i8x8_mode_count)
vp9_zero(cpi->y_uv_mode_count)
vp9_zero(cpi->sub_mv_ref_count)
vp9_zero(cpi->mbsplit_count)
vp9_zero(cpi->common.fc.mv_ref_ct)
#if CONFIG_SUPERBLOCKS
vp9_zero(cpi->sb_ymode_count)
cpi->sb_count = 0;
#endif
#if CONFIG_COMP_INTERINTRA_PRED
vp9_zero(cpi->interintra_count);
vp9_zero(cpi->interintra_select_count);
#endif
vpx_memset(cm->above_context, 0,
sizeof(ENTROPY_CONTEXT_PLANES) * cm->mb_cols);
xd->fullpixel_mask = 0xffffffff;
if (cm->full_pixel)
xd->fullpixel_mask = 0xfffffff8;
}
static void encode_frame_internal(VP9_COMP *cpi) {
int mb_row;
MACROBLOCK *const x = &cpi->mb;
VP9_COMMON *const cm = &cpi->common;
MACROBLOCKD *const xd = &x->e_mbd;
TOKENEXTRA *tp = cpi->tok;
int totalrate;
// printf("encode_frame_internal frame %d (%d)\n",
// cpi->common.current_video_frame, cpi->common.show_frame);
// Compute a modified set of reference frame probabilities to use when
// prediction fails. These are based on the current general estimates for
// this frame which may be updated with each iteration of the recode loop.
vp9_compute_mod_refprobs(cm);
// debug output
#if DBG_PRNT_SEGMAP
{
FILE *statsfile;
statsfile = fopen("segmap2.stt", "a");
fprintf(statsfile, "\n");
fclose(statsfile);
}
#endif
totalrate = 0;
// Functions setup for all frame types so we can use MC in AltRef
vp9_setup_interp_filters(xd, cm->mcomp_filter_type, cm);
// Reset frame count of inter 0,0 motion vector usage.
cpi->inter_zz_count = 0;
cpi->prediction_error = 0;
cpi->intra_error = 0;
cpi->skip_true_count[0] = cpi->skip_true_count[1] = cpi->skip_true_count[2] = 0;
cpi->skip_false_count[0] = cpi->skip_false_count[1] = cpi->skip_false_count[2] = 0;
#if CONFIG_PRED_FILTER
if (cm->current_video_frame == 0) {
1471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540
// Initially assume that we'll signal the prediction filter
// state at the frame level and that it is off.
cpi->common.pred_filter_mode = 0;
cpi->common.prob_pred_filter_off = 128;
}
cpi->pred_filter_on_count = 0;
cpi->pred_filter_off_count = 0;
#endif
vp9_zero(cpi->switchable_interp_count);
xd->mode_info_context = cm->mi;
xd->prev_mode_info_context = cm->prev_mi;
vp9_zero(cpi->NMVcount);
vp9_zero(cpi->coef_counts_4x4);
vp9_zero(cpi->hybrid_coef_counts_4x4);
vp9_zero(cpi->coef_counts_8x8);
vp9_zero(cpi->hybrid_coef_counts_8x8);
vp9_zero(cpi->coef_counts_16x16);
vp9_zero(cpi->hybrid_coef_counts_16x16);
#if CONFIG_TX32X32 && CONFIG_SUPERBLOCKS
vp9_zero(cpi->coef_counts_32x32);
#endif
#if CONFIG_NEW_MVREF
vp9_zero(cpi->mb_mv_ref_count);
#endif
vp9_frame_init_quantizer(cpi);
vp9_initialize_rd_consts(cpi, cm->base_qindex + cm->y1dc_delta_q);
vp9_initialize_me_consts(cpi, cm->base_qindex);
if (cpi->oxcf.tuning == VP8_TUNE_SSIM) {
// Initialize encode frame context.
init_encode_frame_mb_context(cpi);
// Build a frame level activity map
build_activity_map(cpi);
}
// re-initencode frame context.
init_encode_frame_mb_context(cpi);
vpx_memset(cpi->rd_comp_pred_diff, 0, sizeof(cpi->rd_comp_pred_diff));
vpx_memset(cpi->single_pred_count, 0, sizeof(cpi->single_pred_count));
vpx_memset(cpi->comp_pred_count, 0, sizeof(cpi->comp_pred_count));
vpx_memset(cpi->txfm_count_32x32p, 0, sizeof(cpi->txfm_count_32x32p));
vpx_memset(cpi->txfm_count_16x16p, 0, sizeof(cpi->txfm_count_16x16p));
vpx_memset(cpi->txfm_count_8x8p, 0, sizeof(cpi->txfm_count_8x8p));
vpx_memset(cpi->rd_tx_select_diff, 0, sizeof(cpi->rd_tx_select_diff));
{
struct vpx_usec_timer emr_timer;
vpx_usec_timer_start(&emr_timer);
{
// For each row of SBs in the frame
for (mb_row = 0; mb_row < cm->mb_rows; mb_row += 2) {
int offset = (cm->mb_cols + 1) & ~0x1;
encode_sb_row(cpi, cm, mb_row, x, xd, &tp, &totalrate);
// adjust to the next row of SBs
x->src.y_buffer += 32 * x->src.y_stride - 16 * offset;
x->src.u_buffer += 16 * x->src.uv_stride - 8 * offset;
x->src.v_buffer += 16 * x->src.uv_stride - 8 * offset;
}
cpi->tok_count = (unsigned int)(tp - cpi->tok);
}
1541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610
vpx_usec_timer_mark(&emr_timer);
cpi->time_encode_mb_row += vpx_usec_timer_elapsed(&emr_timer);
}
// 256 rate units to the bit,
// projected_frame_size in units of BYTES
cpi->projected_frame_size = totalrate >> 8;
#if 0
// Keep record of the total distortion this time around for future use
cpi->last_frame_distortion = cpi->frame_distortion;
#endif
}
static int check_dual_ref_flags(VP9_COMP *cpi) {
MACROBLOCKD *xd = &cpi->mb.e_mbd;
int ref_flags = cpi->ref_frame_flags;
if (vp9_segfeature_active(xd, 1, SEG_LVL_REF_FRAME)) {
if ((ref_flags & (VP9_LAST_FLAG | VP9_GOLD_FLAG)) == (VP9_LAST_FLAG | VP9_GOLD_FLAG) &&
vp9_check_segref(xd, 1, LAST_FRAME))
return 1;
if ((ref_flags & (VP9_GOLD_FLAG | VP9_ALT_FLAG)) == (VP9_GOLD_FLAG | VP9_ALT_FLAG) &&
vp9_check_segref(xd, 1, GOLDEN_FRAME))
return 1;
if ((ref_flags & (VP9_ALT_FLAG | VP9_LAST_FLAG)) == (VP9_ALT_FLAG | VP9_LAST_FLAG) &&
vp9_check_segref(xd, 1, ALTREF_FRAME))
return 1;
return 0;
} else {
return (!!(ref_flags & VP9_GOLD_FLAG) +
!!(ref_flags & VP9_LAST_FLAG) +
!!(ref_flags & VP9_ALT_FLAG)) >= 2;
}
}
static void reset_skip_txfm_size(VP9_COMP *cpi, TX_SIZE txfm_max) {
VP9_COMMON *cm = &cpi->common;
int mb_row, mb_col, mis = cm->mode_info_stride, segment_id;
MODE_INFO *mi, *mi_ptr = cm->mi;
#if CONFIG_SUPERBLOCKS
int skip;
MODE_INFO *sb_mi_ptr = cm->mi, *sb_mi;
MB_MODE_INFO *sb_mbmi;
#endif
MB_MODE_INFO *mbmi;
MACROBLOCK *x = &cpi->mb;
MACROBLOCKD *xd = &x->e_mbd;
for (mb_row = 0; mb_row < cm->mb_rows; mb_row++, mi_ptr += mis) {
mi = mi_ptr;
#if CONFIG_SUPERBLOCKS
sb_mi = sb_mi_ptr;
#endif
for (mb_col = 0; mb_col < cm->mb_cols; mb_col++, mi++) {
mbmi = &mi->mbmi;
#if CONFIG_SUPERBLOCKS
sb_mbmi = &sb_mi->mbmi;
#endif
if (mbmi->txfm_size > txfm_max) {
#if CONFIG_SUPERBLOCKS
if (sb_mbmi->encoded_as_sb) {
if (!((mb_col & 1) || (mb_row & 1))) {
segment_id = mbmi->segment_id;
skip = mbmi->mb_skip_coeff;
if (mb_col < cm->mb_cols - 1) {
segment_id = segment_id && mi[1].mbmi.segment_id;
1611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680
skip = skip && mi[1].mbmi.mb_skip_coeff;
}
if (mb_row < cm->mb_rows - 1) {
segment_id = segment_id &&
mi[cm->mode_info_stride].mbmi.segment_id;
skip = skip && mi[cm->mode_info_stride].mbmi.mb_skip_coeff;
if (mb_col < cm->mb_cols - 1) {
segment_id = segment_id &&
mi[cm->mode_info_stride + 1].mbmi.segment_id;
skip = skip && mi[cm->mode_info_stride + 1].mbmi.mb_skip_coeff;
}
}
xd->mode_info_context = mi;
assert((vp9_segfeature_active(xd, segment_id, SEG_LVL_EOB) &&
vp9_get_segdata(xd, segment_id, SEG_LVL_EOB) == 0) ||
(cm->mb_no_coeff_skip && skip));
mbmi->txfm_size = txfm_max;
} else {
mbmi->txfm_size = sb_mbmi->txfm_size;
}
} else {
#endif
segment_id = mbmi->segment_id;
xd->mode_info_context = mi;
assert((vp9_segfeature_active(xd, segment_id, SEG_LVL_EOB) &&
vp9_get_segdata(xd, segment_id, SEG_LVL_EOB) == 0) ||
(cm->mb_no_coeff_skip && mbmi->mb_skip_coeff));
mbmi->txfm_size = txfm_max;
#if CONFIG_SUPERBLOCKS
}
#endif
}
#if CONFIG_SUPERBLOCKS
if (mb_col & 1)
sb_mi += 2;
#endif
}
#if CONFIG_SUPERBLOCKS
if (mb_row & 1)
sb_mi_ptr += 2 * mis;
#endif
}
}
void vp9_encode_frame(VP9_COMP *cpi) {
if (cpi->sf.RD) {
int i, frame_type, pred_type;
TXFM_MODE txfm_type;
/*
* This code does a single RD pass over the whole frame assuming
* either compound, single or hybrid prediction as per whatever has
* worked best for that type of frame in the past.
* It also predicts whether another coding mode would have worked
* better that this coding mode. If that is the case, it remembers
* that for subsequent frames.
* It does the same analysis for transform size selection also.
*/
if (cpi->common.frame_type == KEY_FRAME)
frame_type = 0;
else if (cpi->is_src_frame_alt_ref && cpi->common.refresh_golden_frame)
frame_type = 3;
else if (cpi->common.refresh_golden_frame || cpi->common.refresh_alt_ref_frame)
frame_type = 1;
else
frame_type = 2;
/* prediction (compound, single or hybrid) mode selection */
if (frame_type == 3)
pred_type = SINGLE_PREDICTION_ONLY;
1681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750
else if (cpi->rd_prediction_type_threshes[frame_type][1] >
cpi->rd_prediction_type_threshes[frame_type][0] &&
cpi->rd_prediction_type_threshes[frame_type][1] >
cpi->rd_prediction_type_threshes[frame_type][2] &&
check_dual_ref_flags(cpi) && cpi->static_mb_pct == 100)
pred_type = COMP_PREDICTION_ONLY;
else if (cpi->rd_prediction_type_threshes[frame_type][0] >
cpi->rd_prediction_type_threshes[frame_type][2])
pred_type = SINGLE_PREDICTION_ONLY;
else
pred_type = HYBRID_PREDICTION;
/* transform size (4x4, 8x8, 16x16 or select-per-mb) selection */
#if CONFIG_LOSSLESS
if (cpi->oxcf.lossless) {
txfm_type = ONLY_4X4;
} else
#endif
/* FIXME (rbultje)
* this is a hack (no really), basically to work around the complete
* nonsense coefficient cost prediction for keyframes. The probabilities
* are reset to defaults, and thus we basically have no idea how expensive
* a 4x4 vs. 8x8 will really be. The result is that any estimate at which
* of the two is better is utterly bogus.
* I'd like to eventually remove this hack, but in order to do that, we
* need to move the frame reset code from the frame encode init to the
* bitstream write code, or alternatively keep a backup of the previous
* keyframe's probabilities as an estimate of what the current keyframe's
* coefficient cost distributions may look like. */
if (frame_type == 0) {
#if CONFIG_TX32X32 && CONFIG_SUPERBLOCKS
txfm_type = ALLOW_32X32;
#else
txfm_type = ALLOW_16X16;
#endif
} else
#if 0
/* FIXME (rbultje)
* this code is disabled for a similar reason as the code above; the
* problem is that each time we "revert" to 4x4 only (or even 8x8 only),
* the coefficient probabilities for 16x16 (and 8x8) start lagging behind,
* thus leading to them lagging further behind and not being chosen for
* subsequent frames either. This is essentially a local minimum problem
* that we can probably fix by estimating real costs more closely within
* a frame, perhaps by re-calculating costs on-the-fly as frame encoding
* progresses. */
if (cpi->rd_tx_select_threshes[frame_type][TX_MODE_SELECT] >
cpi->rd_tx_select_threshes[frame_type][ONLY_4X4] &&
cpi->rd_tx_select_threshes[frame_type][TX_MODE_SELECT] >
cpi->rd_tx_select_threshes[frame_type][ALLOW_16X16] &&
cpi->rd_tx_select_threshes[frame_type][TX_MODE_SELECT] >
cpi->rd_tx_select_threshes[frame_type][ALLOW_8X8]) {
txfm_type = TX_MODE_SELECT;
} else if (cpi->rd_tx_select_threshes[frame_type][ONLY_4X4] >
cpi->rd_tx_select_threshes[frame_type][ALLOW_8X8]
&& cpi->rd_tx_select_threshes[frame_type][ONLY_4X4] >
cpi->rd_tx_select_threshes[frame_type][ALLOW_16X16]
) {
txfm_type = ONLY_4X4;
} else if (cpi->rd_tx_select_threshes[frame_type][ALLOW_16X16] >=
cpi->rd_tx_select_threshes[frame_type][ALLOW_8X8]) {
txfm_type = ALLOW_16X16;
} else
txfm_type = ALLOW_8X8;
#else
#if CONFIG_TX32X32 && CONFIG_SUPERBLOCKS
txfm_type = cpi->rd_tx_select_threshes[frame_type][ALLOW_32X32] >=
cpi->rd_tx_select_threshes[frame_type][TX_MODE_SELECT] ?
ALLOW_32X32 : TX_MODE_SELECT;
#else
1751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820
txfm_type = cpi->rd_tx_select_threshes[frame_type][ALLOW_16X16] >=
cpi->rd_tx_select_threshes[frame_type][TX_MODE_SELECT] ?
ALLOW_16X16 : TX_MODE_SELECT;
#endif
#endif
cpi->common.txfm_mode = txfm_type;
if (txfm_type != TX_MODE_SELECT) {
cpi->common.prob_tx[0] = 128;
cpi->common.prob_tx[1] = 128;
}
cpi->common.comp_pred_mode = pred_type;
encode_frame_internal(cpi);
for (i = 0; i < NB_PREDICTION_TYPES; ++i) {
const int diff = (int)(cpi->rd_comp_pred_diff[i] / cpi->common.MBs);
cpi->rd_prediction_type_threshes[frame_type][i] += diff;
cpi->rd_prediction_type_threshes[frame_type][i] >>= 1;
}
for (i = 0; i < NB_TXFM_MODES; ++i) {
int64_t pd = cpi->rd_tx_select_diff[i];
int diff;
if (i == TX_MODE_SELECT)
pd -= RDCOST(cpi->mb.rdmult, cpi->mb.rddiv,
2048 * (TX_SIZE_MAX_SB - 1), 0);
diff = (int)(pd / cpi->common.MBs);
cpi->rd_tx_select_threshes[frame_type][i] += diff;
cpi->rd_tx_select_threshes[frame_type][i] /= 2;
}
if (cpi->common.comp_pred_mode == HYBRID_PREDICTION) {
int single_count_zero = 0;
int comp_count_zero = 0;
for (i = 0; i < COMP_PRED_CONTEXTS; i++) {
single_count_zero += cpi->single_pred_count[i];
comp_count_zero += cpi->comp_pred_count[i];
}
if (comp_count_zero == 0) {
cpi->common.comp_pred_mode = SINGLE_PREDICTION_ONLY;
} else if (single_count_zero == 0) {
cpi->common.comp_pred_mode = COMP_PREDICTION_ONLY;
}
}
if (cpi->common.txfm_mode == TX_MODE_SELECT) {
const int count4x4 = cpi->txfm_count_16x16p[TX_4X4] +
cpi->txfm_count_32x32p[TX_4X4] +
cpi->txfm_count_8x8p[TX_4X4];
const int count8x8_lp = cpi->txfm_count_32x32p[TX_8X8] +
cpi->txfm_count_16x16p[TX_8X8];
const int count8x8_8x8p = cpi->txfm_count_8x8p[TX_8X8];
const int count16x16_16x16p = cpi->txfm_count_16x16p[TX_16X16];
const int count16x16_lp = cpi->txfm_count_32x32p[TX_16X16];
#if CONFIG_TX32X32 && CONFIG_SUPERBLOCKS
const int count32x32 = cpi->txfm_count_32x32p[TX_32X32];
#else
const int count32x32 = 0;
#endif
if (count4x4 == 0 && count16x16_lp == 0 && count16x16_16x16p == 0 &&
count32x32 == 0) {
cpi->common.txfm_mode = ALLOW_8X8;
reset_skip_txfm_size(cpi, TX_8X8);
} else if (count8x8_8x8p == 0 && count16x16_16x16p == 0 &&
count8x8_lp == 0 && count16x16_lp == 0 && count32x32 == 0) {
cpi->common.txfm_mode = ONLY_4X4;
reset_skip_txfm_size(cpi, TX_4X4);
#if CONFIG_TX32X32 && CONFIG_SUPERBLOCKS
1821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890
} else if (count8x8_lp == 0 && count16x16_lp == 0 && count4x4 == 0) {
cpi->common.txfm_mode = ALLOW_32X32;
#endif
} else if (count32x32 == 0 && count8x8_lp == 0 && count4x4 == 0) {
cpi->common.txfm_mode = ALLOW_16X16;
#if CONFIG_TX32X32 && CONFIG_SUPERBLOCKS
reset_skip_txfm_size(cpi, TX_16X16);
#endif
}
}
} else {
encode_frame_internal(cpi);
}
}
void vp9_setup_block_ptrs(MACROBLOCK *x) {
int r, c;
int i;
for (r = 0; r < 4; r++) {
for (c = 0; c < 4; c++) {
x->block[r * 4 + c].src_diff = x->src_diff + r * 4 * 16 + c * 4;
}
}
for (r = 0; r < 2; r++) {
for (c = 0; c < 2; c++) {
x->block[16 + r * 2 + c].src_diff = x->src_diff + 256 + r * 4 * 8 + c * 4;
}
}
for (r = 0; r < 2; r++) {
for (c = 0; c < 2; c++) {
x->block[20 + r * 2 + c].src_diff = x->src_diff + 320 + r * 4 * 8 + c * 4;
}
}
x->block[24].src_diff = x->src_diff + 384;
for (i = 0; i < 25; i++) {
x->block[i].coeff = x->coeff + i * 16;
}
}
void vp9_build_block_offsets(MACROBLOCK *x) {
int block = 0;
int br, bc;
vp9_build_block_doffsets(&x->e_mbd);
#if !CONFIG_SUPERBLOCKS
// y blocks
x->thismb_ptr = &x->thismb[0];
for (br = 0; br < 4; br++) {
for (bc = 0; bc < 4; bc++) {
BLOCK *this_block = &x->block[block];
// this_block->base_src = &x->src.y_buffer;
// this_block->src_stride = x->src.y_stride;
// this_block->src = 4 * br * this_block->src_stride + 4 * bc;
this_block->base_src = &x->thismb_ptr;
this_block->src_stride = 16;
this_block->src = 4 * br * 16 + 4 * bc;
++block;
}
}
#else
for (br = 0; br < 4; br++) {
1891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960
for (bc = 0; bc < 4; bc++) {
BLOCK *this_block = &x->block[block];
// this_block->base_src = &x->src.y_buffer;
// this_block->src_stride = x->src.y_stride;
// this_block->src = 4 * br * this_block->src_stride + 4 * bc;
this_block->base_src = &x->src.y_buffer;
this_block->src_stride = x->src.y_stride;
this_block->src = 4 * br * this_block->src_stride + 4 * bc;
++block;
}
}
#endif
// u blocks
for (br = 0; br < 2; br++) {
for (bc = 0; bc < 2; bc++) {
BLOCK *this_block = &x->block[block];
this_block->base_src = &x->src.u_buffer;
this_block->src_stride = x->src.uv_stride;
this_block->src = 4 * br * this_block->src_stride + 4 * bc;
++block;
}
}
// v blocks
for (br = 0; br < 2; br++) {
for (bc = 0; bc < 2; bc++) {
BLOCK *this_block = &x->block[block];
this_block->base_src = &x->src.v_buffer;
this_block->src_stride = x->src.uv_stride;
this_block->src = 4 * br * this_block->src_stride + 4 * bc;
++block;
}
}
}
static void sum_intra_stats(VP9_COMP *cpi, MACROBLOCK *x) {
const MACROBLOCKD *xd = &x->e_mbd;
const MB_PREDICTION_MODE m = xd->mode_info_context->mbmi.mode;
const MB_PREDICTION_MODE uvm = xd->mode_info_context->mbmi.uv_mode;
#ifdef MODE_STATS
const int is_key = cpi->common.frame_type == KEY_FRAME;
++ (is_key ? uv_modes : inter_uv_modes)[uvm];
++ uv_modes_y[m][uvm];
if (m == B_PRED) {
unsigned int *const bct = is_key ? b_modes : inter_b_modes;
int b = 0;
do {
++ bct[xd->block[b].bmi.as_mode.first];
} while (++b < 16);
}
if (m == I8X8_PRED) {
i8x8_modes[xd->block[0].bmi.as_mode.first]++;
i8x8_modes[xd->block[2].bmi.as_mode.first]++;
i8x8_modes[xd->block[8].bmi.as_mode.first]++;
i8x8_modes[xd->block[10].bmi.as_mode.first]++;
}
#endif
#if CONFIG_SUPERBLOCKS
if (xd->mode_info_context->mbmi.encoded_as_sb) {
++cpi->sb_ymode_count[m];
} else
#endif
1961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030
++cpi->ymode_count[m];
if (m != I8X8_PRED)
++cpi->y_uv_mode_count[m][uvm];
else {
cpi->i8x8_mode_count[xd->block[0].bmi.as_mode.first]++;
cpi->i8x8_mode_count[xd->block[2].bmi.as_mode.first]++;
cpi->i8x8_mode_count[xd->block[8].bmi.as_mode.first]++;
cpi->i8x8_mode_count[xd->block[10].bmi.as_mode.first]++;
}
if (m == B_PRED) {
int b = 0;
do {
int m = xd->block[b].bmi.as_mode.first;
#if CONFIG_NEWBINTRAMODES
if (m == B_CONTEXT_PRED) m -= CONTEXT_PRED_REPLACEMENTS;
#endif
++cpi->bmode_count[m];
} while (++b < 16);
}
}
// Experimental stub function to create a per MB zbin adjustment based on
// some previously calculated measure of MB activity.
static void adjust_act_zbin(VP9_COMP *cpi, MACROBLOCK *x) {
#if USE_ACT_INDEX
x->act_zbin_adj = *(x->mb_activity_ptr);
#else
int64_t a;
int64_t b;
int64_t act = *(x->mb_activity_ptr);
// Apply the masking to the RD multiplier.
a = act + 4 * cpi->activity_avg;
b = 4 * act + cpi->activity_avg;
if (act > cpi->activity_avg)
x->act_zbin_adj = (int)(((int64_t)b + (a >> 1)) / a) - 1;
else
x->act_zbin_adj = 1 - (int)(((int64_t)a + (b >> 1)) / b);
#endif
}
#if CONFIG_SUPERBLOCKS
static void update_sb_skip_coeff_state(VP9_COMP *cpi,
MACROBLOCK *x,
ENTROPY_CONTEXT_PLANES ta[4],
ENTROPY_CONTEXT_PLANES tl[4],
TOKENEXTRA *t[4],
TOKENEXTRA **tp,
int skip[4])
{
TOKENEXTRA tokens[4][16 * 24];
int n_tokens[4], n;
// if there were no skips, we don't need to do anything
if (!skip[0] && !skip[1] && !skip[2] && !skip[3])
return;
// if we don't do coeff skipping for this frame, we don't
// need to do anything here
if (!cpi->common.mb_no_coeff_skip)
return;
// if all 4 MBs skipped coeff coding, nothing to be done
if (skip[0] && skip[1] && skip[2] && skip[3])
return;
// so the situation now is that we want to skip coeffs
// for some MBs, but not all, and we didn't code EOB
// coefficients for them. However, the skip flag for this
2031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100
// SB will be 0 overall, so we need to insert EOBs in the
// middle of the token tree. Do so here.
n_tokens[0] = t[1] - t[0];
n_tokens[1] = t[2] - t[1];
n_tokens[2] = t[3] - t[2];
n_tokens[3] = *tp - t[3];
if (n_tokens[0])
memcpy(tokens[0], t[0], n_tokens[0] * sizeof(*t[0]));
if (n_tokens[1])
memcpy(tokens[1], t[1], n_tokens[1] * sizeof(*t[0]));
if (n_tokens[2])
memcpy(tokens[2], t[2], n_tokens[2] * sizeof(*t[0]));
if (n_tokens[3])
memcpy(tokens[3], t[3], n_tokens[3] * sizeof(*t[0]));
// reset pointer, stuff EOBs where necessary
*tp = t[0];
for (n = 0; n < 4; n++) {
if (skip[n]) {
x->e_mbd.above_context = &ta[n];
x->e_mbd.left_context = &tl[n];
vp9_stuff_mb(cpi, &x->e_mbd, tp, 0);
} else {
if (n_tokens[n]) {
memcpy(*tp, tokens[n], sizeof(*t[0]) * n_tokens[n]);
}
(*tp) += n_tokens[n];
}
}
}
#endif /* CONFIG_SUPERBLOCKS */
static void encode_macroblock(VP9_COMP *cpi, MACROBLOCK *x,
TOKENEXTRA **t, int recon_yoffset,
int recon_uvoffset, int output_enabled,
int mb_col, int mb_row) {
VP9_COMMON *cm = &cpi->common;
MACROBLOCKD *const xd = &x->e_mbd;
MB_MODE_INFO * mbmi = &xd->mode_info_context->mbmi;
unsigned char *segment_id = &mbmi->segment_id;
int seg_ref_active;
unsigned char ref_pred_flag;
x->skip = 0;
#if CONFIG_SUPERBLOCKS
assert(!xd->mode_info_context->mbmi.encoded_as_sb);
#endif
#ifdef ENC_DEBUG
enc_debug = (cpi->common.current_video_frame == 46 &&
mb_row == 5 && mb_col == 2);
if (enc_debug)
printf("Encode MB %d %d output %d\n", mb_row, mb_col, output_enabled);
#endif
if (cm->frame_type == KEY_FRAME) {
if (cpi->oxcf.tuning == VP8_TUNE_SSIM && output_enabled) {
// Adjust the zbin based on this MB rate.
adjust_act_zbin(cpi, x);
vp9_update_zbin_extra(cpi, x);
}
} else {
vp9_setup_interp_filters(xd, mbmi->interp_filter, cm);
if (cpi->oxcf.tuning == VP8_TUNE_SSIM) {
// Adjust the zbin based on this MB rate.
adjust_act_zbin(cpi, x);
}
// Experimental code. Special case for gf and arf zeromv modes.
// Increase zbin size to suppress noise
2101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170
cpi->zbin_mode_boost = 0;
if (cpi->zbin_mode_boost_enabled) {
if (mbmi->ref_frame != INTRA_FRAME) {
if (mbmi->mode == ZEROMV) {
if (mbmi->ref_frame != LAST_FRAME)
cpi->zbin_mode_boost = GF_ZEROMV_ZBIN_BOOST;
else
cpi->zbin_mode_boost = LF_ZEROMV_ZBIN_BOOST;
} else if (mbmi->mode == SPLITMV)
cpi->zbin_mode_boost = 0;
else
cpi->zbin_mode_boost = MV_ZBIN_BOOST;
}
}
vp9_update_zbin_extra(cpi, x);
seg_ref_active = vp9_segfeature_active(xd, *segment_id, SEG_LVL_REF_FRAME);
// SET VARIOUS PREDICTION FLAGS
// Did the chosen reference frame match its predicted value.
ref_pred_flag = ((mbmi->ref_frame == vp9_get_pred_ref(cm, xd)));
vp9_set_pred_flag(xd, PRED_REF, ref_pred_flag);
}
assert(mbmi->txfm_size <= TX_16X16);
if (mbmi->ref_frame == INTRA_FRAME) {
#ifdef ENC_DEBUG
if (enc_debug) {
printf("Mode %d skip %d tx_size %d\n", mbmi->mode, x->skip,
mbmi->txfm_size);
}
#endif
if (mbmi->mode == B_PRED) {
vp9_encode_intra16x16mbuv(x);
vp9_encode_intra4x4mby(x);
} else if (mbmi->mode == I8X8_PRED) {
vp9_encode_intra8x8mby(x);
vp9_encode_intra8x8mbuv(x);
} else {
vp9_encode_intra16x16mbuv(x);
vp9_encode_intra16x16mby(x);
}
if (output_enabled)
sum_intra_stats(cpi, x);
} else {
int ref_fb_idx;
#ifdef ENC_DEBUG
if (enc_debug)
printf("Mode %d skip %d tx_size %d ref %d ref2 %d mv %d %d interp %d\n",
mbmi->mode, x->skip, mbmi->txfm_size,
mbmi->ref_frame, mbmi->second_ref_frame,
mbmi->mv[0].as_mv.row, mbmi->mv[0].as_mv.col,
mbmi->interp_filter);
#endif
assert(cm->frame_type != KEY_FRAME);
if (mbmi->ref_frame == LAST_FRAME)
ref_fb_idx = cpi->common.lst_fb_idx;
else if (mbmi->ref_frame == GOLDEN_FRAME)
ref_fb_idx = cpi->common.gld_fb_idx;
else
ref_fb_idx = cpi->common.alt_fb_idx;
xd->pre.y_buffer = cpi->common.yv12_fb[ref_fb_idx].y_buffer + recon_yoffset;
xd->pre.u_buffer = cpi->common.yv12_fb[ref_fb_idx].u_buffer + recon_uvoffset;
xd->pre.v_buffer = cpi->common.yv12_fb[ref_fb_idx].v_buffer + recon_uvoffset;
2171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240
if (mbmi->second_ref_frame > 0) {
int second_ref_fb_idx;
if (mbmi->second_ref_frame == LAST_FRAME)
second_ref_fb_idx = cpi->common.lst_fb_idx;
else if (mbmi->second_ref_frame == GOLDEN_FRAME)
second_ref_fb_idx = cpi->common.gld_fb_idx;
else
second_ref_fb_idx = cpi->common.alt_fb_idx;
xd->second_pre.y_buffer = cpi->common.yv12_fb[second_ref_fb_idx].y_buffer +
recon_yoffset;
xd->second_pre.u_buffer = cpi->common.yv12_fb[second_ref_fb_idx].u_buffer +
recon_uvoffset;
xd->second_pre.v_buffer = cpi->common.yv12_fb[second_ref_fb_idx].v_buffer +
recon_uvoffset;
}
if (!x->skip) {
vp9_encode_inter16x16(x);
// Clear mb_skip_coeff if mb_no_coeff_skip is not set
if (!cpi->common.mb_no_coeff_skip)
mbmi->mb_skip_coeff = 0;
} else {
vp9_build_1st_inter16x16_predictors_mb(xd,
xd->dst.y_buffer,
xd->dst.u_buffer,
xd->dst.v_buffer,
xd->dst.y_stride,
xd->dst.uv_stride);
if (xd->mode_info_context->mbmi.second_ref_frame > 0) {
vp9_build_2nd_inter16x16_predictors_mb(xd,
xd->dst.y_buffer,
xd->dst.u_buffer,
xd->dst.v_buffer,
xd->dst.y_stride,
xd->dst.uv_stride);
}
#if CONFIG_COMP_INTERINTRA_PRED
else if (xd->mode_info_context->mbmi.second_ref_frame == INTRA_FRAME) {
vp9_build_interintra_16x16_predictors_mb(xd,
xd->dst.y_buffer,
xd->dst.u_buffer,
xd->dst.v_buffer,
xd->dst.y_stride,
xd->dst.uv_stride);
}
#endif
}
}
if (!x->skip) {
#ifdef ENC_DEBUG
if (enc_debug) {
int i, j;
printf("\n");
printf("qcoeff\n");
for (i = 0; i < 400; i++) {
printf("%3d ", xd->qcoeff[i]);
if (i % 16 == 15) printf("\n");
}
printf("\n");
printf("predictor\n");
for (i = 0; i < 384; i++) {
printf("%3d ", xd->predictor[i]);
if (i % 16 == 15) printf("\n");
}
2241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310
printf("\n");
printf("src_diff\n");
for (i = 0; i < 384; i++) {
printf("%3d ", x->src_diff[i]);
if (i % 16 == 15) printf("\n");
}
printf("\n");
printf("diff\n");
for (i = 0; i < 384; i++) {
printf("%3d ", xd->block[0].diff[i]);
if (i % 16 == 15) printf("\n");
}
printf("\n");
printf("final y\n");
for (i = 0; i < 16; i++) {
for (j = 0; j < 16; j++)
printf("%3d ", xd->dst.y_buffer[i * xd->dst.y_stride + j]);
printf("\n");
}
printf("\n");
printf("final u\n");
for (i = 0; i < 8; i++) {
for (j = 0; j < 8; j++)
printf("%3d ", xd->dst.u_buffer[i * xd->dst.uv_stride + j]);
printf("\n");
}
printf("\n");
printf("final v\n");
for (i = 0; i < 8; i++) {
for (j = 0; j < 8; j++)
printf("%3d ", xd->dst.v_buffer[i * xd->dst.uv_stride + j]);
printf("\n");
}
fflush(stdout);
}
#endif
vp9_tokenize_mb(cpi, xd, t, !output_enabled);
} else {
int mb_skip_context =
cpi->common.mb_no_coeff_skip ?
(x->e_mbd.mode_info_context - 1)->mbmi.mb_skip_coeff +
(x->e_mbd.mode_info_context - cpi->common.mode_info_stride)->mbmi.mb_skip_coeff :
0;
if (cpi->common.mb_no_coeff_skip) {
mbmi->mb_skip_coeff = 1;
if (output_enabled)
cpi->skip_true_count[mb_skip_context]++;
vp9_reset_mb_tokens_context(xd);
} else {
vp9_stuff_mb(cpi, xd, t, !output_enabled);
mbmi->mb_skip_coeff = 0;
if (output_enabled)
cpi->skip_false_count[mb_skip_context]++;
}
}
if (output_enabled) {
int segment_id = mbmi->segment_id;
if (cpi->common.txfm_mode == TX_MODE_SELECT &&
!((cpi->common.mb_no_coeff_skip && mbmi->mb_skip_coeff) ||
(vp9_segfeature_active(&x->e_mbd, segment_id, SEG_LVL_EOB) &&
vp9_get_segdata(&x->e_mbd, segment_id, SEG_LVL_EOB) == 0))) {
if (mbmi->mode != B_PRED && mbmi->mode != I8X8_PRED &&
mbmi->mode != SPLITMV) {
cpi->txfm_count_16x16p[mbmi->txfm_size]++;
} else if (mbmi->mode == I8X8_PRED ||
(mbmi->mode == SPLITMV &&
mbmi->partitioning != PARTITIONING_4X4)) {
2311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380
cpi->txfm_count_8x8p[mbmi->txfm_size]++;
}
} else if (mbmi->mode != B_PRED && mbmi->mode != I8X8_PRED &&
mbmi->mode != SPLITMV && cpi->common.txfm_mode >= ALLOW_16X16) {
mbmi->txfm_size = TX_16X16;
} else if (mbmi->mode != B_PRED &&
!(mbmi->mode == SPLITMV &&
mbmi->partitioning == PARTITIONING_4X4) &&
cpi->common.txfm_mode >= ALLOW_8X8) {
mbmi->txfm_size = TX_8X8;
} else {
mbmi->txfm_size = TX_4X4;
}
}
}
#if CONFIG_SUPERBLOCKS
static void encode_superblock(VP9_COMP *cpi, MACROBLOCK *x,
TOKENEXTRA **t, int recon_yoffset,
int recon_uvoffset, int mb_col, int mb_row) {
VP9_COMMON *const cm = &cpi->common;
MACROBLOCKD *const xd = &x->e_mbd;
const uint8_t *src = x->src.y_buffer;
uint8_t *dst = xd->dst.y_buffer;
const uint8_t *usrc = x->src.u_buffer;
uint8_t *udst = xd->dst.u_buffer;
const uint8_t *vsrc = x->src.v_buffer;
uint8_t *vdst = xd->dst.v_buffer;
int src_y_stride = x->src.y_stride, dst_y_stride = xd->dst.y_stride;
int src_uv_stride = x->src.uv_stride, dst_uv_stride = xd->dst.uv_stride;
int seg_ref_active;
unsigned char ref_pred_flag;
int n;
TOKENEXTRA *tp[4];
int skip[4];
MODE_INFO *mi = x->e_mbd.mode_info_context;
unsigned int segment_id = mi->mbmi.segment_id;
ENTROPY_CONTEXT_PLANES ta[4], tl[4];
const int mis = cm->mode_info_stride;
x->skip = 0;
if (cm->frame_type == KEY_FRAME) {
if (cpi->oxcf.tuning == VP8_TUNE_SSIM) {
adjust_act_zbin(cpi, x);
vp9_update_zbin_extra(cpi, x);
}
} else {
vp9_setup_interp_filters(xd, xd->mode_info_context->mbmi.interp_filter, cm);
if (cpi->oxcf.tuning == VP8_TUNE_SSIM) {
// Adjust the zbin based on this MB rate.
adjust_act_zbin(cpi, x);
}
// Experimental code. Special case for gf and arf zeromv modes.
// Increase zbin size to suppress noise
cpi->zbin_mode_boost = 0;
if (cpi->zbin_mode_boost_enabled) {
if (xd->mode_info_context->mbmi.ref_frame != INTRA_FRAME) {
if (xd->mode_info_context->mbmi.mode == ZEROMV) {
if (xd->mode_info_context->mbmi.ref_frame != LAST_FRAME)
cpi->zbin_mode_boost = GF_ZEROMV_ZBIN_BOOST;
else
cpi->zbin_mode_boost = LF_ZEROMV_ZBIN_BOOST;
} else if (xd->mode_info_context->mbmi.mode == SPLITMV)
cpi->zbin_mode_boost = 0;
else
cpi->zbin_mode_boost = MV_ZBIN_BOOST;
}
2381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450
}
vp9_update_zbin_extra(cpi, x);
seg_ref_active = vp9_segfeature_active(xd, segment_id, SEG_LVL_REF_FRAME);
// SET VARIOUS PREDICTION FLAGS
// Did the chosen reference frame match its predicted value.
ref_pred_flag = ((xd->mode_info_context->mbmi.ref_frame ==
vp9_get_pred_ref(cm, xd)));
vp9_set_pred_flag(xd, PRED_REF, ref_pred_flag);
}
if (xd->mode_info_context->mbmi.ref_frame == INTRA_FRAME) {
vp9_build_intra_predictors_sby_s(&x->e_mbd);
vp9_build_intra_predictors_sbuv_s(&x->e_mbd);
sum_intra_stats(cpi, x);
} else {
int ref_fb_idx;
assert(cm->frame_type != KEY_FRAME);
if (xd->mode_info_context->mbmi.ref_frame == LAST_FRAME)
ref_fb_idx = cpi->common.lst_fb_idx;
else if (xd->mode_info_context->mbmi.ref_frame == GOLDEN_FRAME)
ref_fb_idx = cpi->common.gld_fb_idx;
else
ref_fb_idx = cpi->common.alt_fb_idx;
xd->pre.y_buffer = cpi->common.yv12_fb[ref_fb_idx].y_buffer + recon_yoffset;
xd->pre.u_buffer = cpi->common.yv12_fb[ref_fb_idx].u_buffer + recon_uvoffset;
xd->pre.v_buffer = cpi->common.yv12_fb[ref_fb_idx].v_buffer + recon_uvoffset;
if (xd->mode_info_context->mbmi.second_ref_frame > 0) {
int second_ref_fb_idx;
if (xd->mode_info_context->mbmi.second_ref_frame == LAST_FRAME)
second_ref_fb_idx = cpi->common.lst_fb_idx;
else if (xd->mode_info_context->mbmi.second_ref_frame == GOLDEN_FRAME)
second_ref_fb_idx = cpi->common.gld_fb_idx;
else
second_ref_fb_idx = cpi->common.alt_fb_idx;
xd->second_pre.y_buffer = cpi->common.yv12_fb[second_ref_fb_idx].y_buffer +
recon_yoffset;
xd->second_pre.u_buffer = cpi->common.yv12_fb[second_ref_fb_idx].u_buffer +
recon_uvoffset;
xd->second_pre.v_buffer = cpi->common.yv12_fb[second_ref_fb_idx].v_buffer +
recon_uvoffset;
}
vp9_build_inter32x32_predictors_sb(xd, xd->dst.y_buffer,
xd->dst.u_buffer, xd->dst.v_buffer,
xd->dst.y_stride, xd->dst.uv_stride);
}
#if CONFIG_TX32X32
if (xd->mode_info_context->mbmi.txfm_size == TX_32X32) {
vp9_subtract_sby_s_c(x->sb_coeff_data.src_diff, src, src_y_stride,
dst, dst_y_stride);
vp9_subtract_sbuv_s_c(x->sb_coeff_data.src_diff,
usrc, vsrc, src_uv_stride,
udst, vdst, dst_uv_stride);
vp9_transform_sby_32x32(x);
vp9_transform_sbuv_16x16(x);
vp9_quantize_sby_32x32(x);
vp9_quantize_sbuv_16x16(x);
// TODO(rbultje): trellis optimize
2451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520
vp9_inverse_transform_sbuv_16x16(&x->e_mbd.sb_coeff_data);
vp9_inverse_transform_sby_32x32(&x->e_mbd.sb_coeff_data);
vp9_recon_sby_s_c(&x->e_mbd, dst);
vp9_recon_sbuv_s_c(&x->e_mbd, udst, vdst);
if (!x->skip) {
vp9_tokenize_sb(cpi, &x->e_mbd, t, 0);
} else {
int mb_skip_context =
cpi->common.mb_no_coeff_skip ?
(mi - 1)->mbmi.mb_skip_coeff +
(mi - mis)->mbmi.mb_skip_coeff :
0;
mi->mbmi.mb_skip_coeff = 1;
if (cm->mb_no_coeff_skip) {
cpi->skip_true_count[mb_skip_context]++;
vp9_fix_contexts_sb(xd);
} else {
vp9_stuff_sb(cpi, xd, t, 0);
cpi->skip_false_count[mb_skip_context]++;
}
}
// copy skip flag on all mb_mode_info contexts in this SB
// if this was a skip at this txfm size
if (mb_col < cm->mb_cols - 1)
mi[1].mbmi.mb_skip_coeff = mi->mbmi.mb_skip_coeff;
if (mb_row < cm->mb_rows - 1) {
mi[mis].mbmi.mb_skip_coeff = mi->mbmi.mb_skip_coeff;
if (mb_col < cm->mb_cols - 1)
mi[mis + 1].mbmi.mb_skip_coeff = mi->mbmi.mb_skip_coeff;
}
skip[0] = skip[2] = skip[1] = skip[3] = mi->mbmi.mb_skip_coeff;
} else {
#endif
for (n = 0; n < 4; n++) {
int x_idx = n & 1, y_idx = n >> 1;
xd->left_context = cm->left_context + y_idx;
xd->above_context = cm->above_context + mb_col + x_idx;
memcpy(&ta[n], xd->above_context, sizeof(ta[n]));
memcpy(&tl[n], xd->left_context, sizeof(tl[n]));
tp[n] = *t;
xd->mode_info_context = mi + x_idx + y_idx * mis;
vp9_subtract_mby_s_c(x->src_diff,
src + x_idx * 16 + y_idx * 16 * src_y_stride,
src_y_stride,
dst + x_idx * 16 + y_idx * 16 * dst_y_stride,
dst_y_stride);
vp9_subtract_mbuv_s_c(x->src_diff,
usrc + x_idx * 8 + y_idx * 8 * src_uv_stride,
vsrc + x_idx * 8 + y_idx * 8 * src_uv_stride,
src_uv_stride,
udst + x_idx * 8 + y_idx * 8 * dst_uv_stride,
vdst + x_idx * 8 + y_idx * 8 * dst_uv_stride,
dst_uv_stride);
vp9_fidct_mb(x);
vp9_recon_mby_s_c(&x->e_mbd,
dst + x_idx * 16 + y_idx * 16 * dst_y_stride);
vp9_recon_mbuv_s_c(&x->e_mbd,
udst + x_idx * 8 + y_idx * 8 * dst_uv_stride,
vdst + x_idx * 8 + y_idx * 8 * dst_uv_stride);
if (!x->skip) {
vp9_tokenize_mb(cpi, &x->e_mbd, t, 0);
skip[n] = xd->mode_info_context->mbmi.mb_skip_coeff;
} else {
int mb_skip_context =
cpi->common.mb_no_coeff_skip ?
2521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566
(x->e_mbd.mode_info_context - 1)->mbmi.mb_skip_coeff +
(x->e_mbd.mode_info_context - mis)->mbmi.mb_skip_coeff :
0;
xd->mode_info_context->mbmi.mb_skip_coeff = skip[n] = 1;
if (cpi->common.mb_no_coeff_skip) {
// TODO(rbultje) this should be done per-sb instead of per-mb?
cpi->skip_true_count[mb_skip_context]++;
vp9_reset_mb_tokens_context(xd);
} else {
vp9_stuff_mb(cpi, xd, t, 0);
// TODO(rbultje) this should be done per-sb instead of per-mb?
cpi->skip_false_count[mb_skip_context]++;
}
}
}
xd->mode_info_context = mi;
update_sb_skip_coeff_state(cpi, x, ta, tl, tp, t, skip);
#if CONFIG_TX32X32
}
#endif
if (cm->txfm_mode == TX_MODE_SELECT &&
!((cm->mb_no_coeff_skip && skip[0] && skip[1] && skip[2] && skip[3]) ||
(vp9_segfeature_active(xd, segment_id, SEG_LVL_EOB) &&
vp9_get_segdata(xd, segment_id, SEG_LVL_EOB) == 0))) {
cpi->txfm_count_32x32p[mi->mbmi.txfm_size]++;
} else {
TX_SIZE sz = (cm->txfm_mode == TX_MODE_SELECT) ?
#if CONFIG_TX32X32
TX_32X32 :
#else
TX_16X16 :
#endif
cm->txfm_mode;
mi->mbmi.txfm_size = sz;
if (mb_col < cm->mb_cols - 1)
mi[1].mbmi.txfm_size = sz;
if (mb_row < cm->mb_rows - 1) {
mi[mis].mbmi.txfm_size = sz;
if (mb_col < cm->mb_cols - 1)
mi[mis + 1].mbmi.txfm_size = sz;
}
}
}
#endif