前面两篇文章,我们分别讲了setdataSource和prepare的过程,获得了mVideoTrack,mAudioTrack,mVideoSourc,mAudioSource,前两个来自于setdataSource过程,后面两是prepare。
通过mVideoTrack,mAudioTrack我们找到了相应的解码器,并初始化了,下面我们就开讲mediaplayer如何播放了。前面的一些接口实现,我们就不讲了,不懂的可以回到setdataSource这一篇继续研究,我们直接看Awesomeplayer的实现。先看大体的时序图吧:
如果单是音频,直接播放
有视频时,发送event到queue,等待处理
(3) postVideoEvent_l();
有视频,音频时,检查他们是否同步
在playe_l方法里,我们可以看到首先是实例化一个audioplayer来播放音频,如果单单是音频直接就播放,现在我们是本地视频播放,将不会走第二步,直接走第三和第四步。我们看下postVideoEvent_l()方法,跟我们在讲prepareAsync_l的类似:
mVideoEvent在我们构造awesomeplayer时已经定义:
所以我们看onVideoEvent方法:
我们看到通过read方法去解码一个个sample,获取videobuffer,然后render到surfaceTexture。
read 方法:
在讲read之前我们先来回顾下prepare时候的omxcodec::start方法,因为跟我们讲read有千丝万缕的关系,start方法:
由于我们以MP4为例,所以mSource就是MPEG4Source,MPEG4Source在MPEG4Extractor.cpp,我们看下start方法做了什么:
原来是设定输入的最大buffer.
我再看看allocateBuffers();
OMX_PARAM_PORTDEFINITIonTYPE 是component的配置信息。
OMX_PARAM_PORTDEFINITIONTYPE的参数从哪里来呢?原来来自解码器端,包括输入输出端的buffer大小,总数等信息。
当输出的时候走这里,给输出端分配内存空间,并dequeue buffer 到OMX。
从getParameter获得的每个输入/输出端的buffer大小和总数
复习完start方法,我们就来讲reader方法了:
先看drainInputBuffers方法,主要是从mediasource读取数据元,
mPortBuffers是我们allocateBuffersOnPort方法存下来的对应的输入/输出bufferinfo数据
循环每次输入端能填充数据的buffer总数,这是由component的结构决定的,各个厂商的解码器配置不一样
往buffer里面填元数据,给解码器解码
seek模式
读mediasource,我们以mpeg4为例,它的实现就在MPEG4Extrator.cpp(),根据seek模式和seek时间从sampletable里面找到meta_data。存到srcBuffer。
让bufferinfo的mData指向元数据的data
设置状态为OWNED_BY_COMPONENT
}
从上面的分析,我们得知emtyBuffer后在5msec之内会有个EmptyBufferDone回调,我们看下omxcodec对该回调的处理:
-------------通过buffer_id找到Vector<BufferInfo> bufferInfo
设置info的状态为OWNED_BY_US
释放mediabuffer
下一片段buffer移交给component
没有数据了退出
锁定该buffer,准备render图像
fillbuffer后获得mVideoBuffer就可以在Awesomeplayer的onvideoEvent方法中的mVideoRenderer->render(mVideoBuffer);进行图像的显示了。
以上我们就是播放的过程了。到此多媒体本地播放流程全部讲完了,里面很多细节的东西,还得大伙自己深入理解,往后有什么需要补充和添加的,我会再次补充上。