fixed coverity issues
[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 TIZEN_FEATURE_E3250
42 #define MAX_RESOURCE_VIDEO_DEC 8 /* for TIZEN */
43 #define MAX_RESOURCE_VIDEO_ENC 2 /* for TIZEN */
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         return -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     return ret;
167 }
168
169 OMX_ERRORTYPE removeComponent(OMX_COMPONENTTYPE *pOMXComponent)
170 {
171     OMX_ERRORTYPE             ret = OMX_ErrorNone;
172     EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL;
173
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;
182             goto EXIT;
183         }
184     } else if ((pExynosComponent->currentState == OMX_StateExecuting) || (pExynosComponent->currentState == OMX_StatePause)) {
185         /* Todo */
186     }
187
188     ret = OMX_ErrorNone;
189
190 EXIT:
191     return ret;
192 }
193
194
195 OMX_ERRORTYPE Exynos_OMX_ResourceManager_Init()
196 {
197     OMX_ERRORTYPE ret = OMX_ErrorNone;
198
199     FunctionIn();
200     ret = Exynos_OSAL_MutexCreate(&ghVideoRMComponentListMutex);
201     FunctionOut();
202
203     return ret;
204 }
205
206 OMX_ERRORTYPE Exynos_OMX_ResourceManager_Deinit()
207 {
208     OMX_ERRORTYPE ret = OMX_ErrorNone;
209     EXYNOS_OMX_RM_COMPONENT_LIST *pCurrComponent;
210     EXYNOS_OMX_RM_COMPONENT_LIST *pNextComponent;
211
212     FunctionIn();
213
214     Exynos_OSAL_MutexLock(ghVideoRMComponentListMutex);
215
216     if (gpVideoDecRMComponentList) {
217         pCurrComponent = gpVideoDecRMComponentList;
218         while (pCurrComponent != NULL) {
219             pNextComponent = pCurrComponent->pNext;
220             Exynos_OSAL_Free(pCurrComponent);
221             pCurrComponent = pNextComponent;
222         }
223         gpVideoDecRMComponentList = NULL;
224     }
225     if (gpVideoDecRMWaitingList) {
226         pCurrComponent = gpVideoDecRMWaitingList;
227         while (pCurrComponent != NULL) {
228             pNextComponent = pCurrComponent->pNext;
229             Exynos_OSAL_Free(pCurrComponent);
230             pCurrComponent = pNextComponent;
231         }
232         gpVideoDecRMWaitingList = NULL;
233     }
234
235     if (gpVideoEncRMComponentList) {
236         pCurrComponent = gpVideoEncRMComponentList;
237         while (pCurrComponent != NULL) {
238             pNextComponent = pCurrComponent->pNext;
239             Exynos_OSAL_Free(pCurrComponent);
240             pCurrComponent = pNextComponent;
241         }
242         gpVideoEncRMComponentList = NULL;
243     }
244     if (gpVideoEncRMWaitingList) {
245         pCurrComponent = gpVideoEncRMWaitingList;
246         while (pCurrComponent != NULL) {
247             pNextComponent = pCurrComponent->pNext;
248             Exynos_OSAL_Free(pCurrComponent);
249             pCurrComponent = pNextComponent;
250         }
251         gpVideoEncRMWaitingList = NULL;
252     }
253
254     Exynos_OSAL_MutexUnlock(ghVideoRMComponentListMutex);
255
256     Exynos_OSAL_MutexTerminate(ghVideoRMComponentListMutex);
257     ghVideoRMComponentListMutex = NULL;
258
259     ret = OMX_ErrorNone;
260
261     FunctionOut();
262
263     return ret;
264 }
265
266 OMX_ERRORTYPE Exynos_OMX_Get_Resource(OMX_COMPONENTTYPE *pOMXComponent)
267 {
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;
272     int numElem = 0;
273     int lowCompDetect = 0;
274
275     FunctionIn();
276
277     Exynos_OSAL_MutexLock(ghVideoRMComponentListMutex);
278
279     pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate;
280
281     if (pExynosComponent->codecType == HW_VIDEO_DEC_CODEC) {
282         pComponentTemp = gpVideoDecRMComponentList;
283         if (pComponentTemp != NULL) {
284             while (pComponentTemp) {
285                 numElem++;
286                 pComponentTemp = pComponentTemp->pNext;
287             }
288         } else {
289             numElem = 0;
290         }
291         if (numElem >= MAX_RESOURCE_VIDEO_DEC) {
292             lowCompDetect = searchLowPriority(gpVideoDecRMComponentList, pExynosComponent->compPriority.nGroupPriority, &pComponentCandidate);
293             if (lowCompDetect <= 0) {
294                 ret = OMX_ErrorInsufficientResources;
295                 goto EXIT;
296             } else {
297                 ret = removeComponent(pComponentCandidate->pOMXStandComp);
298                 if (ret != OMX_ErrorNone) {
299                     ret = OMX_ErrorInsufficientResources;
300                     goto EXIT;
301                 } else {
302                     ret = removeElementList(&gpVideoDecRMComponentList, pComponentCandidate->pOMXStandComp);
303                     ret = addElementList(&gpVideoDecRMComponentList, pOMXComponent);
304                     if (ret != OMX_ErrorNone) {
305                         ret = OMX_ErrorInsufficientResources;
306                         goto EXIT;
307                     }
308                 }
309             }
310         } else {
311             ret = addElementList(&gpVideoDecRMComponentList, pOMXComponent);
312             if (ret != OMX_ErrorNone) {
313                 ret = OMX_ErrorInsufficientResources;
314                 goto EXIT;
315             }
316         }
317     } else if (pExynosComponent->codecType == HW_VIDEO_ENC_CODEC) {
318         pComponentTemp = gpVideoEncRMComponentList;
319         if (pComponentTemp != NULL) {
320             while (pComponentTemp) {
321                 numElem++;
322                 pComponentTemp = pComponentTemp->pNext;
323             }
324         } else {
325             numElem = 0;
326         }
327         if (numElem >= MAX_RESOURCE_VIDEO_ENC) {
328             lowCompDetect = searchLowPriority(gpVideoEncRMComponentList, pExynosComponent->compPriority.nGroupPriority, &pComponentCandidate);
329             if (lowCompDetect <= 0) {
330                 ret = OMX_ErrorInsufficientResources;
331                 goto EXIT;
332             } else {
333                 ret = removeComponent(pComponentCandidate->pOMXStandComp);
334                 if (ret != OMX_ErrorNone) {
335                     ret = OMX_ErrorInsufficientResources;
336                     goto EXIT;
337                 } else {
338                     ret = removeElementList(&gpVideoEncRMComponentList, pComponentCandidate->pOMXStandComp);
339                     ret = addElementList(&gpVideoEncRMComponentList, pOMXComponent);
340                     if (ret != OMX_ErrorNone) {
341                         ret = OMX_ErrorInsufficientResources;
342                         goto EXIT;
343                     }
344                 }
345             }
346         } else {
347             ret = addElementList(&gpVideoEncRMComponentList, pOMXComponent);
348             if (ret != OMX_ErrorNone) {
349                 ret = OMX_ErrorInsufficientResources;
350                 goto EXIT;
351             }
352         }
353     }
354     ret = OMX_ErrorNone;
355
356 EXIT:
357
358     Exynos_OSAL_MutexUnlock(ghVideoRMComponentListMutex);
359
360     FunctionOut();
361
362     return ret;
363 }
364
365 OMX_ERRORTYPE Exynos_OMX_Release_Resource(OMX_COMPONENTTYPE *pOMXComponent)
366 {
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;
371     int numElem = 0;
372
373     FunctionIn();
374
375     Exynos_OSAL_MutexLock(ghVideoRMComponentListMutex);
376
377     pExynosComponent = (EXYNOS_OMX_BASECOMPONENT *)pOMXComponent->pComponentPrivate;
378
379     if (pExynosComponent->codecType == HW_VIDEO_DEC_CODEC) {
380         pComponentTemp = gpVideoDecRMWaitingList;
381         if (gpVideoDecRMComponentList == NULL) {
382             ret = OMX_ErrorUndefined;
383             goto EXIT;
384         }
385
386         ret = removeElementList(&gpVideoDecRMComponentList, pOMXComponent);
387         if (ret != OMX_ErrorNone) {
388             ret = OMX_ErrorUndefined;
389             goto EXIT;
390         }
391         while (pComponentTemp) {
392             numElem++;
393             pComponentTemp = pComponentTemp->pNext;
394         }
395         if (numElem > 0) {
396             pOMXWaitComponent = gpVideoDecRMWaitingList->pOMXStandComp;
397             removeElementList(&gpVideoDecRMWaitingList, pOMXWaitComponent);
398             ret = OMX_SendCommand(pOMXWaitComponent, OMX_CommandStateSet, OMX_StateIdle, NULL);
399             if (ret != OMX_ErrorNone) {
400                 goto EXIT;
401             }
402         }
403     } else if (pExynosComponent->codecType == HW_VIDEO_ENC_CODEC) {
404         pComponentTemp = gpVideoEncRMWaitingList;
405         if (gpVideoEncRMComponentList == NULL) {
406             ret = OMX_ErrorUndefined;
407             goto EXIT;
408         }
409
410         ret = removeElementList(&gpVideoEncRMComponentList, pOMXComponent);
411         if (ret != OMX_ErrorNone) {
412             ret = OMX_ErrorUndefined;
413             goto EXIT;
414         }
415         while (pComponentTemp) {
416             numElem++;
417             pComponentTemp = pComponentTemp->pNext;
418         }
419         if (numElem > 0) {
420             pOMXWaitComponent = gpVideoEncRMWaitingList->pOMXStandComp;
421             removeElementList(&gpVideoEncRMWaitingList, pOMXWaitComponent);
422             ret = OMX_SendCommand(pOMXWaitComponent, OMX_CommandStateSet, OMX_StateIdle, NULL);
423             if (ret != OMX_ErrorNone) {
424                 goto EXIT;
425             }
426         }
427     }
428
429 EXIT:
430
431     Exynos_OSAL_MutexUnlock(ghVideoRMComponentListMutex);
432
433     FunctionOut();
434
435     return ret;
436 }
437
438 OMX_ERRORTYPE Exynos_OMX_In_WaitForResource(OMX_COMPONENTTYPE *pOMXComponent)
439 {
440     OMX_ERRORTYPE             ret = OMX_ErrorNone;
441     EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL;
442
443     FunctionIn();
444
445     Exynos_OSAL_MutexLock(ghVideoRMComponentListMutex);
446
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);
452
453     Exynos_OSAL_MutexUnlock(ghVideoRMComponentListMutex);
454
455     FunctionOut();
456
457     return ret;
458 }
459
460 OMX_ERRORTYPE Exynos_OMX_Out_WaitForResource(OMX_COMPONENTTYPE *pOMXComponent)
461 {
462     OMX_ERRORTYPE             ret = OMX_ErrorNone;
463     EXYNOS_OMX_BASECOMPONENT *pExynosComponent = NULL;
464
465     FunctionIn();
466
467     Exynos_OSAL_MutexLock(ghVideoRMComponentListMutex);
468
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);
474
475     Exynos_OSAL_MutexUnlock(ghVideoRMComponentListMutex);
476
477     FunctionOut();
478
479     return ret;
480 }
481