blob: abb829a8de9cc59a4d46d00ef7b5cc5f692d2d26 [file] [log] [blame]
Stefan Holmere5904162015-03-26 11:11:06 +01001/*
2 * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
11#include <list>
kwiberg22feaa32016-03-17 09:17:43 -070012#include <memory>
Stefan Holmere5904162015-03-26 11:11:06 +010013
Henrik Kjellander0b9e29c2015-11-16 11:12:24 +010014#include "webrtc/modules/pacing/packet_router.h"
Henrik Kjellanderff761fb2015-11-04 08:31:52 +010015#include "webrtc/modules/rtp_rtcp/include/rtp_rtcp.h"
Stefan Holmere5904162015-03-26 11:11:06 +010016#include "webrtc/modules/rtp_rtcp/mocks/mock_rtp_rtcp.h"
stefanbba9dec2016-02-01 04:39:55 -080017#include "webrtc/modules/rtp_rtcp/source/rtcp_packet/transport_feedback.h"
Edward Lemurc20978e2017-07-06 19:44:34 +020018#include "webrtc/rtc_base/checks.h"
19#include "webrtc/rtc_base/fakeclock.h"
kwibergac9f8762016-09-30 22:29:43 -070020#include "webrtc/test/gmock.h"
21#include "webrtc/test/gtest.h"
Stefan Holmere5904162015-03-26 11:11:06 +010022
23using ::testing::_;
24using ::testing::AnyNumber;
philipelc7bf32a2017-02-17 03:59:43 -080025using ::testing::Field;
Stefan Holmere5904162015-03-26 11:11:06 +010026using ::testing::NiceMock;
27using ::testing::Return;
eladalon822ff2b2017-08-01 06:30:28 -070028using ::testing::ReturnPointee;
29using ::testing::SaveArg;
Stefan Holmere5904162015-03-26 11:11:06 +010030
31namespace webrtc {
32
eladalon822ff2b2017-08-01 06:30:28 -070033// TODO(eladalon): Restructure and/or replace the existing monolithic tests
34// (only some of the test are monolithic) according to the new
35// guidelines - small tests for one thing at a time.
36// (I'm not removing any tests during CL, so as to demonstrate no regressions.)
37
eladalonb1338fe2017-08-01 09:36:19 -070038namespace {
39constexpr int kProbeMinProbes = 5;
40constexpr int kProbeMinBytes = 1000;
41
eladalon822ff2b2017-08-01 06:30:28 -070042class MockRtpRtcpWithRembTracking : public MockRtpRtcp {
43 public:
44 MockRtpRtcpWithRembTracking() {
45 ON_CALL(*this, SetREMBStatus(_)).WillByDefault(SaveArg<0>(&remb_));
46 ON_CALL(*this, REMB()).WillByDefault(ReturnPointee(&remb_));
47 }
48
49 private:
50 bool remb_ = false;
51};
eladalonb1338fe2017-08-01 09:36:19 -070052} // namespace
eladalon822ff2b2017-08-01 06:30:28 -070053
eladalonb1338fe2017-08-01 09:36:19 -070054TEST(PacketRouterTest, TimeToSendPacket) {
55 PacketRouter packet_router;
eladalon6c9556e2017-07-10 03:33:00 -070056 NiceMock<MockRtpRtcp> rtp_1;
57 NiceMock<MockRtpRtcp> rtp_2;
eladalonb1338fe2017-08-01 09:36:19 -070058
59 packet_router.AddSendRtpModule(&rtp_1, false);
60 packet_router.AddSendRtpModule(&rtp_2, false);
Stefan Holmere5904162015-03-26 11:11:06 +010061
62 const uint16_t kSsrc1 = 1234;
63 uint16_t sequence_number = 17;
64 uint64_t timestamp = 7890;
65 bool retransmission = false;
66
67 // Send on the first module by letting rtp_1 be sending with correct ssrc.
68 EXPECT_CALL(rtp_1, SendingMedia()).Times(1).WillOnce(Return(true));
69 EXPECT_CALL(rtp_1, SSRC()).Times(1).WillOnce(Return(kSsrc1));
philipelc7bf32a2017-02-17 03:59:43 -080070 EXPECT_CALL(rtp_1, TimeToSendPacket(
71 kSsrc1, sequence_number, timestamp, retransmission,
72 Field(&PacedPacketInfo::probe_cluster_id, 1)))
Stefan Holmere5904162015-03-26 11:11:06 +010073 .Times(1)
74 .WillOnce(Return(true));
philipela1ed0b32016-06-01 06:31:17 -070075 EXPECT_CALL(rtp_2, TimeToSendPacket(_, _, _, _, _)).Times(0);
eladalonb1338fe2017-08-01 09:36:19 -070076 EXPECT_TRUE(packet_router.TimeToSendPacket(
philipelc7bf32a2017-02-17 03:59:43 -080077 kSsrc1, sequence_number, timestamp, retransmission,
78 PacedPacketInfo(1, kProbeMinProbes, kProbeMinBytes)));
Stefan Holmere5904162015-03-26 11:11:06 +010079
80 // Send on the second module by letting rtp_2 be sending, but not rtp_1.
81 ++sequence_number;
82 timestamp += 30;
83 retransmission = true;
84 const uint16_t kSsrc2 = 4567;
85 EXPECT_CALL(rtp_1, SendingMedia()).Times(1).WillOnce(Return(false));
86 EXPECT_CALL(rtp_2, SendingMedia()).Times(1).WillOnce(Return(true));
87 EXPECT_CALL(rtp_2, SSRC()).Times(1).WillOnce(Return(kSsrc2));
philipela1ed0b32016-06-01 06:31:17 -070088 EXPECT_CALL(rtp_1, TimeToSendPacket(_, _, _, _, _)).Times(0);
philipelc7bf32a2017-02-17 03:59:43 -080089 EXPECT_CALL(rtp_2, TimeToSendPacket(
90 kSsrc2, sequence_number, timestamp, retransmission,
91 Field(&PacedPacketInfo::probe_cluster_id, 2)))
Stefan Holmere5904162015-03-26 11:11:06 +010092 .Times(1)
93 .WillOnce(Return(true));
eladalonb1338fe2017-08-01 09:36:19 -070094 EXPECT_TRUE(packet_router.TimeToSendPacket(
philipelc7bf32a2017-02-17 03:59:43 -080095 kSsrc2, sequence_number, timestamp, retransmission,
96 PacedPacketInfo(2, kProbeMinProbes, kProbeMinBytes)));
Stefan Holmere5904162015-03-26 11:11:06 +010097
98 // No module is sending, hence no packet should be sent.
99 EXPECT_CALL(rtp_1, SendingMedia()).Times(1).WillOnce(Return(false));
philipela1ed0b32016-06-01 06:31:17 -0700100 EXPECT_CALL(rtp_1, TimeToSendPacket(_, _, _, _, _)).Times(0);
Stefan Holmere5904162015-03-26 11:11:06 +0100101 EXPECT_CALL(rtp_2, SendingMedia()).Times(1).WillOnce(Return(false));
philipela1ed0b32016-06-01 06:31:17 -0700102 EXPECT_CALL(rtp_2, TimeToSendPacket(_, _, _, _, _)).Times(0);
eladalonb1338fe2017-08-01 09:36:19 -0700103 EXPECT_TRUE(packet_router.TimeToSendPacket(
philipelc7bf32a2017-02-17 03:59:43 -0800104 kSsrc1, sequence_number, timestamp, retransmission,
105 PacedPacketInfo(1, kProbeMinProbes, kProbeMinBytes)));
Stefan Holmere5904162015-03-26 11:11:06 +0100106
107 // Add a packet with incorrect ssrc and test it's dropped in the router.
108 EXPECT_CALL(rtp_1, SendingMedia()).Times(1).WillOnce(Return(true));
109 EXPECT_CALL(rtp_1, SSRC()).Times(1).WillOnce(Return(kSsrc1));
110 EXPECT_CALL(rtp_2, SendingMedia()).Times(1).WillOnce(Return(true));
111 EXPECT_CALL(rtp_2, SSRC()).Times(1).WillOnce(Return(kSsrc2));
philipela1ed0b32016-06-01 06:31:17 -0700112 EXPECT_CALL(rtp_1, TimeToSendPacket(_, _, _, _, _)).Times(0);
113 EXPECT_CALL(rtp_2, TimeToSendPacket(_, _, _, _, _)).Times(0);
eladalonb1338fe2017-08-01 09:36:19 -0700114 EXPECT_TRUE(packet_router.TimeToSendPacket(
philipelc7bf32a2017-02-17 03:59:43 -0800115 kSsrc1 + kSsrc2, sequence_number, timestamp, retransmission,
116 PacedPacketInfo(1, kProbeMinProbes, kProbeMinBytes)));
Stefan Holmere5904162015-03-26 11:11:06 +0100117
eladalonb1338fe2017-08-01 09:36:19 -0700118 packet_router.RemoveSendRtpModule(&rtp_1);
Stefan Holmere5904162015-03-26 11:11:06 +0100119
120 // rtp_1 has been removed, try sending a packet on that ssrc and make sure
121 // it is dropped as expected by not expecting any calls to rtp_1.
122 EXPECT_CALL(rtp_2, SendingMedia()).Times(1).WillOnce(Return(true));
123 EXPECT_CALL(rtp_2, SSRC()).Times(1).WillOnce(Return(kSsrc2));
philipela1ed0b32016-06-01 06:31:17 -0700124 EXPECT_CALL(rtp_2, TimeToSendPacket(_, _, _, _, _)).Times(0);
eladalonb1338fe2017-08-01 09:36:19 -0700125 EXPECT_TRUE(packet_router.TimeToSendPacket(
philipelc7bf32a2017-02-17 03:59:43 -0800126 kSsrc1, sequence_number, timestamp, retransmission,
127 PacedPacketInfo(PacedPacketInfo::kNotAProbe, kProbeMinBytes,
128 kProbeMinBytes)));
Stefan Holmere5904162015-03-26 11:11:06 +0100129
eladalonb1338fe2017-08-01 09:36:19 -0700130 packet_router.RemoveSendRtpModule(&rtp_2);
Stefan Holmere5904162015-03-26 11:11:06 +0100131}
132
eladalonb1338fe2017-08-01 09:36:19 -0700133TEST(PacketRouterTest, TimeToSendPadding) {
134 PacketRouter packet_router;
135
sprang867fb522015-08-03 04:38:41 -0700136 const uint16_t kSsrc1 = 1234;
137 const uint16_t kSsrc2 = 4567;
138
eladalon6c9556e2017-07-10 03:33:00 -0700139 NiceMock<MockRtpRtcp> rtp_1;
stefan16b02212017-01-27 07:12:16 -0800140 EXPECT_CALL(rtp_1, RtxSendStatus()).WillOnce(Return(kRtxOff));
sprang867fb522015-08-03 04:38:41 -0700141 EXPECT_CALL(rtp_1, SSRC()).WillRepeatedly(Return(kSsrc1));
eladalon6c9556e2017-07-10 03:33:00 -0700142 NiceMock<MockRtpRtcp> rtp_2;
stefan16b02212017-01-27 07:12:16 -0800143 // rtp_2 will be prioritized for padding.
144 EXPECT_CALL(rtp_2, RtxSendStatus()).WillOnce(Return(kRtxRedundantPayloads));
sprang867fb522015-08-03 04:38:41 -0700145 EXPECT_CALL(rtp_2, SSRC()).WillRepeatedly(Return(kSsrc2));
eladalonb1338fe2017-08-01 09:36:19 -0700146 packet_router.AddSendRtpModule(&rtp_1, false);
147 packet_router.AddSendRtpModule(&rtp_2, false);
Stefan Holmere5904162015-03-26 11:11:06 +0100148
sprang867fb522015-08-03 04:38:41 -0700149 // Default configuration, sending padding on all modules sending media,
stefan16b02212017-01-27 07:12:16 -0800150 // ordered by priority (based on rtx mode).
Stefan Holmere5904162015-03-26 11:11:06 +0100151 const size_t requested_padding_bytes = 1000;
152 const size_t sent_padding_bytes = 890;
stefan16b02212017-01-27 07:12:16 -0800153 EXPECT_CALL(rtp_2, SendingMedia()).Times(1).WillOnce(Return(true));
stefan53b6cc32017-02-03 08:13:57 -0800154 EXPECT_CALL(rtp_2, HasBweExtensions()).Times(1).WillOnce(Return(true));
philipelc7bf32a2017-02-17 03:59:43 -0800155 EXPECT_CALL(rtp_2,
156 TimeToSendPadding(requested_padding_bytes,
157 Field(&PacedPacketInfo::probe_cluster_id, 111)))
Stefan Holmere5904162015-03-26 11:11:06 +0100158 .Times(1)
159 .WillOnce(Return(sent_padding_bytes));
stefan16b02212017-01-27 07:12:16 -0800160 EXPECT_CALL(rtp_1, SendingMedia()).Times(1).WillOnce(Return(true));
stefan53b6cc32017-02-03 08:13:57 -0800161 EXPECT_CALL(rtp_1, HasBweExtensions()).Times(1).WillOnce(Return(true));
philipelc7bf32a2017-02-17 03:59:43 -0800162 EXPECT_CALL(rtp_1,
163 TimeToSendPadding(requested_padding_bytes - sent_padding_bytes,
164 Field(&PacedPacketInfo::probe_cluster_id, 111)))
sprang867fb522015-08-03 04:38:41 -0700165 .Times(1)
166 .WillOnce(Return(requested_padding_bytes - sent_padding_bytes));
167 EXPECT_EQ(requested_padding_bytes,
eladalonb1338fe2017-08-01 09:36:19 -0700168 packet_router.TimeToSendPadding(
philipelc7bf32a2017-02-17 03:59:43 -0800169 requested_padding_bytes,
170 PacedPacketInfo(111, kProbeMinBytes, kProbeMinBytes)));
Stefan Holmere5904162015-03-26 11:11:06 +0100171
stefan16b02212017-01-27 07:12:16 -0800172 // Let only the lower priority module be sending and verify the padding
173 // request is routed there.
174 EXPECT_CALL(rtp_2, SendingMedia()).Times(1).WillOnce(Return(false));
175 EXPECT_CALL(rtp_2, TimeToSendPadding(requested_padding_bytes, _)).Times(0);
176 EXPECT_CALL(rtp_1, SendingMedia()).Times(1).WillOnce(Return(true));
stefan53b6cc32017-02-03 08:13:57 -0800177 EXPECT_CALL(rtp_1, HasBweExtensions()).Times(1).WillOnce(Return(true));
stefan16b02212017-01-27 07:12:16 -0800178 EXPECT_CALL(rtp_1, TimeToSendPadding(_, _))
Stefan Holmere5904162015-03-26 11:11:06 +0100179 .Times(1)
180 .WillOnce(Return(sent_padding_bytes));
181 EXPECT_EQ(sent_padding_bytes,
eladalonb1338fe2017-08-01 09:36:19 -0700182 packet_router.TimeToSendPadding(
philipelc7bf32a2017-02-17 03:59:43 -0800183 requested_padding_bytes,
184 PacedPacketInfo(PacedPacketInfo::kNotAProbe, kProbeMinBytes,
185 kProbeMinBytes)));
Stefan Holmere5904162015-03-26 11:11:06 +0100186
187 // No sending module at all.
188 EXPECT_CALL(rtp_1, SendingMedia()).Times(1).WillOnce(Return(false));
philipela1ed0b32016-06-01 06:31:17 -0700189 EXPECT_CALL(rtp_1, TimeToSendPadding(requested_padding_bytes, _)).Times(0);
Stefan Holmere5904162015-03-26 11:11:06 +0100190 EXPECT_CALL(rtp_2, SendingMedia()).Times(1).WillOnce(Return(false));
philipela1ed0b32016-06-01 06:31:17 -0700191 EXPECT_CALL(rtp_2, TimeToSendPadding(_, _)).Times(0);
philipelc7bf32a2017-02-17 03:59:43 -0800192 EXPECT_EQ(0u,
eladalonb1338fe2017-08-01 09:36:19 -0700193 packet_router.TimeToSendPadding(
philipelc7bf32a2017-02-17 03:59:43 -0800194 requested_padding_bytes,
195 PacedPacketInfo(PacedPacketInfo::kNotAProbe, kProbeMinBytes,
196 kProbeMinBytes)));
Stefan Holmere5904162015-03-26 11:11:06 +0100197
stefan53b6cc32017-02-03 08:13:57 -0800198 // Only one module has BWE extensions.
199 EXPECT_CALL(rtp_1, SendingMedia()).Times(1).WillOnce(Return(true));
200 EXPECT_CALL(rtp_1, HasBweExtensions()).Times(1).WillOnce(Return(false));
201 EXPECT_CALL(rtp_1, TimeToSendPadding(requested_padding_bytes, _)).Times(0);
202 EXPECT_CALL(rtp_2, SendingMedia()).Times(1).WillOnce(Return(true));
203 EXPECT_CALL(rtp_2, HasBweExtensions()).Times(1).WillOnce(Return(true));
204 EXPECT_CALL(rtp_2, TimeToSendPadding(requested_padding_bytes, _))
205 .Times(1)
206 .WillOnce(Return(sent_padding_bytes));
207 EXPECT_EQ(sent_padding_bytes,
eladalonb1338fe2017-08-01 09:36:19 -0700208 packet_router.TimeToSendPadding(
philipelc7bf32a2017-02-17 03:59:43 -0800209 requested_padding_bytes,
210 PacedPacketInfo(PacedPacketInfo::kNotAProbe, kProbeMinBytes,
211 kProbeMinBytes)));
stefan53b6cc32017-02-03 08:13:57 -0800212
eladalonb1338fe2017-08-01 09:36:19 -0700213 packet_router.RemoveSendRtpModule(&rtp_1);
Stefan Holmere5904162015-03-26 11:11:06 +0100214
215 // rtp_1 has been removed, try sending padding and make sure rtp_1 isn't asked
216 // to send by not expecting any calls. Instead verify rtp_2 is called.
217 EXPECT_CALL(rtp_2, SendingMedia()).Times(1).WillOnce(Return(true));
stefan53b6cc32017-02-03 08:13:57 -0800218 EXPECT_CALL(rtp_2, HasBweExtensions()).Times(1).WillOnce(Return(true));
philipela1ed0b32016-06-01 06:31:17 -0700219 EXPECT_CALL(rtp_2, TimeToSendPadding(requested_padding_bytes, _)).Times(1);
philipelc7bf32a2017-02-17 03:59:43 -0800220 EXPECT_EQ(0u,
eladalonb1338fe2017-08-01 09:36:19 -0700221 packet_router.TimeToSendPadding(
philipelc7bf32a2017-02-17 03:59:43 -0800222 requested_padding_bytes,
223 PacedPacketInfo(PacedPacketInfo::kNotAProbe, kProbeMinBytes,
224 kProbeMinBytes)));
Stefan Holmere5904162015-03-26 11:11:06 +0100225
eladalonb1338fe2017-08-01 09:36:19 -0700226 packet_router.RemoveSendRtpModule(&rtp_2);
Peter Boström3dd5d1d2016-02-25 16:56:48 +0100227}
228
eladalonb1338fe2017-08-01 09:36:19 -0700229TEST(PacketRouterTest, SenderOnlyFunctionsRespectSendingMedia) {
230 PacketRouter packet_router;
eladalon6c9556e2017-07-10 03:33:00 -0700231 NiceMock<MockRtpRtcp> rtp;
eladalonb1338fe2017-08-01 09:36:19 -0700232 packet_router.AddSendRtpModule(&rtp, false);
Peter Boström3dd5d1d2016-02-25 16:56:48 +0100233 static const uint16_t kSsrc = 1234;
234 EXPECT_CALL(rtp, SSRC()).WillRepeatedly(Return(kSsrc));
235 EXPECT_CALL(rtp, SendingMedia()).WillRepeatedly(Return(false));
236
237 // Verify that TimeToSendPacket does not end up in a receiver.
philipela1ed0b32016-06-01 06:31:17 -0700238 EXPECT_CALL(rtp, TimeToSendPacket(_, _, _, _, _)).Times(0);
eladalonb1338fe2017-08-01 09:36:19 -0700239 EXPECT_TRUE(packet_router.TimeToSendPacket(
philipelc7bf32a2017-02-17 03:59:43 -0800240 kSsrc, 1, 1, false, PacedPacketInfo(PacedPacketInfo::kNotAProbe,
241 kProbeMinBytes, kProbeMinBytes)));
Peter Boström3dd5d1d2016-02-25 16:56:48 +0100242 // Verify that TimeToSendPadding does not end up in a receiver.
philipela1ed0b32016-06-01 06:31:17 -0700243 EXPECT_CALL(rtp, TimeToSendPadding(_, _)).Times(0);
philipelc7bf32a2017-02-17 03:59:43 -0800244 EXPECT_EQ(0u,
eladalonb1338fe2017-08-01 09:36:19 -0700245 packet_router.TimeToSendPadding(
philipelc7bf32a2017-02-17 03:59:43 -0800246 200, PacedPacketInfo(PacedPacketInfo::kNotAProbe,
247 kProbeMinBytes, kProbeMinBytes)));
Peter Boström3dd5d1d2016-02-25 16:56:48 +0100248
eladalonb1338fe2017-08-01 09:36:19 -0700249 packet_router.RemoveSendRtpModule(&rtp);
Stefan Holmere5904162015-03-26 11:11:06 +0100250}
sprang867fb522015-08-03 04:38:41 -0700251
eladalonb1338fe2017-08-01 09:36:19 -0700252TEST(PacketRouterTest, AllocateSequenceNumbers) {
253 PacketRouter packet_router;
254
sprang867fb522015-08-03 04:38:41 -0700255 const uint16_t kStartSeq = 0xFFF0;
256 const size_t kNumPackets = 32;
257
eladalonb1338fe2017-08-01 09:36:19 -0700258 packet_router.SetTransportWideSequenceNumber(kStartSeq - 1);
sprang867fb522015-08-03 04:38:41 -0700259
260 for (size_t i = 0; i < kNumPackets; ++i) {
eladalonb1338fe2017-08-01 09:36:19 -0700261 uint16_t seq = packet_router.AllocateSequenceNumber();
sprang867fb522015-08-03 04:38:41 -0700262 uint32_t expected_unwrapped_seq = static_cast<uint32_t>(kStartSeq) + i;
263 EXPECT_EQ(static_cast<uint16_t>(expected_unwrapped_seq & 0xFFFF), seq);
264 }
265}
stefanbba9dec2016-02-01 04:39:55 -0800266
eladalonb1338fe2017-08-01 09:36:19 -0700267TEST(PacketRouterTest, SendTransportFeedback) {
268 PacketRouter packet_router;
eladalon6c9556e2017-07-10 03:33:00 -0700269 NiceMock<MockRtpRtcp> rtp_1;
270 NiceMock<MockRtpRtcp> rtp_2;
eladalonb1338fe2017-08-01 09:36:19 -0700271
272 packet_router.AddSendRtpModule(&rtp_1, false);
273 packet_router.AddReceiveRtpModule(&rtp_2, false);
stefanbba9dec2016-02-01 04:39:55 -0800274
275 rtcp::TransportFeedback feedback;
nisse05843312017-04-18 23:38:35 -0700276 EXPECT_CALL(rtp_1, SendFeedbackPacket(_)).Times(1).WillOnce(Return(true));
eladalonb1338fe2017-08-01 09:36:19 -0700277 packet_router.SendTransportFeedback(&feedback);
278 packet_router.RemoveSendRtpModule(&rtp_1);
nisse05843312017-04-18 23:38:35 -0700279 EXPECT_CALL(rtp_2, SendFeedbackPacket(_)).Times(1).WillOnce(Return(true));
eladalonb1338fe2017-08-01 09:36:19 -0700280 packet_router.SendTransportFeedback(&feedback);
281 packet_router.RemoveReceiveRtpModule(&rtp_2);
stefanbba9dec2016-02-01 04:39:55 -0800282}
nisse05843312017-04-18 23:38:35 -0700283
eladalon822ff2b2017-08-01 06:30:28 -0700284#if RTC_DCHECK_IS_ON && GTEST_HAS_DEATH_TEST && !defined(WEBRTC_ANDROID)
eladalonb1338fe2017-08-01 09:36:19 -0700285TEST(PacketRouterTest, DoubleRegistrationOfSendModuleDisallowed) {
286 PacketRouter packet_router;
eladalon822ff2b2017-08-01 06:30:28 -0700287 NiceMock<MockRtpRtcp> module;
288
289 constexpr bool remb_candidate = false; // Value irrelevant.
eladalonb1338fe2017-08-01 09:36:19 -0700290 packet_router.AddSendRtpModule(&module, remb_candidate);
291 EXPECT_DEATH(packet_router.AddSendRtpModule(&module, remb_candidate), "");
eladalon822ff2b2017-08-01 06:30:28 -0700292
293 // Test tear-down
eladalonb1338fe2017-08-01 09:36:19 -0700294 packet_router.RemoveSendRtpModule(&module);
eladalon822ff2b2017-08-01 06:30:28 -0700295}
296
eladalonb1338fe2017-08-01 09:36:19 -0700297TEST(PacketRouterTest, DoubleRegistrationOfReceiveModuleDisallowed) {
298 PacketRouter packet_router;
eladalon822ff2b2017-08-01 06:30:28 -0700299 NiceMock<MockRtpRtcp> module;
300
301 constexpr bool remb_candidate = false; // Value irrelevant.
eladalonb1338fe2017-08-01 09:36:19 -0700302 packet_router.AddReceiveRtpModule(&module, remb_candidate);
303 EXPECT_DEATH(packet_router.AddReceiveRtpModule(&module, remb_candidate), "");
eladalon822ff2b2017-08-01 06:30:28 -0700304
305 // Test tear-down
eladalonb1338fe2017-08-01 09:36:19 -0700306 packet_router.RemoveReceiveRtpModule(&module);
eladalon822ff2b2017-08-01 06:30:28 -0700307}
308
eladalonb1338fe2017-08-01 09:36:19 -0700309TEST(PacketRouterTest, RemovalOfNeverAddedSendModuleDisallowed) {
310 PacketRouter packet_router;
eladalon822ff2b2017-08-01 06:30:28 -0700311 NiceMock<MockRtpRtcp> module;
312
eladalonb1338fe2017-08-01 09:36:19 -0700313 EXPECT_DEATH(packet_router.RemoveSendRtpModule(&module), "");
eladalon822ff2b2017-08-01 06:30:28 -0700314}
315
eladalonb1338fe2017-08-01 09:36:19 -0700316TEST(PacketRouterTest, RemovalOfNeverAddedReceiveModuleDisallowed) {
317 PacketRouter packet_router;
eladalon822ff2b2017-08-01 06:30:28 -0700318 NiceMock<MockRtpRtcp> module;
319
eladalonb1338fe2017-08-01 09:36:19 -0700320 EXPECT_DEATH(packet_router.RemoveReceiveRtpModule(&module), "");
eladalon822ff2b2017-08-01 06:30:28 -0700321}
322#endif // RTC_DCHECK_IS_ON && GTEST_HAS_DEATH_TEST && !defined(WEBRTC_ANDROID)
323
324// TODO(eladalon): Remove this test; it should be covered by:
325// 1. SendCandidatePreferredOverReceiveCandidate_SendModuleAddedFirst
326// 2. SendCandidatePreferredOverReceiveCandidate_ReceiveModuleAddedFirst
327// 3. LowerEstimateToSendRemb
328// (Not removing in this CL to prove it doesn't break this test.)
nisse05843312017-04-18 23:38:35 -0700329TEST(PacketRouterRembTest, PreferSendModuleOverReceiveModule) {
330 rtc::ScopedFakeClock clock;
eladalon822ff2b2017-08-01 06:30:28 -0700331 NiceMock<MockRtpRtcpWithRembTracking> rtp_recv;
332 NiceMock<MockRtpRtcpWithRembTracking> rtp_send;
nisse05843312017-04-18 23:38:35 -0700333 PacketRouter packet_router;
334
eladalon822ff2b2017-08-01 06:30:28 -0700335 packet_router.AddReceiveRtpModule(&rtp_recv, true);
336 ASSERT_TRUE(rtp_recv.REMB());
nisse05843312017-04-18 23:38:35 -0700337
338 const uint32_t bitrate_estimate = 456;
339 const std::vector<uint32_t> ssrcs = {1234};
340
nisse05843312017-04-18 23:38:35 -0700341 packet_router.OnReceiveBitrateChanged(ssrcs, bitrate_estimate);
342
343 // Call OnReceiveBitrateChanged twice to get a first estimate.
344 clock.AdvanceTime(rtc::TimeDelta::FromMilliseconds(1000));
345 EXPECT_CALL(rtp_recv, SetREMBData(bitrate_estimate, ssrcs)).Times(1);
346 packet_router.OnReceiveBitrateChanged(ssrcs, bitrate_estimate);
347
348 // Add a send module, which should be preferred over the receive module.
eladalon822ff2b2017-08-01 06:30:28 -0700349 packet_router.AddSendRtpModule(&rtp_send, true);
350 EXPECT_FALSE(rtp_recv.REMB());
351 EXPECT_TRUE(rtp_send.REMB());
nisse05843312017-04-18 23:38:35 -0700352
353 // Lower bitrate to send another REMB packet.
354 EXPECT_CALL(rtp_send, SetREMBData(bitrate_estimate - 100, ssrcs)).Times(1);
355 packet_router.OnReceiveBitrateChanged(ssrcs, bitrate_estimate - 100);
356
nisse05843312017-04-18 23:38:35 -0700357 packet_router.RemoveSendRtpModule(&rtp_send);
eladalon822ff2b2017-08-01 06:30:28 -0700358 EXPECT_TRUE(rtp_recv.REMB());
359 EXPECT_FALSE(rtp_send.REMB());
360
nisse05843312017-04-18 23:38:35 -0700361 packet_router.RemoveReceiveRtpModule(&rtp_recv);
362}
363
364TEST(PacketRouterRembTest, LowerEstimateToSendRemb) {
365 rtc::ScopedFakeClock clock;
eladalon822ff2b2017-08-01 06:30:28 -0700366 NiceMock<MockRtpRtcpWithRembTracking> rtp;
nisse05843312017-04-18 23:38:35 -0700367 PacketRouter packet_router;
368
eladalon822ff2b2017-08-01 06:30:28 -0700369 packet_router.AddSendRtpModule(&rtp, true);
370 EXPECT_TRUE(rtp.REMB());
nisse05843312017-04-18 23:38:35 -0700371
372 uint32_t bitrate_estimate = 456;
373 const std::vector<uint32_t> ssrcs = {1234};
374
nisse05843312017-04-18 23:38:35 -0700375 packet_router.OnReceiveBitrateChanged(ssrcs, bitrate_estimate);
376
377 // Call OnReceiveBitrateChanged twice to get a first estimate.
378 clock.AdvanceTime(rtc::TimeDelta::FromMilliseconds(1000));
379 EXPECT_CALL(rtp, SetREMBData(bitrate_estimate, ssrcs)).Times(1);
380 packet_router.OnReceiveBitrateChanged(ssrcs, bitrate_estimate);
381
382 // Lower the estimate with more than 3% to trigger a call to SetREMBData right
383 // away.
384 bitrate_estimate = bitrate_estimate - 100;
385 EXPECT_CALL(rtp, SetREMBData(bitrate_estimate, ssrcs)).Times(1);
386 packet_router.OnReceiveBitrateChanged(ssrcs, bitrate_estimate);
387
nisse05843312017-04-18 23:38:35 -0700388 packet_router.RemoveSendRtpModule(&rtp);
eladalon822ff2b2017-08-01 06:30:28 -0700389 EXPECT_FALSE(rtp.REMB());
nisse05843312017-04-18 23:38:35 -0700390}
391
392TEST(PacketRouterRembTest, VerifyIncreasingAndDecreasing) {
393 rtc::ScopedFakeClock clock;
eladalon6c9556e2017-07-10 03:33:00 -0700394 NiceMock<MockRtpRtcp> rtp;
nisse05843312017-04-18 23:38:35 -0700395 PacketRouter packet_router;
eladalon822ff2b2017-08-01 06:30:28 -0700396 packet_router.AddSendRtpModule(&rtp, true);
nisse05843312017-04-18 23:38:35 -0700397
398 uint32_t bitrate_estimate[] = {456, 789};
399 std::vector<uint32_t> ssrcs = {1234, 5678};
400
401 ON_CALL(rtp, REMB()).WillByDefault(Return(true));
402 packet_router.OnReceiveBitrateChanged(ssrcs, bitrate_estimate[0]);
403
404 // Call OnReceiveBitrateChanged twice to get a first estimate.
405 EXPECT_CALL(rtp, SetREMBData(bitrate_estimate[0], ssrcs)).Times(1);
406 clock.AdvanceTime(rtc::TimeDelta::FromMilliseconds(1000));
407 packet_router.OnReceiveBitrateChanged(ssrcs, bitrate_estimate[0]);
408
409 packet_router.OnReceiveBitrateChanged(ssrcs, bitrate_estimate[1] + 100);
410
411 // Lower the estimate to trigger a callback.
412 EXPECT_CALL(rtp, SetREMBData(bitrate_estimate[1], ssrcs)).Times(1);
413 packet_router.OnReceiveBitrateChanged(ssrcs, bitrate_estimate[1]);
414
415 packet_router.RemoveSendRtpModule(&rtp);
416}
417
418TEST(PacketRouterRembTest, NoRembForIncreasedBitrate) {
419 rtc::ScopedFakeClock clock;
eladalon6c9556e2017-07-10 03:33:00 -0700420 NiceMock<MockRtpRtcp> rtp;
nisse05843312017-04-18 23:38:35 -0700421 PacketRouter packet_router;
eladalon822ff2b2017-08-01 06:30:28 -0700422 packet_router.AddSendRtpModule(&rtp, true);
nisse05843312017-04-18 23:38:35 -0700423
424 uint32_t bitrate_estimate = 456;
425 std::vector<uint32_t> ssrcs = {1234, 5678};
426
427 ON_CALL(rtp, REMB()).WillByDefault(Return(true));
428 packet_router.OnReceiveBitrateChanged(ssrcs, bitrate_estimate);
429
430 // Call OnReceiveBitrateChanged twice to get a first estimate.
431 EXPECT_CALL(rtp, SetREMBData(bitrate_estimate, ssrcs)).Times(1);
432 clock.AdvanceTime(rtc::TimeDelta::FromMilliseconds(1000));
433 packet_router.OnReceiveBitrateChanged(ssrcs, bitrate_estimate);
434
435 // Increased estimate shouldn't trigger a callback right away.
436 EXPECT_CALL(rtp, SetREMBData(_, _)).Times(0);
437 packet_router.OnReceiveBitrateChanged(ssrcs, bitrate_estimate + 1);
438
439 // Decreasing the estimate less than 3% shouldn't trigger a new callback.
440 EXPECT_CALL(rtp, SetREMBData(_, _)).Times(0);
441 int lower_estimate = bitrate_estimate * 98 / 100;
442 packet_router.OnReceiveBitrateChanged(ssrcs, lower_estimate);
443
444 packet_router.RemoveSendRtpModule(&rtp);
445}
446
447TEST(PacketRouterRembTest, ChangeSendRtpModule) {
448 rtc::ScopedFakeClock clock;
eladalon6c9556e2017-07-10 03:33:00 -0700449 NiceMock<MockRtpRtcp> rtp_send;
450 NiceMock<MockRtpRtcp> rtp_recv;
nisse05843312017-04-18 23:38:35 -0700451 PacketRouter packet_router;
eladalon822ff2b2017-08-01 06:30:28 -0700452 packet_router.AddSendRtpModule(&rtp_send, true);
453 packet_router.AddReceiveRtpModule(&rtp_recv, true);
nisse05843312017-04-18 23:38:35 -0700454
455 uint32_t bitrate_estimate = 456;
456 std::vector<uint32_t> ssrcs = {1234, 5678};
457
458 ON_CALL(rtp_send, REMB()).WillByDefault(Return(true));
459 packet_router.OnReceiveBitrateChanged(ssrcs, bitrate_estimate);
460
461 // Call OnReceiveBitrateChanged twice to get a first estimate.
462 clock.AdvanceTime(rtc::TimeDelta::FromMilliseconds(1000));
463 EXPECT_CALL(rtp_send, SetREMBData(bitrate_estimate, ssrcs)).Times(1);
464 packet_router.OnReceiveBitrateChanged(ssrcs, bitrate_estimate);
465
466 // Decrease estimate to trigger a REMB.
467 bitrate_estimate = bitrate_estimate - 100;
468 EXPECT_CALL(rtp_send, SetREMBData(bitrate_estimate, ssrcs)).Times(1);
469 packet_router.OnReceiveBitrateChanged(ssrcs, bitrate_estimate);
470
471 // Remove the sending module -> should get remb on the second module.
472 packet_router.RemoveSendRtpModule(&rtp_send);
473
474 ON_CALL(rtp_send, REMB()).WillByDefault(Return(false));
475 ON_CALL(rtp_recv, REMB()).WillByDefault(Return(true));
476
477 packet_router.OnReceiveBitrateChanged(ssrcs, bitrate_estimate);
478
479 bitrate_estimate = bitrate_estimate - 100;
480 EXPECT_CALL(rtp_recv, SetREMBData(bitrate_estimate, ssrcs)).Times(1);
481 packet_router.OnReceiveBitrateChanged(ssrcs, bitrate_estimate);
482
483 packet_router.RemoveReceiveRtpModule(&rtp_recv);
484}
485
486TEST(PacketRouterRembTest, OnlyOneRembForRepeatedOnReceiveBitrateChanged) {
487 rtc::ScopedFakeClock clock;
eladalon6c9556e2017-07-10 03:33:00 -0700488 NiceMock<MockRtpRtcp> rtp;
nisse05843312017-04-18 23:38:35 -0700489 PacketRouter packet_router;
eladalon822ff2b2017-08-01 06:30:28 -0700490 packet_router.AddSendRtpModule(&rtp, true);
nisse05843312017-04-18 23:38:35 -0700491
492 uint32_t bitrate_estimate = 456;
493 const std::vector<uint32_t> ssrcs = {1234};
494
495 ON_CALL(rtp, REMB()).WillByDefault(Return(true));
496 packet_router.OnReceiveBitrateChanged(ssrcs, bitrate_estimate);
497
498 // Call OnReceiveBitrateChanged twice to get a first estimate.
499 clock.AdvanceTime(rtc::TimeDelta::FromMilliseconds(1000));
500 EXPECT_CALL(rtp, SetREMBData(_, _)).Times(1);
501 packet_router.OnReceiveBitrateChanged(ssrcs, bitrate_estimate);
502
503 // Lower the estimate, should trigger a call to SetREMBData right away.
504 bitrate_estimate = bitrate_estimate - 100;
505 EXPECT_CALL(rtp, SetREMBData(bitrate_estimate, ssrcs)).Times(1);
506 packet_router.OnReceiveBitrateChanged(ssrcs, bitrate_estimate);
507
508 // Call OnReceiveBitrateChanged again, this should not trigger a new callback.
509 EXPECT_CALL(rtp, SetREMBData(_, _)).Times(0);
510 packet_router.OnReceiveBitrateChanged(ssrcs, bitrate_estimate);
511 packet_router.RemoveSendRtpModule(&rtp);
512}
513
514// Only register receiving modules and make sure we fallback to trigger a REMB
515// packet on this one.
516TEST(PacketRouterRembTest, NoSendingRtpModule) {
517 rtc::ScopedFakeClock clock;
eladalon6c9556e2017-07-10 03:33:00 -0700518 NiceMock<MockRtpRtcp> rtp;
nisse05843312017-04-18 23:38:35 -0700519 PacketRouter packet_router;
520
521 EXPECT_CALL(rtp, SetREMBStatus(true)).Times(1);
eladalon822ff2b2017-08-01 06:30:28 -0700522 packet_router.AddReceiveRtpModule(&rtp, true);
nisse05843312017-04-18 23:38:35 -0700523
524 uint32_t bitrate_estimate = 456;
525 const std::vector<uint32_t> ssrcs = {1234};
526
527 ON_CALL(rtp, REMB()).WillByDefault(Return(true));
528 packet_router.OnReceiveBitrateChanged(ssrcs, bitrate_estimate);
529
530 // Call OnReceiveBitrateChanged twice to get a first estimate.
531 clock.AdvanceTime(rtc::TimeDelta::FromMilliseconds(1000));
532 EXPECT_CALL(rtp, SetREMBData(bitrate_estimate, ssrcs)).Times(1);
533 packet_router.OnReceiveBitrateChanged(ssrcs, bitrate_estimate);
534
535 // Lower the estimate to trigger a new packet REMB packet.
536 EXPECT_CALL(rtp, SetREMBData(bitrate_estimate - 100, ssrcs)).Times(1);
537 packet_router.OnReceiveBitrateChanged(ssrcs, bitrate_estimate - 100);
538
539 EXPECT_CALL(rtp, SetREMBStatus(false)).Times(1);
540 packet_router.RemoveReceiveRtpModule(&rtp);
541}
542
eladalon822ff2b2017-08-01 06:30:28 -0700543TEST(PacketRouterRembTest, NonCandidateSendRtpModuleNotUsedForRemb) {
544 rtc::ScopedFakeClock clock;
545 PacketRouter packet_router;
546 NiceMock<MockRtpRtcpWithRembTracking> module;
547
548 constexpr bool remb_candidate = false;
549
550 packet_router.AddSendRtpModule(&module, remb_candidate);
551 EXPECT_FALSE(module.REMB());
552
553 constexpr uint32_t bitrate_estimate = 456;
554 const std::vector<uint32_t> ssrcs = {1234};
555 EXPECT_CALL(module, SetREMBData(_, _)).Times(0);
556 clock.AdvanceTime(rtc::TimeDelta::FromMilliseconds(1000));
557 packet_router.OnReceiveBitrateChanged(ssrcs, bitrate_estimate);
558
559 // Test tear-down
560 packet_router.RemoveSendRtpModule(&module);
561}
562
563TEST(PacketRouterRembTest, CandidateSendRtpModuleUsedForRemb) {
564 rtc::ScopedFakeClock clock;
565 PacketRouter packet_router;
566 NiceMock<MockRtpRtcpWithRembTracking> module;
567
568 constexpr bool remb_candidate = true;
569
570 packet_router.AddSendRtpModule(&module, remb_candidate);
571 EXPECT_TRUE(module.REMB());
572
573 constexpr uint32_t bitrate_estimate = 456;
574 const std::vector<uint32_t> ssrcs = {1234};
575 EXPECT_CALL(module, SetREMBData(bitrate_estimate, ssrcs)).Times(1);
576 clock.AdvanceTime(rtc::TimeDelta::FromMilliseconds(1000));
577 packet_router.OnReceiveBitrateChanged(ssrcs, bitrate_estimate);
578
579 // Test tear-down
580 packet_router.RemoveSendRtpModule(&module);
581}
582
583TEST(PacketRouterRembTest, NonCandidateReceiveRtpModuleNotUsedForRemb) {
584 rtc::ScopedFakeClock clock;
585 PacketRouter packet_router;
586 NiceMock<MockRtpRtcpWithRembTracking> module;
587
588 constexpr bool remb_candidate = false;
589
590 packet_router.AddReceiveRtpModule(&module, remb_candidate);
591 ASSERT_FALSE(module.REMB());
592
593 constexpr uint32_t bitrate_estimate = 456;
594 const std::vector<uint32_t> ssrcs = {1234};
595 EXPECT_CALL(module, SetREMBData(_, _)).Times(0);
596 clock.AdvanceTime(rtc::TimeDelta::FromMilliseconds(1000));
597 packet_router.OnReceiveBitrateChanged(ssrcs, bitrate_estimate);
598
599 // Test tear-down
600 packet_router.RemoveReceiveRtpModule(&module);
601}
602
603TEST(PacketRouterRembTest, CandidateReceiveRtpModuleUsedForRemb) {
604 rtc::ScopedFakeClock clock;
605 PacketRouter packet_router;
606 NiceMock<MockRtpRtcpWithRembTracking> module;
607
608 constexpr bool remb_candidate = true;
609
610 packet_router.AddReceiveRtpModule(&module, remb_candidate);
611 EXPECT_TRUE(module.REMB());
612
613 constexpr uint32_t bitrate_estimate = 456;
614 const std::vector<uint32_t> ssrcs = {1234};
615 EXPECT_CALL(module, SetREMBData(bitrate_estimate, ssrcs)).Times(1);
616 clock.AdvanceTime(rtc::TimeDelta::FromMilliseconds(1000));
617 packet_router.OnReceiveBitrateChanged(ssrcs, bitrate_estimate);
618
619 // Test tear-down
620 packet_router.RemoveReceiveRtpModule(&module);
621}
622
623TEST(PacketRouterRembTest,
624 SendCandidatePreferredOverReceiveCandidate_SendModuleAddedFirst) {
625 rtc::ScopedFakeClock clock;
626 PacketRouter packet_router;
627 NiceMock<MockRtpRtcpWithRembTracking> send_module;
628 NiceMock<MockRtpRtcpWithRembTracking> receive_module;
629
630 constexpr bool remb_candidate = true;
631
632 // Send module added - activated.
633 packet_router.AddSendRtpModule(&send_module, remb_candidate);
634 ASSERT_TRUE(send_module.REMB());
635
636 // Receive module added - the send module remains the active one.
637 packet_router.AddReceiveRtpModule(&receive_module, remb_candidate);
638 EXPECT_TRUE(send_module.REMB());
639 EXPECT_FALSE(receive_module.REMB());
640
641 constexpr uint32_t bitrate_estimate = 456;
642 const std::vector<uint32_t> ssrcs = {1234};
643 EXPECT_CALL(send_module, SetREMBData(bitrate_estimate, ssrcs)).Times(1);
644 EXPECT_CALL(receive_module, SetREMBData(_, _)).Times(0);
645
646 clock.AdvanceTime(rtc::TimeDelta::FromMilliseconds(1000));
647 packet_router.OnReceiveBitrateChanged(ssrcs, bitrate_estimate);
648
649 // Test tear-down
650 packet_router.RemoveReceiveRtpModule(&receive_module);
651 packet_router.RemoveSendRtpModule(&send_module);
652}
653
654TEST(PacketRouterRembTest,
655 SendCandidatePreferredOverReceiveCandidate_ReceiveModuleAddedFirst) {
656 rtc::ScopedFakeClock clock;
657 PacketRouter packet_router;
658 NiceMock<MockRtpRtcpWithRembTracking> send_module;
659 NiceMock<MockRtpRtcpWithRembTracking> receive_module;
660
661 constexpr bool remb_candidate = true;
662
663 // Receive module added - activated.
664 packet_router.AddReceiveRtpModule(&receive_module, remb_candidate);
665 ASSERT_TRUE(receive_module.REMB());
666
667 // Send module added - replaces receive module as active.
668 packet_router.AddSendRtpModule(&send_module, remb_candidate);
669 EXPECT_FALSE(receive_module.REMB());
670 EXPECT_TRUE(send_module.REMB());
671
672 constexpr uint32_t bitrate_estimate = 456;
673 const std::vector<uint32_t> ssrcs = {1234};
674 EXPECT_CALL(send_module, SetREMBData(bitrate_estimate, ssrcs)).Times(1);
675 EXPECT_CALL(receive_module, SetREMBData(_, _)).Times(0);
676
677 clock.AdvanceTime(rtc::TimeDelta::FromMilliseconds(1000));
678 packet_router.OnReceiveBitrateChanged(ssrcs, bitrate_estimate);
679
680 // Test tear-down
681 packet_router.RemoveReceiveRtpModule(&receive_module);
682 packet_router.RemoveSendRtpModule(&send_module);
683}
684
685TEST(PacketRouterRembTest, ReceiveModuleTakesOverWhenLastSendModuleRemoved) {
686 rtc::ScopedFakeClock clock;
687 PacketRouter packet_router;
688 NiceMock<MockRtpRtcpWithRembTracking> send_module;
689 NiceMock<MockRtpRtcpWithRembTracking> receive_module;
690
691 constexpr bool remb_candidate = true;
692
693 // Send module active, receive module inactive.
694 packet_router.AddSendRtpModule(&send_module, remb_candidate);
695 packet_router.AddReceiveRtpModule(&receive_module, remb_candidate);
696 ASSERT_TRUE(send_module.REMB());
697 ASSERT_FALSE(receive_module.REMB());
698
699 // Send module removed - receive module becomes active.
700 packet_router.RemoveSendRtpModule(&send_module);
701 EXPECT_FALSE(send_module.REMB());
702 EXPECT_TRUE(receive_module.REMB());
703 constexpr uint32_t bitrate_estimate = 456;
704 const std::vector<uint32_t> ssrcs = {1234};
705 EXPECT_CALL(send_module, SetREMBData(_, _)).Times(0);
706 EXPECT_CALL(receive_module, SetREMBData(bitrate_estimate, ssrcs)).Times(1);
707
708 clock.AdvanceTime(rtc::TimeDelta::FromMilliseconds(1000));
709 packet_router.OnReceiveBitrateChanged(ssrcs, bitrate_estimate);
710
711 // Test tear-down
712 packet_router.RemoveReceiveRtpModule(&receive_module);
713}
714
Stefan Holmere5904162015-03-26 11:11:06 +0100715} // namespace webrtc