blob: e38f9c5d21c109d1077f1ce83d13b712a2107163 [file] [log] [blame]
mikhal@webrtc.org381da4b2013-04-25 21:45:29 +00001/* 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
Jonas Olssona4d87372019-07-05 19:08:33 +020010#include "modules/video_coding/receiver.h"
11
mikhal@webrtc.org381da4b2013-04-25 21:45:29 +000012#include <string.h>
Jonas Olssona4d87372019-07-05 19:08:33 +020013
Yves Gerey3e707812018-11-28 16:47:49 +010014#include <cstdint>
kwiberg3f55dea2016-02-29 05:51:59 -080015#include <memory>
Qiang Chend4cec152015-06-19 09:17:00 -070016#include <queue>
philipel9d3ab612015-12-21 04:12:39 -080017#include <vector>
mikhal@webrtc.org381da4b2013-04-25 21:45:29 +000018
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020019#include "modules/video_coding/encoded_frame.h"
Yves Gerey3e707812018-11-28 16:47:49 +010020#include "modules/video_coding/jitter_buffer_common.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020021#include "modules/video_coding/packet.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020022#include "modules/video_coding/test/stream_generator.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020023#include "modules/video_coding/timing.h"
24#include "rtc_base/checks.h"
25#include "system_wrappers/include/clock.h"
26#include "test/gtest.h"
mikhal@webrtc.org381da4b2013-04-25 21:45:29 +000027
28namespace webrtc {
29
30class TestVCMReceiver : public ::testing::Test {
31 protected:
mikhal@webrtc.org381da4b2013-04-25 21:45:29 +000032 TestVCMReceiver()
Åsa Persson90719572021-04-08 19:05:30 +020033 : clock_(0),
34 timing_(&clock_),
35 receiver_(&timing_, &clock_),
36 stream_generator_(0, clock_.TimeInMilliseconds()) {}
mikhal@webrtc.org381da4b2013-04-25 21:45:29 +000037
38 int32_t InsertPacket(int index) {
39 VCMPacket packet;
Åsa Persson90719572021-04-08 19:05:30 +020040 bool packet_available = stream_generator_.GetPacket(&packet, index);
mikhal@webrtc.org381da4b2013-04-25 21:45:29 +000041 EXPECT_TRUE(packet_available);
42 if (!packet_available)
stefan@webrtc.org3417eb42013-05-21 15:25:53 +000043 return kGeneralError; // Return here to avoid crashes below.
Johan Ahlers95348f72016-06-28 11:11:28 +020044 return receiver_.InsertPacket(packet);
mikhal@webrtc.org381da4b2013-04-25 21:45:29 +000045 }
46
47 int32_t InsertPacketAndPop(int index) {
48 VCMPacket packet;
Åsa Persson90719572021-04-08 19:05:30 +020049 bool packet_available = stream_generator_.PopPacket(&packet, index);
mikhal@webrtc.org381da4b2013-04-25 21:45:29 +000050 EXPECT_TRUE(packet_available);
51 if (!packet_available)
stefan@webrtc.org3417eb42013-05-21 15:25:53 +000052 return kGeneralError; // Return here to avoid crashes below.
Johan Ahlers95348f72016-06-28 11:11:28 +020053 return receiver_.InsertPacket(packet);
mikhal@webrtc.org381da4b2013-04-25 21:45:29 +000054 }
55
Niels Möller87e2d782019-03-07 10:18:23 +010056 int32_t InsertFrame(VideoFrameType frame_type, bool complete) {
mikhal@webrtc.org381da4b2013-04-25 21:45:29 +000057 int num_of_packets = complete ? 1 : 2;
Åsa Persson90719572021-04-08 19:05:30 +020058 stream_generator_.GenerateFrame(
Niels Möller8f7ce222019-03-21 15:43:58 +010059 frame_type,
60 (frame_type != VideoFrameType::kEmptyFrame) ? num_of_packets : 0,
61 (frame_type == VideoFrameType::kEmptyFrame) ? 1 : 0,
Åsa Persson90719572021-04-08 19:05:30 +020062 clock_.TimeInMilliseconds());
mikhal@webrtc.org381da4b2013-04-25 21:45:29 +000063 int32_t ret = InsertPacketAndPop(0);
stefan@webrtc.orgef144882013-05-07 19:16:33 +000064 if (!complete) {
65 // Drop the second packet.
66 VCMPacket packet;
Åsa Persson90719572021-04-08 19:05:30 +020067 stream_generator_.PopPacket(&packet, 0);
stefan@webrtc.orgef144882013-05-07 19:16:33 +000068 }
Åsa Persson90719572021-04-08 19:05:30 +020069 clock_.AdvanceTimeMilliseconds(kDefaultFramePeriodMs);
mikhal@webrtc.org381da4b2013-04-25 21:45:29 +000070 return ret;
71 }
72
stefan@webrtc.orgef144882013-05-07 19:16:33 +000073 bool DecodeNextFrame() {
Johan Ahlers31b2ec42016-06-28 13:32:49 +020074 VCMEncodedFrame* frame = receiver_.FrameForDecoding(0, false);
stefan@webrtc.orgef144882013-05-07 19:16:33 +000075 if (!frame)
76 return false;
77 receiver_.ReleaseFrame(frame);
78 return true;
79 }
80
Åsa Persson90719572021-04-08 19:05:30 +020081 SimulatedClock clock_;
mikhal@webrtc.org381da4b2013-04-25 21:45:29 +000082 VCMTiming timing_;
mikhal@webrtc.org381da4b2013-04-25 21:45:29 +000083 VCMReceiver receiver_;
Åsa Persson90719572021-04-08 19:05:30 +020084 StreamGenerator stream_generator_;
mikhal@webrtc.org381da4b2013-04-25 21:45:29 +000085};
86
stefan@webrtc.orgef144882013-05-07 19:16:33 +000087TEST_F(TestVCMReceiver, NonDecodableDuration_Empty) {
stefan@webrtc.orgef144882013-05-07 19:16:33 +000088 const size_t kMaxNackListSize = 1000;
89 const int kMaxPacketAgeToNack = 1000;
90 const int kMaxNonDecodableDuration = 500;
91 const int kMinDelayMs = 500;
92 receiver_.SetNackSettings(kMaxNackListSize, kMaxPacketAgeToNack,
philipel9d3ab612015-12-21 04:12:39 -080093 kMaxNonDecodableDuration);
Niels Möller8f7ce222019-03-21 15:43:58 +010094 EXPECT_GE(InsertFrame(VideoFrameType::kVideoFrameKey, true), kNoError);
stefan@webrtc.orgef144882013-05-07 19:16:33 +000095 // Advance time until it's time to decode the key frame.
Åsa Persson90719572021-04-08 19:05:30 +020096 clock_.AdvanceTimeMilliseconds(kMinDelayMs);
stefan@webrtc.orgef144882013-05-07 19:16:33 +000097 EXPECT_TRUE(DecodeNextFrame());
Wan-Teh Changb1825a42015-06-03 15:03:35 -070098 bool request_key_frame = false;
99 std::vector<uint16_t> nack_list = receiver_.NackList(&request_key_frame);
100 EXPECT_FALSE(request_key_frame);
stefan@webrtc.orgef144882013-05-07 19:16:33 +0000101}
102
103TEST_F(TestVCMReceiver, NonDecodableDuration_NoKeyFrame) {
stefan@webrtc.orgef144882013-05-07 19:16:33 +0000104 const size_t kMaxNackListSize = 1000;
105 const int kMaxPacketAgeToNack = 1000;
106 const int kMaxNonDecodableDuration = 500;
107 receiver_.SetNackSettings(kMaxNackListSize, kMaxPacketAgeToNack,
philipel9d3ab612015-12-21 04:12:39 -0800108 kMaxNonDecodableDuration);
stefan@webrtc.orgef144882013-05-07 19:16:33 +0000109 const int kNumFrames = kDefaultFrameRate * kMaxNonDecodableDuration / 1000;
110 for (int i = 0; i < kNumFrames; ++i) {
Niels Möller8f7ce222019-03-21 15:43:58 +0100111 EXPECT_GE(InsertFrame(VideoFrameType::kVideoFrameDelta, true), kNoError);
stefan@webrtc.orgef144882013-05-07 19:16:33 +0000112 }
Wan-Teh Changb1825a42015-06-03 15:03:35 -0700113 bool request_key_frame = false;
114 std::vector<uint16_t> nack_list = receiver_.NackList(&request_key_frame);
115 EXPECT_TRUE(request_key_frame);
stefan@webrtc.orgef144882013-05-07 19:16:33 +0000116}
117
118TEST_F(TestVCMReceiver, NonDecodableDuration_OneIncomplete) {
stefan@webrtc.orgef144882013-05-07 19:16:33 +0000119 const size_t kMaxNackListSize = 1000;
120 const int kMaxPacketAgeToNack = 1000;
121 const int kMaxNonDecodableDuration = 500;
philipel9d3ab612015-12-21 04:12:39 -0800122 const int kMaxNonDecodableDurationFrames =
123 (kDefaultFrameRate * kMaxNonDecodableDuration + 500) / 1000;
stefan@webrtc.orgef144882013-05-07 19:16:33 +0000124 const int kMinDelayMs = 500;
125 receiver_.SetNackSettings(kMaxNackListSize, kMaxPacketAgeToNack,
philipel9d3ab612015-12-21 04:12:39 -0800126 kMaxNonDecodableDuration);
Evan Shrubsoled6cdf802022-03-02 15:13:55 +0100127 timing_.set_min_playout_delay(TimeDelta::Millis(kMinDelayMs));
Åsa Persson90719572021-04-08 19:05:30 +0200128 int64_t key_frame_inserted = clock_.TimeInMilliseconds();
Niels Möller8f7ce222019-03-21 15:43:58 +0100129 EXPECT_GE(InsertFrame(VideoFrameType::kVideoFrameKey, true), kNoError);
stefan@webrtc.orgef144882013-05-07 19:16:33 +0000130 // Insert an incomplete frame.
Niels Möller8f7ce222019-03-21 15:43:58 +0100131 EXPECT_GE(InsertFrame(VideoFrameType::kVideoFrameDelta, false), kNoError);
stefan@webrtc.orgef144882013-05-07 19:16:33 +0000132 // Insert enough frames to have too long non-decodable sequence.
philipel9d3ab612015-12-21 04:12:39 -0800133 for (int i = 0; i < kMaxNonDecodableDurationFrames; ++i) {
Niels Möller8f7ce222019-03-21 15:43:58 +0100134 EXPECT_GE(InsertFrame(VideoFrameType::kVideoFrameDelta, true), kNoError);
stefan@webrtc.orgef144882013-05-07 19:16:33 +0000135 }
136 // Advance time until it's time to decode the key frame.
Åsa Persson90719572021-04-08 19:05:30 +0200137 clock_.AdvanceTimeMilliseconds(kMinDelayMs - clock_.TimeInMilliseconds() -
138 key_frame_inserted);
stefan@webrtc.orgef144882013-05-07 19:16:33 +0000139 EXPECT_TRUE(DecodeNextFrame());
140 // Make sure we get a key frame request.
Wan-Teh Changb1825a42015-06-03 15:03:35 -0700141 bool request_key_frame = false;
142 std::vector<uint16_t> nack_list = receiver_.NackList(&request_key_frame);
143 EXPECT_TRUE(request_key_frame);
stefan@webrtc.orgef144882013-05-07 19:16:33 +0000144}
145
146TEST_F(TestVCMReceiver, NonDecodableDuration_NoTrigger) {
stefan@webrtc.orgef144882013-05-07 19:16:33 +0000147 const size_t kMaxNackListSize = 1000;
148 const int kMaxPacketAgeToNack = 1000;
149 const int kMaxNonDecodableDuration = 500;
philipel9d3ab612015-12-21 04:12:39 -0800150 const int kMaxNonDecodableDurationFrames =
151 (kDefaultFrameRate * kMaxNonDecodableDuration + 500) / 1000;
stefan@webrtc.orgef144882013-05-07 19:16:33 +0000152 const int kMinDelayMs = 500;
153 receiver_.SetNackSettings(kMaxNackListSize, kMaxPacketAgeToNack,
philipel9d3ab612015-12-21 04:12:39 -0800154 kMaxNonDecodableDuration);
Evan Shrubsoled6cdf802022-03-02 15:13:55 +0100155 timing_.set_min_playout_delay(TimeDelta::Millis(kMinDelayMs));
Åsa Persson90719572021-04-08 19:05:30 +0200156 int64_t key_frame_inserted = clock_.TimeInMilliseconds();
Niels Möller8f7ce222019-03-21 15:43:58 +0100157 EXPECT_GE(InsertFrame(VideoFrameType::kVideoFrameKey, true), kNoError);
stefan@webrtc.orgef144882013-05-07 19:16:33 +0000158 // Insert an incomplete frame.
Niels Möller8f7ce222019-03-21 15:43:58 +0100159 EXPECT_GE(InsertFrame(VideoFrameType::kVideoFrameDelta, false), kNoError);
stefan@webrtc.orgef144882013-05-07 19:16:33 +0000160 // Insert all but one frame to not trigger a key frame request due to
161 // too long duration of non-decodable frames.
philipel9d3ab612015-12-21 04:12:39 -0800162 for (int i = 0; i < kMaxNonDecodableDurationFrames - 1; ++i) {
Niels Möller8f7ce222019-03-21 15:43:58 +0100163 EXPECT_GE(InsertFrame(VideoFrameType::kVideoFrameDelta, true), kNoError);
stefan@webrtc.orgef144882013-05-07 19:16:33 +0000164 }
165 // Advance time until it's time to decode the key frame.
Åsa Persson90719572021-04-08 19:05:30 +0200166 clock_.AdvanceTimeMilliseconds(kMinDelayMs - clock_.TimeInMilliseconds() -
167 key_frame_inserted);
stefan@webrtc.orgef144882013-05-07 19:16:33 +0000168 EXPECT_TRUE(DecodeNextFrame());
169 // Make sure we don't get a key frame request since we haven't generated
170 // enough frames.
Wan-Teh Changb1825a42015-06-03 15:03:35 -0700171 bool request_key_frame = false;
172 std::vector<uint16_t> nack_list = receiver_.NackList(&request_key_frame);
173 EXPECT_FALSE(request_key_frame);
stefan@webrtc.orgef144882013-05-07 19:16:33 +0000174}
175
stefan@webrtc.org16734812013-05-14 12:00:47 +0000176TEST_F(TestVCMReceiver, NonDecodableDuration_NoTrigger2) {
stefan@webrtc.org16734812013-05-14 12:00:47 +0000177 const size_t kMaxNackListSize = 1000;
178 const int kMaxPacketAgeToNack = 1000;
179 const int kMaxNonDecodableDuration = 500;
philipel9d3ab612015-12-21 04:12:39 -0800180 const int kMaxNonDecodableDurationFrames =
181 (kDefaultFrameRate * kMaxNonDecodableDuration + 500) / 1000;
stefan@webrtc.org16734812013-05-14 12:00:47 +0000182 const int kMinDelayMs = 500;
183 receiver_.SetNackSettings(kMaxNackListSize, kMaxPacketAgeToNack,
philipel9d3ab612015-12-21 04:12:39 -0800184 kMaxNonDecodableDuration);
Evan Shrubsoled6cdf802022-03-02 15:13:55 +0100185 timing_.set_min_playout_delay(TimeDelta::Millis(kMinDelayMs));
Åsa Persson90719572021-04-08 19:05:30 +0200186 int64_t key_frame_inserted = clock_.TimeInMilliseconds();
Niels Möller8f7ce222019-03-21 15:43:58 +0100187 EXPECT_GE(InsertFrame(VideoFrameType::kVideoFrameKey, true), kNoError);
stefan@webrtc.org16734812013-05-14 12:00:47 +0000188 // Insert enough frames to have too long non-decodable sequence, except that
189 // we don't have any losses.
philipel9d3ab612015-12-21 04:12:39 -0800190 for (int i = 0; i < kMaxNonDecodableDurationFrames; ++i) {
Niels Möller8f7ce222019-03-21 15:43:58 +0100191 EXPECT_GE(InsertFrame(VideoFrameType::kVideoFrameDelta, true), kNoError);
stefan@webrtc.org16734812013-05-14 12:00:47 +0000192 }
193 // Insert an incomplete frame.
Niels Möller8f7ce222019-03-21 15:43:58 +0100194 EXPECT_GE(InsertFrame(VideoFrameType::kVideoFrameDelta, false), kNoError);
stefan@webrtc.org16734812013-05-14 12:00:47 +0000195 // Advance time until it's time to decode the key frame.
Åsa Persson90719572021-04-08 19:05:30 +0200196 clock_.AdvanceTimeMilliseconds(kMinDelayMs - clock_.TimeInMilliseconds() -
197 key_frame_inserted);
stefan@webrtc.org16734812013-05-14 12:00:47 +0000198 EXPECT_TRUE(DecodeNextFrame());
199 // Make sure we don't get a key frame request since the non-decodable duration
200 // is only one frame.
Wan-Teh Changb1825a42015-06-03 15:03:35 -0700201 bool request_key_frame = false;
202 std::vector<uint16_t> nack_list = receiver_.NackList(&request_key_frame);
203 EXPECT_FALSE(request_key_frame);
stefan@webrtc.org16734812013-05-14 12:00:47 +0000204}
205
stefan@webrtc.orgef144882013-05-07 19:16:33 +0000206TEST_F(TestVCMReceiver, NonDecodableDuration_KeyFrameAfterIncompleteFrames) {
stefan@webrtc.orgef144882013-05-07 19:16:33 +0000207 const size_t kMaxNackListSize = 1000;
208 const int kMaxPacketAgeToNack = 1000;
209 const int kMaxNonDecodableDuration = 500;
philipel9d3ab612015-12-21 04:12:39 -0800210 const int kMaxNonDecodableDurationFrames =
211 (kDefaultFrameRate * kMaxNonDecodableDuration + 500) / 1000;
stefan@webrtc.orgef144882013-05-07 19:16:33 +0000212 const int kMinDelayMs = 500;
213 receiver_.SetNackSettings(kMaxNackListSize, kMaxPacketAgeToNack,
philipel9d3ab612015-12-21 04:12:39 -0800214 kMaxNonDecodableDuration);
Evan Shrubsoled6cdf802022-03-02 15:13:55 +0100215 timing_.set_min_playout_delay(TimeDelta::Millis(kMinDelayMs));
Åsa Persson90719572021-04-08 19:05:30 +0200216 int64_t key_frame_inserted = clock_.TimeInMilliseconds();
Niels Möller8f7ce222019-03-21 15:43:58 +0100217 EXPECT_GE(InsertFrame(VideoFrameType::kVideoFrameKey, true), kNoError);
stefan@webrtc.orgef144882013-05-07 19:16:33 +0000218 // Insert an incomplete frame.
Niels Möller8f7ce222019-03-21 15:43:58 +0100219 EXPECT_GE(InsertFrame(VideoFrameType::kVideoFrameDelta, false), kNoError);
stefan@webrtc.orgef144882013-05-07 19:16:33 +0000220 // Insert enough frames to have too long non-decodable sequence.
philipel9d3ab612015-12-21 04:12:39 -0800221 for (int i = 0; i < kMaxNonDecodableDurationFrames; ++i) {
Niels Möller8f7ce222019-03-21 15:43:58 +0100222 EXPECT_GE(InsertFrame(VideoFrameType::kVideoFrameDelta, true), kNoError);
stefan@webrtc.orgef144882013-05-07 19:16:33 +0000223 }
Niels Möller8f7ce222019-03-21 15:43:58 +0100224 EXPECT_GE(InsertFrame(VideoFrameType::kVideoFrameKey, true), kNoError);
stefan@webrtc.orgef144882013-05-07 19:16:33 +0000225 // Advance time until it's time to decode the key frame.
Åsa Persson90719572021-04-08 19:05:30 +0200226 clock_.AdvanceTimeMilliseconds(kMinDelayMs - clock_.TimeInMilliseconds() -
227 key_frame_inserted);
stefan@webrtc.orgef144882013-05-07 19:16:33 +0000228 EXPECT_TRUE(DecodeNextFrame());
229 // Make sure we don't get a key frame request since we have a key frame
230 // in the list.
Wan-Teh Changb1825a42015-06-03 15:03:35 -0700231 bool request_key_frame = false;
232 std::vector<uint16_t> nack_list = receiver_.NackList(&request_key_frame);
233 EXPECT_FALSE(request_key_frame);
stefan@webrtc.orgef144882013-05-07 19:16:33 +0000234}
Qiang Chend4cec152015-06-19 09:17:00 -0700235
236// A simulated clock, when time elapses, will insert frames into the jitter
237// buffer, based on initial settings.
238class SimulatedClockWithFrames : public SimulatedClock {
239 public:
240 SimulatedClockWithFrames(StreamGenerator* stream_generator,
241 VCMReceiver* receiver)
242 : SimulatedClock(0),
243 stream_generator_(stream_generator),
244 receiver_(receiver) {}
245 virtual ~SimulatedClockWithFrames() {}
246
Artem Titovdcd7fc72021-08-09 13:02:57 +0200247 // If `stop_on_frame` is true and next frame arrives between now and
248 // now+`milliseconds`, the clock will be advanced to the arrival time of next
Qiang Chend4cec152015-06-19 09:17:00 -0700249 // frame.
Artem Titovdcd7fc72021-08-09 13:02:57 +0200250 // Otherwise, the clock will be advanced by `milliseconds`.
Qiang Chend4cec152015-06-19 09:17:00 -0700251 //
252 // For both cases, a frame will be inserted into the jitter buffer at the
253 // instant when the clock time is timestamps_.front().arrive_time.
254 //
Artem Titovdcd7fc72021-08-09 13:02:57 +0200255 // Return true if some frame arrives between now and now+`milliseconds`.
Qiang Chend4cec152015-06-19 09:17:00 -0700256 bool AdvanceTimeMilliseconds(int64_t milliseconds, bool stop_on_frame) {
257 return AdvanceTimeMicroseconds(milliseconds * 1000, stop_on_frame);
philipel9d3ab612015-12-21 04:12:39 -0800258 }
Qiang Chend4cec152015-06-19 09:17:00 -0700259
260 bool AdvanceTimeMicroseconds(int64_t microseconds, bool stop_on_frame) {
261 int64_t start_time = TimeInMicroseconds();
262 int64_t end_time = start_time + microseconds;
263 bool frame_injected = false;
264 while (!timestamps_.empty() &&
265 timestamps_.front().arrive_time <= end_time) {
Sebastian Jansson5a000162019-04-12 11:21:32 +0200266 RTC_DCHECK_GE(timestamps_.front().arrive_time, start_time);
Qiang Chend4cec152015-06-19 09:17:00 -0700267
268 SimulatedClock::AdvanceTimeMicroseconds(timestamps_.front().arrive_time -
269 TimeInMicroseconds());
270 GenerateAndInsertFrame((timestamps_.front().render_time + 500) / 1000);
271 timestamps_.pop();
272 frame_injected = true;
273
274 if (stop_on_frame)
275 return frame_injected;
276 }
277
278 if (TimeInMicroseconds() < end_time) {
279 SimulatedClock::AdvanceTimeMicroseconds(end_time - TimeInMicroseconds());
280 }
281 return frame_injected;
philipel9d3ab612015-12-21 04:12:39 -0800282 }
Qiang Chend4cec152015-06-19 09:17:00 -0700283
284 // Input timestamps are in unit Milliseconds.
Artem Titovdcd7fc72021-08-09 13:02:57 +0200285 // And `arrive_timestamps` must be positive and in increasing order.
286 // `arrive_timestamps` determine when we are going to insert frames into the
Qiang Chend4cec152015-06-19 09:17:00 -0700287 // jitter buffer.
Artem Titovdcd7fc72021-08-09 13:02:57 +0200288 // `render_timestamps` are the timestamps on the frame.
Qiang Chend4cec152015-06-19 09:17:00 -0700289 void SetFrames(const int64_t* arrive_timestamps,
290 const int64_t* render_timestamps,
291 size_t size) {
292 int64_t previous_arrive_timestamp = 0;
293 for (size_t i = 0; i < size; i++) {
Sebastian Jansson5a000162019-04-12 11:21:32 +0200294 RTC_CHECK_GE(arrive_timestamps[i], previous_arrive_timestamp);
Qiang Chend4cec152015-06-19 09:17:00 -0700295 timestamps_.push(TimestampPair(arrive_timestamps[i] * 1000,
296 render_timestamps[i] * 1000));
297 previous_arrive_timestamp = arrive_timestamps[i];
298 }
299 }
300
301 private:
302 struct TimestampPair {
303 TimestampPair(int64_t arrive_timestamp, int64_t render_timestamp)
304 : arrive_time(arrive_timestamp), render_time(render_timestamp) {}
305
306 int64_t arrive_time;
307 int64_t render_time;
308 };
309
310 void GenerateAndInsertFrame(int64_t render_timestamp_ms) {
311 VCMPacket packet;
Niels Möller87e2d782019-03-07 10:18:23 +0100312 stream_generator_->GenerateFrame(VideoFrameType::kVideoFrameKey,
Qiang Chend4cec152015-06-19 09:17:00 -0700313 1, // media packets
314 0, // empty packets
315 render_timestamp_ms);
316
317 bool packet_available = stream_generator_->PopPacket(&packet, 0);
318 EXPECT_TRUE(packet_available);
319 if (!packet_available)
320 return; // Return here to avoid crashes below.
Johan Ahlers95348f72016-06-28 11:11:28 +0200321 receiver_->InsertPacket(packet);
Qiang Chend4cec152015-06-19 09:17:00 -0700322 }
323
324 std::queue<TimestampPair> timestamps_;
325 StreamGenerator* stream_generator_;
326 VCMReceiver* receiver_;
327};
328
329// Use a SimulatedClockWithFrames
330// Wait call will do either of these:
Artem Titovdcd7fc72021-08-09 13:02:57 +0200331// 1. If `stop_on_frame` is true, the clock will be turned to the exact instant
Qiang Chend4cec152015-06-19 09:17:00 -0700332// that the first frame comes and the frame will be inserted into the jitter
Artem Titovdcd7fc72021-08-09 13:02:57 +0200333// buffer, or the clock will be turned to now + `max_time` if no frame comes in
Qiang Chend4cec152015-06-19 09:17:00 -0700334// the window.
Artem Titovdcd7fc72021-08-09 13:02:57 +0200335// 2. If `stop_on_frame` is false, the clock will be turn to now + `max_time`,
336// and all the frames arriving between now and now + `max_time` will be
Qiang Chend4cec152015-06-19 09:17:00 -0700337// inserted into the jitter buffer.
338//
339// This is used to simulate the JitterBuffer getting packets from internet as
340// time elapses.
341
342class FrameInjectEvent : public EventWrapper {
343 public:
344 FrameInjectEvent(SimulatedClockWithFrames* clock, bool stop_on_frame)
345 : clock_(clock), stop_on_frame_(stop_on_frame) {}
346
347 bool Set() override { return true; }
348
Niels Möllerd3da6b02020-03-05 15:31:10 +0100349 EventTypeWrapper Wait(int max_time_ms) override {
350 if (clock_->AdvanceTimeMilliseconds(max_time_ms, stop_on_frame_) &&
Qiang Chend4cec152015-06-19 09:17:00 -0700351 stop_on_frame_) {
352 return EventTypeWrapper::kEventSignaled;
353 } else {
354 return EventTypeWrapper::kEventTimeout;
355 }
356 }
357
358 private:
359 SimulatedClockWithFrames* clock_;
360 bool stop_on_frame_;
361};
362
363class VCMReceiverTimingTest : public ::testing::Test {
364 protected:
Qiang Chend4cec152015-06-19 09:17:00 -0700365 VCMReceiverTimingTest()
Qiang Chend4cec152015-06-19 09:17:00 -0700366 : clock_(&stream_generator_, &receiver_),
367 stream_generator_(0, clock_.TimeInMilliseconds()),
368 timing_(&clock_),
369 receiver_(
370 &timing_,
371 &clock_,
kwiberg3f55dea2016-02-29 05:51:59 -0800372 std::unique_ptr<EventWrapper>(new FrameInjectEvent(&clock_, false)),
373 std::unique_ptr<EventWrapper>(
Qiang Chend4cec152015-06-19 09:17:00 -0700374 new FrameInjectEvent(&clock_, true))) {}
375
Niels Möller45b01c72019-09-10 13:02:28 +0200376 virtual void SetUp() {}
Qiang Chend4cec152015-06-19 09:17:00 -0700377
378 SimulatedClockWithFrames clock_;
379 StreamGenerator stream_generator_;
380 VCMTiming timing_;
381 VCMReceiver receiver_;
382};
383
384// Test whether VCMReceiver::FrameForDecoding handles parameter
Artem Titovdcd7fc72021-08-09 13:02:57 +0200385// `max_wait_time_ms` correctly:
386// 1. The function execution should never take more than `max_wait_time_ms`.
387// 2. If the function exit before now + `max_wait_time_ms`, a frame must be
Qiang Chend4cec152015-06-19 09:17:00 -0700388// returned.
389TEST_F(VCMReceiverTimingTest, FrameForDecoding) {
390 const size_t kNumFrames = 100;
391 const int kFramePeriod = 40;
392 int64_t arrive_timestamps[kNumFrames];
393 int64_t render_timestamps[kNumFrames];
Qiang Chend4cec152015-06-19 09:17:00 -0700394
395 // Construct test samples.
396 // render_timestamps are the timestamps stored in the Frame;
397 // arrive_timestamps controls when the Frame packet got received.
398 for (size_t i = 0; i < kNumFrames; i++) {
399 // Preset frame rate to 25Hz.
400 // But we add a reasonable deviation to arrive_timestamps to mimic Internet
401 // fluctuation.
402 arrive_timestamps[i] =
403 (i + 1) * kFramePeriod + (i % 10) * ((i % 2) ? 1 : -1);
404 render_timestamps[i] = (i + 1) * kFramePeriod;
405 }
406
407 clock_.SetFrames(arrive_timestamps, render_timestamps, kNumFrames);
408
409 // Record how many frames we finally get out of the receiver.
410 size_t num_frames_return = 0;
411
412 const int64_t kMaxWaitTime = 30;
413
414 // Ideally, we should get all frames that we input in InitializeFrames.
415 // In the case that FrameForDecoding kills frames by error, we rely on the
416 // build bot to kill the test.
417 while (num_frames_return < kNumFrames) {
418 int64_t start_time = clock_.TimeInMilliseconds();
Johan Ahlers31b2ec42016-06-28 13:32:49 +0200419 VCMEncodedFrame* frame = receiver_.FrameForDecoding(kMaxWaitTime, false);
Qiang Chend4cec152015-06-19 09:17:00 -0700420 int64_t end_time = clock_.TimeInMilliseconds();
421
422 // In any case the FrameForDecoding should not wait longer than
423 // max_wait_time.
424 // In the case that we did not get a frame, it should have been waiting for
425 // exactly max_wait_time. (By the testing samples we constructed above, we
426 // are sure there is no timing error, so the only case it returns with NULL
427 // is that it runs out of time.)
428 if (frame) {
429 receiver_.ReleaseFrame(frame);
430 ++num_frames_return;
431 EXPECT_GE(kMaxWaitTime, end_time - start_time);
432 } else {
433 EXPECT_EQ(kMaxWaitTime, end_time - start_time);
434 }
435 }
436}
437
perkj796cfaf2015-12-10 09:27:38 -0800438// Test whether VCMReceiver::FrameForDecoding handles parameter
Artem Titovdcd7fc72021-08-09 13:02:57 +0200439// `prefer_late_decoding` and `max_wait_time_ms` correctly:
440// 1. The function execution should never take more than `max_wait_time_ms`.
441// 2. If the function exit before now + `max_wait_time_ms`, a frame must be
perkj796cfaf2015-12-10 09:27:38 -0800442// returned and the end time must be equal to the render timestamp - delay
443// for decoding and rendering.
444TEST_F(VCMReceiverTimingTest, FrameForDecodingPreferLateDecoding) {
445 const size_t kNumFrames = 100;
446 const int kFramePeriod = 40;
447
448 int64_t arrive_timestamps[kNumFrames];
449 int64_t render_timestamps[kNumFrames];
perkj796cfaf2015-12-10 09:27:38 -0800450
Evan Shrubsole92e89d72022-03-22 10:55:15 +0100451 auto timings = timing_.GetTimings();
452 TimeDelta render_delay = timings.render_delay;
453 TimeDelta max_decode = timings.max_decode_duration;
perkj796cfaf2015-12-10 09:27:38 -0800454
455 // Construct test samples.
456 // render_timestamps are the timestamps stored in the Frame;
457 // arrive_timestamps controls when the Frame packet got received.
458 for (size_t i = 0; i < kNumFrames; i++) {
459 // Preset frame rate to 25Hz.
460 // But we add a reasonable deviation to arrive_timestamps to mimic Internet
461 // fluctuation.
462 arrive_timestamps[i] =
463 (i + 1) * kFramePeriod + (i % 10) * ((i % 2) ? 1 : -1);
464 render_timestamps[i] = (i + 1) * kFramePeriod;
465 }
466
467 clock_.SetFrames(arrive_timestamps, render_timestamps, kNumFrames);
468
469 // Record how many frames we finally get out of the receiver.
470 size_t num_frames_return = 0;
471 const int64_t kMaxWaitTime = 30;
472 bool prefer_late_decoding = true;
473 while (num_frames_return < kNumFrames) {
474 int64_t start_time = clock_.TimeInMilliseconds();
475
Johan Ahlers31b2ec42016-06-28 13:32:49 +0200476 VCMEncodedFrame* frame =
477 receiver_.FrameForDecoding(kMaxWaitTime, prefer_late_decoding);
perkj796cfaf2015-12-10 09:27:38 -0800478 int64_t end_time = clock_.TimeInMilliseconds();
479 if (frame) {
Evan Shrubsole92e89d72022-03-22 10:55:15 +0100480 EXPECT_EQ(frame->RenderTimeMs() - max_decode.ms() - render_delay.ms(),
481 end_time);
perkj796cfaf2015-12-10 09:27:38 -0800482 receiver_.ReleaseFrame(frame);
483 ++num_frames_return;
484 } else {
485 EXPECT_EQ(kMaxWaitTime, end_time - start_time);
486 }
487 }
488}
489
mikhal@webrtc.org381da4b2013-04-25 21:45:29 +0000490} // namespace webrtc