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