/src/libde265/libde265/decctx.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 "decctx.h" |
22 | | #include "util.h" |
23 | | #include "sao.h" |
24 | | #include "sei.h" |
25 | | #include "deblock.h" |
26 | | |
27 | | #include <algorithm> |
28 | | #include <utility> |
29 | | #include <string.h> |
30 | | #include <assert.h> |
31 | | #include <stdlib.h> |
32 | | #include <stdio.h> |
33 | | #include <math.h> |
34 | | |
35 | | #include "fallback.h" |
36 | | |
37 | | #ifdef HAVE_CONFIG_H |
38 | | #include "config.h" |
39 | | #endif |
40 | | |
41 | | #ifdef HAVE_SSE4_1 |
42 | | #include "x86/sse.h" |
43 | | #endif |
44 | | |
45 | | #ifdef HAVE_ARM32 |
46 | | #include "arm32/arm.h" |
47 | | #endif |
48 | | |
49 | | #define SAVE_INTERMEDIATE_IMAGES 0 |
50 | | |
51 | | #if SAVE_INTERMEDIATE_IMAGES |
52 | | #include "visualize.h" |
53 | | #endif |
54 | | |
55 | | extern void thread_decode_CTB_row(void* d); |
56 | | extern void thread_decode_slice_segment(void* d); |
57 | | |
58 | | |
59 | | thread_context::thread_context() |
60 | 13.0k | { |
61 | | // There is an interesting issue here. When aligning _coeffBuf to 16 bytes offset with |
62 | | // __attribute__((align(16))), the following statement is optimized away since the |
63 | | // compiler assumes that the pointer would be 16-byte aligned. However, this is not the |
64 | | // case when the structure has been dynamically allocated. In this case, the base can |
65 | | // also be at 8 byte offsets (at least with MingW,32 bit). |
66 | 13.0k | int offset = ((uintptr_t)_coeffBuf) & 0xf; |
67 | | |
68 | 13.0k | if (offset == 0) { |
69 | 0 | coeffBuf = _coeffBuf; |
70 | 0 | } |
71 | 13.0k | else { |
72 | 13.0k | coeffBuf = (int16_t *) (((uint8_t *)_coeffBuf) + (16-offset)); |
73 | 13.0k | } |
74 | | |
75 | 13.0k | memset(coeffBuf, 0, 32*32*sizeof(int16_t)); |
76 | 13.0k | } |
77 | | |
78 | | |
79 | | slice_unit::slice_unit(decoder_context* decctx) |
80 | 8.40k | : nal(nullptr), |
81 | 8.40k | shdr(nullptr), |
82 | 8.40k | imgunit(nullptr), |
83 | 8.40k | flush_reorder_buffer(false), |
84 | 8.40k | nThreads(0), |
85 | 8.40k | first_decoded_CTB_RS(-1), |
86 | 8.40k | last_decoded_CTB_RS(-1), |
87 | 8.40k | thread_contexts(nullptr), |
88 | 8.40k | ctx(decctx) |
89 | 8.40k | { |
90 | 8.40k | state = Unprocessed; |
91 | 8.40k | nThreadContexts = 0; |
92 | 8.40k | } |
93 | | |
94 | | slice_unit::~slice_unit() |
95 | 8.40k | { |
96 | | // Return our NAL to the reuse pool. (Letting the unique_ptr delete it would be |
97 | | // memory-safe too, but would bypass pooling.) |
98 | 8.40k | ctx->nal_parser.free_NAL_unit(std::move(nal)); |
99 | | |
100 | 8.40k | if (thread_contexts) { |
101 | 1.06k | delete[] thread_contexts; |
102 | 1.06k | } |
103 | 8.40k | } |
104 | | |
105 | | |
106 | | void slice_unit::allocate_thread_contexts(int n) |
107 | 1.06k | { |
108 | 1.06k | assert(thread_contexts==nullptr); |
109 | | |
110 | 1.06k | thread_contexts = new thread_context[n]; |
111 | 1.06k | nThreadContexts = n; |
112 | 1.06k | } |
113 | | |
114 | | |
115 | 8.37k | image_unit::image_unit() = default; |
116 | | |
117 | | |
118 | | image_unit::~image_unit() |
119 | 8.37k | { |
120 | 16.7k | for (size_t i=0;i<slice_units.size();i++) { |
121 | 8.40k | delete slice_units[i]; |
122 | 8.40k | } |
123 | | |
124 | 312k | for (size_t i=0;i<tasks.size();i++) { |
125 | 304k | delete tasks[i]; |
126 | 304k | } |
127 | 8.37k | } |
128 | | |
129 | | |
130 | | base_context::base_context() |
131 | 9.07k | { |
132 | 9.07k | set_acceleration_functions(de265_acceleration_AUTO); |
133 | 9.07k | } |
134 | | |
135 | | |
136 | | decoder_context::decoder_context() |
137 | 9.07k | { |
138 | 9.07k | param_image_allocation_functions = de265_image::default_image_allocation; |
139 | 9.07k | nal_parser.set_security_limits(¶m_security_limits); |
140 | 9.07k | compute_framedrop_table(); |
141 | 9.07k | } |
142 | | |
143 | | |
144 | | decoder_context::~decoder_context() |
145 | 9.07k | { |
146 | 9.19k | while (!image_units.empty()) { |
147 | 116 | delete image_units.back(); |
148 | 116 | image_units.pop_back(); |
149 | 116 | } |
150 | 9.07k | } |
151 | | |
152 | | |
153 | | void decoder_context::set_image_allocation_functions(de265_image_allocation* allocfunc, |
154 | | void* userdata) |
155 | 0 | { |
156 | 0 | if (allocfunc) { |
157 | 0 | param_image_allocation_functions = *allocfunc; |
158 | 0 | param_image_allocation_userdata = userdata; |
159 | 0 | } |
160 | 0 | else { |
161 | 0 | assert(false); // actually, it makes no sense to reset the allocation functions |
162 | | |
163 | 0 | param_image_allocation_functions = de265_image::default_image_allocation; |
164 | 0 | param_image_allocation_userdata = nullptr; |
165 | 0 | } |
166 | 0 | } |
167 | | |
168 | | |
169 | | de265_error decoder_context::start_thread_pool(int nThreads) |
170 | 9.07k | { |
171 | 9.07k | thread_pool_.start(nThreads); |
172 | | |
173 | 9.07k | num_worker_threads = nThreads; |
174 | | |
175 | 9.07k | return DE265_OK; |
176 | 9.07k | } |
177 | | |
178 | | |
179 | | void decoder_context::stop_thread_pool() |
180 | 9.07k | { |
181 | 9.07k | if (get_num_worker_threads()>0) { |
182 | | //flush_thread_pool(&ctx->thread_pool); |
183 | 9.07k | thread_pool_.stop(); |
184 | 9.07k | } |
185 | 9.07k | } |
186 | | |
187 | | |
188 | | void decoder_context::reset() |
189 | 0 | { |
190 | 0 | if (num_worker_threads>0) { |
191 | | //flush_thread_pool(&ctx->thread_pool); |
192 | 0 | thread_pool_.stop(); |
193 | 0 | } |
194 | | |
195 | | // -------------------------------------------------- |
196 | |
|
197 | 0 | NumPocStCurrBefore = 0; |
198 | 0 | NumPocStCurrAfter = 0; |
199 | 0 | NumPocStFoll = 0; |
200 | 0 | NumPocLtCurr = 0; |
201 | 0 | NumPocLtFoll = 0; |
202 | 0 | nal_unit_type = 0; |
203 | 0 | IdrPicFlag = 0; |
204 | 0 | RapPicFlag = 0; |
205 | |
|
206 | 0 | img = nullptr; |
207 | | |
208 | | // Drop the back-reference to the previous picture's slice header before the |
209 | | // DPB is cleared below. dpb.clear() releases the images, which own and free |
210 | | // their slice_segment_header structs (see de265_image::release()). Leaving |
211 | | // previous_slice_header pointing into that freed storage lets a following |
212 | | // dependent slice read from it (slice.cc: '*this = *ctx->previous_slice_header'), |
213 | | // a heap-use-after-free. This mirrors the in-stream new-picture guard in |
214 | | // read_slice_NAL(): only a slice header still retained by a live image may |
215 | | // remain as previous_slice_header. |
216 | 0 | previous_slice_header = nullptr; |
217 | | |
218 | | |
219 | | // TODO: remove all pending image_units |
220 | | |
221 | | |
222 | | // --- decoded picture buffer --- |
223 | |
|
224 | 0 | current_image_poc_lsb = -1; // any invalid number |
225 | 0 | first_decoded_picture = true; |
226 | | |
227 | | |
228 | | // --- remove all pictures from output queue --- |
229 | | |
230 | | // there was a bug the peek_next_image did not return nullptr on empty output queues. |
231 | | // This was (indirectly) fixed by recreating the DPB buffer, but it should actually |
232 | | // be sufficient to clear it like this. |
233 | | // The error showed while scrubbing the ToS video in VLC. |
234 | 0 | dpb.clear(); |
235 | |
|
236 | 0 | nal_parser.remove_pending_input_data(); |
237 | | |
238 | |
|
239 | 0 | while (!image_units.empty()) { |
240 | 0 | delete image_units.back(); |
241 | 0 | image_units.pop_back(); |
242 | 0 | } |
243 | | |
244 | | // --- start threads again --- |
245 | |
|
246 | 0 | if (num_worker_threads>0) { |
247 | | // TODO: need error checking |
248 | 0 | start_thread_pool(num_worker_threads); |
249 | 0 | } |
250 | 0 | } |
251 | | |
252 | | void base_context::set_acceleration_functions(enum de265_acceleration l) |
253 | 9.07k | { |
254 | | // fill scalar functions first (so that function table is completely filled) |
255 | | |
256 | 9.07k | init_acceleration_functions_fallback(&acceleration); |
257 | | |
258 | | |
259 | | // override functions with optimized variants |
260 | | |
261 | | #ifdef HAVE_SSE4_1 |
262 | | if (l>=de265_acceleration_SSE) { |
263 | | init_acceleration_functions_sse(&acceleration); |
264 | | } |
265 | | #endif |
266 | | #if HAVE_AVX2 |
267 | | // layered on top of SSE: overrides a few transform kernels (runtime-checked) |
268 | | if (l>=de265_acceleration_AVX2) { |
269 | | init_acceleration_functions_avx2(&acceleration); |
270 | | } |
271 | | #endif |
272 | | #if HAVE_AVX512 |
273 | | // layered on top of AVX2: overrides the 32x32 transform (runtime-checked) |
274 | | if (l>=de265_acceleration_AVX2) { |
275 | | init_acceleration_functions_avx512(&acceleration); |
276 | | } |
277 | | #endif |
278 | | #ifdef HAVE_ARM32 |
279 | | if (l>=de265_acceleration_ARM) { |
280 | | init_acceleration_functions_arm(&acceleration); |
281 | | } |
282 | | #endif |
283 | 9.07k | } |
284 | | |
285 | | |
286 | | void decoder_context::init_thread_context(thread_context* tctx) |
287 | 12.5k | { |
288 | | // zero scrap memory for coefficient blocks |
289 | 12.5k | memset(tctx->_coeffBuf, 0, sizeof(tctx->_coeffBuf)); // TODO: check if we can safely remove this |
290 | | |
291 | 12.5k | tctx->currentQG_x = -1; |
292 | 12.5k | tctx->currentQG_y = -1; |
293 | | |
294 | | |
295 | | |
296 | | // --- find QPY that was active at the end of the previous slice --- |
297 | | |
298 | | // find the previous CTB in TS order |
299 | | |
300 | 12.5k | const pic_parameter_set& pps = tctx->img->get_pps(); |
301 | 12.5k | const seq_parameter_set& sps = tctx->img->get_sps(); |
302 | | |
303 | | |
304 | 12.5k | if (tctx->shdr->slice_segment_address > 0) { |
305 | 27 | int prevCtb = pps.scan->CtbAddrTStoRS[ pps.scan->CtbAddrRStoTS[tctx->shdr->slice_segment_address] -1 ]; |
306 | | |
307 | 27 | int ctbX = prevCtb % sps.PicWidthInCtbsY; |
308 | 27 | int ctbY = prevCtb / sps.PicWidthInCtbsY; |
309 | | |
310 | | |
311 | | // take the pixel at the bottom right corner (but consider that the image size might be smaller) |
312 | | |
313 | 27 | int x = ((ctbX+1) << sps.Log2CtbSizeY)-1; |
314 | 27 | int y = ((ctbY+1) << sps.Log2CtbSizeY)-1; |
315 | | |
316 | 27 | x = std::min(x,sps.pic_width_in_luma_samples-1); |
317 | 27 | y = std::min(y,sps.pic_height_in_luma_samples-1); |
318 | | |
319 | | //printf("READ QPY: %d %d -> %d (should %d)\n",x,y,imgunit->img->get_QPY(x,y), tc.currentQPY); |
320 | | |
321 | | //if (tctx->shdr->dependent_slice_segment_flag) { // TODO: do we need this condition ? |
322 | 27 | tctx->currentQPY = tctx->img->get_QPY(x,y); |
323 | | //} |
324 | 27 | } |
325 | 12.5k | } |
326 | | |
327 | | |
328 | | void decoder_context::add_task_decode_CTB_row(thread_context* tctx, |
329 | | bool firstSliceSubstream, |
330 | | uint16_t ctbRow) |
331 | 5.00k | { |
332 | 5.00k | thread_task_ctb_row* task = new thread_task_ctb_row; |
333 | 5.00k | task->firstSliceSubstream = firstSliceSubstream; |
334 | 5.00k | task->tctx = tctx; |
335 | 5.00k | task->debug_startCtbRow = ctbRow; |
336 | 5.00k | tctx->task = task; |
337 | | |
338 | 5.00k | thread_pool_.add_task(task); |
339 | | |
340 | 5.00k | tctx->imgunit->tasks.push_back(task); |
341 | 5.00k | } |
342 | | |
343 | | |
344 | | void decoder_context::add_task_decode_slice_segment(thread_context* tctx, bool firstSliceSubstream, |
345 | | uint16_t ctbx, uint16_t ctby) |
346 | 322 | { |
347 | 322 | thread_task_slice_segment* task = new thread_task_slice_segment; |
348 | 322 | task->firstSliceSubstream = firstSliceSubstream; |
349 | 322 | task->tctx = tctx; |
350 | 322 | task->debug_startCtbX = ctbx; |
351 | 322 | task->debug_startCtbY = ctby; |
352 | 322 | tctx->task = task; |
353 | | |
354 | 322 | thread_pool_.add_task(task); |
355 | | |
356 | 322 | tctx->imgunit->tasks.push_back(task); |
357 | 322 | } |
358 | | |
359 | | |
360 | | de265_error decoder_context::read_vps_NAL(bitreader& reader) |
361 | 13.0k | { |
362 | 13.0k | logdebug(LogHeaders,"---> read VPS\n"); |
363 | | |
364 | 13.0k | std::shared_ptr<video_parameter_set> new_vps = std::make_shared<video_parameter_set>(); |
365 | 13.0k | de265_error err = new_vps->read(this,&reader); |
366 | 13.0k | if (err != DE265_OK) { |
367 | 1.12k | return err; |
368 | 1.12k | } |
369 | | |
370 | 11.9k | if (param_vps_headers_fd>=0) { |
371 | 0 | new_vps->dump(param_vps_headers_fd); |
372 | 0 | } |
373 | | |
374 | 11.9k | vps[ new_vps->video_parameter_set_id ] = new_vps; |
375 | | |
376 | 11.9k | return DE265_OK; |
377 | 13.0k | } |
378 | | |
379 | | de265_error decoder_context::read_sps_NAL(bitreader& reader) |
380 | 14.2k | { |
381 | 14.2k | logdebug(LogHeaders,"----> read SPS\n"); |
382 | | |
383 | 14.2k | std::shared_ptr<seq_parameter_set> new_sps = std::make_shared<seq_parameter_set>(); |
384 | 14.2k | de265_error err; |
385 | | |
386 | 14.2k | if ((err=new_sps->read(this, &reader)) != DE265_OK) { |
387 | 1.22k | return err; |
388 | 1.22k | } |
389 | | |
390 | 12.9k | if (param_sps_headers_fd>=0) { |
391 | 0 | new_sps->dump(param_sps_headers_fd); |
392 | 0 | } |
393 | | |
394 | 12.9k | sps[ new_sps->seq_parameter_set_id ] = new_sps; |
395 | | |
396 | | // Remove the all PPS that referenced the old SPS because parameters may have changed and we do not want to |
397 | | // get the SPS and PPS parameters (e.g. image size) out of sync. |
398 | | |
399 | 830k | for (auto& p : pps) { |
400 | 830k | if (p && p->seq_parameter_set_id == new_sps->seq_parameter_set_id) { |
401 | 3.78k | p = nullptr; |
402 | 3.78k | } |
403 | 830k | } |
404 | | |
405 | 12.9k | return DE265_OK; |
406 | 14.2k | } |
407 | | |
408 | | de265_error decoder_context::read_pps_NAL(bitreader& reader) |
409 | 14.2k | { |
410 | 14.2k | logdebug(LogHeaders,"----> read PPS\n"); |
411 | | |
412 | 14.2k | std::shared_ptr<pic_parameter_set> new_pps = std::make_shared<pic_parameter_set>(); |
413 | | |
414 | 14.2k | bool success = new_pps->read(&reader,this); |
415 | 14.2k | if (!success) { |
416 | 1.82k | return DE265_WARNING_PPS_HEADER_INVALID; |
417 | 1.82k | } |
418 | | |
419 | 12.3k | if (param_pps_headers_fd>=0) { |
420 | 0 | new_pps->dump(param_pps_headers_fd); |
421 | 0 | } |
422 | | |
423 | 12.3k | pps[ (int)new_pps->pic_parameter_set_id ] = new_pps; |
424 | | |
425 | 12.3k | return DE265_OK; |
426 | 14.2k | } |
427 | | |
428 | | de265_error decoder_context::read_sei_NAL(bitreader& reader, bool suffix) |
429 | 39 | { |
430 | 39 | logdebug(LogHeaders,"----> read SEI\n"); |
431 | | |
432 | 39 | sei_message sei; |
433 | | |
434 | | //push_current_picture_to_output_queue(); |
435 | | |
436 | 39 | de265_error err = DE265_OK; |
437 | | |
438 | 39 | if ((err=read_sei(&reader,&sei, suffix, current_sps.get())) == DE265_OK) { |
439 | 38 | dump_sei(&sei, current_sps.get()); |
440 | | |
441 | 38 | if (image_units.empty()==false && suffix) { |
442 | 1 | uint32_t max_SEI_messages = param_security_limits.max_SEI_messages; |
443 | 1 | if (max_SEI_messages != 0 && |
444 | 1 | image_units.back()->suffix_SEIs.size() >= max_SEI_messages) { |
445 | | // too many SEI messages for this access unit -> drop to bound memory usage |
446 | 0 | add_warning(DE265_WARNING_MAX_NUMBER_OF_SEI_MESSAGES_EXCEEDED, false); |
447 | 0 | return DE265_WARNING_MAX_NUMBER_OF_SEI_MESSAGES_EXCEEDED; |
448 | 0 | } |
449 | | |
450 | 1 | image_units.back()->suffix_SEIs.push_back(sei); |
451 | 1 | } |
452 | 38 | } |
453 | 1 | else { |
454 | 1 | add_warning(err, false); |
455 | 1 | } |
456 | | |
457 | 39 | return err; |
458 | 39 | } |
459 | | |
460 | | de265_error decoder_context::read_eos_NAL(bitreader& reader) |
461 | 0 | { |
462 | 0 | FirstAfterEndOfSequenceNAL = true; |
463 | 0 | return DE265_OK; |
464 | 0 | } |
465 | | |
466 | | bool decoder_context::slice_segment_order_is_valid(image_unit* imgunit, |
467 | | const slice_segment_header* shdr) |
468 | 8.41k | { |
469 | | // Nothing to compare against for the first slice segment of the picture. |
470 | 8.41k | if (imgunit->slice_units.empty() || imgunit->img == nullptr) { |
471 | 8.37k | return true; |
472 | 8.37k | } |
473 | | |
474 | 41 | de265_image* img = imgunit->img; |
475 | 41 | const pic_parameter_set& pps = img->get_pps(); |
476 | 41 | if (!pps.scan) { |
477 | 0 | return true; |
478 | 0 | } |
479 | | |
480 | 41 | const std::vector<uint32_t>& RStoTS = pps.scan->CtbAddrRStoTS; |
481 | | |
482 | 41 | uint32_t prevAddr = imgunit->slice_units.back()->shdr->slice_segment_address; |
483 | 41 | uint32_t thisAddr = shdr->slice_segment_address; |
484 | | |
485 | 41 | if (prevAddr >= RStoTS.size() || thisAddr >= RStoTS.size()) { |
486 | 0 | add_warning(DE265_WARNING_SLICE_SEGMENT_ADDRESS_INVALID, false); |
487 | 0 | img->integrity = INTEGRITY_DECODING_ERRORS; |
488 | 0 | return false; |
489 | 0 | } |
490 | | |
491 | | // H.265 7.4.2.4.5: the slice segments of a coded picture shall be ordered by |
492 | | // increasing tile-scan address of their first CTB, and (7.4.7.1) no two slice |
493 | | // segments of a picture share a slice_segment_address. A slice segment that |
494 | | // repeats or goes back to an earlier address would re-decode CTBs that were |
495 | | // already decoded. In WPP mode the progress of those CTBs is already marked |
496 | | // as finished, so the row tasks of the offending slice segment would not wait |
497 | | // for the row above and would race with each other on the CTB metadata and |
498 | | // the reconstructed pixels. Drop such slice segments. |
499 | 41 | if (RStoTS[thisAddr] <= RStoTS[prevAddr]) { |
500 | 11 | add_warning(DE265_WARNING_SLICE_SEGMENT_ADDRESS_NOT_INCREASING, false); |
501 | 11 | img->integrity = INTEGRITY_DECODING_ERRORS; |
502 | 11 | return false; |
503 | 11 | } |
504 | | |
505 | 30 | return true; |
506 | 41 | } |
507 | | |
508 | | |
509 | | de265_error decoder_context::read_slice_NAL(bitreader& reader, std::unique_ptr<NAL_unit> nal, nal_header& nal_hdr) |
510 | 9.73k | { |
511 | 9.73k | logdebug(LogHeaders,"---> read slice segment header\n"); |
512 | | |
513 | | |
514 | | // --- read slice header --- |
515 | | |
516 | 9.73k | slice_segment_header* shdr = new slice_segment_header; |
517 | 9.73k | bool continueDecoding; |
518 | 9.73k | de265_error err = shdr->read(&reader,this, &continueDecoding); |
519 | 9.73k | if (!continueDecoding) { |
520 | 1.15k | if (img) { img->integrity = INTEGRITY_NOT_DECODED; } |
521 | 1.15k | nal_parser.free_NAL_unit(std::move(nal)); |
522 | 1.15k | delete shdr; |
523 | 1.15k | return err; |
524 | 1.15k | } |
525 | | |
526 | 8.57k | if (param_slice_headers_fd>=0) { |
527 | 0 | shdr->dump_slice_segment_header(this, param_slice_headers_fd); |
528 | 0 | } |
529 | | |
530 | | |
531 | 8.57k | if (process_slice_segment_header(shdr, &err, nal->pts, &nal_hdr, nal->user_data) == false) |
532 | 165 | { |
533 | 165 | if (img!=nullptr) img->integrity = INTEGRITY_NOT_DECODED; |
534 | 165 | nal_parser.free_NAL_unit(std::move(nal)); |
535 | 165 | delete shdr; |
536 | 165 | return err; |
537 | 165 | } |
538 | | |
539 | 8.40k | reader.skip_bits(1); // TODO: why? |
540 | 8.40k | reader.prepare_for_CABAC(); |
541 | | |
542 | | |
543 | | // modify entry_point_offsets |
544 | | |
545 | 8.40k | uint32_t headerLength = reader.data - nal->data(); |
546 | 13.2k | for (uint32_t i=0;i<shdr->num_entry_point_offsets;i++) { |
547 | 4.82k | uint32_t skipped = nal->num_skipped_bytes_before(shdr->entry_point_offset[i], |
548 | 4.82k | headerLength); |
549 | 4.82k | if (skipped > shdr->entry_point_offset[i]) { |
550 | 0 | add_warning(DE265_WARNING_SLICEHEADER_INVALID, false); |
551 | 0 | nal_parser.free_NAL_unit(std::move(nal)); |
552 | 0 | delete shdr; |
553 | 0 | return DE265_ERROR_CODED_PARAMETER_OUT_OF_RANGE; |
554 | 0 | } |
555 | 4.82k | shdr->entry_point_offset[i] -= skipped; |
556 | 4.82k | } |
557 | | |
558 | | // --- start a new image if this is the first slice --- |
559 | | |
560 | 8.40k | if (shdr->first_slice_segment_in_pic_flag) { |
561 | 8.36k | image_unit* imgunit = new image_unit; |
562 | 8.36k | imgunit->img = this->img; |
563 | 8.36k | image_units.push_back(imgunit); |
564 | | |
565 | | // A new picture starts here. Drop the reference to the previous picture's |
566 | | // slice header, whose storage may be released independently of this decoder |
567 | | // state. Dependent slices only ever reference a preceding slice header |
568 | | // within the same picture, which is set below as slices are retained. |
569 | 8.36k | previous_slice_header = nullptr; |
570 | 8.36k | } |
571 | | |
572 | | |
573 | | // --- add slice to current picture --- |
574 | | |
575 | 8.40k | if ( ! image_units.empty() && |
576 | 8.41k | slice_segment_order_is_valid(image_units.back(), shdr) ) { |
577 | | |
578 | | // Hand the slice header to the picture (which takes ownership and frees it |
579 | | // on release). Only do this when there is an active image unit to decode |
580 | | // the slice; otherwise the header would be retained on img->slices forever, |
581 | | // which a crafted stream of non-first slice NALs can exploit to grow memory |
582 | | // without bound. |
583 | 8.40k | this->img->add_slice_segment_header(shdr); |
584 | | |
585 | | // The header is now owned by the image and stays alive at least until the |
586 | | // image is released, so it is safe for a following dependent slice to copy |
587 | | // from it. Only retained headers may become 'previous_slice_header'. |
588 | 8.40k | previous_slice_header = shdr; |
589 | | |
590 | 8.40k | slice_unit* sliceunit = new slice_unit(this); |
591 | 8.40k | sliceunit->nal = std::move(nal); |
592 | 8.40k | sliceunit->shdr = shdr; |
593 | 8.40k | sliceunit->reader = reader; |
594 | | |
595 | 8.40k | sliceunit->flush_reorder_buffer = flush_reorder_buffer_at_this_frame; |
596 | | |
597 | | |
598 | 8.40k | image_units.back()->slice_units.push_back(sliceunit); |
599 | 8.40k | } |
600 | 3 | else { |
601 | 3 | nal_parser.free_NAL_unit(std::move(nal)); |
602 | 3 | delete shdr; |
603 | 3 | } |
604 | | |
605 | 8.40k | bool did_work; |
606 | 8.40k | err = decode_some(&did_work); |
607 | | |
608 | 8.40k | return DE265_OK; |
609 | 8.40k | } |
610 | | |
611 | | |
612 | | template <class T> void pop_front(std::vector<T>& vec) |
613 | 8.26k | { |
614 | 8.37k | for (size_t i=1;i<vec.size();i++) |
615 | 117 | vec[i-1] = vec[i]; |
616 | | |
617 | 8.26k | vec.pop_back(); |
618 | 8.26k | } |
619 | | |
620 | | |
621 | | de265_error decoder_context::decode_some(bool* did_work) |
622 | 9.09k | { |
623 | 9.09k | de265_error err = DE265_OK; |
624 | | |
625 | 9.09k | *did_work = false; |
626 | | |
627 | 9.09k | if (image_units.empty()) { return DE265_OK; } // nothing to do |
628 | | |
629 | | |
630 | | // decode something if there is work to do |
631 | | |
632 | 9.09k | if ( ! image_units.empty() ) { // && ! image_units[0]->slice_units.empty() ) { |
633 | | |
634 | 9.08k | image_unit* imgunit = image_units[0]; |
635 | 9.08k | slice_unit* sliceunit = imgunit->get_next_unprocessed_slice_segment(); |
636 | | |
637 | 9.08k | if (sliceunit != nullptr) { |
638 | | |
639 | | //pop_front(imgunit->slice_units); |
640 | | |
641 | 8.28k | if (sliceunit->flush_reorder_buffer) { |
642 | 8.03k | dpb.flush_reorder_buffer(); |
643 | 8.03k | } |
644 | | |
645 | 8.28k | *did_work = true; |
646 | | |
647 | | //err = decode_slice_unit_sequential(imgunit, sliceunit); |
648 | 8.28k | err = decode_slice_unit_parallel(imgunit, sliceunit); |
649 | 8.28k | if (err) { |
650 | 56 | return err; |
651 | 56 | } |
652 | | |
653 | | //delete sliceunit; |
654 | 8.28k | } |
655 | 9.08k | } |
656 | | |
657 | | |
658 | | |
659 | | // if we decoded all slices of the current image and there will not |
660 | | // be added any more slices to the image, output the image |
661 | | |
662 | 9.03k | if ( ( image_units.size()>=2 && image_units[0]->all_slice_segments_processed()) || |
663 | 8.92k | ( image_units.size()>=1 && image_units[0]->all_slice_segments_processed() && |
664 | 8.92k | nal_parser.number_of_NAL_units_pending()==0 && |
665 | 8.26k | (nal_parser.is_end_of_stream() || nal_parser.is_end_of_frame()) )) { |
666 | | |
667 | 8.26k | image_unit* imgunit = image_units[0]; |
668 | | |
669 | 8.26k | *did_work=true; |
670 | | |
671 | | |
672 | | // mark all CTBs as decoded even if they are not, because faulty input |
673 | | // streams could miss part of the picture |
674 | | // TODO: this will not work when slice decoding is parallel to post-filtering, |
675 | | // so we will have to replace this with keeping track of which CTB should have |
676 | | // been decoded (but aren't because of the input stream being faulty) |
677 | | |
678 | 8.26k | imgunit->img->mark_all_CTB_progress(CTB_PROGRESS_PREFILTER); |
679 | | |
680 | | |
681 | | |
682 | | // run post-processing filters (deblocking & SAO) |
683 | | |
684 | 8.26k | if (img->decctx->num_worker_threads) |
685 | 8.26k | run_postprocessing_filters_parallel(imgunit); |
686 | 0 | else |
687 | 0 | run_postprocessing_filters_sequential(imgunit->img); |
688 | | |
689 | | // process suffix SEIs |
690 | | |
691 | 8.26k | for (size_t i=0;i<imgunit->suffix_SEIs.size();i++) { |
692 | 1 | const sei_message& sei = imgunit->suffix_SEIs[i]; |
693 | | |
694 | 1 | err = process_sei(&sei, imgunit->img); |
695 | 1 | if (err != DE265_OK) |
696 | 0 | break; |
697 | 1 | } |
698 | | |
699 | | |
700 | 8.26k | push_picture_to_output_queue(imgunit); |
701 | | |
702 | | // remove just decoded image unit from queue |
703 | | |
704 | 8.26k | delete imgunit; |
705 | | |
706 | 8.26k | pop_front(image_units); |
707 | 8.26k | } |
708 | | |
709 | 9.03k | return err; |
710 | 9.09k | } |
711 | | |
712 | | |
713 | | de265_error decoder_context::decode_slice_unit_sequential(image_unit* imgunit, |
714 | | slice_unit* sliceunit) |
715 | 7.20k | { |
716 | 7.20k | de265_error err = DE265_OK; |
717 | | |
718 | | /* |
719 | | printf("decode slice POC=%d addr=%d, img=%p\n", |
720 | | sliceunit->shdr->slice_pic_order_cnt_lsb, |
721 | | sliceunit->shdr->slice_segment_address, |
722 | | imgunit->img); |
723 | | */ |
724 | | |
725 | 7.20k | remove_images_from_dpb(sliceunit->shdr->RemoveReferencesList); |
726 | | |
727 | 7.20k | if (sliceunit->shdr->slice_segment_address >= imgunit->img->get_pps().scan->CtbAddrRStoTS.size()) { |
728 | 0 | return DE265_ERROR_CTB_OUTSIDE_IMAGE_AREA; |
729 | 0 | } |
730 | | |
731 | | |
732 | 7.20k | thread_context tctx; |
733 | | |
734 | 7.20k | tctx.shdr = sliceunit->shdr; |
735 | 7.20k | tctx.img = imgunit->img; |
736 | 7.20k | tctx.decctx = this; |
737 | 7.20k | tctx.imgunit = imgunit; |
738 | 7.20k | tctx.sliceunit= sliceunit; |
739 | 7.20k | tctx.CtbAddrInTS = imgunit->img->get_pps().scan->CtbAddrRStoTS[tctx.shdr->slice_segment_address]; |
740 | 7.20k | tctx.task = nullptr; |
741 | | |
742 | 7.20k | init_thread_context(&tctx); |
743 | | |
744 | 7.20k | if (sliceunit->reader.bytes_remaining <= 0) { |
745 | 14 | return DE265_ERROR_PREMATURE_END_OF_SLICE; |
746 | 14 | } |
747 | | |
748 | 7.19k | tctx.cabac_decoder.init(sliceunit->reader.data, |
749 | 7.19k | sliceunit->reader.bytes_remaining); |
750 | | |
751 | | // alloc CABAC-model array if entropy_coding_sync is enabled |
752 | | |
753 | 7.19k | if (imgunit->img->get_pps().entropy_coding_sync_enabled_flag && |
754 | 0 | sliceunit->shdr->first_slice_segment_in_pic_flag) { |
755 | 0 | imgunit->ctx_models.resize( (img->get_sps().PicHeightInCtbsY-1) ); //* CONTEXT_MODEL_TABLE_LENGTH ); |
756 | 0 | imgunit->StatCoeff_models.assign( (img->get_sps().PicHeightInCtbsY-1), {{0,0,0,0}} ); |
757 | 0 | } |
758 | | |
759 | 7.19k | sliceunit->nThreads=1; |
760 | | |
761 | 7.19k | err=read_slice_segment_data(&tctx); |
762 | | |
763 | 7.19k | sliceunit->finished_threads.set_progress(1); |
764 | | |
765 | 7.19k | return err; |
766 | 7.20k | } |
767 | | |
768 | | |
769 | | void decoder_context::mark_whole_slice_as_processed(image_unit* imgunit, |
770 | | slice_unit* sliceunit, |
771 | | int progress) |
772 | 8.31k | { |
773 | | //printf("mark whole slice\n"); |
774 | | |
775 | | |
776 | | // mark all CTBs upto the next slice segment as processed |
777 | | |
778 | 8.31k | slice_unit* nextSegment = imgunit->get_next_slice_segment(sliceunit); |
779 | 8.31k | if (nextSegment) { |
780 | | /* |
781 | | printf("mark whole slice between %d and %d\n", |
782 | | sliceunit->shdr->slice_segment_address, |
783 | | nextSegment->shdr->slice_segment_address); |
784 | | */ |
785 | | |
786 | 29 | for (uint32_t ctb=sliceunit->shdr->slice_segment_address; |
787 | 1.19k | ctb < nextSegment->shdr->slice_segment_address; |
788 | 1.17k | ctb++) |
789 | 1.17k | { |
790 | 1.17k | if (ctb >= imgunit->img->number_of_ctbs()) |
791 | 0 | break; |
792 | | |
793 | 1.17k | imgunit->img->ctb_progress[ctb].set_progress(progress); |
794 | 1.17k | } |
795 | 29 | } |
796 | 8.31k | } |
797 | | |
798 | | |
799 | | de265_error decoder_context::decode_slice_unit_parallel(image_unit* imgunit, |
800 | | slice_unit* sliceunit) |
801 | 8.27k | { |
802 | 8.27k | de265_error err = DE265_OK; |
803 | | |
804 | 8.27k | remove_images_from_dpb(sliceunit->shdr->RemoveReferencesList); |
805 | | |
806 | | /* |
807 | | printf("-------- decode --------\n"); |
808 | | printf("IMAGE UNIT %p\n",imgunit); |
809 | | sliceunit->shdr->dump_slice_segment_header(sliceunit->ctx, 1); |
810 | | imgunit->dump_slices(); |
811 | | */ |
812 | | |
813 | 8.27k | de265_image* img = imgunit->img; |
814 | 8.27k | const pic_parameter_set& pps = img->get_pps(); |
815 | | |
816 | 8.27k | sliceunit->state = slice_unit::InProgress; |
817 | | |
818 | 8.27k | bool use_WPP = (img->decctx->num_worker_threads > 0 && |
819 | 8.28k | pps.entropy_coding_sync_enabled_flag); |
820 | | |
821 | 8.27k | bool use_tiles = (img->decctx->num_worker_threads > 0 && |
822 | 8.28k | pps.tiles_enabled_flag); |
823 | | |
824 | | |
825 | | // TODO: remove this warning later when we do frame-parallel decoding |
826 | 8.27k | if (img->decctx->num_worker_threads > 0 && |
827 | 8.27k | pps.entropy_coding_sync_enabled_flag == false && |
828 | 7.46k | pps.tiles_enabled_flag == false) { |
829 | | |
830 | 7.20k | img->decctx->add_warning(DE265_WARNING_NO_WPP_CANNOT_USE_MULTITHREADING, true); |
831 | 7.20k | } |
832 | | |
833 | | |
834 | | // If this is the first slice segment, mark all CTBs before this as processed |
835 | | // (the real first slice segment could be missing). |
836 | | |
837 | 8.27k | if (imgunit->is_first_slice_segment(sliceunit)) { |
838 | 8.25k | slice_segment_header* shdr = sliceunit->shdr; |
839 | 8.25k | int firstCTB = shdr->slice_segment_address; |
840 | | |
841 | 8.25k | for (int ctb=0;ctb<firstCTB;ctb++) { |
842 | | //printf("mark pre progress %d\n",ctb); |
843 | 0 | img->ctb_progress[ctb].set_progress(CTB_PROGRESS_PREFILTER); |
844 | 0 | } |
845 | 8.25k | } |
846 | | |
847 | | |
848 | | // if there is a previous slice that has been completely decoded, |
849 | | // mark all CTBs until the start of this slice as completed |
850 | | |
851 | | //printf("this slice: %p\n",sliceunit); |
852 | 8.27k | slice_unit* prevSlice = imgunit->get_prev_slice_segment(sliceunit); |
853 | | //if (prevSlice) printf("prev slice state: %d\n",prevSlice->state); |
854 | 8.27k | if (prevSlice && prevSlice->state == slice_unit::Decoded) { |
855 | 29 | mark_whole_slice_as_processed(imgunit,prevSlice,CTB_PROGRESS_PREFILTER); |
856 | 29 | } |
857 | | |
858 | | |
859 | | // TODO: even though we cannot split this into several tasks, we should run it |
860 | | // as a background thread |
861 | 8.27k | if (!use_WPP && !use_tiles) { |
862 | | //printf("SEQ\n"); |
863 | 7.21k | err = decode_slice_unit_sequential(imgunit, sliceunit); |
864 | 7.21k | sliceunit->state = slice_unit::Decoded; |
865 | 7.21k | mark_whole_slice_as_processed(imgunit,sliceunit,CTB_PROGRESS_PREFILTER); |
866 | 7.21k | return err; |
867 | 7.21k | } |
868 | | |
869 | | |
870 | 1.06k | if (use_WPP && use_tiles) { |
871 | | // TODO: this is not allowed ... output some warning or error |
872 | | |
873 | 7 | return DE265_WARNING_PPS_HEADER_INVALID; |
874 | 7 | } |
875 | | |
876 | | |
877 | 1.05k | if (use_WPP) { |
878 | | //printf("WPP\n"); |
879 | 811 | err = decode_slice_unit_WPP(imgunit, sliceunit); |
880 | 811 | sliceunit->state = slice_unit::Decoded; |
881 | 811 | mark_whole_slice_as_processed(imgunit,sliceunit,CTB_PROGRESS_PREFILTER); |
882 | 811 | return err; |
883 | 811 | } |
884 | 254 | else if (use_tiles) { |
885 | | //printf("TILE\n"); |
886 | 254 | err = decode_slice_unit_tiles(imgunit, sliceunit); |
887 | 254 | sliceunit->state = slice_unit::Decoded; |
888 | 254 | mark_whole_slice_as_processed(imgunit,sliceunit,CTB_PROGRESS_PREFILTER); |
889 | 254 | return err; |
890 | 254 | } |
891 | | |
892 | 18.4E | assert(false); |
893 | 0 | return err; |
894 | 18.4E | } |
895 | | |
896 | | |
897 | | de265_error decoder_context::decode_slice_unit_WPP(image_unit* imgunit, |
898 | | slice_unit* sliceunit) |
899 | 811 | { |
900 | 811 | de265_error err = DE265_OK; |
901 | | |
902 | 811 | de265_image* img = imgunit->img; |
903 | 811 | slice_segment_header* shdr = sliceunit->shdr; |
904 | 811 | const pic_parameter_set& pps = img->get_pps(); |
905 | | |
906 | 811 | uint16_t nRows = shdr->num_entry_point_offsets +1; |
907 | 811 | uint16_t ctbsWidth = img->get_sps().PicWidthInCtbsY; |
908 | | |
909 | | |
910 | 811 | assert(img->num_threads_active() == 0); |
911 | | |
912 | | |
913 | | // reserve space to store entropy coding context models for each CTB row |
914 | | |
915 | 811 | if (shdr->first_slice_segment_in_pic_flag) { |
916 | | // reserve space for nRows-1 because we don't need to save the CABAC model in the last CTB row |
917 | 796 | imgunit->ctx_models.resize( (img->get_sps().PicHeightInCtbsY-1) ); //* CONTEXT_MODEL_TABLE_LENGTH ); |
918 | 796 | imgunit->StatCoeff_models.assign( (img->get_sps().PicHeightInCtbsY-1), {{0,0,0,0}} ); |
919 | 796 | } |
920 | | |
921 | | |
922 | 811 | sliceunit->allocate_thread_contexts(nRows); |
923 | | |
924 | | |
925 | | // first CTB in this slice |
926 | 811 | uint32_t ctbAddrRS = shdr->slice_segment_address; |
927 | 811 | uint16_t ctbRow = ctbAddrRS / ctbsWidth; |
928 | | |
929 | 811 | if (ctbRow + nRows > img->get_sps().PicHeightInCtbsY) { |
930 | 1 | return DE265_WARNING_SLICEHEADER_INVALID; |
931 | 1 | } |
932 | | |
933 | | // Reset the decoding progress of all CTBs that the row tasks of this slice |
934 | | // segment are going to decode (from its first CTB to the end of its last |
935 | | // CTB row). Their progress may already be marked as finished, e.g. by a |
936 | | // preceding slice segment whose entry points claimed more rows than its |
937 | | // data covered, because a row task marks the rest of its row as finished |
938 | | // when it fails. Stale progress would let the row tasks of this slice |
939 | | // segment skip waiting for the row above and race with each other on the |
940 | | // CTB metadata and the reconstructed pixels. No task is running on the |
941 | | // image at this point (asserted above), so nobody can be waiting on the |
942 | | // CTBs that are reset here. |
943 | 810 | { |
944 | 810 | uint32_t endCtb = std::min<uint32_t>((uint32_t)(ctbRow + nRows) * ctbsWidth, |
945 | 810 | img->number_of_ctbs()); |
946 | 58.9k | for (uint32_t ctb = ctbAddrRS; ctb < endCtb; ctb++) { |
947 | 58.1k | img->ctb_progress[ctb].reset(CTB_PROGRESS_NONE); |
948 | 58.1k | } |
949 | 810 | } |
950 | | |
951 | 5.81k | for (uint16_t entryPt=0;entryPt<nRows;entryPt++) { |
952 | | // entry points other than the first start at CTB rows |
953 | 5.03k | if (entryPt>0) { |
954 | 4.22k | ctbRow++; |
955 | 4.22k | ctbAddrRS = ctbRow * ctbsWidth; |
956 | 4.22k | } |
957 | 810 | else if (nRows>1 && (ctbAddrRS % ctbsWidth) != 0) { |
958 | | // If slice segment consists of several WPP rows, each of them |
959 | | // has to start at a row. |
960 | | |
961 | | //printf("does not start at start\n"); |
962 | | |
963 | 1 | err = DE265_WARNING_SLICEHEADER_INVALID; |
964 | 1 | break; |
965 | 1 | } |
966 | | |
967 | | |
968 | | // prepare thread context |
969 | | |
970 | 5.03k | thread_context* tctx = sliceunit->get_thread_context(entryPt); |
971 | | |
972 | 5.03k | tctx->shdr = shdr; |
973 | 5.03k | tctx->decctx = img->decctx; |
974 | 5.03k | tctx->img = img; |
975 | 5.03k | tctx->imgunit = imgunit; |
976 | 5.03k | tctx->sliceunit= sliceunit; |
977 | | |
978 | 5.03k | if (ctbAddrRS >= pps.scan->CtbAddrRStoTS.size()) { |
979 | 0 | err = DE265_WARNING_SLICEHEADER_INVALID; |
980 | 0 | break; |
981 | 0 | } |
982 | 5.03k | tctx->CtbAddrInTS = pps.scan->CtbAddrRStoTS[ctbAddrRS]; |
983 | | |
984 | 5.03k | init_thread_context(tctx); |
985 | | |
986 | | |
987 | | // init CABAC |
988 | | |
989 | 5.03k | int dataStartIndex; |
990 | 5.03k | if (entryPt==0) { dataStartIndex=0; } |
991 | 4.22k | else { dataStartIndex=shdr->entry_point_offset[entryPt-1]; } |
992 | | |
993 | 5.03k | int dataEnd; |
994 | 5.03k | if (entryPt==nRows-1) dataEnd = sliceunit->reader.bytes_remaining; |
995 | 4.25k | else dataEnd = shdr->entry_point_offset[entryPt]; |
996 | | |
997 | 5.03k | if (dataStartIndex<0 || dataEnd>sliceunit->reader.bytes_remaining || |
998 | 5.01k | dataEnd <= dataStartIndex) { |
999 | | //printf("WPP premature end\n"); |
1000 | 31 | err = DE265_ERROR_PREMATURE_END_OF_SLICE; |
1001 | 31 | break; |
1002 | 31 | } |
1003 | | |
1004 | 5.00k | tctx->cabac_decoder.init(&sliceunit->reader.data[dataStartIndex], |
1005 | 5.00k | dataEnd-dataStartIndex); |
1006 | | |
1007 | | // add task |
1008 | | |
1009 | | //printf("start task for ctb-row: %d\n",ctbRow); |
1010 | 5.00k | img->thread_start(1); |
1011 | 5.00k | sliceunit->nThreads++; |
1012 | 5.00k | add_task_decode_CTB_row(tctx, entryPt==0, ctbRow); |
1013 | 5.00k | } |
1014 | | |
1015 | | #if 0 |
1016 | | for (;;) { |
1017 | | printf("q:%d r:%d b:%d f:%d\n", |
1018 | | img->nThreadsQueued, |
1019 | | img->nThreadsRunning, |
1020 | | img->nThreadsBlocked, |
1021 | | img->nThreadsFinished); |
1022 | | |
1023 | | if (img->debug_is_completed()) break; |
1024 | | |
1025 | | usleep(1000); |
1026 | | } |
1027 | | #endif |
1028 | | |
1029 | 810 | img->wait_for_completion(); |
1030 | | |
1031 | 5.81k | for (size_t i=0;i<imgunit->tasks.size();i++) |
1032 | 5.00k | delete imgunit->tasks[i]; |
1033 | 810 | imgunit->tasks.clear(); |
1034 | | |
1035 | 810 | return err; |
1036 | 811 | } |
1037 | | |
1038 | | de265_error decoder_context::decode_slice_unit_tiles(image_unit* imgunit, |
1039 | | slice_unit* sliceunit) |
1040 | 254 | { |
1041 | 254 | de265_error err = DE265_OK; |
1042 | | |
1043 | 254 | de265_image* img = imgunit->img; |
1044 | 254 | slice_segment_header* shdr = sliceunit->shdr; |
1045 | 254 | const pic_parameter_set& pps = img->get_pps(); |
1046 | | |
1047 | 254 | uint16_t nTiles = shdr->num_entry_point_offsets +1; |
1048 | 254 | uint16_t ctbsWidth = img->get_sps().PicWidthInCtbsY; |
1049 | | |
1050 | | |
1051 | 254 | assert(img->num_threads_active() == 0); |
1052 | | |
1053 | 254 | sliceunit->allocate_thread_contexts(nTiles); |
1054 | | |
1055 | | |
1056 | | // first CTB in this slice |
1057 | 254 | uint32_t ctbAddrRS = shdr->slice_segment_address; |
1058 | | |
1059 | | // pps.scan->TileIdRS and pps.scan->CtbAddrRStoTS are both sized to PicSizeInCtbsY in |
1060 | | // set_derived_values(), so one bound covers both accesses below. |
1061 | 254 | if (ctbAddrRS >= pps.scan->CtbAddrRStoTS.size()) { |
1062 | 0 | return DE265_WARNING_SLICEHEADER_INVALID; |
1063 | 0 | } |
1064 | 254 | int tileID = pps.scan->TileIdRS[ctbAddrRS]; |
1065 | | |
1066 | 576 | for (uint16_t entryPt=0;entryPt<nTiles;entryPt++) { |
1067 | | // entry points other than the first start at tile beginnings |
1068 | 324 | if (entryPt>0) { |
1069 | 70 | tileID++; |
1070 | | |
1071 | 70 | if (tileID >= pps.num_tile_columns * pps.num_tile_rows) { |
1072 | 0 | err = DE265_WARNING_SLICEHEADER_INVALID; |
1073 | 0 | break; |
1074 | 0 | } |
1075 | | |
1076 | 70 | uint16_t ctbX = pps.colBd[tileID % pps.num_tile_columns]; |
1077 | 70 | uint16_t ctbY = pps.rowBd[tileID / pps.num_tile_columns]; |
1078 | 70 | ctbAddrRS = ctbY * ctbsWidth + ctbX; |
1079 | | |
1080 | 70 | if (ctbAddrRS >= pps.scan->CtbAddrRStoTS.size()) { |
1081 | 0 | err = DE265_WARNING_SLICEHEADER_INVALID; |
1082 | 0 | break; |
1083 | 0 | } |
1084 | 70 | } |
1085 | | |
1086 | | // set thread context |
1087 | | |
1088 | 324 | thread_context* tctx = sliceunit->get_thread_context(entryPt); |
1089 | | |
1090 | 324 | tctx->shdr = shdr; |
1091 | 324 | tctx->decctx = img->decctx; |
1092 | 324 | tctx->img = img; |
1093 | 324 | tctx->imgunit = imgunit; |
1094 | 324 | tctx->sliceunit= sliceunit; |
1095 | 324 | tctx->CtbAddrInTS = pps.scan->CtbAddrRStoTS[ctbAddrRS]; |
1096 | | |
1097 | 324 | init_thread_context(tctx); |
1098 | | |
1099 | | |
1100 | | // init CABAC |
1101 | | |
1102 | 324 | int dataStartIndex; |
1103 | 324 | if (entryPt==0) { dataStartIndex=0; } |
1104 | 70 | else { dataStartIndex=shdr->entry_point_offset[entryPt-1]; } |
1105 | | |
1106 | 324 | int dataEnd; |
1107 | 324 | if (entryPt==nTiles-1) dataEnd = sliceunit->reader.bytes_remaining; |
1108 | 71 | else dataEnd = shdr->entry_point_offset[entryPt]; |
1109 | | |
1110 | 324 | if (dataStartIndex<0 || dataEnd>sliceunit->reader.bytes_remaining || |
1111 | 323 | dataEnd <= dataStartIndex) { |
1112 | 2 | err = DE265_ERROR_PREMATURE_END_OF_SLICE; |
1113 | 2 | break; |
1114 | 2 | } |
1115 | | |
1116 | 322 | tctx->cabac_decoder.init(&sliceunit->reader.data[dataStartIndex], |
1117 | 322 | dataEnd-dataStartIndex); |
1118 | | |
1119 | | // add task |
1120 | | |
1121 | | //printf("add tiles thread\n"); |
1122 | 322 | img->thread_start(1); |
1123 | 322 | sliceunit->nThreads++; |
1124 | 322 | add_task_decode_slice_segment(tctx, entryPt==0, |
1125 | 322 | static_cast<uint16_t>(ctbAddrRS % ctbsWidth), |
1126 | 322 | static_cast<uint16_t>(ctbAddrRS / ctbsWidth)); |
1127 | 322 | } |
1128 | | |
1129 | 254 | img->wait_for_completion(); |
1130 | | |
1131 | 576 | for (size_t i=0;i<imgunit->tasks.size();i++) |
1132 | 322 | delete imgunit->tasks[i]; |
1133 | 254 | imgunit->tasks.clear(); |
1134 | | |
1135 | 254 | return err; |
1136 | 254 | } |
1137 | | |
1138 | | |
1139 | | // Ownership: decode_NAL() receives the NAL by moved-in unique_ptr and releases |
1140 | | // it on every return path. Parameter-set, SEI and discarded NALs are returned to |
1141 | | // the pool directly here; slice NALs are moved into read_slice_NAL(), which |
1142 | | // either releases the NAL or moves it into a slice_unit that owns it for the rest |
1143 | | // of the image_unit's lifetime. Because ownership is a unique_ptr, the NAL cannot |
1144 | | // be released twice. |
1145 | | de265_error decoder_context::decode_NAL(std::unique_ptr<NAL_unit> nal) |
1146 | 52.4k | { |
1147 | | //return decode_NAL_OLD(nal); |
1148 | | |
1149 | 52.4k | decoder_context* ctx = this; |
1150 | | |
1151 | 52.4k | de265_error err = DE265_OK; |
1152 | | |
1153 | 52.4k | bitreader reader(nal->data(), nal->size()); |
1154 | | |
1155 | 52.4k | nal_header nal_hdr; |
1156 | 52.4k | err = nal_hdr.read(&reader); |
1157 | 52.4k | if (err != DE265_OK) { |
1158 | 67 | nal_parser.free_NAL_unit(std::move(nal)); |
1159 | 67 | return err; |
1160 | 67 | } |
1161 | 52.3k | ctx->process_nal_hdr(&nal_hdr); |
1162 | | |
1163 | 52.3k | if (nal_hdr.nuh_layer_id > 0) { |
1164 | | // Discard all NAL units with nuh_layer_id > 0 |
1165 | | // These will have to be handled by an SHVC decoder. |
1166 | 1.25k | nal_parser.free_NAL_unit(std::move(nal)); |
1167 | 1.25k | return DE265_OK; |
1168 | 1.25k | } |
1169 | | |
1170 | 51.0k | loginfo(LogHighlevel,"NAL: 0x%x 0x%x - unit type:%s temporal id:%d\n", |
1171 | 51.0k | nal->data()[0], nal->data()[1], |
1172 | 51.0k | get_NAL_name(nal_hdr.nal_unit_type), |
1173 | 51.0k | nal_hdr.nuh_temporal_id); |
1174 | | |
1175 | | /* |
1176 | | printf("NAL: 0x%x 0x%x - unit type:%s temporal id:%d\n", |
1177 | | nal->data()[0], nal->data()[1], |
1178 | | get_NAL_name(nal_hdr.nal_unit_type), |
1179 | | nal_hdr.nuh_temporal_id); |
1180 | | */ |
1181 | | |
1182 | | // throw away NALs from higher TIDs than currently selected |
1183 | | // TODO: better online switching of HighestTID |
1184 | | |
1185 | | //printf("hTid: %d\n", current_HighestTid); |
1186 | | |
1187 | 51.0k | if (nal_hdr.nuh_temporal_id > current_HighestTid) { |
1188 | 7 | nal_parser.free_NAL_unit(std::move(nal)); |
1189 | 7 | return DE265_OK; |
1190 | 7 | } |
1191 | | |
1192 | | |
1193 | 51.0k | if (nal_hdr.nal_unit_type<32) { |
1194 | 9.73k | err = read_slice_NAL(reader, std::move(nal), nal_hdr); |
1195 | 9.73k | } |
1196 | 41.3k | else switch (nal_hdr.nal_unit_type) { |
1197 | 13.0k | case NAL_UNIT_VPS_NUT: |
1198 | 13.0k | err = read_vps_NAL(reader); |
1199 | 13.0k | nal_parser.free_NAL_unit(std::move(nal)); |
1200 | 13.0k | break; |
1201 | | |
1202 | 14.2k | case NAL_UNIT_SPS_NUT: |
1203 | 14.2k | err = read_sps_NAL(reader); |
1204 | 14.2k | nal_parser.free_NAL_unit(std::move(nal)); |
1205 | 14.2k | break; |
1206 | | |
1207 | 14.2k | case NAL_UNIT_PPS_NUT: |
1208 | 14.2k | err = read_pps_NAL(reader); |
1209 | 14.2k | nal_parser.free_NAL_unit(std::move(nal)); |
1210 | 14.2k | break; |
1211 | | |
1212 | 32 | case NAL_UNIT_PREFIX_SEI_NUT: |
1213 | 39 | case NAL_UNIT_SUFFIX_SEI_NUT: |
1214 | 39 | err = read_sei_NAL(reader, nal_hdr.nal_unit_type==NAL_UNIT_SUFFIX_SEI_NUT); |
1215 | 39 | nal_parser.free_NAL_unit(std::move(nal)); |
1216 | 39 | break; |
1217 | | |
1218 | 7 | case NAL_UNIT_EOS_NUT: |
1219 | 7 | ctx->FirstAfterEndOfSequenceNAL = true; |
1220 | 7 | nal_parser.free_NAL_unit(std::move(nal)); |
1221 | 7 | break; |
1222 | | |
1223 | 51 | default: |
1224 | 51 | nal_parser.free_NAL_unit(std::move(nal)); |
1225 | 51 | break; |
1226 | 41.3k | } |
1227 | | |
1228 | 51.3k | return err; |
1229 | 51.0k | } |
1230 | | |
1231 | | |
1232 | | de265_error decoder_context::decode(int* more) |
1233 | 95.1k | { |
1234 | 95.1k | decoder_context* ctx = this; |
1235 | | |
1236 | | // if the stream has ended, and no more NALs are to be decoded, flush all pictures |
1237 | | |
1238 | 95.1k | if (ctx->nal_parser.get_NAL_queue_length() == 0 && |
1239 | 42.6k | (ctx->nal_parser.is_end_of_stream() || ctx->nal_parser.is_end_of_frame()) && |
1240 | 42.6k | ctx->image_units.empty()) { |
1241 | | |
1242 | | // flush all pending pictures into output queue |
1243 | | |
1244 | | // ctx->push_current_picture_to_output_queue(); // TODO: not with new queue |
1245 | 42.0k | ctx->dpb.flush_reorder_buffer(); |
1246 | | |
1247 | 42.0k | if (more) { *more = ctx->dpb.num_pictures_in_output_queue(); } |
1248 | | |
1249 | 42.0k | return DE265_OK; |
1250 | 42.0k | } |
1251 | | |
1252 | | |
1253 | | // if NAL-queue is empty, we need more data |
1254 | | // -> input stalled |
1255 | | |
1256 | 53.1k | if (ctx->nal_parser.is_end_of_stream() == false && |
1257 | 0 | ctx->nal_parser.is_end_of_frame() == false && |
1258 | 0 | ctx->nal_parser.get_NAL_queue_length() == 0) { |
1259 | 0 | if (more) { *more=1; } |
1260 | |
|
1261 | 0 | return DE265_ERROR_WAITING_FOR_INPUT_DATA; |
1262 | 0 | } |
1263 | | |
1264 | | |
1265 | | // when there are no free image buffers in the DPB, pause decoding |
1266 | | // -> output stalled |
1267 | | |
1268 | 53.1k | if (!ctx->dpb.has_free_dpb_picture(false)) { |
1269 | 0 | if (more) *more = 1; |
1270 | 0 | return DE265_ERROR_IMAGE_BUFFER_FULL; |
1271 | 0 | } |
1272 | | |
1273 | | |
1274 | | // decode one NAL from the queue |
1275 | | |
1276 | 53.1k | de265_error err = DE265_OK; |
1277 | 53.1k | bool did_work = false; |
1278 | | |
1279 | 53.1k | if (ctx->nal_parser.get_NAL_queue_length()) { // number_of_NAL_units_pending()) { |
1280 | 52.4k | std::unique_ptr<NAL_unit> nal = ctx->nal_parser.pop_from_NAL_queue(); |
1281 | 52.4k | assert(nal); |
1282 | | |
1283 | | // Ownership of the dequeued NAL moves into decode_NAL(), which releases it on |
1284 | | // every path (directly, or via a slice_unit that returns it to the pool when |
1285 | | // the image_unit is destroyed). Nothing to free here. |
1286 | 52.4k | err = ctx->decode_NAL(std::move(nal)); |
1287 | 52.4k | did_work=true; |
1288 | 52.4k | } |
1289 | 720 | else if (ctx->nal_parser.is_end_of_frame() == true && |
1290 | 0 | ctx->image_units.empty()) { |
1291 | 0 | if (more) { *more=1; } |
1292 | |
|
1293 | 0 | return DE265_ERROR_WAITING_FOR_INPUT_DATA; |
1294 | 0 | } |
1295 | 720 | else { |
1296 | 720 | err = decode_some(&did_work); |
1297 | 720 | } |
1298 | | |
1299 | 53.3k | if (more) { |
1300 | | // decoding error is assumed to be unrecoverable |
1301 | 53.3k | *more = (err==DE265_OK && did_work); |
1302 | 53.3k | } |
1303 | | |
1304 | 53.1k | return err; |
1305 | 53.1k | } |
1306 | | |
1307 | | |
1308 | | void decoder_context::process_nal_hdr(nal_header* nal) |
1309 | 52.5k | { |
1310 | 52.5k | nal_unit_type = nal->nal_unit_type; |
1311 | | |
1312 | 52.5k | IdrPicFlag = isIdrPic(nal->nal_unit_type); |
1313 | 52.5k | RapPicFlag = isRapPic(nal->nal_unit_type); |
1314 | 52.5k | } |
1315 | | |
1316 | | |
1317 | | |
1318 | | /* 8.3.1 |
1319 | | */ |
1320 | | void decoder_context::process_picture_order_count(slice_segment_header* hdr) |
1321 | 8.52k | { |
1322 | 8.52k | loginfo(LogHeaders,"POC computation. lsb:%d prev.pic.lsb:%d msb:%d\n", |
1323 | 8.52k | hdr->slice_pic_order_cnt_lsb, |
1324 | 8.52k | prevPicOrderCntLsb, |
1325 | 8.52k | PicOrderCntMsb); |
1326 | | |
1327 | 8.52k | if (isIRAP(nal_unit_type) && |
1328 | 8.11k | NoRaslOutputFlag) |
1329 | 8.11k | { |
1330 | 8.11k | PicOrderCntMsb=0; |
1331 | | |
1332 | | |
1333 | | // flush all images from reorder buffer |
1334 | | |
1335 | 8.11k | flush_reorder_buffer_at_this_frame = true; |
1336 | | //ctx->dpb.flush_reorder_buffer(); |
1337 | 8.11k | } |
1338 | 414 | else |
1339 | 414 | { |
1340 | 414 | int MaxPicOrderCntLsb = current_sps->MaxPicOrderCntLsb; |
1341 | | |
1342 | 414 | if ((hdr->slice_pic_order_cnt_lsb < prevPicOrderCntLsb) && |
1343 | 56 | (prevPicOrderCntLsb - hdr->slice_pic_order_cnt_lsb) >= MaxPicOrderCntLsb/2) { |
1344 | 8 | PicOrderCntMsb = prevPicOrderCntMsb + MaxPicOrderCntLsb; |
1345 | 8 | } |
1346 | 406 | else if ((hdr->slice_pic_order_cnt_lsb > prevPicOrderCntLsb) && |
1347 | 316 | (hdr->slice_pic_order_cnt_lsb - prevPicOrderCntLsb) > MaxPicOrderCntLsb/2) { |
1348 | 189 | PicOrderCntMsb = prevPicOrderCntMsb - MaxPicOrderCntLsb; |
1349 | 189 | } |
1350 | 217 | else { |
1351 | 217 | PicOrderCntMsb = prevPicOrderCntMsb; |
1352 | 217 | } |
1353 | 414 | } |
1354 | | |
1355 | 8.52k | img->PicOrderCntVal = PicOrderCntMsb + hdr->slice_pic_order_cnt_lsb; |
1356 | 8.52k | img->picture_order_cnt_lsb = hdr->slice_pic_order_cnt_lsb; |
1357 | | |
1358 | 8.52k | loginfo(LogHeaders,"POC computation. new msb:%d POC=%d\n", |
1359 | 8.52k | PicOrderCntMsb, |
1360 | 8.52k | img->PicOrderCntVal); |
1361 | | |
1362 | 8.52k | if (img->nal_hdr.nuh_temporal_id==0 && |
1363 | 8.52k | !isSublayerNonReference(nal_unit_type) && |
1364 | 8.51k | !isRASL(nal_unit_type) && |
1365 | 8.51k | !isRADL(nal_unit_type)) |
1366 | 8.51k | { |
1367 | 8.51k | loginfo(LogHeaders,"set prevPicOrderCntLsb/Msb\n"); |
1368 | | |
1369 | 8.51k | prevPicOrderCntLsb = hdr->slice_pic_order_cnt_lsb; |
1370 | 8.51k | prevPicOrderCntMsb = PicOrderCntMsb; |
1371 | 8.51k | } |
1372 | 8.52k | } |
1373 | | |
1374 | | |
1375 | | /* 8.3.3.2 |
1376 | | Returns DPB index of the generated picture. |
1377 | | */ |
1378 | | int decoder_context::generate_unavailable_reference_picture(const seq_parameter_set* sps, |
1379 | | int POC, bool longTerm) |
1380 | 4.37k | { |
1381 | 4.37k | assert(dpb.has_free_dpb_picture(true)); |
1382 | | |
1383 | 4.37k | std::shared_ptr<const seq_parameter_set> current_sps = this->sps[ (int)current_pps->seq_parameter_set_id ]; |
1384 | | |
1385 | 4.37k | int idx = dpb.new_image(current_sps, this, 0,0, false); |
1386 | 4.37k | if (idx<0) { |
1387 | 0 | return idx; |
1388 | 0 | } |
1389 | | |
1390 | 4.37k | de265_image* img = dpb.get_image(idx); |
1391 | | |
1392 | 4.37k | img->fill_image(1<<(sps->BitDepth_Y-1), |
1393 | 4.37k | 1<<(sps->BitDepth_C-1), |
1394 | 4.37k | 1<<(sps->BitDepth_C-1)); |
1395 | | |
1396 | 4.37k | img->fill_pred_mode(MODE_INTRA); |
1397 | | |
1398 | 4.37k | img->PicOrderCntVal = POC; |
1399 | 4.37k | img->picture_order_cnt_lsb = POC & (sps->MaxPicOrderCntLsb-1); |
1400 | 4.37k | img->PicOutputFlag = false; |
1401 | 4.37k | img->PicState = (longTerm ? UsedForLongTermReference : UsedForShortTermReference); |
1402 | 4.37k | img->integrity = INTEGRITY_UNAVAILABLE_REFERENCE; |
1403 | | |
1404 | 4.37k | return idx; |
1405 | 4.37k | } |
1406 | | |
1407 | | |
1408 | | /* 8.3.2 invoked once per picture |
1409 | | |
1410 | | This function will mark pictures in the DPB as 'unused' or 'used for long-term reference' |
1411 | | */ |
1412 | | de265_error decoder_context::process_reference_picture_set(slice_segment_header* hdr) |
1413 | 8.52k | { |
1414 | 8.52k | std::vector<int> removeReferencesList; |
1415 | | |
1416 | 8.52k | const uint32_t currentID = img->get_ID(); |
1417 | | |
1418 | | |
1419 | 8.52k | if (isIRAP(nal_unit_type) && NoRaslOutputFlag) { |
1420 | | |
1421 | 8.10k | int currentPOC = img->PicOrderCntVal; |
1422 | | |
1423 | | // reset DPB |
1424 | | |
1425 | | /* The standard says: "When the current picture is an IRAP picture with NoRaslOutputFlag |
1426 | | equal to 1, all reference pictures currently in the DPB (if any) are marked as |
1427 | | "unused for reference". |
1428 | | |
1429 | | This seems to be wrong as it also throws out the first CRA picture in a stream like |
1430 | | RAP_A (decoding order: CRA,POC=64, RASL,POC=60). Removing only the pictures with |
1431 | | lower POCs seems to be compliant to the reference decoder. |
1432 | | */ |
1433 | | |
1434 | 16.2k | for (size_t i=0;i<dpb.size();i++) { |
1435 | 8.10k | de265_image* img = dpb.get_image(i); |
1436 | | |
1437 | 8.10k | if (img->PicState != UnusedForReference && |
1438 | 8.11k | img->PicOrderCntVal < currentPOC && |
1439 | 0 | img->removed_at_picture_id > img->get_ID()) { |
1440 | |
|
1441 | 0 | removeReferencesList.push_back(img->get_ID()); |
1442 | 0 | img->removed_at_picture_id = img->get_ID(); |
1443 | | |
1444 | | //printf("will remove ID %d (a)\n",img->get_ID()); |
1445 | 0 | } |
1446 | 8.10k | } |
1447 | 8.10k | } |
1448 | | |
1449 | | |
1450 | 8.52k | if (isIDR(nal_unit_type)) { |
1451 | | |
1452 | | // clear all reference pictures |
1453 | | |
1454 | 6.24k | NumPocStCurrBefore = 0; |
1455 | 6.24k | NumPocStCurrAfter = 0; |
1456 | 6.24k | NumPocStFoll = 0; |
1457 | 6.24k | NumPocLtCurr = 0; |
1458 | 6.24k | NumPocLtFoll = 0; |
1459 | 6.24k | } |
1460 | 2.28k | else { |
1461 | 2.28k | const ref_pic_set* rps = &hdr->CurrRps; |
1462 | | |
1463 | | // (8-98) |
1464 | | |
1465 | 2.28k | int i,j,k; |
1466 | | |
1467 | | // scan ref-pic-set for smaller POCs and fill into PocStCurrBefore / PocStFoll |
1468 | | |
1469 | 2.28k | for (i=0, j=0, k=0; |
1470 | 4.73k | i<rps->NumNegativePics; |
1471 | 2.45k | i++) |
1472 | 2.45k | { |
1473 | 2.45k | if (rps->UsedByCurrPicS0[i]) { |
1474 | 1.64k | PocStCurrBefore[j++] = img->PicOrderCntVal + rps->DeltaPocS0[i]; |
1475 | | //printf("PocStCurrBefore = %d\n",PocStCurrBefore[j-1]); |
1476 | 1.64k | } |
1477 | 814 | else { |
1478 | 814 | PocStFoll[k++] = img->PicOrderCntVal + rps->DeltaPocS0[i]; |
1479 | 814 | } |
1480 | 2.45k | } |
1481 | | |
1482 | 2.28k | NumPocStCurrBefore = j; |
1483 | | |
1484 | | |
1485 | | // scan ref-pic-set for larger POCs and fill into PocStCurrAfter / PocStFoll |
1486 | | |
1487 | 2.28k | for (i=0, j=0; |
1488 | 5.88k | i<rps->NumPositivePics; |
1489 | 3.60k | i++) |
1490 | 3.60k | { |
1491 | 3.60k | if (rps->UsedByCurrPicS1[i]) { |
1492 | 1.78k | PocStCurrAfter[j++] = img->PicOrderCntVal + rps->DeltaPocS1[i]; |
1493 | | //printf("PocStCurrAfter = %d\n",PocStCurrAfter[j-1]); |
1494 | 1.78k | } |
1495 | 1.81k | else { |
1496 | 1.81k | PocStFoll[k++] = img->PicOrderCntVal + rps->DeltaPocS1[i]; |
1497 | 1.81k | } |
1498 | 3.60k | } |
1499 | | |
1500 | 2.28k | NumPocStCurrAfter = j; |
1501 | 2.28k | NumPocStFoll = k; |
1502 | | |
1503 | | |
1504 | | // find used / future long-term references |
1505 | | |
1506 | 2.28k | for (i=0, j=0, k=0; |
1507 | | //i<current_sps->num_long_term_ref_pics_sps + hdr->num_long_term_pics; |
1508 | 3.86k | i<hdr->num_long_term_sps + hdr->num_long_term_pics; |
1509 | 2.28k | i++) |
1510 | 1.59k | { |
1511 | 1.59k | int pocLt = PocLsbLt[i]; |
1512 | | |
1513 | 1.59k | if (hdr->delta_poc_msb_present_flag[i]) { |
1514 | 754 | int currentPictureMSB = img->PicOrderCntVal - hdr->slice_pic_order_cnt_lsb; |
1515 | 754 | if (DeltaPocMsbCycleLt[i] > static_cast<uint32_t>(INT32_MAX) / current_sps->MaxPicOrderCntLsb) { |
1516 | 10 | add_warning(DE265_WARNING_SLICEHEADER_INVALID, false); |
1517 | 10 | return DE265_ERROR_CODED_PARAMETER_OUT_OF_RANGE; |
1518 | 10 | } |
1519 | 744 | pocLt += currentPictureMSB |
1520 | 744 | - static_cast<int>(DeltaPocMsbCycleLt[i] * current_sps->MaxPicOrderCntLsb); |
1521 | 744 | } |
1522 | | |
1523 | 1.58k | if (UsedByCurrPicLt[i]) { |
1524 | 931 | PocLtCurr[j] = pocLt; |
1525 | 931 | CurrDeltaPocMsbPresentFlag[j] = hdr->delta_poc_msb_present_flag[i]; |
1526 | 931 | j++; |
1527 | 931 | } |
1528 | 655 | else { |
1529 | 655 | PocLtFoll[k] = pocLt; |
1530 | 655 | FollDeltaPocMsbPresentFlag[k] = hdr->delta_poc_msb_present_flag[i]; |
1531 | 655 | k++; |
1532 | 655 | } |
1533 | 1.58k | } |
1534 | | |
1535 | 2.27k | NumPocLtCurr = j; |
1536 | 2.27k | NumPocLtFoll = k; |
1537 | 2.27k | } |
1538 | | |
1539 | | |
1540 | | // (old 8-99) / (new 8-106) |
1541 | | // 1. |
1542 | | |
1543 | 8.51k | std::vector<char> picInAnyList(dpb.size(), false); |
1544 | | |
1545 | | |
1546 | 8.51k | dpb.log_dpb_content(); |
1547 | | |
1548 | 9.43k | for (int i=0;i<NumPocLtCurr;i++) { |
1549 | 922 | int k; |
1550 | 922 | if (!CurrDeltaPocMsbPresentFlag[i]) { |
1551 | 315 | k = dpb.DPB_index_of_picture_with_LSB(PocLtCurr[i], currentID, true); |
1552 | 315 | } |
1553 | 607 | else { |
1554 | 607 | k = dpb.DPB_index_of_picture_with_POC(PocLtCurr[i], currentID, true); |
1555 | 607 | } |
1556 | | |
1557 | 922 | RefPicSetLtCurr[i] = k; // -1 == "no reference picture" |
1558 | 922 | if (k>=0) picInAnyList[k]=true; |
1559 | 716 | else { |
1560 | | // TODO, CHECK: is it ok that we generate a picture with POC = LSB (PocLtCurr) |
1561 | | // We do not know the correct MSB |
1562 | 716 | int concealedPicture = generate_unavailable_reference_picture(current_sps.get(), |
1563 | 716 | PocLtCurr[i], true); |
1564 | 716 | if (concealedPicture<0) { |
1565 | 0 | return (de265_error)(-concealedPicture); |
1566 | 0 | } |
1567 | 716 | picInAnyList.resize(dpb.size(), false); // adjust size of array to hold new picture |
1568 | | |
1569 | 716 | RefPicSetLtCurr[i] = k = concealedPicture; |
1570 | 716 | picInAnyList[concealedPicture]=true; |
1571 | 716 | } |
1572 | | |
1573 | 922 | if (dpb.get_image(k)->integrity != INTEGRITY_CORRECT) { |
1574 | 876 | img->integrity = INTEGRITY_DERIVED_FROM_FAULTY_REFERENCE; |
1575 | 876 | } |
1576 | 922 | } |
1577 | | |
1578 | | |
1579 | 9.15k | for (int i=0;i<NumPocLtFoll;i++) { |
1580 | 641 | int k; |
1581 | 641 | if (!FollDeltaPocMsbPresentFlag[i]) { |
1582 | 519 | k = dpb.DPB_index_of_picture_with_LSB(PocLtFoll[i], currentID, true); |
1583 | 519 | } |
1584 | 122 | else { |
1585 | 122 | k = dpb.DPB_index_of_picture_with_POC(PocLtFoll[i], currentID, true); |
1586 | 122 | } |
1587 | | |
1588 | 641 | RefPicSetLtFoll[i] = k; // -1 == "no reference picture" |
1589 | 641 | if (k>=0) picInAnyList[k]=true; |
1590 | 324 | else { |
1591 | 324 | int concealedPicture = k = generate_unavailable_reference_picture(current_sps.get(), |
1592 | 324 | PocLtFoll[i], true); |
1593 | 324 | if (concealedPicture<0) { |
1594 | 0 | return (de265_error)(-concealedPicture); |
1595 | 0 | } |
1596 | 324 | picInAnyList.resize(dpb.size(), false); // adjust size of array to hold new picture |
1597 | | |
1598 | 324 | RefPicSetLtFoll[i] = concealedPicture; |
1599 | 324 | picInAnyList[concealedPicture]=true; |
1600 | 324 | } |
1601 | 641 | } |
1602 | | |
1603 | | |
1604 | | // 2. Mark all pictures in RefPicSetLtCurr / RefPicSetLtFoll as UsedForLongTermReference |
1605 | | |
1606 | 9.43k | for (int i=0;i<NumPocLtCurr;i++) { |
1607 | 922 | dpb.get_image(RefPicSetLtCurr[i])->PicState = UsedForLongTermReference; |
1608 | 922 | } |
1609 | | |
1610 | 9.15k | for (int i=0;i<NumPocLtFoll;i++) { |
1611 | 641 | dpb.get_image(RefPicSetLtFoll[i])->PicState = UsedForLongTermReference; |
1612 | 641 | } |
1613 | | |
1614 | | |
1615 | | // 3. |
1616 | | |
1617 | 10.1k | for (int i=0;i<NumPocStCurrBefore;i++) { |
1618 | 1.64k | int k = dpb.DPB_index_of_picture_with_POC(PocStCurrBefore[i], currentID); |
1619 | | |
1620 | | //printf("st curr before, poc=%d -> idx=%d\n",PocStCurrBefore[i], k); |
1621 | | |
1622 | 1.64k | RefPicSetStCurrBefore[i] = k; // -1 == "no reference picture" |
1623 | 1.64k | if (k>=0) picInAnyList[k]=true; |
1624 | 1.61k | else { |
1625 | 1.61k | int concealedPicture = generate_unavailable_reference_picture(current_sps.get(), |
1626 | 1.61k | PocStCurrBefore[i], false); |
1627 | 1.61k | if (concealedPicture<0) { |
1628 | 0 | return (de265_error)(-concealedPicture); |
1629 | 0 | } |
1630 | 1.61k | RefPicSetStCurrBefore[i] = k = concealedPicture; |
1631 | | |
1632 | 1.61k | picInAnyList.resize(dpb.size(), false); // adjust size of array to hold new picture |
1633 | 1.61k | picInAnyList[concealedPicture] = true; |
1634 | | |
1635 | | //printf(" concealed: %d\n", concealedPicture); |
1636 | 1.61k | } |
1637 | | |
1638 | 1.64k | if (dpb.get_image(k)->integrity != INTEGRITY_CORRECT) { |
1639 | 1.64k | img->integrity = INTEGRITY_DERIVED_FROM_FAULTY_REFERENCE; |
1640 | 1.64k | } |
1641 | 1.64k | } |
1642 | | |
1643 | 10.2k | for (int i=0;i<NumPocStCurrAfter;i++) { |
1644 | 1.78k | int k = dpb.DPB_index_of_picture_with_POC(PocStCurrAfter[i], currentID); |
1645 | | |
1646 | | //printf("st curr after, poc=%d -> idx=%d\n",PocStCurrAfter[i], k); |
1647 | | |
1648 | 1.78k | RefPicSetStCurrAfter[i] = k; // -1 == "no reference picture" |
1649 | 1.78k | if (k>=0) picInAnyList[k]=true; |
1650 | 1.72k | else { |
1651 | 1.72k | int concealedPicture = generate_unavailable_reference_picture(current_sps.get(), |
1652 | 1.72k | PocStCurrAfter[i], false); |
1653 | 1.72k | if (concealedPicture<0) { |
1654 | 0 | return (de265_error)(-concealedPicture); |
1655 | 0 | } |
1656 | 1.72k | RefPicSetStCurrAfter[i] = k = concealedPicture; |
1657 | | |
1658 | | |
1659 | 1.72k | picInAnyList.resize(dpb.size(), false); // adjust size of array to hold new picture |
1660 | 1.72k | picInAnyList[concealedPicture]=true; |
1661 | | |
1662 | | //printf(" concealed: %d\n", concealedPicture); |
1663 | 1.72k | } |
1664 | | |
1665 | 1.78k | if (dpb.get_image(k)->integrity != INTEGRITY_CORRECT) { |
1666 | 1.78k | img->integrity = INTEGRITY_DERIVED_FROM_FAULTY_REFERENCE; |
1667 | 1.78k | } |
1668 | 1.78k | } |
1669 | | |
1670 | 11.1k | for (int i=0;i<NumPocStFoll;i++) { |
1671 | 2.63k | int k = dpb.DPB_index_of_picture_with_POC(PocStFoll[i], currentID); |
1672 | | // if (k<0) { assert(false); } // IGNORE |
1673 | | |
1674 | 2.63k | RefPicSetStFoll[i] = k; // -1 == "no reference picture" |
1675 | 2.63k | if (k>=0) picInAnyList[k]=true; |
1676 | 2.63k | } |
1677 | | |
1678 | | // 4. any picture that is not marked for reference is put into the "UnusedForReference" state |
1679 | | |
1680 | 22.4k | for (size_t i=0;i<dpb.size();i++) |
1681 | 13.9k | if (i>=picInAnyList.size() || !picInAnyList[i]) // no reference |
1682 | 9.32k | { |
1683 | 9.32k | de265_image* dpbimg = dpb.get_image(i); |
1684 | 9.32k | if (dpbimg != img && // not the current picture |
1685 | 898 | dpbimg->removed_at_picture_id > img->get_ID()) // has not been removed before |
1686 | 761 | { |
1687 | 761 | if (dpbimg->PicState != UnusedForReference) { |
1688 | 761 | removeReferencesList.push_back(dpbimg->get_ID()); |
1689 | | //printf("will remove ID %d (b)\n",dpbimg->get_ID()); |
1690 | | |
1691 | 761 | dpbimg->removed_at_picture_id = img->get_ID(); |
1692 | 761 | } |
1693 | 761 | } |
1694 | 9.32k | } |
1695 | | |
1696 | 8.51k | hdr->RemoveReferencesList = removeReferencesList; |
1697 | | |
1698 | | //remove_images_from_dpb(hdr->RemoveReferencesList); |
1699 | | |
1700 | 8.51k | return DE265_OK; |
1701 | 8.51k | } |
1702 | | |
1703 | | |
1704 | | // 8.3.4 |
1705 | | // Returns whether we can continue decoding (or whether there is a severe error). |
1706 | | /* Called at beginning of each slice. |
1707 | | |
1708 | | Constructs |
1709 | | - the RefPicList[2][], containing indices into the DPB, and |
1710 | | - the RefPicList_POC[2][], containing POCs. |
1711 | | - LongTermRefPic[2][] is also set to true if it is a long-term reference |
1712 | | */ |
1713 | | bool decoder_context::construct_reference_picture_lists(slice_segment_header* hdr) |
1714 | 1.59k | { |
1715 | 1.59k | int NumPocTotalCurr = hdr->NumPocTotalCurr; |
1716 | 1.59k | int NumRpsCurrTempList0 = std::max((int)hdr->num_ref_idx_l0_active, NumPocTotalCurr); |
1717 | | |
1718 | | // TODO: fold code for both lists together |
1719 | | |
1720 | 1.59k | int RefPicListTemp0[3*MAX_NUM_REF_PICS]; // TODO: what would be the correct maximum ? |
1721 | 1.59k | int RefPicListTemp1[3*MAX_NUM_REF_PICS]; // TODO: what would be the correct maximum ? |
1722 | 1.59k | char isLongTerm[2][3*MAX_NUM_REF_PICS]; |
1723 | | |
1724 | 1.59k | memset(isLongTerm,0,2*3*MAX_NUM_REF_PICS); |
1725 | | |
1726 | | /* --- Fill RefPicListTmp0 with reference pictures in this order: |
1727 | | 1) short term, past POC |
1728 | | 2) short term, future POC |
1729 | | 3) long term |
1730 | | */ |
1731 | | |
1732 | 1.59k | int rIdx=0; |
1733 | 4.32k | while (rIdx < NumRpsCurrTempList0) { |
1734 | 4.08k | for (int i=0;i<NumPocStCurrBefore && rIdx<NumRpsCurrTempList0; rIdx++,i++) |
1735 | 1.25k | RefPicListTemp0[rIdx] = RefPicSetStCurrBefore[i]; |
1736 | | |
1737 | 5.12k | for (int i=0;i<NumPocStCurrAfter && rIdx<NumRpsCurrTempList0; rIdx++,i++) |
1738 | 2.30k | RefPicListTemp0[rIdx] = RefPicSetStCurrAfter[i]; |
1739 | | |
1740 | 4.51k | for (int i=0;i<NumPocLtCurr && rIdx<NumRpsCurrTempList0; rIdx++,i++) { |
1741 | 1.68k | RefPicListTemp0[rIdx] = RefPicSetLtCurr[i]; |
1742 | 1.68k | isLongTerm[0][rIdx] = true; |
1743 | 1.68k | } |
1744 | | |
1745 | | // This check is to prevent an endless loop when no images are added above. |
1746 | 2.82k | if (rIdx==0) { |
1747 | 95 | add_warning(DE265_WARNING_FAULTY_REFERENCE_PICTURE_LIST, false); |
1748 | 95 | return false; |
1749 | 95 | } |
1750 | 2.82k | } |
1751 | | |
1752 | | /* |
1753 | | if (hdr->num_ref_idx_l0_active > 16) { |
1754 | | add_warning(DE265_WARNING_NONEXISTING_REFERENCE_PICTURE_ACCESSED, false); |
1755 | | return false; |
1756 | | } |
1757 | | */ |
1758 | | |
1759 | 1.59k | assert(hdr->num_ref_idx_l0_active <= 16); |
1760 | 5.48k | for (rIdx=0; rIdx<hdr->num_ref_idx_l0_active; rIdx++) { |
1761 | 4.03k | int idx = hdr->ref_pic_list_modification_flag_l0 ? hdr->list_entry_l0[rIdx] : rIdx; |
1762 | | |
1763 | 4.03k | if (idx >= NumRpsCurrTempList0) { |
1764 | 52 | add_warning(DE265_WARNING_FAULTY_REFERENCE_PICTURE_LIST, false); |
1765 | 52 | return false; |
1766 | 52 | } |
1767 | | |
1768 | 3.97k | hdr->RefPicList[0][rIdx] = RefPicListTemp0[idx]; |
1769 | 3.97k | hdr->LongTermRefPic[0][rIdx] = isLongTerm[0][idx]; |
1770 | | |
1771 | | // remember POC of referenced image (needed in motion.c, derive_collocated_motion_vector) |
1772 | 3.97k | de265_image* img_0_rIdx = dpb.get_image(hdr->RefPicList[0][rIdx]); |
1773 | 3.97k | if (img_0_rIdx==nullptr) { |
1774 | 0 | return false; |
1775 | 0 | } |
1776 | 3.97k | hdr->RefPicList_POC[0][rIdx] = img_0_rIdx->PicOrderCntVal; |
1777 | 3.97k | hdr->RefPicList_PicState[0][rIdx] = img_0_rIdx->PicState; |
1778 | 3.97k | } |
1779 | | |
1780 | | |
1781 | | /* --- Fill RefPicListTmp1 with reference pictures in this order: |
1782 | | 1) short term, future POC |
1783 | | 2) short term, past POC |
1784 | | 3) long term |
1785 | | */ |
1786 | | |
1787 | 1.45k | if (hdr->slice_type == SLICE_TYPE_B) { |
1788 | 1.30k | int NumRpsCurrTempList1 = std::max((int)hdr->num_ref_idx_l1_active, NumPocTotalCurr); |
1789 | | |
1790 | 1.30k | int rIdx=0; |
1791 | 3.37k | while (rIdx < NumRpsCurrTempList1) { |
1792 | 3.84k | for (int i=0;i<NumPocStCurrAfter && rIdx<NumRpsCurrTempList1; rIdx++,i++) { |
1793 | 1.77k | RefPicListTemp1[rIdx] = RefPicSetStCurrAfter[i]; |
1794 | 1.77k | } |
1795 | | |
1796 | 3.11k | for (int i=0;i<NumPocStCurrBefore && rIdx<NumRpsCurrTempList1; rIdx++,i++) { |
1797 | 1.04k | RefPicListTemp1[rIdx] = RefPicSetStCurrBefore[i]; |
1798 | 1.04k | } |
1799 | | |
1800 | 3.41k | for (int i=0;i<NumPocLtCurr && rIdx<NumRpsCurrTempList1; rIdx++,i++) { |
1801 | 1.34k | RefPicListTemp1[rIdx] = RefPicSetLtCurr[i]; |
1802 | 1.34k | isLongTerm[1][rIdx] = true; |
1803 | 1.34k | } |
1804 | | |
1805 | | // This check is to prevent an endless loop when no images are added above. |
1806 | 2.07k | if (rIdx==0) { |
1807 | 0 | add_warning(DE265_WARNING_FAULTY_REFERENCE_PICTURE_LIST, false); |
1808 | 0 | return false; |
1809 | 0 | } |
1810 | 2.07k | } |
1811 | | |
1812 | 1.30k | if (hdr->num_ref_idx_l0_active > 16) { |
1813 | 0 | add_warning(DE265_WARNING_NONEXISTING_REFERENCE_PICTURE_ACCESSED, false); |
1814 | 0 | return false; |
1815 | 0 | } |
1816 | | |
1817 | 1.30k | assert(hdr->num_ref_idx_l1_active <= 16); |
1818 | 4.23k | for (rIdx=0; rIdx<hdr->num_ref_idx_l1_active; rIdx++) { |
1819 | 2.93k | int idx = hdr->ref_pic_list_modification_flag_l1 ? hdr->list_entry_l1[rIdx] : rIdx; |
1820 | | |
1821 | 2.93k | if (idx >= NumRpsCurrTempList1) { |
1822 | 2 | add_warning(DE265_WARNING_FAULTY_REFERENCE_PICTURE_LIST, false); |
1823 | 2 | return false; |
1824 | 2 | } |
1825 | | |
1826 | 2.93k | hdr->RefPicList[1][rIdx] = RefPicListTemp1[idx]; |
1827 | 2.93k | hdr->LongTermRefPic[1][rIdx] = isLongTerm[1][idx]; |
1828 | | |
1829 | | // remember POC of referenced imaged (needed in motion.c, derive_collocated_motion_vector) |
1830 | 2.93k | de265_image* img_1_rIdx = dpb.get_image(hdr->RefPicList[1][rIdx]); |
1831 | 2.93k | if (img_1_rIdx == nullptr) { return false; } |
1832 | 2.93k | hdr->RefPicList_POC[1][rIdx] = img_1_rIdx->PicOrderCntVal; |
1833 | 2.93k | hdr->RefPicList_PicState[1][rIdx] = img_1_rIdx->PicState; |
1834 | 2.93k | } |
1835 | 1.30k | } |
1836 | | |
1837 | | |
1838 | | // show reference picture lists |
1839 | | |
1840 | 1.44k | loginfo(LogHeaders,"RefPicList[0] ="); |
1841 | 5.42k | for (rIdx=0; rIdx<hdr->num_ref_idx_l0_active; rIdx++) { |
1842 | 3.97k | loginfo(LogHeaders,"* [%d]=%d (LT=%d)", |
1843 | 3.97k | hdr->RefPicList[0][rIdx], |
1844 | 3.97k | hdr->RefPicList_POC[0][rIdx], |
1845 | 3.97k | hdr->LongTermRefPic[0][rIdx] |
1846 | 3.97k | ); |
1847 | 3.97k | } |
1848 | 1.44k | loginfo(LogHeaders,"*\n"); |
1849 | | |
1850 | 1.44k | if (hdr->slice_type == SLICE_TYPE_B) { |
1851 | 1.29k | loginfo(LogHeaders,"RefPicList[1] ="); |
1852 | 4.23k | for (rIdx=0; rIdx<hdr->num_ref_idx_l1_active; rIdx++) { |
1853 | 2.93k | loginfo(LogHeaders,"* [%d]=%d (LT=%d)", |
1854 | 2.93k | hdr->RefPicList[1][rIdx], |
1855 | 2.93k | hdr->RefPicList_POC[1][rIdx], |
1856 | 2.93k | hdr->LongTermRefPic[1][rIdx] |
1857 | 2.93k | ); |
1858 | 2.93k | } |
1859 | 1.29k | loginfo(LogHeaders,"*\n"); |
1860 | 1.29k | } |
1861 | | |
1862 | 1.44k | return true; |
1863 | 1.45k | } |
1864 | | |
1865 | | |
1866 | | |
1867 | | void decoder_context::run_postprocessing_filters_sequential(de265_image* img) |
1868 | 0 | { |
1869 | | #if SAVE_INTERMEDIATE_IMAGES |
1870 | | char buf[1000]; |
1871 | | sprintf(buf,"pre-lf-%05d.yuv", img->PicOrderCntVal); |
1872 | | write_picture_to_file(img, buf); |
1873 | | #endif |
1874 | |
|
1875 | 0 | if (!img->decctx->param_disable_deblocking) { |
1876 | 0 | apply_deblocking_filter(img); |
1877 | 0 | } |
1878 | |
|
1879 | | #if SAVE_INTERMEDIATE_IMAGES |
1880 | | sprintf(buf,"pre-sao-%05d.yuv", img->PicOrderCntVal); |
1881 | | write_picture_to_file(img, buf); |
1882 | | #endif |
1883 | |
|
1884 | 0 | if (!img->decctx->param_disable_sao) { |
1885 | 0 | apply_sample_adaptive_offset_sequential(img); |
1886 | 0 | } |
1887 | |
|
1888 | | #if SAVE_INTERMEDIATE_IMAGES |
1889 | | sprintf(buf,"sao-%05d.yuv", img->PicOrderCntVal); |
1890 | | write_picture_to_file(img, buf); |
1891 | | #endif |
1892 | 0 | } |
1893 | | |
1894 | | |
1895 | | void decoder_context::run_postprocessing_filters_parallel(image_unit* imgunit) |
1896 | 8.26k | { |
1897 | 8.26k | de265_image* img = imgunit->img; |
1898 | | |
1899 | 8.26k | int saoWaitsForProgress = CTB_PROGRESS_PREFILTER; |
1900 | 8.26k | bool waitForCompletion = false; |
1901 | | |
1902 | 8.26k | if (!img->decctx->param_disable_deblocking) { |
1903 | 8.26k | add_deblocking_tasks(imgunit); |
1904 | 8.26k | saoWaitsForProgress = CTB_PROGRESS_DEBLK_H; |
1905 | 8.26k | } |
1906 | | |
1907 | 8.26k | if (!img->decctx->param_disable_sao) { |
1908 | 8.26k | waitForCompletion |= add_sao_tasks(imgunit, saoWaitsForProgress); |
1909 | | //apply_sample_adaptive_offset(img); |
1910 | 8.26k | } |
1911 | | |
1912 | | // The original intention was to skip wait_for_completion() if there is no SAO task, |
1913 | | // but it does not work as intended. (TODO: check why) |
1914 | 8.26k | (void)waitForCompletion; |
1915 | | |
1916 | 8.26k | img->wait_for_completion(); |
1917 | 8.26k | } |
1918 | | |
1919 | | /* |
1920 | | void decoder_context::push_current_picture_to_output_queue() |
1921 | | { |
1922 | | push_picture_to_output_queue(img); |
1923 | | } |
1924 | | */ |
1925 | | |
1926 | | de265_error decoder_context::push_picture_to_output_queue(image_unit* imgunit) |
1927 | 8.26k | { |
1928 | 8.26k | de265_image* outimg = imgunit->img; |
1929 | | |
1930 | 8.26k | if (outimg==nullptr) { return DE265_OK; } |
1931 | | |
1932 | | |
1933 | | // push image into output queue |
1934 | | |
1935 | 8.26k | if (outimg->PicOutputFlag) { |
1936 | 8.20k | loginfo(LogDPB,"new picture has output-flag=true\n"); |
1937 | | |
1938 | 8.20k | if (outimg->integrity != INTEGRITY_CORRECT && |
1939 | 4.81k | param_suppress_faulty_pictures) { |
1940 | 0 | } |
1941 | 8.20k | else { |
1942 | 8.20k | dpb.insert_image_into_reorder_buffer(outimg); |
1943 | 8.20k | } |
1944 | | |
1945 | 8.20k | loginfo(LogDPB,"push image %d into reordering queue\n", outimg->PicOrderCntVal); |
1946 | 8.20k | } |
1947 | | |
1948 | | // check for full reorder buffers |
1949 | | |
1950 | 8.26k | int maxNumPicsInReorderBuffer = 0; |
1951 | | |
1952 | | // TODO: I'd like to have the has_vps() check somewhere else (not decode the picture at all) |
1953 | 8.26k | if (outimg->has_vps()) { |
1954 | 6.15k | int sublayer = outimg->get_vps().vps_max_sub_layers -1; |
1955 | 6.15k | maxNumPicsInReorderBuffer = outimg->get_vps().layer[sublayer].vps_max_num_reorder_pics; |
1956 | 6.15k | } |
1957 | | |
1958 | 8.26k | if (dpb.num_pictures_in_reorder_buffer() > maxNumPicsInReorderBuffer) { |
1959 | 8.19k | dpb.output_next_picture_in_reorder_buffer(); |
1960 | 8.19k | } |
1961 | | |
1962 | 8.26k | dpb.log_dpb_queues(); |
1963 | | |
1964 | 8.26k | return DE265_OK; |
1965 | 8.26k | } |
1966 | | |
1967 | | |
1968 | | // returns whether we can continue decoding the stream or whether we should give up |
1969 | | bool decoder_context::process_slice_segment_header(slice_segment_header* hdr, |
1970 | | de265_error* err, de265_PTS pts, |
1971 | | nal_header* nal_hdr, |
1972 | | void* user_data) |
1973 | 8.54k | { |
1974 | 8.54k | *err = DE265_OK; |
1975 | | |
1976 | 8.54k | flush_reorder_buffer_at_this_frame = false; |
1977 | | |
1978 | | |
1979 | | // get PPS and SPS for this slice |
1980 | | |
1981 | 8.54k | int pps_id = hdr->slice_pic_parameter_set_id; |
1982 | 8.55k | if (pps[pps_id]==nullptr || pps[pps_id]->pps_read==false) { |
1983 | 0 | logerror(LogHeaders, "PPS %d has not been read\n", pps_id); |
1984 | 0 | img->decctx->add_warning(DE265_WARNING_NONEXISTING_PPS_REFERENCED, false); |
1985 | 0 | return false; |
1986 | 0 | } |
1987 | | |
1988 | 8.54k | current_pps = pps[pps_id]; |
1989 | 8.54k | current_sps = sps[ (int)current_pps->seq_parameter_set_id ]; |
1990 | 8.54k | current_vps = vps[ (int)current_sps->video_parameter_set_id ]; |
1991 | | |
1992 | 8.54k | calc_tid_and_framerate_ratio(); |
1993 | | |
1994 | | |
1995 | | // --- prepare decoding of new picture --- |
1996 | | |
1997 | 8.54k | if (hdr->first_slice_segment_in_pic_flag) { |
1998 | | |
1999 | | // previous picture has been completely decoded |
2000 | | |
2001 | | //ctx->push_current_picture_to_output_queue(); |
2002 | | |
2003 | 8.53k | current_image_poc_lsb = hdr->slice_pic_order_cnt_lsb; |
2004 | | |
2005 | | |
2006 | 8.53k | seq_parameter_set* sps = current_sps.get(); |
2007 | | |
2008 | | |
2009 | | // --- find and allocate image buffer for decoding --- |
2010 | | |
2011 | 8.53k | int image_buffer_idx; |
2012 | 8.53k | bool isOutputImage = (!sps->sample_adaptive_offset_enabled_flag || param_disable_sao); |
2013 | 8.53k | image_buffer_idx = dpb.new_image(current_sps, this, pts, user_data, isOutputImage); |
2014 | 8.53k | if (image_buffer_idx < 0) { |
2015 | 0 | *err = (de265_error)(-image_buffer_idx); |
2016 | 0 | return false; |
2017 | 0 | } |
2018 | | |
2019 | 8.53k | /*de265_image* */ img = dpb.get_image(image_buffer_idx); |
2020 | 8.53k | img->nal_hdr = *nal_hdr; |
2021 | | |
2022 | | // Note: sps is already set in new_image() -> ??? still the case with shared_ptr ? |
2023 | | |
2024 | 8.53k | img->set_headers(current_vps, current_sps, current_pps); |
2025 | | |
2026 | 8.53k | img->decctx = this; |
2027 | | |
2028 | 8.53k | img->clear_metadata(); |
2029 | | |
2030 | | |
2031 | 8.53k | if (isIRAP(nal_unit_type)) { |
2032 | 8.11k | if (isIDR(nal_unit_type) || |
2033 | 1.87k | isBLA(nal_unit_type) || |
2034 | 653 | first_decoded_picture || |
2035 | 0 | FirstAfterEndOfSequenceNAL) |
2036 | 8.11k | { |
2037 | 8.11k | NoRaslOutputFlag = true; |
2038 | 8.11k | FirstAfterEndOfSequenceNAL = false; |
2039 | 8.11k | } |
2040 | 18.4E | else if (0) // TODO: set HandleCraAsBlaFlag by external means |
2041 | 0 | { |
2042 | 0 | } |
2043 | 18.4E | else |
2044 | 18.4E | { |
2045 | 18.4E | NoRaslOutputFlag = false; |
2046 | 18.4E | HandleCraAsBlaFlag = false; |
2047 | 18.4E | } |
2048 | 8.11k | } |
2049 | | |
2050 | | |
2051 | 8.53k | if (isRASL(nal_unit_type) && |
2052 | 5 | NoRaslOutputFlag) |
2053 | 2 | { |
2054 | 2 | img->PicOutputFlag = false; |
2055 | 2 | } |
2056 | 8.53k | else |
2057 | 8.53k | { |
2058 | 8.53k | img->PicOutputFlag = !!hdr->pic_output_flag; |
2059 | 8.53k | } |
2060 | | |
2061 | 8.53k | process_picture_order_count(hdr); |
2062 | | |
2063 | 8.53k | if (hdr->first_slice_segment_in_pic_flag) { |
2064 | | // mark picture so that it is not overwritten by unavailable reference frames |
2065 | 8.52k | img->PicState = UsedForShortTermReference; |
2066 | | |
2067 | 8.52k | *err = process_reference_picture_set(hdr); |
2068 | 8.52k | if (*err != DE265_OK) { |
2069 | 10 | return false; |
2070 | 10 | } |
2071 | 8.52k | } |
2072 | | |
2073 | 8.52k | img->PicState = UsedForShortTermReference; |
2074 | | |
2075 | 8.52k | log_set_current_POC(img->PicOrderCntVal); |
2076 | | |
2077 | | |
2078 | | // next image is not the first anymore |
2079 | | |
2080 | 8.52k | first_decoded_picture = false; |
2081 | 8.52k | } |
2082 | 14 | else { |
2083 | | // claims to be not the first slice, but there is no active image available |
2084 | | |
2085 | 14 | if (img == nullptr) { |
2086 | 6 | return false; |
2087 | 6 | } |
2088 | 14 | } |
2089 | | |
2090 | 8.53k | if (hdr->slice_type == SLICE_TYPE_B || |
2091 | 7.22k | hdr->slice_type == SLICE_TYPE_P) |
2092 | 1.59k | { |
2093 | 1.59k | bool success = construct_reference_picture_lists(hdr); |
2094 | 1.59k | if (!success) { |
2095 | 149 | return false; |
2096 | 149 | } |
2097 | 1.59k | } |
2098 | | |
2099 | | //printf("process slice segment header\n"); |
2100 | | |
2101 | 8.38k | loginfo(LogHeaders,"end of process-slice-header\n"); |
2102 | 8.38k | dpb.log_dpb_content(); |
2103 | | |
2104 | | |
2105 | 8.40k | if (hdr->dependent_slice_segment_flag==0) { |
2106 | 8.40k | hdr->SliceAddrRS = hdr->slice_segment_address; |
2107 | 18.4E | } else { |
2108 | 18.4E | hdr->SliceAddrRS = previous_slice_header->SliceAddrRS; |
2109 | 18.4E | } |
2110 | | |
2111 | | // Note: previous_slice_header is updated by the caller (read_slice_NAL) only |
2112 | | // once the slice header is actually retained by the image. Setting it here |
2113 | | // would leave a dangling pointer when the caller discards/deletes 'hdr'. |
2114 | | |
2115 | | |
2116 | 8.38k | loginfo(LogHeaders,"SliceAddrRS = %d\n",hdr->SliceAddrRS); |
2117 | | |
2118 | 8.38k | return true; |
2119 | 8.53k | } |
2120 | | |
2121 | | |
2122 | | void decoder_context::remove_images_from_dpb(const std::vector<int>& removeImageList) |
2123 | 15.4k | { |
2124 | 15.7k | for (size_t i=0;i<removeImageList.size();i++) { |
2125 | 243 | int idx = dpb.DPB_index_of_picture_with_ID( removeImageList[i] ); |
2126 | 243 | if (idx>=0) { |
2127 | | //printf("remove ID %d\n", removeImageList[i]); |
2128 | 243 | de265_image* dpbimg = dpb.get_image( idx ); |
2129 | 243 | dpbimg->PicState = UnusedForReference; |
2130 | 243 | } |
2131 | 243 | } |
2132 | 15.4k | } |
2133 | | |
2134 | | |
2135 | | |
2136 | | /* |
2137 | | . 0 1 2 <- goal_HighestTid |
2138 | | +-----+-----+-----+ |
2139 | | | -0->| -1->| -2->| |
2140 | | +-----+-----+-----+ |
2141 | | 0 33 66 100 <- framerate_ratio |
2142 | | */ |
2143 | | |
2144 | | int decoder_context::get_highest_TID() const |
2145 | 25.9k | { |
2146 | 25.9k | if (current_sps) { return current_sps->sps_max_sub_layers-1; } |
2147 | 9.07k | if (current_vps) { return current_vps->vps_max_sub_layers-1; } |
2148 | | |
2149 | 9.07k | return 6; |
2150 | 9.07k | } |
2151 | | |
2152 | | void decoder_context::set_limit_TID(int max_tid) |
2153 | 0 | { |
2154 | 0 | limit_HighestTid = max_tid; |
2155 | 0 | calc_tid_and_framerate_ratio(); |
2156 | 0 | } |
2157 | | |
2158 | | int decoder_context::change_framerate(int more) |
2159 | 0 | { |
2160 | 0 | if (current_sps == nullptr) { return framerate_ratio; } |
2161 | | |
2162 | 0 | int highestTid = get_highest_TID(); |
2163 | |
|
2164 | 0 | assert(more>=-1 && more<=1); |
2165 | | |
2166 | 0 | goal_HighestTid += more; |
2167 | 0 | goal_HighestTid = std::max(goal_HighestTid, 0); |
2168 | 0 | goal_HighestTid = std::min(goal_HighestTid, highestTid); |
2169 | |
|
2170 | 0 | framerate_ratio = framedrop_tid_index[goal_HighestTid]; |
2171 | |
|
2172 | 0 | calc_tid_and_framerate_ratio(); |
2173 | |
|
2174 | 0 | return framerate_ratio; |
2175 | 0 | } |
2176 | | |
2177 | | void decoder_context::set_framerate_ratio(int percent) |
2178 | 0 | { |
2179 | 0 | framerate_ratio = percent; |
2180 | 0 | calc_tid_and_framerate_ratio(); |
2181 | 0 | } |
2182 | | |
2183 | | void decoder_context::compute_framedrop_table() |
2184 | 17.3k | { |
2185 | 17.3k | int highestTID = get_highest_TID(); |
2186 | | |
2187 | 89.4k | for (int tid=highestTID ; tid>=0 ; tid--) { |
2188 | 72.1k | int lower = 100 * tid /(highestTID+1); |
2189 | 72.1k | int higher = 100 * (tid+1)/(highestTID+1); |
2190 | | |
2191 | 1.87M | for (int l=lower; l<=higher; l++) { |
2192 | 1.80M | int ratio = 100 * (l-lower) / (higher-lower); |
2193 | | |
2194 | | // if we would exceed our TID limit, decode the highest TID at full frame-rate |
2195 | 1.80M | if (tid > limit_HighestTid) { |
2196 | 0 | tid = limit_HighestTid; |
2197 | 0 | ratio = 100; |
2198 | 0 | } |
2199 | | |
2200 | 1.80M | framedrop_tab[l].tid = tid; |
2201 | 1.80M | framedrop_tab[l].ratio = ratio; |
2202 | 1.80M | } |
2203 | | |
2204 | 72.1k | framedrop_tid_index[tid] = higher; |
2205 | 72.1k | } |
2206 | | |
2207 | | #if 0 |
2208 | | for (int i=0;i<=100;i++) { |
2209 | | printf("%d%%: %d/%d",i, framedrop_tab[i].tid, framedrop_tab[i].ratio); |
2210 | | for (int k=0;k<=highestTID;k++) { |
2211 | | if (framedrop_tid_index[k] == i) printf(" ** TID=%d **",k); |
2212 | | } |
2213 | | printf("\n"); |
2214 | | } |
2215 | | #endif |
2216 | 17.3k | } |
2217 | | |
2218 | | void decoder_context::calc_tid_and_framerate_ratio() |
2219 | 8.57k | { |
2220 | 8.57k | int highestTID = get_highest_TID(); |
2221 | | |
2222 | | |
2223 | | // if number of temporal layers changed, we have to recompute the framedrop table |
2224 | | |
2225 | 8.57k | if (framedrop_tab[100].tid != highestTID) { |
2226 | 8.28k | compute_framedrop_table(); |
2227 | 8.28k | } |
2228 | | |
2229 | 8.57k | goal_HighestTid = framedrop_tab[framerate_ratio].tid; |
2230 | 8.57k | layer_framerate_ratio = framedrop_tab[framerate_ratio].ratio; |
2231 | | |
2232 | | // TODO: for now, we switch immediately |
2233 | 8.57k | current_HighestTid = goal_HighestTid; |
2234 | 8.57k | } |
2235 | | |
2236 | | |
2237 | | void error_queue::add_warning(de265_error warning, bool once) |
2238 | 35.8k | { |
2239 | 35.8k | std::lock_guard<std::mutex> lock(m_mutex); |
2240 | | |
2241 | | // check if warning was already shown |
2242 | 35.8k | if (once) { |
2243 | 22.8k | if (std::find(warnings_shown.begin(), warnings_shown.end(), warning) != warnings_shown.end()) { |
2244 | 15.5k | return; |
2245 | 15.5k | } |
2246 | 7.23k | warnings_shown.push_back(warning); |
2247 | 7.23k | } |
2248 | | |
2249 | | // add warning to output queue |
2250 | 20.3k | if (warnings.size() >= MAX_WARNINGS) { |
2251 | 1.00k | warnings.back() = DE265_WARNING_WARNING_BUFFER_FULL; |
2252 | 1.00k | return; |
2253 | 1.00k | } |
2254 | | |
2255 | 19.3k | warnings.push_back(warning); |
2256 | 19.3k | } |
2257 | | |
2258 | | de265_error error_queue::get_warning() |
2259 | 0 | { |
2260 | 0 | std::lock_guard<std::mutex> lock(m_mutex); |
2261 | |
|
2262 | 0 | if (warnings.empty()) { |
2263 | 0 | return DE265_OK; |
2264 | 0 | } |
2265 | | |
2266 | 0 | de265_error warn = warnings.front(); |
2267 | 0 | warnings.erase(warnings.begin()); |
2268 | |
|
2269 | 0 | return warn; |
2270 | 0 | } |