Android系统很多模块都是采用采取C/S架构模式,金典的3层结构(ep: Camera, Audio, Surface, Mediaplayer ……)
以多媒体在安卓系统中的分层结构为例:
根据图上的播放地址,可以给android系统支持的多媒体分为3类
1:本地文件播放:也就是从手机的sdcard中读取文件播放,这里我将http://192.xxxx.mp4也分到本地文件,因为他们的解析是差不多的,不同的是http是从网络上取出一段MP4进行解析
2:http协议:这个根据m3u8文件格式进行解析
3:rtsp协议:直播协议
后面我会详细介绍这几种协议
1:mp4,ts,mkv这些格式相当于一个容器,里面封装了audio,video,字幕等数据。
2 :解析文件的目的有两个:
1):将音频和视频的数据分离
2):将播放时间对应到文件的内存地址(举个例子:用户想seek到mp4文件2min的地方播放
那解析完成之后,要通过这个时间找到对应的文件的内存地址。)
如何解析:
根据上图简单说明:
1)track字段:就是当前有几个音视频轨道
2)stbl字段下面包括很多字段,主要就是通过这些字段来计算每一个track的时间到内存地址的映射。
3)stsd字段 sample description box, 视频的编码类型、宽高、长度,音频的声道、采样等信息都会出现在这个box中。
4)stts字段存储了sample的duration
5)stsz定义了每个sample的大小
6)stsc定义了chunk到sample的映射
7)stss定义了video的关键帧
8)stco定义了定义了每个thunk在媒体流中的位置
这样根据每一个文件格式的解析协议解析出音频和视频然后传到给解码器进行解码,然后将解码出的pcm和yuv数据,分别传递给alsa和surface进行显示
输入的link是这种http://192.xxx.xxx.m3u8,m3u8 是一种文件格式内容如下
下图左边是带宽自适应使用的link,右边是其中的一个link
http的link通过解析之后得到一个ts文件下载地址,每个ts文件都会有duration。下载完成之后,剩下的操作就和本地播放一样了,通过Extractor解析ts文件,分离音视频,然后将音视频数据传递给解码器
1.2.3:rtsp 协议
Client通过tcp和server建立rtsp连接,然后发送消息。Client需要知道的内容:
1:server端有几个track
2:audio和video的信息,音频采样率,声道数,视频的宽高
3:音视频的端口号,之后client创建udp通道,接收server发过来的音视频数据。
接收的音视频数据不再是之前提到的本地文件一样的ts,mp4这样的格式,而是裸的h264,aac等。
以上android支持的media协议部分就讲到这里。基本上包含了主流的多媒体协议
FillThisBuffer:codec告诉omx解码的数据填入这个buffer里面
FillThisBufferDone:omx告诉解码器解码的数据已经填入这个buffer
EmptyThisBuffer:codec告诉omx取这个buffer里面的数据进行解码
EmptyThisBufferDone:omx告诉codec这个buffer的数据已经解码完成
Render中有两个buffer队列,分别存放codec解码完成之后的pcm数据和yuv数据。这里面做的最重要的工作就是A/V sycn
主要是根据buffer里面的时间戳来进行同步,同步的原则是以音频的时间为基准,比较视频的时间戳进行丢帧或者延迟显示
MixerThread 主要工作:
1:操作声卡驱动将pcm数据写入底层。
2:如果有多个track,会将pcm混成一个
3:设置pcm音量等
OffloadThread:
主要是mp3文件使用,传入的是没有解码的mp3数据
Machine 是指某一款机器,可以是某款设备,某款开发板,又或者是某款智能手机,由此可以看出 Machine几乎是不可重用的,每个Machine上的硬件实现可能都不一样,CPU不一样,Codec不一样,音频的输入、输出设备也不一样,Machine为CPU、Codec、输入输出设备提供了一个载体。
Platform 一般是指某一个SoC平台,比如pxaxxx,s3cxxxx,omapxxx等等,与音频相关的通常包含该SoC中 的时钟、DMA、I2S、PCM等等,只要指定了SoC,那么我们可以认为它会有一个对应的Platform,它只与 SoC相关,与Machine无关,这样我们就可以把Platform抽象出来,使得同一款SoC不用做任何的改动,就 可以用在不同的Machine中。实际上,把Platform认为是某个SoC更好理解。
Codec 字面上的意思就是编解码器,Codec里面包含了I2S接口、D/A、A/D、Mixer、PA(功放),通常 包含多种输入(Mic、Line-in、I2S、PCM)和多个输出(耳机、喇叭、听筒,Line-out),Codec和 Platform一样,是可重用的部件,同一个Codec可以被不同的Machine使用。嵌入式Codec通常通过I2C对 内部的寄存器进行控制。
6:Surface 显示部分
7:底层fb的操作
显示部分最复杂的还是Surface和上层App的绘制过程。因为涉及到各个窗口的覆盖,穿透,大小的计算等问题。
Android的UI部分是每一版更新的重点,基本上每一版都有很大变化,因为UI的流畅性是手机性能高低的主要体现
以上部分设计JAVA层,native层,直到Linux的kernel部分。了解它们的全貌,有助于我们理解整个android的架构。