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"
42 #define MAX_RESOURCE_VIDEO_DEC 8 /* for SLP */
43 #define MAX_RESOURCE_VIDEO_ENC 2 /* for SLP */
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)
170 OMX_ERRORTYPE removeComponent(OMX_COMPONENTTYPE *pOMXComponent)
172 OMX_ERRORTYPE ret = OMX_ErrorNone;
173 EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL;
175 pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate;
176 if (pExynosComponent->currentState == OMX_StateIdle) {
177 (*(pExynosComponent->pCallbacks->EventHandler))
178 (pOMXComponent, pExynosComponent->callbackData,
179 OMX_EventError, OMX_ErrorResourcesLost, 0, NULL);
180 ret = OMX_SendCommand(pOMXComponent, OMX_CommandStateSet, OMX_StateLoaded, NULL);
181 if (ret != OMX_ErrorNone) {
182 ret = OMX_ErrorUndefined;
185 } else if ((pExynosComponent->currentState == OMX_StateExecuting) || (pExynosComponent->currentState == OMX_StatePause)) {
196 OMX_ERRORTYPE Exynos_OMX_ResourceManager_Init()
198 OMX_ERRORTYPE ret = OMX_ErrorNone;
201 ret = Exynos_OSAL_MutexCreate(&ghVideoRMComponentListMutex);
207 OMX_ERRORTYPE Exynos_OMX_ResourceManager_Deinit()
209 OMX_ERRORTYPE ret = OMX_ErrorNone;
210 EXYNOS_OMX_RM_COMPONENT_LIST *pCurrComponent;
211 EXYNOS_OMX_RM_COMPONENT_LIST *pNextComponent;
215 Exynos_OSAL_MutexLock(ghVideoRMComponentListMutex);
217 if (gpVideoDecRMComponentList) {
218 pCurrComponent = gpVideoDecRMComponentList;
219 while (pCurrComponent != NULL) {
220 pNextComponent = pCurrComponent->pNext;
221 Exynos_OSAL_Free(pCurrComponent);
222 pCurrComponent = pNextComponent;
224 gpVideoDecRMComponentList = NULL;
226 if (gpVideoDecRMWaitingList) {
227 pCurrComponent = gpVideoDecRMWaitingList;
228 while (pCurrComponent != NULL) {
229 pNextComponent = pCurrComponent->pNext;
230 Exynos_OSAL_Free(pCurrComponent);
231 pCurrComponent = pNextComponent;
233 gpVideoDecRMWaitingList = NULL;
236 if (gpVideoEncRMComponentList) {
237 pCurrComponent = gpVideoEncRMComponentList;
238 while (pCurrComponent != NULL) {
239 pNextComponent = pCurrComponent->pNext;
240 Exynos_OSAL_Free(pCurrComponent);
241 pCurrComponent = pNextComponent;
243 gpVideoEncRMComponentList = NULL;
245 if (gpVideoEncRMWaitingList) {
246 pCurrComponent = gpVideoEncRMWaitingList;
247 while (pCurrComponent != NULL) {
248 pNextComponent = pCurrComponent->pNext;
249 Exynos_OSAL_Free(pCurrComponent);
250 pCurrComponent = pNextComponent;
252 gpVideoEncRMWaitingList = NULL;
255 Exynos_OSAL_MutexUnlock(ghVideoRMComponentListMutex);
257 Exynos_OSAL_MutexTerminate(ghVideoRMComponentListMutex);
258 ghVideoRMComponentListMutex = NULL;
267 OMX_ERRORTYPE Exynos_OMX_Get_Resource(OMX_COMPONENTTYPE *pOMXComponent)
269 OMX_ERRORTYPE ret = OMX_ErrorNone;
270 EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL;
271 EXYNOS_OMX_RM_COMPONENT_LIST *pComponentTemp = NULL;
272 EXYNOS_OMX_RM_COMPONENT_LIST *pComponentCandidate = NULL;
274 int lowCompDetect = 0;
278 Exynos_OSAL_MutexLock(ghVideoRMComponentListMutex);
280 pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate;
282 if (pExynosComponent->codecType == HW_VIDEO_DEC_CODEC) {
283 pComponentTemp = gpVideoDecRMComponentList;
284 if (pComponentTemp != NULL) {
285 while (pComponentTemp) {
287 pComponentTemp = pComponentTemp->pNext;
292 if (numElem >= MAX_RESOURCE_VIDEO_DEC) {
293 lowCompDetect = searchLowPriority(gpVideoDecRMComponentList, pExynosComponent->compPriority.nGroupPriority, &pComponentCandidate);
294 if (lowCompDetect <= 0) {
295 ret = OMX_ErrorInsufficientResources;
298 ret = removeComponent(pComponentCandidate->pOMXStandComp);
299 if (ret != OMX_ErrorNone) {
300 ret = OMX_ErrorInsufficientResources;
303 ret = removeElementList(&gpVideoDecRMComponentList, pComponentCandidate->pOMXStandComp);
304 ret = addElementList(&gpVideoDecRMComponentList, pOMXComponent);
305 if (ret != OMX_ErrorNone) {
306 ret = OMX_ErrorInsufficientResources;
312 ret = addElementList(&gpVideoDecRMComponentList, pOMXComponent);
313 if (ret != OMX_ErrorNone) {
314 ret = OMX_ErrorInsufficientResources;
318 } else if (pExynosComponent->codecType == HW_VIDEO_ENC_CODEC) {
319 pComponentTemp = gpVideoEncRMComponentList;
320 if (pComponentTemp != NULL) {
321 while (pComponentTemp) {
323 pComponentTemp = pComponentTemp->pNext;
328 if (numElem >= MAX_RESOURCE_VIDEO_ENC) {
329 lowCompDetect = searchLowPriority(gpVideoEncRMComponentList, pExynosComponent->compPriority.nGroupPriority, &pComponentCandidate);
330 if (lowCompDetect <= 0) {
331 ret = OMX_ErrorInsufficientResources;
334 ret = removeComponent(pComponentCandidate->pOMXStandComp);
335 if (ret != OMX_ErrorNone) {
336 ret = OMX_ErrorInsufficientResources;
339 ret = removeElementList(&gpVideoEncRMComponentList, pComponentCandidate->pOMXStandComp);
340 ret = addElementList(&gpVideoEncRMComponentList, pOMXComponent);
341 if (ret != OMX_ErrorNone) {
342 ret = OMX_ErrorInsufficientResources;
348 ret = addElementList(&gpVideoEncRMComponentList, pOMXComponent);
349 if (ret != OMX_ErrorNone) {
350 ret = OMX_ErrorInsufficientResources;
359 Exynos_OSAL_MutexUnlock(ghVideoRMComponentListMutex);
366 OMX_ERRORTYPE Exynos_OMX_Release_Resource(OMX_COMPONENTTYPE *pOMXComponent)
368 OMX_ERRORTYPE ret = OMX_ErrorNone;
369 EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL;
370 EXYNOS_OMX_RM_COMPONENT_LIST *pComponentTemp = NULL;
371 OMX_COMPONENTTYPE *pOMXWaitComponent = NULL;
376 Exynos_OSAL_MutexLock(ghVideoRMComponentListMutex);
378 pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate;
380 if (pExynosComponent->codecType == HW_VIDEO_DEC_CODEC) {
381 pComponentTemp = gpVideoDecRMWaitingList;
382 if (gpVideoDecRMComponentList == NULL) {
383 ret = OMX_ErrorUndefined;
387 ret = removeElementList(&gpVideoDecRMComponentList, pOMXComponent);
388 if (ret != OMX_ErrorNone) {
389 ret = OMX_ErrorUndefined;
392 while (pComponentTemp) {
394 pComponentTemp = pComponentTemp->pNext;
397 pOMXWaitComponent = gpVideoDecRMWaitingList->pOMXStandComp;
398 removeElementList(&gpVideoDecRMWaitingList, pOMXWaitComponent);
399 ret = OMX_SendCommand(pOMXWaitComponent, OMX_CommandStateSet, OMX_StateIdle, NULL);
400 if (ret != OMX_ErrorNone) {
404 } else if (pExynosComponent->codecType == HW_VIDEO_ENC_CODEC) {
405 pComponentTemp = gpVideoEncRMWaitingList;
406 if (gpVideoEncRMComponentList == NULL) {
407 ret = OMX_ErrorUndefined;
411 ret = removeElementList(&gpVideoEncRMComponentList, pOMXComponent);
412 if (ret != OMX_ErrorNone) {
413 ret = OMX_ErrorUndefined;
416 while (pComponentTemp) {
418 pComponentTemp = pComponentTemp->pNext;
421 pOMXWaitComponent = gpVideoEncRMWaitingList->pOMXStandComp;
422 removeElementList(&gpVideoEncRMWaitingList, pOMXWaitComponent);
423 ret = OMX_SendCommand(pOMXWaitComponent, OMX_CommandStateSet, OMX_StateIdle, NULL);
424 if (ret != OMX_ErrorNone) {
432 Exynos_OSAL_MutexUnlock(ghVideoRMComponentListMutex);
439 OMX_ERRORTYPE Exynos_OMX_In_WaitForResource(OMX_COMPONENTTYPE *pOMXComponent)
441 OMX_ERRORTYPE ret = OMX_ErrorNone;
442 EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL;
446 Exynos_OSAL_MutexLock(ghVideoRMComponentListMutex);
448 pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate;
449 if (pExynosComponent->codecType == HW_VIDEO_DEC_CODEC)
450 ret = addElementList(&gpVideoDecRMWaitingList, pOMXComponent);
451 else if (pExynosComponent->codecType == HW_VIDEO_ENC_CODEC)
452 ret = addElementList(&gpVideoEncRMWaitingList, pOMXComponent);
454 Exynos_OSAL_MutexUnlock(ghVideoRMComponentListMutex);
461 OMX_ERRORTYPE Exynos_OMX_Out_WaitForResource(OMX_COMPONENTTYPE *pOMXComponent)
463 OMX_ERRORTYPE ret = OMX_ErrorNone;
464 EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL;
468 Exynos_OSAL_MutexLock(ghVideoRMComponentListMutex);
470 pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate;
471 if (pExynosComponent->codecType == HW_VIDEO_DEC_CODEC)
472 ret = removeElementList(&gpVideoDecRMWaitingList, pOMXComponent);
473 else if (pExynosComponent->codecType == HW_VIDEO_ENC_CODEC)
474 ret = removeElementList(&gpVideoEncRMWaitingList, pOMXComponent);
476 Exynos_OSAL_MutexUnlock(ghVideoRMComponentListMutex);