WebRTC源码线程-1

news2025/6/8 6:26:03

1、概述

本篇主要是简单介绍WebRTC中的线程,WebRTC源码对线程做了很多的封装。

1.1 WebRTC中线程的种类

1.1.1 信令线程

用于与应用层的交互,比如创建offer,answer,candidate等绝大多数的操作

1.1.2 工作线程

负责内部的处理逻辑,比如音视频编解码、采集、渲染这些操作,平滑处理,质量监测

1.1.3 网络线程

负责网络数据包的转发,工作线程对音视频数据进行编码后,发送编码后的音视频数据到网络。

从网络中接收音视频数据包,然后交给工作线程进行解码,丢包处理等操作

1.2 peerconnection_client

peerconnection_client一共创建了5个线程,分别为

主线程:windows中main函数的,处理窗口消息的线程

与信令服务器连接处理的线程:PhysicalSocketServer关联

信令线程:PhysicalSocketServer关联

工作线程:NullSocketServer关联

网络线程:PhysicalSocketServer关联

1.3 线程类关系图

1.4 线程类

class RTC_LOCKABLE RTC_EXPORT Thread : public TaskQueueBase {
 public:
  explicit Thread(SocketServer* ss);
  SocketServer* socketserver();
  bool Start();
  virtual void Stop();
  virtual void Run();
  bool ProcessMessages(int cms);

 protected:
  void PostTaskImpl(absl::AnyInvocable<void() &&> task,
                    const PostTaskTraits& traits,
                    const Location& location) override;

 private:
  absl::AnyInvocable<void() &&> Get(int cmsWait);
  void Dispatch(absl::AnyInvocable<void() &&> task);


#if defined(WEBRTC_WIN)
  static DWORD WINAPI PreRun(LPVOID context);
#else
  static void* PreRun(void* pv);
#endif

  std::queue<absl::AnyInvocable<void() &&>> messages_ RTC_GUARDED_BY(mutex_);
  std::priority_queue<DelayedMessage> delayed_messages_ RTC_GUARDED_BY(mutex_);
  SocketServer* const ss_;
#if defined(WEBRTC_POSIX)
  pthread_t thread_ = 0;
#endif
#if defined(WEBRTC_WIN)
  HANDLE thread_ = nullptr;
  DWORD thread_id_ = 0;
#endif
};
  • 成员变量 thread_ 在不同平台有不同的实现,win下采用线程内核对象创建,linux下采用pthread创建
  • 成员变量 messages_ 相当于里面保存的是函数对象,只不过用absl库,我们可以把它当做是std::function函数对象
  • 线程之间通信,通过PostTask函数进行,相当于线程1需要执行的任务放入线程2的queue,然后线程2不断从queue读取任务执行,这样来进行通信

1.5 线程管理类 

class RTC_EXPORT ThreadManager {
 public:

  static ThreadManager* Instance();

  static void Add(Thread* message_queue);
  static void Remove(Thread* message_queue);
  
  Thread* CurrentThread();
  void SetCurrentThread(Thread* thread);

private:
  // This list contains all live Threads.
  std::vector<Thread*> message_queues_ RTC_GUARDED_BY(crit_);


#if defined(WEBRTC_POSIX)
  pthread_key_t key_;
#endif

#if defined(WEBRTC_WIN)
  const DWORD key_;
#endif
};

线程管理类ThreadManager用到一个技术点是线程本地存储(TLS),需要理解这个技术点,否则比较难读懂WebRTC源码中线程这块的代码。

1.5.1 线程本地化存储(TLS)

#include <windows.h>
#include <stdio.h>

// 全局 TLS 索引
DWORD tlsIndex;

// 线程函数
DWORD WINAPI ThreadFunction(LPVOID lpParam) {
    int threadNum = *(int*)lpParam;
    char buffer[256];
    
    // 为当前线程设置 TLS 值
    sprintf_s(buffer, "线程 %d 的私有数据", threadNum);
    TlsSetValue(tlsIndex, strdup(buffer));  // 注意:使用 strdup 分配内存
    
    // 获取并打印当前线程ID和TLS值
    DWORD threadId = GetCurrentThreadId();
    char* data = (char*)TlsGetValue(tlsIndex);
    printf("线程 ID=%lu, 编号=%d, TLS 数据: %s\n", threadId, threadNum, data);
    
    // 清理分配的内存
    free(data);
    return 0;
}

