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
This commit is contained in:
committed by
Debargha Mukherjee
parent
04ed7ad57b
commit
e40e6e576a
@@ -82,7 +82,14 @@ void vp10_free_ref_frame_buffers(BufferPool *pool) {
|
||||
|
||||
#if CONFIG_LOOP_RESTORATION
|
||||
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
|
||||
|
||||
|
||||
@@ -1602,7 +1602,10 @@ void vp10_setup_past_independence(VP10_COMMON *cm) {
|
||||
// To force update of the sharpness
|
||||
lf->last_sharpness_level = -1;
|
||||
#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
|
||||
|
||||
vp10_default_coef_probs(cm);
|
||||
|
||||
@@ -168,10 +168,6 @@ typedef struct VP10Common {
|
||||
|
||||
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.*/
|
||||
#if CONFIG_EXT_REFS
|
||||
// frame type of the frame before last frame
|
||||
|
||||
@@ -18,33 +18,33 @@
|
||||
#include "vpx_mem/vpx_mem.h"
|
||||
#include "vpx_ports/mem.h"
|
||||
|
||||
#define RESTORATION_PARAM_PRECISION 16
|
||||
#define RESTORATION_RANGE 256
|
||||
#define RESTORATION_RANGE_SYM (2 * RESTORATION_RANGE + 1)
|
||||
#define BILATERAL_PARAM_PRECISION 16
|
||||
#define BILATERAL_AMP_RANGE 256
|
||||
#define BILATERAL_AMP_RANGE_SYM (2 * BILATERAL_AMP_RANGE + 1)
|
||||
|
||||
static uint8_t
|
||||
restoration_filters_r_kf[RESTORATION_LEVELS_KF][RESTORATION_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];
|
||||
bilateral_filter_coeffs_r_kf[BILATERAL_LEVELS_KF][BILATERAL_AMP_RANGE_SYM];
|
||||
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_y; // spatial variance y
|
||||
int sigma_r; // range variance
|
||||
} RestorationParamsType;
|
||||
} BilateralParamsType;
|
||||
|
||||
static RestorationParamsType
|
||||
restoration_level_to_params_arr[RESTORATION_LEVELS] = {
|
||||
// Values are rounded to 1/16 th precision
|
||||
{ 8, 9, 30 }, { 9, 8, 30 }, { 9, 11, 32 }, { 11, 9, 32 },
|
||||
{ 14, 14, 32 }, { 18, 18, 36 }, { 24, 24, 40 }, { 32, 32, 40 },
|
||||
};
|
||||
static BilateralParamsType bilateral_level_to_params_arr[BILATERAL_LEVELS] = {
|
||||
// Values are rounded to 1/16 th precision
|
||||
{ 8, 9, 30 }, { 9, 8, 30 }, { 9, 11, 32 }, { 11, 9, 32 },
|
||||
{ 14, 14, 32 }, { 18, 18, 36 }, { 24, 24, 40 }, { 32, 32, 40 },
|
||||
};
|
||||
|
||||
static RestorationParamsType
|
||||
restoration_level_to_params_arr_kf[RESTORATION_LEVELS_KF] = {
|
||||
static BilateralParamsType
|
||||
bilateral_level_to_params_arr_kf[BILATERAL_LEVELS_KF] = {
|
||||
// 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 },
|
||||
@@ -55,7 +55,6 @@ static RestorationParamsType
|
||||
typedef void (*restore_func_type)(uint8_t *data8, int width, int height,
|
||||
int stride, RestorationInternal *rst,
|
||||
uint8_t *tmpdata8, int tmpstride);
|
||||
|
||||
#if CONFIG_VP9_HIGHBITDEPTH
|
||||
typedef void (*restore_func_highbd_type)(uint8_t *data8, int width, int height,
|
||||
int stride, RestorationInternal *rst,
|
||||
@@ -63,26 +62,56 @@ typedef void (*restore_func_highbd_type)(uint8_t *data8, int width, int height,
|
||||
int bit_depth);
|
||||
#endif // CONFIG_VP9_HIGHBITDEPTH
|
||||
|
||||
static INLINE RestorationParamsType vp10_restoration_level_to_params(int index,
|
||||
int kf) {
|
||||
return kf ? restoration_level_to_params_arr_kf[index]
|
||||
: restoration_level_to_params_arr[index];
|
||||
static INLINE BilateralParamsType vp10_bilateral_level_to_params(int index,
|
||||
int kf) {
|
||||
return kf ? bilateral_level_to_params_arr_kf[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() {
|
||||
int i;
|
||||
for (i = 0; i < RESTORATION_LEVELS_KF; i++) {
|
||||
const RestorationParamsType param = vp10_restoration_level_to_params(i, 1);
|
||||
for (i = 0; i < BILATERAL_LEVELS_KF; i++) {
|
||||
const BilateralParamsType param = vp10_bilateral_level_to_params(i, 1);
|
||||
const int sigma_x = param.sigma_x;
|
||||
const int sigma_y = param.sigma_y;
|
||||
const int sigma_r = param.sigma_r;
|
||||
const double sigma_r_d = (double)sigma_r / RESTORATION_PARAM_PRECISION;
|
||||
const double sigma_x_d = (double)sigma_x / RESTORATION_PARAM_PRECISION;
|
||||
const double sigma_y_d = (double)sigma_y / RESTORATION_PARAM_PRECISION;
|
||||
const double sigma_r_d = (double)sigma_r / BILATERAL_PARAM_PRECISION;
|
||||
const double sigma_x_d = (double)sigma_x / BILATERAL_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;
|
||||
for (j = 0; j <= RESTORATION_RANGE; j++) {
|
||||
for (j = 0; j <= BILATERAL_AMP_RANGE; j++) {
|
||||
fr[j] = (uint8_t)(0.5 +
|
||||
RESTORATION_FILT_STEP *
|
||||
exp(-(j * j) / (2 * sigma_r_d * sigma_r_d)));
|
||||
@@ -90,28 +119,27 @@ void vp10_loop_restoration_precal() {
|
||||
}
|
||||
for (y = -RESTORATION_HALFWIN; y <= RESTORATION_HALFWIN; y++) {
|
||||
for (x = -RESTORATION_HALFWIN; x <= RESTORATION_HALFWIN; x++) {
|
||||
restoration_filters_s_kf[i][y +
|
||||
RESTORATION_HALFWIN][x +
|
||||
RESTORATION_HALFWIN] =
|
||||
(uint8_t)(0.5 +
|
||||
RESTORATION_FILT_STEP *
|
||||
exp(-(x * x) / (2 * sigma_x_d * sigma_x_d) -
|
||||
(y * y) / (2 * sigma_y_d * sigma_y_d)));
|
||||
bilateral_filter_coeffs_s_kf
|
||||
[i][y + RESTORATION_HALFWIN][x + RESTORATION_HALFWIN] =
|
||||
(uint8_t)(0.5 +
|
||||
RESTORATION_FILT_STEP *
|
||||
exp(-(x * x) / (2 * sigma_x_d * sigma_x_d) -
|
||||
(y * y) / (2 * sigma_y_d * sigma_y_d)));
|
||||
}
|
||||
}
|
||||
}
|
||||
for (i = 0; i < RESTORATION_LEVELS; i++) {
|
||||
const RestorationParamsType param = vp10_restoration_level_to_params(i, 0);
|
||||
for (i = 0; i < BILATERAL_LEVELS; i++) {
|
||||
const BilateralParamsType param = vp10_bilateral_level_to_params(i, 0);
|
||||
const int sigma_x = param.sigma_x;
|
||||
const int sigma_y = param.sigma_y;
|
||||
const int sigma_r = param.sigma_r;
|
||||
const double sigma_r_d = (double)sigma_r / RESTORATION_PARAM_PRECISION;
|
||||
const double sigma_x_d = (double)sigma_x / RESTORATION_PARAM_PRECISION;
|
||||
const double sigma_y_d = (double)sigma_y / RESTORATION_PARAM_PRECISION;
|
||||
const double sigma_r_d = (double)sigma_r / BILATERAL_PARAM_PRECISION;
|
||||
const double sigma_x_d = (double)sigma_x / BILATERAL_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;
|
||||
for (j = 0; j <= RESTORATION_RANGE; j++) {
|
||||
for (j = 0; j <= BILATERAL_AMP_RANGE; j++) {
|
||||
fr[j] = (uint8_t)(0.5 +
|
||||
RESTORATION_FILT_STEP *
|
||||
exp(-(j * j) / (2 * sigma_r_d * sigma_r_d)));
|
||||
@@ -119,7 +147,8 @@ void vp10_loop_restoration_precal() {
|
||||
}
|
||||
for (y = -RESTORATION_HALFWIN; y <= RESTORATION_HALFWIN; y++) {
|
||||
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] =
|
||||
(uint8_t)(0.5 +
|
||||
RESTORATION_FILT_STEP *
|
||||
@@ -130,31 +159,68 @@ void vp10_loop_restoration_precal() {
|
||||
}
|
||||
}
|
||||
|
||||
int vp10_restoration_level_bits(const VP10_COMMON *const cm) {
|
||||
return cm->frame_type == KEY_FRAME ? RESTORATION_LEVEL_BITS_KF
|
||||
: RESTORATION_LEVEL_BITS;
|
||||
int vp10_bilateral_level_bits(const VP10_COMMON *const cm) {
|
||||
return cm->frame_type == KEY_FRAME ? BILATERAL_LEVEL_BITS_KF
|
||||
: BILATERAL_LEVEL_BITS;
|
||||
}
|
||||
|
||||
void vp10_loop_restoration_init(RestorationInternal *rst, RestorationInfo *rsi,
|
||||
int kf) {
|
||||
int i;
|
||||
int kf, int width, int height) {
|
||||
int i, tile_idx;
|
||||
rst->restoration_type = rsi->restoration_type;
|
||||
rst->subsampling_x = 0;
|
||||
rst->subsampling_y = 0;
|
||||
if (rsi->restoration_type == RESTORE_BILATERAL) {
|
||||
const int level = rsi->restoration_level;
|
||||
assert(level >= 0);
|
||||
rst->wr_lut =
|
||||
kf ? restoration_filters_r_kf[level] : restoration_filters_r[level];
|
||||
for (i = 0; i < RESTORATION_WIN; i++)
|
||||
rst->wx_lut[i] = kf ? restoration_filters_s_kf[level][i]
|
||||
: restoration_filters_s[level][i];
|
||||
rst->tilesize_index = BILATERAL_TILESIZE;
|
||||
rst->ntiles =
|
||||
vp10_get_restoration_ntiles(rst->tilesize_index, width, height);
|
||||
vp10_get_restoration_tile_size(rst->tilesize_index, width, height,
|
||||
&rst->tile_width, &rst->tile_height,
|
||||
&rst->nhtiles, &rst->nvtiles);
|
||||
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) {
|
||||
rst->vfilter[RESTORATION_HALFWIN] = rst->hfilter[RESTORATION_HALFWIN] =
|
||||
RESTORATION_FILT_STEP;
|
||||
for (i = 0; i < RESTORATION_HALFWIN; ++i) {
|
||||
rst->vfilter[i] = rst->vfilter[RESTORATION_WIN - 1 - i] = rsi->vfilter[i];
|
||||
rst->hfilter[i] = rst->hfilter[RESTORATION_WIN - 1 - i] = rsi->hfilter[i];
|
||||
rst->vfilter[RESTORATION_HALFWIN] -= 2 * rsi->vfilter[i];
|
||||
rst->hfilter[RESTORATION_HALFWIN] -= 2 * rsi->hfilter[i];
|
||||
rst->tilesize_index = WIENER_TILESIZE;
|
||||
rst->ntiles =
|
||||
vp10_get_restoration_ntiles(rst->tilesize_index, width, height);
|
||||
vp10_get_restoration_tile_size(rst->tilesize_index, width, height,
|
||||
&rst->tile_width, &rst->tile_height,
|
||||
&rst->nhtiles, &rst->nvtiles);
|
||||
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,
|
||||
static void loop_bilateral_filter(uint8_t *data, int width, int height,
|
||||
int stride, RestorationInternal *rst,
|
||||
uint8_t *tmpdata, int tmpstride) {
|
||||
int i, j;
|
||||
const uint8_t *wr_lut_ = rst->wr_lut + RESTORATION_RANGE;
|
||||
int i, j, tile_idx, htile_idx, vtile_idx;
|
||||
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;
|
||||
for (i = RESTORATION_HALFWIN; i < height - RESTORATION_HALFWIN; ++i) {
|
||||
for (j = RESTORATION_HALFWIN; j < width - RESTORATION_HALFWIN; ++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[y + RESTORATION_HALFWIN][x + RESTORATION_HALFWIN] *
|
||||
(int)wr_lut_[data_p2[x] - data_p[j]];
|
||||
wtsum += wt;
|
||||
flsum += wt * data_p2[x];
|
||||
tile_width = rst->tile_width >> rst->subsampling_x;
|
||||
tile_height = rst->tile_height >> rst->subsampling_y;
|
||||
|
||||
for (tile_idx = 0; tile_idx < rst->ntiles; ++tile_idx) {
|
||||
uint8_t *data_p, *tmpdata_p;
|
||||
const uint8_t *wr_lut_ = rst->wr_lut[tile_idx] + BILATERAL_AMP_RANGE;
|
||||
|
||||
if (rst->bilateral_level[tile_idx] < 0) continue;
|
||||
|
||||
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 + ((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[j] = clip_pixel((int)((flsum + wtsum / 2) / wtsum));
|
||||
else
|
||||
tmpdata_p[j] = data_p[j];
|
||||
tmpdata_p += tmpstride;
|
||||
data_p += stride;
|
||||
}
|
||||
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) {
|
||||
static void loop_wiener_filter(uint8_t *data, int width, int height, int stride,
|
||||
RestorationInternal *rst, uint8_t *tmpdata,
|
||||
int tmpstride) {
|
||||
uint8_t *data_p = data;
|
||||
uint8_t *tmpdata_p = tmpdata;
|
||||
int i, j;
|
||||
int i, j, tile_idx, htile_idx, vtile_idx;
|
||||
int h_start, h_end, v_start, v_end;
|
||||
int tile_width, tile_height;
|
||||
uint8_t *data_p, *tmpdata_p;
|
||||
|
||||
for (i = 0; i < height; ++i) {
|
||||
memcpy(tmpdata_p, data_p, sizeof(*data_p) * RESTORATION_HALFWIN);
|
||||
data_p += RESTORATION_HALFWIN;
|
||||
tmpdata_p += RESTORATION_HALFWIN;
|
||||
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;
|
||||
}
|
||||
tile_width = rst->tile_width >> rst->subsampling_x;
|
||||
tile_height = rst->tile_height >> rst->subsampling_y;
|
||||
|
||||
// Initialize tmp buffer
|
||||
data_p = data;
|
||||
tmpdata_p = tmpdata;
|
||||
for (i = 0; i < RESTORATION_HALFWIN; ++i) {
|
||||
memcpy(data_p, tmpdata_p, sizeof(*data_p) * width);
|
||||
for (i = 0; i < height; ++i) {
|
||||
memcpy(tmpdata_p, data_p, sizeof(*data_p) * width);
|
||||
data_p += stride;
|
||||
tmpdata_p += tmpstride;
|
||||
}
|
||||
for (; i < height - RESTORATION_HALFWIN; ++i) {
|
||||
for (j = 0; j < width; ++j)
|
||||
*data_p++ = ver_sym_filter(tmpdata_p++, tmpstride, rst->vfilter);
|
||||
data_p += stride - width;
|
||||
tmpdata_p += tmpstride - width;
|
||||
|
||||
// Filter row-wise tile-by-tile
|
||||
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 + ((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);
|
||||
data_p += stride;
|
||||
tmpdata_p += tmpstride;
|
||||
|
||||
// Filter column-wise tile-by-tile (bands of thickness RESTORATION_HALFWIN
|
||||
// at top and bottom of tiles allow filtering overlap, and are not optimally
|
||||
// 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,
|
||||
int stride, RestorationInternal *rst,
|
||||
uint8_t *tmpdata8, int tmpstride,
|
||||
int bit_depth) {
|
||||
int i, j;
|
||||
const uint8_t *wr_lut_ = rst->wr_lut + RESTORATION_RANGE;
|
||||
int i, j, tile_idx, htile_idx, vtile_idx;
|
||||
int h_start, h_end, v_start, v_end;
|
||||
int tile_width, tile_height;
|
||||
|
||||
uint16_t *data = CONVERT_TO_SHORTPTR(data8);
|
||||
uint16_t *tmpdata = CONVERT_TO_SHORTPTR(tmpdata8);
|
||||
uint16_t *data_p = data + RESTORATION_HALFWIN * stride;
|
||||
uint16_t *tmpdata_p = tmpdata + RESTORATION_HALFWIN * tmpstride;
|
||||
for (i = RESTORATION_HALFWIN; i < height - RESTORATION_HALFWIN; ++i) {
|
||||
for (j = RESTORATION_HALFWIN; j < width - RESTORATION_HALFWIN; ++j) {
|
||||
int x, y, diff_r;
|
||||
int flsum = 0, wtsum = 0, wt;
|
||||
uint16_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) {
|
||||
diff_r = (data_p2[x] - data_p[j]) >> (bit_depth - 8);
|
||||
assert(diff_r >= -RESTORATION_RANGE && diff_r <= RESTORATION_RANGE);
|
||||
wt = (int)rst
|
||||
->wx_lut[y + RESTORATION_HALFWIN][x + RESTORATION_HALFWIN] *
|
||||
(int)wr_lut_[diff_r];
|
||||
wtsum += wt;
|
||||
flsum += wt * data_p2[x];
|
||||
}
|
||||
data_p2 += stride;
|
||||
}
|
||||
if (wtsum > 0)
|
||||
tmpdata_p[j] =
|
||||
clip_pixel_highbd((int)((flsum + wtsum / 2) / wtsum), bit_depth);
|
||||
else
|
||||
tmpdata_p[j] = data_p[j];
|
||||
}
|
||||
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));
|
||||
tile_width = rst->tile_width >> rst->subsampling_x;
|
||||
tile_height = rst->tile_height >> rst->subsampling_y;
|
||||
|
||||
for (tile_idx = 0; tile_idx < rst->ntiles; ++tile_idx) {
|
||||
uint16_t *data_p, *tmpdata_p;
|
||||
const uint8_t *wr_lut_ = rst->wr_lut[tile_idx] + BILATERAL_AMP_RANGE;
|
||||
|
||||
if (rst->bilateral_level[tile_idx] < 0) continue;
|
||||
|
||||
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 + ((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;
|
||||
uint16_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;
|
||||
}
|
||||
if (wtsum > 0)
|
||||
tmpdata_p[j] =
|
||||
clip_pixel_highbd((int)((flsum + wtsum / 2) / wtsum), bit_depth);
|
||||
else
|
||||
tmpdata_p[j] = data_p[j];
|
||||
}
|
||||
tmpdata_p += tmpstride;
|
||||
data_p += stride;
|
||||
}
|
||||
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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -324,38 +463,71 @@ static void loop_wiener_filter_highbd(uint8_t *data8, int width, int height,
|
||||
int bit_depth) {
|
||||
uint16_t *data = CONVERT_TO_SHORTPTR(data8);
|
||||
uint16_t *tmpdata = CONVERT_TO_SHORTPTR(tmpdata8);
|
||||
uint16_t *data_p = data;
|
||||
uint16_t *tmpdata_p = tmpdata;
|
||||
int i, j;
|
||||
for (i = 0; i < height; ++i) {
|
||||
memcpy(tmpdata_p, data_p, sizeof(*data_p) * RESTORATION_HALFWIN);
|
||||
data_p += RESTORATION_HALFWIN;
|
||||
tmpdata_p += RESTORATION_HALFWIN;
|
||||
for (j = RESTORATION_HALFWIN; j < width - RESTORATION_HALFWIN; ++j) {
|
||||
*tmpdata_p++ = hor_sym_filter_highbd(data_p++, rst->hfilter, bit_depth);
|
||||
}
|
||||
memcpy(tmpdata_p, data_p, sizeof(*data_p) * RESTORATION_HALFWIN);
|
||||
data_p += RESTORATION_HALFWIN - width + stride;
|
||||
tmpdata_p += RESTORATION_HALFWIN - width + tmpstride;
|
||||
}
|
||||
int i, j, tile_idx, htile_idx, vtile_idx;
|
||||
int h_start, h_end, v_start, v_end;
|
||||
int tile_width, tile_height;
|
||||
uint16_t *data_p, *tmpdata_p;
|
||||
|
||||
tile_width = rst->tile_width >> rst->subsampling_x;
|
||||
tile_height = rst->tile_height >> rst->subsampling_y;
|
||||
|
||||
// Initialize tmp buffer
|
||||
data_p = data;
|
||||
tmpdata_p = tmpdata;
|
||||
for (i = 0; i < RESTORATION_HALFWIN; ++i) {
|
||||
memcpy(data_p, tmpdata_p, sizeof(*data_p) * width);
|
||||
for (i = 0; i < height; ++i) {
|
||||
memcpy(tmpdata_p, data_p, sizeof(*data_p) * width);
|
||||
data_p += stride;
|
||||
tmpdata_p += tmpstride;
|
||||
}
|
||||
for (; i < height - RESTORATION_HALFWIN; ++i) {
|
||||
for (j = 0; j < width; ++j)
|
||||
*data_p++ = ver_sym_filter_highbd(tmpdata_p++, tmpstride, rst->vfilter,
|
||||
bit_depth);
|
||||
data_p += stride - width;
|
||||
tmpdata_p += tmpstride - width;
|
||||
|
||||
// Filter row-wise tile-by-tile
|
||||
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 + ((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_highbd(data_p++, rst->hfilter[tile_idx], bit_depth);
|
||||
}
|
||||
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);
|
||||
data_p += stride;
|
||||
tmpdata_p += tmpstride;
|
||||
|
||||
// Filter column-wise tile-by-tile (bands of thickness RESTORATION_HALFWIN
|
||||
// at top and bottom of tiles allow filtering overlap, and are not optimally
|
||||
// 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_highbd(tmpdata_p++, tmpstride,
|
||||
rst->vfilter[tile_idx], bit_depth);
|
||||
}
|
||||
data_p += stride - (h_end - h_start);
|
||||
tmpdata_p += tmpstride - (h_end - h_start);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif // CONFIG_VP9_HIGHBITDEPTH
|
||||
@@ -380,60 +552,73 @@ void vp10_loop_restoration_rows(YV12_BUFFER_CONFIG *frame, VP10_COMMON *cm,
|
||||
? loop_bilateral_filter_highbd
|
||||
: loop_wiener_filter_highbd;
|
||||
#endif // CONFIG_VP9_HIGHBITDEPTH
|
||||
YV12_BUFFER_CONFIG *tmp_buf;
|
||||
YV12_BUFFER_CONFIG tmp_buf;
|
||||
memset(&tmp_buf, 0, sizeof(YV12_BUFFER_CONFIG));
|
||||
|
||||
yend = VPXMIN(yend, cm->height);
|
||||
uvend = VPXMIN(uvend, cm->subsampling_y ? (cm->height + 1) >> 1 : cm->height);
|
||||
|
||||
if (vpx_realloc_frame_buffer(&cm->tmp_loop_buf, cm->width, cm->height,
|
||||
cm->subsampling_x, cm->subsampling_y,
|
||||
if (vpx_realloc_frame_buffer(
|
||||
&tmp_buf, cm->width, cm->height, cm->subsampling_x, cm->subsampling_y,
|
||||
#if CONFIG_VP9_HIGHBITDEPTH
|
||||
cm->use_highbitdepth,
|
||||
cm->use_highbitdepth,
|
||||
#endif
|
||||
VPX_DEC_BORDER_IN_PIXELS, cm->byte_alignment,
|
||||
NULL, NULL, NULL) < 0)
|
||||
VPX_DEC_BORDER_IN_PIXELS, cm->byte_alignment, NULL, NULL, NULL) < 0)
|
||||
vpx_internal_error(&cm->error, VPX_CODEC_MEM_ERROR,
|
||||
"Failed to allocate tmp restoration buffer");
|
||||
|
||||
tmp_buf = &cm->tmp_loop_buf;
|
||||
|
||||
#if CONFIG_VP9_HIGHBITDEPTH
|
||||
if (cm->use_highbitdepth)
|
||||
restore_func_highbd(frame->y_buffer + ystart * ystride, ywidth,
|
||||
yend - ystart, ystride, &cm->rst_internal,
|
||||
tmp_buf->y_buffer + ystart * tmp_buf->y_stride,
|
||||
tmp_buf->y_stride, cm->bit_depth);
|
||||
tmp_buf.y_buffer + ystart * tmp_buf.y_stride,
|
||||
tmp_buf.y_stride, cm->bit_depth);
|
||||
else
|
||||
#endif // CONFIG_VP9_HIGHBITDEPTH
|
||||
restore_func(frame->y_buffer + ystart * ystride, ywidth, yend - ystart,
|
||||
ystride, &cm->rst_internal,
|
||||
tmp_buf->y_buffer + ystart * tmp_buf->y_stride,
|
||||
tmp_buf->y_stride);
|
||||
tmp_buf.y_buffer + ystart * tmp_buf.y_stride,
|
||||
tmp_buf.y_stride);
|
||||
if (!y_only) {
|
||||
cm->rst_internal.subsampling_x = cm->subsampling_x;
|
||||
cm->rst_internal.subsampling_y = cm->subsampling_y;
|
||||
#if CONFIG_VP9_HIGHBITDEPTH
|
||||
if (cm->use_highbitdepth) {
|
||||
restore_func_highbd(frame->u_buffer + uvstart * uvstride, uvwidth,
|
||||
uvend - uvstart, uvstride, &cm->rst_internal,
|
||||
tmp_buf->u_buffer + uvstart * tmp_buf->uv_stride,
|
||||
tmp_buf->uv_stride, cm->bit_depth);
|
||||
tmp_buf.u_buffer + uvstart * tmp_buf.uv_stride,
|
||||
tmp_buf.uv_stride, cm->bit_depth);
|
||||
restore_func_highbd(frame->v_buffer + uvstart * uvstride, uvwidth,
|
||||
uvend - uvstart, uvstride, &cm->rst_internal,
|
||||
tmp_buf->v_buffer + uvstart * tmp_buf->uv_stride,
|
||||
tmp_buf->uv_stride, cm->bit_depth);
|
||||
tmp_buf.v_buffer + uvstart * tmp_buf.uv_stride,
|
||||
tmp_buf.uv_stride, cm->bit_depth);
|
||||
} else {
|
||||
#endif // CONFIG_VP9_HIGHBITDEPTH
|
||||
restore_func(frame->u_buffer + uvstart * uvstride, uvwidth,
|
||||
uvend - uvstart, uvstride, &cm->rst_internal,
|
||||
tmp_buf->u_buffer + uvstart * tmp_buf->uv_stride,
|
||||
tmp_buf->uv_stride);
|
||||
tmp_buf.u_buffer + uvstart * tmp_buf.uv_stride,
|
||||
tmp_buf.uv_stride);
|
||||
restore_func(frame->v_buffer + uvstart * uvstride, uvwidth,
|
||||
uvend - uvstart, uvstride, &cm->rst_internal,
|
||||
tmp_buf->v_buffer + uvstart * tmp_buf->uv_stride,
|
||||
tmp_buf->uv_stride);
|
||||
tmp_buf.v_buffer + uvstart * tmp_buf.uv_stride,
|
||||
tmp_buf.uv_stride);
|
||||
#if CONFIG_VP9_HIGHBITDEPTH
|
||||
}
|
||||
#endif // CONFIG_VP9_HIGHBITDEPTH
|
||||
}
|
||||
vpx_free_frame_buffer(&tmp_buf);
|
||||
if (cm->rst_internal.restoration_type == RESTORE_BILATERAL) {
|
||||
free(cm->rst_internal.wr_lut);
|
||||
cm->rst_internal.wr_lut = NULL;
|
||||
free(cm->rst_internal.wx_lut);
|
||||
cm->rst_internal.wx_lut = NULL;
|
||||
}
|
||||
if (cm->rst_internal.restoration_type == RESTORE_WIENER) {
|
||||
free(cm->rst_internal.vfilter);
|
||||
cm->rst_internal.vfilter = NULL;
|
||||
free(cm->rst_internal.hfilter);
|
||||
cm->rst_internal.hfilter = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void vp10_loop_restoration_frame(YV12_BUFFER_CONFIG *frame, VP10_COMMON *cm,
|
||||
@@ -450,7 +635,8 @@ void vp10_loop_restoration_frame(YV12_BUFFER_CONFIG *frame, VP10_COMMON *cm,
|
||||
}
|
||||
end_mi_row = start_mi_row + mi_rows_to_filter;
|
||||
vp10_loop_restoration_init(&cm->rst_internal, rsi,
|
||||
cm->frame_type == KEY_FRAME);
|
||||
cm->frame_type == KEY_FRAME, cm->width,
|
||||
cm->height);
|
||||
vp10_loop_restoration_rows(frame, cm, start_mi_row, end_mi_row, y_only);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,8 +11,8 @@
|
||||
#ifndef VP10_COMMON_RESTORATION_H_
|
||||
#define VP10_COMMON_RESTORATION_H_
|
||||
|
||||
#include "vpx_ports/mem.h"
|
||||
#include "./vpx_config.h"
|
||||
#include "vpx_ports/mem.h"
|
||||
|
||||
#include "vp10/common/blockd.h"
|
||||
|
||||
@@ -20,11 +20,15 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define RESTORATION_LEVEL_BITS_KF 4
|
||||
#define RESTORATION_LEVELS_KF (1 << RESTORATION_LEVEL_BITS_KF)
|
||||
#define RESTORATION_LEVEL_BITS 3
|
||||
#define RESTORATION_LEVELS (1 << RESTORATION_LEVEL_BITS)
|
||||
#define DEF_RESTORATION_LEVEL 2
|
||||
#define BILATERAL_LEVEL_BITS_KF 4
|
||||
#define BILATERAL_LEVELS_KF (1 << BILATERAL_LEVEL_BITS_KF)
|
||||
#define BILATERAL_LEVEL_BITS 3
|
||||
#define BILATERAL_LEVELS (1 << BILATERAL_LEVEL_BITS)
|
||||
// #define DEF_BILATERAL_LEVEL 2
|
||||
|
||||
#define RESTORATION_TILESIZES 3
|
||||
#define BILATERAL_TILESIZE 0
|
||||
#define WIENER_TILESIZE 2
|
||||
|
||||
#define RESTORATION_HALFWIN 3
|
||||
#define RESTORATION_HALFWIN1 (RESTORATION_HALFWIN + 1)
|
||||
@@ -34,9 +38,9 @@ extern "C" {
|
||||
#define RESTORATION_FILT_BITS 7
|
||||
#define RESTORATION_FILT_STEP (1 << RESTORATION_FILT_BITS)
|
||||
|
||||
#define WIENER_FILT_TAP0_MINV -5
|
||||
#define WIENER_FILT_TAP0_MINV (-5)
|
||||
#define WIENER_FILT_TAP1_MINV (-23)
|
||||
#define WIENER_FILT_TAP2_MINV -20
|
||||
#define WIENER_FILT_TAP2_MINV (-16)
|
||||
|
||||
#define WIENER_FILT_TAP0_BITS 4
|
||||
#define WIENER_FILT_TAP1_BITS 5
|
||||
@@ -60,20 +64,37 @@ typedef enum {
|
||||
|
||||
typedef struct {
|
||||
RestorationType restoration_type;
|
||||
int restoration_level;
|
||||
int vfilter[RESTORATION_HALFWIN], hfilter[RESTORATION_HALFWIN];
|
||||
// Bilateral filter
|
||||
int *bilateral_level;
|
||||
// Wiener filter
|
||||
int *wiener_level;
|
||||
int (*vfilter)[RESTORATION_HALFWIN], (*hfilter)[RESTORATION_HALFWIN];
|
||||
} RestorationInfo;
|
||||
|
||||
typedef struct {
|
||||
RestorationType restoration_type;
|
||||
uint8_t *wx_lut[RESTORATION_WIN];
|
||||
uint8_t *wr_lut;
|
||||
int vfilter[RESTORATION_WIN], hfilter[RESTORATION_WIN];
|
||||
int subsampling_x;
|
||||
int subsampling_y;
|
||||
int tilesize_index;
|
||||
int ntiles;
|
||||
int tile_width, tile_height;
|
||||
int nhtiles, nvtiles;
|
||||
// Bilateral filter
|
||||
int *bilateral_level;
|
||||
uint8_t (**wx_lut)[RESTORATION_WIN];
|
||||
uint8_t **wr_lut;
|
||||
// Wiener filter
|
||||
int *wiener_level;
|
||||
int (*vfilter)[RESTORATION_WIN], (*hfilter)[RESTORATION_WIN];
|
||||
} RestorationInternal;
|
||||
|
||||
int vp10_restoration_level_bits(const struct VP10Common *const cm);
|
||||
int vp10_bilateral_level_bits(const struct VP10Common *const cm);
|
||||
int vp10_get_restoration_ntiles(int tilesize, int width, int height);
|
||||
void vp10_get_restoration_tile_size(int tilesize, int width, int height,
|
||||
int *tile_width, int *tile_height,
|
||||
int *nhtiles, int *nvtiles);
|
||||
void vp10_loop_restoration_init(RestorationInternal *rst, RestorationInfo *rsi,
|
||||
int kf);
|
||||
int kf, int width, int height);
|
||||
void vp10_loop_restoration_frame(YV12_BUFFER_CONFIG *frame,
|
||||
struct VP10Common *cm, RestorationInfo *rsi,
|
||||
int y_only, int partial_frame);
|
||||
|
||||
@@ -12,12 +12,12 @@
|
||||
#include <stdlib.h> // qsort()
|
||||
|
||||
#include "./vp10_rtcd.h"
|
||||
#include "./vpx_config.h"
|
||||
#include "./vpx_dsp_rtcd.h"
|
||||
#include "./vpx_scale_rtcd.h"
|
||||
#include "./vpx_config.h"
|
||||
|
||||
#include "vpx_dsp/bitreader_buffer.h"
|
||||
#include "vp10/decoder/bitreader.h"
|
||||
#include "vpx_dsp/bitreader_buffer.h"
|
||||
#include "vpx_dsp/vpx_dsp_common.h"
|
||||
#include "vpx_mem/vpx_mem.h"
|
||||
#include "vpx_ports/mem.h"
|
||||
@@ -36,18 +36,18 @@
|
||||
#include "vp10/common/entropy.h"
|
||||
#include "vp10/common/entropymode.h"
|
||||
#include "vp10/common/idct.h"
|
||||
#include "vp10/common/thread_common.h"
|
||||
#include "vp10/common/pred_common.h"
|
||||
#include "vp10/common/quant_common.h"
|
||||
#include "vp10/common/reconintra.h"
|
||||
#include "vp10/common/reconinter.h"
|
||||
#include "vp10/common/reconintra.h"
|
||||
#include "vp10/common/seg_common.h"
|
||||
#include "vp10/common/thread_common.h"
|
||||
#include "vp10/common/tile_common.h"
|
||||
|
||||
#include "vp10/decoder/decodeframe.h"
|
||||
#include "vp10/decoder/detokenize.h"
|
||||
#include "vp10/decoder/decodemv.h"
|
||||
#include "vp10/decoder/decoder.h"
|
||||
#include "vp10/decoder/detokenize.h"
|
||||
#include "vp10/decoder/dsubexp.h"
|
||||
|
||||
#define MAX_VPX_HEADER_SIZE 80
|
||||
@@ -1922,29 +1922,61 @@ static void setup_segmentation(VP10_COMMON *const cm,
|
||||
|
||||
#if CONFIG_LOOP_RESTORATION
|
||||
static void setup_restoration(VP10_COMMON *cm, struct vpx_read_bit_buffer *rb) {
|
||||
RestorationInfo *rst = &cm->rst_info;
|
||||
int i;
|
||||
RestorationInfo *rsi = &cm->rst_info;
|
||||
int ntiles;
|
||||
if (vpx_rb_read_bit(rb)) {
|
||||
if (vpx_rb_read_bit(rb)) {
|
||||
rst->restoration_type = RESTORE_BILATERAL;
|
||||
rst->restoration_level =
|
||||
vpx_rb_read_literal(rb, vp10_restoration_level_bits(cm));
|
||||
rsi->restoration_type = RESTORE_BILATERAL;
|
||||
ntiles = vp10_get_restoration_ntiles(BILATERAL_TILESIZE, cm->width,
|
||||
cm->height);
|
||||
rsi->bilateral_level = (int *)vpx_realloc(
|
||||
rsi->bilateral_level, sizeof(*rsi->bilateral_level) * ntiles);
|
||||
assert(rsi->bilateral_level != NULL);
|
||||
for (i = 0; i < ntiles; ++i) {
|
||||
if (vpx_rb_read_bit(rb)) {
|
||||
rsi->bilateral_level[i] =
|
||||
vpx_rb_read_literal(rb, vp10_bilateral_level_bits(cm));
|
||||
} else {
|
||||
rsi->bilateral_level[i] = -1;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
rst->restoration_type = RESTORE_WIENER;
|
||||
rst->vfilter[0] = vpx_rb_read_literal(rb, WIENER_FILT_TAP0_BITS) +
|
||||
WIENER_FILT_TAP0_MINV;
|
||||
rst->vfilter[1] = vpx_rb_read_literal(rb, WIENER_FILT_TAP1_BITS) +
|
||||
WIENER_FILT_TAP1_MINV;
|
||||
rst->vfilter[2] = vpx_rb_read_literal(rb, WIENER_FILT_TAP2_BITS) +
|
||||
WIENER_FILT_TAP2_MINV;
|
||||
rst->hfilter[0] = vpx_rb_read_literal(rb, WIENER_FILT_TAP0_BITS) +
|
||||
WIENER_FILT_TAP0_MINV;
|
||||
rst->hfilter[1] = vpx_rb_read_literal(rb, WIENER_FILT_TAP1_BITS) +
|
||||
WIENER_FILT_TAP1_MINV;
|
||||
rst->hfilter[2] = vpx_rb_read_literal(rb, WIENER_FILT_TAP2_BITS) +
|
||||
WIENER_FILT_TAP2_MINV;
|
||||
rsi->restoration_type = RESTORE_WIENER;
|
||||
ntiles =
|
||||
vp10_get_restoration_ntiles(WIENER_TILESIZE, cm->width, cm->height);
|
||||
rsi->wiener_level = (int *)vpx_realloc(
|
||||
rsi->wiener_level, sizeof(*rsi->wiener_level) * ntiles);
|
||||
assert(rsi->wiener_level != NULL);
|
||||
rsi->vfilter = (int(*)[RESTORATION_HALFWIN])vpx_realloc(
|
||||
rsi->vfilter, sizeof(*rsi->vfilter) * ntiles);
|
||||
assert(rsi->vfilter != NULL);
|
||||
rsi->hfilter = (int(*)[RESTORATION_HALFWIN])vpx_realloc(
|
||||
rsi->hfilter, sizeof(*rsi->hfilter) * ntiles);
|
||||
assert(rsi->hfilter != NULL);
|
||||
for (i = 0; i < ntiles; ++i) {
|
||||
rsi->wiener_level[i] = vpx_rb_read_bit(rb);
|
||||
if (rsi->wiener_level[i]) {
|
||||
rsi->vfilter[i][0] = vpx_rb_read_literal(rb, WIENER_FILT_TAP0_BITS) +
|
||||
WIENER_FILT_TAP0_MINV;
|
||||
rsi->vfilter[i][1] = vpx_rb_read_literal(rb, WIENER_FILT_TAP1_BITS) +
|
||||
WIENER_FILT_TAP1_MINV;
|
||||
rsi->vfilter[i][2] = vpx_rb_read_literal(rb, WIENER_FILT_TAP2_BITS) +
|
||||
WIENER_FILT_TAP2_MINV;
|
||||
rsi->hfilter[i][0] = vpx_rb_read_literal(rb, WIENER_FILT_TAP0_BITS) +
|
||||
WIENER_FILT_TAP0_MINV;
|
||||
rsi->hfilter[i][1] = vpx_rb_read_literal(rb, WIENER_FILT_TAP1_BITS) +
|
||||
WIENER_FILT_TAP1_MINV;
|
||||
rsi->hfilter[i][2] = vpx_rb_read_literal(rb, WIENER_FILT_TAP2_BITS) +
|
||||
WIENER_FILT_TAP2_MINV;
|
||||
} else {
|
||||
rsi->vfilter[i][0] = rsi->vfilter[i][1] = rsi->vfilter[i][2] = 0;
|
||||
rsi->hfilter[i][0] = rsi->hfilter[i][1] = rsi->hfilter[i][2] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
rst->restoration_type = RESTORE_NONE;
|
||||
rsi->restoration_type = RESTORE_NONE;
|
||||
}
|
||||
}
|
||||
#endif // CONFIG_LOOP_RESTORATION
|
||||
@@ -3817,7 +3849,8 @@ void vp10_decode_frame(VP10Decoder *pbi, const uint8_t *data,
|
||||
#if CONFIG_LOOP_RESTORATION
|
||||
if (cm->rst_info.restoration_type != RESTORE_NONE) {
|
||||
vp10_loop_restoration_init(&cm->rst_internal, &cm->rst_info,
|
||||
cm->frame_type == KEY_FRAME);
|
||||
cm->frame_type == KEY_FRAME, cm->width,
|
||||
cm->height);
|
||||
vp10_loop_restoration_rows(new_fb, cm, 0, cm->mi_rows, 0);
|
||||
}
|
||||
#endif // CONFIG_LOOP_RESTORATION
|
||||
|
||||
@@ -9,8 +9,8 @@
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <limits.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "vpx/vpx_encoder.h"
|
||||
#include "vpx_dsp/bitwriter_buffer.h"
|
||||
@@ -38,8 +38,8 @@
|
||||
#if CONFIG_ANS
|
||||
#include "vp10/encoder/buf_ans.h"
|
||||
#endif // CONFIG_ANS
|
||||
#include "vp10/encoder/cost.h"
|
||||
#include "vp10/encoder/bitstream.h"
|
||||
#include "vp10/encoder/cost.h"
|
||||
#include "vp10/encoder/encodemv.h"
|
||||
#include "vp10/encoder/mcomp.h"
|
||||
#include "vp10/encoder/segmentation.h"
|
||||
@@ -2410,27 +2410,42 @@ static void update_coef_probs(VP10_COMP *cpi, vp10_writer *w) {
|
||||
#if CONFIG_LOOP_RESTORATION
|
||||
static void encode_restoration(VP10_COMMON *cm,
|
||||
struct vpx_write_bit_buffer *wb) {
|
||||
int i;
|
||||
RestorationInfo *rst = &cm->rst_info;
|
||||
vpx_wb_write_bit(wb, rst->restoration_type != RESTORE_NONE);
|
||||
if (rst->restoration_type != RESTORE_NONE) {
|
||||
if (rst->restoration_type == RESTORE_BILATERAL) {
|
||||
vpx_wb_write_bit(wb, 1);
|
||||
vpx_wb_write_literal(wb, rst->restoration_level,
|
||||
vp10_restoration_level_bits(cm));
|
||||
for (i = 0; i < cm->rst_internal.ntiles; ++i) {
|
||||
if (rst->bilateral_level[i] >= 0) {
|
||||
vpx_wb_write_bit(wb, 1);
|
||||
vpx_wb_write_literal(wb, rst->bilateral_level[i],
|
||||
vp10_bilateral_level_bits(cm));
|
||||
} else {
|
||||
vpx_wb_write_bit(wb, 0);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
vpx_wb_write_bit(wb, 0);
|
||||
vpx_wb_write_literal(wb, rst->vfilter[0] - WIENER_FILT_TAP0_MINV,
|
||||
WIENER_FILT_TAP0_BITS);
|
||||
vpx_wb_write_literal(wb, rst->vfilter[1] - WIENER_FILT_TAP1_MINV,
|
||||
WIENER_FILT_TAP1_BITS);
|
||||
vpx_wb_write_literal(wb, rst->vfilter[2] - WIENER_FILT_TAP2_MINV,
|
||||
WIENER_FILT_TAP2_BITS);
|
||||
vpx_wb_write_literal(wb, rst->hfilter[0] - WIENER_FILT_TAP0_MINV,
|
||||
WIENER_FILT_TAP0_BITS);
|
||||
vpx_wb_write_literal(wb, rst->hfilter[1] - WIENER_FILT_TAP1_MINV,
|
||||
WIENER_FILT_TAP1_BITS);
|
||||
vpx_wb_write_literal(wb, rst->hfilter[2] - WIENER_FILT_TAP2_MINV,
|
||||
WIENER_FILT_TAP2_BITS);
|
||||
for (i = 0; i < cm->rst_internal.ntiles; ++i) {
|
||||
if (rst->wiener_level[i]) {
|
||||
vpx_wb_write_bit(wb, 1);
|
||||
vpx_wb_write_literal(wb, rst->vfilter[i][0] - WIENER_FILT_TAP0_MINV,
|
||||
WIENER_FILT_TAP0_BITS);
|
||||
vpx_wb_write_literal(wb, rst->vfilter[i][1] - WIENER_FILT_TAP1_MINV,
|
||||
WIENER_FILT_TAP1_BITS);
|
||||
vpx_wb_write_literal(wb, rst->vfilter[i][2] - WIENER_FILT_TAP2_MINV,
|
||||
WIENER_FILT_TAP2_BITS);
|
||||
vpx_wb_write_literal(wb, rst->hfilter[i][0] - WIENER_FILT_TAP0_MINV,
|
||||
WIENER_FILT_TAP0_BITS);
|
||||
vpx_wb_write_literal(wb, rst->hfilter[i][1] - WIENER_FILT_TAP1_MINV,
|
||||
WIENER_FILT_TAP1_BITS);
|
||||
vpx_wb_write_literal(wb, rst->hfilter[i][2] - WIENER_FILT_TAP2_MINV,
|
||||
WIENER_FILT_TAP2_BITS);
|
||||
} else {
|
||||
vpx_wb_write_bit(wb, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,9 +8,9 @@
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include <limits.h>
|
||||
#include <math.h>
|
||||
#include <stdio.h>
|
||||
#include <limits.h>
|
||||
|
||||
#include "./vpx_config.h"
|
||||
|
||||
@@ -459,14 +459,12 @@ static void dealloc_compressor_data(VP10_COMP *cpi) {
|
||||
vpx_free_frame_buffer(&cpi->upsampled_ref_bufs[i].buf);
|
||||
|
||||
vp10_free_ref_frame_buffers(cm->buffer_pool);
|
||||
#if CONFIG_LOOP_RESTORATION
|
||||
vp10_free_restoration_buffers(cm);
|
||||
#endif // CONFIG_LOOP_RESTORATION
|
||||
vp10_free_context_buffers(cm);
|
||||
|
||||
vpx_free_frame_buffer(&cpi->last_frame_uf);
|
||||
#if CONFIG_LOOP_RESTORATION
|
||||
vpx_free_frame_buffer(&cpi->last_frame_db);
|
||||
vp10_free_restoration_buffers(cm);
|
||||
#endif // CONFIG_LOOP_RESTORATION
|
||||
vpx_free_frame_buffer(&cpi->scaled_source);
|
||||
vpx_free_frame_buffer(&cpi->scaled_last_source);
|
||||
@@ -3492,7 +3490,8 @@ static void loopfilter_frame(VP10_COMP *cpi, VP10_COMMON *cm) {
|
||||
#if CONFIG_LOOP_RESTORATION
|
||||
if (cm->rst_info.restoration_type != RESTORE_NONE) {
|
||||
vp10_loop_restoration_init(&cm->rst_internal, &cm->rst_info,
|
||||
cm->frame_type == KEY_FRAME);
|
||||
cm->frame_type == KEY_FRAME, cm->width,
|
||||
cm->height);
|
||||
vp10_loop_restoration_rows(cm->frame_to_show, cm, 0, cm->mi_rows, 0);
|
||||
}
|
||||
#endif // CONFIG_LOOP_RESTORATION
|
||||
|
||||
@@ -24,9 +24,9 @@
|
||||
#include "vp10/common/quant_common.h"
|
||||
|
||||
#include "vp10/encoder/encoder.h"
|
||||
#include "vp10/encoder/quantize.h"
|
||||
#include "vp10/encoder/picklpf.h"
|
||||
#include "vp10/encoder/pickrst.h"
|
||||
#include "vp10/encoder/quantize.h"
|
||||
|
||||
static int64_t try_restoration_frame(const YV12_BUFFER_CONFIG *sd,
|
||||
VP10_COMP *const cpi, RestorationInfo *rsi,
|
||||
@@ -51,17 +51,18 @@ static int64_t try_restoration_frame(const YV12_BUFFER_CONFIG *sd,
|
||||
|
||||
static int search_bilateral_level(const YV12_BUFFER_CONFIG *sd, VP10_COMP *cpi,
|
||||
int filter_level, int partial_frame,
|
||||
double *best_cost_ret) {
|
||||
int *bilateral_level, double *best_cost_ret) {
|
||||
VP10_COMMON *const cm = &cpi->common;
|
||||
int i, restoration_best;
|
||||
int i, j, tile_idx;
|
||||
int64_t err;
|
||||
double best_cost;
|
||||
double cost;
|
||||
const int restoration_level_bits = vp10_restoration_level_bits(&cpi->common);
|
||||
const int restoration_levels = 1 << restoration_level_bits;
|
||||
MACROBLOCK *x = &cpi->td.mb;
|
||||
int bits;
|
||||
double cost, best_cost, cost_norestore, cost_bilateral;
|
||||
const int bilateral_level_bits = vp10_bilateral_level_bits(&cpi->common);
|
||||
const int bilateral_levels = 1 << bilateral_level_bits;
|
||||
MACROBLOCK *x = &cpi->td.mb;
|
||||
RestorationInfo rsi;
|
||||
const int ntiles =
|
||||
vp10_get_restoration_ntiles(BILATERAL_TILESIZE, cm->width, cm->height);
|
||||
|
||||
// Make a copy of the unfiltered / processed recon buffer
|
||||
vpx_yv12_copy_y(cm->frame_to_show, &cpi->last_frame_uf);
|
||||
@@ -69,60 +70,102 @@ static int search_bilateral_level(const YV12_BUFFER_CONFIG *sd, VP10_COMP *cpi,
|
||||
1, partial_frame);
|
||||
vpx_yv12_copy_y(cm->frame_to_show, &cpi->last_frame_db);
|
||||
|
||||
restoration_best = -1;
|
||||
// RD cost associated with no restoration
|
||||
rsi.restoration_type = RESTORE_NONE;
|
||||
err = try_restoration_frame(sd, cpi, &rsi, partial_frame);
|
||||
bits = 0;
|
||||
best_cost = RDCOST_DBL(x->rdmult, x->rddiv,
|
||||
(bits << (VP10_PROB_COST_SHIFT - 4)), err);
|
||||
for (i = 0; i < restoration_levels; ++i) {
|
||||
rsi.restoration_type = RESTORE_BILATERAL;
|
||||
rsi.restoration_level = i;
|
||||
err = try_restoration_frame(sd, cpi, &rsi, partial_frame);
|
||||
// Normally the rate is rate in bits * 256 and dist is sum sq err * 64
|
||||
// when RDCOST is used. However below we just scale both in the correct
|
||||
// ratios appropriately but not exactly by these values.
|
||||
bits = restoration_level_bits;
|
||||
cost = RDCOST_DBL(x->rdmult, x->rddiv, (bits << (VP10_PROB_COST_SHIFT - 4)),
|
||||
err);
|
||||
if (cost < best_cost) {
|
||||
restoration_best = i;
|
||||
best_cost = cost;
|
||||
cost_norestore = RDCOST_DBL(x->rdmult, x->rddiv,
|
||||
(bits << (VP10_PROB_COST_SHIFT - 4)), err);
|
||||
best_cost = cost_norestore;
|
||||
|
||||
// RD cost associated with bilateral filtering
|
||||
rsi.restoration_type = RESTORE_BILATERAL;
|
||||
rsi.bilateral_level =
|
||||
(int *)vpx_malloc(sizeof(*rsi.bilateral_level) * ntiles);
|
||||
assert(rsi.bilateral_level != NULL);
|
||||
|
||||
for (j = 0; j < ntiles; ++j) bilateral_level[j] = -1;
|
||||
|
||||
// Find best filter for each tile
|
||||
for (tile_idx = 0; tile_idx < ntiles; ++tile_idx) {
|
||||
for (j = 0; j < ntiles; ++j) rsi.bilateral_level[j] = -1;
|
||||
best_cost = cost_norestore;
|
||||
for (i = 0; i < bilateral_levels; ++i) {
|
||||
rsi.bilateral_level[tile_idx] = i;
|
||||
err = try_restoration_frame(sd, cpi, &rsi, partial_frame);
|
||||
bits = bilateral_level_bits + 1;
|
||||
// Normally the rate is rate in bits * 256 and dist is sum sq err * 64
|
||||
// when RDCOST is used. However below we just scale both in the correct
|
||||
// ratios appropriately but not exactly by these values.
|
||||
cost = RDCOST_DBL(x->rdmult, x->rddiv,
|
||||
(bits << (VP10_PROB_COST_SHIFT - 4)), err);
|
||||
if (cost < best_cost) {
|
||||
bilateral_level[tile_idx] = i;
|
||||
best_cost = cost;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (best_cost_ret) *best_cost_ret = best_cost;
|
||||
// Find cost for combined configuration
|
||||
bits = 0;
|
||||
for (j = 0; j < ntiles; ++j) {
|
||||
rsi.bilateral_level[j] = bilateral_level[j];
|
||||
if (rsi.bilateral_level[j] >= 0) {
|
||||
bits += (bilateral_level_bits + 1);
|
||||
} else {
|
||||
bits += 1;
|
||||
}
|
||||
}
|
||||
err = try_restoration_frame(sd, cpi, &rsi, partial_frame);
|
||||
cost_bilateral = RDCOST_DBL(x->rdmult, x->rddiv,
|
||||
(bits << (VP10_PROB_COST_SHIFT - 4)), err);
|
||||
|
||||
vpx_free(rsi.bilateral_level);
|
||||
|
||||
vpx_yv12_copy_y(&cpi->last_frame_uf, cm->frame_to_show);
|
||||
return restoration_best;
|
||||
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 *sd,
|
||||
VP10_COMP *cpi, int partial_frame,
|
||||
int *restoration_level,
|
||||
int *filter_best, int *bilateral_level,
|
||||
double *best_cost_ret) {
|
||||
const VP10_COMMON *const cm = &cpi->common;
|
||||
const struct loopfilter *const lf = &cm->lf;
|
||||
const int min_filter_level = 0;
|
||||
const int max_filter_level = vp10_get_max_filter_level(cpi);
|
||||
int filt_direction = 0;
|
||||
int filt_best, restoration_best;
|
||||
int filt_best;
|
||||
double best_err;
|
||||
int i;
|
||||
int bilateral_lev;
|
||||
int i, j;
|
||||
int *tmp_level;
|
||||
int bilateral_success[MAX_LOOP_FILTER + 1];
|
||||
|
||||
const int ntiles =
|
||||
vp10_get_restoration_ntiles(BILATERAL_TILESIZE, cm->width, cm->height);
|
||||
|
||||
// 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;
|
||||
|
||||
bilateral_lev =
|
||||
search_bilateral_level(sd, cpi, filt_mid, partial_frame, &best_err);
|
||||
tmp_level = (int *)vpx_malloc(sizeof(*tmp_level) * ntiles);
|
||||
|
||||
bilateral_success[filt_mid] = search_bilateral_level(
|
||||
sd, cpi, filt_mid, partial_frame, tmp_level, &best_err);
|
||||
filt_best = filt_mid;
|
||||
restoration_best = bilateral_lev;
|
||||
ss_err[filt_mid] = best_err;
|
||||
for (j = 0; j < ntiles; ++j) {
|
||||
bilateral_level[j] = tmp_level[j];
|
||||
}
|
||||
|
||||
while (filter_step > 0) {
|
||||
const int filt_high = VPXMIN(filt_mid + filter_step, max_filter_level);
|
||||
@@ -140,8 +183,8 @@ static int search_filter_bilateral_level(const YV12_BUFFER_CONFIG *sd,
|
||||
if (filt_direction <= 0 && filt_low != filt_mid) {
|
||||
// Get Low filter error score
|
||||
if (ss_err[filt_low] < 0) {
|
||||
bilateral_lev = search_bilateral_level(sd, cpi, filt_low, partial_frame,
|
||||
&ss_err[filt_low]);
|
||||
bilateral_success[filt_low] = search_bilateral_level(
|
||||
sd, cpi, filt_low, partial_frame, tmp_level, &ss_err[filt_low]);
|
||||
}
|
||||
// If value is close to the best so far then bias towards a lower loop
|
||||
// filter value.
|
||||
@@ -151,22 +194,26 @@ static int search_filter_bilateral_level(const YV12_BUFFER_CONFIG *sd,
|
||||
best_err = ss_err[filt_low];
|
||||
}
|
||||
filt_best = filt_low;
|
||||
restoration_best = bilateral_lev;
|
||||
for (j = 0; j < ntiles; ++j) {
|
||||
bilateral_level[j] = tmp_level[j];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Now look at filt_high
|
||||
if (filt_direction >= 0 && filt_high != filt_mid) {
|
||||
if (ss_err[filt_high] < 0) {
|
||||
bilateral_lev = search_bilateral_level(
|
||||
sd, cpi, filt_high, partial_frame, &ss_err[filt_high]);
|
||||
bilateral_success[filt_high] = search_bilateral_level(
|
||||
sd, cpi, filt_high, partial_frame, tmp_level, &ss_err[filt_high]);
|
||||
}
|
||||
// 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;
|
||||
restoration_best = bilateral_lev;
|
||||
for (j = 0; j < ntiles; ++j) {
|
||||
bilateral_level[j] = tmp_level[j];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -180,35 +227,40 @@ static int search_filter_bilateral_level(const YV12_BUFFER_CONFIG *sd,
|
||||
}
|
||||
}
|
||||
|
||||
vpx_free(tmp_level);
|
||||
|
||||
// Update best error
|
||||
best_err = ss_err[filt_best];
|
||||
|
||||
*restoration_level = restoration_best;
|
||||
if (best_cost_ret) *best_cost_ret = best_err;
|
||||
return filt_best;
|
||||
if (filter_best) *filter_best = filt_best;
|
||||
|
||||
return bilateral_success[filt_best];
|
||||
}
|
||||
|
||||
static double find_average(uint8_t *src, int width, int height, int stride) {
|
||||
static double find_average(uint8_t *src, int h_start, int h_end, int v_start,
|
||||
int v_end, int stride) {
|
||||
uint64_t sum = 0;
|
||||
double avg = 0;
|
||||
int i, j;
|
||||
for (i = 0; i < height; i++)
|
||||
for (j = 0; j < width; j++) sum += src[i * stride + j];
|
||||
avg = (double)sum / (height * width);
|
||||
for (i = v_start; i < v_end; i++)
|
||||
for (j = h_start; j < h_end; j++) sum += src[i * stride + j];
|
||||
avg = (double)sum / ((v_end - v_start) * (h_end - h_start));
|
||||
return avg;
|
||||
}
|
||||
|
||||
static void compute_stats(uint8_t *dgd, uint8_t *src, int width, int height,
|
||||
int dgd_stride, int src_stride, double *M,
|
||||
double *H) {
|
||||
static void compute_stats(uint8_t *dgd, uint8_t *src, int h_start, int h_end,
|
||||
int v_start, int v_end, int dgd_stride,
|
||||
int src_stride, double *M, double *H) {
|
||||
int i, j, k, l;
|
||||
double Y[RESTORATION_WIN2];
|
||||
const double avg = find_average(dgd, width, height, dgd_stride);
|
||||
const double avg =
|
||||
find_average(dgd, h_start, h_end, v_start, v_end, dgd_stride);
|
||||
|
||||
memset(M, 0, sizeof(*M) * RESTORATION_WIN2);
|
||||
memset(H, 0, sizeof(*H) * RESTORATION_WIN2 * RESTORATION_WIN2);
|
||||
for (i = RESTORATION_HALFWIN; i < height - RESTORATION_HALFWIN; i++) {
|
||||
for (j = RESTORATION_HALFWIN; j < width - RESTORATION_HALFWIN; j++) {
|
||||
for (i = v_start; i < v_end; i++) {
|
||||
for (j = h_start; j < h_end; j++) {
|
||||
const double X = (double)src[i * src_stride + j] - avg;
|
||||
int idx = 0;
|
||||
for (k = -RESTORATION_HALFWIN; k <= RESTORATION_HALFWIN; k++) {
|
||||
@@ -231,30 +283,32 @@ static void compute_stats(uint8_t *dgd, uint8_t *src, int width, int height,
|
||||
}
|
||||
|
||||
#if CONFIG_VP9_HIGHBITDEPTH
|
||||
static double find_average_highbd(uint16_t *src, int width, int height,
|
||||
int stride) {
|
||||
static double find_average_highbd(uint16_t *src, int h_start, int h_end,
|
||||
int v_start, int v_end, int stride) {
|
||||
uint64_t sum = 0;
|
||||
double avg = 0;
|
||||
int i, j;
|
||||
for (i = 0; i < height; i++)
|
||||
for (j = 0; j < width; j++) sum += src[i * stride + j];
|
||||
avg = (double)sum / (height * width);
|
||||
for (i = v_start; i < v_end; i++)
|
||||
for (j = h_start; j < h_end; j++) sum += src[i * stride + j];
|
||||
avg = (double)sum / ((v_end - v_start) * (h_end - h_start));
|
||||
return avg;
|
||||
}
|
||||
|
||||
static void compute_stats_highbd(uint8_t *dgd8, uint8_t *src8, int width,
|
||||
int height, int dgd_stride, int src_stride,
|
||||
double *M, double *H) {
|
||||
static void compute_stats_highbd(uint8_t *dgd8, uint8_t *src8, int h_start,
|
||||
int h_end, int v_start, int v_end,
|
||||
int dgd_stride, int src_stride, double *M,
|
||||
double *H) {
|
||||
int i, j, k, l;
|
||||
double Y[RESTORATION_WIN2];
|
||||
uint16_t *src = CONVERT_TO_SHORTPTR(src8);
|
||||
uint16_t *dgd = CONVERT_TO_SHORTPTR(dgd8);
|
||||
const double avg = find_average_highbd(dgd, width, height, dgd_stride);
|
||||
const double avg =
|
||||
find_average_highbd(dgd, h_start, h_end, v_start, v_end, dgd_stride);
|
||||
|
||||
memset(M, 0, sizeof(*M) * RESTORATION_WIN2);
|
||||
memset(H, 0, sizeof(*H) * RESTORATION_WIN2 * RESTORATION_WIN2);
|
||||
for (i = RESTORATION_HALFWIN; i < height - RESTORATION_HALFWIN; i++) {
|
||||
for (j = RESTORATION_HALFWIN; j < width - RESTORATION_HALFWIN; j++) {
|
||||
for (i = v_start; i < v_end; i++) {
|
||||
for (j = h_start; j < h_end; j++) {
|
||||
const double X = (double)src[i * src_stride + j] - avg;
|
||||
int idx = 0;
|
||||
for (k = -RESTORATION_HALFWIN; k <= RESTORATION_HALFWIN; k++) {
|
||||
@@ -492,8 +546,9 @@ static void quantize_sym_filter(double *f, int *fi) {
|
||||
|
||||
static int search_wiener_filter(const YV12_BUFFER_CONFIG *src, VP10_COMP *cpi,
|
||||
int filter_level, int partial_frame,
|
||||
int *vfilter, int *hfilter,
|
||||
double *best_cost_ret) {
|
||||
int (*vfilter)[RESTORATION_HALFWIN],
|
||||
int (*hfilter)[RESTORATION_HALFWIN],
|
||||
int *process_tile, double *best_cost_ret) {
|
||||
VP10_COMMON *const cm = &cpi->common;
|
||||
RestorationInfo rsi;
|
||||
int64_t err;
|
||||
@@ -509,12 +564,21 @@ static int search_wiener_filter(const YV12_BUFFER_CONFIG *src, VP10_COMP *cpi,
|
||||
const int src_stride = src->y_stride;
|
||||
const int dgd_stride = dgd->y_stride;
|
||||
double score;
|
||||
int tile_idx, htile_idx, vtile_idx, tile_width, tile_height, nhtiles, nvtiles;
|
||||
int h_start, h_end, v_start, v_end;
|
||||
int i, j;
|
||||
|
||||
const int tilesize = WIENER_TILESIZE;
|
||||
const int ntiles = vp10_get_restoration_ntiles(tilesize, width, height);
|
||||
|
||||
assert(width == dgd->y_crop_width);
|
||||
assert(height == dgd->y_crop_height);
|
||||
assert(width == src->y_crop_width);
|
||||
assert(height == src->y_crop_height);
|
||||
|
||||
vp10_get_restoration_tile_size(tilesize, width, height, &tile_width,
|
||||
&tile_height, &nhtiles, &nvtiles);
|
||||
|
||||
// Make a copy of the unfiltered / processed recon buffer
|
||||
vpx_yv12_copy_y(cm->frame_to_show, &cpi->last_frame_uf);
|
||||
vp10_loop_filter_frame(cm->frame_to_show, cm, &cpi->td.mb.e_mbd, filter_level,
|
||||
@@ -527,45 +591,91 @@ static int search_wiener_filter(const YV12_BUFFER_CONFIG *src, VP10_COMP *cpi,
|
||||
cost_norestore = RDCOST_DBL(x->rdmult, x->rddiv,
|
||||
(bits << (VP10_PROB_COST_SHIFT - 4)), err);
|
||||
|
||||
#if CONFIG_VP9_HIGHBITDEPTH
|
||||
if (cm->use_highbitdepth)
|
||||
compute_stats_highbd(dgd->y_buffer, src->y_buffer, width, height,
|
||||
dgd_stride, src_stride, M, H);
|
||||
else
|
||||
#endif // CONFIG_VP9_HIGHBITDEPTH
|
||||
compute_stats(dgd->y_buffer, src->y_buffer, width, height, dgd_stride,
|
||||
src_stride, M, H);
|
||||
|
||||
if (!wiener_decompose_sep_sym(M, H, vfilterd, hfilterd)) {
|
||||
*best_cost_ret = DBL_MAX;
|
||||
return 0;
|
||||
}
|
||||
quantize_sym_filter(vfilterd, vfilter);
|
||||
quantize_sym_filter(hfilterd, 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, vfilter, hfilter);
|
||||
if (score > 0.0) {
|
||||
int i;
|
||||
for (i = 0; i < RESTORATION_HALFWIN; ++i) vfilter[i] = hfilter[i] = 0;
|
||||
rsi.restoration_type = RESTORE_NONE;
|
||||
if (best_cost_ret) *best_cost_ret = cost_norestore;
|
||||
vpx_yv12_copy_y(&cpi->last_frame_uf, cm->frame_to_show);
|
||||
return 0;
|
||||
}
|
||||
|
||||
rsi.restoration_type = RESTORE_WIENER;
|
||||
memcpy(rsi.vfilter, vfilter, sizeof(rsi.vfilter));
|
||||
memcpy(rsi.hfilter, hfilter, sizeof(rsi.hfilter));
|
||||
rsi.vfilter =
|
||||
(int(*)[RESTORATION_HALFWIN])vpx_malloc(sizeof(*rsi.vfilter) * ntiles);
|
||||
assert(rsi.vfilter != NULL);
|
||||
rsi.hfilter =
|
||||
(int(*)[RESTORATION_HALFWIN])vpx_malloc(sizeof(*rsi.hfilter) * ntiles);
|
||||
assert(rsi.hfilter != NULL);
|
||||
rsi.wiener_level = (int *)vpx_malloc(sizeof(*rsi.wiener_level) * ntiles);
|
||||
assert(rsi.wiener_level != NULL);
|
||||
|
||||
// Compute best Wiener filters for each tile
|
||||
for (tile_idx = 0; tile_idx < ntiles; ++tile_idx) {
|
||||
htile_idx = tile_idx % nhtiles;
|
||||
vtile_idx = tile_idx / nhtiles;
|
||||
h_start =
|
||||
htile_idx * tile_width + ((htile_idx > 0) ? 0 : RESTORATION_HALFWIN);
|
||||
h_end = (htile_idx < 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 < nvtiles - 1) ? ((vtile_idx + 1) * tile_height)
|
||||
: (height - RESTORATION_HALFWIN);
|
||||
|
||||
#if CONFIG_VP9_HIGHBITDEPTH
|
||||
if (cm->use_highbitdepth)
|
||||
compute_stats_highbd(dgd->y_buffer, src->y_buffer, h_start, h_end,
|
||||
v_start, v_end, dgd_stride, src_stride, M, H);
|
||||
else
|
||||
#endif // CONFIG_VP9_HIGHBITDEPTH
|
||||
compute_stats(dgd->y_buffer, src->y_buffer, h_start, h_end, v_start,
|
||||
v_end, dgd_stride, src_stride, M, H);
|
||||
|
||||
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;
|
||||
process_tile[tile_idx] = 0;
|
||||
continue;
|
||||
}
|
||||
quantize_sym_filter(vfilterd, rsi.vfilter[tile_idx]);
|
||||
quantize_sym_filter(hfilterd, rsi.hfilter[tile_idx]);
|
||||
process_tile[tile_idx] = 1;
|
||||
|
||||
// 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]);
|
||||
if (score > 0.0) {
|
||||
for (i = 0; i < RESTORATION_HALFWIN; ++i)
|
||||
rsi.vfilter[tile_idx][i] = rsi.hfilter[tile_idx][i] = 0;
|
||||
process_tile[tile_idx] = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
for (j = 0; j < ntiles; ++j) rsi.wiener_level[j] = 0;
|
||||
rsi.wiener_level[tile_idx] = 1;
|
||||
|
||||
err = try_restoration_frame(src, cpi, &rsi, partial_frame);
|
||||
bits = 1 + WIENER_FILT_BITS;
|
||||
cost_wiener = RDCOST_DBL(x->rdmult, x->rddiv,
|
||||
(bits << (VP10_PROB_COST_SHIFT - 4)), err);
|
||||
if (cost_wiener >= cost_norestore) process_tile[tile_idx] = 0;
|
||||
}
|
||||
// Cost for Wiener filtering
|
||||
bits = 0;
|
||||
for (tile_idx = 0; tile_idx < ntiles; ++tile_idx) {
|
||||
bits += (process_tile[tile_idx] ? (WIENER_FILT_BITS + 1) : 1);
|
||||
rsi.wiener_level[tile_idx] = process_tile[tile_idx];
|
||||
}
|
||||
err = try_restoration_frame(src, cpi, &rsi, partial_frame);
|
||||
bits = WIENER_FILT_BITS;
|
||||
cost_wiener = RDCOST_DBL(x->rdmult, x->rddiv,
|
||||
(bits << (VP10_PROB_COST_SHIFT - 4)), err);
|
||||
|
||||
vpx_yv12_copy_y(&cpi->last_frame_uf, cm->frame_to_show);
|
||||
for (tile_idx = 0; tile_idx < ntiles; ++tile_idx) {
|
||||
if (process_tile[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];
|
||||
}
|
||||
}
|
||||
|
||||
vpx_free(rsi.vfilter);
|
||||
vpx_free(rsi.hfilter);
|
||||
vpx_free(rsi.wiener_level);
|
||||
|
||||
vpx_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;
|
||||
@@ -580,9 +690,29 @@ void vp10_pick_filter_restoration(const YV12_BUFFER_CONFIG *sd, VP10_COMP *cpi,
|
||||
VP10_COMMON *const cm = &cpi->common;
|
||||
struct loopfilter *const lf = &cm->lf;
|
||||
int wiener_success = 0;
|
||||
int bilateral_success = 0;
|
||||
double cost_bilateral = DBL_MAX;
|
||||
double cost_wiener = DBL_MAX;
|
||||
double cost_norestore = DBL_MAX;
|
||||
int ntiles;
|
||||
|
||||
ntiles =
|
||||
vp10_get_restoration_ntiles(BILATERAL_TILESIZE, cm->width, cm->height);
|
||||
cm->rst_info.bilateral_level =
|
||||
(int *)vpx_realloc(cm->rst_info.bilateral_level,
|
||||
sizeof(*cm->rst_info.bilateral_level) * ntiles);
|
||||
assert(cm->rst_info.bilateral_level != NULL);
|
||||
|
||||
ntiles = vp10_get_restoration_ntiles(WIENER_TILESIZE, cm->width, cm->height);
|
||||
cm->rst_info.wiener_level = (int *)vpx_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_HALFWIN])vpx_realloc(
|
||||
cm->rst_info.vfilter, sizeof(*cm->rst_info.vfilter) * ntiles);
|
||||
assert(cm->rst_info.vfilter != NULL);
|
||||
cm->rst_info.hfilter = (int(*)[RESTORATION_HALFWIN])vpx_realloc(
|
||||
cm->rst_info.hfilter, sizeof(*cm->rst_info.hfilter) * ntiles);
|
||||
assert(cm->rst_info.hfilter != NULL);
|
||||
|
||||
lf->sharpness_level = cm->frame_type == KEY_FRAME ? 0 : cpi->oxcf.sharpness;
|
||||
|
||||
@@ -618,14 +748,15 @@ void vp10_pick_filter_restoration(const YV12_BUFFER_CONFIG *sd, VP10_COMP *cpi,
|
||||
#endif // CONFIG_VP9_HIGHBITDEPTH
|
||||
if (cm->frame_type == KEY_FRAME) filt_guess -= 4;
|
||||
lf->filter_level = clamp(filt_guess, min_filter_level, max_filter_level);
|
||||
cm->rst_info.restoration_level = search_bilateral_level(
|
||||
bilateral_success = search_bilateral_level(
|
||||
sd, cpi, lf->filter_level, method == LPF_PICK_FROM_SUBIMAGE,
|
||||
&cost_bilateral);
|
||||
cm->rst_info.bilateral_level, &cost_bilateral);
|
||||
wiener_success = search_wiener_filter(
|
||||
sd, cpi, lf->filter_level, method == LPF_PICK_FROM_SUBIMAGE,
|
||||
cm->rst_info.vfilter, cm->rst_info.hfilter, &cost_wiener);
|
||||
cm->rst_info.vfilter, cm->rst_info.hfilter, cm->rst_info.wiener_level,
|
||||
&cost_wiener);
|
||||
if (cost_bilateral < cost_wiener) {
|
||||
if (cm->rst_info.restoration_level != -1)
|
||||
if (bilateral_success)
|
||||
cm->rst_info.restoration_type = RESTORE_BILATERAL;
|
||||
else
|
||||
cm->rst_info.restoration_type = RESTORE_NONE;
|
||||
@@ -637,17 +768,18 @@ void vp10_pick_filter_restoration(const YV12_BUFFER_CONFIG *sd, VP10_COMP *cpi,
|
||||
}
|
||||
} else {
|
||||
int blf_filter_level = -1;
|
||||
blf_filter_level = search_filter_bilateral_level(
|
||||
sd, cpi, method == LPF_PICK_FROM_SUBIMAGE,
|
||||
&cm->rst_info.restoration_level, &cost_bilateral);
|
||||
bilateral_success = search_filter_bilateral_level(
|
||||
sd, cpi, method == LPF_PICK_FROM_SUBIMAGE, &blf_filter_level,
|
||||
cm->rst_info.bilateral_level, &cost_bilateral);
|
||||
lf->filter_level = vp10_search_filter_level(
|
||||
sd, cpi, method == LPF_PICK_FROM_SUBIMAGE, &cost_norestore);
|
||||
wiener_success = search_wiener_filter(
|
||||
sd, cpi, lf->filter_level, method == LPF_PICK_FROM_SUBIMAGE,
|
||||
cm->rst_info.vfilter, cm->rst_info.hfilter, &cost_wiener);
|
||||
cm->rst_info.vfilter, cm->rst_info.hfilter, cm->rst_info.wiener_level,
|
||||
&cost_wiener);
|
||||
if (cost_bilateral < cost_wiener) {
|
||||
lf->filter_level = blf_filter_level;
|
||||
if (cm->rst_info.restoration_level != -1)
|
||||
if (bilateral_success)
|
||||
cm->rst_info.restoration_type = RESTORE_BILATERAL;
|
||||
else
|
||||
cm->rst_info.restoration_type = RESTORE_NONE;
|
||||
@@ -658,7 +790,19 @@ void vp10_pick_filter_restoration(const YV12_BUFFER_CONFIG *sd, VP10_COMP *cpi,
|
||||
cm->rst_info.restoration_type = RESTORE_NONE;
|
||||
}
|
||||
// printf("[%d] Costs %g %g (%d) %g (%d)\n", cm->rst_info.restoration_type,
|
||||
// cost_norestore, cost_bilateral, lf->filter_level, cost_wiener,
|
||||
// wiener_success);
|
||||
// cost_norestore, cost_bilateral, lf->filter_level, cost_wiener,
|
||||
// wiener_success);
|
||||
}
|
||||
if (cm->rst_info.restoration_type != RESTORE_BILATERAL) {
|
||||
vpx_free(cm->rst_info.bilateral_level);
|
||||
cm->rst_info.bilateral_level = NULL;
|
||||
}
|
||||
if (cm->rst_info.restoration_type != RESTORE_WIENER) {
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user