1:
如果数据是rtp/rtsp传输的话,ffmpeg会每隔30s(哪里设置该值?)发送一个keepalive包,如果ipc支持
GET_PARAMETER命令,就发该命令等ipc回复以确认ipc还活着。
某些ipc(IPCamera)不支持GET_PARAMETER的rtsp命令。则会通过OPTIONS *来是keepalive,不过这会导致连接断掉
原代码,及修改部分如下。先这样处理,有时间再研究原代码为什么不这么处理。
-
//ffmpeg/libavformat/rtspdec.c rtsp_read_packet()
-
if (!(rt->rtsp_flags & RTSP_FLAG_LISTEN)) {
-
/* send dummy request to keep TCP connection alive */
-
if ((av_gettime() - rt->last_cmd_time) / 1000000 >= rt->timeout / 2 ||
-
rt->auth_state.stale) {
-
if (rt->server_type == RTSP_SERVER_WMS ||
-
(rt->server_type != RTSP_SERVER_REAL &&
-
rt->get_parameter_supported)) {
-
ff_rtsp_send_cmd_async(s, "GET_PARAMETER", rt->control_uri, NULL);
-
} else {
-
// ff_rtsp_send_cmd_async(s, "OPTIONS", "*", NULL); //原代码
-
ff_rtsp_send_cmd_async(s, "OPTIONS", rt->control_uri, NULL); //修改后的代码,这样就算ipc不支持GET_PARAMETER的命令可以keepalive了
-
}
-
/* The stale flag should be reset when creating the auth response in
-
* ff_rtsp_send_cmd_async, but reset it here just in case we never
-
* called the auth code (if we didn't have any credentials set). */
-
rt->auth_state.stale = 0;
-
}
-
}
2:
如果数据是rtp/rtsp/tcp传输,如果没有设置stimeout(socket timeout),那么server断线后av_read_frame会阻塞
-
AVFormatContext *pFormatCtx = NULL;
-
AVPacket packet;
-
AVDictionary *optionsDict = NULL;
-
char *streamurl1 = "rtsp://test:test@192.168.11.111:554/test.stream";
-
-
// Register all formats and codecs
-
av_register_all();
-
avformat_network_init();
-
-
pFormatCtx = avformat_alloc_context();
-
av_dict_set(&optionsDict, "rtsp_transport", "tcp", 0); //采用tcp传输
-
av_dict_set(&optionsDict, "stimeout", "2000000", 0); //如果没有设置stimeout,那么把ipc网线拔掉,av_read_frame会阻塞(时间单位是微妙)
-
-
// Open video file
-
if(avformat_open_input(&pFormatCtx, streamurl, NULL, &optionsDict)!=0){
-
printf("linesize = %d\n", __LINE__);
-
return -1; // Couldn't open file
-
}
-
-
// Retrieve stream information
-
if(avformat_find_stream_info(pFormatCtx, NULL)<0){
-
printf("linesize = %d\n", __LINE__);
-
return -1; // Couldn't find stream information
-
}
-
-
// Find the first video stream
-
int videoStream=-1;
-
for(i=0; i<pFormatCtx->nb_streams; i++){
-
if(pFormatCtx->streams[i]->codec->codec_type==AVMEDIA_TYPE_VIDEO) {
-
videoStream=i;
-
break;
-
}
-
}
-
-
if(videoStream==-1){
-
printf("linesize = %d\n", __LINE__);
-
return -1; // Didn't find a video stream
-
}
-
-
// Read frames and save first five frames to disk
-
while(av_read_frame(pFormatCtx, &packet)>=0) {
-
av_free_packet(&packet);
-
}
如果是ffmpeg2.0.1版本的话,添加一句就ok了。可是旧版本ffmpeg1.2.*没有stimeout这个字段可以设置
那么只好自己添加了。
在ffmpeg/libavformat/rtsp.h struct RTSPState添加一个stimeout字段
-
typedef struct RTSPState {
-
/**
-
* timeout of socket i/o operations.(this version do not have this segment. added by yqing, refer to ffmpeg-2.0.1)
-
*/
-
int stimeout;
-
} RTSPState;
在ffmpeg/libavformat/rtsp.c ff_rtsp_options添加一个stimeout字段
-
const AVOption ff_rtsp_options[] = {
-
{ "stimeout", "timeout (in micro seconds) of socket i/o operations.", OFFSET(stimeout), AV_OPT_TYPE_INT, {.i64 = 0}, INT_MIN, INT_MAX, DEC }, //添加这行代码
-
RTSP_REORDERING_OPTS(),
-
{ NULL },
-
};
在ffmpeg/libavformat/rtsp.c ff_rtsp_connect函数修改部分代码如下
-
//ff_url_join(tcpname, sizeof(tcpname), "tcp", NULL, host, port, NULL); //原代码
-
ff_url_join(tcpname, sizeof(tcpname), "tcp", NULL, host, port, "?timeout=%d", rt->stimeout); //修改后的代码
阅读(15336) | 评论(0) | 转发(0) |