Coverage Report

Created: 2026-09-14 07:15

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libde265/libde265/pps.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 "pps.h"
22
#include "decctx.h"
23
#include "util.h"
24
25
#include <assert.h>
26
#include <stdlib.h>
27
#include <string.h>
28
#include <mutex>
29
#include <memory>
30
#include <atomic>
31
#if defined(_MSC_VER) || defined(__MINGW32__)
32
# include <malloc.h>
33
#elif defined(HAVE_ALLOCA_H)
34
# include <alloca.h>
35
#endif
36
37
38
void pps_range_extension::reset()
39
34.1k
{
40
34.1k
  log2_max_transform_skip_block_size = 2;
41
34.1k
  cross_component_prediction_enabled_flag = false;
42
34.1k
  chroma_qp_offset_list_enabled_flag = false;
43
34.1k
  diff_cu_chroma_qp_offset_depth = 0;
44
34.1k
  chroma_qp_offset_list_len = 0;
45
34.1k
  log2_sao_offset_scale_luma = 0;
46
34.1k
  log2_sao_offset_scale_chroma = 0;
47
34.1k
}
48
49
50
bool pps_range_extension::read(bitreader* br, decoder_context* ctx, const pic_parameter_set* pps)
51
216
{
52
216
  const seq_parameter_set* sps = ctx->get_sps(pps->seq_parameter_set_id);
53
54
216
  uint32_t uvlc;
55
56
216
  if (pps->transform_skip_enabled_flag) {
57
79
    uvlc = br->get_uvlc();
58
79
    if (uvlc == UVLC_ERROR) {
59
1
      ctx->add_warning(DE265_WARNING_PPS_HEADER_INVALID, false);
60
1
      return false;
61
1
    }
62
63
    // The standard requires log2_max_transform_skip_block_size_minus2 <=
64
    // Log2MaxTrafoSize-2, but real-world RExt streams (e.g. the conformance
65
    // stream PERSIST_RPARAM_A_RExt_Sony_2) code a larger value. This field
66
    // only gates whether transform_skip_flag may be present for a TU of a
67
    // given size (log2TrafoSize <= Log2MaxTransformSkipSize); since
68
    // log2TrafoSize can never exceed Log2MaxTrafoSize, clamping to the
69
    // maximum in-range value reproduces the same "always present" decoding
70
    // behavior as any larger out-of-range value, so it is safe to clamp
71
    // instead of rejecting the whole PPS.
72
78
    uint32_t maxAllowed = static_cast<uint32_t>(sps->Log2MaxTrafoSize) - 2;
73
78
    if (uvlc > maxAllowed) {
74
1
      ctx->add_warning(DE265_WARNING_PPS_HEADER_INVALID, false);
75
1
      uvlc = maxAllowed;
76
1
    }
77
78
78
    log2_max_transform_skip_block_size = uvlc+2;
79
78
  }
80
81
215
  cross_component_prediction_enabled_flag = br->get_bits(1);
82
  // shall be 0 when ChromaArrayType is not 3 (Sec. 7.4.3.3.2)
83
215
  if (sps->ChromaArrayType != CHROMA_444 &&
84
13
      cross_component_prediction_enabled_flag) {
85
6
      ctx->add_warning(DE265_WARNING_PPS_HEADER_INVALID, false);
86
6
      return false;
87
6
  }
88
89
209
  chroma_qp_offset_list_enabled_flag = br->get_bits(1);
90
  // shall be 0 when ChromaArrayType is 0 (mono) (Sec. 7.4.3.3.2)
91
209
  if (sps->ChromaArrayType == CHROMA_MONO &&
92
4
      chroma_qp_offset_list_enabled_flag) {
93
2
      ctx->add_warning(DE265_WARNING_PPS_HEADER_INVALID, false);
94
2
      return false;
95
2
  }
96
97
207
  if (chroma_qp_offset_list_enabled_flag) {
98
37
    uvlc = br->get_uvlc();
99
37
    if (uvlc == UVLC_ERROR ||
100
36
        uvlc > static_cast<uint32_t>(sps->log2_diff_max_min_luma_coding_block_size)) {
101
2
      ctx->add_warning(DE265_WARNING_PPS_HEADER_INVALID, false);
102
2
      return false;
103
2
    }
104
105
35
    diff_cu_chroma_qp_offset_depth = uvlc;
106
107
108
35
    uvlc = br->get_uvlc();
109
35
    if (uvlc == UVLC_ERROR ||
110
34
        uvlc > 5) {
111
2
      ctx->add_warning(DE265_WARNING_PPS_HEADER_INVALID, false);
112
2
      return false;
113
2
    }
114
115
33
    chroma_qp_offset_list_len = uvlc+1;
116
117
77
    for (int i=0;i<chroma_qp_offset_list_len;i++) {
118
47
      int32_t svlc;
119
47
      svlc = br->get_svlc();
120
47
      if (svlc == SVLC_ERROR ||
121
46
          svlc < -12 || svlc > 12) {
122
2
        ctx->add_warning(DE265_WARNING_PPS_HEADER_INVALID, false);
123
2
        return false;
124
2
      }
125
126
45
      cb_qp_offset_list[i] = svlc;
127
128
45
      svlc = br->get_svlc();
129
45
      if (svlc == SVLC_ERROR ||
130
44
          svlc < -12 || svlc > 12) {
131
1
        ctx->add_warning(DE265_WARNING_PPS_HEADER_INVALID, false);
132
1
        return false;
133
1
      }
134
135
44
      cr_qp_offset_list[i] = svlc;
136
44
    }
137
33
  }
138
139
140
200
  uvlc = br->get_uvlc();
141
200
  if (uvlc == UVLC_ERROR ||
142
191
      uvlc > static_cast<uint32_t>(std::max(0, sps->BitDepth_Y-10))) {
143
12
    ctx->add_warning(DE265_WARNING_PPS_HEADER_INVALID, false);
144
12
    return false;
145
12
  }
146
147
188
  log2_sao_offset_scale_luma = uvlc;
148
149
188
  uvlc = br->get_uvlc();
150
188
  if (uvlc == UVLC_ERROR ||
151
187
      uvlc > static_cast<uint32_t>(std::max(0, sps->BitDepth_C-10))) {
152
2
    ctx->add_warning(DE265_WARNING_PPS_HEADER_INVALID, false);
153
2
    return false;
154
2
  }
155
156
186
  log2_sao_offset_scale_chroma = uvlc;
157
158
186
  return true;
159
188
}
160
161
162
void pps_range_extension::dump(int fd) const
163
0
{
164
0
  FILE* fh;
165
0
  if (fd==1) fh=stdout;
166
0
  else if (fd==2) fh=stderr;
167
0
  else { return; }
168
169
0
#define LOG0(t) log2fh(fh, t)
170
0
#define LOG1(t,d) log2fh(fh, t,d)
171
0
#define LOG2(t,d,e) log2fh(fh, t,d,e)
172
173
0
  LOG0("---------- PPS range-extension ----------\n");
174
0
  LOG1("log2_max_transform_skip_block_size      : %d\n", log2_max_transform_skip_block_size);
175
0
  LOG1("cross_component_prediction_enabled_flag : %d\n", cross_component_prediction_enabled_flag);
176
0
  LOG1("chroma_qp_offset_list_enabled_flag      : %d\n", chroma_qp_offset_list_enabled_flag);
177
0
  if (chroma_qp_offset_list_enabled_flag) {
178
0
    LOG1("diff_cu_chroma_qp_offset_depth          : %d\n", diff_cu_chroma_qp_offset_depth);
179
0
    LOG1("chroma_qp_offset_list_len               : %d\n", chroma_qp_offset_list_len);
180
0
    for (int i=0;i<chroma_qp_offset_list_len;i++) {
181
0
      LOG2("cb_qp_offset_list[%d]                    : %d\n", i,cb_qp_offset_list[i]);
182
0
      LOG2("cr_qp_offset_list[%d]                    : %d\n", i,cr_qp_offset_list[i]);
183
0
    }
184
0
  }
185
186
0
  LOG1("log2_sao_offset_scale_luma              : %d\n", log2_sao_offset_scale_luma);
187
0
  LOG1("log2_sao_offset_scale_chroma            : %d\n", log2_sao_offset_scale_chroma);
188
0
#undef LOG2
189
0
#undef LOG1
190
0
#undef LOG0
191
0
}
192
193
194
195
196
197
pic_parameter_set::pic_parameter_set()
198
11.4k
{
199
11.4k
  reset();
200
11.4k
}
201
202
203
pic_parameter_set::~pic_parameter_set()
204
11.4k
{
205
11.4k
}
206
207
208
void pic_parameter_set::set_defaults(enum PresetSet)
209
22.8k
{
210
22.8k
  pps_read = false;
211
22.8k
  sps = nullptr;
212
213
22.8k
  pic_parameter_set_id = 0;
214
22.8k
  seq_parameter_set_id = 0;
215
22.8k
  dependent_slice_segments_enabled_flag = 0;
216
22.8k
  sign_data_hiding_flag = 0;
217
22.8k
  cabac_init_present_flag = 0;
218
22.8k
  num_ref_idx_l0_default_active = 1;
219
22.8k
  num_ref_idx_l1_default_active = 1;
220
221
22.8k
  pic_init_qp = 27;
222
22.8k
  constrained_intra_pred_flag = 0;
223
22.8k
  transform_skip_enabled_flag = 0;
224
225
22.8k
  cu_qp_delta_enabled_flag = 0;
226
22.8k
  diff_cu_qp_delta_depth = 0;
227
228
22.8k
  pic_cb_qp_offset = 0;
229
22.8k
  pic_cr_qp_offset = 0;
230
22.8k
  pps_slice_chroma_qp_offsets_present_flag = 0;
231
22.8k
  weighted_pred_flag  = 0;
232
22.8k
  weighted_bipred_flag= 0;
233
22.8k
  output_flag_present_flag = 0;
234
22.8k
  transquant_bypass_enable_flag = 0;
235
22.8k
  entropy_coding_sync_enabled_flag = 0;
236
237
  // --- tiles ---
238
239
22.8k
  tiles_enabled_flag = 0;
240
22.8k
  num_tile_columns = 1;
241
22.8k
  num_tile_rows    = 1;
242
22.8k
  uniform_spacing_flag = 1;
243
244
245
  // --- ---
246
247
22.8k
  loop_filter_across_tiles_enabled_flag = 1;
248
22.8k
  pps_loop_filter_across_slices_enabled_flag = 1;
249
250
250k
  for (int i=0;i<DE265_MAX_TILE_COLUMNS;i++) { colWidth[i]=0; }
251
250k
  for (int i=0;i<DE265_MAX_TILE_ROWS;i++)    { rowHeight[i]=0; }
252
273k
  for (int i=0;i<=DE265_MAX_TILE_COLUMNS;i++) { colBd[i]=0; }
253
273k
  for (int i=0;i<=DE265_MAX_TILE_ROWS;i++)    { rowBd[i]=0; }
254
255
22.8k
  scan.reset();
256
257
258
22.8k
  Log2MinCuQpDeltaSize = 0;
259
260
22.8k
  deblocking_filter_control_present_flag = 0;
261
22.8k
  deblocking_filter_override_enabled_flag = 0;
262
22.8k
  pic_disable_deblocking_filter_flag = 0;
263
264
22.8k
  beta_offset = 0;
265
22.8k
  tc_offset   = 0;
266
267
22.8k
  pic_scaling_list_data_present_flag = 0;
268
  // TODO struct scaling_list_data scaling_list;
269
270
22.8k
  lists_modification_present_flag = 0;
271
22.8k
  log2_parallel_merge_level = 2;
272
273
22.8k
  num_extra_slice_header_bits = 0;
274
22.8k
  slice_segment_header_extension_present_flag = 0;
275
22.8k
  pps_extension_flag = 0;
276
277
22.8k
  pps_range_extension_flag = 0;
278
22.8k
  pps_multilayer_extension_flag = 0;
279
22.8k
  pps_extension_6bits = 0;
280
281
22.8k
  range_extension.reset();
282
22.8k
}
283
284
285
bool pic_parameter_set::read(bitreader* br, decoder_context* ctx)
286
11.4k
{
287
11.4k
  reset();
288
289
290
11.4k
  uint32_t uvlc;
291
11.4k
  uvlc = br->get_uvlc();
292
11.4k
  if (uvlc == UVLC_ERROR || uvlc >= DE265_MAX_PPS_SETS) {
293
24
    ctx->add_warning(DE265_WARNING_NONEXISTING_PPS_REFERENCED, false);
294
24
    return false;
295
24
  }
296
11.3k
  pic_parameter_set_id = uvlc;
297
298
11.3k
  uvlc = br->get_uvlc();
299
11.3k
  if (uvlc == UVLC_ERROR || uvlc >= DE265_MAX_SPS_SETS) {
300
10
    ctx->add_warning(DE265_WARNING_NONEXISTING_SPS_REFERENCED, false);
301
10
    return false;
302
10
  }
303
11.3k
  seq_parameter_set_id = uvlc;
304
305
11.3k
  dependent_slice_segments_enabled_flag = br->get_bits(1);
306
11.3k
  output_flag_present_flag = br->get_bits(1);
307
11.3k
  num_extra_slice_header_bits = br->get_bits(3);
308
11.3k
  sign_data_hiding_flag = br->get_bits(1);
309
11.3k
  cabac_init_present_flag = br->get_bits(1);
310
11.3k
  uvlc = br->get_uvlc();
311
11.3k
  if (uvlc == UVLC_ERROR || uvlc > 15) {
312
13
    ctx->add_warning(DE265_WARNING_PPS_HEADER_INVALID, false);
313
13
    return false;
314
13
  }
315
11.3k
  num_ref_idx_l0_default_active = uvlc + 1;
316
317
11.3k
  uvlc = br->get_uvlc();
318
11.3k
  if (uvlc == UVLC_ERROR || uvlc > 15) {
319
24
    ctx->add_warning(DE265_WARNING_PPS_HEADER_INVALID, false);
320
24
    return false;
321
24
  }
322
11.3k
  num_ref_idx_l1_default_active = uvlc + 1;
323
324
325
11.3k
  if (!ctx->has_sps(seq_parameter_set_id)) {
326
733
    ctx->add_warning(DE265_WARNING_NONEXISTING_SPS_REFERENCED, false);
327
733
    return false;
328
733
  }
329
330
10.6k
  sps = ctx->get_shared_sps(seq_parameter_set_id);
331
332
10.6k
  {
333
10.6k
    int32_t svlc;
334
    // init_qp_minus26 shall be in [-(26 + QpBdOffset_Y), +25] (Sec. 7.4.3.3.1)
335
10.6k
    if ((svlc = br->get_svlc()) == SVLC_ERROR ||
336
10.6k
        svlc < -(26 + sps->QpBdOffset_Y) || svlc > 25) {
337
6
      ctx->add_warning(DE265_WARNING_PPS_HEADER_INVALID, false);
338
6
      return false;
339
6
    }
340
10.5k
    pic_init_qp = svlc + 26;
341
10.5k
  }
342
343
0
  constrained_intra_pred_flag = br->get_bits(1);
344
10.5k
  transform_skip_enabled_flag = br->get_bits(1);
345
10.5k
  cu_qp_delta_enabled_flag = br->get_bits(1);
346
347
10.5k
  if (cu_qp_delta_enabled_flag) {
348
    // diff_cu_qp_delta_depth shall be in [0, log2_diff_max_min_luma_coding_block_size] (Sec. 7.4.3.3.1)
349
8.06k
    if ((uvlc = br->get_uvlc()) == UVLC_ERROR ||
350
8.05k
        uvlc > sps->log2_diff_max_min_luma_coding_block_size) {
351
4
      ctx->add_warning(DE265_WARNING_PPS_HEADER_INVALID, false);
352
4
      return false;
353
4
    }
354
8.05k
    diff_cu_qp_delta_depth = uvlc;
355
8.05k
  } else {
356
2.53k
    diff_cu_qp_delta_depth = 0;
357
2.53k
  }
358
359
10.5k
  {
360
10.5k
    int32_t svlc;
361
10.5k
    if ((svlc = br->get_svlc()) == SVLC_ERROR) {
362
7
      ctx->add_warning(DE265_WARNING_PPS_HEADER_INVALID, false);
363
7
      return false;
364
7
    }
365
10.5k
    pic_cb_qp_offset = svlc;
366
10.5k
  }
367
368
0
  {
369
10.5k
    int32_t svlc;
370
10.5k
    if ((svlc = br->get_svlc()) == SVLC_ERROR) {
371
4
      ctx->add_warning(DE265_WARNING_PPS_HEADER_INVALID, false);
372
4
      return false;
373
4
    }
374
10.5k
    pic_cr_qp_offset = svlc;
375
10.5k
  }
376
377
0
  pps_slice_chroma_qp_offsets_present_flag = br->get_bits(1);
378
10.5k
  weighted_pred_flag = br->get_bits(1);
379
10.5k
  weighted_bipred_flag = br->get_bits(1);
380
10.5k
  transquant_bypass_enable_flag = br->get_bits(1);
381
10.5k
  tiles_enabled_flag = br->get_bits(1);
382
10.5k
  entropy_coding_sync_enabled_flag = br->get_bits(1);
383
384
385
  // --- tiles ---
386
387
10.5k
  if (tiles_enabled_flag) {
388
542
    if ((uvlc = br->get_uvlc()) == UVLC_ERROR ||
389
539
        uvlc + 1 > DE265_MAX_TILE_COLUMNS ||
390
534
        uvlc + 1 > sps->PicWidthInCtbsY) {
391
13
      ctx->add_warning(DE265_WARNING_PPS_HEADER_INVALID, false);
392
13
      return false;
393
13
    }
394
529
    num_tile_columns = uvlc + 1;
395
396
529
    if ((uvlc = br->get_uvlc()) == UVLC_ERROR ||
397
528
        uvlc + 1 > DE265_MAX_TILE_ROWS ||
398
522
        uvlc + 1 > sps->PicHeightInCtbsY) {
399
11
      ctx->add_warning(DE265_WARNING_PPS_HEADER_INVALID, false);
400
11
      return false;
401
11
    }
402
518
    num_tile_rows = uvlc + 1;
403
404
518
    uniform_spacing_flag = br->get_bits(1);
405
406
518
    if (uniform_spacing_flag==false) {
407
275
      uint16_t lastColumnWidth = sps->PicWidthInCtbsY;
408
275
      uint16_t lastRowHeight   = sps->PicHeightInCtbsY;
409
410
350
      for (int i = 0; i < num_tile_columns - 1; i++) {
411
89
        if ((uvlc = br->get_uvlc()) == UVLC_ERROR ||
412
78
            uvlc + 1 >= lastColumnWidth) {
413
14
          ctx->add_warning(DE265_WARNING_PPS_HEADER_INVALID, false);
414
14
          return false;
415
14
        }
416
417
75
        colWidth[i] = uvlc + 1;
418
419
75
        lastColumnWidth -= colWidth[i];
420
75
      }
421
422
261
      colWidth[num_tile_columns - 1] = lastColumnWidth;
423
424
356
      for (int i = 0; i < num_tile_rows - 1; i++) {
425
114
        if ((uvlc = br->get_uvlc()) == UVLC_ERROR ||
426
100
            uvlc + 1 >= lastRowHeight) {
427
19
          ctx->add_warning(DE265_WARNING_PPS_HEADER_INVALID, false);
428
19
          return false;
429
19
        }
430
95
        rowHeight[i] = uvlc + 1;
431
95
        lastRowHeight -= rowHeight[i];
432
95
      }
433
434
435
242
      rowHeight[num_tile_rows-1] = lastRowHeight;
436
242
    }
437
438
485
    loop_filter_across_tiles_enabled_flag = br->get_bits(1);
439
440
10.0k
  } else {
441
10.0k
    num_tile_columns = 1;
442
10.0k
    num_tile_rows    = 1;
443
10.0k
    uniform_spacing_flag = 1;
444
10.0k
    loop_filter_across_tiles_enabled_flag = 0;
445
10.0k
  }
446
447
448
449
  // END tiles
450
451
452
453
10.5k
  beta_offset = 0; // default value
454
10.5k
  tc_offset   = 0; // default value
455
456
10.5k
  pps_loop_filter_across_slices_enabled_flag = br->get_bits(1);
457
10.5k
  deblocking_filter_control_present_flag = br->get_bits(1);
458
10.5k
  if (deblocking_filter_control_present_flag) {
459
6.79k
    deblocking_filter_override_enabled_flag = br->get_bits(1);
460
6.79k
    pic_disable_deblocking_filter_flag = br->get_bits(1);
461
6.79k
    if (!pic_disable_deblocking_filter_flag) {
462
6.60k
      {
463
6.60k
        int32_t svlc;
464
        // pps_beta_offset_div2 shall be in [-6, 6] (Sec. 7.4.3.3.1)
465
6.60k
        if ((svlc = br->get_svlc()) == SVLC_ERROR || svlc < -6 || svlc > 6) {
466
10
    ctx->add_warning(DE265_WARNING_PPS_HEADER_INVALID, false);
467
10
    return false;
468
10
        }
469
6.59k
        beta_offset = svlc * 2;
470
471
        // pps_tc_offset_div2 shall be in [-6, 6] (Sec. 7.4.3.3.1)
472
6.59k
        if ((svlc = br->get_svlc()) == SVLC_ERROR || svlc < -6 || svlc > 6) {
473
18
    ctx->add_warning(DE265_WARNING_PPS_HEADER_INVALID, false);
474
18
    return false;
475
18
        }
476
6.57k
        tc_offset = svlc * 2;
477
6.57k
      }
478
6.57k
    }
479
6.79k
  }
480
3.73k
  else {
481
3.73k
    deblocking_filter_override_enabled_flag = 0;
482
3.73k
    pic_disable_deblocking_filter_flag = 0;
483
3.73k
  }
484
485
486
  // --- scaling list ---
487
488
10.4k
  pic_scaling_list_data_present_flag = br->get_bits(1);
489
490
  // check consistency: if scaling-lists are not enabled, pic_scalign_list_data_present_flag
491
  // must be FALSE
492
10.4k
  if (sps->scaling_list_enable_flag==0 &&
493
9.89k
      pic_scaling_list_data_present_flag != 0) {
494
30
    ctx->add_warning(DE265_WARNING_PPS_HEADER_INVALID, false);
495
30
    return false;
496
30
  }
497
498
10.4k
  if (pic_scaling_list_data_present_flag) {
499
24
    de265_error err = read_scaling_list(br, sps.get(), &scaling_list, true);
500
24
    if (err != DE265_OK) {
501
24
      ctx->add_warning(err, false);
502
24
      return false;
503
24
    }
504
24
  }
505
10.4k
  else {
506
10.4k
    scaling_list = sps->scaling_list;
507
10.4k
  }
508
509
510
511
512
10.4k
  lists_modification_present_flag = br->get_bits(1);
513
10.4k
  if ((uvlc = br->get_uvlc()) == UVLC_ERROR || uvlc > 4) {
514
65
    ctx->add_warning(DE265_WARNING_PPS_HEADER_INVALID, false);
515
65
    return false;
516
65
  }
517
10.3k
  log2_parallel_merge_level = uvlc + 2;
518
519
10.3k
  if (log2_parallel_merge_level-2 > sps->log2_min_luma_coding_block_size-3 +1 +
520
10.3k
      sps->log2_diff_max_min_luma_coding_block_size) {
521
21
    return false;
522
21
  }
523
524
10.3k
  slice_segment_header_extension_present_flag = br->get_bits(1);
525
10.3k
  pps_extension_flag = br->get_bits(1);
526
527
10.3k
  if (pps_extension_flag) {
528
267
    pps_range_extension_flag = br->get_bits(1);
529
267
    pps_multilayer_extension_flag = br->get_bits(1);
530
267
    pps_extension_6bits = br->get_bits(6);
531
532
267
    if (pps_range_extension_flag) {
533
216
      bool success = range_extension.read(br, ctx, this);
534
216
      if (!success) {
535
30
        return false;
536
30
      }
537
216
    }
538
539
    // The reserved extension bits could carry a 3D/SCC PPS extension whose
540
    // payload changes base-layer decoding (e.g. SCC palette / adaptive
541
    // colour transform). We do not parse it, so reject the stream.
542
237
    if (pps_extension_6bits) {
543
18
      ctx->add_warning(DE265_ERROR_NOT_IMPLEMENTED_YET, false);
544
18
      return false;
545
18
    }
546
547
    // The multilayer extension only describes enhancement layers appended
548
    // at the end of the PPS RBSP; skipping its payload does not affect
549
    // base-layer decoding or the parsing of subsequent NAL units, so we
550
    // just warn and continue decoding the base layer.
551
219
    if (pps_multilayer_extension_flag) {
552
13
      ctx->add_warning(DE265_ERROR_NOT_IMPLEMENTED_YET, false);
553
13
    }
554
219
  }
555
556
557
10.3k
  set_derived_values(sps.get());
558
559
10.3k
  pps_read = true;
560
561
10.3k
  return true;
562
10.3k
}
563
564
565
//----------------------------------------------------------------------------
566
// Library-scope cache for the geometry-derived scan tables (HEVC Sec. 6.5).
567
//
568
// The tables depend only on the picture/tile geometry. Many independent decoder
569
// contexts (e.g. libheif tile grids) decode images of the same geometry, so we
570
// compute the tables once and share them read-only via shared_ptr. A small LRU
571
// cache (a few distinct geometries) protected by a mutex serves concurrent
572
// decoders. The compute is done while holding the lock on purpose: a burst of
573
// contexts with the same new geometry then computes the tables exactly once
574
// (the others block briefly and pick up the cached result).
575
//----------------------------------------------------------------------------
576
577
namespace {
578
579
struct pps_scan_key {
580
  uint8_t  log2CtbSize;
581
  uint8_t  log2MinTrafo;
582
  uint16_t picWidthInCtbs, picHeightInCtbs;
583
  uint16_t picWidthInTbs,  picHeightInTbs;
584
  uint32_t picSizeInCtbs,  picSizeInTbs;
585
  uint16_t numTileCols,    numTileRows;
586
  uint16_t colBd[DE265_MAX_TILE_COLUMNS+1];
587
  uint16_t rowBd[DE265_MAX_TILE_ROWS+1];
588
589
6.40k
  bool operator==(const pps_scan_key& o) const {
590
6.40k
    if (log2CtbSize    != o.log2CtbSize    || log2MinTrafo   != o.log2MinTrafo   ||
591
6.33k
        picWidthInCtbs != o.picWidthInCtbs || picHeightInCtbs!= o.picHeightInCtbs||
592
6.28k
        picWidthInTbs  != o.picWidthInTbs  || picHeightInTbs != o.picHeightInTbs ||
593
6.28k
        picSizeInCtbs  != o.picSizeInCtbs  || picSizeInTbs   != o.picSizeInTbs   ||
594
6.28k
        numTileCols    != o.numTileCols    || numTileRows    != o.numTileRows) return false;
595
18.7k
    for (int i=0;i<=numTileCols;i++) if (colBd[i]!=o.colBd[i]) return false;
596
18.7k
    for (int i=0;i<=numTileRows;i++) if (rowBd[i]!=o.rowBd[i]) return false;
597
6.23k
    return true;
598
6.23k
  }
599
};
600
601
// Build the five scan tables from the geometry key (HEVC 6.5.1 + 6.5.2).
602
std::shared_ptr<const pps_scan_tables> compute_scan_tables(const pps_scan_key& k)
603
4.08k
{
604
4.08k
  std::shared_ptr<pps_scan_tables> t = std::make_shared<pps_scan_tables>();
605
4.08k
  t->CtbAddrRStoTS.resize(k.picSizeInCtbs);
606
4.08k
  t->CtbAddrTStoRS.resize(k.picSizeInCtbs);
607
4.08k
  t->TileId       .resize(k.picSizeInCtbs);
608
4.08k
  t->TileIdRS     .resize(k.picSizeInCtbs);
609
4.08k
  t->MinTbAddrZS  .resize(k.picSizeInTbs);
610
611
  // 6.5.1 raster (RS) <-> tile scan (TS) conversion + tile-ID assignment.
612
4.08k
  uint32_t ctbAddrTS = 0;
613
4.08k
  uint32_t tIdx = 0;
614
8.62k
  for (int tileY=0; tileY<k.numTileRows; tileY++) {
615
11.6k
    for (int tileX=0; tileX<k.numTileCols; tileX++) {
616
39.4k
      for (int y=k.rowBd[tileY]; y<k.rowBd[tileY+1]; y++) {
617
328k
        for (int x=k.colBd[tileX]; x<k.colBd[tileX+1]; x++) {
618
295k
          uint32_t ctbAddrRS = y * k.picWidthInCtbs + x;
619
295k
          t->CtbAddrRStoTS[ctbAddrRS] = ctbAddrTS;
620
295k
          t->CtbAddrTStoRS[ctbAddrTS] = ctbAddrRS;
621
295k
          t->TileId  [ctbAddrTS] = tIdx;
622
295k
          t->TileIdRS[ctbAddrRS] = tIdx;
623
295k
          ctbAddrTS++;
624
295k
        }
625
32.3k
      }
626
7.11k
      tIdx++;
627
7.11k
    }
628
4.54k
  }
629
4.08k
  assert(ctbAddrTS == k.picSizeInCtbs);
630
631
  // 6.5.2 Z-scan order array initialization process.
632
4.08k
  const int shift = k.log2CtbSize - k.log2MinTrafo;
633
221k
  for (int y=0; y<k.picHeightInTbs; y++)
634
14.5M
    for (int x=0; x<k.picWidthInTbs; x++) {
635
14.3M
      int tbX = (x<<k.log2MinTrafo)>>k.log2CtbSize;
636
14.3M
      int tbY = (y<<k.log2MinTrafo)>>k.log2CtbSize;
637
14.3M
      int ctbAddrRS = k.picWidthInCtbs*tbY + tbX;
638
639
14.3M
      uint32_t v = t->CtbAddrRStoTS[ctbAddrRS] << (shift*2);
640
14.3M
      int p=0;
641
60.4M
      for (int i=0;i<shift;i++) {
642
46.1M
        int m=1<<i;
643
46.1M
        p += (m & x ? m*m : 0) + (m & y ? 2*m*m : 0);
644
46.1M
      }
645
14.3M
      t->MinTbAddrZS[x + y*k.picWidthInTbs] = v + p;
646
14.3M
    }
647
648
4.08k
  return t;
649
4.08k
}
650
651
class pps_scan_cache {
652
public:
653
10.3k
  std::shared_ptr<const pps_scan_tables> get(const pps_scan_key& key) {
654
10.3k
    std::lock_guard<std::mutex> lock(mMutex);
655
656
10.4k
    for (size_t i=0; i<mEntries.size(); i++) {
657
6.40k
      if (mEntries[i].key == key) {
658
6.23k
        std::shared_ptr<const pps_scan_tables> tables = mEntries[i].tables;
659
6.23k
        if (i != 0) {  // move-to-front (LRU)
660
72
          Entry e = mEntries[i];
661
72
          mEntries.erase(mEntries.begin()+i);
662
72
          mEntries.insert(mEntries.begin(), e);
663
72
        }
664
6.23k
        return tables;
665
6.23k
      }
666
6.40k
    }
667
668
    // Miss: compute while holding the lock so that a burst of concurrent decoders
669
    // with the same new geometry computes the tables exactly once.
670
4.07k
    std::shared_ptr<const pps_scan_tables> tables = compute_scan_tables(key);
671
4.07k
    mEntries.insert(mEntries.begin(), Entry{key, tables});
672
4.07k
    if (mEntries.size() > kMaxEntries) mEntries.pop_back();  // evict LRU
673
4.07k
    return tables;
674
10.3k
  }
675
676
private:
677
  static const size_t kMaxEntries = 3;
678
  struct Entry { pps_scan_key key; std::shared_ptr<const pps_scan_tables> tables; };
679
  std::mutex mMutex;
680
  std::vector<Entry> mEntries;
681
};
682
683
// Owned by the de265_init()/de265_free() lifecycle (see de265.cc). It is created
684
// and destroyed (under de265's init mutex) while no decoder is running, so it is
685
// read locklessly during decoding; the cache's own mutex guards concurrent get()
686
// calls. Atomic so the publish/read of the pointer is well-defined.
687
std::atomic<pps_scan_cache*> g_pps_scan_cache{nullptr};
688
689
std::shared_ptr<const pps_scan_tables> get_pps_scan_tables(const pps_scan_key& key)
690
10.3k
{
691
10.3k
  pps_scan_cache* cache = g_pps_scan_cache.load(std::memory_order_acquire);
692
10.3k
  if (cache) return cache->get(key);
693
18.4E
  return compute_scan_tables(key);  // library not initialized: compute without caching
694
10.3k
}
695
696
} // namespace
697
698
699
void pps_scan_cache_init()
700
20.6k
{
701
20.6k
  if (!g_pps_scan_cache.load(std::memory_order_relaxed)) {
702
20.6k
    g_pps_scan_cache.store(new pps_scan_cache(), std::memory_order_release);
703
20.6k
  }
704
20.6k
}
705
706
void pps_scan_cache_free()
707
20.6k
{
708
20.6k
  delete g_pps_scan_cache.exchange(nullptr, std::memory_order_acq_rel);
709
20.6k
}
710
711
712
void pic_parameter_set::set_derived_values(const seq_parameter_set* sps)
713
10.3k
{
714
10.3k
  Log2MinCuQpDeltaSize = sps->Log2CtbSizeY - diff_cu_qp_delta_depth;
715
716
10.3k
  Log2MinCuChromaQpOffsetSize = sps->Log2CtbSizeY - range_extension.diff_cu_chroma_qp_offset_depth;
717
10.3k
  Log2MaxTransformSkipSize = range_extension.log2_max_transform_skip_block_size;
718
719
10.3k
  if (uniform_spacing_flag) {
720
721
    // set columns widths
722
723
10.0k
    int *const colPos = static_cast<int*>(alloca((num_tile_columns+1) * sizeof(int)));
724
725
30.9k
    for (int i=0;i<=num_tile_columns;i++) {
726
20.8k
      colPos[i] = i*sps->PicWidthInCtbsY / num_tile_columns;
727
20.8k
    }
728
20.8k
    for (int i=0;i<num_tile_columns;i++) {
729
10.8k
      colWidth[i] = colPos[i+1] - colPos[i];
730
10.8k
    }
731
732
    // set row heights
733
734
10.0k
    int *const rowPos = static_cast<int*>(alloca((num_tile_rows+1) * sizeof(int)));
735
736
30.6k
    for (int i=0;i<=num_tile_rows;i++) {
737
20.5k
      rowPos[i] = i*sps->PicHeightInCtbsY / num_tile_rows;
738
20.5k
    }
739
20.5k
    for (int i=0;i<num_tile_rows;i++) {
740
10.4k
      rowHeight[i] = rowPos[i+1] - rowPos[i];
741
10.4k
    }
742
10.0k
  }
743
744
745
  // set tile boundaries
746
747
10.3k
  colBd[0]=0;
748
21.3k
  for (int i=0;i<num_tile_columns;i++) {
749
11.0k
    colBd[i+1] = colBd[i] + colWidth[i];
750
11.0k
  }
751
752
10.3k
  rowBd[0]=0;
753
21.0k
  for (int i=0;i<num_tile_rows;i++) {
754
10.7k
    rowBd[i+1] = rowBd[i] + rowHeight[i];
755
10.7k
  }
756
757
758
759
  // The derived scan tables (Sec. 6.5.1 + 6.5.2) depend only on the picture/tile
760
  // geometry computed above. Build the geometry key and fetch the shared tables
761
  // from the library-scope cache (computing+caching them on a miss). This avoids
762
  // recomputing the (potentially large) MinTbAddrZS table for every decoder
763
  // context when many contexts decode images of the same geometry.
764
765
10.3k
  pps_scan_key key;
766
10.3k
  memset(&key, 0, sizeof(key));   // zero padding/unused tile entries for clean compares
767
10.3k
  key.log2CtbSize     = sps->Log2CtbSizeY;
768
10.3k
  key.log2MinTrafo    = sps->Log2MinTrafoSize;
769
10.3k
  key.picWidthInCtbs  = sps->PicWidthInCtbsY;
770
10.3k
  key.picHeightInCtbs = sps->PicHeightInCtbsY;
771
10.3k
  key.picWidthInTbs   = sps->PicWidthInTbsY;
772
10.3k
  key.picHeightInTbs  = sps->PicHeightInTbsY;
773
10.3k
  key.picSizeInCtbs   = sps->PicSizeInCtbsY;
774
10.3k
  key.picSizeInTbs    = sps->PicSizeInTbsY;
775
10.3k
  key.numTileCols     = num_tile_columns;
776
10.3k
  key.numTileRows     = num_tile_rows;
777
31.6k
  for (int i=0;i<=num_tile_columns;i++) key.colBd[i] = colBd[i];
778
31.3k
  for (int i=0;i<=num_tile_rows;   i++) key.rowBd[i] = rowBd[i];
779
780
10.3k
  scan = get_pps_scan_tables(key);
781
10.3k
}
782
783
784
bool pic_parameter_set::write(error_queue* errqueue, CABAC_encoder& out,
785
                              const seq_parameter_set* sps)
