diff --git a/av1/common/alloccommon.c b/av1/common/alloccommon.c index db4fbf71e76c775171ebc4057e2931220648629b..7c5b358aa2a775f287d8b829ee57beb382908092 100644 --- a/av1/common/alloccommon.c +++ b/av1/common/alloccommon.c @@ -85,14 +85,10 @@ void av1_free_ref_frame_buffers(BufferPool *pool) { void av1_free_restoration_buffers(AV1_COMMON *cm) { aom_free(cm->rst_info.restoration_type); cm->rst_info.restoration_type = NULL; - aom_free(cm->rst_info.bilateral_level); - cm->rst_info.bilateral_level = NULL; - aom_free(cm->rst_info.vfilter); - cm->rst_info.vfilter = NULL; - aom_free(cm->rst_info.hfilter); - cm->rst_info.hfilter = NULL; - aom_free(cm->rst_info.wiener_level); - cm->rst_info.wiener_level = NULL; + aom_free(cm->rst_info.bilateral_info); + cm->rst_info.bilateral_info = NULL; + aom_free(cm->rst_info.wiener_info); + cm->rst_info.wiener_info = NULL; } #endif // CONFIG_LOOP_RESTORATION diff --git a/av1/common/entropymode.c b/av1/common/entropymode.c index a999950f6895831652fa8cda72203a830352c15b..b65b6dffabf503e0bcec176b999ac2b7b566e2a0 100644 --- a/av1/common/entropymode.c +++ b/av1/common/entropymode.c @@ -1655,9 +1655,11 @@ void av1_setup_past_independence(AV1_COMMON *cm) { // To force update of the sharpness lf->last_sharpness_level = -1; #if CONFIG_LOOP_RESTORATION - if (cm->rst_info.bilateral_level) { + if (cm->rst_info.bilateral_info) { + int s; for (i = 0; i < cm->rst_internal.ntiles; ++i) - cm->rst_info.bilateral_level[i] = -1; + for (s = 0; s < BILATERAL_SUBTILES; ++s) + cm->rst_info.bilateral_info[i].level[s] = -1; } #endif // CONFIG_LOOP_RESTORATION diff --git a/av1/common/restoration.c b/av1/common/restoration.c index 1baa5b4fcb7be1c0016fe3d24a03f413f934eb22..f58d91a917ca04ecd86ad508456e8608735acf6c 100644 --- a/av1/common/restoration.c +++ b/av1/common/restoration.c @@ -40,14 +40,14 @@ typedef struct bilateral_params { } BilateralParamsType; static BilateralParamsType bilateral_level_to_params_arr[BILATERAL_LEVELS] = { - // Values are rounded to 1/16 th precision + // Values are rounded to 1/16 th precision { 8, 9, 30 }, { 9, 8, 30 }, { 9, 11, 32 }, { 11, 9, 32 }, { 14, 14, 36 }, { 18, 18, 36 }, { 24, 24, 40 }, { 32, 32, 40 }, }; static BilateralParamsType bilateral_level_to_params_arr_kf[BILATERAL_LEVELS_KF] = { - // Values are rounded to 1/16 th precision + // Values are rounded to 1/16 th precision { 8, 8, 30 }, { 9, 9, 32 }, { 10, 10, 32 }, { 12, 12, 32 }, { 14, 14, 32 }, { 18, 18, 36 }, { 24, 24, 40 }, { 30, 30, 44 }, { 36, 36, 48 }, { 42, 42, 48 }, { 48, 48, 48 }, { 48, 48, 56 }, @@ -151,33 +151,35 @@ void av1_loop_restoration_init(RestorationInternal *rst, RestorationInfo *rsi, &rst->nhtiles, &rst->nvtiles); if (rsi->frame_restoration_type == RESTORE_WIENER) { for (tile_idx = 0; tile_idx < rst->ntiles; ++tile_idx) { - rsi->vfilter[tile_idx][RESTORATION_HALFWIN] = - rsi->hfilter[tile_idx][RESTORATION_HALFWIN] = RESTORATION_FILT_STEP; + rsi->wiener_info[tile_idx].vfilter[RESTORATION_HALFWIN] = + rsi->wiener_info[tile_idx].hfilter[RESTORATION_HALFWIN] = + RESTORATION_FILT_STEP; for (i = 0; i < RESTORATION_HALFWIN; ++i) { - rsi->vfilter[tile_idx][RESTORATION_WIN - 1 - i] = - rsi->vfilter[tile_idx][i]; - rsi->hfilter[tile_idx][RESTORATION_WIN - 1 - i] = - rsi->hfilter[tile_idx][i]; - rsi->vfilter[tile_idx][RESTORATION_HALFWIN] -= - 2 * rsi->vfilter[tile_idx][i]; - rsi->hfilter[tile_idx][RESTORATION_HALFWIN] -= - 2 * rsi->hfilter[tile_idx][i]; + rsi->wiener_info[tile_idx].vfilter[RESTORATION_WIN - 1 - i] = + rsi->wiener_info[tile_idx].vfilter[i]; + rsi->wiener_info[tile_idx].hfilter[RESTORATION_WIN - 1 - i] = + rsi->wiener_info[tile_idx].hfilter[i]; + rsi->wiener_info[tile_idx].vfilter[RESTORATION_HALFWIN] -= + 2 * rsi->wiener_info[tile_idx].vfilter[i]; + rsi->wiener_info[tile_idx].hfilter[RESTORATION_HALFWIN] -= + 2 * rsi->wiener_info[tile_idx].hfilter[i]; } } } else if (rsi->frame_restoration_type == RESTORE_SWITCHABLE) { for (tile_idx = 0; tile_idx < rst->ntiles; ++tile_idx) { if (rsi->restoration_type[tile_idx] == RESTORE_WIENER) { - rsi->vfilter[tile_idx][RESTORATION_HALFWIN] = - rsi->hfilter[tile_idx][RESTORATION_HALFWIN] = RESTORATION_FILT_STEP; + rsi->wiener_info[tile_idx].vfilter[RESTORATION_HALFWIN] = + rsi->wiener_info[tile_idx].hfilter[RESTORATION_HALFWIN] = + RESTORATION_FILT_STEP; for (i = 0; i < RESTORATION_HALFWIN; ++i) { - rsi->vfilter[tile_idx][RESTORATION_WIN - 1 - i] = - rsi->vfilter[tile_idx][i]; - rsi->hfilter[tile_idx][RESTORATION_WIN - 1 - i] = - rsi->hfilter[tile_idx][i]; - rsi->vfilter[tile_idx][RESTORATION_HALFWIN] -= - 2 * rsi->vfilter[tile_idx][i]; - rsi->hfilter[tile_idx][RESTORATION_HALFWIN] -= - 2 * rsi->hfilter[tile_idx][i]; + rsi->wiener_info[tile_idx].vfilter[RESTORATION_WIN - 1 - i] = + rsi->wiener_info[tile_idx].vfilter[i]; + rsi->wiener_info[tile_idx].hfilter[RESTORATION_WIN - 1 - i] = + rsi->wiener_info[tile_idx].hfilter[i]; + rsi->wiener_info[tile_idx].vfilter[RESTORATION_HALFWIN] -= + 2 * rsi->wiener_info[tile_idx].vfilter[i]; + rsi->wiener_info[tile_idx].hfilter[RESTORATION_HALFWIN] -= + 2 * rsi->wiener_info[tile_idx].hfilter[i]; } } } @@ -195,8 +197,7 @@ static void loop_bilateral_filter_tile(uint8_t *data, int tile_idx, int width, for (subtile_idx = 0; subtile_idx < BILATERAL_SUBTILES; ++subtile_idx) { uint8_t *data_p, *tmpdata_p; - const int level = - rst->rsi->bilateral_level[tile_idx * BILATERAL_SUBTILES + subtile_idx]; + const int level = rst->rsi->bilateral_info[tile_idx].level[subtile_idx]; uint8_t(*wx_lut)[RESTORATION_WIN]; uint8_t *wr_lut_; @@ -282,7 +283,7 @@ static void loop_wiener_filter_tile(uint8_t *data, int tile_idx, int width, int h_start, h_end, v_start, v_end; uint8_t *data_p, *tmpdata_p; - if (rst->rsi->wiener_level[tile_idx] == 0) return; + if (rst->rsi->wiener_info[tile_idx].level == 0) return; // Filter row-wise av1_get_rest_tile_limits(tile_idx, 0, 0, rst->nhtiles, rst->nvtiles, tile_width, tile_height, width, height, 1, 0, @@ -291,7 +292,8 @@ static void loop_wiener_filter_tile(uint8_t *data, int tile_idx, int width, tmpdata_p = tmpdata + h_start + v_start * tmpstride; for (i = 0; i < (v_end - v_start); ++i) { for (j = 0; j < (h_end - h_start); ++j) { - *tmpdata_p++ = hor_sym_filter(data_p++, rst->rsi->hfilter[tile_idx]); + *tmpdata_p++ = + hor_sym_filter(data_p++, rst->rsi->wiener_info[tile_idx].hfilter); } data_p += stride - (h_end - h_start); tmpdata_p += tmpstride - (h_end - h_start); @@ -304,8 +306,8 @@ static void loop_wiener_filter_tile(uint8_t *data, int tile_idx, int width, tmpdata_p = tmpdata + h_start + v_start * tmpstride; for (i = 0; i < (v_end - v_start); ++i) { for (j = 0; j < (h_end - h_start); ++j) { - *data_p++ = - ver_sym_filter(tmpdata_p++, tmpstride, rst->rsi->vfilter[tile_idx]); + *data_p++ = ver_sym_filter(tmpdata_p++, tmpstride, + rst->rsi->wiener_info[tile_idx].vfilter); } data_p += stride - (h_end - h_start); tmpdata_p += tmpstride - (h_end - h_start); @@ -370,8 +372,7 @@ static void loop_bilateral_filter_tile_highbd(uint16_t *data, int tile_idx, for (subtile_idx = 0; subtile_idx < BILATERAL_SUBTILES; ++subtile_idx) { uint16_t *data_p, *tmpdata_p; - const int level = - rst->rsi->bilateral_level[tile_idx * BILATERAL_SUBTILES + subtile_idx]; + const int level = rst->rsi->bilateral_info[tile_idx].level[subtile_idx]; uint8_t(*wx_lut)[RESTORATION_WIN]; uint8_t *wr_lut_; @@ -462,7 +463,7 @@ static void loop_wiener_filter_tile_highbd(uint16_t *data, int tile_idx, int i, j; uint16_t *data_p, *tmpdata_p; - if (rst->rsi->wiener_level[tile_idx] == 0) return; + if (rst->rsi->wiener_info[tile_idx].level == 0) return; // Filter row-wise av1_get_rest_tile_limits(tile_idx, 0, 0, rst->nhtiles, rst->nvtiles, tile_width, tile_height, width, height, 1, 0, @@ -472,7 +473,7 @@ static void loop_wiener_filter_tile_highbd(uint16_t *data, int tile_idx, for (i = 0; i < (v_end - v_start); ++i) { for (j = 0; j < (h_end - h_start); ++j) { *tmpdata_p++ = hor_sym_filter_highbd( - data_p++, rst->rsi->hfilter[tile_idx], bit_depth); + data_p++, rst->rsi->wiener_info[tile_idx].hfilter, bit_depth); } data_p += stride - (h_end - h_start); tmpdata_p += tmpstride - (h_end - h_start); @@ -486,7 +487,8 @@ static void loop_wiener_filter_tile_highbd(uint16_t *data, int tile_idx, for (i = 0; i < (v_end - v_start); ++i) { for (j = 0; j < (h_end - h_start); ++j) { *data_p++ = ver_sym_filter_highbd(tmpdata_p++, tmpstride, - rst->rsi->vfilter[tile_idx], bit_depth); + rst->rsi->wiener_info[tile_idx].vfilter, + bit_depth); } data_p += stride - (h_end - h_start); tmpdata_p += tmpstride - (h_end - h_start); diff --git a/av1/common/restoration.h b/av1/common/restoration.h index b478bb8452da83dab2b95a6d1c133ffb93547b24..a5150ad3804577bdf631d1c89d707c5b79512266 100644 --- a/av1/common/restoration.h +++ b/av1/common/restoration.h @@ -57,14 +57,20 @@ extern "C" { #define WIENER_FILT_TAP2_MAXV \ (WIENER_FILT_TAP2_MINV - 1 + (1 << WIENER_FILT_TAP2_BITS)) +typedef struct { int level[BILATERAL_SUBTILES]; } BilateralInfo; + +typedef struct { + int level; + int vfilter[RESTORATION_WIN], hfilter[RESTORATION_WIN]; +} WienerInfo; + typedef struct { RestorationType frame_restoration_type; RestorationType *restoration_type; // Bilateral filter - int *bilateral_level; + BilateralInfo *bilateral_info; // Wiener filter - int *wiener_level; - int (*vfilter)[RESTORATION_WIN], (*hfilter)[RESTORATION_WIN]; + WienerInfo *wiener_info; } RestorationInfo; typedef struct { diff --git a/av1/decoder/decodeframe.c b/av1/decoder/decodeframe.c index 9efe01652c4a58f6b6f20879b5291125a38b5450..c2f187036beea569c32356d2761e0dc9603f8081 100644 --- a/av1/decoder/decodeframe.c +++ b/av1/decoder/decodeframe.c @@ -1920,101 +1920,96 @@ static void decode_restoration(AV1_COMMON *cm, aom_reader *rb) { rsi->restoration_type = (RestorationType *)aom_realloc( rsi->restoration_type, sizeof(*rsi->restoration_type) * ntiles); if (rsi->frame_restoration_type == RESTORE_SWITCHABLE) { - rsi->bilateral_level = (int *)aom_realloc( - rsi->bilateral_level, - sizeof(*rsi->bilateral_level) * ntiles * BILATERAL_SUBTILES); - assert(rsi->bilateral_level != NULL); - rsi->wiener_level = (int *)aom_realloc( - rsi->wiener_level, sizeof(*rsi->wiener_level) * ntiles); - assert(rsi->wiener_level != NULL); - rsi->vfilter = (int(*)[RESTORATION_WIN])aom_realloc( - rsi->vfilter, sizeof(*rsi->vfilter) * ntiles); - assert(rsi->vfilter != NULL); - rsi->hfilter = (int(*)[RESTORATION_WIN])aom_realloc( - rsi->hfilter, sizeof(*rsi->hfilter) * ntiles); - assert(rsi->hfilter != NULL); + rsi->bilateral_info = (BilateralInfo *)aom_realloc( + rsi->bilateral_info, sizeof(*rsi->bilateral_info) * ntiles); + assert(rsi->bilateral_info != NULL); + rsi->wiener_info = (WienerInfo *)aom_realloc( + rsi->wiener_info, sizeof(*rsi->wiener_info) * ntiles); + assert(rsi->wiener_info != NULL); for (i = 0; i < ntiles; ++i) { rsi->restoration_type[i] = aom_read_tree( rb, av1_switchable_restore_tree, cm->fc->switchable_restore_prob); if (rsi->restoration_type[i] == RESTORE_WIENER) { - rsi->wiener_level[i] = 1; - rsi->vfilter[i][0] = aom_read_literal(rb, WIENER_FILT_TAP0_BITS) + - WIENER_FILT_TAP0_MINV; - rsi->vfilter[i][1] = aom_read_literal(rb, WIENER_FILT_TAP1_BITS) + - WIENER_FILT_TAP1_MINV; - rsi->vfilter[i][2] = aom_read_literal(rb, WIENER_FILT_TAP2_BITS) + - WIENER_FILT_TAP2_MINV; - rsi->hfilter[i][0] = aom_read_literal(rb, WIENER_FILT_TAP0_BITS) + - WIENER_FILT_TAP0_MINV; - rsi->hfilter[i][1] = aom_read_literal(rb, WIENER_FILT_TAP1_BITS) + - WIENER_FILT_TAP1_MINV; - rsi->hfilter[i][2] = aom_read_literal(rb, WIENER_FILT_TAP2_BITS) + - WIENER_FILT_TAP2_MINV; + rsi->wiener_info[i].level = 1; + rsi->wiener_info[i].vfilter[0] = + aom_read_literal(rb, WIENER_FILT_TAP0_BITS) + + WIENER_FILT_TAP0_MINV; + rsi->wiener_info[i].vfilter[1] = + aom_read_literal(rb, WIENER_FILT_TAP1_BITS) + + WIENER_FILT_TAP1_MINV; + rsi->wiener_info[i].vfilter[2] = + aom_read_literal(rb, WIENER_FILT_TAP2_BITS) + + WIENER_FILT_TAP2_MINV; + rsi->wiener_info[i].hfilter[0] = + aom_read_literal(rb, WIENER_FILT_TAP0_BITS) + + WIENER_FILT_TAP0_MINV; + rsi->wiener_info[i].hfilter[1] = + aom_read_literal(rb, WIENER_FILT_TAP1_BITS) + + WIENER_FILT_TAP1_MINV; + rsi->wiener_info[i].hfilter[2] = + aom_read_literal(rb, WIENER_FILT_TAP2_BITS) + + WIENER_FILT_TAP2_MINV; } else if (rsi->restoration_type[i] == RESTORE_BILATERAL) { int s; for (s = 0; s < BILATERAL_SUBTILES; ++s) { - const int j = i * BILATERAL_SUBTILES + s; #if BILATERAL_SUBTILES == 0 - rsi->bilateral_level[j] = + rsi->bilateral_info[i].level[s] = aom_read_literal(rb, av1_bilateral_level_bits(cm)); #else if (aom_read(rb, RESTORE_NONE_BILATERAL_PROB)) { - rsi->bilateral_level[j] = + rsi->bilateral_info[i].level[s] = aom_read_literal(rb, av1_bilateral_level_bits(cm)); } else { - rsi->bilateral_level[j] = -1; + rsi->bilateral_info[i].level[s] = -1; } #endif } } } } else if (rsi->frame_restoration_type == RESTORE_WIENER) { - rsi->wiener_level = (int *)aom_realloc( - rsi->wiener_level, sizeof(*rsi->wiener_level) * ntiles); - assert(rsi->wiener_level != NULL); - rsi->vfilter = (int(*)[RESTORATION_WIN])aom_realloc( - rsi->vfilter, sizeof(*rsi->vfilter) * ntiles); - assert(rsi->vfilter != NULL); - rsi->hfilter = (int(*)[RESTORATION_WIN])aom_realloc( - rsi->hfilter, sizeof(*rsi->hfilter) * ntiles); - assert(rsi->hfilter != NULL); + rsi->wiener_info = (WienerInfo *)aom_realloc( + rsi->wiener_info, sizeof(*rsi->wiener_info) * ntiles); + assert(rsi->wiener_info != NULL); for (i = 0; i < ntiles; ++i) { if (aom_read(rb, RESTORE_NONE_WIENER_PROB)) { - rsi->wiener_level[i] = 1; + rsi->wiener_info[i].level = 1; rsi->restoration_type[i] = RESTORE_WIENER; - rsi->vfilter[i][0] = aom_read_literal(rb, WIENER_FILT_TAP0_BITS) + - WIENER_FILT_TAP0_MINV; - rsi->vfilter[i][1] = aom_read_literal(rb, WIENER_FILT_TAP1_BITS) + - WIENER_FILT_TAP1_MINV; - rsi->vfilter[i][2] = aom_read_literal(rb, WIENER_FILT_TAP2_BITS) + - WIENER_FILT_TAP2_MINV; - rsi->hfilter[i][0] = aom_read_literal(rb, WIENER_FILT_TAP0_BITS) + - WIENER_FILT_TAP0_MINV; - rsi->hfilter[i][1] = aom_read_literal(rb, WIENER_FILT_TAP1_BITS) + - WIENER_FILT_TAP1_MINV; - rsi->hfilter[i][2] = aom_read_literal(rb, WIENER_FILT_TAP2_BITS) + - WIENER_FILT_TAP2_MINV; + rsi->wiener_info[i].vfilter[0] = + aom_read_literal(rb, WIENER_FILT_TAP0_BITS) + + WIENER_FILT_TAP0_MINV; + rsi->wiener_info[i].vfilter[1] = + aom_read_literal(rb, WIENER_FILT_TAP1_BITS) + + WIENER_FILT_TAP1_MINV; + rsi->wiener_info[i].vfilter[2] = + aom_read_literal(rb, WIENER_FILT_TAP2_BITS) + + WIENER_FILT_TAP2_MINV; + rsi->wiener_info[i].hfilter[0] = + aom_read_literal(rb, WIENER_FILT_TAP0_BITS) + + WIENER_FILT_TAP0_MINV; + rsi->wiener_info[i].hfilter[1] = + aom_read_literal(rb, WIENER_FILT_TAP1_BITS) + + WIENER_FILT_TAP1_MINV; + rsi->wiener_info[i].hfilter[2] = + aom_read_literal(rb, WIENER_FILT_TAP2_BITS) + + WIENER_FILT_TAP2_MINV; } else { - rsi->wiener_level[i] = 0; + rsi->wiener_info[i].level = 0; rsi->restoration_type[i] = RESTORE_NONE; } } } else { - rsi->frame_restoration_type = RESTORE_BILATERAL; - rsi->bilateral_level = (int *)aom_realloc( - rsi->bilateral_level, - sizeof(*rsi->bilateral_level) * ntiles * BILATERAL_SUBTILES); - assert(rsi->bilateral_level != NULL); + rsi->bilateral_info = (BilateralInfo *)aom_realloc( + rsi->bilateral_info, sizeof(*rsi->bilateral_info) * ntiles); + assert(rsi->bilateral_info != NULL); for (i = 0; i < ntiles; ++i) { int s; rsi->restoration_type[i] = RESTORE_BILATERAL; for (s = 0; s < BILATERAL_SUBTILES; ++s) { - const int j = i * BILATERAL_SUBTILES + s; if (aom_read(rb, RESTORE_NONE_BILATERAL_PROB)) { - rsi->bilateral_level[j] = + rsi->bilateral_info[i].level[s] = aom_read_literal(rb, av1_bilateral_level_bits(cm)); } else { - rsi->bilateral_level[j] = -1; + rsi->bilateral_info[i].level[s] = -1; } } } diff --git a/av1/encoder/bitstream.c b/av1/encoder/bitstream.c index fedc26390bf0aff8c46bb8f99f79b23992eceee1..ce16fcf615916ace762dad5f38d65618b079a06e 100644 --- a/av1/encoder/bitstream.c +++ b/av1/encoder/bitstream.c @@ -2455,75 +2455,84 @@ static void encode_restoration_mode(AV1_COMMON *cm, static void encode_restoration(AV1_COMMON *cm, aom_writer *wb) { int i; - RestorationInfo *rst = &cm->rst_info; - if (rst->frame_restoration_type != RESTORE_NONE) { - if (rst->frame_restoration_type == RESTORE_SWITCHABLE) { + RestorationInfo *rsi = &cm->rst_info; + if (rsi->frame_restoration_type != RESTORE_NONE) { + if (rsi->frame_restoration_type == RESTORE_SWITCHABLE) { // RESTORE_SWITCHABLE for (i = 0; i < cm->rst_internal.ntiles; ++i) { av1_write_token( wb, av1_switchable_restore_tree, cm->fc->switchable_restore_prob, - &switchable_restore_encodings[rst->restoration_type[i]]); - if (rst->restoration_type[i] == RESTORE_NONE) { - } else if (rst->restoration_type[i] == RESTORE_BILATERAL) { + &switchable_restore_encodings[rsi->restoration_type[i]]); + if (rsi->restoration_type[i] == RESTORE_BILATERAL) { int s; for (s = 0; s < BILATERAL_SUBTILES; ++s) { - const int j = i * BILATERAL_SUBTILES + s; #if BILATERAL_SUBTILES == 0 - aom_write_literal(wb, rst->bilateral_level[j], + aom_write_literal(wb, rsi->bilateral_info[i].level[s], av1_bilateral_level_bits(cm)); #else - aom_write(wb, rst->bilateral_level[j] >= 0, + aom_write(wb, rsi->bilateral_info[i].level[s] >= 0, RESTORE_NONE_BILATERAL_PROB); - if (rst->bilateral_level[j] >= 0) { - aom_write_literal(wb, rst->bilateral_level[j], + if (rsi->bilateral_info[i].level[s] >= 0) { + aom_write_literal(wb, rsi->bilateral_info[i].level[s], av1_bilateral_level_bits(cm)); } #endif } - } else { - aom_write_literal(wb, rst->vfilter[i][0] - WIENER_FILT_TAP0_MINV, - WIENER_FILT_TAP0_BITS); - aom_write_literal(wb, rst->vfilter[i][1] - WIENER_FILT_TAP1_MINV, - WIENER_FILT_TAP1_BITS); - aom_write_literal(wb, rst->vfilter[i][2] - WIENER_FILT_TAP2_MINV, - WIENER_FILT_TAP2_BITS); - aom_write_literal(wb, rst->hfilter[i][0] - WIENER_FILT_TAP0_MINV, - WIENER_FILT_TAP0_BITS); - aom_write_literal(wb, rst->hfilter[i][1] - WIENER_FILT_TAP1_MINV, - WIENER_FILT_TAP1_BITS); - aom_write_literal(wb, rst->hfilter[i][2] - WIENER_FILT_TAP2_MINV, - WIENER_FILT_TAP2_BITS); + } else if (rsi->restoration_type[i] == RESTORE_WIENER) { + aom_write_literal( + wb, rsi->wiener_info[i].vfilter[0] - WIENER_FILT_TAP0_MINV, + WIENER_FILT_TAP0_BITS); + aom_write_literal( + wb, rsi->wiener_info[i].vfilter[1] - WIENER_FILT_TAP1_MINV, + WIENER_FILT_TAP1_BITS); + aom_write_literal( + wb, rsi->wiener_info[i].vfilter[2] - WIENER_FILT_TAP2_MINV, + WIENER_FILT_TAP2_BITS); + aom_write_literal( + wb, rsi->wiener_info[i].hfilter[0] - WIENER_FILT_TAP0_MINV, + WIENER_FILT_TAP0_BITS); + aom_write_literal( + wb, rsi->wiener_info[i].hfilter[1] - WIENER_FILT_TAP1_MINV, + WIENER_FILT_TAP1_BITS); + aom_write_literal( + wb, rsi->wiener_info[i].hfilter[2] - WIENER_FILT_TAP2_MINV, + WIENER_FILT_TAP2_BITS); } } - } else if (rst->frame_restoration_type == RESTORE_BILATERAL) { + } else if (rsi->frame_restoration_type == RESTORE_BILATERAL) { for (i = 0; i < cm->rst_internal.ntiles; ++i) { int s; for (s = 0; s < BILATERAL_SUBTILES; ++s) { - const int j = i * BILATERAL_SUBTILES + s; - aom_write(wb, rst->bilateral_level[j] >= 0, + aom_write(wb, rsi->bilateral_info[i].level[s] >= 0, RESTORE_NONE_BILATERAL_PROB); - if (rst->bilateral_level[j] >= 0) { - aom_write_literal(wb, rst->bilateral_level[j], + if (rsi->bilateral_info[i].level[s] >= 0) { + aom_write_literal(wb, rsi->bilateral_info[i].level[s], av1_bilateral_level_bits(cm)); } } } - } else if (rst->frame_restoration_type == RESTORE_WIENER) { + } else if (rsi->frame_restoration_type == RESTORE_WIENER) { for (i = 0; i < cm->rst_internal.ntiles; ++i) { - aom_write(wb, rst->wiener_level[i] != 0, RESTORE_NONE_WIENER_PROB); - if (rst->wiener_level[i]) { - aom_write_literal(wb, rst->vfilter[i][0] - WIENER_FILT_TAP0_MINV, - WIENER_FILT_TAP0_BITS); - aom_write_literal(wb, rst->vfilter[i][1] - WIENER_FILT_TAP1_MINV, - WIENER_FILT_TAP1_BITS); - aom_write_literal(wb, rst->vfilter[i][2] - WIENER_FILT_TAP2_MINV, - WIENER_FILT_TAP2_BITS); - aom_write_literal(wb, rst->hfilter[i][0] - WIENER_FILT_TAP0_MINV, - WIENER_FILT_TAP0_BITS); - aom_write_literal(wb, rst->hfilter[i][1] - WIENER_FILT_TAP1_MINV, - WIENER_FILT_TAP1_BITS); - aom_write_literal(wb, rst->hfilter[i][2] - WIENER_FILT_TAP2_MINV, - WIENER_FILT_TAP2_BITS); + aom_write(wb, rsi->wiener_info[i].level != 0, RESTORE_NONE_WIENER_PROB); + if (rsi->wiener_info[i].level) { + aom_write_literal( + wb, rsi->wiener_info[i].vfilter[0] - WIENER_FILT_TAP0_MINV, + WIENER_FILT_TAP0_BITS); + aom_write_literal( + wb, rsi->wiener_info[i].vfilter[1] - WIENER_FILT_TAP1_MINV, + WIENER_FILT_TAP1_BITS); + aom_write_literal( + wb, rsi->wiener_info[i].vfilter[2] - WIENER_FILT_TAP2_MINV, + WIENER_FILT_TAP2_BITS); + aom_write_literal( + wb, rsi->wiener_info[i].hfilter[0] - WIENER_FILT_TAP0_MINV, + WIENER_FILT_TAP0_BITS); + aom_write_literal( + wb, rsi->wiener_info[i].hfilter[1] - WIENER_FILT_TAP1_MINV, + WIENER_FILT_TAP1_BITS); + aom_write_literal( + wb, rsi->wiener_info[i].hfilter[2] - WIENER_FILT_TAP2_MINV, + WIENER_FILT_TAP2_BITS); } } } diff --git a/av1/encoder/pickrst.c b/av1/encoder/pickrst.c index 00e46a689562cc4afb5e19931b11850ecd2180fe..28bdcc3e77b9758a6f0ad707378aa2c50068d4b7 100644 --- a/av1/encoder/pickrst.c +++ b/av1/encoder/pickrst.c @@ -28,6 +28,11 @@ #include "av1/encoder/pickrst.h" #include "av1/encoder/quantize.h" +typedef double (*search_restore_type)(const YV12_BUFFER_CONFIG *src, + AV1_COMP *cpi, int filter_level, + int partial_frame, RestorationInfo *info, + double *best_tile_cost); + const int frame_level_restore_bits[RESTORE_TYPES] = { 2, 2, 2, 2 }; static int64_t sse_restoration_tile(const YV12_BUFFER_CONFIG *src, @@ -95,16 +100,15 @@ static int64_t try_restoration_frame(const YV12_BUFFER_CONFIG *src, return filt_err; } -static int search_bilateral_level(const YV12_BUFFER_CONFIG *src, AV1_COMP *cpi, - int filter_level, int partial_frame, - int *bilateral_level, double *best_cost_ret, - double *best_tile_cost) { +static double search_bilateral(const YV12_BUFFER_CONFIG *src, AV1_COMP *cpi, + int filter_level, int partial_frame, + RestorationInfo *info, double *best_tile_cost) { + BilateralInfo *bilateral_info = info->bilateral_info; AV1_COMMON *const cm = &cpi->common; - int i, j, tile_idx; + int i, tile_idx, subtile_idx; int64_t err; int bits; - double cost, best_cost, cost_norestore, cost_bilateral, - cost_norestore_subtile; + double cost, best_cost, cost_bilateral, cost_norestore_subtile; const int bilateral_level_bits = av1_bilateral_level_bits(&cpi->common); const int bilateral_levels = 1 << bilateral_level_bits; MACROBLOCK *x = &cpi->td.mb; @@ -120,29 +124,19 @@ static int search_bilateral_level(const YV12_BUFFER_CONFIG *src, AV1_COMP *cpi, 1, partial_frame); aom_yv12_copy_y(cm->frame_to_show, &cpi->last_frame_db); - // RD cost associated with no restoration - rsi.frame_restoration_type = RESTORE_NONE; - err = try_restoration_frame(src, cpi, &rsi, partial_frame); - // err = sse_restoration_tile(src, cm, 0, cm->width, 0, cm->height); - bits = frame_level_restore_bits[rsi.frame_restoration_type] - << AV1_PROB_COST_SHIFT; - cost_norestore = RDCOST_DBL(x->rdmult, x->rddiv, (bits >> 4), err); - - // RD cost associated with bilateral filtering rsi.frame_restoration_type = RESTORE_BILATERAL; - rsi.bilateral_level = (int *)aom_malloc(sizeof(*rsi.bilateral_level) * - ntiles * BILATERAL_SUBTILES); - assert(rsi.bilateral_level != NULL); + rsi.bilateral_info = + (BilateralInfo *)aom_malloc(sizeof(*rsi.bilateral_info) * ntiles); + assert(rsi.bilateral_info != NULL); - for (j = 0; j < ntiles * BILATERAL_SUBTILES; ++j) bilateral_level[j] = -1; + for (tile_idx = 0; tile_idx < ntiles; ++tile_idx) + for (subtile_idx = 0; subtile_idx < BILATERAL_SUBTILES; ++subtile_idx) + bilateral_info[tile_idx].level[subtile_idx] = + rsi.bilateral_info[tile_idx].level[subtile_idx] = -1; - // TODO(debargha): This is a pretty inefficient way to find the best - // parameters per tile. Needs fixing. // Find best filter for each tile for (tile_idx = 0; tile_idx < ntiles; ++tile_idx) { - int subtile_idx; for (subtile_idx = 0; subtile_idx < BILATERAL_SUBTILES; ++subtile_idx) { - const int fulltile_idx = tile_idx * BILATERAL_SUBTILES + subtile_idx; av1_get_rest_tile_limits(tile_idx, subtile_idx, BILATERAL_SUBTILE_BITS, nhtiles, nvtiles, tile_width, tile_height, cm->width, cm->height, 0, 0, &h_start, &h_end, @@ -158,181 +152,62 @@ static int search_bilateral_level(const YV12_BUFFER_CONFIG *src, AV1_COMP *cpi, cost_norestore_subtile = RDCOST_DBL(x->rdmult, x->rddiv, (bits >> 4), err); best_cost = cost_norestore_subtile; - for (j = 0; j < ntiles * BILATERAL_SUBTILES; ++j) - rsi.bilateral_level[j] = -1; for (i = 0; i < bilateral_levels; ++i) { - rsi.bilateral_level[fulltile_idx] = i; + rsi.bilateral_info[tile_idx].level[subtile_idx] = i; err = try_restoration_tile(src, cpi, &rsi, partial_frame, tile_idx, subtile_idx, BILATERAL_SUBTILE_BITS); bits = bilateral_level_bits << AV1_PROB_COST_SHIFT; bits += av1_cost_bit(RESTORE_NONE_BILATERAL_PROB, 1); cost = RDCOST_DBL(x->rdmult, x->rddiv, (bits >> 4), err); if (cost < best_cost) { - bilateral_level[fulltile_idx] = i; + bilateral_info[tile_idx].level[subtile_idx] = i; best_cost = cost; } + rsi.bilateral_info[tile_idx].level[subtile_idx] = -1; } } - if (best_tile_cost) { - bits = 0; - for (j = 0; j < ntiles * BILATERAL_SUBTILES; ++j) - rsi.bilateral_level[j] = -1; - for (subtile_idx = 0; subtile_idx < BILATERAL_SUBTILES; ++subtile_idx) { - const int fulltile_idx = tile_idx * BILATERAL_SUBTILES + subtile_idx; - rsi.bilateral_level[fulltile_idx] = bilateral_level[fulltile_idx]; - if (rsi.bilateral_level[fulltile_idx] >= 0) - bits += bilateral_level_bits << AV1_PROB_COST_SHIFT; + bits = 0; + for (subtile_idx = 0; subtile_idx < BILATERAL_SUBTILES; ++subtile_idx) { + rsi.bilateral_info[tile_idx].level[subtile_idx] = + bilateral_info[tile_idx].level[subtile_idx]; + if (rsi.bilateral_info[tile_idx].level[subtile_idx] >= 0) + bits += bilateral_level_bits << AV1_PROB_COST_SHIFT; #if BILATERAL_SUBTILES - bits += av1_cost_bit(RESTORE_NONE_BILATERAL_PROB, - rsi.bilateral_level[fulltile_idx] >= 0); + bits += + av1_cost_bit(RESTORE_NONE_BILATERAL_PROB, + rsi.bilateral_info[tile_idx].level[subtile_idx] >= 0); #endif - } - err = try_restoration_tile(src, cpi, &rsi, partial_frame, tile_idx, 0, 0); - best_tile_cost[tile_idx] = RDCOST_DBL( - x->rdmult, x->rddiv, - (bits + cpi->switchable_restore_cost[RESTORE_BILATERAL]) >> 4, err); } + err = try_restoration_tile(src, cpi, &rsi, partial_frame, tile_idx, 0, 0); + best_tile_cost[tile_idx] = RDCOST_DBL( + x->rdmult, x->rddiv, + (bits + cpi->switchable_restore_cost[RESTORE_BILATERAL]) >> 4, err); } // Find cost for combined configuration bits = frame_level_restore_bits[rsi.frame_restoration_type] << AV1_PROB_COST_SHIFT; - for (j = 0; j < ntiles * BILATERAL_SUBTILES; ++j) { - rsi.bilateral_level[j] = bilateral_level[j]; - if (rsi.bilateral_level[j] >= 0) { - bits += bilateral_level_bits << AV1_PROB_COST_SHIFT; - } + for (tile_idx = 0; tile_idx < ntiles; ++tile_idx) { + for (subtile_idx = 0; subtile_idx < BILATERAL_SUBTILES; ++subtile_idx) { + rsi.bilateral_info[tile_idx].level[subtile_idx] = + bilateral_info[tile_idx].level[subtile_idx]; + if (rsi.bilateral_info[tile_idx].level[subtile_idx] >= 0) { + bits += bilateral_level_bits << AV1_PROB_COST_SHIFT; + } #if BILATERAL_SUBTILES - bits += - av1_cost_bit(RESTORE_NONE_BILATERAL_PROB, rsi.bilateral_level[j] >= 0); + bits += + av1_cost_bit(RESTORE_NONE_BILATERAL_PROB, + rsi.bilateral_info[tile_idx].level[subtile_idx] >= 0); #endif + } } err = try_restoration_frame(src, cpi, &rsi, partial_frame); cost_bilateral = RDCOST_DBL(x->rdmult, x->rddiv, (bits >> 4), err); - aom_free(rsi.bilateral_level); + aom_free(rsi.bilateral_info); aom_yv12_copy_y(&cpi->last_frame_uf, cm->frame_to_show); - if (cost_bilateral < cost_norestore) { - if (best_cost_ret) *best_cost_ret = cost_bilateral; - return 1; - } else { - if (best_cost_ret) *best_cost_ret = cost_norestore; - return 0; - } -} - -static int search_filter_bilateral_level(const YV12_BUFFER_CONFIG *src, - AV1_COMP *cpi, int partial_frame, - int *filter_best, int *bilateral_level, - double *best_cost_ret, - double *best_tile_cost) { - const AV1_COMMON *const cm = &cpi->common; - const struct loopfilter *const lf = &cm->lf; - const int min_filter_level = 0; - const int max_filter_level = av1_get_max_filter_level(cpi); - int filt_direction = 0; - int filt_best; - double best_err; - int i, j; - int *tmp_level; - int bilateral_success[MAX_LOOP_FILTER + 1]; - - const int ntiles = - av1_get_rest_ntiles(cm->width, cm->height, NULL, NULL, NULL, NULL); - double *tile_cost = (double *)aom_malloc(sizeof(*tile_cost) * ntiles); - - // Start the search at the previous frame filter level unless it is now out of - // range. - int filt_mid = clamp(lf->filter_level, min_filter_level, max_filter_level); - int filter_step = filt_mid < 16 ? 4 : filt_mid / 4; - double ss_err[MAX_LOOP_FILTER + 1]; - // Set each entry to -1 - for (i = 0; i <= MAX_LOOP_FILTER; ++i) ss_err[i] = -1.0; - - tmp_level = - (int *)aom_malloc(sizeof(*tmp_level) * ntiles * BILATERAL_SUBTILES); - - bilateral_success[filt_mid] = search_bilateral_level( - src, cpi, filt_mid, partial_frame, tmp_level, &best_err, best_tile_cost); - filt_best = filt_mid; - ss_err[filt_mid] = best_err; - for (j = 0; j < ntiles * BILATERAL_SUBTILES; ++j) { - bilateral_level[j] = tmp_level[j]; - } - - while (filter_step > 0) { - const int filt_high = AOMMIN(filt_mid + filter_step, max_filter_level); - const int filt_low = AOMMAX(filt_mid - filter_step, min_filter_level); - - // Bias against raising loop filter in favor of lowering it. - double bias = (best_err / (1 << (15 - (filt_mid / 8)))) * filter_step; - - if ((cpi->oxcf.pass == 2) && (cpi->twopass.section_intra_rating < 20)) - bias = (bias * cpi->twopass.section_intra_rating) / 20; - - // yx, bias less for large block size - if (cm->tx_mode != ONLY_4X4) bias /= 2; - - if (filt_direction <= 0 && filt_low != filt_mid) { - // Get Low filter error score - if (ss_err[filt_low] < 0) { - bilateral_success[filt_low] = - search_bilateral_level(src, cpi, filt_low, partial_frame, tmp_level, - &ss_err[filt_low], tile_cost); - } - // If value is close to the best so far then bias towards a lower loop - // filter value. - if (ss_err[filt_low] < (best_err + bias)) { - // Was it actually better than the previous best? - if (ss_err[filt_low] < best_err) { - best_err = ss_err[filt_low]; - } - filt_best = filt_low; - for (j = 0; j < ntiles * BILATERAL_SUBTILES; ++j) { - bilateral_level[j] = tmp_level[j]; - } - memcpy(best_tile_cost, tile_cost, sizeof(*tile_cost) * ntiles); - } - } - - // Now look at filt_high - if (filt_direction >= 0 && filt_high != filt_mid) { - if (ss_err[filt_high] < 0) { - bilateral_success[filt_high] = - search_bilateral_level(src, cpi, filt_high, partial_frame, - tmp_level, &ss_err[filt_high], tile_cost); - } - // If value is significantly better than previous best, bias added against - // raising filter value - if (ss_err[filt_high] < (best_err - bias)) { - best_err = ss_err[filt_high]; - filt_best = filt_high; - for (j = 0; j < ntiles * BILATERAL_SUBTILES; ++j) { - bilateral_level[j] = tmp_level[j]; - } - memcpy(best_tile_cost, tile_cost, sizeof(*tile_cost) * ntiles); - } - } - - // Half the step distance if the best filter value was the same as last time - if (filt_best == filt_mid) { - filter_step /= 2; - filt_direction = 0; - } else { - filt_direction = (filt_best < filt_mid) ? -1 : 1; - filt_mid = filt_best; - } - } - aom_free(tmp_level); - aom_free(tile_cost); - - // Update best error - best_err = ss_err[filt_best]; - if (best_cost_ret) *best_cost_ret = best_err; - if (filter_best) *filter_best = filt_best; - - return bilateral_success[filt_best]; + return cost_bilateral; } static double find_average(uint8_t *src, int h_start, int h_end, int v_start, @@ -610,9 +485,7 @@ static double compute_score(double *M, double *H, int *vfilt, int *hfilt) { b[RESTORATION_HALFWIN] -= 2 * b[i]; } for (k = 0; k < w; ++k) { - for (l = 0; l < w; ++l) { - ab[k * w + l] = a[l] * b[k]; - } + for (l = 0; l < w; ++l) ab[k * w + l] = a[l] * b[k]; } for (k = 0; k < w * w; ++k) { P += ab[k] * M[k]; @@ -641,17 +514,15 @@ static void quantize_sym_filter(double *f, int *fi) { fi[2] = CLIP(fi[2], WIENER_FILT_TAP2_MINV, WIENER_FILT_TAP2_MAXV); } -static int search_wiener_filter(const YV12_BUFFER_CONFIG *src, AV1_COMP *cpi, - int filter_level, int partial_frame, - int (*vfilter)[RESTORATION_WIN], - int (*hfilter)[RESTORATION_WIN], - int *wiener_level, double *best_cost_ret, - double *best_tile_cost) { +static double search_wiener(const YV12_BUFFER_CONFIG *src, AV1_COMP *cpi, + int filter_level, int partial_frame, + RestorationInfo *info, double *best_tile_cost) { + WienerInfo *wiener_info = info->wiener_info; AV1_COMMON *const cm = &cpi->common; RestorationInfo rsi; int64_t err; int bits; - double cost_wiener, cost_norestore, cost_norestore_tile; + double cost_wiener, cost_norestore_tile; MACROBLOCK *x = &cpi->td.mb; double M[RESTORATION_WIN2]; double H[RESTORATION_WIN2 * RESTORATION_WIN2]; @@ -679,25 +550,14 @@ static int search_wiener_filter(const YV12_BUFFER_CONFIG *src, AV1_COMP *cpi, 1, partial_frame); aom_yv12_copy_y(cm->frame_to_show, &cpi->last_frame_db); - rsi.frame_restoration_type = RESTORE_NONE; - err = sse_restoration_tile(src, cm, 0, cm->width, 0, cm->height); - bits = frame_level_restore_bits[rsi.frame_restoration_type] - << AV1_PROB_COST_SHIFT; - cost_norestore = RDCOST_DBL(x->rdmult, x->rddiv, (bits >> 4), err); - rsi.frame_restoration_type = RESTORE_WIENER; - rsi.vfilter = - (int(*)[RESTORATION_WIN])aom_malloc(sizeof(*rsi.vfilter) * ntiles); - assert(rsi.vfilter != NULL); - rsi.hfilter = - (int(*)[RESTORATION_WIN])aom_malloc(sizeof(*rsi.hfilter) * ntiles); - assert(rsi.hfilter != NULL); - rsi.wiener_level = (int *)aom_malloc(sizeof(*rsi.wiener_level) * ntiles); - assert(rsi.wiener_level != NULL); + rsi.wiener_info = (WienerInfo *)aom_malloc(sizeof(*rsi.wiener_info) * ntiles); + assert(rsi.wiener_info != NULL); + + for (j = 0; j < ntiles; ++j) rsi.wiener_info[j].level = 0; // Compute best Wiener filters for each tile for (tile_idx = 0; tile_idx < ntiles; ++tile_idx) { - wiener_level[tile_idx] = 0; av1_get_rest_tile_limits(tile_idx, 0, 0, nhtiles, nvtiles, tile_width, tile_height, width, height, 0, 0, &h_start, &h_end, &v_start, &v_end); @@ -706,7 +566,7 @@ static int search_wiener_filter(const YV12_BUFFER_CONFIG *src, AV1_COMP *cpi, // #bits when a tile is not restored bits = av1_cost_bit(RESTORE_NONE_WIENER_PROB, 0); cost_norestore_tile = RDCOST_DBL(x->rdmult, x->rddiv, (bits >> 4), err); - if (best_tile_cost) best_tile_cost[tile_idx] = cost_norestore_tile; + best_tile_cost[tile_idx] = DBL_MAX; av1_get_rest_tile_limits(tile_idx, 0, 0, nhtiles, nvtiles, tile_width, tile_height, width, height, 1, 1, &h_start, &h_end, @@ -720,91 +580,78 @@ static int search_wiener_filter(const YV12_BUFFER_CONFIG *src, AV1_COMP *cpi, compute_stats(dgd->y_buffer, src->y_buffer, h_start, h_end, v_start, v_end, dgd_stride, src_stride, M, H); + wiener_info[tile_idx].level = 1; if (!wiener_decompose_sep_sym(M, H, vfilterd, hfilterd)) { - for (i = 0; i < RESTORATION_HALFWIN; ++i) - rsi.vfilter[tile_idx][i] = rsi.hfilter[tile_idx][i] = 0; - wiener_level[tile_idx] = 0; + wiener_info[tile_idx].level = 0; continue; } - quantize_sym_filter(vfilterd, rsi.vfilter[tile_idx]); - quantize_sym_filter(hfilterd, rsi.hfilter[tile_idx]); - wiener_level[tile_idx] = 1; + quantize_sym_filter(vfilterd, rsi.wiener_info[tile_idx].vfilter); + quantize_sym_filter(hfilterd, rsi.wiener_info[tile_idx].hfilter); // Filter score computes the value of the function x'*A*x - x'*b for the // learned filter and compares it against identity filer. If there is no // reduction in the function, the filter is reverted back to identity - score = compute_score(M, H, rsi.vfilter[tile_idx], rsi.hfilter[tile_idx]); + score = compute_score(M, H, rsi.wiener_info[tile_idx].vfilter, + rsi.wiener_info[tile_idx].hfilter); if (score > 0.0) { - for (i = 0; i < RESTORATION_HALFWIN; ++i) - rsi.vfilter[tile_idx][i] = rsi.hfilter[tile_idx][i] = 0; - wiener_level[tile_idx] = 0; + wiener_info[tile_idx].level = 0; continue; } - for (j = 0; j < ntiles; ++j) rsi.wiener_level[j] = 0; - rsi.wiener_level[tile_idx] = 1; - + rsi.wiener_info[tile_idx].level = 1; err = try_restoration_tile(src, cpi, &rsi, partial_frame, tile_idx, 0, 0); bits = WIENER_FILT_BITS << AV1_PROB_COST_SHIFT; bits += av1_cost_bit(RESTORE_NONE_WIENER_PROB, 1); cost_wiener = RDCOST_DBL(x->rdmult, x->rddiv, (bits >> 4), err); - if (cost_wiener >= cost_norestore_tile) wiener_level[tile_idx] = 0; - if (best_tile_cost) { + if (cost_wiener >= cost_norestore_tile) { + wiener_info[tile_idx].level = 0; + } else { + wiener_info[tile_idx].level = 1; + for (i = 0; i < RESTORATION_HALFWIN; ++i) { + wiener_info[tile_idx].vfilter[i] = rsi.wiener_info[tile_idx].vfilter[i]; + wiener_info[tile_idx].hfilter[i] = rsi.wiener_info[tile_idx].hfilter[i]; + } bits = WIENER_FILT_BITS << AV1_PROB_COST_SHIFT; best_tile_cost[tile_idx] = RDCOST_DBL( x->rdmult, x->rddiv, (bits + cpi->switchable_restore_cost[RESTORE_WIENER]) >> 4, err); } + rsi.wiener_info[tile_idx].level = 0; } // Cost for Wiener filtering bits = frame_level_restore_bits[rsi.frame_restoration_type] << AV1_PROB_COST_SHIFT; for (tile_idx = 0; tile_idx < ntiles; ++tile_idx) { - bits += av1_cost_bit(RESTORE_NONE_WIENER_PROB, wiener_level[tile_idx]); - if (wiener_level[tile_idx]) + bits += av1_cost_bit(RESTORE_NONE_WIENER_PROB, wiener_info[tile_idx].level); + rsi.wiener_info[tile_idx].level = wiener_info[tile_idx].level; + if (wiener_info[tile_idx].level) { bits += (WIENER_FILT_BITS << AV1_PROB_COST_SHIFT); - rsi.wiener_level[tile_idx] = wiener_level[tile_idx]; + for (i = 0; i < RESTORATION_HALFWIN; ++i) { + rsi.wiener_info[tile_idx].vfilter[i] = wiener_info[tile_idx].vfilter[i]; + rsi.wiener_info[tile_idx].hfilter[i] = wiener_info[tile_idx].hfilter[i]; + } + } } - // TODO(debargha): This is a pretty inefficient way to find the error - // for the whole frame. Specialize for a specific tile. err = try_restoration_frame(src, cpi, &rsi, partial_frame); cost_wiener = RDCOST_DBL(x->rdmult, x->rddiv, (bits >> 4), err); - - for (tile_idx = 0; tile_idx < ntiles; ++tile_idx) { - if (wiener_level[tile_idx] == 0) continue; - for (i = 0; i < RESTORATION_HALFWIN; ++i) { - vfilter[tile_idx][i] = rsi.vfilter[tile_idx][i]; - hfilter[tile_idx][i] = rsi.hfilter[tile_idx][i]; - } - } - - aom_free(rsi.vfilter); - aom_free(rsi.hfilter); - aom_free(rsi.wiener_level); + aom_free(rsi.wiener_info); aom_yv12_copy_y(&cpi->last_frame_uf, cm->frame_to_show); - if (cost_wiener < cost_norestore) { - if (best_cost_ret) *best_cost_ret = cost_wiener; - return 1; - } else { - if (best_cost_ret) *best_cost_ret = cost_norestore; - return 0; - } + return cost_wiener; } -static int search_switchable_restoration( - const YV12_BUFFER_CONFIG *src, AV1_COMP *cpi, int filter_level, - int partial_frame, RestorationInfo *rsi, double *tile_cost_bilateral, - double *tile_cost_wiener, double *best_cost_ret) { - AV1_COMMON *const cm = &cpi->common; - const int bilateral_level_bits = av1_bilateral_level_bits(&cpi->common); +static double search_norestore(const YV12_BUFFER_CONFIG *src, AV1_COMP *cpi, + int filter_level, int partial_frame, + RestorationInfo *info, double *best_tile_cost) { + double err, cost_norestore; + int bits; MACROBLOCK *x = &cpi->td.mb; - double err, cost_norestore, cost_norestore_tile, cost_switchable; - int bits, tile_idx; - int tile_width, tile_height, nhtiles, nvtiles; + AV1_COMMON *const cm = &cpi->common; + int tile_idx, tile_width, tile_height, nhtiles, nvtiles; int h_start, h_end, v_start, v_end; const int ntiles = av1_get_rest_ntiles(cm->width, cm->height, &tile_width, &tile_height, &nhtiles, &nvtiles); + (void)info; // Make a copy of the unfiltered / processed recon buffer aom_yv12_copy_y(cm->frame_to_show, &cpi->last_frame_uf); @@ -812,99 +659,86 @@ static int search_switchable_restoration( 1, partial_frame); aom_yv12_copy_y(cm->frame_to_show, &cpi->last_frame_db); - // RD cost associated with no restoration - rsi->frame_restoration_type = RESTORE_NONE; - err = sse_restoration_tile(src, cm, 0, cm->width, 0, cm->height); - bits = frame_level_restore_bits[rsi->frame_restoration_type] - << AV1_PROB_COST_SHIFT; - cost_norestore = RDCOST_DBL(x->rdmult, x->rddiv, (bits >> 4), err); - - rsi->frame_restoration_type = RESTORE_SWITCHABLE; - bits = frame_level_restore_bits[rsi->frame_restoration_type] - << AV1_PROB_COST_SHIFT; for (tile_idx = 0; tile_idx < ntiles; ++tile_idx) { av1_get_rest_tile_limits(tile_idx, 0, 0, nhtiles, nvtiles, tile_width, tile_height, cm->width, cm->height, 0, 0, &h_start, &h_end, &v_start, &v_end); err = sse_restoration_tile(src, cm, h_start, h_end - h_start, v_start, v_end - v_start); - cost_norestore_tile = + best_tile_cost[tile_idx] = RDCOST_DBL(x->rdmult, x->rddiv, (cpi->switchable_restore_cost[RESTORE_NONE] >> 4), err); - if (tile_cost_wiener[tile_idx] > cost_norestore_tile && - tile_cost_bilateral[tile_idx] > cost_norestore_tile) { - rsi->restoration_type[tile_idx] = RESTORE_NONE; - } else { - rsi->restoration_type[tile_idx] = - tile_cost_wiener[tile_idx] < tile_cost_bilateral[tile_idx] - ? RESTORE_WIENER - : RESTORE_BILATERAL; - if (rsi->restoration_type[tile_idx] == RESTORE_WIENER) { - if (rsi->wiener_level[tile_idx]) { - bits += (WIENER_FILT_BITS << AV1_PROB_COST_SHIFT); - } else { - rsi->restoration_type[tile_idx] = RESTORE_NONE; - } - } else { - int s; - for (s = 0; s < BILATERAL_SUBTILES; ++s) { -#if BILATERAL_SUBTILES - bits += av1_cost_bit( - RESTORE_NONE_BILATERAL_PROB, - rsi->bilateral_level[tile_idx * BILATERAL_SUBTILES + s] >= 0); -#endif - if (rsi->bilateral_level[tile_idx * BILATERAL_SUBTILES + s] >= 0) - bits += bilateral_level_bits << AV1_PROB_COST_SHIFT; - } + } + // RD cost associated with no restoration + err = sse_restoration_tile(src, cm, 0, cm->width, 0, cm->height); + bits = frame_level_restore_bits[RESTORE_NONE] << AV1_PROB_COST_SHIFT; + cost_norestore = RDCOST_DBL(x->rdmult, x->rddiv, (bits >> 4), err); + aom_yv12_copy_y(&cpi->last_frame_uf, cm->frame_to_show); + return cost_norestore; +} + +static double search_switchable_restoration( + AV1_COMP *cpi, int filter_level, int partial_frame, RestorationInfo *rsi, + double *tile_cost[RESTORE_SWITCHABLE_TYPES]) { + AV1_COMMON *const cm = &cpi->common; + MACROBLOCK *x = &cpi->td.mb; + double cost_switchable = 0; + int r, bits, tile_idx; + const int ntiles = + av1_get_rest_ntiles(cm->width, cm->height, NULL, NULL, NULL, NULL); + + // Make a copy of the unfiltered / processed recon buffer + aom_yv12_copy_y(cm->frame_to_show, &cpi->last_frame_uf); + av1_loop_filter_frame(cm->frame_to_show, cm, &cpi->td.mb.e_mbd, filter_level, + 1, partial_frame); + aom_yv12_copy_y(cm->frame_to_show, &cpi->last_frame_db); + + rsi->frame_restoration_type = RESTORE_SWITCHABLE; + bits = frame_level_restore_bits[rsi->frame_restoration_type] + << AV1_PROB_COST_SHIFT; + cost_switchable = RDCOST_DBL(x->rdmult, x->rddiv, bits >> 4, 0); + for (tile_idx = 0; tile_idx < ntiles; ++tile_idx) { + double best_cost = tile_cost[RESTORE_NONE][tile_idx]; + rsi->restoration_type[tile_idx] = RESTORE_NONE; + for (r = 1; r < RESTORE_SWITCHABLE_TYPES; r++) { + if (tile_cost[r][tile_idx] < best_cost) { + rsi->restoration_type[tile_idx] = r; + best_cost = tile_cost[r][tile_idx]; } } - bits += cpi->switchable_restore_cost[rsi->restoration_type[tile_idx]]; + cost_switchable += best_cost; } - err = try_restoration_frame(src, cpi, rsi, partial_frame); - cost_switchable = RDCOST_DBL(x->rdmult, x->rddiv, (bits >> 4), err); aom_yv12_copy_y(&cpi->last_frame_uf, cm->frame_to_show); - if (cost_switchable < cost_norestore) { - *best_cost_ret = cost_switchable; - return 1; - } else { - *best_cost_ret = cost_norestore; - return 0; - } + return cost_switchable; } void av1_pick_filter_restoration(const YV12_BUFFER_CONFIG *src, AV1_COMP *cpi, LPF_PICK_METHOD method) { + static search_restore_type search_restore_fun[RESTORE_SWITCHABLE_TYPES] = { + search_norestore, search_bilateral, search_wiener, + }; AV1_COMMON *const cm = &cpi->common; struct loopfilter *const lf = &cm->lf; - int wiener_success = 0; - int bilateral_success = 0; - int switchable_success = 0; - double cost_bilateral = DBL_MAX; - double cost_wiener = DBL_MAX; - // double cost_norestore = DBL_MAX; - double cost_switchable = DBL_MAX; - double *tile_cost_bilateral, *tile_cost_wiener; + double cost_restore[RESTORE_TYPES]; + double *tile_cost[RESTORE_SWITCHABLE_TYPES]; + double best_cost_restore; + RestorationType r, best_restore; + const int ntiles = av1_get_rest_ntiles(cm->width, cm->height, NULL, NULL, NULL, NULL); cm->rst_info.restoration_type = (RestorationType *)aom_realloc( cm->rst_info.restoration_type, sizeof(*cm->rst_info.restoration_type) * ntiles); - cm->rst_info.bilateral_level = (int *)aom_realloc( - cm->rst_info.bilateral_level, - sizeof(*cm->rst_info.bilateral_level) * ntiles * BILATERAL_SUBTILES); - assert(cm->rst_info.bilateral_level != NULL); - - cm->rst_info.wiener_level = (int *)aom_realloc( - cm->rst_info.wiener_level, sizeof(*cm->rst_info.wiener_level) * ntiles); - assert(cm->rst_info.wiener_level != NULL); - cm->rst_info.vfilter = (int(*)[RESTORATION_WIN])aom_realloc( - cm->rst_info.vfilter, sizeof(*cm->rst_info.vfilter) * ntiles); - assert(cm->rst_info.vfilter != NULL); - cm->rst_info.hfilter = (int(*)[RESTORATION_WIN])aom_realloc( - cm->rst_info.hfilter, sizeof(*cm->rst_info.hfilter) * ntiles); - assert(cm->rst_info.hfilter != NULL); - tile_cost_wiener = (double *)aom_malloc(sizeof(cost_wiener) * ntiles); - tile_cost_bilateral = (double *)aom_malloc(sizeof(cost_bilateral) * ntiles); + cm->rst_info.bilateral_info = (BilateralInfo *)aom_realloc( + cm->rst_info.bilateral_info, + sizeof(*cm->rst_info.bilateral_info) * ntiles); + assert(cm->rst_info.bilateral_info != NULL); + cm->rst_info.wiener_info = (WienerInfo *)aom_realloc( + cm->rst_info.wiener_info, sizeof(*cm->rst_info.wiener_info) * ntiles); + assert(cm->rst_info.wiener_info != NULL); + + for (r = 0; r < RESTORE_SWITCHABLE_TYPES; r++) + tile_cost[r] = (double *)aom_malloc(sizeof(*tile_cost[0]) * ntiles); lf->sharpness_level = cm->frame_type == KEY_FRAME ? 0 : cpi->oxcf.sharpness; @@ -940,52 +774,34 @@ void av1_pick_filter_restoration(const YV12_BUFFER_CONFIG *src, AV1_COMP *cpi, #endif // CONFIG_AOM_HIGHBITDEPTH if (cm->frame_type == KEY_FRAME) filt_guess -= 4; lf->filter_level = clamp(filt_guess, min_filter_level, max_filter_level); - bilateral_success = search_bilateral_level( - src, cpi, lf->filter_level, method == LPF_PICK_FROM_SUBIMAGE, - cm->rst_info.bilateral_level, &cost_bilateral, tile_cost_bilateral); - wiener_success = search_wiener_filter( - src, cpi, lf->filter_level, method == LPF_PICK_FROM_SUBIMAGE, - cm->rst_info.vfilter, cm->rst_info.hfilter, cm->rst_info.wiener_level, - &cost_wiener, tile_cost_wiener); - switchable_success = search_switchable_restoration( - src, cpi, lf->filter_level, method == LPF_PICK_FROM_SUBIMAGE, - &cm->rst_info, tile_cost_bilateral, tile_cost_wiener, &cost_switchable); } else { - // lf->filter_level = av1_search_filter_level( - // src, cpi, method == LPF_PICK_FROM_SUBIMAGE, &cost_norestore); - // bilateral_success = search_bilateral_level( - // src, cpi, lf->filter_level, method == LPF_PICK_FROM_SUBIMAGE, - // cm->rst_info.bilateral_level, &cost_bilateral, tile_cost_bilateral); - bilateral_success = search_filter_bilateral_level( - src, cpi, method == LPF_PICK_FROM_SUBIMAGE, &lf->filter_level, - cm->rst_info.bilateral_level, &cost_bilateral, tile_cost_bilateral); - wiener_success = search_wiener_filter( - src, cpi, lf->filter_level, method == LPF_PICK_FROM_SUBIMAGE, - cm->rst_info.vfilter, cm->rst_info.hfilter, cm->rst_info.wiener_level, - &cost_wiener, tile_cost_wiener); - switchable_success = search_switchable_restoration( - src, cpi, lf->filter_level, method == LPF_PICK_FROM_SUBIMAGE, - &cm->rst_info, tile_cost_bilateral, tile_cost_wiener, &cost_switchable); - } - if (cost_bilateral < AOMMIN(cost_wiener, cost_switchable)) { - if (bilateral_success) - cm->rst_info.frame_restoration_type = RESTORE_BILATERAL; - else - cm->rst_info.frame_restoration_type = RESTORE_NONE; - } else if (cost_wiener < AOMMIN(cost_bilateral, cost_switchable)) { - if (wiener_success) - cm->rst_info.frame_restoration_type = RESTORE_WIENER; - else - cm->rst_info.frame_restoration_type = RESTORE_NONE; - } else { - if (switchable_success) - cm->rst_info.frame_restoration_type = RESTORE_SWITCHABLE; - else - cm->rst_info.frame_restoration_type = RESTORE_NONE; + lf->filter_level = + av1_search_filter_level(src, cpi, method == LPF_PICK_FROM_SUBIMAGE, + &cost_restore[RESTORE_NONE]); + } + for (r = 0; r < RESTORE_SWITCHABLE_TYPES; ++r) { + cost_restore[r] = search_restore_fun[r](src, cpi, lf->filter_level, + method == LPF_PICK_FROM_SUBIMAGE, + &cm->rst_info, tile_cost[r]); + } + cost_restore[RESTORE_SWITCHABLE] = search_switchable_restoration( + cpi, lf->filter_level, method == LPF_PICK_FROM_SUBIMAGE, &cm->rst_info, + tile_cost); + + best_cost_restore = DBL_MAX; + best_restore = 0; + for (r = 0; r < RESTORE_TYPES; ++r) { + if (cost_restore[r] < best_cost_restore) { + best_restore = r; + best_cost_restore = cost_restore[r]; + } } - printf("Frame %d frame_restore_type %d [%d]: %f %f %f\n", - cm->current_video_frame, cm->rst_info.frame_restoration_type, ntiles, - cost_bilateral, cost_wiener, cost_switchable); - aom_free(tile_cost_bilateral); - aom_free(tile_cost_wiener); + cm->rst_info.frame_restoration_type = best_restore; + /* + printf("Frame %d/%d frame_restore_type %d : %f %f %f %f\n", + cm->current_video_frame, cm->show_frame, + cm->rst_info.frame_restoration_type, + cost_restore[0], cost_restore[1], cost_restore[2], cost_restore[3]); + */ + for (r = 0; r < RESTORE_SWITCHABLE_TYPES; r++) aom_free(tile_cost[r]); }