ref: fc0b33182b119d5d5efab964dba9367537b74e4d
parent: 6bdfc8cd0b2f4d5078048e56feb4516e63af9baf
author: Marco Paniconi <marpan@google.com>
date: Wed Mar 26 14:09:20 EDT 2014
aq_mode=3: Set target seg_map in sb-block order. Removes a TODO. Changed meaning of some parameters (target-max-percent refresh and starting index) to be defined relative to superblock. Also, modify turn-off condition. Change-Id: I5e55f372b7079c24f9cdac0b06fa34620dbf456b
--- a/vp9/encoder/vp9_aq_cyclicrefresh.c
+++ b/vp9/encoder/vp9_aq_cyclicrefresh.c
@@ -20,17 +20,18 @@
#include "vp9/encoder/vp9_segmentation.h"
struct CYCLIC_REFRESH {
- // Target percentage of blocks per frame that are cyclicly refreshed.
- int max_mbs_perframe;
+ // Percentage of super-blocks per frame that are targeted as candidates
+ // for cyclic refresh.
+ int max_sbs_perframe;
// Maximum q-delta as percentage of base q.
int max_qdelta_perc;
// Block size below which we don't apply cyclic refresh.
BLOCK_SIZE min_block_size;
- // Macroblock starting index (unit of 8x8) for cycling through the frame.
- int mb_index;
+ // Superblock starting index for cycling through the frame.
+ int sb_index;
// Controls how long a block will need to wait to be refreshed again.
int time_for_refresh;
- // Actual number of blocks that were applied delta-q (segment 1).
+ // Actual number of (8x8) blocks that were applied delta-q (segment 1).
int num_seg_blocks;
// Actual encoding bits for segment 1.
int actual_seg_bits;
@@ -77,7 +78,13 @@
const int number_blocks = cm->mi_rows * cm->mi_cols;
// The condition below corresponds to turning off at target bitrates:
// ~24kbps for CIF, 72kbps for VGA (at 30fps).
- return rc->av_per_frame_bandwidth >= factor * number_blocks;
+ // Also turn off at very small frame sizes, to avoid too large fraction of
+ // superblocks to be refreshed per frame. Threshold below is less than QCIF.
+ if (rc->av_per_frame_bandwidth < factor * number_blocks ||
+ number_blocks / 64 < 5)
+ return 0;
+ else
+ return 1;
}
// Check if this coding block, of size bsize, should be considered for refresh
@@ -184,19 +191,18 @@
vpx_memset(seg_map, 0, cm->mi_rows * cm->mi_cols);
vp9_disable_segmentation(&cm->seg);
if (cm->frame_type == KEY_FRAME)
- cr->mb_index = 0;
+ cr->sb_index = 0;
return;
} else {
- const int mbs_in_frame = cm->mi_rows * cm->mi_cols;
int qindex_delta = 0;
- int i, x, y, block_count;
- int mi_row, mi_col, qindex2;
+ int i, block_count, bl_index, sb_rows, sb_cols, sbs_in_frame;
+ int xmis, ymis, x, y, qindex2;
// Rate target ratio to set q delta.
const float rate_ratio_qdelta = 2.0;
vp9_clear_system_state();
// Some of these parameters may be set via codec-control function later.
- cr->max_mbs_perframe = 10;
+ cr->max_sbs_perframe = 10;
cr->max_qdelta_perc = 50;
cr->min_block_size = BLOCK_16X16;
cr->time_for_refresh = 1;
@@ -248,52 +254,62 @@
cr->rdmult = vp9_compute_rd_mult(cpi, qindex2);
vp9_set_segdata(seg, 1, SEG_LVL_ALT_Q, qindex_delta);
- // Number of target macroblocks to get the q delta (segment 1).
- block_count = cr->max_mbs_perframe * mbs_in_frame / 100;
- // Set the segmentation map: cycle through the macroblocks, starting at
+
+ 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;
+ // Number of target superblocks to get the q delta (segment 1).
+ block_count = cr->max_sbs_perframe * sbs_in_frame / 100;
+ // Set the segmentation map: cycle through the superblocks, starting at
// cr->mb_index, and stopping when either block_count blocks have been found
// to be refreshed, or we have passed through whole frame.
- // Note the setting of seg_map below is done in two steps (one over 8x8)
- // and then another over SB, in order to keep the value constant over SB.
- // TODO(marpan): Do this in one pass in SB order.
- assert(cr->mb_index < mbs_in_frame);
- i = cr->mb_index;
+ assert(cr->sb_index < sbs_in_frame);
+ i = cr->sb_index;
do {
- // If the macroblock is as a candidate for clean up then mark it
- // for possible boost/refresh (segment 1). The segment id may get reset to
- // 0 later if the macroblock gets coded anything other than ZEROMV.
- if (cr->map[i] == 0) {
- seg_map[i] = 1;
- block_count--;
- } else if (cr->map[i] < 0) {
- cr->map[i]++;
+ int sum_map = 0;
+ // Get the mi_row/mi_col corresponding to superblock index i.
+ int sb_row_index = (i / sb_cols);
+ int sb_col_index = i - sb_row_index * sb_cols;
+ int mi_row = sb_row_index * MI_BLOCK_SIZE;
+ int mi_col = sb_col_index * MI_BLOCK_SIZE;
+ assert(mi_row >= 0 && mi_row < cm->mi_rows);
+ assert(mi_col >= 0 && mi_col < cm->mi_cols);
+ bl_index = mi_row * cm->mi_cols + mi_col;
+ // Loop through all 8x8 blocks in superblock and update map.
+ xmis = MIN(cm->mi_cols - mi_col,
+ num_8x8_blocks_wide_lookup[BLOCK_64X64]);
+ ymis = MIN(cm->mi_rows - mi_row,
+ num_8x8_blocks_high_lookup[BLOCK_64X64]);
+ for (y = 0; y < ymis; y++) {
+ for (x = 0; x < xmis; x++) {
+ const int bl_index2 = bl_index + y * cm->mi_cols + x;
+ // If the block is as a candidate for clean up then mark it
+ // for possible boost/refresh (segment 1). The segment id may get
+ // reset to 0 later if block gets coded anything other than ZEROMV.
+ if (cr->map[bl_index2] == 0) {
+ seg_map[bl_index2] = 1;
+ sum_map++;
+ } else if (cr->map[bl_index2] < 0) {
+ cr->map[bl_index2]++;
+ }
+ }
}
- i++;
- if (i == mbs_in_frame) {
- i = 0;
- }
- } while (block_count && i != cr->mb_index);
- cr->mb_index = i;
- // Enforce constant segment map over superblock.
- for (mi_row = 0; mi_row < cm->mi_rows; mi_row += MI_BLOCK_SIZE)
- for (mi_col = 0; mi_col < cm->mi_cols; mi_col += MI_BLOCK_SIZE) {
- const int bl_index = mi_row * cm->mi_cols + mi_col;
- const int xmis = MIN(cm->mi_cols - mi_col,
- num_8x8_blocks_wide_lookup[BLOCK_64X64]);
- const int ymis = MIN(cm->mi_rows - mi_row,
- num_8x8_blocks_high_lookup[BLOCK_64X64]);
- int sum_map = 0;
+ // Enforce constant segment over superblock.
+ // If segment is partial over superblock, reset to either all 1 or 0.
+ if (sum_map > 0 && sum_map < xmis * ymis) {
+ const int new_value = (sum_map >= xmis * ymis / 2);
for (y = 0; y < ymis; y++)
for (x = 0; x < xmis; x++)
- sum_map += seg_map[bl_index + y * cm->mi_cols + x];
- // If segment is partial over superblock, reset.
- if (sum_map > 0 && sum_map < xmis * ymis) {
- const int new_value = (sum_map >= xmis * ymis / 2);
- for (y = 0; y < ymis; y++)
- for (x = 0; x < xmis; x++)
- seg_map[bl_index + y * cm->mi_cols + x] = new_value;
- }
+ seg_map[bl_index + y * cm->mi_cols + x] = new_value;
}
+ i++;
+ if (i == sbs_in_frame) {
+ i = 0;
+ }
+ if (sum_map >= xmis * ymis /2)
+ block_count--;
+ } while (block_count && i != cr->sb_index);
+ cr->sb_index = i;
}
}
--
⑨