Coverage Report

Created: 2026-08-13 07:23

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