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