我将AVFrames收集到数组中,然后释放它们,但这会导致内存泄漏。
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检查),但是释放的内存不会立即返回到操作系统,这让我感到困惑。
发布于 2020-04-05 02:13:05
您可以直接在新分配的AVFrame上使用av_image_fill_arrays,如下所示:
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()。
希望这能有所帮助。
发布于 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)。您将看到它实际上维护了一个池列表,用于重用已分配的缓冲区。
https://stackoverflow.com/questions/61006755
复制相似问题