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
相关产品推荐
相关产品推荐

