avformat_new_stream接口声明位于ffmpeg/libavformat/avformat.h 中,主要功能为在AVFormatContext 中创建 Stream 通道
/**
* Add a new stream to a media file.
*
* When demuxing, it is called by the demuxer in read_header(). If the
* flag AVFMTCTX_NOHEADER is set in s.ctx_flags, then it may also
* be called in read_packet().
*
* When muxing, should be called by the user before avformat_write_header().
*
* User is required to call avcodec_close() and avformat_free_context() to
* clean up the allocation by avformat_new_stream().
*
* @param s media file handle
* @param c If non-NULL, the AVCodecContext corresponding to the new stream
* will be initialized to use this codec. This is needed for e.g. codec-specific
* defaults to be set, so codec should be provided if it is known.
*
* @return newly created stream or NULL on error.
*/
AVStream *avformat_new_stream(AVFormatContext *s, const AVCodec *c);
与该接口相关的结构体
AVFormatContext :
unsigned int nb_streams; 记录stream通道数目。
AVStream **streams; 存储stream通道。
AVStream :
int index; 在AVFormatContext 中所处的通道索引
avformat_new_stream接口实现位于ffmpeg/libavformat/utils.c 中
AVStream *avformat_new_stream(AVFormatContext *s, const AVCodec *c)
{
AVStream *st;
int i;
AVStream **streams;
//创建avstream
if (s->nb_streams >= FFMIN(s->max_streams, INT_MAX/sizeof(*streams))) {
if (s->max_streams < INT_MAX/sizeof(*streams))
av_log(s, AV_LOG_ERROR, "Number of streams exceeds max_streams parameter (%d), see the documentation if you wish to increase it\n", s->max_streams);
return NULL;
}
streams = av_realloc_array(s->streams, s->nb_streams + 1, sizeof(*streams));
if (!streams)
return NULL;
s->streams = streams;
st = av_mallocz(sizeof(AVStream));
if (!st)
return NULL;
if (!(st->info = av_mallocz(sizeof(*st->info)))) {
av_free(st);
return NULL;
}
st->info->last_dts = AV_NOPTS_VALUE;
//ffmpeg 3.1.4版本codec 已经废除了
#if FF_API_LAVF_AVCTX
FF_DISABLE_DEPRECATION_WARNINGS
st->codec = avcodec_alloc_context3(c);
if (!st->codec) {
av_free(st->info);
av_free(st);
return NULL;
}
FF_ENABLE_DEPRECATION_WARNINGS
#endif
st->internal = av_mallocz(sizeof(*st->internal));
if (!st->internal)
goto fail;
////通道记录的流的编码参数的默认设置
//注: AVCodecParameters codecpar 替换原先的CodecContext codec
st->codecpar = avcodec_parameters_alloc();
if (!st->codecpar)
goto fail;
st->internal->avctx = avcodec_alloc_context3(NULL);
if (!st->internal->avctx)
goto fail;
if (s->iformat) {
#if FF_API_LAVF_AVCTX
FF_DISABLE_DEPRECATION_WARNINGS
/* no default bitrate if decoding */
st->codec->bit_rate = 0;
FF_ENABLE_DEPRECATION_WARNINGS
#endif
/* default pts setting is MPEG-like */
avpriv_set_pts_info(st, 33, 1, 90000);
/* we set the current DTS to 0 so that formats without any timestamps
* but durations get some timestamps, formats with some unknown
* timestamps have their first few packets buffered and the
* timestamps corrected before they are returned to the user */
st->cur_dts = RELATIVE_TS_BASE;
} else {
st->cur_dts = AV_NOPTS_VALUE;
}
st->index = s->nb_streams;
st->start_time = AV_NOPTS_VALUE;
st->duration = AV_NOPTS_VALUE;
st->first_dts = AV_NOPTS_VALUE;
st->probe_packets = s->max_probe_packets;
st->pts_wrap_reference = AV_NOPTS_VALUE;
st->pts_wrap_behavior = AV_PTS_WRAP_IGNORE;
st->last_IP_pts = AV_NOPTS_VALUE;
st->last_dts_for_order_check = AV_NOPTS_VALUE;
for (i = 0; i < MAX_REORDER_DELAY + 1; i++)
st->pts_buffer[i] = AV_NOPTS_VALUE;
st->sample_aspect_ratio = (AVRational) { 0, 1 };
#if FF_API_R_FRAME_RATE
st->info->last_dts = AV_NOPTS_VALUE;
#endif
st->info->fps_first_dts = AV_NOPTS_VALUE;
st->info->fps_last_dts = AV_NOPTS_VALUE;
st->inject_global_side_data = s->internal->inject_global_side_data;
st->internal->need_context_update = 1;
s->streams[s->nb_streams++] = st;
return st;
fail:
free_stream(&st);
return NULL;
}