WebRTC中线程模型和常见线程模型介绍

WebRTC线程模型、常见线程模型

Posted by chensong on 2021-12-11 18::43::01

WebRTC中线程模型和常见线程模型介绍

WebRTC专题开嗨鸭 !!!

一、 WebRTC 线程模型

1、WebRTC中线程模型和常见线程模型介绍

2、WebRTC网络PhysicalSocketServer之WSAEventselect模型使用

二、 WebRTC媒体协商

1、WebRTC媒体协商之SDP中JsepSessionDescription类结构分析

三、 WebRTC 音频数据采集

1、WebRTC源码之音频设备播放流程源码分析

2、WebRTC源码之音频设备的录制流程源码分析

四、 WebRTC 音频引擎(编解码和3A算法)

五、 WebRTC 视频数据采集

六、 WebRTC 视频引擎( 编解码)

七、 WebRTC 网络传输

1、WebRTC的ICE之STUN协议

2、WebRTC的ICE之Dtls/SSL/TLSv1.x协议详解

八、 WebRTC服务质量(Qos)

1、WebRTC中RTCP协议详解

2、WebRTC中RTP协议详解

3、WebRTC之NACK、RTX 在什么时机判断丢包发送NACK请求和RTX丢包重传

4、WebRTC源码之视频质量统计数据的数据结构分析

九、 NetEQ

十、 Simulcast与SVC

@TOC

</font>

<hr style=” border:solid; width:100px; height:1px;” color=#000000 size=1”>

前言

<font color=#999AAA >WebRTC是音视频行业的标杆, 如果要学习音视频, WebRTC是进入音视频行业最好方法, 里面可以有成熟方案, 例如:音频中3A 算法、网络评估、自适应码流、SVC等等 , 非常适和刚刚进入音视频行业小伙伴, 以后再音视频行业长期打算的小伙伴的学习项目。 里面有大量知识点 , 小伙伴们加油吧!!! 奔跑起来吧 ^_^ </font>

<hr style=” border:solid; width:100px; height:1px;” color=#000000 size=1”>

<font color=#999AAA >提示:以下是本篇文章正文内容,下面案例可供参考

一、WebRTC线程模式和常见线程模式

1、WebRTC线程模式

在这里插入图片描述

上图就是WebRTC中三大线程模式: 分别是网络线程工作线程信号线程

webrtc -> api

webrtc ->proxy

webrtc -> core

WebRTC中线程模型与对外接口非常有关系, 是封装SDK非常好的方法。 无论用户多少个线程访问最后都不会有线程安全的问题,这个与WebRTC架构有关系的WebRTC中写一个代理类

2、常见线程模型

在这里插入图片描述

常见线程模型就是任务队列中有任务就分配空闲线程去执行。

二、WebRTC线程模型源码走读

1、 Thread

rtc_base/thread.h

①、 任务放到队列中函数Post

是把任务放到任务队列中msgq_

<font color=#999AAA >代码如下(示例):

void MessageQueue::Post(const Location& posted_from,
                        MessageHandler* phandler,
                        uint32_t id,
                        MessageData* pdata,
                        bool time_sensitive) {
  if (IsQuitting()) {
    delete pdata;
    return;
  }

  // Keep thread safe
  // Add the message to the end of the queue
  // Signal for the multiplexer to return

  {
    CritScope cs(&crit_);
    Message msg;
    msg.posted_from = posted_from;
    msg.phandler = phandler;
    msg.message_id = id;
    msg.pdata = pdata;
    if (time_sensitive) {
      msg.ts_sensitive = TimeMillis() + kMaxMsgLatency;
    }
    msgq_.push_back(msg);
  }
  WakeUpSocketServer();
}

②、 执行任务接口 Dispatch

<font color=#999AAA >代码如下(示例):


bool Thread::ProcessMessages(int cmsLoop) {
  // Using ProcessMessages with a custom clock for testing and a time greater
  // than 0 doesn't work, since it's not guaranteed to advance the custom
  // clock's time, and may get stuck in an infinite loop.
  RTC_DCHECK(GetClockForTesting() == nullptr || cmsLoop == 0 ||
             cmsLoop == kForever);
  int64_t msEnd = (kForever == cmsLoop) ? 0 : TimeAfter(cmsLoop);
  int cmsNext = cmsLoop;

  while (true) {
#if defined(WEBRTC_MAC)
    ScopedAutoReleasePool pool;
#endif
    Message msg;
    if (!Get(&msg, cmsNext))
      return !IsQuitting();
    Dispatch(&msg);

    if (cmsLoop != kForever) {
      cmsNext = static_cast<int>(TimeUntil(msEnd));
      if (cmsNext < 0)
        return true;
    }
  }
}