int main() {
    // 分配 TLS 索引
    tlsIndex = TlsAlloc();
    if (tlsIndex == TLS_OUT_OF_INDEXES) {
        printf("TlsAlloc 失败,错误码: %d\n", GetLastError());
        return 1;
    }
    
    // 在主线程中设置并获取 TLS 值
    char mainBuffer[256];
    sprintf_s(mainBuffer, "主线程的私有数据");
    TlsSetValue(tlsIndex, strdup(mainBuffer));
    
    // 打印主线程ID和TLS值
    DWORD mainThreadId = GetCurrentThreadId();
    char* mainData = (char*)TlsGetValue(tlsIndex);
    printf("主线程 ID=%lu, TLS 数据: %s\n", mainThreadId, mainData);
    
    // 创建两个线程
    int thread1Num = 1;
    int thread2Num = 2;
    HANDLE hThread1 = CreateThread(NULL, 0, ThreadFunction, &thread1Num, 0, NULL);
    HANDLE hThread2 = CreateThread(NULL, 0, ThreadFunction, &thread2Num, 0, NULL);
    
    // 等待线程结束
    WaitForSingleObject(hThread1, INFINITE);
    WaitForSingleObject(hThread2, INFINITE);
    
    // 关闭线程句柄
    CloseHandle(hThread1);
    CloseHandle(hThread2);
    
    // 清理主线程分配的内存
    free(TlsGetValue(tlsIndex));
    
    // 释放 TLS 索引
    TlsFree(tlsIndex);
    
    return 0;
}

在每个线程中保存的value不一样,每个线程取出来的value就是不一样,通俗地说,假设我们有3个线程,分别为Thread1、Thread2、Thread3, 分别保存value为1、2、3,那么如果当前如果在Thread2运行的代码里面打印value,那么打印的就是2。通过这样的原理,假如当前是信令线程,通过ThreadManager的函数CurrentThread那么返回的就是信令线程,如果需要在网络线程中运行,则需要利用PostTask放入到网络线程中使用,我们可以看到WebRTC源码很多都是用这个来进行判断。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2403816.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

MySQL中的内置函数

文章目录 一、日期函数1.1 获取当前的日期1.2 获取当前时间1.3 获取当前日期和时间1.4 提取时间日期1.5 添加日期1.6 减少日期1.7 两个日期的差值 二、字符串处理函数2.1 获取字符串的长度2.2 获取字符串的字节数2.3 字符串拼接2.4 转小写2.5 转大写2.6 子字符串第⼀次出现的索…

YOLOv8n行人检测实战:从数据集准备到模型训练

YOLOv8n行人检测实战&#xff1a;从数据集准备到模型训练 一、为什么选择YOLOv8&#xff1f;二、环境准备2.1 环境配置解析 三、安装Ultralytics框架四、数据集准备与理解4.1 数据集下载4.2 数据集结构4.3 YOLO标签格式解析 五、数据集可视化&#xff1a;理解标注数据5.1 可视化…

国标GB28181设备管理软件EasyGBS远程视频监控方案助力高效安全运营

一、方案背景​ 在商业快速扩张的背景下&#xff0c;连锁店门店数量激增&#xff0c;分布范围广。但传统人工巡检、电话汇报等管理方式效率低下&#xff0c;存在信息滞后、管理盲区&#xff0c;难以掌握店铺运营情况&#xff0c;影响企业效率与安全。网络远程视频监控系统可有…

网络寻路--图论

所以我们固定题中M条边&#xff08;因为这M条一定联通&#xff09; P8605 [蓝桥杯 2013 国 AC] 网络寻路 - 洛谷 #include<bits/stdc.h> using namespace std; #define N 100011 typedef long long ll; typedef pair<int,int> pii; int n,m; int d[N],u[N],v[N]…

LangChain4j 学习教程项目

LangChain4j 学习教程 项目地址项目简介主要功能使用的技术和库项目环境配置环境要求 依赖版本每天学习内容和目标Day 01Day 02Day 03Day 04Day 05Day 06Day 07Day 08Day 09Day 10Day 11Day 12重点学习内容 RAG 经过为期12天&#xff08;日均1小时&#xff09;的LangChain4j源码…

【读论文】U-Net: Convolutional Networks for Biomedical Image Segmentation 卷积神经网络

摘要1 Introduction2 Network Architecture3 Training3.1 Data Augmentation 4 Experiments5 Conclusion背景知识卷积激活函数池化上采样、上池化、反卷积softmax 归一化函数交叉熵损失 Olaf Ronneberger, Philipp Fischer, Thomas Brox Paper&#xff1a;https://arxiv.org/ab…

Linux 文件系统与 I/O 编程核心原理及实践笔记

文章目录 一、理解文件1.1 狭义理解1.2 广义理解1.3 文件操作的归类认识1.4 系统角度&#xff1a;进程与文件的交互1.5 实践示例 二、回顾 C 文件接口2.1 hello.c 打开文件2.2 hello.c 写文件2.3 hello.c 读文件2.4 输出信息到显示器的几种方法2.5 stdin & stdout & st…

vite+tailwind封装组件库

前言 演示视频 https://www.bilibili.com/video/BV1EST3zPEyP/?spm_id_from333.1387.homepage.video_card.click 参考 https://juejin.cn/post/7112295067682865166 https://juejin.cn/post/7046187185615142949 代码仓库 https://gitee.com/malguy/vite-components-li…

