| Index: source/libvpx/vp9/encoder/vp9_aq_cyclicrefresh.c
|
| diff --git a/source/libvpx/vp9/encoder/vp9_aq_cyclicrefresh.c b/source/libvpx/vp9/encoder/vp9_aq_cyclicrefresh.c
|
| index 4bd083c27cc21c57135f70d23901bafa37021934..24b427df575cb9237f7d544f818894a6f35b940e 100644
|
| --- a/source/libvpx/vp9/encoder/vp9_aq_cyclicrefresh.c
|
| +++ b/source/libvpx/vp9/encoder/vp9_aq_cyclicrefresh.c
|
| @@ -279,29 +279,68 @@ void vp9_cyclic_refresh_set_golden_update(VP9_COMP *const cpi) {
|
| // period. Depending on past encoding stats, GF flag may be reset and update
|
| // may not occur until next baseline_gf_interval.
|
| if (cr->percent_refresh > 0)
|
| - rc->baseline_gf_interval = 2 * (100 / cr->percent_refresh);
|
| + rc->baseline_gf_interval = 4 * (100 / cr->percent_refresh);
|
| else
|
| - rc->baseline_gf_interval = 20;
|
| + rc->baseline_gf_interval = 40;
|
| }
|
|
|
| -// Update some encoding stats (from the just encoded frame), and if the golden
|
| -// reference is to be updated check if we should NOT update the golden ref.
|
| +// Update some encoding stats (from the just encoded frame). If this frame's
|
| +// background has high motion, refresh the golden frame. Otherwise, if the
|
| +// golden reference is to be updated check if we should NOT update the golden
|
| +// ref.
|
| void vp9_cyclic_refresh_check_golden_update(VP9_COMP *const cpi) {
|
| VP9_COMMON *const cm = &cpi->common;
|
| CYCLIC_REFRESH *const cr = cpi->cyclic_refresh;
|
| int mi_row, mi_col;
|
| double fraction_low = 0.0;
|
| int low_content_frame = 0;
|
| - for (mi_row = 0; mi_row < cm->mi_rows; mi_row++)
|
| - for (mi_col = 0; mi_col < cm->mi_cols; mi_col++) {
|
| - if (cr->map[mi_row * cm->mi_cols + mi_col] < 1)
|
| +
|
| + MODE_INFO **mi = cm->mi_grid_visible;
|
| + RATE_CONTROL *const rc = &cpi->rc;
|
| + const int rows = cm->mi_rows, cols = cm->mi_cols;
|
| + int cnt1 = 0, cnt2 = 0;
|
| + int force_gf_refresh = 0;
|
| +
|
| + for (mi_row = 0; mi_row < rows; mi_row++) {
|
| + for (mi_col = 0; mi_col < cols; mi_col++) {
|
| + int16_t abs_mvr = mi[0]->mbmi.mv[0].as_mv.row >= 0 ?
|
| + mi[0]->mbmi.mv[0].as_mv.row : -1 * mi[0]->mbmi.mv[0].as_mv.row;
|
| + int16_t abs_mvc = mi[0]->mbmi.mv[0].as_mv.col >= 0 ?
|
| + mi[0]->mbmi.mv[0].as_mv.col : -1 * mi[0]->mbmi.mv[0].as_mv.col;
|
| +
|
| + // Calculate the motion of the background.
|
| + if (abs_mvr <= 16 && abs_mvc <= 16) {
|
| + cnt1++;
|
| + if (abs_mvr == 0 && abs_mvc == 0)
|
| + cnt2++;
|
| + }
|
| + mi++;
|
| +
|
| + // Accumulate low_content_frame.
|
| + if (cr->map[mi_row * cols + mi_col] < 1)
|
| low_content_frame++;
|
| }
|
| + mi += 8;
|
| + }
|
| +
|
| + // For video conference clips, if the background has high motion in current
|
| + // frame because of the camera movement, set this frame as the golden frame.
|
| + // Use 70% and 5% as the thresholds for golden frame refreshing.
|
| + if (cnt1 * 10 > (70 * rows * cols) && cnt2 * 20 < cnt1) {
|
| + vp9_cyclic_refresh_set_golden_update(cpi);
|
| + rc->frames_till_gf_update_due = rc->baseline_gf_interval;
|
| +
|
| + if (rc->frames_till_gf_update_due > rc->frames_to_key)
|
| + rc->frames_till_gf_update_due = rc->frames_to_key;
|
| + cpi->refresh_golden_frame = 1;
|
| + force_gf_refresh = 1;
|
| + }
|
| +
|
| fraction_low =
|
| - (double)low_content_frame / (cm->mi_rows * cm->mi_cols);
|
| + (double)low_content_frame / (rows * cols);
|
| // Update average.
|
| cr->low_content_avg = (fraction_low + 3 * cr->low_content_avg) / 4;
|
| - if (cpi->refresh_golden_frame == 1) {
|
| + if (!force_gf_refresh && cpi->refresh_golden_frame == 1) {
|
| // Don't update golden reference if the amount of low_content for the
|
| // current encoded frame is small, or if the recursive average of the
|
| // low_content over the update interval window falls below threshold.
|
| @@ -324,7 +363,7 @@ void vp9_cyclic_refresh_update_map(VP9_COMP *const cpi) {
|
| unsigned char *const seg_map = cpi->segmentation_map;
|
| int i, block_count, bl_index, sb_rows, sb_cols, sbs_in_frame;
|
| int xmis, ymis, x, y;
|
| - vpx_memset(seg_map, CR_SEGMENT_ID_BASE, cm->mi_rows * cm->mi_cols);
|
| + memset(seg_map, CR_SEGMENT_ID_BASE, cm->mi_rows * cm->mi_cols);
|
| sb_cols = (cm->mi_cols + MI_BLOCK_SIZE - 1) / MI_BLOCK_SIZE;
|
| sb_rows = (cm->mi_rows + MI_BLOCK_SIZE - 1) / MI_BLOCK_SIZE;
|
| sbs_in_frame = sb_cols * sb_rows;
|
| @@ -411,7 +450,7 @@ void vp9_cyclic_refresh_setup(VP9_COMP *const cpi) {
|
| (cpi->svc.spatial_layer_id > 0)) {
|
| // Set segmentation map to 0 and disable.
|
| unsigned char *const seg_map = cpi->segmentation_map;
|
| - vpx_memset(seg_map, 0, cm->mi_rows * cm->mi_cols);
|
| + memset(seg_map, 0, cm->mi_rows * cm->mi_cols);
|
| vp9_disable_segmentation(&cm->seg);
|
| if (cm->frame_type == KEY_FRAME)
|
| cr->sb_index = 0;
|
|
|