OMX_ErrorHardware which is 0x80001009 is returned from OMX_GetHandle

Hi all,

On tablet with OMAP4 processor, when try to use hardware Codec by calling TI component, we found OMX_ErrorHardware which is 0x80001009 is returned from OMX_GetHandle.

We use following steps in native code:

1) dlopen /system/lib/libOMX_Core.so

2) dlsym OMX_Init, OMX_GetHandle from 1)

3) call OMX_Init and OMX_GetHandle ..

Components we tried are OMX.TI.DUCATI1.VIDEO.DECODER and OMX.TI.DUCATI1.VIDEO.H264E. Os version is Android 4.0.1

But returned value from OMX_GetHandle is OMX_ErrorHardware which is 0x80001009.

Why calling OMX component is failed on TI component? Does anyone have suggestions about how to call TI component in native code? Thx.

regards,

guangx

  • guang xu;

    You could take a look at code in next location and use it like reference,

    ./4ai/4AI.1.2/mydroid/hardware/ti/omap4xxx/libstagefrighthw

    it is 4AI but i think it is in IS2 too, what release are you working on?

    http://omapedia.org/wiki/L27.IS.2.P2_OMAP4_Icecream_Sandwich_Release_Notes

    http://omapedia.org/wiki/4AI.1.2_OMAP4_Icecream_Sandwich_Release_Notes

    you will need to add -ldl and a #include <dlfcn.h> in order to use dynamic loading library,

    if it doesn't help it would be great if you share a log to trace the error back,

    please take in consideration next information in case it applies to your case;

    http://source.android.com/tech/security/index.html#android-application-security

    http://source.android.com/tech/security/index.html#the-android-permission-model-accessing-protected-apis

    http://developer.android.com/guide/practices/security.html#DynamicCode

  • In reply to Manuel Contreras:

    Code for libstagefrighthw library is used in

    ./4ai/4AI.1.1/mydroid/frameworks/base/media/libstagefright/omx/OMXMaster.cpp

    it could help to find out some more information on how to call the functions.

    another code approach is the code in next link (for ICS/4AI)

    http://review.omapzoom.org/#/c/14814/

  • In reply to Manuel Contreras:

    Hi Manuel,

    Thanks for your reply.

    I have read code of stagefright lib. We try to use same calling sequence to call API of TI component in our code.

    Our code is native code. In our code, we don't want to use framwork of libstagefright. There is no code to call MediaService.

    1) I doubt if there is some permission setting in androidManifest.xml need to do.

    2) If RPC/IPC is used in implementation of TI component, should we add some initilization for some system mechanism in code?

     

    regards,

    guangx

  • In reply to guang xu:

    Guang Xu;

    There is some missing information but i going to try to fill the gap, i haven't seen full error log, 0x80001009 can be returned by almost at any part of OMX code, and i haven't read your actual code.

    One point to consider is that you are trying to use dynamic loading, then to access OMX_Core library you require correct .mk file, some examples are in the NDK

    depending if you want o use it like library or executable;
    ./android-ndk-r7b/samples/san-angeles
    ./android-ndk-r7b/tests/device/whole-static-libs

    other option in case you need to use C++ library you can use code in next location
    ./4ai/4AI.1.1/mydroid/device/sample

    this library is compiled like part of the system inside frameworks/base, you can find all instructions in README.txt files inside samples folder, each folder or project has it's own README.txt. An example of using C++ is the OMX_Plugin it is in .cpp file. NDK select C++ or C base in file extension if it is not indicated other thing.

    about this;

    ./android-ndk-r7b/docs/STABLE-APIS.html
    Dynamic Linker Library:
    -----------------------
    <dlfcn.h> is available and can be used to use the dlopen()/dlsym()/dlclose()
    functions provided by the Android dynamic linker. You will need to link
    against /system/lib/libdl.so with:
      LOCAL_LDLIBS := -ldl

    libstagefrighthw library is below or part of Media Service, they call from OMXMaster.cpp it can be used to read the way OMX_Core is loaded, and this library is on top of OMX_Core that is similar to what you are doing.

    Did you considered the use of OpenMax AL? it is added in Android 4.0.

    ./android-ndk-r7b/docs/openmaxal/index.html

    ./android-ndk-r7b/docs/openmaxal/OpenMAX_AL_1_0_1_Specification.pdf

    about 1)

    About the security links, i added them because if your actual user doesn't have correct permission it could not be passing some of the security layers that Android offers and the way they are propagated by all layers, from .apk to .jar/.so to kernel, that is explained in those links.

    about 2)

    It must access it by the dynamic library use (it is not static linking), you are accessing OMX_Core directly by OpenMax IL spec that is the meaning of it, provide a common interface, what is great of it  - i think.

    if you are referring to RPC/IPC from Android system and shared security links? they are the Android's interface to System resources from regular user apk/UI, for example in order to propagate the permission from a AndroidManifest.xml to all the layers down the device they mention that creating a system service and accessing/connecting to it using IPC, examples of this are MediaService, AudioFlinger, and PowerManagerService, among others services, and Android provides an interface to these services using Android's SDK/NDK.

    http://source.android.com/tech/security/index.html
    http://developer.android.com/guide/topics/security/security.html
    http://developer.android.com/guide/practices/security.html
    http://developer.android.com/guide/developing/tools/aidl.html

  • In reply to Manuel Contreras:

    Hi Manuel,

    Thx for your reply at first.

    1. Here is my code in cpp file, in MK file -ldl is used

      m_pOMXModule = dlopen(/system/lib/libOMX_Core.so, RTLD_LAZY);  //open omx library

      m_pfOMX_Init = (OMX_Init_Type)(dlsym(m_pOMXModule, "OMX_Init"));
      m_pfOMX_DeInit = (OMX_DeInit_Type)(dlsym(m_pOMXModule, "OMX_Deinit"));
      m_pfOMX_ComponentNameEnum = (OMX_ComponentNameEnum_Type)(dlsym(m_pOMXModule,"OMX_ComponentNameEnum"));
      m_pfOMX_GetRolesOfComponent = (OMX_GetRolesOfComponent_Type)(dlsym(m_pOMXModule, "OMX_GetRolesOfComponent"));
      m_pfOMX_GetHandle = (OMX_GetHandle_Type)(dlsym(m_pOMXModule, "OMX_GetHandle"));
      m_pfOMX_FreeHandel = (OMX_FreeHandle_Type)(dlsym(m_pOMXModule, "OMX_FreeHandle"));
      m_pfOMX_GetComponentsOfRole = (OMX_GetComponentsOfRole_Type)(dlsym(m_pOMXModule, "OMX_GetComponentsOfRole"));
    ......................................

    eError =m_pfOMX_Init();

    .........

    //call  m_pfOMX_ComponentNameEnum

    //call  m_pfOMX_GetComponentsOfRole

     ........................................

     m_videodeccallbacks.EventHandler         = TI_videodecEventHandler;
     m_videodeccallbacks.EmptyBufferDone  = TI_videodecEmptyBufferDone;
     m_videodeccallbacks.FillBufferDone       = TI_videodecFillBufferDone;

    eError =m_pfOMX_GetHandle(&(m_componentHandle), "OMX.TI.DUCATI1.VIDEO.DECODER",
       this, &(m_videodeccallbacks));

    from m_pfOMX_GetHandle there is error return, error is  0x80001009

    2. here is the trace information

    03-30 00:55:06.075: DEBUG/TRY_OMX(13237): ------------try to list component or roles on this device---------
    03-30 00:55:06.075: DEBUG/TRY_OMX(13237): component [ 0] name:OMX.TI.DUCATI1.VIDEO.DECODER
    03-30 00:55:06.075: DEBUG/TRY_OMX(13237): -->its role [ 0] name:video_decoder.mpeg4
    03-30 00:55:06.075: DEBUG/TRY_OMX(13237): -->its role [ 1] name:video_decoder.avc
    03-30 00:55:06.075: DEBUG/TRY_OMX(13237): -->its role [ 2] name:video_decoder.h263
    03-30 00:55:06.075: DEBUG/TRY_OMX(13237): -->its role [ 3] name:video_decoder.wmv
    03-30 00:55:06.075: DEBUG/TRY_OMX(13237): -->its role [ 4] name:video_decoder.mpeg2
    03-30 00:55:06.075: DEBUG/TRY_OMX(13237): -->its role [ 5] name:video_decoder.vp6
    03-30 00:55:06.075: DEBUG/TRY_OMX(13237): -->its role [ 6] name:video_decoder.vp7
    03-30 00:55:06.075: DEBUG/TRY_OMX(13237): component [ 1] name:OMX.TI.DUCATI1.VIDEO.DECODER.secure
    03-30 00:55:06.075: DEBUG/TRY_OMX(13237): -->its role [ 0] name:video_decoder.mpeg4
    03-30 00:55:06.075: DEBUG/TRY_OMX(13237): -->its role [ 1] name:video_decoder.avc
    03-30 00:55:06.075: DEBUG/TRY_OMX(13237): -->its role [ 2] name:video_decoder.h263
    03-30 00:55:06.075: DEBUG/TRY_OMX(13237): component [ 2] name:OMX.TI.DUCATI1.VIDEO.H264D
    03-30 00:55:06.075: DEBUG/TRY_OMX(13237): -->its role [ 0] name:video_decoder.avc
    03-30 00:55:06.075: DEBUG/TRY_OMX(13237): component [ 3] name:OMX.TI.DUCATI1.VIDEO.H264E
    03-30 00:55:06.075: DEBUG/TRY_OMX(13237): -->its role [ 0] name:video_encoder.avc
    03-30 00:55:06.075: DEBUG/TRY_OMX(13237): component [ 4] name:OMX.TI.DUCATI1.VIDEO.MPEG4D
    03-30 00:55:06.075: DEBUG/TRY_OMX(13237): -->its role [ 0] name:video_decoder.mpeg4
    03-30 00:55:06.075: DEBUG/TRY_OMX(13237): component [ 5] name:OMX.TI.DUCATI1.VIDEO.MPEG4E
    03-30 00:55:06.075: DEBUG/TRY_OMX(13237): -->its role [ 0] name:video_encoder.mpeg4
    03-30 00:55:06.075: DEBUG/TRY_OMX(13237): -->its role [ 1] name:video_encoder.h263
    03-30 00:55:06.075: DEBUG/TRY_OMX(13237): component [ 6] name:OMX.TI.DUCATI1.VIDEO.VP6D
    03-30 00:55:06.075: DEBUG/TRY_OMX(13237): -->its role [ 0] name:video_decoder.vp6
    03-30 00:55:06.075: DEBUG/TRY_OMX(13237): component [ 7] name:OMX.TI.DUCATI1.VIDEO.VP7D
    03-30 00:55:06.075: DEBUG/TRY_OMX(13237): -->its role [ 0] name:video_decoder.vp7
    03-30 00:55:06.075: DEBUG/TRY_OMX(13237): component [ 8] name:OMX.TI.DUCATI1.IMAGE.JPEGD
    03-30 00:55:06.075: DEBUG/TRY_OMX(13237): -->its role [ 0] name:jpeg_decoder.jpeg
    03-30 00:55:06.075: DEBUG/TRY_OMX(13237): component [ 9] name:OMX.TI.DUCATI1.VIDEO.CAMERA
    03-30 00:55:06.075: DEBUG/TRY_OMX(13237): -->its role [ 0] name:camera.omx
    03-30 00:55:06.075: DEBUG/TRY_OMX(13237): component [10] name:OMX.ITTIAM.WMA.decode
    03-30 00:55:06.075: DEBUG/TRY_OMX(13237): -->its role [ 0] name:audio_decoder.wma
    03-30 00:55:06.075: DEBUG/TRY_OMX(13237): component [11] name:OMX.ITTIAM.WMALSL.decode
    03-30 00:55:06.075: DEBUG/TRY_OMX(13237): -->its role [ 0] name:audio_decoder.wmalsl
    03-30 00:55:06.083: DEBUG/TRY_OMX(13237): component [12] name:OMX.ITTIAM.WMAPRO.decode
    03-30 00:55:06.083: DEBUG/TRY_OMX(13237): -->its role [ 0] name:audio_decoder.wmapro
    03-30 00:55:06.083: DEBUG/TRY_OMX(13237): ------------------------------------
    03-30 00:55:06.083: DEBUG/TRY_OMX(13237): For Role:video_decoder.avc
    03-30 00:55:06.083: DEBUG/TRY_OMX(13237): -->its component [ 0] name:OMX.TI.DUCATI1.VIDEO.DECODER
    03-30 00:55:06.083: DEBUG/TRY_OMX(13237): -->its component [ 1] name:OMX.TI.DUCATI1.VIDEO.DECODER.secure
    03-30 00:55:06.083: DEBUG/TRY_OMX(13237): -->its component [ 2] name:OMX.TI.DUCATI1.VIDEO.H264D
    03-30 00:55:06.083: DEBUG/TRY_OMX(13237): ------------------------------------
    03-30 00:55:06.114: DEBUG/TRY_OMX(13237): int init(),  OMX_GetHandle failed, eError:800010093. others

    3. I also tried to call OMX_ComponentInit as following like code in OMX_GetHandle function in OMX_Core.c. After calling OMX_ComponentInit error is also 80001009.

      static const char prefix[] = "lib";
      static const char postfix[] = ".so";
      char buf[256];
      void *pfile = NULL;
      typedef  OMX_ERRORTYPE OMX_APIENTRY (*OMX_ComponentInit_Type)(OMX_HANDLETYPE* handle);

      OMX_ComponentInit_Type pComponentInit;

      strcpy(buf, prefix);                      /* the lengths are defined herein or have been */
      strcat(buf, "OMX.TI.DUCATI1.VIDEO.DECODER");  /* checked already, so strcpy and strcat are  */
      strcat(buf, postfix);                      /* are safe to use in this context. */

     pfile = dlopen(buf, RTLD_NOW);//RTLD_LAZY | RTLD_GLOBAL);
     if (pfile == NULL)
     {
           __android_log_print(ANDROID_LOG_DEBUG, "TRY_OMX", "---------dlopen path:%s failed", buf);
     }
     else
     {
           __android_log_print(ANDROID_LOG_DEBUG, "TRY_OMX", "---------dlopen path:%s succssfully", buf);
     }

     pComponentInit = (OMX_ComponentInit_Type)dlsym(pfile, "OMX_ComponentInit");
     if (pComponentInit != NULL)
     {

            eError = pComponentInit(&m_componentHandle);
     
             __android_log_print(ANDROID_LOG_DEBUG, "TRY_OMX", "---------OMX_ComponentInit result:%x", eError);
     }
     else
     {
              __android_log_print(ANDROID_LOG_DEBUG, "TRY_OMX", "---------OMX_ComponentInit is null");
     }

    ----------------------------------------------------------------------------------------------------

    We are looking forward to your reply. thx

    regards,

    guangx

  • In reply to guang xu:

    guangx;

    change from .cpp to .c, you are getting to compile phase then this step could not be needed from your side, just check that variables and funtions for JNIEnv are correctly used; Android NDK selects between C++ and C using file extension.

    added next includes to .c file
    #include <android/log.h>
    #include <OMX_Core.h>
    #include <dlfcn.h>

    and copied OMX headers to the same code folder than .c file, and defined my own applications data pointer to

    static struct mystruct{
        OMX_U32 mydata;
    } mystructdata;

    I am using you code plus added function prototypes and 3 functions used for OMX_CALLBACKTYPE, and function prototypes for pointers to functions to be used for dlsym.

    added variable definitions
        OMX_ERRORTYPE eError = OMX_ErrorNone;
        OMX_HANDLETYPE m_componentHandle = NULL;

    added "" to library name
        m_pOMXModule = dlopen("/system/lib/libOMX_Core.so", RTLD_LAZY);

    removed next code from lines, i don't have those defined, i think you use them to cast functions and have their definitions.
    (OMX_Init_Type)
    (OMX_DeInit_Type)
    (OMX_ComponentNameEnum_Type)
    (OMX_GetRolesOfComponent_Type)
    (OMX_GetHandle_Type)
    (OMX_FreeHandle_Type)
    (OMX_GetComponentsOfRole_Type)

    and modified calling OMX_GetHandle to use mystructdata, this because i am using .c instead of .cpp and this is not defined in my case

        eError =m_pfOMX_GetHandle(&(m_componentHandle), "OMX.TI.DUCATI1.VIDEO.DECODER",
           &mystructdata, &(m_videodeccallbacks));

    and for Android.mk it's contents are

    ////////////////////////////////////////////////////////////////
    include $(CLEAR_VARS)

    LOCAL_MODULE    := nativeapp
    LOCAL_SRC_FILES := native.c
    LOCAL_LDLIBS := -ldl  -llog
    LOCAL_MODULE_TAGS := optional
    LOCAL_CFLAGS := -DANDROID_NDK

    include $(BUILD_EXECUTABLE)

    ////////////////////////////////////////////////////////////////

    one difference is about LOCAL_MODULE_TAGS, this is used to indicate where the binary is going to run, it needs to match with your actual development environment.

    and i am not getting the error, can you try those modifications at your side?

    there are more options to build an native binary in NDK, i used BUILD_EXECUTABLE, just try to check about this for your specific case.

  • In reply to Manuel Contreras:

    Hi Manuel,

    Thanks for your detailed help. I can get handle successfully only in running binary by command line as root account. 

    My another question is why get handle is unsuccessfully by calling OMX IL API if our calling code is compiled into shared lib in using BUILD_SHARED_LIBRARY in MK file? What priviledge or enviroment setting we need to do if we want to get handle succssfully and we want to compile our code into shared lib not exe file? Thx

    regards,

    guangx

  • In reply to guang xu:

    Guang Xu;

    About root user, I am using "adb kill-server" and root user to run "adb root" and "adb remount" to push the naitve library and binary to device, that is giving me root privileges from "adb shell" when running native binary this matches with what you are seeing.

    After restarting the device and ran the same commands it is failing in OMX_GetHandle the same.

    By modifying the native code to run like library and creating a new native binary to access it, they are running ok,

    by using your shared code inside the library,

    void main_run (OMX_CALLBACKTYPE *m_videodeccallbacks_in, OMX_PTR pAppData_in){
        __android_log_print(ANDROID_LOG_DEBUG, "TRY_OMX", "inside library\n");
        OMX_ERRORTYPE eError = OMX_ErrorNone;
        OMX_HANDLETYPE m_componentHandle = NULL;
        m_pOMXModule = dlopen("/system/lib/libOMX_Core.so", RTLD_LAZY);
        m_pfOMX_Init = (dlsym(m_pOMXModule, "OMX_Init"));
        m_pfOMX_DeInit = (dlsym(m_pOMXModule, "OMX_Deinit"));
        m_pfOMX_ComponentNameEnum = (dlsym(m_pOMXModule,"OMX_ComponentNameEnum"));
        m_pfOMX_GetRolesOfComponent = (dlsym(m_pOMXModule, "OMX_GetRolesOfComponent"));
        m_pfOMX_GetHandle = (dlsym(m_pOMXModule, "OMX_GetHandle"));
        m_pfOMX_FreeHandel = (dlsym(m_pOMXModule, "OMX_FreeHandle"));
        m_pfOMX_GetComponentsOfRole = (dlsym(m_pOMXModule, "OMX_GetComponentsOfRole"));
        __android_log_print(ANDROID_LOG_DEBUG, "TRY_OMX", "---------OMX_ComponentInit");
        eError =m_pfOMX_Init();
        __android_log_print(ANDROID_LOG_DEBUG, "TRY_OMX", "---------OMX_ComponentInit result:%x", eError);
        __android_log_print(ANDROID_LOG_DEBUG, "TRY_OMX", "---------m_pfOMX_GetHandle");
        eError =m_pfOMX_GetHandle(&(m_componentHandle), "OMX.TI.DUCATI1.VIDEO.DECODER",
           pAppData_in, (m_videodeccallbacks_in));
        __android_log_print(ANDROID_LOG_DEBUG, "TRY_OMX", "---------m_pfOMX_GetHandle:%x", eError);
        eError =m_pfOMX_FreeHandel((m_componentHandle));
        eError =m_pfOMX_DeInit();
        __android_log_print(ANDROID_LOG_DEBUG, "TRY_OMX", "going outside library\n");
    }

    and calling it from native binary code

    void main (int argc, char*  argv[]){
        __android_log_print(ANDROID_LOG_DEBUG, "TRY_OMX", "inside main_use\n");
        OMX_ERRORTYPE eError = OMX_ErrorNone;
        m_pOMXModule = dlopen("/system/lib/libhello-jni.so", RTLD_LAZY);
        m_main_use = (dlsym(m_pOMXModule, "main_run"));
        __android_log_print(ANDROID_LOG_DEBUG, "TRY_OMX", "---------setting callbacks:%x", eError);
        m_videodeccallbacks.EventHandler         = TI_videodecEventHandler;
        m_videodeccallbacks.EmptyBufferDone  = TI_videodecEmptyBufferDone;
        m_videodeccallbacks.FillBufferDone       = TI_videodecFillBufferDone;
        __android_log_print(ANDROID_LOG_DEBUG, "TRY_OMX", "---------m_main_use");
        m_main_use(&m_videodeccallbacks,&mystructdata);
        __android_log_print(ANDROID_LOG_DEBUG, "TRY_OMX", "going outside main_use\n");
    }

    I replaced the passed pointers to match with arguments and used definitions, not tried to process buffers yet to check if this approach is correct,

    m_main_use(&m_videodeccallbacks,&mystructdata);

    from

       eError =m_pfOMX_GetHandle(&(m_componentHandle), "OMX.TI.DUCATI1.VIDEO.DECODER",
           &mystructdata, &(m_videodeccallbacks_in));

    to

        eError =m_pfOMX_GetHandle(&(m_componentHandle), "OMX.TI.DUCATI1.VIDEO.DECODER",
           pAppData_in, (m_videodeccallbacks_in));

    output log is

    D/TRY_OMX (  929): inside main_use
    D/TRY_OMX (  929): ---------setting callbacks:0
    D/TRY_OMX (  929): ---------m_main_use
    D/TRY_OMX (  929): inside library
    D/TRY_OMX (  929): ---------OMX_ComponentInit
    D/TRY_OMX (  929): ---------OMX_ComponentInit result:0
    D/TRY_OMX (  929): ---------m_pfOMX_GetHandle
    D/TRY_OMX (  929): ---------m_pfOMX_GetHandle:0
    D/TRY_OMX (  929): going outside library
    D/TRY_OMX (  929): going outside main_use

    copying from Android.com for a direct reference to text

    about Security access and from my point of view, next is an explanation of previously shared links,

    in next link

    http://source.android.com/tech/security/index.html

    it is explained the different security layers that Android provides, from SandBox at Kernel access to AndroidManifest.xml in .apk calls,

    http://source.android.com/tech/security/index.html#the-android-permission-model-accessing-protected-apis

    they mention that there are many APIs to use in order to access system resources, regular user doesn't have regular access to tehm and that these permissions are granted using system properties or Manifest permissions.

    going down in the AFS thes permission are being propagated and used by the application itself, for OMX_Core there was no specific API until OpenMax AL that was released in Android 4.0, Android NDK offers access to this API that connects to OpenMax IL that is actual matter, and offers correct permissions using AndroidManifest.xml.

    http://developer.android.com/guide/practices/security.html

    http://developer.android.com/guide/practices/security.html#DynamicCode

    Dynamic Code links talks about the permission that an .apk gets from running dynamic code, it uses the same permissions that current user, in our case that means that it will not get OMX_Core access because of system restrictions and what is mentioned in this link about security features.

    going back to security/index.html information they mention that the way to access system resources is by using system services, that counts with enough permissions to access them, one way to access OMX_Core is by using those resources that one is OpenMax AL, other is using MediaPlayerService that is accessed by MediaPlayer/VideoView code that accesses StageFright and then OMX_Core, connecting to MediaPlayerService using MediaPlayer object;

    i haven't finished reading/understanding next patch/code yet, but i think it is one example of accessing MediaPlayerService using MediaPlayer and getting inheritance  from the  system that i think is great approach from native code by connecting to MediaPlayerService, giving some more flexibility and how to handle objects.

    http://review.omapzoom.org/#/c/14814/

    If you are regular user and what to access a native library in a dynamic way (using APK or regular user) by what is in previous links that is not possible, one reason is that APK is going to have regular user permissions to access system resources and adding permissions to AndroidManifest.xml used by the native apk is not going to allow it. An example of this could be using a platform library that counts with a Manifest and declares the permissions to correctly access the library from an APK, this access to library is granted but the access to system resources is not granted even if all HW permissions are in code.

    Other option that I don't know if it is allowed or not, and if you need to access OMX_Core directly, is to add a new service to the system with all the security features and permissions added to it, these in order to propagate correct permissions for all system layers, this implies that thread process is going to run as service, that you can define it from using a service object and start it with proper configuration, adding all the needed interfaces between .apk/.java/.cpp/.c code between layers to reach the point you need, considering that it is going to be a contact point similar/[in parallel] to MediaPlayerService that interconnects Video/Audio/Surfaces/Overlay/etc... and other system resources needed to play a video file (i mean if needed, it could be only a service that uses OMX_Core features), and adding a Binder/IPC code to connect to it, plus the client code that is going to load the file and do similar job to MediaPlayer. In this the service is going to run like root or system enough to access system resources and communicate to this using Binder/IPC like described in next link.

    http://developer.android.com/guide/topics/fundamentals/bound-services.html

    http://developer.android.com/guide/topics/fundamentals/bound-services.html#Binder

    http://developer.android.com/guide/developing/tools/aidl.html

    Matter to check if using "am" command or creating a APK to runs like service is getting correct permissions, and to check if system allows HW access, if that is not the case then it will require to add them in init.rc or if needs to be a part of the ALL system started from init/Zygote.

    some useful links related to this are

    ./mydroid/system/core/init/readme.txt

    http://developer.android.com/guide/topics/fundamentals/services.html

    http://developer.android.com/reference/android/app/Service.html

    http://android-developers.blogspot.com/2010/02/service-api-changes-starting-with.html

    http://elinux.org/Android_Booting

    I think books and web pages don't mention this because it is not part of regular system interface used in Android SDK/NDK.

  • In reply to Manuel Contreras:

    Hi Guang Xu and Manuel Contreras,

    Even i am working on similar thing of using standalone TI Hardware encoder and decoder on OMAP4430 Platform (Panda Board). Is it possible to share your code with me ?

    Thanks for the help in advance.

    Regards

    Girish


  • In reply to Girish H T:

    Girish;

    You need to download Android NDK  and use /android-ndk-r7b_2/samples/hello-jni sample code like base,

    download OpenMax IL library headers from Krhonos site and copy them inside ./android-ndk-r7b_2/samples/hello-jni

    http://www.khronos.org/registry/omxil/api/1.1.2/OpenMAX_IL_1_1_2_Header.zip

    in order to get TI's OpenMax functionalities you could use headers from

    $MYDROID/hardware/ti/domx/omx_core/inc 

    and replace/create next files according, apk code is not being used,

    and this code is crude, I change it to function like library code  and like native application at same time,

    check hello-jni.c for main_run() and main(),

    code based in http://e2e.ti.com/support/omap/f/849/p/178679/645475.aspx#645475

    related code samples that uses static libraries are in

    ./android-ndk-r7b_2/samples/san-angeles

    ./android-ndk-r7b_2/tests/build/import-static

    //////////////////////////////////./android-ndk-r7b_2/samples/hello-jni/jni/hello-jni_use.c/////////////////////////////

    /*
     * Copyright (C) 2009 The Android Open Source Project
     *
     * Licensed under the Apache License, Version 2.0 (the "License");
     * you may not use this file except in compliance with the License.
     * You may obtain a copy of the License at
     *
     *      http://www.apache.org/licenses/LICENSE-2.0
     *
     * Unless required by applicable law or agreed to in writing, software
     * distributed under the License is distributed on an "AS IS" BASIS,
     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     * See the License for the specific language governing permissions and
     * limitations under the License.
     *
     */
    #include <string.h>
    #include <jni.h>
    #include <dlfcn.h>
    #include <android/log.h>
    #include <OMX_Core.h>

    static void *m_pOMXModule;
    static OMX_ERRORTYPE (*m_main_use) (OMX_CALLBACKTYPE *m_videodeccallbacks_in, OMX_PTR pAppData_in);

    static OMX_ERRORTYPE TI_videodecEventHandler(OMX_HANDLETYPE ,
            OMX_PTR app_data, OMX_EVENTTYPE event, OMX_U32 , OMX_U32, OMX_PTR );
    static OMX_ERRORTYPE TI_videodecEmptyBufferDone(OMX_HANDLETYPE , OMX_PTR , OMX_BUFFERHEADERTYPE *);
    static OMX_ERRORTYPE TI_videodecFillBufferDone(OMX_HANDLETYPE , OMX_PTR , OMX_BUFFERHEADERTYPE *);

    static OMX_CALLBACKTYPE m_videodeccallbacks;

    static struct mystruct{
        OMX_U32 mydata;
    } mystructdata;

    static OMX_ERRORTYPE TI_videodecEventHandler(OMX_HANDLETYPE omx_handle,
            OMX_PTR app_data, OMX_EVENTTYPE event, OMX_U32 data_1, OMX_U32 data_2,
            OMX_PTR event_data)
    {
    return 0;
    };
    static OMX_ERRORTYPE TI_videodecEmptyBufferDone(OMX_HANDLETYPE omx_handle,
            OMX_PTR app_data, OMX_BUFFERHEADERTYPE *omx_header)
    {
    return 0;
    };
    static OMX_ERRORTYPE TI_videodecFillBufferDone(OMX_HANDLETYPE omx_handle,
            OMX_PTR app_data, OMX_BUFFERHEADERTYPE *omx_header)
    {
    return 0;
    };

    void main (int argc, char*  argv[]){
        __android_log_print(ANDROID_LOG_DEBUG, "TRY_OMX", "inside main_use\n");
        OMX_ERRORTYPE eError = OMX_ErrorNone;
        OMX_HANDLETYPE m_componentHandle = NULL;
        m_pOMXModule = dlopen("/system/lib/libhello-jni.so", RTLD_LAZY);
        m_main_use = (dlsym(m_pOMXModule, "main_run"));
        __android_log_print(ANDROID_LOG_DEBUG, "TRY_OMX", "---------setting callbacks:%x", eError);
        m_videodeccallbacks.EventHandler         = TI_videodecEventHandler;
        m_videodeccallbacks.EmptyBufferDone  = TI_videodecEmptyBufferDone;
        m_videodeccallbacks.FillBufferDone       = TI_videodecFillBufferDone;
        __android_log_print(ANDROID_LOG_DEBUG, "TRY_OMX", "---------m_main_use");
        m_main_use(&m_videodeccallbacks,&mystructdata);
        __android_log_print(ANDROID_LOG_DEBUG, "TRY_OMX", "going outside main_use\n");
    }


    ///////////////////////////////////./android-ndk-r7b_2/samples/hello-jni/jni/hello-jni.c//////////////////////////////////////

    /*
     * Copyright (C) 2009 The Android Open Source Project
     *
     * Licensed under the Apache License, Version 2.0 (the "License");
     * you may not use this file except in compliance with the License.
     * You may obtain a copy of the License at
     *
     *      http://www.apache.org/licenses/LICENSE-2.0
     *
     * Unless required by applicable law or agreed to in writing, software
     * distributed under the License is distributed on an "AS IS" BASIS,
     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     * See the License for the specific language governing permissions and
     * limitations under the License.
     *
     */
    #include <string.h>
    #include <jni.h>
    #include <dlfcn.h>
    #include <android/log.h>
    #include <OMX_Core.h>

    static void *m_pOMXModule;
    static OMX_ERRORTYPE (*m_pfOMX_Init) (void);
    static OMX_ERRORTYPE (*m_pfOMX_DeInit) (void);
    static OMX_ERRORTYPE (*m_pfOMX_GetHandle) (OMX_HANDLETYPE *, OMX_STRING,
                                           OMX_PTR, OMX_CALLBACKTYPE *);
    static OMX_ERRORTYPE (*m_pfOMX_FreeHandel) (OMX_HANDLETYPE omx_handle);
    static OMX_ERRORTYPE (*m_pfOMX_GetComponentsOfRole)(OMX_STRING, OMX_U32 *, OMX_U8 **);
    static OMX_ERRORTYPE (*m_pfOMX_ComponentNameEnum)(OMX_STRING, OMX_U32, OMX_U32);
    static OMX_ERRORTYPE (*m_pfOMX_GetRolesOfComponent)(OMX_STRING, OMX_U32 *, OMX_U8 **);

    void main_run (OMX_CALLBACKTYPE *m_videodeccallbacks_in, OMX_PTR pAppData_in);

    static OMX_ERRORTYPE TI_videodecEventHandler(OMX_HANDLETYPE ,
            OMX_PTR app_data, OMX_EVENTTYPE event, OMX_U32 , OMX_U32, OMX_PTR );
    static OMX_ERRORTYPE TI_videodecEmptyBufferDone(OMX_HANDLETYPE , OMX_PTR , OMX_BUFFERHEADERTYPE *);
    static OMX_ERRORTYPE TI_videodecFillBufferDone(OMX_HANDLETYPE , OMX_PTR , OMX_BUFFERHEADERTYPE *);

    static OMX_CALLBACKTYPE m_videodeccallbacks;

    static struct mystruct{
        OMX_U32 mydata;
    } mystructdata;

    /* This is a trivial JNI example where we use a native method
     * to return a new VM String. See the corresponding Java source
     * file located at:
     *
     *   apps/samples/hello-jni/project/src/com/example/HelloJni/HelloJni.java
     */
    jstring
    Java_com_example_hellojni_HelloJni_stringFromJNI( JNIEnv* env,
                                                      jobject thiz )
    {
        OMX_ERRORTYPE eError = OMX_ErrorNone;

        OMX_HANDLETYPE m_componentHandle = NULL;

        m_pOMXModule = dlopen("/system/lib/libOMX_Core.so", RTLD_LAZY);

        m_pfOMX_Init = (dlsym(m_pOMXModule, "OMX_Init"));
        m_pfOMX_DeInit = (dlsym(m_pOMXModule, "OMX_Deinit"));
        m_pfOMX_ComponentNameEnum = (dlsym(m_pOMXModule,"OMX_ComponentNameEnum"));
        m_pfOMX_GetRolesOfComponent = (dlsym(m_pOMXModule, "OMX_GetRolesOfComponent"));
        m_pfOMX_GetHandle = (dlsym(m_pOMXModule, "OMX_GetHandle"));
        m_pfOMX_FreeHandel = (dlsym(m_pOMXModule, "OMX_FreeHandle"));
        m_pfOMX_GetComponentsOfRole = (dlsym(m_pOMXModule, "OMX_GetComponentsOfRole"));


        __android_log_print(ANDROID_LOG_DEBUG, "TRY_OMX", "---------OMX_ComponentInit");
        eError =m_pfOMX_Init();

        __android_log_print(ANDROID_LOG_DEBUG, "TRY_OMX", "---------OMX_ComponentInit result:%x", eError);

        m_videodeccallbacks.EventHandler         = TI_videodecEventHandler;
        m_videodeccallbacks.EmptyBufferDone  = TI_videodecEmptyBufferDone;
        m_videodeccallbacks.FillBufferDone       = TI_videodecFillBufferDone;

        __android_log_print(ANDROID_LOG_DEBUG, "TRY_OMX", "---------m_pfOMX_GetHandle");
        eError =m_pfOMX_GetHandle(&(m_componentHandle), "OMX.TI.DUCATI1.VIDEO.DECODER",
           &mystructdata, &(m_videodeccallbacks));
        __android_log_print(ANDROID_LOG_DEBUG, "TRY_OMX", "---------m_pfOMX_GetHandle:%x", eError);

        eError =m_pfOMX_FreeHandel((m_componentHandle));

        eError =m_pfOMX_DeInit();

        return (*env)->NewStringUTF(env, "Hello from JNI !");
    }

    static OMX_ERRORTYPE TI_videodecEventHandler(OMX_HANDLETYPE omx_handle,
            OMX_PTR app_data, OMX_EVENTTYPE event, OMX_U32 data_1, OMX_U32 data_2,
            OMX_PTR event_data)
    {
    return 0;
    };
    static OMX_ERRORTYPE TI_videodecEmptyBufferDone(OMX_HANDLETYPE omx_handle,
            OMX_PTR app_data, OMX_BUFFERHEADERTYPE *omx_header)
    {
    return 0;
    };
    static OMX_ERRORTYPE TI_videodecFillBufferDone(OMX_HANDLETYPE omx_handle,
            OMX_PTR app_data, OMX_BUFFERHEADERTYPE *omx_header)
    {
    return 0;
    };

    void main (int argc, char*  argv[]){
        __android_log_print(ANDROID_LOG_DEBUG, "TRY_OMX", "inside main\n");

        OMX_ERRORTYPE eError = OMX_ErrorNone;

        OMX_HANDLETYPE m_componentHandle = NULL;

        m_pOMXModule = dlopen("/system/lib/libOMX_Core.so", RTLD_LAZY);

        m_pfOMX_Init = (dlsym(m_pOMXModule, "OMX_Init"));
        m_pfOMX_DeInit = (dlsym(m_pOMXModule, "OMX_Deinit"));
        m_pfOMX_ComponentNameEnum = (dlsym(m_pOMXModule,"OMX_ComponentNameEnum"));
        m_pfOMX_GetRolesOfComponent = (dlsym(m_pOMXModule, "OMX_GetRolesOfComponent"));
        m_pfOMX_GetHandle = (dlsym(m_pOMXModule, "OMX_GetHandle"));
        m_pfOMX_FreeHandel = (dlsym(m_pOMXModule, "OMX_FreeHandle"));
        m_pfOMX_GetComponentsOfRole = (dlsym(m_pOMXModule, "OMX_GetComponentsOfRole"));

        __android_log_print(ANDROID_LOG_DEBUG, "TRY_OMX", "---------OMX_ComponentInit");
        eError =m_pfOMX_Init();

        __android_log_print(ANDROID_LOG_DEBUG, "TRY_OMX", "---------OMX_ComponentInit result:%x", eError);

        m_videodeccallbacks.EventHandler         = TI_videodecEventHandler;
        m_videodeccallbacks.EmptyBufferDone  = TI_videodecEmptyBufferDone;
        m_videodeccallbacks.FillBufferDone       = TI_videodecFillBufferDone;

        __android_log_print(ANDROID_LOG_DEBUG, "TRY_OMX", "---------m_pfOMX_GetHandle");
        eError =m_pfOMX_GetHandle(&(m_componentHandle), "OMX.TI.DUCATI1.VIDEO.DECODER",
           &mystructdata, &(m_videodeccallbacks));
        __android_log_print(ANDROID_LOG_DEBUG, "TRY_OMX", "---------m_pfOMX_GetHandle:%x", eError);

        eError =m_pfOMX_FreeHandel((m_componentHandle));

        eError =m_pfOMX_DeInit();

        __android_log_print(ANDROID_LOG_DEBUG, "TRY_OMX", "outside main\n");
    }

    void main_run (OMX_CALLBACKTYPE *m_videodeccallbacks_in, OMX_PTR pAppData_in){
        __android_log_print(ANDROID_LOG_DEBUG, "TRY_OMX", "inside library\n");


        OMX_ERRORTYPE eError = OMX_ErrorNone;

        OMX_HANDLETYPE m_componentHandle = NULL;

        m_pOMXModule = dlopen("/system/lib/libOMX_Core.so", RTLD_LAZY);

        m_pfOMX_Init = (dlsym(m_pOMXModule, "OMX_Init"));
        m_pfOMX_DeInit = (dlsym(m_pOMXModule, "OMX_Deinit"));
        m_pfOMX_ComponentNameEnum = (dlsym(m_pOMXModule,"OMX_ComponentNameEnum"));
        m_pfOMX_GetRolesOfComponent = (dlsym(m_pOMXModule, "OMX_GetRolesOfComponent"));
        m_pfOMX_GetHandle = (dlsym(m_pOMXModule, "OMX_GetHandle"));
        m_pfOMX_FreeHandel = (dlsym(m_pOMXModule, "OMX_FreeHandle"));
        m_pfOMX_GetComponentsOfRole = (dlsym(m_pOMXModule, "OMX_GetComponentsOfRole"));

        __android_log_print(ANDROID_LOG_DEBUG, "TRY_OMX", "---------OMX_ComponentInit");
        eError =m_pfOMX_Init();

        __android_log_print(ANDROID_LOG_DEBUG, "TRY_OMX", "---------OMX_ComponentInit result:%x", eError);

        __android_log_print(ANDROID_LOG_DEBUG, "TRY_OMX", "---------m_pfOMX_GetHandle");
        eError =m_pfOMX_GetHandle(&(m_componentHandle), "OMX.TI.DUCATI1.VIDEO.DECODER",
           pAppData_in, (m_videodeccallbacks_in));
        __android_log_print(ANDROID_LOG_DEBUG, "TRY_OMX", "---------m_pfOMX_GetHandle:%x", eError);

        eError =m_pfOMX_FreeHandel((m_componentHandle));

        eError =m_pfOMX_DeInit();

        __android_log_print(ANDROID_LOG_DEBUG, "TRY_OMX", "going outside library\n");
    }

    ////////////////////////////////./android-ndk-r7b_2/samples/hello-jni/jni/Android.mk////////////////////////////////////

    # Copyright (C) 2009 The Android Open Source Project
    #
    # Licensed under the Apache License, Version 2.0 (the "License");
    # you may not use this file except in compliance with the License.
    # You may obtain a copy of the License at
    #
    #      http://www.apache.org/licenses/LICENSE-2.0
    #
    # Unless required by applicable law or agreed to in writing, software
    # distributed under the License is distributed on an "AS IS" BASIS,
    # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    # See the License for the specific language governing permissions and
    # limitations under the License.
    #
    LOCAL_PATH := $(call my-dir)

    include $(CLEAR_VARS)

    LOCAL_MODULE    := hello-jni
    LOCAL_SRC_FILES := hello-jni.c
    LOCAL_LDLIBS := -ldl  -llog
    LOCAL_MODULE_TAGS := optional
    LOCAL_CFLAGS := -DANDROID_NDK

    include $(BUILD_SHARED_LIBRARY)

    include $(CLEAR_VARS)

    LOCAL_MODULE    := hello-native
    LOCAL_SRC_FILES := hello-jni.c
    LOCAL_LDLIBS := -ldl  -llog
    LOCAL_MODULE_TAGS := optional
    LOCAL_CFLAGS := -DANDROID_NDK

    include $(BUILD_EXECUTABLE)

    include $(CLEAR_VARS)

    LOCAL_MODULE    := hello-native_use
    LOCAL_SRC_FILES := hello-jni_use.c
    LOCAL_LDLIBS := -ldl  -llog
    LOCAL_MODULE_TAGS := optional
    LOCAL_CFLAGS := -DANDROID_NDK

    include $(BUILD_EXECUTABLE)
    //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////