/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_ |