03-流媒体-ffplay.c代码结构简要分析

ffplay.c是一个使用ffmpeg库的参考代码,实现了一个播放器的功能,源代码的的目录是:
ffmpeg-4.2.2/fftools/ffplay.c
ffplay.c可以作为入门来了解ffmpeg,我们也可以学习其编程方法实践到我们以后的开发中。本节和下一节对ffplay.c的源代码进行一个简单的描述,可以帮助读者来快速了解ffplay工具。另外ffplay.c的代码量还比较多,对于初学者而言,先了解其重要点,后面在做项目时慢慢深入即可。

假如本文媒体文件是由视频h264格式,音频aac格式,字幕封装而成。
1.我们从主函数开始分析,发现主要的功能函数如下:

int main(int argc, char **argv)
{
   
    ......
    avdevice_register_all();   
   ......
    parse_options(NULL, argc, argv, options, opt_input_file);
    ......
    if (SDL_Init (flags)) {
   
    ......
    is = stream_open(input_filename, file_iformat);
   ......
    event_loop(is);
    return 0;
}

(1)注册编码解码器:avdevice_register_all();
(2)解析输入命令:parse_options();
用于解析用客输入的运行指令,了解用户意途
(3)初始化SDL,用于显示:SDL_Init ()
ffplay工具是用SDL控件来播放音视频
(4)打开媒体文件:stream_open()
这个函数是ffplay中最重要的函数,其作用是读一个媒体文件,然后将文件进行解封装,再然后进行解码。
(5)事件刷新(包括视频刷新): event_loop()
这个函数最主要的作用是将stream_open()得到的音视频帧进行播放。

至此,我们可以知道,播放器主要由两个函数完成工作,stream_open和event_loop

2.分析两个主要函数的工作内容:
2.1读文件函数stream_open():
(1)音视频媒体文件->解封装->视频编码文件(如h264)、音频(如aac)、字幕。
后面的处理视频、音频、字幕从原理上差不多,本节以视频为例子进行说明
(2)h264帧->存入packet队列。并创建一个用于解码h264帧的线程。
(3)从packet队列,取出一帧h264帧,用ffmpeg的api解码函数进行解码。h264->YUV数据。
(4)YUV帧->存入frame队列
2.2事件刷新函数event_loop():
(1).从frame中读取一个YUV帧
(2).SDL播放
(3)在播放过程中有音视频同步的策略协调

3.一步一步分析读文件函数
3.1 打开文件函数 stream_open()内容如下

static VideoState *stream_open(const char *filename, AVInputFormat *iformat)
{
   
    ......
    if (frame_queue_init(&is->pictq, &is->videoq, VIDEO_PICTURE_QUEUE_SIZE, 1) < 0)
   ......
    if (frame_queue_init(&is->subpq, &is->subtitleq, SUBPICTURE_QUEUE_SIZE, 0) < 0)
    ......
    if (

你可能感兴趣的:(流媒体,linux)