From 9dde96f25eba741db6fc73653363c769338d99a9 Mon Sep 17 00:00:00 2001 From: Ari Koivula Date: Fri, 7 Mar 2014 15:29:35 +0200 Subject: [PATCH] Refactor search_cu_intra. - Formatted. - Renamed and consolidated variables. - Removed unused x and y pos from intra_prediction function. --- src/intra.c | 4 +- src/intra.h | 4 +- src/search.c | 105 ++++++++++++++++++++++++++++++--------------------- 3 files changed, 67 insertions(+), 46 deletions(-) diff --git a/src/intra.c b/src/intra.c index 5addd362..9013bb39 100644 --- a/src/intra.c +++ b/src/intra.c @@ -251,8 +251,8 @@ 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, uint16_t xpos, - uint16_t ypos, uint8_t width, pixel *dst, int32_t dststride, uint32_t *sad_out, int8_t *intra_preds) +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) { uint32_t best_sad = 0xffffffff; uint32_t sad = 0; diff --git a/src/intra.h b/src/intra.h index 1bf797bf..f1495710 100644 --- a/src/intra.h +++ b/src/intra.h @@ -39,8 +39,8 @@ void intra_build_reference_border(int32_t x_luma, int32_t y_luma, int16_t out_wi 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, uint16_t xpos, - uint16_t ypos, uint8_t width, pixel *dst, int32_t dststride, uint32_t *sad_out, int8_t *intra_preds); +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); 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 0b854de9..35f3b788 100644 --- a/src/search.c +++ b/src/search.c @@ -517,71 +517,92 @@ static void lcu_set_coeff(lcu_t *lcu, int x_px, int y_px, int depth, cu_info *cu * Update lcu to have best modes at this depth. * \return Cost of best mode. */ -static int search_cu_intra(encoder_control *encoder, int x, int y, int depth, lcu_t *lcu) +static int search_cu_intra(encoder_control *encoder, + const int x_px, const int y_px, + const int depth, lcu_t *lcu) { - int width = (LCU_WIDTH >> (depth)); - int x_local = (x&0x3f), y_local = (y&0x3f); - int x_cu = x>>3; - int y_cu = y>>3; - int cu_pos = LCU_CU_OFFSET+(x_local>>3) + (y_local>>3)*LCU_T_CU_WIDTH; + const vector2d lcu_px = { x_px & 0x3f, y_px & 0x3f }; + const vector2d lcu_cu = { lcu_px.x >> 3, lcu_px.y >> 3 }; + const int8_t cu_width = (LCU_WIDTH >> (depth)); + const int cu_index = LCU_CU_OFFSET + lcu_cu.x + lcu_cu.y * LCU_T_CU_WIDTH; - cu_info *cur_cu = &lcu->cu[cu_pos]; + cu_info *cur_cu = &lcu->cu[cu_index]; - // INTRAPREDICTION - pixel pred[LCU_WIDTH * LCU_WIDTH + 1]; - pixel rec[(LCU_WIDTH * 2 + 1) * (LCU_WIDTH * 2 + 1)]; - pixel *rec_shift = &rec[width * 2 + 8 + 1]; + pixel pred_buffer[LCU_WIDTH * LCU_WIDTH + 1]; + pixel rec_buffer[(LCU_WIDTH * 2 + 1) * (LCU_WIDTH * 2 + 1)]; + pixel *cu_in_rec_buffer = &rec_buffer[cu_width * 2 + 8 + 1]; - int8_t intra_preds[3]; + int8_t candidate_modes[3]; - cu_info* left_cu = 0; - cu_info* above_cu = 0; + cu_info *left_cu = 0; + cu_info *above_cu = 0; - if (x_cu > 0) { - left_cu = &lcu->cu[cu_pos - 1]; + if ((x_px >> 3) > 0) { + left_cu = &lcu->cu[cu_index - 1]; } // Don't take the above CU across the LCU boundary. - if (y_cu > 0 && - ((y_cu * (LCU_WIDTH>>MAX_DEPTH)) % LCU_WIDTH) != 0) { - above_cu = &lcu->cu[cu_pos - LCU_T_CU_WIDTH]; + if ((y_px >> 3) > 0 && lcu_cu.y != 0) { + above_cu = &lcu->cu[cu_index - LCU_T_CU_WIDTH]; } // Get intra predictors - intra_get_dir_luma_predictor(x, y, intra_preds, cur_cu, left_cu, above_cu); + intra_get_dir_luma_predictor(x_px, y_px, candidate_modes, cur_cu, left_cu, above_cu); // Build reconstructed block to use in prediction with extrapolated borders - intra_build_reference_border(x, y,(int16_t)width * 2 + 8, rec, (int16_t)width * 2 + 8, 0, - encoder->in.cur_pic->width, encoder->in.cur_pic->height, - lcu); + intra_build_reference_border(x_px, y_px, cu_width * 2 + 8, + rec_buffer, cu_width * 2 + 8, 0, + encoder->in.cur_pic->width, + encoder->in.cur_pic->height, + lcu); - // find best intra mode - cur_cu->intra[0].mode = (int8_t)intra_prediction(&lcu->ref.y[x_local + y_local*LCU_WIDTH], - LCU_WIDTH, rec_shift, width * 2 + 8, x, y, - width, pred, width, &cur_cu->intra[0].cost, intra_preds); - cur_cu->part_size = SIZE_2Nx2N; + // Find best intra mode for 2Nx2N. + { + uint32_t cost = -1; + int16_t mode = -1; + pixel *ref_pixels = &lcu->ref.y[lcu_px.x + lcu_px.y * LCU_WIDTH]; + mode = intra_prediction(ref_pixels, LCU_WIDTH, + cu_in_rec_buffer, cu_width * 2 + 8, cu_width, + pred_buffer, cu_width, + &cost, candidate_modes); + cur_cu->intra[0].mode = (int8_t)mode; + cur_cu->intra[0].cost = cost; + cur_cu->part_size = SIZE_2Nx2N; + } // Do search for NxN split. if (0 && depth == MAX_DEPTH) { //TODO: reactivate NxN when _something_ is done to make it better + static const vector2d offsets[4] = {{0,0},{4,0},{0,4},{4,4}}; + const int nxn_width = 4; + // Save 2Nx2N information to compare with NxN. int nn_cost = cur_cu->intra[0].cost; int8_t nn_mode = cur_cu->intra[0].mode; - int i; - int cost = (int)(g_cur_lambda_cost * 4.5); // round to nearest - static vector2d offsets[4] = {{0,0},{1,0},{0,1},{1,1}}; - width = 4; - rec_shift = &rec[width * 2 + 8 + 1]; + int cost = (int)(g_cur_lambda_cost * 4.5); // +0.5 to round to nearest - for (i = 0; i < 4; ++i) { - int x_pos = x + offsets[i].x * width; - int y_pos = y + offsets[i].y * width; - intra_get_dir_luma_predictor(x_pos,y_pos, intra_preds, cur_cu, left_cu, above_cu); - intra_build_reference_border(x_pos, y_pos,(int16_t)width * 2 + 8, rec, (int16_t)width * 2 + 8, 0, + int nxn_i; + + cu_in_rec_buffer = &rec_buffer[nxn_width * 2 + 8 + 1]; + + 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 }; + intra_get_dir_luma_predictor(nxn_px.x, nxn_px.y, candidate_modes, + cur_cu, left_cu, above_cu); + intra_build_reference_border(nxn_px.x, nxn_px.y, nxn_width * 2 + 8, + rec_buffer, nxn_width * 2 + 8, 0, encoder->in.cur_pic->width, encoder->in.cur_pic->height, lcu); - cur_cu->intra[i].mode = (int8_t)intra_prediction(encoder->in.cur_pic->y_data, - encoder->in.width, rec_shift, width * 2 + 8, (int16_t)x_pos, (int16_t)y_pos, - width, pred, width, &cur_cu->intra[i].cost,intra_preds); - cost += cur_cu->intra[i].cost; + { + uint32_t nxn_cost = -1; + int16_t nxn_mode = -1; + 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); + cur_cu->intra[nxn_i].mode = (int8_t)nxn_mode; + cost += nxn_cost; + } } // Choose between 2Nx2N and NxN.