gpt4 book ai didi

c - 如何正确避免 avformat_new_stream 的 avcodec_alloc_context3 泄漏?

转载 作者:太空狗 更新时间:2023-10-29 12:41:12 25 4
gpt4 key购买 nike

This maddening thread描述了我遇到的问题:由于在调用 avformat_new_stream 时分配了一些内容而导致关机时出现内存泄漏。

这是来自泄漏的 valgrind 堆栈跟踪:

  • 1 个 block 中的 1,447(1,440 个直接,7 个间接)字节在丢失记录 2 of 4 中肯定丢失
  • 在 0x4C2FFC6:memalign(在/usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so 中)
  • 通过 0x4C300D1:posix_memalign(在/usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so 中)
  • 通过 0x690DEFF:av_malloc (mem.c:87)
  • 通过 0x690E09D:av_mallocz ( mem.c:224 )
  • 通过 0x533D28A:init_context_defaults ( options.c:128 )
  • 根据 0x533D325:avcodec_alloc_context3 (options.c:164)
  • 通过 0x663D09E:avformat_new_stream (utils.c:4384)
  • 通过 0x4204B6:main (test_ffmpeg.cpp:918)

很明显,问题是当 AVFormatContext 的流的编解码器上下文的 priv_data 字段未被释放时。

我的代码使用 avformat_free_context 释放了 AVFormatContext .这称为 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 包管理器中遇到了类似的问题,这促使我自己使用符号等构建它。)

最佳答案

我认为您错误地使用了 libav API。作为 API 控制机制的一部分,每个库都有一个 version.h 文件(例如 ./libavformat/version.h ),它定义了一组控制该库公共(public) 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。

关于c - 如何正确避免 avformat_new_stream 的 avcodec_alloc_context3 泄漏?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43389411/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com