ffmpeg 的 api 和 数据结构都是 c 风格,当我在 c++ 中使用它们时,很自然就想到用智能指针去管理(例如 AVFormatContext*
、AVCodecContext*
等),因为可以自定义删除器,将 ffmpeg 提供的 free
操作放进去;但 ffmpeg 中的一些 api 需要传入裸指针,一些 api 甚至会在内部直接分配空间,这样子用智能指针管理的想法会不会是没有必要的?
拿 AVFormatContext
来举例,正常可以像这样得到一个被智能指针管理的 AVFormatContext
结构
auto deleter = [](AVFormatContext* f){
if(f) avformat_free_context(f);
};
std::unique_ptr<AVFormatContext, decltype(deleter)> fmt(avformat_alloc_context(), deleter);
但和它相关的一个 api 是 avformat_open_input
,它的函数声明如下(以下贴出一部分实现)
int avformat_open_input(AVFormatContext **ps, const char *url,
const AVInputFormat *fmt, AVDictionary **options);
// demux.c 下 avformat_open_input 的一部分实现
int avformat_open_input(AVFormatContext **ps, const char *filename,
const AVInputFormat *fmt, AVDictionary **options)
{
...
AVFormatContext *s = *ps;
...
if (!s && !(s = avformat_alloc_context()))
return AVERROR(ENOMEM);
...
}
可以看到 avformat_open_input
需要一个二级指针,所以需要直接传入裸指针。如果想要将一个初始化的 unique_ptr<AVFormatContext>
搭配 avformat_open_input
使用,就需要像这样(网上看到的做法)
auto deleter = [](AVFormatContext* f){
if(f) avformat_free_context(f);
};
std::unique_ptr<AVFormatContext, decltype(deleter)> fmt(avformat_alloc_context(), deleter);
auto tmp = fmt.get();
avformat_open_input(&tmp, ...);
到这里我就开始怀疑用 unique_ptr
管理 AVFormatContext
的意义了,不过以上这个例子还好,只是观感上没那么优雅。但以下的例子让我质疑用智能指针做管理的必要。
AVFormatContext
还有一个相关的 api 是 avformat_alloc_output_context2
,以下是函数声明和部分实现:
int avformat_alloc_output_context2(AVFormatContext **ctx, const AVOutputFormat *oformat,
const char *format_name, const char *filename);
int avformat_alloc_output_context2(AVFormatContext **avctx, const AVOutputFormat *oformat,
const char *format, const char *filename)
{
AVFormatContext *s = avformat_alloc_context();
int ret = 0;
*avctx = NULL;
...
*avctx = s;
}
可以看到,avformat_alloc_output_context2
同样需要传入二级指针,但与 avformat_open_input
的区别在于,它内部直接将 *avctx = NULL
,并没有判断其是否为空,同时还将分配了新的内存地址给 avctx
,这也就意味着以下的操作会造成内存泄漏:
auto deleter = [](AVFormatContext* f){
if(f) avformat_free_context(f);
};
std::unique_ptr<AVFormatContext, decltype(deleter)> fmt(avformat_alloc_context(), deleter);
auto tmp = fmt.get();
avformat_alloc_output_context2(&tmp, ...);
至此让我产生用智能指针管理 ffmpeg 数据结构的必要性,有没有大佬来解答一下。
这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。
V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。
V2EX is a community of developers, designers and creative people.