ACodec和OMXCodec的比较

一直躺在草稿箱里:


要掌握的内容:

1. ACodec中omx组件的创建过程

2. buffer的操作

3. 和OMXCodec的区别


组件的创建基本上和OMXCodec的相同。




1. 在ACodec::ExecutingState::resume()中,有:
   void ACodec::ExecutingState::resume() {
       ....
       submitOutputBuffers();
       ...
       postFillThisBuffer(info);
  }
  大概分别相当于OMXCode的fillOutputBuffer和drainInputBuffer。 
  在onOMXEmptyBufferDone()中,又调用 postFillThisBuffer
  在getMoreInputDataIfPossible()中,又调用 postFillThisBuffer


  在ACodec::OutputPortSettingsChangedState::onOMXEvent中,也调用submitOutputBuffers()






2. 应该分析ACode::resume()的调用过程


  调用resume()的地方有两处,
  一处在:
  ACodec::IdleToExecutingState::onOMXEvent()中  OMX_EventCmdComplete中
  当sendCommand(mCode->mNode, OMXCommandStateSet, OMXStateIdle)之后,
  会在onOMXEvent()中调用 sendCommand(mCode->mNode, OMXCommandStateSet, OMXStateExcuting)
  在设置OMXStateExcuting成功之后,会调用 mCodec->mExecutingState->resume()。


  所以,在start()时会出发resume()的调用
void ACodec::LoadedState::onStart() {
    ALOGV("onStart");


    CHECK_EQ(mCodec->mOMX->sendCommand(
                mCodec->mNode, OMX_CommandStateSet, OMX_StateIdle),
             (status_t)OK);


    mCodec->changeState(mCodec->mLoadedToIdleState);
}




  另一处在:
  ACodec::ExecutingState::onMessageReceived()中 kWhatResum   kWhatFlushCompleted --- > send kWhatResume msg




3. 分析msg的传递
   BufferInfo中有一个AMessage mNotify的成员,在MediaCodec中enqueneInputBuffer()触发 mNotify->post()从而触
   发 mOMX->emptyBuffer()
   从postInputBuffer()开始分析;
   在resume()中,会选取input buffers中第一个进行post
   resume() {
   ....
       // Post the first input buffer.
       CHECK_GT(mCodec->mBuffers[kPortIndexInput].size(), 0u);
       BufferInfo *info = &mCodec->mBuffers[kPortIndexInput].editItemAt(0);
   ....
   }






    void ACodec::BaseState::postFillThisBuffer(BufferInfo *info) {
        ....
        notify->setInt32("what", ACodec::kWhatFillThisBuffer);
        ....
        sp<AMessage> reply = new AMessage(kWhatInputBufferFilled, mCodec->id());//这个reply会在MediaCodec时被调用
        notify->setMessage("reply", reply);


        notify->post();
    }


    接下来在MediaCodec中接收到 kWhatFillThisBuffer消息,将该buffer push到可用buffer中:
    mAvailPortBuffers[portIndex].push_back(i);
    上层通过 dequeueInputBuffer()来获取该buffer的index进行操作


    操作完毕后,调用该buffer的mNotify->post(),出发 mOMX->emptyBuffer()


   
   OMXCodec::create()流程:
    主要工作为:   
    1. findMatchingCodecs(mime, createEncoder, matchComponentName, flags, &matchingCodecs);
    2. observer = new OMXCodecObserver;
    3. omx->allocateNode(componentName, observer, &node);
    4. sp<OMXCodec> codec = new OMXCodec()
    5. observer->setCodec(codec);


OMX:allocateNode()流程:
    原型: virtual status_t allocateNode(
            const char *name, const sp<IOMXObserver> &observer, node_id *node);
    参数: name,  组件名称
           observer, OMXCodecObserver,传递给组件,用来调用callback函数
           node,  用来返回的组件节点,代表一个组件


    主要工作:
    1. OMXNodeInstance *instance = new OMXNodeInstance(this, observer);
       //注意此处的this对象即 OMX 对象。此时已经和相关的 libstagefreighthw.so联系上了。
       //即在此之前,已经进行过 OMXMaster的addVendorPlugin()了
    2. mMaster->makeComponentInstance(
             name, &OMXNodeInstance::kCallbacks,
             instance, &handle);
       //这里根据name去厂家提供的库里面查找组件。
       //和某个组件关联的对象时:instance
    3. *node = makeNodeID(instance);
       //返回这个node后,则可以根据这个node查找到相关的instance
    4. mDispatchers.add(*node, new CallbackDispatcher(instance));




OMX的工作都是通过OMXNodeInstance来完成,比如 sendCommand的操作:
    1. 在OMXCodec中:err = mOMX->sendCommand(mNode, OMX_CommandStateSet, OMX_StateIdle);
    2. 在OMX中, findInstance(node)->sendCommand(cmd, param);
       findInstance(node)即找到相关的 OMXNodeInstance 对象,调用其sendCommand
    3. OMXNodeInstance调用 OMX_SendCommand,成功发送组件到command


