Commit be3b08da authored by Minghai Shang's avatar Minghai Shang

[svc] Temporal svc with two pass rate control

It's built based on current spatial svc code.
We only support one spatial two temporal layers at this time.
Change-Id: I1fdc8584354b910331e626bfae60473b3b701ba1
parent 6b649a0d
......@@ -38,8 +38,10 @@ static const arg_def_t timebase_arg =
ARG_DEF("t", "timebase", 1, "timebase (num/den)");
static const arg_def_t bitrate_arg = ARG_DEF(
"b", "target-bitrate", 1, "encoding bitrate, in kilobits per second");
static const arg_def_t layers_arg =
ARG_DEF("l", "layers", 1, "number of SVC layers");
static const arg_def_t spatial_layers_arg =
ARG_DEF("sl", "spatial-layers", 1, "number of spatial SVC layers");
static const arg_def_t temporal_layers_arg =
ARG_DEF("tl", "temporal-layers", 1, "number of temporal SVC layers");
static const arg_def_t kf_dist_arg =
ARG_DEF("k", "kf-dist", 1, "number of frames between keyframes");
static const arg_def_t scale_factors_arg =
......@@ -65,10 +67,11 @@ static const arg_def_t max_bitrate_arg =
static const arg_def_t *svc_args[] = {
&frames_arg, &width_arg, &height_arg,
&timebase_arg, &bitrate_arg, &skip_frames_arg, &layers_arg,
&timebase_arg, &bitrate_arg, &skip_frames_arg, &spatial_layers_arg,
&kf_dist_arg, &scale_factors_arg, &quantizers_arg, &passes_arg,
&pass_arg, &fpf_name_arg, &min_q_arg, &max_q_arg,
&min_bitrate_arg, &max_bitrate_arg, NULL
&min_bitrate_arg, &max_bitrate_arg, &temporal_layers_arg,
NULL
};
static const uint32_t default_frames_to_skip = 0;
......@@ -79,6 +82,7 @@ static const uint32_t default_timebase_num = 1;
static const uint32_t default_timebase_den = 60;
static const uint32_t default_bitrate = 1000;
static const uint32_t default_spatial_layers = 5;
static const uint32_t default_temporal_layers = 1;
static const uint32_t default_kf_dist = 100;
typedef struct {
......@@ -119,6 +123,7 @@ static void parse_command_line(int argc, const char **argv_,
// initialize SvcContext with parameters that will be passed to vpx_svc_init
svc_ctx->log_level = SVC_LOG_DEBUG;
svc_ctx->spatial_layers = default_spatial_layers;
svc_ctx->temporal_layers = default_temporal_layers;
// start with default encoder configuration
res = vpx_codec_enc_config_default(vpx_codec_vp9_cx(), enc_cfg, 0);
......@@ -156,8 +161,10 @@ static void parse_command_line(int argc, const char **argv_,
enc_cfg->rc_target_bitrate = arg_parse_uint(&arg);
} else if (arg_match(&arg, &skip_frames_arg, argi)) {
app_input->frames_to_skip = arg_parse_uint(&arg);
} else if (arg_match(&arg, &layers_arg, argi)) {
} else if (arg_match(&arg, &spatial_layers_arg, argi)) {
svc_ctx->spatial_layers = arg_parse_uint(&arg);
} else if (arg_match(&arg, &temporal_layers_arg, argi)) {
svc_ctx->temporal_layers = arg_parse_uint(&arg);
} else if (arg_match(&arg, &kf_dist_arg, argi)) {
enc_cfg->kf_min_dist = arg_parse_uint(&arg);
enc_cfg->kf_max_dist = enc_cfg->kf_min_dist;
......
This diff is collapsed.
......@@ -999,8 +999,10 @@ static void write_frame_size_with_refs(VP9_COMP *cpi,
// Set "found" to 0 for temporal svc and for spatial svc key frame
if (cpi->use_svc &&
(cpi->svc.number_spatial_layers == 1 ||
cpi->svc.layer_context[cpi->svc.spatial_layer_id].is_key_frame)) {
((cpi->svc.number_temporal_layers > 1 &&
cpi->oxcf.rc_mode == VPX_CBR) ||
(cpi->svc.number_spatial_layers > 1 &&
cpi->svc.layer_context[cpi->svc.spatial_layer_id].is_key_frame))) {
found = 0;
}
vp9_wb_write_bit(wb, found);
......@@ -1093,7 +1095,7 @@ static void write_uncompressed_header(VP9_COMP *cpi,
// show_existing_frame flag which tells the decoder which frame we want to
// show.
if (!cm->show_frame ||
(is_spatial_svc(cpi) && cm->error_resilient_mode == 0))
(is_two_pass_svc(cpi) && cm->error_resilient_mode == 0))
vp9_wb_write_bit(wb, cm->intra_only);
if (!cm->error_resilient_mode)
......
......@@ -26,7 +26,7 @@ static INLINE int vp9_preserve_existing_gf(VP9_COMP *cpi) {
return !cpi->multi_arf_allowed && cpi->refresh_golden_frame &&
cpi->rc.is_src_frame_alt_ref &&
(!cpi->use_svc || // Add spatial svc base layer case here
(is_spatial_svc(cpi) &&
(is_two_pass_svc(cpi) &&
cpi->svc.spatial_layer_id == 0 &&
cpi->svc.layer_context[0].gold_ref_idx >=0 &&
cpi->oxcf.ss_play_alternate[0]));
......
......@@ -128,7 +128,7 @@ static void setup_frame(VP9_COMP *cpi) {
}
if (cm->frame_type == KEY_FRAME) {
if (!is_spatial_svc(cpi))
if (!is_two_pass_svc(cpi))
cpi->refresh_golden_frame = 1;
cpi->refresh_alt_ref_frame = 1;
vp9_zero(cpi->interp_filter_selected);
......@@ -510,7 +510,7 @@ static void update_frame_size(VP9_COMP *cpi) {
vp9_init_context_buffers(cm);
init_macroblockd(cm, xd);
if (is_spatial_svc(cpi)) {
if (is_two_pass_svc(cpi)) {
if (vp9_realloc_frame_buffer(&cpi->alt_ref_buffer,
cm->width, cm->height,
cm->subsampling_x, cm->subsampling_y,
......@@ -562,7 +562,9 @@ static void init_config(struct VP9_COMP *cpi, VP9EncoderConfig *oxcf) {
cpi->svc.number_temporal_layers = oxcf->ts_number_layers;
if ((cpi->svc.number_temporal_layers > 1 && cpi->oxcf.rc_mode == VPX_CBR) ||
(cpi->svc.number_spatial_layers > 1 && cpi->oxcf.pass == 2)) {
((cpi->svc.number_temporal_layers > 1 ||
cpi->svc.number_spatial_layers > 1) &&
cpi->oxcf.pass == 2)) {
vp9_init_layer_context(cpi);
}
......@@ -654,7 +656,9 @@ void vp9_change_config(struct VP9_COMP *cpi, const VP9EncoderConfig *oxcf) {
if ((cpi->svc.number_temporal_layers > 1 &&
cpi->oxcf.rc_mode == VPX_CBR) ||
(cpi->svc.number_spatial_layers > 1 && cpi->oxcf.pass == 2)) {
((cpi->svc.number_temporal_layers > 1 ||
cpi->svc.number_spatial_layers > 1) &&
cpi->oxcf.pass == 2)) {
vp9_update_layer_context_change_config(cpi,
(int)cpi->oxcf.target_bandwidth);
}
......@@ -902,7 +906,7 @@ VP9_COMP *vp9_create_compressor(VP9EncoderConfig *oxcf) {
const int packets = (int)(oxcf->two_pass_stats_in.sz / packet_sz);
if (cpi->svc.number_spatial_layers > 1
&& cpi->svc.number_temporal_layers == 1) {
|| cpi->svc.number_temporal_layers > 1) {
FIRSTPASS_STATS *const stats = oxcf->two_pass_stats_in.buf;
FIRSTPASS_STATS *stats_copy[VPX_SS_MAX_LAYERS] = {0};
int i;
......@@ -1510,7 +1514,7 @@ void vp9_update_reference_frames(VP9_COMP *cpi) {
cpi->alt_fb_idx = cpi->gld_fb_idx;
cpi->gld_fb_idx = tmp;
if (is_spatial_svc(cpi)) {
if (is_two_pass_svc(cpi)) {
cpi->svc.layer_context[0].gold_ref_idx = cpi->gld_fb_idx;
cpi->svc.layer_context[0].alt_ref_idx = cpi->alt_fb_idx;
}
......@@ -1936,8 +1940,7 @@ static int get_ref_frame_flags(const VP9_COMP *cpi) {
if (gold_is_last)
flags &= ~VP9_GOLD_FLAG;
if (cpi->rc.frames_till_gf_update_due == INT_MAX &&
!is_spatial_svc(cpi))
if (cpi->rc.frames_till_gf_update_due == INT_MAX && !is_two_pass_svc(cpi))
flags &= ~VP9_GOLD_FLAG;
if (alt_is_last)
......@@ -1984,7 +1987,7 @@ static int is_skippable_frame(const VP9_COMP *cpi) {
// can be skipped for partition check, and the partition size is assigned
// according to the variance
const SVC *const svc = &cpi->svc;
const TWO_PASS *const twopass = is_spatial_svc(cpi) ?
const TWO_PASS *const twopass = is_two_pass_svc(cpi) ?
&svc->layer_context[svc->spatial_layer_id].twopass : &cpi->twopass;
return (!frame_is_intra_only(&cpi->common) &&
......@@ -2136,18 +2139,34 @@ static void encode_frame_to_data_rate(VP9_COMP *cpi,
cm->reset_frame_context = 2;
}
}
if (is_spatial_svc(cpi) && cm->error_resilient_mode == 0) {
cm->frame_context_idx = cpi->svc.spatial_layer_id;
if (is_two_pass_svc(cpi) && cm->error_resilient_mode == 0) {
cm->frame_context_idx =
cpi->svc.spatial_layer_id * cpi->svc.number_temporal_layers +
cpi->svc.temporal_layer_id;
// The probs will be updated based on the frame type of its previous
// frame if frame_parallel_decoding_mode is 0. The type may vary for
// the frame after a key frame in base layer since we may drop enhancement
// layers. So set frame_parallel_decoding_mode to 1 in this case.
if (cpi->svc.spatial_layer_id == 0 &&
cpi->svc.layer_context[0].last_frame_type == KEY_FRAME)
cm->frame_parallel_decoding_mode = 1;
else
cm->frame_parallel_decoding_mode = 0;
if (cpi->svc.number_temporal_layers == 1) {
if (cpi->svc.spatial_layer_id == 0 &&
cpi->svc.layer_context[0].last_frame_type == KEY_FRAME)
cm->frame_parallel_decoding_mode = 1;
else
cm->frame_parallel_decoding_mode = 0;
} else if (cpi->svc.spatial_layer_id == 0) {
// Find the 2nd frame in temporal base layer and 1st frame in temporal
// enhancement layers from the key frame.
int i;
for (i = 0; i < cpi->svc.number_temporal_layers; ++i) {
if (cpi->svc.layer_context[0].frames_from_key_frame == 1 << i) {
cm->frame_parallel_decoding_mode = 1;
break;
}
}
if (i == cpi->svc.number_temporal_layers)
cm->frame_parallel_decoding_mode = 0;
}
}
// Configure experimental use of segmentation for enhanced coding of
......@@ -2160,7 +2179,7 @@ static void encode_frame_to_data_rate(VP9_COMP *cpi,
// Check if the current frame is skippable for the partition search in the
// second pass according to the first pass stats
if (oxcf->pass == 2 &&
(!cpi->use_svc || is_spatial_svc(cpi))) {
(!cpi->use_svc || is_two_pass_svc(cpi))) {
cpi->skippable_frame = is_skippable_frame(cpi);
}
......@@ -2306,7 +2325,7 @@ static void encode_frame_to_data_rate(VP9_COMP *cpi,
// reset to normal state now that we are done.
if (!cm->show_existing_frame) {
if (is_spatial_svc(cpi) && cm->error_resilient_mode == 0)
if (is_two_pass_svc(cpi) && cm->error_resilient_mode == 0)
cm->last_show_frame = 0;
else
cm->last_show_frame = cm->show_frame;
......@@ -2319,10 +2338,10 @@ static void encode_frame_to_data_rate(VP9_COMP *cpi,
// update not a real frame
++cm->current_video_frame;
if (cpi->use_svc)
vp9_inc_frame_in_layer(&cpi->svc);
vp9_inc_frame_in_layer(cpi);
}
if (is_spatial_svc(cpi))
if (is_two_pass_svc(cpi))
cpi->svc.layer_context[cpi->svc.spatial_layer_id].last_frame_type =
cm->frame_type;
}
......@@ -2397,7 +2416,7 @@ int vp9_receive_raw_frame(VP9_COMP *cpi, unsigned int frame_flags,
vpx_usec_timer_start(&timer);
#if CONFIG_SPATIAL_SVC
if (is_spatial_svc(cpi))
if (is_two_pass_svc(cpi))
res = vp9_svc_lookahead_push(cpi, cpi->lookahead, sd, time_stamp, end_time,
frame_flags);
else
......@@ -2533,7 +2552,7 @@ int vp9_get_compressed_data(VP9_COMP *cpi, unsigned int *frame_flags,
MV_REFERENCE_FRAME ref_frame;
int arf_src_index;
if (is_spatial_svc(cpi) && oxcf->pass == 2) {
if (is_two_pass_svc(cpi) && oxcf->pass == 2) {
#if CONFIG_SPATIAL_SVC
vp9_svc_lookahead_peek(cpi, cpi->lookahead, 0, 1);
#endif
......@@ -2557,7 +2576,7 @@ int vp9_get_compressed_data(VP9_COMP *cpi, unsigned int *frame_flags,
assert(arf_src_index <= rc->frames_to_key);
#if CONFIG_SPATIAL_SVC
if (is_spatial_svc(cpi))
if (is_two_pass_svc(cpi))
source = vp9_svc_lookahead_peek(cpi, cpi->lookahead, arf_src_index, 0);
else
#endif
......@@ -2566,7 +2585,7 @@ int vp9_get_compressed_data(VP9_COMP *cpi, unsigned int *frame_flags,
cpi->alt_ref_source = source;
#if CONFIG_SPATIAL_SVC
if (is_spatial_svc(cpi) && cpi->svc.spatial_layer_id > 0) {
if (is_two_pass_svc(cpi) && cpi->svc.spatial_layer_id > 0) {
int i;
// Reference a hidden frame from a lower layer
for (i = cpi->svc.spatial_layer_id - 1; i >= 0; --i) {
......@@ -2601,7 +2620,7 @@ int vp9_get_compressed_data(VP9_COMP *cpi, unsigned int *frame_flags,
// Get last frame source.
if (cm->current_video_frame > 0) {
#if CONFIG_SPATIAL_SVC
if (is_spatial_svc(cpi))
if (is_two_pass_svc(cpi))
last_source = vp9_svc_lookahead_peek(cpi, cpi->lookahead, -1, 0);
else
#endif
......@@ -2612,7 +2631,7 @@ int vp9_get_compressed_data(VP9_COMP *cpi, unsigned int *frame_flags,
// Read in the source frame.
#if CONFIG_SPATIAL_SVC
if (is_spatial_svc(cpi))
if (is_two_pass_svc(cpi))
source = vp9_svc_lookahead_pop(cpi, cpi->lookahead, flush);
else
#endif
......@@ -2723,13 +2742,13 @@ int vp9_get_compressed_data(VP9_COMP *cpi, unsigned int *frame_flags,
}
if (oxcf->pass == 1 &&
(!cpi->use_svc || is_spatial_svc(cpi))) {
(!cpi->use_svc || is_two_pass_svc(cpi))) {
const int lossless = is_lossless_requested(oxcf);
cpi->mb.fwd_txm4x4 = lossless ? vp9_fwht4x4 : vp9_fdct4x4;
cpi->mb.itxm_add = lossless ? vp9_iwht4x4_add : vp9_idct4x4_add;
vp9_first_pass(cpi, source);
} else if (oxcf->pass == 2 &&
(!cpi->use_svc || is_spatial_svc(cpi))) {
(!cpi->use_svc || is_two_pass_svc(cpi))) {
Pass2Encode(cpi, size, dest, frame_flags);
} else if (cpi->use_svc) {
SvcEncode(cpi, size, dest, frame_flags);
......@@ -2752,8 +2771,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_spatial_layers > 1 && oxcf->pass == 2)) {
oxcf->rc_mode == VPX_CBR) ||
((cpi->svc.number_temporal_layers > 1 ||
cpi->svc.number_spatial_layers > 1) &&
oxcf->pass == 2)) {
vp9_save_layer_context(cpi);
}
......
......@@ -494,16 +494,17 @@ 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_spatial_svc(const struct VP9_COMP *const cpi) {
static INLINE int is_two_pass_svc(const struct VP9_COMP *const cpi) {
return cpi->use_svc &&
cpi->svc.number_temporal_layers == 1 &&
cpi->svc.number_spatial_layers > 1;
(cpi->svc.number_temporal_layers > 1 ||
cpi->svc.number_spatial_layers > 1) &&
(cpi->oxcf.pass == 1 || cpi->oxcf.pass == 2);
}
static INLINE int is_altref_enabled(const VP9_COMP *const cpi) {
return cpi->oxcf.mode != REALTIME && cpi->oxcf.lag_in_frames > 0 &&
(cpi->oxcf.play_alternate &&
(!is_spatial_svc(cpi) ||
(!is_two_pass_svc(cpi) ||
cpi->oxcf.ss_play_alternate[cpi->svc.spatial_layer_id]));
}
......
......@@ -246,7 +246,7 @@ void vp9_init_first_pass(VP9_COMP *cpi) {
}
void vp9_end_first_pass(VP9_COMP *cpi) {
if (is_spatial_svc(cpi)) {
if (is_two_pass_svc(cpi)) {
int i;
for (i = 0; i < cpi->svc.number_spatial_layers; ++i) {
output_stats(&cpi->svc.layer_context[i].twopass.total_stats,
......@@ -422,8 +422,8 @@ void vp9_first_pass(VP9_COMP *cpi, const struct lookahead_entry *source) {
TWO_PASS *twopass = &cpi->twopass;
const MV zero_mv = {0, 0};
const YV12_BUFFER_CONFIG *first_ref_buf = lst_yv12;
LAYER_CONTEXT *const lc = is_spatial_svc(cpi) ?
&cpi->svc.layer_context[cpi->svc.spatial_layer_id] : 0;
LAYER_CONTEXT *const lc = is_two_pass_svc(cpi) ?
&cpi->svc.layer_context[cpi->svc.spatial_layer_id] : NULL;
#if CONFIG_FP_MB_STATS
if (cpi->use_fp_mb_stats) {
......@@ -438,13 +438,13 @@ void vp9_first_pass(VP9_COMP *cpi, const struct lookahead_entry *source) {
if (lc != NULL) {
MV_REFERENCE_FRAME ref_frame = LAST_FRAME;
const YV12_BUFFER_CONFIG *scaled_ref_buf = NULL;
twopass = &lc->twopass;
if (cpi->common.current_video_frame == 0) {
cpi->ref_frame_flags = 0;
} else {
if (lc->current_video_frame_in_layer == 0)
if (lc->current_video_frame_in_layer <
(unsigned int)cpi->svc.number_temporal_layers)
cpi->ref_frame_flags = VP9_GOLD_FLAG;
else
cpi->ref_frame_flags = VP9_LAST_FLAG | VP9_GOLD_FLAG;
......@@ -454,16 +454,17 @@ void vp9_first_pass(VP9_COMP *cpi, const struct lookahead_entry *source) {
// Use either last frame or alt frame for motion search.
if (cpi->ref_frame_flags & VP9_LAST_FLAG) {
scaled_ref_buf = vp9_get_scaled_ref_frame(cpi, LAST_FRAME);
first_ref_buf = vp9_get_scaled_ref_frame(cpi, LAST_FRAME);
ref_frame = LAST_FRAME;
if (first_ref_buf == NULL)
first_ref_buf = get_ref_frame_buffer(cpi, LAST_FRAME);
} else if (cpi->ref_frame_flags & VP9_GOLD_FLAG) {
scaled_ref_buf = vp9_get_scaled_ref_frame(cpi, GOLDEN_FRAME);
first_ref_buf = vp9_get_scaled_ref_frame(cpi, GOLDEN_FRAME);
ref_frame = GOLDEN_FRAME;
if (first_ref_buf == NULL)
first_ref_buf = get_ref_frame_buffer(cpi, GOLDEN_FRAME);
}
if (scaled_ref_buf != NULL)
first_ref_buf = scaled_ref_buf;
recon_y_stride = new_yv12->y_stride;
recon_uv_stride = new_yv12->uv_stride;
uv_mb_height = 16 >> (new_yv12->y_height > new_yv12->uv_height);
......@@ -914,7 +915,7 @@ void vp9_first_pass(VP9_COMP *cpi, const struct lookahead_entry *source) {
++cm->current_video_frame;
if (cpi->use_svc)
vp9_inc_frame_in_layer(&cpi->svc);
vp9_inc_frame_in_layer(cpi);
}
static double calc_correction_factor(double err_per_mb,
......@@ -952,7 +953,7 @@ static int get_twopass_worst_quality(const VP9_COMP *cpi,
BPER_MB_NORMBITS) / num_mbs;
int q;
int is_svc_upper_layer = 0;
if (is_spatial_svc(cpi) && cpi->svc.spatial_layer_id > 0)
if (is_two_pass_svc(cpi) && cpi->svc.spatial_layer_id > 0)
is_svc_upper_layer = 1;
// Try and pick a max Q that will be high enough to encode the
......@@ -980,9 +981,9 @@ extern void vp9_new_framerate(VP9_COMP *cpi, double framerate);
void vp9_init_second_pass(VP9_COMP *cpi) {
SVC *const svc = &cpi->svc;
const VP9EncoderConfig *const oxcf = &cpi->oxcf;
const int is_spatial_svc = (svc->number_spatial_layers > 1) &&
(svc->number_temporal_layers == 1);
TWO_PASS *const twopass = is_spatial_svc ?
const int is_two_pass_svc = (svc->number_spatial_layers > 1) ||
(svc->number_temporal_layers > 1);
TWO_PASS *const twopass = is_two_pass_svc ?
&svc->layer_context[svc->spatial_layer_id].twopass : &cpi->twopass;
double frame_rate;
FIRSTPASS_STATS *stats;
......@@ -1005,7 +1006,7 @@ void vp9_init_second_pass(VP9_COMP *cpi) {
// It is calculated based on the actual durations of all frames from the
// first pass.
if (is_spatial_svc) {
if (is_two_pass_svc) {
vp9_update_spatial_layer_framerate(cpi, frame_rate);
twopass->bits_left = (int64_t)(stats->duration *
svc->layer_context[svc->spatial_layer_id].target_bandwidth /
......@@ -1020,7 +1021,7 @@ void vp9_init_second_pass(VP9_COMP *cpi) {
// scores used in the second pass. We have this minimum to make sure
// that clips that are static but "low complexity" in the intra domain
// are still boosted appropriately for KF/GF/ARF.
if (!is_spatial_svc) {
if (!is_two_pass_svc) {
// We don't know the number of MBs for each layer at this point.
// So we will do it later.
twopass->kf_intra_err_min = KF_MB_INTRA_MIN * cpi->common.MBs;
......@@ -1368,6 +1369,13 @@ static void allocate_gf_group_bits(VP9_COMP *cpi, int64_t gf_group_bits,
int mid_boost_bits = 0;
int mid_frame_idx;
unsigned char arf_buffer_indices[MAX_ACTIVE_ARFS];
int alt_frame_index = frame_index;
int has_temporal_layers = is_two_pass_svc(cpi) &&
cpi->svc.number_temporal_layers > 1;
// Only encode alt reference frame in temporal base layer.
if (has_temporal_layers)
alt_frame_index = cpi->svc.number_temporal_layers;
key_frame = cpi->common.frame_type == KEY_FRAME ||
vp9_is_upper_layer_key_frame(cpi);
......@@ -1403,16 +1411,24 @@ static void allocate_gf_group_bits(VP9_COMP *cpi, int64_t gf_group_bits,
// Store the bits to spend on the ARF if there is one.
if (rc->source_alt_ref_pending) {
gf_group->update_type[frame_index] = ARF_UPDATE;
gf_group->rf_level[frame_index] = GF_ARF_STD;
gf_group->bit_allocation[frame_index] = gf_arf_bits;
gf_group->arf_src_offset[frame_index] =
(unsigned char)(rc->baseline_gf_interval - 1);
gf_group->arf_update_idx[frame_index] = arf_buffer_indices[0];
gf_group->arf_ref_idx[frame_index] =
gf_group->update_type[alt_frame_index] = ARF_UPDATE;
gf_group->rf_level[alt_frame_index] = GF_ARF_STD;
gf_group->bit_allocation[alt_frame_index] = gf_arf_bits;
if (has_temporal_layers)
gf_group->arf_src_offset[alt_frame_index] =
(unsigned char)(rc->baseline_gf_interval -
cpi->svc.number_temporal_layers);
else
gf_group->arf_src_offset[alt_frame_index] =
(unsigned char)(rc->baseline_gf_interval - 1);
gf_group->arf_update_idx[alt_frame_index] = arf_buffer_indices[0];
gf_group->arf_ref_idx[alt_frame_index] =
arf_buffer_indices[cpi->multi_arf_last_grp_enabled &&
rc->source_alt_ref_active];
++frame_index;
if (!has_temporal_layers)
++frame_index;
if (cpi->multi_arf_enabled) {
// Set aside a slot for a level 1 arf.
......@@ -1435,6 +1451,10 @@ static void allocate_gf_group_bits(VP9_COMP *cpi, int64_t gf_group_bits,
if (EOF == input_stats(twopass, &frame_stats))
break;
if (has_temporal_layers && frame_index == alt_frame_index) {
++frame_index;
}
modified_err = calculate_modified_err(twopass, oxcf, &frame_stats);
if (group_error > 0)
......@@ -1656,6 +1676,21 @@ static void define_gf_group(VP9_COMP *cpi, FIRSTPASS_STATS *this_frame) {
else
rc->baseline_gf_interval = i;
// Only encode alt reference frame in temporal base layer. So
// baseline_gf_interval should be multiple of a temporal layer group
// (typically the frame distance between two base layer frames)
if (is_two_pass_svc(cpi) && cpi->svc.number_temporal_layers > 1) {
int count = (1 << (cpi->svc.number_temporal_layers - 1)) - 1;
int new_gf_interval = (rc->baseline_gf_interval + count) & (~count);
int j;
for (j = 0; j < new_gf_interval - rc->baseline_gf_interval; ++j) {
if (EOF == input_stats(twopass, this_frame))
break;
gf_group_err += calculate_modified_err(twopass, oxcf, this_frame);
}
rc->baseline_gf_interval = new_gf_interval;
}
rc->frames_till_gf_update_due = rc->baseline_gf_interval;
// Should we use the alternate reference frame.
......@@ -1928,6 +1963,18 @@ static void find_next_key_frame(VP9_COMP *cpi, FIRSTPASS_STATS *this_frame) {
rc->next_key_frame_forced = 0;
}
if (is_two_pass_svc(cpi) && cpi->svc.number_temporal_layers > 1) {
int count = (1 << (cpi->svc.number_temporal_layers - 1)) - 1;
int new_frame_to_key = (rc->frames_to_key + count) & (~count);
int j;
for (j = 0; j < new_frame_to_key - rc->frames_to_key; ++j) {
if (EOF == input_stats(twopass, this_frame))
break;
kf_group_err += calculate_modified_err(twopass, oxcf, this_frame);
}
rc->frames_to_key = new_frame_to_key;
}
// Special case for the last key frame of the file.
if (twopass->stats_in >= twopass->stats_in_end) {
// Accumulate kf group error.
......@@ -2086,7 +2133,7 @@ void configure_buffer_updates(VP9_COMP *cpi) {
assert(0);
break;
}
if (is_spatial_svc(cpi)) {
if (is_two_pass_svc(cpi)) {
if (cpi->svc.layer_context[cpi->svc.spatial_layer_id].gold_ref_idx < 0)
cpi->refresh_golden_frame = 0;
if (cpi->alt_ref_source == NULL)
......@@ -2105,7 +2152,7 @@ void vp9_rc_get_second_pass_params(VP9_COMP *cpi) {
FIRSTPASS_STATS this_frame_copy;
int target_rate;
LAYER_CONTEXT *const lc = is_spatial_svc(cpi) ?
LAYER_CONTEXT *const lc = is_two_pass_svc(cpi) ?
&cpi->svc.layer_context[cpi->svc.spatial_layer_id] : 0;
if (lc != NULL) {
......@@ -2188,15 +2235,18 @@ void vp9_rc_get_second_pass_params(VP9_COMP *cpi) {
if (lc != NULL) {
if (cpi->svc.spatial_layer_id == 0) {
lc->is_key_frame = (cm->frame_type == KEY_FRAME);
if (lc->is_key_frame)
if (lc->is_key_frame) {
cpi->ref_frame_flags &=
(~VP9_LAST_FLAG & ~VP9_GOLD_FLAG & ~VP9_ALT_FLAG);
lc->frames_from_key_frame = 0;
}
} else {
cm->frame_type = INTER_FRAME;
lc->is_key_frame = cpi->svc.layer_context[0].is_key_frame;
if (lc->is_key_frame) {
cpi->ref_frame_flags &= (~VP9_LAST_FLAG);
lc->frames_from_key_frame = 0;
}
}
}
......
......@@ -1235,7 +1235,7 @@ void vp9_rc_get_svc_params(VP9_COMP *cpi) {
cm->frame_type = KEY_FRAME;
rc->source_alt_ref_active = 0;
if (is_spatial_svc(cpi)) {
if (is_two_pass_svc(cpi)) {
cpi->svc.layer_context[cpi->svc.spatial_layer_id].is_key_frame = 1;
cpi->ref_frame_flags &=
(~VP9_LAST_FLAG & ~VP9_GOLD_FLAG & ~VP9_ALT_FLAG);
......@@ -1247,7 +1247,7 @@ void vp9_rc_get_svc_params(VP9_COMP *cpi) {
} else {
cm->frame_type = INTER_FRAME;
if (is_spatial_svc(cpi)) {
if (is_two_pass_svc(cpi)) {
LAYER_CONTEXT *lc = &cpi->svc.layer_context[cpi->svc.spatial_layer_id];
if (cpi->svc.spatial_layer_id == 0) {
lc->is_key_frame = 0;
......
......@@ -19,12 +19,12 @@ void vp9_init_layer_context(VP9_COMP *const cpi) {
const VP9EncoderConfig *const oxcf = &cpi->oxcf;
int layer;
int layer_end;
int alt_ref_idx = svc->number_spatial_layers;
int alt_ref_idx = svc->number_spatial_layers * svc->number_temporal_layers;
svc->spatial_layer_id = 0;
svc->temporal_layer_id = 0;
if (svc->number_temporal_layers > 1) {
if (svc->number_temporal_layers > 1 && cpi->oxcf.rc_mode == VPX_CBR) {
layer_end = svc->number_temporal_layers;
} else {
layer_end = svc->number_spatial_layers;
......@@ -36,6 +36,7 @@ void vp9_init_layer_context(VP9_COMP *const cpi) {
int i;
lc->current_video_frame_in_layer = 0;
lc->layer_size = 0;
lc->frames_from_key_frame = 0;
lc->last_frame_type = FRAME_TYPES;
lrc->ni_av_qi = oxcf->worst_allowed_q;
lrc->total_actual_bits = 0;
......@@ -51,7 +52,7 @@ void vp9_init_layer_context(VP9_COMP *const cpi) {
lrc->rate_correction_factors[i] = 1.0;
}
if (svc->number_temporal_layers > 1) {
if (svc->number_temporal_layers > 1 && cpi->oxcf.rc_mode == VPX_CBR) {
lc->target_bandwidth = oxcf->ts_target_bitrate[layer];
lrc->last_q[INTER_FRAME] = oxcf->worst_allowed_q;
lrc->avg_frame_qindex[INTER_FRAME] = oxcf->worst_allowed_q;
......@@ -76,7 +77,8 @@ void vp9_init_layer_context(VP9_COMP *const cpi) {
}
// Still have extra buffer for base layer golden frame
if (svc->number_spatial_layers > 1 && alt_ref_idx < REF_FRAMES)
if (!(svc->number_temporal_layers > 1 && cpi->oxcf.rc_mode == VPX_CBR)
&& alt_ref_idx < REF_FRAMES)
svc->layer_context[0].gold_ref_idx = alt_ref_idx;
}
......@@ -90,7 +92,7 @@ void vp9_update_layer_context_change_config(VP9_COMP *const cpi,
int layer_end;
float bitrate_alloc = 1.0;
if (svc->number_temporal_layers > 1) {
if (svc->number_temporal_layers > 1 && cpi->oxcf.rc_mode == VPX_CBR) {
layer_end = svc->number_temporal_layers;
} else {
layer_end = svc->number_spatial_layers;
......@@ -100,7 +102,7 @@ void vp9_update_layer_context_change_config(VP9_COMP *const cpi,
LAYER_CONTEXT *const lc = &svc->layer_context[layer];
RATE_CONTROL *const lrc = &lc->rc;
if (svc->number_temporal_layers > 1) {
if (svc->number_temporal_layers > 1 && cpi->oxcf.rc_mode == VPX_CBR) {
lc->target_bandwidth = oxcf->ts_target_bitrate[layer];
} else {
lc->target_bandwidth = oxcf->ss_target_bitrate[layer];
......@@ -116,7 +118,7 @@ void vp9_update_layer_context_change_config(VP9_COMP *const cpi,
lrc->bits_off_target = MIN(lrc->bits_off_target, lrc->maximum_buffer_size);
lrc->buffer_level = MIN(lrc->buffer_level, lrc->maximum_buffer_size);
// Update framerate-related quantities.
if (svc->number_temporal_layers > 1) {
if (svc->number_temporal_layers > 1 && cpi->oxcf.rc_mode == VPX_CBR) {
lc->framerate = cpi->framerate / oxcf->ts_rate_decimator[layer];
} else {
lc->framerate = cpi->framerate;
......@@ -129,16 +131,16 @@ void vp9_update_layer_context_change_config(VP9_COMP *const cpi,
}
}
static LAYER_CONTEXT *get_layer_context(SVC *svc) {
return svc->number_temporal_layers > 1 ?
&svc->layer_context[svc->temporal_layer_id] :
&svc->layer_context[svc->spatial_layer_id];
static LAYER_CONTEXT *get_layer_context(VP9_COMP *const cpi) {
return (cpi->svc.number_temporal_layers > 1 && cpi->oxcf.rc_mode == VPX_CBR) ?
&cpi->svc.layer_context[cpi->svc.temporal_layer_id] :
&cpi->svc.layer_context[cpi->svc.spatial_layer_id];
}
void vp9_update_temporal_layer_framerate(VP9_COMP *const cpi) {
SVC *const svc = &cpi->svc;
const VP9EncoderConfig *const oxcf = &cpi->oxcf;
LAYER_CONTEXT *const lc = get_layer_context(svc);
LAYER_CONTEXT *const lc = get_layer_context(cpi);
RATE_CONTROL *const lrc = &lc->rc;
const int layer = svc->temporal_layer_id;
......@@ -160,7 +162,7 @@ void vp9_update_temporal_layer_framerate(VP9_COMP *const cpi) {
void vp9_update_spatial_layer_framerate(VP9_COMP *const cpi, double framerate) {
const VP9EncoderConfig *const oxcf = &cpi->oxcf;
LAYER_CONTEXT *const lc = get_layer_context(&cpi->svc);
LAYER_CONTEXT *const lc = get_layer_context(cpi);
RATE_CONTROL *const lrc = &lc->rc;
lc->framerate = framerate;
......@@ -173,7 +175,7 @@ void vp9_update_spatial_layer_framerate(VP9_COMP *const cpi, double framerate) {
}
void vp9_restore_layer_context(VP9_COMP *const cpi) {
LAYER_CONTEXT *const lc = get_layer_context(&cpi->svc);
LAYER_CONTEXT *const lc = get_layer_context(cpi);
const int old_frame_since_key = cpi->rc.frames_since_key;
const int old_frame_to_key = cpi->rc.frames_to_key;
......@@ -191,7 +193,7 @@ void vp9_restore_layer_context(VP9_COMP *const cpi) {
void vp9_save_layer_context(VP9_COMP *const cpi) {
const VP9EncoderConfig *const oxcf = &cpi->oxcf;
LAYER_CONTEXT *const lc = get_layer_context(&cpi->svc);
LAYER_CONTEXT *const lc = get_layer_context(cpi);
lc->rc = cpi->rc;
lc->twopass = cpi->twopass;
......@@ -215,15 +217,17 @@ void vp9_init_second_pass_spatial_svc(VP9_COMP *cpi) {
svc->spatial_layer_id = 0;
}