/work/libde265/libde265/contextmodel.cc
Line | Count | Source |
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(const context_model_table& src) |
29 | 0 | { |
30 | 0 | if (D) printf("%p c'tor = %p\n",static_cast<void*>(this),static_cast<const void*>(&src)); |
31 | |
|
32 | 0 | if (src.refcnt) { |
33 | 0 | (*(src.refcnt))++; |
34 | 0 | } |
35 | |
|
36 | 0 | refcnt = src.refcnt; |
37 | 0 | model = src.model; |
38 | 0 | } |
39 | | |
40 | | |
41 | | context_model_table::~context_model_table() |
42 | 108 | { |
43 | 108 | if (D) printf("%p destructor\n",static_cast<void*>(this)); |
44 | | |
45 | 108 | if (refcnt) { |
46 | 0 | (*refcnt)--; |
47 | 0 | if (*refcnt==0) { |
48 | 0 | if (D) printf("mfree %p\n",static_cast<void*>(model)); |
49 | 0 | delete[] model; |
50 | 0 | delete refcnt; |
51 | 0 | } |
52 | 0 | } |
53 | 108 | } |
54 | | |
55 | | |
56 | | void context_model_table::init(int initType, int QPY) |
57 | 0 | { |
58 | 0 | if (D) printf("%p init\n",static_cast<void*>(this)); |
59 | |
|
60 | 0 | decouple_or_alloc_with_empty_data(); |
61 | |
|
62 | 0 | initialize_CABAC_models(model, initType, QPY); |
63 | 0 | } |
64 | | |
65 | | |
66 | | void context_model_table::release() |
67 | 0 | { |
68 | 0 | if (D) printf("%p release %p\n",static_cast<void*>(this),static_cast<void*>(refcnt)); |
69 | |
|
70 | 0 | if (!refcnt) { return; } |
71 | | |
72 | | // if (*refcnt == 1) { return; } <- keep memory for later, but does not work when we believe that we freed the memory and nulled all references |
73 | | |
74 | 0 | (*refcnt)--; |
75 | 0 | if (*refcnt==0) { |
76 | 0 | delete[] model; |
77 | 0 | delete refcnt; |
78 | 0 | } |
79 | |
|
80 | 0 | model = nullptr; |
81 | 0 | refcnt= nullptr; |
82 | 0 | } |
83 | | |
84 | | |
85 | | void context_model_table::decouple() |
86 | 0 | { |
87 | 0 | if (D) printf("%p decouple (%p)\n",static_cast<void*>(this),static_cast<void*>(refcnt)); |
88 | |
|
89 | 0 | assert(refcnt); // not necessarily so, but we never use it on an uninitialized object |
90 | | |
91 | 0 | if (*refcnt > 1) { |
92 | 0 | (*refcnt)--; |
93 | |
|
94 | 0 | context_model* oldModel = model; |
95 | |
|
96 | 0 | model = new context_model[CONTEXT_MODEL_TABLE_LENGTH]; |
97 | 0 | refcnt= new int; |
98 | 0 | *refcnt=1; |
99 | |
|
100 | 0 | memcpy(model,oldModel,sizeof(context_model)*CONTEXT_MODEL_TABLE_LENGTH); |
101 | 0 | } |
102 | 0 | } |
103 | | |
104 | | |
105 | | context_model_table context_model_table::transfer() |
106 | 0 | { |
107 | 0 | context_model_table newtable; |
108 | 0 | newtable.model = model; |
109 | 0 | newtable.refcnt= refcnt; |
110 | |
|
111 | 0 | model =nullptr; |
112 | 0 | refcnt=nullptr; |
113 | |
|
114 | 0 | return newtable; |
115 | 0 | } |
116 | | |
117 | | |
118 | | context_model_table& context_model_table::operator=(const context_model_table& src) |
119 | 0 | { |
120 | 0 | if (D) printf("%p assign = %p\n",static_cast<void*>(this),static_cast<const void*>(&src)); |
121 | | |
122 | | // assert(src.refcnt); // not necessarily so, but we never use it on an uninitialized object |
123 | |
|
124 | 0 | if (!src.refcnt) { |
125 | 0 | release(); |
126 | 0 | return *this; |
127 | 0 | } |
128 | | |
129 | 0 | (*(src.refcnt))++; |
130 | |
|
131 | 0 | release(); |
132 | |
|
133 | 0 | model = src.model; |
134 | 0 | refcnt= src.refcnt; |
135 | |
|
136 | 0 | return *this; |
137 | 0 | } |
138 | | |
139 | | |
140 | | bool context_model_table::operator==(const context_model_table& b) const |
141 | 0 | { |
142 | 0 | if (b.model == model) return true; |
143 | 0 | if (b.model == nullptr || model == nullptr) return false; |
144 | | |
145 | 0 | for (int i=0;i<CONTEXT_MODEL_TABLE_LENGTH;i++) { |
146 | 0 | if (!(b.model[i] == model[i])) return false; |
147 | 0 | } |
148 | | |
149 | 0 | return true; |
150 | 0 | } |
151 | | |
152 | | |
153 | | std::string context_model_table::debug_dump() const |
154 | 0 | { |
155 | 0 | int hash = 0; |
156 | 0 | for (int i=0;i<CONTEXT_MODEL_TABLE_LENGTH;i++) { |
157 | 0 | hash ^= ((i+7)*model[i].state) & 0xFFFF; |
158 | 0 | } |
159 | |
|
160 | 0 | std::stringstream sstr; |
161 | 0 | sstr << std::hex << hash; |
162 | 0 | return sstr.str(); |
163 | 0 | } |
164 | | |
165 | | |
166 | | void context_model_table::decouple_or_alloc_with_empty_data() |
167 | 0 | { |
168 | 0 | if (refcnt && *refcnt==1) { return; } |
169 | | |
170 | 0 | if (refcnt) { |
171 | 0 | assert(*refcnt>1); |
172 | 0 | (*refcnt)--; |
173 | 0 | } |
174 | | |
175 | 0 | if (D) printf("%p (alloc)\n",static_cast<void*>(this)); |
176 | |
|
177 | 0 | model = new context_model[CONTEXT_MODEL_TABLE_LENGTH]; |
178 | | // Without initializing the model, we got an invalid model state during decoding (issue #236) |
179 | 0 | memset(model, 0, sizeof(context_model) * CONTEXT_MODEL_TABLE_LENGTH); |
180 | 0 | refcnt= new int; |
181 | 0 | *refcnt=1; |
182 | 0 | } |
183 | | |
184 | | |
185 | | |
186 | | |
187 | | |
188 | | |
189 | | static void set_initValue(int SliceQPY, |
190 | | context_model* model, int initValue, int nContexts) |
191 | 0 | { |
192 | 0 | int slopeIdx = initValue >> 4; |
193 | 0 | int intersecIdx = initValue & 0xF; |
194 | 0 | int m = slopeIdx*5 - 45; |
195 | 0 | int n = (intersecIdx<<3) - 16; |
196 | 0 | int preCtxState = Clip3(1,126, ((m*Clip3(0,51, SliceQPY))>>4)+n); |
197 | | |
198 | | // logtrace(LogSlice,"QP=%d slopeIdx=%d intersecIdx=%d m=%d n=%d\n",SliceQPY,slopeIdx,intersecIdx,m,n); |
199 | |
|
200 | 0 | for (int i=0;i<nContexts;i++) { |
201 | 0 | model[i].MPSbit=(preCtxState<=63) ? 0 : 1; |
202 | 0 | model[i].state = model[i].MPSbit ? (preCtxState-64) : (63-preCtxState); |
203 | | |
204 | | // model state will always be between [0;62] |
205 | |
|
206 | 0 | assert(model[i].state <= 62); |
207 | 0 | } |
208 | 0 | } |
209 | | |
210 | | |
211 | | static const int initValue_split_cu_flag[3][3] = { |
212 | | { 139,141,157 }, |
213 | | { 107,139,126 }, |
214 | | { 107,139,126 }, |
215 | | }; |
216 | | static const int initValue_cu_skip_flag[2][3] = { |
217 | | { 197,185,201 }, |
218 | | { 197,185,201 }, |
219 | | }; |
220 | | static const int initValue_part_mode[9] = { 184,154,139, 154,154,154, 139,154,154 }; |
221 | | static const int initValue_prev_intra_luma_pred_flag[3] = { 184,154,183 }; |
222 | | static const int initValue_intra_chroma_pred_mode[3] = { 63,152,152 }; |
223 | | static const int initValue_cbf_luma[4] = { 111,141,153,111 }; |
224 | | static const int initValue_cbf_chroma[12] = { 94,138,182,154,149,107,167,154,149,92,167,154 }; |
225 | | static const int initValue_split_transform_flag[9] = { 153,138,138, 124,138,94, 224,167,122 }; // FIX712 |
226 | | static const int initValue_last_significant_coefficient_prefix[54] = { |
227 | | 110,110,124,125,140,153,125,127,140,109,111,143,127,111, 79,108,123, 63, |
228 | | 125,110, 94,110, 95, 79,125,111,110, 78,110,111,111, 95, 94,108,123,108, |
229 | | 125,110,124,110, 95, 94,125,111,111, 79,125,126,111,111, 79,108,123, 93 |
230 | | }; |
231 | | static const int initValue_coded_sub_block_flag[12] = { 91,171,134,141,121,140,61,154,121,140,61,154 }; |
232 | | static const int initValue_significant_coeff_flag[3][42] = { |
233 | | { |
234 | | 111, 111, 125, 110, 110, 94, 124, 108, 124, 107, 125, 141, 179, 153, 125, 107, |
235 | | 125, 141, 179, 153, 125, 107, 125, 141, 179, 153, 125, 140, 139, 182, 182, 152, |
236 | | 136, 152, 136, 153, 136, 139, 111, 136, 139, 111 |
237 | | }, |
238 | | { |
239 | | 155, 154, 139, 153, 139, 123, 123, 63, 153, 166, 183, 140, 136, 153, 154, 166, |
240 | | 183, 140, 136, 153, 154, 166, 183, 140, 136, 153, 154, 170, 153, 123, 123, 107, |
241 | | 121, 107, 121, 167, 151, 183, 140, 151, 183, 140, |
242 | | }, |
243 | | { |
244 | | 170, 154, 139, 153, 139, 123, 123, 63, 124, 166, 183, 140, 136, 153, 154, 166, |
245 | | 183, 140, 136, 153, 154, 166, 183, 140, 136, 153, 154, 170, 153, 138, 138, 122, |
246 | | 121, 122, 121, 167, 151, 183, 140, 151, 183, 140 |
247 | | }, |
248 | | }; |
249 | | static const int initValue_significant_coeff_flag_skipmode[3][2] = { |
250 | | { 141,111 }, { 140,140 }, { 140,140 } |
251 | | }; |
252 | | |
253 | | static const int initValue_coeff_abs_level_greater1_flag[72] = { |
254 | | 140, 92,137,138,140,152,138,139,153, 74,149, 92,139,107,122,152, |
255 | | 140,179,166,182,140,227,122,197,154,196,196,167,154,152,167,182, |
256 | | 182,134,149,136,153,121,136,137,169,194,166,167,154,167,137,182, |
257 | | 154,196,167,167,154,152,167,182,182,134,149,136,153,121,136,122, |
258 | | 169,208,166,167,154,152,167,182 |
259 | | }; |
260 | | static const int initValue_coeff_abs_level_greater2_flag[18] = { |
261 | | 138,153,136,167,152,152,107,167, 91,122,107,167, |
262 | | 107,167, 91,107,107,167 |
263 | | }; |
264 | | static const int initValue_sao_merge_leftUp_flag[3] = { 153,153,153 }; |
265 | | static const int initValue_sao_type_idx_lumaChroma_flag[3] = { 200,185,160 }; |
266 | | static const int initValue_cu_qp_delta_abs[2] = { 154,154 }; |
267 | | static const int initValue_transform_skip_flag[2] = { 139,139 }; |
268 | | static const int initValue_merge_flag[2] = { 110,154 }; |
269 | | static const int initValue_merge_idx[2] = { 122,137 }; |
270 | | static const int initValue_pred_mode_flag[2] = { 149,134 }; |
271 | | static const int initValue_abs_mvd_greater01_flag[4] = { 140,198,169,198 }; |
272 | | static const int initValue_mvp_lx_flag[1] = { 168 }; |
273 | | static const int initValue_rqt_root_cbf[1] = { 79 }; |
274 | | static const int initValue_ref_idx_lX[2] = { 153,153 }; |
275 | | static const int initValue_inter_pred_idc[5] = { 95,79,63,31,31 }; |
276 | | static const int initValue_cu_transquant_bypass_flag[3] = { 154,154,154 }; |
277 | | |
278 | | |
279 | | static void init_context(int SliceQPY, |
280 | | context_model* model, |
281 | | const int* initValues, int len) |
282 | 0 | { |
283 | 0 | for (int i=0;i<len;i++) |
284 | 0 | { |
285 | 0 | set_initValue(SliceQPY, &model[i], initValues[i], 1); |
286 | 0 | } |
287 | 0 | } |
288 | | |
289 | | |
290 | | static void init_context_const(int SliceQPY, |
291 | | context_model* model, |
292 | | int initValue, int len) |
293 | 0 | { |
294 | 0 | set_initValue(SliceQPY, model, initValue, len); |
295 | 0 | } |
296 | | |
297 | | void initialize_CABAC_models(context_model context_model_table[CONTEXT_MODEL_TABLE_LENGTH], |
298 | | int initType, |
299 | | int QPY) |
300 | 0 | { |
301 | 0 | context_model* cm = context_model_table; // just an abbreviation |
302 | |
|
303 | 0 | if (initType > 0) { |
304 | 0 | init_context(QPY, cm+CONTEXT_MODEL_CU_SKIP_FLAG, initValue_cu_skip_flag[initType-1], 3); |
305 | 0 | init_context(QPY, cm+CONTEXT_MODEL_PRED_MODE_FLAG, &initValue_pred_mode_flag[initType-1], 1); |
306 | 0 | init_context(QPY, cm+CONTEXT_MODEL_MERGE_FLAG, &initValue_merge_flag[initType-1],1); |
307 | 0 | init_context(QPY, cm+CONTEXT_MODEL_MERGE_IDX, &initValue_merge_idx[initType-1], 1); |
308 | 0 | init_context(QPY, cm+CONTEXT_MODEL_INTER_PRED_IDC, initValue_inter_pred_idc, 5); |
309 | 0 | init_context(QPY, cm+CONTEXT_MODEL_REF_IDX_LX, initValue_ref_idx_lX, 2); |
310 | 0 | init_context(QPY, cm+CONTEXT_MODEL_ABS_MVD_GREATER01_FLAG, &initValue_abs_mvd_greater01_flag[initType == 1 ? 0 : 2], 2); |
311 | 0 | init_context(QPY, cm+CONTEXT_MODEL_MVP_LX_FLAG, initValue_mvp_lx_flag, 1); |
312 | 0 | init_context(QPY, cm+CONTEXT_MODEL_RQT_ROOT_CBF, initValue_rqt_root_cbf, 1); |
313 | |
|
314 | 0 | init_context_const(QPY, cm+CONTEXT_MODEL_RDPCM_FLAG, 139, 2); |
315 | 0 | init_context_const(QPY, cm+CONTEXT_MODEL_RDPCM_DIR, 139, 2); |
316 | 0 | } |
317 | |
|
318 | 0 | init_context(QPY, cm+CONTEXT_MODEL_SPLIT_CU_FLAG, initValue_split_cu_flag[initType], 3); |
319 | 0 | init_context(QPY, cm+CONTEXT_MODEL_PART_MODE, &initValue_part_mode[(initType!=2 ? initType : 5)], 4); |
320 | 0 | init_context(QPY, cm+CONTEXT_MODEL_PREV_INTRA_LUMA_PRED_FLAG, &initValue_prev_intra_luma_pred_flag[initType], 1); |
321 | 0 | init_context(QPY, cm+CONTEXT_MODEL_INTRA_CHROMA_PRED_MODE, &initValue_intra_chroma_pred_mode[initType], 1); |
322 | 0 | init_context(QPY, cm+CONTEXT_MODEL_CBF_LUMA, &initValue_cbf_luma[initType == 0 ? 0 : 2], 2); |
323 | 0 | init_context(QPY, cm+CONTEXT_MODEL_CBF_CHROMA, &initValue_cbf_chroma[initType * 4], 4); |
324 | 0 | init_context(QPY, cm+CONTEXT_MODEL_SPLIT_TRANSFORM_FLAG, &initValue_split_transform_flag[initType * 3], 3); |
325 | 0 | init_context(QPY, cm+CONTEXT_MODEL_LAST_SIGNIFICANT_COEFFICIENT_X_PREFIX, &initValue_last_significant_coefficient_prefix[initType * 18], 18); |
326 | 0 | init_context(QPY, cm+CONTEXT_MODEL_LAST_SIGNIFICANT_COEFFICIENT_Y_PREFIX, &initValue_last_significant_coefficient_prefix[initType * 18], 18); |
327 | 0 | init_context(QPY, cm+CONTEXT_MODEL_CODED_SUB_BLOCK_FLAG, &initValue_coded_sub_block_flag[initType * 4], 4); |
328 | 0 | init_context(QPY, cm+CONTEXT_MODEL_SIGNIFICANT_COEFF_FLAG, initValue_significant_coeff_flag[initType], 42); |
329 | 0 | init_context(QPY, cm+CONTEXT_MODEL_SIGNIFICANT_COEFF_FLAG+42, initValue_significant_coeff_flag_skipmode[initType], 2); |
330 | |
|
331 | 0 | init_context(QPY, cm+CONTEXT_MODEL_COEFF_ABS_LEVEL_GREATER1_FLAG, &initValue_coeff_abs_level_greater1_flag[initType * 24], 24); |
332 | 0 | init_context(QPY, cm+CONTEXT_MODEL_COEFF_ABS_LEVEL_GREATER2_FLAG, &initValue_coeff_abs_level_greater2_flag[initType * 6], 6); |
333 | 0 | init_context(QPY, cm+CONTEXT_MODEL_SAO_MERGE_FLAG, &initValue_sao_merge_leftUp_flag[initType], 1); |
334 | 0 | init_context(QPY, cm+CONTEXT_MODEL_SAO_TYPE_IDX, &initValue_sao_type_idx_lumaChroma_flag[initType], 1); |
335 | 0 | init_context(QPY, cm+CONTEXT_MODEL_CU_QP_DELTA_ABS, initValue_cu_qp_delta_abs, 2); |
336 | 0 | init_context(QPY, cm+CONTEXT_MODEL_TRANSFORM_SKIP_FLAG, initValue_transform_skip_flag, 2); |
337 | 0 | init_context(QPY, cm+CONTEXT_MODEL_CU_TRANSQUANT_BYPASS_FLAG, &initValue_cu_transquant_bypass_flag[initType], 1); |
338 | |
|
339 | 0 | init_context_const(QPY, cm+CONTEXT_MODEL_LOG2_RES_SCALE_ABS_PLUS1, 154, 8); |
340 | 0 | init_context_const(QPY, cm+CONTEXT_MODEL_RES_SCALE_SIGN_FLAG, 154, 2); |
341 | 0 | init_context_const(QPY, cm+CONTEXT_MODEL_CU_CHROMA_QP_OFFSET_FLAG, 154, 1); |
342 | 0 | init_context_const(QPY, cm+CONTEXT_MODEL_CU_CHROMA_QP_OFFSET_IDX, 154, 1); |
343 | 0 | } |