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*/ 79WORD32 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*/ 107IH264_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 137IH264_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*/ 170IH264_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*/ 206IH264_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 237void *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*/ 288IH264_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*/ 347void* 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*/ 394IH264_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*/ 446IH264_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*/ 508IH264_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*/ 561WORD32 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*/ 600void* 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*/ 639WORD32 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*/ 681UWORD32 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