【Java学习笔记】包装类

包装类&#xff08;Wrapper&#xff09; 1. 介绍 &#xff08;1&#xff09;针对八种基本数据类型相应的引用类型 --> 包装类 &#xff08;2&#xff09;有了类的特点&#xff0c;就可以调用类中的方法 2. 分类和继承关系 基本数据类型包装类父类booleanBooleanObjectc…

【高效开发工具系列】Blackmagic Disk Speed Test for Mac:专业硬盘测速工具

博客目录 一、Blackmagic Disk Speed Test 概述二、软件核心功能解析三、v3.3 版本的新特性与改进四、实际应用场景分析五、使用技巧与最佳实践六、与其他工具的比较及优势 一、Blackmagic Disk Speed Test 概述 Blackmagic Disk Speed Test 是 Mac 平台上广受专业人士青睐的一…

UniRig:如何在矩池云一站式解决 3D 模型绑定难题

在 3D 动画制作中&#xff0c;绑定&#xff08;Rigging&#xff09;是一个至关重要但复杂耗时的步骤。它包括为 3D 模型创建骨架并分配蒙皮权重&#xff0c;以实现流畅的动画效果。由清华大学与 Tripo 联合开发的 UniRig 框架&#xff0c;为这一难题提供了全新的解决方案。 什…

字符串字典序最大后缀问题详解

字符串字典序最大后缀问题详解 一、问题定义与背景1.1 问题描述1.2 实际应用场景 二、暴力解法及其局限性2.1 暴力解法思路2.2 代码示例2.3 局限性分析 三、双指针算法&#xff1a;高效解决方案3.1 算法核心思想3.2 算法步骤3.3 代码实现3.4 与暴力解法对比 四、复杂度分析4.1 …

VScode打开后一直显示正在重新激活终端 问题的解决方法

一、问题 本人打开“.py”文件后&#xff0c;同时会出现以下两个问题。 1、VScode一直循环在”正在重新激活终端“ 2、日志显示intellicode报错&#xff1a; Sorry, something went wrong activating IntelliCode support for Python. Please check the “Python” and “VS I…

pe文件结构(TLS)

TLS 什么是TLS? TLS是 Thread Local Storage 的缩写&#xff0c;线程局部存储。主要是为了解决多线程中变量同步的问题 如果需要要一个线程内部的各个函数调用都能访问&#xff0c;但其它线程不能访问的变量&#xff08;被称为static memory local to a thread 线程局部静态变…

中型零售业数据库抉择:MySQL省成本,SQL SERVER?

针对中型零售企业&#xff08;20台固定POS数十台移动POS&#xff0c;含库存管理与结算业务&#xff09;的操作系统与数据库选型&#xff0c;需平衡性能、成本、扩展性及运维效率。结合行业实践与系统需求&#xff0c;建议如下&#xff1a; &#x1f5a5;️ ​​一、操作系统选型…

IDEA中的debug使用技巧

详细教学视频见b站链接&#xff1a;IDEA的debug调试 CSDN详细博客文章链接&#xff1a;debug文章学习 以下为个人学习记录总结&#xff1a; idea中的debug模式界面如下&#xff1a; 现在详细介绍图标作用&#xff1a; 图标一&#xff08;Show Execution Point&#xff09;&…

RockyLinux9.6搭建k8s集群

博主介绍&#xff1a;✌全网粉丝5W&#xff0c;全栈开发工程师&#xff0c;从事多年软件开发&#xff0c;在大厂呆过。持有软件中级、六级等证书。可提供微服务项目搭建与毕业项目实战&#xff0c;博主也曾写过优秀论文&#xff0c;查重率极低&#xff0c;在这方面有丰富的经验…

AI IDE 正式上线!通义灵码开箱即用

近期&#xff0c;通义灵码AI IDE正式上线&#xff0c;即日起用户可在通义灵码官网免费下载开箱即用。 作为AI原生的开发环境工具&#xff0c;通义灵码AI IDE深度适配了最新的千问3大模型&#xff0c;并全面集成通义灵码插件能力&#xff0c;具备编程智能体、行间建议预测、行间…

Ubuntu20.04基础配置安装——系统安装(一)

引言&#xff1a; 工作需要&#xff0c;Ubuntu的各类环境配置&#xff0c;从23年开始使用Ubuntu20.04之后&#xff0c;尽管能力在不断提升&#xff0c;但是依旧会遇到Ubuntu系统崩掉的情况&#xff0c;为了方便后续系统出现问题及时替换&#xff0c;减少从网上搜索资源进行基础…

Kafka入门-消费者

消费者 Kafka消费方式&#xff1a;采用pull&#xff08;拉&#xff09;的方式&#xff0c;消费者从broker中主动拉去数据。使用pull的好处就是消费者可以根据自身需求&#xff0c;进行拉取数据&#xff0c;但是坏处就是如果Kafka没有数据&#xff0c;那么消费者可能会陷入循环…