一种基于VLC的可跨平台的播放器系统设计方法

2021-06-16 14:21蔡晓丽程晓兰
电子技术与软件工程 2021年5期
关键词:共享内存解码器播放器

蔡晓丽 程晓兰

(四川长虹网络科技有限责任公司 四川省绵阳市 621000)

长期以来数字机顶盒上多媒体播放器严重的依耐于各个芯片SDK 提供的媒体播放接口实现。在机顶盒应用开发中,对于每一个芯片平台都需要适配媒体播放接口。加之流媒体的兴起,各种芯片平台对流媒体的支持能力更是参差不齐。基于此设计可跨平台的播放器可以减少对芯片平台的依赖,引进新平台时可以快速的实现播放器成型。通过集成统一的流媒体接口可以更好的规划产品定型。

多媒体涉及MKV, AVI, FLV, WMV, TS 等容器格式以及流媒体中的HLS, Smooth streaming, DASH 等协议内容。媒体完成解析后便形成独立的字幕流,音频流,视频流。将音频流,视频流分别注入芯片底层的解码器实现解码完成播放。利用开源软件实现对多媒体解析,并封装统一的音视频同步控制接口,写解码器控制接口和文件读写控制接口最大程度的弱化媒体播放器对芯片平台的依耐性。另外现有的VLC,FFMPEG 等开源代码均能很好完成多媒体容器解析。而VLC 作为优秀的开源播放器支持多种媒体封装格式解析,而且适用于多个平台集成。

1 播放器系统组成

本文提出一种基于开源软件VLC 的可跨平台应用的多媒体播放器系统。以C/S 模式,VLC 进程作为服务器端等待多媒体解析请求,应用平台端作为客户端向服务端发起播放请求,经进程通信控制模块(IPC)传递播放地址,开启音视频读数据线程并打开底层解码器,之后等待共享内存中视频PES 数据量达到起播值SIZE_READ_START。VLC 进程获取媒体播放地址后开启媒体容器解析线程。一方面将获取的媒体解码器信息包括音视频编码格式,音视频PID 值和文件时长等信息通过IPC 接口传回给客户端。另一方面将音视频流PES 数据写入分配的共享内存BUFFER 供客户端取用。客户端在获取媒体解码信息后配置音视频解码器解码格式。读视频数据线程等待共享内存内数据达到起播阈值后立即开始将数据整块写入解码器缓存,并开启音频流读数据线程。

如图1 所示,播放器系统由两个进程协调实现平台应用客户端进程与VLC 服务端进程。平台应用客户端进程内包括播放器UI 模块,读共享内存控制模块,音视频同步控制模块,解码器模块,输出控制模块,平台抽象层模块。VLC 服务端进程包括媒体解析模块,写共享内存控制模块。各个功能模块的具体实现功能如下。

播放器UI 模块,负责视频元信息展示及视频播放;并与用户交付如暂停,播放,快进快退,SEEK 等播放控制指令。

读共享内存控制模块,负责从共享内存中读视频数据与读音频数据。读取的同时写入解码器控制模块。读视频数据控制等待视频缓存内可用数据量超过阈值SIZE_READ_START 开启读操作。SIZE_READ_START 值的大小会影响起播时间与起播后的流畅性。现在改值量化为20KByte,播放器的起播时间小于15 秒。

读共享内存控制模块,判定当前已写入的数据量Video_writetotalsize 与可读数据量Video_readablesize 进行比较确定读取的数据量Inject_Data_Size。将视频PES 缓存设置成一个循环BUFFER。已写入的数据量Video_writetotalsize 为写入的循环次数Video_writecycle 乘以分配的内存大小VIDEO_BUFFER_MAX_SIZE 在与当前的写地址偏移Video_writesize 求和而得。以读的数据量Video_readtotalsize 为已读的循环次数Video_readcycle 乘以分配的内存大小VIDEO_BUFFER_MAX_SIZE 再与当前的读地址偏移量Video_readsize 求和而得。如图2 所示,根据上述几者的关系确定Inject_Data_Size。读音频数据控制流程与读视频数据控制流程类似不在赘述。

音视频同步控制模块,平台应用第一次读取到视频PES 数据时提取视频第一帧的PTS 值V_PTS。并将此值作为初始值写入平台底层系统同步时间系统,从而初次同步到系统时间戳,再以系统时间戳作为时间基准进行音视频同步。每隔时间T0 抽取音频帧与视频帧的的PTS 时间值与系统时间戳进行对比,如果音频帧PTS 与时间戳的差值远远大于视频帧PTS 值与时间戳的差值则重新收取下一个比较接近PTS 数据的音频帧写入底层解码器实现同步。

