/src/libhevc/common/ihevc_dpb_mgr.c
Line | Count | Source |
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_structs.h" |
51 | | #include "ihevc_buf_mgr.h" |
52 | | #include "ihevc_dpb_mgr.h" |
53 | | |
54 | | /** |
55 | | ******************************************************************************* |
56 | | * |
57 | | * @brief |
58 | | * DPB manager initializer |
59 | | * |
60 | | * @par Description: |
61 | | * Initialises the DPB manager structure |
62 | | * |
63 | | * @param[in] ps_dpb_mgr |
64 | | * Pointer to the DPB manager structure |
65 | | * |
66 | | * @returns |
67 | | * |
68 | | * @remarks |
69 | | * |
70 | | * |
71 | | ******************************************************************************* |
72 | | */ |
73 | | |
74 | | void ihevc_dpb_mgr_init(dpb_mgr_t *ps_dpb_mgr) |
75 | 0 | { |
76 | 0 | UWORD32 i; |
77 | 0 | dpb_info_t *ps_dpb_info = ps_dpb_mgr->as_dpb_info; |
78 | 0 | for(i = 0; i < MAX_DPB_BUFS; i++) |
79 | 0 | { |
80 | 0 | ps_dpb_info[i].ps_prev_dpb = NULL; |
81 | 0 | ps_dpb_info[i].ps_pic_buf = NULL; |
82 | |
|
83 | 0 | } |
84 | |
|
85 | 0 | ps_dpb_mgr->u1_num_ref_bufs = 0; |
86 | 0 | ps_dpb_mgr->ps_dpb_head = NULL; |
87 | |
|
88 | 0 | } |
89 | | |
90 | | |
91 | | /** |
92 | | ******************************************************************************* |
93 | | * |
94 | | * @brief |
95 | | * Adds a reference picture into the linked list |
96 | | * |
97 | | * @par Description: |
98 | | * Adds the reference buffer with the given buffer id into the DPB manager |
99 | | * |
100 | | * |
101 | | * @param[in] ps_dpb_mgr |
102 | | * Pointer to the DPB manager structure |
103 | | * |
104 | | * @param[in] ps_picBuf |
105 | | * Pointer to the picture buffer |
106 | | * |
107 | | * @param[in] buf_id |
108 | | * buffer id of the picture buffer |
109 | | * |
110 | | * @returns 0 if successful, -1 otherwise |
111 | | * |
112 | | * @remarks |
113 | | * |
114 | | * |
115 | | ******************************************************************************* |
116 | | */ |
117 | | |
118 | | WORD32 ihevc_dpb_mgr_insert_ref(dpb_mgr_t *ps_dpb_mgr, |
119 | | pic_buf_t *ps_pic_buf, |
120 | | WORD32 buf_id) |
121 | 0 | { |
122 | 0 | int i; |
123 | 0 | dpb_info_t *ps_dpb_info; |
124 | |
|
125 | 0 | ps_dpb_info = ps_dpb_mgr->as_dpb_info; |
126 | | |
127 | | /* Return error if buffer is already present in the DPB */ |
128 | 0 | for(i = 0; i < MAX_DPB_BUFS; i++) |
129 | 0 | { |
130 | 0 | if((ps_dpb_info[i].ps_pic_buf == ps_pic_buf) |
131 | 0 | && (ps_dpb_info[i].ps_pic_buf->u1_used_as_ref)) |
132 | 0 | { |
133 | 0 | return (-1); |
134 | 0 | } |
135 | | |
136 | |
|
137 | 0 | } |
138 | | |
139 | | /* Find an unused DPB location */ |
140 | 0 | for(i = 0; i < MAX_DPB_BUFS; i++) |
141 | 0 | { |
142 | 0 | if(NULL == ps_dpb_info[i].ps_pic_buf) |
143 | 0 | { |
144 | 0 | break; |
145 | 0 | } |
146 | 0 | } |
147 | 0 | if(i == MAX_DPB_BUFS) |
148 | 0 | { |
149 | 0 | return (-1); |
150 | 0 | } |
151 | | |
152 | | /* Create DPB info */ |
153 | 0 | ps_dpb_info[i].ps_pic_buf = ps_pic_buf; |
154 | 0 | ps_dpb_info[i].ps_prev_dpb = ps_dpb_mgr->ps_dpb_head; |
155 | 0 | ps_dpb_info[i].ps_pic_buf->u1_buf_id = buf_id; |
156 | 0 | ps_dpb_info[i].ps_pic_buf->u1_used_as_ref = SHORT_TERM_REF; |
157 | | |
158 | | /* update the head node of linked list to point to the current picture */ |
159 | 0 | ps_dpb_mgr->ps_dpb_head = ps_dpb_info + i; |
160 | | |
161 | | /* Increment Short term buffer count */ |
162 | 0 | ps_dpb_mgr->u1_num_ref_bufs++; |
163 | |
|
164 | 0 | return 0; |
165 | 0 | } |
166 | | |
167 | | /** |
168 | | ******************************************************************************* |
169 | | * |
170 | | * @brief |
171 | | * Deletes a reference buffer from the dpb manager |
172 | | * |
173 | | * @par Description: |
174 | | * Delete short term reference with a given POC from the linked |
175 | | * list |
176 | | * |
177 | | * @param[in] ps_dpb_mgr |
178 | | * Pointer to DPB Manager structure |
179 | | * |
180 | | * @param[in] ps_buf_mgr |
181 | | * Pointer to buffer manager structure |
182 | | * |
183 | | * @param[in] u4_abs_poc |
184 | | * Node's absolute poc |
185 | | * |
186 | | * |
187 | | * @returns 0 if successful, -1 otherwise |
188 | | * |
189 | | * @remarks |
190 | | * |
191 | | * |
192 | | ******************************************************************************* |
193 | | */ |
194 | | |
195 | | void ihevc_dpb_mgr_del_ref(dpb_mgr_t *ps_dpb_mgr, |
196 | | buf_mgr_t *ps_buf_mgr, |
197 | | WORD32 i4_abs_poc) |
198 | 0 | { |
199 | 0 | int i; |
200 | 0 | dpb_info_t *ps_next_dpb; |
201 | |
|
202 | 0 | dpb_info_t *ps_unmark_node; |
203 | 0 | UWORD8 u1_del_node; |
204 | 0 | UNUSED(u1_del_node); |
205 | 0 | u1_del_node = 0; |
206 | | |
207 | | /* Find the node with matching absolute POC */ |
208 | 0 | ps_next_dpb = ps_dpb_mgr->ps_dpb_head; |
209 | 0 | if(ps_next_dpb->ps_pic_buf->i4_abs_poc == i4_abs_poc) |
210 | 0 | { |
211 | 0 | ps_unmark_node = ps_next_dpb; |
212 | 0 | } |
213 | 0 | else |
214 | 0 | { |
215 | 0 | for(i = 1; i < ps_dpb_mgr->u1_num_ref_bufs; i++) |
216 | 0 | { |
217 | 0 | if(ps_next_dpb->ps_prev_dpb->ps_pic_buf->i4_abs_poc == i4_abs_poc) |
218 | 0 | break; |
219 | 0 | ps_next_dpb = ps_next_dpb->ps_prev_dpb; |
220 | 0 | } |
221 | |
|
222 | 0 | if(i == ps_dpb_mgr->u1_num_ref_bufs) |
223 | 0 | { |
224 | 0 | return; |
225 | 0 | } |
226 | 0 | else |
227 | 0 | ps_unmark_node = ps_next_dpb->ps_prev_dpb; |
228 | 0 | } |
229 | | |
230 | 0 | if(ps_unmark_node == ps_dpb_mgr->ps_dpb_head) |
231 | 0 | { |
232 | 0 | ps_dpb_mgr->ps_dpb_head = ps_unmark_node->ps_prev_dpb; |
233 | 0 | } |
234 | 0 | else |
235 | 0 | { |
236 | 0 | ps_next_dpb->ps_prev_dpb = ps_unmark_node->ps_prev_dpb; //update link |
237 | 0 | ps_unmark_node->ps_prev_dpb = NULL; |
238 | 0 | } |
239 | 0 | ps_dpb_mgr->u1_num_ref_bufs--; //decrement buffer count |
240 | | |
241 | | /* Release the physical buffer */ |
242 | 0 | ihevc_buf_mgr_release((buf_mgr_t *)ps_buf_mgr, ps_unmark_node->ps_pic_buf->u1_buf_id, |
243 | 0 | BUF_MGR_REF); |
244 | 0 | ps_unmark_node->ps_prev_dpb = NULL; |
245 | 0 | ps_unmark_node->ps_pic_buf = NULL; |
246 | 0 | } |
247 | | |
248 | | |
249 | | /** |
250 | | ******************************************************************************* |
251 | | * |
252 | | * @brief |
253 | | * Gets a buffer with abs_poc closest to the current poc |
254 | | * |
255 | | * @par Description: |
256 | | * Returns the pointer to the picture buffer whose poc is equal to abs_poc |
257 | | * |
258 | | * @param[in] ps_dpb_mgr |
259 | | * Pointer to DPB Manager structure |
260 | | * |
261 | | * @param[out] ps_pic_buf |
262 | | * Pointer to picture buffer |
263 | | |
264 | | * @param[in] abs_poc |
265 | | * poc of the buffer to be returned |
266 | | * |
267 | | * @returns |
268 | | * 0 if successful, pic_buf otherwise |
269 | | * @remarks |
270 | | * |
271 | | * |
272 | | ******************************************************************************* |
273 | | */ |
274 | | pic_buf_t* ihevc_dpb_mgr_get_ref_by_nearest_poc(dpb_mgr_t *ps_dpb_mgr, WORD32 cur_abs_poc) |
275 | 0 | { |
276 | 0 | WORD32 i; |
277 | 0 | WORD32 min_diff = 0x7FFFFFFF; |
278 | 0 | pic_buf_t *ps_pic_buf = NULL; |
279 | |
|
280 | 0 | for(i = 0; i < MAX_DPB_BUFS; i++) |
281 | 0 | { |
282 | 0 | if((ps_dpb_mgr->as_dpb_info[i].ps_pic_buf) && |
283 | 0 | (ps_dpb_mgr->as_dpb_info[i].ps_pic_buf->u1_used_as_ref != UNUSED_FOR_REF)) |
284 | 0 | { |
285 | 0 | WORD32 poc_diff = cur_abs_poc - ps_dpb_mgr->as_dpb_info[i].ps_pic_buf->i4_abs_poc; |
286 | 0 | if((poc_diff > 0) && (poc_diff < min_diff)) |
287 | 0 | { |
288 | 0 | min_diff = poc_diff; |
289 | 0 | ps_pic_buf = ps_dpb_mgr->as_dpb_info[i].ps_pic_buf; |
290 | 0 | } |
291 | 0 | } |
292 | 0 | } |
293 | |
|
294 | 0 | if(NULL == ps_pic_buf) |
295 | 0 | { |
296 | 0 | min_diff = 0x7FFFFFFF; |
297 | 0 | for(i = 0; i < MAX_DPB_BUFS; i++) |
298 | 0 | { |
299 | 0 | if((ps_dpb_mgr->as_dpb_info[i].ps_pic_buf) && |
300 | 0 | (ps_dpb_mgr->as_dpb_info[i].ps_pic_buf->u1_used_as_ref != UNUSED_FOR_REF)) |
301 | 0 | { |
302 | 0 | WORD32 poc_diff = cur_abs_poc - ps_dpb_mgr->as_dpb_info[i].ps_pic_buf->i4_abs_poc; |
303 | 0 | if(ABS(poc_diff) < min_diff) |
304 | 0 | { |
305 | 0 | min_diff = ABS(poc_diff); |
306 | 0 | ps_pic_buf = ps_dpb_mgr->as_dpb_info[i].ps_pic_buf; |
307 | 0 | } |
308 | 0 | } |
309 | 0 | } |
310 | 0 | } |
311 | |
|
312 | 0 | return ps_pic_buf; |
313 | 0 | } |
314 | | |
315 | | |
316 | | /** |
317 | | ******************************************************************************* |
318 | | * |
319 | | * @brief |
320 | | * Gets a buffer with abs_poc |
321 | | * |
322 | | * @par Description: |
323 | | * Returns the pointer to the picture buffer whose poc is equal to abs_poc |
324 | | * |
325 | | * @param[in] ps_dpb_mgr |
326 | | * Pointer to DPB Manager structure |
327 | | * |
328 | | * @param[out] ps_pic_buf |
329 | | * Pointer to picture buffer |
330 | | |
331 | | * @param[in] abs_poc |
332 | | * poc of the buffer to be returned |
333 | | * |
334 | | * @returns |
335 | | * 0 if successful, pic_buf otherwise |
336 | | * @remarks |
337 | | * |
338 | | * |
339 | | ******************************************************************************* |
340 | | */ |
341 | | pic_buf_t* ihevc_dpb_mgr_get_ref_by_poc(dpb_mgr_t *ps_dpb_mgr, WORD32 abs_poc) |
342 | 0 | { |
343 | 0 | UWORD32 i; |
344 | 0 | dpb_info_t *ps_next_ref; |
345 | 0 | pic_buf_t *ps_pic_buf = NULL; |
346 | | |
347 | |
|
348 | 0 | ps_next_ref = ps_dpb_mgr->ps_dpb_head; |
349 | 0 | for(i = 0; i < ps_dpb_mgr->u1_num_ref_bufs; i++) |
350 | 0 | { |
351 | 0 | if(ps_next_ref->ps_pic_buf->i4_abs_poc == abs_poc) |
352 | 0 | { |
353 | 0 | ps_pic_buf = ps_next_ref->ps_pic_buf; |
354 | 0 | break; |
355 | 0 | } |
356 | | |
357 | 0 | ps_next_ref = ps_next_ref->ps_prev_dpb; |
358 | 0 | } |
359 | |
|
360 | 0 | if(i == ps_dpb_mgr->u1_num_ref_bufs) |
361 | 0 | { |
362 | 0 | ps_pic_buf = NULL; |
363 | 0 | } |
364 | |
|
365 | 0 | return ps_pic_buf; |
366 | 0 | } |
367 | | |
368 | | /** |
369 | | ******************************************************************************* |
370 | | * |
371 | | * @brief |
372 | | * Gets a buffer with poc_lsb |
373 | | * |
374 | | * @par Description: |
375 | | * Returns the pointer to the picture buffer whose poc is equal to poc_lsb |
376 | | * |
377 | | * @param[in] ps_dpb_mgr |
378 | | * Pointer to DPB Manager structure |
379 | | * |
380 | | * @param[out] ps_pic_buf |
381 | | * Pointer to picture buffer |
382 | | |
383 | | * @param[in] poc_lsb |
384 | | * poc_lsb of the buffer to be returned |
385 | | * |
386 | | * @returns |
387 | | * 0 if successful, pic_buf otherwise |
388 | | * @remarks |
389 | | * |
390 | | * |
391 | | ******************************************************************************* |
392 | | */ |
393 | | |
394 | | pic_buf_t* ihevc_dpb_mgr_get_ref_by_poc_lsb(dpb_mgr_t *ps_dpb_mgr, WORD32 poc_lsb) |
395 | 0 | { |
396 | 0 | pic_buf_t *ps_pic_buf = NULL; |
397 | 0 | UWORD32 i; |
398 | 0 | dpb_info_t *ps_next_ref; |
399 | |
|
400 | 0 | ps_next_ref = ps_dpb_mgr->ps_dpb_head; |
401 | 0 | for(i = 0; i < ps_dpb_mgr->u1_num_ref_bufs; i++) |
402 | 0 | { |
403 | 0 | if(ps_next_ref->ps_pic_buf->i4_poc_lsb == poc_lsb) |
404 | 0 | { |
405 | 0 | ps_pic_buf = ps_next_ref->ps_pic_buf; |
406 | 0 | break; |
407 | 0 | } |
408 | | |
409 | 0 | ps_next_ref = ps_next_ref->ps_prev_dpb; |
410 | 0 | } |
411 | |
|
412 | 0 | if(i == ps_dpb_mgr->u1_num_ref_bufs) |
413 | 0 | { |
414 | 0 | ps_pic_buf = NULL; |
415 | 0 | } |
416 | |
|
417 | 0 | return ps_pic_buf; |
418 | 0 | } |
419 | | |
420 | | |
421 | | /** |
422 | | ******************************************************************************* |
423 | | * |
424 | | * @brief |
425 | | * Resets the DPB manager |
426 | | * |
427 | | * @par Description: |
428 | | * Re-initialises the DPB manager structure |
429 | | * |
430 | | * @param[in] ps_dpb_mgr |
431 | | * Pointer to DPB Manager structure |
432 | | * |
433 | | * @param[in] ps_buf_mgr |
434 | | * Pointer to buffer manager structure |
435 | | * |
436 | | * @returns |
437 | | * |
438 | | * @remarks |
439 | | * |
440 | | * |
441 | | ******************************************************************************* |
442 | | */ |
443 | | |
444 | | void ihevc_dpb_mgr_reset(dpb_mgr_t *ps_dpb_mgr, buf_mgr_t *ps_buf_mgr) |
445 | 0 | { |
446 | 0 | int i; |
447 | 0 | dpb_info_t *ps_dpb_info; |
448 | |
|
449 | 0 | ps_dpb_info = ps_dpb_mgr->as_dpb_info; |
450 | |
|
451 | 0 | for(i = 0; i < MAX_DPB_BUFS; i++) |
452 | 0 | { |
453 | 0 | if(ps_dpb_info[i].ps_pic_buf->u1_used_as_ref) |
454 | 0 | { |
455 | 0 | ps_dpb_info[i].ps_pic_buf->u1_used_as_ref = UNUSED_FOR_REF; |
456 | 0 | ps_dpb_info[i].ps_prev_dpb = NULL; |
457 | | //Release physical buffer |
458 | 0 | ihevc_buf_mgr_release(ps_buf_mgr, ps_dpb_info[i].ps_pic_buf->u1_buf_id, |
459 | 0 | BUF_MGR_REF); |
460 | |
|
461 | 0 | ps_dpb_info[i].ps_pic_buf = NULL; |
462 | 0 | } |
463 | 0 | } |
464 | 0 | ps_dpb_mgr->u1_num_ref_bufs = 0; |
465 | 0 | ps_dpb_mgr->ps_dpb_head = NULL; |
466 | |
|
467 | 0 | } |
468 | | |
469 | | /** |
470 | | ******************************************************************************* |
471 | | * |
472 | | * @brief |
473 | | * deletes all pictures from DPB |
474 | | * |
475 | | * @par Description: |
476 | | * Deletes all pictures present in the DPB manager |
477 | | * |
478 | | * @param[in] ps_buf_mgr |
479 | | * Pointer to buffer manager structure |
480 | | * |
481 | | * @param[in] u1_disp_bufs |
482 | | * Number of buffers to be deleted |
483 | | * |
484 | | * @returns |
485 | | * |
486 | | * @remarks |
487 | | * |
488 | | * |
489 | | ******************************************************************************* |
490 | | */ |
491 | | |
492 | | void ihevc_dpb_mgr_release_pics(buf_mgr_t *ps_buf_mgr, UWORD8 u1_disp_bufs) |
493 | 0 | { |
494 | 0 | WORD8 i; |
495 | 0 | UWORD32 buf_status; |
496 | |
|
497 | 0 | for(i = 0; i < u1_disp_bufs; i++) |
498 | 0 | { |
499 | 0 | buf_status = ihevc_buf_mgr_get_status(ps_buf_mgr, i); |
500 | 0 | if(0 != buf_status) |
501 | 0 | { |
502 | 0 | ihevc_buf_mgr_release((buf_mgr_t *)ps_buf_mgr, i, BUF_MGR_REF); |
503 | 0 | } |
504 | 0 | } |
505 | 0 | } |