在前面我们介绍了ffplay的总体架构和一些关键的数据结构。今天我们还是从这张图开始,主要介绍ffplay的读取线程部分。
ffplay总体架构
图导出的可能有点模糊,再加上上传图床后不知道有没有更加模糊了,想要高清大图的可以后台留言,加v信索取。
从ffplay的main函数入口开始阅读源码,发现是在函数创建了资源读取线程,读取线程执行的函数是,所以要分析读取线程的工作内容,我们只需读懂函数即可。
下面是我加了注释的函数:
读取线程准备工作
1、创建读取线程互斥量SDL_CreateMutex
2、分配AVPacket,av_packet_alloc
3、分配解封装上下文avformat_alloc_context
4、设置回调函数ic->interrupt_callback.callback
5、打开媒体文件avformat_open_input
6、avformat_find_stream_info探测媒体信息
7、是否需要起始seek播放avformat_seek_file
8、获取流索引
9、stream_component_open初始化相关解码器组件
在ffplay读取线程的准备工作中,我们发现一个检查是否是实时流的方法,它是这样子判断的:
for循环读取
1、首先通过大内总管VideoState判断是否请求了退出
2、根据是否暂停了控制RTSP流以及SDL显示
3、处理seek操作
在这个过程中会调用函数刷新待解码包队列,然后将队列的播放序列serial加1,这就是播放序列的妙用之处。
4、检查队列中是否有足够的包,stream_has_enough_packets,如果队列满了则读取线程最多等待10ms,但是可以被唤醒。
5、播放完了,判断是否需要进行重播
6、av_read_frame读取一个资源包
如果读到了文件末尾则增加一个空包,以便于后续在解码线程用于冲刷解码器,这样就能将解码器内部缓存的数据全部取出。
如果读取到的不是空包,则判断该包的pts是否处于有效播放时间内,如果不在则丢弃,如果在则放入队列。
7、失败处理,释放相关资源,SDL发送退出事件FF_QUIT_EVENT
领取专属 10元无门槛券
私享最新 技术干货