如何为FFmpeg各类指针创建并正确使用C++智能指针?
为FFmpeg不同指针类型创建C++智能指针的问题解答
1. AVCodecContext* 智能指针实现分析
场景说明
- 分配:
AVCodecContext *avcodec_alloc_context3(const AVCodec *codec);返回直接可用的指针 - 释放:
void avcodec_free_context(AVCodecContext **avctx);需要传入指针的指针,内部会释放内存并将指针置空 - 使用:
int avcodec_open2(AVCodecContext *avctx, const AVCodec *codec, AVDictionary **options);直接传入指针
用户实现代码
std::shared_ptr<AVCodecContext> av_codec_context(avcodec_alloc_context3(av_codec), [](AVCodecContext* _context) { if (_context) avcodec_free_context(&_context); }); avcodec_open2(av_codec_context.get(), av_codec, NULL);
正确性分析
这段代码是正确的。
- lambda表达式中,
&_context指向传入指针的副本,但副本指向的是智能指针管理的同一块内存,avcodec_free_context会正确释放该内存,并将副本置空(不影响智能指针内部的原始指针,因为此时智能指针已完成所有权释放)。 - 调用
avcodec_open2时通过get()获取原始指针,符合函数参数要求。
优化建议
如果不需要共享所有权,更推荐使用轻量的std::unique_ptr,自定义删除器写法类似:
std::unique_ptr<AVCodecContext, void(*)(AVCodecContext*)> av_codec_context( avcodec_alloc_context3(av_codec), [](AVCodecContext* ctx) { if (ctx) avcodec_free_context(&ctx); } );
2. AVDictionary** 智能指针实现分析
场景说明
- 分配/使用:
int av_dict_set(AVDictionary **pm, const char *key, const char *value, int flags);若*pm为NULL,会自动分配字典并写入*pm - 释放:
void av_dict_free(AVDictionary **m);释放字典内存并将*m置空
用户实现代码
std::shared_ptr<AVDictionary*> av_dict(new (AVDictionary*), [](AVDictionary** _dict) { if (_dict) { if(*_dict) av_dict_free(_dict); delete _dict; } }); av_dict_set(av_dict.get(), "key", "value", 0);
正确性分析
代码逻辑可行,但存在初始化隐患:
new (AVDictionary*)是错误写法,正确初始化应为new AVDictionary*(nullptr),否则创建的指针指针会指向未初始化内存,可能导致av_dict_set行为异常。- 其余部分逻辑正确:智能指针管理
AVDictionary**类型内存,删除器先调用av_dict_free释放字典,再释放外层指针内存。
优化后的代码
// 初始化时将内部指针置为nullptr std::shared_ptr<AVDictionary*> av_dict(new AVDictionary*(nullptr), [](AVDictionary** _dict) { if (_dict) { av_dict_free(_dict); // av_dict_free内部会判断*_dict是否为NULL,无需额外检查 delete _dict; } }); av_dict_set(av_dict.get(), "key", "value", 0);
3. AVFormatContext* 智能指针实现分析
场景说明
- 分配:
AVFormatContext *avformat_alloc_context(void);返回直接可用的指针 - 释放:
void avformat_free_context(AVFormatContext *s);直接传入指针即可释放 - 使用:
int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options);直接传入指针int avformat_open_input(AVFormatContext **ps, const char *url, const AVInputFormat *fmt, AVDictionary **options);可传入指向NULL的指针,函数会自动分配并写入新的上下文
用户实现代码(针对avformat_find_stream_info)
std::shared_ptr<AVFormatContext> av_format_context(avformat_alloc_context(), [](AVFormatContext* _context) { if(_context) avformat_free_context(_context); }); avformat_find_stream_info(av_format_context.get(), NULL);
正确性分析
这段代码是正确的。
- 智能指针接管
avformat_alloc_context分配的内存,删除器直接调用avformat_free_context释放,符合函数要求。 avformat_find_stream_info通过get()获取原始指针,调用方式正确。
适配avformat_open_input的实现方法
avformat_open_input可能会自动分配上下文,此时不能直接传入智能指针内部指针的地址(因为智能指针不会自动更新内部指针),正确做法是先用临时指针接收分配结果,再移交智能指针管理:
std::shared_ptr<AVFormatContext> fmt_ctx; AVFormatContext* raw_ptr = nullptr; // 调用avformat_open_input,传入临时指针的地址 int ret = avformat_open_input(&raw_ptr, "input.mp4", nullptr, nullptr); if (ret == 0) { // 临时指针分配成功后,移交智能指针管理 fmt_ctx.reset(raw_ptr, [](AVFormatContext* ctx) { if (ctx) avformat_free_context(ctx); }); // 后续可正常使用fmt_ctx avformat_find_stream_info(fmt_ctx.get(), nullptr); }
内容的提问来源于stack exchange,提问作者Elija
相关产品推荐
相关产品推荐

