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 static const BLOCK_SIZE square[MAX_SB_SIZE_LOG2 - 1] = {
17 BLOCK_4X4, BLOCK_8X8, BLOCK_16X16, BLOCK_32X32, BLOCK_64X64, BLOCK_128X128,
18 };
19
av1_copy_tree_context(PICK_MODE_CONTEXT * dst_ctx,PICK_MODE_CONTEXT * src_ctx)20 void av1_copy_tree_context(PICK_MODE_CONTEXT *dst_ctx,
21 PICK_MODE_CONTEXT *src_ctx) {
22 dst_ctx->mic = src_ctx->mic;
23 dst_ctx->mbmi_ext_best = src_ctx->mbmi_ext_best;
24
25 dst_ctx->num_4x4_blk = src_ctx->num_4x4_blk;
26 dst_ctx->skippable = src_ctx->skippable;
27 #if CONFIG_INTERNAL_STATS
28 dst_ctx->best_mode_index = src_ctx->best_mode_index;
29 #endif // CONFIG_INTERNAL_STATS
30
31 memcpy(dst_ctx->blk_skip, src_ctx->blk_skip,
32 sizeof(uint8_t) * src_ctx->num_4x4_blk);
33 av1_copy_array(dst_ctx->tx_type_map, src_ctx->tx_type_map,
34 src_ctx->num_4x4_blk);
35
36 dst_ctx->hybrid_pred_diff = src_ctx->hybrid_pred_diff;
37 dst_ctx->comp_pred_diff = src_ctx->comp_pred_diff;
38 dst_ctx->single_pred_diff = src_ctx->single_pred_diff;
39
40 dst_ctx->rd_stats = src_ctx->rd_stats;
41 dst_ctx->rd_mode_is_ready = src_ctx->rd_mode_is_ready;
42 }
43
av1_setup_shared_coeff_buffer(AV1_COMMON * cm,PC_TREE_SHARED_BUFFERS * shared_bufs)44 void av1_setup_shared_coeff_buffer(AV1_COMMON *cm,
45 PC_TREE_SHARED_BUFFERS *shared_bufs) {
46 for (int i = 0; i < 3; i++) {
47 const int max_num_pix = MAX_SB_SIZE * MAX_SB_SIZE;
48 CHECK_MEM_ERROR(cm, shared_bufs->coeff_buf[i],
49 aom_memalign(32, max_num_pix * sizeof(tran_low_t)));
50 CHECK_MEM_ERROR(cm, shared_bufs->qcoeff_buf[i],
51 aom_memalign(32, max_num_pix * sizeof(tran_low_t)));
52 CHECK_MEM_ERROR(cm, shared_bufs->dqcoeff_buf[i],
53 aom_memalign(32, max_num_pix * sizeof(tran_low_t)));
54 }
55 }
56
av1_free_shared_coeff_buffer(PC_TREE_SHARED_BUFFERS * shared_bufs)57 void av1_free_shared_coeff_buffer(PC_TREE_SHARED_BUFFERS *shared_bufs) {
58 for (int i = 0; i < 3; i++) {
59 aom_free(shared_bufs->coeff_buf[i]);
60 aom_free(shared_bufs->qcoeff_buf[i]);
61 aom_free(shared_bufs->dqcoeff_buf[i]);
62 shared_bufs->coeff_buf[i] = NULL;
63 shared_bufs->qcoeff_buf[i] = NULL;
64 shared_bufs->dqcoeff_buf[i] = NULL;
65 }
66 }
67
av1_alloc_pmc(const AV1_COMMON * cm,BLOCK_SIZE bsize,PC_TREE_SHARED_BUFFERS * shared_bufs)68 PICK_MODE_CONTEXT *av1_alloc_pmc(const AV1_COMMON *cm, BLOCK_SIZE bsize,
69 PC_TREE_SHARED_BUFFERS *shared_bufs) {
70 PICK_MODE_CONTEXT *ctx = NULL;
71 struct aom_internal_error_info error;
72
73 AOM_CHECK_MEM_ERROR(&error, ctx, aom_calloc(1, sizeof(*ctx)));
74 ctx->rd_mode_is_ready = 0;
75
76 const int num_planes = av1_num_planes(cm);
77 const int num_pix = block_size_wide[bsize] * block_size_high[bsize];
78 const int num_blk = num_pix / 16;
79
80 AOM_CHECK_MEM_ERROR(&error, ctx->blk_skip,
81 aom_calloc(num_blk, sizeof(*ctx->blk_skip)));
82 AOM_CHECK_MEM_ERROR(&error, ctx->tx_type_map,
83 aom_calloc(num_blk, sizeof(*ctx->tx_type_map)));
84 ctx->num_4x4_blk = num_blk;
85
86 for (int i = 0; i < num_planes; ++i) {
87 ctx->coeff[i] = shared_bufs->coeff_buf[i];
88 ctx->qcoeff[i] = shared_bufs->qcoeff_buf[i];
89 ctx->dqcoeff[i] = shared_bufs->dqcoeff_buf[i];
90 AOM_CHECK_MEM_ERROR(&error, ctx->eobs[i],
91 aom_memalign(32, num_blk * sizeof(*ctx->eobs[i])));
92 AOM_CHECK_MEM_ERROR(
93 &error, ctx->txb_entropy_ctx[i],
94 aom_memalign(32, num_blk * sizeof(*ctx->txb_entropy_ctx[i])));
95 }
96
97 if (num_pix <= MAX_PALETTE_SQUARE) {
98 for (int i = 0; i < 2; ++i) {
99 AOM_CHECK_MEM_ERROR(
100 &error, ctx->color_index_map[i],
101 aom_memalign(32, num_pix * sizeof(*ctx->color_index_map[i])));
102 }
103 }
104
105 av1_invalid_rd_stats(&ctx->rd_stats);
106
107 return ctx;
108 }
109
av1_free_pmc(PICK_MODE_CONTEXT * ctx,int num_planes)110 void av1_free_pmc(PICK_MODE_CONTEXT *ctx, int num_planes) {
111 if (ctx == NULL) return;
112
113 aom_free(ctx->blk_skip);
114 ctx->blk_skip = NULL;
115 aom_free(ctx->tx_type_map);
116 for (int i = 0; i < num_planes; ++i) {
117 ctx->coeff[i] = NULL;
118 ctx->qcoeff[i] = NULL;
119 ctx->dqcoeff[i] = NULL;
120 aom_free(ctx->eobs[i]);
121 ctx->eobs[i] = NULL;
122 aom_free(ctx->txb_entropy_ctx[i]);
123 ctx->txb_entropy_ctx[i] = NULL;
124 }
125
126 for (int i = 0; i < 2; ++i) {
127 aom_free(ctx->color_index_map[i]);
128 ctx->color_index_map[i] = NULL;
129 }
130
131 aom_free(ctx);
132 }
133
av1_alloc_pc_tree_node(BLOCK_SIZE bsize)134 PC_TREE *av1_alloc_pc_tree_node(BLOCK_SIZE bsize) {
135 PC_TREE *pc_tree = NULL;
136 struct aom_internal_error_info error;
137
138 AOM_CHECK_MEM_ERROR(&error, pc_tree, aom_calloc(1, sizeof(*pc_tree)));
139
140 pc_tree->partitioning = PARTITION_NONE;
141 pc_tree->block_size = bsize;
142 pc_tree->index = 0;
143
144 pc_tree->none = NULL;
145 for (int i = 0; i < 2; ++i) {
146 pc_tree->horizontal[i] = NULL;
147 pc_tree->vertical[i] = NULL;
148 }
149 for (int i = 0; i < 3; ++i) {
150 pc_tree->horizontala[i] = NULL;
151 pc_tree->horizontalb[i] = NULL;
152 pc_tree->verticala[i] = NULL;
153 pc_tree->verticalb[i] = NULL;
154 }
155 for (int i = 0; i < 4; ++i) {
156 pc_tree->horizontal4[i] = NULL;
157 pc_tree->vertical4[i] = NULL;
158 pc_tree->split[i] = NULL;
159 }
160
161 return pc_tree;
162 }
163
164 #define FREE_PMC_NODE(CTX) \
165 do { \
166 av1_free_pmc(CTX, num_planes); \
167 CTX = NULL; \
168 } while (0)
169
av1_free_pc_tree_recursive(PC_TREE * pc_tree,int num_planes,int keep_best,int keep_none)170 void av1_free_pc_tree_recursive(PC_TREE *pc_tree, int num_planes, int keep_best,
171 int keep_none) {
172 if (pc_tree == NULL) return;
173
174 const PARTITION_TYPE partition = pc_tree->partitioning;
175
176 if (!keep_none && (!keep_best || (partition != PARTITION_NONE)))
177 FREE_PMC_NODE(pc_tree->none);
178
179 for (int i = 0; i < 2; ++i) {
180 if (!keep_best || (partition != PARTITION_HORZ))
181 FREE_PMC_NODE(pc_tree->horizontal[i]);
182 if (!keep_best || (partition != PARTITION_VERT))
183 FREE_PMC_NODE(pc_tree->vertical[i]);
184 }
185 for (int i = 0; i < 3; ++i) {
186 if (!keep_best || (partition != PARTITION_HORZ_A))
187 FREE_PMC_NODE(pc_tree->horizontala[i]);
188 if (!keep_best || (partition != PARTITION_HORZ_B))
189 FREE_PMC_NODE(pc_tree->horizontalb[i]);
190 if (!keep_best || (partition != PARTITION_VERT_A))
191 FREE_PMC_NODE(pc_tree->verticala[i]);
192 if (!keep_best || (partition != PARTITION_VERT_B))
193 FREE_PMC_NODE(pc_tree->verticalb[i]);
194 }
195 for (int i = 0; i < 4; ++i) {
196 if (!keep_best || (partition != PARTITION_HORZ_4))
197 FREE_PMC_NODE(pc_tree->horizontal4[i]);
198 if (!keep_best || (partition != PARTITION_VERT_4))
199 FREE_PMC_NODE(pc_tree->vertical4[i]);
200 }
201
202 if (!keep_best || (partition != PARTITION_SPLIT)) {
203 for (int i = 0; i < 4; ++i) {
204 if (pc_tree->split[i] != NULL) {
205 av1_free_pc_tree_recursive(pc_tree->split[i], num_planes, 0, 0);
206 pc_tree->split[i] = NULL;
207 }
208 }
209 }
210
211 if (!keep_best && !keep_none) aom_free(pc_tree);
212 }
213
get_pc_tree_nodes(const int is_sb_size_128,int stat_generation_stage)214 static AOM_INLINE int get_pc_tree_nodes(const int is_sb_size_128,
215 int stat_generation_stage) {
216 const int tree_nodes_inc = is_sb_size_128 ? 1024 : 0;
217 const int tree_nodes =
218 stat_generation_stage ? 1 : (tree_nodes_inc + 256 + 64 + 16 + 4 + 1);
219 return tree_nodes;
220 }
221
av1_setup_sms_tree(AV1_COMP * const cpi,ThreadData * td)222 void av1_setup_sms_tree(AV1_COMP *const cpi, ThreadData *td) {
223 AV1_COMMON *const cm = &cpi->common;
224 const int stat_generation_stage = is_stat_generation_stage(cpi);
225 const int is_sb_size_128 = cm->seq_params.sb_size == BLOCK_128X128;
226 const int tree_nodes =
227 get_pc_tree_nodes(is_sb_size_128, stat_generation_stage);
228 int sms_tree_index = 0;
229 SIMPLE_MOTION_DATA_TREE *this_sms;
230 int square_index = 1;
231 int nodes;
232
233 aom_free(td->sms_tree);
234 CHECK_MEM_ERROR(cm, td->sms_tree,
235 aom_calloc(tree_nodes, sizeof(*td->sms_tree)));
236 this_sms = &td->sms_tree[0];
237
238 if (!stat_generation_stage) {
239 const int leaf_factor = is_sb_size_128 ? 4 : 1;
240 const int leaf_nodes = 256 * leaf_factor;
241
242 // Sets up all the leaf nodes in the tree.
243 for (sms_tree_index = 0; sms_tree_index < leaf_nodes; ++sms_tree_index) {
244 SIMPLE_MOTION_DATA_TREE *const tree = &td->sms_tree[sms_tree_index];
245 tree->block_size = square[0];
246 }
247
248 // Each node has 4 leaf nodes, fill each block_size level of the tree
249 // from leafs to the root.
250 for (nodes = leaf_nodes >> 2; nodes > 0; nodes >>= 2) {
251 for (int i = 0; i < nodes; ++i) {
252 SIMPLE_MOTION_DATA_TREE *const tree = &td->sms_tree[sms_tree_index];
253 tree->block_size = square[square_index];
254 for (int j = 0; j < 4; j++) tree->split[j] = this_sms++;
255 ++sms_tree_index;
256 }
257 ++square_index;
258 }
259 } else {
260 // Allocation for firstpass/LAP stage
261 // TODO(Mufaddal): refactor square_index to use a common block_size macro
262 // from firstpass.c
263 SIMPLE_MOTION_DATA_TREE *const tree = &td->sms_tree[sms_tree_index];
264 square_index = 2;
265 tree->block_size = square[square_index];
266 }
267
268 // Set up the root node for the largest superblock size
269 td->sms_root = &td->sms_tree[tree_nodes - 1];
270 }
271
av1_free_sms_tree(ThreadData * td)272 void av1_free_sms_tree(ThreadData *td) {
273 if (td->sms_tree != NULL) {
274 aom_free(td->sms_tree);
275 td->sms_tree = NULL;
276 }
277 }
278