ffplay显示部分代码包括了video、audio、subtitle的显示(输出)。
我们知道要显示画面或者输出声音,在windows、linux、macos等不同平台上的接口都不尽相同,对于这个问题,ffplay选择了sdl作为显示SDK,以实现跨平台支持。
https://zhuanlan.zhihu.com/p/44122324
ffplay的main函数
1、SDL初始化(因为video显示以来SDL窗口显示系统)
2、主循环event_loop
int main(int argc, char **argv)
{
//……
1、初始化---SDL_Init
flags = SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER;
if (SDL_Init (flags)) {
av_log(NULL, AV_LOG_FATAL, "Could not initialize SDL - %s\n", SDL_GetError());
av_log(NULL, AV_LOG_FATAL, "(Did you set the DISPLAY variable?)\n");
exit(1);
}
2、创建窗口---SDL_CreateWindow
window = SDL_CreateWindow(program_name, SDL_WINDOWPOS_UNDEFINED,SDL_WINDOWPOS_UNDEFINED, default_width, default_height, flags);
if (window) {
3、基于窗体创建渲染器(Render)---SDL_CreateRender
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);
}
}
4、stream_open
is = stream_open(input_filename, file_iformat); 创建了read_thread 并启动解码器(创建解码线程),开始读取文件
if (!is) {
av_log(NULL, AV_LOG_FATAL, "Failed to initialize VideoState!\n");
do_exit(NULL);
}
5、事件循环+播放视频---event_loop
event_loop(is);
}
main函数主循环event_loop:
for ( ; ; ) {
1、显示视频
2、有SDL事件就处理switch
}
static void event_loop(VideoState *cur_stream)
{
SDL_Event event;
double incr, pos, frac;
for (;;) {
double x;
1、视频显示 + 接收事件-------没事就内部循环播放视频,有事就退出switch处理事件
refresh_loop_wait_event(cur_stream, &event);
2、SDL队列中的事件处理
//比如按空格键可以触发暂停/恢复,关闭窗口可以触发do_exit销毁播放现场。
switch (event.type) {
//……
case SDLK_SPACE://按空格键触发暂停/恢复
toggle_pause(cur_stream);
break;
case SDL_QUIT:
case FF_QUIT_EVENT://自定义事件,用于出错时的主动退出
do_exit(cur_stream);
break;
}
}