6383566e792d451eab5127c4687bd19044b0f125
[platform/adaptation/ap_samsung/libomxil-e3250-v4l2.git] / openmax / component / common / Exynos_OMX_Resourcemanager.c
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@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 #ifdef SLP_PLATFORM
42 #define MAX_RESOURCE_VIDEO_DEC 8 /* for SLP */
43 #define MAX_RESOURCE_VIDEO_ENC 2 /* for SLP */
44 #else
45 #define MAX_RESOURCE_VIDEO_DEC 3 /* for Android */
46 #define MAX_RESOURCE_VIDEO_ENC 1 /* for Android */
47 #endif
48
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;
55
56
57 OMX_ERRORTYPE addElementList(EXYNOS_OMX_RM_COMPONENT_LIST **ppList, OMX_COMPONENTTYPE *pOMXComponent)
58 {
59     OMX_ERRORTYPE                 ret = OMX_ErrorNone;
60     EXYNOS_OMX_RM_COMPONENT_LIST *pTempComp = NULL;
61     EXYNOS_OMX_BASECOMPONENT     *pExynosComponent = NULL;
62
63     pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate;
64     if (*ppList != NULL) {
65         pTempComp = *ppList;
66         while (pTempComp->pNext != NULL) {
67             pTempComp = pTempComp->pNext;
68         }
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;
72             goto EXIT;
73         }
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;
77         goto EXIT;
78     } else {
79         *ppList = (EXYNOS_OMX_RM_COMPONENT_LIST *)Exynos_OSAL_Malloc(sizeof(EXYNOS_OMX_RM_COMPONENT_LIST));
80         if (*ppList == NULL) {
81             ret = OMX_ErrorInsufficientResources;
82             goto EXIT;
83         }
84         pTempComp = *ppList;
85         pTempComp->pNext = NULL;
86         pTempComp->pOMXStandComp = pOMXComponent;
87         pTempComp->groupPriority = pExynosComponent->compPriority.nGroupPriority;
88     }
89
90 EXIT:
91     return ret;
92 }
93
94 OMX_ERRORTYPE removeElementList(EXYNOS_OMX_RM_COMPONENT_LIST **ppList, OMX_COMPONENTTYPE *pOMXComponent)
95 {
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;
100
101     if (*ppList == NULL) {
102         ret = OMX_ErrorUndefined;
103         goto EXIT;
104     }
105
106     pCurrComp = *ppList;
107     while (pCurrComp != NULL) {
108         if (pCurrComp->pOMXStandComp == pOMXComponent) {
109             if (*ppList == pCurrComp) {
110                 *ppList = pCurrComp->pNext;
111                 Exynos_OSAL_Free(pCurrComp);
112             } else {
113                 if (pPrevComp != NULL)
114                     pPrevComp->pNext = pCurrComp->pNext;
115
116                 Exynos_OSAL_Free(pCurrComp);
117             }
118             bDetectComp = OMX_TRUE;
119             break;
120         } else {
121             pPrevComp = pCurrComp;
122             pCurrComp = pCurrComp->pNext;
123         }
124     }
125
126     if (bDetectComp == OMX_FALSE)
127         ret = OMX_ErrorComponentNotFound;
128     else
129         ret = OMX_ErrorNone;
130
131 EXIT:
132     return ret;
133 }
134
135 int searchLowPriority(EXYNOS_OMX_RM_COMPONENT_LIST *RMComp_list, OMX_U32 inComp_priority, EXYNOS_OMX_RM_COMPONENT_LIST **outLowComp)
136 {
137     int ret = 0;
138     EXYNOS_OMX_RM_COMPONENT_LIST *pTempComp = NULL;
139     EXYNOS_OMX_RM_COMPONENT_LIST *pCandidateComp = NULL;
140
141     if (RMComp_list == NULL)
142         ret = -1;
143
144     pTempComp = RMComp_list;
145     *outLowComp = 0;
146
147     while (pTempComp != NULL) {
148         if (pTempComp->groupPriority > inComp_priority) {
149             if (pCandidateComp != NULL) {
150                 if (pCandidateComp->groupPriority < pTempComp->groupPriority)
151                     pCandidateComp = pTempComp;
152             } else {
153                 pCandidateComp = pTempComp;
154             }
155         }
156
157         pTempComp = pTempComp->pNext;
158     }
159
160     *outLowComp = pCandidateComp;
161     if (pCandidateComp == NULL)
162         ret = 0;
163     else
164         ret = 1;
165
166 EXIT:
167     return ret;
168 }
169
170 OMX_ERRORTYPE removeComponent(OMX_COMPONENTTYPE *pOMXComponent)
171 {
172     OMX_ERRORTYPE             ret = OMX_ErrorNone;
173     EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL;
174
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;
183             goto EXIT;
184         }
185     } else if ((pExynosComponent->currentState == OMX_StateExecuting) || (pExynosComponent->currentState == OMX_StatePause)) {
186         /* Todo */
187     }
188
189     ret = OMX_ErrorNone;
190
191 EXIT:
192     return ret;
193 }
194
195
196 OMX_ERRORTYPE Exynos_OMX_ResourceManager_Init()
197 {
198     OMX_ERRORTYPE ret = OMX_ErrorNone;
199
200     FunctionIn();
201     ret = Exynos_OSAL_MutexCreate(&ghVideoRMComponentListMutex);
202     FunctionOut();
203
204     return ret;
205 }
206
207 OMX_ERRORTYPE Exynos_OMX_ResourceManager_Deinit()
208 {
209     OMX_ERRORTYPE ret = OMX_ErrorNone;
210     EXYNOS_OMX_RM_COMPONENT_LIST *pCurrComponent;
211     EXYNOS_OMX_RM_COMPONENT_LIST *pNextComponent;
212
213     FunctionIn();
214
215     Exynos_OSAL_MutexLock(ghVideoRMComponentListMutex);
216
217     if (gpVideoDecRMComponentList) {
218         pCurrComponent = gpVideoDecRMComponentList;
219         while (pCurrComponent != NULL) {
220             pNextComponent = pCurrComponent->pNext;
221             Exynos_OSAL_Free(pCurrComponent);
222             pCurrComponent = pNextComponent;
223         }
224         gpVideoDecRMComponentList = NULL;
225     }
226     if (gpVideoDecRMWaitingList) {
227         pCurrComponent = gpVideoDecRMWaitingList;
228         while (pCurrComponent != NULL) {
229             pNextComponent = pCurrComponent->pNext;
230             Exynos_OSAL_Free(pCurrComponent);
231             pCurrComponent = pNextComponent;
232         }
233         gpVideoDecRMWaitingList = NULL;
234     }
235
236     if (gpVideoEncRMComponentList) {
237         pCurrComponent = gpVideoEncRMComponentList;
238         while (pCurrComponent != NULL) {
239             pNextComponent = pCurrComponent->pNext;
240             Exynos_OSAL_Free(pCurrComponent);
241             pCurrComponent = pNextComponent;
242         }
243         gpVideoEncRMComponentList = NULL;
244     }
245     if (gpVideoEncRMWaitingList) {
246         pCurrComponent = gpVideoEncRMWaitingList;
247         while (pCurrComponent != NULL) {
248             pNextComponent = pCurrComponent->pNext;
249             Exynos_OSAL_Free(pCurrComponent);
250             pCurrComponent = pNextComponent;
251         }
252         gpVideoEncRMWaitingList = NULL;
253     }
254
255     Exynos_OSAL_MutexUnlock(ghVideoRMComponentListMutex);
256
257     Exynos_OSAL_MutexTerminate(ghVideoRMComponentListMutex);
258     ghVideoRMComponentListMutex = NULL;
259
260     ret = OMX_ErrorNone;
261 EXIT:
262     FunctionOut();
263
264     return ret;
265 }
266
267 OMX_ERRORTYPE Exynos_OMX_Get_Resource(OMX_COMPONENTTYPE *pOMXComponent)
268 {
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;
273     int numElem = 0;
274     int lowCompDetect = 0;
275
276     FunctionIn();
277
278     Exynos_OSAL_MutexLock(ghVideoRMComponentListMutex);
279
280     pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate;
281
282     if (pExynosComponent->codecType == HW_VIDEO_DEC_CODEC) {
283         pComponentTemp = gpVideoDecRMComponentList;
284         if (pComponentTemp != NULL) {
285             while (pComponentTemp) {
286                 numElem++;
287                 pComponentTemp = pComponentTemp->pNext;
288             }
289         } else {
290             numElem = 0;
291         }
292         if (numElem >= MAX_RESOURCE_VIDEO_DEC) {
293             lowCompDetect = searchLowPriority(gpVideoDecRMComponentList, pExynosComponent->compPriority.nGroupPriority, &pComponentCandidate);
294             if (lowCompDetect <= 0) {
295                 ret = OMX_ErrorInsufficientResources;
296                 goto EXIT;
297             } else {
298                 ret = removeComponent(pComponentCandidate->pOMXStandComp);
299                 if (ret != OMX_ErrorNone) {
300                     ret = OMX_ErrorInsufficientResources;
301                     goto EXIT;
302                 } else {
303                     ret = removeElementList(&gpVideoDecRMComponentList, pComponentCandidate->pOMXStandComp);
304                     ret = addElementList(&gpVideoDecRMComponentList, pOMXComponent);
305                     if (ret != OMX_ErrorNone) {
306                         ret = OMX_ErrorInsufficientResources;
307                         goto EXIT;
308                     }
309                 }
310             }
311         } else {
312             ret = addElementList(&gpVideoDecRMComponentList, pOMXComponent);
313             if (ret != OMX_ErrorNone) {
314                 ret = OMX_ErrorInsufficientResources;
315                 goto EXIT;
316             }
317         }
318     } else if (pExynosComponent->codecType == HW_VIDEO_ENC_CODEC) {
319         pComponentTemp = gpVideoEncRMComponentList;
320         if (pComponentTemp != NULL) {
321             while (pComponentTemp) {
322                 numElem++;
323                 pComponentTemp = pComponentTemp->pNext;
324             }
325         } else {
326             numElem = 0;
327         }
328         if (numElem >= MAX_RESOURCE_VIDEO_ENC) {
329             lowCompDetect = searchLowPriority(gpVideoEncRMComponentList, pExynosComponent->compPriority.nGroupPriority, &pComponentCandidate);
330             if (lowCompDetect <= 0) {
331                 ret = OMX_ErrorInsufficientResources;
332                 goto EXIT;
333             } else {
334                 ret = removeComponent(pComponentCandidate->pOMXStandComp);
335                 if (ret != OMX_ErrorNone) {
336                     ret = OMX_ErrorInsufficientResources;
337                     goto EXIT;
338                 } else {
339                     ret = removeElementList(&gpVideoEncRMComponentList, pComponentCandidate->pOMXStandComp);
340                     ret = addElementList(&gpVideoEncRMComponentList, pOMXComponent);
341                     if (ret != OMX_ErrorNone) {
342                         ret = OMX_ErrorInsufficientResources;
343                         goto EXIT;
344                     }
345                 }
346             }
347         } else {
348             ret = addElementList(&gpVideoEncRMComponentList, pOMXComponent);
349             if (ret != OMX_ErrorNone) {
350                 ret = OMX_ErrorInsufficientResources;
351                 goto EXIT;
352             }
353         }
354     }
355     ret = OMX_ErrorNone;
356
357 EXIT:
358
359     Exynos_OSAL_MutexUnlock(ghVideoRMComponentListMutex);
360
361     FunctionOut();
362
363     return ret;
364 }
365
366 OMX_ERRORTYPE Exynos_OMX_Release_Resource(OMX_COMPONENTTYPE *pOMXComponent)
367 {
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;
372     int numElem = 0;
373
374     FunctionIn();
375
376     Exynos_OSAL_MutexLock(ghVideoRMComponentListMutex);
377
378     pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate;
379
380     if (pExynosComponent->codecType == HW_VIDEO_DEC_CODEC) {
381         pComponentTemp = gpVideoDecRMWaitingList;
382         if (gpVideoDecRMComponentList == NULL) {
383             ret = OMX_ErrorUndefined;
384             goto EXIT;
385         }
386
387         ret = removeElementList(&gpVideoDecRMComponentList, pOMXComponent);
388         if (ret != OMX_ErrorNone) {
389             ret = OMX_ErrorUndefined;
390             goto EXIT;
391         }
392         while (pComponentTemp) {
393             numElem++;
394             pComponentTemp = pComponentTemp->pNext;
395         }
396         if (numElem > 0) {
397             pOMXWaitComponent = gpVideoDecRMWaitingList->pOMXStandComp;
398             removeElementList(&gpVideoDecRMWaitingList, pOMXWaitComponent);
399             ret = OMX_SendCommand(pOMXWaitComponent, OMX_CommandStateSet, OMX_StateIdle, NULL);
400             if (ret != OMX_ErrorNone) {
401                 goto EXIT;
402             }
403         }
404     } else if (pExynosComponent->codecType == HW_VIDEO_ENC_CODEC) {
405         pComponentTemp = gpVideoEncRMWaitingList;
406         if (gpVideoEncRMComponentList == NULL) {
407             ret = OMX_ErrorUndefined;
408             goto EXIT;
409         }
410
411         ret = removeElementList(&gpVideoEncRMComponentList, pOMXComponent);
412         if (ret != OMX_ErrorNone) {
413             ret = OMX_ErrorUndefined;
414             goto EXIT;
415         }
416         while (pComponentTemp) {
417             numElem++;
418             pComponentTemp = pComponentTemp->pNext;
419         }
420         if (numElem > 0) {
421             pOMXWaitComponent = gpVideoEncRMWaitingList->pOMXStandComp;
422             removeElementList(&gpVideoEncRMWaitingList, pOMXWaitComponent);
423             ret = OMX_SendCommand(pOMXWaitComponent, OMX_CommandStateSet, OMX_StateIdle, NULL);
424             if (ret != OMX_ErrorNone) {
425                 goto EXIT;
426             }
427         }
428     }
429
430 EXIT:
431
432     Exynos_OSAL_MutexUnlock(ghVideoRMComponentListMutex);
433
434     FunctionOut();
435
436     return ret;
437 }
438
439 OMX_ERRORTYPE Exynos_OMX_In_WaitForResource(OMX_COMPONENTTYPE *pOMXComponent)
440 {
441     OMX_ERRORTYPE             ret = OMX_ErrorNone;
442     EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL;
443
444     FunctionIn();
445
446     Exynos_OSAL_MutexLock(ghVideoRMComponentListMutex);
447
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);
453
454     Exynos_OSAL_MutexUnlock(ghVideoRMComponentListMutex);
455
456     FunctionOut();
457
458     return ret;
459 }
460
461 OMX_ERRORTYPE Exynos_OMX_Out_WaitForResource(OMX_COMPONENTTYPE *pOMXComponent)
462 {
463     OMX_ERRORTYPE             ret = OMX_ErrorNone;
464     EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL;
465
466     FunctionIn();
467
468     Exynos_OSAL_MutexLock(ghVideoRMComponentListMutex);
469
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);
475
476     Exynos_OSAL_MutexUnlock(ghVideoRMComponentListMutex);
477
478     FunctionOut();
479
480     return ret;
481 }
482