Fix setting QP when rate control is disabled.

When rate control is disabled, QP and lambda are now selected like they
were before rate control was implemented.
This commit is contained in:
Arttu Ylä-Outinen 2015-05-29 14:00:51 +03:00
parent b0435d37a9
commit 984e7cb4e0
5 changed files with 63 additions and 20 deletions

View file

@ -537,35 +537,35 @@ static int config_parse(config_t *cfg, const char *name, const char *value)
if(atoi(value) == 8) {
// GOP
cfg->gop_len = 8;
cfg->gop[0].poc_offset = 8; cfg->gop[0].layer = 1; cfg->gop[0].is_ref = 1;
cfg->gop[0].poc_offset = 8; cfg->gop[0].qp_offset = 1; cfg->gop[0].layer = 1; cfg->gop[0].qp_factor = 0.442; cfg->gop[0].is_ref = 1;
cfg->gop[0].ref_pos_count = 0;
cfg->gop[0].ref_neg_count = 3; cfg->gop[0].ref_neg[0] = 8; cfg->gop[0].ref_neg[1] = 12; cfg->gop[0].ref_neg[2] = 16;
cfg->gop[1].poc_offset = 4; cfg->gop[1].layer = 2; cfg->gop[1].is_ref = 1;
cfg->gop[1].poc_offset = 4; cfg->gop[1].qp_offset = 2; cfg->gop[1].layer = 2; cfg->gop[1].qp_factor = 0.3536; cfg->gop[1].is_ref = 1;
cfg->gop[1].ref_neg_count = 2; cfg->gop[1].ref_neg[0] = 4; cfg->gop[1].ref_neg[1] = 8;
cfg->gop[1].ref_pos_count = 1; cfg->gop[1].ref_pos[0] = 4;
cfg->gop[2].poc_offset = 2; cfg->gop[2].layer = 3; cfg->gop[2].is_ref = 1;
cfg->gop[2].poc_offset = 2; cfg->gop[2].qp_offset = 3; cfg->gop[2].layer = 3; cfg->gop[2].qp_factor = 0.3536; cfg->gop[2].is_ref = 1;
cfg->gop[2].ref_neg_count = 2; cfg->gop[2].ref_neg[0] = 2; cfg->gop[2].ref_neg[1] = 6;
cfg->gop[2].ref_pos_count = 2; cfg->gop[2].ref_pos[0] = 2; cfg->gop[2].ref_pos[1] = 6;
cfg->gop[3].poc_offset = 1; cfg->gop[3].layer = 4; cfg->gop[3].is_ref = 0;
cfg->gop[3].poc_offset = 1; cfg->gop[3].qp_offset = 4; cfg->gop[3].layer = 4; cfg->gop[3].qp_factor = 0.68; cfg->gop[3].is_ref = 0;
cfg->gop[3].ref_neg_count = 1; cfg->gop[3].ref_neg[0] = 1;
cfg->gop[3].ref_pos_count = 3; cfg->gop[3].ref_pos[0] = 1; cfg->gop[3].ref_pos[1] = 3; cfg->gop[3].ref_pos[2] = 7;
cfg->gop[4].poc_offset = 3; cfg->gop[4].layer = 4; cfg->gop[4].is_ref = 0;
cfg->gop[4].poc_offset = 3; cfg->gop[4].qp_offset = 4; cfg->gop[4].layer = 4; cfg->gop[4].qp_factor = 0.68; cfg->gop[4].is_ref = 0;
cfg->gop[4].ref_neg_count = 2; cfg->gop[4].ref_neg[0] = 1; cfg->gop[4].ref_neg[1] = 3;
cfg->gop[4].ref_pos_count = 2; cfg->gop[4].ref_pos[0] = 1; cfg->gop[4].ref_pos[1] = 5;
cfg->gop[5].poc_offset = 6; cfg->gop[5].layer = 3; cfg->gop[5].is_ref = 1;
cfg->gop[5].poc_offset = 6; cfg->gop[5].qp_offset = 3; cfg->gop[5].layer = 3; cfg->gop[5].qp_factor = 0.3536; cfg->gop[5].is_ref = 1;
cfg->gop[5].ref_neg_count = 2; cfg->gop[5].ref_neg[0] = 2; cfg->gop[5].ref_neg[1] = 6;
cfg->gop[5].ref_pos_count = 1; cfg->gop[5].ref_pos[0] = 2;
cfg->gop[6].poc_offset = 5; cfg->gop[6].layer = 4; cfg->gop[6].is_ref = 0;
cfg->gop[6].poc_offset = 5; cfg->gop[6].qp_offset = 4; cfg->gop[6].layer = 4; cfg->gop[6].qp_factor = 0.68; cfg->gop[6].is_ref = 0;
cfg->gop[6].ref_neg_count = 2; cfg->gop[6].ref_neg[0] = 1; cfg->gop[6].ref_neg[1] = 5;
cfg->gop[6].ref_pos_count = 2; cfg->gop[6].ref_pos[0] = 1; cfg->gop[6].ref_pos[1] = 3;
cfg->gop[7].poc_offset = 7; cfg->gop[7].layer = 4; cfg->gop[7].is_ref = 0;
cfg->gop[7].poc_offset = 7; cfg->gop[7].qp_offset = 4; cfg->gop[7].layer = 4; cfg->gop[7].qp_factor = 0.68; cfg->gop[7].is_ref = 0;
cfg->gop[7].ref_neg_count = 3; cfg->gop[7].ref_neg[0] = 1; cfg->gop[7].ref_neg[1] = 3; cfg->gop[7].ref_neg[2] = 7;
cfg->gop[7].ref_pos_count = 1; cfg->gop[7].ref_pos[0] = 1;
} else if(atoi(value)) {

View file

@ -29,6 +29,8 @@
typedef struct {
double qp_factor;
int8_t qp_offset; /*!< \brief QP offset */
int8_t poc_offset; /*!< \brief POC offset */
int8_t layer; /*!< \brief Current layer */
int8_t is_ref; /*!< \brief Flag if this picture is used as a reference */

View file

@ -45,10 +45,6 @@
#include "rdo.h"
#include "rate_control.h"
#ifndef LMBD
# define LMBD 1.0
#endif
int encoder_state_match_children_of_previous_frame(encoder_state_t * const state) {
int i;
for (i = 0; state->children[i].encoder_control; ++i) {
@ -771,10 +767,24 @@ static void encoder_state_new_frame(encoder_state_t * const state) {
encoder_state_ref_sort(state);
}
double lambda = select_picture_lambda(state);
double lambda;
if (encoder->cfg->target_bitrate > 0) {
// Rate control enabled.
lambda = select_picture_lambda(state);
state->global->QP = lambda_to_QP(lambda);
} else {
if (encoder->cfg->gop_len > 0 && state->global->slicetype != SLICE_I) {
gop_config_t const * const gop =
encoder->cfg->gop + state->global->gop_offset;
state->global->QP = encoder->cfg->qp + gop->qp_offset;
state->global->QP_factor = gop->qp_factor;
} else {
state->global->QP = encoder->cfg->qp;
}
lambda = select_picture_lambda_from_qp(state);
}
state->global->cur_lambda_cost = lambda;
state->global->cur_lambda_cost_sqrt = sqrt(lambda);
state->global->QP = lambda_to_QP(lambda);
} else {
//Clear the bitstream if it's not the main encoder

View file

@ -108,22 +108,23 @@ static double pic_allocate_bits(const encoder_state_t * const state)
* \brief Select a lambda value for encoding the next picture
* \param state the main encoder state
* \return lambda for the next picture
*
* Rate control must be enabled (i.e. cfg->target_bitrate > 0) when this
* function is called.
*/
double select_picture_lambda(encoder_state_t * const state)
{
const encoder_control_t * const encoder = state->encoder_control;
if (encoder->cfg->target_bitrate <= 0) {
// Rate control disabled.
return exp((encoder->cfg->qp - 13.7223 - 0.5) / 4.2005);
}
assert(encoder->cfg->target_bitrate > 0);
if (state->global->frame > encoder->cfg->owf) {
// At least one frame has been written.
update_rc_parameters(state);
}
if (encoder->cfg->gop_len == 0 || state->global->gop_offset == 0) {
// a new GOP begins at this frame
// A new GOP begins at this frame.
gop_allocate_bits(state);
} else {
state->global->cur_gop_target_bits =
@ -141,6 +142,34 @@ double select_picture_lambda(encoder_state_t * const state)
int8_t lambda_to_QP(const double lambda)
{
int8_t qp = 4.2005 * log(lambda) + 13.7223 + 0.5;
const int8_t qp = 4.2005 * log(lambda) + 13.7223 + 0.5;
return CLIP(0, 51, qp);
}
/**
* \brief Select a lambda value according to current QP value
* \param state the main encoder state
* \return lambda for the next picture
*
* This function should be used to select lambda when rate control is
* disabled.
*/
double select_picture_lambda_from_qp(encoder_state_t const * const state)
{
const int gop_len = state->encoder_control->cfg->gop_len;
const double qp_temp = state->global->QP - 12;
double qp_factor;
if (state->global->slicetype == SLICE_I) {
const double lambda_scale = 1.0 - CLIP(0.0, 0.5, 0.05 * gop_len);
qp_factor = 0.57 * lambda_scale;
} else if (gop_len > 0) {
qp_factor = 0.95 * state->global->QP_factor;
} else {
// default QP factor from HM config
qp_factor = 0.95 * 0.4624;
}
const double lambda = qp_factor * pow(2.0, qp_temp / 3.0);
return lambda;
}

View file

@ -31,4 +31,6 @@ double select_picture_lambda(encoder_state_t * const state);
int8_t lambda_to_QP(const double lambda);
double select_picture_lambda_from_qp(encoder_state_t const * const state);
#endif // RATE_CONTROL_H_