Coverage Report

Created: 2026-09-14 06:49

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/avm/av2/common/gdf.c
Line
Count
Source
1
/*
2
 * Copyright (c) 2025, Alliance for Open Media. All rights reserved
3
 *
4
 * This source code is subject to the terms of the BSD 3-Clause Clear License
5
 * and the Alliance for Open Media Patent License 1.0. If the BSD 3-Clause Clear
6
 * License was not distributed with this source code in the LICENSE file, you
7
 * can obtain it at aomedia.org/license/software-license/bsd-3-c-c/.  If the
8
 * Alliance for Open Media Patent License 1.0 was not distributed with this
9
 * source code in the PATENTS file, you can obtain it at
10
 * aomedia.org/license/patent-license/.
11
 */
12
#ifndef AVM_COMMON_GDF_H_
13
#define AVM_COMMON_GDF_H_
14
15
#include "av2/common/gdf.h"
16
#include "av2/common/gdf_block.h"
17
18
14.3k
static int gdf_num_stripes_in_tile(int stripe_size, int tile_size) {
19
14.3k
  const int first_stripe_offset = GDF_TEST_STRIPE_OFF;
20
14.3k
  return (tile_size + first_stripe_offset + stripe_size - 1) / stripe_size;
21
14.3k
}
22
23
0
void init_gdf_test(GdfInfo *gi, int mib_size, int rec_height, int rec_width) {
24
0
  gi->gdf_mode = 0;
25
0
  gi->gdf_pic_qp_idx = 0;
26
0
  gi->gdf_pic_scale_idx = 0;
27
0
  gi->gdf_block_size = AVMMAX(mib_size << MI_SIZE_LOG2, GDF_TEST_BLK_SIZE);
28
0
  gi->gdf_stripe_size = GDF_TEST_STRIPE_SIZE;
29
0
  gi->gdf_unit_size = GDF_TEST_STRIPE_SIZE;
30
0
  gi->gdf_vert_blks_per_tile[0] = 1 + ((rec_height - 1) / gi->gdf_block_size);
31
0
  gi->gdf_block_num_h = 1 + ((rec_height - 1) / gi->gdf_block_size);
32
0
  gi->gdf_horz_blks_per_tile[0] = 1 + ((rec_width - 1) / gi->gdf_block_size);
33
0
  gi->gdf_block_num_w = 1 + ((rec_width - 1) / gi->gdf_block_size);
34
0
  gi->gdf_block_num = gi->gdf_block_num_h * gi->gdf_block_num_w;
35
0
  gi->gdf_vert_stripes_per_tile[0] =
36
0
      gdf_num_stripes_in_tile(gi->gdf_stripe_size, rec_height);
37
0
  gi->err_height = gi->gdf_unit_size;
38
0
  gi->lap_stride = gi->gdf_unit_size + GDF_ERR_STRIDE_MARGIN;
39
0
  gi->cls_stride = (gi->gdf_unit_size >> 1) + GDF_ERR_STRIDE_MARGIN;
40
0
  gi->err_stride = gi->gdf_unit_size + GDF_ERR_STRIDE_MARGIN;
41
0
}
42
43
5.65k
void init_gdf(AV2_COMMON *cm) {
44
5.65k
  GdfInfo *gi = &cm->gdf_info;
45
5.65k
  gi->gdf_mode = 0;
46
5.65k
  gi->gdf_pic_qp_idx = 0;
47
5.65k
  gi->gdf_pic_scale_idx = 0;
48
5.65k
  gi->gdf_block_size =
49
5.65k
      cm->seq_params.gdf_unit_matches_sb_size
50
5.65k
          ? cm->mib_size << MI_SIZE_LOG2
51
5.65k
          : AVMMAX(cm->mib_size << MI_SIZE_LOG2, GDF_TEST_BLK_SIZE);
52
5.65k
  const int num_tile_rows = cm->tiles.rows;
53
5.65k
  const int num_tile_cols = cm->tiles.cols;
54
55
  // if super_block size is 64x64
56
5.65k
  if (cm->mib_size == 16 && !cm->seq_params.gdf_unit_matches_sb_size) {
57
154
    int e2 = 0;
58
348
    for (int i = 0; i < cm->tiles.cols - 1; ++i) {
59
194
      const int size =
60
194
          cm->tiles.col_start_sb[i + 1] - cm->tiles.col_start_sb[i];
61
194
      e2 += size & 1;
62
194
    }
63
685
    for (int i = 0; i < cm->tiles.rows - 1; ++i) {
64
531
      const int size =
65
531
          cm->tiles.row_start_sb[i + 1] - cm->tiles.row_start_sb[i];
66
531
      e2 += size & 1;
67
531
    }
68
154
    if (e2) gi->gdf_block_size = 64;
69
154
  }
70
71
5.65k
  gi->gdf_stripe_size = GDF_TEST_STRIPE_SIZE;
72
5.65k
  gi->gdf_unit_size = GDF_TEST_STRIPE_SIZE;
73
  // Calculate number of blocks
74
5.65k
  gi->gdf_block_num_h = 0;
75
5.65k
  gi->gdf_block_num_w = 0;
76
5.65k
  if (num_tile_rows == 1 && num_tile_cols == 1) {
77
2.48k
    AV2PixelRect tile_rect = av2_whole_frame_rect(cm, 0);
78
2.48k
    const int tile_height = tile_rect.bottom - tile_rect.top;
79
2.48k
    const int tile_width = tile_rect.right - tile_rect.left;
80
2.48k
    gi->gdf_vert_blks_per_tile[0] =
81
2.48k
        1 + ((tile_height - 1) / gi->gdf_block_size);
82
2.48k
    gi->gdf_block_num_h += gi->gdf_vert_blks_per_tile[0];
83
2.48k
    gi->gdf_horz_blks_per_tile[0] = 1 + ((tile_width - 1) / gi->gdf_block_size);
84
2.48k
    gi->gdf_block_num_w += gi->gdf_horz_blks_per_tile[0];
85
2.48k
    gi->gdf_vert_stripes_per_tile[0] =
86
2.48k
        gdf_num_stripes_in_tile(gi->gdf_stripe_size, tile_height);
87
3.16k
  } else {
88
15.0k
    for (int tile_row = 0; tile_row < num_tile_rows; ++tile_row) {
89
11.9k
      TileInfo tile_info;
90
11.9k
      av2_tile_init(&tile_info, cm, tile_row, 0);
91
11.9k
      AV2PixelRect tile_rect = av2_get_tile_rect(&tile_info, cm, 0);
92
11.9k
      const int tile_height = tile_rect.bottom - tile_rect.top;
93
11.9k
      gi->gdf_vert_blks_per_tile[tile_row] =
94
11.9k
          1 + ((tile_height - 1) / gi->gdf_block_size);
95
11.9k
      gi->gdf_block_num_h += gi->gdf_vert_blks_per_tile[tile_row];
96
11.9k
      gi->gdf_vert_stripes_per_tile[tile_row] =
97
11.9k
          gdf_num_stripes_in_tile(gi->gdf_stripe_size, tile_height);
98
11.9k
    }
99
8.16k
    for (int tile_col = 0; tile_col < num_tile_cols; ++tile_col) {
100
4.99k
      TileInfo tile_info;
101
4.99k
      av2_tile_init(&tile_info, cm, 0, tile_col);
102
4.99k
      AV2PixelRect tile_rect = av2_get_tile_rect(&tile_info, cm, 0);
103
4.99k
      const int tile_width = tile_rect.right - tile_rect.left;
104
4.99k
      gi->gdf_horz_blks_per_tile[tile_col] =
105
4.99k
          1 + ((tile_width - 1) / gi->gdf_block_size);
106
4.99k
      gi->gdf_block_num_w += gi->gdf_horz_blks_per_tile[tile_col];
107
4.99k
    }
108
3.16k
  }
109
5.65k
  gi->gdf_block_num = gi->gdf_block_num_h * gi->gdf_block_num_w;
110
5.65k
  gi->err_height = gi->gdf_unit_size;
111
5.65k
  gi->lap_stride = gi->gdf_unit_size + GDF_ERR_STRIDE_MARGIN;
112
5.65k
  gi->cls_stride = (gi->gdf_unit_size >> 1) + GDF_ERR_STRIDE_MARGIN;
113
5.65k
  gi->err_stride = gi->gdf_unit_size + GDF_ERR_STRIDE_MARGIN;
114
5.65k
}
115
116
5.63k
void alloc_gdf_buffers(GdfInfo *gi) {
117
5.63k
  free_gdf_buffers(gi);
118
5.63k
  gi->lap_ptr =
119
5.63k
      (uint16_t **)avm_malloc(GDF_NET_INP_GRD_NUM * sizeof(uint16_t *));
120
5.63k
  const int lap_buf_height = (gi->err_height >> 1) + 2;
121
5.63k
  const int cls_buf_height = (gi->err_height >> 1) + 2;
122
28.1k
  for (int i = 0; i < GDF_NET_INP_GRD_NUM; i++) {
123
22.5k
    gi->lap_ptr[i] = (uint16_t *)avm_memalign(
124
22.5k
        32, lap_buf_height * gi->lap_stride * sizeof(uint16_t));
125
22.5k
    memset(gi->lap_ptr[i], 0,
126
22.5k
           lap_buf_height * gi->lap_stride * sizeof(uint16_t));
127
22.5k
  }
128
5.63k
  gi->cls_ptr = (uint32_t *)avm_memalign(
129
5.63k
      32, cls_buf_height * gi->cls_stride * sizeof(uint32_t));
130
5.63k
  memset(gi->cls_ptr, 0, cls_buf_height * gi->cls_stride * sizeof(uint32_t));
131
5.63k
  gi->err_ptr = (int16_t *)avm_memalign(
132
5.63k
      32, gi->err_height * gi->err_stride * sizeof(int16_t));
133
5.63k
  memset(gi->err_ptr, 0, gi->err_height * gi->err_stride * sizeof(int16_t));
134
5.63k
  gi->gdf_block_flags = (int32_t *)avm_malloc(gi->gdf_block_num * sizeof(int));
135
5.63k
  memset(gi->gdf_block_flags, 0, gi->gdf_block_num * sizeof(int));
136
5.63k
  gi->glbs = (GDFLineBuffers *)avm_malloc(sizeof(GDFLineBuffers));
137
5.63k
  gi->tmp_save_left = (uint16_t *)avm_malloc(
138
5.63k
      (gi->gdf_unit_size + 2 * GDF_TEST_EXTRA_VER_BORDER) *
139
5.63k
      GDF_TEST_EXTRA_HOR_BORDER * sizeof(*gi->tmp_save_left));
140
5.63k
  gi->tmp_save_right = (uint16_t *)avm_malloc(
141
5.63k
      (gi->gdf_unit_size + 2 * GDF_TEST_EXTRA_VER_BORDER) *
142
5.63k
      GDF_TEST_EXTRA_HOR_BORDER * sizeof(*gi->tmp_save_right));
143
5.63k
}
144
145
16.5k
void free_gdf_buffers(GdfInfo *gi) {
146
16.5k
  if (gi->lap_ptr != NULL) {
147
28.1k
    for (int i = 0; i < GDF_NET_INP_GRD_NUM; i++) {
148
22.5k
      avm_free(gi->lap_ptr[i]);
149
22.5k
      gi->lap_ptr[i] = NULL;
150
22.5k
    }
151
5.63k
    avm_free(gi->lap_ptr);
152
5.63k
    gi->lap_ptr = NULL;
153
5.63k
  }
154
16.5k
  if (gi->cls_ptr != NULL) {
155
5.63k
    avm_free(gi->cls_ptr);
156
5.63k
    gi->cls_ptr = NULL;
157
5.63k
  }
158
16.5k
  if (gi->err_ptr != NULL) {
159
5.63k
    avm_free(gi->err_ptr);
160
5.63k
    gi->err_ptr = NULL;
161
5.63k
  }
162
16.5k
  if (gi->gdf_block_flags != NULL) {
163
5.63k
    avm_free(gi->gdf_block_flags);
164
5.63k
    gi->gdf_block_flags = NULL;
165
5.63k
  }
166
16.5k
  if (gi->glbs != NULL) {
167
5.63k
    avm_free(gi->glbs);
168
5.63k
    gi->glbs = NULL;
169
5.63k
  }
170
16.5k
  if (gi->tmp_save_left != NULL) {
171
5.63k
    avm_free(gi->tmp_save_left);
172
5.63k
    gi->tmp_save_left = NULL;
173
5.63k
  }
174
16.5k
  if (gi->tmp_save_right != NULL) {
175
5.63k
    avm_free(gi->tmp_save_right);
176
5.63k
    gi->tmp_save_right = NULL;
177
5.63k
  }
178
16.5k
}
179
180
0
#define GDF_PRINT_INT(x) printf(#x " : %d\n", x)
181
182
0
void gdf_print_info(AV2_COMMON *cm, char *info, int poc) {
183
0
  printf("=================GDF %s info=================\n", info);
184
185
0
  GDF_PRINT_INT(cm->cur_frame->buf.y_width);
186
0
  GDF_PRINT_INT(cm->cur_frame->buf.y_height);
187
0
  GDF_PRINT_INT(cm->cur_frame->buf.y_stride);
188
0
  GDF_PRINT_INT(cm->cur_frame->buf.bit_depth);
189
0
  GDF_PRINT_INT(cm->quant_params.base_qindex);
190
0
  GDF_PRINT_INT(cm->ref_frames_info.ref_frame_distance[0]);
191
0
  GDF_PRINT_INT(cm->ref_frames_info.ref_frame_distance[1]);
192
0
  GDF_PRINT_INT(cm->current_frame.frame_type);
193
0
  GDF_PRINT_INT(cm->tiles.height);
194
0
  GDF_PRINT_INT(cm->tiles.width);
195
0
  GDF_PRINT_INT(cm->mib_size);
196
197
0
  printf("%s[%3d]: gdf_info = [ flag = %d ", info, poc, cm->gdf_info.gdf_mode);
198
0
  if (cm->gdf_info.gdf_mode > 0) {
199
0
    printf("=> (qp_idx, scale_idx) = (%3d %3d) ", cm->gdf_info.gdf_pic_qp_idx,
200
0
           cm->gdf_info.gdf_pic_scale_idx);
201
0
  }
202
0
  if (cm->gdf_info.gdf_mode > 1) {
203
0
    printf("(");
204
0
    for (int blk_idx = 0; blk_idx < cm->gdf_info.gdf_block_num; blk_idx++) {
205
0
      printf(" %d", cm->gdf_info.gdf_block_flags[blk_idx]);
206
0
    }
207
0
    printf(")");
208
0
  }
209
0
  printf(" ]\n");
210
0
}
211
#undef GDF_PRINT_INT
212
213
void gdf_extend_frame_highbd(uint16_t *data, int width, int height, int stride,
214
3.67k
                             int border_horz, int border_vert) {
215
3.67k
  uint16_t *data_p;
216
3.67k
  int i, j;
217
25.0k
  for (i = 0; i < height; ++i) {
218
21.3k
    data_p = data + i * stride;
219
149k
    for (j = -border_horz; j < 0; ++j) data_p[j] = data_p[0];
220
149k
    for (j = width; j < width + border_horz; ++j) data_p[j] = data_p[width - 1];
221
21.3k
  }
222
3.67k
  data_p = data - border_horz;
223
3.83k
  for (i = -border_vert; i < 0; ++i) {
224
162
    memcpy(data_p + i * stride, data_p,
225
162
           (width + 2 * border_horz) * sizeof(uint16_t));
226
162
  }
227
3.83k
  for (i = height; i < height + border_vert; ++i) {
228
162
    memcpy(data_p + i * stride, data_p + (height - 1) * stride,
229
162
           (width + 2 * border_horz) * sizeof(uint16_t));
230
162
  }
231
3.67k
}
232
233
27
void gdf_copy_guided_frame(AV2_COMMON *cm) {
234
27
  int top_buf = GDF_TEST_EXTRA_VER_BORDER;
235
27
  int bot_buf = GDF_TEST_EXTRA_VER_BORDER;
236
27
  const int rec_height = cm->cur_frame->buf.y_height;
237
27
  const int rec_width = cm->cur_frame->buf.y_width;
238
27
  const int rec_stride = cm->cur_frame->buf.y_stride;
239
240
27
  const int input_stride = (((rec_width + GDF_TEST_STRIPE_SIZE) >> 4) << 4) +
241
27
                           16;  // GDF_TEST_STRIPE_SIZE: max unit size
242
                                // 16: AVX2 vector length
243
27
  cm->gdf_info.inp_stride = input_stride;
244
245
27
  cm->gdf_info.inp_pad_ptr =
246
27
      (uint16_t *)avm_memalign(32, (top_buf + rec_height + bot_buf + 4) *
247
27
                                       input_stride * sizeof(uint16_t));
248
17.7k
  for (int i = top_buf; i < top_buf + rec_height; i++) {
249
17.7k
    memcpy(
250
17.7k
        cm->gdf_info.inp_pad_ptr + i * input_stride + GDF_TEST_EXTRA_HOR_BORDER,
251
17.7k
        cm->cur_frame->buf.buffers[AVM_PLANE_Y] + (i - top_buf) * rec_stride,
252
17.7k
        sizeof(uint16_t) * rec_width);
253
17.7k
    if (cm->cur_frame->buf.bit_depth > GDF_TEST_INP_PREC) {
254
0
      const unsigned int diff_bit_depth =
255
0
          cm->cur_frame->buf.bit_depth - GDF_TEST_INP_PREC;
256
0
      uint16_t *cur_line = cm->gdf_info.inp_pad_ptr + i * input_stride +
257
0
                           GDF_TEST_EXTRA_HOR_BORDER;
258
0
      for (int j = 0; j < rec_width; j++) {
259
0
        cur_line[j] >>= diff_bit_depth;
260
0
      }
261
0
    }
262
17.7k
  }
263
27
  cm->gdf_info.inp_ptr = cm->gdf_info.inp_pad_ptr + top_buf * input_stride +
264
27
                         GDF_TEST_EXTRA_HOR_BORDER;
265
27
  gdf_extend_frame_highbd(cm->gdf_info.inp_ptr, rec_width, rec_height,
266
27
                          input_stride, GDF_TEST_EXTRA_HOR_BORDER,
267
27
                          GDF_TEST_EXTRA_VER_BORDER);
268
27
}
269
270
void gdf_setup_processing_stripe_leftright_boundary(GdfInfo *gdf, int i_min,
271
                                                    int i_max, int j_min,
272
                                                    int j_max,
273
                                                    int tile_boundary_left,
274
328
                                                    int tile_boundary_right) {
275
328
  const int data_stride = gdf->inp_stride;
276
328
  const int h = i_max - i_min;
277
328
  const int w = j_max - j_min;
278
328
  const int h_border = GDF_TEST_EXTRA_HOR_BORDER;
279
328
  const int v_border = GDF_TEST_EXTRA_VER_BORDER;
280
328
  const int stride = GDF_TEST_EXTRA_HOR_BORDER;
281
328
  assert(h <= RESTORATION_PROC_UNIT_SIZE);
282
328
  uint16_t *data_tl = gdf->inp_ptr + i_min * data_stride + j_min;
283
328
  if (tile_boundary_left) {
284
301
    uint16_t *d = data_tl - v_border * data_stride - h_border;
285
2.10k
    for (int i = 0; i < v_border; ++i) {
286
1.80k
      memcpy(gdf->tmp_save_left + i * stride, d + i * data_stride,
287
1.80k
             h_border * sizeof(*d));
288
      // Replicate
289
1.80k
      avm_memset16(d + i * data_stride, *(d + i * data_stride + h_border),
290
1.80k
                   h_border);
291
1.80k
    }
292
18.0k
    for (int i = v_border; i < h + v_border; ++i) {
293
17.7k
      memcpy(gdf->tmp_save_left + i * stride, d + i * data_stride,
294
17.7k
             h_border * sizeof(*d));
295
      // Replicate
296
17.7k
      avm_memset16(d + i * data_stride, *(d + i * data_stride + h_border),
297
17.7k
                   h_border);
298
17.7k
    }
299
2.10k
    for (int i = h + v_border; i < h + 2 * v_border; ++i) {
300
1.80k
      memcpy(gdf->tmp_save_left + i * stride, d + i * data_stride,
301
1.80k
             h_border * sizeof(*d));
302
      // Replicate
303
1.80k
      avm_memset16(d + i * data_stride, *(d + i * data_stride + h_border),
304
1.80k
                   h_border);
305
1.80k
    }
306
301
  }
307
328
  if (tile_boundary_right) {
308
301
    uint16_t *d = data_tl + w - v_border * data_stride;
309
2.10k
    for (int i = 0; i < v_border; ++i) {
310
1.80k
      memcpy(gdf->tmp_save_right + i * stride, d + i * data_stride,
311
1.80k
             h_border * sizeof(*d));
312
      // Replicate
313
1.80k
      avm_memset16(d + i * data_stride, *(d + i * data_stride - 1), h_border);
314
1.80k
    }
315
18.0k
    for (int i = v_border; i < h + v_border; ++i) {
316
17.7k
      memcpy(gdf->tmp_save_right + i * stride, d + i * data_stride,
317
17.7k
             h_border * sizeof(*d));
318
      // Replicate
319
17.7k
      avm_memset16(d + i * data_stride, *(d + i * data_stride - 1), h_border);
320
17.7k
    }
321
2.10k
    for (int i = h + v_border; i < h + 2 * v_border; ++i) {
322
1.80k
      memcpy(gdf->tmp_save_right + i * stride, d + i * data_stride,
323
1.80k
             h_border * sizeof(*d));
324
      // Replicate
325
1.80k
      avm_memset16(d + i * data_stride, *(d + i * data_stride - 1), h_border);
326
1.80k
    }
327
301
  }
328
328
}
329
330
void gdf_restore_processing_stripe_leftright_boundary(GdfInfo *gdf, int i_min,
331
                                                      int i_max, int j_min,
332
                                                      int j_max,
333
                                                      int tile_boundary_left,
334
328
                                                      int tile_boundary_right) {
335
328
  const int data_stride = gdf->inp_stride;
336
328
  const int h = i_max - i_min;
337
328
  const int w = j_max - j_min;
338
328
  const int h_border = GDF_TEST_EXTRA_HOR_BORDER;
339
328
  const int v_border = GDF_TEST_EXTRA_VER_BORDER;
340
328
  const int stride = GDF_TEST_EXTRA_HOR_BORDER;
341
328
  assert(h <= RESTORATION_PROC_UNIT_SIZE);
342
328
  uint16_t *data_tl = gdf->inp_ptr + i_min * data_stride + j_min;
343
328
  if (tile_boundary_left) {
344
301
    uint16_t *d = data_tl - v_border * data_stride - h_border;
345
21.6k
    for (int i = 0; i < h + 2 * v_border; ++i) {
346
21.3k
      memcpy(d + i * data_stride, gdf->tmp_save_left + i * stride,
347
21.3k
             h_border * sizeof(*d));
348
21.3k
    }
349
301
  }
350
328
  if (tile_boundary_right) {
351
301
    uint16_t *d = data_tl + w - v_border * data_stride;
352
21.6k
    for (int i = 0; i < h + 2 * v_border; ++i) {
353
21.3k
      memcpy(d + i * data_stride, gdf->tmp_save_right + i * stride,
354
21.3k
             h_border * sizeof(*d));
355
21.3k
    }
356
301
  }
357
328
}
358
359
void gdf_setup_reference_lines(AV2_COMMON *cm, int i_min, int i_max,
360
                               int frame_stripe, int copy_above,
361
304
                               int copy_below) {
362
304
  const RestorationStripeBoundaries *rsb = &cm->rst_info[0].boundaries;
363
304
  const int rsb_row = frame_stripe * RESTORATION_CTX_VERT;
364
365
304
  const int rec_width = cm->cur_frame->buf.y_width;
366
304
  const int buf_x0_off = RESTORATION_BORDER_HORZ;
367
304
  const int buf_stride = rsb->stripe_boundary_stride;
368
304
  const int data_stride = cm->gdf_info.inp_stride;
369
304
  const int line_size = rec_width << 1;
370
371
304
  if (copy_above) {
372
304
    uint16_t *data_tl = cm->gdf_info.inp_ptr + i_min * data_stride;
373
2.12k
    for (int i = -GDF_TEST_EXTRA_VER_BORDER; i < 0; ++i) {
374
1.82k
      const int buf_row = rsb_row + AVMMAX(i + RESTORATION_CTX_VERT, 0);
375
1.82k
      const int buf_off = buf_x0_off + buf_row * buf_stride;
376
1.82k
      const uint16_t *buf = rsb->stripe_boundary_above + buf_off;
377
1.82k
      uint16_t *dst = data_tl + i * data_stride;
378
      // Save old pixels, then replace with data from stripe_boundary_above
379
1.82k
      memcpy(cm->gdf_info.glbs->gdf_save_above[i + GDF_TEST_EXTRA_VER_BORDER],
380
1.82k
             dst - GDF_TEST_EXTRA_HOR_BORDER,
381
1.82k
             line_size +
382
1.82k
                 4 * GDF_TEST_EXTRA_HOR_BORDER);  // (sizeof(int16_t) * width +
383
                                                  // sizeof(int16_t) * 2 *
384
                                                  // GDF_TEST_EXTRA_HOR_BORDER
385
1.82k
      memcpy(dst, buf, line_size);
386
1.82k
      if (cm->cur_frame->buf.bit_depth > GDF_TEST_INP_PREC) {
387
0
        const unsigned int diff_bit_depth =
388
0
            cm->cur_frame->buf.bit_depth - GDF_TEST_INP_PREC;
389
0
        uint16_t *cur_line = dst;
390
0
        for (int j = 0; j < rec_width; j++) {
391
0
          cur_line[j] >>= diff_bit_depth;
392
0
        }
393
0
      }
394
1.82k
      gdf_extend_frame_highbd(dst, rec_width, 1, data_stride,
395
1.82k
                              GDF_TEST_EXTRA_HOR_BORDER, 0);
396
1.82k
    }
397
304
  }
398
304
  if (copy_below) {
399
304
    uint16_t *data_bl = cm->gdf_info.inp_ptr + i_max * data_stride;
400
2.12k
    for (int i = 0; i < GDF_TEST_EXTRA_VER_BORDER; ++i) {
401
1.82k
      const int buf_row = rsb_row + AVMMIN(i, RESTORATION_CTX_VERT - 1);
402
1.82k
      const int buf_off = buf_x0_off + buf_row * buf_stride;
403
1.82k
      const uint16_t *src = rsb->stripe_boundary_below + buf_off;
404
1.82k
      uint16_t *dst = data_bl + i * data_stride;
405
      // Save old pixels, then replace with data from stripe_boundary_below
406
1.82k
      memcpy(cm->gdf_info.glbs->gdf_save_below[i],
407
1.82k
             dst - GDF_TEST_EXTRA_HOR_BORDER,
408
1.82k
             line_size + 4 * GDF_TEST_EXTRA_HOR_BORDER);
409
1.82k
      memcpy(dst, src, line_size);
410
1.82k
      if (cm->cur_frame->buf.bit_depth > GDF_TEST_INP_PREC) {
411
0
        const unsigned int diff_bit_depth =
412
0
            cm->cur_frame->buf.bit_depth - GDF_TEST_INP_PREC;
413
0
        uint16_t *cur_line = dst;
414
0
        for (int j = 0; j < rec_width; j++) {
415
0
          cur_line[j] >>= diff_bit_depth;
416
0
        }
417
0
      }
418
1.82k
      gdf_extend_frame_highbd(dst, rec_width, 1, data_stride,
419
1.82k
                              GDF_TEST_EXTRA_HOR_BORDER, 0);
420
1.82k
    }
421
304
  }
422
304
}
423
424
void gdf_unset_reference_lines(AV2_COMMON *cm, int i_min, int i_max,
425
304
                               int copy_above, int copy_below) {
426
304
  const int rec_width = cm->cur_frame->buf.y_width;
427
304
  const int data_stride = cm->gdf_info.inp_stride;
428
304
  const int line_size = rec_width << 1;
429
430
304
  if (copy_above) {
431
304
    uint16_t *data_tl = cm->gdf_info.inp_ptr + i_min * data_stride;
432
2.12k
    for (int i = -GDF_TEST_EXTRA_VER_BORDER; i < 0; ++i) {
433
1.82k
      uint16_t *dst = data_tl + i * data_stride;
434
1.82k
      memcpy(dst - GDF_TEST_EXTRA_HOR_BORDER,
435
1.82k
             cm->gdf_info.glbs->gdf_save_above[i + GDF_TEST_EXTRA_VER_BORDER],
436
1.82k
             line_size + 4 * GDF_TEST_EXTRA_HOR_BORDER);
437
1.82k
    }
438
304
  }
439
440
304
  if (copy_below) {
441
304
    uint16_t *data_bl = cm->gdf_info.inp_ptr + i_max * data_stride;
442
2.12k
    for (int i = 0; i < GDF_TEST_EXTRA_VER_BORDER; ++i) {
443
1.82k
      uint16_t *dst = data_bl + i * data_stride;
444
1.82k
      memcpy(dst - GDF_TEST_EXTRA_HOR_BORDER,
445
1.82k
             cm->gdf_info.glbs->gdf_save_below[i],
446
1.82k
             line_size + 4 * GDF_TEST_EXTRA_HOR_BORDER);
447
1.82k
    }
448
304
  }
449
304
}
450
451
27
void gdf_free_guided_frame(AV2_COMMON *cm) {
452
27
  avm_free(cm->gdf_info.inp_pad_ptr);
453
27
}
454
455
4.92M
int gdf_get_block_idx(const AV2_COMMON *cm, int y_h, int y_w) {
456
4.92M
  int blk_idx = -1;
457
4.92M
  if ((y_h % cm->gdf_info.gdf_block_size == 0) &&
458
172k
      (y_w % cm->gdf_info.gdf_block_size == 0)) {
459
6.51k
    int blk_idx_h = y_h / cm->gdf_info.gdf_block_size;
460
6.51k
    int blk_idx_w = y_w / cm->gdf_info.gdf_block_size;
461
6.51k
    blk_idx = blk_idx_h * cm->gdf_info.gdf_block_num_w + blk_idx_w;
462
6.51k
  }
463
4.92M
  blk_idx = blk_idx < cm->gdf_info.gdf_block_num ? blk_idx : -1;
464
4.92M
  return blk_idx;
465
4.92M
}
466
467
0
static INLINE int get_ref_dst_max(const AV2_COMMON *const cm) {
468
0
  int ref_dst_max = 0;
469
0
  for (int i = 0; i < cm->ref_frames_info.num_future_refs; i++) {
470
0
    const int ref = cm->ref_frames_info.future_refs[i];
471
0
    if ((ref == 0 || ref == 1) && get_ref_frame_buf(cm, ref) != NULL) {
472
0
      ref_dst_max =
473
0
          AVMMAX(ref_dst_max, abs(cm->ref_frames_info.ref_frame_distance[ref]));
474
0
    }
475
0
  }
476
0
  for (int i = 0; i < cm->ref_frames_info.num_past_refs; i++) {
477
0
    const int ref = cm->ref_frames_info.past_refs[i];
478
0
    if ((ref == 0 || ref == 1) && get_ref_frame_buf(cm, ref) != NULL) {
479
0
      ref_dst_max =
480
0
          AVMMAX(ref_dst_max, abs(cm->ref_frames_info.ref_frame_distance[ref]));
481
0
    }
482
0
  }
483
484
0
  return ref_dst_max > 0 ? ref_dst_max : INT_MAX;
485
0
}
486
487
27
int gdf_get_ref_dst_idx(const AV2_COMMON *cm) {
488
27
  int ref_dst_idx = 0;
489
27
  if (frame_is_intra_only(cm)) return ref_dst_idx;
490
491
0
  int ref_dst_max = get_ref_dst_max(cm);
492
0
  if (ref_dst_max < 2)
493
0
    ref_dst_idx = 1;
494
0
  else if (ref_dst_max < 3)
495
0
    ref_dst_idx = 2;
496
0
  else if (ref_dst_max < 6)
497
0
    ref_dst_idx = 3;
498
0
  else if (ref_dst_max < 11)
499
0
    ref_dst_idx = 4;
500
0
  else
501
0
    ref_dst_idx = 5;
502
0
  return ref_dst_idx;
503
27
}
504
505
27
int gdf_get_qp_idx_base(const AV2_COMMON *cm) {
506
27
  const int is_intra = frame_is_intra_only(cm);
507
27
  const int bit_depth = cm->cur_frame->buf.bit_depth;
508
27
  int qp_base = is_intra ? 85 : 110;
509
27
  int qp_offset = 24 * (bit_depth - 8);
510
27
  int qp = cm->quant_params.base_qindex;
511
27
  int qp_idx_avg, qp_idx_base;
512
27
  if (qp < (qp_base + 12 + qp_offset))
513
7
    qp_idx_avg = 0;
514
20
  else if (qp < (qp_base + 37 + qp_offset))
515
0
    qp_idx_avg = 1;
516
20
  else if (qp < (qp_base + 62 + qp_offset))
517
0
    qp_idx_avg = 2;
518
20
  else if (qp < (qp_base + 87 + qp_offset))
519
1
    qp_idx_avg = 3;
520
19
  else if (qp < (qp_base + 112 + qp_offset))
521
1
    qp_idx_avg = 4;
522
18
  else
523
18
    qp_idx_avg = 5;
524
27
  qp_idx_base = CLIP(qp_idx_avg - (GDF_RDO_QP_NUM >> 1), 0,
525
27
                     GDF_TRAIN_QP_NUM - GDF_RDO_QP_NUM);
526
27
  return qp_idx_base;
527
27
}
528
529
27
void gdf_filter_frame(AV2_COMMON *cm) {
530
27
  uint16_t *const rec_pnt = cm->cur_frame->buf.buffers[AVM_PLANE_Y];
531
27
  const int rec_stride = cm->cur_frame->buf.y_stride;
532
533
27
  if (cm->bru.frame_inactive_flag) return;
534
27
  if (cm->bridge_frame_info.is_bridge_frame) return;
535
27
  const int bit_depth = cm->cur_frame->buf.bit_depth;
536
27
  const int pxl_max = (1 << cm->cur_frame->buf.bit_depth) - 1;
537
27
  const int pxl_shift =
538
27
      GDF_TEST_INP_PREC - AVMMIN(bit_depth, GDF_TEST_INP_PREC);
539
27
  const int err_shift = GDF_RDO_SCALE_NUM_LOG2 + GDF_TEST_INP_PREC - bit_depth;
540
27
  int ref_dst_idx = gdf_get_ref_dst_idx(cm);
541
27
  int qp_idx_min = gdf_get_qp_idx_base(cm) + cm->gdf_info.gdf_pic_qp_idx;
542
27
  int qp_idx_max_plus_1 = qp_idx_min + 1;
543
27
  int scale_val = cm->gdf_info.gdf_pic_scale_idx + 1;
544
545
27
  const int num_tile_rows = cm->tiles.rows;
546
27
  const int num_tile_cols = cm->tiles.cols;
547
27
  int blk_idx = 0;
548
27
  int tile_blk_stripe0 = 0;
549
54
  for (int tile_row = 0; tile_row < num_tile_rows; ++tile_row) {
550
27
    TileInfo tile_info;
551
27
    av2_tile_init(&tile_info, cm, tile_row, 0);
552
27
    AV2PixelRect tile_rect = av2_get_tile_rect(&tile_info, cm, 0);
553
27
    const int tile_height = tile_rect.bottom - tile_rect.top;
554
321
    for (int y_pos = -GDF_TEST_STRIPE_OFF, blk_idx_h = 0; y_pos < tile_height;
555
294
         y_pos += cm->gdf_info.gdf_block_size, blk_idx_h++) {
556
294
      if (blk_idx_h == cm->gdf_info.gdf_vert_blks_per_tile[tile_row]) {
557
7
        blk_idx -= cm->gdf_info.gdf_block_num_w;
558
7
      }
559
294
      int blk_stripe = 0;
560
588
      for (int tile_col = 0; tile_col < num_tile_cols; ++tile_col) {
561
294
        av2_tile_init(&tile_info, cm, tile_row, tile_col);
562
294
        tile_rect = av2_get_tile_rect(&tile_info, cm, 0);
563
294
        const int tile_width = tile_rect.right - tile_rect.left;
564
591
        for (int x_pos = 0; x_pos < tile_width;
565
297
             x_pos += cm->gdf_info.gdf_block_size) {
566
297
          blk_stripe = 0;
567
601
          for (int v_pos = y_pos; v_pos < y_pos + cm->gdf_info.gdf_block_size &&
568
315
                                  v_pos < tile_height;
569
304
               v_pos += cm->gdf_info.gdf_unit_size) {
570
304
            int i_min =
571
304
                AVMMAX(v_pos, GDF_TEST_FRAME_BOUNDARY_SIZE) + tile_rect.top;
572
304
            int i_max = AVMMIN(v_pos + cm->gdf_info.gdf_unit_size,
573
304
                               tile_height - GDF_TEST_FRAME_BOUNDARY_SIZE) +
574
304
                        tile_rect.top;
575
576
304
            int copy_above = 1, copy_below = 1;
577
304
            if (cm->seq_params.disable_loopfilters_across_tiles == 0) {
578
              // tile top but not picture top
579
0
              if (v_pos == -GDF_TEST_STRIPE_OFF && tile_row != 0)
580
0
                copy_above = 0;
581
              // tile bottom but not picture bottom
582
0
              if (v_pos + cm->gdf_info.gdf_unit_size >= tile_height &&
583
0
                  tile_row != num_tile_rows - 1)
584
0
                copy_below = 0;
585
0
            }
586
587
304
            gdf_setup_reference_lines(cm, i_min, i_max,
588
304
                                      tile_blk_stripe0 + blk_stripe, copy_above,
589
304
                                      copy_below);
590
304
            for (int u_pos = x_pos;
591
632
                 u_pos < x_pos + cm->gdf_info.gdf_block_size &&
592
329
                 u_pos < tile_width;
593
328
                 u_pos += cm->gdf_info.gdf_unit_size) {
594
328
              int j_min =
595
328
                  AVMMAX(u_pos, GDF_TEST_FRAME_BOUNDARY_SIZE) + tile_rect.left;
596
328
              int j_max = AVMMIN(u_pos + cm->gdf_info.gdf_unit_size,
597
328
                                 tile_width - GDF_TEST_FRAME_BOUNDARY_SIZE) +
598
328
                          tile_rect.left;
599
328
              int tile_boundary_left =
600
328
                  cm->seq_params.disable_loopfilters_across_tiles
601
328
                      ? (j_min == tile_rect.left)
602
328
                      : (j_min == 0);
603
328
              int tile_boundary_right =
604
328
                  cm->seq_params.disable_loopfilters_across_tiles
605
328
                      ? (j_max == tile_rect.right)
606
328
                      : (j_max == cm->cur_frame->buf.y_width);
607
608
328
              gdf_setup_processing_stripe_leftright_boundary(
609
328
                  &cm->gdf_info, i_min, i_max, j_min, j_max, tile_boundary_left,
610
328
                  tile_boundary_right);
611
612
328
              int use_gdf_local = 1;
613
              // FU level skip
614
328
              if (cm->bru.enabled) {
615
0
                const int mbmi_idx = get_mi_grid_idx(
616
0
                    &cm->mi_params,
617
0
                    AVMMIN(i_max - 1, (i_min + GDF_TEST_STRIPE_OFF)) >>
618
0
                        MI_SIZE_LOG2,
619
0
                    j_min >> MI_SIZE_LOG2);
620
0
                use_gdf_local =
621
0
                    cm->mi_params.mi_grid_base[mbmi_idx]->local_gdf_mode;
622
0
              }
623
328
              use_gdf_local &=
624
328
                  gdf_block_adjust_and_validate(&i_min, &i_max, &j_min, &j_max);
625
328
              if ((cm->gdf_info.gdf_mode == 1 ||
626
99
                   cm->gdf_info.gdf_block_flags[blk_idx]) &&
627
293
                  use_gdf_local) {
628
293
                const int bru_blk_skip = !bru_is_sb_active(
629
293
                    cm, j_min >> MI_SIZE_LOG2,
630
293
                    AVMMIN(i_max - 1, (i_min + GDF_TEST_STRIPE_OFF)) >>
631
293
                        MI_SIZE_LOG2);
632
293
                if (cm->bru.enabled && bru_blk_skip) {
633
0
                  avm_internal_error(&cm->error, AVM_CODEC_ERROR,
634
0
                                     "GDF on not active SB");
635
0
                }
636
586
                for (int qp_idx = qp_idx_min; qp_idx < qp_idx_max_plus_1;
637
293
                     qp_idx++) {
638
293
                  gdf_set_lap_and_cls_unit(
639
293
                      i_min, i_max, j_min, j_max,
640
293
                      cm->gdf_info.inp_ptr +
641
293
                          cm->gdf_info.inp_stride * (i_min - 1) + (j_min - 1),
642
293
                      cm->gdf_info.inp_stride, bit_depth, cm->gdf_info.lap_ptr,
643
293
                      cm->gdf_info.lap_stride, cm->gdf_info.cls_ptr,
644
293
                      cm->gdf_info.cls_stride);
645
293
                  gdf_inference_unit(
646
293
                      i_min, i_max, j_min, j_max, qp_idx,
647
293
                      cm->gdf_info.inp_ptr + cm->gdf_info.inp_stride * i_min +
648
293
                          j_min,
649
293
                      cm->gdf_info.inp_stride, cm->gdf_info.lap_ptr,
650
293
                      cm->gdf_info.lap_stride, cm->gdf_info.cls_ptr,
651
293
                      cm->gdf_info.cls_stride, cm->gdf_info.err_ptr,
652
293
                      cm->gdf_info.err_stride, pxl_shift, ref_dst_idx);
653
                  // If there is at-least 1 segment is lossless in a frame, we
654
                  // have to do 4x4 processing, because minimum lossless block
655
                  // can be 4x4 size. Although, regardless the value of
656
                  // cm->features.has_lossless_segment, we can always do 4x4
657
                  // processing, however, for software optimization purpose we
658
                  // have used  full block processing for whole lossy frame.
659
293
                  if (cm->features.has_lossless_segment) {
660
                    // 4x4 block level processing
661
0
                    int min_b_size = 1 << MI_SIZE_LOG2;
662
0
                    for (int i_pos_4x4 = i_min; i_pos_4x4 < i_max;
663
0
                         i_pos_4x4 += min_b_size) {
664
0
                      for (int j_pos_4x4 = j_min; j_pos_4x4 < j_max;
665
0
                           j_pos_4x4 += min_b_size) {
666
                        // CHECK_LOSSLESS(j_pos_4x4 % 4, " j_pos_4x4 is not
667
                        // multiple of 4"); CHECK_LOSSLESS(i_pos_4x4 % 4, "
668
                        // i_pos_4x4 is not multiple of 4");
669
670
0
                        const int mi_idx = get_mi_grid_idx(
671
0
                            &cm->mi_params, i_pos_4x4 >> MI_SIZE_LOG2,
672
0
                            j_pos_4x4 >> MI_SIZE_LOG2);
673
0
                        const int is_lossless =
674
0
                            cm->features
675
0
                                .lossless_segment[cm->mi_params
676
0
                                                      .mi_grid_base[mi_idx]
677
0
                                                      ->segment_id];
678
0
                        if (!is_lossless) {
679
0
                          int height_4x4 =
680
0
                              AVMMIN(min_b_size, i_max - i_pos_4x4);
681
0
                          int width_4x4 = AVMMIN(min_b_size, j_max - j_pos_4x4);
682
0
                          uint16_t *rec_pnt_4x4 =
683
0
                              rec_pnt + i_pos_4x4 * rec_stride + j_pos_4x4;
684
0
                          int16_t *errPnt =
685
0
                              cm->gdf_info.err_ptr +
686
0
                              (i_pos_4x4 - i_min) * cm->gdf_info.err_stride +
687
0
                              (j_pos_4x4 - j_min);
688
0
                          gdf_compensation_unit_c(
689
0
                              rec_pnt_4x4, rec_stride, errPnt,
690
0
                              cm->gdf_info.err_stride, err_shift, scale_val,
691
0
                              pxl_max, height_4x4, width_4x4);
692
0
                        }
693
0
                      }
694
0
                    }
695
293
                  } else {
696
293
                    gdf_compensation_unit(rec_pnt + i_min * rec_stride + j_min,
697
293
                                          rec_stride, cm->gdf_info.err_ptr,
698
293
                                          cm->gdf_info.err_stride, err_shift,
699
293
                                          scale_val, pxl_max, i_max - i_min,
700
293
                                          j_max - j_min);
701
293
                  }
702
293
                }
703
293
              }
704
328
              gdf_restore_processing_stripe_leftright_boundary(
705
328
                  &cm->gdf_info, i_min, i_max, j_min, j_max, tile_boundary_left,
706
328
                  tile_boundary_right);
707
328
            }
708
304
            gdf_unset_reference_lines(cm, i_min, i_max, copy_above, copy_below);
709
304
            blk_stripe++;
710
304
          }
711
297
          blk_idx++;
712
297
        }
713
294
      }
714
294
      tile_blk_stripe0 += blk_stripe;
715
294
    }
716
27
  }
717
27
}
718
719
#endif  // AVM_COMMON_GDF_H_