Coverage Report

Created: 2026-10-17 06:52

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/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
12.3k
{
43
12.3k
  if (D) printf("%p destructor\n",static_cast<void*>(this));
44
45
12.3k
  if (refcnt) {
46
4.98k
    (*refcnt)--;
47
4.98k
    if (*refcnt==0) {
48
4.98k
      if (D) printf("mfree %p\n",static_cast<void*>(model));
49
4.98k
      delete[] model;
50
4.98k
      delete refcnt;
51
4.98k
    }
52
4.98k
  }
53
12.3k
}
54
55
56
void context_model_table::init(int initType, int QPY)
57
3.50k
{
58
3.50k
  if (D) printf("%p init\n",static_cast<void*>(this));
59
60
3.50k
  decouple_or_alloc_with_empty_data();
61
62
3.50k
  initialize_CABAC_models(model, initType, QPY);
63
3.50k
}
64
65
66
void context_model_table::release()
67
5.09k
{
68
5.09k
  if (D) printf("%p release %p\n",static_cast<void*>(this),static_cast<void*>(refcnt));
69
70
5.09k
  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
1.38k
  (*refcnt)--;
75
1.38k
  if (*refcnt==0) {
76
1
    delete[] model;
77
1
    delete refcnt;
78
1
  }
79
80
1.38k
  model = nullptr;
81
1.38k
  refcnt= nullptr;
82
1.38k
}
83
84
85
void context_model_table::decouple()
86
1.48k
{
87
1.48k
  if (D) printf("%p decouple (%p)\n",static_cast<void*>(this),static_cast<void*>(refcnt));
88
89
1.48k
  assert(refcnt); // not necessarily so, but we never use it on an uninitialized object
90
91
1.48k
  if (*refcnt > 1) {
92
1.48k
    (*refcnt)--;
93
94
1.48k
    context_model* oldModel = model;
95
96
1.48k
    model = new context_model[CONTEXT_MODEL_TABLE_LENGTH];
97
1.48k
    refcnt= new int;
98
1.48k
    *refcnt=1;
99
100
1.48k
    memcpy(model,oldModel,sizeof(context_model)*CONTEXT_MODEL_TABLE_LENGTH);
101
1.48k
  }
102
1.48k
}
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
3.28k
{
120
3.28k
  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
3.28k
  if (!src.refcnt) {
125
422
    release();
126
422
    return *this;
127
422
  }
128
129
2.86k
  (*(src.refcnt))++;
130
131
2.86k
  release();
132
133
2.86k
  model = src.model;
134
2.86k
  refcnt= src.refcnt;
135
136
2.86k
  return *this;
137
3.28k
}
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
3.50k
{
168
3.50k
  if (refcnt && *refcnt==1) { return; }
169
170
3.50k
  if (refcnt) {
171
0
    assert(*refcnt>1);
172
0
    (*refcnt)--;
173
0
  }
174
175
3.50k
  if (D) printf("%p (alloc)\n",static_cast<void*>(this));
176
177
3.50k
  model = new context_model[CONTEXT_MODEL_TABLE_LENGTH];
178
  // Without initializing the model, we got an invalid model state during decoding (issue #236)
179
3.50k
  memset(model, 0, sizeof(context_model) * CONTEXT_MODEL_TABLE_LENGTH);
180
3.50k
  refcnt= new int;
181
3.50k
  *refcnt=1;
182
3.50k
}
183
184
185
186
187
188
189
static void set_initValue(int SliceQPY,
190
                          context_model* model, int initValue, int nContexts)
191
540k
{
192
540k
  int slopeIdx = initValue >> 4;
193
540k
  int intersecIdx = initValue & 0xF;
194
540k
  int m = slopeIdx*5 - 45;
195
540k
  int n = (intersecIdx<<3) - 16;
196
540k
  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
1.11M
  for (int i=0;i<nContexts;i++) {
201
572k
    model[i].MPSbit=(preCtxState<=63) ? 0 : 1;
202
572k
    model[i].state = model[i].MPSbit ? (preCtxState-64) : (63-preCtxState);
203
204
    // model state will always be between [0;62]
205
206
572k
    assert(model[i].state <= 62);
207
572k
  }
208
540k
}
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
85.3k
{
283
607k
  for (int i=0;i<len;i++)
284
522k
    {
285
522k
      set_initValue(SliceQPY, &model[i], initValues[i], 1);
286
522k
    }
287
85.3k
}
288
289
290
static void init_context_const(int SliceQPY,
291
                               context_model* model,
292
                               int initValue, int len)
293
18.1k
{
294
18.1k
  set_initValue(SliceQPY, model, initValue, len);
295
18.1k
}
296
297
void initialize_CABAC_models(context_model context_model_table[CONTEXT_MODEL_TABLE_LENGTH],
298
                      int initType,
299
                      int QPY)
