MediaCodec 实现探究

Android多媒体框架历史

从 OpenCore 到 libstagefright
关于这段技术改变,可以看看这篇文章

java层

MediaCodec.java

1
2
3
4
5
6
7
8
9
10
11
12
static {
System.loadLibrary("media_jni");
native_init();
}
private MediaCodec(
@NonNull String name, boolean nameIsType, boolean encoder) {
'''
native_setup(name, nameIsType, encoder);
}

jni层

android_media_MediaCodec.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
static void android_media_MediaCodec_native_setup(
JNIEnv *env, jobject thiz,
jstring name, jboolean nameIsType, jboolean encoder) {
'''
sp<JMediaCodec> codec = new JMediaCodec(env, thiz, tmp, nameIsType, encoder);
'''
}
JMediaCodec::JMediaCodec(
JNIEnv *env, jobject thiz,
const char *name, bool nameIsType, bool encoder)
: mClass(NULL),
mObject(NULL) {
'''
mCodec = MediaCodec::CreateByType(mLooper, name, encoder, &mInitStatus);
'''
}

cpp层

MediaCodec.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
tatus_t MediaCodec::init(const AString &name, bool nameIsType, bool encoder) {
mResourceManagerService->init();
...
mCodec = GetCodecBase(name, nameIsType);
...
}
//static
sp<CodecBase> MediaCodec::GetCodecBase(const AString &name, bool nameIsType) {
// at this time only ACodec specifies a mime type.
'''
return new ACodec;
'''
}

ACodec.cpp

1
2
3
4
5
6
7
8
9
bool ACodec::UninitializedState::onAllocateComponent(const sp<AMessage> &msg) {
'''
OMXClient client;
'''
sp<IOMX> omx = client.interface();
'''
mCodec->mOMX = omx;
'''
}

OMXClient.cpp
这个是通过MediaPlayerServer获取到的

1
2
3
4
5
6
7
8
status_t OMXClient::connect() {
sp<IServiceManager> sm = defaultServiceManager();
sp<IBinder> binder = sm->getService(String16("media.player"));
sp<IMediaPlayerService> service = interface_cast<IMediaPlayerService>(binder);
'''
mOMX = service->getOMX();
'''
}

main_mediaserver.cpp

1
2
3
4
5
6
int main(int argc __unused, char** argv)
{
'''
MediaPlayerService::instantiate();
'''
}

MediaPlayerService.cpp

1
2
3
4
5
6
7
sp<IOMX> MediaPlayerService::getOMX() {
Mutex::Autolock autoLock(mLock);
if (mOMX.get() == NULL) {
mOMX = new OMX;
}
return mOMX;
}

OMX.cpp

1
2
3
4
5
6
7
8
9
10
11
12
status_t OMX::setConfig(
node_id node, OMX_INDEXTYPE index,
const void *params, size_t size) {
return findInstance(node)->setConfig(
index, params, size);
}
OMXNodeInstance *OMX::findInstance(node_id node) {
Mutex::Autolock autoLock(mLock);
ssize_t index = mNodeIDToInstance.indexOfKey(node);
return index < 0 ? NULL : mNodeIDToInstance.valueAt(index);
}

在OMX实例返回的是OMXNodeInstance类,
OMXNodeInstance::setConfig 这种方法都转化为 OMX_SetConfig 函数

OMXNodeInstance

1
2
3
4
5
6
7
status_t OMXNodeInstance::setConfig(
OMX_INDEXTYPE index, const void *params, size_t size) {
Mutex::Autolock autoLock(mLock);
OMX_ERRORTYPE err = OMX_SetConfig(
mHandle, index, const_cast<void *>(params));
return StatusFromOMXError(err);
}

在mm-core/inc/OMX_Core.h中转化为

#define OMX_SetConfig( \
hComponent, \
nConfigIndex, \
pComponentConfigStructure) \
((OMX_COMPONENTTYPE*)hComponent)->SetConfig( \
hComponent, \
nConfigIndex, \
pComponentConfigStructure)

mm-core/src/common/omx_core_cmp.cpp 中

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
void * qc_omx_create_component_wrapper(OMX_PTR obj_ptr)
{
qc_omx_component *pThis = (qc_omx_component *)obj_ptr;
OMX_COMPONENTTYPE* component = &(pThis->m_cmp);
memset(&pThis->m_cmp,0,sizeof(OMX_COMPONENTTYPE));
...
component->FillThisBuffer = &qc_omx_component_fill_this_buffer;
component->EmptyThisBuffer = &qc_omx_component_empty_this_buffer;
component->GetState = &qc_omx_component_get_state;
component->GetComponentVersion = &qc_omx_component_get_version;
component->GetConfig = &qc_omx_component_get_config;
component->SetConfig = &qc_omx_component_set_config;
...
return (void *)component;
}
qc_omx_component_set_config(OMX_IN OMX_HANDLETYPE hComp,
OMX_IN OMX_INDEXTYPE configIndex,
OMX_IN OMX_PTR configData)
{
OMX_ERRORTYPE eRet = OMX_ErrorBadParameter;
qc_omx_component *pThis = (hComp)? (qc_omx_component *)(((OMX_COMPONENTTYPE *)hComp)->pComponentPrivate):NULL;
DEBUG_PRINT("OMXCORE: qc_omx_component_set_config %p\n", hComp);
if(pThis)
{
eRet = pThis->set_config(hComp,
configIndex,
configData);
}
return eRet;
}

载入omx的so库

1
2
3
4
5
6
7
static create_qc_omx_component
omx_core_load_cmp_library(char *libname, void **handle_ptr)
{
...
*handle_ptr = dlopen(libname,RTLD_NOW);
...
}

omx库的列表 mm-core/src/8974/qc_registry_table_android.c

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
omx_core_cb_type core[] =
{
{
"OMX.qcom.video.decoder.avc",
NULL, // Create instance function
// Unique instance handle
{
NULL
},
NULL, // Shared object library handle
"libOmxVdec.so",
{
"video_decoder.avc"
}
},
{
"OMX.qcom.video.decoder.avc.secure",
NULL, // Create instance function
// Unique instance handle
{
NULL
},
NULL, // Shared object library handle
"libOmxVdec.so",
{
"video_decoder.avc"
}
},

所以最终加载的是 libOmxVdec.so 里面的实现,应该有个地方会加载这些编解码的so库。