1 /* Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
2 *
3 * Use of this source code is governed by a BSD-style license
4 * that can be found in the LICENSE file in the root of the source
5 * tree. An additional intellectual property rights grant can be found
6 * in the file PATENTS. All contributing project authors may
7 * be found in the AUTHORS file in the root of the source tree.
8 */
9
10 #include <string.h>
11
12 #include <list>
13 #include <memory>
14 #include <queue>
15 #include <vector>
16
17 #include "modules/video_coding/encoded_frame.h"
18 #include "modules/video_coding/packet.h"
19 #include "modules/video_coding/receiver.h"
20 #include "modules/video_coding/test/stream_generator.h"
21 #include "modules/video_coding/test/test_util.h"
22 #include "modules/video_coding/timing.h"
23 #include "rtc_base/checks.h"
24 #include "system_wrappers/include/clock.h"
25 #include "test/gtest.h"
26
27 namespace webrtc {
28
29 class TestVCMReceiver : public ::testing::Test {
30 protected:
TestVCMReceiver()31 TestVCMReceiver()
32 : clock_(new SimulatedClock(0)),
33 timing_(clock_.get()),
34 receiver_(&timing_, clock_.get(), &event_factory_) {
35 stream_generator_.reset(
36 new StreamGenerator(0, clock_->TimeInMilliseconds()));
37 }
38
SetUp()39 virtual void SetUp() { receiver_.Reset(); }
40
InsertPacket(int index)41 int32_t InsertPacket(int index) {
42 VCMPacket packet;
43 bool packet_available = stream_generator_->GetPacket(&packet, index);
44 EXPECT_TRUE(packet_available);
45 if (!packet_available)
46 return kGeneralError; // Return here to avoid crashes below.
47 return receiver_.InsertPacket(packet);
48 }
49
InsertPacketAndPop(int index)50 int32_t InsertPacketAndPop(int index) {
51 VCMPacket packet;
52 bool packet_available = stream_generator_->PopPacket(&packet, index);
53 EXPECT_TRUE(packet_available);
54 if (!packet_available)
55 return kGeneralError; // Return here to avoid crashes below.
56 return receiver_.InsertPacket(packet);
57 }
58
InsertFrame(FrameType frame_type,bool complete)59 int32_t InsertFrame(FrameType frame_type, bool complete) {
60 int num_of_packets = complete ? 1 : 2;
61 stream_generator_->GenerateFrame(
62 frame_type, (frame_type != kEmptyFrame) ? num_of_packets : 0,
63 (frame_type == kEmptyFrame) ? 1 : 0, clock_->TimeInMilliseconds());
64 int32_t ret = InsertPacketAndPop(0);
65 if (!complete) {
66 // Drop the second packet.
67 VCMPacket packet;
68 stream_generator_->PopPacket(&packet, 0);
69 }
70 clock_->AdvanceTimeMilliseconds(kDefaultFramePeriodMs);
71 return ret;
72 }
73
DecodeNextFrame()74 bool DecodeNextFrame() {
75 VCMEncodedFrame* frame = receiver_.FrameForDecoding(0, false);
76 if (!frame)
77 return false;
78 receiver_.ReleaseFrame(frame);
79 return true;
80 }
81
82 std::unique_ptr<SimulatedClock> clock_;
83 VCMTiming timing_;
84 NullEventFactory event_factory_;
85 VCMReceiver receiver_;
86 std::unique_ptr<StreamGenerator> stream_generator_;
87 };
88
TEST_F(TestVCMReceiver,NonDecodableDuration_Empty)89 TEST_F(TestVCMReceiver, NonDecodableDuration_Empty) {
90 // Enable NACK and with no RTT thresholds for disabling retransmission delay.
91 receiver_.SetNackMode(kNack, -1, -1);
92 const size_t kMaxNackListSize = 1000;
93 const int kMaxPacketAgeToNack = 1000;
94 const int kMaxNonDecodableDuration = 500;
95 const int kMinDelayMs = 500;
96 receiver_.SetNackSettings(kMaxNackListSize, kMaxPacketAgeToNack,
97 kMaxNonDecodableDuration);
98 EXPECT_GE(InsertFrame(kVideoFrameKey, true), kNoError);
99 // Advance time until it's time to decode the key frame.
100 clock_->AdvanceTimeMilliseconds(kMinDelayMs);
101 EXPECT_TRUE(DecodeNextFrame());
102 bool request_key_frame = false;
103 std::vector<uint16_t> nack_list = receiver_.NackList(&request_key_frame);
104 EXPECT_FALSE(request_key_frame);
105 }
106
TEST_F(TestVCMReceiver,NonDecodableDuration_NoKeyFrame)107 TEST_F(TestVCMReceiver, NonDecodableDuration_NoKeyFrame) {
108 // Enable NACK and with no RTT thresholds for disabling retransmission delay.
109 receiver_.SetNackMode(kNack, -1, -1);
110 const size_t kMaxNackListSize = 1000;
111 const int kMaxPacketAgeToNack = 1000;
112 const int kMaxNonDecodableDuration = 500;
113 receiver_.SetNackSettings(kMaxNackListSize, kMaxPacketAgeToNack,
114 kMaxNonDecodableDuration);
115 const int kNumFrames = kDefaultFrameRate * kMaxNonDecodableDuration / 1000;
116 for (int i = 0; i < kNumFrames; ++i) {
117 EXPECT_GE(InsertFrame(kVideoFrameDelta, true), kNoError);
118 }
119 bool request_key_frame = false;
120 std::vector<uint16_t> nack_list = receiver_.NackList(&request_key_frame);
121 EXPECT_TRUE(request_key_frame);
122 }
123
TEST_F(TestVCMReceiver,NonDecodableDuration_OneIncomplete)124 TEST_F(TestVCMReceiver, NonDecodableDuration_OneIncomplete) {
125 // Enable NACK and with no RTT thresholds for disabling retransmission delay.
126 receiver_.SetNackMode(kNack, -1, -1);
127 const size_t kMaxNackListSize = 1000;
128 const int kMaxPacketAgeToNack = 1000;
129 const int kMaxNonDecodableDuration = 500;
130 const int kMaxNonDecodableDurationFrames =
131 (kDefaultFrameRate * kMaxNonDecodableDuration + 500) / 1000;
132 const int kMinDelayMs = 500;
133 receiver_.SetNackSettings(kMaxNackListSize, kMaxPacketAgeToNack,
134 kMaxNonDecodableDuration);
135 receiver_.SetMinReceiverDelay(kMinDelayMs);
136 int64_t key_frame_inserted = clock_->TimeInMilliseconds();
137 EXPECT_GE(InsertFrame(kVideoFrameKey, true), kNoError);
138 // Insert an incomplete frame.
139 EXPECT_GE(InsertFrame(kVideoFrameDelta, false), kNoError);
140 // Insert enough frames to have too long non-decodable sequence.
141 for (int i = 0; i < kMaxNonDecodableDurationFrames; ++i) {
142 EXPECT_GE(InsertFrame(kVideoFrameDelta, true), kNoError);
143 }
144 // Advance time until it's time to decode the key frame.
145 clock_->AdvanceTimeMilliseconds(kMinDelayMs - clock_->TimeInMilliseconds() -
146 key_frame_inserted);
147 EXPECT_TRUE(DecodeNextFrame());
148 // Make sure we get a key frame request.
149 bool request_key_frame = false;
150 std::vector<uint16_t> nack_list = receiver_.NackList(&request_key_frame);
151 EXPECT_TRUE(request_key_frame);
152 }
153
TEST_F(TestVCMReceiver,NonDecodableDuration_NoTrigger)154 TEST_F(TestVCMReceiver, NonDecodableDuration_NoTrigger) {
155 // Enable NACK and with no RTT thresholds for disabling retransmission delay.
156 receiver_.SetNackMode(kNack, -1, -1);
157 const size_t kMaxNackListSize = 1000;
158 const int kMaxPacketAgeToNack = 1000;
159 const int kMaxNonDecodableDuration = 500;
160 const int kMaxNonDecodableDurationFrames =
161 (kDefaultFrameRate * kMaxNonDecodableDuration + 500) / 1000;
162 const int kMinDelayMs = 500;
163 receiver_.SetNackSettings(kMaxNackListSize, kMaxPacketAgeToNack,
164 kMaxNonDecodableDuration);
165 receiver_.SetMinReceiverDelay(kMinDelayMs);
166 int64_t key_frame_inserted = clock_->TimeInMilliseconds();
167 EXPECT_GE(InsertFrame(kVideoFrameKey, true), kNoError);
168 // Insert an incomplete frame.
169 EXPECT_GE(InsertFrame(kVideoFrameDelta, false), kNoError);
170 // Insert all but one frame to not trigger a key frame request due to
171 // too long duration of non-decodable frames.
172 for (int i = 0; i < kMaxNonDecodableDurationFrames - 1; ++i) {
173 EXPECT_GE(InsertFrame(kVideoFrameDelta, true), kNoError);
174 }
175 // Advance time until it's time to decode the key frame.
176 clock_->AdvanceTimeMilliseconds(kMinDelayMs - clock_->TimeInMilliseconds() -
177 key_frame_inserted);
178 EXPECT_TRUE(DecodeNextFrame());
179 // Make sure we don't get a key frame request since we haven't generated
180 // enough frames.
181 bool request_key_frame = false;
182 std::vector<uint16_t> nack_list = receiver_.NackList(&request_key_frame);
183 EXPECT_FALSE(request_key_frame);
184 }
185
TEST_F(TestVCMReceiver,NonDecodableDuration_NoTrigger2)186 TEST_F(TestVCMReceiver, NonDecodableDuration_NoTrigger2) {
187 // Enable NACK and with no RTT thresholds for disabling retransmission delay.
188 receiver_.SetNackMode(kNack, -1, -1);
189 const size_t kMaxNackListSize = 1000;
190 const int kMaxPacketAgeToNack = 1000;
191 const int kMaxNonDecodableDuration = 500;
192 const int kMaxNonDecodableDurationFrames =
193 (kDefaultFrameRate * kMaxNonDecodableDuration + 500) / 1000;
194 const int kMinDelayMs = 500;
195 receiver_.SetNackSettings(kMaxNackListSize, kMaxPacketAgeToNack,
196 kMaxNonDecodableDuration);
197 receiver_.SetMinReceiverDelay(kMinDelayMs);
198 int64_t key_frame_inserted = clock_->TimeInMilliseconds();
199 EXPECT_GE(InsertFrame(kVideoFrameKey, true), kNoError);
200 // Insert enough frames to have too long non-decodable sequence, except that
201 // we don't have any losses.
202 for (int i = 0; i < kMaxNonDecodableDurationFrames; ++i) {
203 EXPECT_GE(InsertFrame(kVideoFrameDelta, true), kNoError);
204 }
205 // Insert an incomplete frame.
206 EXPECT_GE(InsertFrame(kVideoFrameDelta, false), kNoError);
207 // Advance time until it's time to decode the key frame.
208 clock_->AdvanceTimeMilliseconds(kMinDelayMs - clock_->TimeInMilliseconds() -
209 key_frame_inserted);
210 EXPECT_TRUE(DecodeNextFrame());
211 // Make sure we don't get a key frame request since the non-decodable duration
212 // is only one frame.
213 bool request_key_frame = false;
214 std::vector<uint16_t> nack_list = receiver_.NackList(&request_key_frame);
215 EXPECT_FALSE(request_key_frame);
216 }
217
TEST_F(TestVCMReceiver,NonDecodableDuration_KeyFrameAfterIncompleteFrames)218 TEST_F(TestVCMReceiver, NonDecodableDuration_KeyFrameAfterIncompleteFrames) {
219 // Enable NACK and with no RTT thresholds for disabling retransmission delay.
220 receiver_.SetNackMode(kNack, -1, -1);
221 const size_t kMaxNackListSize = 1000;
222 const int kMaxPacketAgeToNack = 1000;
223 const int kMaxNonDecodableDuration = 500;
224 const int kMaxNonDecodableDurationFrames =
225 (kDefaultFrameRate * kMaxNonDecodableDuration + 500) / 1000;
226 const int kMinDelayMs = 500;
227 receiver_.SetNackSettings(kMaxNackListSize, kMaxPacketAgeToNack,
228 kMaxNonDecodableDuration);
229 receiver_.SetMinReceiverDelay(kMinDelayMs);
230 int64_t key_frame_inserted = clock_->TimeInMilliseconds();
231 EXPECT_GE(InsertFrame(kVideoFrameKey, true), kNoError);
232 // Insert an incomplete frame.
233 EXPECT_GE(InsertFrame(kVideoFrameDelta, false), kNoError);
234 // Insert enough frames to have too long non-decodable sequence.
235 for (int i = 0; i < kMaxNonDecodableDurationFrames; ++i) {
236 EXPECT_GE(InsertFrame(kVideoFrameDelta, true), kNoError);
237 }
238 EXPECT_GE(InsertFrame(kVideoFrameKey, true), kNoError);
239 // Advance time until it's time to decode the key frame.
240 clock_->AdvanceTimeMilliseconds(kMinDelayMs - clock_->TimeInMilliseconds() -
241 key_frame_inserted);
242 EXPECT_TRUE(DecodeNextFrame());
243 // Make sure we don't get a key frame request since we have a key frame
244 // in the list.
245 bool request_key_frame = false;
246 std::vector<uint16_t> nack_list = receiver_.NackList(&request_key_frame);
247 EXPECT_FALSE(request_key_frame);
248 }
249
250 // A simulated clock, when time elapses, will insert frames into the jitter
251 // buffer, based on initial settings.
252 class SimulatedClockWithFrames : public SimulatedClock {
253 public:
SimulatedClockWithFrames(StreamGenerator * stream_generator,VCMReceiver * receiver)254 SimulatedClockWithFrames(StreamGenerator* stream_generator,
255 VCMReceiver* receiver)
256 : SimulatedClock(0),
257 stream_generator_(stream_generator),
258 receiver_(receiver) {}
~SimulatedClockWithFrames()259 virtual ~SimulatedClockWithFrames() {}
260
261 // If |stop_on_frame| is true and next frame arrives between now and
262 // now+|milliseconds|, the clock will be advanced to the arrival time of next
263 // frame.
264 // Otherwise, the clock will be advanced by |milliseconds|.
265 //
266 // For both cases, a frame will be inserted into the jitter buffer at the
267 // instant when the clock time is timestamps_.front().arrive_time.
268 //
269 // Return true if some frame arrives between now and now+|milliseconds|.
AdvanceTimeMilliseconds(int64_t milliseconds,bool stop_on_frame)270 bool AdvanceTimeMilliseconds(int64_t milliseconds, bool stop_on_frame) {
271 return AdvanceTimeMicroseconds(milliseconds * 1000, stop_on_frame);
272 }
273
AdvanceTimeMicroseconds(int64_t microseconds,bool stop_on_frame)274 bool AdvanceTimeMicroseconds(int64_t microseconds, bool stop_on_frame) {
275 int64_t start_time = TimeInMicroseconds();
276 int64_t end_time = start_time + microseconds;
277 bool frame_injected = false;
278 while (!timestamps_.empty() &&
279 timestamps_.front().arrive_time <= end_time) {
280 RTC_DCHECK(timestamps_.front().arrive_time >= start_time);
281
282 SimulatedClock::AdvanceTimeMicroseconds(timestamps_.front().arrive_time -
283 TimeInMicroseconds());
284 GenerateAndInsertFrame((timestamps_.front().render_time + 500) / 1000);
285 timestamps_.pop();
286 frame_injected = true;
287
288 if (stop_on_frame)
289 return frame_injected;
290 }
291
292 if (TimeInMicroseconds() < end_time) {
293 SimulatedClock::AdvanceTimeMicroseconds(end_time - TimeInMicroseconds());
294 }
295 return frame_injected;
296 }
297
298 // Input timestamps are in unit Milliseconds.
299 // And |arrive_timestamps| must be positive and in increasing order.
300 // |arrive_timestamps| determine when we are going to insert frames into the
301 // jitter buffer.
302 // |render_timestamps| are the timestamps on the frame.
SetFrames(const int64_t * arrive_timestamps,const int64_t * render_timestamps,size_t size)303 void SetFrames(const int64_t* arrive_timestamps,
304 const int64_t* render_timestamps,
305 size_t size) {
306 int64_t previous_arrive_timestamp = 0;
307 for (size_t i = 0; i < size; i++) {
308 RTC_CHECK(arrive_timestamps[i] >= previous_arrive_timestamp);
309 timestamps_.push(TimestampPair(arrive_timestamps[i] * 1000,
310 render_timestamps[i] * 1000));
311 previous_arrive_timestamp = arrive_timestamps[i];
312 }
313 }
314
315 private:
316 struct TimestampPair {
TimestampPairwebrtc::SimulatedClockWithFrames::TimestampPair317 TimestampPair(int64_t arrive_timestamp, int64_t render_timestamp)
318 : arrive_time(arrive_timestamp), render_time(render_timestamp) {}
319
320 int64_t arrive_time;
321 int64_t render_time;
322 };
323
GenerateAndInsertFrame(int64_t render_timestamp_ms)324 void GenerateAndInsertFrame(int64_t render_timestamp_ms) {
325 VCMPacket packet;
326 stream_generator_->GenerateFrame(FrameType::kVideoFrameKey,
327 1, // media packets
328 0, // empty packets
329 render_timestamp_ms);
330
331 bool packet_available = stream_generator_->PopPacket(&packet, 0);
332 EXPECT_TRUE(packet_available);
333 if (!packet_available)
334 return; // Return here to avoid crashes below.
335 receiver_->InsertPacket(packet);
336 }
337
338 std::queue<TimestampPair> timestamps_;
339 StreamGenerator* stream_generator_;
340 VCMReceiver* receiver_;
341 };
342
343 // Use a SimulatedClockWithFrames
344 // Wait call will do either of these:
345 // 1. If |stop_on_frame| is true, the clock will be turned to the exact instant
346 // that the first frame comes and the frame will be inserted into the jitter
347 // buffer, or the clock will be turned to now + |max_time| if no frame comes in
348 // the window.
349 // 2. If |stop_on_frame| is false, the clock will be turn to now + |max_time|,
350 // and all the frames arriving between now and now + |max_time| will be
351 // inserted into the jitter buffer.
352 //
353 // This is used to simulate the JitterBuffer getting packets from internet as
354 // time elapses.
355
356 class FrameInjectEvent : public EventWrapper {
357 public:
FrameInjectEvent(SimulatedClockWithFrames * clock,bool stop_on_frame)358 FrameInjectEvent(SimulatedClockWithFrames* clock, bool stop_on_frame)
359 : clock_(clock), stop_on_frame_(stop_on_frame) {}
360
Set()361 bool Set() override { return true; }
362
Wait(unsigned long max_time)363 EventTypeWrapper Wait(unsigned long max_time) override { // NOLINT
364 if (clock_->AdvanceTimeMilliseconds(max_time, stop_on_frame_) &&
365 stop_on_frame_) {
366 return EventTypeWrapper::kEventSignaled;
367 } else {
368 return EventTypeWrapper::kEventTimeout;
369 }
370 }
371
372 private:
373 SimulatedClockWithFrames* clock_;
374 bool stop_on_frame_;
375 };
376
377 class VCMReceiverTimingTest : public ::testing::Test {
378 protected:
VCMReceiverTimingTest()379 VCMReceiverTimingTest()
380
381 : clock_(&stream_generator_, &receiver_),
382 stream_generator_(0, clock_.TimeInMilliseconds()),
383 timing_(&clock_),
384 receiver_(
385 &timing_,
386 &clock_,
387 std::unique_ptr<EventWrapper>(new FrameInjectEvent(&clock_, false)),
388 std::unique_ptr<EventWrapper>(
389 new FrameInjectEvent(&clock_, true))) {}
390
SetUp()391 virtual void SetUp() { receiver_.Reset(); }
392
393 SimulatedClockWithFrames clock_;
394 StreamGenerator stream_generator_;
395 VCMTiming timing_;
396 VCMReceiver receiver_;
397 };
398
399 // Test whether VCMReceiver::FrameForDecoding handles parameter
400 // |max_wait_time_ms| correctly:
401 // 1. The function execution should never take more than |max_wait_time_ms|.
402 // 2. If the function exit before now + |max_wait_time_ms|, a frame must be
403 // returned.
TEST_F(VCMReceiverTimingTest,FrameForDecoding)404 TEST_F(VCMReceiverTimingTest, FrameForDecoding) {
405 const size_t kNumFrames = 100;
406 const int kFramePeriod = 40;
407 int64_t arrive_timestamps[kNumFrames];
408 int64_t render_timestamps[kNumFrames];
409
410 // Construct test samples.
411 // render_timestamps are the timestamps stored in the Frame;
412 // arrive_timestamps controls when the Frame packet got received.
413 for (size_t i = 0; i < kNumFrames; i++) {
414 // Preset frame rate to 25Hz.
415 // But we add a reasonable deviation to arrive_timestamps to mimic Internet
416 // fluctuation.
417 arrive_timestamps[i] =
418 (i + 1) * kFramePeriod + (i % 10) * ((i % 2) ? 1 : -1);
419 render_timestamps[i] = (i + 1) * kFramePeriod;
420 }
421
422 clock_.SetFrames(arrive_timestamps, render_timestamps, kNumFrames);
423
424 // Record how many frames we finally get out of the receiver.
425 size_t num_frames_return = 0;
426
427 const int64_t kMaxWaitTime = 30;
428
429 // Ideally, we should get all frames that we input in InitializeFrames.
430 // In the case that FrameForDecoding kills frames by error, we rely on the
431 // build bot to kill the test.
432 while (num_frames_return < kNumFrames) {
433 int64_t start_time = clock_.TimeInMilliseconds();
434 VCMEncodedFrame* frame = receiver_.FrameForDecoding(kMaxWaitTime, false);
435 int64_t end_time = clock_.TimeInMilliseconds();
436
437 // In any case the FrameForDecoding should not wait longer than
438 // max_wait_time.
439 // In the case that we did not get a frame, it should have been waiting for
440 // exactly max_wait_time. (By the testing samples we constructed above, we
441 // are sure there is no timing error, so the only case it returns with NULL
442 // is that it runs out of time.)
443 if (frame) {
444 receiver_.ReleaseFrame(frame);
445 ++num_frames_return;
446 EXPECT_GE(kMaxWaitTime, end_time - start_time);
447 } else {
448 EXPECT_EQ(kMaxWaitTime, end_time - start_time);
449 }
450 }
451 }
452
453 // Test whether VCMReceiver::FrameForDecoding handles parameter
454 // |prefer_late_decoding| and |max_wait_time_ms| correctly:
455 // 1. The function execution should never take more than |max_wait_time_ms|.
456 // 2. If the function exit before now + |max_wait_time_ms|, a frame must be
457 // returned and the end time must be equal to the render timestamp - delay
458 // for decoding and rendering.
TEST_F(VCMReceiverTimingTest,FrameForDecodingPreferLateDecoding)459 TEST_F(VCMReceiverTimingTest, FrameForDecodingPreferLateDecoding) {
460 const size_t kNumFrames = 100;
461 const int kFramePeriod = 40;
462
463 int64_t arrive_timestamps[kNumFrames];
464 int64_t render_timestamps[kNumFrames];
465
466 int render_delay_ms;
467 int max_decode_ms;
468 int dummy;
469 timing_.GetTimings(&dummy, &max_decode_ms, &dummy, &dummy, &dummy, &dummy,
470 &render_delay_ms);
471
472 // Construct test samples.
473 // render_timestamps are the timestamps stored in the Frame;
474 // arrive_timestamps controls when the Frame packet got received.
475 for (size_t i = 0; i < kNumFrames; i++) {
476 // Preset frame rate to 25Hz.
477 // But we add a reasonable deviation to arrive_timestamps to mimic Internet
478 // fluctuation.
479 arrive_timestamps[i] =
480 (i + 1) * kFramePeriod + (i % 10) * ((i % 2) ? 1 : -1);
481 render_timestamps[i] = (i + 1) * kFramePeriod;
482 }
483
484 clock_.SetFrames(arrive_timestamps, render_timestamps, kNumFrames);
485
486 // Record how many frames we finally get out of the receiver.
487 size_t num_frames_return = 0;
488 const int64_t kMaxWaitTime = 30;
489 bool prefer_late_decoding = true;
490 while (num_frames_return < kNumFrames) {
491 int64_t start_time = clock_.TimeInMilliseconds();
492
493 VCMEncodedFrame* frame =
494 receiver_.FrameForDecoding(kMaxWaitTime, prefer_late_decoding);
495 int64_t end_time = clock_.TimeInMilliseconds();
496 if (frame) {
497 EXPECT_EQ(frame->RenderTimeMs() - max_decode_ms - render_delay_ms,
498 end_time);
499 receiver_.ReleaseFrame(frame);
500 ++num_frames_return;
501 } else {
502 EXPECT_EQ(kMaxWaitTime, end_time - start_time);
503 }
504 }
505 }
506
507 } // namespace webrtc
508