2019独角兽企业重金招聘Python工程师标准>>>
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()