• MediaPlayer_Analyze-6-MediaCodec和ACodec


    MediaPlayer Analyze - MediaCodec和ACodec

    Refrence

    1. Android ACodec MediaCodec NuPlayer flow
    2. MediaCodec对接到OMX的简单分析
    3. ACodec详细解析
    4. MediaPlayer

    文中序列图用 websequencediagrams 在线工具画的

    ACodec在整个NuPlayer架构中的位置

    buffer传输过程


    一 初始化

    framework层的MediaPlayer初始化未调用NuPlayer用关的函数,进而未调用MediaCodec

    二 设置Source setDataSource

    NuPlayer的setDataSource直接返回结果给NuPlayerDriver,没有调用到MediaCodec。

    三 准备 prepare

    NuPlayer的prepare设置了一些参数,没有调用到MediaCodec。

    四 开始/恢复播放 start/resume

    4.1 NuPlayerDecoder中mCodec = MediaCodec::CreateByComponentName(mCodecLooper, mComponentName.c_str(), NULL /* err */, mPid, mUid);

    frameworks\av\media\libstagefright\MediaCodec.cpp

    sp<MediaCodec> MediaCodec::CreateByType(const sp<ALooper> &looper, const AString &mime, bool encoder, status_t *err, pid_t pid, uid_t uid) {
        Vector<AString> matchingCodecs;
    
        MediaCodecList::findMatchingCodecs(
                mime.c_str(),
                encoder,
                0,
                &matchingCodecs);
    
        if (err != NULL) {
            *err = NAME_NOT_FOUND;
        }
        for (size_t i = 0; i < matchingCodecs.size(); ++i) {
            // 创建MediaCodec实例对象
            sp<MediaCodec> codec = new MediaCodec(looper, pid, uid);
            AString componentName = matchingCodecs[i];
            // 调用MediaCodec::init进行初始化
            status_t ret = codec->init(componentName);
            if (err != NULL) {
                *err = ret;
            }
            if (ret == OK) {
                return codec;
            }
            ALOGD("Allocating component '%s' failed (%d), try next one.", componentName.c_str(), ret);
        }
        return NULL;
    }
    
    status_t MediaCodec::init(const AString &name) {
        ......
        // 实例化ACodec,此处的mCodec未ACodec实例
        mCodec = GetCodecBase(localname, owner);
        ......
        // 注册hanlder用于消息处理
        mLooper->registerHandler(this);
        ......
        // 发送kWhatInit消息
        sp<AMessage> msg = new AMessage(kWhatInit, this);
        ......
        status_t err;
        std::vector<MediaResourceParcel> resources;
        resources.push_back(MediaResource::CodecResource(secureCodec, mIsVideo));
        for (int i = 0; i <= kMaxRetry; ++i) {
            if (i > 0) {
                // Don't try to reclaim resource for the first time.
                if (!mResourceManagerProxy->reclaimResource(resources)) {
                    break;
                }
            }
    
            sp<AMessage> response;
            err = PostAndAwaitResponse(msg, &response);
            if (!isResourceError(err)) {
                break;
            }
        }
        return err;
    }
    
    sp<CodecBase> MediaCodec::GetCodecBase(const AString &name, const char *owner) {
        if (owner) {
            if (strcmp(owner, "default") == 0) {
                return new ACodec;
            } else if (strncmp(owner, "codec2", 6) == 0) {
                return CreateCCodec();
            }
        }
    
        if (name.startsWithIgnoreCase("c2.")) {
            return CreateCCodec();
        } else if (name.startsWithIgnoreCase("omx.")) {
            // at this time only ACodec specifies a mime type.
            return new ACodec;
        } else if (name.startsWithIgnoreCase("android.filter.")) {
            return new MediaFilter;
        } else {
            return NULL;
        }
    }
    
    void MediaCodec::onMessageReceived(const sp<AMessage> &msg) {
        switch (msg->what()) {
            ......
            case kWhatInit:
            {
                ......
                // 调用ACodec::initiateAllocateComponent
                mCodec->initiateAllocateComponent(format);
                break;
            }
            ......
        }
    }
    
    • 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
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94

    frameworks\av\media\libstagefright\ACodec.cpp

    void ACodec::initiateAllocateComponent(const sp<AMessage> &msg) {
        msg->setWhat(kWhatAllocateComponent);
        msg->setTarget(this);
        msg->post();
    }
    
    bool ACodec::UninitializedState::onMessageReceived(const sp<AMessage> &msg) {
        bool handled = false;
    
        switch (msg->what()) {
            ......
            case ACodec::kWhatAllocateComponent:
            {
                onAllocateComponent(msg);
                handled = true;
                break;
            }
            ......
        }
    }
    
    bool ACodec::UninitializedState::onAllocateComponent(const sp<AMessage> &msg) {
        ......
        sp<CodecObserver> observer = new CodecObserver(notify);
        sp<IOMX> omx;
        sp<IOMXNode> omxNode;
    
        status_t err = NAME_NOT_FOUND;
        // 获取OMX的binder对象
        OMXClient client;
        if (client.connect(owner.c_str()) != OK) {
            mCodec->signalError(OMX_ErrorUndefined, NO_INIT);
            return false;
        }
        omx = client.interface();
    
        pid_t tid = gettid();
        int prevPriority = androidGetThreadPriority(tid);
        androidSetThreadPriority(tid, ANDROID_PRIORITY_FOREGROUND);
        // 申请omx组件
        err = omx->allocateNode(componentName.c_str(), observer, &omxNode);
        androidSetThreadPriority(tid, prevPriority);
    
        if (err != OK) {
            ALOGE("Unable to instantiate codec '%s' with err %#x.", componentName.c_str(), err);
    
            mCodec->signalError((OMX_ERRORTYPE)err, makeNoSideEffectStatus(err));
            return false;
        }
        ......
        // 保存OMX相关对象,此时就和OMX关联起来了
        mCodec->mOMX = omx;
        mCodec->mOMXNode = omxNode;
        // 回调通知MediaCodec
        mCodec->mCallback->onComponentAllocated(mCodec->mComponentName.c_str());
        mCodec->changeState(mCodec->mLoadedState);
    
        return true;
    }
    
    • 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
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59

    4.2 NuPlayerDecoder中err = mCodec->configure(format, mSurface, crypto, 0 /* flags */);

    frameworks\av\media\libstagefright\MediaCodec.cpp

    status_t MediaCodec::configure(
            const sp<AMessage> &format,
            const sp<Surface> &surface,
            const sp<ICrypto> &crypto,
            const sp<IDescrambler> &descrambler,
            uint32_t flags) {
        sp<AMessage> msg = new AMessage(kWhatConfigure, this);
        ......
    }
    
    void MediaCodec::onMessageReceived(const sp<AMessage> &msg) {
        switch (msg->what()) {
            ......
            case kWhatConfigure:
            {
                ......
                setState(CONFIGURING);
                ......
                mCodec->initiateConfigureComponent(format);
                break;
            }
            ......
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    frameworks\av\media\libstagefright\ACodec.cpp

    void ACodec::initiateConfigureComponent(const sp<AMessage> &msg) {
        msg->setWhat(kWhatConfigureComponent);
        msg->setTarget(this);
        msg->post();
    }
    
    bool ACodec::LoadedState::onMessageReceived(const sp<AMessage> &msg) {
        bool handled = false;
    
        switch (msg->what()) {
            case ACodec::kWhatConfigureComponent:
            {
                onConfigureComponent(msg);
                handled = true;
                break;
            }
            ......
        }
    }
    
    
    bool ACodec::LoadedState::onConfigureComponent(
            const sp<AMessage> &msg) {
        ALOGV("onConfigureComponent");
    
        CHECK(mCodec->mOMXNode != NULL);
    
        status_t err = OK;
        AString mime;
        if (!msg->findString("mime", &mime)) {
            err = BAD_VALUE;
        } else {
            err = mCodec->configureCodec(mime.c_str(), msg);
        }
        if (err != OK) {
            ALOGE("[%s] configureCodec returning error %d", mCodec->mComponentName.c_str(), err);
    
            mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err));
            return false;
        }
    
        mCodec->mCallback->onComponentConfigured(mCodec->mInputFormat, mCodec->mOutputFormat);
    
        return true;
    }
    
    
    status_t ACodec::configureCodec(const char *mime, const sp<AMessage> &msg) {
        // 内容很多,主要是通过mCodec->mOMXNode对OMX进行参数配置
        ......
    }
    
    • 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
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51

    4.3 NuPlayerDecoder中err = mCodec->start();

    frameworks\av\media\libstagefright\MediaCodec.cpp

    status_t MediaCodec::start() {
        sp<AMessage> msg = new AMessage(kWhatStart, this);
        ......
    }
    
    void MediaCodec::onMessageReceived(const sp<AMessage> &msg) {
        switch (msg->what()) {
            ......
            case kWhatStart:
            {
                sp<AReplyToken> replyID;
                CHECK(msg->senderAwaitsResponse(&replyID));
    
                if (mState == FLUSHED) {
                    setState(STARTED);
                    if (mHavePendingInputBuffers) {
                        onInputBufferAvailable();
                        mHavePendingInputBuffers = false;
                    }
                    mCodec->signalResume();
                    PostReplyWithError(replyID, OK);
                    break;
                } else if (mState != CONFIGURED) {
                    PostReplyWithError(replyID, INVALID_OPERATION);
                    break;
                }
    
                mReplyID = replyID;
                setState(STARTING);
    
                mCodec->initiateStart();
                break;
            }
            ......
        }
    }
    
    • 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
    • 32
    • 33
    • 34
    • 35
    • 36

    frameworks\av\media\libstagefright\ACodec.cpp

    void ACodec::initiateStart() {
        (new AMessage(kWhatStart, this))->post();
    }
    
    bool ACodec::LoadedState::onMessageReceived(const sp<AMessage> &msg) {
        bool handled = false;
    
        switch (msg->what()) {
            ......
            case ACodec::kWhatStart:
            {
                onStart();
                handled = true;
                break;
            }
            ......
        }
    }
    
    void ACodec::LoadedState::onStart() {
        ALOGV("onStart");
    
        status_t err = mCodec->mOMXNode->sendCommand(OMX_CommandStateSet, OMX_StateIdle);
        if (err != OK) {
            mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err));
        } else {
            mCodec->changeState(mCodec->mLoadedToIdleState);
        }
    }
    
    • 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

    五 暂停 pause

    TODO

    六 停止 stop

    TODO

    七 重置 reset

    TODO

    八 释放 release

    TODO

  • 相关阅读:
    百度AI---人脸对比(前端拍照上传后端进行对比,后端调用百度接口返回对比信息)
    Spring Boot工程开发流程
    Spring 源码阅读 74:事务管理的原理 - BeanFactoryTransactionAttributeSourceAdvisor 分析
    Stream流使用
    前端开发规范总结
    微服务与中间件系列——GateWay整合Swagger3增强Knife4j
    宁波大学NBU计算机嵌入式系统期末考试题库(一)
    Flutter笔记:GetX模块中不使用 Get.put 怎么办
    计算机毕业设计Java博弈论学习网站(源码+系统+mysql数据库+lw文档)
    微信小程序怎么通过图片链接获取图片宽高比(适合在下载图片前获取宽高比)
  • 原文地址:https://blog.csdn.net/tujidi1csd/article/details/126867948