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

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


WebRTC专题开嗨鸭 !!!

一、 WebRTC 线程模型

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

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

二、 WebRTC媒体协商

三、 WebRTC 音频数据采集

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

五、 WebRTC 视频数据采集

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

七、 WebRTC 网络传输

八、 WebRTC服务质量(Qos)

九、 NetEQ

十、 Simulcast与SVC

前言

WebRTC是音视频行业的标杆, 如果要学习音视频, WebRTC是进入音视频行业最好方法, 里面可以有成熟方案, 例如:音频中3A 算法、网络评估、自适应码流、Simulcast、SVC等等 , 非常适合刚刚进入音视频行业小伙伴哈_ 我也是哦, 以后再音视频行业长期打算的小伙伴的学习项目。 里面有大量知识点


提示:以下是本篇文章正文内容,下面案例可供参考

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

1、WebRTC线程模式

在这里插入图片描述

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

webrtc -> api

webrtc ->proxy

webrtc -> core

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

2、常见线程模型

在这里插入图片描述

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

二、WebRTC线程模型部分源码走读

1、 Thread

rtc_base/thread.h

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

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

代码如下(示例):

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

代码如下(示例):


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)

①、使用信号量通知的

代码如下(示例):

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的接口

总结

WebRTC中线程模型主要是做线程安全方案

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值