`

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 中头文件的功能分析

 

config.h // 各种本地配置宏定义头
version.h // 版本定义头 #define VERSION "1.0pre7try2-3.4.2"
mp_msg.h // 消息处理头
help_mp.h // 根据配置自动生成的帮助头 #include "help/help_mpen.h"
cfg-mplayer-def.h // Mplayer 运行时的选项缺省值头文件 char*
default_config =
sub_reader.h // 拥有格式自动发现功能的字幕(subtitle)阅读器
libvo/video_out.h // 该文件包含 libvo 视频输出的公共函数、变量
libvo/font_load.h // 有关字体装载的例程
libao2/audio_out.h // 音频输出驱动程序相关结构定义和全局数据
libmpcodecs/dec_audio.h // 音频解码
libmpcodecs/dec_video.h // 视频解码
libmpdemux/matroska.h // 多路解复用,媒体容器格式 matroska 处理头
libmpdemux/stream.h // 流处理
libmpdemux/demuxer.h // 多路解复用头文件
libmpdemux/stheader.h // 媒体流头处理
get_path.c // 路径获取头文件
spudec.h // SPU 子画面单元头,DVD 字幕流
edl.h // 剪辑控制清单
m_option.h // 选项类型处理头
m_config.h // 配置处理头文件

 

 

三. MPlayer.main 主流程简要说明

 

int main() {
1) 变量声明,电影信息 movie info:
2) 初始化,消息系统……
play_next_file:
3)播放文件 filename 的循环 goto play_next_file 开始
main:
4) 主处理 main
5) 播放真正主循环 2010 ~3541 while (!eof)
while (!eof) {
5.1) 播放音频 PLAY AUDIO 2017 ~ 2064 decode_audio(sh_audio, ...);
5.2) 播放视频 PLAY VIDEO, 2068 ~ 2300 decode_video(sh_video, ...);
5.3) 处理暂停 PAUSE
5.4) 处理 EDL
5.5) 键盘事件处理, 搜索2400~3216 while (!brk_cmd &&
(cmd=mp_input_get_cmd(0,0,0))!=NULL)
5.6) 时间寻道(秒) if (seek_to_sec)
5.7) 寻道 3243 ~ 3306, if (rel_seek_secs || abs_seek_pos)
5.8) 处理 GUI
5.9) 变更 Update OSD
5.10) 找到字幕 find sub
5.11) 处理 X11 窗口
5.12) DVD 字幕 sub:
}
goto_next_file:
6) 播放结束,转到下个文件 goto_next_file:
}

 


四.Mplayer源码分析
从Mplayer.c的main开始处理参数

mconfig = m_config_new();
m_config_register_options(mconfig,mplayer_opts);
// TODO : add something to let modules register their options
mp_input_register_options(mconfig);
parse_cfgfiles(mconfig);

初始化mpctx结构体,mpctx应该是mplayer context的意思,顾名思义是一个统筹全局的变量。

static MPContext *mpctx = &mpctx_s;
// Not all functions in mplayer.c take the context as an argument yet
static MPContext mpctx_s = {
.osd_function = OSD_PLAY,
.begin_skip = MP_NOPTS_VALUE,
.play_tree_step = 1,
.global_sub_pos = -1,
.set_of_sub_pos = -1,
.file_format = DEMUXER_TYPE_UNKNOWN,
.loop_times = -1,
#ifdef HAS_DVBIN_SUPPORT
.last_dvb_step = 1,
#endif
};

原型

 

//真正统筹全局的结构
typedef struct MPContext {
    int osd_show_percentage;
    int osd_function;
    const ao_functions_t *audio_out;
    play_tree_t *playtree;
    play_tree_iter_t *playtree_iter;
    int eof;
    int play_tree_step;
    int loop_times;

    stream_t *stream;
    demuxer_t *demuxer;
    sh_audio_t *sh_audio;
    sh_video_t *sh_video;
    demux_stream_t *d_audio;
    demux_stream_t *d_video;
    demux_stream_t *d_sub;
    mixer_t mixer;
    const vo_functions_t *video_out;
    // Frames buffered in the vo ready to flip. Currently always 0 or 1.
    // This is really a vo variable but currently there's no suitable vo
    // struct.
    int num_buffered_frames;

    // used to retry decoding after startup/seeking to compensate for codec delay
    int startup_decode_retry;
    // how long until we need to display the "current" frame
    float time_frame;

    // AV sync: the next frame should be shown when the audio out has this
    // much (in seconds) buffered data left. Increased when more data is
    // written to the ao, decreased when moving to the next frame.
    // In the audio-only case used as a timer since the last seek
    // by the audio CPU usage meter.
    double delay;

    float begin_skip; ///< start time of the current skip while on edlout mode
    // audio is muted if either EDL or user activates mute
    short edl_muted; ///< Stores whether EDL is currently in muted mode.
    short user_muted; ///< Stores whether user wanted muted mode.

    int global_sub_size; // this encompasses all subtitle sources
    int global_sub_pos; // this encompasses all subtitle sources
    int set_of_sub_pos;
    int set_of_sub_size;
    int sub_counts[SUB_SOURCES];
#ifdef CONFIG_ASS
    // set_of_ass_tracks[i] contains subtitles from set_of_subtitles[i]
    // parsed by libass or NULL if format unsupported
    ASS_Track* set_of_ass_tracks[MAX_SUBTITLE_FILES];
#endif
    sub_data* set_of_subtitles[MAX_SUBTITLE_FILES];

    int file_format;

#ifdef CONFIG_DVBIN
    int last_dvb_step;
    int dvbin_reopen;
#endif

    int was_paused;

#ifdef CONFIG_DVDNAV
    struct mp_image *nav_smpi;   ///< last decoded dvdnav video image
    unsigned char *nav_buffer;   ///< last read dvdnav video frame
    unsigned char *nav_start;    ///< pointer to last read video buffer
    int            nav_in_size;  ///< last read size
#endif
} MPContext;

 

 

一些GUI相关的操作
打开字幕流
打开音视频流

mpctx->stream=open_stream(filename,0,&mpctx->file_format);
fileformat 文件还是TV 流DEMUXER_TYPE_PLAYLIST 或DEMUXER_TYPE_UNKNOWN
DEMUXER_TYPE_TV
current_module记录状态vobsub open_stream handle_playlist dumpstream
stream_reset(mpctx->stream);
stream_seek(mpctx->stream,mpctx->stream->start_pos);
f=fopen(stream_dump_name,”wb”); dump文件流
stream->type==STREAMTYPE_DVD

//============ Open DEMUXERS — DETECT file type ======================
Demux。分离视频流和音频流

mpctx->demuxer=demux_open(mpctx->stream,mpctx-
>file_format,audio_id,video_id,dvdsub_id,filename);
Demux过程
demux_open
get_demuxer_type_from_name
……
mpctx->d_audio=mpctx->demuxer->audio;
mpctx->d_video=mpctx->demuxer->video;
mpctx->d_sub=mpctx->demuxer->sub;
mpctx->sh_audio=mpctx->d_audio->sh;
mpctx->sh_video=mpctx->d_video->sh;

分离了之后就开始分别Play audio和video
这里只关心play video

/*======================== PLAY VIDEO ============================*/
vo_pts=mpctx->sh_video->timer*90000.0;
vo_fps=mpctx->sh_video->fps;
if (!mpctx->num_buffered_frames) {
double frame_time = update_video(&blit_frame);
mp_dbg(MSGT_AVSYNC,MSGL_DBG2,”*** ftime=%5.3f ***\n”,frame_time);
if (mpctx->sh_video->vf_inited < 0) {
mp_msg(MSGT_CPLAYER,MSGL_FATAL, MSGTR_NotInitializeVOPorVO);
mpctx->eof = 1; goto goto_next_file;
}
if (frame_time < 0)
mpctx->eof = 1;
else {
// might return with !eof && !blit_frame if !correct_pts
mpctx->num_buffered_frames += blit_frame;
time_frame += frame_time / playback_speed; // for nosound
}
}



关键的函数是update_video根据pts是否正确调整一下同步并在必要的时候丢帧处理。最终调用decode_video开始解码(包括generate_video_frame里)。mpi = mpvdec->decode(sh_video, start, in_size, drop_frame);mpvdec是在main里通过reinit_video_chain的一系列调用动态选定的解码程序。其实就一结构体。它的原型是

typedef struct vd_functions_s
{
vd_info_t *info;
int (*init)(sh_video_t *sh);
void (*uninit)(sh_video_t *sh);
int (*control)(sh_video_t *sh,int cmd,void* arg, …);
mp_image_t* (*decode)(sh_video_t *sh,void* data,int len,int flags);
} vd_functions_t;

这是所有解码器必须实现的接口。
int (*init)(sh_video_t *sh);是一个名为init的指针,指向一个接受sh_video_t *类型参数,并返回int类型值的函数地址。那些vd_开头的文件都是解码相关的。随便打开一个vd文件以上几个函数和info变量肯定都包含了。mpi被mplayer用来存储解码后的图像。在mp_image.h里定义。

 

typedef struct mp_image_s {
unsigned short flags;
unsigned char type;
unsigned char bpp; // bits/pixel. NOT depth! for RGB it will be n*8
unsigned int imgfmt;
int width,height; // stored dimensions
int x,y,w,h; // visible dimensions
unsigned char* planes[MP_MAX_PLANES];
int stride[MP_MAX_PLANES];
char * qscale;
int qstride;
int pict_type; // 0->unknown, 1->I, 2->P, 3->B
int fields;
int qscale_type; // 0->mpeg1/4/h263, 1->mpeg2
int num_planes;
/* these are only used by planar formats Y,U(Cb),V(Cr) */
int chroma_width;
int chroma_height;
int chroma_x_shift; // horizontal
int chroma_y_shift; // vertical
/* for private use by filter or vo driver (to store buffer id or dmpi) */
void* priv;
} mp_image_t;

 

 

图像在解码以后会输出到显示器,mplayer本来就是一个视频播放器么。但也有可能作为输入提供给编码器进行二次编码,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结构图:

MPLayer源代码下载地址:http://download.csdn.net/detail/leixiaohua1020/6374337

分享到:
评论

相关推荐

    mplayer源码下载

    在提供的文件列表中,我们看到几个关键的源代码文件,它们分别涉及不同的功能模块: 1. **h264.c**:这是处理H.264编码视频的源码,H.264是一种广泛使用的高效率视频编码标准。这部分代码涉及解码H.264流,包括NAL...

    mplayer播放器源代码

    《mplayer播放器源代码深度解析》 MPlayer是一款开源的多媒体播放器,被誉为播放器的祖宗,因其强大的跨平台能力和丰富的功能而备受开发者喜爱。它的源代码是C语言编写,这使得它具备了高性能和高度可移植性。本文...

    mplayer源码分析.doc

    ### MPlayer源码分析知识点概览 #### 一、MPlayer支持的媒体格式 MPlayer是一款功能强大的多媒体播放器,其显著特点在于广泛的支持多种媒体格式。具体来说: 1. **视频格式**: - MPEG(包括MPEG-1、MPEG-2等) ...

    Mplayer源码分析

    Mplayer 源码分析 Mplayer 是一个功能强大的视频播放器,支持多种媒体格式,包括视频格式如 MPEG、AVI、ASF、WMV、QuickTime、OGG/OGM、SDP、PVA、GIF 等,以及音频格式如 MP3、WAV、OGG/OGM 文件(Vorbis)、WMA、...

    MPlayer 源代码1

    下面,我们将深入探讨MPlayer源代码中的关键知识点。 1. **跨平台架构**:MPlayer能在多种操作系统上运行,包括Linux、Windows、Mac OS X等,这得益于其灵活的跨平台设计。源代码中会包含针对不同平台的特定适配...

    mplayer源码 分享

    2. **文件结构**:MPlayer的源代码包含多个子目录,例如`src`包含主程序源码,`demuxers`是解复用器的代码,`filters`处理视频和音频过滤,`decoders`是解码器,`controllers`管理播放控制,`osd`涉及屏幕显示,`...

    mplayer kk版本源代码

    《mplayer kk版本源代码深度解析》 MPlayer是一款经典的开源媒体播放器,因其高度可配置性和跨平台性而备受开发者喜爱。本文将深入探讨"Mplayer kk版"的源代码,为C++开发者提供一份详尽的研究指南。该版本的...

    MPlayerGUI源代码

    《MPlayerGUI源代码解析与应用》 MPlayerGUI是一款基于MPlayer的图形用户界面(GUI)工具,它为用户提供了一种便捷的方式来播放多种视频和音频格式,包括avi、wmv、rm、rmvb和mkv等。MPlayer本身是一个跨平台的开源...

    mplayer-1.0rc2

    MPlayer-1.0rc2是一款在Linux环境下广泛使用的开源媒体播放器,它的源代码提供了丰富的功能和高度的可定制性,使其成为开发者研究和移植多媒体播放器的理想选择。本文将深入探讨MPlayer的核心特性、其在Linux下的...

    mplayer QT源码

    至于压缩包子文件的文件名称列表,"\no.txt"可能是一个说明文档或者日志文件,而"\4569930_基于Qt&MPlayer的视频播放器源码.zip"则包含了实际的源代码。这个zip文件应该包含了项目的全部源代码,包括Qt的UI文件(如....

    mplayer air flex 源码

    【标题】:“mplayer air flex 源码”是指MPlayer与Adobe Flex技术结合的源代码,这通常涉及到多媒体播放器的开发,特别是在移动设备或Web应用中的使用。MPlayer是一款开源的跨平台媒体播放器,它支持多种视频和音频...

    (求职用)播放器MPlayer源代码(完 整)

    《MPlayer播放器源代码深度解析》 MPlayer是一款跨平台、开源的多媒体播放器,其源代码的完整性和开放性使其成为学习和定制多媒体播放软件的理想选择。本篇文章将深入探讨MPlayer的核心架构,主要关注Delphi语言的...

    基于MPLAYER的万能播放器源码

    1. **postmake.bat**:这是一个批处理文件,通常用于自动化构建过程,比如编译和链接源代码,设置特定的编译选项等。 2. **mplayer.bmp**:这是播放器的界面资源文件,可能是播放器窗口的背景图像,用于美化用户...

    qt制作的mplayer播放器前端源码

    本文将详细解析基于Qt制作的MPlayer播放器前端源码,该播放器实现了播放、暂停、停止、时间条以及音量调节等基本功能。对于初学者或者希望深入了解Qt多媒体编程的开发者来说,这是一个很好的学习资源。 首先,让...

    播放器C源码MPlayer-1.0

    在本文中,我们将深入探讨MPlayer的C源码,了解其核心概念和技术细节。 1. **源码结构**: MPlayer的源码结构通常分为几个主要部分:解码器、播放器核心、视频输出模块、音频输出模块、用户界面和控制接口。这些...

    Mplayer源码

    Mplayer的源码分析: Mplayer的源码结构复杂,但组织有序,主要分为以下几个部分: 1. **解码器(Decoder)**:Mplayer支持多种编码格式,如H.264、MPEG、AVI等,这些解码器是Mplayer的核心组件。开发者可以在此...

    mplayer-export-snapshot.rar_mplayer

    二、MPlayer源码分析 MPlayer的源码是其强大功能的基石,包含了各种解码器、过滤器和播放控制模块。通过阅读和理解源码,开发者可以了解其工作原理,定制适合自己需求的播放器,或者为项目贡献代码。"mplayer-...

    歌曲解析项目.zip_comepme_linux_mplayer_oncemcd_歌词解析

    console.c是C语言源代码,实现了具体的功能,而console.h是头文件,定义了相关的函数原型和常量,供其他模块引用。 6. link_printf.c和link_printf.h:这两个文件可能涉及自定义的日志打印功能,可能用于将程序运行...

    MPUI-src-1.1.10.zip MPlayer的Delphi源码

    MPUI-src-1.1.10.zip是一个包含了MPlayer Delphi源代码的压缩包,对于想要深入理解MPlayer的内部工作原理或者想定制自己的媒体播放器的开发者来说,这是一个宝贵的资源。 在这个压缩包中,我们可以找到以下几个关键...

    mplayer-checkout-snapshot.tar.rar_checkout_mplayer_播放器 源码

    在这个名为“mplayer-checkout-snapshot.tar.bz2”的压缩包中,我们有机会深入研究MPlayer的源代码,了解这款播放器背后的工作原理。 源码是软件开发的核心,它揭示了程序的内部结构和逻辑。对于MPlayer这样的复杂...

Global site tag (gtag.js) - Google Analytics