You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

FFmpeg调用libx264编码器内存泄漏问题(旧版本求助)

FFmpeg libx264旧版本内存泄漏问题解决方案

问题背景

使用FFmpeg 2.8git版本搭配libx264 0.136.x编码器时,发现视频编码完成后的内存释放阶段存在泄漏:调用avcodec_open2分配的内存无法通过avcodec_close和avcodec_free_context完全释放,循环打开关闭编码器(无帧写入)时泄漏现象明显。改用FFmpeg内置编码器(如AV_CODEC_ID_MPEG4)则无泄漏,确认问题与libx264私有数据的释放逻辑相关。尝试过手动释放priv_data的方案,但未解决问题。

复现代码

#include <stdint.h>
extern "C"{
#include <x264.h>
#include <libavcodec/avcodec.h>
#include <libavutil/opt.h>
}

int main()
{
    avcodec_register_all();

    AVCodec *codec;
    AVCodecContext *c;
    for (int n=0; n<2000; n++)
    {
        codec = avcodec_find_encoder_by_name("libx264");
        c=avcodec_alloc_context3(codec);
        c->pix_fmt=AV_PIX_FMT_YUV420P;
        c->width=1920;
        c->height=1080;
        c->time_base=(AVRational){1, 30};
        c->framerate=(AVRational){30, 1};
        avcodec_open2(c, codec, NULL);
        avcodec_close(c);
        av_opt_free(c->priv_data);
        av_freep(&c->priv_data);
        avcodec_free_context(&c);
    }
    return 0;
}

代码问题分析

你的代码中手动调用av_opt_free(c->priv_data)和av_freep(&c->priv_data)是错误操作:

  • avcodec_close本身应该负责释放编码器的私有数据(包括libx264的上下文)
  • 旧版本FFmpeg的libx264封装可能存在释放逻辑漏洞,但手动干预priv_data的释放会破坏内部状态,反而加剧泄漏

适配旧版本的解决方案

方案1:修正释放流程(基础修复)

直接移除手动释放priv_data的代码,确保调用顺序正确:

#include <stdint.h>
extern "C"{
#include <x264.h>
#include <libavcodec/avcodec.h>
#include <libavutil/opt.h>
}

int main()
{
    avcodec_register_all();

    AVCodec *codec;
    AVCodecContext *c;
    for (int n=0; n<2000; n++)
    {
        codec = avcodec_find_encoder_by_name("libx264");
        c=avcodec_alloc_context3(codec);
        c->pix_fmt=AV_PIX_FMT_YUV420P;
        c->width=1920;
        c->height=1080;
        c->time_base=(AVRational){1, 30};
        c->framerate=(AVRational){30, 1};
        avcodec_open2(c, codec, NULL);
        // 只保留标准释放流程
        avcodec_close(c);
        avcodec_free_context(&c);
    }
    return 0;
}

如果此方案仍存在泄漏,说明旧版本FFmpeg的libx264封装确实存在bug,需要使用方案2或3。

方案2:修补FFmpeg的libx264编码器源码

找到FFmpeg源码中的libavcodec/libx264.c,定位x264_close函数,确保它正确销毁x264编码器上下文:

static av_cold int x264_close(AVCodecContext *ctx)
{
    X264Context *x264 = ctx->priv_data;

    // 确保添加以下代码(如果原本没有)
    if (x264->enc) {
        x264_encoder_close(x264->enc);
        x264->enc = NULL;
    }

    av_freep(&x264->sei);
    return 0;
}

重新编译FFmpeg后,标准释放流程即可正常工作。

方案3:临时手动补全释放逻辑(无需修改FFmpeg源码)

如果无法重新编译FFmpeg,可以在avcodec_close后手动调用x264的销毁函数:

#include <stdint.h>
extern "C"{
#include <x264.h>
#include <libavcodec/avcodec.h>
#include <libavutil/opt.h>
}

// 声明FFmpeg内部的X264Context结构(旧版本定义)
typedef struct {
    x264_t *enc;
    // 其他字段无需完全匹配,只需保留enc指针即可
} X264Context;

int main()
{
    avcodec_register_all();

    AVCodec *codec;
    AVCodecContext *c;
    for (int n=0; n<2000; n++)
    {
        codec = avcodec_find_encoder_by_name("libx264");
        c=avcodec_alloc_context3(codec);
        c->pix_fmt=AV_PIX_FMT_YUV420P;
        c->width=1920;
        c->height=1080;
        c->time_base=(AVRational){1, 30};
        c->framerate=(AVRational){30, 1};
        avcodec_open2(c, codec, NULL);
        
        avcodec_close(c);
        // 手动补全x264编码器销毁
        X264Context *x264_ctx = (X264Context*)c->priv_data;
        if (x264_ctx && x264_ctx->enc) {
            x264_encoder_close(x264_ctx->enc);
            x264_ctx->enc = NULL;
        }
        avcodec_free_context(&c);
    }
    return 0;
}

注意:此方案依赖旧版本FFmpeg中X264Context的结构定义,若结构有差异需调整。

内容的提问来源于stack exchange,提问作者ksb496

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.08 12:55:30