summaryrefslogtreecommitdiff
path: root/vp9/encoder/vp9_firstpass.c
diff options
context:
space:
mode:
authorMinghai Shang <minghai@google.com>2014-09-02 12:05:14 -0700
committerMinghai Shang <minghai@google.com>2014-09-02 12:05:14 -0700
commitbe3b08da3e0ee44d7c52fa3aa883b351d969c1cc (patch)
tree770b5f81d86b03c59b2abe95a23d3f2409ef28cb /vp9/encoder/vp9_firstpass.c
parent6b649a0db9727f3dd1d77af7046ecf3b31e18099 (diff)
downloadlibvpx-be3b08da3e0ee44d7c52fa3aa883b351d969c1cc.tar
libvpx-be3b08da3e0ee44d7c52fa3aa883b351d969c1cc.tar.gz
libvpx-be3b08da3e0ee44d7c52fa3aa883b351d969c1cc.tar.bz2
libvpx-be3b08da3e0ee44d7c52fa3aa883b351d969c1cc.zip
[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
Diffstat (limited to 'vp9/encoder/vp9_firstpass.c')
-rw-r--r--vp9/encoder/vp9_firstpass.c106
1 files changed, 78 insertions, 28 deletions
diff --git a/vp9/encoder/vp9_firstpass.c b/vp9/encoder/vp9_firstpass.c
index c2c2d284c..8041b59cf 100644
--- a/vp9/encoder/vp9_firstpass.c
+++ b/vp9/encoder/vp9_firstpass.c
@@ -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;
}
}
}