/src/libhevc/common/ihevc_dpb_mgr.c
Line | Count | Source (jump to first uncovered line) |
1 | | /****************************************************************************** |
2 | | * |
3 | | * Copyright (C) 2012 Ittiam Systems Pvt Ltd, Bangalore |
4 | | * |
5 | | * Licensed under the Apache License, Version 2.0 (the "License"); |
6 | | * you may not use this file except in compliance with the License. |
7 | | * You may obtain a copy of the License at: |
8 | | * |
9 | | * http://www.apache.org/licenses/LICENSE-2.0 |
10 | | * |
11 | | * Unless required by applicable law or agreed to in writing, software |
12 | | * distributed under the License is distributed on an "AS IS" BASIS, |
13 | | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
14 | | * See the License for the specific language governing permissions and |
15 | | * limitations under the License. |
16 | | * |
17 | | ******************************************************************************/ |
18 | | /** |
19 | | ******************************************************************************* |
20 | | * @file |
21 | | * ihevc_dpb_mgr.c |
22 | | * |
23 | | * @brief |
24 | | * Function definitions used for decoded picture buffer management |
25 | | * |
26 | | * @author |
27 | | * Srinivas T |
28 | | * |
29 | | * @par List of Functions: |
30 | | * - ihevc_dpb_mgr_init() |
31 | | * - ihevc_dpb_mgr_del_lt() |
32 | | * - ihevc_dpb_mgr_insert_lt() |
33 | | * - ihevc_dpb_mgr_del_st_or_make_lt() |
34 | | * - ihevc_dpb_mgr_insert_st() |
35 | | * - ihevc_dpb_mgr_reset() |
36 | | * - ihevc_dpb_mgr_release_pics() |
37 | | * |
38 | | * @remarks |
39 | | * None |
40 | | * |
41 | | ******************************************************************************* |
42 | | */ |
43 | | |
44 | | #include <stdio.h> |
45 | | #include <stdlib.h> |
46 | | |
47 | | #include "ihevc_typedefs.h" |
48 | | #include "ihevc_defs.h" |
49 | | #include "ihevc_macros.h" |
50 | | #include "ihevc_func_selector.h" |
51 | | #include "ihevc_structs.h" |
52 | | #include "ihevc_buf_mgr.h" |
53 | | #include "ihevc_dpb_mgr.h" |
54 | | |
55 | | /** |
56 | | ******************************************************************************* |
57 | | * |
58 | | * @brief |
59 | | * DPB manager initializer |
60 | | * |
61 | | * @par Description: |
62 | | * Initialises the DPB manager structure |
63 | | * |
64 | | * @param[in] ps_dpb_mgr |
65 | | * Pointer to the DPB manager structure |
66 | | * |
67 | | * @returns |
68 | | * |
69 | | * @remarks |
70 | | * |
71 | | * |
72 | | ******************************************************************************* |
73 | | */ |
74 | | |
75 | | void ihevc_dpb_mgr_init(dpb_mgr_t *ps_dpb_mgr) |
76 | 102 | { |
77 | 102 | UWORD32 i; |
78 | 102 | dpb_info_t *ps_dpb_info = ps_dpb_mgr->as_dpb_info; |
79 | 6.63k | for(i = 0; i < MAX_DPB_BUFS; i++) |
80 | 6.52k | { |
81 | 6.52k | ps_dpb_info[i].ps_prev_dpb = NULL; |
82 | 6.52k | ps_dpb_info[i].ps_pic_buf = NULL; |
83 | | |
84 | 6.52k | } |
85 | | |
86 | 102 | ps_dpb_mgr->u1_num_ref_bufs = 0; |
87 | 102 | ps_dpb_mgr->ps_dpb_head = NULL; |
88 | | |
89 | 102 | } |
90 | | |
91 | | |
92 | | /** |
93 | | ******************************************************************************* |
94 | | * |
95 | | * @brief |
96 | | * Adds a reference picture into the linked list |
97 | | * |
98 | | * @par Description: |
99 | | * Adds the reference buffer with the given buffer id into the DPB manager |
100 | | * |
101 | | * |
102 | | * @param[in] ps_dpb_mgr |
103 | | * Pointer to the DPB manager structure |
104 | | * |
105 | | * @param[in] ps_picBuf |
106 | | * Pointer to the picture buffer |
107 | | * |
108 | | * @param[in] buf_id |
109 | | * buffer id of the picture buffer |
110 | | * |
111 | | * @returns 0 if successful, -1 otherwise |
112 | | * |
113 | | * @remarks |
114 | | * |
115 | | * |
116 | | ******************************************************************************* |
117 | | */ |
118 | | |
119 | | WORD32 ihevc_dpb_mgr_insert_ref(dpb_mgr_t *ps_dpb_mgr, |
120 | | pic_buf_t *ps_pic_buf, |
121 | | WORD32 buf_id) |
122 | 1.34k | { |
123 | 1.34k | int i; |
124 | 1.34k | dpb_info_t *ps_dpb_info; |
125 | | |
126 | 1.34k | ps_dpb_info = ps_dpb_mgr->as_dpb_info; |
127 | | |
128 | | /* Return error if buffer is already present in the DPB */ |
129 | 87.1k | for(i = 0; i < MAX_DPB_BUFS; i++) |
130 | 85.8k | { |
131 | 85.8k | if((ps_dpb_info[i].ps_pic_buf == ps_pic_buf) |
132 | 85.8k | && (ps_dpb_info[i].ps_pic_buf->u1_used_as_ref)) |
133 | 0 | { |
134 | 0 | return (-1); |
135 | 0 | } |
136 | | |
137 | | |
138 | 85.8k | } |
139 | | |
140 | | /* Find an unused DPB location */ |
141 | 3.47k | for(i = 0; i < MAX_DPB_BUFS; i++) |
142 | 3.47k | { |
143 | 3.47k | if(NULL == ps_dpb_info[i].ps_pic_buf) |
144 | 1.34k | { |
145 | 1.34k | break; |
146 | 1.34k | } |
147 | 3.47k | } |
148 | 1.34k | if(i == MAX_DPB_BUFS) |
149 | 0 | { |
150 | 0 | return (-1); |
151 | 0 | } |
152 | | |
153 | | /* Create DPB info */ |
154 | 1.34k | ps_dpb_info[i].ps_pic_buf = ps_pic_buf; |
155 | 1.34k | ps_dpb_info[i].ps_prev_dpb = ps_dpb_mgr->ps_dpb_head; |
156 | 1.34k | ps_dpb_info[i].ps_pic_buf->u1_buf_id = buf_id; |
157 | 1.34k | ps_dpb_info[i].ps_pic_buf->u1_used_as_ref = SHORT_TERM_REF; |
158 | | |
159 | | /* update the head node of linked list to point to the current picture */ |
160 | 1.34k | ps_dpb_mgr->ps_dpb_head = ps_dpb_info + i; |
161 | | |
162 | | /* Increment Short term buffer count */ |
163 | 1.34k | ps_dpb_mgr->u1_num_ref_bufs++; |
164 | | |
165 | 1.34k | return 0; |
166 | 1.34k | } |
167 | | |
168 | | /** |
169 | | ******************************************************************************* |
170 | | * |
171 | | * @brief |
172 | | * Deletes a reference buffer from the dpb manager |
173 | | * |
174 | | * @par Description: |
175 | | * Delete short term reference with a given POC from the linked |
176 | | * list |
177 | | * |
178 | | * @param[in] ps_dpb_mgr |
179 | | * Pointer to DPB Manager structure |
180 | | * |
181 | | * @param[in] ps_buf_mgr |
182 | | * Pointer to buffer manager structure |
183 | | * |
184 | | * @param[in] u4_abs_poc |
185 | | * Node's absolute poc |
186 | | * |
187 | | * |
188 | | * @returns 0 if successful, -1 otherwise |
189 | | * |
190 | | * @remarks |
191 | | * |
192 | | * |
193 | | ******************************************************************************* |
194 | | */ |
195 | | |
196 | | void ihevc_dpb_mgr_del_ref(dpb_mgr_t *ps_dpb_mgr, |
197 | | buf_mgr_t *ps_buf_mgr, |
198 | | WORD32 i4_abs_poc) |
199 | 1.20k | { |
200 | 1.20k | int i; |
201 | 1.20k | dpb_info_t *ps_next_dpb; |
202 | | |
203 | 1.20k | dpb_info_t *ps_unmark_node; |
204 | 1.20k | UWORD8 u1_del_node; |
205 | 1.20k | UNUSED(u1_del_node); |
206 | 1.20k | u1_del_node = 0; |
207 | | |
208 | | /* Find the node with matching absolute POC */ |
209 | 1.20k | ps_next_dpb = ps_dpb_mgr->ps_dpb_head; |
210 | 1.20k | if(ps_next_dpb->ps_pic_buf->i4_abs_poc == i4_abs_poc) |
211 | 817 | { |
212 | 817 | ps_unmark_node = ps_next_dpb; |
213 | 817 | } |
214 | 389 | else |
215 | 389 | { |
216 | 666 | for(i = 1; i < ps_dpb_mgr->u1_num_ref_bufs; i++) |
217 | 666 | { |
218 | 666 | if(ps_next_dpb->ps_prev_dpb->ps_pic_buf->i4_abs_poc == i4_abs_poc) |
219 | 389 | break; |
220 | 277 | ps_next_dpb = ps_next_dpb->ps_prev_dpb; |
221 | 277 | } |
222 | | |
223 | 389 | if(i == ps_dpb_mgr->u1_num_ref_bufs) |
224 | 0 | { |
225 | 0 | return; |
226 | 0 | } |
227 | 389 | else |
228 | 389 | ps_unmark_node = ps_next_dpb->ps_prev_dpb; |
229 | 389 | } |
230 | | |
231 | 1.20k | if(ps_unmark_node == ps_dpb_mgr->ps_dpb_head) |
232 | 817 | { |
233 | 817 | ps_dpb_mgr->ps_dpb_head = ps_unmark_node->ps_prev_dpb; |
234 | 817 | } |
235 | 389 | else |
236 | 389 | { |
237 | 389 | ps_next_dpb->ps_prev_dpb = ps_unmark_node->ps_prev_dpb; //update link |
238 | 389 | ps_unmark_node->ps_prev_dpb = NULL; |
239 | 389 | } |
240 | 1.20k | ps_dpb_mgr->u1_num_ref_bufs--; //decrement buffer count |
241 | | |
242 | | /* Release the physical buffer */ |
243 | 1.20k | ihevc_buf_mgr_release((buf_mgr_t *)ps_buf_mgr, ps_unmark_node->ps_pic_buf->u1_buf_id, |
244 | 1.20k | BUF_MGR_REF); |
245 | 1.20k | ps_unmark_node->ps_prev_dpb = NULL; |
246 | 1.20k | ps_unmark_node->ps_pic_buf = NULL; |
247 | 1.20k | } |
248 | | |
249 | | |
250 | | /** |
251 | | ******************************************************************************* |
252 | | * |
253 | | * @brief |
254 | | * Gets a buffer with abs_poc closest to the current poc |
255 | | * |
256 | | * @par Description: |
257 | | * Returns the pointer to the picture buffer whose poc is equal to abs_poc |
258 | | * |
259 | | * @param[in] ps_dpb_mgr |
260 | | * Pointer to DPB Manager structure |
261 | | * |
262 | | * @param[out] ps_pic_buf |
263 | | * Pointer to picture buffer |
264 | | |
265 | | * @param[in] abs_poc |
266 | | * poc of the buffer to be returned |
267 | | * |
268 | | * @returns |
269 | | * 0 if successful, pic_buf otherwise |
270 | | * @remarks |
271 | | * |
272 | | * |
273 | | ******************************************************************************* |
274 | | */ |
275 | | pic_buf_t* ihevc_dpb_mgr_get_ref_by_nearest_poc(dpb_mgr_t *ps_dpb_mgr, WORD32 cur_abs_poc) |
276 | 7.22k | { |
277 | 7.22k | WORD32 i; |
278 | 7.22k | WORD32 min_diff = 0x7FFFFFFF; |
279 | 7.22k | pic_buf_t *ps_pic_buf = NULL; |
280 | | |
281 | 469k | for(i = 0; i < MAX_DPB_BUFS; i++) |
282 | 462k | { |
283 | 462k | if((ps_dpb_mgr->as_dpb_info[i].ps_pic_buf) && |
284 | 462k | (ps_dpb_mgr->as_dpb_info[i].ps_pic_buf->u1_used_as_ref != UNUSED_FOR_REF)) |
285 | 17.0k | { |
286 | 17.0k | WORD32 poc_diff = cur_abs_poc - ps_dpb_mgr->as_dpb_info[i].ps_pic_buf->i4_abs_poc; |
287 | 17.0k | if((poc_diff > 0) && (poc_diff < min_diff)) |
288 | 6.54k | { |
289 | 6.54k | min_diff = poc_diff; |
290 | 6.54k | ps_pic_buf = ps_dpb_mgr->as_dpb_info[i].ps_pic_buf; |
291 | 6.54k | } |
292 | 17.0k | } |
293 | 462k | } |
294 | | |
295 | 7.22k | if(NULL == ps_pic_buf) |
296 | 2.34k | { |
297 | 2.34k | min_diff = 0x7FFFFFFF; |
298 | 152k | for(i = 0; i < MAX_DPB_BUFS; i++) |
299 | 149k | { |
300 | 149k | if((ps_dpb_mgr->as_dpb_info[i].ps_pic_buf) && |
301 | 149k | (ps_dpb_mgr->as_dpb_info[i].ps_pic_buf->u1_used_as_ref != UNUSED_FOR_REF)) |
302 | 1.09k | { |
303 | 1.09k | WORD32 poc_diff = cur_abs_poc - ps_dpb_mgr->as_dpb_info[i].ps_pic_buf->i4_abs_poc; |
304 | 1.09k | if(ABS(poc_diff) < min_diff) |
305 | 1.03k | { |
306 | 1.03k | min_diff = ABS(poc_diff); |
307 | 1.03k | ps_pic_buf = ps_dpb_mgr->as_dpb_info[i].ps_pic_buf; |
308 | 1.03k | } |
309 | 1.09k | } |
310 | 149k | } |
311 | 2.34k | } |
312 | | |
313 | 7.22k | return ps_pic_buf; |
314 | 7.22k | } |
315 | | |
316 | | |
317 | | /** |
318 | | ******************************************************************************* |
319 | | * |
320 | | * @brief |
321 | | * Gets a buffer with abs_poc |
322 | | * |
323 | | * @par Description: |
324 | | * Returns the pointer to the picture buffer whose poc is equal to abs_poc |
325 | | * |
326 | | * @param[in] ps_dpb_mgr |
327 | | * Pointer to DPB Manager structure |
328 | | * |
329 | | * @param[out] ps_pic_buf |
330 | | * Pointer to picture buffer |
331 | | |
332 | | * @param[in] abs_poc |
333 | | * poc of the buffer to be returned |
334 | | * |
335 | | * @returns |
336 | | * 0 if successful, pic_buf otherwise |
337 | | * @remarks |
338 | | * |
339 | | * |
340 | | ******************************************************************************* |
341 | | */ |
342 | | pic_buf_t* ihevc_dpb_mgr_get_ref_by_poc(dpb_mgr_t *ps_dpb_mgr, WORD32 abs_poc) |
343 | 16.8k | { |
344 | 16.8k | UWORD32 i; |
345 | 16.8k | dpb_info_t *ps_next_ref; |
346 | 16.8k | pic_buf_t *ps_pic_buf = NULL; |
347 | | |
348 | | |
349 | 16.8k | ps_next_ref = ps_dpb_mgr->ps_dpb_head; |
350 | 42.5k | for(i = 0; i < ps_dpb_mgr->u1_num_ref_bufs; i++) |
351 | 39.9k | { |
352 | 39.9k | if(ps_next_ref->ps_pic_buf->i4_abs_poc == abs_poc) |
353 | 14.1k | { |
354 | 14.1k | ps_pic_buf = ps_next_ref->ps_pic_buf; |
355 | 14.1k | break; |
356 | 14.1k | } |
357 | | |
358 | 25.7k | ps_next_ref = ps_next_ref->ps_prev_dpb; |
359 | 25.7k | } |
360 | | |
361 | 16.8k | if(i == ps_dpb_mgr->u1_num_ref_bufs) |
362 | 2.63k | { |
363 | 2.63k | ps_pic_buf = NULL; |
364 | 2.63k | } |
365 | | |
366 | 16.8k | return ps_pic_buf; |
367 | 16.8k | } |
368 | | |
369 | | /** |
370 | | ******************************************************************************* |
371 | | * |
372 | | * @brief |
373 | | * Gets a buffer with poc_lsb |
374 | | * |
375 | | * @par Description: |
376 | | * Returns the pointer to the picture buffer whose poc is equal to poc_lsb |
377 | | * |
378 | | * @param[in] ps_dpb_mgr |
379 | | * Pointer to DPB Manager structure |
380 | | * |
381 | | * @param[out] ps_pic_buf |
382 | | * Pointer to picture buffer |
383 | | |
384 | | * @param[in] poc_lsb |
385 | | * poc_lsb of the buffer to be returned |
386 | | * |
387 | | * @returns |
388 | | * 0 if successful, pic_buf otherwise |
389 | | * @remarks |
390 | | * |
391 | | * |
392 | | ******************************************************************************* |
393 | | */ |
394 | | |
395 | | pic_buf_t* ihevc_dpb_mgr_get_ref_by_poc_lsb(dpb_mgr_t *ps_dpb_mgr, WORD32 poc_lsb) |
396 | 28 | { |
397 | 28 | pic_buf_t *ps_pic_buf = NULL; |
398 | 28 | UWORD32 i; |
399 | 28 | dpb_info_t *ps_next_ref; |
400 | | |
401 | 28 | ps_next_ref = ps_dpb_mgr->ps_dpb_head; |
402 | 52 | for(i = 0; i < ps_dpb_mgr->u1_num_ref_bufs; i++) |
403 | 32 | { |
404 | 32 | if(ps_next_ref->ps_pic_buf->i4_poc_lsb == poc_lsb) |
405 | 8 | { |
406 | 8 | ps_pic_buf = ps_next_ref->ps_pic_buf; |
407 | 8 | break; |
408 | 8 | } |
409 | | |
410 | 24 | ps_next_ref = ps_next_ref->ps_prev_dpb; |
411 | 24 | } |
412 | | |
413 | 28 | if(i == ps_dpb_mgr->u1_num_ref_bufs) |
414 | 20 | { |
415 | 20 | ps_pic_buf = NULL; |
416 | 20 | } |
417 | | |
418 | 28 | return ps_pic_buf; |
419 | 28 | } |
420 | | |
421 | | |
422 | | /** |
423 | | ******************************************************************************* |
424 | | * |
425 | | * @brief |
426 | | * Resets the DPB manager |
427 | | * |
428 | | * @par Description: |
429 | | * Re-initialises the DPB manager structure |
430 | | * |
431 | | * @param[in] ps_dpb_mgr |
432 | | * Pointer to DPB Manager structure |
433 | | * |
434 | | * @param[in] ps_buf_mgr |
435 | | * Pointer to buffer manager structure |
436 | | * |
437 | | * @returns |
438 | | * |
439 | | * @remarks |
440 | | * |
441 | | * |
442 | | ******************************************************************************* |
443 | | */ |
444 | | |
445 | | void ihevc_dpb_mgr_reset(dpb_mgr_t *ps_dpb_mgr, buf_mgr_t *ps_buf_mgr) |
446 | 0 | { |
447 | 0 | int i; |
448 | 0 | dpb_info_t *ps_dpb_info; |
449 | |
|
450 | 0 | ps_dpb_info = ps_dpb_mgr->as_dpb_info; |
451 | |
|
452 | 0 | for(i = 0; i < MAX_DPB_BUFS; i++) |
453 | 0 | { |
454 | 0 | if(ps_dpb_info[i].ps_pic_buf->u1_used_as_ref) |
455 | 0 | { |
456 | 0 | ps_dpb_info[i].ps_pic_buf->u1_used_as_ref = UNUSED_FOR_REF; |
457 | 0 | ps_dpb_info[i].ps_prev_dpb = NULL; |
458 | | //Release physical buffer |
459 | 0 | ihevc_buf_mgr_release(ps_buf_mgr, ps_dpb_info[i].ps_pic_buf->u1_buf_id, |
460 | 0 | BUF_MGR_REF); |
461 | |
|
462 | 0 | ps_dpb_info[i].ps_pic_buf = NULL; |
463 | 0 | } |
464 | 0 | } |
465 | 0 | ps_dpb_mgr->u1_num_ref_bufs = 0; |
466 | 0 | ps_dpb_mgr->ps_dpb_head = NULL; |
467 | |
|
468 | 0 | } |
469 | | |
470 | | /** |
471 | | ******************************************************************************* |
472 | | * |
473 | | * @brief |
474 | | * deletes all pictures from DPB |
475 | | * |
476 | | * @par Description: |
477 | | * Deletes all pictures present in the DPB manager |
478 | | * |
479 | | * @param[in] ps_buf_mgr |
480 | | * Pointer to buffer manager structure |
481 | | * |
482 | | * @param[in] u1_disp_bufs |
483 | | * Number of buffers to be deleted |
484 | | * |
485 | | * @returns |
486 | | * |
487 | | * @remarks |
488 | | * |
489 | | * |
490 | | ******************************************************************************* |
491 | | */ |
492 | | |
493 | | void ihevc_dpb_mgr_release_pics(buf_mgr_t *ps_buf_mgr, UWORD8 u1_disp_bufs) |
494 | 0 | { |
495 | 0 | WORD8 i; |
496 | 0 | UWORD32 buf_status; |
497 | |
|
498 | 0 | for(i = 0; i < u1_disp_bufs; i++) |
499 | 0 | { |
500 | 0 | buf_status = ihevc_buf_mgr_get_status(ps_buf_mgr, i); |
501 | 0 | if(0 != buf_status) |
502 | 0 | { |
503 | 0 | ihevc_buf_mgr_release((buf_mgr_t *)ps_buf_mgr, i, BUF_MGR_REF); |
504 | 0 | } |
505 | 0 | } |
506 | 0 | } |