/src/libde265/libde265/dpb.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 "dpb.h" |
22 | | #include "decctx.h" |
23 | | #include <string.h> |
24 | | #include <assert.h> |
25 | | |
26 | | |
27 | | decoded_picture_buffer::~decoded_picture_buffer() |
28 | 9.02k | { |
29 | 21.9k | for (size_t i=0;i<dpb.size();i++) |
30 | 12.9k | delete dpb[i]; |
31 | 9.02k | } |
32 | | |
33 | | |
34 | | void decoded_picture_buffer::log_dpb_content() const |
35 | 23.2k | { |
36 | 54.6k | for (size_t i=0;i<dpb.size();i++) { |
37 | 31.4k | loginfo(LogHighlevel, " DPB %d: POC=%d, ID=%d %s %s\n", i, |
38 | 31.4k | dpb[i]->PicOrderCntVal, |
39 | 31.4k | dpb[i]->get_ID(), |
40 | 31.4k | dpb[i]->PicState == UnusedForReference ? "unused" : |
41 | 31.4k | dpb[i]->PicState == UsedForShortTermReference ? "short-term" : "long-term", |
42 | 31.4k | dpb[i]->PicOutputFlag ? "output" : "---"); |
43 | 31.4k | } |
44 | 23.2k | } |
45 | | |
46 | | |
47 | | bool decoded_picture_buffer::has_free_dpb_picture(bool high_priority) const |
48 | 26.8k | { |
49 | | // we will always adapt the buffer to insert high-priority images |
50 | 26.8k | if (high_priority) return true; |
51 | | |
52 | | // quick test to check for free slots |
53 | 26.8k | if (dpb.size() < max_images_in_DPB) return true; |
54 | | |
55 | | // scan for empty slots |
56 | 0 | for (size_t i=0;i<dpb.size();i++) { |
57 | 0 | if (dpb[i]->PicOutputFlag==false && dpb[i]->PicState == UnusedForReference) { |
58 | 0 | return true; |
59 | 0 | } |
60 | 0 | } |
61 | | |
62 | 0 | return false; |
63 | 0 | } |
64 | | |
65 | | |
66 | | int decoded_picture_buffer::DPB_index_of_picture_with_POC(int poc, uint32_t currentID, bool preferLongTerm) const |
67 | 8.03k | { |
68 | 8.03k | logdebug(LogHeaders,"DPB_index_of_picture_with_POC POC=%d\n",poc); |
69 | | |
70 | | //log_dpb_content(ctx); |
71 | | //loginfo(LogDPB,"searching for short-term reference POC=%d\n",poc); |
72 | | |
73 | 8.03k | if (preferLongTerm) { |
74 | 8.00k | for (size_t k=0;k<dpb.size();k++) { |
75 | 4.83k | if (dpb[k]->PicOrderCntVal == poc && |
76 | 115 | dpb[k]->removed_at_picture_id > currentID && |
77 | 110 | dpb[k]->PicState == UsedForLongTermReference) { |
78 | 28 | return k; |
79 | 28 | } |
80 | 4.83k | } |
81 | 3.19k | } |
82 | | |
83 | 22.6k | for (size_t k=0;k<dpb.size();k++) { |
84 | 14.8k | if (dpb[k]->PicOrderCntVal == poc && |
85 | 290 | dpb[k]->removed_at_picture_id > currentID && |
86 | 283 | dpb[k]->PicState != UnusedForReference) { |
87 | 283 | return k; |
88 | 283 | } |
89 | 14.8k | } |
90 | | |
91 | 7.72k | return -1; |
92 | 8.00k | } |
93 | | |
94 | | |
95 | | int decoded_picture_buffer::DPB_index_of_picture_with_LSB(int lsb, uint32_t currentID, bool preferLongTerm) const |
96 | 1.52k | { |
97 | 1.52k | logdebug(LogHeaders,"get access to picture with LSB %d from DPB\n",lsb); |
98 | | |
99 | 1.52k | if (preferLongTerm) { |
100 | 4.10k | for (size_t k=0;k<dpb.size();k++) { |
101 | 2.69k | if (dpb[k]->picture_order_cnt_lsb == lsb && |
102 | 459 | dpb[k]->removed_at_picture_id > currentID && |
103 | 452 | dpb[k]->PicState == UsedForLongTermReference) { |
104 | 114 | return k; |
105 | 114 | } |
106 | 2.69k | } |
107 | 1.52k | } |
108 | | |
109 | 3.35k | for (size_t k=0;k<dpb.size();k++) { |
110 | 2.27k | if (dpb[k]->picture_order_cnt_lsb == lsb && |
111 | 334 | dpb[k]->removed_at_picture_id > currentID && |
112 | 327 | dpb[k]->PicState != UnusedForReference) { |
113 | 327 | return k; |
114 | 327 | } |
115 | 2.27k | } |
116 | | |
117 | 1.08k | return -1; |
118 | 1.41k | } |
119 | | |
120 | | |
121 | | int decoded_picture_buffer::DPB_index_of_picture_with_ID(uint32_t id) const |
122 | 130 | { |
123 | 130 | logdebug(LogHeaders,"get access to picture with ID %d from DPB\n",id); |
124 | | |
125 | 282 | for (size_t k=0;k<dpb.size();k++) { |
126 | 282 | if (dpb[k]->get_ID() == id) { |
127 | 130 | return k; |
128 | 130 | } |
129 | 282 | } |
130 | | |
131 | 0 | return -1; |
132 | 130 | } |
133 | | |
134 | | |
135 | | void decoded_picture_buffer::output_next_picture_in_reorder_buffer() |
136 | 4.40k | { |
137 | 4.40k | assert(!reorder_output_queue.empty()); |
138 | | |
139 | | // search for picture in reorder buffer with minimum POC |
140 | | |
141 | 4.40k | int minPOC = reorder_output_queue[0]->PicOrderCntVal; |
142 | 4.40k | int minIdx = 0; |
143 | 4.41k | for (size_t i=1;i<reorder_output_queue.size();i++) |
144 | 18 | { |
145 | 18 | if (reorder_output_queue[i]->PicOrderCntVal < minPOC) { |
146 | 16 | minPOC = reorder_output_queue[i]->PicOrderCntVal; |
147 | 16 | minIdx = i; |
148 | 16 | } |
149 | 18 | } |
150 | | |
151 | | |
152 | | // put image into output queue |
153 | | |
154 | 4.40k | image_output_queue.push_back(reorder_output_queue[minIdx]); |
155 | | |
156 | | |
157 | | // remove image from reorder buffer |
158 | | |
159 | 4.40k | reorder_output_queue[minIdx] = reorder_output_queue.back(); |
160 | 4.40k | reorder_output_queue.pop_back(); |
161 | 4.40k | } |
162 | | |
163 | | |
164 | | bool decoded_picture_buffer::flush_reorder_buffer() |
165 | 116k | { |
166 | | // return 'false' when there are no pictures in reorder buffer |
167 | 116k | if (reorder_output_queue.empty()) return false; |
168 | | |
169 | 51 | while (!reorder_output_queue.empty()) { |
170 | 29 | output_next_picture_in_reorder_buffer(); |
171 | 29 | } |
172 | | |
173 | 22 | return true; |
174 | 116k | } |
175 | | |
176 | | |
177 | | void decoded_picture_buffer::clear() |
178 | 0 | { |
179 | 0 | for (size_t i=0;i<dpb.size();i++) { |
180 | 0 | if (dpb[i]->PicOutputFlag || |
181 | 0 | dpb[i]->PicState != UnusedForReference) |
182 | 0 | { |
183 | 0 | dpb[i]->PicOutputFlag = false; |
184 | 0 | dpb[i]->PicState = UnusedForReference; |
185 | 0 | dpb[i]->release(); |
186 | 0 | } |
187 | 0 | } |
188 | |
|
189 | 0 | reorder_output_queue.clear(); |
190 | 0 | image_output_queue.clear(); |
191 | 0 | } |
192 | | |
193 | | |
194 | | int decoded_picture_buffer::new_image(std::shared_ptr<const seq_parameter_set> sps, |
195 | | decoder_context* decctx, |
196 | | de265_PTS pts, void* user_data, bool isOutputImage) |
197 | 12.9k | { |
198 | 12.9k | loginfo(LogHeaders,"DPB::new_image\n"); |
199 | 12.9k | log_dpb_content(); |
200 | | |
201 | | // --- search for a free slot in the DPB --- |
202 | | |
203 | 12.9k | uint8_t free_image_buffer_idx = 0; |
204 | 12.9k | uint8_t err = DE265_ERROR_IMAGE_BUFFER_FULL; |
205 | | |
206 | 25.7k | for (size_t i=0;i<dpb.size();i++) { |
207 | 12.8k | if (dpb[i]->can_be_released()) { |
208 | 0 | dpb[i]->release(); /* TODO: this is surely not the best place to free the image, but |
209 | | we have to do it here because releasing it in de265_release_image() |
210 | | would break the API compatibility. */ |
211 | |
|
212 | 0 | free_image_buffer_idx = i; |
213 | 0 | err = DE265_OK; |
214 | 0 | break; |
215 | 0 | } |
216 | 12.8k | } |
217 | | |
218 | | |
219 | | // Try to free a buffer at the end if the DPB got too large. |
220 | | /* This should also probably move to a better place as soon as the API allows for this. */ |
221 | | |
222 | 12.9k | if (dpb.size() > norm_images_in_DPB && // buffer too large |
223 | 0 | free_image_buffer_idx != dpb.size()-1 && // last slot not reused in this alloc |
224 | 0 | dpb.back()->can_be_released()) // last slot is free |
225 | 0 | { |
226 | 0 | delete dpb.back(); |
227 | 0 | dpb.pop_back(); |
228 | 0 | } |
229 | | |
230 | | |
231 | | // create a new image slot if no empty slot remaining |
232 | | |
233 | 12.9k | if (err == DE265_ERROR_IMAGE_BUFFER_FULL) { |
234 | 12.9k | size_t dpb_size = dpb.size(); |
235 | 12.9k | assert(dpb_size < 255); |
236 | | |
237 | 12.9k | free_image_buffer_idx = static_cast<uint8_t>(dpb_size); |
238 | 12.9k | dpb.push_back(new de265_image); |
239 | 12.9k | err = DE265_OK; |
240 | 12.9k | } |
241 | | |
242 | | |
243 | | // --- allocate new image --- |
244 | | |
245 | 12.9k | if (err) { |
246 | 0 | return -err; |
247 | 0 | } |
248 | | |
249 | 12.9k | de265_image* img = dpb[free_image_buffer_idx]; |
250 | | |
251 | 12.9k | int w = sps->pic_width_in_luma_samples; |
252 | 12.9k | int h = sps->pic_height_in_luma_samples; |
253 | | |
254 | | // --- enforce maximum image size before allocating the image buffer --- |
255 | | |
256 | 12.9k | uint32_t max_image_size_pixels = decctx->param_security_limits.max_image_size_pixels; |
257 | 12.9k | if (max_image_size_pixels != 0 && |
258 | 12.9k | (uint64_t)w * h > max_image_size_pixels) { |
259 | 84 | return -DE265_ERROR_IMAGE_SIZE_EXCEEDS_SECURITY_LIMIT; |
260 | 84 | } |
261 | | |
262 | 12.8k | enum de265_chroma chroma; |
263 | 12.8k | switch (sps->chroma_format_idc) { |
264 | 0 | case 0: chroma = de265_chroma_mono; break; |
265 | 6.79k | case 1: chroma = de265_chroma_420; break; |
266 | 3.62k | case 2: chroma = de265_chroma_422; break; |
267 | 2.43k | case 3: chroma = de265_chroma_444; break; |
268 | 0 | default: chroma = de265_chroma_420; assert(0); break; // should never happen |
269 | 12.8k | } |
270 | | |
271 | 12.8k | de265_error error = img->alloc_image(w,h, chroma, sps, true, decctx, /*nullptr,*/ pts, user_data, isOutputImage); |
272 | 12.8k | if (error) { |
273 | 1 | return -error; |
274 | 1 | } |
275 | | |
276 | 12.8k | img->integrity = INTEGRITY_CORRECT; |
277 | | |
278 | 12.8k | return free_image_buffer_idx; |
279 | 12.8k | } |
280 | | |
281 | | |
282 | | void decoded_picture_buffer::pop_next_picture_in_output_queue() |
283 | 4.39k | { |
284 | 4.39k | image_output_queue.pop_front(); |
285 | | |
286 | | |
287 | 4.39k | loginfo(LogDPB, "DPB output queue: "); |
288 | 4.40k | for (size_t i=0;i<image_output_queue.size();i++) { |
289 | 7 | loginfo(LogDPB, "*%d ", image_output_queue[i]->PicOrderCntVal); |
290 | 7 | } |
291 | 4.39k | loginfo(LogDPB,"*\n"); |
292 | 4.39k | } |
293 | | |
294 | | |
295 | | void decoded_picture_buffer::log_dpb_queues() const |
296 | 5.03k | { |
297 | 5.03k | loginfo(LogDPB, "DPB reorder queue (after push): "); |
298 | 5.09k | for (int i=0;i<num_pictures_in_reorder_buffer();i++) { |
299 | 66 | loginfo(LogDPB, "*%d ", reorder_output_queue[i]->PicOrderCntVal); |
300 | 66 | } |
301 | 5.03k | loginfo(LogDPB,"*\n"); |
302 | | |
303 | 5.03k | loginfo(LogDPB, "DPB output queue (after push): "); |
304 | 9.41k | for (int i=0;i<num_pictures_in_output_queue();i++) { |
305 | 4.38k | loginfo(LogDPB, "*%d ", image_output_queue[i]->PicOrderCntVal); |
306 | 4.38k | } |
307 | 5.03k | loginfo(LogDPB,"*\n"); |
308 | 5.03k | } |