Commit e40e6e57 authored by Aamir Anis's avatar Aamir Anis Committed by Debargha Mukherjee

Tiling in loop restoration + cosmetics

Frame can be split into rectangular tiles for application of separate
bilateral or Wiener filters per tile. Some variable names changed for
better readability.

Change-Id: I13ebc4d0b0baf368e524db5ce276f03ed76af9c8
parent 04ed7ad5
...@@ -82,7 +82,14 @@ void vp10_free_ref_frame_buffers(BufferPool *pool) { ...@@ -82,7 +82,14 @@ void vp10_free_ref_frame_buffers(BufferPool *pool) {
#if CONFIG_LOOP_RESTORATION #if CONFIG_LOOP_RESTORATION
void vp10_free_restoration_buffers(VP10_COMMON *cm) { void vp10_free_restoration_buffers(VP10_COMMON *cm) {
vpx_free_frame_buffer(&cm->tmp_loop_buf); vpx_free(cm->rst_info.bilateral_level);
cm->rst_info.bilateral_level = NULL;
vpx_free(cm->rst_info.vfilter);
cm->rst_info.vfilter = NULL;
vpx_free(cm->rst_info.hfilter);
cm->rst_info.hfilter = NULL;
vpx_free(cm->rst_info.wiener_level);
cm->rst_info.wiener_level = NULL;
} }
#endif // CONFIG_LOOP_RESTORATION #endif // CONFIG_LOOP_RESTORATION
......
...@@ -1602,7 +1602,10 @@ void vp10_setup_past_independence(VP10_COMMON *cm) { ...@@ -1602,7 +1602,10 @@ void vp10_setup_past_independence(VP10_COMMON *cm) {
// To force update of the sharpness // To force update of the sharpness
lf->last_sharpness_level = -1; lf->last_sharpness_level = -1;
#if CONFIG_LOOP_RESTORATION #if CONFIG_LOOP_RESTORATION
cm->rst_info.restoration_level = -1; if (cm->rst_info.bilateral_level) {
for (i = 0; i < cm->rst_internal.ntiles; ++i)
cm->rst_info.bilateral_level[i] = -1;
}
#endif // CONFIG_LOOP_RESTORATION #endif // CONFIG_LOOP_RESTORATION
vp10_default_coef_probs(cm); vp10_default_coef_probs(cm);
......
...@@ -168,10 +168,6 @@ typedef struct VP10Common { ...@@ -168,10 +168,6 @@ typedef struct VP10Common {
int new_fb_idx; int new_fb_idx;
#if CONFIG_LOOP_RESTORATION
YV12_BUFFER_CONFIG tmp_loop_buf;
#endif // CONFIG_LOOP_RESTORATION
FRAME_TYPE last_frame_type; /* last frame's frame type for motion search.*/ FRAME_TYPE last_frame_type; /* last frame's frame type for motion search.*/
#if CONFIG_EXT_REFS #if CONFIG_EXT_REFS
// frame type of the frame before last frame // frame type of the frame before last frame
......
...@@ -18,33 +18,33 @@ ...@@ -18,33 +18,33 @@
#include "vpx_mem/vpx_mem.h" #include "vpx_mem/vpx_mem.h"
#include "vpx_ports/mem.h" #include "vpx_ports/mem.h"
#define RESTORATION_PARAM_PRECISION 16 #define BILATERAL_PARAM_PRECISION 16
#define RESTORATION_RANGE 256 #define BILATERAL_AMP_RANGE 256
#define RESTORATION_RANGE_SYM (2 * RESTORATION_RANGE + 1) #define BILATERAL_AMP_RANGE_SYM (2 * BILATERAL_AMP_RANGE + 1)
static uint8_t static uint8_t
restoration_filters_r_kf[RESTORATION_LEVELS_KF][RESTORATION_RANGE_SYM]; bilateral_filter_coeffs_r_kf[BILATERAL_LEVELS_KF][BILATERAL_AMP_RANGE_SYM];
static uint8_t restoration_filters_r[RESTORATION_LEVELS][RESTORATION_RANGE_SYM];
static uint8_t restoration_filters_s_kf[RESTORATION_LEVELS_KF][RESTORATION_WIN]
[RESTORATION_WIN];
static uint8_t static uint8_t
restoration_filters_s[RESTORATION_LEVELS][RESTORATION_WIN][RESTORATION_WIN]; bilateral_filter_coeffs_r[BILATERAL_LEVELS][BILATERAL_AMP_RANGE_SYM];
static uint8_t bilateral_filter_coeffs_s_kf[BILATERAL_LEVELS_KF]
[RESTORATION_WIN][RESTORATION_WIN];
static uint8_t bilateral_filter_coeffs_s[BILATERAL_LEVELS][RESTORATION_WIN]
[RESTORATION_WIN];
typedef struct restoration_params { typedef struct bilateral_params {
int sigma_x; // spatial variance x int sigma_x; // spatial variance x
int sigma_y; // spatial variance y int sigma_y; // spatial variance y
int sigma_r; // range variance int sigma_r; // range variance
} RestorationParamsType; } BilateralParamsType;
static RestorationParamsType static BilateralParamsType bilateral_level_to_params_arr[BILATERAL_LEVELS] = {
restoration_level_to_params_arr[RESTORATION_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 },
{ 8, 9, 30 }, { 9, 8, 30 }, { 9, 11, 32 }, { 11, 9, 32 }, { 14, 14, 32 }, { 18, 18, 36 }, { 24, 24, 40 }, { 32, 32, 40 },
{ 14, 14, 32 }, { 18, 18, 36 }, { 24, 24, 40 }, { 32, 32, 40 }, };
};
static RestorationParamsType static BilateralParamsType
restoration_level_to_params_arr_kf[RESTORATION_LEVELS_KF] = { 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 }, { 8, 8, 30 }, { 9, 9, 32 }, { 10, 10, 32 }, { 12, 12, 32 },
{ 14, 14, 32 }, { 18, 18, 36 }, { 24, 24, 40 }, { 30, 30, 44 }, { 14, 14, 32 }, { 18, 18, 36 }, { 24, 24, 40 }, { 30, 30, 44 },
...@@ -55,7 +55,6 @@ static RestorationParamsType ...@@ -55,7 +55,6 @@ static RestorationParamsType
typedef void (*restore_func_type)(uint8_t *data8, int width, int height, typedef void (*restore_func_type)(uint8_t *data8, int width, int height,
int stride, RestorationInternal *rst, int stride, RestorationInternal *rst,
uint8_t *tmpdata8, int tmpstride); uint8_t *tmpdata8, int tmpstride);
#if CONFIG_VP9_HIGHBITDEPTH #if CONFIG_VP9_HIGHBITDEPTH
typedef void (*restore_func_highbd_type)(uint8_t *data8, int width, int height, typedef void (*restore_func_highbd_type)(uint8_t *data8, int width, int height,
int stride, RestorationInternal *rst, int stride, RestorationInternal *rst,
...@@ -63,26 +62,56 @@ typedef void (*restore_func_highbd_type)(uint8_t *data8, int width, int height, ...@@ -63,26 +62,56 @@ typedef void (*restore_func_highbd_type)(uint8_t *data8, int width, int height,
int bit_depth); int bit_depth);
#endif // CONFIG_VP9_HIGHBITDEPTH #endif // CONFIG_VP9_HIGHBITDEPTH
static INLINE RestorationParamsType vp10_restoration_level_to_params(int index, static INLINE BilateralParamsType vp10_bilateral_level_to_params(int index,
int kf) { int kf) {
return kf ? restoration_level_to_params_arr_kf[index] return kf ? bilateral_level_to_params_arr_kf[index]
: restoration_level_to_params_arr[index]; : bilateral_level_to_params_arr[index];
}
typedef struct TileParams {
int width;
int height;
} TileParams;
static TileParams restoration_tile_sizes[RESTORATION_TILESIZES] = {
{ 64, 64 }, { 128, 128 }, { 256, 256 }
};
void vp10_get_restoration_tile_size(int tilesize, int width, int height,
int *tile_width, int *tile_height,
int *nhtiles, int *nvtiles) {
*tile_width = (tilesize < 0)
? width
: VPXMIN(restoration_tile_sizes[tilesize].width, width);
*tile_height = (tilesize < 0)
? height
: VPXMIN(restoration_tile_sizes[tilesize].height, height);
*nhtiles = (width + (*tile_width >> 1)) / *tile_width;
*nvtiles = (height + (*tile_height >> 1)) / *tile_height;
}
int vp10_get_restoration_ntiles(int tilesize, int width, int height) {
int nhtiles, nvtiles;
int tile_width, tile_height;
vp10_get_restoration_tile_size(tilesize, width, height, &tile_width,
&tile_height, &nhtiles, &nvtiles);
return (nhtiles * nvtiles);
} }
void vp10_loop_restoration_precal() { void vp10_loop_restoration_precal() {
int i; int i;
for (i = 0; i < RESTORATION_LEVELS_KF; i++) { for (i = 0; i < BILATERAL_LEVELS_KF; i++) {
const RestorationParamsType param = vp10_restoration_level_to_params(i, 1); const BilateralParamsType param = vp10_bilateral_level_to_params(i, 1);
const int sigma_x = param.sigma_x; const int sigma_x = param.sigma_x;
const int sigma_y = param.sigma_y; const int sigma_y = param.sigma_y;
const int sigma_r = param.sigma_r; const int sigma_r = param.sigma_r;
const double sigma_r_d = (double)sigma_r / RESTORATION_PARAM_PRECISION; const double sigma_r_d = (double)sigma_r / BILATERAL_PARAM_PRECISION;
const double sigma_x_d = (double)sigma_x / RESTORATION_PARAM_PRECISION; const double sigma_x_d = (double)sigma_x / BILATERAL_PARAM_PRECISION;
const double sigma_y_d = (double)sigma_y / RESTORATION_PARAM_PRECISION; const double sigma_y_d = (double)sigma_y / BILATERAL_PARAM_PRECISION;
uint8_t *fr = restoration_filters_r_kf[i] + RESTORATION_RANGE; uint8_t *fr = bilateral_filter_coeffs_r_kf[i] + BILATERAL_AMP_RANGE;
int j, x, y; int j, x, y;
for (j = 0; j <= RESTORATION_RANGE; j++) { for (j = 0; j <= BILATERAL_AMP_RANGE; j++) {
fr[j] = (uint8_t)(0.5 + fr[j] = (uint8_t)(0.5 +
RESTORATION_FILT_STEP * RESTORATION_FILT_STEP *
exp(-(j * j) / (2 * sigma_r_d * sigma_r_d))); exp(-(j * j) / (2 * sigma_r_d * sigma_r_d)));
...@@ -90,28 +119,27 @@ void vp10_loop_restoration_precal() { ...@@ -90,28 +119,27 @@ void vp10_loop_restoration_precal() {
} }
for (y = -RESTORATION_HALFWIN; y <= RESTORATION_HALFWIN; y++) { for (y = -RESTORATION_HALFWIN; y <= RESTORATION_HALFWIN; y++) {
for (x = -RESTORATION_HALFWIN; x <= RESTORATION_HALFWIN; x++) { for (x = -RESTORATION_HALFWIN; x <= RESTORATION_HALFWIN; x++) {
restoration_filters_s_kf[i][y + bilateral_filter_coeffs_s_kf
RESTORATION_HALFWIN][x + [i][y + RESTORATION_HALFWIN][x + RESTORATION_HALFWIN] =
RESTORATION_HALFWIN] = (uint8_t)(0.5 +
(uint8_t)(0.5 + RESTORATION_FILT_STEP *
RESTORATION_FILT_STEP * exp(-(x * x) / (2 * sigma_x_d * sigma_x_d) -
exp(-(x * x) / (2 * sigma_x_d * sigma_x_d) - (y * y) / (2 * sigma_y_d * sigma_y_d)));
(y * y) / (2 * sigma_y_d * sigma_y_d)));
} }
} }
} }
for (i = 0; i < RESTORATION_LEVELS; i++) { for (i = 0; i < BILATERAL_LEVELS; i++) {
const RestorationParamsType param = vp10_restoration_level_to_params(i, 0); const BilateralParamsType param = vp10_bilateral_level_to_params(i, 0);
const int sigma_x = param.sigma_x; const int sigma_x = param.sigma_x;
const int sigma_y = param.sigma_y; const int sigma_y = param.sigma_y;
const int sigma_r = param.sigma_r; const int sigma_r = param.sigma_r;
const double sigma_r_d = (double)sigma_r / RESTORATION_PARAM_PRECISION; const double sigma_r_d = (double)sigma_r / BILATERAL_PARAM_PRECISION;
const double sigma_x_d = (double)sigma_x / RESTORATION_PARAM_PRECISION; const double sigma_x_d = (double)sigma_x / BILATERAL_PARAM_PRECISION;
const double sigma_y_d = (double)sigma_y / RESTORATION_PARAM_PRECISION; const double sigma_y_d = (double)sigma_y / BILATERAL_PARAM_PRECISION;
uint8_t *fr = restoration_filters_r[i] + RESTORATION_RANGE; uint8_t *fr = bilateral_filter_coeffs_r[i] + BILATERAL_AMP_RANGE;
int j, x, y; int j, x, y;
for (j = 0; j <= RESTORATION_RANGE; j++) { for (j = 0; j <= BILATERAL_AMP_RANGE; j++) {
fr[j] = (uint8_t)(0.5 + fr[j] = (uint8_t)(0.5 +
RESTORATION_FILT_STEP * RESTORATION_FILT_STEP *
exp(-(j * j) / (2 * sigma_r_d * sigma_r_d))); exp(-(j * j) / (2 * sigma_r_d * sigma_r_d)));
...@@ -119,7 +147,8 @@ void vp10_loop_restoration_precal() { ...@@ -119,7 +147,8 @@ void vp10_loop_restoration_precal() {
} }
for (y = -RESTORATION_HALFWIN; y <= RESTORATION_HALFWIN; y++) { for (y = -RESTORATION_HALFWIN; y <= RESTORATION_HALFWIN; y++) {
for (x = -RESTORATION_HALFWIN; x <= RESTORATION_HALFWIN; x++) { for (x = -RESTORATION_HALFWIN; x <= RESTORATION_HALFWIN; x++) {
restoration_filters_s[i][y + RESTORATION_HALFWIN][x + bilateral_filter_coeffs_s[i][y +
RESTORATION_HALFWIN][x +
RESTORATION_HALFWIN] = RESTORATION_HALFWIN] =
(uint8_t)(0.5 + (uint8_t)(0.5 +
RESTORATION_FILT_STEP * RESTORATION_FILT_STEP *
...@@ -130,31 +159,68 @@ void vp10_loop_restoration_precal() { ...@@ -130,31 +159,68 @@ void vp10_loop_restoration_precal() {
} }
} }
int vp10_restoration_level_bits(const VP10_COMMON *const cm) { int vp10_bilateral_level_bits(const VP10_COMMON *const cm) {
return cm->frame_type == KEY_FRAME ? RESTORATION_LEVEL_BITS_KF return cm->frame_type == KEY_FRAME ? BILATERAL_LEVEL_BITS_KF
: RESTORATION_LEVEL_BITS; : BILATERAL_LEVEL_BITS;
} }
void vp10_loop_restoration_init(RestorationInternal *rst, RestorationInfo *rsi, void vp10_loop_restoration_init(RestorationInternal *rst, RestorationInfo *rsi,
int kf) { int kf, int width, int height) {
int i; int i, tile_idx;
rst->restoration_type = rsi->restoration_type; rst->restoration_type = rsi->restoration_type;
rst->subsampling_x = 0;
rst->subsampling_y = 0;
if (rsi->restoration_type == RESTORE_BILATERAL) { if (rsi->restoration_type == RESTORE_BILATERAL) {
const int level = rsi->restoration_level; rst->tilesize_index = BILATERAL_TILESIZE;
assert(level >= 0); rst->ntiles =
rst->wr_lut = vp10_get_restoration_ntiles(rst->tilesize_index, width, height);
kf ? restoration_filters_r_kf[level] : restoration_filters_r[level]; vp10_get_restoration_tile_size(rst->tilesize_index, width, height,
for (i = 0; i < RESTORATION_WIN; i++) &rst->tile_width, &rst->tile_height,
rst->wx_lut[i] = kf ? restoration_filters_s_kf[level][i] &rst->nhtiles, &rst->nvtiles);
: restoration_filters_s[level][i]; rst->bilateral_level = rsi->bilateral_level;
rst->wr_lut = (uint8_t **)malloc(sizeof(*rst->wr_lut) * rst->ntiles);
assert(rst->wr_lut != NULL);
rst->wx_lut = (uint8_t(**)[RESTORATION_WIN])malloc(sizeof(*rst->wx_lut) *
rst->ntiles);
assert(rst->wx_lut != NULL);
for (tile_idx = 0; tile_idx < rst->ntiles; ++tile_idx) {
const int level = rsi->bilateral_level[tile_idx];
if (level >= 0) {
rst->wr_lut[tile_idx] = kf ? bilateral_filter_coeffs_r_kf[level]
: bilateral_filter_coeffs_r[level];
rst->wx_lut[tile_idx] = kf ? bilateral_filter_coeffs_s_kf[level]
: bilateral_filter_coeffs_s[level];
}
}
} else if (rsi->restoration_type == RESTORE_WIENER) { } else if (rsi->restoration_type == RESTORE_WIENER) {
rst->vfilter[RESTORATION_HALFWIN] = rst->hfilter[RESTORATION_HALFWIN] = rst->tilesize_index = WIENER_TILESIZE;
RESTORATION_FILT_STEP; rst->ntiles =
for (i = 0; i < RESTORATION_HALFWIN; ++i) { vp10_get_restoration_ntiles(rst->tilesize_index, width, height);
rst->vfilter[i] = rst->vfilter[RESTORATION_WIN - 1 - i] = rsi->vfilter[i]; vp10_get_restoration_tile_size(rst->tilesize_index, width, height,
rst->hfilter[i] = rst->hfilter[RESTORATION_WIN - 1 - i] = rsi->hfilter[i]; &rst->tile_width, &rst->tile_height,
rst->vfilter[RESTORATION_HALFWIN] -= 2 * rsi->vfilter[i]; &rst->nhtiles, &rst->nvtiles);
rst->hfilter[RESTORATION_HALFWIN] -= 2 * rsi->hfilter[i]; rst->wiener_level = rsi->wiener_level;
rst->vfilter =
(int(*)[RESTORATION_WIN])malloc(sizeof(*rst->vfilter) * rst->ntiles);
assert(rst->vfilter != NULL);
rst->hfilter =
(int(*)[RESTORATION_WIN])malloc(sizeof(*rst->hfilter) * rst->ntiles);
assert(rst->hfilter != NULL);
for (tile_idx = 0; tile_idx < rst->ntiles; ++tile_idx) {
rst->vfilter[tile_idx][RESTORATION_HALFWIN] =
rst->hfilter[tile_idx][RESTORATION_HALFWIN] = RESTORATION_FILT_STEP;
for (i = 0; i < RESTORATION_HALFWIN; ++i) {
rst->vfilter[tile_idx][i] =
rst->vfilter[tile_idx][RESTORATION_WIN - 1 - i] =
rsi->vfilter[tile_idx][i];
rst->hfilter[tile_idx][i] =
rst->hfilter[tile_idx][RESTORATION_WIN - 1 - i] =
rsi->hfilter[tile_idx][i];
rst->vfilter[tile_idx][RESTORATION_HALFWIN] -=
2 * rsi->vfilter[tile_idx][i];
rst->hfilter[tile_idx][RESTORATION_HALFWIN] -=
2 * rsi->hfilter[tile_idx][i];
}
} }
} }
} }
...@@ -162,39 +228,60 @@ void vp10_loop_restoration_init(RestorationInternal *rst, RestorationInfo *rsi, ...@@ -162,39 +228,60 @@ void vp10_loop_restoration_init(RestorationInternal *rst, RestorationInfo *rsi,
static void loop_bilateral_filter(uint8_t *data, int width, int height, static void loop_bilateral_filter(uint8_t *data, int width, int height,
int stride, RestorationInternal *rst, int stride, RestorationInternal *rst,
uint8_t *tmpdata, int tmpstride) { uint8_t *tmpdata, int tmpstride) {
int i, j; int i, j, tile_idx, htile_idx, vtile_idx;
const uint8_t *wr_lut_ = rst->wr_lut + RESTORATION_RANGE; int h_start, h_end, v_start, v_end;
int tile_width, tile_height;
uint8_t *data_p = data + RESTORATION_HALFWIN * stride;
uint8_t *tmpdata_p = tmpdata + RESTORATION_HALFWIN * tmpstride; tile_width = rst->tile_width >> rst->subsampling_x;
for (i = RESTORATION_HALFWIN; i < height - RESTORATION_HALFWIN; ++i) { tile_height = rst->tile_height >> rst->subsampling_y;
for (j = RESTORATION_HALFWIN; j < width - RESTORATION_HALFWIN; ++j) {
int x, y; for (tile_idx = 0; tile_idx < rst->ntiles; ++tile_idx) {
int flsum = 0, wtsum = 0, wt; uint8_t *data_p, *tmpdata_p;
uint8_t *data_p2 = data_p + j - RESTORATION_HALFWIN * stride; const uint8_t *wr_lut_ = rst->wr_lut[tile_idx] + BILATERAL_AMP_RANGE;
for (y = -RESTORATION_HALFWIN; y <= RESTORATION_HALFWIN; ++y) {
for (x = -RESTORATION_HALFWIN; x <= RESTORATION_HALFWIN; ++x) { if (rst->bilateral_level[tile_idx] < 0) continue;
wt = (int)rst
->wx_lut[y + RESTORATION_HALFWIN][x + RESTORATION_HALFWIN] * htile_idx = tile_idx % rst->nhtiles;
(int)wr_lut_[data_p2[x] - data_p[j]]; vtile_idx = tile_idx / rst->nhtiles;
wtsum += wt; h_start =
flsum += wt * data_p2[x]; htile_idx * tile_width + ((htile_idx > 0) ? 0 : RESTORATION_HALFWIN);
h_end = (htile_idx < rst->nhtiles - 1) ? ((htile_idx + 1) * tile_width)
: (width - RESTORATION_HALFWIN);
v_start =
vtile_idx * tile_height + ((vtile_idx > 0) ? 0 : RESTORATION_HALFWIN);
v_end = (vtile_idx < rst->nvtiles - 1) ? ((vtile_idx + 1) * tile_height)
: (height - RESTORATION_HALFWIN);
data_p = data + h_start + v_start * stride;
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) {
int x, y;
int flsum = 0, wtsum = 0, wt;
uint8_t *data_p2 = data_p + j - RESTORATION_HALFWIN * stride;
for (y = -RESTORATION_HALFWIN; y <= RESTORATION_HALFWIN; ++y) {
for (x = -RESTORATION_HALFWIN; x <= RESTORATION_HALFWIN; ++x) {
wt = (int)rst->wx_lut[tile_idx][y + RESTORATION_HALFWIN]
[x + RESTORATION_HALFWIN] *
(int)wr_lut_[data_p2[x] - data_p[j]];
wtsum += wt;
flsum += wt * data_p2[x];
}
data_p2 += stride;
} }
data_p2 += stride; if (wtsum > 0)
tmpdata_p[j] = clip_pixel((int)((flsum + wtsum / 2) / wtsum));
else
tmpdata_p[j] = data_p[j];
} }
if (wtsum > 0) tmpdata_p += tmpstride;
tmpdata_p[j] = clip_pixel((int)((flsum + wtsum / 2) / wtsum)); data_p += stride;
else }
tmpdata_p[j] = data_p[j]; for (i = v_start; i < v_end; ++i) {
memcpy(data + i * stride + h_start, tmpdata + i * tmpstride + h_start,
(h_end - h_start) * sizeof(*data));
} }
tmpdata_p += tmpstride;
data_p += stride;
}
for (i = RESTORATION_HALFWIN; i < height - RESTORATION_HALFWIN; ++i) {
memcpy(data + i * stride + RESTORATION_HALFWIN,
tmpdata + i * tmpstride + RESTORATION_HALFWIN,
(width - RESTORATION_HALFWIN * 2) * sizeof(*data));
} }
} }
...@@ -219,38 +306,70 @@ uint8_t ver_sym_filter(uint8_t *d, int stride, int *vfilter) { ...@@ -219,38 +306,70 @@ uint8_t ver_sym_filter(uint8_t *d, int stride, int *vfilter) {
static void loop_wiener_filter(uint8_t *data, int width, int height, int stride, static void loop_wiener_filter(uint8_t *data, int width, int height, int stride,
RestorationInternal *rst, uint8_t *tmpdata, RestorationInternal *rst, uint8_t *tmpdata,
int tmpstride) { int tmpstride) {
uint8_t *data_p = data; int i, j, tile_idx, htile_idx, vtile_idx;
uint8_t *tmpdata_p = tmpdata; int h_start, h_end, v_start, v_end;
int i, j; int tile_width, tile_height;
uint8_t *data_p, *tmpdata_p;
for (i = 0; i < height; ++i) { tile_width = rst->tile_width >> rst->subsampling_x;
memcpy(tmpdata_p, data_p, sizeof(*data_p) * RESTORATION_HALFWIN); tile_height = rst->tile_height >> rst->subsampling_y;
data_p += RESTORATION_HALFWIN;
tmpdata_p += RESTORATION_HALFWIN; // Initialize tmp buffer
for (j = RESTORATION_HALFWIN; j < width - RESTORATION_HALFWIN; ++j) {
*tmpdata_p++ = hor_sym_filter(data_p++, rst->hfilter);
}
memcpy(tmpdata_p, data_p, sizeof(*data_p) * RESTORATION_HALFWIN);
data_p += RESTORATION_HALFWIN - width + stride;
tmpdata_p += RESTORATION_HALFWIN - width + tmpstride;
}
data_p = data; data_p = data;
tmpdata_p = tmpdata; tmpdata_p = tmpdata;
for (i = 0; i < RESTORATION_HALFWIN; ++i) { for (i = 0; i < height; ++i) {
memcpy(data_p, tmpdata_p, sizeof(*data_p) * width); memcpy(tmpdata_p, data_p, sizeof(*data_p) * width);
data_p += stride; data_p += stride;
tmpdata_p += tmpstride; tmpdata_p += tmpstride;
} }
for (; i < height - RESTORATION_HALFWIN; ++i) {
for (j = 0; j < width; ++j) // Filter row-wise tile-by-tile
*data_p++ = ver_sym_filter(tmpdata_p++, tmpstride, rst->vfilter); for (tile_idx = 0; tile_idx < rst->ntiles; ++tile_idx) {
data_p += stride - width; if (rst->wiener_level[tile_idx] == 0) continue;
tmpdata_p += tmpstride - width; htile_idx = tile_idx % rst->nhtiles;
vtile_idx = tile_idx / rst->nhtiles;
h_start =
htile_idx * tile_width + ((htile_idx > 0) ? 0 : RESTORATION_HALFWIN);
h_end = (htile_idx < rst->nhtiles - 1) ? ((htile_idx + 1) * tile_width)
: (width - RESTORATION_HALFWIN);
v_start = vtile_idx * tile_height;
v_end = (vtile_idx < rst->nvtiles - 1) ? ((vtile_idx + 1) * tile_height)
: height;
data_p = data + h_start + v_start * stride;
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->hfilter[tile_idx]);
}
data_p += stride - (h_end - h_start);
tmpdata_p += tmpstride - (h_end - h_start);
}
} }
for (; i < height; ++i) {
memcpy(data_p, tmpdata_p, sizeof(*data_p) * width); // Filter column-wise tile-by-tile (bands of thickness RESTORATION_HALFWIN
data_p += stride; // at top and bottom of tiles allow filtering overlap, and are not optimally
tmpdata_p += tmpstride; // filtered)
for (tile_idx = 0; tile_idx < rst->ntiles; ++tile_idx) {
if (rst->wiener_level[tile_idx] == 0) continue;
htile_idx = tile_idx % rst->nhtiles;
vtile_idx = tile_idx / rst->nhtiles;
h_start = htile_idx * tile_width;
h_end =
(htile_idx < rst->nhtiles - 1) ? ((htile_idx + 1) * tile_width) : width;
v_start =
vtile_idx * tile_height + ((vtile_idx > 0) ? 0 : RESTORATION_HALFWIN);
v_end = (vtile_idx < rst->nvtiles - 1) ? ((vtile_idx + 1) * tile_height)
: (height - RESTORATION_HALFWIN);
data_p = data + h_start + v_start * stride;
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->vfilter[tile_idx]);
}
data_p += stride - (h_end - h_start);
tmpdata_p += tmpstride - (h_end - h_start);
}
} }
} }
...@@ -259,44 +378,64 @@ static void loop_bilateral_filter_highbd(uint8_t *data8, int width, int height, ...@@ -259,44 +378,64 @@ static void loop_bilateral_filter_highbd(uint8_t *data8, int width, int height,
int stride, RestorationInternal *rst, int stride, RestorationInternal *rst,
uint8_t *tmpdata8, int tmpstride, uint8_t *tmpdata8, int tmpstride,
int bit_depth) { int bit_depth) {
int i, j; int i, j, tile_idx, htile_idx, vtile_idx;
const uint8_t *wr_lut_ = rst->wr_lut + RESTORATION_RANGE; int h_start, h_end, v_start, v_end;
int tile_width, tile_height;
uint16_t *data = CONVERT_TO_SHORTPTR(data8); uint16_t *data = CONVERT_TO_SHORTPTR(data8);
uint16_t *tmpdata = CONVERT_TO_SHORTPTR(tmpdata8); uint16_t *tmpdata = CONVERT_TO_SHORTPTR(tmpdata8);
uint16_t *data_p = data + RESTORATION_HALFWIN * stride;
uint16_t *tmpdata_p = tmpdata + RESTORATION_HALFWIN * tmpstride; tile_width = rst->tile_width >> rst->subsampling_x;
for (i = RESTORATION_HALFWIN; i < height - RESTORATION_HALFWIN; ++i) { tile_height = rst->tile_height >> rst->subsampling_y;
for (j = RESTORATION_HALFWIN; j < width - RESTORATION_HALFWIN; ++j) {
int x, y, diff_r; for (tile_idx = 0; tile_idx < rst->ntiles; ++tile_idx) {
int flsum = 0, wtsum = 0, wt; uint16_t *data_p, *tmpdata_p;
uint16_t *data_p2 = data_p + j - RESTORATION_HALFWIN * stride; const uint8_t *wr_lut_ = rst->wr_lut[tile_idx] + BILATERAL_AMP_RANGE;
for (y = -RESTORATION_HALFWIN; y <= RESTORATION_HALFWIN; ++y) {
for (x = -RESTORATION_HALFWIN; x <= RESTORATION_HALFWIN; ++x) { if (rst->bilateral_level[tile_idx] < 0) continue;
diff_r = (data_p2[x] - data_p[j]) >> (bit_depth - 8);
assert(diff_r >= -RESTORATION_RANGE && diff_r <= RESTORATION_RANGE); htile_idx = tile_idx % rst->nhtiles;
wt = (int)rst vtile_idx = tile_idx / rst->nhtiles;
->wx_lut[y + RESTORATION_HALFWIN][x + RESTORATION_HALFWIN] * h_start =
(int)wr_lut_[diff_r]; htile_idx * tile_width + ((htile_idx > 0) ? 0 : RESTORATION_HALFWIN);
wtsum += wt; h_end = (htile_idx < rst->nhtiles - 1) ? ((htile_idx + 1) * tile_width)
flsum += wt * data_p2[x]; : (width - RESTORATION_HALFWIN);