WebRTC源码分析之任务队列-TaskQueue

本文深入解析 WebRTC 中的 TaskQueue 机制,介绍核心类 TaskQueueStdlib 的实现细节,包括任务队列的创建、销毁、任务投递及处理流程。


在WebRTC中,会单独创建线程用于处理即时任务和延迟任务。其他线程可以将待做的事包装成任务投递到该线程去,由该线程执行。这个线程只做一件事,就是循环的处理任务。

TaskQueue使用示例
工程

先创建一个工程用于运行示例。如何创建工程,参考《WebRTC源码分析之工程-project》,在src\examples\BUILD.gn中添加如下内容:

rtc_executable("webrtc_learn"){
   
   
    testonly = true
  sources = [
    "webrtclearn/main.cc"         
  ]
  deps = [
    "../rtc_base:rtc_base",
    "../rtc_base:rtc_task_queue_stdlib", 
    "../api/task_queue:task_queue"
  ]
}
示例
#include <iostream>
#include <string>
#include "rtc_base/task_queue.h"
#include "rtc_base/task_queue_stdlib.h"
#include "rtc_base/platform_thread.h"
#include "api/task_queue/queued_task.h"
#include "api/task_queue/task_queue_base.h"
#include "api/task_queue/task_queue_factory.h"

using namespace std;
using namespace webrtc;
using  namespace rtc;

/*定义即时任务*/
class instant_task :public QueuedTask
{
   
   
public:
    instant_task(string thread_name)
        :thread_name_(thread_name)
    {
   
   }

    bool Run()  override
    {
   
   
        cout << thread_name_ << " post a task..." << endl;

        return true;
    }

private:
    string thread_name_;
};

/*定义延迟任务*/
class delay_task : public QueuedTask 
{
   
   
 public:
    delay_task(string thread_name)
      : thread_name_(thread_name)
    {
   
   }

  bool Run() override
  {
   
   
    cout << thread_name_ << " post a task..." << endl;

    return true;
  }

 private:
  string thread_name_;
};

void other_thread(void* arg)
{
   
   
    TaskQueue* tq = (TaskQueue*)arg;

    unique_ptr<QueuedTask> instantTask(new instant_task("child_thread"));
    unique_ptr<QueuedTask> delayedTask(new delay_task("child_thread"));

    /*延迟任务3秒后执行*/
    tq->PostDelayedTask(std::move(delayedTask), 3 * 1000);

    /*这个任务是最先执行*/
    tq->PostTask(std::move(instantTask));

    /*睡眠5秒等待任务被执行*/
    Sleep(5000);
}

int main()
{
   
   
    /*定义一个工厂*/
    unique_ptr<TaskQueueFactory> tqFactory = CreateTaskQueueStdlibFactory();

    /*用工厂创建任务队列*/
    unique_ptr<TaskQueueBase, TaskQueueDeleter> tqb = tqFactory->CreateTaskQueue("task queue", TaskQueueFactory::Priority::NORMAL);
    
    /*托管任务队列*/
    TaskQueue tq(std::move(tqb));
      
    /*开启一个子线程*/
    PlatformThread other_th(other_thread, (void*)&tq, "child_thread");
    other_th.Start();

    /*睡眠1秒后投递任务*/
    Sleep(1000);

    /*投递即时任务*/
    unique_ptr<QueuedTask> task(new instant_task("main_thread"));
    tq.PostTask(std::move(task));
    
    /*回收线程*/
    other_th.Stop();

    return 0;
}

在这里插入图片描述
在这里插入图片描述

在创建任务队列时,会创建一个线程,这个线程只用于任务的处理,其他线程可以向其投递任务。在主线程中又创建了一个子线程,并将任务队列传入,在子线程也可以向其投递任务。

TaskQueue源码分析
类关系图

在这里插入图片描述

TaskQueueBase类

TaskQueueBase类所在文件的位置:src\api\task_queue\task_queue_base.h task_queue_base.cc

声明
class RTC_LOCKABLE TaskQueueBase 
{
   
   
 public:
    /*释放任务队列*/
    virtual void Delete() = 0;
    
    /*投递即时任务*/
    virtual void PostTask(std::unique_ptr<QueuedTask> task) = 0;
    
    /*投递延迟任务*/
    virtual void PostDelayedTask(std::unique_ptr<QueuedTask> task,uint32_t milliseconds) = 0;
    
    /*返回当前线程保存的任务队列*/
    static TaskQueueBase* Current();
    
