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); //修改后的代码
原贴地址:http://blog.chinaunix.net/uid-27091949-id-4186640.html
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); //修改后的代码
本文探讨FFmpeg在处理RTP/RTSP流时的Keepalive机制,特别是针对不支持GET_PARAMETER命令的IP摄像头。文章还讨论了在使用TCP传输时设置socket超时(stimeout)的重要性,以防止服务器断线后av_read_frame阻塞。
6955

被折叠的 条评论
为什么被折叠?



