FFMPEG函数avformat_open_input()-输入url为rtmp

2019独角兽企业重金招聘Python工程师标准>>> hot3.png

FFMPEG版本为3.2,输入url为rtmp

函数init_input()

/* 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);
}

函数av_probe_input_format2()返回值为空,即没有得到输入文件的格式。

函数s->io_open()回调io_open_default()

static int io_open_default(AVFormatContext *s, AVIOContext **pb,
                           const char *url, int flags, AVDictionary **options)
{
#if FF_API_OLD_OPEN_CALLBACKS
FF_DISABLE_DEPRECATION_WARNINGS
    if (s->open_cb)
        return s->open_cb(s, pb, url, flags, &s->interrupt_callback, options);
FF_ENABLE_DEPRECATION_WARNINGS
#endif

    return ffio_open_whitelist(pb, url, flags, &s->interrupt_callback, options, s->protocol_whitelist, s->protocol_blacklist);
}
int ffio_open_whitelist(AVIOContext **s, const char *filename, int flags,
                         const AVIOInterruptCB *int_cb, AVDictionary **options,
                         const char *whitelist, const char *blacklist
                        )
{
    URLContext *h;
    int err;

    err = ffurl_open_whitelist(&h, filename, flags, int_cb, options, whitelist, blacklist, NULL);
    if (err < 0)
        return err;
    err = ffio_fdopen(s, h);
    if (err < 0) {
        ffurl_close(h);
        return err;
    }
    return 0;
}
int ffurl_open_whitelist(URLContext **puc, const char *filename, int flags,
                         const AVIOInterruptCB *int_cb, AVDictionary **options,
                         const char *whitelist, const char* blacklist,
                         URLContext *parent)
{
    AVDictionary *tmp_opts = NULL;
    AVDictionaryEntry *e;
    int ret = ffurl_alloc(puc, filename, flags, int_cb);
    if (ret < 0)
        return ret;
    if (parent)
        av_opt_copy(*puc, parent);
    if (options &&
        (ret = av_opt_set_dict(*puc, options)) < 0)
        goto fail;
    if (options && (*puc)->prot->priv_data_class &&
        (ret = av_opt_set_dict((*puc)->priv_data, options)) < 0)
        goto fail;

    if (!options)
        options = &tmp_opts;

    av_assert0(!whitelist ||
               !(e=av_dict_get(*options, "protocol_whitelist", NULL, 0)) ||
               !strcmp(whitelist, e->value));
    av_assert0(!blacklist ||
               !(e=av_dict_get(*options, "protocol_blacklist", NULL, 0)) ||
               !strcmp(blacklist, e->value));

    if ((ret = av_dict_set(options, "protocol_whitelist", whitelist, 0)) < 0)
        goto fail;

    if ((ret = av_dict_set(options, "protocol_blacklist", blacklist, 0)) < 0)
        goto fail;

    if ((ret = av_opt_set_dict(*puc, options)) < 0)
        goto fail;

    ret = ffurl_connect(*puc, options);

    if (!ret)
        return 0;
fail:
    ffurl_close(*puc);
    *puc = NULL;
    return ret;
}

函数ffurl_alloc()

int ffurl_alloc(URLContext **puc, const char *filename, int flags,
                const AVIOInterruptCB *int_cb)
{
    const URLProtocol *p = NULL;

    p = url_find_protocol(filename);
    if (p)
       return url_alloc_for_protocol(puc, p, filename, flags, int_cb);

    *puc = NULL;
    if (av_strstart(filename, "https:", NULL))
        av_log(NULL, AV_LOG_WARNING, "https protocol not found, recompile FFmpeg with "
                                     "openssl, gnutls "
                                     "or securetransport enabled.\n");
    return AVERROR_PROTOCOL_NOT_FOUND;
}

通过filename和函数url_find_protocol()得到指针p的内容,例如:

(gdb) p *p
$7 = {name = 0x18b0c31 "rtmp", url_open = 0x6c0760 , url_open2 = 0, url_accept = 0, url_handshake = 0, url_read = 0x6c06b0 , url_write = 0x6bfac0 , url_seek = 0, url_close = 0x6bc1e0 , 
  url_read_pause = 0x6bc0a0 , url_read_seek = 0x6bbf50 , url_get_file_handle = 0, url_get_multi_file_handle = 0, url_shutdown = 0, priv_data_size = 1000, priv_data_class = 0x18b1560, flags = 2, url_check = 0, 
  url_open_dir = 0, url_read_dir = 0, url_close_dir = 0, url_delete = 0, url_move = 0, default_whitelist = 0x0}

执行函数url_alloc_for_protocol()后,puc的内容如下:

gdb) p **puc
$23 = {av_class = 0x1884920, prot = 0x18b1040, priv_data = 0x2768680, filename = 0x2768618 "rtmp://180.97.184.107:1936/live?vhost=cc.com/stream_1", flags = 1, max_packet_size = 0, is_streamed = 0, is_connected = 0, 
  interrupt_callback = {callback = 0x4861d0 , opaque = 0x0}, rw_timeout = 0, protocol_whitelist = 0x0, protocol_blacklist = 0x0}
(gdb) p *(puc->prot)
$24 = {name = 0x18b0c31 "rtmp", url_open = 0x6c0760 , url_open2 = 0, url_accept = 0, url_handshake = 0, url_read = 0x6c06b0 , url_write = 0x6bfac0 , url_seek = 0, url_close = 0x6bc1e0 , 
  url_read_pause = 0x6bc0a0 , url_read_seek = 0x6bbf50 , url_get_file_handle = 0, url_get_multi_file_handle = 0, url_shutdown = 0, priv_data_size = 1000, priv_data_class = 0x18b1560, flags = 2, url_check = 0, 
  url_open_dir = 0, url_read_dir = 0, url_close_dir = 0, url_delete = 0, url_move = 0, default_whitelist = 0x0}

 

函数ffurl_connect()调用uc->prot->url_open(uc, uc->filename, uc->flags);其中回调libavformat/rtmpproto.c:rtmp_open()

转载于:https://my.oschina.net/u/2326611/blog/800993

你可能感兴趣的:(ffmpeg)