• ffmpeg问题汇总及解决方案 <设置avformat_open_input 超时><转>


    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
    ", __LINE__);    
            return -1; // Couldn't open file
        }
    
        // Retrieve stream information
        if(avformat_find_stream_info(pFormatCtx, NULL)<0){
            printf("linesize = %d
    ", __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
    ", __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.     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 ", __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 ", __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 ", __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);     //修改后的代码
  • 相关阅读:
    nose测试中修改nose_html_reporting插件,使生成的html报告加入显示截图功能
    python selenium中等待元素出现及等待元素消失操作
    在python pydev中使用todo标注任务
    云存储命令行工具---libs3
    关于qt creator各种假死的问题
    小端存储转大端存储 & 大端存储转小端存储
    C++判断计算式是大端存储模式,还是小端存储模式
    请教网友:#pragma pack(push) #pragma pack(pop)无效
    sizeof 计算 struct 占字节数的方法总结
    const 变量在多个文件共享,如何验证两种不同的方式下,编译器是否会在多个文件下建立多个副本
  • 原文地址:https://www.cnblogs.com/wainiwann/p/7391229.html
Copyright © 2020-2023  润新知