/* activity_avg must be positive, or flat regions could get a zero weight *(infinitelambda),whichconfoundsanalysis. *Thisalsoavoidstheneedfordividebyzerochecksin *vp8_activity_masking().
*/ #define VP8_ACTIVITY_AVG_MIN (64)
/* This is used as a reference when computing the source variance for the *purposesofactivitymasking. *Eventuallythisshouldbereplacedbycustomno-referenceroutines, *whichwillbefaster.
*/ staticconstunsignedchar VP8_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. */ staticunsignedint tt_activity_measure(MACROBLOCK *x) { unsignedint act; unsignedint sse; /* TODO: This could also be done over smaller areas (8x8), but that would *requireextensivechangeselsewhere,aslambdaisassumedtobefixed *overanentireMBinmostofthecode. *Anotheroptionistocomputefour8x8variances,andpickasingle *lambdausinganon-linearcombination(e.g.,thesmallest,orsecond *smallest,etc.).
*/
act = vpx_variance16x16(x->src.y_buffer, x->src.y_stride, VP8_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;
}
/* Measure the activity of the current macroblock *WhatwemeasurehereisTBDsoabstractedtothisfunction
*/ #define ALT_ACT_MEASURE 1 staticunsignedint mb_activity_measure(MACROBLOCK *x, int mb_row, int mb_col) { unsignedint mb_activity;
if (ALT_ACT_MEASURE) { int use_dc_pred = (mb_col > 1 && mb_row > 1); /* Or use an alternative. */
mb_activity = vp8_encode_intra(x, use_dc_pred);
} else { /* Original activity measure from Tim T's code. */
mb_activity = tt_activity_measure(x);
}
if (mb_activity < VP8_ACTIVITY_AVG_MIN) mb_activity = VP8_ACTIVITY_AVG_MIN;
return mb_activity;
}
/* Calculate an "average" mb activity value for the frame */ #define ACT_MEDIAN 0 staticvoid calc_av_activity(VP8_COMP *cpi, int64_t activity_sum) { #if ACT_MEDIAN /* Find median: Simple n^2 algorithm for experimentation */
{ unsignedint median; unsignedint i, j; unsignedint *sortlist; unsignedint tmp;
/* Create a list to sort to */
CHECK_MEM_ERROR(&cpi->common.error, sortlist,
vpx_calloc(sizeof(unsignedint), cpi->common.MBs));
/* Copy map to sort list */
memcpy(sortlist, cpi->mb_activity_map, sizeof(unsignedint) * 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 = (unsignedint)(activity_sum / cpi->common.MBs); #endif
if (cpi->activity_avg < VP8_ACTIVITY_AVG_MIN) {
cpi->activity_avg = VP8_ACTIVITY_AVG_MIN;
}
/* Experimental code: return fixed value normalized for several clips */ if (ALT_ACT_MEASURE) cpi->activity_avg = 100000;
}
#if USE_ACT_INDEX /* Calculate and activity index for each mb */ staticvoid calc_activity_index(VP8_COMP *cpi, MACROBLOCK *x) {
VP8_COMMON *const cm = &cpi->common; int mb_row, mb_col;
/* Loop through all MBs. Note activity of each, average activity and *calculateanormalizedactivityforeach
*/ staticvoid build_activity_map(VP8_COMP *cpi) {
MACROBLOCK *const x = &cpi->mb;
MACROBLOCKD *xd = &x->e_mbd;
VP8_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; unsignedint 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);
recon_yoffset += 16; #endif /* Copy current mb to a buffer */
vp8_copy_mem16x16(x->src.y_buffer, x->src.y_stride, x->thismb, 16);
/* Activity based Zbin adjustment */
adjust_act_zbin(cpi, x);
}
staticvoid encode_mb_row(VP8_COMP *cpi, VP8_COMMON *cm, int mb_row,
MACROBLOCK *x, MACROBLOCKD *xd, TOKENEXTRA **tp, int *segment_counts, int *totalrate) { int recon_yoffset, recon_uvoffset; int mb_col; 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 map_index = (mb_row * cpi->common.mb_cols);
if (cpi->oxcf.tuning == VP8_TUNE_SSIM) vp8_activity_masking(cpi, x);
/* Is segmentation enabled */ /* MB level adjustment to quantizer */ if (xd->segmentation_enabled) { /* Code to set segment id in xd->mbmi.segment_id for current MB *(withrangechecking)
*/ if (cpi->segmentation_map[map_index + mb_col] <= 3) {
xd->mode_info_context->mbmi.segment_id =
cpi->segmentation_map[map_index + mb_col];
} else {
xd->mode_info_context->mbmi.segment_id = 0;
}
vp8cx_mb_init_quantizer(cpi, x, 1);
} else { /* Set to Segment 0 by default */
xd->mode_info_context->mbmi.segment_id = 0;
}
/* reset intra mode contexts */ if (cm->frame_type == KEY_FRAME) vp8_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 */
vp8_setup_intra_recon(&cm->yv12_fb[cm->new_fb_idx]);
#if CONFIG_MULTITHREAD staticvoid sum_coef_counts(MACROBLOCK *x, MACROBLOCK *x_thread) { int i = 0; do { int j = 0; do { int k = 0; do { /* at every context */
/* calc probs and branch cts for this frame only */ int t = 0; /* token/prob index */
do {
x->coef_counts[i][j][k][t] += x_thread->coef_counts[i][j][k][t];
} while (++t < ENTROPY_NODES);
} while (++k < PREV_COEF_CONTEXTS);
} while (++j < COEF_BANDS);
} while (++i < BLOCK_TYPES);
} #endif// CONFIG_MULTITHREAD
void vp8_encode_frame(VP8_COMP *cpi) { int mb_row;
MACROBLOCK *const x = &cpi->mb;
VP8_COMMON *const cm = &cpi->common;
MACROBLOCKD *const xd = &x->e_mbd;
TOKENEXTRA *tp = cpi->tok; int segment_counts[MAX_MB_SEGMENTS]; int totalrate; #if CONFIG_REALTIME_ONLY & CONFIG_ONTHEFLY_BITPACKING
BOOL_CODER *bc = &cpi->bc[1]; /* bc[0] is for control partition */ constint num_part = (1 << cm->multi_token_partition); #endif
if (xd->segmentation_enabled) { for (i = 0; i < cpi->encoding_thread_count; ++i) { for (j = 0; j < 4; ++j) {
segment_counts[j] += cpi->mb_row_ei[i].segment_counts[j];
}
}
}
}
for (i = 0; i < cpi->encoding_thread_count; ++i) { int mode_count; int c_idx; /* Saturate like encode_mb_row(); per-thread totalrate is already
* clamped to INT_MAX individually, so their sum can overflow. */ constint thread_rate = cpi->mb_row_ei[i].totalrate; if (INT_MAX - totalrate > thread_rate)
totalrate += thread_rate; else
totalrate = INT_MAX;
// Work out the segment probabilities if segmentation is enabled // and needs to be updated if (xd->segmentation_enabled && xd->update_mb_segmentation_map) { int tot_count; int i;
/* Set to defaults */
memset(xd->mb_segment_tree_probs, 255, sizeof(xd->mb_segment_tree_probs));
/* Zero probabilities not allowed */ for (i = 0; i < MB_FEATURE_TREE_PROBS; ++i) { if (xd->mb_segment_tree_probs[i] == 0) xd->mb_segment_tree_probs[i] = 1;
}
}
}
/* projected_frame_size in units of BYTES */
cpi->projected_frame_size = totalrate >> 8;
/* Make a note of the percentage MBs coded Intra. */ if (cm->frame_type == KEY_FRAME) {
cpi->this_frame_percent_intra = 100;
} else { int tot_modes;
int vp8cx_encode_inter_macroblock(VP8_COMP *cpi, MACROBLOCK *x, TOKENEXTRA **t, int recon_yoffset, int recon_uvoffset, int mb_row, int mb_col) {
MACROBLOCKD *const xd = &x->e_mbd; int intra_error = 0; int rate; int distortion;
#if CONFIG_TEMPORAL_DENOISING /* Reset the best sse mode/mv for each macroblock. */
x->best_reference_frame = INTRA_FRAME;
x->best_zeromv_reference_frame = INTRA_FRAME;
x->best_sse_inter_mode = 0;
x->best_sse_mv.as_int = 0;
x->need_to_clamp_best_mvs = 0; #endif
if (cpi->sf.RD) { int zbin_mode_boost_enabled = x->zbin_mode_boost_enabled;
/* Are we using the fast quantizer for the mode selection? */ if (cpi->sf.use_fastquant_for_pick) {
x->quantize_b = vp8_fast_quantize_b;
/* the fast quantizer does not use zbin_extra, so
* do not recalculate */
x->zbin_mode_boost_enabled = 0;
}
vp8_rd_pick_inter_mode(cpi, x, recon_yoffset, recon_uvoffset, &rate,
&distortion, &intra_error, mb_row, mb_col);
/* switch back to the regular quantizer for the encode */ if (cpi->sf.improved_quant) {
x->quantize_b = vp8_regular_quantize_b;
}
if (xd->mode_info_context->mbmi.mode != B_PRED) {
vp8_inverse_transform_mby(xd);
}
vp8_dequant_idct_add_uv_block(xd->qcoeff + 16 * 16, xd->dequant_uv,
xd->dst.u_buffer, xd->dst.v_buffer,
xd->dst.uv_stride, xd->eobs + 16);
} else { /* always set mb_skip_coeff as it is needed by the loopfilter */
xd->mode_info_context->mbmi.mb_skip_coeff = 1;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.