    /*判断当前线程保存的任务队列是否是自己*/
    bool IsCurrent() 
<think>好的,我现在需要分析WebRTC GCC接收端带宽估计的源码实现细节。首先,我需要回忆一下用户提供的引用内容,看看有没有相关的信息。根据引用[3],接收端带宽估计主要处理丢包和延迟,并通过RTCP反馈给发送端。同时,引用[2]提到了UpdateReceiverEstimate函数,这可能涉及到接收端估计值的更新。引用[1]则提到GCC算法的发展历程,特别是接收端到发送端的转变,这可能影响源码结构。 接下来,我应该考虑WebRTC的模块结构。接收端带宽估计可能在接收端处理RTP包,计算延迟和丢包率,然后通过RTCP发送反馈。根据引用[3]中的描述,丢包处理分为收包一致、丢包评估和评估值限制三个步骤。这可能对应到源码中的某些函数,比如处理每个到达的RTP包,更新统计信息,然后评估当前网络状况。 另外,引用[4]提到基于丢包率的调整,这可能与接收端如何计算丢包率有关。在源码中,可能会有计算丢包率的模块,比如统计一段时间内的丢包数量,并据此调整带宽估计。 我需要确定接收端带宽估计的核心类或模块。根据引用[2],BitrateControllerImpl和SendSideBandwidthEstimation可能涉及发送端的处理,但接收端估计可能位于其他模块,比如在接收端的RTP处理部分。可能的关键类包括ReceiveSideCongestionController或者类似的模块。 延迟估计也是关键部分,GCC使用基于延迟的算法。这部分可能涉及到InterArrivalTime和KalmanFilter等实现,如引用[1]提到的敏感度和稳定性,这可能对应到算法中的参数调整或滤波处理。 在源码分析中,需要关注以下几个步骤:接收RTP包的时间戳处理、计算包组间的到达时间差、使用延迟变化估计带宽、丢包统计、以及最终的RTCP反馈生成。具体到函数,可能包括处理每个包的OnReceivedPacket,更新延迟估计的UpdateDelayEstimate,计算带宽的UpdateBandwidthEstimate等。 此外,引用[3]提到的CapBitrateToThresholds可能用于限制带宽估计的范围,确保不会超过预设的最小或最大值。这可能在代码中通过比较当前估计值和阈值来实现。 最后,需要查看RTCP反馈的发送过程,如引用[2]中的TriggerCallbacksFromRtcpPacket和UpdateReceiverEstimate,这可能将接收端的估计结果传递给发送端,完成闭环控制。 总结下来,接收端带宽估计的源码分析需要关注丢包处理、延迟估计、带宽计算和RTCP反馈这几个模块,结合具体的类和方法,逐步跟踪数据流和处理逻辑。</think>### WebRTC GCC接收端带宽估计源码分析 #### 1. **核心模块与流程** WebRTC GCC接收端带宽估计的核心实现在`RemoteEstimatorProxy`和`ReceiveSideCongestionController`模块中,主要流程包括: - **RTP包处理**:接收端通过`RtpStreamReceiver`处理每个到达的RTP包,记录时间戳、序列号等信息[^3]。 - **延迟计算**:利用包组到达时间差(Inter-arrival Delay)计算网络延迟变化,通过卡尔曼滤波器(Kalman Filter)平滑噪声[^1]。 - **丢包统计**:基于RTP序列号连续性检测丢包率,例如通过`RtpPacketCounter`统计接收状态[^4]。 - **带宽估计整合**:将延迟和丢包率输入到`DelayBasedBwe`(基于延迟的带宽估计器)中,结合`LossBasedBwe`(基于丢包的带宽估计器)生成最终估计值[^3]。 #### 2. **关键代码片段分析 ```cpp // webrtc/modules/remote_bitrate_estimator/remote_estimator_proxy.cc void RemoteEstimatorProxy::IncomingPacket( int64_t arrival_time_ms, size_t payload_size, const RTPHeader& header) { // 记录包到达时间和序列号 PacketInfo packet_info(arrival_time_ms, header.sequenceNumber); packet_info.ssrc = header.ssrc; // 触发延迟估计更新 delay_based_bwe_->IncomingPacketFeedbackVector({packet_info}); } ``` #### 3. **延迟估计核心逻辑 - **包组划分**:通过`InterArrival`类判断是否为新包组(时间差超过5ms或序列号不连续)[^3]。 - **卡尔曼滤波**:在`DelayIncreaseDetector`中预测网络队列延迟变化,公式为: $$ \Delta t = \frac{\text{到达时间差} - \text{发送时间差}}{\text{包组大小}} $$ 若$\Delta t > 0$则判定为网络拥塞[^1]。 #### 4. **丢包率计算实现 ```cpp // webrtc/call/rtp_stream_receiver_controller.cc void RtpStreamReceiver::UpdatePacketLossStats( const RtpPacketReceived& packet) { if (IsPacketReordered(packet.SequenceNumber())) { loss_stats_.AddLostPacket(packet.SequenceNumber()); } current_loss_ratio_ = loss_stats_.GetLostPacketsRatio(); } ``` #### 5. **带宽反馈机制 最终估计的带宽通过RTCP REMB消息反馈至发送端: ```cpp // webrtc/modules/rtp_rtcp/source/rtcp_sender.cc void RTCPSender::SendRTCP(const FeedbackState& feedback_state, ...) { if (remb_enabled_ && feedback_state.has_bandwidth_estimate) { BuildRemb(feedback_state.remb_bitrate); } } ``` 此过程通过`BitrateController::OnReceivedEstimatedBitrate`触发发送端带宽调整[^2]。 ####
评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值