786
0
{
787
0
  if (pic_parameter_set_id >= DE265_MAX_PPS_SETS) {
788
0
    errqueue->add_warning(DE265_WARNING_NONEXISTING_PPS_REFERENCED, false);
789
0
    return false;
790
0
  }
791
0
  out.write_uvlc(pic_parameter_set_id);
792
793
0
  if (seq_parameter_set_id >= DE265_MAX_SPS_SETS) {
794
0
    errqueue->add_warning(DE265_WARNING_NONEXISTING_SPS_REFERENCED, false);
795
0
    return false;
796
0
  }
797
0
  out.write_uvlc(seq_parameter_set_id);
798
799
0
  out.write_bit(dependent_slice_segments_enabled_flag);
800
0
  out.write_bit(output_flag_present_flag);
801
0
  out.write_bits(num_extra_slice_header_bits,3);
802
0
  out.write_bit(sign_data_hiding_flag);
803
0
  out.write_bit(cabac_init_present_flag);
804
0
  out.write_uvlc(num_ref_idx_l0_default_active-1);
805
0
  out.write_uvlc(num_ref_idx_l1_default_active-1);
806
807
0
  out.write_svlc(pic_init_qp-26);
808
809
0
  out.write_bit(constrained_intra_pred_flag);
810
0
  out.write_bit(transform_skip_enabled_flag);
811
0
  out.write_bit(cu_qp_delta_enabled_flag);
812
813
0
  if (cu_qp_delta_enabled_flag) {
814
0
    out.write_uvlc(diff_cu_qp_delta_depth);
815
0
  }
816
817
0
  out.write_svlc(pic_cb_qp_offset);
818
0
  out.write_svlc(pic_cr_qp_offset);
819
820
0
  out.write_bit(pps_slice_chroma_qp_offsets_present_flag);
821
0
  out.write_bit(weighted_pred_flag);
822
0
  out.write_bit(weighted_bipred_flag);
823
0
  out.write_bit(transquant_bypass_enable_flag);
824
0
  out.write_bit(tiles_enabled_flag);
825
0
  out.write_bit(entropy_coding_sync_enabled_flag);
826
827
828
  // --- tiles ---
829
830
0
  if (tiles_enabled_flag) {
831
0
    if (num_tile_columns > DE265_MAX_TILE_COLUMNS) {
832
0
      errqueue->add_warning(DE265_WARNING_PPS_HEADER_INVALID, false);
833
0
      return false;
834
0
    }
835
0
    out.write_uvlc(num_tile_columns-1);
836
837
0
    if (num_tile_rows > DE265_MAX_TILE_ROWS) {
838
0
      errqueue->add_warning(DE265_WARNING_PPS_HEADER_INVALID, false);
839
0
      return false;
840
0
    }
841
0
    out.write_uvlc(num_tile_rows-1);
842
843
0
    out.write_bit(uniform_spacing_flag);
844
845
0
    if (uniform_spacing_flag==false) {
846
0
      for (int i=0; i<num_tile_columns-1; i++)
847
0
        {
848
0
          out.write_uvlc(colWidth[i]-1);
849
0
        }
850
851
0
      for (int i=0; i<num_tile_rows-1; i++)
852
0
        {
853
0
          out.write_uvlc(rowHeight[i]-1);
854
0
        }
855
0
    }
856
857
0
    out.write_bit(loop_filter_across_tiles_enabled_flag);
858
0
  }
859
860
861
0
  out.write_bit(pps_loop_filter_across_slices_enabled_flag);
862
0
  out.write_bit(deblocking_filter_control_present_flag);
863
864
0
  if (deblocking_filter_control_present_flag) {
865
0
    out.write_bit(deblocking_filter_override_enabled_flag);
866
0
    out.write_bit(pic_disable_deblocking_filter_flag);
867
868
0
    if (!pic_disable_deblocking_filter_flag) {
869
0
      out.write_svlc(beta_offset/2);
870
0
      out.write_svlc(tc_offset  /2);
871
0
    }
872
0
  }
873
874
875
  // --- scaling list ---
876
877
0
  out.write_bit(pic_scaling_list_data_present_flag);
878
879
  // check consistency: if scaling-lists are not enabled, pic_scalign_list_data_present_flag
880
  // must be FALSE
881
0
  if (sps->scaling_list_enable_flag==0 &&
882
0
      pic_scaling_list_data_present_flag != 0) {
883
0
    errqueue->add_warning(DE265_WARNING_PPS_HEADER_INVALID, false);
884
0
    return false;
885
0
  }
886
887
0
  if (pic_scaling_list_data_present_flag) {
888
0
    de265_error err = write_scaling_list(out, sps, &scaling_list, true);
889
0
    if (err != DE265_OK) {
890
0
      errqueue->add_warning(err, false);
891
0
      return false;
892
0
    }
893
0
  }
894
895
896
897
0
  out.write_bit(lists_modification_present_flag);
898
0
  out.write_uvlc(log2_parallel_merge_level-2);
899
900
0
  out.write_bit(slice_segment_header_extension_present_flag);
901
0
  out.write_bit(pps_extension_flag);
902
903
0
  if (pps_extension_flag) {
904
    //assert(false);
905
    /*
906
      while( more_rbsp_data() )
907
908
      pps_extension_data_flag
909
      u(1)
910
      rbsp_trailing_bits()
911
912
      }
913
    */
914
0
  }
915
916
917
0
  pps_read = true;
918
919
0
  return true;
920
0
}
921
922
923
void pic_parameter_set::dump(int fd) const
924
0
{
925
0
  FILE* fh;
926
0
  if (fd==1) fh=stdout;
927
0
  else if (fd==2) fh=stderr;
928
0
  else { return; }
929
930
0
#define LOG0(t) log2fh(fh, t)
931
0
#define LOG1(t,d) log2fh(fh, t,d)
932
933
0
  LOG0("----------------- PPS -----------------\n");
934
0
  LOG1("pic_parameter_set_id       : %d\n", pic_parameter_set_id);
935
0
  LOG1("seq_parameter_set_id       : %d\n", seq_parameter_set_id);
936
0
  LOG1("dependent_slice_segments_enabled_flag : %d\n", dependent_slice_segments_enabled_flag);
937
0
  LOG1("sign_data_hiding_flag      : %d\n", sign_data_hiding_flag);
938
0
  LOG1("cabac_init_present_flag    : %d\n", cabac_init_present_flag);
939
0
  LOG1("num_ref_idx_l0_default_active : %d\n", num_ref_idx_l0_default_active);
940
0
  LOG1("num_ref_idx_l1_default_active : %d\n", num_ref_idx_l1_default_active);
941
942
0
  LOG1("pic_init_qp                : %d\n", pic_init_qp);
943
0
  LOG1("constrained_intra_pred_flag: %d\n", constrained_intra_pred_flag);
944
0
  LOG1("transform_skip_enabled_flag: %d\n", transform_skip_enabled_flag);
945
0
  LOG1("cu_qp_delta_enabled_flag   : %d\n", cu_qp_delta_enabled_flag);
946
947
0
  if (cu_qp_delta_enabled_flag) {
948
0
    LOG1("diff_cu_qp_delta_depth     : %d\n", diff_cu_qp_delta_depth);
949
0
  }
950
951
0
  LOG1("pic_cb_qp_offset             : %d\n", pic_cb_qp_offset);
952
0
  LOG1("pic_cr_qp_offset             : %d\n", pic_cr_qp_offset);
953
0
  LOG1("pps_slice_chroma_qp_offsets_present_flag : %d\n", pps_slice_chroma_qp_offsets_present_flag);
954
0
  LOG1("weighted_pred_flag           : %d\n", weighted_pred_flag);
955
0
  LOG1("weighted_bipred_flag         : %d\n", weighted_bipred_flag);
956
0
  LOG1("output_flag_present_flag     : %d\n", output_flag_present_flag);
957
0
  LOG1("transquant_bypass_enable_flag: %d\n", transquant_bypass_enable_flag);
958
0
  LOG1("tiles_enabled_flag           : %d\n", tiles_enabled_flag);
959
0
  LOG1("entropy_coding_sync_enabled_flag: %d\n", entropy_coding_sync_enabled_flag);
960
961
0
  if (tiles_enabled_flag) {
962
0
    LOG1("num_tile_columns    : %d\n", num_tile_columns);
963
0
    LOG1("num_tile_rows       : %d\n", num_tile_rows);
964
0
    LOG1("uniform_spacing_flag: %d\n", uniform_spacing_flag);
965
966
0
    LOG0("tile column boundaries: ");
967
0
    for (int i=0;i<=num_tile_columns;i++) {
968
0
      LOG1("*%d ",colBd[i]);
969
0
    }
970
0
    LOG0("*\n");
971
972
0
    LOG0("tile row boundaries: ");
973
0
    for (int i=0;i<=num_tile_rows;i++) {
974
0
      LOG1("*%d ",rowBd[i]);
975
0
    }
976
0
    LOG0("*\n");
977
978
  //if( !uniform_spacing_flag ) {
979
  /*
980
            for( i = 0; i < num_tile_columns_minus1; i++ )
981
982
              column_width_minus1[i]
983
                ue(v)
984
                for( i = 0; i < num_tile_rows_minus1; i++ )
985
986
                  row_height_minus1[i]
987
                    ue(v)
988
                    }
989
  */
990
991
0
    LOG1("loop_filter_across_tiles_enabled_flag : %d\n", loop_filter_across_tiles_enabled_flag);
992
0
  }
993
994
0
  LOG1("pps_loop_filter_across_slices_enabled_flag: %d\n", pps_loop_filter_across_slices_enabled_flag);
995
0
  LOG1("deblocking_filter_control_present_flag: %d\n", deblocking_filter_control_present_flag);
996
997
0
  if (deblocking_filter_control_present_flag) {
998
0
    LOG1("deblocking_filter_override_enabled_flag: %d\n", deblocking_filter_override_enabled_flag);
999
0
    LOG1("pic_disable_deblocking_filter_flag: %d\n", pic_disable_deblocking_filter_flag);
1000
1001
0
    LOG1("beta_offset:  %d\n", beta_offset);
1002
0
    LOG1("tc_offset:    %d\n", tc_offset);
1003
0
  }
1004
1005
0
  LOG1("pic_scaling_list_data_present_flag: %d\n", pic_scaling_list_data_present_flag);
1006
0
  if (pic_scaling_list_data_present_flag) {
1007
    //scaling_list_data()
1008
0
  }
1009
1010
0
  LOG1("lists_modification_present_flag: %d\n", lists_modification_present_flag);
1011
0
  LOG1("log2_parallel_merge_level      : %d\n", log2_parallel_merge_level);
1012
0
  LOG1("num_extra_slice_header_bits    : %d\n", num_extra_slice_header_bits);
1013
0
  LOG1("slice_segment_header_extension_present_flag : %d\n", slice_segment_header_extension_present_flag);
1014
0
  LOG1("pps_extension_flag            : %d\n", pps_extension_flag);
1015
0
  LOG1("pps_range_extension_flag      : %d\n", pps_range_extension_flag);
1016
0
  LOG1("pps_multilayer_extension_flag : %d\n", pps_multilayer_extension_flag);
1017
0
  LOG1("pps_extension_6bits           : %d\n", pps_extension_6bits);
1018
1019
0
  LOG1("Log2MinCuQpDeltaSize          : %d\n", Log2MinCuQpDeltaSize);
1020
0
  LOG1("Log2MinCuChromaQpOffsetSize (RExt) : %d\n", Log2MinCuChromaQpOffsetSize);
1021
0
  LOG1("Log2MaxTransformSkipSize    (RExt) : %d\n", Log2MaxTransformSkipSize);
1022
1023
0
#undef LOG0
1024
0
#undef LOG1
1025
1026
1027
0
  if (pps_range_extension_flag) {
1028
0
    range_extension.dump(fd);
1029
0
  }
1030
0
}
1031
1032
1033
bool pic_parameter_set::is_tile_start_CTB(int ctbX,int ctbY) const
1034
19.1k
{
1035
  // fast check
1036
19.1k
  if (tiles_enabled_flag==0) {
1037
51
    return ctbX == 0 && ctbY == 0;
1038
51
  }
1039
1040
56.6k
  for (int i=0;i<num_tile_columns;i++)
1041
46.5k
    if (colBd[i]==ctbX)
1042
9.01k
      {
1043
28.3k
        for (int k=0;k<num_tile_rows;k++)
1044
23.0k
          if (rowBd[k]==ctbY)
1045
3.71k
            {
1046
3.71k
              return true;
1047
3.71k
            }
1048
1049
5.29k
        return false;
1050
9.01k
      }
1051
1052
10.0k
  return false;
1053
19.0k
}