300
3.50k
{
301
3.50k
  context_model* cm = context_model_table; // just an abbreviation
302
303
3.50k
  if (initType > 0) {
304
2.09k
    init_context(QPY, cm+CONTEXT_MODEL_CU_SKIP_FLAG,    initValue_cu_skip_flag[initType-1],  3);
305
2.09k
    init_context(QPY, cm+CONTEXT_MODEL_PRED_MODE_FLAG, &initValue_pred_mode_flag[initType-1], 1);
306
2.09k
    init_context(QPY, cm+CONTEXT_MODEL_MERGE_FLAG,             &initValue_merge_flag[initType-1],1);
307
2.09k
    init_context(QPY, cm+CONTEXT_MODEL_MERGE_IDX,              &initValue_merge_idx[initType-1], 1);
308
2.09k
    init_context(QPY, cm+CONTEXT_MODEL_INTER_PRED_IDC,         initValue_inter_pred_idc,         5);
309
2.09k
    init_context(QPY, cm+CONTEXT_MODEL_REF_IDX_LX,             initValue_ref_idx_lX,             2);
310
2.09k
    init_context(QPY, cm+CONTEXT_MODEL_ABS_MVD_GREATER01_FLAG, &initValue_abs_mvd_greater01_flag[initType == 1 ? 0 : 2], 2);
311
2.09k
    init_context(QPY, cm+CONTEXT_MODEL_MVP_LX_FLAG,            initValue_mvp_lx_flag,            1);
312
2.09k
    init_context(QPY, cm+CONTEXT_MODEL_RQT_ROOT_CBF,           initValue_rqt_root_cbf,           1);
313
314
2.09k
    init_context_const(QPY, cm+CONTEXT_MODEL_RDPCM_FLAG, 139, 2);
315
2.09k
    init_context_const(QPY, cm+CONTEXT_MODEL_RDPCM_DIR,  139, 2);
316
2.09k
  }
317
318
3.50k
  init_context(QPY, cm+CONTEXT_MODEL_SPLIT_CU_FLAG, initValue_split_cu_flag[initType], 3);
319
3.50k
  init_context(QPY, cm+CONTEXT_MODEL_PART_MODE,     &initValue_part_mode[(initType!=2 ? initType : 5)], 4);
320
3.50k
  init_context(QPY, cm+CONTEXT_MODEL_PREV_INTRA_LUMA_PRED_FLAG, &initValue_prev_intra_luma_pred_flag[initType], 1);
321
3.50k
  init_context(QPY, cm+CONTEXT_MODEL_INTRA_CHROMA_PRED_MODE,    &initValue_intra_chroma_pred_mode[initType],    1);
322
3.50k
  init_context(QPY, cm+CONTEXT_MODEL_CBF_LUMA,                  &initValue_cbf_luma[initType == 0 ? 0 : 2],     2);
323
3.50k
  init_context(QPY, cm+CONTEXT_MODEL_CBF_CHROMA,                &initValue_cbf_chroma[initType * 4],            4);
324
3.50k
  init_context(QPY, cm+CONTEXT_MODEL_SPLIT_TRANSFORM_FLAG,      &initValue_split_transform_flag[initType * 3],  3);
325
3.50k
  init_context(QPY, cm+CONTEXT_MODEL_LAST_SIGNIFICANT_COEFFICIENT_X_PREFIX, &initValue_last_significant_coefficient_prefix[initType * 18], 18);
326
3.50k
  init_context(QPY, cm+CONTEXT_MODEL_LAST_SIGNIFICANT_COEFFICIENT_Y_PREFIX, &initValue_last_significant_coefficient_prefix[initType * 18], 18);
327
3.50k
  init_context(QPY, cm+CONTEXT_MODEL_CODED_SUB_BLOCK_FLAG,                  &initValue_coded_sub_block_flag[initType * 4],        4);
328
3.50k
  init_context(QPY, cm+CONTEXT_MODEL_SIGNIFICANT_COEFF_FLAG,              initValue_significant_coeff_flag[initType],    42);
329
3.50k
  init_context(QPY, cm+CONTEXT_MODEL_SIGNIFICANT_COEFF_FLAG+42, initValue_significant_coeff_flag_skipmode[initType], 2);
330
331
3.50k
  init_context(QPY, cm+CONTEXT_MODEL_COEFF_ABS_LEVEL_GREATER1_FLAG,       &initValue_coeff_abs_level_greater1_flag[initType * 24], 24);
332
3.50k
  init_context(QPY, cm+CONTEXT_MODEL_COEFF_ABS_LEVEL_GREATER2_FLAG,       &initValue_coeff_abs_level_greater2_flag[initType *  6],  6);
333
3.50k
  init_context(QPY, cm+CONTEXT_MODEL_SAO_MERGE_FLAG,                      &initValue_sao_merge_leftUp_flag[initType],    1);
334
3.50k
  init_context(QPY, cm+CONTEXT_MODEL_SAO_TYPE_IDX,                        &initValue_sao_type_idx_lumaChroma_flag[initType], 1);
335
3.50k
  init_context(QPY, cm+CONTEXT_MODEL_CU_QP_DELTA_ABS,        initValue_cu_qp_delta_abs,        2);
336
3.50k
  init_context(QPY, cm+CONTEXT_MODEL_TRANSFORM_SKIP_FLAG,    initValue_transform_skip_flag,    2);
337
3.50k
  init_context(QPY, cm+CONTEXT_MODEL_CU_TRANSQUANT_BYPASS_FLAG, &initValue_cu_transquant_bypass_flag[initType], 1);
338
339
3.50k
  init_context_const(QPY, cm+CONTEXT_MODEL_LOG2_RES_SCALE_ABS_PLUS1, 154, 8);
340
3.50k
  init_context_const(QPY, cm+CONTEXT_MODEL_RES_SCALE_SIGN_FLAG,      154, 2);
341
3.50k
  init_context_const(QPY, cm+CONTEXT_MODEL_CU_CHROMA_QP_OFFSET_FLAG, 154, 1);
342
3.50k
  init_context_const(QPY, cm+CONTEXT_MODEL_CU_CHROMA_QP_OFFSET_IDX,  154, 1);
343
3.50k
}