文章没啥干货,就只是自己一个疑问的记录。
在工作中解决一个bug,继而引发关于流信息是怎么获取的,是在avformat_open_input()函数中已经获取了?还是要去avformat_find_stream_info()函数中获取?
先看nb_streams值是在哪变化的,看变量声明得知是avformat_new_stream()中修改的
/**
* Number of elements in AVFormatContext.streams.
*
* Set by avformat_new_stream(), must not be modified by any other code.
* 由avformat_new_stream()设置,不能被任何其他代码修改。
*/
再寻找哪些函数调用了avformat_new_stream(),找到avformat_open_input()中的一行调用s->iformat->read_header(s),查看函数声明
/**
* Read the format header and initialize the AVFormatContext
* structure. Return 0 if OK. 'avformat_new_stream' should be
* called to create new streams.
*/
读取格式头文件并初始化AVFormatContext结构。如果OK则返回0。调用“avformat_new_stream”来创建新的流。
根据这位老哥的文章:avformat_find_stream_info() 函数源码解析
老哥原话:
//接下来就需要从网络/文件中读取 packet,这个函数里面做的事情很多,拿 flv 来举例子,执行完 read_frame_internal() 函数,正常情况下,音视频对应的 AVStream 结构体会被创建,并且 ic->nb_streams,也就是流的个数也会是正常的值,比如如果包含音频和视频,nb_streams 的值会是 2。
跟踪源码:
avformat_find_stream_info() -> read_frame_internal() -> ff_read_packet() -> flv_read_packet()
拿flv举例,在flv_read_packet()中(文件是flvdec.c)
if (i == s->nb_streams) {
static const enum AVMediaType stream_types[] = {AVMEDIA_TYPE_VIDEO, AVMEDIA_TYPE_AUDIO, AVMEDIA_TYPE_SUBTITLE, AVMEDIA_TYPE_DATA};
st = create_stream(s, stream_types[stream_type]);
if (!st)
return AVERROR(ENOMEM);
}
static AVStream *create_stream(AVFormatContext *s, int codec_type)
{
FLVContext *flv = s->priv_data;
AVStream *st = avformat_new_stream(s, NULL);
if (!st)
return NULL;
st->codecpar->codec_type = codec_type;
if (s->nb_streams>=3 ||( s->nb_streams=
我看源码里,aac,avi是read_head发现的流信息,flv是read_packet发现的流信息,rtsp也是read_head时
/* NOTE: A new stream can be added there if no header in file
* (AVFMTCTX_NOHEADER). */
ret = read_frame_internal(ic, &pkt1);
在ffmpeg源码中有这么一段注释,可是flv不是有格式头吗?不太懂。。。
====================================================================