1 /* 2 * 3 * Copyright 2010 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 SEC_OMX_Resourcemanager.c 20 * @brief 21 * @author SeungBeom Kim (sbcrux.kim (at) samsung.com) 22 * @version 1.0 23 * @history 24 * 2010.7.15 : Create 25 */ 26 27 #include <stdio.h> 28 #include <stdlib.h> 29 #include <string.h> 30 31 #include "SEC_OMX_Resourcemanager.h" 32 #include "SEC_OMX_Basecomponent.h" 33 34 #undef SEC_LOG_TAG 35 #define SEC_LOG_TAG "SEC_RM" 36 #define SEC_LOG_OFF 37 #include "SEC_OSAL_Log.h" 38 39 40 #define MAX_RESOURCE_VIDEO 4 41 42 /* Max allowable video scheduler component instance */ 43 static SEC_OMX_RM_COMPONENT_LIST *gpVideoRMComponentList = NULL; 44 static SEC_OMX_RM_COMPONENT_LIST *gpVideoRMWaitingList = NULL; 45 static OMX_HANDLETYPE ghVideoRMComponentListMutex = NULL; 46 47 48 OMX_ERRORTYPE addElementList(SEC_OMX_RM_COMPONENT_LIST **ppList, OMX_COMPONENTTYPE *pOMXComponent) 49 { 50 OMX_ERRORTYPE ret = OMX_ErrorNone; 51 SEC_OMX_RM_COMPONENT_LIST *pTempComp = NULL; 52 SEC_OMX_BASECOMPONENT *pSECComponent = NULL; 53 54 pSECComponent = (SEC_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; 55 if (*ppList != NULL) { 56 pTempComp = *ppList; 57 while (pTempComp->pNext != NULL) { 58 pTempComp = pTempComp->pNext; 59 } 60 pTempComp->pNext = (SEC_OMX_RM_COMPONENT_LIST *)SEC_OSAL_Malloc(sizeof(SEC_OMX_RM_COMPONENT_LIST)); 61 if (pTempComp->pNext == NULL) { 62 ret = OMX_ErrorInsufficientResources; 63 goto EXIT; 64 } 65 ((SEC_OMX_RM_COMPONENT_LIST *)(pTempComp->pNext))->pNext = NULL; 66 ((SEC_OMX_RM_COMPONENT_LIST *)(pTempComp->pNext))->pOMXStandComp = pOMXComponent; 67 ((SEC_OMX_RM_COMPONENT_LIST *)(pTempComp->pNext))->groupPriority = pSECComponent->compPriority.nGroupPriority; 68 goto EXIT; 69 } else { 70 *ppList = (SEC_OMX_RM_COMPONENT_LIST *)SEC_OSAL_Malloc(sizeof(SEC_OMX_RM_COMPONENT_LIST)); 71 if (*ppList == NULL) { 72 ret = OMX_ErrorInsufficientResources; 73 goto EXIT; 74 } 75 pTempComp = *ppList; 76 pTempComp->pNext = NULL; 77 pTempComp->pOMXStandComp = pOMXComponent; 78 pTempComp->groupPriority = pSECComponent->compPriority.nGroupPriority; 79 } 80 81 EXIT: 82 return ret; 83 } 84 85 OMX_ERRORTYPE removeElementList(SEC_OMX_RM_COMPONENT_LIST **ppList, OMX_COMPONENTTYPE *pOMXComponent) 86 { 87 OMX_ERRORTYPE ret = OMX_ErrorNone; 88 SEC_OMX_RM_COMPONENT_LIST *pCurrComp = NULL; 89 SEC_OMX_RM_COMPONENT_LIST *pPrevComp = NULL; 90 OMX_BOOL bDetectComp = OMX_FALSE; 91 92 if (*ppList == NULL) { 93 ret = OMX_ErrorUndefined; 94 goto EXIT; 95 } 96 97 pCurrComp = *ppList; 98 while (pCurrComp != NULL) { 99 if (pCurrComp->pOMXStandComp == pOMXComponent) { 100 if (*ppList == pCurrComp) { 101 *ppList = pCurrComp->pNext; 102 SEC_OSAL_Free(pCurrComp); 103 } else { 104 pPrevComp->pNext = pCurrComp->pNext; 105 SEC_OSAL_Free(pCurrComp); 106 } 107 bDetectComp = OMX_TRUE; 108 break; 109 } else { 110 pPrevComp = pCurrComp; 111 pCurrComp = pCurrComp->pNext; 112 } 113 } 114 115 if (bDetectComp == OMX_FALSE) 116 ret = OMX_ErrorComponentNotFound; 117 else 118 ret = OMX_ErrorNone; 119 120 EXIT: 121 return ret; 122 } 123 124 int searchLowPriority(SEC_OMX_RM_COMPONENT_LIST *RMComp_list, int inComp_priority, SEC_OMX_RM_COMPONENT_LIST **outLowComp) 125 { 126 int ret = 0; 127 SEC_OMX_RM_COMPONENT_LIST *pTempComp = NULL; 128 SEC_OMX_RM_COMPONENT_LIST *pCandidateComp = NULL; 129 130 if (RMComp_list == NULL) 131 ret = -1; 132 133 pTempComp = RMComp_list; 134 *outLowComp = 0; 135 136 while (pTempComp != NULL) { 137 if (pTempComp->groupPriority > inComp_priority) { 138 if (pCandidateComp != NULL) { 139 if (pCandidateComp->groupPriority < pTempComp->groupPriority) 140 pCandidateComp = pTempComp; 141 } else { 142 pCandidateComp = pTempComp; 143 } 144 } 145 146 pTempComp = pTempComp->pNext; 147 } 148 149 *outLowComp = pCandidateComp; 150 if (pCandidateComp == NULL) 151 ret = 0; 152 else 153 ret = 1; 154 155 EXIT: 156 return ret; 157 } 158 159 OMX_ERRORTYPE removeComponent(OMX_COMPONENTTYPE *pOMXComponent) 160 { 161 OMX_ERRORTYPE ret = OMX_ErrorNone; 162 SEC_OMX_BASECOMPONENT *pSECComponent = NULL; 163 164 pSECComponent = (SEC_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; 165 if (pSECComponent->currentState == OMX_StateIdle) { 166 (*(pSECComponent->pCallbacks->EventHandler)) 167 (pOMXComponent, pSECComponent->callbackData, 168 OMX_EventError, OMX_ErrorResourcesLost, 0, NULL); 169 ret = OMX_SendCommand(pOMXComponent, OMX_CommandStateSet, OMX_StateLoaded, NULL); 170 if (ret != OMX_ErrorNone) { 171 ret = OMX_ErrorUndefined; 172 goto EXIT; 173 } 174 } else if ((pSECComponent->currentState == OMX_StateExecuting) || (pSECComponent->currentState == OMX_StatePause)) { 175 /* Todo */ 176 } 177 178 ret = OMX_ErrorNone; 179 180 EXIT: 181 return ret; 182 } 183 184 185 OMX_ERRORTYPE SEC_OMX_ResourceManager_Init() 186 { 187 FunctionIn(); 188 SEC_OSAL_MutexCreate(&ghVideoRMComponentListMutex); 189 FunctionOut(); 190 return OMX_ErrorNone; 191 } 192 193 OMX_ERRORTYPE SEC_OMX_ResourceManager_Deinit() 194 { 195 OMX_ERRORTYPE ret = OMX_ErrorNone; 196 SEC_OMX_RM_COMPONENT_LIST *pCurrComponent; 197 SEC_OMX_RM_COMPONENT_LIST *pNextComponent; 198 199 FunctionIn(); 200 201 SEC_OSAL_MutexLock(ghVideoRMComponentListMutex); 202 203 if (gpVideoRMComponentList) { 204 pCurrComponent = gpVideoRMComponentList; 205 while (pCurrComponent != NULL) { 206 pNextComponent = pCurrComponent->pNext; 207 SEC_OSAL_Free(pCurrComponent); 208 pCurrComponent = pNextComponent; 209 } 210 gpVideoRMComponentList = NULL; 211 } 212 213 if (gpVideoRMWaitingList) { 214 pCurrComponent = gpVideoRMWaitingList; 215 while (pCurrComponent != NULL) { 216 pNextComponent = pCurrComponent->pNext; 217 SEC_OSAL_Free(pCurrComponent); 218 pCurrComponent = pNextComponent; 219 } 220 gpVideoRMWaitingList = NULL; 221 } 222 SEC_OSAL_MutexUnlock(ghVideoRMComponentListMutex); 223 224 SEC_OSAL_MutexTerminate(ghVideoRMComponentListMutex); 225 ghVideoRMComponentListMutex = NULL; 226 227 ret = OMX_ErrorNone; 228 EXIT: 229 FunctionOut(); 230 231 return ret; 232 } 233 234 OMX_ERRORTYPE SEC_OMX_Get_Resource(OMX_COMPONENTTYPE *pOMXComponent) 235 { 236 OMX_ERRORTYPE ret = OMX_ErrorNone; 237 SEC_OMX_BASECOMPONENT *pSECComponent = NULL; 238 SEC_OMX_RM_COMPONENT_LIST *pComponentTemp = NULL; 239 SEC_OMX_RM_COMPONENT_LIST *pComponentCandidate = NULL; 240 int numElem = 0; 241 int lowCompDetect = 0; 242 243 FunctionIn(); 244 245 SEC_OSAL_MutexLock(ghVideoRMComponentListMutex); 246 247 pSECComponent = (SEC_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; 248 pComponentTemp = gpVideoRMComponentList; 249 if (pSECComponent->codecType == HW_VIDEO_CODEC) { 250 if (pComponentTemp != NULL) { 251 while (pComponentTemp) { 252 numElem++; 253 pComponentTemp = pComponentTemp->pNext; 254 } 255 } else { 256 numElem = 0; 257 } 258 if (numElem >= MAX_RESOURCE_VIDEO) { 259 lowCompDetect = searchLowPriority(gpVideoRMComponentList, pSECComponent->compPriority.nGroupPriority, &pComponentCandidate); 260 if (lowCompDetect <= 0) { 261 ret = OMX_ErrorInsufficientResources; 262 goto EXIT; 263 } else { 264 ret = removeComponent(pComponentCandidate->pOMXStandComp); 265 if (ret != OMX_ErrorNone) { 266 ret = OMX_ErrorInsufficientResources; 267 goto EXIT; 268 } else { 269 ret = removeElementList(&gpVideoRMComponentList, pComponentCandidate->pOMXStandComp); 270 ret = addElementList(&gpVideoRMComponentList, pOMXComponent); 271 if (ret != OMX_ErrorNone) { 272 ret = OMX_ErrorInsufficientResources; 273 goto EXIT; 274 } 275 } 276 } 277 } else { 278 ret = addElementList(&gpVideoRMComponentList, pOMXComponent); 279 if (ret != OMX_ErrorNone) { 280 ret = OMX_ErrorInsufficientResources; 281 goto EXIT; 282 } 283 } 284 } 285 ret = OMX_ErrorNone; 286 287 EXIT: 288 289 SEC_OSAL_MutexUnlock(ghVideoRMComponentListMutex); 290 291 FunctionOut(); 292 293 return ret; 294 } 295 296 OMX_ERRORTYPE SEC_OMX_Release_Resource(OMX_COMPONENTTYPE *pOMXComponent) 297 { 298 OMX_ERRORTYPE ret = OMX_ErrorNone; 299 SEC_OMX_BASECOMPONENT *pSECComponent = NULL; 300 SEC_OMX_RM_COMPONENT_LIST *pComponentTemp = NULL; 301 OMX_COMPONENTTYPE *pOMXWaitComponent = NULL; 302 int numElem = 0; 303 304 FunctionIn(); 305 306 SEC_OSAL_MutexLock(ghVideoRMComponentListMutex); 307 308 pSECComponent = (SEC_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; 309 pComponentTemp = gpVideoRMWaitingList; 310 if (pSECComponent->codecType == HW_VIDEO_CODEC) { 311 if (gpVideoRMComponentList == NULL) { 312 ret = OMX_ErrorUndefined; 313 goto EXIT; 314 } 315 316 ret = removeElementList(&gpVideoRMComponentList, pOMXComponent); 317 if (ret != OMX_ErrorNone) { 318 ret = OMX_ErrorUndefined; 319 goto EXIT; 320 } 321 while (pComponentTemp) { 322 numElem++; 323 pComponentTemp = pComponentTemp->pNext; 324 } 325 if (numElem > 0) { 326 pOMXWaitComponent = gpVideoRMWaitingList->pOMXStandComp; 327 removeElementList(&gpVideoRMWaitingList, pOMXWaitComponent); 328 ret = OMX_SendCommand(pOMXWaitComponent, OMX_CommandStateSet, OMX_StateIdle, NULL); 329 if (ret != OMX_ErrorNone) { 330 goto EXIT; 331 } 332 } 333 } 334 335 EXIT: 336 337 SEC_OSAL_MutexUnlock(ghVideoRMComponentListMutex); 338 339 FunctionOut(); 340 341 return ret; 342 } 343 344 OMX_ERRORTYPE SEC_OMX_In_WaitForResource(OMX_COMPONENTTYPE *pOMXComponent) 345 { 346 OMX_ERRORTYPE ret = OMX_ErrorNone; 347 SEC_OMX_BASECOMPONENT *pSECComponent = NULL; 348 349 FunctionIn(); 350 351 SEC_OSAL_MutexLock(ghVideoRMComponentListMutex); 352 353 pSECComponent = (SEC_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; 354 if (pSECComponent->codecType == HW_VIDEO_CODEC) 355 ret = addElementList(&gpVideoRMWaitingList, pOMXComponent); 356 357 SEC_OSAL_MutexUnlock(ghVideoRMComponentListMutex); 358 359 FunctionOut(); 360 361 return ret; 362 } 363 364 OMX_ERRORTYPE SEC_OMX_Out_WaitForResource(OMX_COMPONENTTYPE *pOMXComponent) 365 { 366 OMX_ERRORTYPE ret = OMX_ErrorNone; 367 SEC_OMX_BASECOMPONENT *pSECComponent = NULL; 368 369 FunctionIn(); 370 371 SEC_OSAL_MutexLock(ghVideoRMComponentListMutex); 372 373 pSECComponent = (SEC_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate; 374 if (pSECComponent->codecType == HW_VIDEO_CODEC) 375 ret = removeElementList(&gpVideoRMWaitingList, pOMXComponent); 376 377 SEC_OSAL_MutexUnlock(ghVideoRMComponentListMutex); 378 379 FunctionOut(); 380 381 return ret; 382 } 383 384