1. Create a new
UUID
In
ANDROID_DIR/external/opencore/codecs_v2/omx/omx_common/include/pv_omxcore.h
#if
USE_DYNAMIC_LOAD_OMX_COMPONENTS
#define PV_OMX_MP3DEC_UUID
OsclUuid(0x1d4769f0,0xca0c,0x11dc,0x95,0xff,0x08,0x00,0x20,0x0c,0x9a,0x
70)
#define
PV_OMX_AACENC_UUID
OsclUuid(0x1d4769f0,0xca0c,0x11dc,0x95,0xff,0x08,0x00,0x20,0x0c,0x9a,0x76)
2.
Add in your decoder library and interface head file
In fold
ANDROID_DIR/external/opencore/codecs_v2/, create a new directory and put your
decoder files in. Here we take the mp3 decoder as an example.The mp3 decoder is
put in the fold audio/mp3/dec/ and the head file will be used by us are:(you can
get this in Android.mk)
LOCAL_COPY_HEADERS :=
\
include/pvmp3_decoder.h \
include/pvmp3decoder_api.h
\
include/pvmp3_audio_type_defs.h
The decoder library will be
compiled to be a static library named libpvmp3.a
3. Intergrate the
decoder library into openmax in opencore
Create a new directory in
codecs_v2/omx. Here we take the mp3 decoder as an example. The mp3 omx component
is placed in the fold omx/omx_mp3/. From the Android.mk file you can know the
most imp
ortant files are:
LOCAL_SRC_FILES := \
src/mp3_dec.cpp
\
src/omx_mp3_component.cpp
\
src/mp3_timestamp.cpp
LOCAL_COPY_HEADERS :=
\
include/mp3_dec.h \
include/omx_mp3_component.h
\
include/mp3_timestamp.h
We can get a snap from the head files.
In the file mp3_dec.h, a new class named Mp3Decoder will be created to use the
mp3 decoder.
CPvMP3_Decoder* iAudioMp3Decoder; // defined in
pvmp3_decoder.h
tPVMP3DecoderExternal* iMP3DecExt; //defined in
pvmp3decoder_api.h
Some import interfaces will be created
here:
Mp3Decoder();
OMX_BOOL
Mp3DecInit(OMX_AUDIO_CONFIG_EQUALIZERTYPE* aEqualizerType);
void
Mp3DecDeinit();
Int Mp3DecodeAudio(OMX_S16* aOutBuff,
OMX_U32*
aOutputLength, OMX_U8** aInputBuf,
OMX_U32* aInBufSize,
OMX_S32*
aFrameCount,
OMX_AUDIO_PARAM_PCMMODETYPE*
aAudioPcmParam,
OMX_AUDIO_PARAM_MP3TYPE* aAudioMp3Param,
OMX_BOOL
aMarkerFlag,
OMX_BOOL* aResizeFlag);
void ResetDecoder(); //
for repositioning
If your decoder is an audio decoder you should
create a class which inherits from OmxComponentAudio. If your decoder is a video
decoder you should create a class which inherits from
OmxComponentVideo.
The OmxComponetAudio class:
class
OmxComponentAudio : public
OmxComponentBase
{
public:
OmxComponentAudio();
virtual
~OmxComponentAudio() {}
OMX_ERRORTYPE GetParameter(
OMX_IN
OMX_HANDLETYPE hComponent,
OMX_IN OMX_INDEXTYPE
nParamIndex,
OMX_INOUT OMX_PTR
ComponentParameterStructure);
OMX_ERRORTYPE
SetParameter(
OMX_IN OMX_HANDLETYPE hComponent,
OMX_IN
OMX_INDEXTYPE nParamIndex,
OMX_IN OMX_PTR
ComponentParameterStructure);
virtual void UpdateAACPlusFlag(OMX_BOOL
aAacPlusFlag)
{
OSCL_UNUSED_ARG(aAacPlusFlag);
}
};
The
OmxComponentVideo class:
class OmxComponentVideo : public
OmxComponentBase
{
public:
OmxComponentVideo();
virtual
~OmxComponentVideo() {}
OMX_ERRORTYPE GetParameter(
OMX_IN
OMX_HANDLETYPE hComponent,
OMX_IN OMX_INDEXTYPE
nParamIndex,
OMX_INOUT OMX_PTR
ComponentParameterStructure);
OMX_ERRORTYPE
SetParameter(
OMX_IN OMX_HANDLETYPE hComponent,
OMX_IN
OMX_INDEXTYPE nParamIndex,
OMX_IN OMX_PTR
ComponentParameterStructure);
};
In the base class
OmxComponentBase you can see there are 5 pure virtual interfaces:
virtual
OMX_ERRORTYPE GetParameter(
OMX_IN OMX_HANDLETYPE
hComponent,
OMX_IN OMX_INDEXTYPE nParamIndex,
OMX_INOUT OMX_PTR
ComponentParameterStructure) = 0;
virtual OMX_ERRORTYPE
SetParameter(
OMX_IN OMX_HANDLETYPE hComponent,
OMX_IN
OMX_INDEXTYPE nParamIndex,
OMX_IN OMX_PTR ComponentParameterStructure) =
0;
virtual void ProcessData() = 0;
virtual OMX_ERRORTYPE
ComponentInit() = 0;
virtual OMX_ERRORTYPE ComponentDeInit() =
0;
So these interfaces must have a definition in derived components. The
first two will be derived in OmxComponent Audio and OmxComponentVideo. So our
component must define the left 3 functions.
And here in our mp3
componet(named OpenmaxMp3AO in the file
omx_mp3_component.h)
OpenmaxMp3AO();
~OpenmaxMp3AO();
OMX_ERRORTYPE
ConstructComponent(OMX_PTR pAppData, OMX_PTR pProxy);
OMX_ERRORTYPE
DestroyComponent();
OMX_ERRORTYPE
ComponentInit();
OMX_ERRORTYPE ComponentDeInit();
static void
ComponentGetRolesOfComponent(OMX_STRING* aRoleString);
void
ProcessData();
void SyncWithInputTimestamp();
void
ProcessInBufferFlag();
void ResetComponent();
OMX_ERRORTYPE
GetConfig(
OMX_IN OMX_HANDLETYPE hComponent,
OMX_IN OMX_INDEXTYPE
nIndex,
OMX_INOUT OMX_PTR pComponentConfigStructure);
And we will
use the Mp3Decoder to implement the component OpenmaxMp3AO
Mp3Decoder*
ipMp3Dec;
Sometimes we need a timestamp
Mp3TimeStampCalc
iCurrentFrameTS;
In omx_mp3_component.cpp we can know the
Mp3OmxSharedLibraryInterface will be implemented as a singleton because we need
mp3 deocoder at time. And here the UUID will be used to judge whether this
library is the right.
OsclAny *QueryOmxComponentInterface(const
OsclUuid& aOmxTypeId, const OsclUuid& aInterfaceId)
{
if
(PV_OMX_MP3DEC_UUID == aOmxTypeId)
{
if (PV_OMX_CREATE_INTERFACE
== aInterfaceId)
{
return
((OsclAny*)(&Mp3OmxComponentFactory));
}
else if
(PV_OMX_DESTROY_INTERFACE == aInterfaceId)
{
return
((OsclAny*)(&Mp3OmxComponentDestructor));
}
}
return
NULL;
};
OsclAny *SharedLibraryLookup(const OsclUuid&
aInterfaceId)
{
if (aInterfaceId ==
PV_OMX_SHARED_INTERFACE)
{
return
OSCL_STATIC_CAST(OmxSharedLibraryInterface*, this);
}
return
NULL;
};
Finally after we finished all the source code we will get
a new component library,here the mp3 component will be compiled to be library
named libomx_mp3_component_lib.so
4. Compile the two libs to be the
shared lib
In
build_config/opencore_dynamic/Android_omx_mp3dec_sharedlibrary.mk, we will
compile the mp3 decoder lib and the mp3 component lib to
libomx_mp3dec_sharedlibrary.so
LOCAL_WHOLE_STATIC_LIBRARIES :=
\
libomx_mp3_component_lib \
libpvmp3
LOCAL_MODULE :=
libomx_mp3dec_sharedlibrary
…..
include
$(PV_TOP)/codecs_v2/omx/omx_mp3/Android.mk
include
$(PV_TOP)/codecs_v2/audio/mp3/dec/Android.mk
5. Regist the shared lib in
soure code
In codecs_v2/omx/omx_common/src/pv_omxregistry.cpp
#if
(REGISTER_OMX_MP3_COMPONENT) ||
(USE_DYNAMIC_LOAD_OMX_COMPONENTS)
/////////////////////////////////////////////////////////////////////////////
OMX_ERRORTYPE
Mp3Register()
{
….
pCRT->SharedLibraryName =
(OMX_STRING)"libomx_mp3dec_sharedlibrary.so";
….
OSCL_PLACEMENT_NEW(temp,
PV_OMX_MP3DEC_UUID);
And this function Mp3Register will be called in
omx_common/src/pv_omxcore.cpp
OSCL_EXPORT_REF OMX_ERRORTYPE
OMX_Init()
{
…
if (status ==
OMX_ErrorNone)
{
_Try_OMX_Init(error,
status);
…
}
...
}
static void
_Try_OMX_Init(int32& aError, OMX_ERRORTYPE&
aStatus)
{
OSCL_TRY(aError, aStatus =
_OMX_Init(););
}
tatic OMX_ERRORTYPE
_OMX_Init()
{
….
Status =
Mp3Register();
…
}
6. At last we need to finish the
PVOMXInterface in pv_omx_interface.cpp
Because the PV OpenCORE framework
is utilizing dynamic loading and linking to handle
potentially multiple
OMX cores simultaneously, the OMX core libraries must be built as
shared
objects .
There are currently two different build methods
to include the PV OMX core wrapper into the final
shared object library
(.so):
6.1 If your opencore shared library and the opencore wrapper
library are build seperately:
we need to modify the file
omx_core_plugins/template/src/pv_omx_interface.cpp.
#define
OMX_CORE_LIBRARY "libOmxCore.so" →
needs to be substituted with the
following line that contains the name of the pre-built shared
library
that contains OMX core methods (but does not contain OMX core
wrapper):
#define OMX_CORE_LIBRAY “
“lib_prebuilt_omxcore_no_wrapper.so”
As part of dynamic loading process,
the OMX core wrapper for this case must open
“lib_prebuilt
omxcore_no_wrapper.so” library and link to the OMX core
methods in this library explicitly (using
dlopen & dlsym
calls).
In pv_omx_interface.cpp:
pOMX_Init =
(tpOMX_Init)dlsym(ipHandle, "OMX_Init");
...
The provider of the
final OMX core library must ensure that makefiles that create the final
OMX
library (“lib_omxcore_plus_wrapper.so”) include the OMX core library
wrapper as well. The
purpose of OMX core library wrapper is to provide
the PV OpenCORE framework with common
APIs to dynamically load and
communicate with OMX core plugins.
6.2 OMX core methods and the OMX core
wrapper interface can be built simultaneously:
The code for the OMX core
wrapper interface for this case is provided in:
.../codecs_v2/omx/omx_sharedlibrary/interface/src
This code needs to be
copied to an appropriate place in the directory structure of vendor's
code
that will enable the creation of
“lib_omxcore_and_simultaneous_wrapper.so”
In
pv_omx_interface.cpp:
pOMX_Init = OMX_Init;
==============================================