Better lambda cost implementation (from HM12)

- Lambda array changed to double as in HM
 - Needs updating when GOP / B-pictures are used
This commit is contained in:
Marko Viitanen 2014-02-05 15:57:16 +02:00
parent 2438386f4b
commit 337a565232
4 changed files with 34 additions and 21 deletions

View file

@ -68,7 +68,7 @@ unsigned render_cu_file(encoder_control *encoder, picture *pic,
{ {
cu_info *cu = &pic->cu_array[depth][xCtb + yCtb * (pic->width_in_lcu<<MAX_DEPTH)]; cu_info *cu = &pic->cu_array[depth][xCtb + yCtb * (pic->width_in_lcu<<MAX_DEPTH)];
cu_info *final_cu = &pic->cu_array[MAX_DEPTH][xCtb + yCtb * (pic->width_in_lcu<<MAX_DEPTH)]; cu_info *final_cu = &pic->cu_array[MAX_DEPTH][xCtb + yCtb * (pic->width_in_lcu<<MAX_DEPTH)];
unsigned lambda_cost = (4 * g_lambda_cost[encoder->QP]) << 4; unsigned lambda_cost = (4 * g_lambda_cost[encoder->QP]);
unsigned sum = 0; unsigned sum = 0;
unsigned best_cost = -1; unsigned best_cost = -1;
char type = cu->type == CU_INTRA ? 'I' : 'P'; char type = cu->type == CU_INTRA ? 'I' : 'P';

View file

@ -42,7 +42,7 @@
#include "sao.h" #include "sao.h"
#include "rdo.h" #include "rdo.h"
int16_t g_lambda_cost[55]; double g_lambda_cost[55];
uint32_t* g_sig_last_scan[3][7]; uint32_t* g_sig_last_scan[3][7];
/* Local functions. */ /* Local functions. */
@ -179,6 +179,7 @@ void init_tables(void)
{ {
int i; int i;
int c = 0; int c = 0;
memset( g_convert_to_bit,-1, sizeof( g_convert_to_bit ) ); memset( g_convert_to_bit,-1, sizeof( g_convert_to_bit ) );
for (i = 4; i < (1 << 7); i *= 2) { for (i = 4; i < (1 << 7); i *= 2) {
@ -199,27 +200,35 @@ void init_tables(void)
c <<= 1; c <<= 1;
} }
// Lambda cost }
// TODO: cleanup
for (i = 0; i < 55; i++) {
// Force minimum lambda cost of 1 /*!
if (i < 15) { \brief Initializes lambda-value for current QP
g_lambda_cost[i] = 1;
} else { Implementation closer to HM (Used HM12 as reference)
g_lambda_cost[i] = (int16_t)sqrt(0.57 * pow(2.0, (i - 12) / 3)); - Still missing functionality when GOP and B-pictures are used
*/
void init_lambda(encoder_control *encoder)
{
double qp = encoder->QP;
double lambda_scale = 1.0;
double qp_temp = qp - 12;
double lambda;
// Default QP-factor from HM config
double qp_factor = 0.4624;
if (encoder->in.cur_pic->slicetype == SLICE_I) {
qp_factor=0.57*lambda_scale;
} }
/** lambda = qp_factor*pow( 2.0, qp_temp/3.0 );
* While working on RDOQ it was clear that the current lambda cost is wrong (compared to HM)
* so the cost is now lambda*lambda to fix some of those issues. if (encoder->in.cur_pic->slicetype != SLICE_I ) {
* This is not the final solution and this should be fixed by calculating the lambda like HM. lambda *= 0.95;
* TODO: fix lambda cost calculation
* - Marko Viitanen (Fador)
**/
g_lambda_cost[i] = g_lambda_cost[i]*g_lambda_cost[i];
} }
g_lambda_cost[encoder->QP] = lambda;
} }
void free_tables(void) void free_tables(void)
@ -362,6 +371,9 @@ void init_encoder_input(encoder_input *input, FILE *inputfile,
void encode_one_frame(encoder_control* encoder) void encode_one_frame(encoder_control* encoder)
{ {
// Initialize lambda value(s) to use in search
init_lambda(encoder);
/** IDR picture when: period == 0 and frame == 0 /** IDR picture when: period == 0 and frame == 0
* period == 1 && frame%2 == 0 * period == 1 && frame%2 == 0
* period != 0 && frame%period == 0 * period != 0 && frame%period == 0

View file

@ -81,6 +81,7 @@ typedef struct
} encoder_control; } encoder_control;
void init_tables(void); void init_tables(void);
void init_lambda(encoder_control* encoder);
void free_tables(void); void free_tables(void);
encoder_control *init_encoder_control(config *cfg); encoder_control *init_encoder_control(config *cfg);
void init_encoder_input(encoder_input *input, FILE* inputfile, void init_encoder_input(encoder_input *input, FILE* inputfile,
@ -107,7 +108,7 @@ void encode_transform_coeff(encoder_control *encoder, int32_t x_cu, int32_t y_cu
void encode_block_residual(encoder_control *encoder, void encode_block_residual(encoder_control *encoder,
uint16_t x_ctb, uint16_t y_ctb, uint8_t depth); uint16_t x_ctb, uint16_t y_ctb, uint8_t depth);
extern int16_t g_lambda_cost[55]; extern double g_lambda_cost[55];
extern uint32_t* g_sig_last_scan[3][7]; extern uint32_t* g_sig_last_scan[3][7];
int8_t g_convert_to_bit[LCU_WIDTH + 1]; int8_t g_convert_to_bit[LCU_WIDTH + 1];
static int8_t g_bitdepth = 8; static int8_t g_bitdepth = 8;

View file

@ -336,7 +336,7 @@ void search_intra(encoder_control *encoder, uint16_t x_ctb, uint16_t y_ctb, uint
int nn_cost = cur_cu->intra[0].cost; int nn_cost = cur_cu->intra[0].cost;
int nn_mode = cur_cu->intra[0].mode; int nn_mode = cur_cu->intra[0].mode;
int i; int i;
int cost = g_lambda_cost[encoder->QP] << 8; int cost = g_lambda_cost[encoder->QP] * 256.0;
static vector2d offsets[4] = {{0,0},{1,0},{0,1},{1,1}}; static vector2d offsets[4] = {{0,0},{1,0},{0,1},{1,1}};
width = 4; width = 4;
recShift = &rec[width * 2 + 8 + 1]; recShift = &rec[width * 2 + 8 + 1];