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,不过这会导致连接断掉
原代码,及修改部分如下。先这样处理,有时间再研究原代码为什么不这么处理。
点击(此处)折叠或打开
1. //ffmpeg/libavformat/rtspdec.c rtsp_read_packet()
2. if (!(rt->rtsp_flags & RTSP_FLAG_LISTEN)) {
3. /* send dummy request to keep TCP connection alive */
4. if ((av_gettime() - rt->last_cmd_time) / 1000000 >= rt->timeout / 2 ||
5. rt->auth_state.stale) {
6. if (rt->server_type == RTSP_SERVER_WMS ||
7. (rt->server_type != RTSP_SERVER_REAL &&
8. rt->get_parameter_supported)) {
9. ff_rtsp_send_cmd_async(s, "GET_PARAMETER", rt->control_uri, NULL);
10. } else {
11. // ff_rtsp_send_cmd_async(s, "OPTIONS", "*", NULL); //原代码
12. ff_rtsp_send_cmd_async(s, "OPTIONS", rt->control_uri, NULL); //修改后的代码,这样就算ipc不支持GET_PARAMETER的命令可以keepalive了
13. }
14. /* The stale flag should be reset when creating the auth response in
15. * ff_rtsp_send_cmd_async, but reset it here just in case we never
16. * called the auth code (if we didn't have any credentials set). */
17. rt->auth_state.stale = 0;
18. }
19. }
2:
如果数据是rtp/rtsp/tcp传输,如果没有设置stimeout(socket timeout),那么server断线后av_read_frame会阻塞
点击(此处)折叠或打开
1. AVFormatContext *pFormatCtx = NULL;
2. AVPacket packet;
3. AVDictionary *optionsDict = NULL;
4. char *streamurl1 = "rtsp://test:test@192.168.11.111:554/test.stream";
5.
6. // Register all formats and codecs
7. av_register_all();
8. avformat_network_init();
9.
10. pFormatCtx = avformat_alloc_context();
11. av_dict_set(&optionsDict, "rtsp_transport", "tcp", 0); //采用tcp传输
12. av_dict_set(&optionsDict, "stimeout", "2000000", 0); //如果没有设置stimeout,那么把ipc网线拔掉,av_read_frame会阻塞(时间单位是微妙)
13.
14. // Open video file
15. if(avformat_open_input(&pFormatCtx, streamurl, NULL, &optionsDict)!=0){
16. printf("linesize = %d\n", __LINE__);
17. return -1; // Couldn't open file
18. }
19.
20. // Retrieve stream information
21. if(avformat_find_stream_info(pFormatCtx, NULL)<0){
22. printf("linesize = %d\n", __LINE__);
23. return -1; // Couldn't find stream information
24. }
25.
26. // Find the first video stream
27. int videoStream=-1;
28. for(i=0; i<pFormatCtx->nb_streams; i++){
29. if(pFormatCtx->streams[i]->codec->codec_type==AVMEDIA_TYPE_VIDEO) {
30. videoStream=i;
31. break;
32. }
33. }
34.
35. if(videoStream==-1){
36. printf("linesize = %d\n", __LINE__);
37. return -1; // Didn't find a video stream
38. }
39.
40. // Read frames and save first five frames to disk
41. while(av_read_frame(pFormatCtx, &packet)>=0) {
42. av_free_packet(&packet);
43. }
如果是ffmpeg2.0.1版本的话,添加一句就ok了。可是旧版本ffmpeg1.2.*没有stimeout这个字段可以设置
那么只好自己添加了。
在ffmpeg/libavformat/rtsp.h struct RTSPState添加一个stimeout字段
点击(此处)折叠或打开
1. typedef struct RTSPState {
2. /**
3. * timeout of socket i/o operations.(this version do not have this segment. added by yqing, refer to ffmpeg-2.0.1)
4. */
5. int stimeout;
6. } RTSPState;
在ffmpeg/libavformat/rtsp.c ff_rtsp_options添加一个stimeout字段
点击(此处)折叠或打开
1. const AVOption ff_rtsp_options[] = {
2. { "stimeout", "timeout (in micro seconds) of socket i/o operations.", OFFSET(stimeout), AV_OPT_TYPE_INT, {.i64 = 0}, INT_MIN, INT_MAX, DEC }, //添加这行代码
3. RTSP_REORDERING_OPTS(),
4. { NULL },
5. };
在ffmpeg/libavformat/rtsp.c ff_rtsp_connect函数修改部分代码如下
点击(此处)折叠或打开
1. //ff_url_join(tcpname, sizeof(tcpname), "tcp", NULL, host, port, NULL); //原代码
2. ff_url_join(tcpname, sizeof(tcpname), "tcp", NULL, host, port, "?timeout=%d", rt->stimeout); //修改后的代码
3.