Commit eb53c69e authored by Marco's avatar Marco

Add cyclic refresh parameters to svc-layer context.

For 1 pass CBR spatial-SVC:
Add cyclic refresh parameters to the svc-layer context.

This allows cyclic refresh (aq-mode=3) to be applied to
the whole super-frame (all spatial layers).
This gives a performance improvement for spatial layer encoding.

Addd the aq_mode mode on/off setting as command line option.

Change-Id: Ib9c3b5ba3cb7851bfb8c37d4f911664bef38e165
parent 0e1b4fb9
......@@ -80,6 +80,8 @@ static const arg_def_t rc_end_usage_arg =
ARG_DEF(NULL, "rc-end-usage", 1, "0 - 3: VBR, CBR, CQ, Q");
static const arg_def_t speed_arg =
ARG_DEF("sp", "speed", 1, "speed configuration");
static const arg_def_t aqmode_arg =
ARG_DEF("aq", "aqmode", 1, "aq-mode off/on");
#if CONFIG_VP9_HIGHBITDEPTH
static const struct arg_enum_list bitdepth_enum[] = {
......@@ -101,7 +103,7 @@ static const arg_def_t *svc_args[] = {
&kf_dist_arg, &scale_factors_arg, &passes_arg, &pass_arg,
&fpf_name_arg, &min_q_arg, &max_q_arg, &min_bitrate_arg,
&max_bitrate_arg, &temporal_layers_arg, &temporal_layering_mode_arg,
&lag_in_frame_arg, &threads_arg,
&lag_in_frame_arg, &threads_arg, &aqmode_arg,
#if OUTPUT_RC_STATS
&output_rc_stats_arg,
#endif
......@@ -221,6 +223,8 @@ static void parse_command_line(int argc, const char **argv_,
#endif
} else if (arg_match(&arg, &speed_arg, argi)) {
svc_ctx->speed = arg_parse_uint(&arg);
} else if (arg_match(&arg, &aqmode_arg, argi)) {
svc_ctx->aqmode = arg_parse_uint(&arg);
} else if (arg_match(&arg, &threads_arg, argi)) {
svc_ctx->threads = arg_parse_uint(&arg);
} else if (arg_match(&arg, &temporal_layering_mode_arg, argi)) {
......@@ -635,7 +639,7 @@ int main(int argc, const char **argv) {
vpx_codec_control(&codec, VP8E_SET_CPUUSED, svc_ctx.speed);
if (svc_ctx.threads)
vpx_codec_control(&codec, VP9E_SET_TILE_COLUMNS, (svc_ctx.threads >> 1));
if (svc_ctx.speed >= 5)
if (svc_ctx.speed >= 5 && svc_ctx.aqmode == 1)
vpx_codec_control(&codec, VP9E_SET_AQ_MODE, 3);
......
......@@ -449,6 +449,10 @@ void vp9_cyclic_refresh_update_parameters(VP9_COMP *const cpi) {
cr->motion_thresh = 32;
cr->rate_boost_fac = 17;
}
if (cpi->svc.spatial_layer_id > 0) {
cr->motion_thresh = 4;
cr->rate_boost_fac = 12;
}
}
// Setup cyclic background refresh: set delta q and segmentation map.
......@@ -460,11 +464,10 @@ void vp9_cyclic_refresh_setup(VP9_COMP *const cpi) {
const int apply_cyclic_refresh = apply_cyclic_refresh_bitrate(cm, rc);
if (cm->current_video_frame == 0)
cr->low_content_avg = 0.0;
// Don't apply refresh on key frame or enhancement layer frames.
// Don't apply refresh on key frame or temporal enhancement layer frames.
if (!apply_cyclic_refresh ||
(cm->frame_type == KEY_FRAME) ||
(cpi->svc.temporal_layer_id > 0) ||
(cpi->svc.spatial_layer_id > 0)) {
(cpi->svc.temporal_layer_id > 0)) {
// Set segmentation map to 0 and disable.
unsigned char *const seg_map = cpi->segmentation_map;
memset(seg_map, 0, cm->mi_rows * cm->mi_cols);
......
......@@ -412,6 +412,8 @@ static void dealloc_compressor_data(VP9_COMP *cpi) {
vpx_free_frame_buffer(&cpi->svc.empty_frame.img);
memset(&cpi->svc.empty_frame, 0, sizeof(cpi->svc.empty_frame));
vp9_free_svc_cyclic_refresh(cpi);
}
static void save_coding_context(VP9_COMP *cpi) {
......
......@@ -533,8 +533,7 @@ int vp9_rc_regulate_q(const VP9_COMP *cpi, int target_bits_per_frame,
do {
if (cpi->oxcf.aq_mode == CYCLIC_REFRESH_AQ &&
cm->seg.enabled &&
cpi->svc.temporal_layer_id == 0 &&
cpi->svc.spatial_layer_id == 0) {
cpi->svc.temporal_layer_id == 0) {
bits_per_mb_at_this_q =
(int)vp9_cyclic_refresh_rc_bits_per_mb(cpi, i, correction_factor);
} else {
......
......@@ -10,6 +10,7 @@
#include <math.h>
#include "vp9/encoder/vp9_aq_cyclicrefresh.h"
#include "vp9/encoder/vp9_encoder.h"
#include "vp9/encoder/vp9_svc_layercontext.h"
#include "vp9/encoder/vp9_extend.h"
......@@ -22,6 +23,8 @@
void vp9_init_layer_context(VP9_COMP *const cpi) {
SVC *const svc = &cpi->svc;
const VP9EncoderConfig *const oxcf = &cpi->oxcf;
int mi_rows = cpi->common.mi_rows;
int mi_cols = cpi->common.mi_cols;
int sl, tl;
int alt_ref_idx = svc->number_spatial_layers;
......@@ -52,6 +55,7 @@ void vp9_init_layer_context(VP9_COMP *const cpi) {
int layer = LAYER_IDS_TO_IDX(sl, tl, oxcf->ts_number_layers);
LAYER_CONTEXT *const lc = &svc->layer_context[layer];
RATE_CONTROL *const lrc = &lc->rc;
size_t last_coded_q_map_size;
int i;
lc->current_video_frame_in_layer = 0;
lc->layer_size = 0;
......@@ -94,6 +98,22 @@ void vp9_init_layer_context(VP9_COMP *const cpi) {
lrc->buffer_level = oxcf->starting_buffer_level_ms *
lc->target_bandwidth / 1000;
lrc->bits_off_target = lrc->buffer_level;
// Initialize the cyclic refresh parameters. If spatial layers are used
// (i.e., ss_number_layers > 1), these need to be updated per spatial
// layer.
// Cyclic refresh is only applied on base temporal layer.
if (oxcf->ss_number_layers > 1 &&
tl == 0) {
lc->sb_index = 0;
lc->map = vpx_malloc(mi_rows * mi_cols * sizeof(signed char));
memset(lc->map, 0, mi_rows * mi_cols);
last_coded_q_map_size =
mi_rows * mi_cols * sizeof(uint8_t);
lc->last_coded_q_map = vpx_malloc(last_coded_q_map_size);
assert(MAXQ <= 255);
memset(lc->last_coded_q_map, MAXQ, last_coded_q_map_size);
}
}
}
......@@ -257,6 +277,21 @@ void vp9_restore_layer_context(VP9_COMP *const cpi) {
cpi->rc.frames_since_key = old_frame_since_key;
cpi->rc.frames_to_key = old_frame_to_key;
}
// For spatial-svc, allow cyclic-refresh to be applied on the spatial layers,
// for the base temporal layer.
if (cpi->oxcf.aq_mode == CYCLIC_REFRESH_AQ &&
cpi->svc.number_spatial_layers > 1 &&
cpi->svc.temporal_layer_id == 0) {
CYCLIC_REFRESH *const cr = cpi->cyclic_refresh;
signed char *temp = cr->map;
uint8_t *temp2 = cr->last_coded_q_map;
cr->map = lc->map;
lc->map = temp;
cr->last_coded_q_map = lc->last_coded_q_map;
lc->last_coded_q_map = temp2;
cr->sb_index = lc->sb_index;
}
}
void vp9_save_layer_context(VP9_COMP *const cpi) {
......@@ -267,6 +302,21 @@ void vp9_save_layer_context(VP9_COMP *const cpi) {
lc->twopass = cpi->twopass;
lc->target_bandwidth = (int)oxcf->target_bandwidth;
lc->alt_ref_source = cpi->alt_ref_source;
// For spatial-svc, allow cyclic-refresh to be applied on the spatial layers,
// for the base temporal layer.
if (cpi->oxcf.aq_mode == CYCLIC_REFRESH_AQ &&
cpi->svc.number_spatial_layers > 1 &&
cpi->svc.temporal_layer_id == 0) {
CYCLIC_REFRESH *const cr = cpi->cyclic_refresh;
signed char *temp = lc->map;
uint8_t *temp2 = lc->last_coded_q_map;
lc->map = cr->map;
cr->map = temp;
lc->last_coded_q_map = cr->last_coded_q_map;
cr->last_coded_q_map = temp2;
lc->sb_index = cr->sb_index;
}
}
void vp9_init_second_pass_spatial_svc(VP9_COMP *cpi) {
......@@ -642,3 +692,19 @@ struct lookahead_entry *vp9_svc_lookahead_pop(VP9_COMP *const cpi,
}
return buf;
}
void vp9_free_svc_cyclic_refresh(VP9_COMP *const cpi) {
int sl, tl;
SVC *const svc = &cpi->svc;
const VP9EncoderConfig *const oxcf = &cpi->oxcf;
for (sl = 0; sl < oxcf->ss_number_layers; ++sl) {
for (tl = 0; tl < oxcf->ts_number_layers; ++tl) {
int layer = LAYER_IDS_TO_IDX(sl, tl, oxcf->ts_number_layers);
LAYER_CONTEXT *const lc = &svc->layer_context[layer];
if (lc->map)
vpx_free(lc->map);
if (lc->last_coded_q_map)
vpx_free(lc->last_coded_q_map);
}
}
}
......@@ -41,6 +41,10 @@ typedef struct {
int has_alt_frame;
size_t layer_size;
struct vpx_psnr_pkt psnr_pkt;
// Cyclic refresh parameters (aq-mode=3), that need to be updated per-frame.
int sb_index;
signed char *map;
uint8_t *last_coded_q_map;
} LAYER_CONTEXT;
typedef struct {
......@@ -115,6 +119,8 @@ int vp9_svc_start_frame(struct VP9_COMP *const cpi);
int vp9_one_pass_cbr_svc_start_layer(struct VP9_COMP *const cpi);
void vp9_free_svc_cyclic_refresh(struct VP9_COMP *const cpi);
#ifdef __cplusplus
} // extern "C"
#endif
......
......@@ -40,6 +40,7 @@ typedef struct {
int output_rc_stat; // for outputting rc stats
int speed; // speed setting for codec
int threads;
int aqmode; // turns on aq-mdoe=3 (cyclic_refresh): 0=off, 1=on.
// private storage for vpx_svc_encode
void *internal;
} SvcContext;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment