blob: 2772104b4c615c1455d4aaf84da3dde9a4e959df [file] [log] [blame]
pbos@webrtc.org8a9739d2013-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 */
henrik.lundin@webrtc.orgd4ec1f52013-10-28 10:16:14 +000010#include <algorithm> // max
11
pbos@webrtc.org8a9739d2013-08-20 13:14:07 +000012#include "testing/gtest/include/gtest/gtest.h"
henrik.lundin@webrtc.orgce21c822013-10-23 11:04:57 +000013#include "webrtc/common_video/interface/i420_video_frame.h"
pbos@webrtc.org8a9739d2013-08-20 13:14:07 +000014#include "webrtc/modules/rtp_rtcp/interface/rtp_header_parser.h"
pbos@webrtc.orgaf730832013-09-10 14:56:33 +000015#include "webrtc/modules/rtp_rtcp/source/rtcp_sender.h"
pbos@webrtc.orgdebc6722013-08-22 09:42:17 +000016#include "webrtc/modules/rtp_rtcp/source/rtcp_utility.h"
henrik.lundin@webrtc.orgce21c822013-10-23 11:04:57 +000017#include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
pbos@webrtc.org8a9739d2013-08-20 13:14:07 +000018#include "webrtc/system_wrappers/interface/event_wrapper.h"
19#include "webrtc/system_wrappers/interface/scoped_ptr.h"
pbos@webrtc.org905cebd2013-09-11 10:14:56 +000020#include "webrtc/system_wrappers/interface/sleep.h"
pbos@webrtc.orgaf730832013-09-10 14:56:33 +000021#include "webrtc/system_wrappers/interface/thread_wrapper.h"
pbos@webrtc.orgaa693dd2013-09-20 11:56:26 +000022#include "webrtc/video_engine/internal/transport_adapter.h"
23#include "webrtc/video_engine/new_include/call.h"
henrik.lundin@webrtc.orgce21c822013-10-23 11:04:57 +000024#include "webrtc/video_engine/new_include/frame_callback.h"
pbos@webrtc.orgaa693dd2013-09-20 11:56:26 +000025#include "webrtc/video_engine/new_include/video_send_stream.h"
26#include "webrtc/video_engine/test/common/direct_transport.h"
pbos@webrtc.org43ec3572013-09-03 09:10:37 +000027#include "webrtc/video_engine/test/common/fake_encoder.h"
pbos@webrtc.org8a9739d2013-08-20 13:14:07 +000028#include "webrtc/video_engine/test/common/frame_generator_capturer.h"
29#include "webrtc/video_engine/test/common/null_transport.h"
pbos@webrtc.org8a9739d2013-08-20 13:14:07 +000030
31namespace webrtc {
32
pbos@webrtc.org8a9739d2013-08-20 13:14:07 +000033class SendTransportObserver : public test::NullTransport {
34 public:
35 explicit SendTransportObserver(unsigned long timeout_ms)
36 : rtp_header_parser_(RtpHeaderParser::Create()),
37 send_test_complete_(EventWrapper::Create()),
38 timeout_ms_(timeout_ms) {}
39
pbos@webrtc.orgfdc43522013-09-09 15:04:25 +000040 EventTypeWrapper Wait() { return send_test_complete_->Wait(timeout_ms_); }
pbos@webrtc.org8a9739d2013-08-20 13:14:07 +000041
42 protected:
43 scoped_ptr<RtpHeaderParser> rtp_header_parser_;
44 scoped_ptr<EventWrapper> send_test_complete_;
45
46 private:
47 unsigned long timeout_ms_;
48};
49
pbos@webrtc.orgdebc6722013-08-22 09:42:17 +000050class VideoSendStreamTest : public ::testing::Test {
pbos@webrtc.org43ec3572013-09-03 09:10:37 +000051 public:
52 VideoSendStreamTest() : fake_encoder_(Clock::GetRealTimeClock()) {}
pbos@webrtc.orgfdc43522013-09-09 15:04:25 +000053
pbos@webrtc.orgdebc6722013-08-22 09:42:17 +000054 protected:
pbos@webrtc.orgfdc43522013-09-09 15:04:25 +000055 void RunSendTest(Call* call,
pbos@webrtc.orgd8e92c92013-08-23 09:19:30 +000056 const VideoSendStream::Config& config,
pbos@webrtc.orgdebc6722013-08-22 09:42:17 +000057 SendTransportObserver* observer) {
pbos@webrtc.orgd8e92c92013-08-23 09:19:30 +000058 VideoSendStream* send_stream = call->CreateSendStream(config);
pbos@webrtc.orgdebc6722013-08-22 09:42:17 +000059 scoped_ptr<test::FrameGeneratorCapturer> frame_generator_capturer(
60 test::FrameGeneratorCapturer::Create(
andresp@webrtc.org9612f5a2013-09-19 12:14:03 +000061 send_stream->Input(), 320, 240, 30, Clock::GetRealTimeClock()));
pbos@webrtc.orgdebc6722013-08-22 09:42:17 +000062 send_stream->StartSend();
63 frame_generator_capturer->Start();
64
65 EXPECT_EQ(kEventSignaled, observer->Wait());
66
67 frame_generator_capturer->Stop();
68 send_stream->StopSend();
69 call->DestroySendStream(send_stream);
70 }
pbos@webrtc.org43ec3572013-09-03 09:10:37 +000071
pbos@webrtc.orgfdc43522013-09-09 15:04:25 +000072 VideoSendStream::Config GetSendTestConfig(Call* call) {
pbos@webrtc.org43ec3572013-09-03 09:10:37 +000073 VideoSendStream::Config config = call->GetDefaultSendConfig();
74 config.encoder = &fake_encoder_;
75 config.internal_source = false;
pbos@webrtc.orgaf730832013-09-10 14:56:33 +000076 config.rtp.ssrcs.push_back(kSendSsrc);
pbos@webrtc.org0ee03f92013-09-09 08:26:30 +000077 test::FakeEncoder::SetCodecSettings(&config.codec, 1);
pbos@webrtc.org43ec3572013-09-03 09:10:37 +000078 return config;
79 }
80
pbos@webrtc.orgf952fce2013-09-16 13:01:47 +000081 void TestNackRetransmission(uint32_t retransmit_ssrc);
82
pbos@webrtc.orgaa693dd2013-09-20 11:56:26 +000083 static const uint32_t kSendSsrc;
84 static const uint32_t kSendRtxSsrc;
85
pbos@webrtc.org43ec3572013-09-03 09:10:37 +000086 test::FakeEncoder fake_encoder_;
pbos@webrtc.orgdebc6722013-08-22 09:42:17 +000087};
88
89const uint32_t VideoSendStreamTest::kSendSsrc = 0xC0FFEE;
pbos@webrtc.orgf952fce2013-09-16 13:01:47 +000090const uint32_t VideoSendStreamTest::kSendRtxSsrc = 0xBADCAFE;
pbos@webrtc.orgdebc6722013-08-22 09:42:17 +000091
pbos@webrtc.org8a9739d2013-08-20 13:14:07 +000092TEST_F(VideoSendStreamTest, SendsSetSsrc) {
pbos@webrtc.org8a9739d2013-08-20 13:14:07 +000093 class SendSsrcObserver : public SendTransportObserver {
94 public:
95 SendSsrcObserver() : SendTransportObserver(30 * 1000) {}
96
97 virtual bool SendRTP(const uint8_t* packet, size_t length) OVERRIDE {
98 RTPHeader header;
99 EXPECT_TRUE(
100 rtp_header_parser_->Parse(packet, static_cast<int>(length), &header));
101
102 if (header.ssrc == kSendSsrc)
103 send_test_complete_->Set();
104
105 return true;
106 }
107 } observer;
108
pbos@webrtc.orgfdc43522013-09-09 15:04:25 +0000109 Call::Config call_config(&observer);
110 scoped_ptr<Call> call(Call::Create(call_config));
pbos@webrtc.org8a9739d2013-08-20 13:14:07 +0000111
pbos@webrtc.org43ec3572013-09-03 09:10:37 +0000112 VideoSendStream::Config send_config = GetSendTestConfig(call.get());
sprang@webrtc.org4fe85432013-10-16 11:37:54 +0000113 send_config.rtp.max_packet_size = 128;
pbos@webrtc.org8a9739d2013-08-20 13:14:07 +0000114
pbos@webrtc.orgdebc6722013-08-22 09:42:17 +0000115 RunSendTest(call.get(), send_config, &observer);
116}
pbos@webrtc.org8a9739d2013-08-20 13:14:07 +0000117
pbos@webrtc.orgdebc6722013-08-22 09:42:17 +0000118TEST_F(VideoSendStreamTest, SupportsCName) {
119 static std::string kCName = "PjQatC14dGfbVwGPUOA9IH7RlsFDbWl4AhXEiDsBizo=";
120 class CNameObserver : public SendTransportObserver {
121 public:
122 CNameObserver() : SendTransportObserver(30 * 1000) {}
123
124 virtual bool SendRTCP(const uint8_t* packet, size_t length) OVERRIDE {
125 RTCPUtility::RTCPParserV2 parser(packet, length, true);
126 EXPECT_TRUE(parser.IsValid());
127
128 RTCPUtility::RTCPPacketTypes packet_type = parser.Begin();
129 while (packet_type != RTCPUtility::kRtcpNotValidCode) {
130 if (packet_type == RTCPUtility::kRtcpSdesChunkCode) {
131 EXPECT_EQ(parser.Packet().CName.CName, kCName);
132 send_test_complete_->Set();
133 }
134
135 packet_type = parser.Iterate();
136 }
137
138 return true;
139 }
140 } observer;
141
pbos@webrtc.orgfdc43522013-09-09 15:04:25 +0000142 Call::Config call_config(&observer);
143 scoped_ptr<Call> call(Call::Create(call_config));
pbos@webrtc.orgdebc6722013-08-22 09:42:17 +0000144
pbos@webrtc.org43ec3572013-09-03 09:10:37 +0000145 VideoSendStream::Config send_config = GetSendTestConfig(call.get());
pbos@webrtc.orgdebc6722013-08-22 09:42:17 +0000146 send_config.rtp.c_name = kCName;
147
148 RunSendTest(call.get(), send_config, &observer);
pbos@webrtc.org8a9739d2013-08-20 13:14:07 +0000149}
150
pbos@webrtc.orge22b7612013-09-11 19:00:39 +0000151TEST_F(VideoSendStreamTest, SupportsAbsoluteSendTime) {
152 static const uint8_t kAbsSendTimeExtensionId = 13;
153 class AbsoluteSendTimeObserver : public SendTransportObserver {
154 public:
155 AbsoluteSendTimeObserver() : SendTransportObserver(30 * 1000) {
156 EXPECT_TRUE(rtp_header_parser_->RegisterRtpHeaderExtension(
157 kRtpExtensionAbsoluteSendTime, kAbsSendTimeExtensionId));
158 }
159
160 virtual bool SendRTP(const uint8_t* packet, size_t length) OVERRIDE {
161 RTPHeader header;
162 EXPECT_TRUE(
163 rtp_header_parser_->Parse(packet, static_cast<int>(length), &header));
164
165 if (header.extension.absoluteSendTime > 0)
166 send_test_complete_->Set();
167
168 return true;
169 }
170 } observer;
171
172 Call::Config call_config(&observer);
173 scoped_ptr<Call> call(Call::Create(call_config));
174
175 VideoSendStream::Config send_config = GetSendTestConfig(call.get());
176 send_config.rtp.extensions.push_back(
177 RtpExtension("abs-send-time", kAbsSendTimeExtensionId));
178
179 RunSendTest(call.get(), send_config, &observer);
180}
181
pbos@webrtc.org905cebd2013-09-11 10:14:56 +0000182TEST_F(VideoSendStreamTest, SupportsTransmissionTimeOffset) {
183 static const uint8_t kTOffsetExtensionId = 13;
184 class DelayedEncoder : public test::FakeEncoder {
185 public:
henrik.lundin@webrtc.orgce21c822013-10-23 11:04:57 +0000186 explicit DelayedEncoder(Clock* clock) : test::FakeEncoder(clock) {}
pbos@webrtc.org905cebd2013-09-11 10:14:56 +0000187 virtual int32_t Encode(
188 const I420VideoFrame& input_image,
189 const CodecSpecificInfo* codec_specific_info,
190 const std::vector<VideoFrameType>* frame_types) OVERRIDE {
191 // A delay needs to be introduced to assure that we get a timestamp
192 // offset.
193 SleepMs(5);
194 return FakeEncoder::Encode(input_image, codec_specific_info, frame_types);
195 }
196 } encoder(Clock::GetRealTimeClock());
197
198 class TransmissionTimeOffsetObserver : public SendTransportObserver {
199 public:
200 TransmissionTimeOffsetObserver() : SendTransportObserver(30 * 1000) {
201 EXPECT_TRUE(rtp_header_parser_->RegisterRtpHeaderExtension(
202 kRtpExtensionTransmissionTimeOffset, kTOffsetExtensionId));
203 }
204
205 virtual bool SendRTP(const uint8_t* packet, size_t length) OVERRIDE {
206 RTPHeader header;
207 EXPECT_TRUE(
208 rtp_header_parser_->Parse(packet, static_cast<int>(length), &header));
209
210 EXPECT_GT(header.extension.transmissionTimeOffset, 0);
211 send_test_complete_->Set();
212
213 return true;
214 }
215 } observer;
216
217 Call::Config call_config(&observer);
218 scoped_ptr<Call> call(Call::Create(call_config));
219
220 VideoSendStream::Config send_config = GetSendTestConfig(call.get());
221 send_config.encoder = &encoder;
222 send_config.rtp.extensions.push_back(
223 RtpExtension("toffset", kTOffsetExtensionId));
224
225 RunSendTest(call.get(), send_config, &observer);
226}
227
henrik.lundin@webrtc.orgce21c822013-10-23 11:04:57 +0000228class FakeReceiveStatistics : public NullReceiveStatistics {
pbos@webrtc.orgaa693dd2013-09-20 11:56:26 +0000229 public:
henrik.lundin@webrtc.orgce21c822013-10-23 11:04:57 +0000230 FakeReceiveStatistics(uint32_t send_ssrc,
231 uint32_t last_sequence_number,
232 uint32_t cumulative_lost,
233 uint8_t fraction_lost)
pbos@webrtc.orgaa693dd2013-09-20 11:56:26 +0000234 : lossy_stats_(new LossyStatistician(last_sequence_number,
235 cumulative_lost,
236 fraction_lost)) {
237 stats_map_[send_ssrc] = lossy_stats_.get();
238 }
239
240 virtual StatisticianMap GetActiveStatisticians() const OVERRIDE {
241 return stats_map_;
242 }
243
244 virtual StreamStatistician* GetStatistician(uint32_t ssrc) const OVERRIDE {
245 return lossy_stats_.get();
246 }
247
248 private:
249 class LossyStatistician : public StreamStatistician {
250 public:
251 LossyStatistician(uint32_t extended_max_sequence_number,
252 uint32_t cumulative_lost,
253 uint8_t fraction_lost) {
254 stats_.fraction_lost = fraction_lost;
255 stats_.cumulative_lost = cumulative_lost;
256 stats_.extended_max_sequence_number = extended_max_sequence_number;
257 }
258 virtual bool GetStatistics(Statistics* statistics, bool reset) OVERRIDE {
259 *statistics = stats_;
260 return true;
261 }
262 virtual void GetDataCounters(uint32_t* bytes_received,
263 uint32_t* packets_received) const OVERRIDE {
264 *bytes_received = 0;
265 *packets_received = 0;
266 }
267 virtual uint32_t BitrateReceived() const OVERRIDE { return 0; }
268 virtual void ResetStatistics() OVERRIDE {}
269 virtual bool IsRetransmitOfOldPacket(const RTPHeader& header,
270 int min_rtt) const OVERRIDE {
271 return false;
272 }
273
274 virtual bool IsPacketInOrder(uint16_t sequence_number) const OVERRIDE {
275 return true;
276 }
277 Statistics stats_;
278 };
279
280 scoped_ptr<LossyStatistician> lossy_stats_;
281 StatisticianMap stats_map_;
282};
283
284TEST_F(VideoSendStreamTest, SupportsFec) {
285 static const int kRedPayloadType = 118;
286 static const int kUlpfecPayloadType = 119;
287 class FecObserver : public SendTransportObserver {
288 public:
289 FecObserver()
290 : SendTransportObserver(30 * 1000),
291 transport_adapter_(&transport_),
292 send_count_(0),
293 received_media_(false),
294 received_fec_(false) {}
295
296 void SetReceiver(PacketReceiver* receiver) {
297 transport_.SetReceiver(receiver);
298 }
299
300 virtual bool SendRTP(const uint8_t* packet, size_t length) OVERRIDE {
301 RTPHeader header;
302 EXPECT_TRUE(
303 rtp_header_parser_->Parse(packet, static_cast<int>(length), &header));
304
305 // Send lossy receive reports to trigger FEC enabling.
306 if (send_count_++ % 2 != 0) {
307 // Receive statistics reporting having lost 50% of the packets.
henrik.lundin@webrtc.orgce21c822013-10-23 11:04:57 +0000308 FakeReceiveStatistics lossy_receive_stats(
pbos@webrtc.orgaa693dd2013-09-20 11:56:26 +0000309 kSendSsrc, header.sequenceNumber, send_count_ / 2, 127);
310 RTCPSender rtcp_sender(
311 0, false, Clock::GetRealTimeClock(), &lossy_receive_stats);
312 EXPECT_EQ(0, rtcp_sender.RegisterSendTransport(&transport_adapter_));
313
314 rtcp_sender.SetRTCPStatus(kRtcpNonCompound);
315 rtcp_sender.SetRemoteSSRC(kSendSsrc);
316
317 RTCPSender::FeedbackState feedback_state;
318
319 EXPECT_EQ(0, rtcp_sender.SendRTCP(feedback_state, kRtcpRr));
320 }
321
322 EXPECT_EQ(kRedPayloadType, header.payloadType);
323
324 uint8_t encapsulated_payload_type = packet[header.headerLength];
325
326 if (encapsulated_payload_type == kUlpfecPayloadType) {
327 received_fec_ = true;
328 } else {
329 received_media_ = true;
330 }
331
332 if (received_media_ && received_fec_)
333 send_test_complete_->Set();
334
335 return true;
336 }
337
338 private:
339 internal::TransportAdapter transport_adapter_;
340 test::DirectTransport transport_;
341 int send_count_;
342 bool received_media_;
343 bool received_fec_;
344 } observer;
345
346 Call::Config call_config(&observer);
347 scoped_ptr<Call> call(Call::Create(call_config));
348
349 observer.SetReceiver(call->Receiver());
350
351 VideoSendStream::Config send_config = GetSendTestConfig(call.get());
352 send_config.rtp.fec.red_payload_type = kRedPayloadType;
353 send_config.rtp.fec.ulpfec_payload_type = kUlpfecPayloadType;
354
355 RunSendTest(call.get(), send_config, &observer);
356}
357
pbos@webrtc.orgf952fce2013-09-16 13:01:47 +0000358void VideoSendStreamTest::TestNackRetransmission(uint32_t retransmit_ssrc) {
pbos@webrtc.orgaa693dd2013-09-20 11:56:26 +0000359 class NackObserver : public SendTransportObserver {
pbos@webrtc.orgaf730832013-09-10 14:56:33 +0000360 public:
henrik.lundin@webrtc.orgce21c822013-10-23 11:04:57 +0000361 explicit NackObserver(uint32_t retransmit_ssrc)
pbos@webrtc.orgaf730832013-09-10 14:56:33 +0000362 : SendTransportObserver(30 * 1000),
pbos@webrtc.orgaa693dd2013-09-20 11:56:26 +0000363 transport_adapter_(&transport_),
pbos@webrtc.orgaf730832013-09-10 14:56:33 +0000364 send_count_(0),
pbos@webrtc.orgf952fce2013-09-16 13:01:47 +0000365 retransmit_ssrc_(retransmit_ssrc),
pbos@webrtc.orgaf730832013-09-10 14:56:33 +0000366 nacked_sequence_number_(0) {}
367
pbos@webrtc.orgaa693dd2013-09-20 11:56:26 +0000368 void SetReceiver(PacketReceiver* receiver) {
369 transport_.SetReceiver(receiver);
pbos@webrtc.orgaf730832013-09-10 14:56:33 +0000370 }
371
372 virtual bool SendRTP(const uint8_t* packet, size_t length) OVERRIDE {
pbos@webrtc.orgaf730832013-09-10 14:56:33 +0000373 RTPHeader header;
374 EXPECT_TRUE(
375 rtp_header_parser_->Parse(packet, static_cast<int>(length), &header));
376
377 // Nack second packet after receiving the third one.
378 if (++send_count_ == 3) {
pbos@webrtc.orgaf730832013-09-10 14:56:33 +0000379 nacked_sequence_number_ = header.sequenceNumber - 1;
pbos@webrtc.orgaa693dd2013-09-20 11:56:26 +0000380 NullReceiveStatistics null_stats;
381 RTCPSender rtcp_sender(
382 0, false, Clock::GetRealTimeClock(), &null_stats);
383 EXPECT_EQ(0, rtcp_sender.RegisterSendTransport(&transport_adapter_));
384
385 rtcp_sender.SetRTCPStatus(kRtcpNonCompound);
386 rtcp_sender.SetRemoteSSRC(kSendSsrc);
387
388 RTCPSender::FeedbackState feedback_state;
389
390 EXPECT_EQ(0,
391 rtcp_sender.SendRTCP(
392 feedback_state, kRtcpNack, 1, &nacked_sequence_number_));
pbos@webrtc.orgaf730832013-09-10 14:56:33 +0000393 }
394
pbos@webrtc.orgf952fce2013-09-16 13:01:47 +0000395 uint16_t sequence_number = header.sequenceNumber;
396
397 if (header.ssrc == retransmit_ssrc_ && retransmit_ssrc_ != kSendSsrc) {
398 // Not kSendSsrc, assume correct RTX packet. Extract sequence number.
399 const uint8_t* rtx_header = packet + header.headerLength;
400 sequence_number = (rtx_header[0] << 8) + rtx_header[1];
401 }
402
403 if (sequence_number == nacked_sequence_number_) {
404 EXPECT_EQ(retransmit_ssrc_, header.ssrc);
pbos@webrtc.orgaf730832013-09-10 14:56:33 +0000405 send_test_complete_->Set();
pbos@webrtc.orgf952fce2013-09-16 13:01:47 +0000406 }
pbos@webrtc.orgaf730832013-09-10 14:56:33 +0000407
408 return true;
409 }
henrik.lundin@webrtc.orgce21c822013-10-23 11:04:57 +0000410
pbos@webrtc.orgaf730832013-09-10 14:56:33 +0000411 private:
pbos@webrtc.orgaa693dd2013-09-20 11:56:26 +0000412 internal::TransportAdapter transport_adapter_;
413 test::DirectTransport transport_;
pbos@webrtc.orgaf730832013-09-10 14:56:33 +0000414 int send_count_;
pbos@webrtc.orgf952fce2013-09-16 13:01:47 +0000415 uint32_t retransmit_ssrc_;
pbos@webrtc.orgaf730832013-09-10 14:56:33 +0000416 uint16_t nacked_sequence_number_;
pbos@webrtc.orgf952fce2013-09-16 13:01:47 +0000417 } observer(retransmit_ssrc);
pbos@webrtc.orgaf730832013-09-10 14:56:33 +0000418
419 Call::Config call_config(&observer);
420 scoped_ptr<Call> call(Call::Create(call_config));
421 observer.SetReceiver(call->Receiver());
422
423 VideoSendStream::Config send_config = GetSendTestConfig(call.get());
424 send_config.rtp.nack.rtp_history_ms = 1000;
pbos@webrtc.orgf952fce2013-09-16 13:01:47 +0000425 if (retransmit_ssrc != kSendSsrc)
426 send_config.rtp.rtx.ssrcs.push_back(retransmit_ssrc);
pbos@webrtc.orgaf730832013-09-10 14:56:33 +0000427
428 RunSendTest(call.get(), send_config, &observer);
429}
430
pbos@webrtc.orgf952fce2013-09-16 13:01:47 +0000431TEST_F(VideoSendStreamTest, RetransmitsNack) {
432 // Normal NACKs should use the send SSRC.
433 TestNackRetransmission(kSendSsrc);
434}
435
436TEST_F(VideoSendStreamTest, RetransmitsNackOverRtx) {
437 // NACKs over RTX should use a separate SSRC.
438 TestNackRetransmission(kSendRtxSsrc);
439}
440
sprang@webrtc.org4fe85432013-10-16 11:37:54 +0000441TEST_F(VideoSendStreamTest, MaxPacketSize) {
442 class PacketSizeObserver : public SendTransportObserver {
443 public:
444 PacketSizeObserver(size_t max_length) : SendTransportObserver(30 * 1000),
445 max_length_(max_length), accumulated_size_(0) {}
446
447 virtual bool SendRTP(const uint8_t* packet, size_t length) OVERRIDE {
448 RTPHeader header;
449 EXPECT_TRUE(
450 rtp_header_parser_->Parse(packet, static_cast<int>(length), &header));
451
sprang@webrtc.org6133dd52013-10-16 13:29:14 +0000452 EXPECT_LE(length, max_length_);
sprang@webrtc.org4fe85432013-10-16 11:37:54 +0000453
454 accumulated_size_ += length;
455
456 // Marker bit set indicates last fragment of a packet
457 if (header.markerBit) {
458 if (accumulated_size_ + length > max_length_) {
459 // The packet was fragmented, total size was larger than max size,
460 // but size of individual fragments were within size limit => pass!
461 send_test_complete_->Set();
462 }
463 accumulated_size_ = 0; // Last fragment, reset packet size
464 }
465
466 return true;
467 }
468
469 private:
470 size_t max_length_;
471 size_t accumulated_size_;
472 };
473
474 static const uint32_t kMaxPacketSize = 128;
475
476 PacketSizeObserver observer(kMaxPacketSize);
477 Call::Config call_config(&observer);
478 scoped_ptr<Call> call(Call::Create(call_config));
479
480 VideoSendStream::Config send_config = GetSendTestConfig(call.get());
481 send_config.rtp.max_packet_size = kMaxPacketSize;
482
483 RunSendTest(call.get(), send_config, &observer);
484}
485
henrik.lundin@webrtc.orgce21c822013-10-23 11:04:57 +0000486// The test will go through a number of phases.
487// 1. Start sending packets.
488// 2. As soon as the RTP stream has been detected, signal a low REMB value to
489// activate the auto muter.
490// 3. Wait until |kMuteTimeFrames| have been captured without seeing any RTP
491// packets.
492// 4. Signal a high REMB and the wait for the RTP stream to start again.
493// When the stream is detected again, the test ends.
494TEST_F(VideoSendStreamTest, AutoMute) {
495 static const int kMuteTimeFrames = 60; // Mute for 2 seconds @ 30 fps.
henrik.lundin@webrtc.orgce21c822013-10-23 11:04:57 +0000496
497 class RembObserver : public SendTransportObserver, public I420FrameCallback {
498 public:
499 RembObserver()
500 : SendTransportObserver(30 * 1000), // Timeout after 30 seconds.
501 transport_adapter_(&transport_),
502 clock_(Clock::GetRealTimeClock()),
503 test_state_(kBeforeMute),
504 rtp_count_(0),
505 last_sequence_number_(0),
506 mute_frame_count_(0),
henrik.lundin@webrtc.orgd4ec1f52013-10-28 10:16:14 +0000507 low_remb_bps_(0),
508 high_remb_bps_(0),
henrik.lundin@webrtc.orgce21c822013-10-23 11:04:57 +0000509 crit_sect_(CriticalSectionWrapper::CreateCriticalSection()) {}
510
511 void SetReceiver(PacketReceiver* receiver) {
512 transport_.SetReceiver(receiver);
513 }
514
515 virtual bool SendRTCP(const uint8_t* packet, size_t length) OVERRIDE {
516 // Receive statistics reporting having lost 0% of the packets.
517 // This is needed for the send-side bitrate controller to work properly.
518 CriticalSectionScoped lock(crit_sect_.get());
519 SendRtcpFeedback(0); // REMB is only sent if value is > 0.
520 return true;
521 }
522
523 virtual bool SendRTP(const uint8_t* packet, size_t length) OVERRIDE {
524 CriticalSectionScoped lock(crit_sect_.get());
525 ++rtp_count_;
526 RTPHeader header;
527 EXPECT_TRUE(
528 rtp_header_parser_->Parse(packet, static_cast<int>(length), &header));
529 last_sequence_number_ = header.sequenceNumber;
530
531 if (test_state_ == kBeforeMute) {
532 // The stream has started. Try to mute it.
henrik.lundin@webrtc.orgd4ec1f52013-10-28 10:16:14 +0000533 SendRtcpFeedback(low_remb_bps_);
henrik.lundin@webrtc.orgce21c822013-10-23 11:04:57 +0000534 test_state_ = kDuringMute;
535 } else if (test_state_ == kDuringMute) {
536 mute_frame_count_ = 0;
537 } else if (test_state_ == kWaitingForPacket) {
538 send_test_complete_->Set();
539 }
540
541 return true;
542 }
543
544 // This method implements the I420FrameCallback.
545 void FrameCallback(I420VideoFrame* video_frame) OVERRIDE {
546 CriticalSectionScoped lock(crit_sect_.get());
547 if (test_state_ == kDuringMute && ++mute_frame_count_ > kMuteTimeFrames) {
henrik.lundin@webrtc.orgd4ec1f52013-10-28 10:16:14 +0000548 SendRtcpFeedback(high_remb_bps_);
henrik.lundin@webrtc.orgce21c822013-10-23 11:04:57 +0000549 test_state_ = kWaitingForPacket;
550 }
551 }
552
henrik.lundin@webrtc.orgd4ec1f52013-10-28 10:16:14 +0000553 void set_low_remb_bps(int value) { low_remb_bps_ = value; }
554
555 void set_high_remb_bps(int value) { high_remb_bps_ = value; }
556
henrik.lundin@webrtc.orgce21c822013-10-23 11:04:57 +0000557 private:
558 enum TestState {
559 kBeforeMute,
560 kDuringMute,
561 kWaitingForPacket,
562 kAfterMute
563 };
564
565 virtual void SendRtcpFeedback(int remb_value) {
566 FakeReceiveStatistics receive_stats(
567 kSendSsrc, last_sequence_number_, rtp_count_, 0);
568 RTCPSender rtcp_sender(0, false, clock_, &receive_stats);
569 EXPECT_EQ(0, rtcp_sender.RegisterSendTransport(&transport_adapter_));
570
571 rtcp_sender.SetRTCPStatus(kRtcpNonCompound);
572 rtcp_sender.SetRemoteSSRC(kSendSsrc);
573 if (remb_value > 0) {
574 rtcp_sender.SetREMBStatus(true);
575 rtcp_sender.SetREMBData(remb_value, 0, NULL);
576 }
577 RTCPSender::FeedbackState feedback_state;
578 EXPECT_EQ(0, rtcp_sender.SendRTCP(feedback_state, kRtcpRr));
579 }
580
581 internal::TransportAdapter transport_adapter_;
582 test::DirectTransport transport_;
583 Clock* clock_;
584 TestState test_state_;
585 int rtp_count_;
586 int last_sequence_number_;
587 int mute_frame_count_;
henrik.lundin@webrtc.orgd4ec1f52013-10-28 10:16:14 +0000588 int low_remb_bps_;
589 int high_remb_bps_;
henrik.lundin@webrtc.orgce21c822013-10-23 11:04:57 +0000590 scoped_ptr<CriticalSectionWrapper> crit_sect_;
591 } observer;
592
593 Call::Config call_config(&observer);
594 scoped_ptr<Call> call(Call::Create(call_config));
595 observer.SetReceiver(call->Receiver());
596
597 VideoSendStream::Config send_config = GetSendTestConfig(call.get());
598 send_config.rtp.nack.rtp_history_ms = 1000;
henrik.lundin@webrtc.orgce21c822013-10-23 11:04:57 +0000599 send_config.pre_encode_callback = &observer;
henrik.lundin@webrtc.orgd4ec1f52013-10-28 10:16:14 +0000600 send_config.auto_mute = true;
601 unsigned int min_bitrate_bps =
602 send_config.codec.simulcastStream[0].minBitrate * 1000;
603 observer.set_low_remb_bps(min_bitrate_bps - 10000);
604 unsigned int threshold_window = std::max(min_bitrate_bps / 10, 10000u);
605 ASSERT_GT(send_config.codec.simulcastStream[0].maxBitrate * 1000,
606 min_bitrate_bps + threshold_window + 5000);
607 observer.set_high_remb_bps(min_bitrate_bps + threshold_window + 5000);
henrik.lundin@webrtc.orgce21c822013-10-23 11:04:57 +0000608
609 RunSendTest(call.get(), send_config, &observer);
610}
611
pbos@webrtc.org8a9739d2013-08-20 13:14:07 +0000612} // namespace webrtc