mplayer大体框架及流程可参考网络其他资料。这里只是记录一些小细节。 mplayer解码视频数据时基本可以分为如下几个步骤:解析参数、demux、选择音视频codec(包括选择初始化vo vf等)、解码数据、输出到显示设备,依次循环解码显示。
1、先看了视频codec的选择部分。大体过程如下:reinit_video_chain()--> init_best_video_codec(sh_video,video_codec_list,video_fm_list)-->init_video(sh_video, NULL, NULL, status, &selected)--> find_video_codec(sh_video->format,sh_video->bih ? ((unsigned int sh_video->codec, force))-->find_codec(fourcc, fourccmap, start, 0, force); 其中归根结底是在find_codec中进行匹配,匹配方式是通过FOURCC进行的,FOURCC可以对视频数据进行标识,在/etc/codec.conf中定义了所有的解码器,其中有两个关键字fourcc与format都代表了FOURCC字段,从代码common_init()-->parse_codec_cfg(MPLAYER_CONFDIR "/codecs.conf")中可以看出,format与fourcc字段都被添加到fourcc中,都标识视频编码格式,选择过程即init_video通过两次循环,首先查找status低于untested的编码格式与fourcc匹配的所有编码器,第二次循环式在这些编码器重查找第一个status=working的编码器,并执行init初始化如果成功,则选择此codec,如果不成功,继续选择下面的。 所以存在这种情况,即有多个解码器都可以解码此文件,则mplayer从第一个开始选。
2、vf--vo流程:
选择vo:首先通过reinit_video_chain()-->init_best_video_out(video_driver_list) 选择一个合适的vo,(注 preinit成功的第一个vo即选中)。
init_best_video_codec(sh_video,video_codec_list,video_fm_list)-->init_video(sh_video, NULL, NULL, status, &selected)-->init(sh_video)中调mpcodecs_config_vo(sh,sh->disp_w,sh->disp_h,sh->bih ? sh->bih->biCompression : sh->format)中调用vf->query_format(vf, out_fmt)来匹配codec中的out输出格式,如果有不需要转化支持的(VFCAP_CSP_SUPPORTED_BY_HW),则选择。否则选择第一个满足VFCAP_CSP_SUPPORTED的输出格式。并且在下面代码中还会调用vf_config_wrapper(vf, sh->disp_w, sh->disp_h, screen_size_x, screen_size_y, vocfg_flags,out_fmt) == 0)-->vf->config(vf, width, height, d_width, d_height, flags, outfmt);(位置在libmpcodecs\vf_vo.c),代码中包含++vo_config_count使得后面显示的时候不会因vo_config_count==0而退出。
下面是解码播放视频时,update_video(int *blit_frame)-->filter_video(sh_video, decoded_frame,sh_video->pts)-->vf->put_image(vf, mpi, pts)。 put_image会调用vo实现的显示方法。
其中,vf->put_image(vf, mpi, pts)是在libmpcodecs/vf_vo.c中定义的,在里面赋值具体使用drawslice 还是别的显示方式。
3、使用cache时进行的操作:
在mplayer.c的main函数中goto_enable_cache,stream_enable_cache(***),在此函数中通过线程(ThreadProc)或者fork子进程的方式进行原始视频数据到cache的搬运工作,之后demux便从cache中取数据进行相应操作。之后ThreadProc-->Cache_fill(s)-->stream_read(**)-->cache_stream_fill_buffer(s),在此函数中调用stream_fill_buffer()方法进行原数据--cache buffer的搬运。原理是在stream_enable_cache中有两个进程或者是两个线程,通过stream->cache_pid进行区分,来决定是否执行cache_stream_fill_buffer(s)中的stream_fill_buffer();语句。 通过循环填充方式为demux提供数据。
此处有一个注意的点是:播放文件与播放网络流stream_fill_buffer调用的方法不同,分别是fill_buffer 或者streaming_ctrl->streaming_read,此函数指针是在stream_st结构体中定义的。
4、demuxer流程 待续
注:一家之言,各位同仁如发现错误请帮助指正。
阅读(1632) | 评论(1) | 转发(0) |