Coverage Report

Created: 2026-06-15 06:22

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
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
}