blob: f0d06713b34f4012ab323adadabc7caa599c642e [file] [log] [blame]
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001/*
2 * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000010#include <algorithm>
11#include <map>
12#include <sstream>
13#include <string>
14
15#include "testing/gtest/include/gtest/gtest.h"
16
pbos@webrtc.org2b4ce3a2015-03-23 13:12:24 +000017#include "webrtc/base/checks.h"
kwiberg@webrtc.org00b8f6b2015-02-26 14:34:55 +000018#include "webrtc/base/scoped_ptr.h"
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000019#include "webrtc/call.h"
20#include "webrtc/frame_callback.h"
21#include "webrtc/modules/rtp_rtcp/source/rtcp_utility.h"
marpan@webrtc.org5b883172014-11-01 06:10:48 +000022#include "webrtc/modules/video_coding/codecs/vp8/include/vp8.h"
23#include "webrtc/modules/video_coding/codecs/vp9/include/vp9.h"
24#include "webrtc/modules/video_coding/main/interface/video_coding_defines.h"
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000025#include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
26#include "webrtc/system_wrappers/interface/event_wrapper.h"
Åsa Persson352b2d72015-04-15 18:00:40 +020027#include "webrtc/system_wrappers/interface/metrics.h"
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000028#include "webrtc/system_wrappers/interface/sleep.h"
29#include "webrtc/test/call_test.h"
30#include "webrtc/test/direct_transport.h"
31#include "webrtc/test/encoder_settings.h"
32#include "webrtc/test/fake_audio_device.h"
33#include "webrtc/test/fake_decoder.h"
34#include "webrtc/test/fake_encoder.h"
35#include "webrtc/test/frame_generator.h"
36#include "webrtc/test/frame_generator_capturer.h"
Åsa Persson352b2d72015-04-15 18:00:40 +020037#include "webrtc/test/histogram.h"
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000038#include "webrtc/test/null_transport.h"
asapersson@webrtc.org37c05592015-01-28 13:58:27 +000039#include "webrtc/test/rtcp_packet_parser.h"
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000040#include "webrtc/test/rtp_rtcp_observer.h"
41#include "webrtc/test/testsupport/fileutils.h"
andresp@webrtc.orgab071da2014-09-18 08:58:15 +000042#include "webrtc/test/testsupport/gtest_disable.h"
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000043#include "webrtc/test/testsupport/perf_test.h"
44#include "webrtc/video/transport_adapter.h"
pbos@webrtc.orgab990ae2014-09-17 09:02:25 +000045#include "webrtc/video_encoder.h"
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000046
47namespace webrtc {
48
pbos@webrtc.org26c0c412014-09-03 16:17:12 +000049static const unsigned long kSilenceTimeoutMs = 2000;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000050
51class EndToEndTest : public test::CallTest {
52 public:
53 EndToEndTest() {}
54
55 virtual ~EndToEndTest() {
pbos@webrtc.org2b4ce3a2015-03-23 13:12:24 +000056 EXPECT_EQ(nullptr, send_stream_);
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +000057 EXPECT_TRUE(receive_streams_.empty());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000058 }
59
60 protected:
pbos@webrtc.org26c0c412014-09-03 16:17:12 +000061 class UnusedTransport : public newapi::Transport {
62 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +000063 bool SendRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +000064 ADD_FAILURE() << "Unexpected RTP sent.";
65 return false;
66 }
67
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +000068 bool SendRtcp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +000069 ADD_FAILURE() << "Unexpected RTCP sent.";
70 return false;
71 }
72 };
73
Shao Changbine62202f2015-04-21 20:24:50 +080074 void DecodesRetransmittedFrame(bool use_rtx, bool use_red);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000075 void ReceivesPliAndRecovers(int rtp_history_ms);
76 void RespectsRtcpMode(newapi::RtcpMode rtcp_mode);
77 void TestXrReceiverReferenceTimeReport(bool enable_rrtr);
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +000078 void TestSendsSetSsrcs(size_t num_ssrcs, bool send_single_ssrc_first);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +000079 void TestRtpStatePreservation(bool use_rtx);
asapersson@webrtc.org37c05592015-01-28 13:58:27 +000080 void TestReceivedFecPacketsNotNacked(const FakeNetworkPipe::Config& config);
Åsa Persson3c391cb2015-04-27 10:09:49 +020081 void VerifyHistogramStats(bool use_rtx, bool use_red);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000082};
83
84TEST_F(EndToEndTest, ReceiverCanBeStartedTwice) {
85 test::NullTransport transport;
86 CreateCalls(Call::Config(&transport), Call::Config(&transport));
87
88 CreateSendConfig(1);
89 CreateMatchingReceiveConfigs();
90
91 CreateStreams();
92
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +000093 receive_streams_[0]->Start();
94 receive_streams_[0]->Start();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +000095
96 DestroyStreams();
97}
98
99TEST_F(EndToEndTest, ReceiverCanBeStoppedTwice) {
100 test::NullTransport transport;
101 CreateCalls(Call::Config(&transport), Call::Config(&transport));
102
103 CreateSendConfig(1);
104 CreateMatchingReceiveConfigs();
105
106 CreateStreams();
107
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000108 receive_streams_[0]->Stop();
109 receive_streams_[0]->Stop();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000110
111 DestroyStreams();
112}
113
114TEST_F(EndToEndTest, RendersSingleDelayedFrame) {
115 static const int kWidth = 320;
116 static const int kHeight = 240;
117 // This constant is chosen to be higher than the timeout in the video_render
118 // module. This makes sure that frames aren't dropped if there are no other
119 // frames in the queue.
120 static const int kDelayRenderCallbackMs = 1000;
121
122 class Renderer : public VideoRenderer {
123 public:
124 Renderer() : event_(EventWrapper::Create()) {}
125
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000126 void RenderFrame(const I420VideoFrame& video_frame,
127 int /*time_to_render_ms*/) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000128 event_->Set();
129 }
130
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000131 bool IsTextureSupported() const override { return false; }
pbos@webrtc.org0d852d52015-02-09 15:14:36 +0000132
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000133 EventTypeWrapper Wait() { return event_->Wait(kDefaultTimeoutMs); }
134
kwiberg@webrtc.org00b8f6b2015-02-26 14:34:55 +0000135 rtc::scoped_ptr<EventWrapper> event_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000136 } renderer;
137
138 class TestFrameCallback : public I420FrameCallback {
139 public:
140 TestFrameCallback() : event_(EventWrapper::Create()) {}
141
142 EventTypeWrapper Wait() { return event_->Wait(kDefaultTimeoutMs); }
143
144 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000145 void FrameCallback(I420VideoFrame* frame) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000146 SleepMs(kDelayRenderCallbackMs);
147 event_->Set();
148 }
149
kwiberg@webrtc.org00b8f6b2015-02-26 14:34:55 +0000150 rtc::scoped_ptr<EventWrapper> event_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000151 };
152
153 test::DirectTransport sender_transport, receiver_transport;
154
155 CreateCalls(Call::Config(&sender_transport),
156 Call::Config(&receiver_transport));
157
158 sender_transport.SetReceiver(receiver_call_->Receiver());
159 receiver_transport.SetReceiver(sender_call_->Receiver());
160
161 CreateSendConfig(1);
162 CreateMatchingReceiveConfigs();
163
164 TestFrameCallback pre_render_callback;
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000165 receive_configs_[0].pre_render_callback = &pre_render_callback;
166 receive_configs_[0].renderer = &renderer;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000167
168 CreateStreams();
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000169 Start();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000170
171 // Create frames that are smaller than the send width/height, this is done to
172 // check that the callbacks are done after processing video.
kwiberg@webrtc.org00b8f6b2015-02-26 14:34:55 +0000173 rtc::scoped_ptr<test::FrameGenerator> frame_generator(
sprang@webrtc.org131bea82015-02-18 12:46:06 +0000174 test::FrameGenerator::CreateChromaGenerator(kWidth, kHeight));
perkj@webrtc.orgaf612d52015-03-18 09:51:05 +0000175 send_stream_->Input()->IncomingCapturedFrame(*frame_generator->NextFrame());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000176 EXPECT_EQ(kEventSignaled, pre_render_callback.Wait())
177 << "Timed out while waiting for pre-render callback.";
178 EXPECT_EQ(kEventSignaled, renderer.Wait())
179 << "Timed out while waiting for the frame to render.";
180
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000181 Stop();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000182
183 sender_transport.StopSending();
184 receiver_transport.StopSending();
185
186 DestroyStreams();
187}
188
189TEST_F(EndToEndTest, TransmitsFirstFrame) {
190 class Renderer : public VideoRenderer {
191 public:
192 Renderer() : event_(EventWrapper::Create()) {}
193
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000194 void RenderFrame(const I420VideoFrame& video_frame,
195 int /*time_to_render_ms*/) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000196 event_->Set();
197 }
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000198 bool IsTextureSupported() const override { return false; }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000199
200 EventTypeWrapper Wait() { return event_->Wait(kDefaultTimeoutMs); }
201
kwiberg@webrtc.org00b8f6b2015-02-26 14:34:55 +0000202 rtc::scoped_ptr<EventWrapper> event_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000203 } renderer;
204
205 test::DirectTransport sender_transport, receiver_transport;
206
207 CreateCalls(Call::Config(&sender_transport),
208 Call::Config(&receiver_transport));
209
210 sender_transport.SetReceiver(receiver_call_->Receiver());
211 receiver_transport.SetReceiver(sender_call_->Receiver());
212
213 CreateSendConfig(1);
214 CreateMatchingReceiveConfigs();
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000215 receive_configs_[0].renderer = &renderer;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000216
217 CreateStreams();
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000218 Start();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000219
kwiberg@webrtc.org00b8f6b2015-02-26 14:34:55 +0000220 rtc::scoped_ptr<test::FrameGenerator> frame_generator(
sprang@webrtc.org131bea82015-02-18 12:46:06 +0000221 test::FrameGenerator::CreateChromaGenerator(
222 encoder_config_.streams[0].width, encoder_config_.streams[0].height));
perkj@webrtc.orgaf612d52015-03-18 09:51:05 +0000223 send_stream_->Input()->IncomingCapturedFrame(*frame_generator->NextFrame());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000224
225 EXPECT_EQ(kEventSignaled, renderer.Wait())
226 << "Timed out while waiting for the frame to render.";
227
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000228 Stop();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000229
230 sender_transport.StopSending();
231 receiver_transport.StopSending();
232
233 DestroyStreams();
234}
235
marpan@webrtc.org5f1e2e42014-11-06 02:02:28 +0000236TEST_F(EndToEndTest, SendsAndReceivesVP9) {
marpan@webrtc.org5b883172014-11-01 06:10:48 +0000237 class VP9Observer : public test::EndToEndTest, public VideoRenderer {
238 public:
239 VP9Observer()
240 : EndToEndTest(2 * kDefaultTimeoutMs),
241 encoder_(VideoEncoder::Create(VideoEncoder::kVp9)),
242 decoder_(VP9Decoder::Create()),
243 frame_counter_(0) {}
244
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000245 void PerformTest() override {
marpan@webrtc.org5b883172014-11-01 06:10:48 +0000246 EXPECT_EQ(kEventSignaled, Wait())
247 << "Timed out while waiting for enough frames to be decoded.";
248 }
249
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000250 void ModifyConfigs(VideoSendStream::Config* send_config,
251 std::vector<VideoReceiveStream::Config>* receive_configs,
252 VideoEncoderConfig* encoder_config) override {
marpan@webrtc.org5b883172014-11-01 06:10:48 +0000253 send_config->encoder_settings.encoder = encoder_.get();
254 send_config->encoder_settings.payload_name = "VP9";
255 send_config->encoder_settings.payload_type = VCM_VP9_PAYLOAD_TYPE;
256 encoder_config->streams[0].min_bitrate_bps = 50000;
257 encoder_config->streams[0].target_bitrate_bps =
258 encoder_config->streams[0].max_bitrate_bps = 2000000;
259
260 (*receive_configs)[0].renderer = this;
261 (*receive_configs)[0].decoders.resize(1);
262 (*receive_configs)[0].decoders[0].payload_type =
263 send_config->encoder_settings.payload_type;
264 (*receive_configs)[0].decoders[0].payload_name =
265 send_config->encoder_settings.payload_name;
266 (*receive_configs)[0].decoders[0].decoder = decoder_.get();
267 }
268
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000269 void RenderFrame(const I420VideoFrame& video_frame,
270 int time_to_render_ms) override {
marpan@webrtc.org5b883172014-11-01 06:10:48 +0000271 const int kRequiredFrames = 500;
272 if (++frame_counter_ == kRequiredFrames)
273 observation_complete_->Set();
274 }
275
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000276 bool IsTextureSupported() const override { return false; }
pbos@webrtc.org0d852d52015-02-09 15:14:36 +0000277
marpan@webrtc.org5b883172014-11-01 06:10:48 +0000278 private:
kwiberg@webrtc.org00b8f6b2015-02-26 14:34:55 +0000279 rtc::scoped_ptr<webrtc::VideoEncoder> encoder_;
280 rtc::scoped_ptr<webrtc::VideoDecoder> decoder_;
marpan@webrtc.org5b883172014-11-01 06:10:48 +0000281 int frame_counter_;
282 } test;
283
284 RunBaseTest(&test);
285}
286
stefan@webrtc.org79c33592014-08-06 09:24:53 +0000287TEST_F(EndToEndTest, SendsAndReceivesH264) {
288 class H264Observer : public test::EndToEndTest, public VideoRenderer {
289 public:
290 H264Observer()
291 : EndToEndTest(2 * kDefaultTimeoutMs),
292 fake_encoder_(Clock::GetRealTimeClock()),
293 frame_counter_(0) {}
294
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000295 void PerformTest() override {
stefan@webrtc.org79c33592014-08-06 09:24:53 +0000296 EXPECT_EQ(kEventSignaled, Wait())
297 << "Timed out while waiting for enough frames to be decoded.";
298 }
299
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000300 void ModifyConfigs(VideoSendStream::Config* send_config,
301 std::vector<VideoReceiveStream::Config>* receive_configs,
302 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org8278c072015-02-23 11:11:49 +0000303 send_config->rtp.nack.rtp_history_ms =
304 (*receive_configs)[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
stefan@webrtc.org79c33592014-08-06 09:24:53 +0000305 send_config->encoder_settings.encoder = &fake_encoder_;
306 send_config->encoder_settings.payload_name = "H264";
307 send_config->encoder_settings.payload_type = kFakeSendPayloadType;
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +0000308 encoder_config->streams[0].min_bitrate_bps = 50000;
309 encoder_config->streams[0].target_bitrate_bps =
310 encoder_config->streams[0].max_bitrate_bps = 2000000;
stefan@webrtc.org79c33592014-08-06 09:24:53 +0000311
312 (*receive_configs)[0].renderer = this;
pbos@webrtc.org776e6f22014-10-29 15:28:39 +0000313 (*receive_configs)[0].decoders.resize(1);
314 (*receive_configs)[0].decoders[0].payload_type =
stefan@webrtc.org79c33592014-08-06 09:24:53 +0000315 send_config->encoder_settings.payload_type;
pbos@webrtc.org776e6f22014-10-29 15:28:39 +0000316 (*receive_configs)[0].decoders[0].payload_name =
317 send_config->encoder_settings.payload_name;
318 (*receive_configs)[0].decoders[0].decoder = &fake_decoder_;
stefan@webrtc.org79c33592014-08-06 09:24:53 +0000319 }
320
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000321 void RenderFrame(const I420VideoFrame& video_frame,
322 int time_to_render_ms) override {
stefan@webrtc.org79c33592014-08-06 09:24:53 +0000323 const int kRequiredFrames = 500;
324 if (++frame_counter_ == kRequiredFrames)
325 observation_complete_->Set();
326 }
327
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000328 bool IsTextureSupported() const override { return false; }
pbos@webrtc.org0d852d52015-02-09 15:14:36 +0000329
stefan@webrtc.org79c33592014-08-06 09:24:53 +0000330 private:
331 test::FakeH264Decoder fake_decoder_;
332 test::FakeH264Encoder fake_encoder_;
333 int frame_counter_;
334 } test;
335
336 RunBaseTest(&test);
337}
338
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000339TEST_F(EndToEndTest, ReceiverUsesLocalSsrc) {
340 class SyncRtcpObserver : public test::EndToEndTest {
341 public:
342 SyncRtcpObserver() : EndToEndTest(kDefaultTimeoutMs) {}
343
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000344 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000345 RTCPUtility::RTCPParserV2 parser(packet, length, true);
346 EXPECT_TRUE(parser.IsValid());
347 uint32_t ssrc = 0;
348 ssrc |= static_cast<uint32_t>(packet[4]) << 24;
349 ssrc |= static_cast<uint32_t>(packet[5]) << 16;
350 ssrc |= static_cast<uint32_t>(packet[6]) << 8;
351 ssrc |= static_cast<uint32_t>(packet[7]) << 0;
352 EXPECT_EQ(kReceiverLocalSsrc, ssrc);
353 observation_complete_->Set();
354
355 return SEND_PACKET;
356 }
357
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000358 void PerformTest() override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000359 EXPECT_EQ(kEventSignaled, Wait())
360 << "Timed out while waiting for a receiver RTCP packet to be sent.";
361 }
362 } test;
363
364 RunBaseTest(&test);
365}
366
367TEST_F(EndToEndTest, ReceivesAndRetransmitsNack) {
368 static const int kNumberOfNacksToObserve = 2;
369 static const int kLossBurstSize = 2;
370 static const int kPacketsBetweenLossBursts = 9;
371 class NackObserver : public test::EndToEndTest {
372 public:
373 NackObserver()
374 : EndToEndTest(kLongTimeoutMs),
375 rtp_parser_(RtpHeaderParser::Create()),
376 sent_rtp_packets_(0),
377 packets_left_to_drop_(0),
378 nacks_left_(kNumberOfNacksToObserve) {}
379
380 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000381 Action OnSendRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000382 RTPHeader header;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000383 EXPECT_TRUE(rtp_parser_->Parse(packet, length, &header));
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000384
385 // Never drop retransmitted packets.
386 if (dropped_packets_.find(header.sequenceNumber) !=
387 dropped_packets_.end()) {
388 retransmitted_packets_.insert(header.sequenceNumber);
389 if (nacks_left_ == 0 &&
390 retransmitted_packets_.size() == dropped_packets_.size()) {
391 observation_complete_->Set();
392 }
393 return SEND_PACKET;
394 }
395
396 ++sent_rtp_packets_;
397
398 // Enough NACKs received, stop dropping packets.
399 if (nacks_left_ == 0)
400 return SEND_PACKET;
401
402 // Check if it's time for a new loss burst.
403 if (sent_rtp_packets_ % kPacketsBetweenLossBursts == 0)
404 packets_left_to_drop_ = kLossBurstSize;
405
Stefan Holmer01b48882015-05-05 10:21:24 +0200406 // Never drop padding packets as those won't be retransmitted.
407 if (packets_left_to_drop_ > 0 && header.paddingLength == 0) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000408 --packets_left_to_drop_;
409 dropped_packets_.insert(header.sequenceNumber);
410 return DROP_PACKET;
411 }
412
413 return SEND_PACKET;
414 }
415
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000416 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000417 RTCPUtility::RTCPParserV2 parser(packet, length, true);
418 EXPECT_TRUE(parser.IsValid());
419
420 RTCPUtility::RTCPPacketTypes packet_type = parser.Begin();
Erik Språng242e22b2015-05-11 10:17:43 +0200421 while (packet_type != RTCPUtility::RTCPPacketTypes::kInvalid) {
422 if (packet_type == RTCPUtility::RTCPPacketTypes::kRtpfbNack) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000423 --nacks_left_;
424 break;
425 }
426 packet_type = parser.Iterate();
427 }
428 return SEND_PACKET;
429 }
430
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000431 void ModifyConfigs(VideoSendStream::Config* send_config,
432 std::vector<VideoReceiveStream::Config>* receive_configs,
433 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000434 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000435 (*receive_configs)[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000436 }
437
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000438 void PerformTest() override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000439 EXPECT_EQ(kEventSignaled, Wait())
440 << "Timed out waiting for packets to be NACKed, retransmitted and "
441 "rendered.";
442 }
443
kwiberg@webrtc.org00b8f6b2015-02-26 14:34:55 +0000444 rtc::scoped_ptr<RtpHeaderParser> rtp_parser_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000445 std::set<uint16_t> dropped_packets_;
446 std::set<uint16_t> retransmitted_packets_;
447 uint64_t sent_rtp_packets_;
448 int packets_left_to_drop_;
449 int nacks_left_;
450 } test;
451
452 RunBaseTest(&test);
453}
454
pbos@webrtc.orga9c2d452014-11-13 14:40:15 +0000455TEST_F(EndToEndTest, CanReceiveFec) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000456 class FecRenderObserver : public test::EndToEndTest, public VideoRenderer {
457 public:
458 FecRenderObserver()
pbos@webrtc.orga9c2d452014-11-13 14:40:15 +0000459 : EndToEndTest(kDefaultTimeoutMs), state_(kFirstPacket) {}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000460
461 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000462 Action OnSendRtp(const uint8_t* packet, size_t length) override
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000463 EXCLUSIVE_LOCKS_REQUIRED(crit_) {
464 RTPHeader header;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000465 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000466
Stefan Holmer01b48882015-05-05 10:21:24 +0200467 int encapsulated_payload_type = -1;
468 if (header.payloadType == kRedPayloadType) {
469 encapsulated_payload_type =
470 static_cast<int>(packet[header.headerLength]);
471 if (encapsulated_payload_type != kFakeSendPayloadType)
472 EXPECT_EQ(kUlpfecPayloadType, encapsulated_payload_type);
473 } else {
474 EXPECT_EQ(kFakeSendPayloadType, header.payloadType);
475 }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000476
pbos@webrtc.orga9c2d452014-11-13 14:40:15 +0000477 if (protected_sequence_numbers_.count(header.sequenceNumber) != 0) {
478 // Retransmitted packet, should not count.
479 protected_sequence_numbers_.erase(header.sequenceNumber);
480 EXPECT_GT(protected_timestamps_.count(header.timestamp), 0u);
481 protected_timestamps_.erase(header.timestamp);
482 return SEND_PACKET;
483 }
484
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000485 switch (state_) {
486 case kFirstPacket:
487 state_ = kDropEveryOtherPacketUntilFec;
488 break;
489 case kDropEveryOtherPacketUntilFec:
490 if (encapsulated_payload_type == kUlpfecPayloadType) {
491 state_ = kDropNextMediaPacket;
492 return SEND_PACKET;
493 }
494 if (header.sequenceNumber % 2 == 0)
495 return DROP_PACKET;
496 break;
497 case kDropNextMediaPacket:
498 if (encapsulated_payload_type == kFakeSendPayloadType) {
pbos@webrtc.orga9c2d452014-11-13 14:40:15 +0000499 protected_sequence_numbers_.insert(header.sequenceNumber);
500 protected_timestamps_.insert(header.timestamp);
501 state_ = kDropEveryOtherPacketUntilFec;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000502 return DROP_PACKET;
503 }
504 break;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000505 }
506
507 return SEND_PACKET;
508 }
509
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000510 void RenderFrame(const I420VideoFrame& video_frame,
511 int time_to_render_ms) override {
Peter Boströmf2f82832015-05-01 13:00:41 +0200512 rtc::CritScope lock(&crit_);
pbos@webrtc.orga9c2d452014-11-13 14:40:15 +0000513 // Rendering frame with timestamp of packet that was dropped -> FEC
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000514 // protection worked.
pbos@webrtc.orga9c2d452014-11-13 14:40:15 +0000515 if (protected_timestamps_.count(video_frame.timestamp()) != 0)
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000516 observation_complete_->Set();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000517 }
518
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000519 bool IsTextureSupported() const override { return false; }
pbos@webrtc.org0d852d52015-02-09 15:14:36 +0000520
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000521 enum {
522 kFirstPacket,
523 kDropEveryOtherPacketUntilFec,
524 kDropNextMediaPacket,
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000525 } state_;
526
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000527 void ModifyConfigs(VideoSendStream::Config* send_config,
528 std::vector<VideoReceiveStream::Config>* receive_configs,
529 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000530 // TODO(pbos): Run this test with combined NACK/FEC enabled as well.
531 // int rtp_history_ms = 1000;
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000532 // (*receive_configs)[0].rtp.nack.rtp_history_ms = rtp_history_ms;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000533 // send_config->rtp.nack.rtp_history_ms = rtp_history_ms;
534 send_config->rtp.fec.red_payload_type = kRedPayloadType;
535 send_config->rtp.fec.ulpfec_payload_type = kUlpfecPayloadType;
536
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000537 (*receive_configs)[0].rtp.fec.red_payload_type = kRedPayloadType;
538 (*receive_configs)[0].rtp.fec.ulpfec_payload_type = kUlpfecPayloadType;
539 (*receive_configs)[0].renderer = this;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000540 }
541
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000542 void PerformTest() override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000543 EXPECT_EQ(kEventSignaled, Wait())
pbos@webrtc.orga9c2d452014-11-13 14:40:15 +0000544 << "Timed out waiting for dropped frames frames to be rendered.";
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000545 }
546
pbos@webrtc.orga9c2d452014-11-13 14:40:15 +0000547 std::set<uint32_t> protected_sequence_numbers_ GUARDED_BY(crit_);
548 std::set<uint32_t> protected_timestamps_ GUARDED_BY(crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000549 } test;
550
551 RunBaseTest(&test);
552}
553
Henrik Kjellanderdb313b62015-04-02 08:45:41 +0200554// Flacky on all platforms. See webrtc:4328.
555TEST_F(EndToEndTest, DISABLED_ReceivedFecPacketsNotNacked) {
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000556 // At low RTT (< kLowRttNackMs) -> NACK only, no FEC.
557 // Configure some network delay.
558 const int kNetworkDelayMs = 50;
559 FakeNetworkPipe::Config config;
560 config.queue_delay_ms = kNetworkDelayMs;
561 TestReceivedFecPacketsNotNacked(config);
562}
563
564void EndToEndTest::TestReceivedFecPacketsNotNacked(
565 const FakeNetworkPipe::Config& config) {
566 class FecNackObserver : public test::EndToEndTest {
567 public:
568 explicit FecNackObserver(const FakeNetworkPipe::Config& config)
569 : EndToEndTest(kDefaultTimeoutMs, config),
asapersson@webrtc.org5c928eb2015-02-25 11:47:11 +0000570 state_(kFirstPacket),
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000571 fec_sequence_number_(0),
572 has_last_sequence_number_(false),
573 last_sequence_number_(0) {}
574
575 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000576 Action OnSendRtp(const uint8_t* packet, size_t length) override {
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000577 RTPHeader header;
578 EXPECT_TRUE(parser_->Parse(packet, length, &header));
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000579
Stefan Holmer01b48882015-05-05 10:21:24 +0200580 int encapsulated_payload_type = -1;
581 if (header.payloadType == kRedPayloadType) {
582 encapsulated_payload_type =
583 static_cast<int>(packet[header.headerLength]);
584 if (encapsulated_payload_type != kFakeSendPayloadType)
585 EXPECT_EQ(kUlpfecPayloadType, encapsulated_payload_type);
586 } else {
587 EXPECT_EQ(kFakeSendPayloadType, header.payloadType);
588 }
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000589
590 if (has_last_sequence_number_ &&
591 !IsNewerSequenceNumber(header.sequenceNumber,
592 last_sequence_number_)) {
593 // Drop retransmitted packets.
594 return DROP_PACKET;
595 }
596 last_sequence_number_ = header.sequenceNumber;
597 has_last_sequence_number_ = true;
598
599 bool fec_packet = encapsulated_payload_type == kUlpfecPayloadType;
600 switch (state_) {
asapersson@webrtc.org5c928eb2015-02-25 11:47:11 +0000601 case kFirstPacket:
602 state_ = kDropEveryOtherPacketUntilFec;
603 break;
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000604 case kDropEveryOtherPacketUntilFec:
605 if (fec_packet) {
606 state_ = kDropAllMediaPacketsUntilFec;
607 } else if (header.sequenceNumber % 2 == 0) {
608 return DROP_PACKET;
609 }
610 break;
611 case kDropAllMediaPacketsUntilFec:
612 if (!fec_packet)
613 return DROP_PACKET;
614 fec_sequence_number_ = header.sequenceNumber;
615 state_ = kVerifyFecPacketNotInNackList;
616 break;
617 case kVerifyFecPacketNotInNackList:
618 // Continue to drop packets. Make sure no frame can be decoded.
619 if (fec_packet || header.sequenceNumber % 2 == 0)
620 return DROP_PACKET;
621 break;
622 }
623 return SEND_PACKET;
624 }
625
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000626 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000627 if (state_ == kVerifyFecPacketNotInNackList) {
628 test::RtcpPacketParser rtcp_parser;
629 rtcp_parser.Parse(packet, length);
630 std::vector<uint16_t> nacks = rtcp_parser.nack_item()->last_nack_list();
631 if (!nacks.empty() &&
632 IsNewerSequenceNumber(nacks.back(), fec_sequence_number_)) {
633 EXPECT_TRUE(std::find(
634 nacks.begin(), nacks.end(), fec_sequence_number_) == nacks.end());
635 observation_complete_->Set();
636 }
637 }
638 return SEND_PACKET;
639 }
640
Stefan Holmere5904162015-03-26 11:11:06 +0100641 // TODO(holmer): Investigate why we don't send FEC packets when the bitrate
642 // is 10 kbps.
643 Call::Config GetSenderCallConfig() override {
644 Call::Config config(SendTransport());
645 const int kMinBitrateBps = 30000;
646 config.bitrate_config.min_bitrate_bps = kMinBitrateBps;
647 return config;
648 }
649
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000650 void ModifyConfigs(VideoSendStream::Config* send_config,
651 std::vector<VideoReceiveStream::Config>* receive_configs,
652 VideoEncoderConfig* encoder_config) override {
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000653 // Configure hybrid NACK/FEC.
654 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
655 send_config->rtp.fec.red_payload_type = kRedPayloadType;
656 send_config->rtp.fec.ulpfec_payload_type = kUlpfecPayloadType;
657 (*receive_configs)[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
658 (*receive_configs)[0].rtp.fec.red_payload_type = kRedPayloadType;
659 (*receive_configs)[0].rtp.fec.ulpfec_payload_type = kUlpfecPayloadType;
660 }
661
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000662 void PerformTest() override {
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000663 EXPECT_EQ(kEventSignaled, Wait())
664 << "Timed out while waiting for FEC packets to be received.";
665 }
666
667 enum {
asapersson@webrtc.org5c928eb2015-02-25 11:47:11 +0000668 kFirstPacket,
asapersson@webrtc.org37c05592015-01-28 13:58:27 +0000669 kDropEveryOtherPacketUntilFec,
670 kDropAllMediaPacketsUntilFec,
671 kVerifyFecPacketNotInNackList,
672 } state_;
673
674 uint16_t fec_sequence_number_;
675 bool has_last_sequence_number_;
676 uint16_t last_sequence_number_;
677 } test(config);
678
679 RunBaseTest(&test);
680}
681
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000682// This test drops second RTP packet with a marker bit set, makes sure it's
683// retransmitted and renders. Retransmission SSRCs are also checked.
Shao Changbine62202f2015-04-21 20:24:50 +0800684void EndToEndTest::DecodesRetransmittedFrame(bool use_rtx, bool use_red) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000685 static const int kDroppedFrameNumber = 2;
686 class RetransmissionObserver : public test::EndToEndTest,
687 public I420FrameCallback {
688 public:
Shao Changbine62202f2015-04-21 20:24:50 +0800689 explicit RetransmissionObserver(bool use_rtx, bool use_red)
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000690 : EndToEndTest(kDefaultTimeoutMs),
Shao Changbine62202f2015-04-21 20:24:50 +0800691 payload_type_(GetPayloadType(false, use_red)),
692 retransmission_ssrc_(use_rtx ? kSendRtxSsrcs[0] : kSendSsrcs[0]),
693 retransmission_payload_type_(GetPayloadType(use_rtx, use_red)),
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000694 marker_bits_observed_(0),
695 retransmitted_timestamp_(0),
696 frame_retransmitted_(false) {}
697
698 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000699 Action OnSendRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000700 RTPHeader header;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000701 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000702
703 if (header.timestamp == retransmitted_timestamp_) {
704 EXPECT_EQ(retransmission_ssrc_, header.ssrc);
705 EXPECT_EQ(retransmission_payload_type_, header.payloadType);
706 frame_retransmitted_ = true;
707 return SEND_PACKET;
708 }
709
710 EXPECT_EQ(kSendSsrcs[0], header.ssrc);
Shao Changbine62202f2015-04-21 20:24:50 +0800711 EXPECT_EQ(payload_type_, header.payloadType);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000712
713 // Found the second frame's final packet, drop this and expect a
714 // retransmission.
715 if (header.markerBit && ++marker_bits_observed_ == kDroppedFrameNumber) {
716 retransmitted_timestamp_ = header.timestamp;
717 return DROP_PACKET;
718 }
719
720 return SEND_PACKET;
721 }
722
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000723 void FrameCallback(I420VideoFrame* frame) override {
Peter Boströmf2f82832015-05-01 13:00:41 +0200724 rtc::CritScope lock(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000725 if (frame->timestamp() == retransmitted_timestamp_) {
726 EXPECT_TRUE(frame_retransmitted_);
727 observation_complete_->Set();
728 }
729 }
730
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000731 void ModifyConfigs(VideoSendStream::Config* send_config,
732 std::vector<VideoReceiveStream::Config>* receive_configs,
733 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000734 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000735 (*receive_configs)[0].pre_render_callback = this;
736 (*receive_configs)[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
Shao Changbine62202f2015-04-21 20:24:50 +0800737
738 if (payload_type_ == kRedPayloadType) {
739 send_config->rtp.fec.ulpfec_payload_type = kUlpfecPayloadType;
740 send_config->rtp.fec.red_payload_type = kRedPayloadType;
741 (*receive_configs)[0].rtp.fec.red_payload_type = kRedPayloadType;
742 (*receive_configs)[0].rtp.fec.ulpfec_payload_type = kUlpfecPayloadType;
743 }
744
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +0000745 if (retransmission_ssrc_ == kSendRtxSsrcs[0]) {
746 send_config->rtp.rtx.ssrcs.push_back(kSendRtxSsrcs[0]);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000747 send_config->rtp.rtx.payload_type = kSendRtxPayloadType;
Shao Changbine62202f2015-04-21 20:24:50 +0800748 (*receive_configs)[0].rtp.rtx[kFakeSendPayloadType].ssrc =
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +0000749 kSendRtxSsrcs[0];
Shao Changbine62202f2015-04-21 20:24:50 +0800750 (*receive_configs)[0].rtp.rtx[kFakeSendPayloadType].payload_type =
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000751 kSendRtxPayloadType;
752 }
753 }
754
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000755 void PerformTest() override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000756 EXPECT_EQ(kEventSignaled, Wait())
757 << "Timed out while waiting for retransmission to render.";
758 }
759
Shao Changbine62202f2015-04-21 20:24:50 +0800760 int GetPayloadType(bool use_rtx, bool use_red) {
761 return use_rtx ? kSendRtxPayloadType
762 : (use_red ? kRedPayloadType : kFakeSendPayloadType);
763 }
764
765 const int payload_type_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000766 const uint32_t retransmission_ssrc_;
767 const int retransmission_payload_type_;
768 int marker_bits_observed_;
769 uint32_t retransmitted_timestamp_;
770 bool frame_retransmitted_;
Shao Changbine62202f2015-04-21 20:24:50 +0800771 } test(use_rtx, use_red);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000772
773 RunBaseTest(&test);
774}
775
776TEST_F(EndToEndTest, DecodesRetransmittedFrame) {
Shao Changbine62202f2015-04-21 20:24:50 +0800777 DecodesRetransmittedFrame(false, false);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000778}
779
780TEST_F(EndToEndTest, DecodesRetransmittedFrameOverRtx) {
Shao Changbine62202f2015-04-21 20:24:50 +0800781 DecodesRetransmittedFrame(true, false);
782}
783
784TEST_F(EndToEndTest, DecodesRetransmittedFrameByRed) {
785 DecodesRetransmittedFrame(false, true);
786}
787
788TEST_F(EndToEndTest, DecodesRetransmittedFrameByRedOverRtx) {
789 DecodesRetransmittedFrame(true, true);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000790}
791
andresp@webrtc.org02686112014-09-19 08:24:19 +0000792TEST_F(EndToEndTest, UsesFrameCallbacks) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000793 static const int kWidth = 320;
794 static const int kHeight = 240;
795
796 class Renderer : public VideoRenderer {
797 public:
798 Renderer() : event_(EventWrapper::Create()) {}
799
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000800 void RenderFrame(const I420VideoFrame& video_frame,
801 int /*time_to_render_ms*/) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000802 EXPECT_EQ(0, *video_frame.buffer(kYPlane))
803 << "Rendered frame should have zero luma which is applied by the "
804 "pre-render callback.";
805 event_->Set();
806 }
807
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000808 bool IsTextureSupported() const override { return false; }
pbos@webrtc.org0d852d52015-02-09 15:14:36 +0000809
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000810 EventTypeWrapper Wait() { return event_->Wait(kDefaultTimeoutMs); }
kwiberg@webrtc.org00b8f6b2015-02-26 14:34:55 +0000811 rtc::scoped_ptr<EventWrapper> event_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000812 } renderer;
813
814 class TestFrameCallback : public I420FrameCallback {
815 public:
816 TestFrameCallback(int expected_luma_byte, int next_luma_byte)
817 : event_(EventWrapper::Create()),
818 expected_luma_byte_(expected_luma_byte),
819 next_luma_byte_(next_luma_byte) {}
820
821 EventTypeWrapper Wait() { return event_->Wait(kDefaultTimeoutMs); }
822
823 private:
824 virtual void FrameCallback(I420VideoFrame* frame) {
825 EXPECT_EQ(kWidth, frame->width())
826 << "Width not as expected, callback done before resize?";
827 EXPECT_EQ(kHeight, frame->height())
828 << "Height not as expected, callback done before resize?";
829
830 // Previous luma specified, observed luma should be fairly close.
831 if (expected_luma_byte_ != -1) {
832 EXPECT_NEAR(expected_luma_byte_, *frame->buffer(kYPlane), 10);
833 }
834
835 memset(frame->buffer(kYPlane),
836 next_luma_byte_,
837 frame->allocated_size(kYPlane));
838
839 event_->Set();
840 }
841
kwiberg@webrtc.org00b8f6b2015-02-26 14:34:55 +0000842 rtc::scoped_ptr<EventWrapper> event_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000843 int expected_luma_byte_;
844 int next_luma_byte_;
845 };
846
847 TestFrameCallback pre_encode_callback(-1, 255); // Changes luma to 255.
848 TestFrameCallback pre_render_callback(255, 0); // Changes luma from 255 to 0.
849
850 test::DirectTransport sender_transport, receiver_transport;
851
852 CreateCalls(Call::Config(&sender_transport),
853 Call::Config(&receiver_transport));
854
855 sender_transport.SetReceiver(receiver_call_->Receiver());
856 receiver_transport.SetReceiver(sender_call_->Receiver());
857
858 CreateSendConfig(1);
kwiberg@webrtc.org00b8f6b2015-02-26 14:34:55 +0000859 rtc::scoped_ptr<VideoEncoder> encoder(
pbos@webrtc.orgab990ae2014-09-17 09:02:25 +0000860 VideoEncoder::Create(VideoEncoder::kVp8));
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000861 send_config_.encoder_settings.encoder = encoder.get();
862 send_config_.encoder_settings.payload_name = "VP8";
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +0000863 ASSERT_EQ(1u, encoder_config_.streams.size()) << "Test setup error.";
864 encoder_config_.streams[0].width = kWidth;
865 encoder_config_.streams[0].height = kHeight;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000866 send_config_.pre_encode_callback = &pre_encode_callback;
867
868 CreateMatchingReceiveConfigs();
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000869 receive_configs_[0].pre_render_callback = &pre_render_callback;
870 receive_configs_[0].renderer = &renderer;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000871
872 CreateStreams();
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000873 Start();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000874
875 // Create frames that are smaller than the send width/height, this is done to
876 // check that the callbacks are done after processing video.
kwiberg@webrtc.org00b8f6b2015-02-26 14:34:55 +0000877 rtc::scoped_ptr<test::FrameGenerator> frame_generator(
sprang@webrtc.org131bea82015-02-18 12:46:06 +0000878 test::FrameGenerator::CreateChromaGenerator(kWidth / 2, kHeight / 2));
perkj@webrtc.orgaf612d52015-03-18 09:51:05 +0000879 send_stream_->Input()->IncomingCapturedFrame(*frame_generator->NextFrame());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000880
881 EXPECT_EQ(kEventSignaled, pre_encode_callback.Wait())
882 << "Timed out while waiting for pre-encode callback.";
883 EXPECT_EQ(kEventSignaled, pre_render_callback.Wait())
884 << "Timed out while waiting for pre-render callback.";
885 EXPECT_EQ(kEventSignaled, renderer.Wait())
886 << "Timed out while waiting for the frame to render.";
887
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000888 Stop();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000889
890 sender_transport.StopSending();
891 receiver_transport.StopSending();
892
893 DestroyStreams();
894}
895
896void EndToEndTest::ReceivesPliAndRecovers(int rtp_history_ms) {
897 static const int kPacketsToDrop = 1;
898
899 class PliObserver : public test::EndToEndTest, public VideoRenderer {
900 public:
901 explicit PliObserver(int rtp_history_ms)
902 : EndToEndTest(kLongTimeoutMs),
903 rtp_history_ms_(rtp_history_ms),
904 nack_enabled_(rtp_history_ms > 0),
905 highest_dropped_timestamp_(0),
906 frames_to_drop_(0),
907 received_pli_(false) {}
908
909 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000910 Action OnSendRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000911 RTPHeader header;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +0000912 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000913
914 // Drop all retransmitted packets to force a PLI.
915 if (header.timestamp <= highest_dropped_timestamp_)
916 return DROP_PACKET;
917
918 if (frames_to_drop_ > 0) {
919 highest_dropped_timestamp_ = header.timestamp;
920 --frames_to_drop_;
921 return DROP_PACKET;
922 }
923
924 return SEND_PACKET;
925 }
926
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000927 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000928 RTCPUtility::RTCPParserV2 parser(packet, length, true);
929 EXPECT_TRUE(parser.IsValid());
930
931 for (RTCPUtility::RTCPPacketTypes packet_type = parser.Begin();
Erik Språng242e22b2015-05-11 10:17:43 +0200932 packet_type != RTCPUtility::RTCPPacketTypes::kInvalid;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000933 packet_type = parser.Iterate()) {
934 if (!nack_enabled_)
Erik Språng242e22b2015-05-11 10:17:43 +0200935 EXPECT_NE(packet_type, RTCPUtility::RTCPPacketTypes::kRtpfbNack);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000936
Erik Språng242e22b2015-05-11 10:17:43 +0200937 if (packet_type == RTCPUtility::RTCPPacketTypes::kPsfbPli) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000938 received_pli_ = true;
939 break;
940 }
941 }
942 return SEND_PACKET;
943 }
944
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000945 void RenderFrame(const I420VideoFrame& video_frame,
946 int time_to_render_ms) override {
Peter Boströmf2f82832015-05-01 13:00:41 +0200947 rtc::CritScope lock(&crit_);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000948 if (received_pli_ &&
949 video_frame.timestamp() > highest_dropped_timestamp_) {
950 observation_complete_->Set();
951 }
952 if (!received_pli_)
953 frames_to_drop_ = kPacketsToDrop;
954 }
955
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000956 bool IsTextureSupported() const override { return false; }
pbos@webrtc.org0d852d52015-02-09 15:14:36 +0000957
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000958 void ModifyConfigs(VideoSendStream::Config* send_config,
959 std::vector<VideoReceiveStream::Config>* receive_configs,
960 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000961 send_config->rtp.nack.rtp_history_ms = rtp_history_ms_;
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000962 (*receive_configs)[0].rtp.nack.rtp_history_ms = rtp_history_ms_;
963 (*receive_configs)[0].renderer = this;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000964 }
965
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000966 void PerformTest() override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +0000967 EXPECT_EQ(kEventSignaled, Wait()) << "Timed out waiting for PLI to be "
968 "received and a frame to be "
969 "rendered afterwards.";
970 }
971
972 int rtp_history_ms_;
973 bool nack_enabled_;
974 uint32_t highest_dropped_timestamp_;
975 int frames_to_drop_;
976 bool received_pli_;
977 } test(rtp_history_ms);
978
979 RunBaseTest(&test);
980}
981
982TEST_F(EndToEndTest, ReceivesPliAndRecoversWithNack) {
983 ReceivesPliAndRecovers(1000);
984}
985
986// TODO(pbos): Enable this when 2250 is resolved.
987TEST_F(EndToEndTest, DISABLED_ReceivesPliAndRecoversWithoutNack) {
988 ReceivesPliAndRecovers(0);
989}
990
991TEST_F(EndToEndTest, UnknownRtpPacketGivesUnknownSsrcReturnCode) {
992 class PacketInputObserver : public PacketReceiver {
993 public:
994 explicit PacketInputObserver(PacketReceiver* receiver)
995 : receiver_(receiver), delivered_packet_(EventWrapper::Create()) {}
996
997 EventTypeWrapper Wait() {
998 return delivered_packet_->Wait(kDefaultTimeoutMs);
999 }
1000
1001 private:
Fredrik Solenberg23fba1f2015-04-29 15:24:01 +02001002 DeliveryStatus DeliverPacket(MediaType media_type, const uint8_t* packet,
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001003 size_t length) override {
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001004 if (RtpHeaderParser::IsRtcp(packet, length)) {
Fredrik Solenberg23fba1f2015-04-29 15:24:01 +02001005 return receiver_->DeliverPacket(media_type, packet, length);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001006 } else {
1007 DeliveryStatus delivery_status =
Fredrik Solenberg23fba1f2015-04-29 15:24:01 +02001008 receiver_->DeliverPacket(media_type, packet, length);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001009 EXPECT_EQ(DELIVERY_UNKNOWN_SSRC, delivery_status);
1010 delivered_packet_->Set();
1011 return delivery_status;
1012 }
1013 }
1014
1015 PacketReceiver* receiver_;
kwiberg@webrtc.org00b8f6b2015-02-26 14:34:55 +00001016 rtc::scoped_ptr<EventWrapper> delivered_packet_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001017 };
1018
1019 test::DirectTransport send_transport, receive_transport;
1020
1021 CreateCalls(Call::Config(&send_transport), Call::Config(&receive_transport));
1022 PacketInputObserver input_observer(receiver_call_->Receiver());
1023
1024 send_transport.SetReceiver(&input_observer);
1025 receive_transport.SetReceiver(sender_call_->Receiver());
1026
1027 CreateSendConfig(1);
1028 CreateMatchingReceiveConfigs();
1029
1030 CreateStreams();
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001031 CreateFrameGeneratorCapturer();
1032 Start();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001033
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001034 receiver_call_->DestroyVideoReceiveStream(receive_streams_[0]);
1035 receive_streams_.clear();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001036
1037 // Wait() waits for a received packet.
1038 EXPECT_EQ(kEventSignaled, input_observer.Wait());
1039
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001040 Stop();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001041
1042 DestroyStreams();
1043
1044 send_transport.StopSending();
1045 receive_transport.StopSending();
1046}
1047
1048void EndToEndTest::RespectsRtcpMode(newapi::RtcpMode rtcp_mode) {
1049 static const int kNumCompoundRtcpPacketsToObserve = 10;
1050 class RtcpModeObserver : public test::EndToEndTest {
1051 public:
1052 explicit RtcpModeObserver(newapi::RtcpMode rtcp_mode)
1053 : EndToEndTest(kDefaultTimeoutMs),
1054 rtcp_mode_(rtcp_mode),
1055 sent_rtp_(0),
1056 sent_rtcp_(0) {}
1057
1058 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001059 Action OnSendRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001060 if (++sent_rtp_ % 3 == 0)
1061 return DROP_PACKET;
1062
1063 return SEND_PACKET;
1064 }
1065
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001066 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001067 ++sent_rtcp_;
1068 RTCPUtility::RTCPParserV2 parser(packet, length, true);
1069 EXPECT_TRUE(parser.IsValid());
1070
1071 RTCPUtility::RTCPPacketTypes packet_type = parser.Begin();
1072 bool has_report_block = false;
Erik Språng242e22b2015-05-11 10:17:43 +02001073 while (packet_type != RTCPUtility::RTCPPacketTypes::kInvalid) {
1074 EXPECT_NE(RTCPUtility::RTCPPacketTypes::kSr, packet_type);
1075 if (packet_type == RTCPUtility::RTCPPacketTypes::kRr) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001076 has_report_block = true;
1077 break;
1078 }
1079 packet_type = parser.Iterate();
1080 }
1081
1082 switch (rtcp_mode_) {
1083 case newapi::kRtcpCompound:
1084 if (!has_report_block) {
1085 ADD_FAILURE() << "Received RTCP packet without receiver report for "
1086 "kRtcpCompound.";
1087 observation_complete_->Set();
1088 }
1089
1090 if (sent_rtcp_ >= kNumCompoundRtcpPacketsToObserve)
1091 observation_complete_->Set();
1092
1093 break;
1094 case newapi::kRtcpReducedSize:
1095 if (!has_report_block)
1096 observation_complete_->Set();
1097 break;
1098 }
1099
1100 return SEND_PACKET;
1101 }
1102
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001103 void ModifyConfigs(VideoSendStream::Config* send_config,
1104 std::vector<VideoReceiveStream::Config>* receive_configs,
1105 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001106 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001107 (*receive_configs)[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
1108 (*receive_configs)[0].rtp.rtcp_mode = rtcp_mode_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001109 }
1110
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001111 void PerformTest() override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001112 EXPECT_EQ(kEventSignaled, Wait())
1113 << (rtcp_mode_ == newapi::kRtcpCompound
1114 ? "Timed out before observing enough compound packets."
1115 : "Timed out before receiving a non-compound RTCP packet.");
1116 }
1117
1118 newapi::RtcpMode rtcp_mode_;
1119 int sent_rtp_;
1120 int sent_rtcp_;
1121 } test(rtcp_mode);
1122
1123 RunBaseTest(&test);
1124}
1125
1126TEST_F(EndToEndTest, UsesRtcpCompoundMode) {
1127 RespectsRtcpMode(newapi::kRtcpCompound);
1128}
1129
1130TEST_F(EndToEndTest, UsesRtcpReducedSizeMode) {
1131 RespectsRtcpMode(newapi::kRtcpReducedSize);
1132}
1133
1134// Test sets up a Call multiple senders with different resolutions and SSRCs.
1135// Another is set up to receive all three of these with different renderers.
1136// Each renderer verifies that it receives the expected resolution, and as soon
1137// as every renderer has received a frame, the test finishes.
andresp@webrtc.org02686112014-09-19 08:24:19 +00001138TEST_F(EndToEndTest, SendsAndReceivesMultipleStreams) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001139 static const size_t kNumStreams = 3;
1140
1141 class VideoOutputObserver : public VideoRenderer {
1142 public:
1143 VideoOutputObserver(test::FrameGeneratorCapturer** capturer,
1144 int width,
1145 int height)
1146 : capturer_(capturer),
1147 width_(width),
1148 height_(height),
1149 done_(EventWrapper::Create()) {}
1150
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001151 void RenderFrame(const I420VideoFrame& video_frame,
1152 int time_to_render_ms) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001153 EXPECT_EQ(width_, video_frame.width());
1154 EXPECT_EQ(height_, video_frame.height());
1155 (*capturer_)->Stop();
1156 done_->Set();
1157 }
1158
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001159 bool IsTextureSupported() const override { return false; }
pbos@webrtc.org0d852d52015-02-09 15:14:36 +00001160
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001161 EventTypeWrapper Wait() { return done_->Wait(kDefaultTimeoutMs); }
1162
1163 private:
1164 test::FrameGeneratorCapturer** capturer_;
1165 int width_;
1166 int height_;
kwiberg@webrtc.org00b8f6b2015-02-26 14:34:55 +00001167 rtc::scoped_ptr<EventWrapper> done_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001168 };
1169
1170 struct {
1171 uint32_t ssrc;
1172 int width;
1173 int height;
1174 } codec_settings[kNumStreams] = {{1, 640, 480}, {2, 320, 240}, {3, 240, 160}};
1175
1176 test::DirectTransport sender_transport, receiver_transport;
kwiberg@webrtc.org00b8f6b2015-02-26 14:34:55 +00001177 rtc::scoped_ptr<Call> sender_call(
1178 Call::Create(Call::Config(&sender_transport)));
1179 rtc::scoped_ptr<Call> receiver_call(
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001180 Call::Create(Call::Config(&receiver_transport)));
1181 sender_transport.SetReceiver(receiver_call->Receiver());
1182 receiver_transport.SetReceiver(sender_call->Receiver());
1183
1184 VideoSendStream* send_streams[kNumStreams];
1185 VideoReceiveStream* receive_streams[kNumStreams];
1186
1187 VideoOutputObserver* observers[kNumStreams];
1188 test::FrameGeneratorCapturer* frame_generators[kNumStreams];
1189
kwiberg@webrtc.org00b8f6b2015-02-26 14:34:55 +00001190 rtc::scoped_ptr<VideoEncoder> encoders[kNumStreams];
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001191 for (size_t i = 0; i < kNumStreams; ++i)
pbos@webrtc.orgab990ae2014-09-17 09:02:25 +00001192 encoders[i].reset(VideoEncoder::Create(VideoEncoder::kVp8));
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001193
pbos@webrtc.org776e6f22014-10-29 15:28:39 +00001194 ScopedVector<VideoDecoder> allocated_decoders;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001195 for (size_t i = 0; i < kNumStreams; ++i) {
1196 uint32_t ssrc = codec_settings[i].ssrc;
1197 int width = codec_settings[i].width;
1198 int height = codec_settings[i].height;
1199 observers[i] = new VideoOutputObserver(&frame_generators[i], width, height);
1200
pbos@webrtc.orgbd249bc2014-07-07 04:45:15 +00001201 VideoSendStream::Config send_config;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001202 send_config.rtp.ssrcs.push_back(ssrc);
1203 send_config.encoder_settings.encoder = encoders[i].get();
1204 send_config.encoder_settings.payload_name = "VP8";
1205 send_config.encoder_settings.payload_type = 124;
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +00001206 VideoEncoderConfig encoder_config;
1207 encoder_config.streams = test::CreateVideoStreams(1);
1208 VideoStream* stream = &encoder_config.streams[0];
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001209 stream->width = width;
1210 stream->height = height;
1211 stream->max_framerate = 5;
1212 stream->min_bitrate_bps = stream->target_bitrate_bps =
1213 stream->max_bitrate_bps = 100000;
1214 send_streams[i] =
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +00001215 sender_call->CreateVideoSendStream(send_config, encoder_config);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001216 send_streams[i]->Start();
1217
pbos@webrtc.orgbd249bc2014-07-07 04:45:15 +00001218 VideoReceiveStream::Config receive_config;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001219 receive_config.renderer = observers[i];
1220 receive_config.rtp.remote_ssrc = ssrc;
1221 receive_config.rtp.local_ssrc = kReceiverLocalSsrc;
pbos@webrtc.org776e6f22014-10-29 15:28:39 +00001222 VideoReceiveStream::Decoder decoder =
1223 test::CreateMatchingDecoder(send_config.encoder_settings);
1224 allocated_decoders.push_back(decoder.decoder);
1225 receive_config.decoders.push_back(decoder);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001226 receive_streams[i] =
1227 receiver_call->CreateVideoReceiveStream(receive_config);
1228 receive_streams[i]->Start();
1229
1230 frame_generators[i] = test::FrameGeneratorCapturer::Create(
1231 send_streams[i]->Input(), width, height, 30, Clock::GetRealTimeClock());
1232 frame_generators[i]->Start();
1233 }
1234
1235 for (size_t i = 0; i < kNumStreams; ++i) {
1236 EXPECT_EQ(kEventSignaled, observers[i]->Wait())
1237 << "Timed out while waiting for observer " << i << " to render.";
1238 }
1239
1240 for (size_t i = 0; i < kNumStreams; ++i) {
1241 frame_generators[i]->Stop();
1242 sender_call->DestroyVideoSendStream(send_streams[i]);
1243 receiver_call->DestroyVideoReceiveStream(receive_streams[i]);
1244 delete frame_generators[i];
1245 delete observers[i];
1246 }
1247
1248 sender_transport.StopSending();
1249 receiver_transport.StopSending();
1250}
1251
1252TEST_F(EndToEndTest, ObserversEncodedFrames) {
1253 class EncodedFrameTestObserver : public EncodedFrameObserver {
1254 public:
1255 EncodedFrameTestObserver()
1256 : length_(0),
1257 frame_type_(kFrameEmpty),
1258 called_(EventWrapper::Create()) {}
1259 virtual ~EncodedFrameTestObserver() {}
1260
1261 virtual void EncodedFrameCallback(const EncodedFrame& encoded_frame) {
1262 frame_type_ = encoded_frame.frame_type_;
1263 length_ = encoded_frame.length_;
1264 buffer_.reset(new uint8_t[length_]);
1265 memcpy(buffer_.get(), encoded_frame.data_, length_);
1266 called_->Set();
1267 }
1268
1269 EventTypeWrapper Wait() { return called_->Wait(kDefaultTimeoutMs); }
1270
1271 void ExpectEqualFrames(const EncodedFrameTestObserver& observer) {
1272 ASSERT_EQ(length_, observer.length_)
1273 << "Observed frames are of different lengths.";
1274 EXPECT_EQ(frame_type_, observer.frame_type_)
1275 << "Observed frames have different frame types.";
1276 EXPECT_EQ(0, memcmp(buffer_.get(), observer.buffer_.get(), length_))
1277 << "Observed encoded frames have different content.";
1278 }
1279
1280 private:
kwiberg@webrtc.org00b8f6b2015-02-26 14:34:55 +00001281 rtc::scoped_ptr<uint8_t[]> buffer_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001282 size_t length_;
1283 FrameType frame_type_;
kwiberg@webrtc.org00b8f6b2015-02-26 14:34:55 +00001284 rtc::scoped_ptr<EventWrapper> called_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001285 };
1286
1287 EncodedFrameTestObserver post_encode_observer;
1288 EncodedFrameTestObserver pre_decode_observer;
1289
1290 test::DirectTransport sender_transport, receiver_transport;
1291
1292 CreateCalls(Call::Config(&sender_transport),
1293 Call::Config(&receiver_transport));
1294
1295 sender_transport.SetReceiver(receiver_call_->Receiver());
1296 receiver_transport.SetReceiver(sender_call_->Receiver());
1297
1298 CreateSendConfig(1);
1299 CreateMatchingReceiveConfigs();
1300 send_config_.post_encode_callback = &post_encode_observer;
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001301 receive_configs_[0].pre_decode_callback = &pre_decode_observer;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001302
1303 CreateStreams();
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001304 Start();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001305
kwiberg@webrtc.org00b8f6b2015-02-26 14:34:55 +00001306 rtc::scoped_ptr<test::FrameGenerator> frame_generator(
sprang@webrtc.org131bea82015-02-18 12:46:06 +00001307 test::FrameGenerator::CreateChromaGenerator(
1308 encoder_config_.streams[0].width, encoder_config_.streams[0].height));
perkj@webrtc.orgaf612d52015-03-18 09:51:05 +00001309 send_stream_->Input()->IncomingCapturedFrame(*frame_generator->NextFrame());
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001310
1311 EXPECT_EQ(kEventSignaled, post_encode_observer.Wait())
1312 << "Timed out while waiting for send-side encoded-frame callback.";
1313
1314 EXPECT_EQ(kEventSignaled, pre_decode_observer.Wait())
1315 << "Timed out while waiting for pre-decode encoded-frame callback.";
1316
1317 post_encode_observer.ExpectEqualFrames(pre_decode_observer);
1318
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001319 Stop();
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001320
1321 sender_transport.StopSending();
1322 receiver_transport.StopSending();
1323
1324 DestroyStreams();
1325}
1326
1327TEST_F(EndToEndTest, ReceiveStreamSendsRemb) {
1328 class RembObserver : public test::EndToEndTest {
1329 public:
1330 RembObserver() : EndToEndTest(kDefaultTimeoutMs) {}
1331
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001332 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001333 RTCPUtility::RTCPParserV2 parser(packet, length, true);
1334 EXPECT_TRUE(parser.IsValid());
1335
1336 bool received_psfb = false;
1337 bool received_remb = false;
1338 RTCPUtility::RTCPPacketTypes packet_type = parser.Begin();
Erik Språng242e22b2015-05-11 10:17:43 +02001339 while (packet_type != RTCPUtility::RTCPPacketTypes::kInvalid) {
1340 if (packet_type == RTCPUtility::RTCPPacketTypes::kPsfbRemb) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001341 const RTCPUtility::RTCPPacket& packet = parser.Packet();
1342 EXPECT_EQ(packet.PSFBAPP.SenderSSRC, kReceiverLocalSsrc);
1343 received_psfb = true;
Erik Språng242e22b2015-05-11 10:17:43 +02001344 } else if (packet_type == RTCPUtility::RTCPPacketTypes::kPsfbRembItem) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001345 const RTCPUtility::RTCPPacket& packet = parser.Packet();
1346 EXPECT_GT(packet.REMBItem.BitRate, 0u);
1347 EXPECT_EQ(packet.REMBItem.NumberOfSSRCs, 1u);
1348 EXPECT_EQ(packet.REMBItem.SSRCs[0], kSendSsrcs[0]);
1349 received_remb = true;
1350 }
1351 packet_type = parser.Iterate();
1352 }
1353 if (received_psfb && received_remb)
1354 observation_complete_->Set();
1355 return SEND_PACKET;
1356 }
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001357 void PerformTest() override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001358 EXPECT_EQ(kEventSignaled, Wait()) << "Timed out while waiting for a "
1359 "receiver RTCP REMB packet to be "
1360 "sent.";
1361 }
1362 } test;
1363
1364 RunBaseTest(&test);
1365}
1366
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00001367TEST_F(EndToEndTest, VerifyBandwidthStats) {
1368 class RtcpObserver : public test::EndToEndTest, public PacketReceiver {
1369 public:
1370 RtcpObserver()
1371 : EndToEndTest(kDefaultTimeoutMs),
pbos@webrtc.org2b4ce3a2015-03-23 13:12:24 +00001372 sender_call_(nullptr),
1373 receiver_call_(nullptr),
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00001374 has_seen_pacer_delay_(false) {}
1375
Fredrik Solenberg23fba1f2015-04-29 15:24:01 +02001376 DeliveryStatus DeliverPacket(MediaType media_type, const uint8_t* packet,
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001377 size_t length) override {
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00001378 Call::Stats sender_stats = sender_call_->GetStats();
1379 Call::Stats receiver_stats = receiver_call_->GetStats();
1380 if (!has_seen_pacer_delay_)
1381 has_seen_pacer_delay_ = sender_stats.pacer_delay_ms > 0;
1382 if (sender_stats.send_bandwidth_bps > 0 &&
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00001383 receiver_stats.recv_bandwidth_bps > 0 && has_seen_pacer_delay_) {
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00001384 observation_complete_->Set();
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00001385 }
Fredrik Solenberg23fba1f2015-04-29 15:24:01 +02001386 return receiver_call_->Receiver()->DeliverPacket(media_type, packet,
1387 length);
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00001388 }
1389
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001390 void OnCallsCreated(Call* sender_call, Call* receiver_call) override {
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00001391 sender_call_ = sender_call;
1392 receiver_call_ = receiver_call;
1393 }
1394
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001395 void PerformTest() override {
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00001396 EXPECT_EQ(kEventSignaled, Wait()) << "Timed out while waiting for "
1397 "non-zero bandwidth stats.";
1398 }
1399
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001400 void SetReceivers(PacketReceiver* send_transport_receiver,
1401 PacketReceiver* receive_transport_receiver) override {
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00001402 test::RtpRtcpObserver::SetReceivers(this, receive_transport_receiver);
1403 }
1404
1405 private:
1406 Call* sender_call_;
1407 Call* receiver_call_;
1408 bool has_seen_pacer_delay_;
1409 } test;
1410
1411 RunBaseTest(&test);
1412}
1413
Åsa Persson352b2d72015-04-15 18:00:40 +02001414TEST_F(EndToEndTest, VerifyNackStats) {
1415 static const int kPacketNumberToDrop = 200;
1416 class NackObserver : public test::EndToEndTest {
1417 public:
1418 NackObserver()
1419 : EndToEndTest(kLongTimeoutMs),
1420 sent_rtp_packets_(0),
1421 dropped_rtp_packet_(0),
1422 dropped_rtp_packet_requested_(false),
1423 send_stream_(nullptr),
1424 start_runtime_ms_(-1) {}
1425
1426 private:
1427 Action OnSendRtp(const uint8_t* packet, size_t length) override {
1428 if (++sent_rtp_packets_ == kPacketNumberToDrop) {
1429 rtc::scoped_ptr<RtpHeaderParser> parser(RtpHeaderParser::Create());
1430 RTPHeader header;
1431 EXPECT_TRUE(parser->Parse(packet, length, &header));
1432 dropped_rtp_packet_ = header.sequenceNumber;
1433 return DROP_PACKET;
1434 }
1435 VerifyStats();
1436 return SEND_PACKET;
1437 }
1438
1439 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
1440 test::RtcpPacketParser rtcp_parser;
1441 rtcp_parser.Parse(packet, length);
1442 std::vector<uint16_t> nacks = rtcp_parser.nack_item()->last_nack_list();
1443 if (!nacks.empty() && std::find(
1444 nacks.begin(), nacks.end(), dropped_rtp_packet_) != nacks.end()) {
1445 dropped_rtp_packet_requested_ = true;
1446 }
1447 return SEND_PACKET;
1448 }
1449
1450 void VerifyStats() {
1451 if (!dropped_rtp_packet_requested_)
1452 return;
1453 int send_stream_nack_packets = 0;
1454 int receive_stream_nack_packets = 0;
1455 VideoSendStream::Stats stats = send_stream_->GetStats();
1456 for (std::map<uint32_t, VideoSendStream::StreamStats>::const_iterator it =
1457 stats.substreams.begin(); it != stats.substreams.end(); ++it) {
1458 const VideoSendStream::StreamStats& stream_stats = it->second;
1459 send_stream_nack_packets +=
1460 stream_stats.rtcp_packet_type_counts.nack_packets;
1461 }
1462 for (size_t i = 0; i < receive_streams_.size(); ++i) {
1463 VideoReceiveStream::Stats stats = receive_streams_[i]->GetStats();
1464 receive_stream_nack_packets +=
1465 stats.rtcp_packet_type_counts.nack_packets;
1466 }
1467 if (send_stream_nack_packets >= 1 && receive_stream_nack_packets >= 1) {
1468 // NACK packet sent on receive stream and received on sent stream.
1469 if (MinMetricRunTimePassed())
1470 observation_complete_->Set();
1471 }
1472 }
1473
1474 bool MinMetricRunTimePassed() {
1475 int64_t now = Clock::GetRealTimeClock()->TimeInMilliseconds();
1476 if (start_runtime_ms_ == -1) {
1477 start_runtime_ms_ = now;
1478 return false;
1479 }
1480 int64_t elapsed_sec = (now - start_runtime_ms_) / 1000;
1481 return elapsed_sec > metrics::kMinRunTimeInSeconds;
1482 }
1483
1484 void ModifyConfigs(VideoSendStream::Config* send_config,
1485 std::vector<VideoReceiveStream::Config>* receive_configs,
1486 VideoEncoderConfig* encoder_config) override {
1487 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
1488 (*receive_configs)[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
1489 }
1490
1491 void OnStreamsCreated(
1492 VideoSendStream* send_stream,
1493 const std::vector<VideoReceiveStream*>& receive_streams) override {
1494 send_stream_ = send_stream;
1495 receive_streams_ = receive_streams;
1496 }
1497
1498 void PerformTest() override {
1499 EXPECT_EQ(kEventSignaled, Wait())
1500 << "Timed out waiting for packet to be NACKed.";
1501 }
1502
1503 uint64_t sent_rtp_packets_;
1504 uint16_t dropped_rtp_packet_;
1505 bool dropped_rtp_packet_requested_;
1506 std::vector<VideoReceiveStream*> receive_streams_;
1507 VideoSendStream* send_stream_;
1508 int64_t start_runtime_ms_;
1509 } test;
1510
Åsa Persson3c391cb2015-04-27 10:09:49 +02001511 test::ClearHistograms();
Åsa Persson352b2d72015-04-15 18:00:40 +02001512 RunBaseTest(&test);
1513
Åsa Persson3c391cb2015-04-27 10:09:49 +02001514 EXPECT_EQ(1, test::NumHistogramSamples(
Åsa Persson352b2d72015-04-15 18:00:40 +02001515 "WebRTC.Video.UniqueNackRequestsSentInPercent"));
Åsa Persson3c391cb2015-04-27 10:09:49 +02001516 EXPECT_EQ(1, test::NumHistogramSamples(
Åsa Persson352b2d72015-04-15 18:00:40 +02001517 "WebRTC.Video.UniqueNackRequestsReceivedInPercent"));
1518 EXPECT_GT(test::LastHistogramSample(
1519 "WebRTC.Video.NackPacketsSentPerMinute"), 0);
1520 EXPECT_GT(test::LastHistogramSample(
1521 "WebRTC.Video.NackPacketsReceivedPerMinute"), 0);
1522}
1523
Åsa Persson3c391cb2015-04-27 10:09:49 +02001524void EndToEndTest::VerifyHistogramStats(bool use_rtx, bool use_red) {
1525 class StatsObserver : public test::EndToEndTest, public PacketReceiver {
1526 public:
1527 StatsObserver(bool use_rtx, bool use_red)
1528 : EndToEndTest(kLongTimeoutMs),
1529 use_rtx_(use_rtx),
1530 use_red_(use_red),
1531 sender_call_(nullptr),
1532 receiver_call_(nullptr),
1533 start_runtime_ms_(-1) {}
1534
1535 private:
1536 Action OnSendRtp(const uint8_t* packet, size_t length) override {
1537 if (MinMetricRunTimePassed())
1538 observation_complete_->Set();
1539
1540 return SEND_PACKET;
1541 }
1542
Fredrik Solenberg23fba1f2015-04-29 15:24:01 +02001543 DeliveryStatus DeliverPacket(MediaType media_type, const uint8_t* packet,
Åsa Persson3c391cb2015-04-27 10:09:49 +02001544 size_t length) override {
1545 // GetStats calls GetSendChannelRtcpStatistics
1546 // (via VideoSendStream::GetRtt) which updates ReportBlockStats used by
1547 // WebRTC.Video.SentPacketsLostInPercent.
1548 // TODO(asapersson): Remove dependency on calling GetStats.
1549 sender_call_->GetStats();
Fredrik Solenberg23fba1f2015-04-29 15:24:01 +02001550 return receiver_call_->Receiver()->DeliverPacket(media_type, packet,
1551 length);
Åsa Persson3c391cb2015-04-27 10:09:49 +02001552 }
1553
1554 bool MinMetricRunTimePassed() {
1555 int64_t now = Clock::GetRealTimeClock()->TimeInMilliseconds();
1556 if (start_runtime_ms_ == -1) {
1557 start_runtime_ms_ = now;
1558 return false;
1559 }
1560 int64_t elapsed_sec = (now - start_runtime_ms_) / 1000;
1561 return elapsed_sec > metrics::kMinRunTimeInSeconds * 2;
1562 }
1563
1564 void ModifyConfigs(VideoSendStream::Config* send_config,
1565 std::vector<VideoReceiveStream::Config>* receive_configs,
1566 VideoEncoderConfig* encoder_config) override {
1567 // NACK
1568 send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
1569 (*receive_configs)[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
1570 // FEC
1571 if (use_red_) {
1572 send_config->rtp.fec.ulpfec_payload_type = kUlpfecPayloadType;
1573 send_config->rtp.fec.red_payload_type = kRedPayloadType;
1574 (*receive_configs)[0].rtp.fec.red_payload_type = kRedPayloadType;
1575 (*receive_configs)[0].rtp.fec.ulpfec_payload_type = kUlpfecPayloadType;
1576 }
1577 // RTX
1578 if (use_rtx_) {
1579 send_config->rtp.rtx.ssrcs.push_back(kSendRtxSsrcs[0]);
1580 send_config->rtp.rtx.payload_type = kSendRtxPayloadType;
1581 (*receive_configs)[0].rtp.rtx[kFakeSendPayloadType].ssrc =
1582 kSendRtxSsrcs[0];
1583 (*receive_configs)[0].rtp.rtx[kFakeSendPayloadType].payload_type =
1584 kSendRtxPayloadType;
1585 }
1586 }
1587
1588 void OnCallsCreated(Call* sender_call, Call* receiver_call) override {
1589 sender_call_ = sender_call;
1590 receiver_call_ = receiver_call;
1591 }
1592
1593 void SetReceivers(PacketReceiver* send_transport_receiver,
1594 PacketReceiver* receive_transport_receiver) override {
1595 test::RtpRtcpObserver::SetReceivers(this, receive_transport_receiver);
1596 }
1597
1598 void PerformTest() override {
1599 EXPECT_EQ(kEventSignaled, Wait())
1600 << "Timed out waiting for packet to be NACKed.";
1601 }
1602
1603 bool use_rtx_;
1604 bool use_red_;
1605 Call* sender_call_;
1606 Call* receiver_call_;
1607 int64_t start_runtime_ms_;
1608 } test(use_rtx, use_red);
1609
1610 test::ClearHistograms();
1611 RunBaseTest(&test);
1612
1613 // Verify that stats have been updated once.
1614 EXPECT_EQ(1, test::NumHistogramSamples(
1615 "WebRTC.Video.NackPacketsSentPerMinute"));
1616 EXPECT_EQ(1, test::NumHistogramSamples(
1617 "WebRTC.Video.NackPacketsReceivedPerMinute"));
1618 EXPECT_EQ(1, test::NumHistogramSamples(
1619 "WebRTC.Video.FirPacketsSentPerMinute"));
1620 EXPECT_EQ(1, test::NumHistogramSamples(
1621 "WebRTC.Video.FirPacketsReceivedPerMinute"));
1622 EXPECT_EQ(1, test::NumHistogramSamples(
1623 "WebRTC.Video.PliPacketsSentPerMinute"));
1624 EXPECT_EQ(1, test::NumHistogramSamples(
1625 "WebRTC.Video.PliPacketsReceivedPerMinute"));
1626
1627 EXPECT_EQ(1, test::NumHistogramSamples(
1628 "WebRTC.Video.KeyFramesSentInPermille"));
1629 EXPECT_EQ(1, test::NumHistogramSamples(
1630 "WebRTC.Video.KeyFramesReceivedInPermille"));
1631
1632 EXPECT_EQ(1, test::NumHistogramSamples(
1633 "WebRTC.Video.SentPacketsLostInPercent"));
1634 EXPECT_EQ(1, test::NumHistogramSamples(
1635 "WebRTC.Video.ReceivedPacketsLostInPercent"));
1636
1637 EXPECT_EQ(1, test::NumHistogramSamples(
1638 "WebRTC.Video.DecodedFramesPerSecond"));
1639
1640 EXPECT_EQ(1, test::NumHistogramSamples(
1641 "WebRTC.Video.BitrateSentInKbps"));
1642 EXPECT_EQ(1, test::NumHistogramSamples(
1643 "WebRTC.Video.BitrateReceivedInKbps"));
1644 EXPECT_EQ(1, test::NumHistogramSamples(
1645 "WebRTC.Video.MediaBitrateSentInKbps"));
1646 EXPECT_EQ(1, test::NumHistogramSamples(
1647 "WebRTC.Video.MediaBitrateReceivedInKbps"));
1648 EXPECT_EQ(1, test::NumHistogramSamples(
1649 "WebRTC.Video.PaddingBitrateSentInKbps"));
1650 EXPECT_EQ(1, test::NumHistogramSamples(
1651 "WebRTC.Video.PaddingBitrateReceivedInKbps"));
1652 EXPECT_EQ(1, test::NumHistogramSamples(
1653 "WebRTC.Video.RetransmittedBitrateSentInKbps"));
1654 EXPECT_EQ(1, test::NumHistogramSamples(
1655 "WebRTC.Video.RetransmittedBitrateReceivedInKbps"));
1656
1657 int num_rtx_samples = use_rtx ? 1 : 0;
1658 EXPECT_EQ(num_rtx_samples, test::NumHistogramSamples(
1659 "WebRTC.Video.RtxBitrateSentInKbps"));
1660 EXPECT_EQ(num_rtx_samples, test::NumHistogramSamples(
1661 "WebRTC.Video.RtxBitrateReceivedInKbps"));
1662
1663 int num_red_samples = use_red ? 1 : 0;
1664 EXPECT_EQ(num_red_samples, test::NumHistogramSamples(
1665 "WebRTC.Video.FecBitrateSentInKbps"));
1666 EXPECT_EQ(num_red_samples, test::NumHistogramSamples(
1667 "WebRTC.Video.FecBitrateReceivedInKbps"));
1668 EXPECT_EQ(num_red_samples, test::NumHistogramSamples(
1669 "WebRTC.Video.ReceivedFecPacketsInPercent"));
1670}
1671
1672TEST_F(EndToEndTest, VerifyHistogramStatsWithRtx) {
1673 const bool kEnabledRtx = true;
1674 const bool kEnabledRed = false;
1675 VerifyHistogramStats(kEnabledRtx, kEnabledRed);
1676}
1677
1678TEST_F(EndToEndTest, VerifyHistogramStatsWithRed) {
1679 const bool kEnabledRtx = false;
1680 const bool kEnabledRed = true;
1681 VerifyHistogramStats(kEnabledRtx, kEnabledRed);
1682}
1683
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001684void EndToEndTest::TestXrReceiverReferenceTimeReport(bool enable_rrtr) {
1685 static const int kNumRtcpReportPacketsToObserve = 5;
1686 class RtcpXrObserver : public test::EndToEndTest {
1687 public:
1688 explicit RtcpXrObserver(bool enable_rrtr)
1689 : EndToEndTest(kDefaultTimeoutMs),
1690 enable_rrtr_(enable_rrtr),
1691 sent_rtcp_sr_(0),
1692 sent_rtcp_rr_(0),
1693 sent_rtcp_rrtr_(0),
1694 sent_rtcp_dlrr_(0) {}
1695
1696 private:
1697 // Receive stream should send RR packets (and RRTR packets if enabled).
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001698 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001699 RTCPUtility::RTCPParserV2 parser(packet, length, true);
1700 EXPECT_TRUE(parser.IsValid());
1701
1702 RTCPUtility::RTCPPacketTypes packet_type = parser.Begin();
Erik Språng242e22b2015-05-11 10:17:43 +02001703 while (packet_type != RTCPUtility::RTCPPacketTypes::kInvalid) {
1704 if (packet_type == RTCPUtility::RTCPPacketTypes::kRr) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001705 ++sent_rtcp_rr_;
1706 } else if (packet_type ==
Erik Språng242e22b2015-05-11 10:17:43 +02001707 RTCPUtility::RTCPPacketTypes::kXrReceiverReferenceTime) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001708 ++sent_rtcp_rrtr_;
1709 }
Erik Språng242e22b2015-05-11 10:17:43 +02001710 EXPECT_NE(packet_type, RTCPUtility::RTCPPacketTypes::kSr);
1711 EXPECT_NE(packet_type,
1712 RTCPUtility::RTCPPacketTypes::kXrDlrrReportBlockItem);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001713 packet_type = parser.Iterate();
1714 }
1715 return SEND_PACKET;
1716 }
1717 // Send stream should send SR packets (and DLRR packets if enabled).
1718 virtual Action OnSendRtcp(const uint8_t* packet, size_t length) {
1719 RTCPUtility::RTCPParserV2 parser(packet, length, true);
1720 EXPECT_TRUE(parser.IsValid());
1721
1722 RTCPUtility::RTCPPacketTypes packet_type = parser.Begin();
Erik Språng242e22b2015-05-11 10:17:43 +02001723 while (packet_type != RTCPUtility::RTCPPacketTypes::kInvalid) {
1724 if (packet_type == RTCPUtility::RTCPPacketTypes::kSr) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001725 ++sent_rtcp_sr_;
Erik Språng242e22b2015-05-11 10:17:43 +02001726 } else if (packet_type ==
1727 RTCPUtility::RTCPPacketTypes::kXrDlrrReportBlockItem) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001728 ++sent_rtcp_dlrr_;
1729 }
Erik Språng242e22b2015-05-11 10:17:43 +02001730 EXPECT_NE(packet_type,
1731 RTCPUtility::RTCPPacketTypes::kXrReceiverReferenceTime);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001732 packet_type = parser.Iterate();
1733 }
1734 if (sent_rtcp_sr_ > kNumRtcpReportPacketsToObserve &&
1735 sent_rtcp_rr_ > kNumRtcpReportPacketsToObserve) {
1736 if (enable_rrtr_) {
1737 EXPECT_GT(sent_rtcp_rrtr_, 0);
1738 EXPECT_GT(sent_rtcp_dlrr_, 0);
1739 } else {
1740 EXPECT_EQ(0, sent_rtcp_rrtr_);
1741 EXPECT_EQ(0, sent_rtcp_dlrr_);
1742 }
1743 observation_complete_->Set();
1744 }
1745 return SEND_PACKET;
1746 }
1747
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001748 void ModifyConfigs(VideoSendStream::Config* send_config,
1749 std::vector<VideoReceiveStream::Config>* receive_configs,
1750 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001751 (*receive_configs)[0].rtp.rtcp_mode = newapi::kRtcpReducedSize;
1752 (*receive_configs)[0].rtp.rtcp_xr.receiver_reference_time_report =
1753 enable_rrtr_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001754 }
1755
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001756 void PerformTest() override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001757 EXPECT_EQ(kEventSignaled, Wait())
1758 << "Timed out while waiting for RTCP SR/RR packets to be sent.";
1759 }
1760
1761 bool enable_rrtr_;
1762 int sent_rtcp_sr_;
1763 int sent_rtcp_rr_;
1764 int sent_rtcp_rrtr_;
1765 int sent_rtcp_dlrr_;
1766 } test(enable_rrtr);
1767
1768 RunBaseTest(&test);
1769}
1770
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001771void EndToEndTest::TestSendsSetSsrcs(size_t num_ssrcs,
1772 bool send_single_ssrc_first) {
1773 class SendsSetSsrcs : public test::EndToEndTest {
1774 public:
1775 SendsSetSsrcs(const uint32_t* ssrcs,
1776 size_t num_ssrcs,
1777 bool send_single_ssrc_first)
1778 : EndToEndTest(kDefaultTimeoutMs),
1779 num_ssrcs_(num_ssrcs),
1780 send_single_ssrc_first_(send_single_ssrc_first),
1781 ssrcs_to_observe_(num_ssrcs),
1782 expect_single_ssrc_(send_single_ssrc_first) {
1783 for (size_t i = 0; i < num_ssrcs; ++i)
1784 valid_ssrcs_[ssrcs[i]] = true;
1785 }
1786
1787 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001788 Action OnSendRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001789 RTPHeader header;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00001790 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001791
1792 EXPECT_TRUE(valid_ssrcs_[header.ssrc])
1793 << "Received unknown SSRC: " << header.ssrc;
1794
1795 if (!valid_ssrcs_[header.ssrc])
1796 observation_complete_->Set();
1797
1798 if (!is_observed_[header.ssrc]) {
1799 is_observed_[header.ssrc] = true;
1800 --ssrcs_to_observe_;
1801 if (expect_single_ssrc_) {
1802 expect_single_ssrc_ = false;
1803 observation_complete_->Set();
1804 }
1805 }
1806
1807 if (ssrcs_to_observe_ == 0)
1808 observation_complete_->Set();
1809
1810 return SEND_PACKET;
1811 }
1812
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001813 size_t GetNumStreams() const override { return num_ssrcs_; }
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001814
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001815 void ModifyConfigs(VideoSendStream::Config* send_config,
1816 std::vector<VideoReceiveStream::Config>* receive_configs,
1817 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001818 if (num_ssrcs_ > 1) {
1819 // Set low simulcast bitrates to not have to wait for bandwidth ramp-up.
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +00001820 for (size_t i = 0; i < encoder_config->streams.size(); ++i) {
1821 encoder_config->streams[i].min_bitrate_bps = 10000;
1822 encoder_config->streams[i].target_bitrate_bps = 15000;
1823 encoder_config->streams[i].max_bitrate_bps = 20000;
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001824 }
1825 }
1826
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +00001827 encoder_config_all_streams_ = *encoder_config;
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001828 if (send_single_ssrc_first_)
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +00001829 encoder_config->streams.resize(1);
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001830 }
1831
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001832 void OnStreamsCreated(
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001833 VideoSendStream* send_stream,
pbos@webrtc.org0d852d52015-02-09 15:14:36 +00001834 const std::vector<VideoReceiveStream*>& receive_streams) override {
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001835 send_stream_ = send_stream;
1836 }
1837
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001838 void PerformTest() override {
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001839 EXPECT_EQ(kEventSignaled, Wait())
1840 << "Timed out while waiting for "
1841 << (send_single_ssrc_first_ ? "first SSRC." : "SSRCs.");
1842
1843 if (send_single_ssrc_first_) {
1844 // Set full simulcast and continue with the rest of the SSRCs.
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +00001845 send_stream_->ReconfigureVideoEncoder(encoder_config_all_streams_);
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001846 EXPECT_EQ(kEventSignaled, Wait())
1847 << "Timed out while waiting on additional SSRCs.";
1848 }
1849 }
1850
1851 private:
1852 std::map<uint32_t, bool> valid_ssrcs_;
1853 std::map<uint32_t, bool> is_observed_;
1854
1855 const size_t num_ssrcs_;
1856 const bool send_single_ssrc_first_;
1857
1858 size_t ssrcs_to_observe_;
1859 bool expect_single_ssrc_;
1860
1861 VideoSendStream* send_stream_;
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +00001862 VideoEncoderConfig encoder_config_all_streams_;
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001863 } test(kSendSsrcs, num_ssrcs, send_single_ssrc_first);
1864
1865 RunBaseTest(&test);
1866}
1867
pbos@webrtc.org891d4832015-02-26 13:15:22 +00001868TEST_F(EndToEndTest, ReportsSetEncoderRates) {
1869 class EncoderRateStatsTest : public test::EndToEndTest,
1870 public test::FakeEncoder {
1871 public:
1872 EncoderRateStatsTest()
1873 : EndToEndTest(kDefaultTimeoutMs),
1874 FakeEncoder(Clock::GetRealTimeClock()) {}
1875
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001876 void OnStreamsCreated(
pbos@webrtc.org891d4832015-02-26 13:15:22 +00001877 VideoSendStream* send_stream,
1878 const std::vector<VideoReceiveStream*>& receive_streams) override {
1879 send_stream_ = send_stream;
1880 }
1881
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001882 void ModifyConfigs(VideoSendStream::Config* send_config,
1883 std::vector<VideoReceiveStream::Config>* receive_configs,
1884 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org891d4832015-02-26 13:15:22 +00001885 send_config->encoder_settings.encoder = this;
1886 }
1887
1888 int32_t SetRates(uint32_t new_target_bitrate, uint32_t framerate) override {
1889 // Make sure not to trigger on any default zero bitrates.
1890 if (new_target_bitrate == 0)
1891 return 0;
Peter Boströmf2f82832015-05-01 13:00:41 +02001892 rtc::CritScope lock(&crit_);
pbos@webrtc.org891d4832015-02-26 13:15:22 +00001893 bitrate_kbps_ = new_target_bitrate;
1894 observation_complete_->Set();
1895 return 0;
1896 }
1897
1898 void PerformTest() override {
1899 ASSERT_EQ(kEventSignaled, Wait())
1900 << "Timed out while waiting for encoder SetRates() call.";
1901 // Wait for GetStats to report a corresponding bitrate.
1902 for (unsigned int i = 0; i < kDefaultTimeoutMs; ++i) {
1903 VideoSendStream::Stats stats = send_stream_->GetStats();
1904 {
Peter Boströmf2f82832015-05-01 13:00:41 +02001905 rtc::CritScope lock(&crit_);
pbos@webrtc.org891d4832015-02-26 13:15:22 +00001906 if ((stats.target_media_bitrate_bps + 500) / 1000 ==
1907 static_cast<int>(bitrate_kbps_)) {
1908 return;
1909 }
1910 }
1911 SleepMs(1);
1912 }
1913 FAIL()
1914 << "Timed out waiting for stats reporting the currently set bitrate.";
1915 }
1916
1917 private:
1918 VideoSendStream* send_stream_;
1919 uint32_t bitrate_kbps_ GUARDED_BY(crit_);
1920 } test;
1921
1922 RunBaseTest(&test);
1923}
1924
pbos@webrtc.orgba253472014-11-25 09:39:04 +00001925TEST_F(EndToEndTest, GetStats) {
1926 static const int kStartBitrateBps = 3000000;
Peter Boströmdef398832015-05-27 17:59:11 +02001927 static const int kExpectedRenderDelayMs = 20;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001928 class StatsObserver : public test::EndToEndTest, public I420FrameCallback {
1929 public:
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00001930 explicit StatsObserver(const FakeNetworkPipe::Config& config)
1931 : EndToEndTest(kLongTimeoutMs, config),
pbos@webrtc.org2b4ce3a2015-03-23 13:12:24 +00001932 send_stream_(nullptr),
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001933 expected_send_ssrcs_(),
1934 check_stats_event_(EventWrapper::Create()) {}
1935
1936 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001937 Action OnSendRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001938 check_stats_event_->Set();
1939 return SEND_PACKET;
1940 }
1941
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001942 Action OnSendRtcp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001943 check_stats_event_->Set();
1944 return SEND_PACKET;
1945 }
1946
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001947 Action OnReceiveRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001948 check_stats_event_->Set();
1949 return SEND_PACKET;
1950 }
1951
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001952 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001953 check_stats_event_->Set();
1954 return SEND_PACKET;
1955 }
1956
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00001957 void FrameCallback(I420VideoFrame* video_frame) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001958 // Ensure that we have at least 5ms send side delay.
1959 int64_t render_time = video_frame->render_time_ms();
1960 if (render_time > 0)
1961 video_frame->set_render_time_ms(render_time - 5);
1962 }
1963
1964 bool CheckReceiveStats() {
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00001965 for (size_t i = 0; i < receive_streams_.size(); ++i) {
1966 VideoReceiveStream::Stats stats = receive_streams_[i]->GetStats();
1967 EXPECT_EQ(expected_receive_ssrcs_[i], stats.ssrc);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001968
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00001969 // Make sure all fields have been populated.
1970 // TODO(pbos): Use CompoundKey if/when we ever know that all stats are
1971 // always filled for all receivers.
1972 receive_stats_filled_["IncomingRate"] |=
1973 stats.network_frame_rate != 0 || stats.total_bitrate_bps != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001974
Peter Boströmdef398832015-05-27 17:59:11 +02001975 receive_stats_filled_["RenderDelayAsHighAsExpected"] |=
1976 stats.render_delay_ms >= kExpectedRenderDelayMs;
1977
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00001978 receive_stats_filled_["FrameCallback"] |= stats.decode_frame_rate != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001979
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00001980 receive_stats_filled_["FrameRendered"] |= stats.render_frame_rate != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001981
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00001982 receive_stats_filled_["StatisticsUpdated"] |=
1983 stats.rtcp_stats.cumulative_lost != 0 ||
1984 stats.rtcp_stats.extended_max_sequence_number != 0 ||
1985 stats.rtcp_stats.fraction_lost != 0 || stats.rtcp_stats.jitter != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001986
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00001987 receive_stats_filled_["DataCountersUpdated"] |=
1988 stats.rtp_stats.transmitted.payload_bytes != 0 ||
1989 stats.rtp_stats.fec.packets != 0 ||
1990 stats.rtp_stats.transmitted.header_bytes != 0 ||
1991 stats.rtp_stats.transmitted.packets != 0 ||
1992 stats.rtp_stats.transmitted.padding_bytes != 0 ||
1993 stats.rtp_stats.retransmitted.packets != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001994
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00001995 receive_stats_filled_["CodecStats"] |=
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00001996 stats.target_delay_ms != 0 || stats.discarded_packets != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00001997
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00001998 receive_stats_filled_["FrameCounts"] |=
1999 stats.frame_counts.key_frames != 0 ||
2000 stats.frame_counts.delta_frames != 0;
pbos@webrtc.orgce4e9a32014-12-18 13:50:16 +00002001
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002002 receive_stats_filled_["CName"] |= stats.c_name != "";
pbos@webrtc.orgce4e9a32014-12-18 13:50:16 +00002003
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002004 receive_stats_filled_["RtcpPacketTypeCount"] |=
2005 stats.rtcp_packet_type_counts.fir_packets != 0 ||
2006 stats.rtcp_packet_type_counts.nack_packets != 0 ||
2007 stats.rtcp_packet_type_counts.pli_packets != 0 ||
2008 stats.rtcp_packet_type_counts.nack_requests != 0 ||
2009 stats.rtcp_packet_type_counts.unique_nack_requests != 0;
2010 }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002011
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002012 return AllStatsFilled(receive_stats_filled_);
2013 }
2014
2015 bool CheckSendStats() {
pbos@webrtc.org2b4ce3a2015-03-23 13:12:24 +00002016 DCHECK(send_stream_ != nullptr);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002017 VideoSendStream::Stats stats = send_stream_->GetStats();
2018
2019 send_stats_filled_["NumStreams"] |=
2020 stats.substreams.size() == expected_send_ssrcs_.size();
2021
pbos@webrtc.org3e6e2712015-02-26 12:19:31 +00002022 send_stats_filled_["CpuOveruseMetrics"] |=
2023 stats.avg_encode_time_ms != 0 || stats.encode_usage_percent != 0;
2024
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00002025 for (std::map<uint32_t, VideoSendStream::StreamStats>::const_iterator it =
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002026 stats.substreams.begin();
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00002027 it != stats.substreams.end(); ++it) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002028 EXPECT_TRUE(expected_send_ssrcs_.find(it->first) !=
2029 expected_send_ssrcs_.end());
2030
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002031 send_stats_filled_[CompoundKey("CapturedFrameRate", it->first)] |=
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002032 stats.input_frame_rate != 0;
2033
pbos@webrtc.org09c77b92015-02-25 10:42:16 +00002034 const VideoSendStream::StreamStats& stream_stats = it->second;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002035
2036 send_stats_filled_[CompoundKey("StatisticsUpdated", it->first)] |=
2037 stream_stats.rtcp_stats.cumulative_lost != 0 ||
2038 stream_stats.rtcp_stats.extended_max_sequence_number != 0 ||
2039 stream_stats.rtcp_stats.fraction_lost != 0;
2040
2041 send_stats_filled_[CompoundKey("DataCountersUpdated", it->first)] |=
asapersson@webrtc.orgcfd82df2015-01-22 09:39:59 +00002042 stream_stats.rtp_stats.fec.packets != 0 ||
2043 stream_stats.rtp_stats.transmitted.padding_bytes != 0 ||
2044 stream_stats.rtp_stats.retransmitted.packets != 0 ||
2045 stream_stats.rtp_stats.transmitted.packets != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002046
2047 send_stats_filled_[CompoundKey("BitrateStatisticsObserver",
2048 it->first)] |=
stefan@webrtc.org0bae1fa2014-11-05 14:05:29 +00002049 stream_stats.total_bitrate_bps != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002050
2051 send_stats_filled_[CompoundKey("FrameCountObserver", it->first)] |=
pbos@webrtc.orgce4e9a32014-12-18 13:50:16 +00002052 stream_stats.frame_counts.delta_frames != 0 ||
2053 stream_stats.frame_counts.key_frames != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002054
2055 send_stats_filled_[CompoundKey("OutgoingRate", it->first)] |=
2056 stats.encode_frame_rate != 0;
stefan@webrtc.org168f23f2014-07-11 13:44:02 +00002057
2058 send_stats_filled_[CompoundKey("Delay", it->first)] |=
2059 stream_stats.avg_delay_ms != 0 || stream_stats.max_delay_ms != 0;
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002060
2061 // TODO(pbos): Use CompoundKey when the test makes sure that all SSRCs
2062 // report dropped packets.
2063 send_stats_filled_["RtcpPacketTypeCount"] |=
2064 stream_stats.rtcp_packet_type_counts.fir_packets != 0 ||
2065 stream_stats.rtcp_packet_type_counts.nack_packets != 0 ||
2066 stream_stats.rtcp_packet_type_counts.pli_packets != 0 ||
2067 stream_stats.rtcp_packet_type_counts.nack_requests != 0 ||
2068 stream_stats.rtcp_packet_type_counts.unique_nack_requests != 0;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002069 }
2070
2071 return AllStatsFilled(send_stats_filled_);
2072 }
2073
2074 std::string CompoundKey(const char* name, uint32_t ssrc) {
2075 std::ostringstream oss;
2076 oss << name << "_" << ssrc;
2077 return oss.str();
2078 }
2079
2080 bool AllStatsFilled(const std::map<std::string, bool>& stats_map) {
2081 for (std::map<std::string, bool>::const_iterator it = stats_map.begin();
2082 it != stats_map.end();
2083 ++it) {
2084 if (!it->second)
2085 return false;
2086 }
2087 return true;
2088 }
2089
pbos@webrtc.org0d852d52015-02-09 15:14:36 +00002090 Call::Config GetSenderCallConfig() override {
pbos@webrtc.orgba253472014-11-25 09:39:04 +00002091 Call::Config config = EndToEndTest::GetSenderCallConfig();
Stefan Holmere5904162015-03-26 11:11:06 +01002092 config.bitrate_config.start_bitrate_bps = kStartBitrateBps;
pbos@webrtc.orgba253472014-11-25 09:39:04 +00002093 return config;
2094 }
2095
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002096 void ModifyConfigs(VideoSendStream::Config* send_config,
2097 std::vector<VideoReceiveStream::Config>* receive_configs,
2098 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002099 send_config->pre_encode_callback = this; // Used to inject delay.
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002100 expected_cname_ = send_config->rtp.c_name = "SomeCName";
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002101
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002102 const std::vector<uint32_t>& ssrcs = send_config->rtp.ssrcs;
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002103 for (size_t i = 0; i < ssrcs.size(); ++i) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002104 expected_send_ssrcs_.insert(ssrcs[i]);
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002105 expected_receive_ssrcs_.push_back(
2106 (*receive_configs)[i].rtp.remote_ssrc);
Peter Boströmdef398832015-05-27 17:59:11 +02002107 (*receive_configs)[i].render_delay_ms = kExpectedRenderDelayMs;
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002108 }
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002109 }
2110
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002111 size_t GetNumStreams() const override { return kNumSsrcs; }
pbos@webrtc.orgece38902014-11-14 11:52:04 +00002112
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002113 void OnStreamsCreated(
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002114 VideoSendStream* send_stream,
pbos@webrtc.org0d852d52015-02-09 15:14:36 +00002115 const std::vector<VideoReceiveStream*>& receive_streams) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002116 send_stream_ = send_stream;
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002117 receive_streams_ = receive_streams;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002118 }
2119
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002120 void PerformTest() override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002121 Clock* clock = Clock::GetRealTimeClock();
2122 int64_t now = clock->TimeInMilliseconds();
2123 int64_t stop_time = now + test::CallTest::kLongTimeoutMs;
2124 bool receive_ok = false;
2125 bool send_ok = false;
2126
2127 while (now < stop_time) {
2128 if (!receive_ok)
2129 receive_ok = CheckReceiveStats();
2130 if (!send_ok)
2131 send_ok = CheckSendStats();
2132
2133 if (receive_ok && send_ok)
2134 return;
2135
2136 int64_t time_until_timout_ = stop_time - now;
2137 if (time_until_timout_ > 0)
2138 check_stats_event_->Wait(time_until_timout_);
2139 now = clock->TimeInMilliseconds();
2140 }
2141
2142 ADD_FAILURE() << "Timed out waiting for filled stats.";
2143 for (std::map<std::string, bool>::const_iterator it =
2144 receive_stats_filled_.begin();
2145 it != receive_stats_filled_.end();
2146 ++it) {
2147 if (!it->second) {
2148 ADD_FAILURE() << "Missing receive stats: " << it->first;
2149 }
2150 }
2151
2152 for (std::map<std::string, bool>::const_iterator it =
2153 send_stats_filled_.begin();
2154 it != send_stats_filled_.end();
2155 ++it) {
2156 if (!it->second) {
2157 ADD_FAILURE() << "Missing send stats: " << it->first;
2158 }
2159 }
2160 }
2161
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002162 std::vector<VideoReceiveStream*> receive_streams_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002163 std::map<std::string, bool> receive_stats_filled_;
2164
2165 VideoSendStream* send_stream_;
2166 std::map<std::string, bool> send_stats_filled_;
2167
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002168 std::vector<uint32_t> expected_receive_ssrcs_;
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002169 std::set<uint32_t> expected_send_ssrcs_;
2170 std::string expected_cname_;
2171
kwiberg@webrtc.org00b8f6b2015-02-26 14:34:55 +00002172 rtc::scoped_ptr<EventWrapper> check_stats_event_;
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002173 };
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002174
pbos@webrtc.org1d0fa5d2015-02-19 12:47:00 +00002175 FakeNetworkPipe::Config network_config;
2176 network_config.loss_percent = 5;
2177
2178 StatsObserver test(network_config);
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002179 RunBaseTest(&test);
2180}
2181
2182TEST_F(EndToEndTest, ReceiverReferenceTimeReportEnabled) {
2183 TestXrReceiverReferenceTimeReport(true);
2184}
2185
2186TEST_F(EndToEndTest, ReceiverReferenceTimeReportDisabled) {
2187 TestXrReceiverReferenceTimeReport(false);
2188}
2189
2190TEST_F(EndToEndTest, TestReceivedRtpPacketStats) {
2191 static const size_t kNumRtpPacketsToSend = 5;
2192 class ReceivedRtpStatsObserver : public test::EndToEndTest {
2193 public:
2194 ReceivedRtpStatsObserver()
2195 : EndToEndTest(kDefaultTimeoutMs),
pbos@webrtc.org2b4ce3a2015-03-23 13:12:24 +00002196 receive_stream_(nullptr),
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002197 sent_rtp_(0) {}
2198
2199 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002200 void OnStreamsCreated(
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002201 VideoSendStream* send_stream,
pbos@webrtc.org0d852d52015-02-09 15:14:36 +00002202 const std::vector<VideoReceiveStream*>& receive_streams) override {
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002203 receive_stream_ = receive_streams[0];
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002204 }
2205
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002206 Action OnSendRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002207 if (sent_rtp_ >= kNumRtpPacketsToSend) {
2208 VideoReceiveStream::Stats stats = receive_stream_->GetStats();
asapersson@webrtc.orgcfd82df2015-01-22 09:39:59 +00002209 if (kNumRtpPacketsToSend == stats.rtp_stats.transmitted.packets) {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002210 observation_complete_->Set();
2211 }
2212 return DROP_PACKET;
2213 }
2214 ++sent_rtp_;
2215 return SEND_PACKET;
2216 }
2217
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002218 void PerformTest() override {
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002219 EXPECT_EQ(kEventSignaled, Wait())
2220 << "Timed out while verifying number of received RTP packets.";
2221 }
2222
2223 VideoReceiveStream* receive_stream_;
2224 uint32_t sent_rtp_;
2225 } test;
2226
2227 RunBaseTest(&test);
2228}
2229
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00002230TEST_F(EndToEndTest, SendsSetSsrc) { TestSendsSetSsrcs(1, false); }
2231
2232TEST_F(EndToEndTest, SendsSetSimulcastSsrcs) {
2233 TestSendsSetSsrcs(kNumSsrcs, false);
2234}
2235
2236TEST_F(EndToEndTest, CanSwitchToUseAllSsrcs) {
2237 TestSendsSetSsrcs(kNumSsrcs, true);
2238}
2239
mflodman@webrtc.orgf9460682014-07-24 16:41:25 +00002240TEST_F(EndToEndTest, DISABLED_RedundantPayloadsTransmittedOnAllSsrcs) {
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00002241 class ObserveRedundantPayloads: public test::EndToEndTest {
2242 public:
2243 ObserveRedundantPayloads()
2244 : EndToEndTest(kDefaultTimeoutMs), ssrcs_to_observe_(kNumSsrcs) {
pbos@webrtc.orgdde16f12014-08-05 23:35:43 +00002245 for (size_t i = 0; i < kNumSsrcs; ++i) {
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00002246 registered_rtx_ssrc_[kSendRtxSsrcs[i]] = true;
2247 }
2248 }
2249
2250 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002251 Action OnSendRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00002252 RTPHeader header;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00002253 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00002254
2255 if (!registered_rtx_ssrc_[header.ssrc])
2256 return SEND_PACKET;
2257
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +00002258 EXPECT_LE(header.headerLength + header.paddingLength, length);
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00002259 const bool packet_is_redundant_payload =
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +00002260 header.headerLength + header.paddingLength < length;
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00002261
2262 if (!packet_is_redundant_payload)
2263 return SEND_PACKET;
2264
2265 if (!observed_redundant_retransmission_[header.ssrc]) {
2266 observed_redundant_retransmission_[header.ssrc] = true;
2267 if (--ssrcs_to_observe_ == 0)
2268 observation_complete_->Set();
2269 }
2270
2271 return SEND_PACKET;
2272 }
2273
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002274 size_t GetNumStreams() const override { return kNumSsrcs; }
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00002275
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002276 void ModifyConfigs(VideoSendStream::Config* send_config,
2277 std::vector<VideoReceiveStream::Config>* receive_configs,
2278 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00002279 // Set low simulcast bitrates to not have to wait for bandwidth ramp-up.
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +00002280 for (size_t i = 0; i < encoder_config->streams.size(); ++i) {
2281 encoder_config->streams[i].min_bitrate_bps = 10000;
2282 encoder_config->streams[i].target_bitrate_bps = 15000;
2283 encoder_config->streams[i].max_bitrate_bps = 20000;
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00002284 }
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00002285
2286 send_config->rtp.rtx.payload_type = kSendRtxPayloadType;
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00002287
2288 for (size_t i = 0; i < kNumSsrcs; ++i)
2289 send_config->rtp.rtx.ssrcs.push_back(kSendRtxSsrcs[i]);
pbos@webrtc.orgad3b5a52014-10-24 09:23:21 +00002290
2291 // Significantly higher than max bitrates for all video streams -> forcing
2292 // padding to trigger redundant padding on all RTX SSRCs.
2293 encoder_config->min_transmit_bitrate_bps = 100000;
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00002294 }
2295
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002296 void PerformTest() override {
pbos@webrtc.org20c1f562014-07-04 10:58:12 +00002297 EXPECT_EQ(kEventSignaled, Wait())
2298 << "Timed out while waiting for redundant payloads on all SSRCs.";
2299 }
2300
2301 private:
2302 size_t ssrcs_to_observe_;
2303 std::map<uint32_t, bool> observed_redundant_retransmission_;
2304 std::map<uint32_t, bool> registered_rtx_ssrc_;
2305 } test;
2306
2307 RunBaseTest(&test);
2308}
2309
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00002310void EndToEndTest::TestRtpStatePreservation(bool use_rtx) {
2311 static const uint32_t kMaxSequenceNumberGap = 100;
2312 static const uint64_t kMaxTimestampGap = kDefaultTimeoutMs * 90;
2313 class RtpSequenceObserver : public test::RtpRtcpObserver {
2314 public:
pbos@webrtc.orgdde16f12014-08-05 23:35:43 +00002315 explicit RtpSequenceObserver(bool use_rtx)
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00002316 : test::RtpRtcpObserver(kDefaultTimeoutMs),
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00002317 ssrcs_to_observe_(kNumSsrcs) {
2318 for (size_t i = 0; i < kNumSsrcs; ++i) {
2319 configured_ssrcs_[kSendSsrcs[i]] = true;
2320 if (use_rtx)
2321 configured_ssrcs_[kSendRtxSsrcs[i]] = true;
2322 }
2323 }
2324
2325 void ResetExpectedSsrcs(size_t num_expected_ssrcs) {
Peter Boströmf2f82832015-05-01 13:00:41 +02002326 rtc::CritScope lock(&crit_);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00002327 ssrc_observed_.clear();
2328 ssrcs_to_observe_ = num_expected_ssrcs;
2329 }
2330
2331 private:
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002332 Action OnSendRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00002333 RTPHeader header;
pbos@webrtc.org62bafae2014-07-08 12:10:51 +00002334 EXPECT_TRUE(parser_->Parse(packet, length, &header));
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00002335 const uint32_t ssrc = header.ssrc;
2336 const uint16_t sequence_number = header.sequenceNumber;
2337 const uint32_t timestamp = header.timestamp;
2338 const bool only_padding =
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +00002339 header.headerLength + header.paddingLength == length;
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00002340
2341 EXPECT_TRUE(configured_ssrcs_[ssrc])
2342 << "Received SSRC that wasn't configured: " << ssrc;
2343
2344 std::map<uint32_t, uint16_t>::iterator it =
2345 last_observed_sequence_number_.find(header.ssrc);
2346 if (it == last_observed_sequence_number_.end()) {
2347 last_observed_sequence_number_[ssrc] = sequence_number;
2348 last_observed_timestamp_[ssrc] = timestamp;
2349 } else {
2350 // Verify sequence numbers are reasonably close.
2351 uint32_t extended_sequence_number = sequence_number;
2352 // Check for roll-over.
2353 if (sequence_number < last_observed_sequence_number_[ssrc])
2354 extended_sequence_number += 0xFFFFu + 1;
2355 EXPECT_LE(
2356 extended_sequence_number - last_observed_sequence_number_[ssrc],
2357 kMaxSequenceNumberGap)
2358 << "Gap in sequence numbers ("
2359 << last_observed_sequence_number_[ssrc] << " -> " << sequence_number
2360 << ") too large for SSRC: " << ssrc << ".";
2361 last_observed_sequence_number_[ssrc] = sequence_number;
2362
2363 // TODO(pbos): Remove this check if we ever have monotonically
2364 // increasing timestamps. Right now padding packets add a delta which
2365 // can cause reordering between padding packets and regular packets,
2366 // hence we drop padding-only packets to not flake.
2367 if (only_padding) {
2368 // Verify that timestamps are reasonably close.
2369 uint64_t extended_timestamp = timestamp;
2370 // Check for roll-over.
2371 if (timestamp < last_observed_timestamp_[ssrc])
2372 extended_timestamp += static_cast<uint64_t>(0xFFFFFFFFu) + 1;
2373 EXPECT_LE(extended_timestamp - last_observed_timestamp_[ssrc],
2374 kMaxTimestampGap)
2375 << "Gap in timestamps (" << last_observed_timestamp_[ssrc]
2376 << " -> " << timestamp << ") too large for SSRC: " << ssrc << ".";
2377 }
2378 last_observed_timestamp_[ssrc] = timestamp;
2379 }
2380
Peter Boströmf2f82832015-05-01 13:00:41 +02002381 rtc::CritScope lock(&crit_);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00002382 // Wait for media packets on all ssrcs.
2383 if (!ssrc_observed_[ssrc] && !only_padding) {
2384 ssrc_observed_[ssrc] = true;
2385 if (--ssrcs_to_observe_ == 0)
2386 observation_complete_->Set();
2387 }
2388
2389 return SEND_PACKET;
2390 }
2391
2392 std::map<uint32_t, uint16_t> last_observed_sequence_number_;
2393 std::map<uint32_t, uint32_t> last_observed_timestamp_;
2394 std::map<uint32_t, bool> configured_ssrcs_;
2395
Peter Boströmf2f82832015-05-01 13:00:41 +02002396 rtc::CriticalSection crit_;
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00002397 size_t ssrcs_to_observe_ GUARDED_BY(crit_);
2398 std::map<uint32_t, bool> ssrc_observed_ GUARDED_BY(crit_);
2399 } observer(use_rtx);
2400
2401 CreateCalls(Call::Config(observer.SendTransport()),
2402 Call::Config(observer.ReceiveTransport()));
pbos@webrtc.org2b4ce3a2015-03-23 13:12:24 +00002403 observer.SetReceivers(sender_call_->Receiver(), nullptr);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00002404
2405 CreateSendConfig(kNumSsrcs);
2406
2407 if (use_rtx) {
2408 for (size_t i = 0; i < kNumSsrcs; ++i) {
2409 send_config_.rtp.rtx.ssrcs.push_back(kSendRtxSsrcs[i]);
2410 }
2411 send_config_.rtp.rtx.payload_type = kSendRtxPayloadType;
2412 }
2413
2414 // Lower bitrates so that all streams send initially.
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +00002415 for (size_t i = 0; i < encoder_config_.streams.size(); ++i) {
2416 encoder_config_.streams[i].min_bitrate_bps = 10000;
2417 encoder_config_.streams[i].target_bitrate_bps = 15000;
2418 encoder_config_.streams[i].max_bitrate_bps = 20000;
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00002419 }
2420
pbos@webrtc.org32452b22014-10-22 12:15:24 +00002421 // Use the same total bitrates when sending a single stream to avoid lowering
2422 // the bitrate estimate and requiring a subsequent rampup.
2423 VideoEncoderConfig one_stream = encoder_config_;
2424 one_stream.streams.resize(1);
2425 for (size_t i = 1; i < encoder_config_.streams.size(); ++i) {
2426 one_stream.streams.front().min_bitrate_bps +=
2427 encoder_config_.streams[i].min_bitrate_bps;
2428 one_stream.streams.front().target_bitrate_bps +=
2429 encoder_config_.streams[i].target_bitrate_bps;
2430 one_stream.streams.front().max_bitrate_bps +=
2431 encoder_config_.streams[i].max_bitrate_bps;
2432 }
2433
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00002434 CreateMatchingReceiveConfigs();
2435
2436 CreateStreams();
2437 CreateFrameGeneratorCapturer();
2438
2439 Start();
2440 EXPECT_EQ(kEventSignaled, observer.Wait())
2441 << "Timed out waiting for all SSRCs to send packets.";
2442
2443 // Test stream resetting more than once to make sure that the state doesn't
2444 // get set once (this could be due to using std::map::insert for instance).
2445 for (size_t i = 0; i < 3; ++i) {
2446 frame_generator_capturer_->Stop();
2447 sender_call_->DestroyVideoSendStream(send_stream_);
2448
2449 // Re-create VideoSendStream with only one stream.
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00002450 send_stream_ =
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +00002451 sender_call_->CreateVideoSendStream(send_config_, one_stream);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00002452 send_stream_->Start();
2453 CreateFrameGeneratorCapturer();
2454 frame_generator_capturer_->Start();
2455
2456 observer.ResetExpectedSsrcs(1);
2457 EXPECT_EQ(kEventSignaled, observer.Wait())
2458 << "Timed out waiting for single RTP packet.";
2459
2460 // Reconfigure back to use all streams.
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +00002461 send_stream_->ReconfigureVideoEncoder(encoder_config_);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00002462 observer.ResetExpectedSsrcs(kNumSsrcs);
2463 EXPECT_EQ(kEventSignaled, observer.Wait())
2464 << "Timed out waiting for all SSRCs to send packets.";
2465
2466 // Reconfigure down to one stream.
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +00002467 send_stream_->ReconfigureVideoEncoder(one_stream);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00002468 observer.ResetExpectedSsrcs(1);
2469 EXPECT_EQ(kEventSignaled, observer.Wait())
2470 << "Timed out waiting for single RTP packet.";
2471
2472 // Reconfigure back to use all streams.
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +00002473 send_stream_->ReconfigureVideoEncoder(encoder_config_);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00002474 observer.ResetExpectedSsrcs(kNumSsrcs);
2475 EXPECT_EQ(kEventSignaled, observer.Wait())
2476 << "Timed out waiting for all SSRCs to send packets.";
2477 }
2478
2479 observer.StopSending();
2480
2481 Stop();
2482 DestroyStreams();
2483}
2484
aluebs@webrtc.orgb623c5c2014-08-26 14:22:51 +00002485TEST_F(EndToEndTest, DISABLED_RestartingSendStreamPreservesRtpState) {
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00002486 TestRtpStatePreservation(false);
2487}
2488
2489TEST_F(EndToEndTest, RestartingSendStreamPreservesRtpStatesWithRtx) {
2490 TestRtpStatePreservation(true);
2491}
2492
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00002493TEST_F(EndToEndTest, RespectsNetworkState) {
2494 // TODO(pbos): Remove accepted downtime packets etc. when signaling network
2495 // down blocks until no more packets will be sent.
2496
2497 // Pacer will send from its packet list and then send required padding before
2498 // checking paused_ again. This should be enough for one round of pacing,
2499 // otherwise increase.
2500 static const int kNumAcceptedDowntimeRtp = 5;
2501 // A single RTCP may be in the pipeline.
2502 static const int kNumAcceptedDowntimeRtcp = 1;
2503 class NetworkStateTest : public test::EndToEndTest, public test::FakeEncoder {
2504 public:
2505 NetworkStateTest()
2506 : EndToEndTest(kDefaultTimeoutMs),
2507 FakeEncoder(Clock::GetRealTimeClock()),
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00002508 encoded_frames_(EventWrapper::Create()),
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00002509 packet_event_(EventWrapper::Create()),
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00002510 sender_state_(Call::kNetworkUp),
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00002511 sender_rtp_(0),
2512 sender_rtcp_(0),
2513 receiver_rtcp_(0),
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00002514 down_frames_(0) {}
2515
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002516 Action OnSendRtp(const uint8_t* packet, size_t length) override {
Peter Boströmf2f82832015-05-01 13:00:41 +02002517 rtc::CritScope lock(&test_crit_);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00002518 ++sender_rtp_;
2519 packet_event_->Set();
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00002520 return SEND_PACKET;
2521 }
2522
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002523 Action OnSendRtcp(const uint8_t* packet, size_t length) override {
Peter Boströmf2f82832015-05-01 13:00:41 +02002524 rtc::CritScope lock(&test_crit_);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00002525 ++sender_rtcp_;
2526 packet_event_->Set();
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00002527 return SEND_PACKET;
2528 }
2529
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002530 Action OnReceiveRtp(const uint8_t* packet, size_t length) override {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00002531 ADD_FAILURE() << "Unexpected receiver RTP, should not be sending.";
2532 return SEND_PACKET;
2533 }
2534
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002535 Action OnReceiveRtcp(const uint8_t* packet, size_t length) override {
Peter Boströmf2f82832015-05-01 13:00:41 +02002536 rtc::CritScope lock(&test_crit_);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00002537 ++receiver_rtcp_;
2538 packet_event_->Set();
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00002539 return SEND_PACKET;
2540 }
2541
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002542 void OnCallsCreated(Call* sender_call, Call* receiver_call) override {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00002543 sender_call_ = sender_call;
2544 receiver_call_ = receiver_call;
2545 }
2546
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002547 void ModifyConfigs(VideoSendStream::Config* send_config,
2548 std::vector<VideoReceiveStream::Config>* receive_configs,
2549 VideoEncoderConfig* encoder_config) override {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00002550 send_config->encoder_settings.encoder = this;
2551 }
2552
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002553 void PerformTest() override {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00002554 EXPECT_EQ(kEventSignaled, encoded_frames_->Wait(kDefaultTimeoutMs))
2555 << "No frames received by the encoder.";
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00002556 // Wait for packets from both sender/receiver.
2557 WaitForPacketsOrSilence(false, false);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00002558
2559 // Sender-side network down.
2560 sender_call_->SignalNetworkState(Call::kNetworkDown);
2561 {
Peter Boströmf2f82832015-05-01 13:00:41 +02002562 rtc::CritScope lock(&test_crit_);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00002563 // After network goes down we shouldn't be encoding more frames.
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00002564 sender_state_ = Call::kNetworkDown;
2565 }
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00002566 // Wait for receiver-packets and no sender packets.
2567 WaitForPacketsOrSilence(true, false);
2568
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00002569 // Receiver-side network down.
2570 receiver_call_->SignalNetworkState(Call::kNetworkDown);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00002571 WaitForPacketsOrSilence(true, true);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00002572
2573 // Network back up again for both.
2574 {
Peter Boströmf2f82832015-05-01 13:00:41 +02002575 rtc::CritScope lock(&test_crit_);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00002576 // It's OK to encode frames again, as we're about to bring up the
2577 // network.
2578 sender_state_ = Call::kNetworkUp;
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00002579 }
2580 sender_call_->SignalNetworkState(Call::kNetworkUp);
2581 receiver_call_->SignalNetworkState(Call::kNetworkUp);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00002582 WaitForPacketsOrSilence(false, false);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00002583 }
2584
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002585 int32_t Encode(const I420VideoFrame& input_image,
2586 const CodecSpecificInfo* codec_specific_info,
2587 const std::vector<VideoFrameType>* frame_types) override {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00002588 {
Peter Boströmf2f82832015-05-01 13:00:41 +02002589 rtc::CritScope lock(&test_crit_);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00002590 if (sender_state_ == Call::kNetworkDown) {
2591 ++down_frames_;
2592 EXPECT_LE(down_frames_, 1)
2593 << "Encoding more than one frame while network is down.";
2594 if (down_frames_ > 1)
2595 encoded_frames_->Set();
2596 } else {
2597 encoded_frames_->Set();
2598 }
2599 }
2600 return test::FakeEncoder::Encode(
2601 input_image, codec_specific_info, frame_types);
2602 }
2603
2604 private:
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00002605 void WaitForPacketsOrSilence(bool sender_down, bool receiver_down) {
2606 int64_t initial_time_ms = clock_->TimeInMilliseconds();
2607 int initial_sender_rtp;
2608 int initial_sender_rtcp;
2609 int initial_receiver_rtcp;
2610 {
Peter Boströmf2f82832015-05-01 13:00:41 +02002611 rtc::CritScope lock(&test_crit_);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00002612 initial_sender_rtp = sender_rtp_;
2613 initial_sender_rtcp = sender_rtcp_;
2614 initial_receiver_rtcp = receiver_rtcp_;
2615 }
2616 bool sender_done = false;
2617 bool receiver_done = false;
2618 while(!sender_done || !receiver_done) {
2619 packet_event_->Wait(kSilenceTimeoutMs);
2620 int64_t time_now_ms = clock_->TimeInMilliseconds();
Peter Boströmf2f82832015-05-01 13:00:41 +02002621 rtc::CritScope lock(&test_crit_);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00002622 if (sender_down) {
2623 ASSERT_LE(sender_rtp_ - initial_sender_rtp, kNumAcceptedDowntimeRtp)
2624 << "RTP sent during sender-side downtime.";
2625 ASSERT_LE(sender_rtcp_ - initial_sender_rtcp,
2626 kNumAcceptedDowntimeRtcp)
2627 << "RTCP sent during sender-side downtime.";
2628 if (time_now_ms - initial_time_ms >=
2629 static_cast<int64_t>(kSilenceTimeoutMs)) {
2630 sender_done = true;
2631 }
2632 } else {
2633 if (sender_rtp_ > initial_sender_rtp)
2634 sender_done = true;
2635 }
2636 if (receiver_down) {
2637 ASSERT_LE(receiver_rtcp_ - initial_receiver_rtcp,
2638 kNumAcceptedDowntimeRtcp)
2639 << "RTCP sent during receiver-side downtime.";
2640 if (time_now_ms - initial_time_ms >=
2641 static_cast<int64_t>(kSilenceTimeoutMs)) {
2642 receiver_done = true;
2643 }
2644 } else {
2645 if (receiver_rtcp_ > initial_receiver_rtcp)
2646 receiver_done = true;
2647 }
2648 }
2649 }
2650
Peter Boströmf2f82832015-05-01 13:00:41 +02002651 rtc::CriticalSection test_crit_;
kwiberg@webrtc.org00b8f6b2015-02-26 14:34:55 +00002652 const rtc::scoped_ptr<EventWrapper> encoded_frames_;
2653 const rtc::scoped_ptr<EventWrapper> packet_event_;
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00002654 Call* sender_call_;
2655 Call* receiver_call_;
2656 Call::NetworkState sender_state_ GUARDED_BY(test_crit_);
pbos@webrtc.orgd5ce2e62015-02-13 14:58:18 +00002657 int sender_rtp_ GUARDED_BY(test_crit_);
2658 int sender_rtcp_ GUARDED_BY(test_crit_);
2659 int receiver_rtcp_ GUARDED_BY(test_crit_);
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00002660 int down_frames_ GUARDED_BY(test_crit_);
2661 } test;
2662
2663 RunBaseTest(&test);
2664}
2665
pbos@webrtc.org2b19f062014-12-11 13:26:09 +00002666TEST_F(EndToEndTest, CallReportsRttForSender) {
2667 static const int kSendDelayMs = 30;
2668 static const int kReceiveDelayMs = 70;
2669
2670 FakeNetworkPipe::Config config;
2671 config.queue_delay_ms = kSendDelayMs;
2672 test::DirectTransport sender_transport(config);
2673 config.queue_delay_ms = kReceiveDelayMs;
2674 test::DirectTransport receiver_transport(config);
2675
2676 CreateCalls(Call::Config(&sender_transport),
2677 Call::Config(&receiver_transport));
2678
2679 sender_transport.SetReceiver(receiver_call_->Receiver());
2680 receiver_transport.SetReceiver(sender_call_->Receiver());
2681
2682 CreateSendConfig(1);
2683 CreateMatchingReceiveConfigs();
2684
2685 CreateStreams();
2686 CreateFrameGeneratorCapturer();
2687 Start();
2688
2689 int64_t start_time_ms = clock_->TimeInMilliseconds();
2690 while (true) {
2691 Call::Stats stats = sender_call_->GetStats();
2692 ASSERT_GE(start_time_ms + kDefaultTimeoutMs,
2693 clock_->TimeInMilliseconds())
2694 << "No RTT stats before timeout!";
2695 if (stats.rtt_ms != -1) {
2696 EXPECT_GE(stats.rtt_ms, kSendDelayMs + kReceiveDelayMs);
2697 break;
2698 }
2699 SleepMs(10);
2700 }
2701
2702 Stop();
2703 DestroyStreams();
2704}
2705
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00002706TEST_F(EndToEndTest, NewSendStreamsRespectNetworkDown) {
2707 class UnusedEncoder : public test::FakeEncoder {
2708 public:
2709 UnusedEncoder() : FakeEncoder(Clock::GetRealTimeClock()) {}
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +00002710 int32_t Encode(const I420VideoFrame& input_image,
2711 const CodecSpecificInfo* codec_specific_info,
2712 const std::vector<VideoFrameType>* frame_types) override {
pbos@webrtc.org26c0c412014-09-03 16:17:12 +00002713 ADD_FAILURE() << "Unexpected frame encode.";
2714 return test::FakeEncoder::Encode(
2715 input_image, codec_specific_info, frame_types);
2716 }
2717 };
2718
2719 UnusedTransport transport;
2720 CreateSenderCall(Call::Config(&transport));
2721 sender_call_->SignalNetworkState(Call::kNetworkDown);
2722
2723 CreateSendConfig(1);
2724 UnusedEncoder unused_encoder;
2725 send_config_.encoder_settings.encoder = &unused_encoder;
2726 CreateStreams();
2727 CreateFrameGeneratorCapturer();
2728
2729 Start();
2730 SleepMs(kSilenceTimeoutMs);
2731 Stop();
2732
2733 DestroyStreams();
2734}
2735
2736TEST_F(EndToEndTest, NewReceiveStreamsRespectNetworkDown) {
2737 test::DirectTransport sender_transport;
2738 CreateSenderCall(Call::Config(&sender_transport));
2739 UnusedTransport transport;
2740 CreateReceiverCall(Call::Config(&transport));
2741 sender_transport.SetReceiver(receiver_call_->Receiver());
2742
2743 receiver_call_->SignalNetworkState(Call::kNetworkDown);
2744
2745 CreateSendConfig(1);
2746 CreateMatchingReceiveConfigs();
2747 CreateStreams();
2748 CreateFrameGeneratorCapturer();
2749
2750 Start();
2751 SleepMs(kSilenceTimeoutMs);
2752 Stop();
2753
2754 sender_transport.StopSending();
2755
2756 DestroyStreams();
2757}
pbos@webrtc.org09cc6862014-11-04 13:48:15 +00002758
2759// TODO(pbos): Remove this regression test when VideoEngine is no longer used as
2760// a backend. This is to test that we hand channels back properly.
2761TEST_F(EndToEndTest, CanCreateAndDestroyManyVideoStreams) {
2762 test::NullTransport transport;
kwiberg@webrtc.org00b8f6b2015-02-26 14:34:55 +00002763 rtc::scoped_ptr<Call> call(Call::Create(Call::Config(&transport)));
pbos@webrtc.org09cc6862014-11-04 13:48:15 +00002764 test::FakeDecoder fake_decoder;
2765 test::FakeEncoder fake_encoder(Clock::GetRealTimeClock());
2766 for (size_t i = 0; i < 100; ++i) {
2767 VideoSendStream::Config send_config;
2768 send_config.encoder_settings.encoder = &fake_encoder;
2769 send_config.encoder_settings.payload_name = "FAKE";
2770 send_config.encoder_settings.payload_type = 123;
2771
2772 VideoEncoderConfig encoder_config;
2773 encoder_config.streams = test::CreateVideoStreams(1);
2774 send_config.rtp.ssrcs.push_back(1);
2775 VideoSendStream* send_stream =
2776 call->CreateVideoSendStream(send_config, encoder_config);
2777 call->DestroyVideoSendStream(send_stream);
2778
2779 VideoReceiveStream::Config receive_config;
2780 receive_config.rtp.remote_ssrc = 1;
2781 receive_config.rtp.local_ssrc = kReceiverLocalSsrc;
2782 VideoReceiveStream::Decoder decoder;
2783 decoder.decoder = &fake_decoder;
2784 decoder.payload_type = 123;
2785 decoder.payload_name = "FAKE";
2786 receive_config.decoders.push_back(decoder);
2787 VideoReceiveStream* receive_stream =
2788 call->CreateVideoReceiveStream(receive_config);
2789 call->DestroyVideoReceiveStream(receive_stream);
2790 }
2791}
pbos@webrtc.org994d0b72014-06-27 08:47:52 +00002792} // namespace webrtc