Merge remote branch 'origin/master' into experimental
Conflicts: vp8/encoder/rdopt.c Change-Id: I85275aab07625bd30bbef16a752b08b18f4451ab
This commit is contained in:
commit
11b9b14691
@ -82,7 +82,9 @@ typedef struct
|
||||
int errthresh;
|
||||
int rddiv;
|
||||
int rdmult;
|
||||
INT64 activity_sum;
|
||||
unsigned int * mb_activity_ptr;
|
||||
int * mb_norm_activity_ptr;
|
||||
signed int act_zbin_adj;
|
||||
|
||||
int mvcosts[2][MVvals+1];
|
||||
int *mvcost[2];
|
||||
|
@ -326,7 +326,10 @@ void vp8cx_mb_init_quantizer(VP8_COMP *cpi, MACROBLOCK *x)
|
||||
QIndex = cpi->common.base_qindex;
|
||||
|
||||
// Y
|
||||
zbin_extra = (cpi->common.Y1dequant[QIndex][1] * (cpi->zbin_over_quant + cpi->zbin_mode_boost)) >> 7;
|
||||
zbin_extra = ( cpi->common.Y1dequant[QIndex][1] *
|
||||
( cpi->zbin_over_quant +
|
||||
cpi->zbin_mode_boost +
|
||||
x->act_zbin_adj ) ) >> 7;
|
||||
|
||||
for (i = 0; i < 16; i++)
|
||||
{
|
||||
@ -341,7 +344,10 @@ void vp8cx_mb_init_quantizer(VP8_COMP *cpi, MACROBLOCK *x)
|
||||
}
|
||||
|
||||
// UV
|
||||
zbin_extra = (cpi->common.UVdequant[QIndex][1] * (cpi->zbin_over_quant + cpi->zbin_mode_boost)) >> 7;
|
||||
zbin_extra = ( cpi->common.UVdequant[QIndex][1] *
|
||||
( cpi->zbin_over_quant +
|
||||
cpi->zbin_mode_boost +
|
||||
x->act_zbin_adj ) ) >> 7;
|
||||
|
||||
for (i = 16; i < 24; i++)
|
||||
{
|
||||
@ -356,7 +362,11 @@ void vp8cx_mb_init_quantizer(VP8_COMP *cpi, MACROBLOCK *x)
|
||||
}
|
||||
|
||||
// Y2
|
||||
zbin_extra = (cpi->common.Y2dequant[QIndex][1] * ((cpi->zbin_over_quant / 2) + cpi->zbin_mode_boost)) >> 7;
|
||||
zbin_extra = ( cpi->common.Y2dequant[QIndex][1] *
|
||||
( (cpi->zbin_over_quant / 2) +
|
||||
cpi->zbin_mode_boost +
|
||||
x->act_zbin_adj ) ) >> 7;
|
||||
|
||||
x->block[24].quant_fast = cpi->Y2quant_fast[QIndex];
|
||||
x->block[24].quant = cpi->Y2quant[QIndex];
|
||||
x->block[24].quant_shift = cpi->Y2quant_shift[QIndex];
|
||||
@ -376,21 +386,32 @@ void vp8_update_zbin_extra(VP8_COMP *cpi, MACROBLOCK *x)
|
||||
int zbin_extra;
|
||||
|
||||
// Y
|
||||
zbin_extra = (cpi->common.Y1dequant[QIndex][1] * (cpi->zbin_over_quant + cpi->zbin_mode_boost)) >> 7;
|
||||
zbin_extra = ( cpi->common.Y1dequant[QIndex][1] *
|
||||
( cpi->zbin_over_quant +
|
||||
cpi->zbin_mode_boost +
|
||||
x->act_zbin_adj ) ) >> 7;
|
||||
for (i = 0; i < 16; i++)
|
||||
{
|
||||
x->block[i].zbin_extra = (short)zbin_extra;
|
||||
}
|
||||
|
||||
// UV
|
||||
zbin_extra = (cpi->common.UVdequant[QIndex][1] * (cpi->zbin_over_quant + cpi->zbin_mode_boost)) >> 7;
|
||||
zbin_extra = ( cpi->common.UVdequant[QIndex][1] *
|
||||
( cpi->zbin_over_quant +
|
||||
cpi->zbin_mode_boost +
|
||||
x->act_zbin_adj ) ) >> 7;
|
||||
|
||||
for (i = 16; i < 24; i++)
|
||||
{
|
||||
x->block[i].zbin_extra = (short)zbin_extra;
|
||||
}
|
||||
|
||||
// Y2
|
||||
zbin_extra = (cpi->common.Y2dequant[QIndex][1] * ((cpi->zbin_over_quant / 2) + cpi->zbin_mode_boost)) >> 7;
|
||||
zbin_extra = ( cpi->common.Y2dequant[QIndex][1] *
|
||||
( (cpi->zbin_over_quant / 2) +
|
||||
cpi->zbin_mode_boost +
|
||||
x->act_zbin_adj ) ) >> 7;
|
||||
|
||||
x->block[24].zbin_extra = (short)zbin_extra;
|
||||
}
|
||||
|
||||
@ -421,13 +442,14 @@ static const unsigned char VP8_VAR_OFFS[16]=
|
||||
128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128
|
||||
};
|
||||
|
||||
unsigned int vp8_activity_masking(VP8_COMP *cpi, MACROBLOCK *x)
|
||||
|
||||
// Original activity measure from Tim T's code.
|
||||
unsigned int tt_activity_measure( VP8_COMP *cpi, MACROBLOCK *x )
|
||||
{
|
||||
unsigned int act;
|
||||
unsigned int sse;
|
||||
int sum;
|
||||
unsigned int a;
|
||||
unsigned int b;
|
||||
|
||||
/* 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.
|
||||
@ -436,29 +458,213 @@ unsigned int vp8_activity_masking(VP8_COMP *cpi, MACROBLOCK *x)
|
||||
* smallest, etc.).
|
||||
*/
|
||||
VARIANCE_INVOKE(&cpi->rtcd.variance, get16x16var)(x->src.y_buffer,
|
||||
x->src.y_stride, VP8_VAR_OFFS, 0, &sse, &sum);
|
||||
x->src.y_stride, VP8_VAR_OFFS, 0, &sse, &sum);
|
||||
|
||||
/* This requires a full 32 bits of precision. */
|
||||
act = (sse<<8) - sum*sum;
|
||||
|
||||
/* Drop 4 to give us some headroom to work with. */
|
||||
act = (act + 8) >> 4;
|
||||
|
||||
/* If the region is flat, lower the activity some more. */
|
||||
if (act < 8<<12)
|
||||
act = act < 5<<12 ? act : 5<<12;
|
||||
/* TODO: For non-flat regions, edge regions should receive less masking
|
||||
* than textured regions, but identifying edge regions quickly and
|
||||
* reliably enough is still a subject of experimentation.
|
||||
* This will be most noticable near edges with a complex shape (e.g.,
|
||||
* text), but the 4x4 transform size should make this less of a problem
|
||||
* than it would be for an 8x8 transform.
|
||||
*/
|
||||
/* Apply the masking to the RD multiplier. */
|
||||
a = act + 4*cpi->activity_avg;
|
||||
b = 4*act + cpi->activity_avg;
|
||||
x->rdmult = (unsigned int)(((INT64)x->rdmult*b + (a>>1))/a);
|
||||
|
||||
return act;
|
||||
}
|
||||
|
||||
// Stub for alternative experimental activity measures.
|
||||
unsigned int alt_activity_measure( VP8_COMP *cpi, MACROBLOCK *x )
|
||||
{
|
||||
unsigned int mb_activity = VP8_ACTIVITY_AVG_MIN;
|
||||
|
||||
x->e_mbd.mode_info_context->mbmi.mode = DC_PRED;
|
||||
x->e_mbd.mode_info_context->mbmi.uv_mode = DC_PRED;
|
||||
x->e_mbd.mode_info_context->mbmi.ref_frame = INTRA_FRAME;
|
||||
|
||||
vp8_encode_intra16x16mby(IF_RTCD(&cpi->rtcd), x);
|
||||
|
||||
mb_activity = VARIANCE_INVOKE(&cpi->rtcd.variance, getmbss)(x->src_diff);
|
||||
|
||||
return mb_activity;
|
||||
}
|
||||
|
||||
|
||||
// Measure the activity of the current macroblock
|
||||
// What we measure here is TBD so abstracted to this function
|
||||
unsigned int mb_activity_measure( VP8_COMP *cpi, MACROBLOCK *x )
|
||||
{
|
||||
unsigned int mb_activity;
|
||||
|
||||
if ( 1 )
|
||||
{
|
||||
// Original activity measure from Tim T's code.
|
||||
mb_activity = tt_activity_measure( cpi, x );
|
||||
}
|
||||
else
|
||||
{
|
||||
// Or use and alternative.
|
||||
mb_activity = alt_activity_measure( cpi, x );
|
||||
}
|
||||
|
||||
return mb_activity;
|
||||
}
|
||||
|
||||
// Calculate an "average" mb activity value for the frame
|
||||
void calc_av_activity( VP8_COMP *cpi, INT64 activity_sum )
|
||||
{
|
||||
// Simple mean for now
|
||||
cpi->activity_avg = (unsigned int)(activity_sum/cpi->common.MBs);
|
||||
if (cpi->activity_avg < VP8_ACTIVITY_AVG_MIN)
|
||||
cpi->activity_avg = VP8_ACTIVITY_AVG_MIN;
|
||||
}
|
||||
|
||||
#define OUTPUT_NORM_ACT_STATS 0
|
||||
// Calculate a normalized activity value for each mb
|
||||
void calc_norm_activity( VP8_COMP *cpi, MACROBLOCK *x )
|
||||
{
|
||||
VP8_COMMON *const cm = & cpi->common;
|
||||
int mb_row, mb_col;
|
||||
|
||||
unsigned int act;
|
||||
unsigned int a;
|
||||
unsigned int b;
|
||||
|
||||
#if OUTPUT_NORM_ACT_STATS
|
||||
FILE *f = fopen("norm_act.stt", "a");
|
||||
fprintf(f, "\n");
|
||||
#endif
|
||||
|
||||
// Reset pointers to start of activity map
|
||||
x->mb_activity_ptr = cpi->mb_activity_map;
|
||||
x->mb_norm_activity_ptr = cpi->mb_norm_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 + 2*cpi->activity_avg;
|
||||
b = 2*act + cpi->activity_avg;
|
||||
|
||||
if ( b >= a )
|
||||
*(x->mb_norm_activity_ptr) = (int)((b + (a>>1))/a);
|
||||
else
|
||||
*(x->mb_norm_activity_ptr) = -(int)((a + (b>>1))/b);
|
||||
|
||||
if ( *(x->mb_norm_activity_ptr) == 0 )
|
||||
{
|
||||
*(x->mb_norm_activity_ptr) = 1;
|
||||
}
|
||||
|
||||
#if OUTPUT_NORM_ACT_STATS
|
||||
fprintf(f, " %6d", *(x->mb_norm_activity_ptr));
|
||||
#endif
|
||||
// Increment activity map pointers
|
||||
x->mb_activity_ptr++;
|
||||
x->mb_norm_activity_ptr++;
|
||||
}
|
||||
|
||||
#if OUTPUT_NORM_ACT_STATS
|
||||
fprintf(f, "\n");
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
#if OUTPUT_NORM_ACT_STATS
|
||||
fclose(f);
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
|
||||
// Loop through all MBs. Note activity of each, average activity and
|
||||
// calculate a normalized activity for each
|
||||
void build_activity_map( VP8_COMP *cpi )
|
||||
{
|
||||
MACROBLOCK *const x = & cpi->mb;
|
||||
VP8_COMMON *const cm = & cpi->common;
|
||||
|
||||
int mb_row, mb_col;
|
||||
unsigned int mb_activity;
|
||||
INT64 activity_sum = 0;
|
||||
|
||||
// Initialise source buffer pointer
|
||||
x->src = *cpi->Source;
|
||||
|
||||
// Set pointer to start of activity map
|
||||
x->mb_activity_ptr = cpi->mb_activity_map;
|
||||
|
||||
// for each macroblock row in image
|
||||
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++)
|
||||
{
|
||||
// measure activity
|
||||
mb_activity = mb_activity_measure( cpi, x );
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
// Calculate an "average" MB activity
|
||||
calc_av_activity(cpi, activity_sum);
|
||||
|
||||
// Calculate a normalized activity number of each mb
|
||||
calc_norm_activity( cpi, x );
|
||||
}
|
||||
|
||||
// Activity masking based on Tim T's original code
|
||||
void vp8_activity_masking(VP8_COMP *cpi, MACROBLOCK *x)
|
||||
{
|
||||
unsigned int a;
|
||||
unsigned int b;
|
||||
unsigned int act = *(x->mb_activity_ptr);
|
||||
|
||||
// Apply the masking to the RD multiplier.
|
||||
a = act + 2*cpi->activity_avg;
|
||||
b = 2*act + cpi->activity_avg;
|
||||
|
||||
//tmp = (unsigned int)(((INT64)tmp*b + (a>>1))/a);
|
||||
x->rdmult = (unsigned int)(((INT64)x->rdmult*b + (a>>1))/a);
|
||||
|
||||
// For now now zbin adjustment on mode choice
|
||||
x->act_zbin_adj = 0;
|
||||
}
|
||||
|
||||
// Stub function to use a normalized activity measure stored at mb level.
|
||||
void vp8_norm_activity_masking(VP8_COMP *cpi, MACROBLOCK *x)
|
||||
{
|
||||
int norm_act;
|
||||
|
||||
norm_act = *(x->mb_norm_activity_ptr);
|
||||
if (norm_act > 0)
|
||||
x->rdmult = norm_act * (x->rdmult);
|
||||
else
|
||||
x->rdmult = -(x->rdmult / norm_act);
|
||||
|
||||
// For now now zbin adjustment on mode choice
|
||||
x->act_zbin_adj = 0;
|
||||
}
|
||||
|
||||
static
|
||||
void encode_mb_row(VP8_COMP *cpi,
|
||||
@ -470,7 +676,6 @@ void encode_mb_row(VP8_COMP *cpi,
|
||||
int *segment_counts,
|
||||
int *totalrate)
|
||||
{
|
||||
INT64 activity_sum = 0;
|
||||
int i;
|
||||
int recon_yoffset, recon_uvoffset;
|
||||
int mb_col;
|
||||
@ -478,7 +683,7 @@ void encode_mb_row(VP8_COMP *cpi,
|
||||
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 seg_map_index = (mb_row * cpi->common.mb_cols);
|
||||
int map_index = (mb_row * cpi->common.mb_cols);
|
||||
|
||||
#if CONFIG_MULTITHREAD
|
||||
const int nsync = cpi->mt_sync_range;
|
||||
@ -512,6 +717,10 @@ void encode_mb_row(VP8_COMP *cpi,
|
||||
x->mv_row_max = ((cm->mb_rows - 1 - mb_row) * 16)
|
||||
+ (VP8BORDERINPIXELS - 16);
|
||||
|
||||
// Set the mb activity pointer to the start of the row.
|
||||
x->mb_activity_ptr = &cpi->mb_activity_map[map_index];
|
||||
x->mb_norm_activity_ptr = &cpi->mb_norm_activity_map[map_index];
|
||||
|
||||
// for each macroblock col in image
|
||||
for (mb_col = 0; mb_col < cm->mb_cols; mb_col++)
|
||||
{
|
||||
@ -551,15 +760,15 @@ void encode_mb_row(VP8_COMP *cpi,
|
||||
#endif
|
||||
|
||||
if(cpi->oxcf.tuning == VP8_TUNE_SSIM)
|
||||
activity_sum += vp8_activity_masking(cpi, x);
|
||||
vp8_activity_masking(cpi, x);
|
||||
|
||||
// Is segmentation enabled
|
||||
// MB level adjutment to quantizer
|
||||
if (xd->segmentation_enabled)
|
||||
{
|
||||
// Code to set segment id in xd->mbmi.segment_id for current MB (with range checking)
|
||||
if (cpi->segmentation_map[seg_map_index+mb_col] <= 3)
|
||||
xd->mode_info_context->mbmi.segment_id = cpi->segmentation_map[seg_map_index+mb_col];
|
||||
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;
|
||||
|
||||
@ -568,7 +777,7 @@ void encode_mb_row(VP8_COMP *cpi,
|
||||
else
|
||||
xd->mode_info_context->mbmi.segment_id = 0; // Set to Segment 0 by default
|
||||
|
||||
x->active_ptr = cpi->active_map + seg_map_index + mb_col;
|
||||
x->active_ptr = cpi->active_map + map_index + mb_col;
|
||||
|
||||
if (cm->frame_type == KEY_FRAME)
|
||||
{
|
||||
@ -605,27 +814,32 @@ void encode_mb_row(VP8_COMP *cpi,
|
||||
// during vp8cx_encode_inter_macroblock()) back into the global sgmentation map
|
||||
if (cpi->cyclic_refresh_mode_enabled && xd->segmentation_enabled)
|
||||
{
|
||||
cpi->segmentation_map[seg_map_index+mb_col] = xd->mode_info_context->mbmi.segment_id;
|
||||
cpi->segmentation_map[map_index+mb_col] = xd->mode_info_context->mbmi.segment_id;
|
||||
|
||||
// If the block has been refreshed mark it as clean (the magnitude of the -ve influences how long it will be before we consider another refresh):
|
||||
// Else if it was coded (last frame 0,0) and has not already been refreshed then mark it as a candidate for cleanup next time (marked 0)
|
||||
// else mark it as dirty (1).
|
||||
if (xd->mode_info_context->mbmi.segment_id)
|
||||
cpi->cyclic_refresh_map[seg_map_index+mb_col] = -1;
|
||||
cpi->cyclic_refresh_map[map_index+mb_col] = -1;
|
||||
else if ((xd->mode_info_context->mbmi.mode == ZEROMV) && (xd->mode_info_context->mbmi.ref_frame == LAST_FRAME))
|
||||
{
|
||||
if (cpi->cyclic_refresh_map[seg_map_index+mb_col] == 1)
|
||||
cpi->cyclic_refresh_map[seg_map_index+mb_col] = 0;
|
||||
if (cpi->cyclic_refresh_map[map_index+mb_col] == 1)
|
||||
cpi->cyclic_refresh_map[map_index+mb_col] = 0;
|
||||
}
|
||||
else
|
||||
cpi->cyclic_refresh_map[seg_map_index+mb_col] = 1;
|
||||
cpi->cyclic_refresh_map[map_index+mb_col] = 1;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
cpi->tplist[mb_row].stop = *tp;
|
||||
|
||||
x->gf_active_ptr++; // Increment pointer into gf useage flags structure for next mb
|
||||
// Increment pointer into gf useage flags structure.
|
||||
x->gf_active_ptr++;
|
||||
|
||||
// Increment the activity mask pointers.
|
||||
x->mb_activity_ptr++;
|
||||
x->mb_norm_activity_ptr++;
|
||||
|
||||
for (i = 0; i < 16; i++)
|
||||
vpx_memcpy(&xd->mode_info_context->bmi[i], &xd->block[i].bmi, sizeof(xd->block[i].bmi));
|
||||
@ -664,7 +878,6 @@ void encode_mb_row(VP8_COMP *cpi,
|
||||
// this is to account for the border
|
||||
xd->mode_info_context++;
|
||||
x->partition_info++;
|
||||
x->activity_sum += activity_sum;
|
||||
|
||||
#if CONFIG_MULTITHREAD
|
||||
if ((cpi->b_multi_threaded != 0) && (mb_row == cm->mb_rows - 1))
|
||||
@ -726,6 +939,8 @@ void vp8_encode_frame(VP8_COMP *cpi)
|
||||
cpi->skip_true_count = 0;
|
||||
cpi->skip_false_count = 0;
|
||||
|
||||
x->act_zbin_adj = 0;
|
||||
|
||||
#if 0
|
||||
// Experimental code
|
||||
cpi->frame_distortion = 0;
|
||||
@ -766,7 +981,6 @@ void vp8_encode_frame(VP8_COMP *cpi)
|
||||
vp8cx_initialize_me_consts(cpi, cm->base_qindex);
|
||||
|
||||
// Copy data over into macro block data sturctures.
|
||||
|
||||
x->src = * cpi->Source;
|
||||
xd->pre = cm->yv12_fb[cm->lst_fb_idx];
|
||||
xd->dst = cm->yv12_fb[cm->new_fb_idx];
|
||||
@ -781,8 +995,6 @@ void vp8_encode_frame(VP8_COMP *cpi)
|
||||
|
||||
vp8_setup_block_ptrs(x);
|
||||
|
||||
x->activity_sum = 0;
|
||||
|
||||
xd->mode_info_context->mbmi.mode = DC_PRED;
|
||||
xd->mode_info_context->mbmi.uv_mode = DC_PRED;
|
||||
|
||||
@ -796,6 +1008,20 @@ void vp8_encode_frame(VP8_COMP *cpi)
|
||||
|
||||
vpx_memset(cm->above_context, 0, sizeof(ENTROPY_CONTEXT_PLANES) * cm->mb_cols);
|
||||
|
||||
if(cpi->oxcf.tuning == VP8_TUNE_SSIM)
|
||||
{
|
||||
if(1)
|
||||
{
|
||||
// Build a frame level activity map
|
||||
build_activity_map(cpi);
|
||||
}
|
||||
|
||||
// Reset various MB pointers.
|
||||
x->src = *cpi->Source;
|
||||
x->mb_activity_ptr = cpi->mb_activity_map;
|
||||
x->mb_norm_activity_ptr = cpi->mb_norm_activity_map;
|
||||
}
|
||||
|
||||
{
|
||||
struct vpx_usec_timer emr_timer;
|
||||
vpx_usec_timer_start(&emr_timer);
|
||||
@ -863,11 +1089,6 @@ void vp8_encode_frame(VP8_COMP *cpi)
|
||||
totalrate += cpi->mb_row_ei[i].totalrate;
|
||||
}
|
||||
|
||||
for (i = 0; i < cpi->encoding_thread_count; i++)
|
||||
{
|
||||
x->activity_sum += cpi->mb_row_ei[i].mb.activity_sum;
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
#endif
|
||||
@ -1021,14 +1242,6 @@ void vp8_encode_frame(VP8_COMP *cpi)
|
||||
cpi->last_frame_distortion = cpi->frame_distortion;
|
||||
#endif
|
||||
|
||||
/* Update the average activity for the next frame.
|
||||
* This is feed-forward for now; it could also be saved in two-pass, or
|
||||
* done during lookahead when that is eventually added.
|
||||
*/
|
||||
cpi->activity_avg = (unsigned int )(x->activity_sum/cpi->common.MBs);
|
||||
if (cpi->activity_avg < VP8_ACTIVITY_AVG_MIN)
|
||||
cpi->activity_avg = VP8_ACTIVITY_AVG_MIN;
|
||||
|
||||
}
|
||||
void vp8_setup_block_ptrs(MACROBLOCK *x)
|
||||
{
|
||||
@ -1146,6 +1359,32 @@ static void sum_intra_stats(VP8_COMP *cpi, MACROBLOCK *x)
|
||||
++cpi->uv_mode_count[uvm];
|
||||
|
||||
}
|
||||
|
||||
// Experimental stub function to create a per MB zbin adjustment based on
|
||||
// some previously calculated measure of MB activity.
|
||||
void adjust_act_zbin( VP8_COMP *cpi, int rate, MACROBLOCK *x )
|
||||
{
|
||||
INT64 act;
|
||||
INT64 a;
|
||||
INT64 b;
|
||||
|
||||
// Read activity from the map
|
||||
act = (INT64)(*(x->mb_activity_ptr));
|
||||
|
||||
// Calculate a zbin adjustment for this mb
|
||||
a = act + 4*cpi->activity_avg;
|
||||
b = 4*act + cpi->activity_avg;
|
||||
if ( b > a )
|
||||
//x->act_zbin_adj = (char)((b * 8) / a) - 8;
|
||||
x->act_zbin_adj = 8;
|
||||
else
|
||||
x->act_zbin_adj = 0;
|
||||
|
||||
// Tmp force to 0 to disable.
|
||||
x->act_zbin_adj = 0;
|
||||
|
||||
}
|
||||
|
||||
int vp8cx_encode_intra_macro_block(VP8_COMP *cpi, MACROBLOCK *x, TOKENEXTRA **t)
|
||||
{
|
||||
int Error4x4, Error16x16;
|
||||
@ -1168,6 +1407,12 @@ int vp8cx_encode_intra_macro_block(VP8_COMP *cpi, MACROBLOCK *x, TOKENEXTRA **t)
|
||||
Error4x4 = vp8_rd_pick_intra4x4mby_modes(cpi, x, &rate4x4, &rate4x4_tokenonly, &dist4x4, Error16x16);
|
||||
|
||||
rate += (Error4x4 < Error16x16) ? rate4x4 : rate16x16;
|
||||
|
||||
if(cpi->oxcf.tuning == VP8_TUNE_SSIM)
|
||||
{
|
||||
adjust_act_zbin( cpi, rate, x );
|
||||
vp8_update_zbin_extra(cpi, x);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -1248,13 +1493,15 @@ int vp8cx_encode_inter_macroblock
|
||||
/* Are we using the fast quantizer for the mode selection? */
|
||||
if(cpi->sf.use_fastquant_for_pick)
|
||||
{
|
||||
cpi->mb.quantize_b = QUANTIZE_INVOKE(&cpi->rtcd.quantize, fastquantb);
|
||||
cpi->mb.quantize_b = QUANTIZE_INVOKE(&cpi->rtcd.quantize,
|
||||
fastquantb);
|
||||
|
||||
/* the fast quantizer does not use zbin_extra, so
|
||||
* do not recalculate */
|
||||
cpi->zbin_mode_boost_enabled = 0;
|
||||
}
|
||||
vp8_rd_pick_inter_mode(cpi, x, recon_yoffset, recon_uvoffset, &rate, &distortion, &intra_error);
|
||||
vp8_rd_pick_inter_mode(cpi, x, recon_yoffset, recon_uvoffset, &rate,
|
||||
&distortion, &intra_error);
|
||||
|
||||
/* switch back to the regular quantizer for the encode */
|
||||
if (cpi->sf.improved_quant)
|
||||
@ -1267,11 +1514,18 @@ int vp8cx_encode_inter_macroblock
|
||||
|
||||
}
|
||||
else
|
||||
vp8_pick_inter_mode(cpi, x, recon_yoffset, recon_uvoffset, &rate, &distortion, &intra_error);
|
||||
vp8_pick_inter_mode(cpi, x, recon_yoffset, recon_uvoffset, &rate,
|
||||
&distortion, &intra_error);
|
||||
|
||||
cpi->prediction_error += distortion;
|
||||
cpi->intra_error += intra_error;
|
||||
|
||||
if(cpi->oxcf.tuning == VP8_TUNE_SSIM)
|
||||
{
|
||||
// Adjust the zbin based on this MB rate.
|
||||
adjust_act_zbin( cpi, rate, x );
|
||||
}
|
||||
|
||||
#if 0
|
||||
// Experimental RD code
|
||||
cpi->frame_distortion += distortion;
|
||||
@ -1297,7 +1551,8 @@ int vp8cx_encode_inter_macroblock
|
||||
}
|
||||
|
||||
{
|
||||
// Experimental code. Special case for gf and arf zeromv modes. Increase zbin size to supress noise
|
||||
// Experimental code. Special case for gf and arf zeromv modes.
|
||||
// Increase zbin size to supress noise
|
||||
if (cpi->zbin_mode_boost_enabled)
|
||||
{
|
||||
if ( xd->mode_info_context->mbmi.ref_frame == INTRA_FRAME )
|
||||
|
@ -91,8 +91,8 @@ THREAD_FUNCTION thread_encoding_proc(void *p_data)
|
||||
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 * cm->mb_cols);
|
||||
volatile int *last_row_current_mb_col;
|
||||
INT64 activity_sum = 0;
|
||||
|
||||
tp = cpi->tok + (mb_row * (cm->mb_cols * 16 * 24));
|
||||
|
||||
@ -112,6 +112,11 @@ THREAD_FUNCTION thread_encoding_proc(void *p_data)
|
||||
|
||||
//printf("Thread mb_row = %d\n", mb_row);
|
||||
|
||||
// Set the mb activity pointer to the start of the row.
|
||||
x->mb_activity_ptr = &cpi->mb_activity_map[map_index];
|
||||
x->mb_norm_activity_ptr =
|
||||
&cpi->mb_norm_activity_map[map_index];
|
||||
|
||||
// for each macroblock col in image
|
||||
for (mb_col = 0; mb_col < cm->mb_cols; mb_col++)
|
||||
{
|
||||
@ -148,15 +153,15 @@ THREAD_FUNCTION thread_encoding_proc(void *p_data)
|
||||
x->rdmult = cpi->RDMULT;
|
||||
|
||||
if (cpi->oxcf.tuning == VP8_TUNE_SSIM)
|
||||
activity_sum += vp8_activity_masking(cpi, x);
|
||||
vp8_activity_masking(cpi, x);
|
||||
|
||||
// Is segmentation enabled
|
||||
// MB level adjutment to quantizer
|
||||
if (xd->segmentation_enabled)
|
||||
{
|
||||
// Code to set segment id in xd->mbmi.segment_id for current MB (with range checking)
|
||||
if (cpi->segmentation_map[seg_map_index + mb_col] <= 3)
|
||||
xd->mode_info_context->mbmi.segment_id = cpi->segmentation_map[seg_map_index + mb_col];
|
||||
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;
|
||||
|
||||
@ -165,7 +170,7 @@ THREAD_FUNCTION thread_encoding_proc(void *p_data)
|
||||
else
|
||||
xd->mode_info_context->mbmi.segment_id = 0; // Set to Segment 0 by default
|
||||
|
||||
x->active_ptr = cpi->active_map + seg_map_index + mb_col;
|
||||
x->active_ptr = cpi->active_map + map_index + mb_col;
|
||||
|
||||
if (cm->frame_type == KEY_FRAME)
|
||||
{
|
||||
@ -203,26 +208,31 @@ THREAD_FUNCTION thread_encoding_proc(void *p_data)
|
||||
if (cpi->cyclic_refresh_mode_enabled && xd->segmentation_enabled)
|
||||
{
|
||||
const MB_MODE_INFO * mbmi = &xd->mode_info_context->mbmi;
|
||||
cpi->segmentation_map[seg_map_index + mb_col] = mbmi->segment_id;
|
||||
cpi->segmentation_map[map_index + mb_col] = mbmi->segment_id;
|
||||
|
||||
// If the block has been refreshed mark it as clean (the magnitude of the -ve influences how long it will be before we consider another refresh):
|
||||
// Else if it was coded (last frame 0,0) and has not already been refreshed then mark it as a candidate for cleanup next time (marked 0)
|
||||
// else mark it as dirty (1).
|
||||
if (mbmi->segment_id)
|
||||
cpi->cyclic_refresh_map[seg_map_index + mb_col] = -1;
|
||||
cpi->cyclic_refresh_map[map_index + mb_col] = -1;
|
||||
else if ((mbmi->mode == ZEROMV) && (mbmi->ref_frame == LAST_FRAME))
|
||||
{
|
||||
if (cpi->cyclic_refresh_map[seg_map_index + mb_col] == 1)
|
||||
cpi->cyclic_refresh_map[seg_map_index + mb_col] = 0;
|
||||
if (cpi->cyclic_refresh_map[map_index + mb_col] == 1)
|
||||
cpi->cyclic_refresh_map[map_index + mb_col] = 0;
|
||||
}
|
||||
else
|
||||
cpi->cyclic_refresh_map[seg_map_index + mb_col] = 1;
|
||||
cpi->cyclic_refresh_map[map_index + mb_col] = 1;
|
||||
|
||||
}
|
||||
}
|
||||
cpi->tplist[mb_row].stop = tp;
|
||||
|
||||
x->gf_active_ptr++; // Increment pointer into gf useage flags structure for next mb
|
||||
// Increment pointer into gf useage flags structure.
|
||||
x->gf_active_ptr++;
|
||||
|
||||
// Increment the activity mask pointers.
|
||||
x->mb_activity_ptr++;
|
||||
x->mb_norm_activity_ptr++;
|
||||
|
||||
for (i = 0; i < 16; i++)
|
||||
vpx_memcpy(&xd->mode_info_context->bmi[i], &xd->block[i].bmi, sizeof(xd->block[i].bmi));
|
||||
@ -256,7 +266,6 @@ THREAD_FUNCTION thread_encoding_proc(void *p_data)
|
||||
// this is to account for the border
|
||||
xd->mode_info_context++;
|
||||
x->partition_info++;
|
||||
x->activity_sum += activity_sum;
|
||||
|
||||
x->src.y_buffer += 16 * x->src.y_stride * (cpi->encoding_thread_count + 1) - 16 * cm->mb_cols;
|
||||
x->src.u_buffer += 8 * x->src.uv_stride * (cpi->encoding_thread_count + 1) - 8 * cm->mb_cols;
|
||||
@ -444,8 +453,6 @@ void vp8cx_init_mbrthread_data(VP8_COMP *cpi,
|
||||
|
||||
vp8_setup_block_ptrs(mb);
|
||||
|
||||
mb->activity_sum = 0;
|
||||
|
||||
mbd->left_context = &cm->left_context;
|
||||
mb->mvc = cm->fc.mvc;
|
||||
|
||||
|
@ -365,6 +365,12 @@ static void dealloc_compressor_data(VP8_COMP *cpi)
|
||||
vpx_free(cpi->gf_active_flags);
|
||||
cpi->gf_active_flags = 0;
|
||||
|
||||
// Activity mask based per mb zbin adjustments
|
||||
vpx_free(cpi->mb_activity_map);
|
||||
cpi->mb_activity_map = 0;
|
||||
vpx_free(cpi->mb_norm_activity_map);
|
||||
cpi->mb_norm_activity_map = 0;
|
||||
|
||||
vpx_free(cpi->mb.pip);
|
||||
cpi->mb.pip = 0;
|
||||
|
||||
@ -1391,12 +1397,21 @@ void vp8_alloc_compressor_data(VP8_COMP *cpi)
|
||||
|
||||
|
||||
// Structures used to minitor GF usage
|
||||
vpx_free(cpi->gf_active_flags);
|
||||
|
||||
CHECK_MEM_ERROR(cpi->gf_active_flags, vpx_calloc(1, cm->mb_rows * cm->mb_cols));
|
||||
|
||||
vpx_free(cpi->gf_active_flags);
|
||||
CHECK_MEM_ERROR(cpi->gf_active_flags,
|
||||
vpx_calloc(1, cm->mb_rows * cm->mb_cols));
|
||||
cpi->gf_active_count = cm->mb_rows * cm->mb_cols;
|
||||
|
||||
vpx_free(cpi->mb_activity_map);
|
||||
CHECK_MEM_ERROR(cpi->mb_activity_map,
|
||||
vpx_calloc(sizeof(unsigned int),
|
||||
cm->mb_rows * cm->mb_cols));
|
||||
|
||||
vpx_free(cpi->mb_norm_activity_map);
|
||||
CHECK_MEM_ERROR(cpi->mb_norm_activity_map,
|
||||
vpx_calloc(sizeof(unsigned int),
|
||||
cm->mb_rows * cm->mb_cols));
|
||||
|
||||
#if !(CONFIG_REALTIME_ONLY)
|
||||
vpx_free(cpi->total_stats);
|
||||
|
||||
@ -4790,23 +4805,48 @@ int vp8_get_compressed_data(VP8_PTR ptr, unsigned int *frame_flags, unsigned lon
|
||||
// adjust frame rates based on timestamps given
|
||||
if (!cm->refresh_alt_ref_frame)
|
||||
{
|
||||
long long this_duration;
|
||||
int step = 0;
|
||||
|
||||
if (cpi->source->ts_start == cpi->first_time_stamp_ever)
|
||||
{
|
||||
double this_fps = 10000000.000 / (cpi->source->ts_end - cpi->source->ts_start);
|
||||
|
||||
vp8_new_frame_rate(cpi, this_fps);
|
||||
this_duration = cpi->source->ts_end - cpi->source->ts_start;
|
||||
step = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
long long nanosecs = cpi->source->ts_end
|
||||
- cpi->last_end_time_stamp_seen;
|
||||
long long last_duration;
|
||||
|
||||
if (nanosecs > 0)
|
||||
this_duration = cpi->source->ts_end - cpi->last_end_time_stamp_seen;
|
||||
last_duration = cpi->last_end_time_stamp_seen
|
||||
- cpi->last_time_stamp_seen;
|
||||
// do a step update if the duration changes by 10%
|
||||
if (last_duration)
|
||||
step = ((this_duration - last_duration) * 10 / last_duration);
|
||||
}
|
||||
|
||||
if (this_duration)
|
||||
{
|
||||
if (step)
|
||||
vp8_new_frame_rate(cpi, 10000000.0 / this_duration);
|
||||
else
|
||||
{
|
||||
double this_fps = 10000000.000 / nanosecs;
|
||||
vp8_new_frame_rate(cpi, (7 * cpi->oxcf.frame_rate + this_fps) / 8);
|
||||
}
|
||||
double avg_duration, interval;
|
||||
|
||||
/* Average this frame's rate into the last second's average
|
||||
* frame rate. If we haven't seen 1 second yet, then average
|
||||
* over the whole interval seen.
|
||||
*/
|
||||
interval = cpi->source->ts_end - cpi->first_time_stamp_ever;
|
||||
if(interval > 10000000.0)
|
||||
interval = 10000000;
|
||||
|
||||
avg_duration = 10000000.0 / cpi->oxcf.frame_rate;
|
||||
avg_duration *= (interval - avg_duration + this_duration);
|
||||
avg_duration /= interval;
|
||||
|
||||
vp8_new_frame_rate(cpi, 10000000.0 / avg_duration);
|
||||
}
|
||||
}
|
||||
|
||||
cpi->last_time_stamp_seen = cpi->source->ts_start;
|
||||
|
@ -317,7 +317,6 @@ typedef struct
|
||||
int mvcostmultiplier;
|
||||
int subseqblockweight;
|
||||
int errthresh;
|
||||
unsigned int activity_avg;
|
||||
|
||||
int RDMULT;
|
||||
int RDDIV ;
|
||||
@ -648,8 +647,14 @@ typedef struct
|
||||
#endif
|
||||
int b_calculate_psnr;
|
||||
|
||||
// Per MB activity measurement
|
||||
unsigned int activity_avg;
|
||||
unsigned int * mb_activity_map;
|
||||
int * mb_norm_activity_map;
|
||||
|
||||
unsigned char *gf_active_flags; // Record of which MBs still refer to last golden frame either directly or through 0,0
|
||||
// Record of which MBs still refer to last golden frame either
|
||||
// directly or through 0,0
|
||||
unsigned char *gf_active_flags;
|
||||
int gf_active_count;
|
||||
|
||||
//Store last frame's MV info for next frame MV prediction
|
||||
@ -668,7 +673,7 @@ void vp8_encode_frame(VP8_COMP *cpi);
|
||||
|
||||
void vp8_pack_bitstream(VP8_COMP *cpi, unsigned char *dest, unsigned long *size);
|
||||
|
||||
unsigned int vp8_activity_masking(VP8_COMP *cpi, MACROBLOCK *x);
|
||||
void vp8_activity_masking(VP8_COMP *cpi, MACROBLOCK *x);
|
||||
|
||||
int rd_cost_intra_mb(MACROBLOCKD *x);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user