summaryrefslogtreecommitdiff
path: root/vp9/encoder
diff options
context:
space:
mode:
authorMinghai Shang <minghai@google.com>2014-05-01 10:53:47 -0700
committerGerrit Code Review <gerrit@gerrit.golo.chromium.org>2014-05-01 10:53:47 -0700
commit528a5c28b313fbcc7da6264f7151d26a610ddcfd (patch)
treec981455db5f05fc5b539214823561c969defcd69 /vp9/encoder
parent1d29ce53fe75cf03481f6044caa2b1cbbfc08c92 (diff)
parentf916a3e256bc0e54852b48ec741c594aa58e2f26 (diff)
downloadlibvpx-528a5c28b313fbcc7da6264f7151d26a610ddcfd.tar
libvpx-528a5c28b313fbcc7da6264f7151d26a610ddcfd.tar.gz
libvpx-528a5c28b313fbcc7da6264f7151d26a610ddcfd.tar.bz2
libvpx-528a5c28b313fbcc7da6264f7151d26a610ddcfd.zip
Merge "[svc rc] RC improvement for key frames in upper layers for spatial svc."
Diffstat (limited to 'vp9/encoder')
-rw-r--r--vp9/encoder/vp9_encoder.h3
-rw-r--r--vp9/encoder/vp9_firstpass.c21
-rw-r--r--vp9/encoder/vp9_ratectrl.c5
-rw-r--r--vp9/encoder/vp9_svc_layercontext.c13
-rw-r--r--vp9/encoder/vp9_svc_layercontext.h4
5 files changed, 36 insertions, 10 deletions
diff --git a/vp9/encoder/vp9_encoder.h b/vp9/encoder/vp9_encoder.h
index 132b479e2..edd45948d 100644
--- a/vp9/encoder/vp9_encoder.h
+++ b/vp9/encoder/vp9_encoder.h
@@ -594,7 +594,8 @@ static INLINE YV12_BUFFER_CONFIG *get_ref_frame_buffer(
// alt ref frames tend to be coded at a higher than ambient quality
static INLINE int frame_is_boosted(const VP9_COMP *cpi) {
return frame_is_intra_only(&cpi->common) || cpi->refresh_alt_ref_frame ||
- (cpi->refresh_golden_frame && !cpi->rc.is_src_frame_alt_ref);
+ (cpi->refresh_golden_frame && !cpi->rc.is_src_frame_alt_ref) ||
+ vp9_is_upper_layer_key_frame(cpi);
}
static INLINE int get_token_alloc(int mb_rows, int mb_cols) {
diff --git a/vp9/encoder/vp9_firstpass.c b/vp9/encoder/vp9_firstpass.c
index bd6984161..1f995c9e7 100644
--- a/vp9/encoder/vp9_firstpass.c
+++ b/vp9/encoder/vp9_firstpass.c
@@ -1740,8 +1740,8 @@ static void define_gf_group(VP9_COMP *cpi, FIRSTPASS_STATS *this_frame) {
twopass->gf_bits = gf_bits;
}
if (i == 1 ||
- (!rc->source_alt_ref_pending &&
- cpi->common.frame_type != KEY_FRAME)) {
+ (!rc->source_alt_ref_pending && cpi->common.frame_type != KEY_FRAME &&
+ !vp9_is_upper_layer_key_frame(cpi))) {
// Calculate the per frame bit target for this frame.
vp9_rc_set_frame_target(cpi, gf_bits);
}
@@ -2303,11 +2303,16 @@ void vp9_rc_get_second_pass_params(VP9_COMP *cpi) {
this_frame_copy = this_frame;
find_next_key_frame(cpi, &this_frame_copy);
// Don't place key frame in any enhancement layers in spatial svc
- if (cpi->use_svc && cpi->svc.number_temporal_layers == 1 &&
- cpi->svc.spatial_layer_id > 0) {
- cm->frame_type = INTER_FRAME;
+ if (cpi->use_svc && cpi->svc.number_temporal_layers == 1) {
+ lc->is_key_frame = 1;
+ if (cpi->svc.spatial_layer_id > 0) {
+ cm->frame_type = INTER_FRAME;
+ }
}
} else {
+ if (cpi->use_svc && cpi->svc.number_temporal_layers == 1) {
+ lc->is_key_frame = 0;
+ }
cm->frame_type = INTER_FRAME;
}
@@ -2405,9 +2410,11 @@ void vp9_twopass_postencode_update(VP9_COMP *cpi) {
cpi->twopass.bits_left = MAX(cpi->twopass.bits_left, 0);
#ifdef LONG_TERM_VBR_CORRECTION
- if (cpi->common.frame_type != KEY_FRAME) {
+ if (cpi->common.frame_type != KEY_FRAME &&
+ !vp9_is_upper_layer_key_frame(cpi)) {
#else
- if (cpi->common.frame_type == KEY_FRAME) {
+ if (cpi->common.frame_type == KEY_FRAME ||
+ vp9_is_upper_layer_key_frame(cpi)) {
// For key frames kf_group_bits already had the target bits subtracted out.
// So now update to the correct value based on the actual bits used.
cpi->twopass.kf_group_bits += cpi->rc.this_frame_target - bits_used;
diff --git a/vp9/encoder/vp9_ratectrl.c b/vp9/encoder/vp9_ratectrl.c
index 6ebd9f3fa..b123bfdcb 100644
--- a/vp9/encoder/vp9_ratectrl.c
+++ b/vp9/encoder/vp9_ratectrl.c
@@ -807,7 +807,7 @@ static int rc_pick_q_and_bounds_two_pass(const VP9_COMP *cpi,
int active_worst_quality = cpi->twopass.active_worst_quality;
int q;
- if (frame_is_intra_only(cm)) {
+ if (frame_is_intra_only(cm) || vp9_is_upper_layer_key_frame(cpi)) {
#if !CONFIG_MULTIPLE_ARF
// Handle the special case for key frames forced when we have75 reached
// the maximum key frame interval. Here force the Q to a range
@@ -928,7 +928,8 @@ static int rc_pick_q_and_bounds_two_pass(const VP9_COMP *cpi,
vp9_clear_system_state();
// Limit Q range for the adaptive loop.
- if (cm->frame_type == KEY_FRAME && !rc->this_key_frame_forced) {
+ if ((cm->frame_type == KEY_FRAME || vp9_is_upper_layer_key_frame(cpi)) &&
+ !rc->this_key_frame_forced) {
qdelta = vp9_compute_qdelta_by_rate(&cpi->rc, cm->frame_type,
active_worst_quality, 2.0);
} else if (!rc->is_src_frame_alt_ref &&
diff --git a/vp9/encoder/vp9_svc_layercontext.c b/vp9/encoder/vp9_svc_layercontext.c
index 2379f35b5..5342447d6 100644
--- a/vp9/encoder/vp9_svc_layercontext.c
+++ b/vp9/encoder/vp9_svc_layercontext.c
@@ -220,3 +220,16 @@ void vp9_inc_frame_in_layer(SVC *svc) {
: &svc->layer_context[svc->spatial_layer_id];
++lc->current_video_frame_in_layer;
}
+
+int vp9_is_upper_layer_key_frame(const struct VP9_COMP *const cpi) {
+ int is_upper_layer_key_frame = 0;
+
+ if (cpi->use_svc && cpi->svc.number_temporal_layers == 1 &&
+ cpi->svc.spatial_layer_id > 0) {
+ if (cpi->svc.layer_context[cpi->svc.spatial_layer_id].is_key_frame) {
+ is_upper_layer_key_frame = 1;
+ }
+ }
+
+ return is_upper_layer_key_frame;
+}
diff --git a/vp9/encoder/vp9_svc_layercontext.h b/vp9/encoder/vp9_svc_layercontext.h
index 2abed3055..74d9c1c0d 100644
--- a/vp9/encoder/vp9_svc_layercontext.h
+++ b/vp9/encoder/vp9_svc_layercontext.h
@@ -30,6 +30,7 @@ typedef struct {
struct twopass_rc twopass;
struct vpx_fixed_buf rc_twopass_stats_in;
unsigned int current_video_frame_in_layer;
+ int is_key_frame;
} LAYER_CONTEXT;
typedef struct {
@@ -73,6 +74,9 @@ void vp9_init_second_pass_spatial_svc(struct VP9_COMP *cpi);
// Increment number of video frames in layer
void vp9_inc_frame_in_layer(SVC *svc);
+// Check if current layer is key frame in spatial upper layer
+int vp9_is_upper_layer_key_frame(const struct VP9_COMP *const cpi);
+
#ifdef __cplusplus
} // extern "C"
#endif