blob: 879a3e416b7548332c2f58f1668477a5759c685d [file] [log] [blame]
pbos@webrtc.org119a1cc2013-08-20 13:14:07 +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 */
10#include "testing/gtest/include/gtest/gtest.h"
11#include "webrtc/modules/rtp_rtcp/interface/rtp_header_parser.h"
pbos@webrtc.orgdf531a22013-09-10 14:56:33 +000012#include "webrtc/modules/rtp_rtcp/source/rtcp_sender.h"
pbos@webrtc.org013d9942013-08-22 09:42:17 +000013#include "webrtc/modules/rtp_rtcp/source/rtcp_utility.h"
pbos@webrtc.org119a1cc2013-08-20 13:14:07 +000014#include "webrtc/system_wrappers/interface/event_wrapper.h"
15#include "webrtc/system_wrappers/interface/scoped_ptr.h"
pbos@webrtc.org29023282013-09-11 10:14:56 +000016#include "webrtc/system_wrappers/interface/sleep.h"
pbos@webrtc.orgdf531a22013-09-10 14:56:33 +000017#include "webrtc/system_wrappers/interface/thread_wrapper.h"
pbos@webrtc.orgcb5118c2013-09-03 09:10:37 +000018#include "webrtc/video_engine/test/common/fake_encoder.h"
pbos@webrtc.org119a1cc2013-08-20 13:14:07 +000019#include "webrtc/video_engine/test/common/frame_generator.h"
20#include "webrtc/video_engine/test/common/frame_generator_capturer.h"
21#include "webrtc/video_engine/test/common/null_transport.h"
pbos@webrtc.org841c8a42013-09-09 15:04:25 +000022#include "webrtc/video_engine/new_include/call.h"
pbos@webrtc.org119a1cc2013-08-20 13:14:07 +000023#include "webrtc/video_engine/new_include/video_send_stream.h"
24
25namespace webrtc {
26
pbos@webrtc.org119a1cc2013-08-20 13:14:07 +000027class SendTransportObserver : public test::NullTransport {
28 public:
29 explicit SendTransportObserver(unsigned long timeout_ms)
30 : rtp_header_parser_(RtpHeaderParser::Create()),
31 send_test_complete_(EventWrapper::Create()),
32 timeout_ms_(timeout_ms) {}
33
pbos@webrtc.org841c8a42013-09-09 15:04:25 +000034 EventTypeWrapper Wait() { return send_test_complete_->Wait(timeout_ms_); }
pbos@webrtc.org119a1cc2013-08-20 13:14:07 +000035
36 protected:
37 scoped_ptr<RtpHeaderParser> rtp_header_parser_;
38 scoped_ptr<EventWrapper> send_test_complete_;
39
40 private:
41 unsigned long timeout_ms_;
42};
43
pbos@webrtc.org013d9942013-08-22 09:42:17 +000044class VideoSendStreamTest : public ::testing::Test {
pbos@webrtc.orgcb5118c2013-09-03 09:10:37 +000045 public:
46 VideoSendStreamTest() : fake_encoder_(Clock::GetRealTimeClock()) {}
pbos@webrtc.org841c8a42013-09-09 15:04:25 +000047
pbos@webrtc.org013d9942013-08-22 09:42:17 +000048 protected:
49 static const uint32_t kSendSsrc;
pbos@webrtc.org5860de02013-09-16 13:01:47 +000050 static const uint32_t kSendRtxSsrc;
pbos@webrtc.org841c8a42013-09-09 15:04:25 +000051 void RunSendTest(Call* call,
pbos@webrtc.org74fa4892013-08-23 09:19:30 +000052 const VideoSendStream::Config& config,
pbos@webrtc.org013d9942013-08-22 09:42:17 +000053 SendTransportObserver* observer) {
pbos@webrtc.org74fa4892013-08-23 09:19:30 +000054 VideoSendStream* send_stream = call->CreateSendStream(config);
pbos@webrtc.org013d9942013-08-22 09:42:17 +000055 scoped_ptr<test::FrameGeneratorCapturer> frame_generator_capturer(
56 test::FrameGeneratorCapturer::Create(
57 send_stream->Input(),
58 test::FrameGenerator::Create(320, 240, Clock::GetRealTimeClock()),
59 30));
60 send_stream->StartSend();
61 frame_generator_capturer->Start();
62
63 EXPECT_EQ(kEventSignaled, observer->Wait());
64
65 frame_generator_capturer->Stop();
66 send_stream->StopSend();
67 call->DestroySendStream(send_stream);
68 }
pbos@webrtc.orgcb5118c2013-09-03 09:10:37 +000069
pbos@webrtc.org841c8a42013-09-09 15:04:25 +000070 VideoSendStream::Config GetSendTestConfig(Call* call) {
pbos@webrtc.orgcb5118c2013-09-03 09:10:37 +000071 VideoSendStream::Config config = call->GetDefaultSendConfig();
72 config.encoder = &fake_encoder_;
73 config.internal_source = false;
pbos@webrtc.orgdf531a22013-09-10 14:56:33 +000074 config.rtp.ssrcs.push_back(kSendSsrc);
pbos@webrtc.org0181b5f2013-09-09 08:26:30 +000075 test::FakeEncoder::SetCodecSettings(&config.codec, 1);
pbos@webrtc.orgcb5118c2013-09-03 09:10:37 +000076 return config;
77 }
78
pbos@webrtc.org5860de02013-09-16 13:01:47 +000079 void TestNackRetransmission(uint32_t retransmit_ssrc);
80
pbos@webrtc.orgcb5118c2013-09-03 09:10:37 +000081 test::FakeEncoder fake_encoder_;
pbos@webrtc.org013d9942013-08-22 09:42:17 +000082};
83
84const uint32_t VideoSendStreamTest::kSendSsrc = 0xC0FFEE;
pbos@webrtc.org5860de02013-09-16 13:01:47 +000085const uint32_t VideoSendStreamTest::kSendRtxSsrc = 0xBADCAFE;
pbos@webrtc.org013d9942013-08-22 09:42:17 +000086
pbos@webrtc.org119a1cc2013-08-20 13:14:07 +000087TEST_F(VideoSendStreamTest, SendsSetSsrc) {
pbos@webrtc.org119a1cc2013-08-20 13:14:07 +000088 class SendSsrcObserver : public SendTransportObserver {
89 public:
90 SendSsrcObserver() : SendTransportObserver(30 * 1000) {}
91
92 virtual bool SendRTP(const uint8_t* packet, size_t length) OVERRIDE {
93 RTPHeader header;
94 EXPECT_TRUE(
95 rtp_header_parser_->Parse(packet, static_cast<int>(length), &header));
96
97 if (header.ssrc == kSendSsrc)
98 send_test_complete_->Set();
99
100 return true;
101 }
102 } observer;
103
pbos@webrtc.org841c8a42013-09-09 15:04:25 +0000104 Call::Config call_config(&observer);
105 scoped_ptr<Call> call(Call::Create(call_config));
pbos@webrtc.org119a1cc2013-08-20 13:14:07 +0000106
pbos@webrtc.orgcb5118c2013-09-03 09:10:37 +0000107 VideoSendStream::Config send_config = GetSendTestConfig(call.get());
pbos@webrtc.org119a1cc2013-08-20 13:14:07 +0000108
pbos@webrtc.org013d9942013-08-22 09:42:17 +0000109 RunSendTest(call.get(), send_config, &observer);
110}
pbos@webrtc.org119a1cc2013-08-20 13:14:07 +0000111
pbos@webrtc.org013d9942013-08-22 09:42:17 +0000112TEST_F(VideoSendStreamTest, SupportsCName) {
113 static std::string kCName = "PjQatC14dGfbVwGPUOA9IH7RlsFDbWl4AhXEiDsBizo=";
114 class CNameObserver : public SendTransportObserver {
115 public:
116 CNameObserver() : SendTransportObserver(30 * 1000) {}
117
118 virtual bool SendRTCP(const uint8_t* packet, size_t length) OVERRIDE {
119 RTCPUtility::RTCPParserV2 parser(packet, length, true);
120 EXPECT_TRUE(parser.IsValid());
121
122 RTCPUtility::RTCPPacketTypes packet_type = parser.Begin();
123 while (packet_type != RTCPUtility::kRtcpNotValidCode) {
124 if (packet_type == RTCPUtility::kRtcpSdesChunkCode) {
125 EXPECT_EQ(parser.Packet().CName.CName, kCName);
126 send_test_complete_->Set();
127 }
128
129 packet_type = parser.Iterate();
130 }
131
132 return true;
133 }
134 } observer;
135
pbos@webrtc.org841c8a42013-09-09 15:04:25 +0000136 Call::Config call_config(&observer);
137 scoped_ptr<Call> call(Call::Create(call_config));
pbos@webrtc.org013d9942013-08-22 09:42:17 +0000138
pbos@webrtc.orgcb5118c2013-09-03 09:10:37 +0000139 VideoSendStream::Config send_config = GetSendTestConfig(call.get());
pbos@webrtc.org013d9942013-08-22 09:42:17 +0000140 send_config.rtp.c_name = kCName;
141
142 RunSendTest(call.get(), send_config, &observer);
pbos@webrtc.org119a1cc2013-08-20 13:14:07 +0000143}
144
pbos@webrtc.org5c678ea2013-09-11 19:00:39 +0000145TEST_F(VideoSendStreamTest, SupportsAbsoluteSendTime) {
146 static const uint8_t kAbsSendTimeExtensionId = 13;
147 class AbsoluteSendTimeObserver : public SendTransportObserver {
148 public:
149 AbsoluteSendTimeObserver() : SendTransportObserver(30 * 1000) {
150 EXPECT_TRUE(rtp_header_parser_->RegisterRtpHeaderExtension(
151 kRtpExtensionAbsoluteSendTime, kAbsSendTimeExtensionId));
152 }
153
154 virtual bool SendRTP(const uint8_t* packet, size_t length) OVERRIDE {
155 RTPHeader header;
156 EXPECT_TRUE(
157 rtp_header_parser_->Parse(packet, static_cast<int>(length), &header));
158
159 if (header.extension.absoluteSendTime > 0)
160 send_test_complete_->Set();
161
162 return true;
163 }
164 } observer;
165
166 Call::Config call_config(&observer);
167 scoped_ptr<Call> call(Call::Create(call_config));
168
169 VideoSendStream::Config send_config = GetSendTestConfig(call.get());
170 send_config.rtp.extensions.push_back(
171 RtpExtension("abs-send-time", kAbsSendTimeExtensionId));
172
173 RunSendTest(call.get(), send_config, &observer);
174}
175
pbos@webrtc.org29023282013-09-11 10:14:56 +0000176TEST_F(VideoSendStreamTest, SupportsTransmissionTimeOffset) {
177 static const uint8_t kTOffsetExtensionId = 13;
178 class DelayedEncoder : public test::FakeEncoder {
179 public:
180 DelayedEncoder(Clock* clock) : test::FakeEncoder(clock) {}
181 virtual int32_t Encode(
182 const I420VideoFrame& input_image,
183 const CodecSpecificInfo* codec_specific_info,
184 const std::vector<VideoFrameType>* frame_types) OVERRIDE {
185 // A delay needs to be introduced to assure that we get a timestamp
186 // offset.
187 SleepMs(5);
188 return FakeEncoder::Encode(input_image, codec_specific_info, frame_types);
189 }
190 } encoder(Clock::GetRealTimeClock());
191
192 class TransmissionTimeOffsetObserver : public SendTransportObserver {
193 public:
194 TransmissionTimeOffsetObserver() : SendTransportObserver(30 * 1000) {
195 EXPECT_TRUE(rtp_header_parser_->RegisterRtpHeaderExtension(
196 kRtpExtensionTransmissionTimeOffset, kTOffsetExtensionId));
197 }
198
199 virtual bool SendRTP(const uint8_t* packet, size_t length) OVERRIDE {
200 RTPHeader header;
201 EXPECT_TRUE(
202 rtp_header_parser_->Parse(packet, static_cast<int>(length), &header));
203
204 EXPECT_GT(header.extension.transmissionTimeOffset, 0);
205 send_test_complete_->Set();
206
207 return true;
208 }
209 } observer;
210
211 Call::Config call_config(&observer);
212 scoped_ptr<Call> call(Call::Create(call_config));
213
214 VideoSendStream::Config send_config = GetSendTestConfig(call.get());
215 send_config.encoder = &encoder;
216 send_config.rtp.extensions.push_back(
217 RtpExtension("toffset", kTOffsetExtensionId));
218
219 RunSendTest(call.get(), send_config, &observer);
220}
221
pbos@webrtc.org5860de02013-09-16 13:01:47 +0000222void VideoSendStreamTest::TestNackRetransmission(uint32_t retransmit_ssrc) {
pbos@webrtc.orgdf531a22013-09-10 14:56:33 +0000223 class NackObserver : public SendTransportObserver, webrtc::Transport {
224 public:
pbos@webrtc.org5860de02013-09-16 13:01:47 +0000225 NackObserver(uint32_t retransmit_ssrc)
pbos@webrtc.orgdf531a22013-09-10 14:56:33 +0000226 : SendTransportObserver(30 * 1000),
227 thread_(ThreadWrapper::CreateThread(NackProcess, this)),
228 send_call_receiver_(NULL),
229 send_count_(0),
pbos@webrtc.org5860de02013-09-16 13:01:47 +0000230 retransmit_ssrc_(retransmit_ssrc),
pbos@webrtc.orgdf531a22013-09-10 14:56:33 +0000231 nacked_sequence_number_(0) {}
232
233 ~NackObserver() {
234 EXPECT_TRUE(thread_->Stop());
235 }
236
237 void SetReceiver(PacketReceiver* send_call_receiver) {
238 send_call_receiver_ = send_call_receiver;
239 }
240
241 // Sending NACKs must be done from a different "network" thread to prevent
242 // violating locking orders. With this no locks are held prior to inserting
243 // packets back into the sender.
244 static bool NackProcess(void* observer) {
245 return static_cast<NackObserver*>(observer)->SendNack();
246 }
247
248 bool SendNack() {
249 NullReceiveStatistics null_stats;
250 RTCPSender rtcp_sender(0, false, Clock::GetRealTimeClock(), &null_stats);
251 EXPECT_EQ(0, rtcp_sender.RegisterSendTransport(this));
252
253 rtcp_sender.SetRTCPStatus(kRtcpNonCompound);
pbos@webrtc.org5860de02013-09-16 13:01:47 +0000254 rtcp_sender.SetRemoteSSRC(kSendSsrc);
pbos@webrtc.orgdf531a22013-09-10 14:56:33 +0000255
256 RTCPSender::FeedbackState feedback_state;
257 EXPECT_EQ(0, rtcp_sender.SendRTCP(
258 feedback_state, kRtcpNack, 1, &nacked_sequence_number_));
259 return false;
260 }
261
262 virtual int SendPacket(int channel, const void* data, int len) OVERRIDE {
263 ADD_FAILURE()
264 << "This should never be reached. Only a NACK should be sent.";
265 return -1;
266 }
267
268 virtual int SendRTCPPacket(int channel,
269 const void* data,
270 int len) OVERRIDE {
271 EXPECT_TRUE(send_call_receiver_->DeliverPacket(
272 static_cast<const uint8_t*>(data), static_cast<size_t>(len)));
273 return len;
274 }
275
276 virtual bool SendRTP(const uint8_t* packet, size_t length) OVERRIDE {
277 EXPECT_TRUE(send_call_receiver_ != NULL);
278 RTPHeader header;
279 EXPECT_TRUE(
280 rtp_header_parser_->Parse(packet, static_cast<int>(length), &header));
281
282 // Nack second packet after receiving the third one.
283 if (++send_count_ == 3) {
pbos@webrtc.orgdf531a22013-09-10 14:56:33 +0000284 nacked_sequence_number_ = header.sequenceNumber - 1;
285 unsigned int id;
286 EXPECT_TRUE(thread_->Start(id));
287 }
288
pbos@webrtc.org5860de02013-09-16 13:01:47 +0000289 uint16_t sequence_number = header.sequenceNumber;
290
291 if (header.ssrc == retransmit_ssrc_ && retransmit_ssrc_ != kSendSsrc) {
292 // Not kSendSsrc, assume correct RTX packet. Extract sequence number.
293 const uint8_t* rtx_header = packet + header.headerLength;
294 sequence_number = (rtx_header[0] << 8) + rtx_header[1];
295 }
296
297 if (sequence_number == nacked_sequence_number_) {
298 EXPECT_EQ(retransmit_ssrc_, header.ssrc);
pbos@webrtc.orgdf531a22013-09-10 14:56:33 +0000299 send_test_complete_->Set();
pbos@webrtc.org5860de02013-09-16 13:01:47 +0000300 }
pbos@webrtc.orgdf531a22013-09-10 14:56:33 +0000301
302 return true;
303 }
304 private:
305 scoped_ptr<ThreadWrapper> thread_;
306 PacketReceiver* send_call_receiver_;
307 int send_count_;
pbos@webrtc.org5860de02013-09-16 13:01:47 +0000308 uint32_t retransmit_ssrc_;
pbos@webrtc.orgdf531a22013-09-10 14:56:33 +0000309 uint16_t nacked_sequence_number_;
pbos@webrtc.org5860de02013-09-16 13:01:47 +0000310 } observer(retransmit_ssrc);
pbos@webrtc.orgdf531a22013-09-10 14:56:33 +0000311
312 Call::Config call_config(&observer);
313 scoped_ptr<Call> call(Call::Create(call_config));
314 observer.SetReceiver(call->Receiver());
315
316 VideoSendStream::Config send_config = GetSendTestConfig(call.get());
317 send_config.rtp.nack.rtp_history_ms = 1000;
pbos@webrtc.org5860de02013-09-16 13:01:47 +0000318 if (retransmit_ssrc != kSendSsrc)
319 send_config.rtp.rtx.ssrcs.push_back(retransmit_ssrc);
pbos@webrtc.orgdf531a22013-09-10 14:56:33 +0000320
321 RunSendTest(call.get(), send_config, &observer);
322}
323
pbos@webrtc.org5860de02013-09-16 13:01:47 +0000324TEST_F(VideoSendStreamTest, RetransmitsNack) {
325 // Normal NACKs should use the send SSRC.
326 TestNackRetransmission(kSendSsrc);
327}
328
329TEST_F(VideoSendStreamTest, RetransmitsNackOverRtx) {
330 // NACKs over RTX should use a separate SSRC.
331 TestNackRetransmission(kSendRtxSsrc);
332}
333
pbos@webrtc.org119a1cc2013-08-20 13:14:07 +0000334} // namespace webrtc