libstagefright 框架设计分析(2): omx 相关
2016-01-17 18:15
441 查看
OMX 框架是android 音视频codec 的入口吧。 说到入口, 首先omx 就是在ACodec 被使用, 而且是以一个client 来使用, 所以omx 会有个service。这个分析就从这里开始好了。
IOMX.h
这里是interface, binder 的client server 就没必要纠结, 我们都知道最后的实现是在server 端。所以就直接分析server 端。
就从上面的ACodec::UninitializedState::onAllocateComponent() 来分析好了, 在这个函数里面有一句代码
字面上就知道是要分配一个node, 一个omx node, 因为omx 是一个service, 管理着多个component, 也就是这里的node。
就这样, 在ACodec 中, 会根据allocate 回来的handle 和 node id, 最后就可以对所谓的component 操作了, 如下
ACodec->OMX->Component (比如aac,就是SoftAAC2.cpp 的内容),
反向都是Component->OMXNodeInstance->OMX->ACodec
bool ACodec::UninitializedState::onAllocateComponent(const sp<AMessage> &msg) { ALOGV("onAllocateComponent"); CHECK(mCodec->mNode == NULL); OMXClient client; CHECK_EQ(client.connect(), (status_t)OK); sp<IOMX> omx = client.interface(); .... mCodec->mQuirks = quirks; mCodec->mOMX = omx; // omx client mCodec->mNode = node; // node 很关键所以在ACodec.cpp 的代码中会发现所以omx相关的操作都是mCodec->mOMX->xxxx, 主要对omx 的操作方法显然就可以从头文件一目了然了。
IOMX.h
#ifndef ANDROID_IOMX_H_ #define ANDROID_IOMX_H_ #include <binder/IInterface.h> #include <gui/IGraphicBufferProducer.h> #include <ui/GraphicBuffer.h> #include <utils/List.h> #include <utils/String8.h> #include <OMX_Core.h> #include <OMX_Video.h> namespace android { class IMemory; class IOMXObserver; class IOMXRenderer; class Surface; class IOMX : public IInterface { public: DECLARE_META_INTERFACE(OMX); typedef uint32_t buffer_id; typedef uint32_t node_id; // Given a node_id and the calling process' pid, returns true iff // the implementation of the OMX interface lives in the same // process. virtual bool livesLocally(node_id node, pid_t pid) = 0; struct ComponentInfo { String8 mName; List<String8> mRoles; }; virtual status_t listNodes(List<ComponentInfo> *list) = 0; virtual status_t allocateNode( const char *name, const sp<IOMXObserver> &observer, node_id *node) = 0; virtual status_t freeNode(node_id node) = 0; virtual status_t sendCommand( node_id node, OMX_COMMANDTYPE cmd, OMX_S32 param) = 0; virtual status_t getParameter( node_id node, OMX_INDEXTYPE index, void *params, size_t size) = 0; virtual status_t setParameter( node_id node, OMX_INDEXTYPE index, const void *params, size_t size) = 0; virtual status_t getConfig( node_id node, OMX_INDEXTYPE index, void *params, size_t size) = 0; virtual status_t setConfig( node_id node, OMX_INDEXTYPE index, const void *params, size_t size) = 0; virtual status_t getState( node_id node, OMX_STATETYPE* state) = 0; virtual status_t storeMetaDataInBuffers( node_id node, OMX_U32 port_index, OMX_BOOL enable) = 0; virtual status_t prepareForAdaptivePlayback( node_id node, OMX_U32 portIndex, OMX_BOOL enable, OMX_U32 maxFrameWidth, OMX_U32 maxFrameHeight) = 0; virtual status_t configureVideoTunnelMode( node_id node, OMX_U32 portIndex, OMX_BOOL tunneled, OMX_U32 audioHwSync, native_handle_t **sidebandHandle) = 0; virtual status_t enableGraphicBuffers( node_id node, OMX_U32 port_index, OMX_BOOL enable) = 0; virtual status_t getGraphicBufferUsage( node_id node, OMX_U32 port_index, OMX_U32* usage) = 0; virtual status_t useBuffer( node_id node, OMX_U32 port_index, const sp<IMemory> ¶ms, buffer_id *buffer) = 0; virtual status_t useGraphicBuffer( node_id node, OMX_U32 port_index, const sp<GraphicBuffer> &graphicBuffer, buffer_id *buffer) = 0; virtual status_t updateGraphicBufferInMeta( node_id node, OMX_U32 port_index, const sp<GraphicBuffer> &graphicBuffer, buffer_id buffer) = 0; virtual status_t createInputSurface( node_id node, OMX_U32 port_index, sp<IGraphicBufferProducer> *bufferProducer) = 0; virtual status_t signalEndOfInputStream(node_id node) = 0; // This API clearly only makes sense if the caller lives in the // same process as the callee, i.e. is the media_server, as the // returned "buffer_data" pointer is just that, a pointer into local // address space. virtual status_t allocateBuffer( node_id node, OMX_U32 port_index, size_t size, buffer_id *buffer, void **buffer_data) = 0; virtual status_t allocateBufferWithBackup( node_id node, OMX_U32 port_index, const sp<IMemory> ¶ms, buffer_id *buffer) = 0; virtual status_t freeBuffer( node_id node, OMX_U32 port_index, buffer_id buffer) = 0; virtual status_t fillBuffer(node_id node, buffer_id buffer) = 0; virtual status_t emptyBuffer( node_id node, buffer_id buffer, OMX_U32 range_offset, OMX_U32 range_length, OMX_U32 flags, OMX_TICKS timestamp) = 0; virtual status_t getExtensionIndex( node_id node, const char *parameter_name, OMX_INDEXTYPE *index) = 0; enum InternalOptionType { INTERNAL_OPTION_SUSPEND, // data is a bool INTERNAL_OPTION_REPEAT_PREVIOUS_FRAME_DELAY, // data is an int64_t INTERNAL_OPTION_MAX_TIMESTAMP_GAP, // data is int64_t INTERNAL_OPTION_START_TIME, // data is an int64_t INTERNAL_OPTION_TIME_LAPSE, // data is an int64_t[2] }; virtual status_t setInternalOption( node_id node, OMX_U32 port_index, InternalOptionType type, const void *data, size_t size) = 0; }; struct omx_message { enum { EVENT, EMPTY_BUFFER_DONE, FILL_BUFFER_DONE, } type; IOMX::node_id node; union { // if type == EVENT struct { OMX_EVENTTYPE event; OMX_U32 data1; OMX_U32 data2; } event_data; // if type == EMPTY_BUFFER_DONE struct { IOMX::buffer_id buffer; } buffer_data; // if type == FILL_BUFFER_DONE struct { IOMX::buffer_id buffer; OMX_U32 range_offset; OMX_U32 range_length; OMX_U32 flags; OMX_TICKS timestamp; } extended_buffer_data; } u; }; class IOMXObserver : public IInterface { public: DECLARE_META_INTERFACE(OMXObserver); virtual void onMessage(const omx_message &msg) = 0; }; //////////////////////////////////////////////////////////////////////////////// class BnOMX : public BnInterface<IOMX> { public: virtual status_t onTransact( uint32_t code, const Parcel &data, Parcel *reply, uint32_t flags = 0); }; class BnOMXObserver : public BnInterface<IOMXObserver> { public: virtual status_t onTransact( uint32_t code, const Parcel &data, Parcel *reply, uint32_t flags = 0); }; struct CodecProfileLevel { OMX_U32 mProfile; OMX_U32 mLevel; }; } // namespace android #endif
这里是interface, binder 的client server 就没必要纠结, 我们都知道最后的实现是在server 端。所以就直接分析server 端。
就从上面的ACodec::UninitializedState::onAllocateComponent() 来分析好了, 在这个函数里面有一句代码
status_t err = omx->allocateNode(componentName.c_str(), observer, &node);
字面上就知道是要分配一个node, 一个omx node, 因为omx 是一个service, 管理着多个component, 也就是这里的node。
status_t OMX::allocateNode( const char *name, const sp<IOMXObserver> &observer, node_id *node) { // 注意参数node, 这个会是ACodec 在OMX service 找到对应component 的id, Mutex::Autolock autoLock(mLock); *node = 0; OMXNodeInstance *instance = new OMXNodeInstance(this, observer, name); // new omx node 的实例 OMX_COMPONENTTYPE *handle; OMX_ERRORTYPE err = mMaster->makeComponentInstance( // 这里根据参数name 去找到对应的component, 也就是这里的参handle最后被赋值 name, &OMXNodeInstance::kCallbacks, // callback 函数会在component 中调用 instance, &handle);if (err != OMX_ErrorNone) { ALOGE("FAILED to allocate omx component '%s'", name); instance->onGetHandleFailed(); return UNKNOWN_ERROR; } *node = makeNodeID(instance); // 对应instance 生成一个唯一的node id mDispatchers.add(*node, new CallbackDispatcher(instance)); instance->setHandle(*node, handle); // hanle, node id, instance 这里扯上关系了, 在OMX 中多个node, 最后也是靠node id 来找到 mLiveNodes.add(observer->asBinder(), instance); observer->asBinder()->linkToDeath(this); return OK; } ============================================================================ OMX_ERRORTYPE OMXMaster::makeComponentInstance( const char *name, const OMX_CALLBACKTYPE *callbacks, OMX_PTR appData, OMX_COMPONENTTYPE **component) { Mutex::Autolock autoLock(mLock); *component = NULL; ssize_t index = mPluginByComponentName.indexOfKey(String8(name)); // 这里根据name 找到对应的plugin 的index, 为什么要plugin 呢, // 因为android 除了原生的,还要支持vendor的, 这个会OMXMaster 实例化的时候加进来 if (index < 0) { return OMX_ErrorInvalidComponentName; } OMXPluginBase *plugin = mPluginByComponentName.valueAt(index); // 由上面得到的index 找到plugin 指针,然后再找 OMX_ERRORTYPE err = plugin->makeComponentInstance(name, callbacks, appData, component); // 注意这个component 参数 ====================================================================== 原生android 的Plugin OMX_ERRORTYPE SoftOMXPlugin::makeComponentInstance( const char *name, const OMX_CALLBACKTYPE *callbacks, OMX_PTR appData, OMX_COMPONENTTYPE **component) { ALOGV("makeComponentInstance '%s'", name); for (size_t i = 0; i < kNumComponents; ++i) { if (strcmp(name, kComponents[i].mName)) { continue; } AString libName = "libstagefright_soft_"; libName.append(kComponents[i].mLibNameSuffix); libName.append(".so"); void *libHandle = dlopen(libName.c_str(), RTLD_NOW); // component 都是so的形式, 比如aac, 就是libstagefright_soft_aac.so if (libHandle == NULL) { ALOGE("unable to dlopen %s", libName.c_str()); return OMX_ErrorComponentNotFound; } typedef SoftOMXComponent *(*CreateSoftOMXComponentFunc)( const char *, const OMX_CALLBACKTYPE *, OMX_PTR, OMX_COMPONENTTYPE **); CreateSoftOMXComponentFunc createSoftOMXComponent = (CreateSoftOMXComponentFunc)dlsym( // 这里找到了component 的create 函数, 下面就可以生成component 的实例 libHandle, "_Z22createSoftOMXComponentPKcPK16OMX_CALLBACKTYPE" "PvPP17OMX_COMPONENTTYPE"); if (createSoftOMXComponent == NULL) { dlclose(libHandle); libHandle = NULL; return OMX_ErrorComponentNotFound; } sp<SoftOMXComponent> codec = (*createSoftOMXComponent)(name, callbacks, appData, component); // 比如aac , 这里就会call 到aac 的createSoftOMXComponent 函数, // 最后component 指针会被赋值 if (codec == NULL) { dlclose(libHandle); libHandle = NULL; return OMX_ErrorInsufficientResources; } OMX_ERRORTYPE err = codec->initCheck(); if (err != OMX_ErrorNone) { dlclose(libHandle); libHandle = NULL; return err; } codec->incStrong(this); codec->setLibHandle(libHandle); return OMX_ErrorNone; }
就这样, 在ACodec 中, 会根据allocate 回来的handle 和 node id, 最后就可以对所谓的component 操作了, 如下
ACodec->OMX->Component (比如aac,就是SoftAAC2.cpp 的内容),
反向都是Component->OMXNodeInstance->OMX->ACodec
相关文章推荐
- Android Studio 将Library上传到JCenter
- WPS中设置一级、二级、三级标题以及正文和目录
- Mac系统杂项 (持续更新)
- LeetCode273. Integer to English Words
- BZOJ 3130 SDOI 2013 最大流
- 高效的找出两个List中的不同元素
- 关于组织机构细腻化分割---递归
- Windows环境下ARM集成开发环境的搭建与使用
- android stdio 的github
- hdu 1423 Greatest Common Increasing Subsequence (最长上升公共子序列)
- getopt
- html+css踩过的一些坑
- hdu 2203 kmp+strstr两种方法代码
- blueStacks模拟器安装应用慢的问题
- cmd运行的程序的工作目录
- 多做善事,会得到好报的
- 《Node.js入门》Windows 7下Node.js Web开发环境搭建笔记
- PHP - 防止 XSS(跨站脚本攻击)
- 使用springMVC上传文件
- linux特效