1 /****************************************************************************** 2 * 3 * Copyright (C) 2015 The Android Open Source Project 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 * Originally developed and contributed by Ittiam Systems Pvt. Ltd, Bangalore 19 */ 20 /** 21 ******************************************************************************* 22 * @file 23 * ih264_dpb_mgr.c 24 * 25 * @brief 26 * Function definitions used for decoded picture buffer management 27 * 28 * @author 29 * Srinivas T 30 * 31 * @par List of Functions: 32 * - ih264_dpb_mgr_init() 33 * - ih264_dpb_mgr_sort_short_term_fields_by_frame_num() 34 * - ih264_dpb_mgr_sort_short_term_fields_by_poc_l0() 35 * - ih264_dpb_mgr_sort_short_term_fields_by_poc_l1() 36 * - ih264_dpb_mgr_sort_long_term_fields_by_frame_idx() 37 * - ih264_dpb_mgr_alternate_ref_fields() 38 * - ih264_dpb_mgr_insert_ref_field() 39 * - ih264_dpb_mgr_insert_ref_frame() 40 * - ih264_dpb_mgr_count_ref_frames() 41 * - ih264_dpb_mgr_delete_ref_frame() 42 * - ih264_dpb_mgr_delete_long_ref_fields_max_frame_idx() 43 * - ih264_dpb_mgr_delete_short_ref_frame() 44 * - ih264_dpb_mgr_delete_all_ref_frames() 45 * - ih264_dpb_mgr_reset() 46 * - ih264_dpb_mgr_release_pics() 47 * 48 * @remarks 49 * None 50 * 51 ******************************************************************************* 52 */ 53 54 #include <stdio.h> 55 #include <stdlib.h> 56 #include <assert.h> 57 58 #include "ih264_typedefs.h" 59 #include "ih264_defs.h" 60 #include "ih264_macros.h" 61 #include "ih264_error.h" 62 #include "ih264_structs.h" 63 #include "ih264_buf_mgr.h" 64 #include "ih264_dpb_mgr.h" 65 #include "ih264_debug.h" 66 67 /** 68 ******************************************************************************* 69 * 70 * @brief 71 * DPB manager initializer 72 * 73 * @par Description: 74 * Initialises the DPB manager structure 75 * 76 * @param[in] ps_dpb_mgr 77 * Pointer to the DPB manager structure 78 * 79 * @returns 80 * 81 * @remarks 82 * 83 * 84 ******************************************************************************* 85 */ 86 87 void ih264_dpb_mgr_init(dpb_mgr_t *ps_dpb_mgr) 88 { 89 UWORD32 i; 90 dpb_info_t *ps_dpb_info = ps_dpb_mgr->as_dpb_info; 91 for(i = 0; i < MAX_DPB_BUFS; i++) 92 { 93 ps_dpb_info[i].ps_prev_dpb = NULL; 94 ps_dpb_info[i].ps_pic_buf = NULL; 95 ps_dpb_mgr->as_top_field_pics[i].i4_used_as_ref = INVALID; 96 ps_dpb_mgr->as_bottom_field_pics[i].i4_used_as_ref = INVALID; 97 ps_dpb_mgr->as_top_field_pics[i].i1_field_type = INVALID; 98 ps_dpb_mgr->as_bottom_field_pics[i].i1_field_type = INVALID; 99 ps_dpb_mgr->as_top_field_pics[i].i4_long_term_frame_idx = -1; 100 ps_dpb_mgr->as_bottom_field_pics[i].i4_long_term_frame_idx = -1; 101 } 102 103 ps_dpb_mgr->u1_num_short_term_ref_bufs = 0; 104 ps_dpb_mgr->u1_num_long_term_ref_bufs = 0; 105 ps_dpb_mgr->ps_dpb_short_term_head = NULL; 106 ps_dpb_mgr->ps_dpb_long_term_head = NULL; 107 } 108 109 /** 110 ******************************************************************************* 111 * 112 * @brief 113 * Function to sort sort term pics by frame_num. 114 * 115 * @par Description: 116 * Sorts short term fields by frame_num. For 2 fields having same frame_num, 117 * orders them based on requested first field type. 118 * 119 * @param[in] ps_dpb_mgr 120 * Pointer to the DPB manager structure 121 * 122 * @param[in] curr_frame_num 123 * frame_num of the current pic 124 * 125 * @param[in] first_field_type 126 * For complementary fields, required first field 127 * 128 * @param[in] max_frame_num 129 * Maximum frame_num allowed 130 * 131 * @returns 132 * 133 * @remarks 134 * 135 * 136 ******************************************************************************* 137 */ 138 WORD32 ih264_dpb_mgr_sort_short_term_fields_by_frame_num(dpb_mgr_t *ps_dpb_mgr, 139 WORD32 curr_frame_num, 140 WORD32 first_field_type, 141 WORD32 max_frame_num) 142 { 143 dpb_info_t *ps_dpb_node1 = ps_dpb_mgr->ps_dpb_short_term_head; 144 dpb_info_t *ps_dpb_node2; 145 WORD32 frame_num_node1; 146 WORD32 frame_num_node2; 147 pic_buf_t *ps_pic_buf; 148 149 if(ps_dpb_node1 == NULL) 150 return -1; 151 152 for (; ps_dpb_node1 != NULL; ps_dpb_node1 = ps_dpb_node1->ps_prev_dpb) 153 { 154 for (ps_dpb_node2 = ps_dpb_node1->ps_prev_dpb; ps_dpb_node2 != NULL; ps_dpb_node2 = ps_dpb_node2->ps_prev_dpb) 155 { 156 frame_num_node1 = ps_dpb_node1->ps_pic_buf->i4_frame_num; 157 frame_num_node2 = ps_dpb_node2->ps_pic_buf->i4_frame_num; 158 159 if(frame_num_node1 > curr_frame_num) 160 frame_num_node1 = frame_num_node1 - max_frame_num; 161 if(frame_num_node2 > curr_frame_num) 162 frame_num_node2 = frame_num_node2 - max_frame_num; 163 164 if(frame_num_node1 < frame_num_node2) 165 { 166 ps_pic_buf = ps_dpb_node1->ps_pic_buf; 167 ps_dpb_node1->ps_pic_buf = ps_dpb_node2->ps_pic_buf; 168 ps_dpb_node2->ps_pic_buf = ps_pic_buf; 169 } 170 } 171 } 172 173 /** 174 * For frames and complementary field pairs, 175 * ensure first_field_type appears first in the list 176 */ 177 ps_dpb_node1 = ps_dpb_mgr->ps_dpb_short_term_head; 178 ps_dpb_node2 = ps_dpb_node1->ps_prev_dpb; 179 while(ps_dpb_node2 != NULL) 180 { 181 pic_buf_t *ps_pic_node1 = ps_dpb_node1->ps_pic_buf; 182 pic_buf_t *ps_pic_node2 = ps_dpb_node2->ps_pic_buf; 183 frame_num_node1 = ps_pic_node1->i4_frame_num; 184 frame_num_node2 = ps_pic_node2->i4_frame_num; 185 if(frame_num_node1 == frame_num_node2) 186 { 187 ASSERT(ps_pic_node1->i1_field_type != ps_pic_node2->i1_field_type); 188 if(ps_pic_node1->i1_field_type != first_field_type) 189 { 190 ps_dpb_node1->ps_pic_buf = ps_pic_node2; 191 ps_dpb_node2->ps_pic_buf = ps_pic_node1; 192 } 193 } 194 ps_dpb_node1 = ps_dpb_node2; 195 ps_dpb_node2 = ps_dpb_node2->ps_prev_dpb; 196 } 197 return 0; 198 199 } 200 201 /** 202 ******************************************************************************* 203 * 204 * @brief 205 * Function to sort sort term pics by poc for list 0. 206 * 207 * @par Description: 208 * Orders all the pocs less than current poc in the descending order. 209 * Then orders all the pocs greater than current poc in the ascending order. 210 * 211 * @param[in] ps_dpb_mgr 212 * Pointer to the DPB manager structure 213 * 214 * @param[in] curr_poc 215 * Poc of the current pic 216 * 217 * @param[in] first_field_type 218 * For complementary fields, required first field 219 * 220 * @returns 221 * 222 * @remarks 223 * 224 * 225 ******************************************************************************* 226 */ 227 WORD32 ih264_dpb_mgr_sort_short_term_fields_by_poc_l0(dpb_mgr_t *ps_dpb_mgr, 228 WORD32 curr_poc, 229 WORD32 first_field_type) 230 { 231 dpb_info_t *ps_dpb_node1 = ps_dpb_mgr->ps_dpb_short_term_head; 232 dpb_info_t *ps_dpb_node2; 233 WORD32 poc_node1; 234 WORD32 poc_node2; 235 WORD32 frame_num_node1; 236 WORD32 frame_num_node2; 237 pic_buf_t *ps_pic_buf; 238 239 if(ps_dpb_node1 == NULL) 240 return -1; 241 242 /** 243 * Sort the fields by poc. 244 * All POCs less than current poc are first placed in the descending order. 245 * Then all POCs greater than current poc are placed in the ascending order. 246 */ 247 for (; ps_dpb_node1 != NULL; ps_dpb_node1 = ps_dpb_node1->ps_prev_dpb) 248 { 249 for (ps_dpb_node2 = ps_dpb_node1->ps_prev_dpb; ps_dpb_node2 != NULL; ps_dpb_node2 = ps_dpb_node2->ps_prev_dpb) 250 { 251 poc_node1 = ps_dpb_node1->ps_pic_buf->i4_abs_poc; 252 poc_node2 = ps_dpb_node2->ps_pic_buf->i4_abs_poc; 253 ASSERT(poc_node1 != curr_poc); 254 ASSERT(poc_node2 != curr_poc); 255 if(((poc_node1 < curr_poc) && (poc_node2 > curr_poc)) || 256 ((poc_node1 < curr_poc) && (poc_node2 < curr_poc) && (poc_node1 > poc_node2)) || 257 ((poc_node1 > curr_poc) && (poc_node2 > curr_poc) && (poc_node1 < poc_node2))) 258 continue; 259 260 ps_pic_buf = ps_dpb_node1->ps_pic_buf; 261 ps_dpb_node1->ps_pic_buf = ps_dpb_node2->ps_pic_buf; 262 ps_dpb_node2->ps_pic_buf = ps_pic_buf; 263 } 264 } 265 266 ps_dpb_node1 = ps_dpb_mgr->ps_dpb_short_term_head; 267 ps_dpb_node2 = ps_dpb_node1->ps_prev_dpb; 268 while(ps_dpb_node2 != NULL) 269 { 270 pic_buf_t *ps_pic_node1 = ps_dpb_node1->ps_pic_buf; 271 pic_buf_t *ps_pic_node2 = ps_dpb_node2->ps_pic_buf; 272 frame_num_node1 = ps_pic_node1->i4_frame_num; 273 frame_num_node2 = ps_pic_node2->i4_frame_num; 274 if(frame_num_node1 == frame_num_node2) 275 { 276 ASSERT(ps_pic_node1->i1_field_type != ps_pic_node2->i1_field_type); 277 if(ps_pic_node1->i1_field_type != first_field_type) 278 { 279 ps_dpb_node1->ps_pic_buf = ps_pic_node2; 280 ps_dpb_node2->ps_pic_buf = ps_pic_node1; 281 } 282 } 283 ps_dpb_node1 = ps_dpb_node2; 284 ps_dpb_node2 = ps_dpb_node2->ps_prev_dpb; 285 } 286 return 0; 287 288 } 289 290 /** 291 ******************************************************************************* 292 * 293 * @brief 294 * Function to sort sort term pics by poc for list 1. 295 * 296 * @par Description: 297 * Orders all the pocs greater than current poc in the ascending order. 298 * Then rrders all the pocs less than current poc in the descending order. 299 * 300 * @param[in] ps_dpb_mgr 301 * Pointer to the DPB manager structure 302 * 303 * @param[in] curr_poc 304 * Poc of the current pic 305 * 306 * @param[in] first_field_type 307 * For complementary fields, required first field 308 * 309 * @returns 310 * 311 * @remarks 312 * 313 * 314 ******************************************************************************* 315 */ 316 WORD32 ih264_dpb_mgr_sort_short_term_fields_by_poc_l1(dpb_mgr_t *ps_dpb_mgr, 317 WORD32 curr_poc, 318 WORD32 first_field_type) 319 { 320 dpb_info_t *ps_dpb_node1 = ps_dpb_mgr->ps_dpb_short_term_head; 321 dpb_info_t *ps_dpb_node2; 322 WORD32 poc_node1; 323 WORD32 poc_node2; 324 WORD32 frame_num_node1; 325 WORD32 frame_num_node2; 326 pic_buf_t *ps_pic_buf; 327 328 if(ps_dpb_node1 == NULL) 329 return -1; 330 331 /** 332 * Sort the fields by poc. 333 * All POCs greater than current poc are first placed in the ascending order. 334 * Then all POCs less than current poc are placed in the decending order. 335 */ 336 for (; ps_dpb_node1 != NULL; ps_dpb_node1 = ps_dpb_node1->ps_prev_dpb) 337 { 338 for (ps_dpb_node2 = ps_dpb_node1->ps_prev_dpb; ps_dpb_node2 != NULL; ps_dpb_node2 = ps_dpb_node2->ps_prev_dpb) 339 { 340 poc_node1 = ps_dpb_node1->ps_pic_buf->i4_abs_poc; 341 poc_node2 = ps_dpb_node2->ps_pic_buf->i4_abs_poc; 342 ASSERT(poc_node1 != curr_poc); 343 ASSERT(poc_node2 != curr_poc); 344 if(((poc_node1 > curr_poc) && (poc_node2 < curr_poc)) || 345 ((poc_node1 < curr_poc) && (poc_node2 < curr_poc) && (poc_node1 > poc_node2)) || 346 ((poc_node1 > curr_poc) && (poc_node2 > curr_poc) && (poc_node1 < poc_node2))) 347 continue; 348 349 ps_pic_buf = ps_dpb_node1->ps_pic_buf; 350 ps_dpb_node1->ps_pic_buf = ps_dpb_node2->ps_pic_buf; 351 ps_dpb_node2->ps_pic_buf = ps_pic_buf; 352 } 353 } 354 355 ps_dpb_node1 = ps_dpb_mgr->ps_dpb_short_term_head; 356 ps_dpb_node2 = ps_dpb_node1->ps_prev_dpb; 357 while(ps_dpb_node2 != NULL) 358 { 359 pic_buf_t *ps_pic_node1 = ps_dpb_node1->ps_pic_buf; 360 pic_buf_t *ps_pic_node2 = ps_dpb_node2->ps_pic_buf; 361 frame_num_node1 = ps_pic_node1->i4_frame_num; 362 frame_num_node2 = ps_pic_node2->i4_frame_num; 363 if(frame_num_node1 == frame_num_node2) 364 { 365 ASSERT(ps_pic_node1->i1_field_type != ps_pic_node2->i1_field_type); 366 if(ps_pic_node1->i1_field_type != first_field_type) 367 { 368 ps_dpb_node1->ps_pic_buf = ps_pic_node2; 369 ps_dpb_node2->ps_pic_buf = ps_pic_node1; 370 } 371 } 372 ps_dpb_node1 = ps_dpb_node2; 373 ps_dpb_node2 = ps_dpb_node2->ps_prev_dpb; 374 } 375 return 0; 376 } 377 /** 378 ******************************************************************************* 379 * 380 * @brief 381 * Function to sort long term pics by long term frame idx. 382 * 383 * @par Description: 384 * Sorts long term fields by long term frame idx. For 2 fields 385 * having same frame_num, orders them based on requested first field type. 386 * 387 * @param[in] ps_dpb_mgr 388 * Pointer to the DPB manager structure 389 * 390 * @param[in] first_field_type 391 * For complementary fields, required first field 392 * 393 * @returns 394 * 395 * @remarks 396 * 397 * 398 ******************************************************************************* 399 */ 400 WORD32 ih264_dpb_mgr_sort_long_term_fields_by_frame_idx(dpb_mgr_t *ps_dpb_mgr, 401 WORD32 first_field_type) 402 { 403 dpb_info_t *ps_dpb_node1 = ps_dpb_mgr->ps_dpb_long_term_head; 404 dpb_info_t *ps_dpb_node2; 405 WORD32 frame_idx_node1; 406 WORD32 frame_idx_node2; 407 pic_buf_t *ps_pic_buf; 408 409 if(ps_dpb_node1 == NULL) 410 return -1; 411 412 /* Sort the fields by frame idx */ 413 for (; ps_dpb_node1 != NULL; ps_dpb_node1 = ps_dpb_node1->ps_prev_dpb) 414 { 415 for (ps_dpb_node2 = ps_dpb_node1->ps_prev_dpb; ps_dpb_node2 != NULL; ps_dpb_node2 = ps_dpb_node2->ps_prev_dpb) 416 { 417 frame_idx_node1 = ps_dpb_node1->ps_pic_buf->i4_long_term_frame_idx; 418 frame_idx_node2 = ps_dpb_node2->ps_pic_buf->i4_long_term_frame_idx; 419 420 if(frame_idx_node1 > frame_idx_node2) 421 { 422 ps_pic_buf = ps_dpb_node1->ps_pic_buf; 423 ps_dpb_node1->ps_pic_buf = ps_dpb_node2->ps_pic_buf; 424 ps_dpb_node2->ps_pic_buf = ps_pic_buf; 425 } 426 } 427 } 428 429 /** 430 * For frames and complementary field pairs, 431 * ensure first_field_type appears first in the list 432 */ 433 ps_dpb_node1 = ps_dpb_mgr->ps_dpb_long_term_head; 434 ps_dpb_node2 = ps_dpb_node1->ps_prev_dpb; 435 while(ps_dpb_node2 != NULL) 436 { 437 pic_buf_t *ps_pic_node1 = ps_dpb_node1->ps_pic_buf; 438 pic_buf_t *ps_pic_node2 = ps_dpb_node2->ps_pic_buf; 439 frame_idx_node1 = ps_pic_node1->i4_long_term_frame_idx; 440 frame_idx_node2 = ps_pic_node2->i4_long_term_frame_idx; 441 if(frame_idx_node1 == frame_idx_node2) 442 { 443 ASSERT(ps_pic_node1->i1_field_type != ps_pic_node2->i1_field_type); 444 if(ps_pic_node1->i1_field_type != first_field_type) 445 { 446 ps_dpb_node1->ps_pic_buf = ps_pic_node2; 447 ps_dpb_node2->ps_pic_buf = ps_pic_node1; 448 } 449 } 450 ps_dpb_node1 = ps_dpb_node2; 451 ps_dpb_node2 = ps_dpb_node2->ps_prev_dpb; 452 } 453 return 0; 454 } 455 456 /** 457 ******************************************************************************* 458 * 459 * @brief 460 * Function to alternate fields. 461 * 462 * @par Description: 463 * In the ordered list of fields, alternate fields starting with 464 * first_field_type 465 * 466 * @param[in] ps_dpb_mgr 467 * Pointer to the DPB manager structure 468 * 469 * @param[in] reference_type 470 * This is used to select between short-term and long-term linked list. 471 * 472 * @param[in] first_field_type 473 * For complementary fields, required first field 474 * 475 * @returns 476 * 477 * @remarks 478 * 479 * 480 ******************************************************************************* 481 */ 482 WORD32 ih264_dpb_mgr_alternate_ref_fields(dpb_mgr_t *ps_dpb_mgr, 483 WORD32 reference_type, 484 WORD32 first_field_type) 485 { 486 dpb_info_t s_dpb_head; 487 dpb_info_t *ps_dpb_head; 488 dpb_info_t *ps_dpb_node1; 489 dpb_info_t *ps_dpb_node2; 490 dpb_info_t *ps_dpb_node3; 491 dpb_info_t *ps_dpb_node4; 492 WORD32 expected_field; 493 494 expected_field = first_field_type; 495 496 ps_dpb_head = &s_dpb_head; 497 498 ps_dpb_head->ps_prev_dpb = (reference_type == SHORT_TERM_REF) ? 499 ps_dpb_mgr->ps_dpb_short_term_head: 500 ps_dpb_mgr->ps_dpb_long_term_head; 501 502 ps_dpb_node1 = ps_dpb_head; 503 ps_dpb_node2 = ps_dpb_node1->ps_prev_dpb; 504 while(ps_dpb_node2 != NULL) 505 { 506 pic_buf_t *ps_pic_node2 = ps_dpb_node2->ps_pic_buf; 507 if(ps_pic_node2->i1_field_type != expected_field) 508 { 509 /* 510 * If it is not expected field, loop over the node till 511 * the expected field. 512 */ 513 ps_dpb_node3 = ps_dpb_node2; 514 ps_dpb_node4 = ps_dpb_node2->ps_prev_dpb; 515 while((ps_dpb_node4 != NULL) && 516 (ps_dpb_node4->ps_pic_buf->i1_field_type != expected_field)) 517 { 518 ps_dpb_node3 = ps_dpb_node4; 519 ps_dpb_node4 = ps_dpb_node4->ps_prev_dpb; 520 } 521 if(ps_dpb_node4 != NULL) 522 { 523 ps_dpb_node1->ps_prev_dpb = ps_dpb_node4; 524 ps_dpb_node3->ps_prev_dpb = ps_dpb_node4->ps_prev_dpb; 525 ps_dpb_node4->ps_prev_dpb = ps_dpb_node2; 526 } 527 else 528 { 529 /* node4 null means we have reached the end */ 530 break; 531 } 532 } 533 ps_dpb_node1 = ps_dpb_node1->ps_prev_dpb; 534 ps_dpb_node2 = ps_dpb_node1->ps_prev_dpb; 535 expected_field = (ps_dpb_node1->ps_pic_buf->i1_field_type == TOP_FIELD)? 536 BOTTOM_FIELD:TOP_FIELD; 537 } 538 539 if(reference_type == SHORT_TERM_REF) 540 { 541 ps_dpb_mgr->ps_dpb_short_term_head = ps_dpb_head->ps_prev_dpb; 542 } 543 else 544 { 545 ps_dpb_mgr->ps_dpb_long_term_head = ps_dpb_head->ps_prev_dpb; 546 } 547 548 return 0; 549 } 550 551 /** 552 ******************************************************************************* 553 * 554 * @brief 555 * Add a ref field to short-term or long-term linked list. 556 * 557 * @par Description: 558 * This function adds a ref field to either short-term or long-term linked 559 * list. It picks up memory for the link from the array of dpb_info in 560 * dpb_mgr. The field is added to the beginning of the linked list and the 561 * head is set the the field. 562 * 563 * @param[in] ps_dpb_mgr 564 * Pointer to the DPB manager structure 565 * 566 * @param[in] ps_pic_buf 567 * Pic buf structure for the field being added. 568 * 569 * @param[in] reference_type 570 * This is used to select between short-term and long-term linked list. 571 * 572 * @param[in] frame_num 573 * frame_num for the field. 574 * 575 * @param[in] long_term_frame_idx 576 * If the ref being added is long-term, long_term_frame_idx of the field. 577 * Otherwise invalid. 578 * 579 * @returns 580 * 581 * @remarks 582 * 583 * 584 ******************************************************************************* 585 */ 586 WORD32 ih264_dpb_mgr_insert_ref_field(dpb_mgr_t *ps_dpb_mgr, 587 pic_buf_t *ps_pic_buf, 588 WORD32 reference_type, 589 UWORD32 frame_num, 590 WORD32 long_term_frame_idx) 591 { 592 WORD32 i; 593 dpb_info_t *ps_dpb_info; 594 dpb_info_t *ps_dpb_head; 595 596 ps_dpb_info = ps_dpb_mgr->as_dpb_info; 597 598 /* Return error if buffer is already present in the DPB */ 599 for(i = 0; i < MAX_DPB_BUFS; i++) 600 { 601 if( (ps_dpb_info[i].ps_pic_buf == ps_pic_buf) 602 && (ps_dpb_info[i].ps_pic_buf->i4_used_as_ref == reference_type) ) 603 { 604 return (-1); 605 } 606 } 607 608 /* Find an unused DPB location */ 609 for(i = 0; i < MAX_DPB_BUFS; i++) 610 { 611 if(NULL == ps_dpb_info[i].ps_pic_buf) 612 { 613 break; 614 } 615 } 616 if(i == MAX_DPB_BUFS) 617 { 618 return (-1); 619 } 620 621 ps_dpb_head = (reference_type == SHORT_TERM_REF) 622 ?ps_dpb_mgr->ps_dpb_short_term_head 623 :ps_dpb_mgr->ps_dpb_long_term_head; 624 625 if(reference_type == SHORT_TERM_REF) 626 long_term_frame_idx = -1; 627 628 /* Create DPB info */ 629 ps_dpb_info[i].ps_pic_buf = ps_pic_buf; 630 ps_dpb_info[i].ps_prev_dpb = ps_dpb_head; 631 ps_dpb_info[i].ps_pic_buf->i4_used_as_ref = reference_type; 632 ps_dpb_info[i].ps_pic_buf->i4_frame_num = frame_num; 633 ps_dpb_info[i].ps_pic_buf->i4_long_term_frame_idx = long_term_frame_idx; 634 635 /* update the head node of linked list to point to the current picture */ 636 if(reference_type == SHORT_TERM_REF) 637 { 638 ps_dpb_mgr->ps_dpb_short_term_head = ps_dpb_info + i; 639 640 /* Increment Short term buffer count */ 641 ps_dpb_mgr->u1_num_short_term_ref_bufs++; 642 643 } 644 else 645 { 646 ps_dpb_mgr->ps_dpb_long_term_head = ps_dpb_info + i; 647 648 /* Increment Long term buffer count */ 649 ps_dpb_mgr->u1_num_long_term_ref_bufs++; 650 } 651 652 return 0; 653 } 654 655 /** 656 ******************************************************************************* 657 * 658 * @brief 659 * Add a ref frame to short-term or long-term linked list. 660 * 661 * @par Description: 662 * This function adds a ref frame to either short-term or long-term linked 663 * list. Internally it calls add ref field twice to add top and bottom field. 664 * 665 * @param[in] ps_dpb_mgr 666 * Pointer to the DPB manager structure 667 * 668 * @param[in] ps_pic_buf 669 * Pic buf structure for the field being added. 670 * 671 * @param[in] reference_type 672 * This is used to select between short-term and long-term linked list. 673 * 674 * @param[in] frame_num 675 * frame_num for the field. 676 * 677 * @param[in] long_term_frame_idx 678 * If the ref being added is long-term, long_term_frame_idx of the field. 679 * Otherwise invalid. 680 * 681 * @returns 682 * 683 * @remarks 684 * 685 * 686 ******************************************************************************* 687 */ 688 WORD32 ih264_dpb_mgr_insert_ref_frame(dpb_mgr_t *ps_dpb_mgr, 689 pic_buf_t *ps_pic_buf, 690 WORD32 reference_type, 691 UWORD32 frame_num, 692 WORD32 long_term_frame_idx) 693 { 694 WORD32 buf_id; 695 pic_buf_t *ps_pic_top; 696 pic_buf_t *ps_pic_bottom; 697 WORD32 ret; 698 699 /* 700 * For a frame, since the ps_pic_buf passed to this function is that of top field 701 * obtain bottom field using buf_id. 702 */ 703 ps_pic_top = ps_pic_buf; 704 buf_id = ps_pic_top->i4_buf_id; 705 ps_pic_bottom = &ps_dpb_mgr->as_bottom_field_pics[buf_id]; 706 707 /* Insert top field */ 708 ret = ih264_dpb_mgr_insert_ref_field(ps_dpb_mgr, 709 ps_pic_top, 710 reference_type, 711 frame_num, 712 long_term_frame_idx); 713 714 if(ret != 0) 715 return ret; 716 717 /* Insert bottom field */ 718 ret = ih264_dpb_mgr_insert_ref_field(ps_dpb_mgr, 719 ps_pic_bottom, 720 reference_type, 721 frame_num, 722 long_term_frame_idx); 723 724 if(ret != 0) 725 return ret; 726 727 return ret; 728 } 729 730 /** 731 ******************************************************************************* 732 * 733 * @brief 734 * Returns the number of ref frames in both the linked list. 735 * 736 * @par Description: 737 * Returns the count of number of frames, number of complementary field pairs 738 * and number of unpaired fields. 739 * 740 * @param[in] ps_dpb_mgr 741 * Pointer to the DPB manager structure 742 * 743 * @param[in] curr_frame_num 744 * frame_num for the field. 745 * 746 * @param[in] max_frame_num 747 * Maximum frame_num allowed 748 * 749 * @returns 750 * 751 * @remarks 752 * 753 * 754 ******************************************************************************* 755 */ 756 WORD32 ih264_dpb_mgr_count_ref_frames(dpb_mgr_t *ps_dpb_mgr, 757 WORD32 curr_frame_num, 758 WORD32 max_frame_num) 759 { 760 WORD32 numShortTerm = 0; 761 WORD32 numLongTerm = 0; 762 dpb_info_t *ps_dpb_node; 763 WORD32 frame_num; 764 WORD32 prev_frame_num; 765 766 /* 767 * Compute the number of short-term frames/complementary field pairs/ 768 * unpaired fields 769 */ 770 if(ps_dpb_mgr->ps_dpb_short_term_head != NULL) 771 { 772 /* Sort the short-term list by frame_num */ 773 ih264_dpb_mgr_sort_short_term_fields_by_frame_num(ps_dpb_mgr, 774 curr_frame_num, 775 TOP_FIELD, 776 max_frame_num); 777 778 ps_dpb_node = ps_dpb_mgr->ps_dpb_short_term_head; 779 if(ps_dpb_node != NULL) 780 { 781 numShortTerm++; 782 prev_frame_num = ps_dpb_node->ps_pic_buf->i4_frame_num; 783 ps_dpb_node = ps_dpb_node->ps_prev_dpb; 784 } 785 786 while(ps_dpb_node != NULL) 787 { 788 frame_num = ps_dpb_node->ps_pic_buf->i4_frame_num; 789 if(frame_num != prev_frame_num) 790 numShortTerm++; 791 prev_frame_num = ps_dpb_node->ps_pic_buf->i4_frame_num; 792 ps_dpb_node = ps_dpb_node->ps_prev_dpb; 793 } 794 } 795 796 /* 797 * Compute the number of long-term frames/complementary field pairs/ 798 * unpaired fields 799 */ 800 if(ps_dpb_mgr->ps_dpb_long_term_head != NULL) 801 { 802 ih264_dpb_mgr_sort_long_term_fields_by_frame_idx(ps_dpb_mgr, 803 TOP_FIELD); 804 805 ps_dpb_node = ps_dpb_mgr->ps_dpb_long_term_head; 806 if(ps_dpb_node != NULL) 807 { 808 numLongTerm++; 809 prev_frame_num = ps_dpb_node->ps_pic_buf->i4_frame_num; 810 ps_dpb_node = ps_dpb_node->ps_prev_dpb; 811 } 812 813 while(ps_dpb_node != NULL) 814 { 815 frame_num = ps_dpb_node->ps_pic_buf->i4_frame_num; 816 if(frame_num != prev_frame_num) 817 numLongTerm++; 818 prev_frame_num = ps_dpb_node->ps_pic_buf->i4_frame_num; 819 ps_dpb_node = ps_dpb_node->ps_prev_dpb; 820 } 821 } 822 return (numShortTerm + numLongTerm); 823 } 824 825 /** 826 ******************************************************************************* 827 * 828 * @brief 829 * Deletes the ref frame at the end of the linked list. 830 * 831 * @par Description: 832 * Deletes the ref frame at the end of the linked list. For unpaired fields, 833 * it deletes just the last node. For frame or complementary field pair, it 834 * deletes the last two nodes. 835 * 836 * @param[in] ps_dpb_mgr 837 * Pointer to the DPB manager structure 838 * 839 * @param[in] reference_type 840 * This is used to select between short-term and long-term linked list. 841 * 842 * @returns 843 * 844 * @remarks 845 * 846 * 847 ******************************************************************************* 848 */ 849 WORD32 ih264_dpb_mgr_delete_ref_frame(dpb_mgr_t *ps_dpb_mgr, 850 WORD32 reference_type) 851 { 852 dpb_info_t *ps_dpb_node1; 853 dpb_info_t *ps_dpb_node2; 854 dpb_info_t *ps_dpb_node3; 855 856 /* 857 * Assumption: The nodes sorted for frame num. 858 */ 859 860 861 /* Select bw short-term and long-term list. */ 862 ps_dpb_node1 = (reference_type == SHORT_TERM_REF) 863 ?ps_dpb_mgr->ps_dpb_short_term_head 864 :ps_dpb_mgr->ps_dpb_long_term_head; 865 /* If null, no entries in the list. Hence return. */ 866 if(ps_dpb_node1 == NULL) 867 return 0; 868 869 /* If only one node in the list, set as unsed for refer and return. */ 870 if(ps_dpb_node1->ps_prev_dpb == NULL) 871 { 872 /* Set the picture as unused for reference */ 873 ps_dpb_node1->ps_pic_buf->i4_used_as_ref = UNUSED_FOR_REF; 874 ps_dpb_node1->ps_pic_buf = NULL; 875 876 if(reference_type == SHORT_TERM_REF) 877 { 878 ps_dpb_mgr->ps_dpb_short_term_head = NULL; 879 880 /* Increment Short term buffer count */ 881 ps_dpb_mgr->u1_num_short_term_ref_bufs = 0; 882 883 } 884 else 885 { 886 ps_dpb_mgr->ps_dpb_long_term_head = NULL; 887 888 /* Increment Long term buffer count */ 889 ps_dpb_mgr->u1_num_long_term_ref_bufs = 0; 890 891 } 892 return 0; 893 } 894 895 /** 896 * If there are only 2 nodes in the list, set second node as unused for reference. 897 * If the frame_num of second node and first node is same, set first node also as 898 * unused for reference and set the corresponding head to NULL. 899 */ 900 ps_dpb_node2 = ps_dpb_node1->ps_prev_dpb; 901 if(ps_dpb_node2->ps_prev_dpb == NULL) 902 { 903 /* Set the picture as unused for reference */ 904 if(ps_dpb_node2->ps_pic_buf->i4_frame_num == ps_dpb_node1->ps_pic_buf->i4_frame_num) 905 { 906 /* Set the picture as unused for reference */ 907 ps_dpb_node1->ps_pic_buf->i4_used_as_ref = UNUSED_FOR_REF; 908 ps_dpb_node1->ps_pic_buf = NULL; 909 if(reference_type == SHORT_TERM_REF) 910 { 911 ps_dpb_mgr->ps_dpb_short_term_head = NULL; 912 913 /* Increment Short term buffer count */ 914 ps_dpb_mgr->u1_num_short_term_ref_bufs = 0; 915 916 } 917 else 918 { 919 ps_dpb_mgr->ps_dpb_long_term_head = NULL; 920 921 /* Increment Long term buffer count */ 922 ps_dpb_mgr->u1_num_long_term_ref_bufs = 0; 923 924 } 925 926 } 927 ps_dpb_node2->ps_pic_buf->i4_used_as_ref = UNUSED_FOR_REF; 928 ps_dpb_node2->ps_pic_buf = NULL; 929 ps_dpb_node1->ps_prev_dpb = NULL; 930 return 0; 931 } 932 /* 933 * If there are more than 2 nodes, run a loop to get the last 3 nodes. 934 */ 935 ps_dpb_node3 = ps_dpb_node2->ps_prev_dpb; 936 while(ps_dpb_node3->ps_prev_dpb != NULL) 937 { 938 ps_dpb_node1 = ps_dpb_node2; 939 ps_dpb_node2 = ps_dpb_node3; 940 ps_dpb_node3 = ps_dpb_node3->ps_prev_dpb; 941 } 942 /* 943 * If node 2 and node 3 frame_nums are same, set node 2 also as unsed for 944 * reference and del reference from node1. 945 */ 946 if(ps_dpb_node2->ps_pic_buf->i4_frame_num == ps_dpb_node3->ps_pic_buf->i4_frame_num) 947 { 948 ps_dpb_node2->ps_pic_buf->i4_used_as_ref = UNUSED_FOR_REF; 949 ps_dpb_node2->ps_pic_buf = NULL; 950 ps_dpb_node1->ps_prev_dpb = NULL; 951 952 } 953 /* Set the third node as unused for reference */ 954 ps_dpb_node3->ps_pic_buf->i4_used_as_ref = UNUSED_FOR_REF; 955 ps_dpb_node3->ps_pic_buf = NULL; 956 ps_dpb_node2->ps_prev_dpb = NULL; 957 958 return 0; 959 } 960 /** 961 ******************************************************************************* 962 * 963 * @brief 964 * Delete long-term ref fields above max frame idx. 965 * 966 * @par Description: 967 * Deletes all the long-term ref fields having idx greater than max_frame_idx 968 * 969 * @param[in] ps_dpb_mgr 970 * Pointer to the DPB manager structure 971 * 972 * @param[in] max_frame_idx 973 * Max long-term frame idx allowed. 974 * 975 * @returns 976 * 977 * @remarks 978 * 979 * 980 ******************************************************************************* 981 */ 982 WORD32 ih264_dpb_mgr_delete_long_ref_fields_max_frame_idx(dpb_mgr_t *ps_dpb_mgr, 983 WORD32 max_frame_idx) 984 { 985 dpb_info_t *ps_dpb_node1; 986 dpb_info_t *ps_dpb_node2; 987 /* 988 * Loop until there is node which isn't to be deleted is encountered. 989 */ 990 while(ps_dpb_mgr->ps_dpb_long_term_head != NULL) 991 { 992 if(ps_dpb_mgr->ps_dpb_long_term_head->ps_pic_buf->i4_long_term_frame_idx 993 <= max_frame_idx) 994 { 995 break; 996 } 997 ps_dpb_mgr->ps_dpb_long_term_head->ps_pic_buf->i4_used_as_ref = UNUSED_FOR_REF; 998 ps_dpb_mgr->ps_dpb_long_term_head->ps_pic_buf = NULL; 999 ps_dpb_mgr->ps_dpb_long_term_head = ps_dpb_mgr->ps_dpb_long_term_head->ps_prev_dpb; 1000 } 1001 1002 ps_dpb_node1 = ps_dpb_mgr->ps_dpb_long_term_head; 1003 if(ps_dpb_node1 == NULL) 1004 return 0; 1005 /* 1006 * With the node that isn't to be deleted as head, loop until the end. 1007 */ 1008 ps_dpb_node2 = ps_dpb_node1->ps_prev_dpb; 1009 while(ps_dpb_node2 != NULL) 1010 { 1011 if(ps_dpb_node2->ps_pic_buf->i4_long_term_frame_idx > max_frame_idx) 1012 { 1013 ps_dpb_node2->ps_pic_buf->i4_used_as_ref = UNUSED_FOR_REF; 1014 ps_dpb_node2->ps_pic_buf = NULL; 1015 ps_dpb_node1->ps_prev_dpb = ps_dpb_node2->ps_prev_dpb; 1016 } 1017 ps_dpb_node1 = ps_dpb_node1->ps_prev_dpb; 1018 if(ps_dpb_node1 == NULL) 1019 break; 1020 ps_dpb_node2 = ps_dpb_node1->ps_prev_dpb; 1021 } 1022 return 0; 1023 } 1024 1025 /** 1026 ******************************************************************************* 1027 * 1028 * @brief 1029 * Deletes the short-term with least frame_num 1030 * 1031 * @par Description: 1032 * Deletes the short-term with least frame_num. It sorts the function the 1033 * short-term linked list by frame-num and the function that deletes the last 1034 * frame in the linked list. 1035 * 1036 * @param[in] ps_dpb_mgr 1037 * Pointer to the DPB manager structure 1038 * 1039 * @param[in] curr_frame_num 1040 * frame_num of the current pic 1041 * 1042 * @param[in] max_frame_num 1043 * Maximum frame_num allowed 1044 * 1045 * @returns 1046 * 1047 * @remarks 1048 * 1049 * 1050 ******************************************************************************* 1051 */ 1052 WORD32 ih264_dpb_mgr_delete_short_ref_frame(dpb_mgr_t *ps_dpb_mgr, 1053 WORD32 curr_frame_num, 1054 WORD32 max_frame_num) 1055 { 1056 WORD32 ret; 1057 /* Sort the short-term list by frame_num */ 1058 ret = ih264_dpb_mgr_sort_short_term_fields_by_frame_num(ps_dpb_mgr, 1059 curr_frame_num, 1060 TOP_FIELD, 1061 max_frame_num); 1062 1063 /* Delete the last reference frame or field */ 1064 ret = ih264_dpb_mgr_delete_ref_frame(ps_dpb_mgr,SHORT_TERM_REF); 1065 1066 if(ret != 0) 1067 { 1068 ASSERT(0); 1069 } 1070 1071 return ret; 1072 } 1073 /** 1074 ******************************************************************************* 1075 * 1076 * @brief 1077 * Deletes all the ref frames. 1078 * 1079 * @par Description: 1080 * Deletes all of the ref frames/fields in the short-term and long-term linked 1081 * list. 1082 * 1083 * @param[in] ps_dpb_mgr 1084 * Pointer to the DPB manager structure 1085 * 1086 * @returns 1087 * 1088 * @remarks 1089 * 1090 * 1091 ******************************************************************************* 1092 */ 1093 WORD32 ih264_dpb_mgr_delete_all_ref_frames(dpb_mgr_t *ps_dpb_mgr) 1094 { 1095 /* Loop over short-term linked list. */ 1096 while(ps_dpb_mgr->ps_dpb_short_term_head != NULL) 1097 { 1098 ih264_dpb_mgr_delete_ref_frame(ps_dpb_mgr,SHORT_TERM_REF); 1099 } 1100 1101 /* Loop over long-term linked list. */ 1102 while(ps_dpb_mgr->ps_dpb_long_term_head != NULL) 1103 { 1104 ih264_dpb_mgr_delete_ref_frame(ps_dpb_mgr,LONG_TERM_REF); 1105 } 1106 return 0; 1107 } 1108 1109 1110 void ih264_dpb_mgr_reset(dpb_mgr_t *ps_dpb_mgr, buf_mgr_t *ps_buf_mgr) 1111 { 1112 WORD32 i; 1113 dpb_info_t *ps_dpb_info; 1114 ASSERT(0); 1115 1116 1117 ps_dpb_info = ps_dpb_mgr->as_dpb_info; 1118 1119 for(i = 0; i < MAX_DPB_BUFS; i++) 1120 { 1121 if(ps_dpb_info[i].ps_pic_buf->i4_used_as_ref) 1122 { 1123 ps_dpb_info[i].ps_pic_buf->i4_used_as_ref = UNUSED_FOR_REF; 1124 ps_dpb_info[i].ps_prev_dpb = NULL; 1125 //Release physical buffer 1126 ih264_buf_mgr_release(ps_buf_mgr, ps_dpb_info[i].ps_pic_buf->i4_buf_id, 1127 BUF_MGR_REF); 1128 1129 ps_dpb_info[i].ps_pic_buf = NULL; 1130 } 1131 } 1132 ps_dpb_mgr->u1_num_short_term_ref_bufs = 0; 1133 ps_dpb_mgr->u1_num_long_term_ref_bufs = 0; 1134 ps_dpb_mgr->ps_dpb_short_term_head = NULL; 1135 ps_dpb_mgr->ps_dpb_long_term_head = NULL; 1136 1137 } 1138 1139 /** 1140 ******************************************************************************* 1141 * 1142 * @brief 1143 * deletes all pictures from DPB 1144 * 1145 * @par Description: 1146 * Deletes all pictures present in the DPB manager 1147 * 1148 * @param[in] ps_buf_mgr 1149 * Pointer to buffer manager structure 1150 * 1151 * @param[in] u1_disp_bufs 1152 * Number of buffers to be deleted 1153 * 1154 * @returns 1155 * 1156 * @remarks 1157 * 1158 * 1159 ******************************************************************************* 1160 */ 1161 1162 void ih264_dpb_mgr_release_pics(buf_mgr_t *ps_buf_mgr, UWORD8 u1_disp_bufs) 1163 { 1164 WORD8 i; 1165 UWORD32 buf_status; 1166 ASSERT(0); 1167 1168 for(i = 0; i < u1_disp_bufs; i++) 1169 { 1170 buf_status = ih264_buf_mgr_get_status(ps_buf_mgr, i); 1171 if(0 != buf_status) 1172 { 1173 ih264_buf_mgr_release((buf_mgr_t *)ps_buf_mgr, i, BUF_MGR_REF); 1174 } 1175 } 1176 } 1177