DoubleLi

qq: 517712484 wx: ldbgliet

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::
  4737 随笔 :: 2 文章 :: 542 评论 :: 1615万 阅读
< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5

ffmpeg拉取RTSP流 正常操作不会有问题 但是如果途中,

把RTSP的流断了, 发现 会卡死 在avformat_find_stream_info函数中,

把这个函数注释掉的话就会卡死在av_read_frame中 ,大概需要30m才会返回 

网上搜了下 无论是 设置超时方法 还是  回调函数都不管用,不知道为什么。

经过测试实际的断流有两种情况:

1.是RTSP服务断了 ,这种情况 open_input 那里会返回失败,比较好处理

2.是RTSP服务没断,但是没有视频流了 这种情况会导致open_input成功,但是会导致程序一直卡死在av_read_frame函数里面  具体网上可以搜 FFMpeg源码里面就这么写了,

大体上有两种方法 设置超时处理 第一种是 通过av_dict_set函数设置timeout超时时间,但是我这么试了没有效果,所以只能是第二种方法,设置callback  经过测试 这种callback机制可以实现

具体原因下面FFmpeg代码这么写的 

 

 
 
 
 
static inline int retry_transfer_wrapper(URLContext *h, uint8_t *buf,
 
int size, int size_min,
 
int (*transfer_func)(URLContext *h,
 
uint8_t *buf,
 
int size))
 
{
 
int ret, len;
 
int fast_retries = 5;
 
int64_t wait_since = 0;
 
 
 
len = 0;
 
while (len < size_min) {
 
if (ff_check_interrupt(&h->interrupt_callback))
 
return AVERROR_EXIT;
 
ret = transfer_func(h, buf + len, size - len);
 
if (ret == AVERROR(EINTR))
 
continue;
 
if (h->flags & AVIO_FLAG_NONBLOCK)
 
return ret;
 
if (ret == AVERROR(EAGAIN)) {
 
ret = 0;
 
if (fast_retries) {
 
fast_retries--;
 
} else {
 
if (h->rw_timeout) {
 
if (!wait_since)
 
wait_since = av_gettime_relative();
 
else if (av_gettime_relative() > wait_since + h->rw_timeout)
 
return AVERROR(EIO);
 
}
 
av_usleep(1000);
 
}
 
} else if (ret == AVERROR_EOF)
 
return (len > 0) ? len : AVERROR_EOF;
 
else if (ret < 0)
 
return ret;
 
if (ret) {
 
fast_retries = FFMAX(fast_retries, 2);
 
wait_since = 0;
 
}
 
len += ret;
 
}
 
return len;
 
}
 
 

 

可以看到这个while循环里面有一个判断有没有callback 如果没有callback 就会一直卡在这个循环里直到读到了数据,经过实际测试,如果没有callback 视频流断了 之后又重新打开的话,大概需要30-50S左右 av_read_frame会返回失败。可以看下ff_check_interrupt函数

 
 
int ff_check_interrupt(AVIOInterruptCB *cb)
 
{
 
if (cb && cb->callback)
 
return cb->callback(cb->opaque);
 
return 0;
 
}
 
 

直接返回callback的,只要是非0 就会跳出这个循环。

 

可以通过av_time 获取时间,然后在callback里面判断超时时间  比如3s 超过3s之后  callback返回非0 就可以 

 

 

 

 
posted on   DoubleLi  阅读(972)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
历史上的今天:
2020-03-17 RTMP、RTSP、HTTP视频协议详解(附:直播流地址、播放软件)
2017-03-17 H265(HEVC) nal 单元头介绍及rtp发送中的fu分组发送详解
2015-03-17 Linux操作系统下三种配置环境变量的方法
2015-03-17 Linux中环境变量文件及配置
2015-03-17 Linux如何实现开机启动程序详解
2014-03-17 ActiveX控件的安全初始化和脚本操作 和 数字签名SIGN
2014-03-17 编写在浏览器中不弹出警告的ActiveX控件
点击右上角即可分享
微信分享提示