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