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
ihevc_dpb_mgr_init(dpb_mgr_t * ps_dpb_mgr)75 void ihevc_dpb_mgr_init(dpb_mgr_t *ps_dpb_mgr)
76 {
77 UWORD32 i;
78 dpb_info_t *ps_dpb_info = ps_dpb_mgr->as_dpb_info;
79 for(i = 0; i < MAX_DPB_BUFS; i++)
80 {
81 ps_dpb_info[i].ps_prev_dpb = NULL;
82 ps_dpb_info[i].ps_pic_buf = NULL;
83
84 }
85
86 ps_dpb_mgr->u1_num_ref_bufs = 0;
87 ps_dpb_mgr->ps_dpb_head = NULL;
88
89 }
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
ihevc_dpb_mgr_insert_ref(dpb_mgr_t * ps_dpb_mgr,pic_buf_t * ps_pic_buf,WORD32 buf_id)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 {
123 int i;
124 dpb_info_t *ps_dpb_info;
125
126 ps_dpb_info = ps_dpb_mgr->as_dpb_info;
127
128 /* Return error if buffer is already present in the DPB */
129 for(i = 0; i < MAX_DPB_BUFS; i++)
130 {
131 if((ps_dpb_info[i].ps_pic_buf == ps_pic_buf)
132 && (ps_dpb_info[i].ps_pic_buf->u1_used_as_ref))
133 {
134 return (-1);
135 }
136
137
138 }
139
140 /* Find an unused DPB location */
141 for(i = 0; i < MAX_DPB_BUFS; i++)
142 {
143 if(NULL == ps_dpb_info[i].ps_pic_buf)
144 {
145 break;
146 }
147 }
148 if(i == MAX_DPB_BUFS)
149 {
150 return (-1);
151 }
152
153 /* Create DPB info */
154 ps_dpb_info[i].ps_pic_buf = ps_pic_buf;
155 ps_dpb_info[i].ps_prev_dpb = ps_dpb_mgr->ps_dpb_head;
156 ps_dpb_info[i].ps_pic_buf->u1_buf_id = buf_id;
157 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 ps_dpb_mgr->ps_dpb_head = ps_dpb_info + i;
161
162 /* Increment Short term buffer count */
163 ps_dpb_mgr->u1_num_ref_bufs++;
164
165 return 0;
166 }
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
ihevc_dpb_mgr_del_ref(dpb_mgr_t * ps_dpb_mgr,buf_mgr_t * ps_buf_mgr,WORD32 i4_abs_poc)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 {
200 int i;
201 dpb_info_t *ps_next_dpb;
202
203 dpb_info_t *ps_unmark_node;
204 UWORD8 u1_del_node;
205 UNUSED(u1_del_node);
206 u1_del_node = 0;
207
208 /* Find the node with matching absolute POC */
209 ps_next_dpb = ps_dpb_mgr->ps_dpb_head;
210 if(ps_next_dpb->ps_pic_buf->i4_abs_poc == i4_abs_poc)
211 {
212 ps_unmark_node = ps_next_dpb;
213 }
214 else
215 {
216 for(i = 1; i < ps_dpb_mgr->u1_num_ref_bufs; i++)
217 {
218 if(ps_next_dpb->ps_prev_dpb->ps_pic_buf->i4_abs_poc == i4_abs_poc)
219 break;
220 ps_next_dpb = ps_next_dpb->ps_prev_dpb;
221 }
222
223 if(i == ps_dpb_mgr->u1_num_ref_bufs)
224 {
225 return;
226 }
227 else
228 ps_unmark_node = ps_next_dpb->ps_prev_dpb;
229 }
230
231 if(ps_unmark_node == ps_dpb_mgr->ps_dpb_head)
232 {
233 ps_dpb_mgr->ps_dpb_head = ps_unmark_node->ps_prev_dpb;
234 }
235 else
236 {
237 ps_next_dpb->ps_prev_dpb = ps_unmark_node->ps_prev_dpb; //update link
238 ps_unmark_node->ps_prev_dpb = NULL;
239 }
240 ps_dpb_mgr->u1_num_ref_bufs--; //decrement buffer count
241
242 /* Release the physical buffer */
243 ihevc_buf_mgr_release((buf_mgr_t *)ps_buf_mgr, ps_unmark_node->ps_pic_buf->u1_buf_id,
244 BUF_MGR_REF);
245 ps_unmark_node->ps_prev_dpb = NULL;
246 ps_unmark_node->ps_pic_buf = NULL;
247 }
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 */
ihevc_dpb_mgr_get_ref_by_nearest_poc(dpb_mgr_t * ps_dpb_mgr,WORD32 cur_abs_poc)275 pic_buf_t* ihevc_dpb_mgr_get_ref_by_nearest_poc(dpb_mgr_t *ps_dpb_mgr, WORD32 cur_abs_poc)
276 {
277 WORD32 i;
278 WORD32 min_diff = 0x7FFFFFFF;
279 pic_buf_t *ps_pic_buf = NULL;
280
281 for(i = 0; i < MAX_DPB_BUFS; i++)
282 {
283 if((ps_dpb_mgr->as_dpb_info[i].ps_pic_buf) &&
284 (ps_dpb_mgr->as_dpb_info[i].ps_pic_buf->u1_used_as_ref != UNUSED_FOR_REF))
285 {
286 WORD32 poc_diff = cur_abs_poc - ps_dpb_mgr->as_dpb_info[i].ps_pic_buf->i4_abs_poc;
287 if((poc_diff > 0) && (poc_diff < min_diff))
288 {
289 min_diff = poc_diff;
290 ps_pic_buf = ps_dpb_mgr->as_dpb_info[i].ps_pic_buf;
291 }
292 }
293 }
294
295 if(NULL == ps_pic_buf)
296 {
297 min_diff = 0x7FFFFFFF;
298 for(i = 0; i < MAX_DPB_BUFS; i++)
299 {
300 if((ps_dpb_mgr->as_dpb_info[i].ps_pic_buf) &&
301 (ps_dpb_mgr->as_dpb_info[i].ps_pic_buf->u1_used_as_ref != UNUSED_FOR_REF))
302 {
303 WORD32 poc_diff = cur_abs_poc - ps_dpb_mgr->as_dpb_info[i].ps_pic_buf->i4_abs_poc;
304 if(ABS(poc_diff) < min_diff)
305 {
306 min_diff = ABS(poc_diff);
307 ps_pic_buf = ps_dpb_mgr->as_dpb_info[i].ps_pic_buf;
308 }
309 }
310 }
311 }
312
313 return ps_pic_buf;
314 }
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 */
ihevc_dpb_mgr_get_ref_by_poc(dpb_mgr_t * ps_dpb_mgr,WORD32 abs_poc)342 pic_buf_t* ihevc_dpb_mgr_get_ref_by_poc(dpb_mgr_t *ps_dpb_mgr, WORD32 abs_poc)
343 {
344 UWORD32 i;
345 dpb_info_t *ps_next_ref;
346 pic_buf_t *ps_pic_buf = NULL;
347
348
349 ps_next_ref = ps_dpb_mgr->ps_dpb_head;
350 for(i = 0; i < ps_dpb_mgr->u1_num_ref_bufs; i++)
351 {
352 if(ps_next_ref->ps_pic_buf->i4_abs_poc == abs_poc)
353 {
354 ps_pic_buf = ps_next_ref->ps_pic_buf;
355 break;
356 }
357
358 ps_next_ref = ps_next_ref->ps_prev_dpb;
359 }
360
361 if(i == ps_dpb_mgr->u1_num_ref_bufs)
362 {
363 ps_pic_buf = NULL;
364 }
365
366 return ps_pic_buf;
367 }
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
ihevc_dpb_mgr_get_ref_by_poc_lsb(dpb_mgr_t * ps_dpb_mgr,WORD32 poc_lsb)395 pic_buf_t* ihevc_dpb_mgr_get_ref_by_poc_lsb(dpb_mgr_t *ps_dpb_mgr, WORD32 poc_lsb)
396 {
397 pic_buf_t *ps_pic_buf = NULL;
398 UWORD32 i;
399 dpb_info_t *ps_next_ref;
400
401 ps_next_ref = ps_dpb_mgr->ps_dpb_head;
402 for(i = 0; i < ps_dpb_mgr->u1_num_ref_bufs; i++)
403 {
404 if(ps_next_ref->ps_pic_buf->i4_poc_lsb == poc_lsb)
405 {
406 ps_pic_buf = ps_next_ref->ps_pic_buf;
407 break;
408 }
409
410 ps_next_ref = ps_next_ref->ps_prev_dpb;
411 }
412
413 if(i == ps_dpb_mgr->u1_num_ref_bufs)
414 {
415 ps_pic_buf = NULL;
416 }
417
418 return ps_pic_buf;
419 }
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
ihevc_dpb_mgr_reset(dpb_mgr_t * ps_dpb_mgr,buf_mgr_t * ps_buf_mgr)445 void ihevc_dpb_mgr_reset(dpb_mgr_t *ps_dpb_mgr, buf_mgr_t *ps_buf_mgr)
446 {
447 int i;
448 dpb_info_t *ps_dpb_info;
449
450 ps_dpb_info = ps_dpb_mgr->as_dpb_info;
451
452 for(i = 0; i < MAX_DPB_BUFS; i++)
453 {
454 if(ps_dpb_info[i].ps_pic_buf->u1_used_as_ref)
455 {
456 ps_dpb_info[i].ps_pic_buf->u1_used_as_ref = UNUSED_FOR_REF;
457 ps_dpb_info[i].ps_prev_dpb = NULL;
458 //Release physical buffer
459 ihevc_buf_mgr_release(ps_buf_mgr, ps_dpb_info[i].ps_pic_buf->u1_buf_id,
460 BUF_MGR_REF);
461
462 ps_dpb_info[i].ps_pic_buf = NULL;
463 }
464 }
465 ps_dpb_mgr->u1_num_ref_bufs = 0;
466 ps_dpb_mgr->ps_dpb_head = NULL;
467
468 }
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
ihevc_dpb_mgr_release_pics(buf_mgr_t * ps_buf_mgr,UWORD8 u1_disp_bufs)493 void ihevc_dpb_mgr_release_pics(buf_mgr_t *ps_buf_mgr, UWORD8 u1_disp_bufs)
494 {
495 WORD8 i;
496 UWORD32 buf_status;
497
498 for(i = 0; i < u1_disp_bufs; i++)
499 {
500 buf_status = ihevc_buf_mgr_get_status(ps_buf_mgr, i);
501 if(0 != buf_status)
502 {
503 ihevc_buf_mgr_release((buf_mgr_t *)ps_buf_mgr, i, BUF_MGR_REF);
504 }
505 }
506 }
507