3 * Copyright 2012 Samsung Electronics S.LSI Co. LTD
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
9 * http://www.apache.org/licenses/LICENSE-2.0
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.
19 * @file Exynos_OMX_Resourcemanager.c
21 * @author SeungBeom Kim (sbcrux.kim@samsung.com)
31 #include "Exynos_OMX_Resourcemanager.h"
32 #include "Exynos_OMX_Basecomponent.h"
33 #include "Exynos_OSAL_Memory.h"
34 #include "Exynos_OSAL_Mutex.h"
37 #define EXYNOS_LOG_TAG "EXYNOS_RM"
38 #define EXYNOS_LOG_OFF
39 #include "Exynos_OSAL_Log.h"
41 #ifdef TIZEN_FEATURE_E3250
42 #define MAX_RESOURCE_VIDEO_DEC 8 /* for TIZEN */
43 #define MAX_RESOURCE_VIDEO_ENC 2 /* for TIZEN */
45 #define MAX_RESOURCE_VIDEO_DEC 3 /* for Android */
46 #define MAX_RESOURCE_VIDEO_ENC 1 /* for Android */
49 /* Max allowable video scheduler component instance */
50 static EXYNOS_OMX_RM_COMPONENT_LIST *gpVideoDecRMComponentList = NULL;
51 static EXYNOS_OMX_RM_COMPONENT_LIST *gpVideoDecRMWaitingList = NULL;
52 static EXYNOS_OMX_RM_COMPONENT_LIST *gpVideoEncRMComponentList = NULL;
53 static EXYNOS_OMX_RM_COMPONENT_LIST *gpVideoEncRMWaitingList = NULL;
54 static OMX_HANDLETYPE ghVideoRMComponentListMutex = NULL;
57 OMX_ERRORTYPE addElementList(EXYNOS_OMX_RM_COMPONENT_LIST **ppList, OMX_COMPONENTTYPE *pOMXComponent)
59 OMX_ERRORTYPE ret = OMX_ErrorNone;
60 EXYNOS_OMX_RM_COMPONENT_LIST *pTempComp = NULL;
61 EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL;
63 pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate;
64 if (*ppList != NULL) {
66 while (pTempComp->pNext != NULL) {
67 pTempComp = pTempComp->pNext;
69 pTempComp->pNext = (EXYNOS_OMX_RM_COMPONENT_LIST *)Exynos_OSAL_Malloc(sizeof(EXYNOS_OMX_RM_COMPONENT_LIST));
70 if (pTempComp->pNext == NULL) {
71 ret = OMX_ErrorInsufficientResources;
74 ((EXYNOS_OMX_RM_COMPONENT_LIST *)(pTempComp->pNext))->pNext = NULL;
75 ((EXYNOS_OMX_RM_COMPONENT_LIST *)(pTempComp->pNext))->pOMXStandComp = pOMXComponent;
76 ((EXYNOS_OMX_RM_COMPONENT_LIST *)(pTempComp->pNext))->groupPriority = pExynosComponent->compPriority.nGroupPriority;
79 *ppList = (EXYNOS_OMX_RM_COMPONENT_LIST *)Exynos_OSAL_Malloc(sizeof(EXYNOS_OMX_RM_COMPONENT_LIST));
80 if (*ppList == NULL) {
81 ret = OMX_ErrorInsufficientResources;
85 pTempComp->pNext = NULL;
86 pTempComp->pOMXStandComp = pOMXComponent;
87 pTempComp->groupPriority = pExynosComponent->compPriority.nGroupPriority;
94 OMX_ERRORTYPE removeElementList(EXYNOS_OMX_RM_COMPONENT_LIST **ppList, OMX_COMPONENTTYPE *pOMXComponent)
96 OMX_ERRORTYPE ret = OMX_ErrorNone;
97 EXYNOS_OMX_RM_COMPONENT_LIST *pCurrComp = NULL;
98 EXYNOS_OMX_RM_COMPONENT_LIST *pPrevComp = NULL;
99 OMX_BOOL bDetectComp = OMX_FALSE;
101 if (*ppList == NULL) {
102 ret = OMX_ErrorUndefined;
107 while (pCurrComp != NULL) {
108 if (pCurrComp->pOMXStandComp == pOMXComponent) {
109 if (*ppList == pCurrComp) {
110 *ppList = pCurrComp->pNext;
111 Exynos_OSAL_Free(pCurrComp);
113 if (pPrevComp != NULL)
114 pPrevComp->pNext = pCurrComp->pNext;
116 Exynos_OSAL_Free(pCurrComp);
118 bDetectComp = OMX_TRUE;
121 pPrevComp = pCurrComp;
122 pCurrComp = pCurrComp->pNext;
126 if (bDetectComp == OMX_FALSE)
127 ret = OMX_ErrorComponentNotFound;
135 int searchLowPriority(EXYNOS_OMX_RM_COMPONENT_LIST *RMComp_list, OMX_U32 inComp_priority, EXYNOS_OMX_RM_COMPONENT_LIST **outLowComp)
138 EXYNOS_OMX_RM_COMPONENT_LIST *pTempComp = NULL;
139 EXYNOS_OMX_RM_COMPONENT_LIST *pCandidateComp = NULL;
141 if (RMComp_list == NULL)
144 pTempComp = RMComp_list;
147 while (pTempComp != NULL) {
148 if (pTempComp->groupPriority > inComp_priority) {
149 if (pCandidateComp != NULL) {
150 if (pCandidateComp->groupPriority < pTempComp->groupPriority)
151 pCandidateComp = pTempComp;
153 pCandidateComp = pTempComp;
157 pTempComp = pTempComp->pNext;
160 *outLowComp = pCandidateComp;
161 if (pCandidateComp == NULL)
169 OMX_ERRORTYPE removeComponent(OMX_COMPONENTTYPE *pOMXComponent)
171 OMX_ERRORTYPE ret = OMX_ErrorNone;
172 EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL;
174 pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate;
175 if (pExynosComponent->currentState == OMX_StateIdle) {
176 (*(pExynosComponent->pCallbacks->EventHandler))
177 (pOMXComponent, pExynosComponent->callbackData,
178 OMX_EventError, OMX_ErrorResourcesLost, 0, NULL);
179 ret = OMX_SendCommand(pOMXComponent, OMX_CommandStateSet, OMX_StateLoaded, NULL);
180 if (ret != OMX_ErrorNone) {
181 ret = OMX_ErrorUndefined;
184 } else if ((pExynosComponent->currentState == OMX_StateExecuting) || (pExynosComponent->currentState == OMX_StatePause)) {
195 OMX_ERRORTYPE Exynos_OMX_ResourceManager_Init()
197 OMX_ERRORTYPE ret = OMX_ErrorNone;
200 ret = Exynos_OSAL_MutexCreate(&ghVideoRMComponentListMutex);
206 OMX_ERRORTYPE Exynos_OMX_ResourceManager_Deinit()
208 OMX_ERRORTYPE ret = OMX_ErrorNone;
209 EXYNOS_OMX_RM_COMPONENT_LIST *pCurrComponent;
210 EXYNOS_OMX_RM_COMPONENT_LIST *pNextComponent;
214 Exynos_OSAL_MutexLock(ghVideoRMComponentListMutex);
216 if (gpVideoDecRMComponentList) {
217 pCurrComponent = gpVideoDecRMComponentList;
218 while (pCurrComponent != NULL) {
219 pNextComponent = pCurrComponent->pNext;
220 Exynos_OSAL_Free(pCurrComponent);
221 pCurrComponent = pNextComponent;
223 gpVideoDecRMComponentList = NULL;
225 if (gpVideoDecRMWaitingList) {
226 pCurrComponent = gpVideoDecRMWaitingList;
227 while (pCurrComponent != NULL) {
228 pNextComponent = pCurrComponent->pNext;
229 Exynos_OSAL_Free(pCurrComponent);
230 pCurrComponent = pNextComponent;
232 gpVideoDecRMWaitingList = NULL;
235 if (gpVideoEncRMComponentList) {
236 pCurrComponent = gpVideoEncRMComponentList;
237 while (pCurrComponent != NULL) {
238 pNextComponent = pCurrComponent->pNext;
239 Exynos_OSAL_Free(pCurrComponent);
240 pCurrComponent = pNextComponent;
242 gpVideoEncRMComponentList = NULL;
244 if (gpVideoEncRMWaitingList) {
245 pCurrComponent = gpVideoEncRMWaitingList;
246 while (pCurrComponent != NULL) {
247 pNextComponent = pCurrComponent->pNext;
248 Exynos_OSAL_Free(pCurrComponent);
249 pCurrComponent = pNextComponent;
251 gpVideoEncRMWaitingList = NULL;
254 Exynos_OSAL_MutexUnlock(ghVideoRMComponentListMutex);
256 Exynos_OSAL_MutexTerminate(ghVideoRMComponentListMutex);
257 ghVideoRMComponentListMutex = NULL;
266 OMX_ERRORTYPE Exynos_OMX_Get_Resource(OMX_COMPONENTTYPE *pOMXComponent)
268 OMX_ERRORTYPE ret = OMX_ErrorNone;
269 EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL;
270 EXYNOS_OMX_RM_COMPONENT_LIST *pComponentTemp = NULL;
271 EXYNOS_OMX_RM_COMPONENT_LIST *pComponentCandidate = NULL;
273 int lowCompDetect = 0;
277 Exynos_OSAL_MutexLock(ghVideoRMComponentListMutex);
279 pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate;
281 if (pExynosComponent->codecType == HW_VIDEO_DEC_CODEC) {
282 pComponentTemp = gpVideoDecRMComponentList;
283 if (pComponentTemp != NULL) {
284 while (pComponentTemp) {
286 pComponentTemp = pComponentTemp->pNext;
291 if (numElem >= MAX_RESOURCE_VIDEO_DEC) {
292 lowCompDetect = searchLowPriority(gpVideoDecRMComponentList, pExynosComponent->compPriority.nGroupPriority, &pComponentCandidate);
293 if (lowCompDetect <= 0) {
294 ret = OMX_ErrorInsufficientResources;
297 ret = removeComponent(pComponentCandidate->pOMXStandComp);
298 if (ret != OMX_ErrorNone) {
299 ret = OMX_ErrorInsufficientResources;
302 ret = removeElementList(&gpVideoDecRMComponentList, pComponentCandidate->pOMXStandComp);
303 ret = addElementList(&gpVideoDecRMComponentList, pOMXComponent);
304 if (ret != OMX_ErrorNone) {
305 ret = OMX_ErrorInsufficientResources;
311 ret = addElementList(&gpVideoDecRMComponentList, pOMXComponent);
312 if (ret != OMX_ErrorNone) {
313 ret = OMX_ErrorInsufficientResources;
317 } else if (pExynosComponent->codecType == HW_VIDEO_ENC_CODEC) {
318 pComponentTemp = gpVideoEncRMComponentList;
319 if (pComponentTemp != NULL) {
320 while (pComponentTemp) {
322 pComponentTemp = pComponentTemp->pNext;
327 if (numElem >= MAX_RESOURCE_VIDEO_ENC) {
328 lowCompDetect = searchLowPriority(gpVideoEncRMComponentList, pExynosComponent->compPriority.nGroupPriority, &pComponentCandidate);
329 if (lowCompDetect <= 0) {
330 ret = OMX_ErrorInsufficientResources;
333 ret = removeComponent(pComponentCandidate->pOMXStandComp);
334 if (ret != OMX_ErrorNone) {
335 ret = OMX_ErrorInsufficientResources;
338 ret = removeElementList(&gpVideoEncRMComponentList, pComponentCandidate->pOMXStandComp);
339 ret = addElementList(&gpVideoEncRMComponentList, pOMXComponent);
340 if (ret != OMX_ErrorNone) {
341 ret = OMX_ErrorInsufficientResources;
347 ret = addElementList(&gpVideoEncRMComponentList, pOMXComponent);
348 if (ret != OMX_ErrorNone) {
349 ret = OMX_ErrorInsufficientResources;
358 Exynos_OSAL_MutexUnlock(ghVideoRMComponentListMutex);
365 OMX_ERRORTYPE Exynos_OMX_Release_Resource(OMX_COMPONENTTYPE *pOMXComponent)
367 OMX_ERRORTYPE ret = OMX_ErrorNone;
368 EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL;
369 EXYNOS_OMX_RM_COMPONENT_LIST *pComponentTemp = NULL;
370 OMX_COMPONENTTYPE *pOMXWaitComponent = NULL;
375 Exynos_OSAL_MutexLock(ghVideoRMComponentListMutex);
377 pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate;
379 if (pExynosComponent->codecType == HW_VIDEO_DEC_CODEC) {
380 pComponentTemp = gpVideoDecRMWaitingList;
381 if (gpVideoDecRMComponentList == NULL) {
382 ret = OMX_ErrorUndefined;
386 ret = removeElementList(&gpVideoDecRMComponentList, pOMXComponent);
387 if (ret != OMX_ErrorNone) {
388 ret = OMX_ErrorUndefined;
391 while (pComponentTemp) {
393 pComponentTemp = pComponentTemp->pNext;
396 pOMXWaitComponent = gpVideoDecRMWaitingList->pOMXStandComp;
397 removeElementList(&gpVideoDecRMWaitingList, pOMXWaitComponent);
398 ret = OMX_SendCommand(pOMXWaitComponent, OMX_CommandStateSet, OMX_StateIdle, NULL);
399 if (ret != OMX_ErrorNone) {
403 } else if (pExynosComponent->codecType == HW_VIDEO_ENC_CODEC) {
404 pComponentTemp = gpVideoEncRMWaitingList;
405 if (gpVideoEncRMComponentList == NULL) {
406 ret = OMX_ErrorUndefined;
410 ret = removeElementList(&gpVideoEncRMComponentList, pOMXComponent);
411 if (ret != OMX_ErrorNone) {
412 ret = OMX_ErrorUndefined;
415 while (pComponentTemp) {
417 pComponentTemp = pComponentTemp->pNext;
420 pOMXWaitComponent = gpVideoEncRMWaitingList->pOMXStandComp;
421 removeElementList(&gpVideoEncRMWaitingList, pOMXWaitComponent);
422 ret = OMX_SendCommand(pOMXWaitComponent, OMX_CommandStateSet, OMX_StateIdle, NULL);
423 if (ret != OMX_ErrorNone) {
431 Exynos_OSAL_MutexUnlock(ghVideoRMComponentListMutex);
438 OMX_ERRORTYPE Exynos_OMX_In_WaitForResource(OMX_COMPONENTTYPE *pOMXComponent)
440 OMX_ERRORTYPE ret = OMX_ErrorNone;
441 EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL;
445 Exynos_OSAL_MutexLock(ghVideoRMComponentListMutex);
447 pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate;
448 if (pExynosComponent->codecType == HW_VIDEO_DEC_CODEC)
449 ret = addElementList(&gpVideoDecRMWaitingList, pOMXComponent);
450 else if (pExynosComponent->codecType == HW_VIDEO_ENC_CODEC)
451 ret = addElementList(&gpVideoEncRMWaitingList, pOMXComponent);
453 Exynos_OSAL_MutexUnlock(ghVideoRMComponentListMutex);
460 OMX_ERRORTYPE Exynos_OMX_Out_WaitForResource(OMX_COMPONENTTYPE *pOMXComponent)
462 OMX_ERRORTYPE ret = OMX_ErrorNone;
463 EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL;
467 Exynos_OSAL_MutexLock(ghVideoRMComponentListMutex);
469 pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate;
470 if (pExynosComponent->codecType == HW_VIDEO_DEC_CODEC)
471 ret = removeElementList(&gpVideoDecRMWaitingList, pOMXComponent);
472 else if (pExynosComponent->codecType == HW_VIDEO_ENC_CODEC)
473 ret = removeElementList(&gpVideoEncRMWaitingList, pOMXComponent);
475 Exynos_OSAL_MutexUnlock(ghVideoRMComponentListMutex);