【六】Android MediaPlayer整体架构源码分析 -【start请求播放处理流程】【Part 7】【01】

承接上一章节分析:【六】Android MediaPlayer整体架构源码分析 -【start请求播放处理流程】【Part 4】【03】
本系列文章分析的安卓源码版本:【Android 10.0 版本】

推荐涉及到的知识点:
Binder机制实现原理:Android C++底层Binder通信机制原理分析总结【通俗易懂】
ALooper机制实现原理:Android native层媒体通信架构AHandler/ALooper机制实现源码分析
Binder异常关闭监听:Android native层DeathRecipient对关联进程(如相关Service服务进程)异常关闭通知事件的监听实现源码分析

【此章节小节编号将重新排序】
onOMXEvent()接收处理执行:
前面小节已分析过该方法可以是BaseState父类状态的具体子类状态实现者进行重写,处理自身业务。但也会有默认父类该方法处理。而对于该方法的所有涉及到的该方法实现的状态实现,如下截图中
onOMXEvent
从上面的实现可知,有这么多个状态实现了该方法,而目前我们只会按照程序执行流程来分析,因此将会分析mLoadedToIdleState状态实现者的【onOMXEvent】方法实现流程,如下
备注:其它流程实现将会在后续有涉及时分析。并且注意,分析该方法时我将会默认为读者已看过8.3小节的分析了。

// [frameworks/av/media/libstagefright/ACodec.cpp]
bool ACodec::LoadedToIdleState::onOMXEvent(
        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
   
    switch (event) {
   
        // 此处就是接收底层组件对于【OMX_StateIdle】该状态命令处理完成事件的处理
        case OMX_EventCmdComplete:
        {
   
            status_t err = OK;
            // 从此处检查状态值有效性也可看出,若不是这两个事件类型参数,即表明底层组件处理发生错误
            if (data1 != (OMX_U32)OMX_CommandStateSet
                    || data2 != (OMX_U32)OMX_StateIdle) {
   
                ALOGE("Unexpected command completion in LoadedToIdleState: %s(%u) %s(%u)",
                        asString((OMX_COMMANDTYPE)data1), data1,
                        asString((OMX_STATETYPE)data2), data2);
                // 底层组件状态扭转处理失败        
                err = FAILED_TRANSACTION;
            }

            if (err == OK) {
   
            	// 成功时,则将会再次发送另一个【OMX_StateExecuting】编解码器执行命令状态事件扭转处理
            	// 非常需要注意该状态扭转请求事件将会影响下面【changeState】状态机扭转之后的执行流程。
            	// 该事件如前面流程分析可知,将是底层组件异步回调通知最终执行ACodec的当前状态的【onOMXEvent】方法实现
                err = mCodec->mOMXNode->sendCommand(
                    OMX_CommandStateSet, OMX_StateExecuting);
            }

            if (err != OK) {
   
            	// 底层组件失败则通知MediaCodec的callback回调监听类接收该错误
            	// 该方法见此前已有分析
                mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err));
            } else {
   
            	// 成功时,将当前状态机状态扭转到【IdleToExecutingState】状态实现者
            	// 见下面的分析
                mCodec->changeState(mCodec->mIdleToExecutingState);
            }

            return true;
        }

        default:
            return BaseState::onOMXEvent(event, data1, data2);
    }
}

mCodec->changeState(mCodec->mIdleToExecutingState)实现分析:
将当前状态机状态扭转到【IdleToExecutingState】状态实现者
由前面状态分析可知,它将会执行该状态实现者的状态进入方法,如下

// [frameworks/av/media/libstagefright/ACodec.cpp]
void ACodec::IdleToExecutingState::stateEntered() {
   
    ALOGV("[%s] Now Idle->Executing", mCodec->mComponentName.c_str());
}

其实可以看到它啥事没做,只是将当前状态机扭转到该状态实现者而已。
但需要注意,上面发送了【OMX_StateExecuting】编解码器执行命令状态事件扭转处理事件,该事件如前面流程分析可知,将是底层组件异步回调通知最终执行ACodec的当前状态【IdleToExecutingState】实现类的【onOMXEvent】方法实现,如下

// [frameworks/av/media/libstagefright/ACodec.cpp]
bool ACodec::IdleToExecutingState::onOMXEvent(
        OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
   
    switch (event) {
   
        case OMX_EventCmdComplete:
        {
   
            // 检查必须是请求扭转到【OMX_StateExecuting】正在执行状态的回调 
            if (data1 != (OMX_U32)OMX_CommandStateSet
                    || data2 != (OMX_U32)OMX_StateExecuting) {
   
                ALOGE("Unexpected command completion in IdleToExecutingState: %s(%u) %s(%u)",
                        asString((OMX_COMMANDTYPE)data1), data1,
                        asString((OMX_STATETYPE)data2), data2);
                mCodec->signalError(OMX_ErrorUndefined, FAILED_TRANSACTION);
                return true;
            }

            // 正在执行状态实现者执行启动(恢复)工作即编解码器真正开始工作了
            // 见第1小节分析
            mCodec->mExecutingState->resume();
            // 切换到该正在执行编解码工作实现者状态
            // 见第2小节分析
            mCodec->changeState(mCodec->mExecutingState);

            return true;
        }

        default:
            return BaseState::onOMXEvent(event, data1, data2);
    }
}

1、mCodec->mExecutingState->resume()实现分析:
正在执行状态实现者执行启动(恢复)工作即编解码器真正开始工作了
一句话总结它的工作任务就是:
递交输出缓冲区Buffer给编解码器(去填充已解码或已编码音视频数据),递交输入Buffer给客户端去填充(待解码或待编码的原始音频或视频)数据。
另外接下来的章节分析中,请记住关于Buffer ID和Buffer Index的概念和区别,ID就是为每个Buffer自动生成的唯一的ID,逐渐递增值。 Buffer Index其实就是Buffer在队列中的索引,即列表item索引。因此ID 和 Index是有区别的。

// [frameworks/av/media/libstagefright/ACodec.cpp]
void ACodec::ExecutingState::resume() {
   
	// mActive标志位表示:如果输入和输出缓冲
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值