/src/libvpx/vp9/encoder/vp9_context_tree.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * Copyright (c) 2014 The WebM project authors. All Rights Reserved. |
3 | | * |
4 | | * Use of this source code is governed by a BSD-style license |
5 | | * that can be found in the LICENSE file in the root of the source |
6 | | * tree. An additional intellectual property rights grant can be found |
7 | | * in the file PATENTS. All contributing project authors may |
8 | | * be found in the AUTHORS file in the root of the source tree. |
9 | | */ |
10 | | |
11 | | #include "vp9/encoder/vp9_context_tree.h" |
12 | | #include "vp9/encoder/vp9_encoder.h" |
13 | | |
14 | | static const BLOCK_SIZE square[] = { |
15 | | BLOCK_8X8, |
16 | | BLOCK_16X16, |
17 | | BLOCK_32X32, |
18 | | BLOCK_64X64, |
19 | | }; |
20 | | |
21 | | static void alloc_mode_context(VP9_COMMON *cm, int num_4x4_blk, |
22 | 1.07M | PICK_MODE_CONTEXT *ctx) { |
23 | 1.07M | const int num_blk = (num_4x4_blk < 4 ? 4 : num_4x4_blk); |
24 | 1.07M | const int num_pix = num_blk << 4; |
25 | 1.07M | int i, k; |
26 | 1.07M | ctx->num_4x4_blk = num_blk; |
27 | | |
28 | 1.07M | CHECK_MEM_ERROR(&cm->error, ctx->zcoeff_blk, |
29 | 1.07M | vpx_calloc(num_blk, sizeof(uint8_t))); |
30 | 4.30M | for (i = 0; i < MAX_MB_PLANE; ++i) { |
31 | 12.9M | for (k = 0; k < 3; ++k) { |
32 | 9.69M | CHECK_MEM_ERROR(&cm->error, ctx->coeff[i][k], |
33 | 9.69M | vpx_memalign(32, num_pix * sizeof(*ctx->coeff[i][k]))); |
34 | 9.69M | CHECK_MEM_ERROR(&cm->error, ctx->qcoeff[i][k], |
35 | 9.69M | vpx_memalign(32, num_pix * sizeof(*ctx->qcoeff[i][k]))); |
36 | 9.69M | CHECK_MEM_ERROR(&cm->error, ctx->dqcoeff[i][k], |
37 | 9.69M | vpx_memalign(32, num_pix * sizeof(*ctx->dqcoeff[i][k]))); |
38 | 9.69M | CHECK_MEM_ERROR(&cm->error, ctx->eobs[i][k], |
39 | 9.69M | vpx_memalign(32, num_blk * sizeof(*ctx->eobs[i][k]))); |
40 | 9.69M | ctx->coeff_pbuf[i][k] = ctx->coeff[i][k]; |
41 | 9.69M | ctx->qcoeff_pbuf[i][k] = ctx->qcoeff[i][k]; |
42 | 9.69M | ctx->dqcoeff_pbuf[i][k] = ctx->dqcoeff[i][k]; |
43 | 9.69M | ctx->eobs_pbuf[i][k] = ctx->eobs[i][k]; |
44 | 9.69M | } |
45 | 3.23M | } |
46 | 1.07M | } |
47 | | |
48 | 1.45M | static void free_mode_context(PICK_MODE_CONTEXT *ctx) { |
49 | 1.45M | int i, k; |
50 | 1.45M | vpx_free(ctx->zcoeff_blk); |
51 | 1.45M | ctx->zcoeff_blk = 0; |
52 | 5.83M | for (i = 0; i < MAX_MB_PLANE; ++i) { |
53 | 17.5M | for (k = 0; k < 3; ++k) { |
54 | 13.1M | vpx_free(ctx->coeff[i][k]); |
55 | 13.1M | ctx->coeff[i][k] = 0; |
56 | 13.1M | vpx_free(ctx->qcoeff[i][k]); |
57 | 13.1M | ctx->qcoeff[i][k] = 0; |
58 | 13.1M | vpx_free(ctx->dqcoeff[i][k]); |
59 | 13.1M | ctx->dqcoeff[i][k] = 0; |
60 | 13.1M | vpx_free(ctx->eobs[i][k]); |
61 | 13.1M | ctx->eobs[i][k] = 0; |
62 | 13.1M | } |
63 | 4.37M | } |
64 | 1.45M | } |
65 | | |
66 | | static void alloc_tree_contexts(VP9_COMMON *cm, PC_TREE *tree, |
67 | 253k | int num_4x4_blk) { |
68 | 253k | alloc_mode_context(cm, num_4x4_blk, &tree->none); |
69 | 253k | alloc_mode_context(cm, num_4x4_blk / 2, &tree->horizontal[0]); |
70 | 253k | alloc_mode_context(cm, num_4x4_blk / 2, &tree->vertical[0]); |
71 | | |
72 | 253k | if (num_4x4_blk > 4) { |
73 | 62.6k | alloc_mode_context(cm, num_4x4_blk / 2, &tree->horizontal[1]); |
74 | 62.6k | alloc_mode_context(cm, num_4x4_blk / 2, &tree->vertical[1]); |
75 | 190k | } else { |
76 | 190k | memset(&tree->horizontal[1], 0, sizeof(tree->horizontal[1])); |
77 | 190k | memset(&tree->vertical[1], 0, sizeof(tree->vertical[1])); |
78 | 190k | } |
79 | 253k | } |
80 | | |
81 | 253k | static void free_tree_contexts(PC_TREE *tree) { |
82 | 253k | free_mode_context(&tree->none); |
83 | 253k | free_mode_context(&tree->horizontal[0]); |
84 | 253k | free_mode_context(&tree->horizontal[1]); |
85 | 253k | free_mode_context(&tree->vertical[0]); |
86 | 253k | free_mode_context(&tree->vertical[1]); |
87 | 253k | } |
88 | | |
89 | | // This function sets up a tree of contexts such that at each square |
90 | | // partition level. There are contexts for none, horizontal, vertical, and |
91 | | // split. Along with a block_size value and a selected block_size which |
92 | | // represents the state of our search. |
93 | 2.98k | void vp9_setup_pc_tree(VP9_COMMON *cm, ThreadData *td) { |
94 | 2.98k | int i, j; |
95 | 2.98k | const int leaf_nodes = 64; |
96 | 2.98k | const int tree_nodes = 64 + 16 + 4 + 1; |
97 | 2.98k | int pc_tree_index = 0; |
98 | 2.98k | PC_TREE *this_pc; |
99 | 2.98k | PICK_MODE_CONTEXT *this_leaf; |
100 | 2.98k | int square_index = 1; |
101 | 2.98k | int nodes; |
102 | | |
103 | 2.98k | vpx_free(td->leaf_tree); |
104 | 2.98k | CHECK_MEM_ERROR(&cm->error, td->leaf_tree, |
105 | 2.98k | vpx_calloc(leaf_nodes, sizeof(*td->leaf_tree))); |
106 | 2.98k | vpx_free(td->pc_tree); |
107 | 2.98k | CHECK_MEM_ERROR(&cm->error, td->pc_tree, |
108 | 2.98k | vpx_calloc(tree_nodes, sizeof(*td->pc_tree))); |
109 | | |
110 | 2.98k | this_pc = &td->pc_tree[0]; |
111 | 2.98k | this_leaf = &td->leaf_tree[0]; |
112 | | |
113 | | // 4x4 blocks smaller than 8x8 but in the same 8x8 block share the same |
114 | | // context so we only need to allocate 1 for each 8x8 block. |
115 | 193k | for (i = 0; i < leaf_nodes; ++i) alloc_mode_context(cm, 1, &td->leaf_tree[i]); |
116 | | |
117 | | // Sets up all the leaf nodes in the tree. |
118 | 193k | for (pc_tree_index = 0; pc_tree_index < leaf_nodes; ++pc_tree_index) { |
119 | 190k | PC_TREE *const tree = &td->pc_tree[pc_tree_index]; |
120 | 190k | tree->block_size = square[0]; |
121 | 190k | alloc_tree_contexts(cm, tree, 4); |
122 | 190k | tree->u.leaf_split[0] = this_leaf++; |
123 | 763k | for (j = 1; j < 4; j++) tree->u.leaf_split[j] = tree->u.leaf_split[0]; |
124 | 190k | } |
125 | | |
126 | | // Each node has 4 leaf nodes, fill each block_size level of the tree |
127 | | // from leafs to the root. |
128 | 11.9k | for (nodes = 16; nodes > 0; nodes >>= 2) { |
129 | 71.5k | for (i = 0; i < nodes; ++i) { |
130 | 62.6k | PC_TREE *const tree = &td->pc_tree[pc_tree_index]; |
131 | 62.6k | alloc_tree_contexts(cm, tree, 4 << (2 * square_index)); |
132 | 62.6k | tree->block_size = square[square_index]; |
133 | 313k | for (j = 0; j < 4; j++) tree->u.split[j] = this_pc++; |
134 | 62.6k | ++pc_tree_index; |
135 | 62.6k | } |
136 | 8.94k | ++square_index; |
137 | 8.94k | } |
138 | 2.98k | td->pc_root = &td->pc_tree[tree_nodes - 1]; |
139 | 2.98k | td->pc_root[0].none.best_mode_index = 2; |
140 | 2.98k | } |
141 | | |
142 | 2.98k | void vp9_free_pc_tree(ThreadData *td) { |
143 | 2.98k | int i; |
144 | | |
145 | 2.98k | if (td == NULL) return; |
146 | | |
147 | 2.98k | if (td->leaf_tree != NULL) { |
148 | | // Set up all 4x4 mode contexts |
149 | 193k | for (i = 0; i < 64; ++i) free_mode_context(&td->leaf_tree[i]); |
150 | 2.98k | vpx_free(td->leaf_tree); |
151 | 2.98k | td->leaf_tree = NULL; |
152 | 2.98k | } |
153 | | |
154 | 2.98k | if (td->pc_tree != NULL) { |
155 | 2.98k | const int tree_nodes = 64 + 16 + 4 + 1; |
156 | | // Sets up all the leaf nodes in the tree. |
157 | 256k | for (i = 0; i < tree_nodes; ++i) free_tree_contexts(&td->pc_tree[i]); |
158 | 2.98k | vpx_free(td->pc_tree); |
159 | 2.98k | td->pc_tree = NULL; |
160 | 2.98k | } |
161 | 2.98k | } |