gpt4 book ai didi

c++ - 如何正确释放 BitStreamFilter (bsf) 而不会出现双重释放错误?

转载 作者:行者123 更新时间:2023-12-04 22:46:53 26 4
gpt4 key购买 nike

我正在尝试编写一个通过 ffmpeg 处理 MP4 电影的 C++ 类。
首先,我创建了几个函数用于 std::unique<>()这样即使在异常情况下事情也会被释放。
但是,当我尝试释放 BitStreamFilter 对象时,我得到了双重释放,但文档清楚地表明每个 av_bsf_alloc()必须与 av_bsf_free() 配对称呼。

@param ctx a pointer into which the pointer to the newly-allocated contextwill be written. It must be freed with av_bsf_free() after thefiltering is done.


注意:强调我的。
然而,当时我调用 avformat_close_input()即使我没有将这两个上下文用于任何事情,我也会收到双重错误!?我在想可能有一个数据包既分配又试图释放。但是由于这两个上下文没有直接联系,我真的不明白他们最终是如何两次释放某些东西的。
下面是重现错误的代码(至少在 amd64 平台上)。编译后,您可以执行它。确保指定文件名,如下所示:
./ffmpeg_demuxer_test mymovie.mp4
我使用以下命令编译和链接代码:
$ /usr/bin/c++ -std=c++17 -DDEBUG -D_DEBUG -D_GLIBCXX_ASSERTIONS -g -O0 \
-fsanitize=address -fsanitize=enum -fsanitize=unreachable \
-o ffmpeg_demuxer_test ffmpeg_demuxer_test.cpp \
-lavformat -lavcodec
注意 -fsanitize=...捕获错误的选项,例如双重释放错误。
这是代码:
extern "C" {
#include <libavformat/avformat.h>
#include <libavformat/avio.h>
#include <libavcodec/avcodec.h>
}
#include <iostream>
#include <memory>


void ffmpeg_demuxer_avformat_context_free(AVFormatContext * context)
{
if(context != nullptr) avformat_close_input(&context);
}

void ffmpeg_demuxer_av_bsf_free(AVBSFContext * context)
{
if(context != nullptr) av_bsf_free(&context);
}


int main(int argc, char * argv [])
{
if(argc != 2)
{
std::cout << "Usage: " << argv[0] << " movie.mp4" << std::endl;
exit(1);
}

// init the AV libraries
//
av_register_all();
avformat_network_init();

// allocate the AVFormatContext
//
AVFormatContext * format_context(nullptr);
int const r1(avformat_open_input(
&format_context
, argv[1]
, nullptr // input format
, nullptr)); // options
if(r1 != 0
|| format_context == nullptr)
{
throw std::bad_alloc();
}

auto f_format_context = std::unique_ptr<
AVFormatContext
, decltype(&ffmpeg_demuxer_avformat_context_free)>(
format_context
, &ffmpeg_demuxer_avformat_context_free);


// now allocate a stream
//
if(avformat_find_stream_info(f_format_context.get(), nullptr) < 0)
{
throw std::runtime_error("ffmpeg: Could not find stream info");
}

auto f_video_stream_index = av_find_best_stream(
f_format_context.get()
, AVMEDIA_TYPE_VIDEO
, -1 // wanted stream (any)
, -1 // related stream (none)
, nullptr // AVCodec *
, 0); // flags
if(f_video_stream_index < 0)
{
throw std::runtime_error("ffmpeg: Could not find stream in input file");
}
if(static_cast<unsigned int>(f_video_stream_index) >= f_format_context->nb_streams)
{
throw std::range_error("ffmpeg: Stream index out of range");
}

auto f_stream = f_format_context->streams[f_video_stream_index];

auto f_video_codec = f_stream->codecpar->codec_id;

int f_bit_depth(0);
switch(f_stream->codecpar->format)
{
case AV_PIX_FMT_YUV420P10LE:
f_bit_depth = 10;
break;

case AV_PIX_FMT_YUV420P12LE:
f_bit_depth = 12;
break;

default:
f_bit_depth = 8;
break;

}

bool f_mp4_h264 = f_video_codec == AV_CODEC_ID_H264 && (
strcmp(f_format_context->iformat->long_name, "QuickTime / MOV") == 0
|| strcmp(f_format_context->iformat->long_name, "FLV (Flash Video)") == 0
|| strcmp(f_format_context->iformat->long_name, "Matroska / WebM") == 0
);

if(f_mp4_h264)
{
AVBitStreamFilter const * bsf_stream_filter(av_bsf_get_by_name("h264_mp4toannexb"));
if(bsf_stream_filter == nullptr)
{
throw std::runtime_error("av_bsf_get_by_name(\"h264_mp4toannexb\") failed");
}
AVBSFContext * bsf_context(nullptr);
int const r2(av_bsf_alloc(bsf_stream_filter, &bsf_context));
if(r2 < 0
|| bsf_context == nullptr)
{
throw std::bad_alloc();
}
auto f_bsf_context = std::unique_ptr<
AVBSFContext
, decltype(&ffmpeg_demuxer_av_bsf_free)>(
bsf_context
, &ffmpeg_demuxer_av_bsf_free);
f_bsf_context->par_in = f_stream->codecpar;
if(av_bsf_init(f_bsf_context.get()) < 0)
{
throw std::runtime_error("av_bsf_init() failed");
}
}

return 0;
}
所以。我是误读了文档还是误用了免费/关闭功能之一?我不认为 AVBSFContext当我关闭 AVFormatContext 时,它本身会被释放,但我可能弄错了?
我不会将“C”作为标签,因为即使这适用于 C,它也会被删除。这并不是因为我使用 C++,所以我获得了双重免费(即它发生在 ffmpeg C 库中)。

最佳答案

它双重释放 AVCodecParameters*你在这里设置的:

f_bsf_context->par_in = f_stream->codecpar;
你应该做一个深拷贝。有一个 avcodec_parameters_copyutils.c .

关于c++ - 如何正确释放 BitStreamFilter (bsf) 而不会出现双重释放错误?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65782600/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com