webrtc RtpRtcp模块化测试-MockRtpRtcp

MockRtpRtcp 是 WebRTC 测试框架中用于模拟(Mock)RTP/RTCP 模块行为的类。

它继承自 RtpRtcp 接口,并使用 Google Mock (gmock) 库将几乎所有虚方法转换为 mock 方法。它通过虚拟化复杂的 RTP/RTCP 协议栈交互,使得上层业务逻辑(如视频编码、拥塞控制、流管理)的单元测试变得简单、快速且可靠。

MockRtpRtcp使得开发者在编写单元测试时,可以隔离依赖,精确控制 RTP/RTCP 模块的行为,并验证上层逻辑是否正确调用了预期的接口。

一、核心目的

• 解耦测试:在测试视频发送器、音频发送器或拥塞控制器时,不需要真实的网络栈或复杂的 RTP 状态机。使用 MockRtpRtcp 可以模拟这些组件的交互。

• 行为验证:验证被测代码是否以正确的参数调用了 RTP/RTCP 接口(例如:是否发送了 NACK,是否设置了正确的 SSRC,是否注册了头部扩展等)。

• 状态模拟:模拟特定的返回值(如当前的序列号、RTT 值、带宽估计等),以测试被测代码在不同网络条件下的反应。

二、主要功能

2.1. 配置与初始化

1 SSRC 与标识符:

• SetRemoteSSRC, SSRC, SetRid, SetMid: 模拟设置和获取同步源标识符、RTP Stream ID 和 Media ID。

2 Payload 管理:

• RegisterSendPayloadFrequency, DeRegisterSendPayload: 模拟编解码器 Payload Type 的注册。

3 头部扩展:

• RegisterSendRtpHeaderExtension, DeregisterSendRtpHeaderExtension: 模拟 RTP 头部扩展(如绝对发送时间、传输宽拥塞控制等)的注册。

2.2. 发送控制

1 状态控制:

• SetSendingStatus, Sending, SetSendingMediaStatus, SendingMedia: 控制流是否处于发送状态。

2 数据包发送:

• TrySendPacket: 模拟尝试发送一个 RTP 包。测试中可以设定其返回 true 或 false 来模拟成功或失败。

• OnSendingRtpFrame: 通知底层即将发送一帧数据。

3 填充包 (Padding):

• GeneratePadding: 当实际媒体数据不足时,生成填充包以维持码率。Mock 可以返回指定大小的空包或特定内容的包。

• SupportsPadding, SupportsRtxPayloadPadding: 查询是否支持填充。

2.3. RTCP 处理与反馈

1 接收 RTCP:

• IncomingRtcpPacket: 模拟从网络收到一个 RTCP 包。测试中可以注入伪造的 RTCP 包来触发上层的处理逻辑(如解析 Receiver Report 或 NACK)。

2 发送 RTCP:

• SendRTCP, SendCombinedRtcpPacket: 验证上层是否请求发送特定的 RTCP 包类型(如 SR, RR, BYE, APP 等)。

• SendNACK / SendNack: 验证是否请求重传特定的丢失包。

• SendLossNotification: 模拟发送丢包通知(用于 FlexFEC 等场景)。

3 统计与查询:

• RTT: 模拟返回往返时延。测试中可以设定不同的 RTT 值来观察拥控算法的反应。

• RemoteCNAME, RemoteNTP: 模拟获取对端的规范名称和时间信息。

• DataCountersRTP, GetSendStreamDataCounters: 模拟返回发送字节数和包数统计。

2.4. 带宽与拥塞控制相关

1, 带宽估计:

• EstimatedReceiveBandwidth: 模拟接收端估算的可用带宽。

• SetRemb, UnsetRemb: 模拟设置接收端最大比特率(REMB)。

• SetVideoBitrateAllocation: 模拟视频码率分配策略。

2, 速率查询:

• BitrateSent, GetSendRates: 查询当前发送的视频、fec、nack 等各部分的码率。

2.5. 状态管理

序列号与时间戳:

• SequenceNumber, SetSequenceNumber: 模拟获取和设置当前 RTP 序列号。

• StartTimestamp, SetStartTimestamp: 模拟 RTP 起始时间戳。

• SetRtpState, GetRtpState: 保存和恢复 RTP 发送状态(用于流切换或重启场景)。

三、特殊处理

cpp 复制代码
int64_t TimeUntilNextProcess() override { return 0xffffffff; }
  1. 原因:RtpRtcp 继承自 Module 接口,通常由一个进程线程(Process Thread)定期调用 Process() 和 TimeUntilNextProcess()。

  2. 风险:如果在 Mock 中简单地返回 0 或一个很小的值,可能会导致测试中的进程线程进入死循环,疯狂调用 Process(),从而卡死测试。

  3. 策略:返回 0xffffffff(最大值)表示"很久之后才需要再次处理", effectively 禁用了自动周期性处理,除非测试显式调用 Process()。这保证了测试的可控性和稳定性。

四、示例

cpp 复制代码
TEST(MyVideoSenderTest, SendsNackOnPacketLoss) {
  // 1. 创建 Mock 对象
  auto mock_rtp_rtcp = std::make_unique<MockRtpRtcp>();
  
  // 2. 设置期望行为:当调用 SendNack 时,我们期望它被调用一次,且参数包含序列号 100
  EXPECT_CALL(*mock_rtp_rtcp, SendNack(std::vector<uint16_t>{100}))
      .Times(1);

  // 3. 将被测对象依赖于这个 Mock
  MyVideoSender sender(std::move(mock_rtp_rtcp));

  // 4. 触发被测逻辑:模拟检测到包 100 丢失
  sender.OnPacketLost(100);

  // 5. 验证:Google Mock 会自动检查 SendNack 是否按预期被调用
}
相关推荐
OpenLoong 开源社区8 天前
打破 NAT 限制,零侵入跨网络通信:基于 WebRTC 的透明 TCP 隧道跨网络通信方案
网络协议·tcp/ip·开源·webrtc·openloong开源社区
探鸽小钛11 天前
4G 终端 ES8311 - 挂断一次,下次说话就没声了之解决办法
物联网·音视频·嵌入式·esp32·webrtc
草根大哥11 天前
AI 编程实践之自建视频CDN
音视频·webrtc·低延迟直播·视频cdn·低延迟cdn
EasyCVR12 天前
应急指挥怕延迟?聊聊视频汇聚/视频融合/视频分析EasyCVR平台WebRTC低延迟方案
音视频·webrtc·easycvr
TrueDei13 天前
WebRTC ICE 候选变成 mDNS 地址导致连接失败:原因分析与解决方案
webrtc
中屹指纹浏览器svip15 天前
WebRTC泄露是什么,怎么关闭?
webrtc
海边捡石子16 天前
从零设计一个通用智能电话平台:FreeSWITCH + ESL + AI 实战架构
人工智能·架构·webrtc
音视频牛哥17 天前
不换摄像机,也能接入 WebRTC?SmartMediaKit RTSP/RTMP 转 WHIP 技术实践
音视频·webrtc·smartmediakit·rtsp转whip·rtmp转whip·whip推流·rtsp转webrtc播放
直播技术开发交流19 天前
Android 端 WHIP 协议推流技术实践:相机/录屏/多路转发WHIP实现测试
webrtc·android whip·rtsp转whip·毫秒级实时媒体流·whip低延时推送·whip推送实现·rtsp转webrtc
程序员阿明20 天前
docker搭建视频流服务go2rtc,webRTC
docker·容器·webrtc