我正在使用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 2)
两个地点之一来删除数据包的数据。结果是应用程序崩溃了消息"Heap Corruption..."
如果我没有释放packet
,则会发生内存泄漏。
请注意,上面的代码在解码H264
流时成功,主要问题是内存泄漏并在我尝试释放packet
有人可以告诉我代码中的问题。
非常感谢,
T&amp; T公司
答案 0 :(得分:2)
av_free_packet
将清除您的数据包数据,这是在av_read_frame
内分配的相同指针。但是你在packet.data += bytesDecoded;
=&gt;中更改了它崩溃。
几个建议:
如果首次使用您的数据包av_init_packet
(在此功能内完成),则无需致电av_read_frame
。但是如果你保留你的代码,你需要它来将packet.size
初始化为0(经过测试,但第一次没有初始化)
每次完成数据包数据时,只有在解码成功时才调用av_free_packet
。在您的代码中,这意味着您必须在avcodec_decode_video2
之后调用它,即使框架未完成。
一旦你的打包被解码(即avcodec_decode_video2
没问题,无论frameFinished
是真还是假),你都可以释放它。无需保留它并更改数据指针。该过程是&#34;读取数据包,解码,释放它。读取下一个数据包,解码,释放它。&#34;。 (请注意,这不适用于音频数据包)。
我建议通过类似的方式简化主循环(首先读取,然后解码):
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
}
答案 1 :(得分:1)
您应该在使用之前初始化您的数据包,如下所示:
AVPacket packet;
av_init_packet(&packet);
您也不要删除AVFormatContext
个实例。
avformat_free_context(pFormatCtx);