Coverage Report

Created: 2026-09-14 06:44

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/work/libde265/libde265/decctx.h
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
#ifndef DE265_DECCTX_H
22
#define DE265_DECCTX_H
23
24
#include "libde265/vps.h"
25
#include "libde265/sps.h"
26
#include "libde265/pps.h"
27
#include "libde265/nal.h"
28
#include "libde265/slice.h"
29
#include "libde265/image.h"
30
#include "libde265/motion.h"
31
#include "libde265/de265.h"
32
#include "libde265/dpb.h"
33
#include "libde265/sei.h"
34
#include "libde265/threads.h"
35
#include "libde265/acceleration.h"
36
#include "libde265/nal-parser.h"
37
38
#include <array>
39
#include <memory>
40
#include <mutex>
41
42
constexpr int DE265_MAX_VPS_SETS = 16;   // this is the maximum as defined in the standard
43
constexpr int DE265_MAX_SPS_SETS = 16;   // this is the maximum as defined in the standard
44
constexpr int DE265_MAX_PPS_SETS = 64;   // this is the maximum as defined in the standard
45
46
constexpr int MAX_WARNINGS = 20;
47
48
49
class slice_segment_header;
50
class image_unit;
51
class slice_unit;
52
class decoder_context;
53
54
55
class thread_context
56
{
57
public:
58
  thread_context();
59
60
  uint32_t CtbAddrInRS;
61
  uint32_t CtbAddrInTS;
62
63
  uint16_t CtbX, CtbY;
64
65
66
  // motion vectors
67
68
  PBMotionCoding motion;
69
70
71
  // prediction
72
73
  // enum IntraPredMode IntraPredModeC[4]; // chroma intra-prediction mode for current CB
74
  int ResScaleVal;
75
76
77
  // residual data
78
79
  uint8_t cu_transquant_bypass_flag;
80
  uint8_t transform_skip_flag[3];
81
  uint8_t explicit_rdpcm_flag;
82
  uint8_t explicit_rdpcm_dir;
83
84
  // we need 16 bytes of extra memory (8*int16) to shift the base for the
85
  // alignment required for SSE code !
86
  int16_t _coeffBuf[(32*32)+8];
87
  int16_t *coeffBuf; // the base pointer for into _coeffBuf, aligned to 16 bytes
88
89
  int16_t coeffList[3][32*32];
90
  int16_t coeffPos[3][32*32];
91
  int16_t nCoeff[3];
92
93
  int32_t residual_luma[32*32]; // only used when cross-comp-prediction is enabled
94
95
96
  // quantization
97
98
  int IsCuQpDeltaCoded = 0;
99
  int CuQpDelta = 0;
100
  int IsCuChromaQpOffsetCoded = 0;
101
  int CuQpOffsetCb = 0, CuQpOffsetCr = 0;
102
103
  int currentQPY;
104
  int currentQG_x, currentQG_y;
105
  int lastQPYinPreviousQG;
106
107
  int qPYPrime, qPCbPrime, qPCrPrime;
108
109
  CABAC_decoder cabac_decoder;
110
111
  context_model_table ctx_model;
112
  uint8_t StatCoeff[4];
113
114
  decoder_context* decctx = nullptr;
115
  struct de265_image *img = nullptr;
116
  slice_segment_header* shdr = nullptr;
117
118
  image_unit* imgunit = nullptr;
119
  slice_unit* sliceunit = nullptr;
120
  thread_task* task; // executing thread_task or nullptr if not multi-threaded
121
122
  thread_context(const thread_context&) = delete;
123
  thread_context& operator=(const thread_context&) = delete;
124
};
125
126
127
128
class error_queue
129
{
130
 public:
131
  void add_warning(de265_error warning, bool once);
132
  de265_error get_warning();
133
134
 private:
135
  std::mutex m_mutex;
136
  std::vector<de265_error> warnings;
137
  std::vector<de265_error> warnings_shown; // warnings that have already occurred
138
};
139
140
141
142
class slice_unit
143
{
144
public:
145
  slice_unit(decoder_context* decctx);
146
  ~slice_unit();
147
148
  std::unique_ptr<NAL_unit> nal;   // we are the owner
149
  slice_segment_header* shdr;  // not the owner (de265_image is owner)
150
  bitreader reader;
151
152
  image_unit* imgunit;
153
154
  bool flush_reorder_buffer;
155
156
157
  // decoding status
158
159
  enum SliceDecodingProgress { Unprocessed,
160
                               InProgress,
161
                               Decoded
162
  } state;
163
164
  de265_progress_lock finished_threads;
165
  int nThreads;
166
167
  int first_decoded_CTB_RS; // TODO
168
  int last_decoded_CTB_RS;  // TODO
169
170
  void allocate_thread_contexts(int n);
171
22.8k
  thread_context* get_thread_context(int n) {
172
22.8k
    assert(n < nThreadContexts);
173
22.9k
    return &thread_contexts[n];
174
22.8k
  }
175
0
  int num_thread_contexts() const { return nThreadContexts; }
176
177
private:
178
  thread_context* thread_contexts; /* NOTE: cannot use std::vector, because thread_context has
179
                                      no copy constructor. */
180
  int nThreadContexts;
181
182
public:
183
  decoder_context* ctx;
184
185
  slice_unit(const slice_unit&) = delete;
186
  slice_unit& operator=(const slice_unit&) = delete;
187
};
188
189
190
class image_unit
191
{
192
public:
193
  image_unit();
194
  ~image_unit();
195
196
  de265_image* img = nullptr;
197
  de265_image  sao_output; // if SAO is used, this is allocated and used as SAO output buffer
198
199
  std::vector<slice_unit*> slice_units;
200
  std::vector<sei_message> suffix_SEIs;
201
202
8.64k
  slice_unit* get_next_unprocessed_slice_segment() const {
203
9.34k
    for (size_t i=0;i<slice_units.size();i++) {
204
8.98k
      if (slice_units[i]->state == slice_unit::Unprocessed) {
205
8.28k
        return slice_units[i];
206
8.28k
      }
207
8.98k
    }
208
209
360
    return nullptr;
210
8.64k
  }
211
212
8.36k
  slice_unit* get_prev_slice_segment(slice_unit* s) const {
213
8.36k
    for (size_t i=1; i<slice_units.size(); i++) {
214
382
      if (slice_units[i]==s) {
215
382
        return slice_units[i-1];
216
382
      }
217
382
    }
218
219
7.98k
    return nullptr;
220
8.36k
  }
221
222
8.57k
  slice_unit* get_next_slice_segment(slice_unit* s) const {
223
8.87k
    for (size_t i=0; i<slice_units.size()-1; i++) {
224
602
      if (slice_units[i]==s) {
225
301
        return slice_units[i+1];
226
301
      }
227
602
    }
228
229
8.27k
    return nullptr;
230
8.57k
  }
231
232
0
  void dump_slices() const {
233
0
    for (size_t i=0; i<slice_units.size(); i++) {
234
0
      printf("[%zu] = %p\n",i,static_cast<void*>(slice_units[i]));
235
0
    }
236
0
  }
237
238
8.43k
  bool all_slice_segments_processed() const {
239
8.43k
    if (slice_units.size()==0) return true;
240
8.43k
    if (slice_units.back()->state != slice_unit::Unprocessed) return true;
241
0
    return false;
242
8.43k
  }
243
244
8.28k
  bool is_first_slice_segment(const slice_unit* s) const {
245
8.28k
    if (slice_units.size()==0) return false;
246
8.28k
    return (slice_units[0] == s);
247
8.28k
  }
248
249
  enum { Invalid, // headers not read yet
250
         Unknown, // SPS/PPS available
251
         Reference, // will be used as reference
252
         Leaf       // not a reference picture
253
  } role = Invalid;
254
255
  enum { Unprocessed,
256
         InProgress,
257
         Decoded,
258
         Dropped         // will not be decoded
259
  } state = Unprocessed;
260
261
  std::vector<thread_task*> tasks; // we are the owner
262
263
  /* Saved context models for WPP.
264
     There is one saved model for the initialization of each CTB row.
265
     The array is unused for non-WPP streams.
266
267
     Threading: context_model_table is a reference-counted handle (model
268
     pointer plus refcount pointer) that is not thread-safe, so each slot is
269
     touched by exactly one producer and one consumer and never concurrently.
270
     The row task of row N stores into ctx_models[N] after decoding CTB x=1
271
     and only then signals CTB_PROGRESS_PREFILTER for that CTB; the row task
272
     of row N+1 waits for that progress before it copies and releases the
273
     slot. The acquire/release ordering of de265_progress_lock makes the
274
     store visible to the consumer, so no lock is needed. This relies on the
275
     wait never being skipped because of stale progress: slice segments must
276
     arrive in increasing address order (slice_segment_order_is_valid()) and
277
     decode_slice_unit_WPP() resets the progress of the rows it schedules
278
     (GHSA-xp3h-6f5r-8cxp). */
279
  std::vector<context_model_table> ctx_models;  // TODO: move this into image ?
280
281
  /* Saved StatCoeff[] (persistent_rice_adaptation state) parallel to ctx_models.
282
     Per HEVC RExt, this state must be carried across WPP CTB rows together
283
     with the CABAC context. */
284
  std::vector<std::array<uint8_t, 4>> StatCoeff_models;
285
};
286
287
288
class base_context : public error_queue
289
{
290
 public:
291
  base_context();
292
42.2k
  virtual ~base_context() { }
293
294
  // --- accelerated DSP functions ---
295
296
  void set_acceleration_functions(enum de265_acceleration);
297
298
  struct acceleration_functions acceleration; // CPU optimized functions
299
300
  //virtual /* */ de265_image* get_image(uint16_t dpb_index)       { return dpb.get_image(dpb_index); }
301
  virtual const de265_image* get_image(uint16_t frame_id) const = 0;
302
  virtual bool has_image(uint16_t frame_id) const = 0;
303
};
304
305
306
class decoder_context : public base_context {
307
 public:
308
  decoder_context();
309
  ~decoder_context();
310
311
  de265_error start_thread_pool(int nThreads);
312
  void        stop_thread_pool();
313
314
  void reset();
315
316
11.9k
  bool has_sps(int id) const { return sps[id] != nullptr; }
317
11.9k
  bool has_pps(int id) const { return pps[id] != nullptr; }
318
319
9.64k
  std::shared_ptr<const seq_parameter_set> get_shared_sps(int id) { return sps[id]; }
320
9.13k
  std::shared_ptr<const pic_parameter_set> get_shared_pps(int id) { return pps[id]; }
321
322
2.21k
  /* */ seq_parameter_set* get_sps(int id)       { return sps[id].get(); }
323
0
  const seq_parameter_set* get_sps(int id) const { return sps[id].get(); }
324
2.05k
  /* */ pic_parameter_set* get_pps(int id)       { return pps[id].get(); }
325
0
  const pic_parameter_set* get_pps(int id) const { return pps[id].get(); }
326
327
  /*
328
  const slice_segment_header* get_SliceHeader_atCtb(int ctb) {
329
    return img->slices[img->get_SliceHeaderIndex_atIndex(ctb)];
330
  }
331
  */
332
333
16.9k
  uint8_t get_nal_unit_type() const { return nal_unit_type; }
334
11.9k
  bool    get_RapPicFlag() const { return RapPicFlag; }
335
336
  de265_error decode_NAL(std::unique_ptr<NAL_unit> nal);
337
338
  de265_error decode(int* more);
339
  de265_error decode_some(bool* did_work);
340
341
  de265_error decode_slice_unit_sequential(image_unit* imgunit, slice_unit* sliceunit);
342
  de265_error decode_slice_unit_parallel(image_unit* imgunit, slice_unit* sliceunit);
343
  de265_error decode_slice_unit_WPP(image_unit* imgunit, slice_unit* sliceunit);
344
  de265_error decode_slice_unit_tiles(image_unit* imgunit, slice_unit* sliceunit);
345
346
347
  void process_nal_hdr(nal_header*);
348
349
  bool process_slice_segment_header(slice_segment_header*,
350
                                    de265_error*, de265_PTS pts,
351
                                    nal_header* nal_hdr, void* user_data);
352
353
  //void push_current_picture_to_output_queue();
354
  de265_error push_picture_to_output_queue(image_unit*);
355
356
357
  // --- parameters ---
358
359
  bool param_sei_check_hash = false;
360
  bool param_conceal_stream_errors = true;
361
  bool param_suppress_faulty_pictures = false;
362
363
  int  param_sps_headers_fd = -1;
364
  int  param_vps_headers_fd = -1;
365
  int  param_pps_headers_fd = -1;
366
  int  param_slice_headers_fd = -1;
367
368
  bool param_disable_deblocking = false;
369
  bool param_disable_sao = false;
370
  //bool param_disable_mc_residual_idct;  // not implemented yet
371
  //bool param_disable_intra_residual_idct;  // not implemented yet
372
373
  de265_security_limits param_security_limits = {
374
    1,                // version
375
    8192 * 8192,      // max_image_size_pixels
376
    16 * 1024 * 1024, // max_NAL_size_bytes
377
    256               // max_SEI_messages
378
  };
379
380
  void set_image_allocation_functions(de265_image_allocation* allocfunc, void* userdata);
381
382
  de265_image_allocation param_image_allocation_functions; // initialized in constructor
383
  void*                  param_image_allocation_userdata = nullptr;
384
385
386
  // --- input stream data ---
387
388
  NAL_Parser nal_parser;
389
390
391
42.2k
  int get_num_worker_threads() const { return num_worker_threads; }
392
393
0
  /* */ de265_image* get_image(uint16_t dpb_index)       { return dpb.get_image(dpb_index); }
394
2.52M
  const de265_image* get_image(uint16_t dpb_index) const override { return dpb.get_image(dpb_index); }
395
396
152k
  bool has_image(uint16_t dpb_index) const override { return dpb_index<dpb.size(); }
397
398
14.8k
  de265_image* get_next_picture_in_output_queue() { return dpb.get_next_picture_in_output_queue(); }
399
322k
  int          num_pictures_in_output_queue() const { return dpb.num_pictures_in_output_queue(); }
400
7.44k
  void         pop_next_picture_in_output_queue() { dpb.pop_next_picture_in_output_queue(); }
401
402
 private:
403
  de265_error read_vps_NAL(bitreader&);
404
  de265_error read_sps_NAL(bitreader&);
405
  de265_error read_pps_NAL(bitreader&);
406
  de265_error read_sei_NAL(bitreader& reader, bool suffix);
407
  de265_error read_eos_NAL(bitreader& reader);
408
  de265_error read_slice_NAL(bitreader&, std::unique_ptr<NAL_unit> nal, nal_header& nal_hdr);
409
410
 private:
411
  // --- internal data ---
412
413
  std::shared_ptr<video_parameter_set>  vps[ DE265_MAX_VPS_SETS ];
414
  std::shared_ptr<seq_parameter_set>    sps[ DE265_MAX_SPS_SETS ];
415
  std::shared_ptr<pic_parameter_set>    pps[ DE265_MAX_PPS_SETS ];
416
417
  std::shared_ptr<video_parameter_set>  current_vps;
418
  std::shared_ptr<seq_parameter_set>    current_sps;
419
  std::shared_ptr<pic_parameter_set>    current_pps;
420
421
 public:
422
  thread_pool thread_pool_;
423
424
 private:
425
  int num_worker_threads = 0;
426
427
428
 public:
429
  // --- frame dropping ---
430
431
  void set_limit_TID(int tid);
432
  int  get_highest_TID() const;
433
0
  int  get_current_TID() const { return current_HighestTid; }
434
  int  change_framerate(int more_vs_less); // 1: more, -1: less
435
  void set_framerate_ratio(int percent);
436
437
 private:
438
  // input parameters
439
  int limit_HighestTid = 6;    // never switch to a layer above this one
440
  int framerate_ratio = 100;
441
442
  // current control parameters
443
  int goal_HighestTid = 6;     // this is the layer we want to decode at
444
  int layer_framerate_ratio = 100; // ratio of frames to keep in the current layer
445
446
  int current_HighestTid = 6;  // the layer which we are currently decoding
447
448
  struct {
449
    int8_t tid;
450
    int8_t ratio;
451
  } framedrop_tab[100+1];
452
  int framedrop_tid_index[6+1];
453
454
  void compute_framedrop_table();
455
  void calc_tid_and_framerate_ratio();
456
457
 private:
458
  // --- decoded picture buffer ---
459
460
  decoded_picture_buffer dpb;
461
462
  int current_image_poc_lsb = -1;
463
  bool first_decoded_picture = true;
464
  bool NoRaslOutputFlag = false;
465
  bool HandleCraAsBlaFlag = false;
466
  bool FirstAfterEndOfSequenceNAL = false;
467
468
  int  PicOrderCntMsb = 0;
469
  int prevPicOrderCntLsb = 0;  // at precTid0Pic
470
  int prevPicOrderCntMsb = 0;  // at precTid0Pic
471
472
  de265_image* img = nullptr;
473
474
 public:
475
  const slice_segment_header* previous_slice_header = nullptr; /* Remember the last slice for a successive
476
                  dependent slice. */
477
478
479
  // --- motion compensation ---
480
481
 public:
482
  int PocLsbLt[MAX_NUM_REF_PICS]{};
483
  int UsedByCurrPicLt[MAX_NUM_REF_PICS]{};
484
  uint32_t DeltaPocMsbCycleLt[MAX_NUM_REF_PICS]{};
485
 private:
486
  int CurrDeltaPocMsbPresentFlag[MAX_NUM_REF_PICS]{};
487
  int FollDeltaPocMsbPresentFlag[MAX_NUM_REF_PICS]{};
488
489
  // The number of entries in the lists below.
490
  int NumPocStCurrBefore = 0;
491
  int NumPocStCurrAfter = 0;
492
  int NumPocStFoll = 0;
493
  int NumPocLtCurr = 0;
494
  int NumPocLtFoll = 0;
495
496
  // These lists contain absolute POC values.
497
  int PocStCurrBefore[MAX_NUM_REF_PICS]{}; // used for reference in current picture, smaller POC
498
  int PocStCurrAfter[MAX_NUM_REF_PICS]{};  // used for reference in current picture, larger POC
499
  int PocStFoll[MAX_NUM_REF_PICS]{}; // not used for reference in current picture, but in future picture
500
  int PocLtCurr[MAX_NUM_REF_PICS]{}; // used in current picture
501
  int PocLtFoll[MAX_NUM_REF_PICS]{}; // used in some future picture
502
503
  // These lists contain indices into the DPB.
504
  int RefPicSetStCurrBefore[MAX_NUM_REF_PICS]{};
505
  int RefPicSetStCurrAfter[MAX_NUM_REF_PICS]{};
506
  int RefPicSetStFoll[MAX_NUM_REF_PICS]{};
507
  int RefPicSetLtCurr[MAX_NUM_REF_PICS]{};
508
  int RefPicSetLtFoll[MAX_NUM_REF_PICS]{};
509
510
511
  // --- parameters derived from parameter sets ---
512
513
  // NAL
514
515
  uint8_t nal_unit_type = 0;
516
517
  bool IdrPicFlag = false;
518
  bool RapPicFlag = false;
519
520
521
  // --- image unit queue ---
522
523
  std::vector<image_unit*> image_units;
524
525
  bool flush_reorder_buffer_at_this_frame = false;
526
527
 private:
528
  void init_thread_context(thread_context* tctx);
529
  void add_task_decode_CTB_row(thread_context* tctx, bool firstSliceSubstream, uint16_t ctbRow);
530
  void add_task_decode_slice_segment(thread_context* tctx, bool firstSliceSubstream,
531
                                     uint16_t ctbX, uint16_t ctbY);
532
533
  /* Check that the slice segment 'shdr' may be appended to 'imgunit', i.e. that
534
     its first CTB follows the previous slice segment of the picture in tile-scan
535
     order (H.265 7.4.2.4.5). Adds a warning and marks the image as faulty when
536
     the slice segment has to be dropped. */
537
  bool slice_segment_order_is_valid(image_unit* imgunit, const slice_segment_header* shdr);
538
539
  void mark_whole_slice_as_processed(image_unit* imgunit,
540
                                     slice_unit* sliceunit,
541
                                     int progress);
542
543
  void process_picture_order_count(slice_segment_header* hdr);
544
545
  /*
546
  If there is no space for a new image, returns the negative value of an de265_error.
547
  I.e. you can check for error by return_value<0, which is error (-return_value);
548
   */
549
  int generate_unavailable_reference_picture(const seq_parameter_set* sps,
550
                                             int POC, bool longTerm);
551
  de265_error process_reference_picture_set(slice_segment_header* hdr);
552
  bool construct_reference_picture_lists(slice_segment_header* hdr);
553
554
555
  void remove_images_from_dpb(const std::vector<int>& removeImageList);
556
  void run_postprocessing_filters_sequential(struct de265_image* img);
557
  void run_postprocessing_filters_parallel(image_unit* img);
558
};
559
560
561
#endif