100行代码实现最简单的基于FFMPEG+SDL的视频播放器
FFplay的总体函数调用结构图如下图所示。
上面地址的那张图保存下来的话就是一张清晰的图片了。
下文对主要函数分别解析。typedef struct OptionDef {
const char *name;
int flags;
#define HAS_ARG 0x0001
#define OPT_BOOL 0x0002
#define OPT_EXPERT 0x0004
#define OPT_STRING 0x0008
#define OPT_VIDEO 0x0010
#define OPT_AUDIO 0x0020
#define OPT_INT 0x0080
#define OPT_FLOAT 0x0100
#define OPT_SUBTITLE 0x0200
#define OPT_INT64 0x0400
#define OPT_EXIT 0x0800
#define OPT_DATA 0x1000
#define OPT_PERFILE 0x2000 /* the option is per-file (currently ffmpeg-only).
implied by OPT_OFFSET or OPT_SPEC */
#define OPT_OFFSET 0x4000 /* option is specified as an offset in a passed optctx */
#define OPT_SPEC 0x8000 /* option is to be stored in an array of SpecifierOpt.
Implies OPT_OFFSET. Next element after the offset is
an int containing element count in the array. */
#define OPT_TIME 0x10000
#define OPT_DOUBLE 0x20000
union {
void *dst_ptr;
int (*func_arg)(void *, const char *, const char *);
size_t off;
} u;
const char *help;
const char *argname;
} OptionDef; { "L" , OPT_EXIT, {(void*)show_license}, "show license" },
{ "h" , OPT_EXIT, {(void*) show_help}, "show help", "topic" },
{ "?" , OPT_EXIT, {(void*)show_help}, "show help", "topic" },
{ "help" , OPT_EXIT, {(void*)show_help}, "show help", "topic" },
{ "-help" , OPT_EXIT, {(void*)show_help}, "show help", "topic" },
{ "version" , OPT_EXIT, {(void*)show_version}, "show version" },
{ "formats" , OPT_EXIT, {(void*)show_formats }, "show available formats" },
{ "codecs" , OPT_EXIT, {(void*)show_codecs }, "show available codecs" },
{ "decoders" , OPT_EXIT, {(void*)show_decoders }, "show available decoders" },
{ "encoders" , OPT_EXIT, {(void*)show_encoders }, "show available encoders" },
{ "bsfs" , OPT_EXIT, {(void*)show_bsfs }, "show available bit stream filters" },
{ "protocols" , OPT_EXIT, {(void*)show_protocols}, "show available protocols" },
{ "filters" , OPT_EXIT, {(void*)show_filters }, "show available filters" },
{ "pix_fmts" , OPT_EXIT, {(void*)show_pix_fmts }, "show available pixel formats" },
{ "layouts" , OPT_EXIT, {(void*)show_layouts }, "show standard channel layouts" },
{ "sample_fmts", OPT_EXIT, {(void*)show_sample_fmts }, "show available audio sample formats" },
{ "loglevel" , HAS_ARG, {(void*)opt_loglevel}, "set libav* logging level", "loglevel" },
{ "v", HAS_ARG, {(void*)opt_loglevel}, "set libav* logging level", "loglevel" },
{ "debug" , HAS_ARG, {(void*)opt_codec_debug}, "set debug flags", "flags" },
{ "fdebug" , HAS_ARG, {(void*)opt_codec_debug}, "set debug flags", "flags" },
{ "report" , 0, {(void*)opt_report}, "generate a report" },
{ "max_alloc" , HAS_ARG, {(void*) opt_max_alloc}, "set maximum size of a single allocated block", "bytes" },
{ "cpuflags" , HAS_ARG | OPT_EXPERT, {(void*) opt_cpuflags}, "force specific cpu flags", "flags" },static const OptionDef options[] = {
#include "cmdutils_common_opts.h"//包含进来
{ "x", HAS_ARG, { (void*) opt_width }, "force displayed width", "width" },
{ "y", HAS_ARG, { (void*) opt_height }, "force displayed height", "height" },
{ "s", HAS_ARG | OPT_VIDEO, { (void*) opt_frame_size }, "set frame size (WxH or abbreviation)", "size" },
{ "fs", OPT_BOOL, { &is_full_screen }, "force full screen" },
{ "an", OPT_BOOL, { &audio_disable }, "disable audio" },
{ "vn", OPT_BOOL, { &video_disable }, "disable video" },
{ "ast", OPT_INT | HAS_ARG | OPT_EXPERT, { &wanted_stream[AVMEDIA_TYPE_AUDIO] }, "select desired audio stream", "stream_number" },
{ "vst", OPT_INT | HAS_ARG | OPT_EXPERT, { &wanted_stream[AVMEDIA_TYPE_VIDEO] }, "select desired video stream", "stream_number" },
{ "sst", OPT_INT | HAS_ARG | OPT_EXPERT, { &wanted_stream[AVMEDIA_TYPE_SUBTITLE] }, "select desired subtitle stream", "stream_number" },
{ "ss", HAS_ARG, { (void*) opt_seek }, "seek to a given position in seconds", "pos" },
{ "t", HAS_ARG, { (void*) opt_duration }, "play \"duration\" seconds of audio/video", "duration" },
//选项众多,不再一一列出…
};{ "x", HAS_ARG, { (void*) opt_width }, "force displayed width", "width" }从代码中可以看出,“-x”选项包含选项值(HAS_ARG),选项处理函数是opt_width()。选项说明是"force displayed width"。opt_width()的内容如下:static int opt_width(void *optctx, const char *opt, const char *arg)
{
screen_width = parse_number_or_die(opt, arg, OPT_INT64, 1, INT_MAX);
return 0;
}{ "fs", OPT_BOOL, { &is_full_screen }, "force full screen" }read_thread()调用了如下函数:
avformat_open_input():打开媒体。refresh_thread()调用了如下函数:
SDL_PushEvent(FF_REFRESH_EVENT):发送FF_REFRESH_EVENT的SDL_Eventstream_component_open()用于打开视频/音频/字幕解码的线程。其函数调用关系如下图所示。
avcodec_decode_subtitle2():解码字幕压缩编码数据。
SDL_Event event;
for (;;) {
SDL_WaitEvent(&event);
switch (event.type) {
case SDLK_ESCAPE:
case SDLK_q:
do_exit(cur_stream);
break;
case SDLK_f:
…
…
}
}原文地址:http://blog.csdn.net/leixiaohua1020/article/details/39762143