Home | History | Annotate | Download | only in common
      1 /*
      2  *
      3  * Copyright 2012 Samsung Electronics S.LSI Co. LTD
      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  * @file       Exynos_OMX_Resourcemanager.c
     20  * @brief
     21  * @author     SeungBeom Kim (sbcrux.kim (at) samsung.com)
     22  * @version    2.0.0
     23  * @history
     24  *    2012.02.20 : Create
     25  */
     26 
     27 #include <stdio.h>
     28 #include <stdlib.h>
     29 #include <string.h>
     30 
     31 #include "Exynos_OMX_Resourcemanager.h"
     32 #include "Exynos_OMX_Basecomponent.h"
     33 #include "Exynos_OSAL_Memory.h"
     34 #include "Exynos_OSAL_Mutex.h"
     35 
     36 #undef  EXYNOS_LOG_TAG
     37 #define EXYNOS_LOG_TAG    "EXYNOS_RM"
     38 #define EXYNOS_LOG_OFF
     39 #include "Exynos_OSAL_Log.h"
     40 
     41 
     42 #define MAX_RESOURCE_VIDEO_DEC 3 /* for Android */
     43 #define MAX_RESOURCE_VIDEO_ENC 2 /* for Android */
     44 
     45 /* Max allowable video scheduler component instance */
     46 static EXYNOS_OMX_RM_COMPONENT_LIST *gpVideoDecRMComponentList = NULL;
     47 static EXYNOS_OMX_RM_COMPONENT_LIST *gpVideoDecRMWaitingList = NULL;
     48 static EXYNOS_OMX_RM_COMPONENT_LIST *gpVideoEncRMComponentList = NULL;
     49 static EXYNOS_OMX_RM_COMPONENT_LIST *gpVideoEncRMWaitingList = NULL;
     50 static OMX_HANDLETYPE ghVideoRMComponentListMutex = NULL;
     51 
     52 
     53 OMX_ERRORTYPE addElementList(EXYNOS_OMX_RM_COMPONENT_LIST **ppList, OMX_COMPONENTTYPE *pOMXComponent)
     54 {
     55     OMX_ERRORTYPE                 ret = OMX_ErrorNone;
     56     EXYNOS_OMX_RM_COMPONENT_LIST *pTempComp = NULL;
     57     EXYNOS_OMX_BASECOMPONENT     *pExynosComponent = NULL;
     58 
     59     pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate;
     60     if (*ppList != NULL) {
     61         pTempComp = *ppList;
     62         while (pTempComp->pNext != NULL) {
     63             pTempComp = pTempComp->pNext;
     64         }
     65         pTempComp->pNext = (EXYNOS_OMX_RM_COMPONENT_LIST *)Exynos_OSAL_Malloc(sizeof(EXYNOS_OMX_RM_COMPONENT_LIST));
     66         if (pTempComp->pNext == NULL) {
     67             ret = OMX_ErrorInsufficientResources;
     68             goto EXIT;
     69         }
     70         ((EXYNOS_OMX_RM_COMPONENT_LIST *)(pTempComp->pNext))->pNext = NULL;
     71         ((EXYNOS_OMX_RM_COMPONENT_LIST *)(pTempComp->pNext))->pOMXStandComp = pOMXComponent;
     72         ((EXYNOS_OMX_RM_COMPONENT_LIST *)(pTempComp->pNext))->groupPriority = pExynosComponent->compPriority.nGroupPriority;
     73         goto EXIT;
     74     } else {
     75         *ppList = (EXYNOS_OMX_RM_COMPONENT_LIST *)Exynos_OSAL_Malloc(sizeof(EXYNOS_OMX_RM_COMPONENT_LIST));
     76         if (*ppList == NULL) {
     77             ret = OMX_ErrorInsufficientResources;
     78             goto EXIT;
     79         }
     80         pTempComp = *ppList;
     81         pTempComp->pNext = NULL;
     82         pTempComp->pOMXStandComp = pOMXComponent;
     83         pTempComp->groupPriority = pExynosComponent->compPriority.nGroupPriority;
     84     }
     85 
     86 EXIT:
     87     return ret;
     88 }
     89 
     90 OMX_ERRORTYPE removeElementList(EXYNOS_OMX_RM_COMPONENT_LIST **ppList, OMX_COMPONENTTYPE *pOMXComponent)
     91 {
     92     OMX_ERRORTYPE                 ret = OMX_ErrorNone;
     93     EXYNOS_OMX_RM_COMPONENT_LIST *pCurrComp = NULL;
     94     EXYNOS_OMX_RM_COMPONENT_LIST *pPrevComp = NULL;
     95     OMX_BOOL                      bDetectComp = OMX_FALSE;
     96 
     97     if (*ppList == NULL) {
     98         ret = OMX_ErrorUndefined;
     99         goto EXIT;
    100     }
    101 
    102     pCurrComp = *ppList;
    103     while (pCurrComp != NULL) {
    104         if (pCurrComp->pOMXStandComp == pOMXComponent) {
    105             if (*ppList == pCurrComp) {
    106                 *ppList = pCurrComp->pNext;
    107                 Exynos_OSAL_Free(pCurrComp);
    108             } else {
    109                 if (pPrevComp != NULL)
    110                     pPrevComp->pNext = pCurrComp->pNext;
    111 
    112                 Exynos_OSAL_Free(pCurrComp);
    113             }
    114             bDetectComp = OMX_TRUE;
    115             break;
    116         } else {
    117             pPrevComp = pCurrComp;
    118             pCurrComp = pCurrComp->pNext;
    119         }
    120     }
    121 
    122     if (bDetectComp == OMX_FALSE)
    123         ret = OMX_ErrorComponentNotFound;
    124     else
    125         ret = OMX_ErrorNone;
    126 
    127 EXIT:
    128     return ret;
    129 }
    130 
    131 int searchLowPriority(EXYNOS_OMX_RM_COMPONENT_LIST *RMComp_list, OMX_U32 inComp_priority, EXYNOS_OMX_RM_COMPONENT_LIST **outLowComp)
    132 {
    133     int ret = 0;
    134     EXYNOS_OMX_RM_COMPONENT_LIST *pTempComp = NULL;
    135     EXYNOS_OMX_RM_COMPONENT_LIST *pCandidateComp = NULL;
    136 
    137     if (RMComp_list == NULL)
    138         ret = -1;
    139 
    140     pTempComp = RMComp_list;
    141     *outLowComp = 0;
    142 
    143     while (pTempComp != NULL) {
    144         if (pTempComp->groupPriority > inComp_priority) {
    145             if (pCandidateComp != NULL) {
    146                 if (pCandidateComp->groupPriority < pTempComp->groupPriority)
    147                     pCandidateComp = pTempComp;
    148             } else {
    149                 pCandidateComp = pTempComp;
    150             }
    151         }
    152 
    153         pTempComp = pTempComp->pNext;
    154     }
    155 
    156     *outLowComp = pCandidateComp;
    157     if (pCandidateComp == NULL)
    158         ret = 0;
    159     else
    160         ret = 1;
    161 
    162 EXIT:
    163     return ret;
    164 }
    165 
    166 OMX_ERRORTYPE removeComponent(OMX_COMPONENTTYPE *pOMXComponent)
    167 {
    168     OMX_ERRORTYPE             ret = OMX_ErrorNone;
    169     EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL;
    170 
    171     pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate;
    172     if (pExynosComponent->currentState == OMX_StateIdle) {
    173         (*(pExynosComponent->pCallbacks->EventHandler))
    174             (pOMXComponent, pExynosComponent->callbackData,
    175             OMX_EventError, OMX_ErrorResourcesLost, 0, NULL);
    176         ret = OMX_SendCommand(pOMXComponent, OMX_CommandStateSet, OMX_StateLoaded, NULL);
    177         if (ret != OMX_ErrorNone) {
    178             ret = OMX_ErrorUndefined;
    179             goto EXIT;
    180         }
    181     } else if ((pExynosComponent->currentState == OMX_StateExecuting) || (pExynosComponent->currentState == OMX_StatePause)) {
    182         /* Todo */
    183     }
    184 
    185     ret = OMX_ErrorNone;
    186 
    187 EXIT:
    188     return ret;
    189 }
    190 
    191 
    192 OMX_ERRORTYPE Exynos_OMX_ResourceManager_Init()
    193 {
    194     OMX_ERRORTYPE ret = OMX_ErrorNone;
    195 
    196     FunctionIn();
    197     ret = Exynos_OSAL_MutexCreate(&ghVideoRMComponentListMutex);
    198     FunctionOut();
    199 
    200     return ret;
    201 }
    202 
    203 OMX_ERRORTYPE Exynos_OMX_ResourceManager_Deinit()
    204 {
    205     OMX_ERRORTYPE ret = OMX_ErrorNone;
    206     EXYNOS_OMX_RM_COMPONENT_LIST *pCurrComponent;
    207     EXYNOS_OMX_RM_COMPONENT_LIST *pNextComponent;
    208 
    209     FunctionIn();
    210 
    211     Exynos_OSAL_MutexLock(ghVideoRMComponentListMutex);
    212 
    213     if (gpVideoDecRMComponentList) {
    214         pCurrComponent = gpVideoDecRMComponentList;
    215         while (pCurrComponent != NULL) {
    216             pNextComponent = pCurrComponent->pNext;
    217             Exynos_OSAL_Free(pCurrComponent);
    218             pCurrComponent = pNextComponent;
    219         }
    220         gpVideoDecRMComponentList = NULL;
    221     }
    222     if (gpVideoDecRMWaitingList) {
    223         pCurrComponent = gpVideoDecRMWaitingList;
    224         while (pCurrComponent != NULL) {
    225             pNextComponent = pCurrComponent->pNext;
    226             Exynos_OSAL_Free(pCurrComponent);
    227             pCurrComponent = pNextComponent;
    228         }
    229         gpVideoDecRMWaitingList = NULL;
    230     }
    231 
    232     if (gpVideoEncRMComponentList) {
    233         pCurrComponent = gpVideoEncRMComponentList;
    234         while (pCurrComponent != NULL) {
    235             pNextComponent = pCurrComponent->pNext;
    236             Exynos_OSAL_Free(pCurrComponent);
    237             pCurrComponent = pNextComponent;
    238         }
    239         gpVideoEncRMComponentList = NULL;
    240     }
    241     if (gpVideoEncRMWaitingList) {
    242         pCurrComponent = gpVideoEncRMWaitingList;
    243         while (pCurrComponent != NULL) {
    244             pNextComponent = pCurrComponent->pNext;
    245             Exynos_OSAL_Free(pCurrComponent);
    246             pCurrComponent = pNextComponent;
    247         }
    248         gpVideoEncRMWaitingList = NULL;
    249     }
    250 
    251     Exynos_OSAL_MutexUnlock(ghVideoRMComponentListMutex);
    252 
    253     Exynos_OSAL_MutexTerminate(ghVideoRMComponentListMutex);
    254     ghVideoRMComponentListMutex = NULL;
    255 
    256     ret = OMX_ErrorNone;
    257 EXIT:
    258     FunctionOut();
    259 
    260     return ret;
    261 }
    262 
    263 OMX_ERRORTYPE Exynos_OMX_Get_Resource(OMX_COMPONENTTYPE *pOMXComponent)
    264 {
    265     OMX_ERRORTYPE                 ret = OMX_ErrorNone;
    266     EXYNOS_OMX_BASECOMPONENT     *pExynosComponent = NULL;
    267     EXYNOS_OMX_RM_COMPONENT_LIST *pComponentTemp = NULL;
    268     EXYNOS_OMX_RM_COMPONENT_LIST *pComponentCandidate = NULL;
    269     int numElem = 0;
    270     int lowCompDetect = 0;
    271 
    272     FunctionIn();
    273 
    274     Exynos_OSAL_MutexLock(ghVideoRMComponentListMutex);
    275 
    276     pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate;
    277 
    278     if (pExynosComponent->codecType == HW_VIDEO_DEC_CODEC) {
    279         pComponentTemp = gpVideoDecRMComponentList;
    280         if (pComponentTemp != NULL) {
    281             while (pComponentTemp) {
    282                 numElem++;
    283                 pComponentTemp = pComponentTemp->pNext;
    284             }
    285         } else {
    286             numElem = 0;
    287         }
    288         if (numElem >= MAX_RESOURCE_VIDEO_DEC) {
    289             lowCompDetect = searchLowPriority(gpVideoDecRMComponentList, pExynosComponent->compPriority.nGroupPriority, &pComponentCandidate);
    290             if (lowCompDetect <= 0) {
    291                 ret = OMX_ErrorInsufficientResources;
    292                 goto EXIT;
    293             } else {
    294                 ret = removeComponent(pComponentCandidate->pOMXStandComp);
    295                 if (ret != OMX_ErrorNone) {
    296                     ret = OMX_ErrorInsufficientResources;
    297                     goto EXIT;
    298                 } else {
    299                     ret = removeElementList(&gpVideoDecRMComponentList, pComponentCandidate->pOMXStandComp);
    300                     ret = addElementList(&gpVideoDecRMComponentList, pOMXComponent);
    301                     if (ret != OMX_ErrorNone) {
    302                         ret = OMX_ErrorInsufficientResources;
    303                         goto EXIT;
    304                     }
    305                 }
    306             }
    307         } else {
    308             ret = addElementList(&gpVideoDecRMComponentList, pOMXComponent);
    309             if (ret != OMX_ErrorNone) {
    310                 ret = OMX_ErrorInsufficientResources;
    311                 goto EXIT;
    312             }
    313         }
    314     } else if (pExynosComponent->codecType == HW_VIDEO_ENC_CODEC) {
    315         pComponentTemp = gpVideoEncRMComponentList;
    316         if (pComponentTemp != NULL) {
    317             while (pComponentTemp) {
    318                 numElem++;
    319                 pComponentTemp = pComponentTemp->pNext;
    320             }
    321         } else {
    322             numElem = 0;
    323         }
    324         if (numElem >= MAX_RESOURCE_VIDEO_ENC) {
    325             lowCompDetect = searchLowPriority(gpVideoEncRMComponentList, pExynosComponent->compPriority.nGroupPriority, &pComponentCandidate);
    326             if (lowCompDetect <= 0) {
    327                 ret = OMX_ErrorInsufficientResources;
    328                 goto EXIT;
    329             } else {
    330                 ret = removeComponent(pComponentCandidate->pOMXStandComp);
    331                 if (ret != OMX_ErrorNone) {
    332                     ret = OMX_ErrorInsufficientResources;
    333                     goto EXIT;
    334                 } else {
    335                     ret = removeElementList(&gpVideoEncRMComponentList, pComponentCandidate->pOMXStandComp);
    336                     ret = addElementList(&gpVideoEncRMComponentList, pOMXComponent);
    337                     if (ret != OMX_ErrorNone) {
    338                         ret = OMX_ErrorInsufficientResources;
    339                         goto EXIT;
    340                     }
    341                 }
    342             }
    343         } else {
    344             ret = addElementList(&gpVideoEncRMComponentList, pOMXComponent);
    345             if (ret != OMX_ErrorNone) {
    346                 ret = OMX_ErrorInsufficientResources;
    347                 goto EXIT;
    348             }
    349         }
    350     }
    351     ret = OMX_ErrorNone;
    352 
    353 EXIT:
    354 
    355     Exynos_OSAL_MutexUnlock(ghVideoRMComponentListMutex);
    356 
    357     FunctionOut();
    358 
    359     return ret;
    360 }
    361 
    362 OMX_ERRORTYPE Exynos_OMX_Release_Resource(OMX_COMPONENTTYPE *pOMXComponent)
    363 {
    364     OMX_ERRORTYPE                 ret = OMX_ErrorNone;
    365     EXYNOS_OMX_BASECOMPONENT     *pExynosComponent = NULL;
    366     EXYNOS_OMX_RM_COMPONENT_LIST *pComponentTemp = NULL;
    367     OMX_COMPONENTTYPE            *pOMXWaitComponent = NULL;
    368     int numElem = 0;
    369 
    370     FunctionIn();
    371 
    372     Exynos_OSAL_MutexLock(ghVideoRMComponentListMutex);
    373 
    374     pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate;
    375 
    376     if (pExynosComponent->codecType == HW_VIDEO_DEC_CODEC) {
    377         pComponentTemp = gpVideoDecRMWaitingList;
    378         if (gpVideoDecRMComponentList == NULL) {
    379             ret = OMX_ErrorUndefined;
    380             goto EXIT;
    381         }
    382 
    383         ret = removeElementList(&gpVideoDecRMComponentList, pOMXComponent);
    384         if (ret != OMX_ErrorNone) {
    385             ret = OMX_ErrorUndefined;
    386             goto EXIT;
    387         }
    388         while (pComponentTemp) {
    389             numElem++;
    390             pComponentTemp = pComponentTemp->pNext;
    391         }
    392         if (numElem > 0) {
    393             pOMXWaitComponent = gpVideoDecRMWaitingList->pOMXStandComp;
    394             removeElementList(&gpVideoDecRMWaitingList, pOMXWaitComponent);
    395             ret = OMX_SendCommand(pOMXWaitComponent, OMX_CommandStateSet, OMX_StateIdle, NULL);
    396             if (ret != OMX_ErrorNone) {
    397                 goto EXIT;
    398             }
    399         }
    400     } else if (pExynosComponent->codecType == HW_VIDEO_ENC_CODEC) {
    401         pComponentTemp = gpVideoEncRMWaitingList;
    402         if (gpVideoEncRMComponentList == NULL) {
    403             ret = OMX_ErrorUndefined;
    404             goto EXIT;
    405         }
    406 
    407         ret = removeElementList(&gpVideoEncRMComponentList, pOMXComponent);
    408         if (ret != OMX_ErrorNone) {
    409             ret = OMX_ErrorUndefined;
    410             goto EXIT;
    411         }
    412         while (pComponentTemp) {
    413             numElem++;
    414             pComponentTemp = pComponentTemp->pNext;
    415         }
    416         if (numElem > 0) {
    417             pOMXWaitComponent = gpVideoEncRMWaitingList->pOMXStandComp;
    418             removeElementList(&gpVideoEncRMWaitingList, pOMXWaitComponent);
    419             ret = OMX_SendCommand(pOMXWaitComponent, OMX_CommandStateSet, OMX_StateIdle, NULL);
    420             if (ret != OMX_ErrorNone) {
    421                 goto EXIT;
    422             }
    423         }
    424     }
    425 
    426 EXIT:
    427 
    428     Exynos_OSAL_MutexUnlock(ghVideoRMComponentListMutex);
    429 
    430     FunctionOut();
    431 
    432     return ret;
    433 }
    434 
    435 OMX_ERRORTYPE Exynos_OMX_In_WaitForResource(OMX_COMPONENTTYPE *pOMXComponent)
    436 {
    437     OMX_ERRORTYPE             ret = OMX_ErrorNone;
    438     EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL;
    439 
    440     FunctionIn();
    441 
    442     Exynos_OSAL_MutexLock(ghVideoRMComponentListMutex);
    443 
    444     pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate;
    445     if (pExynosComponent->codecType == HW_VIDEO_DEC_CODEC)
    446         ret = addElementList(&gpVideoDecRMWaitingList, pOMXComponent);
    447     else if (pExynosComponent->codecType == HW_VIDEO_ENC_CODEC)
    448         ret = addElementList(&gpVideoEncRMWaitingList, pOMXComponent);
    449 
    450     Exynos_OSAL_MutexUnlock(ghVideoRMComponentListMutex);
    451 
    452     FunctionOut();
    453 
    454     return ret;
    455 }
    456 
    457 OMX_ERRORTYPE Exynos_OMX_Out_WaitForResource(OMX_COMPONENTTYPE *pOMXComponent)
    458 {
    459     OMX_ERRORTYPE             ret = OMX_ErrorNone;
    460     EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL;
    461 
    462     FunctionIn();
    463 
    464     Exynos_OSAL_MutexLock(ghVideoRMComponentListMutex);
    465 
    466     pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate;
    467     if (pExynosComponent->codecType == HW_VIDEO_DEC_CODEC)
    468         ret = removeElementList(&gpVideoDecRMWaitingList, pOMXComponent);
    469     else if (pExynosComponent->codecType == HW_VIDEO_ENC_CODEC)
    470         ret = removeElementList(&gpVideoEncRMWaitingList, pOMXComponent);
    471 
    472     Exynos_OSAL_MutexUnlock(ghVideoRMComponentListMutex);
    473 
    474     FunctionOut();
    475 
    476     return ret;
    477 }
    478 
    479