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
This commit is contained in:
parent
6bdfc8cd0b
commit
fc0b33182b
@ -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 @@ static int apply_cyclic_refresh_bitrate(const VP9_COMMON *cm,
|
||||
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 @@ void vp9_cyclic_refresh_setup(VP9_COMP *const cpi) {
|
||||
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 @@ void vp9_cyclic_refresh_setup(VP9_COMP *const cpi) {
|
||||
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]++;
|
||||
}
|
||||
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;
|
||||
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;
|
||||
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]++;
|
||||
}
|
||||
}
|
||||
}
|
||||
// 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++)
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user