Merge remote branch 'origin/master' into experimental

Conflicts:
	vp8/encoder/rdopt.c

Change-Id: I85275aab07625bd30bbef16a752b08b18f4451ab
This commit is contained in:
John Koleszar 2011-05-16 09:11:18 -04:00
commit 11b9b14691
5 changed files with 394 additions and 85 deletions

View File

@ -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];

View File

@ -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 )

View File

@ -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;

View File

@ -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;

View File

@ -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);