自定义博客皮肤VIP专享

*博客头图:

格式为PNG、JPG,宽度*高度大于1920*100像素,不超过2MB,主视觉建议放在右侧,请参照线上博客头图

请上传大于1920*100像素的图片!

博客底图:

图片格式为PNG、JPG,不超过1MB,可上下左右平铺至整个背景

栏目图:

图片格式为PNG、JPG,图片宽度*高度为300*38像素,不超过0.5MB

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

-+
  • 博客(45)
  • 收藏
  • 关注

原创 线程池介绍

这将唤醒正在等待任务的子线程,不过只有一个子线 程将获得新任务的”接管权“,它可以从工作队列中取出任务并执行之,而其他子线程将继续睡眠在 工作队列上。线程池是由服务器预先创建的一组子线程,线程池中的线程数量应该和 CPU 数量差不多。当有新的任务到来时,主线程将通过某种方式选择线程池中的某一个子 线程来为之服务。相比与动态的创建子线程,选择一个已经存在的子线程的代价显然要小得多。创建好线程组后每个线程都会循环等待任务的到来,一旦任务队列中有任务来的时候就会弹出并进行处理。

2024-07-02 15:10:24 242

原创 代码随想录训练营第二十四天 78子集 90子集II

用一个count值来记录当前遍历到IP地址的第几个字段了,如果当前已经遍历到第三个字段的时候,就需要考虑剩下的字符是否符合要求,如果符合要求的话就将剩下的结果添加到path中,如何将path添加到res结果数组中。如果要是全排列的话,每次要从0开始遍历,为了跳过已入栈的元素,需要使用used。终止条件:当前要收集的起始位置已经大于等于数组的大小的时候证明已经搜集到完成了。本题和子集很相似,但是要注意的是本题有重复的元素,但是结果中不能包含重复的子集。本题很简单,就是在每次遍历的地方都要搜集结果。

2024-06-30 16:45:15 305

原创 代码随想录训练营第二十三天 39组合总和 40组合总和II 131分割回文串

本题要注意的就是树层去重的逻辑。树枝上不需要去重,因为树枝上的元素对应的是不同的元素。而树层上的元素必须要去重,因为在树枝上前一个相同的元素的遍历会包含当前元素的所有遍历结果,因此如果在同一层中当前的元素和前一个元素相同并且前一个元素没有被使用过的情况下,该元素直接跳过。当sum的值等于target的时候将组合添加到组合集合中。for循环中注意本题中的元素是可以重复选取的,因此下层递归中的startIndex还是i。在递归的逻辑中是将startIndex的位置向后移动一位。本题要注意的是去重的逻辑。

2024-06-29 17:12:42 192

原创 代码随想录训练营第二十二天 77组合

需要用一个sum来记录当前所有元素加起来的值是多少,然后和n进行比较即可。本题需要用一个string数组来记录每个数字对应的字符串。终止条件,当中间变量用来存储单个结果的大小等于k,则将中间变量存放到结果数组中。先将输入字符串的字符转换为数字。然后在找到数字对应的字符串后进行for循环。回溯的时候单个组合要pop_back(),sum要pop掉的那个值。中间变量的大小等于输入字符串的大小则存放入res数组中。for循环遍历的是字符串中每个数字对应的英文字母。递归是为了找到下一个位置的数字对应的英文字母。

2024-06-27 22:48:06 276

原创 代码随想录训练营第二十一天 669修建二叉搜索树 108将有序数组转换为二叉搜索树 538把二叉搜索树转换为累加树

如果当前节点的val值小于low边界,说明当前这个节点是要删除的节点,但是不能直接返回null,因为在这个节点的右子树中可能存在区间内的值,因此需要继续向右子树遍历,观察右子树中的每个节点值都在区间内。因为题目提到了要求是平衡的二叉搜索树,因此我们直接取数组的中间元素作为root,然后根据mid来划分左右数组区间,依次向左和向右递归两个数组区间。同理当前节点的值大于high边界同上一样的但是相反的操作。采用后序遍历的方式 一开始先向右遍历,然后中再向前。如果root本身为null的话直接返回null;

2024-06-26 21:53:35 286

原创 代码随想录训练营第二十天 235二叉搜索树的最近公共祖先 701二叉搜索树中的插入操作

注意本题是二叉搜索树,只要发现当前节点的值比p节点和q节点的值都大的话,那么最近公共祖先的位置一定的当前节点的左子树中,同理如果都小的话就在当前节点的右子树。当当前节点的值大于p并小于q的时候证明该节点就要返回的节点。先找到右子树左下角的元素,然后让该元素的左指针指向要删除节点的左子树。终止条件就是当前遍历的节点为空,那么就需要新建val节点然后被上一层遍历的节点接住。3.要删除的节点的左节点为空,右节点不为空。4.要删除的节点的左节点不为空,右节点为空。5.要删除的节点的左右节点都不为空。

2024-06-25 22:38:04 166

原创 代码随想录训练营第十八天 530二叉搜索树的最小绝对差 501二叉搜索树中的众数 236二叉树的最近公共祖先

如果count>maxcount的值话,则需要将res中的值全部都清空,再把cur的值存放到res中。maxcount更新为count的值。在中序的时候将当前节点和前一个节点的值相减取绝对值然后和res进行比较。如果count的值和maxcount的值相等的话就将cur的值存放在res中,如果pre为空的话证明当前节点是左下角的那个元素,count记录为1;如果pre的值和cur的值相同,count++;定义一个pre节点来存放当前节点的前一个节点。定义一个pre节点来存放当前节点的前一个节点。

2024-06-24 22:36:53 252

原创 代码随想录训练营第十七天 654最大二叉树 617合并二叉树 700二叉树搜索树的搜索

终止条件:因为传入了两个树,那么就有两个树遍历的节点t1和t2,如果t1==null,那么两个树合并之后就是t2,同理t2==null,合并之后就是t1。将两个树的当前节点进行相加。然后根节点的左指向和右指向就进行递归。先用一个pre来记录当前遍历节点的前一个节点,判断当前节点的值是否大于pre的值。中:当前的pre不为空的情况下进行判断。先向左遍历:找到第一个节点,然后用bool left接住返回值。终止条件:当前节点是的值为目标值的时候,返回当前节点。单层递归逻辑:向左和向右子树遍历。

2024-06-24 21:50:01 282

原创 代码随想录训练营第十六天 513找树左下角的值 112路径总和I 113路径总和II 106从中序和后序遍历序列构造二叉树

采用中序遍历的方式,中左右,中间节点先添加到路径,向左遍历的时候targetSum的值-=节点的值传递给下一层递归逻辑。参数和返回值:参数需要有一个来记录此时的节点的深度,传入下一层递归的时候进行比较,同时这个参数也是要进行回溯的,当回溯的时候深度就要-1;终止条件:当前遍历的节点的左右节点都为空并且当前节点的值等于targetSum的值,则将该这条路径添加到res数组中。终止条件:当前遍历的节点的左右节点都为空并且节点的值等于targetSum的值则返回true;最后递归处理中序和后序的左右区间。

2024-06-24 21:29:09 259

原创 代码随想录训练营第十五天 110平衡二叉树 257二叉树的所有路径 404左子树之和 222完全二叉树的节点

现在要标记的是左右子树的差值是否大于1,那么如果当前传入节点为根节点的二叉树已经不是儿二叉平衡树的话,还返回高度的话就没有意义了,因此可以直接返回-1来标记该树已经不是平衡二叉树了。我们使用前序遍历的方式,那么当我们找到一个左叶子的时候,res加上该叶子的值即可。当当前节点的左右节点都为的空的情况下证明这是一条完整的路径了,可以直接添加“->”然后加入res中。首先我们要定义返回值和传入的参数,传入的参数就是当前传入节点,返回值是传入节点为根节点的树的高度。是指该树所有节点的左右子树的深度相差不超过 1。

2024-06-20 22:14:59 298

原创 代码随想录训练营第十四天 226翻转二叉树 101对称二叉树 104二叉树的最大深度 111二叉树的最小深度

其中需要注意的是在如果左子树为空,右子树不为空的情况下最小深度是1 + 右子树的深度,反之,右子树为空,左子树不为空的情况下返回的是1 + 左子树的深度。思路:使用后序遍历的方式,遍历顺序是左右中。一直遍历到底部,然后取左右子节点中较大的深度再加一返回给上层,最后传递到根节点的值就是最大深度。注意本题最小深度是从根节点到最近叶子节点的最短路劲上的节点数量,注意是叶子节点,什么是叶子节点,左右孩子都为空的节点才是叶子节点。递归法:使用中序遍历的操作,中左右,在遍历到中间节点的时候对它左右节点进行交换。

2024-06-19 22:55:49 249

原创 代码随想录训练营第十三天

因为在中序遍历中,遍历顺序是左中右,而且先访问的是二叉树的顶部的节点,然后一层一层向下访问,直到到达树左面的最底部,再开始处理节点,这样就造成了处理顺序和访问顺序的不一致。就是先定义一个栈,把二叉树的每一层的元素都放入栈中,然后对栈进行操作,把栈中的元素取出放入到结果数组中。前序遍历的话顺序是根左右,因此一来变先将节点的值添加进res数组中,然后先向左递归再向右递归,结果都存在res数组中。在将每一层的元素放入数组中的时候,一定要将size提前声明并赋值好,不然在操作的时候que.size()是会变化的。

2024-06-19 19:20:37 340

原创 代码随想录训练营第十二天

当i大于0的时候,当在que中的第一个元素等于i指向元素的前一位时,证明该元素要弹出了,窗口移动让该元素弹出队列。当que中的元素不为空的时候,如果que的尾元素小于要新添加进来的元素时,我们将这些元素都弹出,这样能保持que的递减。当我们遇到+ - * / 的时候就需要将栈中的最后两个元素取出来,然后进行对应的操作并将结果也放入栈中,如果是数字的话将字符转换为数字放入栈中。deque 内 仅包含窗口内的元素 ⇒ 每轮窗口滑动移除了元素 nums[i−1] ,需将 deque内的对应元素一起删除。

2024-06-18 12:35:08 254

原创 代码随想录训练营第九天232用栈实现队列 225用队列实现栈 20有效的括号 1047删除字符串中的所有相邻重复项

然后遍历整个字符串,如果是{ [ (这个三种括号的话就将它们插入st中,如果不是这三种括号的话则需要判断是什么类型的括号,首先要判断st是否为空,如果为空的话直接就返回false,然后看括号是否与栈顶的括号相匹配,如果是匹配的话则将栈顶的元素弹出,如果不匹配将该元素插入st中。使用两个栈来实现队列,一个栈A用来实现接收添加的元素,另外一个栈B用来记录栈订单元素来实现队列的peek操作,其中便是将A栈中的元素逆序存放在B栈中,A的栈顶元素就是B的栈底元素,A中的栈顶元素就是B中的栈底元素。

2024-06-16 16:35:55 318

原创 代码随想录训练营第八天 151反转字符串中的单词 右旋字符串

使用双指针,一根用来移动寻找每个单词的头,一根用于指向每个单词的末尾。然后将头指针和尾指针的字符添加到结果字符串中,其中头指针遇到空格时要跳过。先把首尾的空格去掉:找到第一个不是空格的字符,找到最后一个不是空格的字符。substr字符串为新的字符串t。将整个字符串反转,然后再对前n个反转和对n之后的字符反转。最后返回的时候最后一定会多一个空格,需要将空格去掉。

2024-06-14 20:49:41 148

原创 代码随想录训练营第七天 344反转字符串 541反转字符串II 替换数字

于是我们遍历的时候直接i += 2 * k。这样我们就直接指向要反转的第一个元素。然后判断i + k是否超过了边界,如果没有超过直接反转前k个元素即可,若超过了就反转剩下的元素。双指针,一根指向字符串的头部,一根指向字符串的尾部。两个指针向中间移动,交换两根指针指向的值。反转可以用reverse(s.begin() + i, s.begin() + i + k);先找出这个字符串中出现数字的个数,然后乘5,然后将字符串扩容。题目要求的是遍历到2k个字符然后反转2k字符的前k个字符。

2024-06-13 21:38:54 217

原创 代码随想录训练营第六天 454四数相加II 383赎金信 15三数之和 18四数之和

先判断我们当前遍历的位置的值是否大于0,如果大于0直接返回res,因为排过序后当前值大于0后面的值也大于0。接在在right > left的循环里判断三数之和是否大于0,大于0right--,如果小于0left++,如果等于0,将这三个值插入res中,然后判断left的值和left+1的值是否相同,相同也要跳过。首先对数组进行排序,这点很关键,可以剪枝。定义unordered_map map,将第一个和第二个数组中的元素相加并填入map中,记录相加之后元素的值对应出现的个数。

2024-06-12 22:42:47 470

原创 代码随想录训练营第五天 242有效的字母异位词 349两个数组的交集 202快乐数 1两数之和

遍历整个数组,当发现当前遍历的数值和target相减之后的值出现在map中,说明这两个数值的下标为返回结果,将两个数值的下标添加进vector<int> res中。= 1 && set.find(n) == set.end()),只有n不等于1才需要进行循环,等于1就直接返回true了,条件二只有set中没出现过n值,证明还没陷入死循环,接着执行循环中的内容。然后遍历第二个数组num2,当发现num2中出现的值在map中出现过,并且返回结果的数组res中没有这个值,就将这个值添加进res中,

2024-06-11 21:54:05 413

原创 代码随想录训练营第四天 24两两交换链表中的节点 19删除链表的倒数第n个节点 02链表相交 142环形链表

本题的思路就是用虚拟头节点指向第二个节点,然后再指向第一个节点,然后再指向第三个节点。本题的关键,要暂存几个节点:首先我们虚拟头结点指向第二个节点的时候,第一个节点就没人指向,所以需要暂存,当我们第二个节点指向第一个节点的时候,第三个节点也没人指向,也需要暂存。首先定义快慢指针都指向链表的头部,判断fast是否为空,并且fast->next是否为空,如果都不为空的话,快指针节点比慢指针节点多走一步,如果是有环的话快慢指针节点肯定会在环内相遇。此时从头节点和相遇节点以相同的步长遍历,相交的地方就是入环处。

2024-06-08 21:39:43 191

原创 代码随想录训练营第三天 203移除链表元素 707设计链表 206翻转链表

细节,我们在遍历的时候直接判断cur -> next 是否为空,不为空则判断cur -> next 的值是否为要移除的元素,是则cur -> next = cur -> next -> next;否则cur = cur -> next;首先定义一个虚拟头结点,然后让虚拟头节点指向head。这个虚拟头节点的next就是我们要返回的答案,因此我们不能用这个虚拟头节点直接去移动,需要在定义一个cur节点指向虚拟头节点。

2024-06-07 11:06:55 124

原创 代码随想录训练营第二天 977有序数组的平方 209长度最小的子数组 59螺旋矩阵II

取这个数组的中间值,然后以此为基准,判断这个基准的左边的元素是否小于基准值,右边的元素是否大于基准值,如果两边都为否,也就是说左边的值大于基准值,右边的值小于基准值,则交换两者的位置。当第一行的元素放入后,上边界++,当最后一列的元素放入后,右边界--,当最后一行的元素放入后,下边界--,当第一列元素放入后,左边界++;此时维护一个范围让这个区间的元素的总和一直大于target,慢指针指向这个区间的最左边,快指针指向区间的最右边。双指针:使用快慢指针,首先定义一个慢指针为0,定义快指针一直遍历整个数组。

2024-06-06 21:33:25 289

原创 代码随想录第一天 704二分查找 27移除元素

然后我们定义快指针fastIndex遍历整个数组,此时我们需要判断快指针是否跟要移除的元素相同,如果不相同则nums[slowIndex] = nums[fastIndex];原因二:当我们判断if(nums[mid] < target)时,我们需要更新左边界,此时需要将left = mid + 1;二分的逻辑也很简单,取中间位置的下标,判断下标处的值是否等于目标值,如果下标处的值小于target,则将左边界更新为mid + 1,反之右边界更新为mid + 1。这样理解可能会更好一些。

2024-06-05 21:02:51 416

原创 1V1音视频实时互动直播系统

如果是otherjoin,则判断自身的状态是否为joined_unbind,如果是则需要重新创建PC并绑定媒体流并将状态设置为joined_conn,如果一开始状态为joined则直接将状态转换为joined_conn,接着开始媒体协商。3.turn,stun是有一定几率是不成功的,因此turn会在云端架设一个服务器,在p2p连接不成功的情况下,保证音视频的互通,它就相当于一个中转站。2.说到这里那么顺便介绍一下stun,这个stun充当的是中介的作用,在NAT的基础上,交换两个公网的信息,使得;

2024-06-03 22:59:36 590

原创 PTS和DTS

如图所示我们播放一个画面是按照I帧,B帧,B帧,P帧这样播放的,但是我们在解码的时候并不是这样的,由于B帧特殊的性质,需要根据I帧和P帧才能进行预测显示,因此P帧应该提前解码。所以当播放画面是I帧,B帧,B帧,P帧时,解码顺序应该是I帧,P帧,B帧,B帧。P帧的解码时间戳(DTS)应该提前,因此PTS一定是大于等于DTS的。DTS(Decoding Time Stamp):即解码时间戳,这个时间戳的意义在于告诉播放器该在什么时候解码这一帧的数据。PTS的值一定都是大于等于DTS。下面通过例子进行解释。

2024-05-06 14:08:19 355

原创 connect_rtmp_server函数介绍

2.先设置RTMP服务地址,以及设置连接超时时间。3.设置推流还是拉流,通过一个开关进行设置。1.创建RTMP对象,并进行初始化。

2024-04-25 17:17:38 178

原创 open_flv函数的实现

这里提到的是flv header,一共占 9 个字节,我们并不需要这 9 个字节的数据,因此要跳过它。在这 9 个字节后面跟着是一个pre_tagsize,占 4 个字节,这 4 个字节我们也不需要,跳过。之前我们提到了在推流的时候第一步是打开读取一个flv文件,那么怎么打开呢,打开后要进行什么操作呢?之后我们会通过打开的这个flv文件fp进行数据的读取和转换,在之后章节会介绍。在打开之前我们要先了解flv文件是什么样的,可以去阅读我的其他文章。声明:本系列都是对李超老师课程的理解和笔记。

2024-04-25 17:04:30 120 1

原创 RTMP推流程序的框架

1.推流首先要要有流,从哪里获取流呢,那就是flv文件,读取flv文件中的tag data中的音频数据和视频数据封装成能够在rtmp协议中传输的rtmpPacket数据。3.将音频数据和视频数据封装好后发送,其中涉及到rtmpPacket内存空间的分配以及rtmpPacket内部变量内存的分配。2.要连接上服务器才能传输到服务器,因此该步骤是关键。有些较为细节的点之后再详细介绍。2.连接RTMPP服务器。

2024-04-25 16:55:41 156 1

原创 FLV协议分析

1.pre tagsize(4个字节)表示前面一个tag的大小,但是FLV中的表示和我们所习惯的有偏差(普通协议:尺寸在前,内容在后,但是RTMP,内容在前,尺寸在后)TT(Tag Type),DataSize(数据大小),TimeStamp(时间戳),E(扩展时间戳),SID(流 ID)变成flv文件,要在tag data前面加一个tag header,再加一个FLV Header 9个字节的文件头。之后是FLV Body,FLV body包含一个一个的pre tagsize , Tag。

2024-04-25 14:23:18 621 1

原创 RTMP Message格式介绍

对于消息流 ID 大于等于 64,但小于 320,基本头部占用 2 个字节,格式如下:第 1 位(Bit 0):格式类型(Fmt Type)。(3)Basic Header(基本头信息)是动态变化的,第一个字节由2部分组成,第一部分fmt(占2位),第2部分,表示chunk stream id(6位,能表示0-63,其中0和1由特殊意义)message header 是可选的,由fmt控制,fmt=10b(只有时间戳),fmt=01b(只有前3个),fmt=00b(有全部),fmt=11b(全不要)

2024-04-25 11:06:42 344 1

原创 RTMP协议

完成连接后创建rtmp流。客户端向服务器端发送publish命令,服务器端接收到后做出response。紧接着客户端向服务器端发送metaData数据,这个metaData包含的是音视频的一些基本数据,对于视频的来说就是帧率,宽高,分辨率等,对于音频来说是就一些采样率,采样格式,通道数等等信息。什么是rtmp,是在tcp之上的协议,也就是应用层的协议。下图为rtmp握手的过程:首先客户端先给服务器端发送C0+C1,服务器端接收到后向客户端发送S0+S1+S2,客户端接收到后再次向服务器端发送C2。

2024-04-25 10:26:26 540 1

原创 TS协议解析

之前介绍的m3u8文件中就是包含着一个一个小的ts文件,那么ts文件是什么呢?

2024-04-24 10:16:19 355

原创 m3u8协议

6. #EXT-X-PLAYLIST-TYPE :提供关于 Playlist 的可变性的信息,这个对整个 Playlist 文件有效, 是可选的,格式如下: #EXT-X-PLAYLIST-TYPE: VOD,即为点播视频,服务器不能改变 Playlist ⽂件,换句话说就是该视频全部的 ts ⽂件已经被生成好了EVENT,就是实时⽣成 m3u8 和 ts 文件。顶级m3u8文件主要是做码率适配的,二级m3u8才是真正的切片文件,客户端会默认选择码率最高的请求,如果发现码率达不到,会请求降低码率的刘。

2024-04-23 15:10:25 312

原创 HLS流媒体框架

这个索引⽂件可以看作是⼀个连续媒体流中的播放列表滑动窗口,每当流分割器生成⼀个新的TS文件时,这个索引文件的内容也被更新,新的文件URI(统⼀资源定位符)加⼊到滑动窗口的末尾,老的文件URI则被移去,这样索引文件中将始终包含最新的固定数量的x个分段。也就是说只能维持固定数量的ts文件。为此,TS⽂件中必须仅包含⼀个MPEG-2节⽬,在每个⽂件的开头应包含⼀个节⽬关联表(PAT)和⼀个节目映射表(PMT),包含视频的⽂件中还必须含有⾄少⼀个关键帧和其他足够信息(如序列头)⽤以完成解码器的初始化。

2024-04-23 14:11:46 306

原创 搭建HLS流媒体服务器

尤其是针对移动端,HLS是移动端实时视频流传输的首选。结果:nowcoder 2993 1 0 14:49 pts/0 00:00:00 ./objs/srs -c conf/srs.conf。HLS流地址为:http://192.168.72.132/live/livestream.m3u8。RTMP流地址为: rtmp://192.168.72.132/live/livestream。第三步编写SRS配置文件,编辑conf/srs.conf,服务器启动的时候要指定该配置文件。

2024-04-23 10:41:10 499 1

原创 设计一个属于自己的播放器5

之前我们讲到在read_thread线程有一个关键函数stream_component_open函数,下面对此函数进行讲解。如果解码器上下文中的codec_type类型是音频的,则进行音频设备的初始化并初始化音频解码线程并打开。如果是视频的则初始化视频解码线程并打开,为什么不初始化视频输出设备因为之前已经初始化过了。对应的有一个stream_component_close函数。将码流中的信息拷贝到分配的上下文中,首先分配解码器上下文,1.打开对应的解码器并做初始化。3.初始化音频或者视频输出设备。

2024-04-21 17:24:16 121 2

原创 设计属于自己的播放器4

这个是播放器的框架图,我们可以看到读取数据模块也就是最左边那一部分,里面包含的就是两个最为关键的函数也就是之后要重点讲的内容,stream_open和read_thread。ffp_prepare_async_l函数中调用的函数stream_open就是本节介绍的重点。在FFPlayer类中的关键API就是ffp_prepare_async_l函数。4.stream_compoment_open,(关键,之后会讲)stream_open对应会有stream_close。FFplayer成员变量。

2024-04-21 17:03:35 209 1

原创 设计一个属于自己的播放器3

在之后讲到的FFPlayer类中会有一个read_thread线程,用来解复用分析完码流情况,初始化对应的解码器,音视频输出,先调用toggle_pause设置为暂停播放的状态,然后发送FFP_MSG_PREPARED。1.状态设置为MP_STATE_ASYNC_PREPARING(正在准备中),那么什么时候状态会转化为MP_STATE_PREPARED(已经准备完成)在IjkMediaPlayer类中收到FFP_MSG_PREPARED这个消息后,会把状态转化为MP_STATE_PREPARED。

2024-04-21 15:25:37 1049 1

原创 设计属于自己的播放器2

例如,当播放器核心模块准备好播放准备时,会发送消息给消息队列,将消息存放在消息队列中,然后IjkMediaPlayer中间层会读取到该消息进行相应的操作,UI界面层也会读取到该消息(取决于IjkMediaPlayer层是否将消息传出给UI层)进行对应的操作。有两根指针分别指向消息队列的头和尾,当消息从消息队列中取出来后有recycle_msg回收消息,recycle_msg指向要回收的消息。在有消息要放入队列的时候,先从recycle_msg中查看是否有消息,如果有直接使用,如果没有则在分配一个消息对象。

2024-04-20 20:56:18 216 2

原创 设计一个属于自己的播放器1

改图为框架的时序图,其主要的流程都包含在其中,首先用户通过点击播放按钮(在UI界面中的CtrlBar上),该按钮会触发on_playOrPauseBtn_clicked()函数,发送SigPlayOrPause信号给MainWindow进行一些初始化设置,例如创建IjkMediaPlayer通道,设置url以及准备播放的工作;UI界面使用Qt进行设计,包含了控制条,播放列表以及播放文件名。实现一些基础的播放设置,例如:播放按钮,停止,快进,快退,前一,后一,一倍速,截屏,设置音量等功能;

2024-04-20 17:19:42 331 2

原创 AVIO内存输入模式

零声教育学习记录

2024-03-07 15:13:17 357 1

空空如也

空空如也

TA创建的收藏夹 TA关注的收藏夹

TA关注的人

提示
确定要删除当前文章?
取消 删除