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