分享

Android 9.0 multimedia框架解析(五)ACodec配置解码器过程

 开花结果 2020-04-29

概述

先来回顾下上篇文章所讲的MediaPlayerService的start过程。MediaPlayerService的start通过层层调用会调用到NuPlayer::onStart,onStart会先启动GenericSource,然后通过异步的方式调用到NuPlayer::instantiateDecoder。在instantiateDecoder中,会创建NuPlayer::Decoder(这个Decoder跟我标题里面的decoder是不一样的,标题里面的decoder指的是实际的解码器,而这里的NuPlayer::Decoder经过层层调用会调用到实际的解码器),然后会进行初始化和配置。从时序图中可以看出Decoder的配置过程会先去查找对应的解码器,然后为为解码器创建ACodec。上一节我们分析到了创建ACodec这里,没有分析ACodec的配置过程。这里我以自己集成的ffmpeg播放视频为场景,分析ACodec配置解码器的过程。

时序图

  

configureCodec

从时序图可以看出配置过程会调用到ACodec::configureCodec,这个configureCodec是配置过程的核心函数。
来看看配置的第一步SetComponentRole。omxNode->setParameter就是调用到OMXNodeInstance::setParameter,然后OMXNodeInstance::setParameter会去调用到真正的解码器。来看看我解码器中对于OMX_IndexParamStandardComponentRole会做什么。可以看出,我会识别roleParams->cRole是否是等于video_decoder.ffmpeg,如果是则返回OMX_ErrorNone,让配置过程继续。

来看看第二步setPortMode。一般来说一个解码器有两个port,一个是input,一个是output。input用于输入数据,output用于存放解码完的数据。我一般只分析output。来看一下我的解码器是怎么实现OMX_GetExtensionIndex对应的函数接口的可以看出我调用OMX_GetExtensionIndex将获取到index为OMX_IndexParamEnableAndroidBuffers的值。再来看看解码器是怎么实现OMX_SetParameter对应的函数接口的。可以看出我对于想要使能AndroidNativeBuffer的操作是拒绝的。我这里直接返回OMX_ErrorUndefined。所以我实现的解码器并不支持把端口模式PortMode设置成kPortModePresetANWBuffer。不过没事下面的步骤会去尝试把PortMode设置成kPortModePresetByteBuffer,这个kPortModePresetByteBuffer我的解码器是支持的。下面的分析会分析到这里的。

来看看第三个配置步骤,这个步骤是我自定义的,因为需要从解析器传递一些参数给解码器。来看看第四个配置步骤,这里会去设置kPortModePresetByteBuffer,前面设置ANW buffer的场景由于我解码器没有去实现相关代码所以没成功的。由于我的解码器的名字是OMX.google开头的,所以会走下面这个分支。

这里有两个enableNativeBuffers_l,第一个对应的OMX.google.android.index.enableAndroidNativeBuffers我解码器有实现,所以会成功;第二个OMX.google.android.index.allocateNativeHandle解码器没实现,所以会失败;第三个storeMetaDataInBuffers_l对应的OMX.google.android.index.storeANWBufferInMetadata我也没有实现,所以会失败。但是这两个失败并不会直接影响解码器的配置,因为他们的返回值都被忽略了。然后mGraphicBufferEnabled[portIndex]会被设置成false,这个变量在配置数据缓冲区的时候会用来作判断。

来看看第五个配置步骤,这个步骤会通过index = OMX_IndexParamVideoPortFormat获取解码器的参数,主要是设置input和ouput的数据格式和颜色空间。对于OMX_IndexParamVideoPortFormat的设置参数的接口,可以只做状态返回。

来看看第六个步骤,这个步骤是通过index=OMX_IndexParamPortDefinition来配置解码器的

然后回到configureCodec函数它会调用getPortFormat获取input和ouput的格式getPortFormat得到的output的格式是这样的,这些格式信息会保存在ACodec的mInputFormat和mOutputFormat中。至此,ACodec::configureCodec已经分析完毕。到了这里你可以会发现没有对input和output的缓冲区进行初始化配置,别急下面就来分析。

既然configureCodec已经执行完毕,现在回到Nuplayer::Decoder 消息处理函数的kWhatConfigure,它的下一步工作就是执行mCodec->start(),从时序图可以看出它会执行到ACodec的LoadedState::onMessageReceived的ACodec::kWhatStart分支。这个分支会通过状态机执行到ACodec::LoadedToIdleState::stateEntered函数

可以看出allocateBuffers用户或OMX_IndexParamPortDefinition获取input和output的信息。通过SprdSimpleOMXComponent::internalGetParameter可以知道获取的是对应端口的所有信息,比如buffer大小nBufferSize、buffer个数nBufferCountActual、视频分辨率format.video.nFrameWidth和format.video.nFrameHeight。对于input,获取视频编码格式(压缩格式)eCompressionFormat、对于output获取颜色格式eColorFormat(一般是YUV420p)。然后初始化每一个端口的缓冲区,例如ouput,会分配4(nBufferCountActual)个buffer,把每一个buffer的hidlMemToken传递给omx,进而传递相关地址给解码器,这样解码器就可以通过这个地址获取到解析器解析完之后的数据了。




原文链接:https://blog.csdn.net/qq_27136111/java/article/details/100011623

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多