使用libavfilter过滤视频时,巨大的内存泄漏 [英] Huge memory leak when filtering video with libavfilter

查看:1128
本文介绍了使用libavfilter过滤视频时,巨大的内存泄漏的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个相对简单的FFMPEG C程序,视频帧被馈送到该FFMPEG C程序,通过过滤器图形进行处理,然后发送到帧渲染器.

I have a relatively simple FFMPEG C program, to which a video frame is fed, processed via filter graph and sent to frame renderer.

以下是一些代码段:

/* Filter graph here */
char args[512];
enum AVPixelFormat pix_fmts[] = {AV_PIX_FMT_RGB32 };    
AVFilterGraph   *filter_graph;
avfilter_register_all();
AVFilter *buffersrc  = avfilter_get_by_name("buffer");
AVFilter *buffersink = avfilter_get_by_name("ffbuffersink");
AVBufferSinkParams *buffersink_params;
AVFilterInOut *outputs = avfilter_inout_alloc();
AVFilterInOut *inputs  = avfilter_inout_alloc();
filter_graph = avfilter_graph_alloc();

snprintf(args, sizeof(args),
        "video_size=%dx%d:pix_fmt=%d:time_base=%d/%d:pixel_aspect=%d/%d",
        av->codec_ctx->width, av->codec_ctx->height, av->codec_ctx->pix_fmt,
        av->codec_ctx->time_base.num, av->codec_ctx->time_base.den,
        av->codec_ctx->sample_aspect_ratio.num, av->codec_ctx->sample_aspect_ratio.den);

if(avfilter_graph_create_filter(&av->buffersrc_ctx, buffersrc, "in",args, NULL, filter_graph) < 0) 
{
    fprintf(stderr, "Cannot create buffer source\n");
    return(0);
}

 /* buffer video sink: to terminate the filter chain. */
buffersink_params = av_buffersink_params_alloc();
buffersink_params->pixel_fmts = pix_fmts;

if(avfilter_graph_create_filter(&av->buffersink_ctx, buffersink, "out",NULL, buffersink_params, filter_graph) < 0) 
{
    printf("Cannot create buffer sink\n");
    return(HACKTV_ERROR);
}

  /* Endpoints for the filter graph. */
    outputs->name       = av_strdup("in");
    outputs->filter_ctx = av->buffersrc_ctx;
    outputs->pad_idx    = 0;
    outputs->next       = NULL;

    inputs->name       = av_strdup("out");
    inputs->filter_ctx = av->buffersink_ctx;
    inputs->pad_idx    = 0;
    inputs->next       = NULL;

const char *filter_descr = "vflip";

    if (avfilter_graph_parse_ptr(filter_graph, filter_descr, &inputs, &outputs, NULL) < 0)
{
    printf("Cannot parse filter graph\n");
    return(0);
}

 if (avfilter_graph_config(filter_graph, NULL) < 0) 
{
    printf("Cannot configure filter graph\n");
    return(0);
}

av_free(buffersink_params);
avfilter_inout_free(&inputs);
avfilter_inout_free(&outputs);

上面的代码在其他地方被调用:

The above code is called by these elsewhere:

av->frame_in->pts = av_frame_get_best_effort_timestamp(av->frame_in);

/* push the decoded frame into the filtergraph*/
if (av_buffersrc_add_frame(av->buffersrc_ctx, av->frame_in) < 0) 
{
    printf( "Error while feeding the filtdergraph\n");
    break;
 }

 /* pull filtered pictures from the filtergraph */ 
 if(av_buffersink_get_frame(av->buffersink_ctx, av->frame_out) < 0) 
 {
      printf( "Error while sourcing the filtergraph\n");
       break;
  }  

/* do stuff with frame */

现在,代码可以正常运行,并且视频以我期望的方式显示(出于测试目的而垂直翻转).

Now, the code works absolutely fine and the video comes out the way I expect it to (vertically flipped for testing purposes).

我遇到的最大问题是存在大量内存泄漏.高分辨率视频将在几秒钟内消耗2Gb,并使程序崩溃.我将泄漏追溯到这段代码:

The biggest issue I have is that there is a massive memory leak. An high res video will consume 2Gb in a matter of seconds and crash the program. I traced the leak to this piece of code:

/* push the decoded frame into the filtergraph*/
if (av_buffersrc_add_frame(av->buffersrc_ctx, av->frame_in) < 0) 

如果我通过执行av->frame_out=av->frame_in;绕过过滤器而没有将框架推入过滤器(并且显然没有从中拉出),则不会发生泄漏并且内存使用情况是稳定的.

If I bypass the filter by doing av->frame_out=av->frame_in; without pushing the frame into it (and obviously not pulling from it), there is no leak and memory usage is stable.

现在,我对C还是很陌生,请保持柔和,但似乎我应该以某种方式清除buffersrc_ctx,但不知道如何清除.我查看了官方文档,但找不到任何东西.

Now, I am very new to C, so be gentle, but it seems like I should be clearing out the buffersrc_ctx somehow but no idea how. I've looked in official documentations but couldn't find anything.

有人可以建议吗?

推荐答案

发布后5分钟,看来我要做的就是在处理完每一帧后取消引用帧.

5 minutes after posting, looks like all I had to do was unreference frames after each one processed.

        av_frame_unref(av->frame_in);
        av_frame_unref(av->frame_out);

这篇关于使用libavfilter过滤视频时,巨大的内存泄漏的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