avformat_open_input阻塞问题解决

1. avformat_open_input默认是阻塞操作,如果不加控制,等待时间可能会达到30s以上,对于有些情况,等待30s的体验是无法接受的。

2. 我设定
AVDictionary* opts = NULL;
av_dict_set(&opts, "timeout", "6000", 0);
avformat_open_input(&m_pFormatCtx,pcURL,NULL,NULL)!=0
这样做的结果,我感觉像是把timeout的时间设置为了0,不论URL值是否正确,avformat_open_input函数都返回错误值。

3. 突发奇想,启动另一个线程调用avformat_open_input,待取流超时后,杀掉线程。但事实证明,这是一个天真的想法,因为pthread_cancel不是一个靠的住的函数。虽然知道了问题所在,但却束手无策。但最终还是在网上找到了解决方案。

4. 该方案具体如下:创建AVFormatContext成功后,设置中断回调(数据成员interrupt_callback.opaque(自定义指针),和interrupt_callback.callback(回调函数)),设置一个全局变量(类成员变量)last_packet_timestamp,调用avformat_open_input前初始化为time(nullptr),在回调函数里计算当前时间和last_packet_timestame的差值,当差值超过某一阈值时,比如说10s时,则认为取流超时,返回一个小于0的值,告诉调用者取流失败,其他情况下返回0。

但是用该方案一定要注意,成功取到流,每次调用av_read_frame成功后,一定要更新last_packet_timestamp。否则,av_read_frame还会超值,因为设置的中断回调会被循环调用,如果last_packet_timestamp不更新,很快就会超时。

ffmpeg支持interrupt_callback机制,可以对输入(或输出)的AVFormatContext的interrupt_callback成员设置,然后再回调函数中做控制。

// 回调函数的参数,用了时间
typedef struct {
	time_t lasttime;
	bool connected;
}Runner;

// 回调函数
static int interrupt_callback(void *p) 
{
	Runner *r = (Runner *)p;
	
	if(r->lasttime > 0) 
	{
		if(time(NULL) - r->lasttime > 2 && !input_runner.connected) 
		{
			return 1;
		}
	}

	
	return 0;
}


// usage
Runner input_runner = {0};

AVFormatContext *ifmt_ctx = avformat_alloc_context();
ifmt_ctx->interrupt_callback.callback = interrupt_callback;
ifmt_ctx->interrupt_callback.opaque = &input_runner;

input_runner.lasttime = time(NULL);
// 调用之前初始化时间
ret = avformat_open_input(&ifmt_ctx, url, NULL, NULL);
if(ret < 0) {
	// error
}

input_runner.lasttime = time(NULL);
ret = av_read_frame(input_fmt_ctx,&pkt);

参考: https://ffmpeg.org/doxygen/3.2/structAVFormatContext.html

  • 0
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值