int av_find_stream_info(AVFormatContext *ic)
{
    int i, count, ret, read_size, j;
    AVStream *st;
    AVPacket pkt1, *pkt;
    int64_t last_dts[MAX_STREAMS];
    int duration_count[MAX_STREAMS]={0};
    double (*duration_error)[MAX_STD_TIMEBASES];
    offset_t old_offset = url_ftell(ic->pb);
    int64_t codec_info_duration[MAX_STREAMS]={0};
    int codec_info_nb_frames[MAX_STREAMS]={0};
    AVProbeData probe_data[MAX_STREAMS];
    int codec_identified[MAX_STREAMS]={0};
    duration_error = av_mallocz(MAX_STREAMS * sizeof(*duration_error));
    if (!duration_error) return AVERROR(ENOMEM);
    for(i=0;i<ic->nb_streams;i++) {
        st = ic->streams[i];
        if(st->codec->codec_type == CODEC_TYPE_VIDEO){
            if(!st->codec->time_base.num)
                st->codec->time_base= st->time_base;
        }
        if (!st->parser) {
            st->parser = av_parser_init(st->codec->codec_id);
            if(st->need_parsing == AVSTREAM_PARSE_HEADERS && st->parser){
                st->parser->flags |= PARSER_FLAG_COMPLETE_FRAMES;
            }
        }
    }
    for(i=0;i<MAX_STREAMS;i++){
        last_dts[i]= AV_NOPTS_VALUE;
    }
    memset(probe_data, 0, sizeof(probe_data));
    count = 0;
    read_size = 0;
    for(;;) {
        for(i=0;i<ic->nb_streams;i++) {
            st = ic->streams[i];
            if (!has_codec_parameters(st->codec))
                break;
            if(   tb_unreliable(st->codec)
               && duration_count[i]<20 && st->codec->codec_type == CODEC_TYPE_VIDEO)
                break;
            if(st->parser && st->parser->parser->split && !st->codec->extradata)
                break;
            if(st->first_dts == AV_NOPTS_VALUE)
                break;
        }
        if (i == ic->nb_streams) {
            if (!(ic->ctx_flags & AVFMTCTX_NOHEADER)) {
                ret = count;
                break;
            }
        }
        if (read_size >= MAX_READ_SIZE) {
            ret = count;
            break;
        }
        ret = av_read_frame_internal(ic, &pkt1);
        if (ret < 0) {
            ret = -1;
            for(i=0;i<ic->nb_streams;i++) {
                st = ic->streams[i];
                if (!has_codec_parameters(st->codec)){
                    char buf[256];
                    avcodec_string(buf, sizeof(buf), st->codec, 0);
                    av_log(ic, AV_LOG_INFO, "Could not find codec parameters (%s)\n", buf);
                } else {
                    ret = 0;
                }
            }
            break;
        }
        pkt= add_to_pktbuf(ic, &pkt1);
        if(av_dup_packet(pkt) < 0)
            return AVERROR(ENOMEM);
        read_size += pkt->size;
        st = ic->streams[pkt->stream_index];
        if(codec_info_nb_frames[st->index]>1)
            codec_info_duration[st->index] += pkt->duration;
        if (pkt->duration != 0)
            codec_info_nb_frames[st->index]++;
        {
            int index= pkt->stream_index;
            int64_t last= last_dts[index];
            int64_t duration= pkt->dts - last;
            if(pkt->dts != AV_NOPTS_VALUE && last != AV_NOPTS_VALUE && duration>0){
                double dur= duration * av_q2d(st->time_base);
                if(duration_count[index] < 2)
                    memset(duration_error[index], 0, sizeof(*duration_error));
                for(i=1; i<MAX_STD_TIMEBASES; i++){
                    int framerate= get_std_framerate(i);
                    int ticks= lrintf(dur*framerate/(1001*12));
                    double error= dur - ticks*1001*12/(double)framerate;
                    duration_error[index][i] += error*error;
                }
                duration_count[index]++;
            }
            if(last == AV_NOPTS_VALUE || duration_count[index]<=1)
                last_dts[pkt->stream_index]= pkt->dts;
            if (st->codec->codec_id == CODEC_ID_NONE) {
                AVProbeData *pd = &(probe_data[st->index]);
                pd->buf = av_realloc(pd->buf, pd->buf_size+pkt->size+AVPROBE_PADDING_SIZE);
                memcpy(pd->buf+pd->buf_size, pkt->data, pkt->size);
                pd->buf_size += pkt->size;
                memset(pd->buf+pd->buf_size, 0, AVPROBE_PADDING_SIZE);
            }
        }
        if(st->parser && st->parser->parser->split && !st->codec->extradata){
            int i= st->parser->parser->split(st->codec, pkt->data, pkt->size);
            if(i){
                st->codec->extradata_size= i;
                st->codec->extradata= av_malloc(st->codec->extradata_size + FF_INPUT_BUFFER_PADDING_SIZE);
                memcpy(st->codec->extradata, pkt->data, st->codec->extradata_size);
                memset(st->codec->extradata + i, 0, FF_INPUT_BUFFER_PADDING_SIZE);
            }
        }
        if (!has_codec_parameters(st->codec)  )
            try_decode_frame(st, pkt->data, pkt->size);
        if (st->time_base.den > 0 && av_rescale_q(codec_info_duration[st->index], st->time_base, AV_TIME_BASE_Q) >= ic->max_analyze_duration) {
            break;
        }
        count++;
    }
    for(i=0;i<ic->nb_streams;i++) {
        st = ic->streams[i];
        if(st->codec->codec)
            avcodec_close(st->codec);
    }
    for(i=0;i<ic->nb_streams;i++) {
        st = ic->streams[i];
        if (st->codec->codec_type == CODEC_TYPE_VIDEO) {
            if(st->codec->codec_id == CODEC_ID_RAWVIDEO && !st->codec->codec_tag && !st->codec->bits_per_sample)
                st->codec->codec_tag= avcodec_pix_fmt_to_codec_tag(st->codec->pix_fmt);
            if(duration_count[i]
               && tb_unreliable(st->codec)  ){
                double best_error= 2*av_q2d(st->time_base);
                best_error= best_error*best_error*duration_count[i]*1000*12*30;
                for(j=1; j<MAX_STD_TIMEBASES; j++){
                    double error= duration_error[i][j] * get_std_framerate(j);
                    if(error < best_error){
                        best_error= error;
                        av_reduce(&st->r_frame_rate.num, &st->r_frame_rate.den, get_std_framerate(j), 12*1001, INT_MAX);
                    }
                }
            }
            if (!st->r_frame_rate.num){
                if(    st->codec->time_base.den * (int64_t)st->time_base.num
                    <= st->codec->time_base.num * (int64_t)st->time_base.den){
                    st->r_frame_rate.num = st->codec->time_base.den;
                    st->r_frame_rate.den = st->codec->time_base.num;
                }else{
                    st->r_frame_rate.num = st->time_base.den;
                    st->r_frame_rate.den = st->time_base.num;
                }
            }
        }else if(st->codec->codec_type == CODEC_TYPE_AUDIO) {
            if (st->codec->codec_id == CODEC_ID_NONE && probe_data[st->index].buf_size > 0) {
                codec_identified[st->index] = set_codec_from_probe_data(st, &(probe_data[st->index]), 1);
                if (codec_identified[st->index]) {
                    st->need_parsing = AVSTREAM_PARSE_FULL;
                }
            }
            if(!st->codec->bits_per_sample)
                st->codec->bits_per_sample= av_get_bits_per_sample(st->codec->codec_id);
        }
    }
    av_estimate_timings(ic, old_offset);
    for(i=0;i<ic->nb_streams;i++) {
        st = ic->streams[i];
        if (codec_identified[st->index])
            break;
    }
    if(i!=ic->nb_streams){
        av_read_frame_flush(ic);
        for(i=0;i<ic->nb_streams;i++) {
            st = ic->streams[i];
            if (codec_identified[st->index]) {
                av_seek_frame(ic, st->index, 0.0, 0);
            }
            st->cur_dts= st->first_dts;
        }
        url_fseek(ic->pb, ic->data_offset, SEEK_SET);
    }
#if 0
    for(i=0;i<ic->nb_streams;i++) {
        st = ic->streams[i];
        if (st->codec->codec_type == CODEC_TYPE_VIDEO) {
            if(b-frames){
                ppktl = &ic->packet_buffer;
                while(ppkt1){
                    if(ppkt1->stream_index != i)
                        continue;
                    if(ppkt1->pkt->dts < 0)
                        break;
                    if(ppkt1->pkt->pts != AV_NOPTS_VALUE)
                        break;
                    ppkt1->pkt->dts -= delta;
                    ppkt1= ppkt1->next;
                }
                if(ppkt1)
                    continue;
                st->cur_dts -= delta;
            }
        }
    }
#endif
    av_free(duration_error);
    for(i=0;i<MAX_STREAMS;i++){
        av_freep(&(probe_data[i].buf));
    }
    return ret;
}
['int av_find_stream_info(AVFormatContext *ic)\n{\n    int i, count, ret, read_size, j;\n    AVStream *st;\n    AVPacket pkt1, *pkt;\n    int64_t last_dts[MAX_STREAMS];\n    int duration_count[MAX_STREAMS]={0};\n    double (*duration_error)[MAX_STD_TIMEBASES];\n    offset_t old_offset = url_ftell(ic->pb);\n    int64_t codec_info_duration[MAX_STREAMS]={0};\n    int codec_info_nb_frames[MAX_STREAMS]={0};\n    AVProbeData probe_data[MAX_STREAMS];\n    int codec_identified[MAX_STREAMS]={0};\n    duration_error = av_mallocz(MAX_STREAMS * sizeof(*duration_error));\n    if (!duration_error) return AVERROR(ENOMEM);\n    for(i=0;i<ic->nb_streams;i++) {\n        st = ic->streams[i];\n        if(st->codec->codec_type == CODEC_TYPE_VIDEO){\n            if(!st->codec->time_base.num)\n                st->codec->time_base= st->time_base;\n        }\n        if (!st->parser) {\n            st->parser = av_parser_init(st->codec->codec_id);\n            if(st->need_parsing == AVSTREAM_PARSE_HEADERS && st->parser){\n                st->parser->flags |= PARSER_FLAG_COMPLETE_FRAMES;\n            }\n        }\n    }\n    for(i=0;i<MAX_STREAMS;i++){\n        last_dts[i]= AV_NOPTS_VALUE;\n    }\n    memset(probe_data, 0, sizeof(probe_data));\n    count = 0;\n    read_size = 0;\n    for(;;) {\n        for(i=0;i<ic->nb_streams;i++) {\n            st = ic->streams[i];\n            if (!has_codec_parameters(st->codec))\n                break;\n            if(   tb_unreliable(st->codec)\n               && duration_count[i]<20 && st->codec->codec_type == CODEC_TYPE_VIDEO)\n                break;\n            if(st->parser && st->parser->parser->split && !st->codec->extradata)\n                break;\n            if(st->first_dts == AV_NOPTS_VALUE)\n                break;\n        }\n        if (i == ic->nb_streams) {\n            if (!(ic->ctx_flags & AVFMTCTX_NOHEADER)) {\n                ret = count;\n                break;\n            }\n        }\n        if (read_size >= MAX_READ_SIZE) {\n            ret = count;\n            break;\n        }\n        ret = av_read_frame_internal(ic, &pkt1);\n        if (ret < 0) {\n            ret = -1;\n            for(i=0;i<ic->nb_streams;i++) {\n                st = ic->streams[i];\n                if (!has_codec_parameters(st->codec)){\n                    char buf[256];\n                    avcodec_string(buf, sizeof(buf), st->codec, 0);\n                    av_log(ic, AV_LOG_INFO, "Could not find codec parameters (%s)\\n", buf);\n                } else {\n                    ret = 0;\n                }\n            }\n            break;\n        }\n        pkt= add_to_pktbuf(ic, &pkt1);\n        if(av_dup_packet(pkt) < 0)\n            return AVERROR(ENOMEM);\n        read_size += pkt->size;\n        st = ic->streams[pkt->stream_index];\n        if(codec_info_nb_frames[st->index]>1)\n            codec_info_duration[st->index] += pkt->duration;\n        if (pkt->duration != 0)\n            codec_info_nb_frames[st->index]++;\n        {\n            int index= pkt->stream_index;\n            int64_t last= last_dts[index];\n            int64_t duration= pkt->dts - last;\n            if(pkt->dts != AV_NOPTS_VALUE && last != AV_NOPTS_VALUE && duration>0){\n                double dur= duration * av_q2d(st->time_base);\n                if(duration_count[index] < 2)\n                    memset(duration_error[index], 0, sizeof(*duration_error));\n                for(i=1; i<MAX_STD_TIMEBASES; i++){\n                    int framerate= get_std_framerate(i);\n                    int ticks= lrintf(dur*framerate/(1001*12));\n                    double error= dur - ticks*1001*12/(double)framerate;\n                    duration_error[index][i] += error*error;\n                }\n                duration_count[index]++;\n            }\n            if(last == AV_NOPTS_VALUE || duration_count[index]<=1)\n                last_dts[pkt->stream_index]= pkt->dts;\n            if (st->codec->codec_id == CODEC_ID_NONE) {\n                AVProbeData *pd = &(probe_data[st->index]);\n                pd->buf = av_realloc(pd->buf, pd->buf_size+pkt->size+AVPROBE_PADDING_SIZE);\n                memcpy(pd->buf+pd->buf_size, pkt->data, pkt->size);\n                pd->buf_size += pkt->size;\n                memset(pd->buf+pd->buf_size, 0, AVPROBE_PADDING_SIZE);\n            }\n        }\n        if(st->parser && st->parser->parser->split && !st->codec->extradata){\n            int i= st->parser->parser->split(st->codec, pkt->data, pkt->size);\n            if(i){\n                st->codec->extradata_size= i;\n                st->codec->extradata= av_malloc(st->codec->extradata_size + FF_INPUT_BUFFER_PADDING_SIZE);\n                memcpy(st->codec->extradata, pkt->data, st->codec->extradata_size);\n                memset(st->codec->extradata + i, 0, FF_INPUT_BUFFER_PADDING_SIZE);\n            }\n        }\n        if (!has_codec_parameters(st->codec)  )\n            try_decode_frame(st, pkt->data, pkt->size);\n        if (st->time_base.den > 0 && av_rescale_q(codec_info_duration[st->index], st->time_base, AV_TIME_BASE_Q) >= ic->max_analyze_duration) {\n            break;\n        }\n        count++;\n    }\n    for(i=0;i<ic->nb_streams;i++) {\n        st = ic->streams[i];\n        if(st->codec->codec)\n            avcodec_close(st->codec);\n    }\n    for(i=0;i<ic->nb_streams;i++) {\n        st = ic->streams[i];\n        if (st->codec->codec_type == CODEC_TYPE_VIDEO) {\n            if(st->codec->codec_id == CODEC_ID_RAWVIDEO && !st->codec->codec_tag && !st->codec->bits_per_sample)\n                st->codec->codec_tag= avcodec_pix_fmt_to_codec_tag(st->codec->pix_fmt);\n            if(duration_count[i]\n               && tb_unreliable(st->codec)  ){\n                double best_error= 2*av_q2d(st->time_base);\n                best_error= best_error*best_error*duration_count[i]*1000*12*30;\n                for(j=1; j<MAX_STD_TIMEBASES; j++){\n                    double error= duration_error[i][j] * get_std_framerate(j);\n                    if(error < best_error){\n                        best_error= error;\n                        av_reduce(&st->r_frame_rate.num, &st->r_frame_rate.den, get_std_framerate(j), 12*1001, INT_MAX);\n                    }\n                }\n            }\n            if (!st->r_frame_rate.num){\n                if(    st->codec->time_base.den * (int64_t)st->time_base.num\n                    <= st->codec->time_base.num * (int64_t)st->time_base.den){\n                    st->r_frame_rate.num = st->codec->time_base.den;\n                    st->r_frame_rate.den = st->codec->time_base.num;\n                }else{\n                    st->r_frame_rate.num = st->time_base.den;\n                    st->r_frame_rate.den = st->time_base.num;\n                }\n            }\n        }else if(st->codec->codec_type == CODEC_TYPE_AUDIO) {\n            if (st->codec->codec_id == CODEC_ID_NONE && probe_data[st->index].buf_size > 0) {\n                codec_identified[st->index] = set_codec_from_probe_data(st, &(probe_data[st->index]), 1);\n                if (codec_identified[st->index]) {\n                    st->need_parsing = AVSTREAM_PARSE_FULL;\n                }\n            }\n            if(!st->codec->bits_per_sample)\n                st->codec->bits_per_sample= av_get_bits_per_sample(st->codec->codec_id);\n        }\n    }\n    av_estimate_timings(ic, old_offset);\n    for(i=0;i<ic->nb_streams;i++) {\n        st = ic->streams[i];\n        if (codec_identified[st->index])\n            break;\n    }\n    if(i!=ic->nb_streams){\n        av_read_frame_flush(ic);\n        for(i=0;i<ic->nb_streams;i++) {\n            st = ic->streams[i];\n            if (codec_identified[st->index]) {\n                av_seek_frame(ic, st->index, 0.0, 0);\n            }\n            st->cur_dts= st->first_dts;\n        }\n        url_fseek(ic->pb, ic->data_offset, SEEK_SET);\n    }\n#if 0\n    for(i=0;i<ic->nb_streams;i++) {\n        st = ic->streams[i];\n        if (st->codec->codec_type == CODEC_TYPE_VIDEO) {\n            if(b-frames){\n                ppktl = &ic->packet_buffer;\n                while(ppkt1){\n                    if(ppkt1->stream_index != i)\n                        continue;\n                    if(ppkt1->pkt->dts < 0)\n                        break;\n                    if(ppkt1->pkt->pts != AV_NOPTS_VALUE)\n                        break;\n                    ppkt1->pkt->dts -= delta;\n                    ppkt1= ppkt1->next;\n                }\n                if(ppkt1)\n                    continue;\n                st->cur_dts -= delta;\n            }\n        }\n    }\n#endif\n    av_free(duration_error);\n    for(i=0;i<MAX_STREAMS;i++){\n        av_freep(&(probe_data[i].buf));\n    }\n    return ret;\n}']