我使用C#来调用ffmpeg lib。 我使用示例代码解码MP4格式的视频。
然而,当我调用avcodec_decode_video2函数时,我发现内存增长很多(比如10MB)。
在我调用avcodec_close(& CodecContext)函数之前,内存一直在增长。
我想原因可能是AVCodecContext在调用avcodec_decode_video2函数期间分配10MB数据。在AVCodecContext关闭之前,这个内存不会被释放。
我不知道我是不对。
主要代码如下。
private bool readNextBuffer(int index)
{
/// Read frames into buffer
//m_codecContext->refcounted_frames = 0;
int frameNumber = 0;
FrameBuffer[index].Clear();
GC.Collect();
while (frameNumber < m_bufferSize)
{
AVPacket Packet; /// vedio packet
AVPacket* pPacket = &Packet;
//AVFrame* pDecodedFrame = FFmpegInvoke.avcodec_alloc_frame();
AVFrame* pDecodedFrame = FFmpegInvoke.av_frame_alloc();
if (FFmpegInvoke.av_read_frame(m_pFormatContext, pPacket) < 0)
{
Console.WriteLine("The end of the vedio.");
break;
}
if (pPacket->stream_index == pStream->index)
{
/// Decode vedio frame
int gotPicture = 0;
int size = FFmpegInvoke.avcodec_decode_video2(m_codecContext, pDecodedFrame, &gotPicture, pPacket);
if (size < 0)
{
Console.WriteLine("End of the vedio.");
//throw new Exception(string.Format("Error while decoding frame {0}", frameNumber));
break;
}
if (gotPicture == 1)
{
/// Allocate an AVFrame structure
if (convertFrame(pDecodedFrame, index))
{
frameNumber++;
}
else
{
Console.WriteLine("Error: convert failed.");
}
}
}
FFmpegInvoke.av_frame_free(&pDecodedFrame);
FFmpegInvoke.av_free_packet(pPacket);
GC.Collect();
}
nowFrameIndex = 0;
return FrameBuffer.Count > 0 ? true : false;
}
答案 0 :(得分:1)
在两种情况下,您的break语句都会导致丢失已分配的帧,并且仅在第二种情况下导致数据包丢失。除此之外,它一见钟情。 10MB不是很多,具体取决于视频的类型。例如,1080p视频是1920x1080x1.5 = 3MB /帧,并且您通常会在视频的整个生命周期内保留一些参考,因此在任何时候您都会有5-10帧活着= 1080p为15-30MB。如果启用了线程(默认情况下已启用),则每个额外活动线程将增加1帧(典型计算机将激活4个线程)。
您没有提及有关视频生命周期内内存使用量增长的任何信息。例如,在播放视频时(即使是100帧或1000帧),它会随着时间的推移呈线性增长吗?那将是一个问题。如果这是c / c ++,你通常会使用valgrind,但也许c#有其他的内存分析工具。
对于你的解码器循环,在解复用器发出信号EOF之后你不会读取缓存帧,即你没有将NULL数据包送入解码器。建议这样做。