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

如何为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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.17 12:25:23