webrtc弱网-VideoSendStreamImpl类源码分析与算法原理

一、核心功能

VideoSendStreamImpl 是 WebRTC 视频发送流的核心实现,主要功能包括:

  1. 视频编码与发送:管理视频编码器输出,将编码后的帧通过 RTP 发送

  2. 码率控制:根据网络状况动态调整视频码率

  3. 带宽分配:与带宽分配器交互获取可用带宽

  4. 流控制:管理流的启动/停止和层级激活

  5. 超时检测:监控编码器活动状态

  6. 配置管理:处理编码器参数变更

二、核心算法原理

  1. 码率分配算法

    • 分层码率分配:支持 simulcast/SVC 的多层码率分配

    • 填充码率计算:根据活跃流计算最大填充码率

    • 码率优先级:基于流优先级分配带宽

    复制代码
    // 计算填充码率 (video_send_stream_impl.cc)
    int CalculateMaxPadBitrateBps(const std::vector<VideoStream>& streams, ...) {
      // 根据活跃流、内容类型、ALR探测等计算填充码率
    }
  2. 码率更新限流

    • 避免频繁发送相似的码率分配

    • 10% 变化阈值 + 500ms 时间窗口

    复制代码
    // 码率分配更新限流 (video_send_stream_impl.cc)
    if (is_similar && (now_ms - last_send_time) < kMaxVbaThrottleTimeMs) {
      throttled_allocation = allocation; // 缓存相似分配
    }
  3. 编码器超时检测

    • 定时检查编码器活动状态

    • 2秒无活动判定为超时

    复制代码
    // 超时检测任务 (video_send_stream_impl.cc)
    check_encoder_activity_task_ = RepeatingTaskHandle::DelayedStart(
        worker_queue_, kEncoderTimeOut, [this] { /* 检测逻辑 */ });

三、关键数据结构

  1. PacingConfig:pacing 控制参数

    复制代码
    struct PacingConfig {
      FieldTrialParameter<double> pacing_factor;
      FieldTrialParameter<TimeDelta> max_pacing_delay;
    };
  2. VbaSendContext:码率分配更新上下文

    复制代码
    struct VbaSendContext {
      VideoBitrateAllocation last_sent_allocation;
      absl::optional<VideoBitrateAllocation> throttled_allocation;
      int64_t last_send_time_ms;
    };
  3. MediaStreamAllocationConfig:带宽分配配置

    复制代码
    struct MediaStreamAllocationConfig {
      uint32_t min_bitrate_bps;
      uint32_t max_bitrate_bps;
      uint32_t pad_up_bitrate_bps;
      uint32_t priority_bitrate_bps;
      bool enforce_min_bitrate;
      double bitrate_priority;
      bool has_packet_feedback;
    };

四、核心方法详解

  1. 码率更新处理 (OnBitrateUpdated)

    复制代码
    uint32_t VideoSendStreamImpl::OnBitrateUpdated(BitrateAllocationUpdate update) {
      // 1. 计算有效载荷码率
      encoder_target_rate_bps_ = rtp_video_sender_->GetPayloadBitrateBps();
      
      // 2. 计算保护码率(FEC/重传)
      uint32_t protection_bitrate = rtp_video_sender_->GetProtectionBitrateBps();
      
      // 3. 计算链路分配码率
      DataRate link_allocation = max(encoder_target_rate, payload_rate - protection);
      
      // 4. 更新编码器码率
      video_stream_encoder_->OnBitrateUpdated(encoder_target_rate, ...);
      
      return protection_bitrate; // 返回保护码率
    }
  2. 编码输出处理 (OnEncodedImage)

    复制代码
    EncodedImageCallback::Result VideoSendStreamImpl::OnEncodedImage(...) {
      activity_ = true; // 标记编码器活跃
      
      // 工作队列中处理码率更新
      worker_queue_->PostTask([this] {
        if (disable_padding_) {
          disable_padding_ = false;
          SignalEncoderActive(); // 重新激活带宽分配
        }
      });
      
      // 转发到RTP发送器
      return rtp_video_sender_->OnEncodedImage(encoded_image, ...);
    }
  3. 流启动/停止

    复制代码
    void VideoSendStreamImpl::StartupVideoSendStream() {
      bitrate_allocator_->AddObserver(this, ...); // 注册带宽观察者
      video_stream_encoder_->SendKeyFrame();      // 发送关键帧
      // 启动超时检测任务
      check_encoder_activity_task_ = RepeatingTaskHandle::DelayedStart(...);
    }
    
    void VideoSendStreamImpl::StopVideoSendStream() {
      bitrate_allocator_->RemoveObserver(this); // 移除带宽观察者
      video_stream_encoder_->OnBitrateUpdated(0, 0, 0, ...); // 清零码率
    }

