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"
|
#include "vp9/encoder/vp9_segmentation.h"
|
||||||
|
|
||||||
struct CYCLIC_REFRESH {
|
struct CYCLIC_REFRESH {
|
||||||
// Target percentage of blocks per frame that are cyclicly refreshed.
|
// Percentage of super-blocks per frame that are targeted as candidates
|
||||||
int max_mbs_perframe;
|
// for cyclic refresh.
|
||||||
|
int max_sbs_perframe;
|
||||||
// Maximum q-delta as percentage of base q.
|
// Maximum q-delta as percentage of base q.
|
||||||
int max_qdelta_perc;
|
int max_qdelta_perc;
|
||||||
// Block size below which we don't apply cyclic refresh.
|
// Block size below which we don't apply cyclic refresh.
|
||||||
BLOCK_SIZE min_block_size;
|
BLOCK_SIZE min_block_size;
|
||||||
// Macroblock starting index (unit of 8x8) for cycling through the frame.
|
// Superblock starting index for cycling through the frame.
|
||||||
int mb_index;
|
int sb_index;
|
||||||
// Controls how long a block will need to wait to be refreshed again.
|
// Controls how long a block will need to wait to be refreshed again.
|
||||||
int time_for_refresh;
|
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;
|
int num_seg_blocks;
|
||||||
// Actual encoding bits for segment 1.
|
// Actual encoding bits for segment 1.
|
||||||
int actual_seg_bits;
|
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;
|
const int number_blocks = cm->mi_rows * cm->mi_cols;
|
||||||
// The condition below corresponds to turning off at target bitrates:
|
// The condition below corresponds to turning off at target bitrates:
|
||||||
// ~24kbps for CIF, 72kbps for VGA (at 30fps).
|
// ~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
|
// 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);
|
vpx_memset(seg_map, 0, cm->mi_rows * cm->mi_cols);
|
||||||
vp9_disable_segmentation(&cm->seg);
|
vp9_disable_segmentation(&cm->seg);
|
||||||
if (cm->frame_type == KEY_FRAME)
|
if (cm->frame_type == KEY_FRAME)
|
||||||
cr->mb_index = 0;
|
cr->sb_index = 0;
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
const int mbs_in_frame = cm->mi_rows * cm->mi_cols;
|
|
||||||
int qindex_delta = 0;
|
int qindex_delta = 0;
|
||||||
int i, x, y, block_count;
|
int i, block_count, bl_index, sb_rows, sb_cols, sbs_in_frame;
|
||||||
int mi_row, mi_col, qindex2;
|
int xmis, ymis, x, y, qindex2;
|
||||||
|
|
||||||
// Rate target ratio to set q delta.
|
// Rate target ratio to set q delta.
|
||||||
const float rate_ratio_qdelta = 2.0;
|
const float rate_ratio_qdelta = 2.0;
|
||||||
vp9_clear_system_state();
|
vp9_clear_system_state();
|
||||||
// Some of these parameters may be set via codec-control function later.
|
// 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->max_qdelta_perc = 50;
|
||||||
cr->min_block_size = BLOCK_16X16;
|
cr->min_block_size = BLOCK_16X16;
|
||||||
cr->time_for_refresh = 1;
|
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);
|
cr->rdmult = vp9_compute_rd_mult(cpi, qindex2);
|
||||||
|
|
||||||
vp9_set_segdata(seg, 1, SEG_LVL_ALT_Q, qindex_delta);
|
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;
|
sb_cols = (cm->mi_cols + MI_BLOCK_SIZE - 1) / MI_BLOCK_SIZE;
|
||||||
// Set the segmentation map: cycle through the macroblocks, starting at
|
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
|
// cr->mb_index, and stopping when either block_count blocks have been found
|
||||||
// to be refreshed, or we have passed through whole frame.
|
// 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)
|
assert(cr->sb_index < sbs_in_frame);
|
||||||
// and then another over SB, in order to keep the value constant over SB.
|
i = cr->sb_index;
|
||||||
// TODO(marpan): Do this in one pass in SB order.
|
|
||||||
assert(cr->mb_index < mbs_in_frame);
|
|
||||||
i = cr->mb_index;
|
|
||||||
do {
|
do {
|
||||||
// If the macroblock is as a candidate for clean up then mark it
|
int sum_map = 0;
|
||||||
// for possible boost/refresh (segment 1). The segment id may get reset to
|
// Get the mi_row/mi_col corresponding to superblock index i.
|
||||||
// 0 later if the macroblock gets coded anything other than ZEROMV.
|
int sb_row_index = (i / sb_cols);
|
||||||
if (cr->map[i] == 0) {
|
int sb_col_index = i - sb_row_index * sb_cols;
|
||||||
seg_map[i] = 1;
|
int mi_row = sb_row_index * MI_BLOCK_SIZE;
|
||||||
block_count--;
|
int mi_col = sb_col_index * MI_BLOCK_SIZE;
|
||||||
} else if (cr->map[i] < 0) {
|
assert(mi_row >= 0 && mi_row < cm->mi_rows);
|
||||||
cr->map[i]++;
|
assert(mi_col >= 0 && mi_col < cm->mi_cols);
|
||||||
}
|
bl_index = mi_row * cm->mi_cols + mi_col;
|
||||||
i++;
|
// Loop through all 8x8 blocks in superblock and update map.
|
||||||
if (i == mbs_in_frame) {
|
xmis = MIN(cm->mi_cols - mi_col,
|
||||||
i = 0;
|
num_8x8_blocks_wide_lookup[BLOCK_64X64]);
|
||||||
}
|
ymis = MIN(cm->mi_rows - mi_row,
|
||||||
} while (block_count && i != cr->mb_index);
|
num_8x8_blocks_high_lookup[BLOCK_64X64]);
|
||||||
cr->mb_index = i;
|
for (y = 0; y < ymis; y++) {
|
||||||
// Enforce constant segment map over superblock.
|
for (x = 0; x < xmis; x++) {
|
||||||
for (mi_row = 0; mi_row < cm->mi_rows; mi_row += MI_BLOCK_SIZE)
|
const int bl_index2 = bl_index + y * cm->mi_cols + x;
|
||||||
for (mi_col = 0; mi_col < cm->mi_cols; mi_col += MI_BLOCK_SIZE) {
|
// If the block is as a candidate for clean up then mark it
|
||||||
const int bl_index = mi_row * cm->mi_cols + mi_col;
|
// for possible boost/refresh (segment 1). The segment id may get
|
||||||
const int xmis = MIN(cm->mi_cols - mi_col,
|
// reset to 0 later if block gets coded anything other than ZEROMV.
|
||||||
num_8x8_blocks_wide_lookup[BLOCK_64X64]);
|
if (cr->map[bl_index2] == 0) {
|
||||||
const int ymis = MIN(cm->mi_rows - mi_row,
|
seg_map[bl_index2] = 1;
|
||||||
num_8x8_blocks_high_lookup[BLOCK_64X64]);
|
sum_map++;
|
||||||
int sum_map = 0;
|
} else if (cr->map[bl_index2] < 0) {
|
||||||
for (y = 0; y < ymis; y++)
|
cr->map[bl_index2]++;
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// 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…
x
Reference in New Issue
Block a user