当前位置:网站首页>播放器的一些改进
播放器的一些改进
2022-08-08 09:18:00 【很难绷得住】
在多线程中学习了unique_lock 与lock_guard,可以利用RAII对锁的生命周期进行管理
在播放器中使用了大量的lock与unlock操作,现在通过对播放器中一些代码进:
在之前写播放器的时候,出现了点击暂停后没反应的bug,也打不开新的多媒体文件,这是因为暂停的函数中没有加锁,导致ispause变量的值还没有被真正修改就切换到其他线程,此时run()一直占着锁,而open()拿不到锁,于是我们将设置ispause变量的代码加锁:
void xaudiothread::SetPause(bool isPause)
{
amux.lock();
this->isPause = isPause;
if (audioplay)
audioplay->SetPause(isPause);
amux.unlock();
}
现在bug得到了解决,然后使用unique_lock 与lock_guard:
void xaudiothread::SetPause(bool isPause)
{
unique_lock<mutex> lock(amux);
//lock_guard<mutex> lock(amux);
this->isPause = isPause;
if (audioplay)
audioplay->SetPause(isPause);
}
lock将在退出栈区时自动释放掉amux,代码更加美观,对于这种只加锁一次的很简单,我们现在去对xvideothread::run()与 xaudiothread::run()去修改,以xvideothread::run()为例,修改前:
void xvideothread::run()
{
cout << "开始视频线程" << endl;
while (!isexit)
{
vmux.lock();
if (isPause)
{
vmux.unlock();
msleep(5);
continue;
}
if (!decode)
{
vmux.unlock();
msleep(1);
continue;
}
if (synpts > 0 && synpts < decode->pts)
{
vmux.unlock();
msleep(2);
continue;
}
AVPacket* pkt = pop();
bool re = decode->send(pkt);
if (!re)
{
vmux.unlock();
msleep(1);
continue;
}
//可能一次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);
}
vmux.unlock();
}
}
修改后:
void xvideothread::run()
{
cout << "开始视频线程" << endl;
while (!isexit)
{
unique_lock<mutex> lock(vmux);
if (isPause)
{
//vmux.unlock();
msleep(5);
continue;
}
if (!decode)
{
//vmux.unlock();
msleep(1);
continue;
}
if (synpts > 0 && synpts < decode->pts)
{
//vmux.unlock();
msleep(2);
continue;
}
AVPacket* pkt = pop();
bool re = decode->send(pkt);
if (!re)
{
//vmux.unlock();
msleep(1);
continue;
}
//可能一次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);
}
}
}
此时会出现音频正常播放,但是画面卡住了,这是因为xvideothread::RepaintPts函数中也要拿到锁才能运行,当这个函数拿不到锁时,将会出现画面卡住的现象,为什么会拿不到锁呢:这是因为unique_lock lock(vmux);的lock在一次循环结束时退出栈区时才会释放,由于之前是手动unlock()然后sleep几毫秒让RepaintPts()去拿锁,所以之前不会卡顿,但是修改了之后这个sleep()是在解锁前sleep(),RepaintPts()仍然拿不到锁,于是我们将这个sleep()移到unique_lock lock(vmux);之前,这样代码还能更加美观:
void xvideothread::run()
{
cout << "开始视频线程" << endl;
while (!isexit)
{
msleep(1);
unique_lock<mutex> lock(vmux);
if (isPause)
{
continue;
}
if (!decode)
{
continue;
}
if (synpts > 0 && synpts < decode->pts)
{
continue;
}
AVPacket* pkt = pop();
bool re = decode->send(pkt);
if (!re)
{
continue;
}
//可能一次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);
}
}
}
其实这里用lock_guard更好些。因为unique_lock比lock_guard灵活很多,效率上差一点,内存占用多一点,播放器这里有大量循环,不断构造占更大内存的unique_lock会略微影响内存的使用情况
未完待续~~
边栏推荐
猜你喜欢
交换两个整型变量的三种方法
方案 | 医疗单据OCR识别,为医保零星报销打造安全屏障
Multi-scalar multiplication: state of the art & new ideas
COMSOL Multiphysics 6.0软件安装包和安装教程
Offensive and defensive world - fakebook
BLOB, TEXT, GEOMETRY or JSON column 'xxxx' can't have a default value
Techwiz OLED:偏振片的发射特性
oracle中联表相关思考
Redis读写分离(三)
Offensive and defensive world - web2
随机推荐
[ 深度学习 ] 课程学习(Curriculum Learning)
【树莓派】vim编辑器
文献学习(part33)--Clustering by fast search and find of density peaks
数学基础(一)矩阵对角化、SVD分解以及应用
22-08-06 西安 EasyExcel实现字典表导入、导出
ES8 | async和await
入职半个月的一些思考
Implementation principle of priority queue
hdu4635 Strongly connected(tarjan计算强连通通分量+缩点+思想)
STL 底层实现原理
Offensive and defensive world - fakebook
Web优化躬行记(6)——优化闭环实践
优先队列的实现原理
VPP source address NAT
牛刀小试基本语法,Go lang1.18入门精炼教程,由白丁入鸿儒,go lang基本语法和变量的使用EP02
斯坦福21秋季:实用机器学习【第5章】
Offensive and defensive world - leaking
中原银行实时风控体系建设实践
PCL 计算两空间直线的交点
【AGC】开放式测试示例