This maddening thread描述了我遇到的问题:由于在调用avformat_new_stream
时分配的一些内容导致关闭时内存泄漏。
这是来自泄漏的valgrind堆栈跟踪:
很明显,问题是当AVFormatContext
的流的编解码器上下文的priv_data
字段以某种方式未被释放时。
我的代码将AVFormatContext
与avformat_free_context
一起释放。这会调用ff_free_stream
,它会调用free_stream
,这会释放一些流的编解码器上下文字段本身 - 但不会释放priv_data
字段!
与the corresponding code in avcodec_close
进行比较和对比。
线程问题的建议解决方案:“在调用av_format_free_context
之前先关闭编解码器”。大概这是指调用avcodec_free_context
? - 但我已经这样做了!大致遵循the muxing example中的结构,我有一个由我的代码创建的编码器上下文,用于跟踪未压缩的输入数据。然后是avformat_new_stream
内部创建的另一个编码器上下文(如上所述),由FFmpeg在内部使用。我关闭了前者,因为它是使用avcodec_open2
打开的,但我没有关闭后者,因为它不是。我正在遵循令人发狂的线索的建议,但我在这里。
此外,使用avcodec_free_context
释放AVStream
的编解码器上下文之间的行读取是不行的,因为在执行此操作时(a)AVStream
's codec
field is deprecated,所以这给出了一堆警告,以及(b)there are no NULL
checks in free_stream
,所以这会在运行时崩溃。
我现在所做的是拖拽avcodec_close
的相应代码,并在调用avformat_free_context
之前将其放在我自己的代码中:
#ifdef __GNUC__
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
#endif
for(unsigned i=0;i<avf_context->nb_streams;++i) {
AVStream *st=avf_context->streams[i];
if(st->codec->priv_data&&
st->codec->codec&&
st->codec->codec->priv_class)
{
av_opt_free(st->codec->priv_data);
}
av_freep(&st->codec->priv_data);
}
#ifdef __GNUC__
#pragma GCC diagnostic pop
#endif
这样可以解决漏洞问题,而且(我的眼睛)显然是一个错误,我需要提交错误报告或其他内容。
然而,corresponding bug report被标记为固定和关闭...以及返回到疯狂线程的链接,并且没有进一步的解释。 (这就是令人抓狂的原因!)所以也许我只是错误地使用FFmpeg?
有人可以确认这是否真的是FFmpeg中的错误?
如果它不是一个错误,那么正确的调用序列是什么?
(我正在使用从提交03eb0515c12637dbd20c2e3ca8503d7b47cf583a本地构建的FFmpeg。我从Ubuntu 16包管理器获得的问题看起来有类似问题,这促使我自己用符号构建它等等。 )
答案 0 :(得分:0)
我认为你错误地使用了libav API。作为API控制机制的一部分,每个库都有一个version.h
文件(例如./libavformat/version.h
),它定义了一组控制该库的公共API的宏。
typedef struct AVStream {
int index; /**< stream index in AVFormatContext */
/**
* Format-specific stream ID.
* decoding: set by libavformat
* encoding: set by the user, replaced by libavformat if left unset
*/
int id;
#if FF_API_LAVF_AVCTX
/**
* @deprecated use the codecpar struct instead
*/
attribute_deprecated
AVCodecContext *codec;
#endif
void *priv_data;
#if FF_API_LAVF_FRAC
/**
* @deprecated this field is unused
*/
attribute_deprecated
struct AVFrac pts;
#endif
当您遇到弃用警告时,您应该查找相应的API控件宏并编译libav以及使用libav并将此宏设置为0的代码(例如-DFF_API_LAVF_AVCTX=0
字段时使用codec
覆盖version.h
内容并确保不再使用此弃用的API。