/src/aom/av1/encoder/context_tree.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * Copyright (c) 2016, Alliance for Open Media. All rights reserved |
3 | | * |
4 | | * This source code is subject to the terms of the BSD 2 Clause License and |
5 | | * the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License |
6 | | * was not distributed with this source code in the LICENSE file, you can |
7 | | * obtain it at www.aomedia.org/license/software. If the Alliance for Open |
8 | | * Media Patent License 1.0 was not distributed with this source code in the |
9 | | * PATENTS file, you can obtain it at www.aomedia.org/license/patent. |
10 | | */ |
11 | | |
12 | | #include "av1/encoder/context_tree.h" |
13 | | #include "av1/encoder/encoder.h" |
14 | | #include "av1/encoder/rd.h" |
15 | | |
16 | | void av1_copy_tree_context(PICK_MODE_CONTEXT *dst_ctx, |
17 | 0 | PICK_MODE_CONTEXT *src_ctx) { |
18 | 0 | dst_ctx->mic = src_ctx->mic; |
19 | 0 | dst_ctx->mbmi_ext_best = src_ctx->mbmi_ext_best; |
20 | |
|
21 | 0 | dst_ctx->num_4x4_blk = src_ctx->num_4x4_blk; |
22 | 0 | dst_ctx->skippable = src_ctx->skippable; |
23 | | #if CONFIG_INTERNAL_STATS |
24 | | dst_ctx->best_mode_index = src_ctx->best_mode_index; |
25 | | #endif // CONFIG_INTERNAL_STATS |
26 | |
|
27 | 0 | memcpy(dst_ctx->blk_skip, src_ctx->blk_skip, |
28 | 0 | sizeof(uint8_t) * src_ctx->num_4x4_blk); |
29 | 0 | av1_copy_array(dst_ctx->tx_type_map, src_ctx->tx_type_map, |
30 | 0 | src_ctx->num_4x4_blk); |
31 | |
|
32 | 0 | dst_ctx->rd_stats = src_ctx->rd_stats; |
33 | 0 | dst_ctx->rd_mode_is_ready = src_ctx->rd_mode_is_ready; |
34 | 0 | } |
35 | | |
36 | | void av1_setup_shared_coeff_buffer(const SequenceHeader *const seq_params, |
37 | | PC_TREE_SHARED_BUFFERS *shared_bufs, |
38 | 3.35k | struct aom_internal_error_info *error) { |
39 | 3.35k | const int num_planes = seq_params->monochrome ? 1 : MAX_MB_PLANE; |
40 | 3.35k | const int max_sb_square_y = 1 << num_pels_log2_lookup[seq_params->sb_size]; |
41 | 3.35k | const int max_sb_square_uv = max_sb_square_y >> (seq_params->subsampling_x + |
42 | 3.35k | seq_params->subsampling_y); |
43 | 13.4k | for (int i = 0; i < num_planes; i++) { |
44 | 10.0k | const int max_num_pix = |
45 | 10.0k | (i == AOM_PLANE_Y) ? max_sb_square_y : max_sb_square_uv; |
46 | 10.0k | AOM_CHECK_MEM_ERROR(error, shared_bufs->coeff_buf[i], |
47 | 10.0k | aom_memalign(32, max_num_pix * sizeof(tran_low_t))); |
48 | 10.0k | AOM_CHECK_MEM_ERROR(error, shared_bufs->qcoeff_buf[i], |
49 | 10.0k | aom_memalign(32, max_num_pix * sizeof(tran_low_t))); |
50 | 10.0k | AOM_CHECK_MEM_ERROR(error, shared_bufs->dqcoeff_buf[i], |
51 | 10.0k | aom_memalign(32, max_num_pix * sizeof(tran_low_t))); |
52 | 10.0k | } |
53 | 3.35k | } |
54 | | |
55 | 3.35k | void av1_free_shared_coeff_buffer(PC_TREE_SHARED_BUFFERS *shared_bufs) { |
56 | 13.4k | for (int i = 0; i < 3; i++) { |
57 | 10.0k | aom_free(shared_bufs->coeff_buf[i]); |
58 | 10.0k | aom_free(shared_bufs->qcoeff_buf[i]); |
59 | 10.0k | aom_free(shared_bufs->dqcoeff_buf[i]); |
60 | 10.0k | shared_bufs->coeff_buf[i] = NULL; |
61 | 10.0k | shared_bufs->qcoeff_buf[i] = NULL; |
62 | 10.0k | shared_bufs->dqcoeff_buf[i] = NULL; |
63 | 10.0k | } |
64 | 3.35k | } |
65 | | |
66 | | PICK_MODE_CONTEXT *av1_alloc_pmc(const struct AV1_COMP *const cpi, |
67 | | BLOCK_SIZE bsize, |
68 | 167k | PC_TREE_SHARED_BUFFERS *shared_bufs) { |
69 | 167k | PICK_MODE_CONTEXT *ctx = NULL; |
70 | 167k | const AV1_COMMON *const cm = &cpi->common; |
71 | 167k | struct aom_internal_error_info error; |
72 | | |
73 | 167k | AOM_CHECK_MEM_ERROR(&error, ctx, aom_calloc(1, sizeof(*ctx))); |
74 | 167k | ctx->rd_mode_is_ready = 0; |
75 | | |
76 | 167k | const int num_planes = av1_num_planes(cm); |
77 | 167k | const int num_pix = block_size_wide[bsize] * block_size_high[bsize]; |
78 | 167k | const int num_blk = num_pix / 16; |
79 | | |
80 | 167k | AOM_CHECK_MEM_ERROR(&error, ctx->blk_skip, |
81 | 167k | aom_calloc(num_blk, sizeof(*ctx->blk_skip))); |
82 | 167k | AOM_CHECK_MEM_ERROR(&error, ctx->tx_type_map, |
83 | 167k | aom_calloc(num_blk, sizeof(*ctx->tx_type_map))); |
84 | 167k | ctx->num_4x4_blk = num_blk; |
85 | | |
86 | 669k | for (int i = 0; i < num_planes; ++i) { |
87 | 502k | ctx->coeff[i] = shared_bufs->coeff_buf[i]; |
88 | 502k | ctx->qcoeff[i] = shared_bufs->qcoeff_buf[i]; |
89 | 502k | ctx->dqcoeff[i] = shared_bufs->dqcoeff_buf[i]; |
90 | 502k | AOM_CHECK_MEM_ERROR(&error, ctx->eobs[i], |
91 | 502k | aom_memalign(32, num_blk * sizeof(*ctx->eobs[i]))); |
92 | 502k | AOM_CHECK_MEM_ERROR( |
93 | 502k | &error, ctx->txb_entropy_ctx[i], |
94 | 502k | aom_memalign(32, num_blk * sizeof(*ctx->txb_entropy_ctx[i]))); |
95 | 502k | } |
96 | | |
97 | 167k | if (num_pix <= MAX_PALETTE_SQUARE) { |
98 | 502k | for (int i = 0; i < 2; ++i) { |
99 | 335k | if (!cpi->sf.rt_sf.use_nonrd_pick_mode || frame_is_intra_only(cm)) { |
100 | 335k | AOM_CHECK_MEM_ERROR( |
101 | 335k | &error, ctx->color_index_map[i], |
102 | 335k | aom_memalign(32, num_pix * sizeof(*ctx->color_index_map[i]))); |
103 | 18.4E | } else { |
104 | 18.4E | ctx->color_index_map[i] = NULL; |
105 | 18.4E | } |
106 | 334k | } |
107 | 167k | } |
108 | | |
109 | 167k | av1_invalid_rd_stats(&ctx->rd_stats); |
110 | | |
111 | 167k | return ctx; |
112 | 167k | } |
113 | | |
114 | 8.23M | void av1_free_pmc(PICK_MODE_CONTEXT *ctx, int num_planes) { |
115 | 8.23M | if (ctx == NULL) return; |
116 | | |
117 | 167k | aom_free(ctx->blk_skip); |
118 | 167k | ctx->blk_skip = NULL; |
119 | 167k | aom_free(ctx->tx_type_map); |
120 | 669k | for (int i = 0; i < num_planes; ++i) { |
121 | 502k | ctx->coeff[i] = NULL; |
122 | 502k | ctx->qcoeff[i] = NULL; |
123 | 502k | ctx->dqcoeff[i] = NULL; |
124 | 502k | aom_free(ctx->eobs[i]); |
125 | 502k | ctx->eobs[i] = NULL; |
126 | 502k | aom_free(ctx->txb_entropy_ctx[i]); |
127 | 502k | ctx->txb_entropy_ctx[i] = NULL; |
128 | 502k | } |
129 | | |
130 | 502k | for (int i = 0; i < 2; ++i) { |
131 | 335k | if (ctx->color_index_map[i]) { |
132 | 335k | aom_free(ctx->color_index_map[i]); |
133 | 335k | ctx->color_index_map[i] = NULL; |
134 | 335k | } |
135 | 335k | } |
136 | | |
137 | 167k | aom_free(ctx); |
138 | 167k | } |
139 | | |
140 | 257k | PC_TREE *av1_alloc_pc_tree_node(BLOCK_SIZE bsize) { |
141 | 257k | PC_TREE *pc_tree = NULL; |
142 | 257k | struct aom_internal_error_info error; |
143 | | |
144 | 257k | AOM_CHECK_MEM_ERROR(&error, pc_tree, aom_calloc(1, sizeof(*pc_tree))); |
145 | | |
146 | 257k | pc_tree->partitioning = PARTITION_NONE; |
147 | 257k | pc_tree->block_size = bsize; |
148 | 257k | pc_tree->index = 0; |
149 | | |
150 | 257k | pc_tree->none = NULL; |
151 | 771k | for (int i = 0; i < 2; ++i) { |
152 | 514k | pc_tree->horizontal[i] = NULL; |
153 | 514k | pc_tree->vertical[i] = NULL; |
154 | 514k | } |
155 | 1.02M | for (int i = 0; i < 3; ++i) { |
156 | 771k | pc_tree->horizontala[i] = NULL; |
157 | 771k | pc_tree->horizontalb[i] = NULL; |
158 | 771k | pc_tree->verticala[i] = NULL; |
159 | 771k | pc_tree->verticalb[i] = NULL; |
160 | 771k | } |
161 | 1.28M | for (int i = 0; i < 4; ++i) { |
162 | 1.02M | pc_tree->horizontal4[i] = NULL; |
163 | 1.02M | pc_tree->vertical4[i] = NULL; |
164 | 1.02M | pc_tree->split[i] = NULL; |
165 | 1.02M | } |
166 | | |
167 | 257k | return pc_tree; |
168 | 257k | } |
169 | | |
170 | | #define FREE_PMC_NODE(CTX) \ |
171 | 8.23M | do { \ |
172 | 8.23M | av1_free_pmc(CTX, num_planes); \ |
173 | 8.23M | CTX = NULL; \ |
174 | 8.23M | } while (0) |
175 | | |
176 | | void av1_free_pc_tree_recursive(PC_TREE *pc_tree, int num_planes, int keep_best, |
177 | 333k | int keep_none) { |
178 | 333k | if (pc_tree == NULL) return; |
179 | | |
180 | 333k | const PARTITION_TYPE partition = pc_tree->partitioning; |
181 | | |
182 | 333k | if (!keep_none && (!keep_best || (partition != PARTITION_NONE))) |
183 | 257k | FREE_PMC_NODE(pc_tree->none); |
184 | | |
185 | 1.00M | for (int i = 0; i < 2; ++i) { |
186 | 666k | if (!keep_best || (partition != PARTITION_HORZ)) |
187 | 652k | FREE_PMC_NODE(pc_tree->horizontal[i]); |
188 | 666k | if (!keep_best || (partition != PARTITION_VERT)) |
189 | 653k | FREE_PMC_NODE(pc_tree->vertical[i]); |
190 | 666k | } |
191 | 1.33M | for (int i = 0; i < 3; ++i) { |
192 | 1.00M | if (!keep_best || (partition != PARTITION_HORZ_A)) |
193 | 1.00M | FREE_PMC_NODE(pc_tree->horizontala[i]); |
194 | 1.00M | if (!keep_best || (partition != PARTITION_HORZ_B)) |
195 | 1.00M | FREE_PMC_NODE(pc_tree->horizontalb[i]); |
196 | 1.00M | if (!keep_best || (partition != PARTITION_VERT_A)) |
197 | 1.00M | FREE_PMC_NODE(pc_tree->verticala[i]); |
198 | 1.00M | if (!keep_best || (partition != PARTITION_VERT_B)) |
199 | 1.00M | FREE_PMC_NODE(pc_tree->verticalb[i]); |
200 | 1.00M | } |
201 | 1.66M | for (int i = 0; i < 4; ++i) { |
202 | 1.33M | if (!keep_best || (partition != PARTITION_HORZ_4)) |
203 | 1.33M | FREE_PMC_NODE(pc_tree->horizontal4[i]); |
204 | 1.33M | if (!keep_best || (partition != PARTITION_VERT_4)) |
205 | 1.33M | FREE_PMC_NODE(pc_tree->vertical4[i]); |
206 | 1.33M | } |
207 | | |
208 | 333k | if (!keep_best || (partition != PARTITION_SPLIT)) { |
209 | 1.66M | for (int i = 0; i < 4; ++i) { |
210 | 1.33M | if (pc_tree->split[i] != NULL) { |
211 | 245k | av1_free_pc_tree_recursive(pc_tree->split[i], num_planes, 0, 0); |
212 | 245k | pc_tree->split[i] = NULL; |
213 | 245k | } |
214 | 1.33M | } |
215 | 332k | } |
216 | | |
217 | 333k | if (!keep_best && !keep_none) aom_free(pc_tree); |
218 | 333k | } |
219 | | |
220 | 3.35k | void av1_setup_sms_tree(AV1_COMP *const cpi, ThreadData *td) { |
221 | 3.35k | AV1_COMMON *const cm = &cpi->common; |
222 | 3.35k | const int stat_generation_stage = is_stat_generation_stage(cpi); |
223 | 3.35k | const int is_sb_size_128 = cm->seq_params->sb_size == BLOCK_128X128; |
224 | 3.35k | const int tree_nodes = |
225 | 3.35k | av1_get_pc_tree_nodes(is_sb_size_128, stat_generation_stage); |
226 | 3.35k | int sms_tree_index = 0; |
227 | 3.35k | SIMPLE_MOTION_DATA_TREE *this_sms; |
228 | 3.35k | int square_index = 1; |
229 | 3.35k | int nodes; |
230 | | |
231 | 3.35k | aom_free(td->sms_tree); |
232 | 3.35k | CHECK_MEM_ERROR(cm, td->sms_tree, |
233 | 3.35k | aom_calloc(tree_nodes, sizeof(*td->sms_tree))); |
234 | 3.35k | this_sms = &td->sms_tree[0]; |
235 | | |
236 | 3.35k | if (!stat_generation_stage) { |
237 | 3.35k | const int leaf_factor = is_sb_size_128 ? 4 : 1; |
238 | 3.35k | const int leaf_nodes = 256 * leaf_factor; |
239 | | |
240 | | // Sets up all the leaf nodes in the tree. |
241 | 1.83M | for (sms_tree_index = 0; sms_tree_index < leaf_nodes; ++sms_tree_index) { |
242 | 1.82M | SIMPLE_MOTION_DATA_TREE *const tree = &td->sms_tree[sms_tree_index]; |
243 | 1.82M | tree->block_size = square[0]; |
244 | 1.82M | } |
245 | | |
246 | | // Each node has 4 leaf nodes, fill each block_size level of the tree |
247 | | // from leafs to the root. |
248 | 18.0k | for (nodes = leaf_nodes >> 2; nodes > 0; nodes >>= 2) { |
249 | 622k | for (int i = 0; i < nodes; ++i) { |
250 | 608k | SIMPLE_MOTION_DATA_TREE *const tree = &td->sms_tree[sms_tree_index]; |
251 | 608k | tree->block_size = square[square_index]; |
252 | 3.04M | for (int j = 0; j < 4; j++) tree->split[j] = this_sms++; |
253 | 608k | ++sms_tree_index; |
254 | 608k | } |
255 | 14.6k | ++square_index; |
256 | 14.6k | } |
257 | 3.35k | } else { |
258 | | // Allocation for firstpass/LAP stage |
259 | | // TODO(Mufaddal): refactor square_index to use a common block_size macro |
260 | | // from firstpass.c |
261 | 0 | SIMPLE_MOTION_DATA_TREE *const tree = &td->sms_tree[sms_tree_index]; |
262 | 0 | square_index = 2; |
263 | 0 | tree->block_size = square[square_index]; |
264 | 0 | } |
265 | | |
266 | | // Set up the root node for the largest superblock size |
267 | 3.35k | td->sms_root = &td->sms_tree[tree_nodes - 1]; |
268 | 3.35k | } |
269 | | |
270 | 3.35k | void av1_free_sms_tree(ThreadData *td) { |
271 | 3.35k | if (td->sms_tree != NULL) { |
272 | 3.35k | aom_free(td->sms_tree); |
273 | 3.35k | td->sms_tree = NULL; |
274 | 3.35k | } |
275 | 3.35k | } |