我使用c#调用ffmpeg库。我使用示例代码来解码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;
}
break语句在两种情况下都会导致分配的帧丢失,而在第二种情况下会导致数据包丢失。除此之外,第一眼看上去还不错。10MB并不多,这取决于视频的类型。例如,1080p视频是1920x1080x1.5=3MB/帧,在整个视频生命周期中,你通常会有一些引用保持活跃,所以在任何时候,1080p都有5-10帧活跃=15-30MB。如果你启用了线程(默认情况下是开启的),每增加一个活动线程,这个帧就会增加1帧(一个典型的机器会有4个活动线程)。
你没有提到任何关于内存使用增长的视频生命周期。例如,当视频播放时,它是否随时间线性增长(甚至是100帧或1000帧)?这将是一个问题。如果这是c/c++,您通常会使用valgrind,但也许c#有其他内存分析工具。
至于你的解码器循环,你没有读取缓存帧后的解路器信号EOF,即你没有馈送NULL数据包到解码器。