webrtc中的线程(一) rtc::Thread


WebRtc中的线程设计非常具有参考价值,通过学习它们的实现,可以对线程的理解更上一个台阶。
在WebRtc并不是简单的对os 线程相关的API进行封装,而是结合功能实现需求对线程进行了设计。
在webrtc有两种线程对象:

  1. rtc::Thread 对象

rtc::Thread是webrtc中最重要的线程类型。它与WebRtc库的实现深度结合。

  1. rtc::ProcessThread 对象

rtc::ProcessThread线程类型,主要是用作执行一些定时任务。

这篇文章将介绍rtc::Thread及它在WebRtc中的使用

rtc:Thread

线程模型

rtc::Thread的线程模型如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-GZPu3OiZ-1678665809251)(https://note.youdao.com/yws/api/personal/file/WEBff381d87c74c6937c35f05c025579f26?method=download&shareKey=d2fd984d0ab7f17fd5395027c1aa3fab#clientId=ua4f980d8-c6d9-4&id=nodDw&originHeight=1190&originWidth=1574&originalType=binary&ratio=1&rotation=0&showTitle=false&status=done&style=none&taskId=u1c3d1033-3e4f-4638-8ea8-2f6a65535ea&title=)]
如上图所示,rtc::Thread不仅仅是只产生一个线程,它还包含一个队列**(message list)**,将它称为异步任务队列更适合。

它的基本功能就是在线程中执行任务队列中的任务。

它靠事件驱动,也就是说当message list中没有任务(message)时,它会阻塞在事件等待上,当有事件唤醒时后会继续在队列中去任务执行。

主要成员及方法

类图

类图中列出了rtc::Thread的核心类及方法。
rtc_thread_1.png

Thread类继承自TaskQueueBase,从语意就表明了它是一个任务队列。

核心成员变量:
  • MessageList messages_

就是任务队列,它是一个std::list,定义如下:
typedef std::list<Message> MessageListMessage类就任务的抽象。

  • PriorityQueue delayed_message_

延迟任务队列,是一个优先队列。

  • SocketServer* const ss_

事件驱动器,从名字上就可以看出它可以处理网络IO事件。

核心方法:

它的核心方法就是ProcessMessageGet方法。

  • ProcessMessage是线程的执行体,是一个while(true)循环,它不断的从Get中取出任务然后执行,方法框架如下:
bool Thread::ProcessMessages(int cmsLoop) {
   
   
	while (true) {
   
   
        Message msg;
        //取出任务
        Get(&msg, cmsNext);
        ...
        //执行任务
        Dispatch(&msg);
    }
}
  • Get方法,首先取出队列中的任务,如果没有任务则处理事件,如果没有事件则阻塞到Wait方法上。
bool Thread::Get(Message* pmsg, int cmsWait, bool process_io) {
   
   
    //取出队列中的任务
	while(true) {
   
   
        ...
        if (messages_.empty()) {
   
   
          break;
        } else {
   
   
          *pmsg = messages_.front();
          messages_.pop_front();
        }
        ...
    	return true;
    }

    ...
    
	//如果没有任务则执行事件,如何也没有事件就阻塞在Wait方法上
    {
   
   
      // Wait and multiplex in the meantime
      if (!ss_->Wait(static_cast<int>(cmsNext), process_io))
        return false;
    }
}
控制类方法

bool Start()
void Stop()
void Run()
这三个是典型的线程控制方法。

任务类方法
异步方法

它是异步队列,有post系列方法,用于将任务投递到线程中执行,这些post方法都是异步方法,马上返回。

  • 放入一个QueuedTask类型的任务。QueuedTask方法内部被封装成了Message类型。
void PostTask(std::unique_ptr<webrtc::QueuedTask> task) override;
  • 放入一个QueuedTask类型的任务,在delay ms后执行。
void PostDelayedTask(std::unique_ptr<webrtc
#include <api/create_peerconnection_factory.h> #include <api/video/video_source_interface.h> #include <modules/video_capture/video_capture_factory.h> #include <rtc_base/ssl_adapter.h> // 自定义观察者类 (核心回调处理) class PeerConnectionObserver : public webrtc::PeerConnectionObserver { public: // ICE Candidate生成回调 void OnIceCandidate(const webrtc::IceCandidateInterface* candidate) override { // 将candidate转为字符串并发送给SFU服务器 std::string sdp; candidate->ToString(&sdp); SendSignalToServer("candidate", sdp); // [^1] } // 本地SDP设置成功回调 void OnSignalingChange(webrtc::PeerConnectionInterface::SignalingState state) override { if (state == webrtc::PeerConnectionInterface::kHaveLocalOffer) { // 发送Offer到服务器 auto local_desc = peer_connection_->local_description(); SendSignalToServer("offer", local_desc->sdp()); } } }; // 视频渲染器实现本地预览 class VideoRenderer : public rtc::VideoSinkInterface<webrtc::VideoFrame> { public: void OnFrame(const webrtc::VideoFrame& frame) override { // 实现帧渲染逻辑 (如OpenGL/Vulkan/DirectX) RenderFrame(frame); // 本地窗口预览 [^1] } }; int main() { // === 1. 初始化WebRTC核心环境 === rtc::InitializeSSL(); // 初始化SSL rtc::ThreadManager::Instance()->WrapCurrentThread(); // 创建网络线程/工作线程/信令线程 auto network_thread = rtc::Thread::CreateWithSocketServer(); auto worker_thread = rtc::Thread::Create(); auto signaling_thread = rtc::Thread::Create(); network_thread->Start(); worker_thread->Start(); signaling_thread->Start(); // === 2. 创建PeerConnection工厂 === auto factory = webrtc::CreatePeerConnectionFactory( network_thread.get(), worker_thread.get(), signaling_thread.get(), nullptr, // 默认音频设备 webrtc::CreateBuiltinAudioEncoderFactory(), webrtc::CreateBuiltinAudioDecoderFactory(), webrtc::CreateBuiltinVideoEncoderFactory(), webrtc::CreateBuiltinVideoDecoderFactory(), nullptr, // 音频混合器 nullptr // 音频处理 ); // === 3. 采集音视频流 === // 视频采集 auto device_info = webrtc::VideoCaptureFactory::CreateDeviceInfo(); auto video_device = device_info->GetDeviceName(0); // 获取第个摄像头 auto video_capturer = webrtc::VideoCaptureFactory::Create(video_device); rtc::scoped_refptr<webrtc::VideoTrackSourceInterface> video_source( factory->CreateVideoSource(std::move(video_capturer), nullptr)); // 创建视频轨道 (添加本地渲染器) auto video_track = factory->CreateVideoTrack("camera", video_source); VideoRenderer local_renderer; video_track->AddOrUpdateSink(&local_renderer, rtc::VideoSinkWants()); // [^1] // 创建音频轨道 auto audio_track = factory->CreateAudioTrack("mic", factory->CreateAudioSource(cricket::AudioOptions())); // === 4. 创建PeerConnection === webrtc::PeerConnectionInterface::RTCConfiguration config; config.sdp_semantics = webrtc::SdpSemantics::kUnifiedPlan; // 添加TURN服务器配置 (连接SRS等SFU) webrtc::PeerConnectionInterface::IceServer turn_server; turn_server.urls = {"turn:your_sfu_ip:3478"}; turn_server.username = "user"; turn_server.password = "pass"; config.servers.push_back(turn_server); PeerConnectionObserver observer; auto peer_connection = factory->CreatePeerConnection(config, nullptr, nullptr, &observer); observer.SetPeerConnection(peer_connection); // === 5. 添加媒体流 === auto stream = factory->CreateLocalMediaStream("local_stream"); stream->AddTrack(video_track); stream->AddTrack(audio_track); peer_connection->AddTrack(video_track, {stream->id()}); peer_connection->AddTrack(audio_track, {stream->id()}); // === 6. 创建Offer并启动推流 === webrtc::PeerConnectionInterface::RTCOfferAnswerOptions options; options.offer_to_receive_video = false; // 纯推流模式 peer_connection->CreateOffer( CreateSessionDescriptionObserver::Create(), // 需实现该观察者 options ); // === 7. 事件循环 (处理信令和ICE) === while (true) { // 接收并处理服务器返回的Answer if (received_answer) { webrtc::SdpParseError error; auto answer = webrtc::CreateSessionDescription( webrtc::SdpType::kAnswer, answer_sdp, &error ); peer_connection->SetRemoteDescription(SetRemoteDescriptionObserver::Create(), answer); } // 处理ICE Candidate if (received_candidate) { webrtc::SdpParseError error; auto candidate = webrtc::CreateIceCandidate( candidate_sdp_mid, candidate_sdp_mline_index, candidate_sdp, &error ); peer_connection->AddIceCandidate(candidate); } rtc::Thread::Current()->ProcessMessages(10); // 消息处理间隔 } // === 清理 === peer_connection->Close(); rtc::CleanupSSL(); } 写出这个编译的makefile
最新发布
09-07
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

mo4776

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值