Commit 3981be93 authored by Debargha Mukherjee's avatar Debargha Mukherjee

Add domain transform recursive filter

This filter is meant to replace the bilateral filter,
but is currently added in addition to the bilateral filter
for testing.

Change-Id: Ia529701e69833d47c11b3367d5bf804eb8498079
parent eee4315e
......@@ -91,6 +91,8 @@ void av1_free_restoration_buffers(AV1_COMMON *cm) {
cm->rst_info.wiener_info = NULL;
aom_free(cm->rst_info.sgrproj_info);
cm->rst_info.sgrproj_info = NULL;
aom_free(cm->rst_info.domaintxfmrf_info);
cm->rst_info.domaintxfmrf_info = NULL;
}
#endif // CONFIG_LOOP_RESTORATION
......
......@@ -1186,11 +1186,20 @@ static const aom_prob default_tx_size_prob[MAX_TX_DEPTH][TX_SIZE_CONTEXTS]
#if CONFIG_LOOP_RESTORATION
const aom_tree_index av1_switchable_restore_tree[TREE_SIZE(
RESTORE_SWITCHABLE_TYPES)] = {
-RESTORE_NONE, 2, -RESTORE_SGRPROJ, 4, -RESTORE_BILATERAL, -RESTORE_WIENER,
// -RESTORE_NONE, 2, -RESTORE_SGRPROJ, 4, -RESTORE_BILATERAL, -RESTORE_WIENER,
-RESTORE_NONE,
2,
4,
6,
-RESTORE_SGRPROJ,
-RESTORE_DOMAINTXFMRF,
-RESTORE_BILATERAL,
-RESTORE_WIENER,
};
static const aom_prob default_switchable_restore_prob[RESTORE_SWITCHABLE_TYPES -
1] = { 32, 85, 128 };
1] = { 32, 128, 128,
128 };
#endif // CONFIG_LOOP_RESTORATION
#if CONFIG_PALETTE
......
......@@ -346,6 +346,7 @@ extern const aom_tree_index av1_motion_mode_tree[TREE_SIZE(MOTION_MODES)];
#define RESTORE_NONE_SGRPROJ_PROB 64
#define RESTORE_NONE_BILATERAL_PROB 16
#define RESTORE_NONE_WIENER_PROB 64
#define RESTORE_NONE_DOMAINTXFMRF_PROB 64
extern const aom_tree_index
av1_switchable_restore_tree[TREE_SIZE(RESTORE_SWITCHABLE_TYPES)];
#endif // CONFIG_LOOP_RESTORATION
......
......@@ -485,7 +485,8 @@ typedef enum {
RESTORE_SGRPROJ = 1,
RESTORE_BILATERAL = 2,
RESTORE_WIENER = 3,
RESTORE_SWITCHABLE = 4,
RESTORE_DOMAINTXFMRF = 4,
RESTORE_SWITCHABLE = 5,
RESTORE_SWITCHABLE_TYPES = RESTORE_SWITCHABLE,
RESTORE_TYPES,
} RestorationType;
......
......@@ -20,6 +20,16 @@
#include "aom_mem/aom_mem.h"
#include "aom_ports/mem.h"
static int domaintxfmrf_vtable[DOMAINTXFMRF_ITERS][DOMAINTXFMRF_PARAMS][256];
static const int domaintxfmrf_params[DOMAINTXFMRF_PARAMS] = {
48, 52, 56, 60, 64, 68, 72, 76, 80, 82, 84, 86, 88,
90, 92, 94, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105,
106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118,
119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 130, 132, 134,
136, 138, 140, 142, 146, 150, 154, 158, 162, 166, 170, 174
};
#define BILATERAL_PARAM_PRECISION 16
#define BILATERAL_AMP_RANGE 256
#define BILATERAL_AMP_RANGE_SYM (2 * BILATERAL_AMP_RANGE + 1)
......@@ -76,7 +86,26 @@ static INLINE BilateralParamsType av1_bilateral_level_to_params(int index,
: bilateral_level_to_params_arr[index];
}
void av1_loop_restoration_precal() {
static void GenDomainTxfmRFVtable() {
int i, j;
const double sigma_s = sqrt(2.0);
for (i = 0; i < DOMAINTXFMRF_ITERS; ++i) {
const int nm = (1 << (DOMAINTXFMRF_ITERS - i - 1));
const double A = exp(-DOMAINTXFMRF_MULT / (sigma_s * nm));
for (j = 0; j < DOMAINTXFMRF_PARAMS; ++j) {
const double sigma_r =
(double)domaintxfmrf_params[j] / DOMAINTXFMRF_SIGMA_SCALE;
const double scale = sigma_s / sigma_r;
int k;
for (k = 0; k < 256; ++k) {
domaintxfmrf_vtable[i][j][k] =
RINT(DOMAINTXFMRF_VTABLE_PREC * pow(A, 1.0 + k * scale));
}
}
}
}
static void GenBilateralTables() {
int i;
for (i = 0; i < BILATERAL_LEVELS_KF; i++) {
const BilateralParamsType param = av1_bilateral_level_to_params(i, 1);
......@@ -140,6 +169,11 @@ void av1_loop_restoration_precal() {
}
}
void av1_loop_restoration_precal() {
GenBilateralTables();
GenDomainTxfmRFVtable();
}
int av1_bilateral_level_bits(const AV1_COMMON *const cm) {
return cm->frame_type == KEY_FRAME ? BILATERAL_LEVEL_BITS_KF
: BILATERAL_LEVEL_BITS;
......@@ -157,18 +191,20 @@ void av1_loop_restoration_init(RestorationInternal *rst, RestorationInfo *rsi,
&rst->nhtiles, &rst->nvtiles);
if (rsi->frame_restoration_type == RESTORE_WIENER) {
for (tile_idx = 0; tile_idx < rst->ntiles; ++tile_idx) {
rsi->wiener_info[tile_idx].vfilter[RESTORATION_HALFWIN] =
rsi->wiener_info[tile_idx].hfilter[RESTORATION_HALFWIN] =
RESTORATION_FILT_STEP;
for (i = 0; i < RESTORATION_HALFWIN; ++i) {
rsi->wiener_info[tile_idx].vfilter[RESTORATION_WIN - 1 - i] =
rsi->wiener_info[tile_idx].vfilter[i];
rsi->wiener_info[tile_idx].hfilter[RESTORATION_WIN - 1 - i] =
rsi->wiener_info[tile_idx].hfilter[i];
rsi->wiener_info[tile_idx].vfilter[RESTORATION_HALFWIN] -=
2 * rsi->wiener_info[tile_idx].vfilter[i];
rsi->wiener_info[tile_idx].hfilter[RESTORATION_HALFWIN] -=
2 * rsi->wiener_info[tile_idx].hfilter[i];
if (rsi->wiener_info[tile_idx].level) {
rsi->wiener_info[tile_idx].vfilter[RESTORATION_HALFWIN] =
rsi->wiener_info[tile_idx].hfilter[RESTORATION_HALFWIN] =
RESTORATION_FILT_STEP;
for (i = 0; i < RESTORATION_HALFWIN; ++i) {
rsi->wiener_info[tile_idx].vfilter[RESTORATION_WIN - 1 - i] =
rsi->wiener_info[tile_idx].vfilter[i];
rsi->wiener_info[tile_idx].hfilter[RESTORATION_WIN - 1 - i] =
rsi->wiener_info[tile_idx].hfilter[i];
rsi->wiener_info[tile_idx].vfilter[RESTORATION_HALFWIN] -=
2 * rsi->wiener_info[tile_idx].vfilter[i];
rsi->wiener_info[tile_idx].hfilter[RESTORATION_HALFWIN] -=
2 * rsi->wiener_info[tile_idx].hfilter[i];
}
}
}
} else if (rsi->frame_restoration_type == RESTORE_SWITCHABLE) {
......@@ -678,6 +714,127 @@ static void loop_sgrproj_filter(uint8_t *data, int width, int height,
aom_free(tmpbuf);
}
static void apply_domaintxfmrf_hor(int iter, int param, uint8_t *img, int width,
int height, int img_stride, int32_t *dat,
int dat_stride) {
int i, j;
for (i = 0; i < height; ++i) {
uint8_t *ip = &img[i * img_stride];
int32_t *dp = &dat[i * dat_stride];
*dp *= DOMAINTXFMRF_VTABLE_PREC;
dp++;
ip++;
// left to right
for (j = 1; j < width; ++j, dp++, ip++) {
const int v = domaintxfmrf_vtable[iter][param][abs(ip[0] - ip[-1])];
dp[0] = dp[0] * (DOMAINTXFMRF_VTABLE_PREC - v) +
((v * dp[-1] + DOMAINTXFMRF_VTABLE_PREC / 2) >>
DOMAINTXFMRF_VTABLE_PRECBITS);
}
// right to left
dp -= 2;
ip -= 2;
for (j = width - 2; j >= 0; --j, dp--, ip--) {
const int v = domaintxfmrf_vtable[iter][param][abs(ip[1] - ip[0])];
dp[0] = (dp[0] * (DOMAINTXFMRF_VTABLE_PREC - v) + v * dp[1] +
DOMAINTXFMRF_VTABLE_PREC / 2) >>
DOMAINTXFMRF_VTABLE_PRECBITS;
}
}
}
static void apply_domaintxfmrf_ver(int iter, int param, uint8_t *img, int width,
int height, int img_stride, int32_t *dat,
int dat_stride) {
int i, j;
for (j = 0; j < width; ++j) {
uint8_t *ip = &img[j];
int32_t *dp = &dat[j];
dp += dat_stride;
ip += img_stride;
// top to bottom
for (i = 1; i < height; ++i, dp += dat_stride, ip += img_stride) {
const int v =
domaintxfmrf_vtable[iter][param][abs(ip[0] - ip[-img_stride])];
dp[0] = (dp[0] * (DOMAINTXFMRF_VTABLE_PREC - v) +
(dp[-dat_stride] * v + DOMAINTXFMRF_VTABLE_PREC / 2)) >>
DOMAINTXFMRF_VTABLE_PRECBITS;
}
// bottom to top
dp -= 2 * dat_stride;
ip -= 2 * img_stride;
for (i = height - 2; i >= 0; --i, dp -= dat_stride, ip -= img_stride) {
const int v =
domaintxfmrf_vtable[iter][param][abs(ip[img_stride] - ip[0])];
dp[0] = (dp[0] * (DOMAINTXFMRF_VTABLE_PREC - v) + dp[dat_stride] * v +
DOMAINTXFMRF_VTABLE_PREC / 2) >>
DOMAINTXFMRF_VTABLE_PRECBITS;
}
}
}
static void apply_domaintxfmrf_reduce_prec(int32_t *dat, int width, int height,
int dat_stride) {
int i, j;
for (i = 0; i < height; ++i) {
for (j = 0; j < width; ++j) {
dat[i * dat_stride + j] = ROUND_POWER_OF_TWO_SIGNED(
dat[i * dat_stride + j], DOMAINTXFMRF_VTABLE_PRECBITS);
}
}
}
void av1_domaintxfmrf_restoration(uint8_t *dgd, int width, int height,
int stride, int param) {
int32_t dat[RESTORATION_TILEPELS_MAX];
int i, j, t;
for (i = 0; i < height; ++i) {
for (j = 0; j < width; ++j) {
dat[i * width + j] = dgd[i * stride + j];
}
}
for (t = 0; t < DOMAINTXFMRF_ITERS; ++t) {
apply_domaintxfmrf_hor(t, param, dgd, width, height, stride, dat, width);
apply_domaintxfmrf_ver(t, param, dgd, width, height, stride, dat, width);
apply_domaintxfmrf_reduce_prec(dat, width, height, width);
}
for (i = 0; i < height; ++i) {
for (j = 0; j < width; ++j) {
dgd[i * stride + j] = clip_pixel(dat[i * width + j]);
}
}
}
static void loop_domaintxfmrf_filter_tile(uint8_t *data, int tile_idx,
int width, int height, int stride,
RestorationInternal *rst,
void *tmpbuf) {
const int tile_width = rst->tile_width >> rst->subsampling_x;
const int tile_height = rst->tile_height >> rst->subsampling_y;
int h_start, h_end, v_start, v_end;
(void)tmpbuf;
if (rst->rsi->domaintxfmrf_info[tile_idx].level == 0) return;
av1_get_rest_tile_limits(tile_idx, 0, 0, rst->nhtiles, rst->nvtiles,
tile_width, tile_height, width, height, 0, 0,
&h_start, &h_end, &v_start, &v_end);
av1_domaintxfmrf_restoration(data + h_start + v_start * stride,
h_end - h_start, v_end - v_start, stride,
rst->rsi->domaintxfmrf_info[tile_idx].sigma_r);
}
static void loop_domaintxfmrf_filter(uint8_t *data, int width, int height,
int stride, RestorationInternal *rst,
uint8_t *tmpdata, int tmpstride) {
int tile_idx;
(void)tmpdata;
(void)tmpstride;
for (tile_idx = 0; tile_idx < rst->ntiles; ++tile_idx) {
loop_domaintxfmrf_filter_tile(data, tile_idx, width, height, stride, rst,
NULL);
}
}
static void loop_switchable_filter(uint8_t *data, int width, int height,
int stride, RestorationInternal *rst,
uint8_t *tmpdata, int tmpstride) {
......@@ -703,6 +860,9 @@ static void loop_switchable_filter(uint8_t *data, int width, int height,
} else if (rst->rsi->restoration_type[tile_idx] == RESTORE_SGRPROJ) {
loop_sgrproj_filter_tile(data, tile_idx, width, height, stride, rst,
tmpbuf);
} else if (rst->rsi->restoration_type[tile_idx] == RESTORE_DOMAINTXFMRF) {
loop_domaintxfmrf_filter_tile(data, tile_idx, width, height, stride, rst,
tmpbuf);
}
}
aom_free(tmpbuf);
......@@ -918,6 +1078,130 @@ static void loop_sgrproj_filter_highbd(uint8_t *data8, int width, int height,
aom_free(tmpbuf);
}
static void apply_domaintxfmrf_hor_highbd(int iter, int param, uint16_t *img,
int width, int height, int img_stride,
int32_t *dat, int dat_stride,
int bd) {
const int shift = (bd - 8);
int i, j;
for (i = 0; i < height; ++i) {
uint16_t *ip = &img[i * img_stride];
int32_t *dp = &dat[i * dat_stride];
*dp *= DOMAINTXFMRF_VTABLE_PREC;
dp++;
ip++;
// left to right
for (j = 1; j < width; ++j, dp++, ip++) {
const int v =
domaintxfmrf_vtable[iter][param]
[abs((ip[0] >> shift) - (ip[-1] >> shift))];
dp[0] = dp[0] * (DOMAINTXFMRF_VTABLE_PREC - v) +
((v * dp[-1] + DOMAINTXFMRF_VTABLE_PREC / 2) >>
DOMAINTXFMRF_VTABLE_PRECBITS);
}
// right to left
dp -= 2;
ip -= 2;
for (j = width - 2; j >= 0; --j, dp--, ip--) {
const int v =
domaintxfmrf_vtable[iter][param]
[abs((ip[1] >> shift) - (ip[0] >> shift))];
dp[0] = (dp[0] * (DOMAINTXFMRF_VTABLE_PREC - v) + v * dp[1] +
DOMAINTXFMRF_VTABLE_PREC / 2) >>
DOMAINTXFMRF_VTABLE_PRECBITS;
}
}
}
static void apply_domaintxfmrf_ver_highbd(int iter, int param, uint16_t *img,
int width, int height, int img_stride,
int32_t *dat, int dat_stride,
int bd) {
int i, j;
const int shift = (bd - 8);
for (j = 0; j < width; ++j) {
uint16_t *ip = &img[j];
int32_t *dp = &dat[j];
dp += dat_stride;
ip += img_stride;
// top to bottom
for (i = 1; i < height; ++i, dp += dat_stride, ip += img_stride) {
const int v = domaintxfmrf_vtable[iter][param][abs(
(ip[0] >> shift) - (ip[-img_stride] >> shift))];
dp[0] = (dp[0] * (DOMAINTXFMRF_VTABLE_PREC - v) +
(dp[-dat_stride] * v + DOMAINTXFMRF_VTABLE_PREC / 2)) >>
DOMAINTXFMRF_VTABLE_PRECBITS;
}
// bottom to top
dp -= 2 * dat_stride;
ip -= 2 * img_stride;
for (i = height - 2; i >= 0; --i, dp -= dat_stride, ip -= img_stride) {
const int v = domaintxfmrf_vtable[iter][param][abs(
(ip[img_stride] >> shift) - (ip[0] >> shift))];
dp[0] = (dp[0] * (DOMAINTXFMRF_VTABLE_PREC - v) + dp[dat_stride] * v +
DOMAINTXFMRF_VTABLE_PREC / 2) >>
DOMAINTXFMRF_VTABLE_PRECBITS;
}
}
}
void av1_domaintxfmrf_restoration_highbd(uint16_t *dgd, int width, int height,
int stride, int param, int bit_depth) {
int32_t dat[RESTORATION_TILEPELS_MAX];
int i, j, t;
for (i = 0; i < height; ++i) {
for (j = 0; j < width; ++j) {
dat[i * width + j] = dgd[i * stride + j];
}
}
for (t = 0; t < DOMAINTXFMRF_ITERS; ++t) {
apply_domaintxfmrf_hor_highbd(t, param, dgd, width, height, stride, dat,
width, bit_depth);
apply_domaintxfmrf_ver_highbd(t, param, dgd, width, height, stride, dat,
width, bit_depth);
apply_domaintxfmrf_reduce_prec(dat, width, height, width);
}
for (i = 0; i < height; ++i) {
for (j = 0; j < width; ++j) {
dgd[i * stride + j] = clip_pixel_highbd(dat[i * width + j], bit_depth);
}
}
}
static void loop_domaintxfmrf_filter_tile_highbd(uint16_t *data, int tile_idx,
int width, int height,
int stride,
RestorationInternal *rst,
int bit_depth, void *tmpbuf) {
const int tile_width = rst->tile_width >> rst->subsampling_x;
const int tile_height = rst->tile_height >> rst->subsampling_y;
int h_start, h_end, v_start, v_end;
(void)tmpbuf;
if (rst->rsi->domaintxfmrf_info[tile_idx].level == 0) return;
av1_get_rest_tile_limits(tile_idx, 0, 0, rst->nhtiles, rst->nvtiles,
tile_width, tile_height, width, height, 0, 0,
&h_start, &h_end, &v_start, &v_end);
av1_domaintxfmrf_restoration_highbd(
data + h_start + v_start * stride, h_end - h_start, v_end - v_start,
stride, rst->rsi->domaintxfmrf_info[tile_idx].sigma_r, bit_depth);
}
static void loop_domaintxfmrf_filter_highbd(uint8_t *data8, int width,
int height, int stride,
RestorationInternal *rst,
uint8_t *tmpdata, int tmpstride,
int bit_depth) {
int tile_idx;
uint16_t *data = CONVERT_TO_SHORTPTR(data8);
(void)tmpdata;
(void)tmpstride;
for (tile_idx = 0; tile_idx < rst->ntiles; ++tile_idx) {
loop_domaintxfmrf_filter_tile_highbd(data, tile_idx, width, height, stride,
rst, bit_depth, NULL);
}
}
static void loop_switchable_filter_highbd(uint8_t *data8, int width, int height,
int stride, RestorationInternal *rst,
uint8_t *tmpdata8, int tmpstride,
......@@ -946,6 +1230,9 @@ static void loop_switchable_filter_highbd(uint8_t *data8, int width, int height,
} else if (rst->rsi->restoration_type[tile_idx] == RESTORE_SGRPROJ) {
loop_sgrproj_filter_tile_highbd(data, tile_idx, width, height, stride,
rst, bit_depth, tmpbuf);
} else if (rst->rsi->restoration_type[tile_idx] == RESTORE_DOMAINTXFMRF) {
loop_domaintxfmrf_filter_tile_highbd(data, tile_idx, width, height,
stride, rst, bit_depth, tmpbuf);
}
}
aom_free(tmpbuf);
......@@ -962,14 +1249,20 @@ void av1_loop_restoration_rows(YV12_BUFFER_CONFIG *frame, AV1_COMMON *cm,
const int uvstart = ystart >> cm->subsampling_y;
int yend = end_mi_row << MI_SIZE_LOG2;
int uvend = yend >> cm->subsampling_y;
restore_func_type restore_funcs[RESTORE_TYPES] = { NULL, loop_sgrproj_filter,
restore_func_type restore_funcs[RESTORE_TYPES] = { NULL,
loop_sgrproj_filter,
loop_bilateral_filter,
loop_wiener_filter,
loop_domaintxfmrf_filter,
loop_switchable_filter };
#if CONFIG_AOM_HIGHBITDEPTH
restore_func_highbd_type restore_funcs_highbd[RESTORE_TYPES] = {
NULL, loop_sgrproj_filter_highbd, loop_bilateral_filter_highbd,
loop_wiener_filter_highbd, loop_switchable_filter_highbd
NULL,
loop_sgrproj_filter_highbd,
loop_bilateral_filter_highbd,
loop_wiener_filter_highbd,
loop_domaintxfmrf_filter_highbd,
loop_switchable_filter_highbd
};
#endif // CONFIG_AOM_HIGHBITDEPTH
restore_func_type restore_func =
......
......@@ -21,12 +21,27 @@
extern "C" {
#endif
#define CLIP(x, lo, hi) ((x) < (lo) ? (lo) : (x) > (hi) ? (hi) : (x))
#define RINT(x) ((x) < 0 ? (int)((x)-0.5) : (int)((x) + 0.5))
#define RESTORATION_TILESIZE_SML 128
#define RESTORATION_TILESIZE_BIG 256
#define RESTORATION_TILEPELS_MAX \
(RESTORATION_TILESIZE_BIG * RESTORATION_TILESIZE_BIG * 9 / 4)
#define SGRPROJ_TMPBUF_SIZE (RESTORATION_TILEPELS_MAX * 6 * 8)
#define DOMAINTXFMRF_PARAMS_BITS 6
#define DOMAINTXFMRF_PARAMS (1 << DOMAINTXFMRF_PARAMS_BITS)
#define DOMAINTXFMRF_SIGMA_SCALEBITS 4
#define DOMAINTXFMRF_SIGMA_SCALE (1 << DOMAINTXFMRF_SIGMA_SCALEBITS)
#define DOMAINTXFMRF_ITERS 3
#define DOMAINTXFMRF_VTABLE_PRECBITS 8
#define DOMAINTXFMRF_VTABLE_PREC (1 << DOMAINTXFMRF_VTABLE_PRECBITS)
#define DOMAINTXFMRF_MULT \
sqrt(((1 << (DOMAINTXFMRF_ITERS * 2)) - 1) * 2.0 / 3.0)
#define DOMAINTXFMRF_TMPBUF_SIZE (RESTORATION_TILEPELS_MAX)
#define DOMAINTXFMRF_BITS (DOMAINTXFMRF_PARAMS_BITS)
#define SGRPROJ_TMPBUF_SIZE (RESTORATION_TILEPELS_MAX * 6 * 8)
#define SGRPROJ_PARAMS_BITS 3
#define SGRPROJ_PARAMS (1 << SGRPROJ_PARAMS_BITS)
......@@ -99,6 +114,11 @@ typedef struct {
int xqd[2];
} SgrprojInfo;
typedef struct {
int level;
int sigma_r;
} DomaintxfmrfInfo;
typedef struct {
RestorationType frame_restoration_type;
RestorationType *restoration_type;
......@@ -108,6 +128,8 @@ typedef struct {
WienerInfo *wiener_info;
// Selfguided proj filter
SgrprojInfo *sgrproj_info;
// Domain transform filter
DomaintxfmrfInfo *domaintxfmrf_info;
} RestorationInfo;
typedef struct {
......@@ -181,6 +203,12 @@ extern const sgr_params_type sgr_params[SGRPROJ_PARAMS];
void av1_selfguided_restoration(int64_t *dgd, int width, int height, int stride,
int bit_depth, int r, int eps, void *tmpbuf);
void av1_domaintxfmrf_restoration(uint8_t *dgd, int width, int height,
int stride, int param);
#if CONFIG_AOM_HIGHBITDEPTH
void av1_domaintxfmrf_restoration_highbd(uint16_t *dgd, int width, int height,
int stride, int param, int bit_depth);
#endif // CONFIG_AOM_HIGHBITDEPTH
void decode_xq(int *xqd, int *xq);
int av1_bilateral_level_bits(const struct AV1Common *const cm);
void av1_loop_restoration_init(RestorationInternal *rst, RestorationInfo *rsi,
......
......@@ -2317,7 +2317,9 @@ static void decode_restoration_mode(AV1_COMMON *cm,
rsi->frame_restoration_type =
(aom_rb_read_bit(rb) ? RESTORE_WIENER : RESTORE_BILATERAL);
else
rsi->frame_restoration_type = RESTORE_SGRPROJ;
rsi->frame_restoration_type =
(aom_rb_read_bit(rb) ? RESTORE_DOMAINTXFMRF : RESTORE_SGRPROJ);
// rsi->frame_restoration_type = RESTORE_SGRPROJ;
} else {
rsi->frame_restoration_type =
aom_rb_read_bit(rb) ? RESTORE_SWITCHABLE : RESTORE_NONE;
......@@ -2353,6 +2355,12 @@ static void read_sgrproj_filter(SgrprojInfo *sgrproj_info, aom_reader *rb) {
aom_read_literal(rb, SGRPROJ_PRJ_BITS, ACCT_STR) + SGRPROJ_PRJ_MIN1;
}
static void read_domaintxfmrf_filter(DomaintxfmrfInfo *domaintxfmrf_info,
aom_reader *rb) {
domaintxfmrf_info->sigma_r =
aom_read_literal(rb, DOMAINTXFMRF_PARAMS_BITS, ACCT_STR);
}
static void read_bilateral_filter(const AV1_COMMON *cm,
BilateralInfo *bilateral_info,
aom_reader *rb) {
......@@ -2385,6 +2393,9 @@ static void decode_restoration(AV1_COMMON *cm, aom_reader *rb) {
rsi->sgrproj_info = (SgrprojInfo *)aom_realloc(
rsi->sgrproj_info, sizeof(*rsi->sgrproj_info) * ntiles);
assert(rsi->sgrproj_info != NULL);
rsi->domaintxfmrf_info = (DomaintxfmrfInfo *)aom_realloc(
rsi->domaintxfmrf_info, sizeof(*rsi->domaintxfmrf_info) * ntiles);
assert(rsi->domaintxfmrf_info != NULL);
for (i = 0; i < ntiles; ++i) {
rsi->restoration_type[i] =
aom_read_tree(rb, av1_switchable_restore_tree,
......@@ -2402,6 +2413,9 @@ static void decode_restoration(AV1_COMMON *cm, aom_reader *rb) {
} else if (rsi->restoration_type[i] == RESTORE_SGRPROJ) {
rsi->sgrproj_info[i].level = 1;
read_sgrproj_filter(&rsi->sgrproj_info[i], rb);
} else if (rsi->restoration_type[i] == RESTORE_DOMAINTXFMRF) {
rsi->domaintxfmrf_info[i].level = 1;
read_domaintxfmrf_filter(&rsi->domaintxfmrf_info[i], rb);
}
}
} else if (rsi->frame_restoration_type == RESTORE_WIENER) {
......@@ -2440,6 +2454,20 @@ static void decode_restoration(AV1_COMMON *cm, aom_reader *rb) {
rsi->restoration_type[i] = RESTORE_NONE;
}
}
} else if (rsi->frame_restoration_type == RESTORE_DOMAINTXFMRF) {
rsi->domaintxfmrf_info = (DomaintxfmrfInfo *)aom_realloc(
rsi->domaintxfmrf_info, sizeof(*rsi->domaintxfmrf_info) * ntiles);
assert(rsi->domaintxfmrf_info != NULL);
for (i = 0; i < ntiles; ++i) {
if (aom_read(rb, RESTORE_NONE_DOMAINTXFMRF_PROB, ACCT_STR)) {
rsi->restoration_type[i] = RESTORE_DOMAINTXFMRF;
rsi->domaintxfmrf_info[i].level = 1;
read_domaintxfmrf_filter(&rsi->domaintxfmrf_info[i], rb);
} else {
rsi->domaintxfmrf_info[i].level = 0;
rsi->restoration_type[i] = RESTORE_NONE;
}
}
}
}
}
......
......@@ -2986,9 +2986,21 @@ static void encode_restoration_mode(AV1_COMMON *cm,
aom_wb_write_bit(wb, 0);
aom_wb_write_bit(wb, 1);
break;
/*
case RESTORE_SGRPROJ:
aom_wb_write_bit(wb, 1);
aom_wb_write_bit(wb, 0);
break;
*/
case RESTORE_SGRPROJ:
aom_wb_write_bit(wb, 1);
aom_wb_write_bit(wb, 0);
aom_wb_write_bit(wb, 0);
break;
case RESTORE_DOMAINTXFMRF:
aom_wb_write_bit(wb, 1);
aom_wb_write_bit(wb, 0);
aom_wb_write_bit(wb, 1);
break;
case RESTORE_BILATERAL:
aom_wb_write_bit(wb, 1);
......@@ -3027,6 +3039,11 @@ static void write_sgrproj_filter(SgrprojInfo *sgrproj_info, aom_writer *wb) {
SGRPROJ_PRJ_BITS);
}
static void write_domaintxfmrf_filter(DomaintxfmrfInfo *domaintxfmrf_info,
aom_writer *wb) {
aom_write_literal(wb, domaintxfmrf_info->sigma_r, DOMAINTXFMRF_PARAMS_BITS);
}
static void write_bilateral_filter(const AV1_COMMON *cm,
BilateralInfo *bilateral_info,
aom_writer *wb) {
......@@ -3061,6 +3078,8 @@ static void encode_restoration(AV1_COMMON *cm, aom_writer *wb) {
write_wiener_filter(&rsi->wiener_info[i], wb);
} else if (rsi->restoration_type[i] == RESTORE_SGRPROJ) {
write_sgrproj_filter(&rsi->sgrproj_info[i], wb);
} else if (rsi->restoration_type[i] == RESTORE_DOMAINTXFMRF) {
write_domaintxfmrf_filter(&rsi->domaintxfmrf_info[i], wb);
}
}
} else if (rsi->frame_restoration_type == RESTORE_BILATERAL) {
......@@ -3082,6 +3101,14 @@ static void encode_restoration(AV1_COMMON *cm, aom_writer *wb) {
write_sgrproj_filter(&rsi->sgrproj_info[i], wb);
}
}
} else if (rsi->frame_restoration_type == RESTORE_DOMAINTXFMRF) {
for (i = 0; i < cm->rst_internal.ntiles; ++i) {
aom_write(wb, rsi->domaintxfmrf_info[i].level != 0,
RESTORE_NONE_DOMAINTXFMRF_PROB);
if (rsi->domaintxfmrf_info[i].level) {