AV框架分层设计
AV框架主要抽象为四个层次:
媒体接入层: access层,负责媒体数据的来源,可能是file、http、fifo、mem等。
解复用层: demux层,负责把容器里的音视频数据剥离出来,然后分别送给audio/video decoder。
解码层: decoder层,将解码完成后的数据(yuv、pcm)送给audio/video output输出。
输出层: output层,负责将decoder过来的数据呈现/播放出来。
如果把数据想象成流水的话,每层的功能虽然不同,但是他们大致抽象的功能都是接收上个模块过来的数据,然后加工并把加工后的数据送到下一个模块。把上述这些层通过某种方式连接起来,就形成了一个音频播放器。
媒体接入层(stream)
UML设计如下图所示:
stream_ops_http、stream_ops_mem、stream_ops_file、stream_ops_fifo分别对应于网络流、内存流、本地文件流、fifo流取流播放。
其中语音合成(TTS)流的播放可基于stream_ops_fifo实现。
后续对于新增的媒体接入类型,可根据struct stream_ops结构中定义的类型,实现对应的接口即可扩展。
媒体接入层中各种流类型的url格式定义规则如下表所示:
流类型 URL前缀 URL格式
网络流 http(s):// http(s)://ip:port/xx.mp3
文件流(SD卡) file:// file:///fatfs0/xx.mp3?avformat=%s&avcodec=%u&channel=%u&rate=%u
内存流 mem:// mem://addr=%u&size=%u&avformat=%u&avcodec=%u&channel=%u&rate=%u
fifo流 fifo:// fifo://tts/1?avformat=%s&avcodec=%u&channel=%u&rate=%u
对于能够探测到媒体信息的码流,url格式中的avformat、avcodec、channel、rate字段不是必须的。
这些配置项一般用于raw pcm的播放(通过这些参数传入裸流的具体格式)。
avformat字段可选有rawaudio/wav/mp3/m4a。
avcodec字段可选有pcm_s16be/pcm_s32be/pcm_s16le/pcm_s32le/pcm_s8/pcm_u16be/pcm_u32be/pcm_u16le/pcm_u32le/pcm_u8。
url格式具体示例如下表所示:
流类型 示例
文件流(SD卡) file:///fatfs0/test.MP3
内存流 mem://addr=765432&size=1024&avformat=rawaudio&avcodec=pcm_s16le &channel=1&rate=16000
fifo流 fifo://tts/1
解复用层(avformat)
UML设计如下图所示:
其中demux_ops_wav、demux_ops_mp3、demux_ops_m4a分别对应于wav、mp3、m4a音频复用格式解复用。解复用出来的一帧音频数据会被送到对应的解码器进行解码。
当前支持wav、mp3、mp4、adts、flac、asf、amr等格式的解复用
后续对于新增的解复用格式,可根据struct demux_ops结构中定义的类型,实现对应的接口即可扩展
解码层(avcodec)
该层将demux解复用后出来的一帧帧编码数据解码成音视频裸数据(pcm/yuv)。
在某些情况下,某些编码类型解码时可能占用很高的主频(如在ck803ef上,HE-AAC解码主频需求在240M左右),此时可能需要通过核间通信(mailbox/IPC)将解码工作放到另一核上执行。
解码层为考虑扩展性,支持本地(核内)与跨核(核间)解码。其中核间解码适配层请参考av/avcodec/ad_ipc.c使用。
核间解码结构如下图所示:
核间解码时序图如下所示:
核内/核间解码框架设计如下图所示:
解码器UML设计如下图所示:
其中ad_ops_pvmp3、ad_ops_rawaudio、ad_ops_opus、ad_ops_fdk分别对应于mp3、裸pcm(解码透传)、opus、aac音频编码格式解码
当前支持mp3、aac、adpcm_ms、flac、amrnb、amrwb等格式的解码
后续对于新增的解码类型,可根据struct ad_ops结构中定义的类型,实现对应的接口即可扩展
输出层(output)
UML设计如下图所示:
其中ao_ops_alsa对应于采用alsa标准音频输出接口实现。通过alsa层来屏蔽各产品不同codec的实现
后续对于新增的输出类型,可根据struct ao_ops结构中定义的类型或在alsa/sound驱动层,实现对应的接口即可扩展
音频输出链路如下图所示: