blob: 2beb97e9725d01b7b2bac1243cbc29f11ff746b3 [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"
Rasmus Brandtc4d253c2022-05-25 12:03:35 +020023#include "modules/video_coding/timing/timing.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020024#include "rtc_base/checks.h"
25#include "system_wrappers/include/clock.h"
26#include "test/gtest.h"
Jonas Orelande02f9ee2022-03-25 12:43:14 +010027#include "test/scoped_key_value_config.h"
mikhal@webrtc.org381da4b2013-04-25 21:45:29 +000028
29namespace webrtc {
30
31class TestVCMReceiver : public ::testing::Test {
32 protected:
mikhal@webrtc.org381da4b2013-04-25 21:45:29 +000033 TestVCMReceiver()
Åsa Persson90719572021-04-08 19:05:30 +020034 : clock_(0),
Jonas Orelande02f9ee2022-03-25 12:43:14 +010035 timing_(&clock_, field_trials_),
36 receiver_(&timing_, &clock_, field_trials_),
Åsa Persson90719572021-04-08 19:05:30 +020037 stream_generator_(0, clock_.TimeInMilliseconds()) {}
mikhal@webrtc.org381da4b2013-04-25 21:45:29 +000038
39 int32_t InsertPacket(int index) {
40 VCMPacket packet;
Åsa Persson90719572021-04-08 19:05:30 +020041 bool packet_available = stream_generator_.GetPacket(&packet, index);
mikhal@webrtc.org381da4b2013-04-25 21:45:29 +000042 EXPECT_TRUE(packet_available);
43 if (!packet_available)
stefan@webrtc.org3417eb42013-05-21 15:25:53 +000044 return kGeneralError; // Return here to avoid crashes below.
Johan Ahlers95348f72016-06-28 11:11:28 +020045 return receiver_.InsertPacket(packet);
mikhal@webrtc.org381da4b2013-04-25 21:45:29 +000046 }
47
48 int32_t InsertPacketAndPop(int index) {
49 VCMPacket packet;
Åsa Persson90719572021-04-08 19:05:30 +020050 bool packet_available = stream_generator_.PopPacket(&packet, index);
mikhal@webrtc.org381da4b2013-04-25 21:45:29 +000051 EXPECT_TRUE(packet_available);
52 if (!packet_available)
stefan@webrtc.org3417eb42013-05-21 15:25:53 +000053 return kGeneralError; // Return here to avoid crashes below.
Johan Ahlers95348f72016-06-28 11:11:28 +020054 return receiver_.InsertPacket(packet);
mikhal@webrtc.org381da4b2013-04-25 21:45:29 +000055 }
56
Niels Möller87e2d782019-03-07 10:18:23 +010057 int32_t InsertFrame(VideoFrameType frame_type, bool complete) {
mikhal@webrtc.org381da4b2013-04-25 21:45:29 +000058 int num_of_packets = complete ? 1 : 2;
Åsa Persson90719572021-04-08 19:05:30 +020059 stream_generator_.GenerateFrame(
Niels Möller8f7ce222019-03-21 15:43:58 +010060 frame_type,
61 (frame_type != VideoFrameType::kEmptyFrame) ? num_of_packets : 0,
62 (frame_type == VideoFrameType::kEmptyFrame) ? 1 : 0,
Åsa Persson90719572021-04-08 19:05:30 +020063 clock_.TimeInMilliseconds());
mikhal@webrtc.org381da4b2013-04-25 21:45:29 +000064 int32_t ret = InsertPacketAndPop(0);
stefan@webrtc.orgef144882013-05-07 19:16:33 +000065 if (!complete) {
66 // Drop the second packet.
67 VCMPacket packet;
Åsa Persson90719572021-04-08 19:05:30 +020068 stream_generator_.PopPacket(&packet, 0);
stefan@webrtc.orgef144882013-05-07 19:16:33 +000069 }
Åsa Persson90719572021-04-08 19:05:30 +020070 clock_.AdvanceTimeMilliseconds(kDefaultFramePeriodMs);
mikhal@webrtc.org381da4b2013-04-25 21:45:29 +000071 return ret;
72 }
73
stefan@webrtc.orgef144882013-05-07 19:16:33 +000074 bool DecodeNextFrame() {
Johan Ahlers31b2ec42016-06-28 13:32:49 +020075 VCMEncodedFrame* frame = receiver_.FrameForDecoding(0, false);
stefan@webrtc.orgef144882013-05-07 19:16:33 +000076 if (!frame)
77 return false;
78 receiver_.ReleaseFrame(frame);
79 return true;
80 }
81
Jonas Orelande02f9ee2022-03-25 12:43:14 +010082 test::ScopedKeyValueConfig field_trials_;
Åsa Persson90719572021-04-08 19:05:30 +020083 SimulatedClock clock_;
mikhal@webrtc.org381da4b2013-04-25 21:45:29 +000084 VCMTiming timing_;
mikhal@webrtc.org381da4b2013-04-25 21:45:29 +000085 VCMReceiver receiver_;
Åsa Persson90719572021-04-08 19:05:30 +020086 StreamGenerator stream_generator_;
mikhal@webrtc.org381da4b2013-04-25 21:45:29 +000087};
88
stefan@webrtc.orgef144882013-05-07 19:16:33 +000089TEST_F(TestVCMReceiver, NonDecodableDuration_Empty) {
stefan@webrtc.orgef144882013-05-07 19:16:33 +000090 const size_t kMaxNackListSize = 1000;
91 const int kMaxPacketAgeToNack = 1000;
92 const int kMaxNonDecodableDuration = 500;
93 const int kMinDelayMs = 500;
94 receiver_.SetNackSettings(kMaxNackListSize, kMaxPacketAgeToNack,
philipel9d3ab612015-12-21 04:12:39 -080095 kMaxNonDecodableDuration);
Niels Möller8f7ce222019-03-21 15:43:58 +010096 EXPECT_GE(InsertFrame(VideoFrameType::kVideoFrameKey, true), kNoError);
stefan@webrtc.orgef144882013-05-07 19:16:33 +000097 // Advance time until it's time to decode the key frame.
Åsa Persson90719572021-04-08 19:05:30 +020098 clock_.AdvanceTimeMilliseconds(kMinDelayMs);
stefan@webrtc.orgef144882013-05-07 19:16:33 +000099 EXPECT_TRUE(DecodeNextFrame());
Wan-Teh Changb1825a42015-06-03 15:03:35 -0700100 bool request_key_frame = false;
101 std::vector<uint16_t> nack_list = receiver_.NackList(&request_key_frame);
102 EXPECT_FALSE(request_key_frame);
stefan@webrtc.orgef144882013-05-07 19:16:33 +0000103}
104
105TEST_F(TestVCMReceiver, NonDecodableDuration_NoKeyFrame) {
stefan@webrtc.orgef144882013-05-07 19:16:33 +0000106 const size_t kMaxNackListSize = 1000;
107 const int kMaxPacketAgeToNack = 1000;
108 const int kMaxNonDecodableDuration = 500;
109 receiver_.SetNackSettings(kMaxNackListSize, kMaxPacketAgeToNack,
philipel9d3ab612015-12-21 04:12:39 -0800110 kMaxNonDecodableDuration);
stefan@webrtc.orgef144882013-05-07 19:16:33 +0000111 const int kNumFrames = kDefaultFrameRate * kMaxNonDecodableDuration / 1000;
112 for (int i = 0; i < kNumFrames; ++i) {
Niels Möller8f7ce222019-03-21 15:43:58 +0100113 EXPECT_GE(InsertFrame(VideoFrameType::kVideoFrameDelta, true), kNoError);
stefan@webrtc.orgef144882013-05-07 19:16:33 +0000114 }
Wan-Teh Changb1825a42015-06-03 15:03:35 -0700115 bool request_key_frame = false;
116 std::vector<uint16_t> nack_list = receiver_.NackList(&request_key_frame);
117 EXPECT_TRUE(request_key_frame);
stefan@webrtc.orgef144882013-05-07 19:16:33 +0000118}
119
120TEST_F(TestVCMReceiver, NonDecodableDuration_OneIncomplete) {
stefan@webrtc.orgef144882013-05-07 19:16:33 +0000121 const size_t kMaxNackListSize = 1000;
122 const int kMaxPacketAgeToNack = 1000;
123 const int kMaxNonDecodableDuration = 500;
philipel9d3ab612015-12-21 04:12:39 -0800124 const int kMaxNonDecodableDurationFrames =
125 (kDefaultFrameRate * kMaxNonDecodableDuration + 500) / 1000;
stefan@webrtc.orgef144882013-05-07 19:16:33 +0000126 const int kMinDelayMs = 500;
127 receiver_.SetNackSettings(kMaxNackListSize, kMaxPacketAgeToNack,
philipel9d3ab612015-12-21 04:12:39 -0800128 kMaxNonDecodableDuration);
Evan Shrubsoled6cdf802022-03-02 15:13:55 +0100129 timing_.set_min_playout_delay(TimeDelta::Millis(kMinDelayMs));
Åsa Persson90719572021-04-08 19:05:30 +0200130 int64_t key_frame_inserted = clock_.TimeInMilliseconds();
Niels Möller8f7ce222019-03-21 15:43:58 +0100131 EXPECT_GE(InsertFrame(VideoFrameType::kVideoFrameKey, true), kNoError);
stefan@webrtc.orgef144882013-05-07 19:16:33 +0000132 // Insert an incomplete frame.
Niels Möller8f7ce222019-03-21 15:43:58 +0100133 EXPECT_GE(InsertFrame(VideoFrameType::kVideoFrameDelta, false), kNoError);
stefan@webrtc.orgef144882013-05-07 19:16:33 +0000134 // Insert enough frames to have too long non-decodable sequence.
philipel9d3ab612015-12-21 04:12:39 -0800135 for (int i = 0; i < kMaxNonDecodableDurationFrames; ++i) {
Niels Möller8f7ce222019-03-21 15:43:58 +0100136 EXPECT_GE(InsertFrame(VideoFrameType::kVideoFrameDelta, true), kNoError);
stefan@webrtc.orgef144882013-05-07 19:16:33 +0000137 }
138 // Advance time until it's time to decode the key frame.
Åsa Persson90719572021-04-08 19:05:30 +0200139 clock_.AdvanceTimeMilliseconds(kMinDelayMs - clock_.TimeInMilliseconds() -
140 key_frame_inserted);
stefan@webrtc.orgef144882013-05-07 19:16:33 +0000141 EXPECT_TRUE(DecodeNextFrame());
142 // Make sure we get a key frame request.
Wan-Teh Changb1825a42015-06-03 15:03:35 -0700143 bool request_key_frame = false;
144 std::vector<uint16_t> nack_list = receiver_.NackList(&request_key_frame);
145 EXPECT_TRUE(request_key_frame);
stefan@webrtc.orgef144882013-05-07 19:16:33 +0000146}
147
148TEST_F(TestVCMReceiver, NonDecodableDuration_NoTrigger) {
stefan@webrtc.orgef144882013-05-07 19:16:33 +0000149 const size_t kMaxNackListSize = 1000;
150 const int kMaxPacketAgeToNack = 1000;
151 const int kMaxNonDecodableDuration = 500;
philipel9d3ab612015-12-21 04:12:39 -0800152 const int kMaxNonDecodableDurationFrames =
153 (kDefaultFrameRate * kMaxNonDecodableDuration + 500) / 1000;
stefan@webrtc.orgef144882013-05-07 19:16:33 +0000154 const int kMinDelayMs = 500;
155 receiver_.SetNackSettings(kMaxNackListSize, kMaxPacketAgeToNack,
philipel9d3ab612015-12-21 04:12:39 -0800156 kMaxNonDecodableDuration);
Evan Shrubsoled6cdf802022-03-02 15:13:55 +0100157 timing_.set_min_playout_delay(TimeDelta::Millis(kMinDelayMs));
Åsa Persson90719572021-04-08 19:05:30 +0200158 int64_t key_frame_inserted = clock_.TimeInMilliseconds();
Niels Möller8f7ce222019-03-21 15:43:58 +0100159 EXPECT_GE(InsertFrame(VideoFrameType::kVideoFrameKey, true), kNoError);
stefan@webrtc.orgef144882013-05-07 19:16:33 +0000160 // Insert an incomplete frame.
Niels Möller8f7ce222019-03-21 15:43:58 +0100161 EXPECT_GE(InsertFrame(VideoFrameType::kVideoFrameDelta, false), kNoError);
stefan@webrtc.orgef144882013-05-07 19:16:33 +0000162 // Insert all but one frame to not trigger a key frame request due to
163 // too long duration of non-decodable frames.
philipel9d3ab612015-12-21 04:12:39 -0800164 for (int i = 0; i < kMaxNonDecodableDurationFrames - 1; ++i) {
Niels Möller8f7ce222019-03-21 15:43:58 +0100165 EXPECT_GE(InsertFrame(VideoFrameType::kVideoFrameDelta, true), kNoError);
stefan@webrtc.orgef144882013-05-07 19:16:33 +0000166 }
167 // Advance time until it's time to decode the key frame.
Åsa Persson90719572021-04-08 19:05:30 +0200168 clock_.AdvanceTimeMilliseconds(kMinDelayMs - clock_.TimeInMilliseconds() -
169 key_frame_inserted);
stefan@webrtc.orgef144882013-05-07 19:16:33 +0000170 EXPECT_TRUE(DecodeNextFrame());
171 // Make sure we don't get a key frame request since we haven't generated
172 // enough frames.
Wan-Teh Changb1825a42015-06-03 15:03:35 -0700173 bool request_key_frame = false;
174 std::vector<uint16_t> nack_list = receiver_.NackList(&request_key_frame);
175 EXPECT_FALSE(request_key_frame);
stefan@webrtc.orgef144882013-05-07 19:16:33 +0000176}
177
stefan@webrtc.org16734812013-05-14 12:00:47 +0000178TEST_F(TestVCMReceiver, NonDecodableDuration_NoTrigger2) {
stefan@webrtc.org16734812013-05-14 12:00:47 +0000179 const size_t kMaxNackListSize = 1000;
180 const int kMaxPacketAgeToNack = 1000;
181 const int kMaxNonDecodableDuration = 500;
philipel9d3ab612015-12-21 04:12:39 -0800182 const int kMaxNonDecodableDurationFrames =
183 (kDefaultFrameRate * kMaxNonDecodableDuration + 500) / 1000;
stefan@webrtc.org16734812013-05-14 12:00:47 +0000184 const int kMinDelayMs = 500;
185 receiver_.SetNackSettings(kMaxNackListSize, kMaxPacketAgeToNack,
philipel9d3ab612015-12-21 04:12:39 -0800186 kMaxNonDecodableDuration);
Evan Shrubsoled6cdf802022-03-02 15:13:55 +0100187 timing_.set_min_playout_delay(TimeDelta::Millis(kMinDelayMs));
Åsa Persson90719572021-04-08 19:05:30 +0200188 int64_t key_frame_inserted = clock_.TimeInMilliseconds();
Niels Möller8f7ce222019-03-21 15:43:58 +0100189 EXPECT_GE(InsertFrame(VideoFrameType::kVideoFrameKey, true), kNoError);
stefan@webrtc.org16734812013-05-14 12:00:47 +0000190 // Insert enough frames to have too long non-decodable sequence, except that
191 // we don't have any losses.
philipel9d3ab612015-12-21 04:12:39 -0800192 for (int i = 0; i < kMaxNonDecodableDurationFrames; ++i) {
Niels Möller8f7ce222019-03-21 15:43:58 +0100193 EXPECT_GE(InsertFrame(VideoFrameType::kVideoFrameDelta, true), kNoError);
stefan@webrtc.org16734812013-05-14 12:00:47 +0000194 }
195 // Insert an incomplete frame.
Niels Möller8f7ce222019-03-21 15:43:58 +0100196 EXPECT_GE(InsertFrame(VideoFrameType::kVideoFrameDelta, false), kNoError);
stefan@webrtc.org16734812013-05-14 12:00:47 +0000197 // Advance time until it's time to decode the key frame.
Åsa Persson90719572021-04-08 19:05:30 +0200198 clock_.AdvanceTimeMilliseconds(kMinDelayMs - clock_.TimeInMilliseconds() -
199 key_frame_inserted);
stefan@webrtc.org16734812013-05-14 12:00:47 +0000200 EXPECT_TRUE(DecodeNextFrame());
201 // Make sure we don't get a key frame request since the non-decodable duration
202 // is only one frame.
Wan-Teh Changb1825a42015-06-03 15:03:35 -0700203 bool request_key_frame = false;
204 std::vector<uint16_t> nack_list = receiver_.NackList(&request_key_frame);
205 EXPECT_FALSE(request_key_frame);
stefan@webrtc.org16734812013-05-14 12:00:47 +0000206}
207
stefan@webrtc.orgef144882013-05-07 19:16:33 +0000208TEST_F(TestVCMReceiver, NonDecodableDuration_KeyFrameAfterIncompleteFrames) {
stefan@webrtc.orgef144882013-05-07 19:16:33 +0000209 const size_t kMaxNackListSize = 1000;
210 const int kMaxPacketAgeToNack = 1000;
211 const int kMaxNonDecodableDuration = 500;
philipel9d3ab612015-12-21 04:12:39 -0800212 const int kMaxNonDecodableDurationFrames =
213 (kDefaultFrameRate * kMaxNonDecodableDuration + 500) / 1000;
stefan@webrtc.orgef144882013-05-07 19:16:33 +0000214 const int kMinDelayMs = 500;
215 receiver_.SetNackSettings(kMaxNackListSize, kMaxPacketAgeToNack,
philipel9d3ab612015-12-21 04:12:39 -0800216 kMaxNonDecodableDuration);
Evan Shrubsoled6cdf802022-03-02 15:13:55 +0100217 timing_.set_min_playout_delay(TimeDelta::Millis(kMinDelayMs));
Åsa Persson90719572021-04-08 19:05:30 +0200218 int64_t key_frame_inserted = clock_.TimeInMilliseconds();
Niels Möller8f7ce222019-03-21 15:43:58 +0100219 EXPECT_GE(InsertFrame(VideoFrameType::kVideoFrameKey, true), kNoError);
stefan@webrtc.orgef144882013-05-07 19:16:33 +0000220 // Insert an incomplete frame.
Niels Möller8f7ce222019-03-21 15:43:58 +0100221 EXPECT_GE(InsertFrame(VideoFrameType::kVideoFrameDelta, false), kNoError);
stefan@webrtc.orgef144882013-05-07 19:16:33 +0000222 // Insert enough frames to have too long non-decodable sequence.
philipel9d3ab612015-12-21 04:12:39 -0800223 for (int i = 0; i < kMaxNonDecodableDurationFrames; ++i) {
Niels Möller8f7ce222019-03-21 15:43:58 +0100224 EXPECT_GE(InsertFrame(VideoFrameType::kVideoFrameDelta, true), kNoError);
stefan@webrtc.orgef144882013-05-07 19:16:33 +0000225 }
Niels Möller8f7ce222019-03-21 15:43:58 +0100226 EXPECT_GE(InsertFrame(VideoFrameType::kVideoFrameKey, true), kNoError);
stefan@webrtc.orgef144882013-05-07 19:16:33 +0000227 // Advance time until it's time to decode the key frame.
Åsa Persson90719572021-04-08 19:05:30 +0200228 clock_.AdvanceTimeMilliseconds(kMinDelayMs - clock_.TimeInMilliseconds() -
229 key_frame_inserted);
stefan@webrtc.orgef144882013-05-07 19:16:33 +0000230 EXPECT_TRUE(DecodeNextFrame());
231 // Make sure we don't get a key frame request since we have a key frame
232 // in the list.
Wan-Teh Changb1825a42015-06-03 15:03:35 -0700233 bool request_key_frame = false;
234 std::vector<uint16_t> nack_list = receiver_.NackList(&request_key_frame);
235 EXPECT_FALSE(request_key_frame);
stefan@webrtc.orgef144882013-05-07 19:16:33 +0000236}
Qiang Chend4cec152015-06-19 09:17:00 -0700237
238// A simulated clock, when time elapses, will insert frames into the jitter
239// buffer, based on initial settings.
240class SimulatedClockWithFrames : public SimulatedClock {
241 public:
242 SimulatedClockWithFrames(StreamGenerator* stream_generator,
243 VCMReceiver* receiver)
244 : SimulatedClock(0),
245 stream_generator_(stream_generator),
246 receiver_(receiver) {}
247 virtual ~SimulatedClockWithFrames() {}
248
Artem Titovdcd7fc72021-08-09 13:02:57 +0200249 // If `stop_on_frame` is true and next frame arrives between now and
250 // now+`milliseconds`, the clock will be advanced to the arrival time of next
Qiang Chend4cec152015-06-19 09:17:00 -0700251 // frame.
Artem Titovdcd7fc72021-08-09 13:02:57 +0200252 // Otherwise, the clock will be advanced by `milliseconds`.
Qiang Chend4cec152015-06-19 09:17:00 -0700253 //
254 // For both cases, a frame will be inserted into the jitter buffer at the
255 // instant when the clock time is timestamps_.front().arrive_time.
256 //
Artem Titovdcd7fc72021-08-09 13:02:57 +0200257 // Return true if some frame arrives between now and now+`milliseconds`.
Qiang Chend4cec152015-06-19 09:17:00 -0700258 bool AdvanceTimeMilliseconds(int64_t milliseconds, bool stop_on_frame) {
259 return AdvanceTimeMicroseconds(milliseconds * 1000, stop_on_frame);
philipel9d3ab612015-12-21 04:12:39 -0800260 }
Qiang Chend4cec152015-06-19 09:17:00 -0700261
262 bool AdvanceTimeMicroseconds(int64_t microseconds, bool stop_on_frame) {
263 int64_t start_time = TimeInMicroseconds();
264 int64_t end_time = start_time + microseconds;
265 bool frame_injected = false;
266 while (!timestamps_.empty() &&
267 timestamps_.front().arrive_time <= end_time) {
Sebastian Jansson5a000162019-04-12 11:21:32 +0200268 RTC_DCHECK_GE(timestamps_.front().arrive_time, start_time);
Qiang Chend4cec152015-06-19 09:17:00 -0700269
270 SimulatedClock::AdvanceTimeMicroseconds(timestamps_.front().arrive_time -
271 TimeInMicroseconds());
272 GenerateAndInsertFrame((timestamps_.front().render_time + 500) / 1000);
273 timestamps_.pop();
274 frame_injected = true;
275
276 if (stop_on_frame)
277 return frame_injected;
278 }
279
280 if (TimeInMicroseconds() < end_time) {
281 SimulatedClock::AdvanceTimeMicroseconds(end_time - TimeInMicroseconds());
282 }
283 return frame_injected;
philipel9d3ab612015-12-21 04:12:39 -0800284 }
Qiang Chend4cec152015-06-19 09:17:00 -0700285
286 // Input timestamps are in unit Milliseconds.
Artem Titovdcd7fc72021-08-09 13:02:57 +0200287 // And `arrive_timestamps` must be positive and in increasing order.
288 // `arrive_timestamps` determine when we are going to insert frames into the
Qiang Chend4cec152015-06-19 09:17:00 -0700289 // jitter buffer.
Artem Titovdcd7fc72021-08-09 13:02:57 +0200290 // `render_timestamps` are the timestamps on the frame.
Qiang Chend4cec152015-06-19 09:17:00 -0700291 void SetFrames(const int64_t* arrive_timestamps,
292 const int64_t* render_timestamps,
293 size_t size) {
294 int64_t previous_arrive_timestamp = 0;
295 for (size_t i = 0; i < size; i++) {
Sebastian Jansson5a000162019-04-12 11:21:32 +0200296 RTC_CHECK_GE(arrive_timestamps[i], previous_arrive_timestamp);
Qiang Chend4cec152015-06-19 09:17:00 -0700297 timestamps_.push(TimestampPair(arrive_timestamps[i] * 1000,
298 render_timestamps[i] * 1000));
299 previous_arrive_timestamp = arrive_timestamps[i];
300 }
301 }
302
303 private:
304 struct TimestampPair {
305 TimestampPair(int64_t arrive_timestamp, int64_t render_timestamp)
306 : arrive_time(arrive_timestamp), render_time(render_timestamp) {}
307
308 int64_t arrive_time;
309 int64_t render_time;
310 };
311
312 void GenerateAndInsertFrame(int64_t render_timestamp_ms) {
313 VCMPacket packet;
Niels Möller87e2d782019-03-07 10:18:23 +0100314 stream_generator_->GenerateFrame(VideoFrameType::kVideoFrameKey,
Qiang Chend4cec152015-06-19 09:17:00 -0700315 1, // media packets
316 0, // empty packets
317 render_timestamp_ms);
318
319 bool packet_available = stream_generator_->PopPacket(&packet, 0);
320 EXPECT_TRUE(packet_available);
321 if (!packet_available)
322 return; // Return here to avoid crashes below.
Johan Ahlers95348f72016-06-28 11:11:28 +0200323 receiver_->InsertPacket(packet);
Qiang Chend4cec152015-06-19 09:17:00 -0700324 }
325
326 std::queue<TimestampPair> timestamps_;
327 StreamGenerator* stream_generator_;
328 VCMReceiver* receiver_;
329};
330
331// Use a SimulatedClockWithFrames
332// Wait call will do either of these:
Artem Titovdcd7fc72021-08-09 13:02:57 +0200333// 1. If `stop_on_frame` is true, the clock will be turned to the exact instant
Qiang Chend4cec152015-06-19 09:17:00 -0700334// that the first frame comes and the frame will be inserted into the jitter
Artem Titovdcd7fc72021-08-09 13:02:57 +0200335// buffer, or the clock will be turned to now + `max_time` if no frame comes in
Qiang Chend4cec152015-06-19 09:17:00 -0700336// the window.
Artem Titovdcd7fc72021-08-09 13:02:57 +0200337// 2. If `stop_on_frame` is false, the clock will be turn to now + `max_time`,
338// and all the frames arriving between now and now + `max_time` will be
Qiang Chend4cec152015-06-19 09:17:00 -0700339// inserted into the jitter buffer.
340//
341// This is used to simulate the JitterBuffer getting packets from internet as
342// time elapses.
343
344class FrameInjectEvent : public EventWrapper {
345 public:
346 FrameInjectEvent(SimulatedClockWithFrames* clock, bool stop_on_frame)
347 : clock_(clock), stop_on_frame_(stop_on_frame) {}
348
349 bool Set() override { return true; }
350
Niels Möllerd3da6b02020-03-05 15:31:10 +0100351 EventTypeWrapper Wait(int max_time_ms) override {
352 if (clock_->AdvanceTimeMilliseconds(max_time_ms, stop_on_frame_) &&
Qiang Chend4cec152015-06-19 09:17:00 -0700353 stop_on_frame_) {
354 return EventTypeWrapper::kEventSignaled;
355 } else {
356 return EventTypeWrapper::kEventTimeout;
357 }
358 }
359
360 private:
361 SimulatedClockWithFrames* clock_;
362 bool stop_on_frame_;
363};
364
365class VCMReceiverTimingTest : public ::testing::Test {
366 protected:
Qiang Chend4cec152015-06-19 09:17:00 -0700367 VCMReceiverTimingTest()
Qiang Chend4cec152015-06-19 09:17:00 -0700368 : clock_(&stream_generator_, &receiver_),
369 stream_generator_(0, clock_.TimeInMilliseconds()),
Jonas Orelande02f9ee2022-03-25 12:43:14 +0100370 timing_(&clock_, field_trials_),
Qiang Chend4cec152015-06-19 09:17:00 -0700371 receiver_(
372 &timing_,
373 &clock_,
kwiberg3f55dea2016-02-29 05:51:59 -0800374 std::unique_ptr<EventWrapper>(new FrameInjectEvent(&clock_, false)),
Jonas Orelande02f9ee2022-03-25 12:43:14 +0100375 std::unique_ptr<EventWrapper>(new FrameInjectEvent(&clock_, true)),
376 field_trials_) {}
Qiang Chend4cec152015-06-19 09:17:00 -0700377
Niels Möller45b01c72019-09-10 13:02:28 +0200378 virtual void SetUp() {}
Qiang Chend4cec152015-06-19 09:17:00 -0700379
Jonas Orelande02f9ee2022-03-25 12:43:14 +0100380 test::ScopedKeyValueConfig field_trials_;
Qiang Chend4cec152015-06-19 09:17:00 -0700381 SimulatedClockWithFrames clock_;
382 StreamGenerator stream_generator_;
383 VCMTiming timing_;
384 VCMReceiver receiver_;
385};
386
387// Test whether VCMReceiver::FrameForDecoding handles parameter
Artem Titovdcd7fc72021-08-09 13:02:57 +0200388// `max_wait_time_ms` correctly:
389// 1. The function execution should never take more than `max_wait_time_ms`.
390// 2. If the function exit before now + `max_wait_time_ms`, a frame must be
Qiang Chend4cec152015-06-19 09:17:00 -0700391// returned.
392TEST_F(VCMReceiverTimingTest, FrameForDecoding) {
393 const size_t kNumFrames = 100;
394 const int kFramePeriod = 40;
395 int64_t arrive_timestamps[kNumFrames];
396 int64_t render_timestamps[kNumFrames];
Qiang Chend4cec152015-06-19 09:17:00 -0700397
398 // Construct test samples.
399 // render_timestamps are the timestamps stored in the Frame;
400 // arrive_timestamps controls when the Frame packet got received.
401 for (size_t i = 0; i < kNumFrames; i++) {
402 // Preset frame rate to 25Hz.
403 // But we add a reasonable deviation to arrive_timestamps to mimic Internet
404 // fluctuation.
405 arrive_timestamps[i] =
406 (i + 1) * kFramePeriod + (i % 10) * ((i % 2) ? 1 : -1);
407 render_timestamps[i] = (i + 1) * kFramePeriod;
408 }
409
410 clock_.SetFrames(arrive_timestamps, render_timestamps, kNumFrames);
411
412 // Record how many frames we finally get out of the receiver.
413 size_t num_frames_return = 0;
414
415 const int64_t kMaxWaitTime = 30;
416
417 // Ideally, we should get all frames that we input in InitializeFrames.
418 // In the case that FrameForDecoding kills frames by error, we rely on the
419 // build bot to kill the test.
420 while (num_frames_return < kNumFrames) {
421 int64_t start_time = clock_.TimeInMilliseconds();
Johan Ahlers31b2ec42016-06-28 13:32:49 +0200422 VCMEncodedFrame* frame = receiver_.FrameForDecoding(kMaxWaitTime, false);
Qiang Chend4cec152015-06-19 09:17:00 -0700423 int64_t end_time = clock_.TimeInMilliseconds();
424
425 // In any case the FrameForDecoding should not wait longer than
426 // max_wait_time.
427 // In the case that we did not get a frame, it should have been waiting for
428 // exactly max_wait_time. (By the testing samples we constructed above, we
429 // are sure there is no timing error, so the only case it returns with NULL
430 // is that it runs out of time.)
431 if (frame) {
432 receiver_.ReleaseFrame(frame);
433 ++num_frames_return;
434 EXPECT_GE(kMaxWaitTime, end_time - start_time);
435 } else {
436 EXPECT_EQ(kMaxWaitTime, end_time - start_time);
437 }
438 }
439}
440
perkj796cfaf2015-12-10 09:27:38 -0800441// Test whether VCMReceiver::FrameForDecoding handles parameter
Artem Titovdcd7fc72021-08-09 13:02:57 +0200442// `prefer_late_decoding` and `max_wait_time_ms` correctly:
443// 1. The function execution should never take more than `max_wait_time_ms`.
444// 2. If the function exit before now + `max_wait_time_ms`, a frame must be
perkj796cfaf2015-12-10 09:27:38 -0800445// returned and the end time must be equal to the render timestamp - delay
446// for decoding and rendering.
447TEST_F(VCMReceiverTimingTest, FrameForDecodingPreferLateDecoding) {
448 const size_t kNumFrames = 100;
449 const int kFramePeriod = 40;
450
451 int64_t arrive_timestamps[kNumFrames];
452 int64_t render_timestamps[kNumFrames];
perkj796cfaf2015-12-10 09:27:38 -0800453
Evan Shrubsole92e89d72022-03-22 10:55:15 +0100454 auto timings = timing_.GetTimings();
455 TimeDelta render_delay = timings.render_delay;
456 TimeDelta max_decode = timings.max_decode_duration;
perkj796cfaf2015-12-10 09:27:38 -0800457
458 // Construct test samples.
459 // render_timestamps are the timestamps stored in the Frame;
460 // arrive_timestamps controls when the Frame packet got received.
461 for (size_t i = 0; i < kNumFrames; i++) {
462 // Preset frame rate to 25Hz.
463 // But we add a reasonable deviation to arrive_timestamps to mimic Internet
464 // fluctuation.
465 arrive_timestamps[i] =
466 (i + 1) * kFramePeriod + (i % 10) * ((i % 2) ? 1 : -1);
467 render_timestamps[i] = (i + 1) * kFramePeriod;
468 }
469
470 clock_.SetFrames(arrive_timestamps, render_timestamps, kNumFrames);
471
472 // Record how many frames we finally get out of the receiver.
473 size_t num_frames_return = 0;
474 const int64_t kMaxWaitTime = 30;
475 bool prefer_late_decoding = true;
476 while (num_frames_return < kNumFrames) {
477 int64_t start_time = clock_.TimeInMilliseconds();
478
Johan Ahlers31b2ec42016-06-28 13:32:49 +0200479 VCMEncodedFrame* frame =
480 receiver_.FrameForDecoding(kMaxWaitTime, prefer_late_decoding);
perkj796cfaf2015-12-10 09:27:38 -0800481 int64_t end_time = clock_.TimeInMilliseconds();
482 if (frame) {
Evan Shrubsole92e89d72022-03-22 10:55:15 +0100483 EXPECT_EQ(frame->RenderTimeMs() - max_decode.ms() - render_delay.ms(),
484 end_time);
perkj796cfaf2015-12-10 09:27:38 -0800485 receiver_.ReleaseFrame(frame);
486 ++num_frames_return;
487 } else {
488 EXPECT_EQ(kMaxWaitTime, end_time - start_time);
489 }
490 }
491}
492
mikhal@webrtc.org381da4b2013-04-25 21:45:29 +0000493} // namespace webrtc