Coverage Report

Created: 2026-07-30 06:25

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