MPlayer视频输出框架分析

来源:互联网 发布:随身携带淘宝去异界 编辑:程序博客网 时间:2024/05/22 13:16
最近要在离子二代平台上移植数字电视播放器,采用NVIDIA的VDPAU硬解码,视频输出采用VDPAU,由于VDPAU不光有视频硬解码功能,还有HW Scale的功能,所以可以基于VDPAU做浮动OSD层(频道列表)。源于这个,最近仔细地分析了一下MPlayer的视频输出框架,着重解释了VDPAU视频输出插件。
1.视频输出框架
    mplayer整体框架采用了函数指针来实现面向对象,视频输出依然不例外。mplayer视频输出包括两层:filter和video out层。video out层是被包含在filter之中。video out层的插件代码是以vo_开头,例如vo_x11.c,vo_xv.c,vo_vdpau.c等等。filter有一个典型的插件就是vf_vo.c,该filter是对video out层的包装。视频解码完毕后是通过filter(vf_vo.c)来调用vo_vdpau.c
2.视频输出插件介绍
    每一个视频输出插件都至少包含如下函数:
    1)preinit:预初始化视频输出插件,该步骤初始化和视频格式不相关的部分,例如视频输出的窗口大小和格式都不应该在该函数中完成。
    VDPAU输出插件的preinit函数:子选项解析,vdpau库初始化,变量初始化。
    2)control:控制视频输出插件。
    VDPAU输出插件的control函数:主要实现了如下功能。
     request = 2,视频输出格式查询
     request = 32,设置和屏幕相关的信息,没有涉及到媒体的格式和分辨率。
     request = 9, 为视频帧分配空间。
     request = 13,输出视频帧到内存,准备flip
    3)config:配置视频输出的插件,包括视频输出的分辨率,视频输出的格式等。
    VDPAU输出插件的config函数:创建x窗口,设置窗口属性,创建VDPAU相关设备
    4)draw_slice:多个slice做成一个frame。
    VDPAU输出插件的draw_slice函数:VDPAU的真正的硬解码是在该函数中做的,MPlayer中关于VDPAU的硬解码实际上是在输出端做的,解码器中实际上只是对帧进行分离,并没有做真正的解码。
    5)draw_osd:绘制osd层。
    6)flip_page:将frame刷新到屏幕上。
3.视频输出初始化
    1)选择视频输出插件并进行预初始化
    该步骤是有mplayer.c中的reinit_video_chain()来完成的,分如下几个步骤完成。
    init_best_video_out()先根据用户指定的视频输出插件的名称去匹配视频输出插件,如果匹配成功,进行预初始化(preinit),然后返回;如果没有匹配成功或者预初始化失败,则逐个预初始化视频输出插件,直到有个预初始化成功,则返回该视频输出插件。
    vf_open_filter()打开vo过滤器(对应vf_vo.c),在该函数分配的内存在uninit_video中释放.
    init_best_video_codec()先根据指定解码器名称打开指定的解码器,否则遍历解码器链表,逐个初始化,直到有一个初始化成功。初始化解码器的函数是init_video,该函数根据解码器名称找到相应的解码器,如果在内置解码器中没有找到解码器,则从动态链接库中寻找。找到相应的解码器后,初始化解码器。
4.视频播放
   VDPAU的视频输出的过程如下:
   control(9:get_image)->control(21:no)->draw_slice->control(13:draw_image)->draw_osd->flip_page->
   1. control(request = 9, ......)
   为解码的帧分配空间,该空间由视频输出插件分配。
   2. control(request = 21, ......)
   通知一个slice开始,VDPAU没有实现这个。
   3. draw_slice()
   对一个slice进行解码,对于VDPAU来说,一个slice就是一个视频输出帧。
   4. control(request = 13, ......)
   将解码后的视频帧输出到输出插件的内存中。
   5. draw_osd()
   在视频帧上绘制OSD
   6. flip_page()
   将生成了OSD层的视频帧刷新到屏幕上。