当前位置:网站首页>播放器的一些改进
播放器的一些改进
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会略微影响内存的使用情况
未完待续~~
边栏推荐
- The keys of the Flutter storage database
- DBeaver 22.1.4 released, a visual database management platform
- hdu4635 Strongly connected (tarjan calculates strongly connected components + shrink points + ideas)
- 【项目问题】Ionic开发移动端app,手把手教你如何打包生成apk
- VPP静态映射实现DNAT
- 中原银行实时风控体系建设实践
- Go 函数与方法
- Offensive and defensive world - ics-05
- 买股票用同花顺安全吗?资金会不会被转走?
- Raspberry pie 】 【 without WIFI even under the condition of the computer screen
猜你喜欢
Stanford Fall 21: Practical Machine Learning [Chapter 5]
推荐系统 使用surprise库基于协同过滤的方法实现
Offensive and defensive world - web2
字节与字符与常见编码方式
今日分享如何提交一个BUG
Offensive and defensive world - ics-05
Offensive and defensive world - lottery
jupyter lab内终端从sh变为bin/bash(切换conda操作)
安装oracle19c时报错DBT-50000
Recommended download software
随机推荐
字节与字符与常见编码方式
VPP source address NAT
MySQL redo log和undo log
数据治理(三):数据质量管理
什么是DFT?FT、FS、DTFT、DFS、DFT的关系
使用分类权重,轻松解决数据不平衡的问题
Go 匿名字段与实现重写方法
安装oracle19c时报错DBT-50000
Offensive and defensive world - leaking
Golang实现sha256或sha512加密
中原银行实时风控体系建设实践
巧用Prometheus来扩展kubernetes调度器
Offensive and defensive world - fakebook
ES8 | async and await
蔚来杯2022牛客暑期多校训练营6 ABGJM
正向传播和反向传播
DVWA full level detailed customs clearance tutorial
渗透测试-xss的三种类型讲解
ES8 | async和await
C# - var 关键字