OMX_SendCommand的定义在  omx_core.h中






callback的调用流程:


    例如从 emptyBuffer怎么调用到 OnEmptyBufferDone():
     OMX::emytpBuffer  -->  OMXNodeInstance::emptyBuffer  -->  OMX_EmptyThisBuffer


     OMX_EmptyThisBuffer 宏定义在omx_core.h中:
        #define OMX_EmptyThisBuffer(                                \
                hComponent,                                         \
                pBuffer)                                            \
            ((OMX_COMPONENTTYPE*)hComponent)->EmptyThisBuffer(      \
                hComponent,                                         \
                pBuffer)                        /* Macro End */


     可知:会调用相关组件的EmptyThisBuffer(比OMXNodeInstance还要往深层次的组件,即厂家组件或软解码组件)
   
     在SoftAAC2::onQueueFilled()中,调用 SoftOMXComponent::notifyEmptyBufferDone(header);
     SoftOMXComponent::notifyEmptyBufferDone调用到 上面注册的callbacks
     在这个组件中,会返回来调用OMXNodeInstance的OnEmptyBufferDone().????咋调用到的?....可以从软解码中看到








     OMXNodeInstance中调用到OMX的OnEmptyBufferDone()
     OMX的OnEmptyBufferDone中,调用  findDispatcher(node)->post(msg);  使用CallbackDispatcher
     CallbackDispatcher中再调用OMXNodeInstance的onMessage()
     OMXNodeInstance的onMessage中调用 OMXCodeObserver的onMessage()
     OMXCodeObserver的onMessage中调用OMXCodec的onMessage
     至此成功调用omMessage,完成EmptyBufferDone的调用










介绍ALooper,AMessage,AHandler


new ALooper();
ALooper.start()
ALooper.registerHandler();//绑定AHandler和Looper


new AMessage(what, id()); //id()决定由哪个handler来处理该message的消息
                          //ACodec和AMediaCode都继承自AHandler
msg->postAndAwaitResponse(response);//发送消息






MediaCodec 和 ACodec流程:




(一)    MediaCodec::createByType 
        主要工作: 
            1. sp<MediaCodec> codec = new MediaCode(lopper)
            2. codec->init(mime, nameIsType, encoder);


        MediaCodec::init(){
        主要工作:
            mLooper->registerHandler(this);  
            mCodec->setNotificationMessage(new AMessage(kWhatCodecNotify, id()));




            sp<AMessage> msg = new AMessage(kWhatInit, id());
            PostAndAwaitResponse(msg, &response);


        onMessageReceived:
            case: kWaitInit
        主要工作:
                 setState(INITIALIZING);
                 sp<AMessage> format = new AMessage;
                 mCodec->initiateAllocateComponent(format);




        OMX的创建:
        OMXClient client;
        client.connect() {
                sp<IServiceManager> sm = defaultServiceManager();
                sp<IBinder> binder = sm->getService(String16("media.player"));
                sp<IMediaPlayerService> service = interface_cast<IMediaPlayerService>(binder);


                CHECK(service.get() != NULL);


                mOMX = service->getOMX();//omx服务端在mediaplayer service中创建
        }


        
         sp<IOMX> MediaPlayerService::getOMX() {
             Mutex::Autolock autoLock(mLock);
 
             if (mOMX.get() == NULL) {
             mOMX = new OMX;
         }
 
         return mOMX;
       }


        ACodec::initiateAllocateComponent()
        主要工作:发送 kWhatAllocateComponent,最终调用到onAllocateComponent


        onAllocateComponent(const sp<AMessage> &msg):
        主要工作://和OMXCodec流程基本一样
        1. 获取omx
        2. 获取matchingCodecs和matchingCodecQuirks。即符合要求的所有的解码组件
        3. observer = new CodecObserver; 
        4. omx->allocateNode(componentName.c_str(), observer, &node);//从符合要求的组件中选取一个allocate
        5. observer->setNotificationMessage(notify);
        6. mCodec->mQuirks = quirks;
           mCodec->mOMX = omx;
           mCodec->mNode = node;
        。。。


      ACodec中和具体解码器相关的地方:
      1. GetVideoCodingTypeFromMime()
         在configureCodec()时调用setupVideoDecoder(),会调用到 GetVideoCodingTypeFromMime
         主要工作是根据mime返回 coding type
      2. setComponentRole() configureCodec()中调用
         主要工作:
         1. 根据mime,得到 decoder role
         2. 确定是哪个decoder role后, 调用InitOMXParams(&roleParams);
         3. mOMX->setParameter()
         
      configureCodec()分析:
      从MediaConfig::configure()中调用过来
      主要工作是设置codec的一些参数
      1. status_t err = setComponentRole(encoder /* isEncoder */, mime);
      2. setupVideoDecoder(mime, width, height)
             
  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值