From 7bb9c25447888e2286ecbc0090fa5721a8300722 Mon Sep 17 00:00:00 2001 From: Ari Koivula Date: Mon, 3 Feb 2014 18:21:57 +0200 Subject: [PATCH] Remove duplicate implementation of intra_build_reference_border. The search_buildReferenceBorder was an ugly hack and a place for bugs to hide that should never have existed. Now it doesn't. The change reduces PSNR a little, but also reduces the bitrate, when the expected result was to have no change in either. I'm guessing there was still some bug in the search_buildReferenceBorder, but the bug could also be in intra_build_reference_border. Will have to do more testing to be sure, but having one place to look at will be better than having two. --- src/encoder.c | 26 ++++++++------ src/intra.c | 4 +-- src/intra.h | 2 +- src/search.c | 93 ++++----------------------------------------------- 4 files changed, 24 insertions(+), 101 deletions(-) diff --git a/src/encoder.c b/src/encoder.c index fdef0629..eed1b70a 100644 --- a/src/encoder.c +++ b/src/encoder.c @@ -2395,7 +2395,8 @@ void encode_block_residual(encoder_control *encoder, // re-doing the search here with actual reconstructed reference lowered // bitrate by 4% and improved luma PSNR by 0.03dB. Doing it here might // not be worth it. - intra_build_reference_border(encoder->in.cur_pic, x_ctb * 8, y_ctb * 8, + intra_build_reference_border(encoder->in.cur_pic, encoder->in.cur_pic->y_recdata, + x_ctb * 8, y_ctb * 8, width * 2 + 8, rec, width * 2 + 8, 0); cur_cu->intra[0].mode = (int8_t)intra_prediction(encoder->in.cur_pic->y_data, encoder->in.width, @@ -2419,8 +2420,9 @@ void encode_block_residual(encoder_control *encoder, recbase_y = &encoder->in.cur_pic->y_recdata[x_pos + y_pos * encoder->in.width]; rec_shift = &rec[width * 2 + 8 + 1]; - intra_build_reference_border(encoder->in.cur_pic, x_pos, y_pos, - width * 2 + 8, rec, width * 2 + 8, 0); + intra_build_reference_border(encoder->in.cur_pic, encoder->in.cur_pic->y_recdata, + x_pos, y_pos, + width * 2 + 8, rec, width * 2 + 8, 0); intra_recon(rec_shift, width * 2 + 8, x_pos, y_pos, width, recbase_y, rec_stride, cur_cu->intra[i].mode, 0); @@ -2439,10 +2441,11 @@ void encode_block_residual(encoder_control *encoder, } rec_shift = &rec[width_c * 2 + 8 + 1]; - intra_build_reference_border(encoder->in.cur_pic, x_ctb << MIN_SIZE, y_ctb << MIN_SIZE, - width_c * 2 + 8, rec, - width_c * 2 + 8, - 1); + intra_build_reference_border(encoder->in.cur_pic, encoder->in.cur_pic->u_recdata, + x_ctb << MIN_SIZE, y_ctb << MIN_SIZE, + width_c * 2 + 8, rec, + width_c * 2 + 8, + 1); intra_recon(rec_shift, width_c * 2 + 8, x_ctb * width_c, @@ -2453,10 +2456,11 @@ void encode_block_residual(encoder_control *encoder, cur_cu->intra[0].mode_chroma != 36 ? cur_cu->intra[0].mode_chroma : cur_cu->intra[0].mode, 1); - intra_build_reference_border(encoder->in.cur_pic, x_ctb << MIN_SIZE, y_ctb << MIN_SIZE, - width_c * 2 + 8, - rec, width_c * 2 + 8, - 2); + intra_build_reference_border(encoder->in.cur_pic, encoder->in.cur_pic->v_recdata, + x_ctb << MIN_SIZE, y_ctb << MIN_SIZE, + width_c * 2 + 8, + rec, width_c * 2 + 8, + 2); intra_recon(rec_shift, width_c * 2 + 8, x_ctb * width_c, diff --git a/src/intra.c b/src/intra.c index a88b3d1e..4e56f32b 100644 --- a/src/intra.c +++ b/src/intra.c @@ -432,7 +432,7 @@ void intra_recon(pixel* rec,uint32_t recstride, uint32_t xpos, uint32_t ypos,uin * The end result is 2*width+8 x 2*width+8 array, with only the top and left * edge pixels filled with the reconstructed pixels. */ -void intra_build_reference_border(picture *pic, int32_t x_luma, int32_t y_luma, int16_t outwidth, +void intra_build_reference_border(picture *pic, const pixel *src, int32_t x_luma, int32_t y_luma, int16_t outwidth, pixel *dst, int32_t dststride, int8_t chroma) { // Some other function might make use of the arrays num_ref_pixels_top and @@ -495,7 +495,7 @@ void intra_build_reference_border(picture *pic, int32_t x_luma, int32_t y_luma, const int src_height = pic->height >> is_chroma; // input picture pointer - const pixel * const src = (!chroma) ? pic->y_recdata : ((chroma == 1) ? pic->u_recdata : pic->v_recdata); + //const pixel * const src = (!chroma) ? pic->y_recdata : ((chroma == 1) ? pic->u_recdata : pic->v_recdata); // Convert luma coordinates to chroma coordinates for chroma. const int x = chroma ? x_luma / 2 : x_luma; diff --git a/src/intra.h b/src/intra.h index e8bf8661..6c6415bd 100644 --- a/src/intra.h +++ b/src/intra.h @@ -35,7 +35,7 @@ int8_t intra_get_block_mode(picture* pic, uint32_t x_ctb, uint32_t y_ctb, uint8_ int8_t intra_get_dir_luma_predictor(picture* pic,uint32_t x_ctb, uint32_t y_ctb, uint8_t depth, int8_t* preds); void intra_dc_pred_filtering(pixel* src, int32_t src_stride, pixel* dst, int32_t dst_stride, int32_t width, int32_t height ); -void intra_build_reference_border(picture* pic, int32_t x_ctb, int32_t y_ctb, int16_t out_width, pixel* dst, int32_t dst_stride, int8_t chroma); +void intra_build_reference_border(picture* pic, const pixel *src, int32_t x_ctb, int32_t y_ctb, int16_t out_width, pixel* dst, int32_t dst_stride, int8_t chroma); void intra_filter(pixel* ref, int32_t stride, int32_t width, int8_t mode); /* Predictions */ diff --git a/src/search.c b/src/search.c index 8f2623ab..d01c8d46 100644 --- a/src/search.c +++ b/src/search.c @@ -279,89 +279,6 @@ unsigned search_mv_full(unsigned depth, return best_cost; } -/** - * \brief - */ -void search_buildReferenceBorder(picture *pic, int32_t x, int32_t y, - int16_t outwidth, pixel *dst, - int32_t dststride, int8_t chroma) -{ - int32_t left_col; // left column iterator - pixel val; // variable to store extrapolated value - int32_t i; // index iterator - pixel dc_val = 1 << (g_bitdepth - 1); // default predictor value - int32_t top_row; // top row iterator - int32_t src_width = (pic->width >> (chroma ? 1 : 0)); // source picture width - int32_t src_height = (pic->height >> (chroma ? 1 : 0)); // source picture height - pixel *src_pic = (!chroma) ? pic->y_data : ((chroma == 1) ? pic->u_data : pic->v_data); // input picture pointer - int16_t scu_width = LCU_WIDTH >> (MAX_DEPTH + (chroma ? 1 : 0)); // Smallest Coding Unit width - int x_ctb = x >> MIN_SIZE; - int y_ctb = y >> MIN_SIZE; - pixel *src_shifted = &src_pic[x_ctb * scu_width + y_ctb * scu_width * src_width]; // input picture pointer shifted to start from the left-top corner of the current block - int32_t width_in_scu = pic->width_in_lcu << MAX_DEPTH; // picture width in SCU - - // Fill left column - if (x_ctb) { - // Loop SCU's - for (left_col = 1; left_col < outwidth / scu_width; left_col++) { - // If over the picture height or block not yet searched, stop - if ((y_ctb + left_col) * scu_width >= src_height - || pic->cu_array[MAX_DEPTH][x_ctb - 1 + (y_ctb + left_col) * width_in_scu].type == CU_NOTSET) { - break; - } - } - - // Copy the pixels to output - for (i = 0; i < left_col * scu_width - 1; i++) { - dst[(i + 1) * dststride] = src_shifted[i * src_width - 1]; - } - - // if the loop was not completed, extrapolate the last pixel pushed to output - if (left_col != outwidth / scu_width) { - val = src_shifted[(left_col * scu_width - 1) * src_width - 1]; - for (i = (left_col * scu_width); i < outwidth; i++) { - dst[i * dststride] = val; - } - } - } else { // If left column not available, copy from toprow or use the default predictor - val = y_ctb ? src_shifted[-src_width] : dc_val; - for (i = 0; i < outwidth; i++) { - dst[i * dststride] = val; - } - } - - if (y_ctb) { - // Loop top SCU's - for (top_row = 1; top_row < outwidth / scu_width; top_row++) { - if ((x_ctb + top_row) * scu_width >= src_width - || pic->cu_array[MAX_DEPTH][x_ctb + top_row + (y_ctb - 1) * width_in_scu].type - == CU_NOTSET) { - break; - } - } - - for (i = 0; i < top_row * scu_width - 1; i++) { - dst[i + 1] = src_shifted[i - src_width]; - } - - if (top_row != outwidth / scu_width) { - val = src_shifted[(top_row * scu_width) - src_width - 1]; - for (i = (top_row * scu_width); i < outwidth; i++) { - dst[i] = val; - } - } - } else { - val = x_ctb ? src_shifted[-1] : dc_val; - for (i = 1; i < outwidth; i++) { - dst[i] = val; - } - } - // Topleft corner - dst[0] = (x_ctb && y_ctb) ? src_shifted[-src_width - 1] : dst[dststride]; - -} - - void search_inter(encoder_control *encoder, uint16_t x_ctb, uint16_t y_ctb, uint8_t depth) { picture *cur_pic = encoder->in.cur_pic; picture *ref_pic = encoder->ref->pics[0]; @@ -404,8 +321,9 @@ void search_intra(encoder_control *encoder, uint16_t x_ctb, uint16_t y_ctb, uint pixel *recShift = &rec[(LCU_WIDTH >> (depth)) * 2 + 8 + 1]; // Build reconstructed block to use in prediction with extrapolated borders - search_buildReferenceBorder(encoder->in.cur_pic, x, y, - width * 2 + 8, rec, width * 2 + 8, 0); + intra_build_reference_border(cur_pic, cur_pic->y_data, + x, y, + width * 2 + 8, rec, width * 2 + 8, 0); cur_cu->intra[0].mode = (uint8_t) intra_prediction(encoder->in.cur_pic->y_data, encoder->in.width, recShift, width * 2 + 8, x, y, width, pred, width, &cur_cu->intra[0].cost); @@ -426,8 +344,9 @@ void search_intra(encoder_control *encoder, uint16_t x_ctb, uint16_t y_ctb, uint for (i = 0; i < 4; ++i) { int x_pos = x + offsets[i].x * width; int y_pos = y + offsets[i].y * width; - search_buildReferenceBorder(encoder->in.cur_pic, x_pos, y_pos, - width * 2 + 8, rec, width * 2 + 8, 0); + intra_build_reference_border(cur_pic, cur_pic->y_recdata, + x_pos, y_pos, + width * 2 + 8, rec, width * 2 + 8, 0); cur_cu->intra[i].mode = (uint8_t) intra_prediction(encoder->in.cur_pic->y_data, encoder->in.width, recShift, width * 2 + 8, x_pos, y_pos, width, pred, width, &cur_cu->intra[i].cost);