当前位置:网站首页>播放器的一些改进
播放器的一些改进
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会略微影响内存的使用情况
未完待续~~
边栏推荐
猜你喜欢

攻防世界——leaking

ES8 | async and await

Offensive and defensive world - lottery

22-08-06 西安 EasyExcel实现字典表导入、导出

Raspberry pie 】 【 without WIFI even under the condition of the computer screen
![[Image Classification] 2021-CoAtNet NeurlPS](/img/e6/c1b9d10dc1605ab568d59f082ac419.png)
[Image Classification] 2021-CoAtNet NeurlPS

渗透测试-xss的三种类型讲解

Redis读写分离(三)

nodeJs--egg框架介绍

【项目问题】Ionic开发移动端app,手把手教你如何打包生成apk
随机推荐
代码检查工具
推荐系统 使用surprise库基于协同过滤的方法实现
什么是DFT?FT、FS、DTFT、DFS、DFT的关系
LVS负载均衡群集及NAT模式群集
Offensive and defensive world - web2
分门别类输入输出,Go lang1.18入门精炼教程,由白丁入鸿儒,go lang基本数据类型和输入输出EP03
开源一夏|Flutter实现搜索的三种方式
[Raspberry Pi] vim editor
推荐100首好听英文歌
正向传播和反向传播
数学基础(二)逆矩阵、伪逆矩阵、最小二乘解、最小范数解
【收藏】3. 壁纸收藏
面试官:工作中用过锁么?说说乐观锁和悲观锁的优劣势和使用场景
67:第五章:开发admin管理服务:20:开发【解冻/冻结用户,接口】;(用户状态变更后,需要刷新用户状态,即变更用户会话信息:我们一般通过“删除redis中会话信息,强制用户重新登录“来做的;)
中原银行实时风控体系建设实践
Techwiz OLED:偏振片的发射特性
P7214 [JOISC2020] 治療計画 题解
PCL calculates the intersection of two straight lines in space
DBeaver 22.1.4 发布,可视化数据库管理平台
各位大佬想问下, flinkcdc采集oracle我看了下延迟大概两分钟左右,想问下有啥解决方法吗