diff --git a/src/intra.c b/src/intra.c index 9013bb39..8b68cd07 100644 --- a/src/intra.c +++ b/src/intra.c @@ -252,14 +252,16 @@ static uint32_t intra_pred_ratecost(int16_t mode, int8_t *intra_preds) This function derives the prediction samples for planar mode (intra coding). */ int16_t intra_prediction(pixel *orig, int32_t origstride, pixel *rec, int16_t recstride, - uint8_t width, pixel *dst, int32_t dststride, uint32_t *sad_out, int8_t *intra_preds) + uint8_t width, pixel *dst, int32_t dststride, uint32_t *sad_out, + int8_t *intra_preds, uint32_t *bitcost_out) { uint32_t best_sad = 0xffffffff; uint32_t sad = 0; int16_t best_mode = 1; + uint32_t best_bitcost = 0; int32_t x,y; int16_t i; - uint32_t ratecost = 0; + uint32_t bitcost = 0; cost_16bit_nxn_func cost_func = get_sad_16bit_nxn_func(width); @@ -279,6 +281,7 @@ int16_t intra_prediction(pixel *orig, int32_t origstride, pixel *rec, int16_t re sad += additional_sad;\ if(sad < best_sad)\ {\ + best_bitcost = bitcost;\ best_sad = sad;\ best_mode = mode;\ COPY_PRED_TO_DST();\ @@ -308,8 +311,8 @@ int16_t intra_prediction(pixel *orig, int32_t origstride, pixel *rec, int16_t re for (i = 0; i < (int32_t)(width*width); i++) { pred[i] = val; } - ratecost = intra_pred_ratecost(1,intra_preds)*(int)(g_cur_lambda_cost+0.5); - CHECK_FOR_BEST(1,ratecost); + bitcost = intra_pred_ratecost(1,intra_preds); + CHECK_FOR_BEST(1,bitcost*(int)(g_cur_lambda_cost+0.5)); } // Check angular not requiring filtering @@ -317,8 +320,8 @@ int16_t intra_prediction(pixel *orig, int32_t origstride, pixel *rec, int16_t re int distance = MIN(abs(i - 26),abs(i - 10)); //!< Distance from top and left predictions if(distance <= threshold) { intra_get_angular_pred(rec, recstride, pred, width, width, i, filter); - ratecost = intra_pred_ratecost(i,intra_preds)*(int)(g_cur_lambda_cost+0.5); - CHECK_FOR_BEST(i,ratecost); + bitcost = intra_pred_ratecost(i,intra_preds); + CHECK_FOR_BEST(i,bitcost*(int)(g_cur_lambda_cost+0.5)); } } @@ -326,8 +329,8 @@ int16_t intra_prediction(pixel *orig, int32_t origstride, pixel *rec, int16_t re // Test planar mode (always filtered) intra_get_planar_pred(rec_filtered, recstride, width, pred, width); - ratecost = intra_pred_ratecost(0,intra_preds)*(int)(g_cur_lambda_cost+0.5); - CHECK_FOR_BEST(0,ratecost); + bitcost = intra_pred_ratecost(0,intra_preds); + CHECK_FOR_BEST(0,bitcost*(int)(g_cur_lambda_cost+0.5)); // Check angular predictions which require filtered samples // TODO: add conditions to skip some modes on borders @@ -336,13 +339,14 @@ int16_t intra_prediction(pixel *orig, int32_t origstride, pixel *rec, int16_t re int distance = MIN(abs(i-26),abs(i-10)); //!< Distance from top and left predictions if(distance > threshold) { intra_get_angular_pred(rec_filtered, recstride, pred, width, width, i, filter); - ratecost = intra_pred_ratecost(i,intra_preds)*(int)(g_cur_lambda_cost+0.5); - CHECK_FOR_BEST(i,ratecost); + bitcost = intra_pred_ratecost(i,intra_preds); + CHECK_FOR_BEST(i,bitcost*(int)(g_cur_lambda_cost+0.5)); } } // assign final sad to output - *sad_out = best_sad; + *sad_out = best_sad; + *bitcost_out = best_bitcost; #undef COPY_PRED_TO_DST #undef CHECK_FOR_BEST diff --git a/src/intra.h b/src/intra.h index f1495710..dca9af87 100644 --- a/src/intra.h +++ b/src/intra.h @@ -40,7 +40,8 @@ void intra_filter(pixel* ref, int32_t stride, int32_t width, int8_t mode); /* Predictions */ int16_t intra_prediction(pixel *orig, int32_t origstride, pixel *rec, int16_t recstride, - uint8_t width, pixel *dst, int32_t dststride, uint32_t *sad_out, int8_t *intra_preds); + uint8_t width, pixel *dst, int32_t dststride, uint32_t *sad_out, + int8_t *intra_preds, uint32_t *bitcost_out); pixel intra_get_dc_pred(pixel* pic, uint16_t pic_width, uint8_t width); void intra_get_planar_pred(pixel* src,int32_t srcstride, uint32_t width, pixel* dst, int32_t dststride); diff --git a/src/search.c b/src/search.c index c18c995d..259c31fb 100644 --- a/src/search.c +++ b/src/search.c @@ -679,6 +679,7 @@ static int search_cu_intra(encoder_control *encoder, cu_info *left_cu = 0; cu_info *above_cu = 0; + uint32_t bitcost = 0, bitcost_nxn; if ((x_px >> 3) > 0) { left_cu = &lcu->cu[cu_index - 1]; @@ -706,7 +707,7 @@ static int search_cu_intra(encoder_control *encoder, mode = intra_prediction(ref_pixels, LCU_WIDTH, cu_in_rec_buffer, cu_width * 2 + 8, cu_width, pred_buffer, cu_width, - &cost, candidate_modes); + &cost, candidate_modes, &bitcost); cur_cu->intra[0].mode = (int8_t)mode; cur_cu->intra[0].cost = cost; cur_cu->part_size = SIZE_2Nx2N; @@ -726,6 +727,8 @@ static int search_cu_intra(encoder_control *encoder, cu_in_rec_buffer = &rec_buffer[nxn_width * 2 + 8 + 1]; + bitcost_nxn = 0; + for (nxn_i = 0; nxn_i < 4; ++nxn_i) { const vector2d nxn_px = { x_px + offsets[nxn_i].x, y_px + offsets[nxn_i].y }; @@ -738,13 +741,15 @@ static int search_cu_intra(encoder_control *encoder, { uint32_t nxn_cost = -1; int16_t nxn_mode = -1; + uint32_t bitcost_temp = 0; pixel *ref_pixels = &lcu->ref.y[nxn_px.x + nxn_px.y * LCU_WIDTH]; nxn_mode = intra_prediction(ref_pixels, encoder->in.width, cu_in_rec_buffer, nxn_width * 2 + 8, nxn_width, pred_buffer, nxn_width, - &nxn_cost, candidate_modes); + &nxn_cost, candidate_modes, &bitcost_temp); cur_cu->intra[nxn_i].mode = (int8_t)nxn_mode; cost += nxn_cost; + bitcost_nxn += bitcost_temp; } } @@ -755,9 +760,12 @@ static int search_cu_intra(encoder_control *encoder, } else { cur_cu->intra[0].cost = cost; cur_cu->part_size = SIZE_NxN; + bitcost = bitcost_nxn; } } + cur_cu->intra[0].bitcost = bitcost; + return cur_cu->intra[0].cost; }