解码器模块,如图3 所示,解码器模块下设置音频解码器写控制与视频解码器写控制。以视频解码器写控制为例,读共享内存控制模块获取Inject_Data_Size 后,从共享内存拷贝大小Inject_Data_Size 的数据量写入底层解码器。最终根据解码器驱动接口返回的写入数据值作为真正写入的数据量,并更新Video_readtotalsize 作为下一次的判定标准。输出模块,对接音频输出驱动和视频输出驱动。

平台抽象层模块,根据媒体播放对平台的依赖性,该模块需要提供内存管理,文件系统,内核管理等平台抽象封装。对平台抽象层的每个模块进行类定义,在类的设计采用C++虚函数机制,该种机制能够实现运行时绑定的特性,因此派生类的行为不影响基类以及基类同一基类的派生类的行为。

媒体解析模块,VLC2.2.0 在DecoderThread 线程内查询共享内存的视频数据的缓存量确定是否继续向共享内存数据写入。Video_readtotalsize 减去Video_writetotalsize 得到的差值Sub_videosize,如果差值大于分配的视频数据缓存量VIDEO_BUFFER_MAX_SIZE*(3/5)就需要暂停从解析线程中读取数据到共享内存。写共享内存控制模块,根据音视频的PID 值分别将音视频PES 数据写入共享内存。

图1:基于VLC 的可跨平台应用的播放器架构图

图3:播放器系统中解析解码功能结构框图

2 PES数据进程交付控制流程

该播放系统的一个重要组成是PES 数据的进程交付控制。一种VLC 提取媒体文件PES 数据以共享内存方式交付另一进程的方法包括以下步骤。

(1)根据需要设置VLC 以文件写入方式输出媒体文件解析的ES 数据到移动硬盘,具体控制命令为:argv[argc++]= "-vvv";argv[argc++]= "--no-loop";argv[argc++]= "--sout";argv[argc++]= "#es{access=file, dst-video=/mnt/usb/video_%d.%c, dst-audio=/mnt/usb/audio_%d.%c}";该控制指令为将解析输出的ES 数据写入到存储盘/mnt/usb。

(2)VLC 进程运行初始化阶段关联共享内存地址到本地内存地址,内存大小分配为视频PES 数据缓存为3.768MByte,音频PES数据缓存为1.88MByte,控制信息缓存1024KByte。

(3)VLC 进程接收播放请求后,首先获取通道音视频编解码信息。其次开启媒体播放线程。在获取文件播放地址后调用libvlc_media_get_duration 获取媒体的时长信息,通过接口libvlc_media_get_tracks_info 获取音视频通道解码信息。通过调用接口libvlc_media_player_play 开启播放流程。

(4)VLC 将解析获取的通道音视频解码信息,写入共享内存控制信息缓存。VLC 需要将解析的视频ES 数据转换成视频PES 数据并写入视频数据缓存,解析的音频ES 数据转换成音频PES 数据写入音频数据缓存。在ES 输出的指令驱使下,VLC2.2.0 在线程DecoderThread 中将解析器输出的数据包经接口DecoderProcessSout写入到对应的存储盘地址/mnt/usb/。此处需要阻断上述过程,修改函数DecoderProcessSout 在得到解析ES 包数据后经重新封装的接口sout_AccessOutMemoryWrite 写入到共享内存。重新封装的接口sout_AccessOutMemoryWrite 首先将ES 数据转换成PES 数据然后写入共享内存。音视频PES 数据写入以PID 信息作为区分标志。VLC2.2.0 中线程DecoderThread 需轮询共享内存区域状态,根据状态确定是否继续向共享内存写入数据,否则会造成数据溢出花屏问题; 轮询平台解码器状态,确定是否继续向共享内存写入数据。

3 结论

本文提出的可跨平台的播放系统将多媒体播放器划分为媒体解析,音视频同步,解码,渲染等几个组成部分。以多进程的方式利用开源软件VLC2.2.0 实现媒体解析,以共享内存方式进行数据通信,仅利用芯片平台提供的解码器解码独立的音视频数据流实现多媒体播放器。利用该方法可以方便在不同芯片平台上集成具有统一播放体验的多媒体播放器。

猜你喜欢
共享内存解码器播放器
科学解码器(一)
科学解码器(二)
科学解码器(三)
Walkman诞生40周年 索尼适时发布NW-ZX500和NW-A100系列播放器
线圣AudioQuest 发布第三代Dragonfly Cobalt蓝蜻蜓解码器
通过QT实现进程间的通信
基于STM32的MP3播放器设计
Moon ACE播放器/放大器一体机
基于PCI总线的多处理器协同机制研究
播放器背板注塑模具设计