/src/libde265/libde265/contextmodel.cc
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * H.265 video codec. |
3 | | * Copyright (c) 2013-2014 struktur AG, Dirk Farin <farin@struktur.de> |
4 | | * |
5 | | * This file is part of libde265. |
6 | | * |
7 | | * libde265 is free software: you can redistribute it and/or modify |
8 | | * it under the terms of the GNU Lesser General Public License as |
9 | | * published by the Free Software Foundation, either version 3 of |
10 | | * the License, or (at your option) any later version. |
11 | | * |
12 | | * libde265 is distributed in the hope that it will be useful, |
13 | | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
14 | | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
15 | | * GNU Lesser General Public License for more details. |
16 | | * |
17 | | * You should have received a copy of the GNU Lesser General Public License |
18 | | * along with libde265. If not, see <http://www.gnu.org/licenses/>. |
19 | | */ |
20 | | |
21 | | #include "slice.h" |
22 | | #include <assert.h> |
23 | | #include <iomanip> |
24 | | #include <sstream> |
25 | | |
26 | | bool D = false; |
27 | | |
28 | | context_model_table::context_model_table() |
29 | | : model(NULL), refcnt(NULL) |
30 | 49.6k | { |
31 | 49.6k | } |
32 | | |
33 | | |
34 | | context_model_table::context_model_table(const context_model_table& src) |
35 | 0 | { |
36 | 0 | if (D) printf("%p c'tor = %p\n",this,&src); |
37 | |
|
38 | 0 | if (src.refcnt) { |
39 | 0 | (*(src.refcnt))++; |
40 | 0 | } |
41 | |
|
42 | 0 | refcnt = src.refcnt; |
43 | 0 | model = src.model; |
44 | 0 | } |
45 | | |
46 | | |
47 | | context_model_table::~context_model_table() |
48 | 50.7k | { |
49 | 50.7k | if (D) printf("%p destructor\n",this); |
50 | | |
51 | 50.7k | if (refcnt) { |
52 | 23.8k | (*refcnt)--; |
53 | 23.8k | if (*refcnt==0) { |
54 | 23.8k | if (D) printf("mfree %p\n",model); |
55 | 23.8k | delete[] model; |
56 | 23.8k | delete refcnt; |
57 | 23.8k | } |
58 | 23.8k | } |
59 | 50.7k | } |
60 | | |
61 | | |
62 | | void context_model_table::init(int initType, int QPY) |
63 | 3.69k | { |
64 | 3.69k | if (D) printf("%p init\n",this); |
65 | | |
66 | 3.69k | decouple_or_alloc_with_empty_data(); |
67 | | |
68 | 3.69k | initialize_CABAC_models(model, initType, QPY); |
69 | 3.69k | } |
70 | | |
71 | | |
72 | | void context_model_table::release() |
73 | 61.9k | { |
74 | 61.9k | if (D) printf("%p release %p\n",this,refcnt); |
75 | | |
76 | 61.9k | if (!refcnt) { return; } |
77 | | |
78 | | // if (*refcnt == 1) { return; } <- keep memory for later, but does not work when we believe that we freed the memory and nulled all references |
79 | | |
80 | 19.8k | (*refcnt)--; |
81 | 19.8k | if (*refcnt==0) { |
82 | 0 | delete[] model; |
83 | 0 | delete refcnt; |
84 | 0 | } |
85 | | |
86 | 19.8k | model = nullptr; |
87 | 19.8k | refcnt= nullptr; |
88 | 19.8k | } |
89 | | |
90 | | |
91 | | void context_model_table::decouple() |
92 | 20.1k | { |
93 | 20.1k | if (D) printf("%p decouple (%p)\n",this,refcnt); |
94 | | |
95 | 20.1k | assert(refcnt); // not necessarily so, but we never use it on an unitialized object |
96 | | |
97 | 20.1k | if (*refcnt > 1) { |
98 | 20.1k | (*refcnt)--; |
99 | | |
100 | 20.1k | context_model* oldModel = model; |
101 | | |
102 | 20.1k | model = new context_model[CONTEXT_MODEL_TABLE_LENGTH]; |
103 | 20.1k | refcnt= new int; |
104 | 20.1k | *refcnt=1; |
105 | | |
106 | 20.1k | memcpy(model,oldModel,sizeof(context_model)*CONTEXT_MODEL_TABLE_LENGTH); |
107 | 20.1k | } |
108 | 20.1k | } |
109 | | |
110 | | |
111 | | context_model_table context_model_table::transfer() |
112 | 0 | { |
113 | 0 | context_model_table newtable; |
114 | 0 | newtable.model = model; |
115 | 0 | newtable.refcnt= refcnt; |
116 | |
|
117 | 0 | model =nullptr; |
118 | 0 | refcnt=nullptr; |
119 | |
|
120 | 0 | return newtable; |
121 | 0 | } |
122 | | |
123 | | |
124 | | context_model_table& context_model_table::operator=(const context_model_table& src) |
125 | 41.0k | { |
126 | 41.0k | if (D) printf("%p assign = %p\n",this,&src); |
127 | | |
128 | | // assert(src.refcnt); // not necessarily so, but we never use it on an unitialized object |
129 | | |
130 | 41.0k | if (!src.refcnt) { |
131 | 994 | release(); |
132 | 994 | return *this; |
133 | 994 | } |
134 | | |
135 | 40.0k | (*(src.refcnt))++; |
136 | | |
137 | 40.0k | release(); |
138 | | |
139 | 40.0k | model = src.model; |
140 | 40.0k | refcnt= src.refcnt; |
141 | | |
142 | 40.0k | return *this; |
143 | 41.0k | } |
144 | | |
145 | | |
146 | | bool context_model_table::operator==(const context_model_table& b) const |
147 | 0 | { |
148 | 0 | if (b.model == model) return true; |
149 | 0 | if (b.model == nullptr || model == nullptr) return false; |
150 | | |
151 | 0 | for (int i=0;i<CONTEXT_MODEL_TABLE_LENGTH;i++) { |
152 | 0 | if (!(b.model[i] == model[i])) return false; |
153 | 0 | } |
154 | | |
155 | 0 | return true; |
156 | 0 | } |
157 | | |
158 | | |
159 | | std::string context_model_table::debug_dump() const |
160 | 0 | { |
161 | 0 | int hash = 0; |
162 | 0 | for (int i=0;i<CONTEXT_MODEL_TABLE_LENGTH;i++) { |
163 | 0 | hash ^= ((i+7)*model[i].state) & 0xFFFF; |
164 | 0 | } |
165 | |
|
166 | 0 | std::stringstream sstr; |
167 | 0 | sstr << std::hex << hash; |
168 | 0 | return sstr.str(); |
169 | 0 | } |
170 | | |
171 | | |
172 | | void context_model_table::decouple_or_alloc_with_empty_data() |
173 | 3.71k | { |
174 | 3.71k | if (refcnt && *refcnt==1) { return; } |
175 | | |
176 | 3.71k | if (refcnt) { |
177 | 0 | assert(*refcnt>1); |
178 | 0 | (*refcnt)--; |
179 | 0 | } |
180 | | |
181 | 3.71k | if (D) printf("%p (alloc)\n",this); |
182 | | |
183 | 3.71k | model = new context_model[CONTEXT_MODEL_TABLE_LENGTH]; |
184 | 3.71k | refcnt= new int; |
185 | 3.71k | *refcnt=1; |
186 | 3.71k | } |
187 | | |
188 | | |
189 | | |
190 | | |
191 | | |
192 | | |
193 | | static void set_initValue(int SliceQPY, |
194 | | context_model* model, int initValue, int nContexts) |
195 | 528k | { |
196 | 528k | int slopeIdx = initValue >> 4; |
197 | 528k | int intersecIdx = initValue & 0xF; |
198 | 528k | int m = slopeIdx*5 - 45; |
199 | 528k | int n = (intersecIdx<<3) - 16; |
200 | 528k | int preCtxState = Clip3(1,126, ((m*Clip3(0,51, SliceQPY))>>4)+n); |
201 | | |
202 | | // logtrace(LogSlice,"QP=%d slopeIdx=%d intersecIdx=%d m=%d n=%d\n",SliceQPY,slopeIdx,intersecIdx,m,n); |
203 | | |
204 | 1.08M | for (int i=0;i<nContexts;i++) { |
205 | 557k | model[i].MPSbit=(preCtxState<=63) ? 0 : 1; |
206 | 557k | model[i].state = model[i].MPSbit ? (preCtxState-64) : (63-preCtxState); |
207 | | |
208 | | // model state will always be between [0;62] |
209 | | |
210 | 557k | assert(model[i].state <= 62); |
211 | 557k | } |
212 | 528k | } |
213 | | |
214 | | |
215 | | static const int initValue_split_cu_flag[3][3] = { |
216 | | { 139,141,157 }, |
217 | | { 107,139,126 }, |
218 | | { 107,139,126 }, |
219 | | }; |
220 | | static const int initValue_cu_skip_flag[2][3] = { |
221 | | { 197,185,201 }, |
222 | | { 197,185,201 }, |
223 | | }; |
224 | | static const int initValue_part_mode[9] = { 184,154,139, 154,154,154, 139,154,154 }; |
225 | | static const int initValue_prev_intra_luma_pred_flag[3] = { 184,154,183 }; |
226 | | static const int initValue_intra_chroma_pred_mode[3] = { 63,152,152 }; |
227 | | static const int initValue_cbf_luma[4] = { 111,141,153,111 }; |
228 | | static const int initValue_cbf_chroma[12] = { 94,138,182,154,149,107,167,154,149,92,167,154 }; |
229 | | static const int initValue_split_transform_flag[9] = { 153,138,138, 124,138,94, 224,167,122 }; // FIX712 |
230 | | static const int initValue_last_significant_coefficient_prefix[54] = { |
231 | | 110,110,124,125,140,153,125,127,140,109,111,143,127,111, 79,108,123, 63, |
232 | | 125,110, 94,110, 95, 79,125,111,110, 78,110,111,111, 95, 94,108,123,108, |
233 | | 125,110,124,110, 95, 94,125,111,111, 79,125,126,111,111, 79,108,123, 93 |
234 | | }; |
235 | | static const int initValue_coded_sub_block_flag[12] = { 91,171,134,141,121,140,61,154,121,140,61,154 }; |
236 | | static const int initValue_significant_coeff_flag[3][42] = { |
237 | | { |
238 | | 111, 111, 125, 110, 110, 94, 124, 108, 124, 107, 125, 141, 179, 153, 125, 107, |
239 | | 125, 141, 179, 153, 125, 107, 125, 141, 179, 153, 125, 140, 139, 182, 182, 152, |
240 | | 136, 152, 136, 153, 136, 139, 111, 136, 139, 111 |
241 | | }, |
242 | | { |
243 | | 155, 154, 139, 153, 139, 123, 123, 63, 153, 166, 183, 140, 136, 153, 154, 166, |
244 | | 183, 140, 136, 153, 154, 166, 183, 140, 136, 153, 154, 170, 153, 123, 123, 107, |
245 | | 121, 107, 121, 167, 151, 183, 140, 151, 183, 140, |
246 | | }, |
247 | | { |
248 | | 170, 154, 139, 153, 139, 123, 123, 63, 124, 166, 183, 140, 136, 153, 154, 166, |
249 | | 183, 140, 136, 153, 154, 166, 183, 140, 136, 153, 154, 170, 153, 138, 138, 122, |
250 | | 121, 122, 121, 167, 151, 183, 140, 151, 183, 140 |
251 | | }, |
252 | | }; |
253 | | static const int initValue_significant_coeff_flag_skipmode[3][2] = { |
254 | | { 141,111 }, { 140,140 }, { 140,140 } |
255 | | }; |
256 | | |
257 | | static const int initValue_coeff_abs_level_greater1_flag[72] = { |
258 | | 140, 92,137,138,140,152,138,139,153, 74,149, 92,139,107,122,152, |
259 | | 140,179,166,182,140,227,122,197,154,196,196,167,154,152,167,182, |
260 | | 182,134,149,136,153,121,136,137,169,194,166,167,154,167,137,182, |
261 | | 154,196,167,167,154,152,167,182,182,134,149,136,153,121,136,122, |
262 | | 169,208,166,167,154,152,167,182 |
263 | | }; |
264 | | static const int initValue_coeff_abs_level_greater2_flag[18] = { |
265 | | 138,153,136,167,152,152,107,167, 91,122,107,167, |
266 | | 107,167, 91,107,107,167 |
267 | | }; |
268 | | static const int initValue_sao_merge_leftUp_flag[3] = { 153,153,153 }; |
269 | | static const int initValue_sao_type_idx_lumaChroma_flag[3] = { 200,185,160 }; |
270 | | static const int initValue_cu_qp_delta_abs[2] = { 154,154 }; |
271 | | static const int initValue_transform_skip_flag[2] = { 139,139 }; |
272 | | static const int initValue_merge_flag[2] = { 110,154 }; |
273 | | static const int initValue_merge_idx[2] = { 122,137 }; |
274 | | static const int initValue_pred_mode_flag[2] = { 149,134 }; |
275 | | static const int initValue_abs_mvd_greater01_flag[4] = { 140,198,169,198 }; |
276 | | static const int initValue_mvp_lx_flag[1] = { 168 }; |
277 | | static const int initValue_rqt_root_cbf[1] = { 79 }; |
278 | | static const int initValue_ref_idx_lX[2] = { 153,153 }; |
279 | | static const int initValue_inter_pred_idc[5] = { 95,79,63,31,31 }; |
280 | | static const int initValue_cu_transquant_bypass_flag[3] = { 154,154,154 }; |
281 | | |
282 | | |
283 | | static void init_context(int SliceQPY, |
284 | | context_model* model, |
285 | | const int* initValues, int len) |
286 | 71.4k | { |
287 | 584k | for (int i=0;i<len;i++) |
288 | 513k | { |
289 | 513k | set_initValue(SliceQPY, &model[i], initValues[i], 1); |
290 | 513k | } |
291 | 71.4k | } |
292 | | |
293 | | |
294 | | static void init_context_const(int SliceQPY, |
295 | | context_model* model, |
296 | | int initValue, int len) |
297 | 15.1k | { |
298 | 15.1k | set_initValue(SliceQPY, model, initValue, len); |
299 | 15.1k | } |
300 | | |
301 | | void initialize_CABAC_models(context_model context_model_table[CONTEXT_MODEL_TABLE_LENGTH], |
302 | | int initType, |
303 | | int QPY) |
304 | 3.71k | { |
305 | 3.71k | context_model* cm = context_model_table; // just an abbreviation |
306 | | |
307 | 3.71k | if (initType > 0) { |
308 | 150 | init_context(QPY, cm+CONTEXT_MODEL_CU_SKIP_FLAG, initValue_cu_skip_flag[initType-1], 3); |
309 | 150 | init_context(QPY, cm+CONTEXT_MODEL_PRED_MODE_FLAG, &initValue_pred_mode_flag[initType-1], 1); |
310 | 150 | init_context(QPY, cm+CONTEXT_MODEL_MERGE_FLAG, &initValue_merge_flag[initType-1],1); |
311 | 150 | init_context(QPY, cm+CONTEXT_MODEL_MERGE_IDX, &initValue_merge_idx[initType-1], 1); |
312 | 150 | init_context(QPY, cm+CONTEXT_MODEL_INTER_PRED_IDC, initValue_inter_pred_idc, 5); |
313 | 150 | init_context(QPY, cm+CONTEXT_MODEL_REF_IDX_LX, initValue_ref_idx_lX, 2); |
314 | 150 | init_context(QPY, cm+CONTEXT_MODEL_ABS_MVD_GREATER01_FLAG, &initValue_abs_mvd_greater01_flag[initType == 1 ? 0 : 2], 2); |
315 | 150 | init_context(QPY, cm+CONTEXT_MODEL_MVP_LX_FLAG, initValue_mvp_lx_flag, 1); |
316 | 150 | init_context(QPY, cm+CONTEXT_MODEL_RQT_ROOT_CBF, initValue_rqt_root_cbf, 1); |
317 | | |
318 | 150 | init_context_const(QPY, cm+CONTEXT_MODEL_RDPCM_FLAG, 139, 2); |
319 | 150 | init_context_const(QPY, cm+CONTEXT_MODEL_RDPCM_DIR, 139, 2); |
320 | 150 | } |
321 | | |
322 | 3.71k | init_context(QPY, cm+CONTEXT_MODEL_SPLIT_CU_FLAG, initValue_split_cu_flag[initType], 3); |
323 | 3.71k | init_context(QPY, cm+CONTEXT_MODEL_PART_MODE, &initValue_part_mode[(initType!=2 ? initType : 5)], 4); |
324 | 3.71k | init_context(QPY, cm+CONTEXT_MODEL_PREV_INTRA_LUMA_PRED_FLAG, &initValue_prev_intra_luma_pred_flag[initType], 1); |
325 | 3.71k | init_context(QPY, cm+CONTEXT_MODEL_INTRA_CHROMA_PRED_MODE, &initValue_intra_chroma_pred_mode[initType], 1); |
326 | 3.71k | init_context(QPY, cm+CONTEXT_MODEL_CBF_LUMA, &initValue_cbf_luma[initType == 0 ? 0 : 2], 2); |
327 | 3.71k | init_context(QPY, cm+CONTEXT_MODEL_CBF_CHROMA, &initValue_cbf_chroma[initType * 4], 4); |
328 | 3.71k | init_context(QPY, cm+CONTEXT_MODEL_SPLIT_TRANSFORM_FLAG, &initValue_split_transform_flag[initType * 3], 3); |
329 | 3.71k | init_context(QPY, cm+CONTEXT_MODEL_LAST_SIGNIFICANT_COEFFICIENT_X_PREFIX, &initValue_last_significant_coefficient_prefix[initType * 18], 18); |
330 | 3.71k | init_context(QPY, cm+CONTEXT_MODEL_LAST_SIGNIFICANT_COEFFICIENT_Y_PREFIX, &initValue_last_significant_coefficient_prefix[initType * 18], 18); |
331 | 3.71k | init_context(QPY, cm+CONTEXT_MODEL_CODED_SUB_BLOCK_FLAG, &initValue_coded_sub_block_flag[initType * 4], 4); |
332 | 3.71k | init_context(QPY, cm+CONTEXT_MODEL_SIGNIFICANT_COEFF_FLAG, initValue_significant_coeff_flag[initType], 42); |
333 | 3.71k | init_context(QPY, cm+CONTEXT_MODEL_SIGNIFICANT_COEFF_FLAG+42, initValue_significant_coeff_flag_skipmode[initType], 2); |
334 | | |
335 | 3.71k | init_context(QPY, cm+CONTEXT_MODEL_COEFF_ABS_LEVEL_GREATER1_FLAG, &initValue_coeff_abs_level_greater1_flag[initType * 24], 24); |
336 | 3.71k | init_context(QPY, cm+CONTEXT_MODEL_COEFF_ABS_LEVEL_GREATER2_FLAG, &initValue_coeff_abs_level_greater2_flag[initType * 6], 6); |
337 | 3.71k | init_context(QPY, cm+CONTEXT_MODEL_SAO_MERGE_FLAG, &initValue_sao_merge_leftUp_flag[initType], 1); |
338 | 3.71k | init_context(QPY, cm+CONTEXT_MODEL_SAO_TYPE_IDX, &initValue_sao_type_idx_lumaChroma_flag[initType], 1); |
339 | 3.71k | init_context(QPY, cm+CONTEXT_MODEL_CU_QP_DELTA_ABS, initValue_cu_qp_delta_abs, 2); |
340 | 3.71k | init_context(QPY, cm+CONTEXT_MODEL_TRANSFORM_SKIP_FLAG, initValue_transform_skip_flag, 2); |
341 | 3.71k | init_context(QPY, cm+CONTEXT_MODEL_CU_TRANSQUANT_BYPASS_FLAG, &initValue_cu_transquant_bypass_flag[initType], 1); |
342 | | |
343 | 3.71k | init_context_const(QPY, cm+CONTEXT_MODEL_LOG2_RES_SCALE_ABS_PLUS1, 154, 8); |
344 | 3.71k | init_context_const(QPY, cm+CONTEXT_MODEL_RES_SCALE_SIGN_FLAG, 154, 2); |
345 | 3.71k | init_context_const(QPY, cm+CONTEXT_MODEL_CU_CHROMA_QP_OFFSET_FLAG, 154, 1); |
346 | 3.71k | init_context_const(QPY, cm+CONTEXT_MODEL_CU_CHROMA_QP_OFFSET_IDX, 154, 1); |
347 | 3.71k | } |