/src/avm/av2/common/blockd.c
Line | Count | Source |
1 | | /* |
2 | | * Copyright (c) 2021, 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 | | |
13 | | #include <assert.h> |
14 | | #include <math.h> |
15 | | |
16 | | #include "avm_ports/system_state.h" |
17 | | |
18 | | #include "av2/common/av2_common_int.h" |
19 | | #include "av2/common/blockd.h" |
20 | | #include "av2/common/enums.h" |
21 | | |
22 | 3.54M | PREDICTION_MODE av2_get_joint_mode(const MB_MODE_INFO *mi) { |
23 | 3.54M | if (!mi) return DC_PRED; |
24 | 3.08M | if (is_inter_block(mi, SHARED_PART) || is_intrabc_block(mi, SHARED_PART)) |
25 | 12.9k | return DC_PRED; |
26 | 3.07M | return mi->joint_y_mode_delta_angle; |
27 | 3.08M | } |
28 | | |
29 | 139k | void av2_reset_is_mi_coded_map(MACROBLOCKD *xd, int stride) { |
30 | 139k | av2_zero(xd->is_mi_coded); |
31 | 139k | xd->is_mi_coded_stride = stride; |
32 | 139k | } |
33 | | |
34 | | void av2_mark_block_as_coded(MACROBLOCKD *xd, BLOCK_SIZE bsize, |
35 | 1.13M | BLOCK_SIZE sb_size) { |
36 | 1.13M | const int mi_row = xd->mi_row; |
37 | 1.13M | const int mi_col = xd->mi_col; |
38 | 1.13M | const int sb_mi_size = mi_size_wide[sb_size]; |
39 | 1.13M | const int mi_row_offset = mi_row & (sb_mi_size - 1); |
40 | 1.13M | const int mi_col_offset = mi_col & (sb_mi_size - 1); |
41 | | |
42 | 9.06M | for (int r = 0; r < mi_size_high[bsize]; ++r) |
43 | 97.6M | for (int c = 0; c < mi_size_wide[bsize]; ++c) { |
44 | 89.6M | const int pos = |
45 | 89.6M | (mi_row_offset + r) * xd->is_mi_coded_stride + mi_col_offset + c; |
46 | 89.6M | switch (xd->tree_type) { |
47 | 58.3M | case SHARED_PART: |
48 | 58.3M | xd->is_mi_coded[0][pos] = 1; |
49 | 58.3M | xd->is_mi_coded[1][pos] = 1; |
50 | 58.3M | break; |
51 | 15.8M | case LUMA_PART: xd->is_mi_coded[0][pos] = 1; break; |
52 | 15.6M | case CHROMA_PART: xd->is_mi_coded[1][pos] = 1; break; |
53 | 0 | default: assert(0 && "Invalid tree type"); |
54 | 89.6M | } |
55 | 89.6M | } |
56 | 1.13M | } |
57 | | |
58 | | void av2_mark_block_as_not_coded(MACROBLOCKD *xd, int mi_row, int mi_col, |
59 | 0 | BLOCK_SIZE bsize, BLOCK_SIZE sb_size) { |
60 | 0 | const int sb_mi_size = mi_size_wide[sb_size]; |
61 | 0 | const int mi_row_offset = mi_row & (sb_mi_size - 1); |
62 | 0 | const int mi_col_offset = mi_col & (sb_mi_size - 1); |
63 | |
|
64 | 0 | for (int r = 0; r < mi_size_high[bsize]; ++r) { |
65 | 0 | const int pos = |
66 | 0 | (mi_row_offset + r) * xd->is_mi_coded_stride + mi_col_offset; |
67 | 0 | uint8_t *row_ptr_luma = &xd->is_mi_coded[0][pos]; |
68 | 0 | uint8_t *row_ptr_chroma = &xd->is_mi_coded[1][pos]; |
69 | 0 | switch (xd->tree_type) { |
70 | 0 | case SHARED_PART: |
71 | 0 | av2_zero_array(row_ptr_luma, mi_size_wide[bsize]); |
72 | 0 | av2_zero_array(row_ptr_chroma, mi_size_wide[bsize]); |
73 | 0 | break; |
74 | 0 | case LUMA_PART: av2_zero_array(row_ptr_luma, mi_size_wide[bsize]); break; |
75 | 0 | case CHROMA_PART: |
76 | 0 | av2_zero_array(row_ptr_chroma, mi_size_wide[bsize]); |
77 | 0 | break; |
78 | 0 | default: assert(0 && "Invalid tree type"); |
79 | 0 | } |
80 | 0 | } |
81 | 0 | } |
82 | | |
83 | | void av2_mark_block_as_pseudo_coded(MACROBLOCKD *xd, int mi_row, int mi_col, |
84 | 63.0k | BLOCK_SIZE bsize, BLOCK_SIZE sb_size) { |
85 | 63.0k | const int sb_mi_size = mi_size_wide[sb_size]; |
86 | 63.0k | const int mi_row_offset = mi_row & (sb_mi_size - 1); |
87 | 63.0k | const int mi_col_offset = mi_col & (sb_mi_size - 1); |
88 | | |
89 | 629k | for (int r = 0; r < mi_size_high[bsize]; ++r) |
90 | 6.53M | for (int c = 0; c < mi_size_wide[bsize]; ++c) { |
91 | 5.96M | const int pos = |
92 | 5.96M | (mi_row_offset + r) * xd->is_mi_coded_stride + mi_col_offset + c; |
93 | 5.96M | switch (xd->tree_type) { |
94 | 3.69M | case SHARED_PART: |
95 | 3.69M | xd->is_mi_coded[0][pos] = 2; |
96 | 3.69M | xd->is_mi_coded[1][pos] = 2; |
97 | 3.69M | break; |
98 | 1.14M | case LUMA_PART: xd->is_mi_coded[0][pos] = 2; break; |
99 | 1.14M | case CHROMA_PART: xd->is_mi_coded[1][pos] = 2; break; |
100 | 0 | default: assert(0 && "Invalid tree type"); |
101 | 5.96M | } |
102 | 5.96M | } |
103 | 63.0k | } |
104 | | |
105 | 2.15M | PARTITION_TREE *av2_alloc_ptree_node(PARTITION_TREE *parent, int index) { |
106 | 2.15M | PARTITION_TREE *ptree = NULL; |
107 | 2.15M | struct avm_internal_error_info error; |
108 | | |
109 | 2.15M | AVM_CHECK_MEM_ERROR(&error, ptree, avm_calloc(1, sizeof(*ptree))); |
110 | | |
111 | 2.15M | ptree->parent = parent; |
112 | 2.15M | ptree->index = index; |
113 | 2.15M | ptree->partition = PARTITION_INVALID; |
114 | 2.15M | ptree->is_settled = 0; |
115 | 10.7M | for (int i = 0; i < 4; ++i) ptree->sub_tree[i] = NULL; |
116 | | |
117 | 2.15M | return ptree; |
118 | 2.15M | } |
119 | | |
120 | 9.45M | void av2_free_ptree_recursive(PARTITION_TREE *ptree) { |
121 | 9.45M | if (ptree == NULL) return; |
122 | | |
123 | 10.8M | for (int i = 0; i < 4; ++i) { |
124 | 8.66M | av2_free_ptree_recursive(ptree->sub_tree[i]); |
125 | 8.66M | ptree->sub_tree[i] = NULL; |
126 | 8.66M | } |
127 | | |
128 | 2.16M | avm_free(ptree); |
129 | 2.16M | } |
130 | | |
131 | 186k | void av2_reset_ptree_in_sbi(SB_INFO *sbi, TREE_TYPE tree_type) { |
132 | 186k | const int idx = av2_get_sdp_idx(tree_type); |
133 | 186k | if (sbi->ptree_root[idx]) av2_free_ptree_recursive(sbi->ptree_root[idx]); |
134 | | |
135 | 186k | sbi->ptree_root[idx] = av2_alloc_ptree_node(NULL, 0); |
136 | 186k | } |
137 | | |
138 | | void av2_set_entropy_contexts(const MACROBLOCKD *xd, |
139 | | struct macroblockd_plane *pd, int plane, |
140 | | BLOCK_SIZE plane_bsize, TX_SIZE tx_size, |
141 | 4.50M | int has_eob, int aoff, int loff) { |
142 | 4.50M | ENTROPY_CONTEXT *const a = pd->above_entropy_context + aoff; |
143 | 4.50M | ENTROPY_CONTEXT *const l = pd->left_entropy_context + loff; |
144 | 4.50M | const int txs_wide = tx_size_wide_unit[tx_size]; |
145 | 4.50M | const int txs_high = tx_size_high_unit[tx_size]; |
146 | | |
147 | | // above |
148 | 4.50M | if (has_eob && xd->mb_to_right_edge < 0) { |
149 | 4.38k | const int blocks_wide = max_block_wide(xd, plane_bsize, plane); |
150 | 4.38k | const int above_contexts = AVMMIN(txs_wide, blocks_wide - aoff); |
151 | 4.38k | memset(a, has_eob, sizeof(*a) * above_contexts); |
152 | 4.38k | memset(a + above_contexts, 0, sizeof(*a) * (txs_wide - above_contexts)); |
153 | 4.50M | } else { |
154 | 4.50M | memset(a, has_eob, sizeof(*a) * txs_wide); |
155 | 4.50M | } |
156 | | |
157 | | // left |
158 | 4.50M | if (has_eob && xd->mb_to_bottom_edge < 0) { |
159 | 5.99k | const int blocks_high = max_block_high(xd, plane_bsize, plane); |
160 | 5.99k | const int left_contexts = AVMMIN(txs_high, blocks_high - loff); |
161 | 5.99k | memset(l, has_eob, sizeof(*l) * left_contexts); |
162 | 5.99k | memset(l + left_contexts, 0, sizeof(*l) * (txs_high - left_contexts)); |
163 | 4.50M | } else { |
164 | 4.50M | memset(l, has_eob, sizeof(*l) * txs_high); |
165 | 4.50M | } |
166 | 4.50M | } |
167 | | |
168 | | void av2_reset_entropy_context(MACROBLOCKD *xd, BLOCK_SIZE bsize, |
169 | 46.3k | const int num_planes) { |
170 | | // TODO(chiyotsai): This part is needed to avoid encoder/decoder mismatch. |
171 | | // Investigate why this is the case. It seems like on the decoder side, the |
172 | | // decoder is failing to clear the context after encoding a skip_txfm chroma |
173 | | // block. |
174 | 46.3k | const int plane_start = (xd->tree_type == CHROMA_PART); |
175 | 46.3k | int plane_end = 0; |
176 | 46.3k | switch (xd->tree_type) { |
177 | 3.20k | case LUMA_PART: plane_end = 1; break; |
178 | 0 | case CHROMA_PART: plane_end = num_planes; break; |
179 | 43.1k | case SHARED_PART: |
180 | 43.1k | plane_end = 1 + (num_planes - 1) * xd->is_chroma_ref; |
181 | 43.1k | break; |
182 | 0 | default: assert(0); |
183 | 46.3k | } |
184 | 134k | for (int i = plane_start; i < plane_end; ++i) { |
185 | 88.4k | struct macroblockd_plane *const pd = &xd->plane[i]; |
186 | 88.4k | const BLOCK_SIZE plane_bsize = get_mb_plane_block_size( |
187 | 88.4k | xd, xd->mi[0], i, pd->subsampling_x, pd->subsampling_y); |
188 | 88.4k | (void)bsize; |
189 | 88.4k | const int txs_wide = mi_size_wide[plane_bsize]; |
190 | 88.4k | const int txs_high = mi_size_high[plane_bsize]; |
191 | 88.4k | memset(pd->above_entropy_context, 0, sizeof(ENTROPY_CONTEXT) * txs_wide); |
192 | 88.4k | memset(pd->left_entropy_context, 0, sizeof(ENTROPY_CONTEXT) * txs_high); |
193 | 88.4k | } |
194 | 46.3k | } |
195 | | |
196 | | // Resets the LR decoding state before decoding each coded tile and |
197 | | // associated LR coefficients |
198 | | void av2_reset_loop_restoration(MACROBLOCKD *xd, int plane_start, int plane_end, |
199 | 29.3k | const int *num_filter_classes) { |
200 | 114k | for (int p = plane_start; p < plane_end; ++p) { |
201 | 85.1k | av2_reset_wienerns_bank(&xd->wienerns_info[p], xd->current_base_qindex, |
202 | 85.1k | num_filter_classes[p], p != AVM_PLANE_Y); |
203 | 85.1k | } |
204 | 29.3k | } |
205 | | |
206 | | // Initialize bank |
207 | | void av2_reset_wienerns_bank(WienerNonsepInfoBank *bank, int qindex, |
208 | 85.1k | int num_classes, int chroma) { |
209 | 424k | for (int i = 0; i < LR_BANK_SIZE; ++i) { |
210 | 338k | set_default_wienerns(&bank->filter[i], qindex, num_classes, chroma); |
211 | 338k | } |
212 | | |
213 | 94.8k | for (int c_id = 0; c_id < num_classes; ++c_id) { |
214 | 9.62k | bank->bank_size_for_class[c_id] = 0; |
215 | 9.62k | bank->bank_ptr_for_class[c_id] = 0; |
216 | 9.62k | } |
217 | 85.1k | } |
218 | | |
219 | | // Add a new filter to bank |
220 | | void av2_add_to_wienerns_bank(WienerNonsepInfoBank *bank, |
221 | | const WienerNonsepInfo *info, |
222 | 36.0k | int wiener_class_id) { |
223 | 36.0k | int c_id_begin = wiener_class_id; |
224 | 36.0k | int c_id_end = wiener_class_id + 1; |
225 | 36.0k | if (wiener_class_id == ALL_WIENERNS_CLASSES) { |
226 | 0 | c_id_begin = 0; |
227 | 0 | c_id_end = info->num_classes; |
228 | 0 | } |
229 | 72.0k | for (int c_id = c_id_begin; c_id < c_id_end; ++c_id) { |
230 | 36.0k | if (bank->bank_size_for_class[c_id] < LR_BANK_SIZE) { |
231 | 34.9k | bank->bank_ptr_for_class[c_id] = bank->bank_size_for_class[c_id]; |
232 | 34.9k | bank->bank_size_for_class[c_id]++; |
233 | 34.9k | } else { |
234 | 1.04k | bank->bank_ptr_for_class[c_id] = |
235 | 1.04k | (bank->bank_ptr_for_class[c_id] + 1) % LR_BANK_SIZE; |
236 | 1.04k | } |
237 | 36.0k | copy_nsfilter_taps_for_class(&bank->filter[bank->bank_ptr_for_class[c_id]], |
238 | 36.0k | info, c_id); |
239 | 36.0k | } |
240 | 36.0k | } |
241 | | |
242 | | // Returns the filter that is at slot ndx from last. When ndx is zero the last |
243 | | // filter added is returned. When ndx is one the filter added before the last |
244 | | // and so on. |
245 | | WienerNonsepInfo *av2_ref_from_wienerns_bank(WienerNonsepInfoBank *bank, |
246 | 0 | int ndx, int wiener_class_id) { |
247 | 0 | assert(wiener_class_id != ALL_WIENERNS_CLASSES); |
248 | 0 | if (bank->bank_size_for_class[wiener_class_id] == 0) { |
249 | 0 | assert(ndx == 0); |
250 | 0 | return &bank->filter[0]; |
251 | 0 | } else { |
252 | 0 | assert(ndx < bank->bank_size_for_class[wiener_class_id]); |
253 | 0 | const int ptr = |
254 | 0 | bank->bank_ptr_for_class[wiener_class_id] - ndx + |
255 | 0 | (bank->bank_ptr_for_class[wiener_class_id] < ndx ? LR_BANK_SIZE : 0); |
256 | 0 | return &bank->filter[ptr]; |
257 | 0 | } |
258 | 0 | } |
259 | | |
260 | | // Get a const reference to a filter given the index |
261 | | const WienerNonsepInfo *av2_constref_from_wienerns_bank( |
262 | 37.9k | const WienerNonsepInfoBank *bank, int ndx, int wiener_class_id) { |
263 | 37.9k | assert(wiener_class_id != ALL_WIENERNS_CLASSES); |
264 | 37.9k | if (bank->bank_size_for_class[wiener_class_id] == 0) { |
265 | 2.19k | return &bank->filter[0]; |
266 | 35.7k | } else { |
267 | 35.7k | assert(ndx < bank->bank_size_for_class[wiener_class_id]); |
268 | 35.7k | const int ptr = |
269 | 35.7k | bank->bank_ptr_for_class[wiener_class_id] - ndx + |
270 | 35.7k | (bank->bank_ptr_for_class[wiener_class_id] < ndx ? LR_BANK_SIZE : 0); |
271 | 35.7k | return &bank->filter[ptr]; |
272 | 35.7k | } |
273 | 37.9k | } |
274 | | |
275 | | // Directly replace a filter in the bank at given index |
276 | | void av2_upd_to_wienerns_bank(WienerNonsepInfoBank *bank, int ndx, |
277 | | const WienerNonsepInfo *info, |
278 | 0 | int wiener_class_id) { |
279 | 0 | copy_nsfilter_taps_for_class( |
280 | 0 | av2_ref_from_wienerns_bank(bank, ndx, wiener_class_id), info, |
281 | 0 | wiener_class_id); |
282 | 0 | } |
283 | | |
284 | 105k | int16_t *nsfilter_taps(WienerNonsepInfo *nsinfo, int wiener_class_id) { |
285 | 105k | assert(wiener_class_id >= 0 && wiener_class_id < nsinfo->num_classes); |
286 | 105k | return nsinfo->allfiltertaps + wiener_class_id * WIENERNS_TAPS_MAX; |
287 | 105k | } |
288 | | |
289 | | const int16_t *const_nsfilter_taps(const WienerNonsepInfo *nsinfo, |
290 | 293k | int wiener_class_id) { |
291 | 293k | assert(wiener_class_id >= 0 && wiener_class_id < nsinfo->num_classes); |
292 | 293k | return nsinfo->allfiltertaps + wiener_class_id * WIENERNS_TAPS_MAX; |
293 | 293k | } |
294 | | |
295 | | void copy_nsfilter_taps_for_class(WienerNonsepInfo *to_info, |
296 | | const WienerNonsepInfo *from_info, |
297 | 40.0k | int wiener_class_id) { |
298 | 40.0k | assert(wiener_class_id >= 0 && wiener_class_id < to_info->num_classes); |
299 | 40.0k | assert(wiener_class_id >= 0 && wiener_class_id < from_info->num_classes); |
300 | 40.0k | const int offset = wiener_class_id * WIENERNS_TAPS_MAX; |
301 | 40.0k | memcpy(to_info->allfiltertaps + offset, from_info->allfiltertaps + offset, |
302 | 40.0k | WIENERNS_TAPS_MAX * sizeof(*to_info->allfiltertaps)); |
303 | 40.0k | to_info->bank_ref_for_class[wiener_class_id] = |
304 | 40.0k | from_info->bank_ref_for_class[wiener_class_id]; |
305 | 40.0k | } |
306 | | |
307 | | void copy_nsfilter_taps(WienerNonsepInfo *to_info, |
308 | 249 | const WienerNonsepInfo *from_info) { |
309 | 249 | assert(to_info->num_classes == from_info->num_classes); |
310 | 249 | memcpy(to_info->allfiltertaps, from_info->allfiltertaps, |
311 | 249 | sizeof(to_info->allfiltertaps)); |
312 | 249 | memcpy(to_info->bank_ref_for_class, from_info->bank_ref_for_class, |
313 | 249 | sizeof(to_info->bank_ref_for_class)); |
314 | 249 | } |
315 | | |
316 | | void av2_setup_block_planes(MACROBLOCKD *xd, int ss_x, int ss_y, |
317 | 4.28k | const int num_planes) { |
318 | 4.28k | int i; |
319 | | |
320 | 16.1k | for (i = 0; i < num_planes; i++) { |
321 | 11.8k | xd->plane[i].plane_type = get_plane_type(i); |
322 | 11.8k | xd->plane[i].subsampling_x = i ? ss_x : 0; |
323 | 11.8k | xd->plane[i].subsampling_y = i ? ss_y : 0; |
324 | 11.8k | } |
325 | 5.32k | for (i = num_planes; i < MAX_MB_PLANE; i++) { |
326 | 1.04k | xd->plane[i].subsampling_x = 1; |
327 | 1.04k | xd->plane[i].subsampling_y = 1; |
328 | 1.04k | } |
329 | 4.28k | } |
330 | | |
331 | 10.0k | int max_dictionary_size(int nopcw) { |
332 | 10.0k | const int max_num_predictors = |
333 | 10.0k | num_dictionary_slots(WIENERNS_MAX_CLASSES, nopcw); |
334 | 10.0k | return max_num_predictors * MAX_NUM_DICTIONARY_TAPS; |
335 | 10.0k | } |
336 | | |
337 | 285 | void allocate_frame_filter_dictionary(AV2_COMMON *cm) { |
338 | | // Use max_dictionary_size(0) below instead of max_dictionary_size(nopcw) |
339 | | // to always allocate for the largest possible dictionary size. |
340 | | // If nopcw is solely based on sequence level parameters, this |
341 | | // should not be strictly necessary, since reallocation should |
342 | | // happen with every new sequence parameter set. However the current |
343 | | // reference decoder does not appear to reallocate when the sequence |
344 | | // level parameters change. Hence this change is needed. |
345 | 285 | const int nopcw = disable_pcwiener_filters_in_framefilters(&cm->seq_params); |
346 | 285 | (void)nopcw; |
347 | 285 | cm->frame_filter_dictionary = |
348 | 285 | avm_calloc(max_dictionary_size(0), sizeof(*cm->frame_filter_dictionary)); |
349 | 285 | cm->translated_pcwiener_filters = |
350 | 285 | avm_calloc(NUM_PC_WIENER_FILTERS * MAX_NUM_DICTIONARY_TAPS, |
351 | 285 | sizeof(*cm->translated_pcwiener_filters)); |
352 | 285 | cm->translation_done = 0; |
353 | 285 | cm->frame_filter_dictionary_stride = MAX_NUM_DICTIONARY_TAPS; |
354 | 285 | cm->num_ref_filters = avm_calloc(1, sizeof(*cm->num_ref_filters)); |
355 | 285 | } |
356 | | |
357 | 2.36k | void free_frame_filter_dictionary(AV2_COMMON *cm) { |
358 | 2.36k | avm_free(cm->frame_filter_dictionary); |
359 | 2.36k | avm_free(cm->translated_pcwiener_filters); |
360 | 2.36k | avm_free(cm->num_ref_filters); |
361 | 2.36k | cm->frame_filter_dictionary = NULL; |
362 | 2.36k | cm->translated_pcwiener_filters = NULL; |
363 | 2.36k | cm->num_ref_filters = NULL; |
364 | 2.36k | cm->translation_done = 0; |
365 | 2.36k | cm->frame_filter_dictionary_stride = 0; |
366 | 2.36k | } |
367 | | |
368 | | // TODO: Refactor so that this gets called only once during encoding/decoding. |
369 | | // Useful when using pre-trained filters (with different config and precision) |
370 | | // to predict transmitetd filters to reduce side-information. |
371 | 285 | void translate_pcwiener_filters_to_wienerns(AV2_COMMON *cm) { |
372 | 285 | if (cm->translation_done) { |
373 | 0 | return; |
374 | 0 | } |
375 | 285 | const int base_qindex = cm->quant_params.base_qindex; |
376 | 285 | const int is_uv = 0; |
377 | 285 | const WienernsFilterParameters *nsfilter_params = |
378 | 285 | get_wienerns_parameters(base_qindex, is_uv); |
379 | 285 | assert(nsfilter_params->ncoeffs <= MAX_NUM_DICTIONARY_TAPS); |
380 | 285 | const int num_feat = nsfilter_params->ncoeffs; |
381 | 285 | const int set_index = 0; // get_filter_set_index(base_qindex, qindex_offset); |
382 | | |
383 | 285 | const int num_pc_wiener_filters = NUM_PC_WIENER_FILTERS; |
384 | 285 | const int(*wienerns_coeffs)[WIENERNS_COEFCFG_LEN] = nsfilter_params->coeffs; |
385 | 285 | const int16_t(*pcwiener_filters_luma)[NUM_PC_WIENER_TAPS_LUMA] = |
386 | 285 | get_filter_set(set_index); |
387 | 285 | const int precision_diff = |
388 | 285 | PC_WIENER_PREC_FILTER - nsfilter_params->nsfilter_config.prec_bits; |
389 | 285 | assert(precision_diff >= 0); |
390 | | |
391 | 18.5k | for (int pc_wiener_cnt = 0; pc_wiener_cnt < num_pc_wiener_filters; |
392 | 18.2k | ++pc_wiener_cnt) { |
393 | 18.2k | int filter_index = pc_wiener_cnt; |
394 | 18.2k | const int16_t *pcwiener_filter = pcwiener_filters_luma[filter_index]; |
395 | | |
396 | 18.2k | const int dict_index = pc_wiener_cnt; |
397 | | |
398 | 18.2k | assert(cm->translated_pcwiener_filters != NULL); |
399 | 237k | for (int i = 0; i < AVMMIN(num_feat, NUM_PC_WIENER_TAPS_LUMA - 1); ++i) { |
400 | 218k | const int16_t scaled_tap = ROUND_POWER_OF_TWO_SIGNED( |
401 | 218k | pcwiener_filter[i], precision_diff); // Assuming no translation |
402 | | // pcwiener_filter[tap_translator[i]], precision_diff); // deprecated |
403 | 218k | cm->translated_pcwiener_filters[dict_index * MAX_NUM_DICTIONARY_TAPS + |
404 | 218k | i] = |
405 | 218k | clip_to_wienerns_range(scaled_tap, |
406 | 218k | wienerns_coeffs[i][WIENERNS_MIN_ID], |
407 | 218k | (1 << wienerns_coeffs[i][WIENERNS_BIT_ID])); |
408 | 218k | } |
409 | 18.2k | } |
410 | 285 | cm->translation_done = 1; |
411 | 285 | } |
412 | | |
413 | | static inline int num_sampled_pc_wiener_filters(int plane, int num_ref_filters, |
414 | 19.5k | int num_classes, int nopcw) { |
415 | 19.5k | if (plane != AVM_PLANE_Y) return 0; |
416 | 17.8k | if (nopcw) return 0; |
417 | 17.7k | return AVMMIN( |
418 | 17.8k | AVMMAX(max_num_base_filters(num_classes, 0) - num_ref_filters, 0), |
419 | 17.8k | NUM_PC_WIENER_FILTERS); |
420 | 17.8k | } |
421 | | |
422 | | void set_group_counts(int plane, int num_classes, int num_ref_frames, |
423 | 9.76k | int *group_counts, int nopcw) { |
424 | 9.76k | int total_slots = num_dictionary_slots(num_classes, nopcw); |
425 | 9.76k | (void)total_slots; |
426 | 9.76k | group_counts[0] = num_classes; |
427 | 9.76k | total_slots -= group_counts[0]; |
428 | 9.76k | assert(total_slots >= 0); |
429 | 9.76k | group_counts[1] = num_ref_frames; |
430 | 9.76k | total_slots -= group_counts[1]; |
431 | 9.76k | assert(total_slots >= 0); |
432 | 9.76k | group_counts[2] = |
433 | 9.76k | num_sampled_pc_wiener_filters(plane, num_ref_frames, num_classes, nopcw); |
434 | 9.76k | } |
435 | | |
436 | | int set_frame_filter_dictionary(int plane, const AV2_COMMON *cm, |
437 | | int num_classes, |
438 | | int16_t *frame_filter_dictionary, |
439 | 9.76k | int dict_stride) { |
440 | 9.76k | assert(frame_filter_dictionary != NULL); |
441 | 9.76k | assert(dict_stride > 0); |
442 | 9.76k | const int base_qindex = cm->quant_params.base_qindex; |
443 | 9.76k | const int is_uv = plane > 0; |
444 | 9.76k | const WienernsFilterParameters *nsfilter_params = |
445 | 9.76k | get_wienerns_parameters(base_qindex, is_uv); |
446 | | |
447 | 9.76k | const int nopcw = disable_pcwiener_filters_in_framefilters(&cm->seq_params); |
448 | 9.76k | if (!nopcw) assert(nsfilter_params->ncoeffs <= MAX_NUM_DICTIONARY_TAPS); |
449 | 9.76k | const int num_feat = nsfilter_params->ncoeffs; |
450 | | |
451 | 9.76k | memset(frame_filter_dictionary, 0, |
452 | 9.76k | max_dictionary_size(nopcw) * sizeof(*frame_filter_dictionary)); |
453 | 9.76k | const int max_predictors = num_dictionary_slots(num_classes, nopcw); |
454 | | |
455 | | // Filters prior to ref_filter_offset are all zeros via calloc. -------------- |
456 | 9.76k | const int ref_filter_offset = reference_filters_begin(num_classes); |
457 | | // --------------------------------------------------------------------------- |
458 | | |
459 | | // Copy available reference filters to the dictionary. ----------------------- |
460 | 9.76k | int num_ref_filters = 0; |
461 | 9.76k | const int min_pc_wiener = plane == AVM_PLANE_Y ? (nopcw ? 0 : 16) : 0; |
462 | 9.76k | assert(min_pc_wiener <= NUM_PC_WIENER_FILTERS); |
463 | 9.76k | const int allowed_num_base_filters = |
464 | 9.76k | max_num_base_filters(num_classes, nopcw) - min_pc_wiener; |
465 | 9.76k | assert(allowed_num_base_filters >= 0); |
466 | 9.76k | assert(allowed_num_base_filters < max_predictors); |
467 | 9.76k | const int num_ref_frames = (frame_is_intra_only(cm) || frame_is_sframe(cm)) |
468 | 9.76k | ? 0 |
469 | 9.76k | : cm->ref_frames_info.num_total_refs; |
470 | 9.76k | for (int ref_idx = 0; ref_idx < num_ref_frames; ref_idx++) { |
471 | 0 | const RefCntBuffer *ref_frame_buf = get_ref_frame_buf(cm, ref_idx); |
472 | 0 | if (ref_frame_buf == NULL) { |
473 | 0 | assert(0); |
474 | 0 | continue; |
475 | 0 | } |
476 | 0 | if (ref_frame_buf->is_restricted) continue; |
477 | 0 | int planes_to_check[2] = { plane, -1 }; |
478 | 0 | int num_planes_to_check = 1; |
479 | 0 | const int mix_planes = 1; |
480 | 0 | if (plane != AVM_PLANE_Y && mix_planes) { |
481 | 0 | num_planes_to_check = 2; |
482 | 0 | planes_to_check[1] = (plane == AVM_PLANE_U) ? AVM_PLANE_V : AVM_PLANE_U; |
483 | 0 | } |
484 | 0 | for (int chk = 0; chk < num_planes_to_check; ++chk) { |
485 | 0 | const int p = planes_to_check[chk]; |
486 | 0 | RestorationInfo rsi = ref_frame_buf->rst_info[p]; |
487 | 0 | if (rsi.frame_filters_on) { |
488 | 0 | for (int c_id = 0; c_id < rsi.num_filter_classes; ++c_id) { |
489 | 0 | if (num_ref_filters >= allowed_num_base_filters) break; |
490 | | |
491 | 0 | int16_t *match_filter = |
492 | 0 | frame_filter_dictionary + |
493 | 0 | (num_ref_filters + ref_filter_offset) * dict_stride; |
494 | 0 | const int16_t *wienerns_filter = |
495 | 0 | const_nsfilter_taps(&rsi.frame_filters, c_id); |
496 | 0 | for (int i = 0; i < num_feat; ++i) { |
497 | 0 | match_filter[i] = wienerns_filter[i]; |
498 | 0 | } |
499 | 0 | ++num_ref_filters; |
500 | 0 | } |
501 | 0 | } |
502 | 0 | } |
503 | 0 | } |
504 | | // --------------------------------------------------------------------------- |
505 | | |
506 | | // Sample from the pc-wiener filters for the remaining allowed slots. -------- |
507 | 9.76k | const int shuffled_index[] = { 16, 7, 58, 21, 12, 61, 26, 38, 18, 30, 50, |
508 | 9.76k | 45, 23, 49, 43, 62, 42, 54, 27, 36, 17, 44, |
509 | 9.76k | 32, 34, 4, 24, 52, 31, 37, 11, 33, 19, 35, |
510 | 9.76k | 6, 22, 53, 63, 25, 41, 47, 1, 59, 0, 28, |
511 | 9.76k | 40, 55, 48, 8, 5, 51, 9, 46, 56, 60, 15, |
512 | 9.76k | 2, 13, 14, 57, 29, 3, 20, 39, 10 }; |
513 | 9.76k | const int num_pc_wiener_filters = |
514 | 9.76k | num_sampled_pc_wiener_filters(plane, num_ref_filters, num_classes, nopcw); |
515 | 9.76k | assert(num_pc_wiener_filters >= 0 && |
516 | 9.76k | num_pc_wiener_filters <= NUM_PC_WIENER_FILTERS); |
517 | | |
518 | 9.76k | assert(cm->translated_pcwiener_filters != NULL); |
519 | 9.76k | assert(cm->translation_done); |
520 | 492k | for (int pc_wiener_cnt = 0; pc_wiener_cnt < num_pc_wiener_filters; |
521 | 482k | ++pc_wiener_cnt) { |
522 | 482k | int filter_index = shuffled_index[pc_wiener_cnt]; |
523 | 482k | assert(filter_index < NUM_PC_WIENER_FILTERS); |
524 | | |
525 | 482k | const int16_t *pcwiener_filter = cm->translated_pcwiener_filters + |
526 | 482k | filter_index * MAX_NUM_DICTIONARY_TAPS; |
527 | | |
528 | 482k | const int dict_index = ref_filter_offset + num_ref_filters + pc_wiener_cnt; |
529 | 482k | assert(dict_index < max_predictors); |
530 | 482k | if (dict_index >= max_predictors) { |
531 | 0 | break; |
532 | 0 | } |
533 | | |
534 | 482k | int16_t *match_filter = frame_filter_dictionary + dict_index * dict_stride; |
535 | 8.20M | for (int i = 0; i < num_feat; ++i) { |
536 | 7.72M | match_filter[i] = pcwiener_filter[i]; |
537 | 7.72M | } |
538 | 482k | } |
539 | | // --------------------------------------------------------------------------- |
540 | | |
541 | | // One or more match filters are all zeros via calloc. ----------------------- |
542 | | // --------------------------------------------------------------------------- |
543 | 9.76k | return num_ref_filters; |
544 | 9.76k | } |
545 | | |
546 | | void add_filter_to_dictionary(const WienerNonsepInfo *filter, int class_id, |
547 | | const WienernsFilterParameters *nsfilter_params, |
548 | | int16_t *frame_filter_dictionary, int dict_stride, |
549 | 78.7k | int nopcw) { |
550 | 78.7k | (void)nopcw; |
551 | 78.7k | assert(frame_filter_dictionary != NULL); |
552 | 78.7k | assert(dict_stride > 0); |
553 | 78.7k | if (class_id == filter->num_classes - 1) return; |
554 | 75.8k | const int filter_index = prev_filters_begin(filter->num_classes) + class_id; |
555 | 75.8k | assert(filter_index < num_dictionary_slots(filter->num_classes, nopcw)); |
556 | 75.8k | int16_t *match_filter = frame_filter_dictionary + filter_index * dict_stride; |
557 | 75.8k | const int16_t *wienerns_filter = const_nsfilter_taps(filter, class_id); |
558 | 75.8k | const int num_feat = nsfilter_params->ncoeffs; |
559 | 1.28M | for (int i = 0; i < num_feat; ++i) { |
560 | 1.21M | match_filter[i] = wienerns_filter[i]; |
561 | 1.21M | } |
562 | 75.8k | } |
563 | | |
564 | 2.12k | void av2_alloc_txk_skip_array(CommonModeInfoParams *mi_params, AV2_COMMON *cm) { |
565 | | // Allocate based on the MIN_TX_SIZE, which is a 4x4 block. |
566 | 2.12k | (void)cm; |
567 | 8.49k | for (int plane = 0; plane < MAX_MB_PLANE; plane++) { |
568 | 6.36k | int w = mi_params->mi_cols << MI_SIZE_LOG2; |
569 | 6.36k | int h = mi_params->mi_rows << MI_SIZE_LOG2; |
570 | 6.36k | w = ((w + MAX_SB_SIZE - 1) >> MAX_SB_SIZE_LOG2) << MAX_SB_SIZE_LOG2; |
571 | 6.36k | h = ((h + MAX_SB_SIZE - 1) >> MAX_SB_SIZE_LOG2) << MAX_SB_SIZE_LOG2; |
572 | 6.36k | int stride = (w + MIN_TX_SIZE - 1) >> MIN_TX_SIZE_LOG2; |
573 | 6.36k | int rows = (h + MIN_TX_SIZE - 1) >> MIN_TX_SIZE_LOG2; |
574 | 6.36k | mi_params->tx_skip[plane] = avm_calloc(rows * stride, sizeof(uint8_t)); |
575 | 6.36k | mi_params->tx_skip_buf_size[plane] = rows * stride; |
576 | 6.36k | mi_params->tx_skip_stride[plane] = stride; |
577 | 6.36k | } |
578 | | #ifndef NDEBUG |
579 | | av2_reset_txk_skip_array(cm); |
580 | | #endif // NDEBUG |
581 | 2.12k | } |
582 | | |
583 | | void av2_set_txk_skip_array_stride(CommonModeInfoParams *mi_params, |
584 | 140 | AV2_COMMON *cm) { |
585 | 140 | (void)cm; |
586 | 560 | for (int plane = 0; plane < MAX_MB_PLANE; plane++) { |
587 | 420 | int w = mi_params->mi_cols << MI_SIZE_LOG2; |
588 | 420 | int h = mi_params->mi_rows << MI_SIZE_LOG2; |
589 | 420 | w = ((w + MAX_SB_SIZE - 1) >> MAX_SB_SIZE_LOG2) << MAX_SB_SIZE_LOG2; |
590 | 420 | h = ((h + MAX_SB_SIZE - 1) >> MAX_SB_SIZE_LOG2) << MAX_SB_SIZE_LOG2; |
591 | 420 | int stride = (w + MIN_TX_SIZE - 1) >> MIN_TX_SIZE_LOG2; |
592 | 420 | int rows = (h + MIN_TX_SIZE - 1) >> MIN_TX_SIZE_LOG2; |
593 | 420 | if (rows * stride > (int)mi_params->tx_skip_buf_size[plane]) { |
594 | 0 | avm_free(mi_params->tx_skip[plane]); |
595 | 0 | mi_params->tx_skip[plane] = avm_calloc(rows * stride, sizeof(uint8_t)); |
596 | 0 | mi_params->tx_skip_buf_size[plane] = rows * stride; |
597 | 0 | } |
598 | 420 | mi_params->tx_skip_stride[plane] = stride; |
599 | 420 | } |
600 | 140 | } |
601 | | |
602 | 4.48k | void av2_dealloc_txk_skip_array(CommonModeInfoParams *mi_params) { |
603 | 17.9k | for (int plane = 0; plane < MAX_MB_PLANE; plane++) { |
604 | 13.4k | avm_free(mi_params->tx_skip[plane]); |
605 | 13.4k | mi_params->tx_skip[plane] = NULL; |
606 | 13.4k | } |
607 | 4.48k | } |
608 | | |
609 | 0 | void av2_reset_txk_skip_array(AV2_COMMON *cm) { |
610 | | // Allocate based on the MIN_TX_SIZE, which is a 4x4 block. |
611 | 0 | for (int plane = 0; plane < MAX_MB_PLANE; plane++) { |
612 | 0 | int h = cm->mi_params.mi_rows << MI_SIZE_LOG2; |
613 | 0 | h = ((h + MAX_SB_SIZE - 1) >> MAX_SB_SIZE_LOG2) << MAX_SB_SIZE_LOG2; |
614 | 0 | h >>= ((plane == 0) ? 0 : cm->seq_params.subsampling_y); |
615 | 0 | int stride = cm->mi_params.tx_skip_stride[plane]; |
616 | 0 | int rows = (h + MIN_TX_SIZE - 1) >> MIN_TX_SIZE_LOG2; |
617 | 0 | memset(cm->mi_params.tx_skip[plane], ILLEGAL_TXK_SKIP_VALUE, rows * stride); |
618 | 0 | } |
619 | 0 | } |
620 | | |
621 | 6.67k | void av2_reset_txk_skip_array_using_mi_params(CommonModeInfoParams *mi_params) { |
622 | 26.7k | for (int plane = 0; plane < MAX_MB_PLANE; plane++) { |
623 | 20.0k | memset(mi_params->tx_skip[plane], ILLEGAL_TXK_SKIP_VALUE, |
624 | 20.0k | mi_params->tx_skip_buf_size[plane]); |
625 | 20.0k | } |
626 | 6.67k | } |
627 | | |
628 | | void av2_init_txk_skip_array(const AV2_COMMON *cm, int mi_row, int mi_col, |
629 | | BLOCK_SIZE bsize, uint8_t value, |
630 | | TREE_TYPE tree_type, |
631 | | const CHROMA_REF_INFO *chroma_ref_info, |
632 | 1.18M | int plane_start, int plane_end) { |
633 | 1.18M | const bool is_chroma_ref = tree_type == SHARED_PART |
634 | 1.18M | ? chroma_ref_info->is_chroma_ref |
635 | 1.18M | : tree_type == LUMA_PART ? 0 |
636 | 507k | : 1; |
637 | 3.69M | for (int plane = plane_start; plane < plane_end; plane++) { |
638 | 2.59M | if (plane && !is_chroma_ref) { |
639 | 82.8k | break; |
640 | 82.8k | } |
641 | 2.51M | const int plane_mi_row = |
642 | 2.51M | plane ? chroma_ref_info->mi_row_chroma_base : mi_row; |
643 | 2.51M | const int plane_mi_col = |
644 | 2.51M | plane ? chroma_ref_info->mi_col_chroma_base : mi_col; |
645 | 2.51M | const BLOCK_SIZE bsize_base = (tree_type == SHARED_PART && plane) |
646 | 2.51M | ? chroma_ref_info->bsize_base |
647 | 2.51M | : bsize; |
648 | 2.51M | int stride = cm->mi_params.tx_skip_stride[plane]; |
649 | 2.51M | int x = (plane_mi_col << MI_SIZE_LOG2) >> |
650 | 2.51M | ((plane == 0) ? 0 : cm->seq_params.subsampling_x); |
651 | 2.51M | int y = (plane_mi_row << MI_SIZE_LOG2) >> |
652 | 2.51M | ((plane == 0) ? 0 : cm->seq_params.subsampling_y); |
653 | 2.51M | int row = y >> MIN_TX_SIZE_LOG2; |
654 | 2.51M | int col = x >> MIN_TX_SIZE_LOG2; |
655 | 2.51M | int blk_w = block_size_wide[bsize_base] >> |
656 | 2.51M | ((plane == 0) ? 0 : cm->seq_params.subsampling_x); |
657 | 2.51M | int blk_h = block_size_high[bsize_base] >> |
658 | 2.51M | ((plane == 0) ? 0 : cm->seq_params.subsampling_y); |
659 | 2.51M | blk_w >>= MIN_TX_SIZE_LOG2; |
660 | 2.51M | blk_h >>= MIN_TX_SIZE_LOG2; |
661 | | |
662 | 2.51M | if (plane && (blk_w == 0 || blk_h == 0) && is_chroma_ref) { |
663 | 450 | blk_w = blk_w == 0 ? 1 : blk_w; |
664 | 450 | blk_h = blk_h == 0 ? 1 : blk_h; |
665 | 450 | } |
666 | | |
667 | 15.4M | for (int r = 0; r < blk_h; r++) { |
668 | 127M | for (int c = 0; c < blk_w; c++) { |
669 | 114M | uint32_t idx = (row + r) * stride + col + c; |
670 | 114M | assert(idx < cm->mi_params.tx_skip_buf_size[plane]); |
671 | 114M | cm->mi_params.tx_skip[plane][idx] = value; |
672 | 114M | } |
673 | 12.9M | } |
674 | 2.51M | } |
675 | 1.18M | } |
676 | | |
677 | | void av2_update_txk_skip_array(const AV2_COMMON *cm, int mi_row, int mi_col, |
678 | | TREE_TYPE tree_type, |
679 | | const CHROMA_REF_INFO *chroma_ref_info, |
680 | | int plane, int blk_row, int blk_col, |
681 | 2.56M | TX_SIZE tx_size) { |
682 | 2.56M | blk_row *= 4; |
683 | 2.56M | blk_col *= 4; |
684 | 2.56M | mi_row = (tree_type == SHARED_PART && plane) |
685 | 2.56M | ? chroma_ref_info->mi_row_chroma_base |
686 | 2.56M | : mi_row; |
687 | 2.56M | mi_col = (tree_type == SHARED_PART && plane) |
688 | 2.56M | ? chroma_ref_info->mi_col_chroma_base |
689 | 2.56M | : mi_col; |
690 | 2.56M | int stride = cm->mi_params.tx_skip_stride[plane]; |
691 | 2.56M | int tx_w = tx_size_wide[tx_size]; |
692 | 2.56M | int tx_h = tx_size_high[tx_size]; |
693 | 2.56M | int cols = tx_w >> MIN_TX_SIZE_LOG2; |
694 | 2.56M | int rows = tx_h >> MIN_TX_SIZE_LOG2; |
695 | 2.56M | int x = (mi_col << MI_SIZE_LOG2) >> |
696 | 2.56M | ((plane == 0) ? 0 : cm->seq_params.subsampling_x); |
697 | 2.56M | int y = (mi_row << MI_SIZE_LOG2) >> |
698 | 2.56M | ((plane == 0) ? 0 : cm->seq_params.subsampling_y); |
699 | 2.56M | x = (x + blk_col) >> MIN_TX_SIZE_LOG2; |
700 | 2.56M | y = (y + blk_row) >> MIN_TX_SIZE_LOG2; |
701 | 13.4M | for (int r = 0; r < rows; r++) { |
702 | 10.8M | uint32_t idx = (y + r) * stride + x; |
703 | 10.8M | assert(idx < cm->mi_params.tx_skip_buf_size[plane]); |
704 | 10.8M | static_assert(sizeof(uint8_t) == sizeof(cm->mi_params.tx_skip[plane][idx]), |
705 | 10.8M | ""); |
706 | 10.8M | memset(&cm->mi_params.tx_skip[plane][idx], 1, |
707 | 10.8M | cols * sizeof(cm->mi_params.tx_skip[plane][idx])); |
708 | 10.8M | } |
709 | 2.56M | } |
710 | | |
711 | | uint8_t av2_get_txk_skip(const AV2_COMMON *cm, int mi_row, int mi_col, |
712 | | TREE_TYPE tree_type, |
713 | | const CHROMA_REF_INFO *chroma_ref_info, int plane, |
714 | 0 | int blk_row, int blk_col) { |
715 | 0 | blk_row *= 4; |
716 | 0 | blk_col *= 4; |
717 | 0 | mi_row = (tree_type == SHARED_PART && plane) |
718 | 0 | ? chroma_ref_info->mi_row_chroma_base |
719 | 0 | : mi_row; |
720 | 0 | mi_col = (tree_type == SHARED_PART && plane) |
721 | 0 | ? chroma_ref_info->mi_col_chroma_base |
722 | 0 | : mi_col; |
723 | 0 | int stride = cm->mi_params.tx_skip_stride[plane]; |
724 | 0 | int x = (mi_col << MI_SIZE_LOG2) >> |
725 | 0 | ((plane == 0) ? 0 : cm->seq_params.subsampling_x); |
726 | 0 | int y = (mi_row << MI_SIZE_LOG2) >> |
727 | 0 | ((plane == 0) ? 0 : cm->seq_params.subsampling_y); |
728 | 0 | x = (x + blk_col) >> MIN_TX_SIZE_LOG2; |
729 | 0 | y = (y + blk_row) >> MIN_TX_SIZE_LOG2; |
730 | 0 | uint32_t idx = y * stride + x; |
731 | 0 | assert(idx < cm->mi_params.tx_skip_buf_size[plane]); |
732 | 0 | assert(cm->mi_params.tx_skip[plane][idx] != ILLEGAL_TXK_SKIP_VALUE); |
733 | 0 | return cm->mi_params.tx_skip[plane][idx]; |
734 | 0 | } |
735 | | |
736 | | void av2_alloc_class_id_array(CommonModeInfoParams *mi_params, AV2_COMMON *cm, |
737 | 2.12k | int height) { |
738 | 2.12k | (void)cm; |
739 | 8.49k | for (int plane = 0; plane < MAX_MB_PLANE; plane++) { |
740 | 6.36k | int w = (mi_params->mi_cols << MI_SIZE_LOG2); |
741 | 6.36k | int h = height; |
742 | 6.36k | w = ((w + MAX_SB_SIZE - 1) >> MAX_SB_SIZE_LOG2) << MAX_SB_SIZE_LOG2; |
743 | 6.36k | h = ((h + MAX_SB_SIZE - 1) >> MAX_SB_SIZE_LOG2) << MAX_SB_SIZE_LOG2; |
744 | 6.36k | int stride = (w + MIN_TX_SIZE - 1) >> MIN_TX_SIZE_LOG2; |
745 | 6.36k | int rows = (h + MIN_TX_SIZE - 1) >> MIN_TX_SIZE_LOG2; |
746 | 6.36k | mi_params->wiener_class_id[plane] = |
747 | 6.36k | avm_calloc(rows * stride, sizeof(uint8_t)); |
748 | 6.36k | mi_params->wiener_class_id_buf_size[plane] = rows * stride; |
749 | 6.36k | mi_params->wiener_class_id_stride[plane] = stride; |
750 | 6.36k | } |
751 | 2.12k | } |
752 | | |
753 | | void av2_set_class_id_array_stride(CommonModeInfoParams *mi_params, |
754 | 140 | AV2_COMMON *cm, int height) { |
755 | 140 | (void)cm; |
756 | 560 | for (int plane = 0; plane < MAX_MB_PLANE; plane++) { |
757 | 420 | int w = (mi_params->mi_cols << MI_SIZE_LOG2); |
758 | 420 | int h = height; |
759 | 420 | w = ((w + MAX_SB_SIZE - 1) >> MAX_SB_SIZE_LOG2) << MAX_SB_SIZE_LOG2; |
760 | 420 | h = ((h + MAX_SB_SIZE - 1) >> MAX_SB_SIZE_LOG2) << MAX_SB_SIZE_LOG2; |
761 | 420 | int stride = (w + MIN_TX_SIZE - 1) >> MIN_TX_SIZE_LOG2; |
762 | 420 | int rows = (h + MIN_TX_SIZE - 1) >> MIN_TX_SIZE_LOG2; |
763 | 420 | if (rows * stride > (int)mi_params->wiener_class_id_buf_size[plane]) { |
764 | 0 | avm_free(mi_params->wiener_class_id[plane]); |
765 | 0 | mi_params->wiener_class_id[plane] = |
766 | 0 | avm_calloc(rows * stride, sizeof(uint8_t)); |
767 | 0 | mi_params->wiener_class_id_buf_size[plane] = rows * stride; |
768 | 0 | } |
769 | 420 | mi_params->wiener_class_id_stride[plane] = stride; |
770 | 420 | } |
771 | 140 | } |
772 | | |
773 | 4.48k | void av2_dealloc_class_id_array(CommonModeInfoParams *mi_params) { |
774 | 17.9k | for (int plane = 0; plane < MAX_MB_PLANE; plane++) { |
775 | 13.4k | avm_free(mi_params->wiener_class_id[plane]); |
776 | | mi_params->wiener_class_id[plane] = NULL; |
777 | 13.4k | } |
778 | 4.48k | } |