blob: 69923a704a2cb7754cd36caf940c482f03dec707 [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.org0e63e762013-09-20 11:56:26 +000018#include "webrtc/video_engine/internal/transport_adapter.h"
19#include "webrtc/video_engine/new_include/call.h"
20#include "webrtc/video_engine/new_include/video_send_stream.h"
21#include "webrtc/video_engine/test/common/direct_transport.h"
pbos@webrtc.orgcb5118c2013-09-03 09:10:37 +000022#include "webrtc/video_engine/test/common/fake_encoder.h"
pbos@webrtc.org119a1cc2013-08-20 13:14:07 +000023#include "webrtc/video_engine/test/common/frame_generator_capturer.h"
24#include "webrtc/video_engine/test/common/null_transport.h"
pbos@webrtc.org119a1cc2013-08-20 13:14:07 +000025
26namespace webrtc {
27
pbos@webrtc.org119a1cc2013-08-20 13:14:07 +000028class SendTransportObserver : public test::NullTransport {
29 public:
30 explicit SendTransportObserver(unsigned long timeout_ms)
31 : rtp_header_parser_(RtpHeaderParser::Create()),
32 send_test_complete_(EventWrapper::Create()),
33 timeout_ms_(timeout_ms) {}
34
pbos@webrtc.org841c8a42013-09-09 15:04:25 +000035 EventTypeWrapper Wait() { return send_test_complete_->Wait(timeout_ms_); }
pbos@webrtc.org119a1cc2013-08-20 13:14:07 +000036
37 protected:
38 scoped_ptr<RtpHeaderParser> rtp_header_parser_;
39 scoped_ptr<EventWrapper> send_test_complete_;
40
41 private:
42 unsigned long timeout_ms_;
43};
44
pbos@webrtc.org013d9942013-08-22 09:42:17 +000045class VideoSendStreamTest : public ::testing::Test {
pbos@webrtc.orgcb5118c2013-09-03 09:10:37 +000046 public:
47 VideoSendStreamTest() : fake_encoder_(Clock::GetRealTimeClock()) {}
pbos@webrtc.org841c8a42013-09-09 15:04:25 +000048
pbos@webrtc.org013d9942013-08-22 09:42:17 +000049 protected:
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.org0e63e762013-09-20 11:56:26 +000078 static const uint32_t kSendSsrc;
79 static const uint32_t kSendRtxSsrc;
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());
sprang@webrtc.org5d957e22013-10-16 11:37:54 +0000108 send_config.rtp.max_packet_size = 128;
pbos@webrtc.org119a1cc2013-08-20 13:14:07 +0000109
pbos@webrtc.org013d9942013-08-22 09:42:17 +0000110 RunSendTest(call.get(), send_config, &observer);
111}
pbos@webrtc.org119a1cc2013-08-20 13:14:07 +0000112
pbos@webrtc.org013d9942013-08-22 09:42:17 +0000113TEST_F(VideoSendStreamTest, SupportsCName) {
114 static std::string kCName = "PjQatC14dGfbVwGPUOA9IH7RlsFDbWl4AhXEiDsBizo=";
115 class CNameObserver : public SendTransportObserver {
116 public:
117 CNameObserver() : SendTransportObserver(30 * 1000) {}
118
119 virtual bool SendRTCP(const uint8_t* packet, size_t length) OVERRIDE {
120 RTCPUtility::RTCPParserV2 parser(packet, length, true);
121 EXPECT_TRUE(parser.IsValid());
122
123 RTCPUtility::RTCPPacketTypes packet_type = parser.Begin();
124 while (packet_type != RTCPUtility::kRtcpNotValidCode) {
125 if (packet_type == RTCPUtility::kRtcpSdesChunkCode) {
126 EXPECT_EQ(parser.Packet().CName.CName, kCName);
127 send_test_complete_->Set();
128 }
129
130 packet_type = parser.Iterate();
131 }
132
133 return true;
134 }
135 } observer;
136
pbos@webrtc.org841c8a42013-09-09 15:04:25 +0000137 Call::Config call_config(&observer);
138 scoped_ptr<Call> call(Call::Create(call_config));
pbos@webrtc.org013d9942013-08-22 09:42:17 +0000139
pbos@webrtc.orgcb5118c2013-09-03 09:10:37 +0000140 VideoSendStream::Config send_config = GetSendTestConfig(call.get());
pbos@webrtc.org013d9942013-08-22 09:42:17 +0000141 send_config.rtp.c_name = kCName;
142
143 RunSendTest(call.get(), send_config, &observer);
pbos@webrtc.org119a1cc2013-08-20 13:14:07 +0000144}
145
pbos@webrtc.org5c678ea2013-09-11 19:00:39 +0000146TEST_F(VideoSendStreamTest, SupportsAbsoluteSendTime) {
147 static const uint8_t kAbsSendTimeExtensionId = 13;
148 class AbsoluteSendTimeObserver : public SendTransportObserver {
149 public:
150 AbsoluteSendTimeObserver() : SendTransportObserver(30 * 1000) {
151 EXPECT_TRUE(rtp_header_parser_->RegisterRtpHeaderExtension(
152 kRtpExtensionAbsoluteSendTime, kAbsSendTimeExtensionId));
153 }
154
155 virtual bool SendRTP(const uint8_t* packet, size_t length) OVERRIDE {
156 RTPHeader header;
157 EXPECT_TRUE(
158 rtp_header_parser_->Parse(packet, static_cast<int>(length), &header));
159
160 if (header.extension.absoluteSendTime > 0)
161 send_test_complete_->Set();
162
163 return true;
164 }
165 } observer;
166
167 Call::Config call_config(&observer);
168 scoped_ptr<Call> call(Call::Create(call_config));
169
170 VideoSendStream::Config send_config = GetSendTestConfig(call.get());
171 send_config.rtp.extensions.push_back(
172 RtpExtension("abs-send-time", kAbsSendTimeExtensionId));
173
174 RunSendTest(call.get(), send_config, &observer);
175}
176
pbos@webrtc.org29023282013-09-11 10:14:56 +0000177TEST_F(VideoSendStreamTest, SupportsTransmissionTimeOffset) {
178 static const uint8_t kTOffsetExtensionId = 13;
179 class DelayedEncoder : public test::FakeEncoder {
180 public:
181 DelayedEncoder(Clock* clock) : test::FakeEncoder(clock) {}
182 virtual int32_t Encode(
183 const I420VideoFrame& input_image,
184 const CodecSpecificInfo* codec_specific_info,
185 const std::vector<VideoFrameType>* frame_types) OVERRIDE {
186 // A delay needs to be introduced to assure that we get a timestamp
187 // offset.
188 SleepMs(5);
189 return FakeEncoder::Encode(input_image, codec_specific_info, frame_types);
190 }
191 } encoder(Clock::GetRealTimeClock());
192
193 class TransmissionTimeOffsetObserver : public SendTransportObserver {
194 public:
195 TransmissionTimeOffsetObserver() : SendTransportObserver(30 * 1000) {
196 EXPECT_TRUE(rtp_header_parser_->RegisterRtpHeaderExtension(
197 kRtpExtensionTransmissionTimeOffset, kTOffsetExtensionId));
198 }
199
200 virtual bool SendRTP(const uint8_t* packet, size_t length) OVERRIDE {
201 RTPHeader header;
202 EXPECT_TRUE(
203 rtp_header_parser_->Parse(packet, static_cast<int>(length), &header));
204
205 EXPECT_GT(header.extension.transmissionTimeOffset, 0);
206 send_test_complete_->Set();
207
208 return true;
209 }
210 } observer;
211
212 Call::Config call_config(&observer);
213 scoped_ptr<Call> call(Call::Create(call_config));
214
215 VideoSendStream::Config send_config = GetSendTestConfig(call.get());
216 send_config.encoder = &encoder;
217 send_config.rtp.extensions.push_back(
218 RtpExtension("toffset", kTOffsetExtensionId));
219
220 RunSendTest(call.get(), send_config, &observer);
221}
222
pbos@webrtc.org0e63e762013-09-20 11:56:26 +0000223class LossyReceiveStatistics : public NullReceiveStatistics {
224 public:
225 LossyReceiveStatistics(uint32_t send_ssrc,
226 uint32_t last_sequence_number,
227 uint32_t cumulative_lost,
228 uint8_t fraction_lost)
229 : lossy_stats_(new LossyStatistician(last_sequence_number,
230 cumulative_lost,
231 fraction_lost)) {
232 stats_map_[send_ssrc] = lossy_stats_.get();
233 }
234
235 virtual StatisticianMap GetActiveStatisticians() const OVERRIDE {
236 return stats_map_;
237 }
238
239 virtual StreamStatistician* GetStatistician(uint32_t ssrc) const OVERRIDE {
240 return lossy_stats_.get();
241 }
242
243 private:
244 class LossyStatistician : public StreamStatistician {
245 public:
246 LossyStatistician(uint32_t extended_max_sequence_number,
247 uint32_t cumulative_lost,
248 uint8_t fraction_lost) {
249 stats_.fraction_lost = fraction_lost;
250 stats_.cumulative_lost = cumulative_lost;
251 stats_.extended_max_sequence_number = extended_max_sequence_number;
252 }
253 virtual bool GetStatistics(Statistics* statistics, bool reset) OVERRIDE {
254 *statistics = stats_;
255 return true;
256 }
257 virtual void GetDataCounters(uint32_t* bytes_received,
258 uint32_t* packets_received) const OVERRIDE {
259 *bytes_received = 0;
260 *packets_received = 0;
261 }
262 virtual uint32_t BitrateReceived() const OVERRIDE { return 0; }
263 virtual void ResetStatistics() OVERRIDE {}
264 virtual bool IsRetransmitOfOldPacket(const RTPHeader& header,
265 int min_rtt) const OVERRIDE {
266 return false;
267 }
268
269 virtual bool IsPacketInOrder(uint16_t sequence_number) const OVERRIDE {
270 return true;
271 }
272 Statistics stats_;
273 };
274
275 scoped_ptr<LossyStatistician> lossy_stats_;
276 StatisticianMap stats_map_;
277};
278
279TEST_F(VideoSendStreamTest, SupportsFec) {
280 static const int kRedPayloadType = 118;
281 static const int kUlpfecPayloadType = 119;
282 class FecObserver : public SendTransportObserver {
283 public:
284 FecObserver()
285 : SendTransportObserver(30 * 1000),
286 transport_adapter_(&transport_),
287 send_count_(0),
288 received_media_(false),
289 received_fec_(false) {}
290
291 void SetReceiver(PacketReceiver* receiver) {
292 transport_.SetReceiver(receiver);
293 }
294
295 virtual bool SendRTP(const uint8_t* packet, size_t length) OVERRIDE {
296 RTPHeader header;
297 EXPECT_TRUE(
298 rtp_header_parser_->Parse(packet, static_cast<int>(length), &header));
299
300 // Send lossy receive reports to trigger FEC enabling.
301 if (send_count_++ % 2 != 0) {
302 // Receive statistics reporting having lost 50% of the packets.
303 LossyReceiveStatistics lossy_receive_stats(
304 kSendSsrc, header.sequenceNumber, send_count_ / 2, 127);
305 RTCPSender rtcp_sender(
306 0, false, Clock::GetRealTimeClock(), &lossy_receive_stats);
307 EXPECT_EQ(0, rtcp_sender.RegisterSendTransport(&transport_adapter_));
308
309 rtcp_sender.SetRTCPStatus(kRtcpNonCompound);
310 rtcp_sender.SetRemoteSSRC(kSendSsrc);
311
312 RTCPSender::FeedbackState feedback_state;
313
314 EXPECT_EQ(0, rtcp_sender.SendRTCP(feedback_state, kRtcpRr));
315 }
316
317 EXPECT_EQ(kRedPayloadType, header.payloadType);
318
319 uint8_t encapsulated_payload_type = packet[header.headerLength];
320
321 if (encapsulated_payload_type == kUlpfecPayloadType) {
322 received_fec_ = true;
323 } else {
324 received_media_ = true;
325 }
326
327 if (received_media_ && received_fec_)
328 send_test_complete_->Set();
329
330 return true;
331 }
332
333 private:
334 internal::TransportAdapter transport_adapter_;
335 test::DirectTransport transport_;
336 int send_count_;
337 bool received_media_;
338 bool received_fec_;
339 } observer;
340
341 Call::Config call_config(&observer);
342 scoped_ptr<Call> call(Call::Create(call_config));
343
344 observer.SetReceiver(call->Receiver());
345
346 VideoSendStream::Config send_config = GetSendTestConfig(call.get());
347 send_config.rtp.fec.red_payload_type = kRedPayloadType;
348 send_config.rtp.fec.ulpfec_payload_type = kUlpfecPayloadType;
349
350 RunSendTest(call.get(), send_config, &observer);
351}
352
pbos@webrtc.org5860de02013-09-16 13:01:47 +0000353void VideoSendStreamTest::TestNackRetransmission(uint32_t retransmit_ssrc) {
pbos@webrtc.org0e63e762013-09-20 11:56:26 +0000354 class NackObserver : public SendTransportObserver {
pbos@webrtc.orgdf531a22013-09-10 14:56:33 +0000355 public:
pbos@webrtc.org5860de02013-09-16 13:01:47 +0000356 NackObserver(uint32_t retransmit_ssrc)
pbos@webrtc.orgdf531a22013-09-10 14:56:33 +0000357 : SendTransportObserver(30 * 1000),
pbos@webrtc.org0e63e762013-09-20 11:56:26 +0000358 transport_adapter_(&transport_),
pbos@webrtc.orgdf531a22013-09-10 14:56:33 +0000359 send_count_(0),
pbos@webrtc.org5860de02013-09-16 13:01:47 +0000360 retransmit_ssrc_(retransmit_ssrc),
pbos@webrtc.orgdf531a22013-09-10 14:56:33 +0000361 nacked_sequence_number_(0) {}
362
pbos@webrtc.org0e63e762013-09-20 11:56:26 +0000363 void SetReceiver(PacketReceiver* receiver) {
364 transport_.SetReceiver(receiver);
pbos@webrtc.orgdf531a22013-09-10 14:56:33 +0000365 }
366
367 virtual bool SendRTP(const uint8_t* packet, size_t length) OVERRIDE {
pbos@webrtc.orgdf531a22013-09-10 14:56:33 +0000368 RTPHeader header;
369 EXPECT_TRUE(
370 rtp_header_parser_->Parse(packet, static_cast<int>(length), &header));
371
372 // Nack second packet after receiving the third one.
373 if (++send_count_ == 3) {
pbos@webrtc.orgdf531a22013-09-10 14:56:33 +0000374 nacked_sequence_number_ = header.sequenceNumber - 1;
pbos@webrtc.org0e63e762013-09-20 11:56:26 +0000375 NullReceiveStatistics null_stats;
376 RTCPSender rtcp_sender(
377 0, false, Clock::GetRealTimeClock(), &null_stats);
378 EXPECT_EQ(0, rtcp_sender.RegisterSendTransport(&transport_adapter_));
379
380 rtcp_sender.SetRTCPStatus(kRtcpNonCompound);
381 rtcp_sender.SetRemoteSSRC(kSendSsrc);
382
383 RTCPSender::FeedbackState feedback_state;
384
385 EXPECT_EQ(0,
386 rtcp_sender.SendRTCP(
387 feedback_state, kRtcpNack, 1, &nacked_sequence_number_));
pbos@webrtc.orgdf531a22013-09-10 14:56:33 +0000388 }
389
pbos@webrtc.org5860de02013-09-16 13:01:47 +0000390 uint16_t sequence_number = header.sequenceNumber;
391
392 if (header.ssrc == retransmit_ssrc_ && retransmit_ssrc_ != kSendSsrc) {
393 // Not kSendSsrc, assume correct RTX packet. Extract sequence number.
394 const uint8_t* rtx_header = packet + header.headerLength;
395 sequence_number = (rtx_header[0] << 8) + rtx_header[1];
396 }
397
398 if (sequence_number == nacked_sequence_number_) {
399 EXPECT_EQ(retransmit_ssrc_, header.ssrc);
pbos@webrtc.orgdf531a22013-09-10 14:56:33 +0000400 send_test_complete_->Set();
pbos@webrtc.org5860de02013-09-16 13:01:47 +0000401 }
pbos@webrtc.orgdf531a22013-09-10 14:56:33 +0000402
403 return true;
404 }
405 private:
pbos@webrtc.org0e63e762013-09-20 11:56:26 +0000406 internal::TransportAdapter transport_adapter_;
407 test::DirectTransport transport_;
pbos@webrtc.orgdf531a22013-09-10 14:56:33 +0000408 int send_count_;
pbos@webrtc.org5860de02013-09-16 13:01:47 +0000409 uint32_t retransmit_ssrc_;
pbos@webrtc.orgdf531a22013-09-10 14:56:33 +0000410 uint16_t nacked_sequence_number_;
pbos@webrtc.org5860de02013-09-16 13:01:47 +0000411 } observer(retransmit_ssrc);
pbos@webrtc.orgdf531a22013-09-10 14:56:33 +0000412
413 Call::Config call_config(&observer);
414 scoped_ptr<Call> call(Call::Create(call_config));
415 observer.SetReceiver(call->Receiver());
416
417 VideoSendStream::Config send_config = GetSendTestConfig(call.get());
418 send_config.rtp.nack.rtp_history_ms = 1000;
pbos@webrtc.org5860de02013-09-16 13:01:47 +0000419 if (retransmit_ssrc != kSendSsrc)
420 send_config.rtp.rtx.ssrcs.push_back(retransmit_ssrc);
pbos@webrtc.orgdf531a22013-09-10 14:56:33 +0000421
422 RunSendTest(call.get(), send_config, &observer);
423}
424
pbos@webrtc.org5860de02013-09-16 13:01:47 +0000425TEST_F(VideoSendStreamTest, RetransmitsNack) {
426 // Normal NACKs should use the send SSRC.
427 TestNackRetransmission(kSendSsrc);
428}
429
430TEST_F(VideoSendStreamTest, RetransmitsNackOverRtx) {
431 // NACKs over RTX should use a separate SSRC.
432 TestNackRetransmission(kSendRtxSsrc);
433}
434
sprang@webrtc.org5d957e22013-10-16 11:37:54 +0000435TEST_F(VideoSendStreamTest, MaxPacketSize) {
436 class PacketSizeObserver : public SendTransportObserver {
437 public:
438 PacketSizeObserver(size_t max_length) : SendTransportObserver(30 * 1000),
439 max_length_(max_length), accumulated_size_(0) {}
440
441 virtual bool SendRTP(const uint8_t* packet, size_t length) OVERRIDE {
442 RTPHeader header;
443 EXPECT_TRUE(
444 rtp_header_parser_->Parse(packet, static_cast<int>(length), &header));
445
sprang@webrtc.org25fce9a2013-10-16 13:29:14 +0000446 EXPECT_LE(length, max_length_);
sprang@webrtc.org5d957e22013-10-16 11:37:54 +0000447
448 accumulated_size_ += length;
449
450 // Marker bit set indicates last fragment of a packet
451 if (header.markerBit) {
452 if (accumulated_size_ + length > max_length_) {
453 // The packet was fragmented, total size was larger than max size,
454 // but size of individual fragments were within size limit => pass!
455 send_test_complete_->Set();
456 }
457 accumulated_size_ = 0; // Last fragment, reset packet size
458 }
459
460 return true;
461 }
462
463 private:
464 size_t max_length_;
465 size_t accumulated_size_;
466 };
467
468 static const uint32_t kMaxPacketSize = 128;
469
470 PacketSizeObserver observer(kMaxPacketSize);
471 Call::Config call_config(&observer);
472 scoped_ptr<Call> call(Call::Create(call_config));
473
474 VideoSendStream::Config send_config = GetSendTestConfig(call.get());
475 send_config.rtp.max_packet_size = kMaxPacketSize;
476
477 RunSendTest(call.get(), send_config, &observer);
478}
479
pbos@webrtc.org119a1cc2013-08-20 13:14:07 +0000480} // namespace webrtc