第五章多媒体播放器的设计与实现3.1 Mplayer的简介
MPlayer是Linux上的电影播放器(也能跑在许多其它平台上,甚至非x86CPU上)。它能使用众多的本地的,XAnim,RealPlayer,和 Win32 DLL编解码器,播放大多数MPEG,VOB,AVI,OGG,VIVO,ASF/WMV,QT/MOV,FLI,RM,Nuppe1Video,yuv4mpeg,FILM,RoQ文件。你还能观看VideoCD,SVCD,DVD,3ivx,Rea1Media,和DivX格式的电影。Mplayer的另一个大的特色是广泛的输出设备支持。它可以在X11,Xv,DGA,OpenGL,SVGAlib,fbdev,AAlib,DirectFB上工作,而且也能使用GGI和SDL(由此可以使用他们支持的各种驱动模式)和一些低级的硬件相关的驱动模式(比如Matrox,3Dfx和Radeon,Mach64,Permedia3)!他们大多数支持软件或者硬件缩放,因此你能在全屏下观赏电影。 MPlayer还支持通过硬件MPEG解码卡显示。可以使用European/IS08859-1,2(匈牙利语,英语,捷克语等等),西里尔语,韩语的字体的清晰放大并且反锯齿的字幕(支持10种格式)。
该播放器能够稳如泰山的播放被破坏的MPEG文件(对一些VCD有用),而它能播放著名的 windows media player都打不开的坏AVI文件。甚至,没有索引部分的AVI文件可播放,你能暂时由重建他们的索引-idx选择,或者用MEncoder永久重建,使你能够在影片中搜索!如你所见,稳定和质量是最重要的事情,而且他的速度是也惊人的。由此,能够将 Mp1ayer移植到嵌入式系统中将极大丰富嵌入式设备的多媒体性能。[1]
5.1嵌入式播放器Mplayer的设计
5.1.1 播放器的工作流程
媒体播放器要具备解码、音视频同步、播放的功能,其工作流程图如下图4-1
所示。首先,播放器进行自身的初始化,包括检测硬件平台、出错信息处理,打开实时时钟等等。然后读入媒体数据文件,并对文件格式进行解析。通过解析文件格式选择相应的分流器对音视频数据进行分流,并将分流后的数据存入到音视频各自的缓冲区中等待处理。下一步读取缓冲区中音、视频各自的头信息,分别将初始化音、视频的过滤器及解码器,开始进行解码。解码后收集时间戳,音、视频做同步处理。最后,将处理后的音、视频分别送到各自的输出设备上进行播出。
32
开始 系统初始化 读入媒体文件并分析媒体类型 将音视频数据分流到不同的缓冲区 音视频分别进行解码 No 音视频同步 将音视频送入到相应的输出设备播放 Yes 处理完所有帧? 结束
图4-1 播放器工作流程图
5.1.2 播放器的逻辑结构
下图4-2展示了嵌入式播放器Mplayer的逻辑结构,该结构主要分为4个功
能层,它们分别是:
(1) 输入层(input layer):包含读取媒体文件模块,主要负责将文件中的媒体数据按照流的方式读入进来,并将数据存放到一块缓冲区中,解析文件头从而判断该流属于何种音、视频的文件。
(2) 分流层(demuxer layer):即图中分流部分,其主要功能模块为分流器,它的功能是依靠数据头来判断音、视频在这段文件数据中的各自位置,继而对音、视频进行分离。分离后的音、视频数据将分别存入各自缓冲区。分流器同时将提取时间戳(PTS, Presentation time stamp),随音、视频数据一同传送。通过PTS,我们可以有效的控制音频和视频的同步输出。
(3) 解码层(decoder layer):该层不但包含音、视频的解码模块,也包含了音、
33
视频解码器的选择模块。在解码层中,由音、视频解码模块根据分流器分离出来的音、视频数据的压缩格式。初始化对应格式的音、视频解码器以便将音、视频数据分别进行解码,将解码出来的信息输出,传递给下一级的输出层。 (4) 输出层(output layer):主要包含音视频同步,音频输出和视频输出三个模块。这一层由输出模块选择最合适的输出设备驱动,根据PTS确定的同步机制进行音、视频的播放以达到同步的目的。
音频解码器选择 音频解码 音频输出 媒体文件 读取媒体文件数据 分流 音视频同步 视频解码 视频输出 视频解码器选择
图4-2 播放器的逻辑结构
5.1.3 Mplayer播放器的目录文件组织结构
为了实现Mplayer媒体播放器的强大功能,其源代码的文件非常庞杂,其中
一部分功能是嵌入式播放器所不需要的,因此我们要对其进行必要的删改。考虑到嵌入式播放器的的需求,我们去掉了其对TV、VCD、DVD支持的功能,其主要目录及文件功能如下表4-1所示:
表4-1 播放器主要目录及文件功能
目录名
目录功能 媒体数据分析分流库 媒体编解码库 音频输出库 视频输出库
模块的文件调度,如图4-3所示:
A、分流 mplayer.c B、解码 外设输入 与OS相关的文件 音频过滤器库 文件功能 播放器出错信息处理功能实现 播放列表功能实现 CPU类型定义 检测CPU类型 主程序 播放器开始运行后,主程序文件mplayer.c负责分流、解码、输出三个功能
C、输出 dec_audio.c dec_video.c video_out.c vo_*.c display stream.c ad.c stream_*.c ad_*.c vd.c vd_*.c
图4-3 播放器的目录文件组织结构
A、分流
对输入的媒体数据进行分流所要调用的文件都存放在媒体数据分析分流库
35
类型,继而调用对应的分流器文件对媒体数据进行音、视频的分流。播放器包含的分流器类型很多,常用的有demux_asf.c、demux_avi.c、demux_mpg.c、demux_mov.c等等。
B、解码
解码分为视频解码和音频解码。以视频解码为例,媒体编解码库
C、输出
输出也分为视频输出和音频输出。以视频输出为例,视频输出库
5.1.4 播放器对解码器和输出设备的管理方式
媒体文件格式的多样性决定了媒体播放器要处理各种类型的音、视频数据,
媒体播放器高效的全局变量调用关系,使其能够为特定的音、视频数据快速准确地找到对应的解码器,为不同的输出设备安装相应的设备驱动。
播放器将解码相关函数的指针放入一个结构体中,这个结构体在设计模式的意义上讲就是一个接口,这些接口被链在了一起,形成了一个接口表,通过对接口表的查询找出恰当的解码接口参与解码操作。如下图4-4所示,播放器通过分析输入进来的媒体文件头信息,从数据流列表(auto_open_streams)中选取对应的数据流类型,进而在分流器列表当中选择正确的分流器(demuxer)来对媒体文件进行音、视频分流。以视频ffmpeg解码器为例,这个解码器本身支持多种解码格式。播放器首先从视频驱动解码列表(mpcodecs_vd_drivers)中选择ffmpeg视频库解码驱动(mpcodecs_vd_ffmpeg),ffmpeg对每种压缩格式所提供的解码接口函数都被记录到一个叫AVCodec的结构之中,所有的这些结构被链成一个链表,表头存放在一个静态变量之中,可以通过avcodec_find_decoder()函数来查找链表中的结构取得需要的AVCodec结构进行解码。在这种方式下,要添加一个或一系列新的解码器是非常容易的,只需要将解码器的解码接口函数加入一个新的AVCodec结构之中并将这个结构添加到链表之中,这样就可以通过同样的方法使用新加入的解码器了。对输入设备的管理与对解码器的管理十分的相
36