网上很多文章,说到avformat_open_input阻塞,就设置一下
av_dict_set(&avdic, "stimeout ", "300000", 0);
ffmpeg源码rtsp.c有这样一段定义
{ "timeout", "set maximum timeout (in seconds) to wait for incoming connections (-1 is infinite, imply flag listen)", OFFSET(initial_timeout), AV_OPT_TYPE_INT, {.i64 = -1}, INT_MIN, INT_MAX, DEC },
{ "stimeout", "set timeout (in microseconds) of socket TCP I/O operations", OFFSET(stimeout), AV_OPT_TYPE_INT, {.i64 = 0}, INT_MIN, INT_MAX, DEC },
按照正常的说法,应该没问题,但就是不行,设置了还是会一直阻塞。
不管那么多,下面是正解,需要设置一下回调函数。部分关键代码
// C++ Header
#ifdef __cplusplus
extern "C" {
#endif
#include <libavformat/avformat.h>
#include <libavfilter/avfiltergraph.h>
#include <libavfilter/buffersink.h>
#include <libavfilter/buffersrc.h>
#include <libavutil/opt.h>
#include <libavutil/time.h>
#ifdef __cplusplus
}
#endif
...
class CFfmpegCapture
{
private:
static int decode_interrupt_cb(void *ctx);
//
int64_t m_nStartOpenTS = 0;
}
//c++ body
int CFfmpegCapture::decode_interrupt_cb(void *ctx)
{
CFfmpegCapture *pThis = (CFfmpegCapture*)ctx;
//microseconds 微秒
int64_t nDurTime = av_gettime() - pThis->m_nStartOpenTS;
if (nDurTime > 3000000 && pThis->m_nStartOpenTS>0)
{
return 1;
}
return 0;
}
int CFfmpegCapture::StartCapture(const char *pUrl)
{
AVDictionary* avdic = NULL;
av_dict_set(&avdic, "rtsp_transport", "tcp", 0);
//set timeout (in microseconds) of socket TCP I/O operations
av_dict_set(&avdic, "stimeout ", "300000", 0);
//set maximum timeout (in seconds) to wait for incoming connections (-1 is infinite, imply flag listen)
//av_dict_set(&avdic, "timeout ", "2", 0);
m_pFmtCtx->interrupt_callback.callback = decode_interrupt_cb;
m_pFmtCtx->interrupt_callback.opaque = (void*)this;
m_nStartOpenTS = av_gettime();
int ret = -1;
ret = avformat_open_input(&m_pFmtCtx, pUrl, nullptr, &avdic);
if (ret != 0) {
return -1;
}
//成功open以后,置0
m_nStartOpenTS = 0;
}
回调函数返回1表示不在阻塞( If the callback returns 1, the blocking operation will be aborted.)
ffmpeg-》avio.h文件描述:
/**
* Callback for checking whether to abort blocking functions.
* AVERROR_EXIT is returned in this case by the interrupted
* function. During blocking operations, callback is called with
* opaque as parameter. If the callback returns 1, the
* blocking operation will be aborted.
*
* No members can be added to this struct without a major bump, if
* new elements have been added after this struct in AVFormatContext
* or AVIOContext.
*/
typedef struct AVIOInterruptCB {
int (*callback)(void*);
void *opaque;
} AVIOInterruptCB;