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_buf_mgr.c 24 * 25 * @brief 26 * Contains function definitions for buffer management 27 * 28 * @author 29 * Srinivas T 30 * 31 * @par List of Functions: 32 * - ih264_buf_mgr_size() 33 * - ih264_buf_mgr_lock() 34 * - ih264_buf_mgr_unlock() 35 * - ih264_buf_mgr_yield() 36 * - ih264_buf_mgr_free() 37 * - ih264_buf_mgr_init() 38 * - ih264_buf_mgr_add() 39 * - ih264_buf_mgr_get_next_free() 40 * - ih264_buf_mgr_check_free() 41 * - ih264_buf_mgr_set_status() 42 * - ih264_buf_mgr_get_status() 43 * - ih264_buf_mgr_get_buf() 44 * - ih264_buf_mgr_get_bufid() 45 * - ih264_buf_mgr_get_num_active_buf() 46 * 47 * @remarks 48 * None 49 * 50 ******************************************************************************* 51 */ 52 #include <stdio.h> 53 #include <stdlib.h> 54 #include "ih264_typedefs.h" 55 #include "ih264_macros.h" 56 #include "ih264_defs.h" 57 #include "ih264_error.h" 58 #include "ih264_buf_mgr.h" 59 60 #include "ithread.h" 61 62 /** 63 ******************************************************************************* 64 * 65 * @brief Returns size for buf queue context. Does not include buf queue buffer 66 * requirements 67 * 68 * @par Description 69 * Returns size for buf queue context. Does not include buf queue buffer 70 * requirements. Buffer size required to store the bufs should be allocated in 71 * addition to the value returned here. 72 * 73 * @returns Size of the buf queue context 74 * 75 * @remarks 76 * 77 ******************************************************************************* 78 */ 79 WORD32 ih264_buf_mgr_size(void) 80 { 81 WORD32 size; 82 83 size = sizeof(buf_mgr_t); 84 size += ithread_get_mutex_lock_size(); 85 86 return size; 87 } 88 89 /** 90 ******************************************************************************* 91 * 92 * @brief 93 * Locks the buf_mgr context 94 * 95 * @par Description 96 * Locks the buf_mgr context by calling ithread_mutex_lock() 97 * 98 * @param[in] ps_buf_mgr 99 * Job Queue context 100 * 101 * @returns IH264_FAIL if mutex lock fails else IH264_SUCCESS 102 * 103 * @remarks 104 * 105 ******************************************************************************* 106 */ 107 IH264_ERROR_T ih264_buf_mgr_lock(buf_mgr_t *ps_buf_mgr) 108 { 109 WORD32 retval; 110 retval = ithread_mutex_lock(ps_buf_mgr->pv_mutex); 111 if(retval) 112 { 113 return IH264_FAIL; 114 } 115 return IH264_SUCCESS; 116 } 117 118 /** 119 ******************************************************************************* 120 * 121 * @brief 122 * Unlocks the buf_mgr context 123 * 124 * @par Description 125 * Unlocks the buf_mgr context by calling ithread_mutex_unlock() 126 * 127 * @param[in] ps_buf_mgr 128 * Job Queue context 129 * 130 * @returns IH264_FAIL if mutex unlock fails else IH264_SUCCESS 131 * 132 * @remarks 133 * 134 ******************************************************************************* 135 */ 136 137 IH264_ERROR_T ih264_buf_mgr_unlock(buf_mgr_t *ps_buf_mgr) 138 { 139 WORD32 retval; 140 retval = ithread_mutex_unlock(ps_buf_mgr->pv_mutex); 141 if(retval) 142 { 143 return IH264_FAIL; 144 } 145 return IH264_SUCCESS; 146 147 } 148 /** 149 ******************************************************************************* 150 * 151 * @brief 152 * Yeilds the thread 153 * 154 * @par Description 155 * Unlocks the buf_mgr context by calling 156 * ih264_buf_mgr_unlock(), ithread_yield() and then ih264_buf_mgr_lock() 157 * buf_mgr is unlocked before to ensure the buf_mgr can be accessed by other threads 158 * If unlock is not done before calling yield then no other thread can access 159 * the buf_mgr functions and update buf_mgr. 160 * 161 * @param[in] ps_buf_mgr 162 * Job Queue context 163 * 164 * @returns IH264_FAIL if mutex lock unlock or yield fails else IH264_SUCCESS 165 * 166 * @remarks 167 * 168 ******************************************************************************* 169 */ 170 IH264_ERROR_T ih264_buf_mgr_yield(buf_mgr_t *ps_buf_mgr) 171 { 172 173 IH264_ERROR_T ret = IH264_SUCCESS; 174 175 IH264_ERROR_T rettmp; 176 rettmp = ih264_buf_mgr_unlock(ps_buf_mgr); 177 RETURN_IF((rettmp != IH264_SUCCESS), rettmp); 178 179 //ithread_usleep(10); 180 ithread_yield(); 181 182 rettmp = ih264_buf_mgr_lock(ps_buf_mgr); 183 RETURN_IF((rettmp != IH264_SUCCESS), rettmp); 184 return ret; 185 } 186 187 188 /** 189 ******************************************************************************* 190 * 191 * @brief free the buf queue pointers 192 * 193 * @par Description 194 * Frees the buf_mgr context 195 * 196 * @param[in] pv_buf 197 * Memoy for buf queue buffer and buf queue context 198 * 199 * @returns Pointer to buf queue context 200 * 201 * @remarks 202 * Since it will be called only once by master thread this is not thread safe. 203 * 204 ******************************************************************************* 205 */ 206 IH264_ERROR_T ih264_buf_mgr_free(buf_mgr_t *ps_buf_mgr) 207 { 208 WORD32 ret; 209 ret = ithread_mutex_destroy(ps_buf_mgr->pv_mutex); 210 211 if(0 == ret) 212 return IH264_SUCCESS; 213 else 214 return IH264_FAIL; 215 } 216 /** 217 ******************************************************************************* 218 * 219 * @brief 220 * Buffer manager initialization function. 221 * 222 * @par Description: 223 * Initializes the buffer manager structure 224 * 225 * @param[in] ps_buf_mgr 226 * Pointer to the buffer manager 227 * 228 * @returns 229 * 230 * @remarks 231 * None 232 * 233 ******************************************************************************* 234 */ 235 236 237 void *ih264_buf_mgr_init(void *pv_buf) 238 { 239 WORD32 id; 240 UWORD8 *pu1_buf; 241 buf_mgr_t *ps_buf_mgr; 242 pu1_buf = (UWORD8 *)pv_buf; 243 244 ps_buf_mgr = (buf_mgr_t *)pu1_buf; 245 pu1_buf += sizeof(buf_mgr_t); 246 247 ps_buf_mgr->pv_mutex = pu1_buf; 248 pu1_buf += ithread_get_mutex_lock_size(); 249 250 ithread_mutex_init(ps_buf_mgr->pv_mutex); 251 252 ps_buf_mgr->i4_max_buf_cnt = BUF_MGR_MAX_CNT; 253 ps_buf_mgr->i4_active_buf_cnt = 0; 254 255 for(id = 0; id < BUF_MGR_MAX_CNT; id++) 256 { 257 ps_buf_mgr->au4_status[id] = 0; 258 ps_buf_mgr->apv_ptr[id] = NULL; 259 } 260 261 return ps_buf_mgr; 262 } 263 264 265 /** 266 ******************************************************************************* 267 * 268 * @brief 269 * Adds and increments the buffer and buffer count. 270 * 271 * @par Description: 272 * Adds a buffer to the buffer manager if it is not already present and 273 * increments the active buffer count 274 * 275 * @param[in] ps_buf_mgr 276 * Pointer to the buffer manager 277 * 278 * @param[in] pv_ptr 279 * Pointer to the buffer to be added 280 * 281 * @returns Returns 0 on success, -1 otherwise 282 * 283 * @remarks 284 * None 285 * 286 ******************************************************************************* 287 */ 288 IH264_ERROR_T ih264_buf_mgr_add(buf_mgr_t *ps_buf_mgr, 289 void *pv_ptr, 290 WORD32 buf_id) 291 { 292 293 IH264_ERROR_T ret = IH264_SUCCESS; 294 ret = ih264_buf_mgr_lock(ps_buf_mgr); 295 RETURN_IF((ret != IH264_SUCCESS), ret); 296 297 /* Check if buffer ID is within allowed range */ 298 if(buf_id >= ps_buf_mgr->i4_max_buf_cnt) 299 { 300 ret = ih264_buf_mgr_unlock(ps_buf_mgr); 301 RETURN_IF((ret != IH264_SUCCESS), ret); 302 303 return IH264_FAIL; 304 } 305 306 /* Check if the current ID is being used to hold some other buffer */ 307 if((ps_buf_mgr->apv_ptr[buf_id] != NULL) && 308 (ps_buf_mgr->apv_ptr[buf_id] !=pv_ptr)) 309 { 310 ret = ih264_buf_mgr_unlock(ps_buf_mgr); 311 RETURN_IF((ret != IH264_SUCCESS), ret); 312 313 return IH264_FAIL; 314 } 315 ps_buf_mgr->apv_ptr[buf_id] = pv_ptr; 316 ps_buf_mgr->i4_active_buf_cnt++; 317 318 ret = ih264_buf_mgr_unlock(ps_buf_mgr); 319 RETURN_IF((ret != IH264_SUCCESS), ret); 320 321 return ret; 322 } 323 324 /** 325 ******************************************************************************* 326 * 327 * @brief 328 * Gets the next free buffer. 329 * 330 * @par Description: 331 * Returns the next free buffer available and sets the corresponding status 332 * to DEC 333 * 334 * @param[in] ps_buf_mgr 335 * Pointer to the buffer manager 336 * 337 * @param[in] pi4_buf_id 338 * Pointer to the id of the free buffer 339 * 340 * @returns Pointer to the free buffer 341 * 342 * @remarks 343 * None 344 * 345 ******************************************************************************* 346 */ 347 void* ih264_buf_mgr_get_next_free(buf_mgr_t *ps_buf_mgr, WORD32 *pi4_buf_id) 348 { 349 WORD32 id; 350 void *pv_ret_ptr; 351 IH264_ERROR_T ret = IH264_SUCCESS; 352 ret = ih264_buf_mgr_lock(ps_buf_mgr); 353 RETURN_IF((ret != IH264_SUCCESS), NULL); 354 355 pv_ret_ptr = NULL; 356 for(id = 0; id < ps_buf_mgr->i4_active_buf_cnt; id++) 357 { 358 /* Check if the buffer is non-null and status is zero */ 359 if((ps_buf_mgr->au4_status[id] == 0) && (ps_buf_mgr->apv_ptr[id])) 360 { 361 *pi4_buf_id = id; 362 /* DEC is set to 1 */ 363 ps_buf_mgr->au4_status[id] = 1; 364 pv_ret_ptr = ps_buf_mgr->apv_ptr[id]; 365 break; 366 } 367 } 368 ret = ih264_buf_mgr_unlock(ps_buf_mgr); 369 RETURN_IF((ret != IH264_SUCCESS), NULL); 370 371 return pv_ret_ptr; 372 } 373 374 375 /** 376 ******************************************************************************* 377 * 378 * @brief 379 * Checks the buffer manager for free buffers available. 380 * 381 * @par Description: 382 * Checks if there are any free buffers available 383 * 384 * @param[in] ps_buf_mgr 385 * Pointer to the buffer manager 386 * 387 * @returns Returns 0 if available, -1 otherwise 388 * 389 * @remarks 390 * None 391 * 392 ******************************************************************************* 393 */ 394 IH264_ERROR_T ih264_buf_mgr_check_free(buf_mgr_t *ps_buf_mgr) 395 { 396 WORD32 id; 397 IH264_ERROR_T ret = IH264_SUCCESS; 398 IH264_ERROR_T rettmp = IH264_SUCCESS; 399 rettmp = ih264_buf_mgr_lock(ps_buf_mgr); 400 RETURN_IF((rettmp != IH264_SUCCESS), ret); 401 402 ret = IH264_FAIL; 403 for(id = 0; id < ps_buf_mgr->i4_active_buf_cnt; id++) 404 { 405 if((ps_buf_mgr->au4_status[id] == 0) && 406 (ps_buf_mgr->apv_ptr[id])) 407 { 408 ret = IH264_SUCCESS; 409 break; 410 } 411 } 412 rettmp = ih264_buf_mgr_unlock(ps_buf_mgr); 413 RETURN_IF((rettmp != IH264_SUCCESS), ret); 414 415 return ret; 416 417 } 418 419 420 /** 421 ******************************************************************************* 422 * 423 * @brief 424 * Resets the status bits. 425 * 426 * @par Description: 427 * resets the status bits that the mask contains (status corresponding to 428 * the id) 429 * 430 * @param[in] ps_buf_mgr 431 * Pointer to the buffer manager 432 * 433 * @param[in] buf_id 434 * ID of the buffer status to be released 435 * 436 * @param[in] mask 437 * Contains the bits that are to be reset 438 * 439 * @returns 0 if success, -1 otherwise 440 * 441 * @remarks 442 * None 443 * 444 ******************************************************************************* 445 */ 446 IH264_ERROR_T ih264_buf_mgr_release(buf_mgr_t *ps_buf_mgr, 447 WORD32 buf_id, 448 UWORD32 mask) 449 { 450 IH264_ERROR_T ret = IH264_SUCCESS; 451 ret = ih264_buf_mgr_lock(ps_buf_mgr); 452 RETURN_IF((ret != IH264_SUCCESS), ret); 453 454 455 /* If the given id is pointing to an id which is not yet added */ 456 if(buf_id >= ps_buf_mgr->i4_active_buf_cnt) 457 { 458 ret = ih264_buf_mgr_unlock(ps_buf_mgr); 459 RETURN_IF((ret != IH264_SUCCESS), ret); 460 return IH264_FAIL; 461 } 462 463 ps_buf_mgr->au4_status[buf_id] &= ~mask; 464 465 466 /* If both the REF and DISP are zero, DEC is set to zero */ 467 if(ps_buf_mgr->au4_status[buf_id] == 1) 468 { 469 ps_buf_mgr->au4_status[buf_id] = 0; 470 } 471 472 473 ret = ih264_buf_mgr_unlock(ps_buf_mgr); 474 RETURN_IF((ret != IH264_SUCCESS), ret); 475 476 return ret; 477 } 478 479 480 /** 481 ******************************************************************************* 482 * 483 * @brief 484 * Sets the status bit. 485 * 486 * @par Description: 487 * sets the status bits that the mask contains (status corresponding to the 488 * id) 489 * 490 * 491 * @param[in] ps_buf_mgr 492 * Pointer to the buffer manager 493 * 494 * @param[in] buf_id 495 * ID of the buffer whose status needs to be modified 496 * 497 * 498 * @param[in] mask 499 * Contains the bits that are to be set 500 * 501 * @returns 0 if success, -1 otherwise 502 * 503 * @remarks 504 * None 505 * 506 ******************************************************************************* 507 */ 508 IH264_ERROR_T ih264_buf_mgr_set_status(buf_mgr_t *ps_buf_mgr, 509 WORD32 buf_id, 510 UWORD32 mask) 511 { 512 IH264_ERROR_T ret = IH264_SUCCESS; 513 ret = ih264_buf_mgr_lock(ps_buf_mgr); 514 RETURN_IF((ret != IH264_SUCCESS), ret); 515 516 if(buf_id >= ps_buf_mgr->i4_active_buf_cnt) 517 { 518 ret = ih264_buf_mgr_unlock(ps_buf_mgr); 519 RETURN_IF((ret != IH264_SUCCESS), ret); 520 return IH264_FAIL; 521 } 522 523 524 if((ps_buf_mgr->au4_status[buf_id] & mask) != 0) 525 { 526 ret = ih264_buf_mgr_unlock(ps_buf_mgr); 527 RETURN_IF((ret != IH264_SUCCESS), ret); 528 return IH264_FAIL; 529 } 530 531 ps_buf_mgr->au4_status[buf_id] |= mask; 532 ret = ih264_buf_mgr_unlock(ps_buf_mgr); 533 RETURN_IF((ret != IH264_SUCCESS), ret); 534 535 return ret; 536 } 537 538 539 /** 540 ******************************************************************************* 541 * 542 * @brief 543 * Returns the status of the buffer. 544 * 545 * @par Description: 546 * Returns the status of the buffer corresponding to the id 547 * 548 * @param[in] ps_buf_mgr 549 * Pointer to the buffer manager 550 * 551 * @param[in] buf_id 552 * ID of the buffer status required 553 * 554 * @returns Status of the buffer corresponding to the id 555 * 556 * @remarks 557 * None 558 * 559 ******************************************************************************* 560 */ 561 WORD32 ih264_buf_mgr_get_status( buf_mgr_t *ps_buf_mgr, WORD32 buf_id ) 562 { 563 IH264_ERROR_T ret = IH264_SUCCESS; 564 UWORD32 status; 565 566 ret = ih264_buf_mgr_lock(ps_buf_mgr); 567 RETURN_IF((ret != IH264_SUCCESS), ret); 568 569 status = ps_buf_mgr->au4_status[buf_id]; 570 571 ret = ih264_buf_mgr_unlock(ps_buf_mgr); 572 RETURN_IF((ret != IH264_SUCCESS), ret); 573 574 return status; 575 } 576 577 578 /** 579 ******************************************************************************* 580 * 581 * @brief 582 * Gets the buffer from the buffer manager 583 * 584 * @par Description: 585 * Returns the pointer to the buffer corresponding to the id 586 * 587 * @param[in] ps_buf_mgr 588 * Pointer to the buffer manager 589 * 590 * @param[in] buf_id 591 * ID of the buffer required 592 * 593 * @returns Pointer to the buffer required 594 * 595 * @remarks 596 * None 597 * 598 ******************************************************************************* 599 */ 600 void* ih264_buf_mgr_get_buf(buf_mgr_t *ps_buf_mgr, WORD32 buf_id) 601 { 602 IH264_ERROR_T ret = IH264_SUCCESS; 603 void *pv_buf; 604 ret = ih264_buf_mgr_lock(ps_buf_mgr); 605 RETURN_IF((ret != IH264_SUCCESS), NULL); 606 607 pv_buf = ps_buf_mgr->apv_ptr[buf_id]; 608 609 ret = ih264_buf_mgr_unlock(ps_buf_mgr); 610 RETURN_IF((ret != IH264_SUCCESS), NULL); 611 612 return pv_buf; 613 } 614 615 616 /** 617 ******************************************************************************* 618 * 619 * @brief 620 * Gets the buffer id from the buffer manager if the buffer is added to the 621 * buffer manager 622 * 623 * @par Description: 624 * Returns the buffer id corresponding to the given buffer if it exists 625 * 626 * @param[in] ps_buf_mgr 627 * Pointer to the buffer manager 628 * 629 * @param[in] pv_buf 630 * Pointer to the buffer 631 * 632 * @returns Buffer id if exists, else -1 633 * 634 * @remarks 635 * None 636 * 637 ******************************************************************************* 638 */ 639 WORD32 ih264_buf_mgr_get_bufid(buf_mgr_t *ps_buf_mgr, void *pv_buf) 640 { 641 WORD32 id; 642 WORD32 buf_id = -1; 643 IH264_ERROR_T ret = IH264_SUCCESS; 644 ret = ih264_buf_mgr_lock(ps_buf_mgr); 645 RETURN_IF((ret != IH264_SUCCESS), ret); 646 647 for(id = 0; id < ps_buf_mgr->i4_active_buf_cnt; id++) 648 { 649 if(ps_buf_mgr->apv_ptr[id] == pv_buf) 650 { 651 buf_id = id; 652 break; 653 } 654 } 655 ret = ih264_buf_mgr_unlock(ps_buf_mgr); 656 RETURN_IF((ret != IH264_SUCCESS), ret); 657 658 return buf_id; 659 } 660 661 662 /** 663 ******************************************************************************* 664 * 665 * @brief 666 * Gets the no.of active buffer 667 * 668 * @par Description: 669 * Return the number of active buffers in the buffer manager 670 * 671 * @param[in] ps_buf_mgr 672 * Pointer to the buffer manager 673 * 674 * @returns number of active buffers 675 * 676 * @remarks 677 * None 678 * 679 ******************************************************************************* 680 */ 681 UWORD32 ih264_buf_mgr_get_num_active_buf(buf_mgr_t *ps_buf_mgr) 682 { 683 UWORD32 u4_buf_cnt; 684 IH264_ERROR_T ret = IH264_SUCCESS; 685 686 u4_buf_cnt = 0; 687 688 ret = ih264_buf_mgr_lock(ps_buf_mgr); 689 RETURN_IF((ret != IH264_SUCCESS), ret); 690 u4_buf_cnt = ps_buf_mgr->i4_active_buf_cnt; 691 692 ret = ih264_buf_mgr_unlock(ps_buf_mgr); 693 RETURN_IF((ret != IH264_SUCCESS), ret); 694 695 return u4_buf_cnt; 696 } 697