该函数对应打开输入流函数,这个函数会检测ps == NULL,如果是true的话,则分配内存。因此它的释放函数也包括释放ps内存的部分。
int avformat_open_input(AVFormatContext **ps, const char *url, ff_const59 AVInputFormat *fmt, AVDictionary **options);
分析该函数分为三部分
第一部分,调用AVInputFormat的read_close()方法关闭输入流
关闭输入:比如从海康读取rtsp流时,会给摄像机发送本地停止接收流的信号。
第二部分,调用avformat_free_context()释放AVFormatContext
这个上面有提到。
avformat_free_context(s)
该函数的核心就是释放申请创建的视频和音频的流
for (i = s->nb_streams - 1; i >= 0; i–)
ff_free_stream(s, s->streams[i]);
第三部分,调用avio_close()关闭并且释放AVIOContext
看下关于AVFormatContext的另一个函数
int avformat_alloc_output_context2(AVFormatContext **avctx, AVOutputFormat *oformat,
const char *format, const char *filename)
这个函数的源码中,会直接把*avctx = NULL,然后再给它分配内存,因此没必要在外给avctx分配内存,会造成内存泄露(后附源码)。
在ffmpeg4.3中实测,avctx并不会内存泄露,在执行
AVFormatContext *ic = NULL; ic = avformat_alloc_context(); printf("ic_b = %d\n", ic); int re = avformat_open_input(&ic, URL, NULL, NULL); if (re != 0) { printf("open input error = %d\n", re); ErrorFunc(re); } printf("ic_a = %d\n", ic);
打印如下:
ic_b = 30900544
ic_a = 30900544
libavformat\mux.c
int avformat_alloc_output_context2(AVFormatContext **avctx, AVOutputFormat *oformat,
const char *format, const char *filename)
{
AVFormatContext *s = avformat_alloc_context();
int ret = 0;
*avctx = NULL;
if (!s)
goto nomem;
if (!oformat) {
if (format) {
oformat = av_guess_format(format, NULL, NULL);
if (!oformat) {
av_log(s, AV_LOG_ERROR, "Requested output format '%s' is not a suitable output format\n", format);
ret = AVERROR(EINVAL);
goto error;
}
} else {
oformat = av_guess_format(NULL, filename, NULL);
if (!oformat) {
ret = AVERROR(EINVAL);
av_log(s, AV_LOG_ERROR, "Unable to find a suitable output format for '%s'\n",
filename);
goto error;
}
}
}
s->oformat = oformat;
if (s->oformat->priv_data_size > 0) {
s->priv_data = av_mallocz(s->oformat->priv_data_size);
if (!s->priv_data)
goto nomem;
if (s->oformat->priv_class) {
*(const AVClass**)s->priv_data= s->oformat->priv_class;
av_opt_set_defaults(s->priv_data);
}
} else
s->priv_data = NULL;
if (filename)
av_strlcpy(s->filename, filename, sizeof(s->filename));
*avctx = s;
return 0;
nomem:
av_log(s, AV_LOG_ERROR, "Out of memory\n");
ret = AVERROR(ENOMEM);
error:
avformat_free_context(s);
return ret;
}