前言
FFmpeg的avformat_open_input函数和av_read_frame函数默认是阻塞的,意味着如果RTSP服务器不在线的情况下,ffplay工具会一直在avformat_open_input函数内部不断尝试连接服务器。
ffplay退出阻塞的机制
decode_interrupt_cb函数主要是为了允许用户中断退出
当用户按下键盘的q,abort_request将会赋值为1,在上述两个函数中,退出循环
连接超时
代码堆栈
核心阻塞代码
默认情况下,不设置连接超时,FFmpeg API ff_poll_interrupt函数会循环调用poll函数不断尝试连接服务器。如果服务器处于离线状态,函数avformat_open_input会一直处于阻塞状态。因此需要设置连接超时,将传递参数给到timeout变量,在尝试一定次数以后,退出该循环
接收超时
默认情况下,不设置接收超时,服务器由于某种问题,虽然保持跟客户端的连接,但是没有发送任何的数据过来,函数av_read_frame会一直处于阻塞状态,直到服务器发送数据过来,或者由于连接异常断开,才会正常返回
代码堆栈
上面两个函数都有机会执行interrupt_callback回调函数
原理说明AVFormatContext结构体中interrupt_callback函数会被av_read_frame重复调用,当interrupt_callback返回1的时候,av_read_frame将会立刻返回,退出阻塞状态,当interrupt_callback返回0的时候,av_read_frame会继续等待数据
设置连接超时
libavformat版本小于59
参数设置说明
设置stimeout参数,单位是微秒,10的负六次方秒
libavformat版本大于等于59
参数设置说明
设置timeout参数,单位是微秒,10的负六次方秒
例子说明(FFmpeg版本7.0.1)
设置AVFormatContext变量的interrupt_callback中断实现阻塞退出
超时退出阻塞连接和接收例子
接收缓存设置
av_dict_set(&opts, "buffer_size", "1024000", 0); // 设置缓冲区大小
设置过大,会占用内存,例如设置为9000000,会每一个链接占用9M的内存空间,当前1920*1080分辨率设置为1024000
max delay reached. need to consume packet
网络不畅的情况下,等待RTP数据超时