介绍:
我是李铁山,ffplay是基于ffmpeg的播放器,B站大名鼎鼎的ijkplayer也是基于此二次开发,因此很有学习价值。
这篇文章是我深入解析ffplay的首篇,将会从main函数,自顶向下地剖析源码。
如果您对于源码感兴趣,可以查看ffplay的github地址https://github.com/FFmpeg/FFmpeg/blob/master/fftools/ffplay.c
解读源码
今天要读的代码有点长,大家耐着点性子看哈~
if (!display_disable) {
int flags = SDL_WINDOW_HIDDEN;
if (alwaysontop)
#if SDL_VERSION_ATLEAST(2,0,5)
flags |= SDL_WINDOW_ALWAYS_ON_TOP;
#else
av_log(NULL, AV_LOG_WARNING, "Your SDL version doesn't support SDL_WINDOW_ALWAYS_ON_TOP. Feature will be inactive.\n");
#endif
if (borderless)
flags |= SDL_WINDOW_BORDERLESS;
else
flags |= SDL_WINDOW_RESIZABLE;
#ifdef SDL_HINT_VIDEO_X11_NET_WM_BYPASS_COMPOSITOR
SDL_SetHint(SDL_HINT_VIDEO_X11_NET_WM_BYPASS_COMPOSITOR, "0");
#endif
window = SDL_CreateWindow(program_name, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, default_width, default_height, flags);
SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "linear");
if (window) {
renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
if (!renderer) {
av_log(NULL, AV_LOG_WARNING, "Failed to initialize a hardware accelerated renderer: %s\n", SDL_GetError());
renderer = SDL_CreateRenderer(window, -1, 0);
}
if (renderer) {
if (!SDL_GetRendererInfo(renderer, &renderer_info))
av_log(NULL, AV_LOG_VERBOSE, "Initialized %s renderer.\n", renderer_info.name);
}
}
if (!window || !renderer || !renderer_info.num_texture_formats) {
av_log(NULL, AV_LOG_FATAL, "Failed to create window or renderer: %s", SDL_GetError());
do_exit(NULL);
}
}
这段代码主要是处理 display_disable 为 false 的情况,就是在可以播放的情况下,开始处理以下逻辑。
首先,定义了一个变量 flags,将 SDL_WINDOW_HIDDEN 赋值给它,用于将窗口设置为不可见状态。这意味着在创建窗口后,该窗口将不会显示在屏幕上。接着我们看下一段代码,这是一个用了宏定义的条件判断,我改写一下,这样可能好阅读点
if (SDL_VERSION_ATLEAST(2,0,5)){
flags |= SDL_WINDOW_ALWAYS_ON_TOP;
}
else{
av_log(NULL, AV_LOG_WARNING, "Your SDL version doesn't
support SDL_WINDOW_ALWAYS_ON_TOP. Feature will be inactive.\n");
}
SDL_VERSION_ATLEAST 是 SDL 中的一个宏,用于检查 SDL 库的版本是否至少符合指定的版本号。如果符合 2.0.5 的版本,那么 flags 再增添 SDL_WINDOW_ALWAYS_ON_TOP 的值,意思为该窗口始终位于其他窗口的顶部,但之前该窗口因为 SDL_WINDOW_HIDDEN 屏蔽掉了,不知道还设置在顶部有什么意义,有没有高手在评论区指点我一下。
如果不符合 2.0.5 的版本,就程序就打印 “你的SDL不支持设置窗口在顶部” 的信息。然后我们接着看下一段,同样是一个条件判断
if (borderless)
flags |= SDL_WINDOW_BORDERLESS;
else
flags |= SDL_WINDOW_RESIZABLE;
这段比较好理解,大家也不用往下深究。符合 borderless 的条件的时候,将 SDL_WINDOW_BORDERLESS 赋值给 flags,表示窗口没有边框,否则窗口可以设置大小。我疑惑的是窗口有没有边框和能不能设置大小冲突吗,算了,这也不是很重要,知道意思后跳过就行。
下面也是一个宏条件判断
#ifdef SDL_HINT_VIDEO_X11_NET_WM_BYPASS_COMPOSITOR
SDL_SetHint(SDL_HINT_VIDEO_X11_NET_WM_BYPASS_COMPOSITOR, "0");
#endif
这应该是希望如果符合这个宏,就直接控制窗口的渲染,而不通过窗口管理器的复合操作,应该是提高性能的一种手段。
好了,这段代码比较长,今天就讲了前一半,前半段代码比较基础,基本就是设置 SDL 窗口的一些效果。后半段比较重要,会涉及到 SDL 窗口的初始化,下一篇文章再讲吧。
欲知后事如何,请听下回分解。