1、mplayer 源码分析一.Mplayer支持的格式MPlayer是一个LINUX下的视频播放器,它支持相当多的媒体格式,无论在音频播放还是在视频播放方面,可以说它支持的格式是相当全面的。视频格式支持:MPEG、AVI、ASF 与WMV、QuickTime 与 OGG/OGM、SDP、PVA、GIF。音频格式支持:MP3、WAV、OGG/OGM 文件(Vorbis)、WMA 与 ASF、MP4、CD音频、XMMS。二. Mplayer 中头文件的功能分析1.config.h/各种本地配置宏定义头2.version.h/版本定义头#defineVERSION1.0pre7try2-3.4.23.
2、mp_msg.h/消息处理头4.help_mp.h/根据配置自动生成的帮助头#includehelp/help_mpen.h5.cfg-mplayer-def.h/Mplayer运行时的选项缺省值头文件char*6.default_config=7.sub_reader.h/拥有格式自动发现功能的字幕(subtitle)阅读器8.libvo/video_out.h/该文件包含libvo视频输出的公共函数、变量9.libvo/font_load.h/有关字体装载的例程10.libao2/audio_out.h/音频输出驱动程序相关结构定义和全局数据11.libmpcodecs/dec_audio
3、.h/音频解码12.libmpcodecs/dec_video.h/视频解码13.libmpdemux/matroska.h/多路解复用,媒体容器格式matroska处理头14.libmpdemux/stream.h/流处理15.libmpdemux/demuxer.h/多路解复用头文件16.libmpdemux/stheader.h/媒体流头处理17.get_path.c/路径获取头文件18.spudec.h/SPU子画面单元头,DVD字幕流19.edl.h/剪辑控制清单20.m_option.h/选项类型处理头21.m_config.h/配置处理头文件三. MPlayer.main 主流程
4、简要说明1.intmain()2.1)变量声明,电影信息movieinfo:3.2)初始化,消息系统4.play_next_file:5.3)播放文件filename的循环gotoplay_next_file开始6.main:7.4)主处理main8.5)播放真正主循环20103541while(!eof)9.while(!eof)10.5.1)播放音频PLAYAUDIO20172064decode_audio(sh_audio,.);11.5.2)播放视频PLAYVIDEO,20682300decode_video(sh_video,.);12.5.3)处理暂停PAUSE13.5.4)处理E
5、DL14.5.5)键盘事件处理,搜索24003216while(!brk_cmd&15.(cmd=mp_input_get_cmd(0,0,0)!=NULL)16.5.6)时间寻道(秒)if(seek_to_sec)17.5.7)寻道32433306,if(rel_seek_secs|abs_seek_pos)18.5.8)处理GUI19.5.9)变更UpdateOSD20.5.10)找到字幕findsub21.5.11)处理X11窗口22.5.12)DVD字幕sub:23.24.goto_next_file:25.6)播放结束,转到下个文件goto_next_file:26.四.Mplaye
6、r源码分析从Mplayer.c的main开始处理参数1.mconfig=m_config_new();2.m_config_register_options(mconfig,mplayer_opts);3./TODO:addsomethingtoletmodulesregistertheiroptions4.mp_input_register_options(mconfig);5.parse_cfgfiles(mconfig);初始化mpctx结构体,mpctx应该是mplayer context的意思,顾名思义是一个统筹全局的变量。cppview plaincopy1.staticMPCon
7、text*mpctx=&mpctx_s;2./Notallfunctionsinmplayer.ctakethecontextasanargumentyet3.staticMPContextmpctx_s=4.osd_function=OSD_PLAY,5.begin_skip=MP_NOPTS_VALUE,6.play_tree_step=1,7.global_sub_pos=-1,8.set_of_sub_pos=-1,9.file_format=DEMUXER_TYPE_UNKNOWN,10.loop_times=-1,11.#ifdefHAS_DVBIN_SUPPORT12.last_
8、dvb_step=1,13.#endif14.;原型1./真正统筹全局的结构2.typedefstructMPContext3.intosd_show_percentage;4.intosd_function;5.constao_functions_t*audio_out;6.play_tree_t*playtree;7.play_tree_iter_t*playtree_iter;8.inteof;9.intplay_tree_step;10.intloop_times;11.12.stream_t*stream;13.demuxer_t*demuxer;14.sh_audio_t*sh_a
9、udio;15.sh_video_t*sh_video;16.demux_stream_t*d_audio;17.demux_stream_t*d_video;18.demux_stream_t*d_sub;19.mixer_tmixer;20.constvo_functions_t*video_out;21./Framesbufferedinthevoreadytoflip.Currentlyalways0or1.22./Thisisreallyavovariablebutcurrentlytheresnosuitablevo23./struct.24.intnum_buffered_fra
10、mes;25.26./usedtoretrydecodingafterstartup/seekingtocompensateforcodecdelay27.intstartup_decode_retry;28./howlonguntilweneedtodisplaythecurrentframe29.floattime_frame;30.31./AVsync:thenextframeshouldbeshownwhentheaudioouthasthis32./much(inseconds)buffereddataleft.Increasedwhenmoredatais33./writtento
11、theao,decreasedwhenmovingtothenextframe.34./Intheaudio-onlycaseusedasatimersincethelastseek35./bytheaudioCPUusagemeter.36.doubledelay;37.38.floatbegin_skip;/starttimeofthecurrentskipwhileonedloutmode39./audioismutedifeitherEDLoruseractivatesmute40.shortedl_muted;/StoreswhetherEDLiscurrentlyinmutedmo
12、de.41.shortuser_muted;/Storeswhetheruserwantedmutedmode.42.43.intglobal_sub_size;/thisencompassesallsubtitlesources44.intglobal_sub_pos;/thisencompassesallsubtitlesources45.intset_of_sub_pos;46.intset_of_sub_size;47.intsub_countsSUB_SOURCES;48.#ifdefCONFIG_ASS49./set_of_ass_tracksicontainssubtitlesf
13、romset_of_subtitlesi50./parsedbylibassorNULLifformatunsupported51.ASS_Track*set_of_ass_tracksMAX_SUBTITLE_FILES;52.#endif53.sub_data*set_of_subtitlesMAX_SUBTITLE_FILES;54.55.intfile_format;56.57.#ifdefCONFIG_DVBIN58.intlast_dvb_step;59.intdvbin_reopen;60.#endif61.62.intwas_paused;63.64.#ifdefCONFIG_
14、DVDNAV65.structmp_image*nav_smpi;/lastdecodeddvdnavvideoimage66.unsignedchar*nav_buffer;/lastreaddvdnavvideoframe67.unsignedchar*nav_start;/pointertolastreadvideobuffer68.intnav_in_size;/stream=open_stream(filename,0,&mpctx-file_format);2.fileformat文件还是TV流DEMUXER_TYPE_PLAYLIST或DEMUXER_TYPE_UNKNOWN3.
15、DEMUXER_TYPE_TV4.current_module记录状态vobsubopen_streamhandle_playlistdumpstream5.stream_reset(mpctx-stream);6.stream_seek(mpctx-stream,mpctx-stream-start_pos);7.f=fopen(stream_dump_name,”wb”);dump文件流8.stream-type=STREAMTYPE_DVD/= Open DEMUXERS DETECT file type =Demux。分离视频流和音频流1.mpctx-demuxer=demux_ope
16、n(mpctx-stream,mpctx-2.file_format,audio_id,video_id,dvdsub_id,filename);3.Demux过程4.demux_open5.get_demuxer_type_from_name6.7.mpctx-d_audio=mpctx-demuxer-audio;8.mpctx-d_video=mpctx-demuxer-video;9.mpctx-d_sub=mpctx-demuxer-sub;10.mpctx-sh_audio=mpctx-d_audio-sh;11.mpctx-sh_video=mpctx-d_video-sh;分离
17、了之后就开始分别Play audio和video这里只关心play video1./*=PLAYVIDEO=*/2.vo_pts=mpctx-sh_video-timer*90000.0;3.vo_fps=mpctx-sh_video-fps;4.if(!mpctx-num_buffered_frames)5.doubleframe_time=update_video(&blit_frame);6.mp_dbg(MSGT_AVSYNC,MSGL_DBG2,”*ftime=%5.3f*n”,frame_time);7.if(mpctx-sh_video-vf_initedeof=1;gotogo
18、to_next_file;10.11.if(frame_timeeof=1;13.else14./mightreturnwith!eof&!blit_frameif!correct_pts15.mpctx-num_buffered_frames+=blit_frame;16.time_frame+=frame_time/playback_speed;/fornosound17.18.关键的函数是update_video根据pts是否正确调整一下同步并在必要的时候丢帧处理。最终调用decode_video开始解码(包括generate_video_frame里)。mpi = mpvdec-dec
19、ode(sh_video, start, in_size, drop_frame);mpvdec是在main里通过reinit_video_chain的一系列调用动态选定的解码程序。其实就一结构体。它的原型是1.typedefstructvd_functions_s2.3.vd_info_t*info;4.int(*init)(sh_video_t*sh);5.void(*uninit)(sh_video_t*sh);6.int(*control)(sh_video_t*sh,intcmd,void*arg,);7.mp_image_t*(*decode)(sh_video_t*sh,void
20、*data,intlen,intflags);8.vd_functions_t;这是所有解码器必须实现的接口。int (*init)(sh_video_t *sh);是一个名为init的指针,指向一个接受sh_video_t *类型参数,并返回int类型值的函数地址。那些vd_开头的文件都是解码相关的。随便打开一个vd文件以上几个函数和info变量肯定都包含了。mpi被mplayer用来存储解码后的图像。在mp_image.h里定义。1.typedefstructmp_image_s2.unsignedshortflags;3.unsignedchartype;4.unsignedcharbp
21、p;/bits/pixel.NOTdepth!forRGBitwillben*85.unsignedintimgfmt;6.intwidth,height;/storeddimensions7.intx,y,w,h;/visibledimensions8.unsignedchar*planesMP_MAX_PLANES;9.intstrideMP_MAX_PLANES;10.char*qscale;11.intqstride;12.intpict_type;/0-unknown,1-I,2-P,3-B13.intfields;14.intqscale_type;/0-mpeg1/4/h263,
22、1-mpeg215.intnum_planes;16./*theseareonlyusedbyplanarformatsY,U(Cb),V(Cr)*/17.intchroma_width;18.intchroma_height;19.intchroma_x_shift;/horizontal20.intchroma_y_shift;/vertical21./*forprivateusebyfilterorvodriver(tostorebufferidordmpi)*/22.void*priv;23.mp_image_t;图像在解码以后会输出到显示器,mplayer本来就是一个视频播放器么。但
23、也有可能作为输入提供给编码器进行二次编码,MP附带的mencoder.exe就是专门用来编码的。在这之前可以定义filter对图像进行处理,以实现各种效果。所有以vf_开头的文件,都是这样的filter。图像的显示是通过vo,即video out来实现的。解码器只负责把解码完成的帧传给vo,怎样显示就不用管了。这也是平台相关性最大的部分,单独分出来的好处是不言而喻的,像在Windows下有通过direcx实现的vo,Linux下有输出到X的vo。vo_*文件是各种不同的vo实现,只是他们不都是以显示为目的,像vo_md5sum.c只是计算一下图像的md5值。在解码完成以后,即得到mpi以后,filter_video被调用,其结果是整个filter链上的所有filter都被调用了一遍,包括最后的VO,在vo的put_image里把图像输出到显示器。这个时候需要考虑的是图像存储的方法即用哪种色彩空间。附上两张MPlayer结构图:如有侵权请联系告知删除,感谢你们的配合!
copyright@ 2008-2023 冰点文库 网站版权所有
经营许可证编号:鄂ICP备19020893号-2