Newer
Older
}
#if CONFIG_SUPERBLOCKS
if (xd->mode_info_context->mbmi.encoded_as_sb)
encode_inter_superblock(cpi, x, tp, recon_yoffset, recon_uvoffset,
mb_col, mb_row);
encode_inter_macroblock(cpi, x, tp, recon_yoffset, recon_uvoffset, 1,
mb_col, mb_row);
// Note the encoder may have changed the segment_id
for (b = 0; b < x->partition_info->count; b++) {
inter_b_modes[x->partition_info->bmi[b].mode]++;
}
}
// 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.
seg_ref_active = vp9_segfeature_active(xd, *segment_id,
SEG_LVL_REF_FRAME);
((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)) {
if ((mbmi->mode == ZEROMV) && (mbmi->ref_frame == LAST_FRAME))
#if CONFIG_SUPERBLOCKS
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;
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;
assert((xd->prev_mode_info_context - cpi->common.prev_mip) ==
(xd->mode_info_context - cpi->common.mip));
(*tp)->Token = EOSB_TOKEN;
(*tp)++;
if (mb_row < cm->mb_rows) cpi->tplist[mb_row].stop = *tp;
{
FILE *statsfile;
statsfile = fopen("segmap2.stt", "a");
fprintf(statsfile, "\n");
fclose(statsfile);
}
#endif
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) {
MODE_INFO *mic = xd->mode_info_context;
PARTITION_INFO *pi = x->partition_info;
signed char *gfa = x->gf_active_ptr;
unsigned char *yb = x->src.y_buffer;
unsigned char *ub = x->src.u_buffer;
unsigned char *vb = x->src.v_buffer;
// 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);
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;
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);
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;
#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
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);
// 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);
assert((xd->prev_mode_info_context - cpi->common.prev_mip) ==
(xd->mode_info_context - cpi->common.mip));
static void init_encode_frame_mb_context(VP9_COMP *cpi) {
VP9_COMMON *const cm = &cpi->common;
// 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));
xd->mode_info_context = cm->mi;
xd->mode_info_stride = cm->mode_info_stride;
xd->prev_mode_info_context = cm->prev_mi;
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];
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);
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)
vp9_zero(cpi->common.fc.mv_ref_ct_a)
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) {
VP9_COMMON *const cm = &cpi->common;
//printf("encode_frame_internal\n");
// 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.
#if CONFIG_NEW_MVREF
// temp stats reset
vp9_zero( cpi->best_ref_index_counts );
{
FILE *statsfile;
statsfile = fopen("segmap2.stt", "a");
fprintf(statsfile, "\n");
fclose(statsfile);
}
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 (cm->current_video_frame == 0) {
// 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;
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);
vp9_zero(cpi->hybrid_coef_counts);
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);
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.
// 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, 0, sizeof(cpi->txfm_count));
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;
// 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);
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;
// Keep record of the total distortion this time around for future use
cpi->last_frame_distortion = cpi->frame_distortion;
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))
if ((ref_flags & (VP9_GOLD_FLAG | VP9_ALT_FLAG)) == (VP9_GOLD_FLAG | VP9_ALT_FLAG) &&
vp9_check_segref(xd, 1, GOLDEN_FRAME))
if ((ref_flags & (VP9_ALT_FLAG | VP9_LAST_FLAG)) == (VP9_ALT_FLAG | VP9_LAST_FLAG) &&
vp9_check_segref(xd, 1, ALTREF_FRAME))
return (!!(ref_flags & VP9_GOLD_FLAG) +
!!(ref_flags & VP9_LAST_FLAG) +
!!(ref_flags & VP9_ALT_FLAG)) >= 2;
Ronald S. Bultje
committed
}
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, skip;
MODE_INFO *mi, *mi_ptr = cm->mi;
#if CONFIG_SUPERBLOCKS
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
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
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;
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
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) {
int i, frame_type, pred_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;
/* prediction (compound, single or hybrid) mode selection */
if (frame_type == 3)
pred_type = SINGLE_PREDICTION_ONLY;
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][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;
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
/* 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) {
txfm_type = ALLOW_16X16;
} 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
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
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 - 1), 0);
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[TX_4X4] + cpi->txfm_count_8x8p[TX_4X4];
const int count8x8 = cpi->txfm_count[TX_8X8];
const int count8x8_8x8p = cpi->txfm_count_8x8p[TX_8X8];
const int count16x16 = cpi->txfm_count[TX_16X16];
if (count4x4 == 0 && count16x16 == 0) {
cpi->common.txfm_mode = ALLOW_8X8;
reset_skip_txfm_size(cpi, TX_8X8);
} else if (count8x8 == 0 && count16x16 == 0 && count8x8_8x8p == 0) {
reset_skip_txfm_size(cpi, TX_4X4);
} else if (count8x8 == 0 && count4x4 == 0) {
cpi->common.txfm_mode = ALLOW_16X16;
}
}
void vp9_setup_block_ptrs(MACROBLOCK *x) {
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;
for (i = 0; i < 25; i++) {
x->block[i].coeff = x->coeff + i * 16;
}
void vp9_build_block_offsets(MACROBLOCK *x) {
vp9_build_block_doffsets(&x->e_mbd);
// 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;
}
// 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 MB_PREDICTION_MODE m = xd->mode_info_context->mbmi.mode;
const MB_PREDICTION_MODE uvm = xd->mode_info_context->mbmi.uv_mode;
++ (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;
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]++;
}
#if CONFIG_SUPERBLOCKS
if (xd->mode_info_context->mbmi.encoded_as_sb) {
++cpi->sb_ymode_count[m];
} else
#endif
++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 {
++ cpi->bmode_count[xd->block[b].bmi.as_mode.first];
} 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) {
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);
static void update_sb_skip_coeff_state(VP9_COMP *cpi,
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
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
// 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];
}
}
}
static void encode_intra_super_block(VP9_COMP *cpi, MACROBLOCK *x,
TOKENEXTRA **t, int mb_col, int mb_row) {
const int output_enabled = 1;
int n;
MACROBLOCKD *xd = &x->e_mbd;
VP9_COMMON *cm = &cpi->common;
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;
const VP9_ENCODER_RTCD *rtcd = IF_RTCD(&cpi->rtcd);
MODE_INFO *mi = xd->mode_info_context;
ENTROPY_CONTEXT_PLANES ta[4], tl[4];
if ((cpi->oxcf.tuning == VP8_TUNE_SSIM) && output_enabled) {
adjust_act_zbin(cpi, x);
vp9_update_zbin_extra(cpi, x);
vp9_build_intra_predictors_sby_s(&x->e_mbd);
vp9_build_intra_predictors_sbuv_s(&x->e_mbd);
int x_idx = n & 1, y_idx = n >> 1;
xd->above_context = cm->above_context + mb_col + (n & 1);
xd->left_context = cm->left_context + (n >> 1);
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, rtcd);
vp9_recon_mby_s_c(xd, dst + x_idx * 16 + y_idx * 16 * dst_y_stride);
vp9_recon_mbuv_s_c(xd,
udst + x_idx * 8 + y_idx * 8 * dst_uv_stride,
vdst + x_idx * 8 + y_idx * 8 * dst_uv_stride);
if (output_enabled) {
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 * cm->mode_info_stride;
vp9_tokenize_mb(cpi, xd, t, 0);
skip[n] = xd->mode_info_context->mbmi.mb_skip_coeff;
}
}
if (output_enabled) {
segment_id = mi->mbmi.segment_id;
sum_intra_stats(cpi, x);
update_sb_skip_coeff_state(cpi, x, ta, tl, tp, t, skip);
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[mi->mbmi.txfm_size]++;
} else {
TX_SIZE sz = (cm->txfm_mode == TX_MODE_SELECT) ? TX_16X16 : 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[cm->mode_info_stride].mbmi.txfm_size = sz;
if (mb_col < cm->mb_cols - 1)
mi[cm->mode_info_stride + 1].mbmi.txfm_size = sz;
}
}
static void encode_intra_macro_block(VP9_COMP *cpi, MACROBLOCK *x,
TOKENEXTRA **t, int output_enabled) {
if ((cpi->oxcf.tuning == VP8_TUNE_SSIM) && output_enabled) {
adjust_act_zbin(cpi, x);
vp9_update_zbin_extra(cpi, x);
vp9_encode_intra8x8mby(IF_RTCD(&cpi->rtcd), x);
vp9_encode_intra8x8mbuv(IF_RTCD(&cpi->rtcd), x);
} else if (mbmi->mode == B_PRED) {
vp9_encode_intra4x4mby(IF_RTCD(&cpi->rtcd), x);
vp9_encode_intra16x16mby(IF_RTCD(&cpi->rtcd), x);
if (mbmi->mode != I8X8_PRED) {
vp9_encode_intra16x16mbuv(IF_RTCD(&cpi->rtcd), x);
int segment_id = mbmi->segment_id;
vp9_tokenize_mb(cpi, &x->e_mbd, t, 0);
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) {
cpi->txfm_count[mbmi->txfm_size]++;
} else if (mbmi->mode == I8X8_PRED) {
cpi->txfm_count_8x8p[mbmi->txfm_size]++;
} else if (cpi->common.txfm_mode >= ALLOW_16X16 && mbmi->mode <= TM_PRED) {
mbmi->txfm_size = TX_16X16;
} else
if (cpi->common.txfm_mode >= ALLOW_8X8 && mbmi->mode != B_PRED) {
mbmi->txfm_size = TX_8X8;
} else {
mbmi->txfm_size = TX_4X4;
}