void MessageQueue::Dispatch(Message* pmsg) {
  TRACE_EVENT2("webrtc", "MessageQueue::Dispatch", "src_file_and_line",
               pmsg->posted_from.file_and_line(), "src_func",
               pmsg->posted_from.function_name());
  int64_t start_time = TimeMillis();
  pmsg->phandler->OnMessage(pmsg);
  int64_t end_time = TimeMillis();
  int64_t diff = TimeDiff(end_time, start_time);
  // 每个函数进行数据统计  那个函数执行时间比较长
  if (diff >= kSlowDispatchLoggingThreshold) {
    RTC_LOG(LS_INFO) << "Message took " << diff
                     << "ms to dispatch. Posted from: "
                     << pmsg->posted_from.ToString();
  }
}

2、 WebRTC中线程切换 (SynchronousMethodCall)

①、使用信号量通知的

<font color=#999AAA >代码如下(示例):

class SynchronousMethodCall : public rtc::MessageData,
                              public rtc::MessageHandler {
 public:
  explicit SynchronousMethodCall(rtc::MessageHandler* proxy);
  ~SynchronousMethodCall() override;

  void Invoke(const rtc::Location& posted_from, rtc::Thread* t);

 private:
  void OnMessage(rtc::Message*) override;

  rtc::Event e_;
  rtc::MessageHandler* proxy_;
};



SynchronousMethodCall::SynchronousMethodCall(rtc::MessageHandler* proxy)
    : proxy_(proxy) {}

SynchronousMethodCall::~SynchronousMethodCall() = default;

void SynchronousMethodCall::Invoke(const rtc::Location& posted_from,
                                   rtc::Thread* t) {
  // 判断是否当前线程如果是当前线程就立即执行,如果不是就把任务放到任务队列中去然后唤醒线程,当前线程wait中
  if (t->IsCurrent()) {
    proxy_->OnMessage(nullptr);
  } else {
  	
    t->Post(posted_from, this, 0);
    e_.Wait(rtc::Event::kForever);
  }
}

void SynchronousMethodCall::OnMessage(rtc::Message*) {
  //执行任务
  proxy_->OnMessage(nullptr);
  //任务执行完成, 就唤醒线程 获取结果
  e_.Set();
}

②、 WebRTC中线程同步绑定函数 MethodCall0

//C++中模版迟绑定多个参数的模版参数   非常有意思
template <typename R>
class ReturnType {
 public:
  template <typename C, typename M>
  void Invoke(C* c, M m) {
    r_ = (c->*m)();
  }
  template <typename C, typename M, typename T1>
  void Invoke(C* c, M m, T1 a1) {
    r_ = (c->*m)(std::move(a1));
  }
  template <typename C, typename M, typename T1, typename T2>
  void Invoke(C* c, M m, T1 a1, T2 a2) {
    r_ = (c->*m)(std::move(a1), std::move(a2));
  }
  template <typename C, typename M, typename T1, typename T2, typename T3>
  void Invoke(C* c, M m, T1 a1, T2 a2, T3 a3) {
    r_ = (c->*m)(std::move(a1), std::move(a2), std::move(a3));
  }
  template <typename C,
            typename M,
            typename T1,
            typename T2,
            typename T3,
            typename T4>
  void Invoke(C* c, M m, T1 a1, T2 a2, T3 a3, T4 a4) {
    r_ = (c->*m)(std::move(a1), std::move(a2), std::move(a3), std::move(a4));
  }
  template <typename C,
            typename M,
            typename T1,
            typename T2,
            typename T3,
            typename T4,
            typename T5>
  void Invoke(C* c, M m, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5) {
    r_ = (c->*m)(std::move(a1), std::move(a2), std::move(a3), std::move(a4),
                 std::move(a5));
  }

  R moved_result() { return std::move(r_); }

 private:
  R r_;
};

template <typename C, typename R>
class MethodCall0 : public rtc::Message, public rtc::MessageHandler {
 public:
  typedef R (C::*Method)();
  MethodCall0(C* c, Method m) : c_(c), m_(m) {}

  R Marshal(const rtc::Location& posted_from, rtc::Thread* t) {
    internal::SynchronousMethodCall(this).Invoke(posted_from, t);
    return r_.moved_result();
  }

 private:
	
  void OnMessage(rtc::Message*) { r_.Invoke(c_, m_); }

  C* c_;
  Method m_;
  ReturnType<R> r_; // 绑定函数和返回值
};

根据WebRTC线程模型封装的SDK的接口

总结

<font color=#999AAA > WebRTC中线程模型主要是做线程安全方案