该函数对应打开输入流函数,这个函数会检测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; }