blob: 645cda0455b39585a446a83a512b32ffc7f1f58b [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.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(
56 send_stream->Input(),
57 test::FrameGenerator::Create(320, 240, Clock::GetRealTimeClock()),
58 30));
59 send_stream->StartSend();
60 frame_generator_capturer->Start();
61
62 EXPECT_EQ(kEventSignaled, observer->Wait());
63
64 frame_generator_capturer->Stop();
65 send_stream->StopSend();
66 call->DestroySendStream(send_stream);
67 }
pbos@webrtc.orgcb5118c2013-09-03 09:10:37 +000068
pbos@webrtc.org841c8a42013-09-09 15:04:25 +000069 VideoSendStream::Config GetSendTestConfig(Call* call) {
pbos@webrtc.orgcb5118c2013-09-03 09:10:37 +000070 VideoSendStream::Config config = call->GetDefaultSendConfig();
71 config.encoder = &fake_encoder_;
72 config.internal_source = false;
pbos@webrtc.orgdf531a22013-09-10 14:56:33 +000073 config.rtp.ssrcs.push_back(kSendSsrc);
pbos@webrtc.org0181b5f2013-09-09 08:26:30 +000074 test::FakeEncoder::SetCodecSettings(&config.codec, 1);
pbos@webrtc.orgcb5118c2013-09-03 09:10:37 +000075 return config;
76 }
77
78 test::FakeEncoder fake_encoder_;
pbos@webrtc.org013d9942013-08-22 09:42:17 +000079};
80
81const uint32_t VideoSendStreamTest::kSendSsrc = 0xC0FFEE;
82
pbos@webrtc.org119a1cc2013-08-20 13:14:07 +000083TEST_F(VideoSendStreamTest, SendsSetSsrc) {
pbos@webrtc.org119a1cc2013-08-20 13:14:07 +000084 class SendSsrcObserver : public SendTransportObserver {
85 public:
86 SendSsrcObserver() : SendTransportObserver(30 * 1000) {}
87
88 virtual bool SendRTP(const uint8_t* packet, size_t length) OVERRIDE {
89 RTPHeader header;
90 EXPECT_TRUE(
91 rtp_header_parser_->Parse(packet, static_cast<int>(length), &header));
92
93 if (header.ssrc == kSendSsrc)
94 send_test_complete_->Set();
95
96 return true;
97 }
98 } observer;
99
pbos@webrtc.org841c8a42013-09-09 15:04:25 +0000100 Call::Config call_config(&observer);
101 scoped_ptr<Call> call(Call::Create(call_config));
pbos@webrtc.org119a1cc2013-08-20 13:14:07 +0000102
pbos@webrtc.orgcb5118c2013-09-03 09:10:37 +0000103 VideoSendStream::Config send_config = GetSendTestConfig(call.get());
pbos@webrtc.org119a1cc2013-08-20 13:14:07 +0000104
pbos@webrtc.org013d9942013-08-22 09:42:17 +0000105 RunSendTest(call.get(), send_config, &observer);
106}
pbos@webrtc.org119a1cc2013-08-20 13:14:07 +0000107
pbos@webrtc.org013d9942013-08-22 09:42:17 +0000108TEST_F(VideoSendStreamTest, SupportsCName) {
109 static std::string kCName = "PjQatC14dGfbVwGPUOA9IH7RlsFDbWl4AhXEiDsBizo=";
110 class CNameObserver : public SendTransportObserver {
111 public:
112 CNameObserver() : SendTransportObserver(30 * 1000) {}
113
114 virtual bool SendRTCP(const uint8_t* packet, size_t length) OVERRIDE {
115 RTCPUtility::RTCPParserV2 parser(packet, length, true);
116 EXPECT_TRUE(parser.IsValid());
117
118 RTCPUtility::RTCPPacketTypes packet_type = parser.Begin();
119 while (packet_type != RTCPUtility::kRtcpNotValidCode) {
120 if (packet_type == RTCPUtility::kRtcpSdesChunkCode) {
121 EXPECT_EQ(parser.Packet().CName.CName, kCName);
122 send_test_complete_->Set();
123 }
124
125 packet_type = parser.Iterate();
126 }
127
128 return true;
129 }
130 } observer;
131
pbos@webrtc.org841c8a42013-09-09 15:04:25 +0000132 Call::Config call_config(&observer);
133 scoped_ptr<Call> call(Call::Create(call_config));
pbos@webrtc.org013d9942013-08-22 09:42:17 +0000134
pbos@webrtc.orgcb5118c2013-09-03 09:10:37 +0000135 VideoSendStream::Config send_config = GetSendTestConfig(call.get());
pbos@webrtc.org013d9942013-08-22 09:42:17 +0000136 send_config.rtp.c_name = kCName;
137
138 RunSendTest(call.get(), send_config, &observer);
pbos@webrtc.org119a1cc2013-08-20 13:14:07 +0000139}
140
pbos@webrtc.org29023282013-09-11 10:14:56 +0000141TEST_F(VideoSendStreamTest, SupportsTransmissionTimeOffset) {
142 static const uint8_t kTOffsetExtensionId = 13;
143 class DelayedEncoder : public test::FakeEncoder {
144 public:
145 DelayedEncoder(Clock* clock) : test::FakeEncoder(clock) {}
146 virtual int32_t Encode(
147 const I420VideoFrame& input_image,
148 const CodecSpecificInfo* codec_specific_info,
149 const std::vector<VideoFrameType>* frame_types) OVERRIDE {
150 // A delay needs to be introduced to assure that we get a timestamp
151 // offset.
152 SleepMs(5);
153 return FakeEncoder::Encode(input_image, codec_specific_info, frame_types);
154 }
155 } encoder(Clock::GetRealTimeClock());
156
157 class TransmissionTimeOffsetObserver : public SendTransportObserver {
158 public:
159 TransmissionTimeOffsetObserver() : SendTransportObserver(30 * 1000) {
160 EXPECT_TRUE(rtp_header_parser_->RegisterRtpHeaderExtension(
161 kRtpExtensionTransmissionTimeOffset, kTOffsetExtensionId));
162 }
163
164 virtual bool SendRTP(const uint8_t* packet, size_t length) OVERRIDE {
165 RTPHeader header;
166 EXPECT_TRUE(
167 rtp_header_parser_->Parse(packet, static_cast<int>(length), &header));
168
169 EXPECT_GT(header.extension.transmissionTimeOffset, 0);
170 send_test_complete_->Set();
171
172 return true;
173 }
174 } observer;
175
176 Call::Config call_config(&observer);
177 scoped_ptr<Call> call(Call::Create(call_config));
178
179 VideoSendStream::Config send_config = GetSendTestConfig(call.get());
180 send_config.encoder = &encoder;
181 send_config.rtp.extensions.push_back(
182 RtpExtension("toffset", kTOffsetExtensionId));
183
184 RunSendTest(call.get(), send_config, &observer);
185}
186
pbos@webrtc.orgdf531a22013-09-10 14:56:33 +0000187TEST_F(VideoSendStreamTest, RespondsToNack) {
188 class NackObserver : public SendTransportObserver, webrtc::Transport {
189 public:
190 NackObserver()
191 : SendTransportObserver(30 * 1000),
192 thread_(ThreadWrapper::CreateThread(NackProcess, this)),
193 send_call_receiver_(NULL),
194 send_count_(0),
195 ssrc_(0),
196 nacked_sequence_number_(0) {}
197
198 ~NackObserver() {
199 EXPECT_TRUE(thread_->Stop());
200 }
201
202 void SetReceiver(PacketReceiver* send_call_receiver) {
203 send_call_receiver_ = send_call_receiver;
204 }
205
206 // Sending NACKs must be done from a different "network" thread to prevent
207 // violating locking orders. With this no locks are held prior to inserting
208 // packets back into the sender.
209 static bool NackProcess(void* observer) {
210 return static_cast<NackObserver*>(observer)->SendNack();
211 }
212
213 bool SendNack() {
214 NullReceiveStatistics null_stats;
215 RTCPSender rtcp_sender(0, false, Clock::GetRealTimeClock(), &null_stats);
216 EXPECT_EQ(0, rtcp_sender.RegisterSendTransport(this));
217
218 rtcp_sender.SetRTCPStatus(kRtcpNonCompound);
219 rtcp_sender.SetRemoteSSRC(ssrc_);
220
221 RTCPSender::FeedbackState feedback_state;
222 EXPECT_EQ(0, rtcp_sender.SendRTCP(
223 feedback_state, kRtcpNack, 1, &nacked_sequence_number_));
224 return false;
225 }
226
227 virtual int SendPacket(int channel, const void* data, int len) OVERRIDE {
228 ADD_FAILURE()
229 << "This should never be reached. Only a NACK should be sent.";
230 return -1;
231 }
232
233 virtual int SendRTCPPacket(int channel,
234 const void* data,
235 int len) OVERRIDE {
236 EXPECT_TRUE(send_call_receiver_->DeliverPacket(
237 static_cast<const uint8_t*>(data), static_cast<size_t>(len)));
238 return len;
239 }
240
241 virtual bool SendRTP(const uint8_t* packet, size_t length) OVERRIDE {
242 EXPECT_TRUE(send_call_receiver_ != NULL);
243 RTPHeader header;
244 EXPECT_TRUE(
245 rtp_header_parser_->Parse(packet, static_cast<int>(length), &header));
246
247 // Nack second packet after receiving the third one.
248 if (++send_count_ == 3) {
249 ssrc_ = header.ssrc;
250 nacked_sequence_number_ = header.sequenceNumber - 1;
251 unsigned int id;
252 EXPECT_TRUE(thread_->Start(id));
253 }
254
255 if (header.sequenceNumber == nacked_sequence_number_)
256 send_test_complete_->Set();
257
258 return true;
259 }
260 private:
261 scoped_ptr<ThreadWrapper> thread_;
262 PacketReceiver* send_call_receiver_;
263 int send_count_;
264 uint32_t ssrc_;
265 uint16_t nacked_sequence_number_;
266 } observer;
267
268 Call::Config call_config(&observer);
269 scoped_ptr<Call> call(Call::Create(call_config));
270 observer.SetReceiver(call->Receiver());
271
272 VideoSendStream::Config send_config = GetSendTestConfig(call.get());
273 send_config.rtp.nack.rtp_history_ms = 1000;
274
275 RunSendTest(call.get(), send_config, &observer);
276}
277
pbos@webrtc.org119a1cc2013-08-20 13:14:07 +0000278} // namespace webrtc