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 %x %s %x\n",(unsigned) handle,
405                                                     componentName,
406                                                     (unsigned) 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 %x Successfully created\n",(unsigned)*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 %x\n",(unsigned) 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 < 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 %x\n",(unsigned) 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  /* Not supported right now */
561  DEBUG_PRINT("OMXCORE API: OMX_SetupTunnel Not implemented \n");
562  return OMX_ErrorNotImplemented;
563}
564/* ======================================================================
565FUNCTION
566  OMX_GetContentPipe
567
568DESCRIPTION
569  Not Implemented.
570
571PARAMETERS
572  None
573
574RETURN VALUE
575  None.
576========================================================================== */
577OMX_API OMX_ERRORTYPE
578OMX_GetContentPipe(OMX_OUT OMX_HANDLETYPE* pipe,
579                   OMX_IN OMX_STRING        uri)
580{
581  /* Not supported right now */
582  DEBUG_PRINT("OMXCORE API: OMX_GetContentPipe Not implemented \n");
583  return OMX_ErrorNotImplemented;
584}
585
586/* ======================================================================
587FUNCTION
588  OMX_GetComponentNameEnum
589
590DESCRIPTION
591  Returns the component name associated with the index.
592
593PARAMETERS
594  None
595
596RETURN VALUE
597  None.
598========================================================================== */
599OMX_API OMX_ERRORTYPE OMX_APIENTRY
600OMX_ComponentNameEnum(OMX_OUT OMX_STRING componentName,
601                      OMX_IN  OMX_U32          nameLen,
602                      OMX_IN  OMX_U32            index)
603{
604  OMX_ERRORTYPE eRet = OMX_ErrorNone;
605  DEBUG_PRINT("OMXCORE API - OMX_ComponentNameEnum %x %d %d\n",(unsigned) componentName
606                                                              ,(unsigned)nameLen
607                                                              ,(unsigned)index);
608  if(index < SIZE_OF_CORE)
609  {
610    #ifdef _ANDROID_
611    strlcpy(componentName, core[index].name,nameLen);
612    #else
613    strncpy(componentName, core[index].name,nameLen);
614    #endif
615  }
616  else
617  {
618    eRet = OMX_ErrorNoMore;
619  }
620  return eRet;
621}
622
623/* ======================================================================
624FUNCTION
625  OMX_GetComponentsOfRole
626
627DESCRIPTION
628  Returns the component name which can fulfill the roles passed in the
629  argument.
630
631PARAMETERS
632  None
633
634RETURN VALUE
635  None.
636========================================================================== */
637OMX_API OMX_ERRORTYPE
638OMX_GetComponentsOfRole(OMX_IN OMX_STRING      role,
639                        OMX_INOUT OMX_U32* numComps,
640                        OMX_INOUT OMX_U8** compNames)
641{
642  OMX_ERRORTYPE eRet = OMX_ErrorNone;
643  unsigned i,j,namecount=0;
644
645  printf(" Inside OMX_GetComponentsOfRole \n");
646
647  /*If CompNames is NULL then return*/
648  if (compNames == NULL)
649  {
650      if (numComps == NULL)
651      {
652          eRet = OMX_ErrorBadParameter;
653      }
654      else
655  {
656    *numComps          = 0;
657    for (i=0; i<SIZE_OF_CORE;i++)
658    {
659      for(j=0; j<OMX_CORE_MAX_CMP_ROLES && core[i].roles[j] ; j++)
660      {
661        if(!strcmp(role,core[i].roles[j]))
662        {
663                  (*numComps)++;
664              }
665            }
666          }
667      }
668      return eRet;
669  }
670
671  if(numComps)
672  {
673      namecount = *numComps;
674
675      if (namecount == 0)
676      {
677          return OMX_ErrorBadParameter;
678      }
679
680    *numComps          = 0;
681
682    for (i=0; i<SIZE_OF_CORE;i++)
683    {
684      for(j=0; j<OMX_CORE_MAX_CMP_ROLES && core[i].roles[j] ; j++)
685      {
686        if(!strcmp(role,core[i].roles[j]))
687          {
688            #ifdef _ANDROID_
689            strlcpy((char *)compNames[*numComps],core[i].name, OMX_MAX_STRINGNAME_SIZE);
690            #else
691            strncpy((char *)compNames[*numComps],core[i].name, OMX_MAX_STRINGNAME_SIZE);
692            #endif
693          (*numComps)++;
694          break;
695        }
696      }
697          if (*numComps == namecount)
698          {
699          break;
700        }
701    }
702  }
703  else
704  {
705    eRet = OMX_ErrorBadParameter;
706  }
707
708  printf(" Leaving OMX_GetComponentsOfRole \n");
709  return eRet;
710}
711/* ======================================================================
712FUNCTION
713  OMX_GetRolesOfComponent
714
715DESCRIPTION
716  Returns the primary role of the components supported.
717
718PARAMETERS
719  None
720
721RETURN VALUE
722  None.
723========================================================================== */
724OMX_API OMX_ERRORTYPE
725OMX_GetRolesOfComponent(OMX_IN OMX_STRING compName,
726                        OMX_INOUT OMX_U32* numRoles,
727                        OMX_OUT OMX_U8** roles)
728{
729  /* Not supported right now */
730  OMX_ERRORTYPE eRet = OMX_ErrorNone;
731  unsigned i,j,numofroles = 0;;
732  DEBUG_PRINT("GetRolesOfComponent %s\n",compName);
733
734  if (roles == NULL)
735  {
736      if (numRoles == NULL)
737      {
738         eRet = OMX_ErrorBadParameter;
739      }
740      else
741      {
742         *numRoles = 0;
743         for(i=0; i< SIZE_OF_CORE; i++)
744         {
745           if(!strcmp(compName,core[i].name))
746           {
747             for(j=0; (j<OMX_CORE_MAX_CMP_ROLES) && core[i].roles[j];j++)
748             {
749                (*numRoles)++;
750             }
751             break;
752           }
753         }
754
755      }
756      return eRet;
757  }
758
759  if(numRoles)
760  {
761    if (*numRoles == 0)
762    {
763        return OMX_ErrorBadParameter;
764    }
765
766    numofroles = *numRoles;
767    *numRoles = 0;
768    for(i=0; i< SIZE_OF_CORE; i++)
769    {
770      if(!strcmp(compName,core[i].name))
771      {
772        for(j=0; (j<OMX_CORE_MAX_CMP_ROLES) && core[i].roles[j];j++)
773        {
774          if(roles && roles[*numRoles])
775          {
776            #ifdef _ANDROID_
777            strlcpy((char *)roles[*numRoles],core[i].roles[j],OMX_MAX_STRINGNAME_SIZE);
778            #else
779            strncpy((char *)roles[*numRoles],core[i].roles[j],OMX_MAX_STRINGNAME_SIZE);
780            #endif
781          }
782          (*numRoles)++;
783          if (numofroles == *numRoles)
784          {
785              break;
786          }
787        }
788        break;
789      }
790    }
791  }
792  else
793  {
794    DEBUG_PRINT("ERROR: Both Roles and numRoles Invalid\n");
795    eRet = OMX_ErrorBadParameter;
796  }
797  return eRet;
798}
799
800OMX_API OMX_BOOL
801OMXConfigParser(
802    OMX_PTR aInputParameters,
803    OMX_PTR aOutputParameters)
804{
805    OMX_BOOL Status = OMX_TRUE;
806    VideoOMXConfigParserOutputs *aOmxOutputParameters;
807    OMXConfigParserInputs *aOmxInputParameters;
808    aOmxOutputParameters = (VideoOMXConfigParserOutputs *)aOutputParameters;
809    aOmxInputParameters = (OMXConfigParserInputs *)aInputParameters;
810
811    aOmxOutputParameters->width = 176; //setting width to QCIF
812    aOmxOutputParameters->height = 144; //setting height to QCIF
813
814    //TODO
815    //Qcom component do not use the level/profile from IL client .They are parsing the first buffer
816    //sent in ETB so for now setting the defalut values . Going farward we can call
817    //QC parser here.
818    if (0 == strcmp(aOmxInputParameters->cComponentRole, (OMX_STRING)"video_decoder.avc"))
819    {
820       aOmxOutputParameters->profile = 66; //minimum supported h264 profile - setting to baseline profile
821       aOmxOutputParameters->level = 0;  // minimum supported h264 level
822    }
823    else if ((0 == strcmp(aOmxInputParameters->cComponentRole, (OMX_STRING)"video_decoder.mpeg4")) || (0 == strcmp(aOmxInputParameters ->cComponentRole, (OMX_STRING)"video_decoder.h263")))
824    {
825       aOmxOutputParameters->profile = 8; //minimum supported h263/mpeg4 profile
826       aOmxOutputParameters->level = 0; // minimum supported h263/mpeg4 level
827    }
828
829    return Status;
830}
831