使用 av_frame_get_buffer() 时内存泄漏
Memory leak when using av_frame_get_buffer()
我正在用 ffmpeg 制作一个简单的视频播放器。我注意到存在源自 libavutil 的内存泄漏。因为 ffmpeg 是一个成熟的库,所以我假设我错误地分配了一个新帧。文档对于释放调用 av_frame_get_buffer()
时创建的缓冲区也含糊不清。下面是我用来解码视频并将其排队以在 UI 线程上显示的代码。
DWORD WINAPI DecoderThread(LPVOID lpParam)
{
AVFrame *frame = NULL;
AVPacket pkt;
SwsContext *swsCtx = NULL;
UINT8 *buffer = NULL;
INT iNumBytes = 0;
INT result = 0;
frame = av_frame_alloc();
av_init_packet(&pkt);
pkt.data = NULL;
pkt.size = 0;
// Create scaling context
swsCtx = sws_getContext(codecCtx->width, codecCtx->height, codecCtx->pix_fmt, codecCtx->width, codecCtx->height, AV_PIX_FMT_BGR24, SWS_BICUBIC, NULL, NULL, NULL);
while (av_read_frame(fmtCtx, &pkt) >= 0) {
if (pkt.stream_index == videoStream) {
result = avcodec_send_packet(codecCtx, &pkt);
while (result >= 0) {
result = avcodec_receive_frame(codecCtx, frame);
if (result == AVERROR(EAGAIN) || result == AVERROR_EOF) {
break;
} else if (result < 0) {
// another error.
}
// Create a new frame to store the RGB24 data.
AVFrame *pFrameRGB = av_frame_alloc();
// Allocate space for the new RGB image.
//av_image_alloc(pFrameRGB->data, pFrameRGB->linesize, codecCtx->width, codecCtx->height, AV_PIX_FMT_BGR24, 1);
// Copy all of the properties from the YUV420P frame.
av_frame_copy_props(pFrameRGB, frame);
pFrameRGB->width = frame->width;
pFrameRGB->height = frame->height;
pFrameRGB->format = AV_PIX_FMT_BGR24;
av_frame_get_buffer(pFrameRGB, 0);
// Convert fram from YUV420P to BGR24 for display.
sws_scale(swsCtx, (const UINT8* const *) frame->data, frame->linesize, 0, codecCtx->height, pFrameRGB->data, pFrameRGB->linesize);
// Queue thr BGR frame for drawing by the main thread.
AddItemToFrameQueue(pFrameRGB);
av_frame_unref(frame);
}
}
while (GetQueueSize() > 100) {
Sleep(10);
}
}
CloseFrameQueue();
av_frame_free(&frame);
avcodec_close(codecCtx);
avformat_close_input(&fmtCtx);
return 0;
}
有没有更好的方法来分配一个新的框架来保持 post sws_scale()
转换?
有一个类似的 Whosebug question 主要使用贬值的函数调用。我似乎无法在文档中找到任何符合新版本 ffmpeg 的答案。任何帮助将不胜感激。
根据评论中提出的建议,我向我的解码循环添加了一个 av_packet_unref()
调用,它阻止了我遇到的内存泄漏问题。
sws_scale(swsCtx, (const UINT8* const *) frame->data, frame->linesize, 0, codecCtx->height, pFrameRGB->data, pFrameRGB->linesize);
// Queue thr BGR frame for drawing by the main thread.
AddItemToFrameQueue(pFrameRGB);
av_frame_unref(frame);
}
av_packet_unref(&pkt);
}
while (GetQueueSize() > 100) {
Sleep(10);
}
我正在用 ffmpeg 制作一个简单的视频播放器。我注意到存在源自 libavutil 的内存泄漏。因为 ffmpeg 是一个成熟的库,所以我假设我错误地分配了一个新帧。文档对于释放调用 av_frame_get_buffer()
时创建的缓冲区也含糊不清。下面是我用来解码视频并将其排队以在 UI 线程上显示的代码。
DWORD WINAPI DecoderThread(LPVOID lpParam)
{
AVFrame *frame = NULL;
AVPacket pkt;
SwsContext *swsCtx = NULL;
UINT8 *buffer = NULL;
INT iNumBytes = 0;
INT result = 0;
frame = av_frame_alloc();
av_init_packet(&pkt);
pkt.data = NULL;
pkt.size = 0;
// Create scaling context
swsCtx = sws_getContext(codecCtx->width, codecCtx->height, codecCtx->pix_fmt, codecCtx->width, codecCtx->height, AV_PIX_FMT_BGR24, SWS_BICUBIC, NULL, NULL, NULL);
while (av_read_frame(fmtCtx, &pkt) >= 0) {
if (pkt.stream_index == videoStream) {
result = avcodec_send_packet(codecCtx, &pkt);
while (result >= 0) {
result = avcodec_receive_frame(codecCtx, frame);
if (result == AVERROR(EAGAIN) || result == AVERROR_EOF) {
break;
} else if (result < 0) {
// another error.
}
// Create a new frame to store the RGB24 data.
AVFrame *pFrameRGB = av_frame_alloc();
// Allocate space for the new RGB image.
//av_image_alloc(pFrameRGB->data, pFrameRGB->linesize, codecCtx->width, codecCtx->height, AV_PIX_FMT_BGR24, 1);
// Copy all of the properties from the YUV420P frame.
av_frame_copy_props(pFrameRGB, frame);
pFrameRGB->width = frame->width;
pFrameRGB->height = frame->height;
pFrameRGB->format = AV_PIX_FMT_BGR24;
av_frame_get_buffer(pFrameRGB, 0);
// Convert fram from YUV420P to BGR24 for display.
sws_scale(swsCtx, (const UINT8* const *) frame->data, frame->linesize, 0, codecCtx->height, pFrameRGB->data, pFrameRGB->linesize);
// Queue thr BGR frame for drawing by the main thread.
AddItemToFrameQueue(pFrameRGB);
av_frame_unref(frame);
}
}
while (GetQueueSize() > 100) {
Sleep(10);
}
}
CloseFrameQueue();
av_frame_free(&frame);
avcodec_close(codecCtx);
avformat_close_input(&fmtCtx);
return 0;
}
有没有更好的方法来分配一个新的框架来保持 post sws_scale()
转换?
有一个类似的 Whosebug question 主要使用贬值的函数调用。我似乎无法在文档中找到任何符合新版本 ffmpeg 的答案。任何帮助将不胜感激。
根据评论中提出的建议,我向我的解码循环添加了一个 av_packet_unref()
调用,它阻止了我遇到的内存泄漏问题。
sws_scale(swsCtx, (const UINT8* const *) frame->data, frame->linesize, 0, codecCtx->height, pFrameRGB->data, pFrameRGB->linesize);
// Queue thr BGR frame for drawing by the main thread.
AddItemToFrameQueue(pFrameRGB);
av_frame_unref(frame);
}
av_packet_unref(&pkt);
}
while (GetQueueSize() > 100) {
Sleep(10);
}