首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >将AVFrames收集到缓冲区中

将AVFrames收集到缓冲区中
EN

Stack Overflow用户
提问于 2020-04-03 15:11:51
回答 2查看 590关注 0票数 1

我将AVFrames收集到数组中,然后释放它们,但这会导致内存泄漏。

代码语言:javascript
复制
extern "C" {
#include <libavutil/frame.h>
#include <libavutil/imgutils.h>
}

#include <vector>
#include <iostream>

AVFrame * createFrame() {
    int width = 1280;
    int height = 720;
    AVPixelFormat format = AV_PIX_FMT_YUV420P;
    int buffer_size = av_image_get_buffer_size(format, width, height, 1);
    uint8_t * buffer = (uint8_t *)av_malloc(buffer_size * sizeof(uint8_t));
    memset(buffer, 1, buffer_size);

    uint8_t *src_buf[4];
    int      src_linesize[4];
    av_image_fill_arrays(src_buf, src_linesize, buffer, format, width, height, 1);

    AVFrame * frame = av_frame_alloc();
    frame->width = width;
    frame->height = height;
    frame->format = format;
    av_frame_get_buffer(frame, 0);
    av_image_copy(frame->data, frame->linesize,
                  const_cast<const uint8_t**>(src_buf), const_cast<const int*>(src_linesize),
                  format, width, height);
    av_free(buffer);
    return frame;
}

int main(int argc, char *argv[]) {
    uint32_t count = 1024;

    // fill array with frames
    std::vector<AVFrame*> list;
    for (uint64_t i = 0; i < count; ++i) {
        list.push_back(createFrame());
    }
    // allocated 1385 mb in heap

    // clear all allocated data
    for (auto i = list.begin(); i < list.end(); ++i) {
        if (*i != NULL) {
            av_frame_free(&(*i));
        }
    }
    list.clear();

    // memory-leak of > 360 Mb
}

但是,如果只是创建帧并立即释放它,而不将其保存到向量中,则不会出现内存泄漏,尽管创建了相同数量的帧。

我哪里做错了?

更新:

我错了。这里没有内存泄漏(由valgrind检查),但是释放的内存不会立即返回到操作系统,这让我感到困惑。

EN

回答 2

Stack Overflow用户

发布于 2020-04-05 02:13:05

您可以直接在新分配的AVFrame上使用av_image_fill_arrays,如下所示:

代码语言:javascript
复制
av_image_fill_arrays(frame->data,       /* destination */
                     frame->linesize,   /* destination */
                     buffer,            /* source      */
                     format,            /* source      */
                     width,             /* source & alingment */
                     height, 1);

去掉上面不必要的代码,比如手动复制缓冲区,也不要在createFrame中使用av_free(buffer);。函数av_image_fill_arrays不分配任何缓冲区。只使用现有的一个;main()中的av_frame_free将负责释放。

以下是一些文档:

av_image_fill_arrays

根据指定的图像参数和提供的数组设置数据指针和行大小。

通过使用指向图像数据缓冲器的src地址来填充给定图像的字段。根据指定的像素格式,将设置一个或多个图像数据指针和行大小。如果指定了平面格式,则将设置多个指向不同图片平面的指针,并且将不同平面的线条大小存储在lines_sizes数组中。使用src == NULL调用以获取src缓冲区所需的大小。

要在一次调用中分配缓冲区并填充dst_data和dst_linesize,请使用av_image_alloc()。

希望这能有所帮助。

票数 1
EN

Stack Overflow用户

发布于 2020-11-24 11:44:13

最近,我遇到了同样的问题。在跟踪调用堆栈之后,我意识到ffmpeg使用AVBufferPool的链表来改进内存分配和释放。

在从av_buffer_unref调用的buffer_replace的函数体中,它调用buffer的free函数:b->free(b->opaque, b->data)。进入此调用后,它会跳转到buffer.c文件中的void pool_release_buffer(void *opaque, uint8_t *data)。您将看到它实际上维护了一个池列表,用于重用已分配的缓冲区。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/61006755

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档