随着打开的多媒体文件的增多,占用的内存也会越来越多:


访问媒体文件的起点是通过xplay2.cpp中的xdemuxthread.open(),因此清理也从xdemuxthread开始:
void xdemuxthread::Close()
{
isexit = true;
wait();
if (vt) vt->Close();
if (at) at->Close();
mux.lock();
delete vt;
delete at;
vt = NULL;
at = NULL;
mux.unlock();
}
1.vt与at是解封装线程来调用的,因为解封装线程要负责来清理vt与at
2.为了防止指针删到一半,然后其他线程突然来使用删掉的指针指针造成bug,因此要将这四句加锁
3.我们在删除一个指针之后,编译器只会释放该指针所指向的内存空间,而不会删除这个指针本身,因此还要将这些new出来的指针置null
对于vt与at的close来说,它们有大部分功能都是一样的,因此把一样的功能放在他们的共同基类xdecodethread中:
void xdecodethread::Close()
{
Clear();
//等待线程退出
isexit = true;
wait();
decode->close();
mux.lock();
delete decode;
decode = NULL;
mux.unlock();
}
class xaudiothread:public xdecodethread
{
public:
long long pts = 0;
xaudiothread();
virtual ~xaudiothread();
void run();
virtual bool open(AVCodecParameters* par, int samplerate, int channels);
protected:
std::mutex amux;
xaudioplay* audioplay=0;
xresample* resample=0;
};
```cpp
class xvideothread:public xdecodethread
{
public:
xvideothread();
virtual ~xvideothread();
virtual bool open(AVCodecParameters*par,ivideocall*call,int width,int height);
void run();
long long synpts = 0;
protected:
xvideowidget* video=0;
ivideocall* call = 0;
std::mutex vmux;
};
下面在对特有的部分处理:
音频线程特有的res与ap
void xaudiothread::Close()
{
xdecodethread::Close();
if (resample)
{
resample->Close();
amux.lock();
delete resample;
resample = NULL;
amux.unlock();
}
if (audioplay)
{
audioplay->close();
amux.lock();
audioplay = NULL;
amux.unlock();
}
}
先调用其父类的清理共同部分,再清理自己的独有的部分
audioplay为单例模式,不需要delete
单例模式:保证一个类仅有一个实例,并提供一个该实例的全局访问点。 ——《设计模式》GoF
在软件系统中,经常有这样一些特殊的类,必须保证他们在系统中只存在一个实例,才能确保它们的逻辑正确性、以及良好的效率。
对于不同的媒体文件,它们使用的都是同一个audioplay
在xplay2的析构中调用该close:
Xplay2::~Xplay2()
{
dt.Close();
}
但是发现并没有什么卵用
可以从进程内存的图中看到内存占了2G,因此主要是解码后的视频数据没有得到释放
然后查看关于解码的receive(),果然在这里出了问题:
//可能一次send多次receive
while (!isexit)
{
AVFrame* frame = decode->receive();
if (!frame)break;
if(call)
{
call->Repaint(frame);
}
else {
cout << "repaint fail " << endl;
}
av_frame_free(&frame);
}
当把从解码队列接收到的frame给repaint完后,这个frame就没用了,因此用av_frame_free(&frame)将其释放掉

此时进程内存稳定在250MB左右,每帧音频或者视频数据,在其播放或者绘制完后,都会立刻得到释放。
本文探讨了多媒体文件打开增多导致内存占用增加的问题,重点分析了解封装线程的关闭过程和内存释放策略。通过在xdecodethread基类中统一清理功能,减少重复代码,并在子类中处理特有部分。音频线程和视频线程在关闭时释放了特有的资源如resample和audioplay。问题定位在解码后的AVFrame未及时释放,通过调用av_frame_free()解决了内存泄漏问题,使进程内存稳定在合理范围。

被折叠的 条评论
为什么被折叠?



