restoration.h 9.95 KB
Newer Older
1
/*
2
 * Copyright (c) 2016, Alliance for Open Media. All rights reserved
3
 *
4
5
6
7
8
9
 * This source code is subject to the terms of the BSD 2 Clause License and
 * the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
 * was not distributed with this source code in the LICENSE file, you can
 * obtain it at www.aomedia.org/license/software. If the Alliance for Open
 * Media Patent License 1.0 was not distributed with this source code in the
 * PATENTS file, you can obtain it at www.aomedia.org/license/patent.
10
11
 */

Yaowu Xu's avatar
Yaowu Xu committed
12
13
#ifndef AV1_COMMON_RESTORATION_H_
#define AV1_COMMON_RESTORATION_H_
14

15
#include "aom_ports/mem.h"
Yaowu Xu's avatar
Yaowu Xu committed
16
#include "./aom_config.h"
17

18
#include "av1/common/blockd.h"
19
20
21
22
23

#ifdef __cplusplus
extern "C" {
#endif

24
25
26
#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))

27
28
29
30
31
#define RESTORATION_TILESIZE_SML 128
#define RESTORATION_TILESIZE_BIG 256
#define RESTORATION_TILEPELS_MAX \
  (RESTORATION_TILESIZE_BIG * RESTORATION_TILESIZE_BIG * 9 / 4)

32
#if USE_DOMAINTXFMRF
33
34
35
36
37
38
39
40
41
#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)
42
43
44
// 1 32-bit and 2 8-bit buffers needed for the filter
#define DOMAINTXFMRF_TMPBUF_SIZE \
  (RESTORATION_TILEPELS_MAX * (sizeof(int32_t) + 2 * sizeof(uint8_t)))
45
46
47
48
49
50
51
// One extra buffer needed in encoder, which is either 8-bit or 16-bit
// depending on the video bit depth.
#if CONFIG_AOM_HIGHBITDEPTH
#define DOMAINTXFMRF_EXTBUF_SIZE (RESTORATION_TILEPELS_MAX * sizeof(uint16_t))
#else
#define DOMAINTXFMRF_EXTBUF_SIZE (RESTORATION_TILEPELS_MAX * sizeof(uint8_t))
#endif
52
#define DOMAINTXFMRF_BITS (DOMAINTXFMRF_PARAMS_BITS)
53
#endif  // USE_DOMAINTXFMRF
54

55
// 4 32-bit buffers needed for the filter:
56
// 2 for the restored versions of the frame and
57
// 2 for each restoration operation
David Barker's avatar
David Barker committed
58
59
60
61
62
#define SGRPROJ_OUTBUF_SIZE \
  ((RESTORATION_TILESIZE_BIG * 3 / 2) * (RESTORATION_TILESIZE_BIG * 3 / 2 + 16))
#define SGRPROJ_TMPBUF_SIZE                         \
  (RESTORATION_TILEPELS_MAX * 2 * sizeof(int32_t) + \
   SGRPROJ_OUTBUF_SIZE * 2 * sizeof(int32_t))
63
#define SGRPROJ_EXTBUF_SIZE (0)
64
#define SGRPROJ_PARAMS_BITS 4
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
#define SGRPROJ_PARAMS (1 << SGRPROJ_PARAMS_BITS)

// Precision bits for projection
#define SGRPROJ_PRJ_BITS 7
// Restoration precision bits generated higher than source before projection
#define SGRPROJ_RST_BITS 4
// Internal precision bits for core selfguided_restoration
#define SGRPROJ_SGR_BITS 8
#define SGRPROJ_SGR (1 << SGRPROJ_SGR_BITS)

#define SGRPROJ_PRJ_MIN0 (-(1 << SGRPROJ_PRJ_BITS) / 4)
#define SGRPROJ_PRJ_MAX0 (SGRPROJ_PRJ_MIN0 + (1 << SGRPROJ_PRJ_BITS) - 1)
#define SGRPROJ_PRJ_MIN1 (-(1 << SGRPROJ_PRJ_BITS) / 4)
#define SGRPROJ_PRJ_MAX1 (SGRPROJ_PRJ_MIN1 + (1 << SGRPROJ_PRJ_BITS) - 1)

#define SGRPROJ_BITS (SGRPROJ_PRJ_BITS * 2 + SGRPROJ_PARAMS_BITS)

David Barker's avatar
David Barker committed
82
83
84
85
86
87
#define MAX_RADIUS 3  // Only 1, 2, 3 allowed
#define MAX_EPS 80    // Max value of eps
#define MAX_NELEM ((2 * MAX_RADIUS + 1) * (2 * MAX_RADIUS + 1))
#define SGRPROJ_MTABLE_BITS 20
#define SGRPROJ_RECIP_BITS 12

88
89
90
91
92
#define WIENER_HALFWIN 3
#define WIENER_HALFWIN1 (WIENER_HALFWIN + 1)
#define WIENER_WIN (2 * WIENER_HALFWIN + 1)
#define WIENER_WIN2 ((WIENER_WIN) * (WIENER_WIN))
#define WIENER_TMPBUF_SIZE (0)
93
#define WIENER_EXTBUF_SIZE (0)
94

95
96
#define WIENER_FILT_PREC_BITS 7
#define WIENER_FILT_STEP (1 << WIENER_FILT_PREC_BITS)
97

98
99
100
// Central values for the taps
#define WIENER_FILT_TAP0_MIDV (3)
#define WIENER_FILT_TAP1_MIDV (-7)
101
#define WIENER_FILT_TAP2_MIDV (15)
102

clang-format's avatar
clang-format committed
103
104
105
#define WIENER_FILT_TAP0_BITS 4
#define WIENER_FILT_TAP1_BITS 5
#define WIENER_FILT_TAP2_BITS 6
106

107
108
109
#define WIENER_FILT_BITS \
  ((WIENER_FILT_TAP0_BITS + WIENER_FILT_TAP1_BITS + WIENER_FILT_TAP2_BITS) * 2)

110
111
112
113
114
115
116
#define WIENER_FILT_TAP0_MINV \
  (WIENER_FILT_TAP0_MIDV - (1 << WIENER_FILT_TAP0_BITS) / 2)
#define WIENER_FILT_TAP1_MINV \
  (WIENER_FILT_TAP1_MIDV - (1 << WIENER_FILT_TAP1_BITS) / 2)
#define WIENER_FILT_TAP2_MINV \
  (WIENER_FILT_TAP2_MIDV - (1 << WIENER_FILT_TAP2_BITS) / 2)

117
#define WIENER_FILT_TAP0_MAXV \
118
  (WIENER_FILT_TAP0_MIDV - 1 + (1 << WIENER_FILT_TAP0_BITS) / 2)
119
#define WIENER_FILT_TAP1_MAXV \
120
  (WIENER_FILT_TAP1_MIDV - 1 + (1 << WIENER_FILT_TAP1_BITS) / 2)
121
#define WIENER_FILT_TAP2_MAXV \
122
123
124
125
  (WIENER_FILT_TAP2_MIDV - 1 + (1 << WIENER_FILT_TAP2_BITS) / 2)

// Max of SGRPROJ_TMPBUF_SIZE, DOMAINTXFMRF_TMPBUF_SIZE, WIENER_TMPBUF_SIZE
#define RESTORATION_TMPBUF_SIZE (SGRPROJ_TMPBUF_SIZE)
126
127

#if USE_DOMAINTXFMRF
128
129
// Max of SGRPROJ_EXTBUF_SIZE, DOMAINTXFMRF_EXTBUF_SIZE, WIENER_EXTBUF_SIZE
#define RESTORATION_EXTBUF_SIZE (DOMAINTXFMRF_EXTBUF_SIZE)
130
131
132
#else
#define RESTORATION_EXTBUF_SIZE (WIENER_EXTBUF_SIZE)
#endif  // USE_DOMAINTXFMRF
133

134
135
136
137
138
139
140
141
142
143
144
// Check the assumptions of the existing code
#if SUBPEL_TAPS != WIENER_WIN + 1
#error "Wiener filter currently only works if SUBPEL_TAPS == WIENER_WIN + 1"
#endif
#if WIENER_FILT_PREC_BITS != 7
#error "Wiener filter currently only works if WIENER_FILT_PREC_BITS == 7"
#endif
typedef struct {
  DECLARE_ALIGNED(16, InterpKernel, vfilter);
  DECLARE_ALIGNED(16, InterpKernel, hfilter);
} WienerInfo;
145

146
147
148
149
150
151
152
153
154
155
156
157
typedef struct {
  int r1;
  int e1;
  int r2;
  int e2;
} sgr_params_type;

typedef struct {
  int ep;
  int xqd[2];
} SgrprojInfo;

158
#if USE_DOMAINTXFMRF
159
typedef struct { int sigma_r; } DomaintxfmrfInfo;
160
#endif  // USE_DOMAINTXFMRF
161

162
typedef struct {
163
164
  RestorationType frame_restoration_type;
  RestorationType *restoration_type;
165
  // Wiener filter
166
  WienerInfo *wiener_info;
167
168
  // Selfguided proj filter
  SgrprojInfo *sgrproj_info;
169
#if USE_DOMAINTXFMRF
170
171
  // Domain transform filter
  DomaintxfmrfInfo *domaintxfmrf_info;
172
#endif  // USE_DOMAINTXFMRF
173
} RestorationInfo;
174

175
typedef struct {
176
177
  RestorationInfo *rsi;
  int keyframe;
178
179
180
  int ntiles;
  int tile_width, tile_height;
  int nhtiles, nvtiles;
181
  int32_t *tmpbuf;
182
} RestorationInternal;
183

184
185
186
187
188
189
190
static INLINE int get_rest_tilesize(int width, int height) {
  if (width * height <= 352 * 288)
    return RESTORATION_TILESIZE_SML;
  else
    return RESTORATION_TILESIZE_BIG;
}

191
192
193
static INLINE int av1_get_rest_ntiles(int width, int height, int *tile_width,
                                      int *tile_height, int *nhtiles,
                                      int *nvtiles) {
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
  int nhtiles_, nvtiles_;
  int tile_width_, tile_height_;
  int tilesize = get_rest_tilesize(width, height);
  tile_width_ = (tilesize < 0) ? width : AOMMIN(tilesize, width);
  tile_height_ = (tilesize < 0) ? height : AOMMIN(tilesize, height);
  nhtiles_ = (width + (tile_width_ >> 1)) / tile_width_;
  nvtiles_ = (height + (tile_height_ >> 1)) / tile_height_;
  if (tile_width) *tile_width = tile_width_;
  if (tile_height) *tile_height = tile_height_;
  if (nhtiles) *nhtiles = nhtiles_;
  if (nvtiles) *nvtiles = nvtiles_;
  return (nhtiles_ * nvtiles_);
}

static INLINE void av1_get_rest_tile_limits(
    int tile_idx, int subtile_idx, int subtile_bits, int nhtiles, int nvtiles,
    int tile_width, int tile_height, int im_width, int im_height, int clamp_h,
    int clamp_v, int *h_start, int *h_end, int *v_start, int *v_end) {
  const int htile_idx = tile_idx % nhtiles;
  const int vtile_idx = tile_idx / nhtiles;
  *h_start = htile_idx * tile_width;
  *v_start = vtile_idx * tile_height;
  *h_end = (htile_idx < nhtiles - 1) ? *h_start + tile_width : im_width;
  *v_end = (vtile_idx < nvtiles - 1) ? *v_start + tile_height : im_height;
  if (subtile_bits) {
    const int num_subtiles_1d = (1 << subtile_bits);
    const int subtile_width = (*h_end - *h_start) >> subtile_bits;
    const int subtile_height = (*v_end - *v_start) >> subtile_bits;
    const int subtile_idx_h = subtile_idx & (num_subtiles_1d - 1);
    const int subtile_idx_v = subtile_idx >> subtile_bits;
    *h_start += subtile_idx_h * subtile_width;
    *v_start += subtile_idx_v * subtile_height;
    *h_end = subtile_idx_h == num_subtiles_1d - 1 ? *h_end
                                                  : *h_start + subtile_width;
    *v_end = subtile_idx_v == num_subtiles_1d - 1 ? *v_end
                                                  : *v_start + subtile_height;
  }
  if (clamp_h) {
232
233
    *h_start = AOMMAX(*h_start, clamp_h);
    *h_end = AOMMIN(*h_end, im_width - clamp_h);
234
235
  }
  if (clamp_v) {
236
237
    *v_start = AOMMAX(*v_start, clamp_v);
    *v_end = AOMMIN(*v_end, im_height - clamp_v);
238
239
240
  }
}

241
extern const sgr_params_type sgr_params[SGRPROJ_PARAMS];
David Barker's avatar
David Barker committed
242
243
244
extern int sgrproj_mtable[MAX_EPS][MAX_NELEM];
extern const int32_t x_by_xplus1[256];
extern const int32_t one_by_x[MAX_NELEM];
245

246
247
int av1_alloc_restoration_struct(struct AV1Common *cm,
                                 RestorationInfo *rst_info, int width,
248
249
250
                                 int height);
void av1_free_restoration_struct(RestorationInfo *rst_info);

251
void extend_frame(uint8_t *data, int width, int height, int stride);
252
#if USE_DOMAINTXFMRF
253
void av1_domaintxfmrf_restoration(uint8_t *dgd, int width, int height,
254
                                  int stride, int param, uint8_t *dst,
255
                                  int dst_stride, int32_t *tmpbuf);
256
#endif  // USE_DOMAINTXFMRF
257
#if CONFIG_AOM_HIGHBITDEPTH
258
void extend_frame_highbd(uint16_t *data, int width, int height, int stride);
259
#if USE_DOMAINTXFMRF
260
void av1_domaintxfmrf_restoration_highbd(uint16_t *dgd, int width, int height,
261
                                         int stride, int param, int bit_depth,
262
263
                                         uint16_t *dst, int dst_stride,
                                         int32_t *tmpbuf);
264
#endif  // USE_DOMAINTXFMRF
265
#endif  // CONFIG_AOM_HIGHBITDEPTH
266
void decode_xq(int *xqd, int *xq);
Yaowu Xu's avatar
Yaowu Xu committed
267
void av1_loop_restoration_frame(YV12_BUFFER_CONFIG *frame, struct AV1Common *cm,
268
                                RestorationInfo *rsi, int components_pattern,
269
                                int partial_frame, YV12_BUFFER_CONFIG *dst);
Yaowu Xu's avatar
Yaowu Xu committed
270
void av1_loop_restoration_precal();
271
272
273
274
#ifdef __cplusplus
}  // extern "C"
#endif

Yaowu Xu's avatar
Yaowu Xu committed
275
#endif  // AV1_COMMON_RESTORATION_H_