Commit c139b81a authored by Marco's avatar Marco Committed by Marco

Vidyo patch: Rate control for SVC, 1 pass CBR mode.

-Make Rate control work for SVC 1 pass CBR mode.
-Added temporal layering mode.
-Fixed bug in non-rd variance partition.
-Modified/updated the sample encoders (vp9_spatial_svc_encoder, vpx_temporal_svc_encoder).
-Added datarate unittest(s) for 1 pass CBR SVC.

Change-Id: Ie94b1b68a56ea1267b5087c625e5df04def2ee48
parent ebf7466c
This diff is collapsed.
......@@ -85,13 +85,13 @@ static void set_rate_control_metrics(struct RateControlMetrics *rc,
// per-frame-bandwidth, for the rate control encoding stats below.
const double framerate = cfg->g_timebase.den / cfg->g_timebase.num;
rc->layer_framerate[0] = framerate / cfg->ts_rate_decimator[0];
rc->layer_pfb[0] = 1000.0 * cfg->ts_target_bitrate[0] /
rc->layer_pfb[0] = 1000.0 * cfg->layer_target_bitrate[0] /
rc->layer_framerate[0];
for (i = 0; i < cfg->ts_number_layers; ++i) {
if (i > 0) {
rc->layer_framerate[i] = framerate / cfg->ts_rate_decimator[i];
rc->layer_pfb[i] = 1000.0 *
(cfg->ts_target_bitrate[i] - cfg->ts_target_bitrate[i - 1]) /
(cfg->layer_target_bitrate[i] - cfg->layer_target_bitrate[i - 1]) /
(rc->layer_framerate[i] - rc->layer_framerate[i - 1]);
}
rc->layer_input_frames[i] = 0;
......@@ -128,7 +128,7 @@ static void printout_rate_control_summary(struct RateControlMetrics *rc,
rc->layer_avg_rate_mismatch[i] = 100.0 * rc->layer_avg_rate_mismatch[i] /
rc->layer_enc_frames[i];
printf("For layer#: %d \n", i);
printf("Bitrate (target vs actual): %d %f \n", cfg->ts_target_bitrate[i],
printf("Bitrate (target vs actual): %d %f \n", cfg->layer_target_bitrate[i],
rc->layer_encoding_bitrate[i]);
printf("Average frame size (target vs actual): %f %f \n", rc->layer_pfb[i],
rc->layer_avg_frame_size[i]);
......@@ -597,7 +597,7 @@ int main(int argc, char **argv) {
for (i = min_args_base;
(int)i < min_args_base + mode_to_num_layers[layering_mode];
++i) {
cfg.ts_target_bitrate[i - 11] = strtol(argv[i], NULL, 0);
cfg.layer_target_bitrate[i - 11] = strtol(argv[i], NULL, 0);
}
// Real time parameters.
......@@ -625,6 +625,8 @@ int main(int argc, char **argv) {
// Disable automatic keyframe placement.
cfg.kf_min_dist = cfg.kf_max_dist = 3000;
cfg.temporal_layering_mode = VP9E_TEMPORAL_LAYERING_MODE_BYPASS;
set_temporal_layer_pattern(layering_mode,
&cfg,
layer_flags,
......@@ -633,8 +635,8 @@ int main(int argc, char **argv) {
set_rate_control_metrics(&rc, &cfg);
// Target bandwidth for the whole stream.
// Set to ts_target_bitrate for highest layer (total bitrate).
cfg.rc_target_bitrate = cfg.ts_target_bitrate[cfg.ts_number_layers - 1];
// Set to layer_target_bitrate for highest layer (total bitrate).
cfg.rc_target_bitrate = cfg.layer_target_bitrate[cfg.ts_number_layers - 1];
// Open input file.
if (!(infile = fopen(argv[1], "rb"))) {
......@@ -677,6 +679,9 @@ int main(int argc, char **argv) {
vpx_codec_control(&codec, VP8E_SET_NOISE_SENSITIVITY, kDenoiserOff);
vpx_codec_control(&codec, VP8E_SET_STATIC_THRESHOLD, 0);
} else if (strncmp(encoder->name, "vp9", 3) == 0) {
#if VPX_ENCODER_ABI_VERSION > (4 + VPX_CODEC_ABI_VERSION)
vpx_svc_extra_cfg_t svc_params;
#endif
vpx_codec_control(&codec, VP8E_SET_CPUUSED, speed);
vpx_codec_control(&codec, VP9E_SET_AQ_MODE, 3);
vpx_codec_control(&codec, VP9E_SET_FRAME_PERIODIC_BOOST, 0);
......@@ -685,6 +690,15 @@ int main(int argc, char **argv) {
vpx_codec_control(&codec, VP9E_SET_TILE_COLUMNS, (cfg.g_threads >> 1));
if (vpx_codec_control(&codec, VP9E_SET_SVC, layering_mode > 0 ? 1: 0)) {
die_codec(&codec, "Failed to set SVC");
#if VPX_ENCODER_ABI_VERSION > (4 + VPX_CODEC_ABI_VERSION)
for (i = 0; i < cfg.ts_number_layers; ++i) {
svc_params.max_quantizers[i] = cfg.rc_max_quantizer;
svc_params.min_quantizers[i] = cfg.rc_min_quantizer;
}
svc_params.scaling_factor_num[0] = cfg.g_h;
svc_params.scaling_factor_den[0] = cfg.g_h;
vpx_codec_control(&codec, VP9E_SET_SVC_PARAMETERS, &svc_params);
#endif
}
}
if (strncmp(encoder->name, "vp8", 3) == 0) {
......
This diff is collapsed.
......@@ -133,6 +133,10 @@ class Encoder {
ASSERT_EQ(VPX_CODEC_OK, res) << EncoderError();
}
void Control(int ctrl_id, struct vpx_svc_parameters *arg) {
const vpx_codec_err_t res = vpx_codec_control_(&encoder_, ctrl_id, arg);
ASSERT_EQ(VPX_CODEC_OK, res) << EncoderError();
}
#if CONFIG_VP8_ENCODER || CONFIG_VP9_ENCODER
void Control(int ctrl_id, vpx_active_map_t *arg) {
const vpx_codec_err_t res = vpx_codec_control_(&encoder_, ctrl_id, arg);
......
......@@ -453,6 +453,7 @@ TEST_F(SvcTest, OnePassEncodeOneFrame) {
TEST_F(SvcTest, OnePassEncodeThreeFrames) {
codec_enc_.g_pass = VPX_RC_ONE_PASS;
codec_enc_.g_lag_in_frames = 0;
vpx_fixed_buf outputs[3];
memset(&outputs[0], 0, sizeof(outputs));
Pass2EncodeNFrames(NULL, 3, 2, &outputs[0]);
......
......@@ -687,17 +687,28 @@ static int choose_partitioning(VP9_COMP *cpi,
s = x->plane[0].src.buf;
sp = x->plane[0].src.stride;
if (!is_key_frame) {
if (!is_key_frame && !(is_one_pass_cbr_svc(cpi) &&
cpi->svc.layer_context[cpi->svc.temporal_layer_id].is_key_frame)) {
// In the case of spatial/temporal scalable coding, the assumption here is
// that the temporal reference frame will always be of type LAST_FRAME.
// TODO(marpan): If that assumption is broken, we need to revisit this code.
MB_MODE_INFO *mbmi = &xd->mi[0]->mbmi;
unsigned int uv_sad;
const YV12_BUFFER_CONFIG *yv12 = get_ref_frame_buffer(cpi, LAST_FRAME);
const YV12_BUFFER_CONFIG *yv12_g = get_ref_frame_buffer(cpi, GOLDEN_FRAME);
const YV12_BUFFER_CONFIG *yv12_g = NULL;
unsigned int y_sad, y_sad_g;
const BLOCK_SIZE bsize = BLOCK_32X32
+ (mi_col + 4 < cm->mi_cols) * 2 + (mi_row + 4 < cm->mi_rows);
assert(yv12 != NULL);
if (!(is_one_pass_cbr_svc(cpi) && cpi->svc.spatial_layer_id)) {
// For now, GOLDEN will not be used for non-zero spatial layers, since
// it may not be a temporal reference.
yv12_g = get_ref_frame_buffer(cpi, GOLDEN_FRAME);
}
if (yv12_g && yv12_g != yv12) {
vp9_setup_pre_planes(xd, 0, yv12_g, mi_row, mi_col,
&cm->frame_refs[GOLDEN_FRAME - 1].sf);
......
......@@ -756,6 +756,8 @@ static void init_config(struct VP9_COMP *cpi, VP9EncoderConfig *oxcf) {
cm->height = oxcf->height;
vp9_alloc_compressor_data(cpi);
cpi->svc.temporal_layering_mode = oxcf->temporal_layering_mode;
// Single thread case: use counts in common.
cpi->td.counts = &cm->counts;
......@@ -2265,8 +2267,9 @@ static void generate_psnr_packet(VP9_COMP *cpi) {
pkt.data.psnr.psnr[i] = psnr.psnr[i];
}
pkt.kind = VPX_CODEC_PSNR_PKT;
if (is_two_pass_svc(cpi))
cpi->svc.layer_context[cpi->svc.spatial_layer_id].psnr_pkt = pkt.data.psnr;
if (cpi->use_svc)
cpi->svc.layer_context[cpi->svc.spatial_layer_id *
cpi->svc.number_temporal_layers].psnr_pkt = pkt.data.psnr;
else
vpx_codec_pkt_list_add(cpi->output_pkt_list, &pkt);
}
......@@ -3667,9 +3670,11 @@ static void encode_frame_to_data_rate(VP9_COMP *cpi,
}
cm->prev_frame = cm->cur_frame;
if (is_two_pass_svc(cpi))
cpi->svc.layer_context[cpi->svc.spatial_layer_id].last_frame_type =
cm->frame_type;
if (cpi->use_svc)
cpi->svc.layer_context[cpi->svc.spatial_layer_id *
cpi->svc.number_temporal_layers +
cpi->svc.temporal_layer_id].last_frame_type =
cm->frame_type;
}
static void SvcEncode(VP9_COMP *cpi, size_t *size, uint8_t *dest,
......@@ -3930,6 +3935,8 @@ int vp9_get_compressed_data(VP9_COMP *cpi, unsigned int *frame_flags,
#endif
if (oxcf->pass == 2)
vp9_restore_layer_context(cpi);
} else if (is_one_pass_cbr_svc(cpi)) {
vp9_one_pass_cbr_svc_start_layer(cpi);
}
vpx_usec_timer_start(&cmptimer);
......@@ -3948,9 +3955,11 @@ int vp9_get_compressed_data(VP9_COMP *cpi, unsigned int *frame_flags,
// Normal defaults
cm->reset_frame_context = 0;
cm->refresh_frame_context = 1;
cpi->refresh_last_frame = 1;
cpi->refresh_golden_frame = 0;
cpi->refresh_alt_ref_frame = 0;
if (!is_one_pass_cbr_svc(cpi)) {
cpi->refresh_last_frame = 1;
cpi->refresh_golden_frame = 0;
cpi->refresh_alt_ref_frame = 0;
}
// Should we encode an arf frame.
arf_src_index = get_arf_src_index(cpi);
......@@ -4006,12 +4015,11 @@ int vp9_get_compressed_data(VP9_COMP *cpi, unsigned int *frame_flags,
}
// Read in the source frame.
#if CONFIG_SPATIAL_SVC
if (is_two_pass_svc(cpi))
if (cpi->use_svc)
source = vp9_svc_lookahead_pop(cpi, cpi->lookahead, flush);
else
#endif
source = vp9_lookahead_pop(cpi->lookahead, flush);
if (source != NULL) {
cm->show_frame = 1;
cm->intra_only = 0;
......@@ -4060,8 +4068,7 @@ int vp9_get_compressed_data(VP9_COMP *cpi, unsigned int *frame_flags,
adjust_frame_rate(cpi, source);
}
if (cpi->svc.number_temporal_layers > 1 &&
oxcf->rc_mode == VPX_CBR) {
if (is_one_pass_cbr_svc(cpi)) {
vp9_update_temporal_layer_framerate(cpi);
vp9_restore_layer_context(cpi);
}
......@@ -4143,11 +4150,10 @@ int vp9_get_compressed_data(VP9_COMP *cpi, unsigned int *frame_flags,
}
// Save layer specific state.
if ((cpi->svc.number_temporal_layers > 1 &&
oxcf->rc_mode == VPX_CBR) ||
((cpi->svc.number_temporal_layers > 1 ||
cpi->svc.number_spatial_layers > 1) &&
oxcf->pass == 2)) {
if (is_one_pass_cbr_svc(cpi) ||
((cpi->svc.number_temporal_layers > 1 ||
cpi->svc.number_spatial_layers > 1) &&
oxcf->pass == 2)) {
vp9_save_layer_context(cpi);
}
......@@ -4343,6 +4349,12 @@ int vp9_get_compressed_data(VP9_COMP *cpi, unsigned int *frame_flags,
// May need the empty frame after an visible frame.
cpi->svc.encode_empty_frame_state = NEED_TO_ENCODE;
}
} else if (is_one_pass_cbr_svc(cpi)) {
if (cm->show_frame) {
++cpi->svc.spatial_layer_to_encode;
if (cpi->svc.spatial_layer_to_encode >= cpi->svc.number_spatial_layers)
cpi->svc.spatial_layer_to_encode = 0;
}
}
return 0;
}
......
......@@ -194,10 +194,10 @@ typedef struct VP9EncoderConfig {
int ss_number_layers; // Number of spatial layers.
int ts_number_layers; // Number of temporal layers.
// Bitrate allocation for spatial layers.
int layer_target_bitrate[VPX_MAX_LAYERS];
int ss_target_bitrate[VPX_SS_MAX_LAYERS];
int ss_enable_auto_arf[VPX_SS_MAX_LAYERS];
// Bitrate allocation (CBR mode) and framerate factor, for temporal layers.
int ts_target_bitrate[VPX_TS_MAX_LAYERS];
int ts_rate_decimator[VPX_TS_MAX_LAYERS];
int enable_auto_arf;
......@@ -237,6 +237,7 @@ typedef struct VP9EncoderConfig {
int use_highbitdepth;
#endif
vpx_color_space_t color_space;
VP9E_TEMPORAL_LAYERING_MODE temporal_layering_mode;
} VP9EncoderConfig;
static INLINE int is_lossless_requested(const VP9EncoderConfig *cfg) {
......@@ -611,9 +612,11 @@ YV12_BUFFER_CONFIG *vp9_scale_if_required(VP9_COMMON *cm,
void vp9_apply_encoding_flags(VP9_COMP *cpi, vpx_enc_frame_flags_t flags);
static INLINE int is_two_pass_svc(const struct VP9_COMP *const cpi) {
return cpi->use_svc &&
((cpi->svc.number_spatial_layers > 1) ||
(cpi->svc.number_temporal_layers > 1 && cpi->oxcf.pass != 0));
return cpi->use_svc && cpi->oxcf.pass != 0;
}
static INLINE int is_one_pass_cbr_svc(const struct VP9_COMP *const cpi) {
return (cpi->use_svc && cpi->oxcf.pass == 0);
}
static INLINE int is_altref_enabled(const VP9_COMP *const cpi) {
......@@ -642,6 +645,8 @@ static INLINE int *cond_cost_list(const struct VP9_COMP *cpi, int *cost_list) {
void vp9_new_framerate(VP9_COMP *cpi, double framerate);
#define LAYER_IDS_TO_IDX(sl, tl, num_tl) ((sl) * (num_tl) + (tl))
#ifdef __cplusplus
} // extern "C"
#endif
......
......@@ -234,13 +234,16 @@ int vp9_rc_clamp_iframe_target_size(const VP9_COMP *const cpi, int target) {
return target;
}
// Update the buffer level for higher layers, given the encoded current layer.
// Update the buffer level for higher temporal layers, given the encoded current
// temporal layer.
static void update_layer_buffer_level(SVC *svc, int encoded_frame_size) {
int temporal_layer = 0;
int i = 0;
int current_temporal_layer = svc->temporal_layer_id;
for (temporal_layer = current_temporal_layer + 1;
temporal_layer < svc->number_temporal_layers; ++temporal_layer) {
LAYER_CONTEXT *lc = &svc->layer_context[temporal_layer];
for (i = current_temporal_layer + 1;
i < svc->number_temporal_layers; ++i) {
const int layer = LAYER_IDS_TO_IDX(svc->spatial_layer_id, i,
svc->number_temporal_layers);
LAYER_CONTEXT *lc = &svc->layer_context[layer];
RATE_CONTROL *lrc = &lc->rc;
int bits_off_for_this_layer = (int)(lc->target_bandwidth / lc->framerate -
encoded_frame_size);
......@@ -268,7 +271,7 @@ static void update_buffer_level(VP9_COMP *cpi, int encoded_frame_size) {
rc->bits_off_target = MIN(rc->bits_off_target, rc->maximum_buffer_size);
rc->buffer_level = rc->bits_off_target;
if (cpi->use_svc && cpi->oxcf.rc_mode == VPX_CBR) {
if (is_one_pass_cbr_svc(cpi)) {
update_layer_buffer_level(&cpi->svc, encoded_frame_size);
}
}
......@@ -1418,13 +1421,14 @@ static int calc_pframe_target_size_one_pass_cbr(const VP9_COMP *cpi) {
} else {
target = rc->avg_frame_bandwidth;
}
if (svc->number_temporal_layers > 1 &&
oxcf->rc_mode == VPX_CBR) {
if (is_one_pass_cbr_svc(cpi)) {
// Note that for layers, avg_frame_bandwidth is the cumulative
// per-frame-bandwidth. For the target size of this frame, use the
// layer average frame size (i.e., non-cumulative per-frame-bw).
int current_temporal_layer = svc->temporal_layer_id;
const LAYER_CONTEXT *lc = &svc->layer_context[current_temporal_layer];
int layer =
LAYER_IDS_TO_IDX(svc->spatial_layer_id,
svc->temporal_layer_id, svc->number_temporal_layers);
const LAYER_CONTEXT *lc = &svc->layer_context[layer];
target = lc->avg_frame_size;
min_frame_target = MAX(lc->avg_frame_size >> 4, FRAME_OVERHEAD_BITS);
}
......@@ -1459,7 +1463,9 @@ static int calc_iframe_target_size_one_pass_cbr(const VP9_COMP *cpi) {
if (svc->number_temporal_layers > 1 &&
oxcf->rc_mode == VPX_CBR) {
// Use the layer framerate for temporal layers CBR mode.
const LAYER_CONTEXT *lc = &svc->layer_context[svc->temporal_layer_id];
const int layer = LAYER_IDS_TO_IDX(svc->spatial_layer_id,
svc->temporal_layer_id, svc->number_temporal_layers);
const LAYER_CONTEXT *lc = &svc->layer_context[layer];
framerate = lc->framerate;
}
kf_boost = MAX(kf_boost, (int)(2 * framerate - 16));
......@@ -1472,10 +1478,27 @@ static int calc_iframe_target_size_one_pass_cbr(const VP9_COMP *cpi) {
return vp9_rc_clamp_iframe_target_size(cpi, target);
}
// Reset information needed to set proper reference frames and buffer updates
// for temporal layering. This is called when a key frame is encoded.
static void reset_temporal_layer_to_zero(VP9_COMP *cpi) {
int sl;
LAYER_CONTEXT *lc = NULL;
cpi->svc.temporal_layer_id = 0;
for (sl = 0; sl < cpi->svc.number_spatial_layers; ++sl) {
lc = &cpi->svc.layer_context[sl * cpi->svc.number_temporal_layers];
lc->current_video_frame_in_layer = 0;
lc->frames_from_key_frame = 0;
}
}
void vp9_rc_get_svc_params(VP9_COMP *cpi) {
VP9_COMMON *const cm = &cpi->common;
RATE_CONTROL *const rc = &cpi->rc;
int target = rc->avg_frame_bandwidth;
const int layer = LAYER_IDS_TO_IDX(cpi->svc.spatial_layer_id,
cpi->svc.temporal_layer_id, cpi->svc.number_temporal_layers);
if ((cm->current_video_frame == 0) ||
(cpi->frame_flags & FRAMEFLAGS_KEY) ||
(cpi->oxcf.auto_key && (rc->frames_since_key %
......@@ -1484,30 +1507,39 @@ void vp9_rc_get_svc_params(VP9_COMP *cpi) {
rc->source_alt_ref_active = 0;
if (is_two_pass_svc(cpi)) {
cpi->svc.layer_context[cpi->svc.spatial_layer_id].is_key_frame = 1;
cpi->svc.layer_context[layer].is_key_frame = 1;
cpi->ref_frame_flags &=
(~VP9_LAST_FLAG & ~VP9_GOLD_FLAG & ~VP9_ALT_FLAG);
}
if (cpi->oxcf.pass == 0 && cpi->oxcf.rc_mode == VPX_CBR) {
} else if (is_one_pass_cbr_svc(cpi)) {
cpi->svc.layer_context[layer].is_key_frame = 1;
reset_temporal_layer_to_zero(cpi);
cpi->ref_frame_flags &=
(~VP9_LAST_FLAG & ~VP9_GOLD_FLAG & ~VP9_ALT_FLAG);
// Assumption here is that LAST_FRAME is being updated for a keyframe.
// Thus no change in update flags.
target = calc_iframe_target_size_one_pass_cbr(cpi);
}
} else {
cm->frame_type = INTER_FRAME;
if (is_two_pass_svc(cpi)) {
LAYER_CONTEXT *lc = &cpi->svc.layer_context[cpi->svc.spatial_layer_id];
LAYER_CONTEXT *lc = &cpi->svc.layer_context[layer];
if (cpi->svc.spatial_layer_id == 0) {
lc->is_key_frame = 0;
} else {
lc->is_key_frame = cpi->svc.layer_context[0].is_key_frame;
lc->is_key_frame =
cpi->svc.layer_context[cpi->svc.temporal_layer_id].is_key_frame;
if (lc->is_key_frame)
cpi->ref_frame_flags &= (~VP9_LAST_FLAG);
}
cpi->ref_frame_flags &= (~VP9_ALT_FLAG);
}
if (cpi->oxcf.pass == 0 && cpi->oxcf.rc_mode == VPX_CBR) {
} else if (is_one_pass_cbr_svc(cpi)) {
LAYER_CONTEXT *lc = &cpi->svc.layer_context[layer];
if (cpi->svc.spatial_layer_id == 0) {
lc->is_key_frame = 0;
} else {
lc->is_key_frame =
cpi->svc.layer_context[cpi->svc.temporal_layer_id].is_key_frame;
}
target = calc_pframe_target_size_one_pass_cbr(cpi);
}
}
......
This diff is collapsed.
......@@ -22,6 +22,7 @@ extern "C" {
typedef struct {
RATE_CONTROL rc;
int target_bandwidth;
int spatial_layer_target_bandwidth; // Target for the spatial layer.
double framerate;
int avg_frame_size;
int max_q;
......@@ -64,9 +65,11 @@ typedef struct {
YV12_BUFFER_CONFIG scaled_frames[MAX_LAG_BUFFERS];
// Layer context used for rate control in one pass temporal CBR mode or
// two pass spatial mode. Defined for temporal or spatial layers for now.
// Does not support temporal combined with spatial RC.
LAYER_CONTEXT layer_context[MAX(VPX_TS_MAX_LAYERS, VPX_SS_MAX_LAYERS)];
// two pass spatial mode.
LAYER_CONTEXT layer_context[VPX_MAX_LAYERS];
// Indicates what sort of temporal layering is used.
// Currently, this only works for CBR mode.
VP9E_TEMPORAL_LAYERING_MODE temporal_layering_mode;
} SVC;
struct VP9_COMP;
......@@ -110,6 +113,8 @@ struct lookahead_entry *vp9_svc_lookahead_pop(struct VP9_COMP *const cpi,
// Start a frame and initialize svc parameters
int vp9_svc_start_frame(struct VP9_COMP *const cpi);
int vp9_one_pass_cbr_svc_start_layer(struct VP9_COMP *const cpi);
#ifdef __cplusplus
} // extern "C"
#endif
......
......@@ -682,7 +682,7 @@ void vp9_temporal_filter(VP9_COMP *cpi, int distance) {
if (frames_to_blur > 0) {
// Setup scaling factors. Scaling on each of the arnr frames is not
// supported.
if (is_two_pass_svc(cpi)) {
if (cpi->use_svc) {
// In spatial svc the scaling factors might be less then 1/2.
// So we will use non-normative scaling.
int frame_used = 0;
......
......@@ -176,15 +176,23 @@ static vpx_codec_err_t validate_config(vpx_codec_alg_priv_t *ctx,
RANGE_CHECK(cfg, ss_number_layers, 1, VPX_SS_MAX_LAYERS);
RANGE_CHECK(cfg, ts_number_layers, 1, VPX_TS_MAX_LAYERS);
if (cfg->ss_number_layers * cfg->ts_number_layers > VPX_MAX_LAYERS)
ERROR("ss_number_layers * ts_number_layers is out of range");
if (cfg->ts_number_layers > 1) {
unsigned int i;
for (i = 1; i < cfg->ts_number_layers; ++i)
if (cfg->ts_target_bitrate[i] < cfg->ts_target_bitrate[i - 1])
unsigned int sl, tl;
for (sl = 1; sl < cfg->ss_number_layers; ++sl) {
for (tl = 1; tl < cfg->ts_number_layers; ++tl) {
const int layer =
LAYER_IDS_TO_IDX(sl, tl, cfg->ts_number_layers);
if (cfg->layer_target_bitrate[layer] <
cfg->layer_target_bitrate[layer - 1])
ERROR("ts_target_bitrate entries are not increasing");
}
}
RANGE_CHECK(cfg, ts_rate_decimator[cfg->ts_number_layers - 1], 1, 1);
for (i = cfg->ts_number_layers - 2; i > 0; --i)
if (cfg->ts_rate_decimator[i - 1] != 2 * cfg->ts_rate_decimator[i])
for (tl = cfg->ts_number_layers - 2; tl > 0; --tl)
if (cfg->ts_rate_decimator[tl - 1] != 2 * cfg->ts_rate_decimator[tl])
ERROR("ts_rate_decimator factors are not powers of 2");
}
......@@ -360,6 +368,7 @@ static vpx_codec_err_t set_encoder_config(
const vpx_codec_enc_cfg_t *cfg,
const struct vp9_extracfg *extra_cfg) {
const int is_vbr = cfg->rc_end_usage == VPX_VBR;
int sl, tl;
oxcf->profile = cfg->g_profile;
oxcf->max_threads = (int)cfg->g_threads;
oxcf->width = cfg->g_w;
......@@ -460,35 +469,33 @@ static vpx_codec_err_t set_encoder_config(
oxcf->frame_periodic_boost = extra_cfg->frame_periodic_boost;
oxcf->ss_number_layers = cfg->ss_number_layers;
oxcf->ts_number_layers = cfg->ts_number_layers;
oxcf->temporal_layering_mode = (enum vp9e_temporal_layering_mode)
cfg->temporal_layering_mode;
if (oxcf->ss_number_layers > 1) {
int i;
for (i = 0; i < VPX_SS_MAX_LAYERS; ++i) {
oxcf->ss_target_bitrate[i] = 1000 * cfg->ss_target_bitrate[i];
for (sl = 0; sl < oxcf->ss_number_layers; ++sl) {
#if CONFIG_SPATIAL_SVC
oxcf->ss_enable_auto_arf[i] = cfg->ss_enable_auto_alt_ref[i];
oxcf->ss_enable_auto_arf[sl] = cfg->ss_enable_auto_alt_ref[sl];
#endif
for (tl = 0; tl < oxcf->ts_number_layers; ++tl) {
oxcf->layer_target_bitrate[sl * oxcf->ts_number_layers + tl] =
1000 * cfg->layer_target_bitrate[sl * oxcf->ts_number_layers + tl];
}
} else if (oxcf->ss_number_layers == 1) {
}
if (oxcf->ss_number_layers == 1 && oxcf->pass != 0) {
oxcf->ss_target_bitrate[0] = (int)oxcf->target_bandwidth;
#if CONFIG_SPATIAL_SVC
oxcf->ss_enable_auto_arf[0] = extra_cfg->enable_auto_alt_ref;
#endif
}
oxcf->ts_number_layers = cfg->ts_number_layers;
if (oxcf->ts_number_layers > 1) {
int i;
for (i = 0; i < VPX_TS_MAX_LAYERS; ++i) {
oxcf->ts_target_bitrate[i] = 1000 * cfg->ts_target_bitrate[i];
oxcf->ts_rate_decimator[i] = cfg->ts_rate_decimator[i];
for (tl = 0; tl < VPX_TS_MAX_LAYERS; ++tl) {
oxcf->ts_rate_decimator[tl] = cfg->ts_rate_decimator[tl] ?
cfg->ts_rate_decimator[tl] : 1;
}
} else if (oxcf->ts_number_layers == 1) {
oxcf->ts_target_bitrate[0] = (int)oxcf->target_bandwidth;
oxcf->ts_rate_decimator[0] = 1;
}
/*
printf("Current VP9 Settings: \n");
printf("target_bandwidth: %d\n", oxcf->target_bandwidth);
......@@ -902,11 +909,12 @@ static vpx_codec_frame_flags_t get_frame_pkt_flags(const VP9_COMP *cpi,
unsigned int lib_flags) {
vpx_codec_frame_flags_t flags = lib_flags << 16;
if (lib_flags & FRAMEFLAGS_KEY
#if CONFIG_SPATIAL_SVC
|| (is_two_pass_svc(cpi) && cpi->svc.layer_context[0].is_key_frame)
#endif
)
if (lib_flags & FRAMEFLAGS_KEY ||
(cpi->use_svc &&
cpi->svc.layer_context[cpi->svc.spatial_layer_id *
cpi->svc.number_temporal_layers +
cpi->svc.temporal_layer_id].is_key_frame)
)
flags |= VPX_FRAME_IS_KEY;
if (cpi->droppable)
......@@ -1022,16 +1030,15 @@ static vpx_codec_err_t encoder_encode(vpx_codec_alg_priv_t *ctx,
vpx_codec_cx_pkt_t pkt;
#if CONFIG_SPATIAL_SVC
if (is_two_pass_svc(cpi))
cpi->svc.layer_context[cpi->svc.spatial_layer_id].layer_size += size;
if (cpi->use_svc)
cpi->svc.layer_context[cpi->svc.spatial_layer_id *
cpi->svc.number_temporal_layers].layer_size += size;
#endif
// Pack invisible frames with the next visible frame
if (!cpi->common.show_frame
#if CONFIG_SPATIAL_SVC
|| (is_two_pass_svc(cpi) &&
cpi->svc.spatial_layer_id < cpi->svc.number_spatial_layers - 1)
#endif
if (!cpi->common.show_frame ||
(cpi->use_svc &&
cpi->svc.spatial_layer_id < cpi->svc.number_spatial_layers - 1)
) {
if (ctx->pending_cx_data == 0)
ctx->pending_cx_data = cx_data;
......@@ -1089,24 +1096,26 @@ static vpx_codec_err_t encoder_encode(vpx_codec_alg_priv_t *ctx,
pkt.data.frame.partition_id = -1;
if(ctx->output_cx_pkt_cb.output_cx_pkt)
ctx->output_cx_pkt_cb.output_cx_pkt(&pkt, ctx->output_cx_pkt_cb.user_priv);
ctx->output_cx_pkt_cb.output_cx_pkt(&pkt,
ctx->output_cx_pkt_cb.user_priv);
else
vpx_codec_pkt_list_add(&ctx->pkt_list.head, &pkt);
cx_data += size;
cx_data_sz -= size;
#if CONFIG_SPATIAL_SVC
if (is_two_pass_svc(cpi) && !ctx->output_cx_pkt_cb.output_cx_pkt) {
if (cpi->use_svc && !ctx->output_cx_pkt_cb.output_cx_pkt) {
vpx_codec_cx_pkt_t pkt_sizes, pkt_psnr;
int i;
int sl;
vp9_zero(pkt_sizes);
vp9_zero(pkt_psnr);
pkt_sizes.kind = VPX_CODEC_SPATIAL_SVC_LAYER_SIZES;
pkt_psnr.kind = VPX_CODEC_SPATIAL_SVC_LAYER_PSNR;
for (i = 0; i < cpi->svc.number_spatial_layers; ++i) {
LAYER_CONTEXT *lc = &cpi->svc.layer_context[i];
pkt_sizes.data.layer_sizes[i] = lc->layer_size;
pkt_psnr.data.layer_psnr[i] = lc->psnr_pkt;
for (sl = 0; sl < cpi->svc.number_spatial_layers; ++sl) {
LAYER_CONTEXT *lc =
&cpi->svc.layer_context[sl * cpi->svc.number_temporal_layers];
pkt_sizes.data.layer_sizes[sl] = lc->layer_size;
pkt_psnr.data.layer_psnr[sl] = lc->psnr_pkt;
lc->layer_size = 0;
}
......@@ -1115,6 +1124,11 @@ static vpx_codec_err_t encoder_encode(vpx_codec_alg_priv_t *ctx,
vpx_codec_pkt_list_add(&ctx->pkt_list.head, &pkt_psnr);
}
#endif
if (is_one_pass_cbr_svc(cpi) &&
(cpi->svc.spatial_layer_id == cpi->svc.number_spatial_layers - 1)) {
// Encoded all spatial layers; exit loop.
break;
}
}
}
}
......@@ -1292,16 +1306,20 @@ static vpx_codec_err_t ctrl_set_scale_mode(vpx_codec_alg_priv_t *ctx,
static vpx_codec_err_t ctrl_set_svc(vpx_codec_alg_priv_t *ctx, va_list args) {
int data = va_arg(args, int);
const vpx_codec_enc_cfg_t *cfg = &ctx->cfg;
// Both one-pass and two-pass RC are supported now.
// User setting this has to make sure of the following.
// In two-pass setting: either (but not both)
// cfg->ss_number_layers > 1, or cfg->ts_number_layers > 1
// In one-pass setting:
// either or both cfg->ss_number_layers > 1, or cfg->ts_number_layers > 1
vp9_set_svc(ctx->cpi, data);
// CBR or two pass mode for SVC with both temporal and spatial layers
// not yet supported.
if (data == 1 &&
(cfg->rc_end_usage == VPX_CBR ||
cfg->g_pass == VPX_RC_FIRST_PASS ||
(cfg->g_pass == VPX_RC_FIRST_PASS ||
cfg->g_pass == VPX_RC_LAST_PASS) &&
cfg->ss_number_layers > 1 &&
cfg->ts_number_layers > 1) {
cfg->ss_number_layers > 1 &&
cfg->ts_number_layers > 1) {
return VPX_CODEC_INVALID_PARAM;
}
return VPX_CODEC_OK;
......@@ -1347,15 +1365,21 @@ static vpx_codec_err_t ctrl_set_svc_parameters(vpx_codec_alg_priv_t *ctx,
va_list args) {
VP9_COMP *const cpi = ctx->cpi;
vpx_svc_extra_cfg_t *const params = va_arg(args, vpx_svc_extra_cfg_t *);
int i;
for (i = 0; i < cpi->svc.number_spatial_layers; ++i) {
LAYER_CONTEXT *lc = &cpi->svc.layer_context[i];
lc->max_q = params->max_quantizers[i];
lc->min_q = params->min_quantizers[i];
lc->scaling_factor_num = params->scaling_factor_num[i];
lc->scaling_factor_den = params->scaling_factor_den[i];
int sl, tl;
// Number of temporal layers and number of spatial layers have to be set
// properly before calling this control function.
for (sl = 0; sl < cpi->svc.number_spatial_layers; ++sl) {
for (tl = 0; tl < cpi->svc.number_temporal_layers; ++tl) {
const int layer =
LAYER_IDS_TO_IDX(sl, tl, cpi->svc.number_temporal_layers);
LAYER_CONTEXT *lc =
&cpi->svc.layer_context[layer];
lc->max_q = params->max_quantizers[sl];
lc->min_q = params->min_quantizers[sl];
lc->scaling_factor_num = params->scaling_factor_num[sl];
lc->scaling_factor_den = params->scaling_factor_den[sl];
}
}
return VPX_CODEC_OK;
......@@ -1495,6 +1519,8 @@ static vpx_codec_enc_cfg_map_t encoder_usage_cfg_map[] = {
{0}, // ts_rate_decimator
0, // ts_periodicity
{0}, // ts_layer_id
{0}, // layer_taget_bitrate
0 // temporal_layering_mode
}
},
};
......
......@@ -302,31 +302,79 @@ void assign_layer_bitrates(const SvcContext *svc_ctx,
vpx_codec_enc_cfg_t *const enc_cfg) {