blob: 10ad66dca6104cbfe456c49019d7a2890f8fdbf3 [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_capturer.h"
20#include "webrtc/video_engine/test/common/null_transport.h"
pbos@webrtc.org841c8a42013-09-09 15:04:25 +000021#include "webrtc/video_engine/new_include/call.h"
pbos@webrtc.org119a1cc2013-08-20 13:14:07 +000022#include "webrtc/video_engine/new_include/video_send_stream.h"
23
24namespace webrtc {
25
pbos@webrtc.org119a1cc2013-08-20 13:14:07 +000026class SendTransportObserver : public test::NullTransport {
27 public:
28 explicit SendTransportObserver(unsigned long timeout_ms)
29 : rtp_header_parser_(RtpHeaderParser::Create()),
30 send_test_complete_(EventWrapper::Create()),
31 timeout_ms_(timeout_ms) {}
32
pbos@webrtc.org841c8a42013-09-09 15:04:25 +000033 EventTypeWrapper Wait() { return send_test_complete_->Wait(timeout_ms_); }
pbos@webrtc.org119a1cc2013-08-20 13:14:07 +000034
35 protected:
36 scoped_ptr<RtpHeaderParser> rtp_header_parser_;
37 scoped_ptr<EventWrapper> send_test_complete_;
38
39 private:
40 unsigned long timeout_ms_;
41};
42
pbos@webrtc.org013d9942013-08-22 09:42:17 +000043class VideoSendStreamTest : public ::testing::Test {
pbos@webrtc.orgcb5118c2013-09-03 09:10:37 +000044 public:
45 VideoSendStreamTest() : fake_encoder_(Clock::GetRealTimeClock()) {}
pbos@webrtc.org841c8a42013-09-09 15:04:25 +000046
pbos@webrtc.org013d9942013-08-22 09:42:17 +000047 protected:
48 static const uint32_t kSendSsrc;
pbos@webrtc.org5860de02013-09-16 13:01:47 +000049 static const uint32_t kSendRtxSsrc;
pbos@webrtc.org841c8a42013-09-09 15:04:25 +000050 void RunSendTest(Call* call,
pbos@webrtc.org74fa4892013-08-23 09:19:30 +000051 const VideoSendStream::Config& config,
pbos@webrtc.org013d9942013-08-22 09:42:17 +000052 SendTransportObserver* observer) {
pbos@webrtc.org74fa4892013-08-23 09:19:30 +000053 VideoSendStream* send_stream = call->CreateSendStream(config);
pbos@webrtc.org013d9942013-08-22 09:42:17 +000054 scoped_ptr<test::FrameGeneratorCapturer> frame_generator_capturer(
55 test::FrameGeneratorCapturer::Create(
andresp@webrtc.orgab654952013-09-19 12:14:03 +000056 send_stream->Input(), 320, 240, 30, Clock::GetRealTimeClock()));
pbos@webrtc.org013d9942013-08-22 09:42:17 +000057 send_stream->StartSend();
58 frame_generator_capturer->Start();
59
60 EXPECT_EQ(kEventSignaled, observer->Wait());
61
62 frame_generator_capturer->Stop();
63 send_stream->StopSend();
64 call->DestroySendStream(send_stream);
65 }
pbos@webrtc.orgcb5118c2013-09-03 09:10:37 +000066
pbos@webrtc.org841c8a42013-09-09 15:04:25 +000067 VideoSendStream::Config GetSendTestConfig(Call* call) {
pbos@webrtc.orgcb5118c2013-09-03 09:10:37 +000068 VideoSendStream::Config config = call->GetDefaultSendConfig();
69 config.encoder = &fake_encoder_;
70 config.internal_source = false;
pbos@webrtc.orgdf531a22013-09-10 14:56:33 +000071 config.rtp.ssrcs.push_back(kSendSsrc);
pbos@webrtc.org0181b5f2013-09-09 08:26:30 +000072 test::FakeEncoder::SetCodecSettings(&config.codec, 1);
pbos@webrtc.orgcb5118c2013-09-03 09:10:37 +000073 return config;
74 }
75
pbos@webrtc.org5860de02013-09-16 13:01:47 +000076 void TestNackRetransmission(uint32_t retransmit_ssrc);
77
pbos@webrtc.orgcb5118c2013-09-03 09:10:37 +000078 test::FakeEncoder fake_encoder_;
pbos@webrtc.org013d9942013-08-22 09:42:17 +000079};
80
81const uint32_t VideoSendStreamTest::kSendSsrc = 0xC0FFEE;
pbos@webrtc.org5860de02013-09-16 13:01:47 +000082const uint32_t VideoSendStreamTest::kSendRtxSsrc = 0xBADCAFE;
pbos@webrtc.org013d9942013-08-22 09:42:17 +000083
pbos@webrtc.org119a1cc2013-08-20 13:14:07 +000084TEST_F(VideoSendStreamTest, SendsSetSsrc) {
pbos@webrtc.org119a1cc2013-08-20 13:14:07 +000085 class SendSsrcObserver : public SendTransportObserver {
86 public:
87 SendSsrcObserver() : SendTransportObserver(30 * 1000) {}
88
89 virtual bool SendRTP(const uint8_t* packet, size_t length) OVERRIDE {
90 RTPHeader header;
91 EXPECT_TRUE(
92 rtp_header_parser_->Parse(packet, static_cast<int>(length), &header));
93
94 if (header.ssrc == kSendSsrc)
95 send_test_complete_->Set();
96
97 return true;
98 }
99 } observer;
100
pbos@webrtc.org841c8a42013-09-09 15:04:25 +0000101 Call::Config call_config(&observer);
102 scoped_ptr<Call> call(Call::Create(call_config));
pbos@webrtc.org119a1cc2013-08-20 13:14:07 +0000103
pbos@webrtc.orgcb5118c2013-09-03 09:10:37 +0000104 VideoSendStream::Config send_config = GetSendTestConfig(call.get());
pbos@webrtc.org119a1cc2013-08-20 13:14:07 +0000105
pbos@webrtc.org013d9942013-08-22 09:42:17 +0000106 RunSendTest(call.get(), send_config, &observer);
107}
pbos@webrtc.org119a1cc2013-08-20 13:14:07 +0000108
pbos@webrtc.org013d9942013-08-22 09:42:17 +0000109TEST_F(VideoSendStreamTest, SupportsCName) {
110 static std::string kCName = "PjQatC14dGfbVwGPUOA9IH7RlsFDbWl4AhXEiDsBizo=";
111 class CNameObserver : public SendTransportObserver {
112 public:
113 CNameObserver() : SendTransportObserver(30 * 1000) {}
114
115 virtual bool SendRTCP(const uint8_t* packet, size_t length) OVERRIDE {
116 RTCPUtility::RTCPParserV2 parser(packet, length, true);
117 EXPECT_TRUE(parser.IsValid());
118
119 RTCPUtility::RTCPPacketTypes packet_type = parser.Begin();
120 while (packet_type != RTCPUtility::kRtcpNotValidCode) {
121 if (packet_type == RTCPUtility::kRtcpSdesChunkCode) {
122 EXPECT_EQ(parser.Packet().CName.CName, kCName);
123 send_test_complete_->Set();
124 }
125
126 packet_type = parser.Iterate();
127 }
128
129 return true;
130 }
131 } observer;
132
pbos@webrtc.org841c8a42013-09-09 15:04:25 +0000133 Call::Config call_config(&observer);
134 scoped_ptr<Call> call(Call::Create(call_config));
pbos@webrtc.org013d9942013-08-22 09:42:17 +0000135
pbos@webrtc.orgcb5118c2013-09-03 09:10:37 +0000136 VideoSendStream::Config send_config = GetSendTestConfig(call.get());
pbos@webrtc.org013d9942013-08-22 09:42:17 +0000137 send_config.rtp.c_name = kCName;
138
139 RunSendTest(call.get(), send_config, &observer);
pbos@webrtc.org119a1cc2013-08-20 13:14:07 +0000140}
141
pbos@webrtc.org5c678ea2013-09-11 19:00:39 +0000142TEST_F(VideoSendStreamTest, SupportsAbsoluteSendTime) {
143 static const uint8_t kAbsSendTimeExtensionId = 13;
144 class AbsoluteSendTimeObserver : public SendTransportObserver {
145 public:
146 AbsoluteSendTimeObserver() : SendTransportObserver(30 * 1000) {
147 EXPECT_TRUE(rtp_header_parser_->RegisterRtpHeaderExtension(
148 kRtpExtensionAbsoluteSendTime, kAbsSendTimeExtensionId));
149 }
150
151 virtual bool SendRTP(const uint8_t* packet, size_t length) OVERRIDE {
152 RTPHeader header;
153 EXPECT_TRUE(
154 rtp_header_parser_->Parse(packet, static_cast<int>(length), &header));
155
156 if (header.extension.absoluteSendTime > 0)
157 send_test_complete_->Set();
158
159 return true;
160 }
161 } observer;
162
163 Call::Config call_config(&observer);
164 scoped_ptr<Call> call(Call::Create(call_config));
165
166 VideoSendStream::Config send_config = GetSendTestConfig(call.get());
167 send_config.rtp.extensions.push_back(
168 RtpExtension("abs-send-time", kAbsSendTimeExtensionId));
169
170 RunSendTest(call.get(), send_config, &observer);
171}
172
pbos@webrtc.org29023282013-09-11 10:14:56 +0000173TEST_F(VideoSendStreamTest, SupportsTransmissionTimeOffset) {
174 static const uint8_t kTOffsetExtensionId = 13;
175 class DelayedEncoder : public test::FakeEncoder {
176 public:
177 DelayedEncoder(Clock* clock) : test::FakeEncoder(clock) {}
178 virtual int32_t Encode(
179 const I420VideoFrame& input_image,
180 const CodecSpecificInfo* codec_specific_info,
181 const std::vector<VideoFrameType>* frame_types) OVERRIDE {
182 // A delay needs to be introduced to assure that we get a timestamp
183 // offset.
184 SleepMs(5);
185 return FakeEncoder::Encode(input_image, codec_specific_info, frame_types);
186 }
187 } encoder(Clock::GetRealTimeClock());
188
189 class TransmissionTimeOffsetObserver : public SendTransportObserver {
190 public:
191 TransmissionTimeOffsetObserver() : SendTransportObserver(30 * 1000) {
192 EXPECT_TRUE(rtp_header_parser_->RegisterRtpHeaderExtension(
193 kRtpExtensionTransmissionTimeOffset, kTOffsetExtensionId));
194 }
195
196 virtual bool SendRTP(const uint8_t* packet, size_t length) OVERRIDE {
197 RTPHeader header;
198 EXPECT_TRUE(
199 rtp_header_parser_->Parse(packet, static_cast<int>(length), &header));
200
201 EXPECT_GT(header.extension.transmissionTimeOffset, 0);
202 send_test_complete_->Set();
203
204 return true;
205 }
206 } observer;
207
208 Call::Config call_config(&observer);
209 scoped_ptr<Call> call(Call::Create(call_config));
210
211 VideoSendStream::Config send_config = GetSendTestConfig(call.get());
212 send_config.encoder = &encoder;
213 send_config.rtp.extensions.push_back(
214 RtpExtension("toffset", kTOffsetExtensionId));
215
216 RunSendTest(call.get(), send_config, &observer);
217}
218
pbos@webrtc.org5860de02013-09-16 13:01:47 +0000219void VideoSendStreamTest::TestNackRetransmission(uint32_t retransmit_ssrc) {
pbos@webrtc.orgdf531a22013-09-10 14:56:33 +0000220 class NackObserver : public SendTransportObserver, webrtc::Transport {
221 public:
pbos@webrtc.org5860de02013-09-16 13:01:47 +0000222 NackObserver(uint32_t retransmit_ssrc)
pbos@webrtc.orgdf531a22013-09-10 14:56:33 +0000223 : SendTransportObserver(30 * 1000),
224 thread_(ThreadWrapper::CreateThread(NackProcess, this)),
225 send_call_receiver_(NULL),
226 send_count_(0),
pbos@webrtc.org5860de02013-09-16 13:01:47 +0000227 retransmit_ssrc_(retransmit_ssrc),
pbos@webrtc.orgdf531a22013-09-10 14:56:33 +0000228 nacked_sequence_number_(0) {}
229
230 ~NackObserver() {
231 EXPECT_TRUE(thread_->Stop());
232 }
233
234 void SetReceiver(PacketReceiver* send_call_receiver) {
235 send_call_receiver_ = send_call_receiver;
236 }
237
238 // Sending NACKs must be done from a different "network" thread to prevent
239 // violating locking orders. With this no locks are held prior to inserting
240 // packets back into the sender.
241 static bool NackProcess(void* observer) {
242 return static_cast<NackObserver*>(observer)->SendNack();
243 }
244
245 bool SendNack() {
246 NullReceiveStatistics null_stats;
247 RTCPSender rtcp_sender(0, false, Clock::GetRealTimeClock(), &null_stats);
248 EXPECT_EQ(0, rtcp_sender.RegisterSendTransport(this));
249
250 rtcp_sender.SetRTCPStatus(kRtcpNonCompound);
pbos@webrtc.org5860de02013-09-16 13:01:47 +0000251 rtcp_sender.SetRemoteSSRC(kSendSsrc);
pbos@webrtc.orgdf531a22013-09-10 14:56:33 +0000252
253 RTCPSender::FeedbackState feedback_state;
254 EXPECT_EQ(0, rtcp_sender.SendRTCP(
255 feedback_state, kRtcpNack, 1, &nacked_sequence_number_));
256 return false;
257 }
258
259 virtual int SendPacket(int channel, const void* data, int len) OVERRIDE {
260 ADD_FAILURE()
261 << "This should never be reached. Only a NACK should be sent.";
262 return -1;
263 }
264
265 virtual int SendRTCPPacket(int channel,
266 const void* data,
267 int len) OVERRIDE {
268 EXPECT_TRUE(send_call_receiver_->DeliverPacket(
269 static_cast<const uint8_t*>(data), static_cast<size_t>(len)));
270 return len;
271 }
272
273 virtual bool SendRTP(const uint8_t* packet, size_t length) OVERRIDE {
274 EXPECT_TRUE(send_call_receiver_ != NULL);
275 RTPHeader header;
276 EXPECT_TRUE(
277 rtp_header_parser_->Parse(packet, static_cast<int>(length), &header));
278
279 // Nack second packet after receiving the third one.
280 if (++send_count_ == 3) {
pbos@webrtc.orgdf531a22013-09-10 14:56:33 +0000281 nacked_sequence_number_ = header.sequenceNumber - 1;
282 unsigned int id;
283 EXPECT_TRUE(thread_->Start(id));
284 }
285
pbos@webrtc.org5860de02013-09-16 13:01:47 +0000286 uint16_t sequence_number = header.sequenceNumber;
287
288 if (header.ssrc == retransmit_ssrc_ && retransmit_ssrc_ != kSendSsrc) {
289 // Not kSendSsrc, assume correct RTX packet. Extract sequence number.
290 const uint8_t* rtx_header = packet + header.headerLength;
291 sequence_number = (rtx_header[0] << 8) + rtx_header[1];
292 }
293
294 if (sequence_number == nacked_sequence_number_) {
295 EXPECT_EQ(retransmit_ssrc_, header.ssrc);
pbos@webrtc.orgdf531a22013-09-10 14:56:33 +0000296 send_test_complete_->Set();
pbos@webrtc.org5860de02013-09-16 13:01:47 +0000297 }
pbos@webrtc.orgdf531a22013-09-10 14:56:33 +0000298
299 return true;
300 }
301 private:
302 scoped_ptr<ThreadWrapper> thread_;
303 PacketReceiver* send_call_receiver_;
304 int send_count_;
pbos@webrtc.org5860de02013-09-16 13:01:47 +0000305 uint32_t retransmit_ssrc_;
pbos@webrtc.orgdf531a22013-09-10 14:56:33 +0000306 uint16_t nacked_sequence_number_;
pbos@webrtc.org5860de02013-09-16 13:01:47 +0000307 } observer(retransmit_ssrc);
pbos@webrtc.orgdf531a22013-09-10 14:56:33 +0000308
309 Call::Config call_config(&observer);
310 scoped_ptr<Call> call(Call::Create(call_config));
311 observer.SetReceiver(call->Receiver());
312
313 VideoSendStream::Config send_config = GetSendTestConfig(call.get());
314 send_config.rtp.nack.rtp_history_ms = 1000;
pbos@webrtc.org5860de02013-09-16 13:01:47 +0000315 if (retransmit_ssrc != kSendSsrc)
316 send_config.rtp.rtx.ssrcs.push_back(retransmit_ssrc);
pbos@webrtc.orgdf531a22013-09-10 14:56:33 +0000317
318 RunSendTest(call.get(), send_config, &observer);
319}
320
pbos@webrtc.org5860de02013-09-16 13:01:47 +0000321TEST_F(VideoSendStreamTest, RetransmitsNack) {
322 // Normal NACKs should use the send SSRC.
323 TestNackRetransmission(kSendSsrc);
324}
325
326TEST_F(VideoSendStreamTest, RetransmitsNackOverRtx) {
327 // NACKs over RTX should use a separate SSRC.
328 TestNackRetransmission(kSendRtxSsrc);
329}
330
pbos@webrtc.org119a1cc2013-08-20 13:14:07 +0000331} // namespace webrtc