FFMPEG版本爲3.2,輸入url爲rtmp函數
/* 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()返回值爲空,即沒有獲得輸入文件的格式。url
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; }
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的內容,例如:spa
(gdb) p *p $7 = {name = 0x18b0c31 "rtmp", url_open = 0x6c0760 <rtmp_open>, url_open2 = 0, url_accept = 0, url_handshake = 0, url_read = 0x6c06b0 <rtmp_read>, url_write = 0x6bfac0 <rtmp_write>, url_seek = 0, url_close = 0x6bc1e0 <rtmp_close>, url_read_pause = 0x6bc0a0 <rtmp_pause>, url_read_seek = 0x6bbf50 <rtmp_seek>, 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 <decode_interrupt_cb>, opaque = 0x0}, rw_timeout = 0, protocol_whitelist = 0x0, protocol_blacklist = 0x0} (gdb) p *(puc->prot) $24 = {name = 0x18b0c31 "rtmp", url_open = 0x6c0760 <rtmp_open>, url_open2 = 0, url_accept = 0, url_handshake = 0, url_read = 0x6c06b0 <rtmp_read>, url_write = 0x6bfac0 <rtmp_write>, url_seek = 0, url_close = 0x6bc1e0 <rtmp_close>, url_read_pause = 0x6bc0a0 <rtmp_pause>, url_read_seek = 0x6bbf50 <rtmp_seek>, 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()code