ffmpeg问题解决

原文链接: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.     pFormatCtx = avformat_alloc_context();
  10.     av_dict_set(&optionsDict, "rtsp_transport", "tcp", 0);                //采用tcp传输
  11.     av_dict_set(&optionsDict, "stimeout", "2000000", 0);                  //如果没有设置stimeout,那么把ipc网线拔掉,av_read_frame会阻塞(时间单位是微妙)

  12.     // Open video file
  13.     if(avformat_open_input(&pFormatCtx, streamurl, NULL, &optionsDict)!=0){
  14.         printf("linesize = %d\n", __LINE__);    
  15.         return -1; // Couldn't open file
  16.     }

  17.     // Retrieve stream information
  18.     if(avformat_find_stream_info(pFormatCtx, NULL)<0){
  19.         printf("linesize = %d\n", __LINE__);    
  20.         return -1; // Couldn't find stream information
  21.     }

  22.     // Find the first video stream
  23.     int videoStream=-1;
  24.     for(i=0; i<pFormatCtx->nb_streams; i++){
  25.         if(pFormatCtx->streams[i]->codec->codec_type==AVMEDIA_TYPE_VIDEO) {
  26.             videoStream=i;
  27.             break;
  28.         }
  29.     }
  30.     
  31.     if(videoStream==-1){
  32.         printf("linesize = %d\n", __LINE__);    
  33.         return -1; // Didn't find a video stream
  34.     }
  35.     
  36.     // Read frames and save first five frames to disk
  37.     while(av_read_frame(pFormatCtx, &packet)>=0) {
  38.         av_free_packet(&packet);
  39.     }
如果是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);     //修改后的代码

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值