Exynos_OMX_Resourcemanager.c revision 38ef2572d26fc760c584a1855a3d002f34eb0231
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
42#define MAX_RESOURCE_VIDEO_DEC 3 /* for Android */
43#define MAX_RESOURCE_VIDEO_ENC 1 /* for Android */
44
45/* Max allowable video scheduler component instance */
46static EXYNOS_OMX_RM_COMPONENT_LIST *gpVideoDecRMComponentList = NULL;
47static EXYNOS_OMX_RM_COMPONENT_LIST *gpVideoDecRMWaitingList = NULL;
48static EXYNOS_OMX_RM_COMPONENT_LIST *gpVideoEncRMComponentList = NULL;
49static EXYNOS_OMX_RM_COMPONENT_LIST *gpVideoEncRMWaitingList = NULL;
50static OMX_HANDLETYPE ghVideoRMComponentListMutex = NULL;
51
52
53OMX_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
86EXIT:
87    return ret;
88}
89
90OMX_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
127EXIT:
128    return ret;
129}
130
131int 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
162EXIT:
163    return ret;
164}
165
166OMX_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
187EXIT:
188    return ret;
189}
190
191
192OMX_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
203OMX_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;
257EXIT:
258    FunctionOut();
259
260    return ret;
261}
262
263OMX_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
353EXIT:
354
355    Exynos_OSAL_MutexUnlock(ghVideoRMComponentListMutex);
356
357    FunctionOut();
358
359    return ret;
360}
361
362OMX_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
426EXIT:
427
428    Exynos_OSAL_MutexUnlock(ghVideoRMComponentListMutex);
429
430    FunctionOut();
431
432    return ret;
433}
434
435OMX_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
457OMX_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