summaryrefslogtreecommitdiff
path: root/vp8
diff options
context:
space:
mode:
authorPaul Wilkins <paulwilkins@google.com>2011-01-17 17:23:11 +0000
committerPaul Wilkins <paulwilkins@google.com>2011-01-17 17:24:45 +0000
commit339c512762542995d51086e1990cf47967687bb5 (patch)
tree514829fd5844f3e851163a3715c1dfa28c7a0ac9 /vp8
parenta1a4d23797b2537f986859c57a73fa9330fa0ed5 (diff)
downloadlibvpx-339c512762542995d51086e1990cf47967687bb5.tar
libvpx-339c512762542995d51086e1990cf47967687bb5.tar.gz
libvpx-339c512762542995d51086e1990cf47967687bb5.tar.bz2
libvpx-339c512762542995d51086e1990cf47967687bb5.zip
Fix CQ range and experimental KF sizing changes.
The CQ level was not using the q_trans[] array to convert to a 0-127 range as per min and maxq Experimental change to try and match the reconstruction error for forced key frames approximately to that of the previous frame by means of the recode loop. Though this may cause extra recodes and the recode behavior has not been optimized, it can only happen on forced key frames. Change-Id: I1f7e42d526f1b1cb556dd461eff1a692bd1b5b2f
Diffstat (limited to 'vp8')
-rw-r--r--vp8/encoder/onyx_if.c97
-rw-r--r--vp8/encoder/onyx_int.h3
-rw-r--r--vp8/vp8_cx_iface.c2
3 files changed, 75 insertions, 27 deletions
diff --git a/vp8/encoder/onyx_if.c b/vp8/encoder/onyx_if.c
index e0d1d7043..47fc3f78e 100644
--- a/vp8/encoder/onyx_if.c
+++ b/vp8/encoder/onyx_if.c
@@ -1551,6 +1551,7 @@ void vp8_init_config(VP8_PTR ptr, VP8_CONFIG *oxcf)
cpi->auto_worst_q = 0;
cpi->oxcf.best_allowed_q = MINQ;
cpi->oxcf.worst_allowed_q = MAXQ;
+ cpi->oxcf.cq_level = MINQ;
cpi->oxcf.end_usage = USAGE_STREAM_FROM_SERVER;
cpi->oxcf.starting_buffer_level = 4000;
@@ -1651,6 +1652,7 @@ void vp8_init_config(VP8_PTR ptr, VP8_CONFIG *oxcf)
cpi->oxcf.worst_allowed_q = q_trans[oxcf->worst_allowed_q];
cpi->oxcf.best_allowed_q = q_trans[oxcf->best_allowed_q];
+ cpi->oxcf.cq_level = q_trans[cpi->oxcf.cq_level];
if (oxcf->fixed_q >= 0)
{
@@ -1740,6 +1742,8 @@ void vp8_init_config(VP8_PTR ptr, VP8_CONFIG *oxcf)
cpi->avg_frame_qindex = cpi->oxcf.worst_allowed_q;
cpi->best_quality = cpi->oxcf.best_allowed_q;
cpi->active_best_quality = cpi->oxcf.best_allowed_q;
+ cpi->cq_target_quality = cpi->oxcf.cq_level;
+
cpi->buffered_mode = (cpi->oxcf.optimal_buffer_level > 0) ? TRUE : FALSE;
cpi->rolling_target_bits = cpi->av_per_frame_bandwidth;
@@ -1936,6 +1940,7 @@ void vp8_change_config(VP8_PTR ptr, VP8_CONFIG *oxcf)
cpi->oxcf.worst_allowed_q = q_trans[oxcf->worst_allowed_q];
cpi->oxcf.best_allowed_q = q_trans[oxcf->best_allowed_q];
+ cpi->oxcf.cq_level = q_trans[cpi->oxcf.cq_level];
if (oxcf->fixed_q >= 0)
{
@@ -2028,7 +2033,6 @@ void vp8_change_config(VP8_PTR ptr, VP8_CONFIG *oxcf)
cpi->active_best_quality = cpi->oxcf.best_allowed_q;
cpi->buffered_mode = (cpi->oxcf.optimal_buffer_level > 0) ? TRUE : FALSE;
- // Experimental cq target value
cpi->cq_target_quality = cpi->oxcf.cq_level;
cpi->rolling_target_bits = cpi->av_per_frame_bandwidth;
@@ -3817,29 +3821,28 @@ static void encode_frame_to_data_rate
if ( cm->frame_type == KEY_FRAME )
{
- // Special case for key frames forced because we have reached
- // the maximum key frame interval. Here force the Q to a range
- // close to but just below the ambient Q to minimize the risk
- // of popping
- if ( cpi->this_key_frame_forced )
- {
- cpi->active_worst_quality = cpi->avg_frame_qindex * 7/8;
- cpi->active_best_quality = cpi->avg_frame_qindex * 2/3;
- }
- else
+ if ( cpi->pass == 2 )
{
- if ( cpi->pass == 2 )
- {
- if (cpi->gfu_boost > 600)
- cpi->active_best_quality = kf_low_motion_minq[Q];
- else
- cpi->active_best_quality = kf_high_motion_minq[Q];
- }
- // One pass more conservative
- else
+ if (cpi->gfu_boost > 600)
+ cpi->active_best_quality = kf_low_motion_minq[Q];
+ else
cpi->active_best_quality = kf_high_motion_minq[Q];
+
+ // Special case for key frames forced because we have reached
+ // the maximum key frame interval. Here force the Q to a range
+ // based on the ambient Q to reduce the risk of popping
+ if ( cpi->this_key_frame_forced )
+ {
+ if ( cpi->active_best_quality > cpi->avg_frame_qindex * 7/8)
+ cpi->active_best_quality = cpi->avg_frame_qindex * 7/8;
+ else if ( cpi->active_best_quality < cpi->avg_frame_qindex >> 2 )
+ cpi->active_best_quality = cpi->avg_frame_qindex >> 2;
+ }
}
- }
+ // One pass more conservative
+ else
+ cpi->active_best_quality = kf_high_motion_minq[Q];
+ }
else if (cm->refresh_golden_frame || cpi->common.refresh_alt_ref_frame)
{
@@ -4153,9 +4156,44 @@ static void encode_frame_to_data_rate
active_worst_qchanged = FALSE;
#if !(CONFIG_REALTIME_ONLY)
+ // Special case handling for forced key frames
+ if ( (cm->frame_type == KEY_FRAME) && cpi->this_key_frame_forced )
+ {
+ int last_q = Q;
+ int kf_err = vp8_calc_ss_err(cpi->Source,
+ &cm->yv12_fb[cm->new_fb_idx],
+ IF_RTCD(&cpi->rtcd.variance));
+
+ // The key frame is not good enough
+ if ( kf_err > ((cpi->ambient_err * 3) >> 2) )
+ {
+ // Lower q_high
+ q_high = (Q > q_low) ? (Q - 1) : q_low;
+
+ // Adjust Q
+ Q = (q_high + q_low) >> 1;
+ }
+ // The key frame is much better than the previous frame
+ else if ( kf_err < (cpi->ambient_err >> 1) )
+ {
+ // Raise q_low
+ q_low = (Q < q_high) ? (Q + 1) : q_high;
+
+ // Adjust Q
+ Q = (q_high + q_low + 1) >> 1;
+ }
+
+ // Clamp Q to upper and lower limits:
+ if (Q > q_high)
+ Q = q_high;
+ else if (Q < q_low)
+ Q = q_low;
+
+ Loop = ((Q != last_q)) ? TRUE : FALSE;
+ }
// Is the projected frame size out of range and are we allowed to attempt to recode.
- if ( recode_loop_test( cpi,
+ else if ( recode_loop_test( cpi,
frame_over_shoot_limit, frame_under_shoot_limit,
Q, top_index, bottom_index ) )
{
@@ -4171,7 +4209,7 @@ static void encode_frame_to_data_rate
//if ( cpi->zbin_over_quant == 0 )
q_low = (Q < q_high) ? (Q + 1) : q_high; // Raise Qlow as to at least the current value
- if (cpi->zbin_over_quant > 0) // If we are using over quant do the same for zbin_oq_low
+ if (cpi->zbin_over_quant > 0) // If we are using over quant do the same for zbin_oq_low
zbin_oq_low = (cpi->zbin_over_quant < zbin_oq_high) ? (cpi->zbin_over_quant + 1) : zbin_oq_high;
//if ( undershoot_seen || (Q == MAXQ) )
@@ -4314,6 +4352,16 @@ static void encode_frame_to_data_rate
}
#endif
+ // Special case code to reduce pulsing when key frames are forced at a
+ // fixed interval. Note the reconstruction error if it is the frame before
+ // the force key frame
+ if ( cpi->next_key_frame_forced && (cpi->frames_to_key == 0) )
+ {
+ cpi->ambient_err = vp8_calc_ss_err(cpi->Source,
+ &cm->yv12_fb[cm->new_fb_idx],
+ IF_RTCD(&cpi->rtcd.variance));
+ }
+
// Update the GF useage maps.
// This is done after completing the compression of a frame when all modes etc. are finalized but before loop filter
vp8_update_gf_useage_maps(cpi, cm, &cpi->mb);
@@ -4343,7 +4391,6 @@ static void encode_frame_to_data_rate
}
}
-
// Update the GF useage maps.
// This is done after completing the compression of a frame when all modes etc. are finalized but before loop filter
vp8_update_gf_useage_maps(cpi, cm, &cpi->mb);
@@ -4374,8 +4421,6 @@ static void encode_frame_to_data_rate
else
cm->frame_to_show = &cm->yv12_fb[cm->new_fb_idx];
-
-
//#pragma omp parallel sections
{
diff --git a/vp8/encoder/onyx_int.h b/vp8/encoder/onyx_int.h
index 6b07e2f22..45fafd5b6 100644
--- a/vp8/encoder/onyx_int.h
+++ b/vp8/encoder/onyx_int.h
@@ -320,6 +320,9 @@ typedef struct
unsigned int this_key_frame_forced;
unsigned int next_key_frame_forced;
+ // Ambient reconstruction err target for force key frames
+ int ambient_err;
+
unsigned int mode_check_freq[MAX_MODES];
unsigned int mode_test_hit_counts[MAX_MODES];
unsigned int mode_chosen_counts[MAX_MODES];
diff --git a/vp8/vp8_cx_iface.c b/vp8/vp8_cx_iface.c
index 4c7aca520..1c9009a57 100644
--- a/vp8/vp8_cx_iface.c
+++ b/vp8/vp8_cx_iface.c
@@ -310,6 +310,7 @@ static vpx_codec_err_t set_vp8e_config(VP8_CONFIG *oxcf,
oxcf->best_allowed_q = cfg.rc_min_quantizer;
oxcf->worst_allowed_q = cfg.rc_max_quantizer;
+ oxcf->cq_level = vp8_cfg.cq_level;
oxcf->fixed_q = -1;
oxcf->under_shoot_pct = cfg.rc_undershoot_pct;
@@ -346,7 +347,6 @@ static vpx_codec_err_t set_vp8e_config(VP8_CONFIG *oxcf,
oxcf->arnr_type = vp8_cfg.arnr_type;
oxcf->tuning = vp8_cfg.tuning;
- oxcf->cq_level = vp8_cfg.cq_level;
/*
printf("Current VP8 Settings: \n");