FFMPEG-FLV格式探测

ffmpeg在使用avformat_open_input接口打开流时,就已经对流的格式做了探测,如果是输入的RTMP地址,它又是如何探测流的呢。

通过之前文档(FFMPEG-RTMP之抽取FLV),我们知道,ffmpeg在读取rtmp模块数据的时候,实际得到的是组装好的完整flv数据,首次读取flv头部数据的时间就发生在init_input函数中,它回调了一个io_open函数,此函数指针映射的正是rtmp模块的流打开函数,回调完成后,我们得到了flv的头部数据。

接下来,ffmpeg通过调用av_probe_input_buffer2匹配媒体数据格式。调用栈如下:

从调用栈可以看出,av_probe_input_buffer2 最终是会回调flv_probe来探测FLV数据的,当探测成功后,flv模块作为AVFormatContext的iformat成员变量保存了下来。至此,flv的探测工作圆满结束。

#0  probe (p=0x7fffffffdbf0, p=0x7fffffffdbf0, live=0) at libavformat/flvdec.c:77
#1  flv_probe (p=0x7fffffffdbf0) at libavformat/flvdec.c:93
#2  0x00005555557df619 in av_probe_input_format3 (pd=pd@entry=0x7fffffffdcd0, is_opened=is_opened@entry=1, score_ret=score_ret@entry=0x7fffffffdc64) at libavformat/format.c:209
#3  0x00005555557df872 in av_probe_input_format2 (pd=pd@entry=0x7fffffffdcd0, is_opened=is_opened@entry=1, score_max=score_max@entry=0x7fffffffdcbc) at libavformat/format.c:252
#4  0x00005555557dfa5b in av_probe_input_buffer2 (pb=0x555556e300a0, fmt=0x555556e2c608, filename=filename@entry=0x7fffffffe848 "rtmp://58.200.131.2:1935/livetv/hunantv", logctx=logctx@entry=0x555556e2c600, offset=offset@entry=0, max_probe_size=1048576)
    at libavformat/format.c:332
#5  0x00005555558d1135 in init_input (options=0x7fffffffdd60, filename=0x7fffffffe848 "rtmp://58.200.131.2:1935/livetv/hunantv", s=0x555556e2c600) at libavformat/utils.c:420
#6  avformat_open_input (ps=ps@entry=0x7fffffffde30, filename=filename@entry=0x7fffffffe848 "rtmp://58.200.131.2:1935/livetv/hunantv", fmt=fmt@entry=0x0, options=0x555556e2c3e8) at libavformat/utils.c:536
#7  0x000055555568335a in open_input_file (o=o@entry=0x7fffffffdff0, filename=<optimized out>) at ffmpeg_opt.c:997
#8  0x0000555555684c52 in open_files (l=0x555556e2c058, l=0x555556e2c058, open_file=0x555555681940 <open_input_file>, inout=0x5555560de7e6 "input") at ffmpeg_opt.c:3135
#9  ffmpeg_parse_options (argc=<optimized out>, argv=<optimized out>) at ffmpeg_opt.c:3175
#10 0x0000555555677177 in main (argc=4, argv=0x7fffffffe5c8) at ffmpeg.c:4569
int avformat_open_input(AVFormatContext **ps, const char *filename,
                        AVInputFormat *fmt, AVDictionary **options)
{
    AVFormatContext *s = *ps;
    int i, ret = 0;
    AVDictionary *tmp = NULL;
    ID3v2ExtraMeta *id3v2_extra_meta = NULL;

    if (!s && !(s = avformat_alloc_context()))
        return AVERROR(ENOMEM);
    if (!s->av_class) {
        av_log(NULL, AV_LOG_ERROR, "Input context has not been properly allocated by avformat_alloc_context() and is not NULL either\n");
        return AVERROR(EINVAL);
    }
    if (fmt)
        s->iformat = fmt;

    if (options)
        av_dict_copy(&tmp, *options, 0);

    if (s->pb) // must be before any goto fail
        s->flags |= AVFMT_FLAG_CUSTOM_IO;

    if ((ret = av_opt_set_dict(s, &tmp)) < 0)
        goto fail;

    av_strlcpy(s->filename, filename ? filename : "", sizeof(s->filename));
    if ((ret = init_input(s, filename, &tmp)) < 0)
        goto fail;
    s->probe_score = ret;

    ....
    if (!(s->flags&AVFMT_FLAG_PRIV_OPT) && s->iformat->read_header)
        if ((ret = s->iformat->read_header(s)) < 0)
            goto fail;
            }

 

/* Open input file and probe the format if necessary. */
static int init_input(AVFormatContext *s, const char *filename,
                      AVDictionary **options)
{
    int ret;
    AVProbeData pd = { filename, NULL, 0 };
    int score = AVPROBE_SCORE_RETRY;

    if (s->pb) {
        s->flags |= AVFMT_FLAG_CUSTOM_IO;
        if (!s->iformat)
            return av_probe_input_buffer2(s->pb, &s->iformat, filename,
                                         s, 0, s->format_probesize);
        else if (s->iformat->flags & AVFMT_NOFILE)
            av_log(s, AV_LOG_WARNING, "Custom AVIOContext makes no sense and "
                                      "will be ignored with AVFMT_NOFILE format.\n");
        return 0;
    }

    if ((s->iformat && s->iformat->flags & AVFMT_NOFILE) ||
        (!s->iformat && (s->iformat = av_probe_input_format2(&pd, 0, &score))))
        return score;

    if ((ret = s->io_open(s, &s->pb, filename, AVIO_FLAG_READ | s->avio_flags, options)) < 0)
        return ret;

    if (s->iformat)
        return 0;
    return av_probe_input_buffer2(s->pb, &s->iformat, filename,
                                 s, 0, s->format_probesize);
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值