[英]FFMPEG: Can not free AVPacket when decode H264 stream?
我正在使用FFMPEG来解码H264流,我的代码如下
AVFormatContext *pFormatCtx = NULL;
AVCodecContext *pCodecCtx = NULL;
AVFrame *pFrame = NULL;
AVPacket packet;
packet.data = NULL;
pFormatCtx = avformat_alloc_context();
avformat_open_input(&pFormatCtx, videoStreamPath, NULL, NULL);
liveHeader.pCodecCtx = pFormatCtx->streams[videoStreamIndex]->codec;
int bytesDecoded = 0;
int frameFinished = 0;
while (true)
{
while (packet.size > 0)
{
// Decode the next chunk of data
bytesDecoded = avcodec_decode_video2(pCodecCtx, pFrame,
&frameFinished, &packet);
// Was there an error?
if (bytesDecoded < 0)
{
printf(strErr, "Error while decoding frame\n");
commonGlobal->WriteRuntimeRecLogs(strErr);
return RS_NOT_OK;
}
packet.size -= bytesDecoded;
packet.data += bytesDecoded;
if (frameFinished)
{
//av_free_packet(&packet); //(free 1)
return RS_OK;
}
// Did we finish the current frame? Then we can return
}
do
{
try
{
int ret = av_read_frame(pFormatCtx, &packet);
if (ret < 0)
{
char strErr[STR_LENGTH_256];
if (ret == AVERROR_EOF || (pFormatCtx->pb && pFormatCtx->pb->eof_reached))
{
sprintf(strErr, "Error end of file line %d", __LINE__);
}
if (pFormatCtx->pb && pFormatCtx->pb->error)
{
sprintf(strErr, "Error end of file line %d", __LINE__);
}
packet.data = NULL;
return RS_NOT_OK;
}
}
catch (...)
{
packet.data = NULL;
return RS_NOT_OK;
}
} while (packet.stream_index != videoStreamIndex);
}
//av_free_packet(&packet); //(free 2)
问题是我不知道如何正确释放packet
内存。
我试图通过调用两个地方中的一个来删除数据包的数据av_free_packet(&packet); (free 1)
av_free_packet(&packet); (free 1)
和av_free_packet(&packet); (free 2)
av_free_packet(&packet); (free 2)
。 结果是应用程序崩溃了"Heap Corruption..."
这个消息"Heap Corruption..."
如果我不释放packet
,则会发生内存泄漏。
注意上面的代码在解码H264
流时成功,主要问题是内存泄漏并在我尝试释放packet
时崩溃
有人可以告诉我代码中的问题。
非常感谢,
T&T
av_free_packet
将清除您的数据包数据,这是在av_read_frame
内分配的相同指针。 但你在packet.data += bytesDecoded;
更改了它packet.data += bytesDecoded;
=>崩溃。
几个建议:
如果首次使用您的数据包是av_read_frame
,则无需调用av_init_packet
(在此函数内部完成)。 但是如果你保留你的代码,你需要它来将packet.size
初始化为0(测试,但第一次没有初始化)
每次完成数据包数据时,只有在解码成功时才调用av_free_packet
。 在您的代码中,这意味着您必须在avcodec_decode_video2
之后调用它,即使帧未完成。
一旦你的包装被解码(即avcodec_decode_video2
是确定的,不管frameFinished
是真的还是假的),你可以释放它。 无需保留它并更改数据指针。 这个过程是“读取数据包,解码它,释放它。读取下一个数据包,解码它,释放它。”。 (请注意,这不适用于音频数据包)。
我建议通过类似的东西来简化你的主循环(先读取,然后解码):
while(true)
{
// Step 1: Read packet
while(true)
{
av_read_frame(pFormatCtx, &packet);
// todo: Error handling
if(packet.stream_index != videoStreamIndex)
{
av_free_packet(&packet);
}
else
{
break;
}
} while (packet.stream_index != videoStreamIndex);
// Step 2/3: Decode and free
avcodec_decode_video2(pCodecCtx, pFrame, &frameFinished, &packet);
av_free_packet(&packet);
// todo: Error handling and checking frameFinished if needed
// Of course, if you need to use the packet now, move the av_free_packet() after this
}
您应该在使用前初始化数据包,如下所示:
AVPacket packet;
av_init_packet(&packet);
您也不要删除AVFormatContext
实例。
avformat_free_context(pFormatCtx);
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.