在上节中大体总结了播放前的步骤。
其中给流上下文赋能的接口:avformat_open_input(),今天简要记录下学习过程。如有错误欢迎指正。
/**
* Open an input stream and read the header. The codecs are not opened.
* The stream must be closed with avformat_close_input().
*
* @param ps Pointer to user-supplied AVFormatContext (allocated by avformat_alloc_context).
* May be a pointer to NULL, in which case an AVFormatContext is allocated by this
* function and written into ps.
* Note that a user-supplied AVFormatContext will be freed on failure.
* @param url URL of the stream to open.
* @param fmt If non-NULL, this parameter forces a specific input format.
* Otherwise the format is autodetected.
* @param options A dictionary filled with AVFormatContext and demuxer-private options.
* On return this parameter will be destroyed and replaced with a dict containing
* options that were not found. May be NULL.
*
* @return 0 on success, a negative AVERROR on failure.
*
* @note If you want to use custom IO, preallocate the format context and set its pb field.
*/
int avformat_open_input(AVFormatContext **ps, const char *url, ff_const59 AVInputFormat *fmt, AVDictionary **options);
大家注意到细节了没?
@param fmt If non-NULL, this parameter forces a specific input format. Otherwise the format is autodetected.
这是细节。
int avformat_open_input(AVFormatContext **ps, const char *filename,
ff_const59 AVInputFormat *fmt, AVDictionary **options)
{
AVFormatContext *s = *ps;
...
if (!s && !(s = avformat_alloc_context()))
return AVERROR(ENOMEM);
...
if (fmt)
s->iformat = fmt;
...
if ((ret = init_input(s, filename, &tmp)) < 0)
goto fail;
s->probe_score = ret;
...
}
如果url 和 fmt 都非空,最后该如何抉择?目的是什么?能不能瞎指定fmt? 反正我第一眼看到的时候就有这个疑问。
另外还有个小的知识点:第二个参数和第三个参数 带了const,不知道有没有人知道这个时候为啥加const ,能否去掉?这里就不推出自己的看法了,有兴趣大家留言。
init_input 是最主要的函数。以上流程图是最一般的走向。特殊情况就不画了。
而avformat_open_input函数最主要的作用就是为了确定format,初始化了结构体里的 AVStream **stream。format如何确定,就是靠着init_input函数。全局变量中有那么多format,花落谁家呢,就是靠着 谭浩强《C程序设计》 提到的打雷台,就是这么的神奇。
最后一个问题,fmt 能不能瞎指定? 可以也不可以,就是这么的玄妙。所有答案就在init_input里。
当url 不为空的时候,一般可以瞎指定,因为这种场景下,在后面的逻辑里会修改format。所以网上所见到的博客,基本上参数 fmt 都置NULL了,不是没有道理的,但是就是没有人解释为什么。
//modify begin @ 6/16
int av_probe_input_buffer2(AVIOContext *pb, ff_const59 AVInputFormat **fmt,
const char *filename, void *logctx,
unsigned int offset, unsigned int max_probe_size)
{ ...for (probe_size = PROBE_BUF_MIN; probe_size <= max_probe_size && !*fmt;
probe_size = FFMIN(probe_size << 1,
FFMAX(max_probe_size, probe_size + 1))) { }}
这里判断条件 !*fmt ,inputfmt是不可以乱取得。 之前看的有误解。
modify end //