Coverage Report

Created: 2026-02-14 07:11

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