blob: 68f96859e3cec622b5df839dd5549f3921710ece [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"
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +000011#include "webrtc/common_video/interface/i420_video_frame.h"
pbos@webrtc.org119a1cc2013-08-20 13:14:07 +000012#include "webrtc/modules/rtp_rtcp/interface/rtp_header_parser.h"
pbos@webrtc.orgdf531a22013-09-10 14:56:33 +000013#include "webrtc/modules/rtp_rtcp/source/rtcp_sender.h"
pbos@webrtc.org013d9942013-08-22 09:42:17 +000014#include "webrtc/modules/rtp_rtcp/source/rtcp_utility.h"
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +000015#include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
pbos@webrtc.org119a1cc2013-08-20 13:14:07 +000016#include "webrtc/system_wrappers/interface/event_wrapper.h"
17#include "webrtc/system_wrappers/interface/scoped_ptr.h"
pbos@webrtc.org29023282013-09-11 10:14:56 +000018#include "webrtc/system_wrappers/interface/sleep.h"
pbos@webrtc.orgdf531a22013-09-10 14:56:33 +000019#include "webrtc/system_wrappers/interface/thread_wrapper.h"
pbos@webrtc.org0e63e762013-09-20 11:56:26 +000020#include "webrtc/video_engine/internal/transport_adapter.h"
21#include "webrtc/video_engine/new_include/call.h"
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +000022#include "webrtc/video_engine/new_include/frame_callback.h"
pbos@webrtc.org0e63e762013-09-20 11:56:26 +000023#include "webrtc/video_engine/new_include/video_send_stream.h"
24#include "webrtc/video_engine/test/common/direct_transport.h"
pbos@webrtc.orgcb5118c2013-09-03 09:10:37 +000025#include "webrtc/video_engine/test/common/fake_encoder.h"
pbos@webrtc.org119a1cc2013-08-20 13:14:07 +000026#include "webrtc/video_engine/test/common/frame_generator_capturer.h"
27#include "webrtc/video_engine/test/common/null_transport.h"
pbos@webrtc.org119a1cc2013-08-20 13:14:07 +000028
29namespace webrtc {
30
pbos@webrtc.org119a1cc2013-08-20 13:14:07 +000031class SendTransportObserver : public test::NullTransport {
32 public:
33 explicit SendTransportObserver(unsigned long timeout_ms)
34 : rtp_header_parser_(RtpHeaderParser::Create()),
35 send_test_complete_(EventWrapper::Create()),
36 timeout_ms_(timeout_ms) {}
37
pbos@webrtc.org841c8a42013-09-09 15:04:25 +000038 EventTypeWrapper Wait() { return send_test_complete_->Wait(timeout_ms_); }
pbos@webrtc.org119a1cc2013-08-20 13:14:07 +000039
40 protected:
41 scoped_ptr<RtpHeaderParser> rtp_header_parser_;
42 scoped_ptr<EventWrapper> send_test_complete_;
43
44 private:
45 unsigned long timeout_ms_;
46};
47
pbos@webrtc.org013d9942013-08-22 09:42:17 +000048class VideoSendStreamTest : public ::testing::Test {
pbos@webrtc.orgcb5118c2013-09-03 09:10:37 +000049 public:
50 VideoSendStreamTest() : fake_encoder_(Clock::GetRealTimeClock()) {}
pbos@webrtc.org841c8a42013-09-09 15:04:25 +000051
pbos@webrtc.org013d9942013-08-22 09:42:17 +000052 protected:
pbos@webrtc.org841c8a42013-09-09 15:04:25 +000053 void RunSendTest(Call* call,
pbos@webrtc.org74fa4892013-08-23 09:19:30 +000054 const VideoSendStream::Config& config,
pbos@webrtc.org013d9942013-08-22 09:42:17 +000055 SendTransportObserver* observer) {
pbos@webrtc.org74fa4892013-08-23 09:19:30 +000056 VideoSendStream* send_stream = call->CreateSendStream(config);
pbos@webrtc.org013d9942013-08-22 09:42:17 +000057 scoped_ptr<test::FrameGeneratorCapturer> frame_generator_capturer(
58 test::FrameGeneratorCapturer::Create(
andresp@webrtc.orgab654952013-09-19 12:14:03 +000059 send_stream->Input(), 320, 240, 30, Clock::GetRealTimeClock()));
pbos@webrtc.org013d9942013-08-22 09:42:17 +000060 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.org0e63e762013-09-20 11:56:26 +000081 static const uint32_t kSendSsrc;
82 static const uint32_t kSendRtxSsrc;
83
pbos@webrtc.orgcb5118c2013-09-03 09:10:37 +000084 test::FakeEncoder fake_encoder_;
pbos@webrtc.org013d9942013-08-22 09:42:17 +000085};
86
87const uint32_t VideoSendStreamTest::kSendSsrc = 0xC0FFEE;
pbos@webrtc.org5860de02013-09-16 13:01:47 +000088const uint32_t VideoSendStreamTest::kSendRtxSsrc = 0xBADCAFE;
pbos@webrtc.org013d9942013-08-22 09:42:17 +000089
pbos@webrtc.org119a1cc2013-08-20 13:14:07 +000090TEST_F(VideoSendStreamTest, SendsSetSsrc) {
pbos@webrtc.org119a1cc2013-08-20 13:14:07 +000091 class SendSsrcObserver : public SendTransportObserver {
92 public:
93 SendSsrcObserver() : SendTransportObserver(30 * 1000) {}
94
95 virtual bool SendRTP(const uint8_t* packet, size_t length) OVERRIDE {
96 RTPHeader header;
97 EXPECT_TRUE(
98 rtp_header_parser_->Parse(packet, static_cast<int>(length), &header));
99
100 if (header.ssrc == kSendSsrc)
101 send_test_complete_->Set();
102
103 return true;
104 }
105 } observer;
106
pbos@webrtc.org841c8a42013-09-09 15:04:25 +0000107 Call::Config call_config(&observer);
108 scoped_ptr<Call> call(Call::Create(call_config));
pbos@webrtc.org119a1cc2013-08-20 13:14:07 +0000109
pbos@webrtc.orgcb5118c2013-09-03 09:10:37 +0000110 VideoSendStream::Config send_config = GetSendTestConfig(call.get());
sprang@webrtc.org5d957e22013-10-16 11:37:54 +0000111 send_config.rtp.max_packet_size = 128;
pbos@webrtc.org119a1cc2013-08-20 13:14:07 +0000112
pbos@webrtc.org013d9942013-08-22 09:42:17 +0000113 RunSendTest(call.get(), send_config, &observer);
114}
pbos@webrtc.org119a1cc2013-08-20 13:14:07 +0000115
pbos@webrtc.org013d9942013-08-22 09:42:17 +0000116TEST_F(VideoSendStreamTest, SupportsCName) {
117 static std::string kCName = "PjQatC14dGfbVwGPUOA9IH7RlsFDbWl4AhXEiDsBizo=";
118 class CNameObserver : public SendTransportObserver {
119 public:
120 CNameObserver() : SendTransportObserver(30 * 1000) {}
121
122 virtual bool SendRTCP(const uint8_t* packet, size_t length) OVERRIDE {
123 RTCPUtility::RTCPParserV2 parser(packet, length, true);
124 EXPECT_TRUE(parser.IsValid());
125
126 RTCPUtility::RTCPPacketTypes packet_type = parser.Begin();
127 while (packet_type != RTCPUtility::kRtcpNotValidCode) {
128 if (packet_type == RTCPUtility::kRtcpSdesChunkCode) {
129 EXPECT_EQ(parser.Packet().CName.CName, kCName);
130 send_test_complete_->Set();
131 }
132
133 packet_type = parser.Iterate();
134 }
135
136 return true;
137 }
138 } observer;
139
pbos@webrtc.org841c8a42013-09-09 15:04:25 +0000140 Call::Config call_config(&observer);
141 scoped_ptr<Call> call(Call::Create(call_config));
pbos@webrtc.org013d9942013-08-22 09:42:17 +0000142
pbos@webrtc.orgcb5118c2013-09-03 09:10:37 +0000143 VideoSendStream::Config send_config = GetSendTestConfig(call.get());
pbos@webrtc.org013d9942013-08-22 09:42:17 +0000144 send_config.rtp.c_name = kCName;
145
146 RunSendTest(call.get(), send_config, &observer);
pbos@webrtc.org119a1cc2013-08-20 13:14:07 +0000147}
148
pbos@webrtc.org5c678ea2013-09-11 19:00:39 +0000149TEST_F(VideoSendStreamTest, SupportsAbsoluteSendTime) {
150 static const uint8_t kAbsSendTimeExtensionId = 13;
151 class AbsoluteSendTimeObserver : public SendTransportObserver {
152 public:
153 AbsoluteSendTimeObserver() : SendTransportObserver(30 * 1000) {
154 EXPECT_TRUE(rtp_header_parser_->RegisterRtpHeaderExtension(
155 kRtpExtensionAbsoluteSendTime, kAbsSendTimeExtensionId));
156 }
157
158 virtual bool SendRTP(const uint8_t* packet, size_t length) OVERRIDE {
159 RTPHeader header;
160 EXPECT_TRUE(
161 rtp_header_parser_->Parse(packet, static_cast<int>(length), &header));
162
163 if (header.extension.absoluteSendTime > 0)
164 send_test_complete_->Set();
165
166 return true;
167 }
168 } observer;
169
170 Call::Config call_config(&observer);
171 scoped_ptr<Call> call(Call::Create(call_config));
172
173 VideoSendStream::Config send_config = GetSendTestConfig(call.get());
174 send_config.rtp.extensions.push_back(
175 RtpExtension("abs-send-time", kAbsSendTimeExtensionId));
176
177 RunSendTest(call.get(), send_config, &observer);
178}
179
pbos@webrtc.org29023282013-09-11 10:14:56 +0000180TEST_F(VideoSendStreamTest, SupportsTransmissionTimeOffset) {
181 static const uint8_t kTOffsetExtensionId = 13;
182 class DelayedEncoder : public test::FakeEncoder {
183 public:
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000184 explicit DelayedEncoder(Clock* clock) : test::FakeEncoder(clock) {}
pbos@webrtc.org29023282013-09-11 10:14:56 +0000185 virtual int32_t Encode(
186 const I420VideoFrame& input_image,
187 const CodecSpecificInfo* codec_specific_info,
188 const std::vector<VideoFrameType>* frame_types) OVERRIDE {
189 // A delay needs to be introduced to assure that we get a timestamp
190 // offset.
191 SleepMs(5);
192 return FakeEncoder::Encode(input_image, codec_specific_info, frame_types);
193 }
194 } encoder(Clock::GetRealTimeClock());
195
196 class TransmissionTimeOffsetObserver : public SendTransportObserver {
197 public:
198 TransmissionTimeOffsetObserver() : SendTransportObserver(30 * 1000) {
199 EXPECT_TRUE(rtp_header_parser_->RegisterRtpHeaderExtension(
200 kRtpExtensionTransmissionTimeOffset, kTOffsetExtensionId));
201 }
202
203 virtual bool SendRTP(const uint8_t* packet, size_t length) OVERRIDE {
204 RTPHeader header;
205 EXPECT_TRUE(
206 rtp_header_parser_->Parse(packet, static_cast<int>(length), &header));
207
208 EXPECT_GT(header.extension.transmissionTimeOffset, 0);
209 send_test_complete_->Set();
210
211 return true;
212 }
213 } observer;
214
215 Call::Config call_config(&observer);
216 scoped_ptr<Call> call(Call::Create(call_config));
217
218 VideoSendStream::Config send_config = GetSendTestConfig(call.get());
219 send_config.encoder = &encoder;
220 send_config.rtp.extensions.push_back(
221 RtpExtension("toffset", kTOffsetExtensionId));
222
223 RunSendTest(call.get(), send_config, &observer);
224}
225
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000226class FakeReceiveStatistics : public NullReceiveStatistics {
pbos@webrtc.org0e63e762013-09-20 11:56:26 +0000227 public:
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000228 FakeReceiveStatistics(uint32_t send_ssrc,
229 uint32_t last_sequence_number,
230 uint32_t cumulative_lost,
231 uint8_t fraction_lost)
pbos@webrtc.org0e63e762013-09-20 11:56:26 +0000232 : lossy_stats_(new LossyStatistician(last_sequence_number,
233 cumulative_lost,
234 fraction_lost)) {
235 stats_map_[send_ssrc] = lossy_stats_.get();
236 }
237
238 virtual StatisticianMap GetActiveStatisticians() const OVERRIDE {
239 return stats_map_;
240 }
241
242 virtual StreamStatistician* GetStatistician(uint32_t ssrc) const OVERRIDE {
243 return lossy_stats_.get();
244 }
245
246 private:
247 class LossyStatistician : public StreamStatistician {
248 public:
249 LossyStatistician(uint32_t extended_max_sequence_number,
250 uint32_t cumulative_lost,
251 uint8_t fraction_lost) {
252 stats_.fraction_lost = fraction_lost;
253 stats_.cumulative_lost = cumulative_lost;
254 stats_.extended_max_sequence_number = extended_max_sequence_number;
255 }
256 virtual bool GetStatistics(Statistics* statistics, bool reset) OVERRIDE {
257 *statistics = stats_;
258 return true;
259 }
260 virtual void GetDataCounters(uint32_t* bytes_received,
261 uint32_t* packets_received) const OVERRIDE {
262 *bytes_received = 0;
263 *packets_received = 0;
264 }
265 virtual uint32_t BitrateReceived() const OVERRIDE { return 0; }
266 virtual void ResetStatistics() OVERRIDE {}
267 virtual bool IsRetransmitOfOldPacket(const RTPHeader& header,
268 int min_rtt) const OVERRIDE {
269 return false;
270 }
271
272 virtual bool IsPacketInOrder(uint16_t sequence_number) const OVERRIDE {
273 return true;
274 }
275 Statistics stats_;
276 };
277
278 scoped_ptr<LossyStatistician> lossy_stats_;
279 StatisticianMap stats_map_;
280};
281
282TEST_F(VideoSendStreamTest, SupportsFec) {
283 static const int kRedPayloadType = 118;
284 static const int kUlpfecPayloadType = 119;
285 class FecObserver : public SendTransportObserver {
286 public:
287 FecObserver()
288 : SendTransportObserver(30 * 1000),
289 transport_adapter_(&transport_),
290 send_count_(0),
291 received_media_(false),
292 received_fec_(false) {}
293
294 void SetReceiver(PacketReceiver* receiver) {
295 transport_.SetReceiver(receiver);
296 }
297
298 virtual bool SendRTP(const uint8_t* packet, size_t length) OVERRIDE {
299 RTPHeader header;
300 EXPECT_TRUE(
301 rtp_header_parser_->Parse(packet, static_cast<int>(length), &header));
302
303 // Send lossy receive reports to trigger FEC enabling.
304 if (send_count_++ % 2 != 0) {
305 // Receive statistics reporting having lost 50% of the packets.
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000306 FakeReceiveStatistics lossy_receive_stats(
pbos@webrtc.org0e63e762013-09-20 11:56:26 +0000307 kSendSsrc, header.sequenceNumber, send_count_ / 2, 127);
308 RTCPSender rtcp_sender(
309 0, false, Clock::GetRealTimeClock(), &lossy_receive_stats);
310 EXPECT_EQ(0, rtcp_sender.RegisterSendTransport(&transport_adapter_));
311
312 rtcp_sender.SetRTCPStatus(kRtcpNonCompound);
313 rtcp_sender.SetRemoteSSRC(kSendSsrc);
314
315 RTCPSender::FeedbackState feedback_state;
316
317 EXPECT_EQ(0, rtcp_sender.SendRTCP(feedback_state, kRtcpRr));
318 }
319
320 EXPECT_EQ(kRedPayloadType, header.payloadType);
321
322 uint8_t encapsulated_payload_type = packet[header.headerLength];
323
324 if (encapsulated_payload_type == kUlpfecPayloadType) {
325 received_fec_ = true;
326 } else {
327 received_media_ = true;
328 }
329
330 if (received_media_ && received_fec_)
331 send_test_complete_->Set();
332
333 return true;
334 }
335
336 private:
337 internal::TransportAdapter transport_adapter_;
338 test::DirectTransport transport_;
339 int send_count_;
340 bool received_media_;
341 bool received_fec_;
342 } observer;
343
344 Call::Config call_config(&observer);
345 scoped_ptr<Call> call(Call::Create(call_config));
346
347 observer.SetReceiver(call->Receiver());
348
349 VideoSendStream::Config send_config = GetSendTestConfig(call.get());
350 send_config.rtp.fec.red_payload_type = kRedPayloadType;
351 send_config.rtp.fec.ulpfec_payload_type = kUlpfecPayloadType;
352
353 RunSendTest(call.get(), send_config, &observer);
354}
355
pbos@webrtc.org5860de02013-09-16 13:01:47 +0000356void VideoSendStreamTest::TestNackRetransmission(uint32_t retransmit_ssrc) {
pbos@webrtc.org0e63e762013-09-20 11:56:26 +0000357 class NackObserver : public SendTransportObserver {
pbos@webrtc.orgdf531a22013-09-10 14:56:33 +0000358 public:
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000359 explicit NackObserver(uint32_t retransmit_ssrc)
pbos@webrtc.orgdf531a22013-09-10 14:56:33 +0000360 : SendTransportObserver(30 * 1000),
pbos@webrtc.org0e63e762013-09-20 11:56:26 +0000361 transport_adapter_(&transport_),
pbos@webrtc.orgdf531a22013-09-10 14:56:33 +0000362 send_count_(0),
pbos@webrtc.org5860de02013-09-16 13:01:47 +0000363 retransmit_ssrc_(retransmit_ssrc),
pbos@webrtc.orgdf531a22013-09-10 14:56:33 +0000364 nacked_sequence_number_(0) {}
365
pbos@webrtc.org0e63e762013-09-20 11:56:26 +0000366 void SetReceiver(PacketReceiver* receiver) {
367 transport_.SetReceiver(receiver);
pbos@webrtc.orgdf531a22013-09-10 14:56:33 +0000368 }
369
370 virtual bool SendRTP(const uint8_t* packet, size_t length) OVERRIDE {
pbos@webrtc.orgdf531a22013-09-10 14:56:33 +0000371 RTPHeader header;
372 EXPECT_TRUE(
373 rtp_header_parser_->Parse(packet, static_cast<int>(length), &header));
374
375 // Nack second packet after receiving the third one.
376 if (++send_count_ == 3) {
pbos@webrtc.orgdf531a22013-09-10 14:56:33 +0000377 nacked_sequence_number_ = header.sequenceNumber - 1;
pbos@webrtc.org0e63e762013-09-20 11:56:26 +0000378 NullReceiveStatistics null_stats;
379 RTCPSender rtcp_sender(
380 0, false, Clock::GetRealTimeClock(), &null_stats);
381 EXPECT_EQ(0, rtcp_sender.RegisterSendTransport(&transport_adapter_));
382
383 rtcp_sender.SetRTCPStatus(kRtcpNonCompound);
384 rtcp_sender.SetRemoteSSRC(kSendSsrc);
385
386 RTCPSender::FeedbackState feedback_state;
387
388 EXPECT_EQ(0,
389 rtcp_sender.SendRTCP(
390 feedback_state, kRtcpNack, 1, &nacked_sequence_number_));
pbos@webrtc.orgdf531a22013-09-10 14:56:33 +0000391 }
392
pbos@webrtc.org5860de02013-09-16 13:01:47 +0000393 uint16_t sequence_number = header.sequenceNumber;
394
395 if (header.ssrc == retransmit_ssrc_ && retransmit_ssrc_ != kSendSsrc) {
396 // Not kSendSsrc, assume correct RTX packet. Extract sequence number.
397 const uint8_t* rtx_header = packet + header.headerLength;
398 sequence_number = (rtx_header[0] << 8) + rtx_header[1];
399 }
400
401 if (sequence_number == nacked_sequence_number_) {
402 EXPECT_EQ(retransmit_ssrc_, header.ssrc);
pbos@webrtc.orgdf531a22013-09-10 14:56:33 +0000403 send_test_complete_->Set();
pbos@webrtc.org5860de02013-09-16 13:01:47 +0000404 }
pbos@webrtc.orgdf531a22013-09-10 14:56:33 +0000405
406 return true;
407 }
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000408
pbos@webrtc.orgdf531a22013-09-10 14:56:33 +0000409 private:
pbos@webrtc.org0e63e762013-09-20 11:56:26 +0000410 internal::TransportAdapter transport_adapter_;
411 test::DirectTransport transport_;
pbos@webrtc.orgdf531a22013-09-10 14:56:33 +0000412 int send_count_;
pbos@webrtc.org5860de02013-09-16 13:01:47 +0000413 uint32_t retransmit_ssrc_;
pbos@webrtc.orgdf531a22013-09-10 14:56:33 +0000414 uint16_t nacked_sequence_number_;
pbos@webrtc.org5860de02013-09-16 13:01:47 +0000415 } observer(retransmit_ssrc);
pbos@webrtc.orgdf531a22013-09-10 14:56:33 +0000416
417 Call::Config call_config(&observer);
418 scoped_ptr<Call> call(Call::Create(call_config));
419 observer.SetReceiver(call->Receiver());
420
421 VideoSendStream::Config send_config = GetSendTestConfig(call.get());
422 send_config.rtp.nack.rtp_history_ms = 1000;
pbos@webrtc.org5860de02013-09-16 13:01:47 +0000423 if (retransmit_ssrc != kSendSsrc)
424 send_config.rtp.rtx.ssrcs.push_back(retransmit_ssrc);
pbos@webrtc.orgdf531a22013-09-10 14:56:33 +0000425
426 RunSendTest(call.get(), send_config, &observer);
427}
428
pbos@webrtc.org5860de02013-09-16 13:01:47 +0000429TEST_F(VideoSendStreamTest, RetransmitsNack) {
430 // Normal NACKs should use the send SSRC.
431 TestNackRetransmission(kSendSsrc);
432}
433
434TEST_F(VideoSendStreamTest, RetransmitsNackOverRtx) {
435 // NACKs over RTX should use a separate SSRC.
436 TestNackRetransmission(kSendRtxSsrc);
437}
438
sprang@webrtc.org5d957e22013-10-16 11:37:54 +0000439TEST_F(VideoSendStreamTest, MaxPacketSize) {
440 class PacketSizeObserver : public SendTransportObserver {
441 public:
442 PacketSizeObserver(size_t max_length) : SendTransportObserver(30 * 1000),
443 max_length_(max_length), accumulated_size_(0) {}
444
445 virtual bool SendRTP(const uint8_t* packet, size_t length) OVERRIDE {
446 RTPHeader header;
447 EXPECT_TRUE(
448 rtp_header_parser_->Parse(packet, static_cast<int>(length), &header));
449
sprang@webrtc.org25fce9a2013-10-16 13:29:14 +0000450 EXPECT_LE(length, max_length_);
sprang@webrtc.org5d957e22013-10-16 11:37:54 +0000451
452 accumulated_size_ += length;
453
454 // Marker bit set indicates last fragment of a packet
455 if (header.markerBit) {
456 if (accumulated_size_ + length > max_length_) {
457 // The packet was fragmented, total size was larger than max size,
458 // but size of individual fragments were within size limit => pass!
459 send_test_complete_->Set();
460 }
461 accumulated_size_ = 0; // Last fragment, reset packet size
462 }
463
464 return true;
465 }
466
467 private:
468 size_t max_length_;
469 size_t accumulated_size_;
470 };
471
472 static const uint32_t kMaxPacketSize = 128;
473
474 PacketSizeObserver observer(kMaxPacketSize);
475 Call::Config call_config(&observer);
476 scoped_ptr<Call> call(Call::Create(call_config));
477
478 VideoSendStream::Config send_config = GetSendTestConfig(call.get());
479 send_config.rtp.max_packet_size = kMaxPacketSize;
480
481 RunSendTest(call.get(), send_config, &observer);
482}
483
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +0000484// The test will go through a number of phases.
485// 1. Start sending packets.
486// 2. As soon as the RTP stream has been detected, signal a low REMB value to
487// activate the auto muter.
488// 3. Wait until |kMuteTimeFrames| have been captured without seeing any RTP
489// packets.
490// 4. Signal a high REMB and the wait for the RTP stream to start again.
491// When the stream is detected again, the test ends.
492TEST_F(VideoSendStreamTest, AutoMute) {
493 static const int kMuteTimeFrames = 60; // Mute for 2 seconds @ 30 fps.
494 static const int kMuteThresholdBps = 70000;
495 static const int kMuteWindowBps = 10000;
496 // Let the low REMB value be 10 kbps lower than the muter threshold, and the
497 // high REMB value be 5 kbps higher than the re-enabling threshold.
498 static const int kLowRembBps = kMuteThresholdBps - 10000;
499 static const int kHighRembBps = kMuteThresholdBps + kMuteWindowBps + 5000;
500
501 class RembObserver : public SendTransportObserver, public I420FrameCallback {
502 public:
503 RembObserver()
504 : SendTransportObserver(30 * 1000), // Timeout after 30 seconds.
505 transport_adapter_(&transport_),
506 clock_(Clock::GetRealTimeClock()),
507 test_state_(kBeforeMute),
508 rtp_count_(0),
509 last_sequence_number_(0),
510 mute_frame_count_(0),
511 crit_sect_(CriticalSectionWrapper::CreateCriticalSection()) {}
512
513 void SetReceiver(PacketReceiver* receiver) {
514 transport_.SetReceiver(receiver);
515 }
516
517 virtual bool SendRTCP(const uint8_t* packet, size_t length) OVERRIDE {
518 // Receive statistics reporting having lost 0% of the packets.
519 // This is needed for the send-side bitrate controller to work properly.
520 CriticalSectionScoped lock(crit_sect_.get());
521 SendRtcpFeedback(0); // REMB is only sent if value is > 0.
522 return true;
523 }
524
525 virtual bool SendRTP(const uint8_t* packet, size_t length) OVERRIDE {
526 CriticalSectionScoped lock(crit_sect_.get());
527 ++rtp_count_;
528 RTPHeader header;
529 EXPECT_TRUE(
530 rtp_header_parser_->Parse(packet, static_cast<int>(length), &header));
531 last_sequence_number_ = header.sequenceNumber;
532
533 if (test_state_ == kBeforeMute) {
534 // The stream has started. Try to mute it.
535 SendRtcpFeedback(kLowRembBps);
536 test_state_ = kDuringMute;
537 } else if (test_state_ == kDuringMute) {
538 mute_frame_count_ = 0;
539 } else if (test_state_ == kWaitingForPacket) {
540 send_test_complete_->Set();
541 }
542
543 return true;
544 }
545
546 // This method implements the I420FrameCallback.
547 void FrameCallback(I420VideoFrame* video_frame) OVERRIDE {
548 CriticalSectionScoped lock(crit_sect_.get());
549 if (test_state_ == kDuringMute && ++mute_frame_count_ > kMuteTimeFrames) {
550 SendRtcpFeedback(kHighRembBps);
551 test_state_ = kWaitingForPacket;
552 }
553 }
554
555 private:
556 enum TestState {
557 kBeforeMute,
558 kDuringMute,
559 kWaitingForPacket,
560 kAfterMute
561 };
562
563 virtual void SendRtcpFeedback(int remb_value) {
564 FakeReceiveStatistics receive_stats(
565 kSendSsrc, last_sequence_number_, rtp_count_, 0);
566 RTCPSender rtcp_sender(0, false, clock_, &receive_stats);
567 EXPECT_EQ(0, rtcp_sender.RegisterSendTransport(&transport_adapter_));
568
569 rtcp_sender.SetRTCPStatus(kRtcpNonCompound);
570 rtcp_sender.SetRemoteSSRC(kSendSsrc);
571 if (remb_value > 0) {
572 rtcp_sender.SetREMBStatus(true);
573 rtcp_sender.SetREMBData(remb_value, 0, NULL);
574 }
575 RTCPSender::FeedbackState feedback_state;
576 EXPECT_EQ(0, rtcp_sender.SendRTCP(feedback_state, kRtcpRr));
577 }
578
579 internal::TransportAdapter transport_adapter_;
580 test::DirectTransport transport_;
581 Clock* clock_;
582 TestState test_state_;
583 int rtp_count_;
584 int last_sequence_number_;
585 int mute_frame_count_;
586 scoped_ptr<CriticalSectionWrapper> crit_sect_;
587 } observer;
588
589 Call::Config call_config(&observer);
590 scoped_ptr<Call> call(Call::Create(call_config));
591 observer.SetReceiver(call->Receiver());
592
593 VideoSendStream::Config send_config = GetSendTestConfig(call.get());
594 send_config.rtp.nack.rtp_history_ms = 1000;
595 send_config.auto_muter.threshold_bps = kMuteThresholdBps;
596 send_config.auto_muter.window_bps = kMuteWindowBps;
597 send_config.pre_encode_callback = &observer;
598
599 RunSendTest(call.get(), send_config, &observer);
600}
601
pbos@webrtc.org119a1cc2013-08-20 13:14:07 +0000602} // namespace webrtc