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 { 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 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 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 */ 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 */ 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 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 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 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