音视频开发中的队列实现
〇、参考
《音视频开发进阶指南:基于Android与iOS平台的实践》:7.2.1 音频队列的实现
一、最小队列
使用C语言
C++类中的方法,对应到C中则为,结构体中的函数指针类型的属性
结构体中的其他属性,称为常规属性
使用链表实现,将队列元素作为有效数据封装到链表节点中,最终连接成的链表就是一个队列
typedef struct PacketQueue {PacketList *mFirst;PacketList *mLast;Mutex *mMutex;Cond *mCond;int (*packet_queue_put)(PacketQueue *que, Packet *pkt);int (*packet_queue_get)(PacketQueue *que, Packet *pkt, int block);
} PacketQueue;
1.0 自定义链表(节点)类型
链表的其中一个成员也是一个链表,由于这种特殊结构的存在,后面我们将链表节点类型和链表类型当成一回事,可以混用。
typedef struct PacketList{Packet *pkt;PacketList *next;
} PacketList;
1.1 队列常规属性
头节点mFirst:链表节点类型,当链表只有一个节点时,头节点同时也是尾节点
尾节点mLast:链表节点类型,当链表只有一个节点时,尾节点同时也是头节点
互斥锁mMutex:和条件变量一起保证线程安全
条件变量mCond:和互斥锁一起保证线程安全
1.2 队列函数指针属性
packet_queue_put:将一个包压入队列尾
packet_queue_get:从队列头获取一个包
1.2.1 packet_queque_put的实现
1.2.1.1 流程
abort操作:如果队列已经abort,什么都不做,返回-1
将包封装为链表节点
上锁(禁止其他线程这时候访问),准备将链表节点放入链表
挂节点:将新链表节点放入链表尾部
如果队列为空,令链表节点任命为尾结点兼头节点;
如果队列不空,将链表节点挂在尾节点后边,然后将链表节点任命为尾节点。
发信号:链表节点放入链表后,条件变量发送一个signal,告诉block住的线程,可以继续从队列中获取元素了
解锁
1.2.1.2 细节说明
往链表中压入节点是在链表尾进行操作,一般涉及不到头节点,仅当链表为空或只有一个链表节点时,会涉及到头节点。所以压包入列时,把对头节点的操作当做特殊情况操作写在特殊情况处理if中,把对尾节点的必经操作(任命操作)写在特殊情况处理if外。
1.2.1.3 完整代码
//成功返回1
//出错或队列abort了,返回-1
int packet_queue_put(PacketQueue *que, Packet *pkt)
{PacketList *pkt_lst; //定义一个链表类型的指针 为pkt_lst分配内存, 若分配不成功返回-1;if(mAbortRequest) return -1;//2. 将包封装为链表节点pkt_lst->pkt = pkt;pkt_lst->next = NULL;//未来该包后面挂哪个包,谁也不知道,所以为NULL//3. 上锁LockMutex(que->mMutex);//4. 将链表节点放入链表尾部if(NULL == que->mLast){ //链表为空的其中一种表示方法que->mFirst = pkt_lst;}else{que->mLast->next = pkt_lst;}que->mLast = pkt_lst;//5. 发信号CondSignal(que->mCond);//6. 解锁UnlockMutex(que->mMutex);释放pkt_lst的内存;return 1;
}
1.2.2 packet_queue_get的实现
1.2.2.1 流程
上锁
abort操作:如果abort了队列,什么也不做,返回-1
取节点:从链表取出头节点
如果队列为空,
如果block非0,表示实现一个blocking queue,则令当前线程阻塞在get方法,并解锁让其他线程得以访问队列,直到当前线程获得队列不为空的信号后,重新上锁再从队取一次包
如果block为0,表示实现非blocking queue,则直接解锁后返回-1
如果队列非空,取出头节点,并任命新的头节点(get方法必经操作),若新的头节点为空(即队列此时为空),则还需重新任命新的尾节点也为空
解封装:解封取出的链表节点,拿到包
解锁
1.2.2.2 细节说明
CondWait(&mCond,&mMutex);可以实现队列为空时的要求
当队列为空时取包,当前线程被阻塞,待队列非空后,有个重新取包的操作。这一重新取包操作通过循环实现,即将“从链表取出头节点”这一操作放入循环中,同时在队列非空时的取包操作后加上break。
由于CondWait(&mCond, &mMutex);在返回前又把mMutx给锁上了(见SDL_几个完整头文件:SDL_mutex.h:SDL_CondWait的说明),所以从链表取头节点之前的上锁操作不用放进循环
重新取包时也要判断队列是否abort了,所以判断队列是否abort了的逻辑也放入循环中,同时不能直接返回-1,因为此时已经上锁(进入循环前),要先解锁后再返回-1
从链表中取头节点是在链表头部进行操作,一般涉及不到尾节点,仅当链表为空或只有一个链表节点时,会涉及到尾节点。所以从链表中取头节点时,把对头节点的必经操作(取出头节点然后任命新的头节点)写在特殊情况处理if外,把对尾节点的操作当做特殊情况操作写在特殊情况处理if中。
1.2.2.3 完整代码
//成功返回1
//非blocking queue为空时,返回0
//出错或队列abort了返回-1int packet_queue_get(PacketQueue *que, Packet* pkt, int block){ret = 0;PacketList *pkt_lst;为pkt_lst分配内存,如果分配不成功返回-1;//1. 上锁LockMutex(que->mMutex);while(1){//2. 队列abort时的操作if(mAbortRequest){ret = -1;break;}//3. 从链表中取出头节点if(que->mFirst){ //队列非空pkt_lst = mFirst;//取出头节点mFirst = pkt_lst->next;//任命新的头节点if(NULL == mFirst){//如果新的队列为空mLast = NULL; }//4. 解封取出的链表节点,拿到包pkt = pkt_lst->pkt;ret = 1;break;}else if(0 == block){ret = 0; break;}else{CondWait(que->mCond, que->mMutex); } }//while(1)//5. 解锁UnlockMutex(que->mMutex);释放pkt_lst的内存;return ret;
}
二、总结
空队列的两种表示方法
if(NULL == mFirst)
if(NULL == mLast)
只有一个元素的队列,该元素既是头节点也是尾节点
压包入队,尾节点操作为必经操作,头节点操作为特殊情况操作
取包出队,头节点操作为必经操作,尾节点操作为特殊情况操作
三、扩展功能队列
3.1 扩展常规属性
队列当前元素数目
队列当前字节数
3.2 扩展函数指针属性
abort队列
销毁队列
音视频开发中的队列实现相关推荐
- 直播软件搭建音视频开发中的视频采集
直播软件搭建音视频开发中的视频采集 前言 在直播和短视频行业日益火热的发展形势下,音视频开发(采集.编解码.传输.播放.美颜)等技术也随之成为开发者们关注的重点,本系列文章就音视频开发过程中所运用到的 ...
- 音视频开发中常见基础问题总结
转载请把头部出处链接和尾部二维码一起转载,本文出自逆流的鱼yuiop:http://blog.csdn.net/hejjunlin/article/details/54962205 前言:音视频中一些 ...
- 18个实时音视频开发中会用到开源项目
实时音视频的开发学习有很多可以参考的开源项目.一个实时音视频应用共包括几个环节:采集.编码.前后处理.传输.解码.缓冲.渲染等很多环节.每一个细分环节,还有更细分的技术模块.比如,前后处理环节有美颜. ...
- 关于在Android音视频开发中,Google API的MediaCodeC与成熟开源编码器X264的应用对比及使用场景
在2019年的一个大项目中,有一个功能模块让笔者感触颇深,那就是实时音视频的预览,当然这不是普通的开开直播,画面出来了就完了那么简单,如果你是一个开发者,那么你肯定知道同样大小的一张图片里,色彩丰富的 ...
- 音视频开发必看:“秒变萝莉音”,游戏中的变声是如何实现的
0.引 自从有了"变声",你永远猜不到隔着网线的另一边和你开黑的队友到底是男是女. 当然,天然会伪音的我们学不来,也没必要,这里主要跟大家分享一个一篇关于音视频开发中的变声实现的技 ...
- Android音视频开发基础(六):学习MediaCodec API,完成视频H.264的解码
前言 在Android音视频开发中,网上知识点过于零碎,自学起来难度非常大,不过音视频大牛Jhuster提出了<Android 音视频从入门到提高 - 任务列表>.本文是Android音视 ...
- FFmpeg 工具:音视频开发都用它,快@你兄弟来看丨音视频工具
(本文基本逻辑:ffmpeg 常用命令介绍 → ffplay 常用命令介绍 → ffprobe 常用命令介绍) 从事音视频开发的程序员几乎都应该知道或使用过 FFmpeg.FFmpeg 是一个开源软件 ...
- Android 音视频开发相关知识
音视频开发技能 要在Android上进行音视频开发,需要掌握以下技能: Android开发:首先,您需要掌握Android应用程序的基本开发技能,包括Java或Kotlin编程语言,Android S ...
- 音视频开发——H265码流解析
概述 H.265技术的应用 编码技术主要运用于视频播放设备.软件应用以及拍摄.录制视频的设备.人们最熟悉的莫过于PPS网络视频播放器.在PC屏客户端产品上面,PPS已经于2013年初推出了基于H.26 ...
最新文章
- sap data service安装方法
- [SpringBoot]全局异常处理
- java难点解析(七)-抽象类
- 看懂OpenCV中IplImage转换成CvMat的语句:CvMat sstub, *src = cvGetMat(srcarr, sstub);
- PAT甲级1020 Tree Traversals:[C++题解]树的遍历、由中序序列和后序序列递归建树
- SAP Spartacus的site context配置参数SiteContextParamsService
- 使用OpenSSL加密,使用Java解密,使​​用OpenSSL RSA公钥
- cortex-m3 操作模式 寄存器组 异常类型 堆栈 中断
- 《十四堂人生创意课》读书笔记,思维导图
- html基本进阶知识【转】
- 计算机音乐数字乐谱fade,faded简谱_faded数字简谱
- 小程序 开发版 上传大小受限制
- 求救 关于ORA-01115的错误
- idea-2017破解教程
- 推荐免费下载430套大型企业管理源码 下载地址:http://www.hur.cn/tg/linkin.asp?linkid=205389 下载地址:[URL=http://www.hur.cn/t
- 趋势 | 极简再见,极繁回潮
- gitee 上传代码时报错git did not exit cleanly (exit code 1)
- 马克下, 初识 runtime (一)
- python0表示剪刀_简化Python代码(石头、纸、剪刀)
- poj2245Lotto
热门文章
- Elasticsearch7.X 入门学习第九课笔记-----聚合分析Aggregation
- 一个脚本还你清爽体验
- 2022届秋招面经--秋招笔试(2)
- 牛顿迭代法的公式推导
- javaScript正则表达式截取字符串【截取中间、截取前面、截取后面】
- 分享在github超酷超炫特效动画,不看你会后悔的。
- sina网页新闻小偷原理及源代码(java版)
- html中%3ch3%3e有颜色吗,在增强 iOS 通知系统这件事上,IFTTT 和 Pushover 谁做得更好?...
- android 音符动画效果,纯css实现音符跳动效果
- 打印1到最大的n位数(Java)