1/*--------------------------------------------------------------------------
2Copyright (c) 2009, The Linux Foundation. All rights reserved.
3
4Redistribution and use in source and binary forms, with or without
5modification, are permitted provided that the following conditions are met:
6    * Redistributions of source code must retain the above copyright
7      notice, this list of conditions and the following disclaimer.
8    * Redistributions in binary form must reproduce the above copyright
9      notice, this list of conditions and the following disclaimer in the
10      documentation and/or other materials provided with the distribution.
11    * Neither the name of The Linux Foundation nor
12      the names of its contributors may be used to endorse or promote
13      products derived from this software without specific prior written
14      permission.
15
16THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19NON-INFRINGEMENT ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
20CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
21EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
22PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
23OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
24WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
25OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
26ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27--------------------------------------------------------------------------*/
28/*============================================================================
29                            O p e n M A X   w r a p p e r s
30                             O p e n  M A X   C o r e
31
32  This module contains the implementation of the OpenMAX core.
33
34*//*========================================================================*/
35
36//////////////////////////////////////////////////////////////////////////////
37//                             Include Files
38//////////////////////////////////////////////////////////////////////////////
39
40#include <dlfcn.h>           // dynamic library
41#include <sys/types.h>
42#include <sys/stat.h>
43#include <unistd.h>
44#include <string.h>
45#include <stdio.h>
46#include <pthread.h>
47
48#include "qc_omx_core.h"
49#include "omx_core_cmp.h"
50
51extern omx_core_cb_type core[];
52extern const unsigned int SIZE_OF_CORE;
53static pthread_mutex_t lock_core = PTHREAD_MUTEX_INITIALIZER;
54
55/* ======================================================================
56FUNCTION
57  omx_core_load_cmp_library
58
59DESCRIPTION
60  Loads up the libary name mentioned in the argument
61
62PARAMETERS
63  None
64
65RETURN VALUE
66  Constructor for creating component instances.
67========================================================================== */
68static create_qc_omx_component
69omx_core_load_cmp_library(char *libname, void **handle_ptr)
70{
71  create_qc_omx_component fn_ptr = NULL;
72  if(handle_ptr)
73  {
74    DEBUG_PRINT("Dynamically Loading the library : %s\n",libname);
75    *handle_ptr = dlopen(libname,RTLD_NOW);
76    if(*handle_ptr)
77    {
78      fn_ptr = dlsym(*handle_ptr, "get_omx_component_factory_fn");
79
80      if(fn_ptr == NULL)
81      {
82        DEBUG_PRINT("Error: Library %s incompatible as QCOM OMX component loader - %s\n",
83                  libname, dlerror());
84        *handle_ptr = NULL;
85      }
86    }
87    else
88    {
89      DEBUG_PRINT("Error: Couldn't load %s: %s\n",libname,dlerror());
90    }
91  }
92  return fn_ptr;
93}
94
95/* ======================================================================
96FUNCTION
97  OMX_Init
98
99DESCRIPTION
100  This is the first function called by the application.
101  There is nothing to do here since components shall be loaded
102  whenever the get handle method is called.
103
104PARAMETERS
105  None
106
107RETURN VALUE
108  None.
109========================================================================== */
110OMX_API OMX_ERRORTYPE OMX_APIENTRY
111OMX_Init()
112{
113  DEBUG_PRINT("OMXCORE API - OMX_Init \n");
114  /* Nothing to do here ; shared objects shall be loaded at the get handle method */
115  return OMX_ErrorNone;
116}
117
118/* ======================================================================
119FUNCTION
120  get_cmp_index
121
122DESCRIPTION
123  Obtains the  index associated with the name.
124
125PARAMETERS
126  None
127
128RETURN VALUE
129  Error None.
130========================================================================== */
131static int get_cmp_index(char *cmp_name)
132{
133  int rc = -1,i=0;
134  DEBUG_PRINT("before get_cmp_index **********%d\n", rc);
135
136  for(i=0; i< (int)SIZE_OF_CORE; i++)
137  {
138   DEBUG_PRINT("get_cmp_index: cmp_name = %s , core[i].name = %s ,count = %d \n",cmp_name,core[i].name,i);
139
140    if(!strcmp(cmp_name, core[i].name))
141    {
142        rc = i;
143        break;
144    }
145  }
146  DEBUG_PRINT("returning index %d\n", rc);
147  return rc;
148}
149
150/* ======================================================================
151FUNCTION
152  clear_cmp_handle
153
154DESCRIPTION
155  Clears the component handle from the component table.
156
157PARAMETERS
158  None
159
160RETURN VALUE
161  None.
162========================================================================== */
163static void clear_cmp_handle(OMX_HANDLETYPE inst)
164{
165  unsigned i = 0,j=0;
166
167  if(NULL == inst)
168     return;
169
170  for(i=0; i< SIZE_OF_CORE; i++)
171  {
172    for(j=0; j< OMX_COMP_MAX_INST; j++)
173    {
174      if(inst == core[i].inst[j])
175      {
176        core[i].inst[j] = NULL;
177        return;
178      }
179    }
180  }
181  return;
182}
183/* ======================================================================
184FUNCTION
185  is_cmp_handle_exists
186
187DESCRIPTION
188  Check if the component handle already exists or not.
189
190PARAMETERS
191  None
192
193RETURN VALUE
194  index pointer if the handle exists
195  negative value otherwise
196========================================================================== */
197static int is_cmp_handle_exists(OMX_HANDLETYPE inst)
198{
199  unsigned i=0,j=0;
200  int rc = -1;
201
202  if(NULL == inst)
203     return rc;
204
205  pthread_mutex_lock(&lock_core);
206  for(i=0; i< SIZE_OF_CORE; i++)
207  {
208    for(j=0; j< OMX_COMP_MAX_INST; j++)
209    {
210      if(inst == core[i].inst[j])
211      {
212        rc = i;
213        goto finish;
214      }
215    }
216  }
217finish:
218  pthread_mutex_unlock(&lock_core);
219  return rc;
220}
221
222/* ======================================================================
223FUNCTION
224  get_comp_handle_index
225
226DESCRIPTION
227  Gets the index to store the next handle for specified component name.
228
229PARAMETERS
230  cmp_name : Component Name
231
232RETURN VALUE
233  Index of next handle to be stored
234========================================================================== */
235static int get_comp_handle_index(char *cmp_name)
236{
237  unsigned i=0,j=0;
238  int rc = -1;
239  for(i=0; i< SIZE_OF_CORE; i++)
240  {
241    if(!strcmp(cmp_name, core[i].name))
242    {
243      for(j=0; j< OMX_COMP_MAX_INST; j++)
244      {
245        if(NULL == core[i].inst[j])
246        {
247          rc = j;
248          DEBUG_PRINT("free handle slot exists %d\n", rc);
249          return rc;
250        }
251      }
252      break;
253    }
254  }
255  return rc;
256}
257
258/* ======================================================================
259FUNCTION
260  check_lib_unload
261
262DESCRIPTION
263  Check if any component instance is using the library
264
265PARAMETERS
266  index: Component Index in core array.
267
268RETURN VALUE
269  1: Library Unused and can be unloaded.
270  0:  Library used and shouldnt be unloaded.
271========================================================================== */
272static int check_lib_unload(int index)
273{
274  unsigned i=0;
275  int rc = 1;
276
277  for(i=0; i< OMX_COMP_MAX_INST; i++)
278  {
279    if(core[index].inst[i])
280    {
281      rc = 0;
282      DEBUG_PRINT("Library Used \n");
283      break;
284    }
285  }
286  return rc;
287}
288/* ======================================================================
289FUNCTION
290  is_cmp_already_exists
291
292DESCRIPTION
293  Check if the component already exists or not. Used in the
294  management of component handles.
295
296PARAMETERS
297  None
298
299RETURN VALUE
300  Error None.
301========================================================================== */
302static int is_cmp_already_exists(char *cmp_name)
303{
304  unsigned i    =0,j=0;
305  int rc = -1;
306  for(i=0; i< SIZE_OF_CORE; i++)
307  {
308    if(!strcmp(cmp_name, core[i].name))
309    {
310      for(j=0; j< OMX_COMP_MAX_INST; j++)
311      {
312        if(core[i].inst[j])
313        {
314          rc = i;
315          DEBUG_PRINT("Component exists %d\n", rc);
316          return rc;
317        }
318      }
319      break;
320    }
321  }
322  return rc;
323}
324
325/* ======================================================================
326FUNCTION
327  get_cmp_handle
328
329DESCRIPTION
330  Get component handle.
331
332PARAMETERS
333  None
334
335RETURN VALUE
336  Error None.
337========================================================================== */
338void* get_cmp_handle(char *cmp_name)
339{
340  unsigned i    =0,j=0;
341
342  DEBUG_PRINT("get_cmp_handle \n");
343  for(i=0; i< SIZE_OF_CORE; i++)
344  {
345    if(!strcmp(cmp_name, core[i].name))
346    {
347      for(j=0; j< OMX_COMP_MAX_INST; j++)
348      {
349        if(core[i].inst[j])
350        {
351          DEBUG_PRINT("get_cmp_handle match\n");
352          return core[i].inst[j];
353        }
354      }
355    }
356  }
357  DEBUG_PRINT("get_cmp_handle returning NULL \n");
358  return NULL;
359}
360
361/* ======================================================================
362FUNCTION
363  OMX_DeInit
364
365DESCRIPTION
366  DeInitialize all the the relevant OMX components.
367
368PARAMETERS
369  None
370
371RETURN VALUE
372  Error None.
373========================================================================== */
374OMX_API OMX_ERRORTYPE OMX_APIENTRY
375OMX_Deinit()
376{
377  return OMX_ErrorNone;
378}
379
380/* ======================================================================
381FUNCTION
382  OMX_GetHandle
383
384DESCRIPTION
385  Constructs requested component. Relevant library is loaded if needed.
386
387PARAMETERS
388  None
389
390RETURN VALUE
391  Error None  if everything goes fine.
392========================================================================== */
393
394 OMX_API OMX_ERRORTYPE OMX_APIENTRY
395OMX_GetHandle(OMX_OUT OMX_HANDLETYPE*     handle,
396              OMX_IN OMX_STRING    componentName,
397              OMX_IN OMX_PTR             appData,
398              OMX_IN OMX_CALLBACKTYPE* callBacks)
399{
400  OMX_ERRORTYPE  eRet = OMX_ErrorNone;
401  int cmp_index = -1;
402  int hnd_index = -1;
403
404  DEBUG_PRINT("OMXCORE API :  Get Handle %p %s %p\n", handle,
405                                                     componentName,
406                                                     appData);
407  pthread_mutex_lock(&lock_core);
408  if(handle)
409  {
410    struct stat sd;
411
412    *handle = NULL;
413
414    cmp_index = get_cmp_index(componentName);
415
416    if(cmp_index >= 0)
417    {
418       DEBUG_PRINT("getting fn pointer\n");
419
420      // dynamically load the so
421      core[cmp_index].fn_ptr =
422        omx_core_load_cmp_library(core[cmp_index].so_lib_name,
423                                  &core[cmp_index].so_lib_handle);
424
425      if(core[cmp_index].fn_ptr)
426      {
427        // Construct the component requested
428        // Function returns the opaque handle
429        void* pThis = (*(core[cmp_index].fn_ptr))();
430        if(pThis)
431        {
432          void *hComp = NULL;
433          hComp = qc_omx_create_component_wrapper((OMX_PTR)pThis);
434          if((eRet = qc_omx_component_init(hComp, core[cmp_index].name)) !=
435                           OMX_ErrorNone)
436          {
437              DEBUG_PRINT("Component not created succesfully\n");
438              pthread_mutex_unlock(&lock_core);
439              return eRet;
440
441          }
442          qc_omx_component_set_callbacks(hComp,callBacks,appData);
443          hnd_index = get_comp_handle_index(componentName);
444          if(hnd_index >= 0)
445          {
446            core[cmp_index].inst[hnd_index]= *handle = (OMX_HANDLETYPE) hComp;
447          }
448          else
449          {
450            DEBUG_PRINT("OMX_GetHandle:NO free slot available to store Component Handle\n");
451            pthread_mutex_unlock(&lock_core);
452            return OMX_ErrorInsufficientResources;
453          }
454          DEBUG_PRINT("Component %p Successfully created\n",*handle);
455        }
456        else
457        {
458          eRet = OMX_ErrorInsufficientResources;
459          DEBUG_PRINT("Component Creation failed\n");
460        }
461      }
462      else
463      {
464        eRet = OMX_ErrorNotImplemented;
465        DEBUG_PRINT("library couldnt return create instance fn\n");
466      }
467
468    }
469    else
470    {
471      eRet = OMX_ErrorNotImplemented;
472      DEBUG_PRINT("ERROR: Already another instance active  ;rejecting \n");
473    }
474  }
475  else
476  {
477    eRet =  OMX_ErrorBadParameter;
478    DEBUG_PRINT("\n OMX_GetHandle: NULL handle \n");
479  }
480  pthread_mutex_unlock(&lock_core);
481  return eRet;
482}
483/* ======================================================================
484FUNCTION
485  OMX_FreeHandle
486
487DESCRIPTION
488  Destructs the component handles.
489
490PARAMETERS
491  None
492
493RETURN VALUE
494  Error None.
495========================================================================== */
496OMX_API OMX_ERRORTYPE OMX_APIENTRY
497OMX_FreeHandle(OMX_IN OMX_HANDLETYPE hComp)
498{
499  OMX_ERRORTYPE eRet = OMX_ErrorNone;
500  int err = 0, i = 0;
501  DEBUG_PRINT("OMXCORE API :  Free Handle %p\n", hComp);
502
503  // 0. Check that we have an active instance
504  if((i=is_cmp_handle_exists(hComp)) >=0)
505  {
506    // 1. Delete the component
507    if ((eRet = qc_omx_component_deinit(hComp)) == OMX_ErrorNone)
508    {
509        pthread_mutex_lock(&lock_core);
510        /* Unload component library */
511    if( (i < (int)SIZE_OF_CORE) && core[i].so_lib_handle)
512    {
513           if(check_lib_unload(i))
514           {
515              DEBUG_PRINT_ERROR(" Unloading the dynamic library for %s\n",
516                                  core[i].name);
517              err = dlclose(core[i].so_lib_handle);
518              if(err)
519              {
520                  DEBUG_PRINT_ERROR("Error %d in dlclose of lib %s\n",
521                                     err,core[i].name);
522              }
523              core[i].so_lib_handle = NULL;
524           }
525    }
526    clear_cmp_handle(hComp);
527    pthread_mutex_unlock(&lock_core);
528    }
529    else
530    {
531    DEBUG_PRINT(" OMX_FreeHandle failed on %p\n", hComp);
532        return eRet;
533    }
534  }
535  else
536  {
537    DEBUG_PRINT_ERROR("OMXCORE Warning: Free Handle called with no active instances\n");
538  }
539  return OMX_ErrorNone;
540}
541/* ======================================================================
542FUNCTION
543  OMX_SetupTunnel
544
545DESCRIPTION
546  Not Implemented.
547
548PARAMETERS
549  None
550
551RETURN VALUE
552  None.
553========================================================================== */
554OMX_API OMX_ERRORTYPE OMX_APIENTRY
555OMX_SetupTunnel(OMX_IN OMX_HANDLETYPE outputComponent,
556                OMX_IN OMX_U32             outputPort,
557                OMX_IN OMX_HANDLETYPE  inputComponent,
558                OMX_IN OMX_U32              inputPort)
559{
560  (void) outputComponent, (void) outputPort, (void) inputComponent, (void) inputPort;
561  /* Not supported right now */
562  DEBUG_PRINT("OMXCORE API: OMX_SetupTunnel Not implemented \n");
563  return OMX_ErrorNotImplemented;
564}
565/* ======================================================================
566FUNCTION
567  OMX_GetContentPipe
568
569DESCRIPTION
570  Not Implemented.
571
572PARAMETERS
573  None
574
575RETURN VALUE
576  None.
577========================================================================== */
578OMX_API OMX_ERRORTYPE
579OMX_GetContentPipe(OMX_OUT OMX_HANDLETYPE* pipe,
580                   OMX_IN OMX_STRING        uri)
581{
582  (void) pipe, (void) uri;
583  /* Not supported right now */
584  DEBUG_PRINT("OMXCORE API: OMX_GetContentPipe Not implemented \n");
585  return OMX_ErrorNotImplemented;
586}
587
588/* ======================================================================
589FUNCTION
590  OMX_GetComponentNameEnum
591
592DESCRIPTION
593  Returns the component name associated with the index.
594
595PARAMETERS
596  None
597
598RETURN VALUE
599  None.
600========================================================================== */
601OMX_API OMX_ERRORTYPE OMX_APIENTRY
602OMX_ComponentNameEnum(OMX_OUT OMX_STRING componentName,
603                      OMX_IN  OMX_U32          nameLen,
604                      OMX_IN  OMX_U32            index)
605{
606  OMX_ERRORTYPE eRet = OMX_ErrorNone;
607  DEBUG_PRINT("OMXCORE API - OMX_ComponentNameEnum %p %d %d\n", componentName
608                                                              ,(unsigned)nameLen
609                                                              ,(unsigned)index);
610  if(index < SIZE_OF_CORE)
611  {
612    #ifdef _ANDROID_
613    strlcpy(componentName, core[index].name,nameLen);
614    #else
615    strncpy(componentName, core[index].name,nameLen);
616    #endif
617  }
618  else
619  {
620    eRet = OMX_ErrorNoMore;
621  }
622  return eRet;
623}
624
625/* ======================================================================
626FUNCTION
627  OMX_GetComponentsOfRole
628
629DESCRIPTION
630  Returns the component name which can fulfill the roles passed in the
631  argument.
632
633PARAMETERS
634  None
635
636RETURN VALUE
637  None.
638========================================================================== */
639OMX_API OMX_ERRORTYPE
640OMX_GetComponentsOfRole(OMX_IN OMX_STRING      role,
641                        OMX_INOUT OMX_U32* numComps,
642                        OMX_INOUT OMX_U8** compNames)
643{
644  OMX_ERRORTYPE eRet = OMX_ErrorNone;
645  unsigned i,j,namecount=0;
646
647  printf(" Inside OMX_GetComponentsOfRole \n");
648
649  /*If CompNames is NULL then return*/
650  if (compNames == NULL)
651  {
652      if (numComps == NULL)
653      {
654          eRet = OMX_ErrorBadParameter;
655      }
656      else
657  {
658    *numComps          = 0;
659    for (i=0; i<SIZE_OF_CORE;i++)
660    {
661      for(j=0; j<OMX_CORE_MAX_CMP_ROLES && core[i].roles[j] ; j++)
662      {
663        if(!strcmp(role,core[i].roles[j]))
664        {
665                  (*numComps)++;
666              }
667            }
668          }
669      }
670      return eRet;
671  }
672
673  if(numComps)
674  {
675      namecount = *numComps;
676
677      if (namecount == 0)
678      {
679          return OMX_ErrorBadParameter;
680      }
681
682    *numComps          = 0;
683
684    for (i=0; i<SIZE_OF_CORE;i++)
685    {
686      for(j=0; j<OMX_CORE_MAX_CMP_ROLES && core[i].roles[j] ; j++)
687      {
688        if(!strcmp(role,core[i].roles[j]))
689          {
690            #ifdef _ANDROID_
691            strlcpy((char *)compNames[*numComps],core[i].name, OMX_MAX_STRINGNAME_SIZE);
692            #else
693            strncpy((char *)compNames[*numComps],core[i].name, OMX_MAX_STRINGNAME_SIZE);
694            #endif
695          (*numComps)++;
696          break;
697        }
698      }
699          if (*numComps == namecount)
700          {
701          break;
702        }
703    }
704  }
705  else
706  {
707    eRet = OMX_ErrorBadParameter;
708  }
709
710  printf(" Leaving OMX_GetComponentsOfRole \n");
711  return eRet;
712}
713/* ======================================================================
714FUNCTION
715  OMX_GetRolesOfComponent
716
717DESCRIPTION
718  Returns the primary role of the components supported.
719
720PARAMETERS
721  None
722
723RETURN VALUE
724  None.
725========================================================================== */
726OMX_API OMX_ERRORTYPE
727OMX_GetRolesOfComponent(OMX_IN OMX_STRING compName,
728                        OMX_INOUT OMX_U32* numRoles,
729                        OMX_OUT OMX_U8** roles)
730{
731  /* Not supported right now */
732  OMX_ERRORTYPE eRet = OMX_ErrorNone;
733  unsigned i,j,numofroles = 0;;
734  DEBUG_PRINT("GetRolesOfComponent %s\n",compName);
735
736  if (roles == NULL)
737  {
738      if (numRoles == NULL)
739      {
740         eRet = OMX_ErrorBadParameter;
741      }
742      else
743      {
744         *numRoles = 0;
745         for(i=0; i< SIZE_OF_CORE; i++)
746         {
747           if(!strcmp(compName,core[i].name))
748           {
749             for(j=0; (j<OMX_CORE_MAX_CMP_ROLES) && core[i].roles[j];j++)
750             {
751                (*numRoles)++;
752             }
753             break;
754           }
755         }
756
757      }
758      return eRet;
759  }
760
761  if(numRoles)
762  {
763    if (*numRoles == 0)
764    {
765        return OMX_ErrorBadParameter;
766    }
767
768    numofroles = *numRoles;
769    *numRoles = 0;
770    for(i=0; i< SIZE_OF_CORE; i++)
771    {
772      if(!strcmp(compName,core[i].name))
773      {
774        for(j=0; (j<OMX_CORE_MAX_CMP_ROLES) && core[i].roles[j];j++)
775        {
776          if(roles && roles[*numRoles])
777          {
778            #ifdef _ANDROID_
779            strlcpy((char *)roles[*numRoles],core[i].roles[j],OMX_MAX_STRINGNAME_SIZE);
780            #else
781            strncpy((char *)roles[*numRoles],core[i].roles[j],OMX_MAX_STRINGNAME_SIZE);
782            #endif
783          }
784          (*numRoles)++;
785          if (numofroles == *numRoles)
786          {
787              break;
788          }
789        }
790        break;
791      }
792    }
793  }
794  else
795  {
796    DEBUG_PRINT("ERROR: Both Roles and numRoles Invalid\n");
797    eRet = OMX_ErrorBadParameter;
798  }
799  return eRet;
800}
801
802OMX_API OMX_BOOL
803OMXConfigParser(
804    OMX_PTR aInputParameters,
805    OMX_PTR aOutputParameters)
806{
807    OMX_BOOL Status = OMX_TRUE;
808    VideoOMXConfigParserOutputs *aOmxOutputParameters;
809    OMXConfigParserInputs *aOmxInputParameters;
810    aOmxOutputParameters = (VideoOMXConfigParserOutputs *)aOutputParameters;
811    aOmxInputParameters = (OMXConfigParserInputs *)aInputParameters;
812
813    aOmxOutputParameters->width = 176; //setting width to QCIF
814    aOmxOutputParameters->height = 144; //setting height to QCIF
815
816    //TODO
817    //Qcom component do not use the level/profile from IL client .They are parsing the first buffer
818    //sent in ETB so for now setting the defalut values . Going farward we can call
819    //QC parser here.
820    if (0 == strcmp(aOmxInputParameters->cComponentRole, (OMX_STRING)"video_decoder.avc"))
821    {
822       aOmxOutputParameters->profile = 66; //minimum supported h264 profile - setting to baseline profile
823       aOmxOutputParameters->level = 0;  // minimum supported h264 level
824    }
825    else if ((0 == strcmp(aOmxInputParameters->cComponentRole, (OMX_STRING)"video_decoder.mpeg4")) || (0 == strcmp(aOmxInputParameters ->cComponentRole, (OMX_STRING)"video_decoder.h263")))
826    {
827       aOmxOutputParameters->profile = 8; //minimum supported h263/mpeg4 profile
828       aOmxOutputParameters->level = 0; // minimum supported h263/mpeg4 level
829    }
830
831    return Status;
832}
833