五、设计亮点

  1. 线程安全设计

    • 使用 SequenceChecker 确保线程安全

    • 工作队列任务通过 ScopedTaskSafety 管理生命周期

    复制代码
    worker_queue_->PostTask(SafeTask(worker_queue_safety_.flag(), ...));
  2. 动态配置支持

    • 通过 FieldTrial 支持运行时参数调整
    复制代码
    // 从字段试验获取pacing配置
    ParseFieldTrial({&pacing_factor, &max_pacing_delay}, 
                   field_trials.Lookup("WebRTC-Video-Pacing"));
  3. 智能码率分配更新

    • 相似分配过滤减少冗余通信

    • 时间窗口限流避免网络拥塞

  4. 分层码率控制

    • 支持 simulcast/SVC 的独立码率控制
    复制代码
    // 多层码率分配处理 (OnEncoderConfigurationChanged)
    for (const VideoStream& stream : streams) {
      encoder_max_bitrate_bps_ += stream.active ? stream.max_bitrate_bps : 0;
    }

六、典型工作流程

  1. 初始化

视频发送流程

超时检测流程

注释精要

复制代码
// 视频发送流核心实现类
class VideoSendStreamImpl : public BitrateAllocatorObserver,
                            public VideoStreamEncoderInterface::EncoderSink {
  // ... 其他代码 ...

  // 处理带宽更新 (核心方法)
  uint32_t OnBitrateUpdated(BitrateAllocationUpdate update) override {
    RTC_DCHECK_RUN_ON(&thread_checker_);
    
    // 当BWE未提供稳定码率时,使用目标码率作为稳定码率
    if (update.stable_target_bitrate.IsZero()) {
      update.stable_target_bitrate = update.target_bitrate;
    }
    
    // 更新RTP视频发送器码率
    rtp_video_sender_->OnBitrateUpdated(update, ...);
    
    // 计算有效载荷码率(视频数据)
    encoder_target_rate_bps_ = rtp_video_sender_->GetPayloadBitrateBps();
    
    // 计算保护码率(FEC/重传)
    const uint32_t protection_bitrate = ...;
    
    // 计算链路分配码率(有效载荷-保护)
    DataRate link_allocation = ...;
    
    // 计算稳定目标码率(考虑网络开销)
    DataRate encoder_stable_target_rate = ...;
    
    // 限制码率不超过编码器最大值
    encoder_target_rate_bps_ = std::min(encoder_max_bitrate_bps_, ...);
    
    // 更新视频编码器码率
    video_stream_encoder_->OnBitrateUpdated(
        encoder_target_rate, 
        encoder_stable_target_rate,
        link_allocation,
        ...);
        
    return protection_bitrate; // 返回保护带宽需求
  }
};
复制代码
// 编码帧处理
EncodedImageCallback::Result VideoSendStreamImpl::OnEncodedImage(
    const EncodedImage& encoded_image,
    const CodecSpecificInfo* codec_specific_info) {
  
  activity_ = true; // 标记编码器活动
  
  // 在工作队列中处理状态更新
  worker_queue_->PostTask([this] {
    // 如果之前禁用了填充,现在重新激活
    if (disable_padding_) {
      disable_padding_ = false;
      SignalEncoderActive(); // 重新注册带宽观察者
    }
    
    // 检查是否有缓存的码率分配需要发送
    if (video_bitrate_allocation_context_ && 
        video_bitrate_allocation_context_->throttled_allocation) {
      OnBitrateAllocationUpdated(*video_bitrate_allocation_context_->throttled_allocation);
    }
  });
  
  // 转发到RTP视频发送器
  return rtp_video_sender_->OnEncodedImage(encoded_image, codec_specific_info);
}

VideoSendStreamImpl 是 WebRTC 视频发送系统的核心实现,负责管理视频编码、码率分配、RTP 封装和网络发送等全流程。是webrtc弱网控制核心组件。