FFmpeg源码分析:avformat_find_stream_info分析码流信息

FFmpeg在调用avformat_open_input()之后,可能码流信息不够完整,可以使用avformat_find_stream_info()获取更多的码流信息。比如获取视频帧率、视频宽高,重新计算最大分析时长,打开解码器解码获取codec数据。具体流程如下图所示:
在这里插入图片描述
avformat_find_stream_info方法位于libavformat/utils.c,具体代码如下(部分删减):

int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options)
{
   
    // 针对flv/mpeg/mpegts格式,max_analyze_duration另外赋值
    if (!max_analyze_duration) {
   
        max_stream_analyze_duration =
        max_analyze_duration        = 5*AV_TIME_BASE;
        max_subtitle_analyze_duration = 30*AV_TIME_BASE;
        if (!strcmp(ic->iformat->name, "flv"))
            max_stream_analyze_duration = 90*AV_TIME_BASE;
        if (!strcmp(ic->iformat->name, "mpeg") || !strcmp(ic->iformat->name, "mpegts"))
            max_stream_analyze_duration = 7*AV_TIME_BASE;
    }
 
    for (i = 0; i < ic->nb_streams; i++) {
   
        // 查找解码器
        codec = find_probe_decoder(ic, st, st->codecpar->codec_id);
        // 确保字幕头信息已正确设置
        if (st->codecpar->codec_type == AVMEDIA_TYPE_SUBTITLE
            && codec && !avctx->codec) {
   
            if (avcodec_open2(avctx, codec, options ? &options[i] : &thread_opt) < 0)
                av_log(ic, AV_LOG_WARNING, "Failed to open codec in %s\n",__FUNCTION__);
        }
        // 尝试打开解码器
        if (!has_codec_parameters(st, NULL) && st->internal->request_probe <= 0) {
   
            if (codec && !avctx->codec)
                if (avcodec_open2(avctx, codec, options ? &options[i] : &thread_opt) < 0)
                    av_log(ic, AV_LOG_WARNING, "Failed to open codec in %s\n",__FUNCTION__);
        }
    }
    ......
    for (;;) {
   
        for (i = 0; i < ic->nb_streams; i++) {
   
            int fps_analyze_framecount = 20;
            int count;
 
            st = ic->streams[i];
            if (!has_codec_parameters(st, NULL))
                break;
            // 如果时间基是粗糙的,比如mkv采用ms作为单位
            // 需要分析更多帧数据来获取帧率
            if (av_q2d(st->time_base) > 0.0005)
                fps_analyze_framecount *= 2;
            if (!tb_unreliable(st->internal->avctx))
                fps_analyze_framecount = 0;
            if (ic->fps_probe_size >= 0)
                fps_analyze_framecount = ic->fps_probe_size;
            if (st->disposition & AV_DISPOSITION_ATTACHED_PIC)
                fps_analyze_framecount = 0;
            count = (ic->iformat->flags & AVFMT_NOTIMESTAMPS) ?
                       st->internal->info->codec_info_duration_fields/2 :
                       st->internal->info->duration_count;
            if (!(st->r_frame_rate.num && st->avg_frame_rate.num) &&
                st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
   
                if (count < fps_analyze_framecount)
                    break;
            }
            // 如果存在帧延时,查看前3帧
            if (st->internal->info->frame_delay_evidence && count < 2 && st->internal->avctx->has_b_frames == 0)
                break;
            if (!st->internal->avctx->extradata &&
                (!st->internal->extract_extradata.inited ||
                 st->internal->extract_extradata.bsf) &&
                extract_extradata_check(st))
                break;
            if (st->first_dts == AV_NOPTS_VALUE &&
                !(ic->iformat->flags & AVFMT_NOTIMESTAMPS) &&
                st->codec_info_nb_frames < ((st->disposition & AV_DISPOSITION_ATTACHED_PIC) ? 1 : ic->max_ts_probe) &&
                (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO ||
                 st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值