Wed, 31 Dec 2014 06:55:50 +0100
Added tag UPSTREAM_283F7C6 for changeset ca08bd8f51b2
1 /* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
3 * You can obtain one at http://mozilla.org/MPL/2.0/. */
5 // Original author: ekr@rtfm.com
7 #include <iostream>
9 #include "sigslot.h"
11 #include "logging.h"
12 #include "nsThreadUtils.h"
13 #include "nsXPCOM.h"
14 #include "nss.h"
15 #include "ssl.h"
16 #include "sslproto.h"
18 #include "dtlsidentity.h"
19 #include "mozilla/RefPtr.h"
20 #include "FakeMediaStreams.h"
21 #include "FakeMediaStreamsImpl.h"
22 #include "MediaConduitErrors.h"
23 #include "MediaConduitInterface.h"
24 #include "MediaPipeline.h"
25 #include "MediaPipelineFilter.h"
26 #include "runnable_utils.h"
27 #include "transportflow.h"
28 #include "transportlayerloopback.h"
29 #include "transportlayerdtls.h"
30 #include "mozilla/SyncRunnable.h"
33 #include "mtransport_test_utils.h"
34 #include "runnable_utils.h"
36 #include "webrtc/modules/interface/module_common_types.h"
38 #define GTEST_HAS_RTTI 0
39 #include "gtest/gtest.h"
40 #include "gtest_utils.h"
42 using namespace mozilla;
43 MOZ_MTLOG_MODULE("mediapipeline")
45 MtransportTestUtils *test_utils;
47 namespace {
49 class TransportInfo {
50 public:
51 TransportInfo() :
52 flow_(nullptr),
53 loopback_(nullptr),
54 dtls_(nullptr) {}
56 static void InitAndConnect(TransportInfo &client, TransportInfo &server) {
57 client.Init(true);
58 server.Init(false);
59 client.PushLayers();
60 server.PushLayers();
61 client.Connect(&server);
62 server.Connect(&client);
63 }
65 void Init(bool client) {
66 nsresult res;
68 flow_ = new TransportFlow();
69 loopback_ = new TransportLayerLoopback();
70 dtls_ = new TransportLayerDtls();
72 res = loopback_->Init();
73 if (res != NS_OK) {
74 FreeLayers();
75 }
76 ASSERT_EQ((nsresult)NS_OK, res);
78 std::vector<uint16_t> ciphers;
79 ciphers.push_back(SRTP_AES128_CM_HMAC_SHA1_80);
80 dtls_->SetSrtpCiphers(ciphers);
81 dtls_->SetIdentity(DtlsIdentity::Generate());
82 dtls_->SetRole(client ? TransportLayerDtls::CLIENT :
83 TransportLayerDtls::SERVER);
84 dtls_->SetVerificationAllowAll();
85 }
87 void PushLayers() {
88 nsresult res;
90 nsAutoPtr<std::queue<TransportLayer *> > layers(
91 new std::queue<TransportLayer *>);
92 layers->push(loopback_);
93 layers->push(dtls_);
94 res = flow_->PushLayers(layers);
95 if (res != NS_OK) {
96 FreeLayers();
97 }
98 ASSERT_EQ((nsresult)NS_OK, res);
99 }
101 void Connect(TransportInfo* peer) {
102 MOZ_ASSERT(loopback_);
103 MOZ_ASSERT(peer->loopback_);
105 loopback_->Connect(peer->loopback_);
106 }
108 // Free the memory allocated at the beginning of Init
109 // if failure occurs before layers setup.
110 void FreeLayers() {
111 delete loopback_;
112 loopback_ = nullptr;
113 delete dtls_;
114 dtls_ = nullptr;
115 }
117 void Shutdown() {
118 if (loopback_) {
119 loopback_->Disconnect();
120 }
121 loopback_ = nullptr;
122 dtls_ = nullptr;
123 flow_ = nullptr;
124 }
126 mozilla::RefPtr<TransportFlow> flow_;
127 TransportLayerLoopback *loopback_;
128 TransportLayerDtls *dtls_;
129 };
131 class TestAgent {
132 public:
133 TestAgent() :
134 audio_config_(109, "opus", 48000, 960, 2, 64000),
135 audio_conduit_(mozilla::AudioSessionConduit::Create(nullptr)),
136 audio_(),
137 audio_pipeline_() {
138 }
140 static void ConnectRtp(TestAgent *client, TestAgent *server) {
141 TransportInfo::InitAndConnect(client->audio_rtp_transport_,
142 server->audio_rtp_transport_);
143 }
145 static void ConnectRtcp(TestAgent *client, TestAgent *server) {
146 TransportInfo::InitAndConnect(client->audio_rtcp_transport_,
147 server->audio_rtcp_transport_);
148 }
150 static void ConnectBundle(TestAgent *client, TestAgent *server) {
151 TransportInfo::InitAndConnect(client->bundle_transport_,
152 server->bundle_transport_);
153 }
155 virtual void CreatePipelines_s(bool aIsRtcpMux) = 0;
157 void Start() {
158 nsresult ret;
160 MOZ_MTLOG(ML_DEBUG, "Starting");
162 mozilla::SyncRunnable::DispatchToThread(
163 test_utils->sts_target(),
164 WrapRunnableRet(audio_->GetStream(), &Fake_MediaStream::Start, &ret));
166 ASSERT_TRUE(NS_SUCCEEDED(ret));
167 }
169 void StopInt() {
170 audio_->GetStream()->Stop();
171 }
173 void Stop() {
174 MOZ_MTLOG(ML_DEBUG, "Stopping");
176 if (audio_pipeline_)
177 audio_pipeline_->ShutdownMedia_m();
179 mozilla::SyncRunnable::DispatchToThread(
180 test_utils->sts_target(),
181 WrapRunnable(this, &TestAgent::StopInt));
182 }
184 void Shutdown_s() {
185 audio_rtp_transport_.Shutdown();
186 audio_rtcp_transport_.Shutdown();
187 bundle_transport_.Shutdown();
188 if (audio_pipeline_)
189 audio_pipeline_->ShutdownTransport_s();
190 }
192 void Shutdown() {
193 if (audio_pipeline_)
194 audio_pipeline_->ShutdownMedia_m();
196 mozilla::SyncRunnable::DispatchToThread(
197 test_utils->sts_target(),
198 WrapRunnable(this, &TestAgent::Shutdown_s));
199 }
201 uint32_t GetRemoteSSRC() {
202 uint32_t res = 0;
203 audio_conduit_->GetRemoteSSRC(&res);
204 return res;
205 }
207 uint32_t GetLocalSSRC() {
208 uint32_t res = 0;
209 audio_conduit_->GetLocalSSRC(&res);
210 return res;
211 }
213 int GetAudioRtpCountSent() {
214 return audio_pipeline_->rtp_packets_sent();
215 }
217 int GetAudioRtpCountReceived() {
218 return audio_pipeline_->rtp_packets_received();
219 }
221 int GetAudioRtcpCountSent() {
222 return audio_pipeline_->rtcp_packets_sent();
223 }
225 int GetAudioRtcpCountReceived() {
226 return audio_pipeline_->rtcp_packets_received();
227 }
229 protected:
230 mozilla::AudioCodecConfig audio_config_;
231 mozilla::RefPtr<mozilla::MediaSessionConduit> audio_conduit_;
232 nsRefPtr<DOMMediaStream> audio_;
233 // TODO(bcampen@mozilla.com): Right now this does not let us test RTCP in
234 // both directions; only the sender's RTCP is sent, but the receiver should
235 // be sending it too.
236 mozilla::RefPtr<mozilla::MediaPipeline> audio_pipeline_;
237 TransportInfo audio_rtp_transport_;
238 TransportInfo audio_rtcp_transport_;
239 TransportInfo bundle_transport_;
240 };
242 class TestAgentSend : public TestAgent {
243 public:
244 TestAgentSend() : use_bundle_(false) {}
246 virtual void CreatePipelines_s(bool aIsRtcpMux) {
247 audio_ = new Fake_DOMMediaStream(new Fake_AudioStreamSource());
249 mozilla::MediaConduitErrorCode err =
250 static_cast<mozilla::AudioSessionConduit *>(audio_conduit_.get())->
251 ConfigureSendMediaCodec(&audio_config_);
252 EXPECT_EQ(mozilla::kMediaConduitNoError, err);
254 std::string test_pc("PC");
256 if (aIsRtcpMux) {
257 ASSERT_FALSE(audio_rtcp_transport_.flow_);
258 }
260 RefPtr<TransportFlow> rtp(audio_rtp_transport_.flow_);
261 RefPtr<TransportFlow> rtcp(audio_rtcp_transport_.flow_);
263 if (use_bundle_) {
264 rtp = bundle_transport_.flow_;
265 rtcp = nullptr;
266 }
268 audio_pipeline_ = new mozilla::MediaPipelineTransmit(
269 test_pc,
270 nullptr,
271 test_utils->sts_target(),
272 audio_,
273 1,
274 1,
275 audio_conduit_,
276 rtp,
277 rtcp);
279 audio_pipeline_->Init();
280 }
282 void SetUsingBundle(bool use_bundle) {
283 use_bundle_ = use_bundle;
284 }
286 private:
287 bool use_bundle_;
288 };
291 class TestAgentReceive : public TestAgent {
292 public:
293 virtual void CreatePipelines_s(bool aIsRtcpMux) {
294 mozilla::SourceMediaStream *audio = new Fake_SourceMediaStream();
295 audio->SetPullEnabled(true);
297 mozilla::AudioSegment* segment= new mozilla::AudioSegment();
298 audio->AddTrack(0, 100, 0, segment);
299 audio->AdvanceKnownTracksTime(mozilla::STREAM_TIME_MAX);
301 audio_ = new Fake_DOMMediaStream(audio);
303 std::vector<mozilla::AudioCodecConfig *> codecs;
304 codecs.push_back(&audio_config_);
306 mozilla::MediaConduitErrorCode err =
307 static_cast<mozilla::AudioSessionConduit *>(audio_conduit_.get())->
308 ConfigureRecvMediaCodecs(codecs);
309 EXPECT_EQ(mozilla::kMediaConduitNoError, err);
311 std::string test_pc("PC");
313 if (aIsRtcpMux) {
314 ASSERT_FALSE(audio_rtcp_transport_.flow_);
315 }
317 // For now, assume bundle always uses rtcp mux
318 RefPtr<TransportFlow> dummy;
319 RefPtr<TransportFlow> bundle_transport;
320 if (bundle_filter_) {
321 bundle_transport = bundle_transport_.flow_;
322 bundle_filter_->AddLocalSSRC(GetLocalSSRC());
323 }
325 audio_pipeline_ = new mozilla::MediaPipelineReceiveAudio(
326 test_pc,
327 nullptr,
328 test_utils->sts_target(),
329 audio_->GetStream(), 1, 1,
330 static_cast<mozilla::AudioSessionConduit *>(audio_conduit_.get()),
331 audio_rtp_transport_.flow_,
332 audio_rtcp_transport_.flow_,
333 bundle_transport,
334 dummy,
335 bundle_filter_);
337 audio_pipeline_->Init();
338 }
340 void SetBundleFilter(nsAutoPtr<MediaPipelineFilter> filter) {
341 bundle_filter_ = filter;
342 }
344 void SetUsingBundle_s(bool decision) {
345 audio_pipeline_->SetUsingBundle_s(decision);
346 }
348 void UpdateFilterFromRemoteDescription_s(
349 nsAutoPtr<MediaPipelineFilter> filter) {
350 audio_pipeline_->UpdateFilterFromRemoteDescription_s(filter);
351 }
353 private:
354 nsAutoPtr<MediaPipelineFilter> bundle_filter_;
355 };
358 class MediaPipelineTest : public ::testing::Test {
359 public:
360 ~MediaPipelineTest() {
361 p1_.Stop();
362 p2_.Stop();
363 p1_.Shutdown();
364 p2_.Shutdown();
365 }
367 // Setup transport.
368 void InitTransports(bool aIsRtcpMux) {
369 // RTP, p1_ is server, p2_ is client
370 mozilla::SyncRunnable::DispatchToThread(
371 test_utils->sts_target(),
372 WrapRunnableNM(&TestAgent::ConnectRtp, &p2_, &p1_));
374 // Create RTCP flows separately if we are not muxing them.
375 if(!aIsRtcpMux) {
376 // RTCP, p1_ is server, p2_ is client
377 mozilla::SyncRunnable::DispatchToThread(
378 test_utils->sts_target(),
379 WrapRunnableNM(&TestAgent::ConnectRtcp, &p2_, &p1_));
380 }
382 // BUNDLE, p1_ is server, p2_ is client
383 mozilla::SyncRunnable::DispatchToThread(
384 test_utils->sts_target(),
385 WrapRunnableNM(&TestAgent::ConnectBundle, &p2_, &p1_));
386 }
388 // Verify RTP and RTCP
389 void TestAudioSend(bool aIsRtcpMux,
390 bool bundle = false,
391 nsAutoPtr<MediaPipelineFilter> localFilter =
392 nsAutoPtr<MediaPipelineFilter>(nullptr),
393 nsAutoPtr<MediaPipelineFilter> remoteFilter =
394 nsAutoPtr<MediaPipelineFilter>(nullptr),
395 unsigned int ms_until_answer = 500,
396 unsigned int ms_of_traffic_after_answer = 10000) {
398 // We do not support testing bundle without rtcp mux, since that doesn't
399 // make any sense.
400 ASSERT_FALSE(!aIsRtcpMux && bundle);
402 p1_.SetUsingBundle(bundle);
403 p2_.SetBundleFilter(localFilter);
405 // Setup transport flows
406 InitTransports(aIsRtcpMux);
408 mozilla::SyncRunnable::DispatchToThread(
409 test_utils->sts_target(),
410 WrapRunnable(&p1_, &TestAgent::CreatePipelines_s, aIsRtcpMux));
412 mozilla::SyncRunnable::DispatchToThread(
413 test_utils->sts_target(),
414 WrapRunnable(&p2_, &TestAgent::CreatePipelines_s, aIsRtcpMux));
416 p2_.Start();
417 p1_.Start();
419 // Simulate pre-answer traffic
420 PR_Sleep(ms_until_answer);
422 mozilla::SyncRunnable::DispatchToThread(
423 test_utils->sts_target(),
424 WrapRunnable(&p2_, &TestAgentReceive::SetUsingBundle_s, bundle));
426 if (bundle) {
427 // Leaving remoteFilter not set implies we want to test sunny-day
428 if (!remoteFilter) {
429 remoteFilter = new MediaPipelineFilter;
430 // Might not be safe, strictly speaking.
431 remoteFilter->AddRemoteSSRC(p1_.GetLocalSSRC());
432 }
434 mozilla::SyncRunnable::DispatchToThread(
435 test_utils->sts_target(),
436 WrapRunnable(&p2_,
437 &TestAgentReceive::UpdateFilterFromRemoteDescription_s,
438 remoteFilter));
439 }
442 // wait for some RTP/RTCP tx and rx to happen
443 PR_Sleep(ms_of_traffic_after_answer);
445 p1_.Stop();
446 p2_.Stop();
448 // wait for any packets in flight to arrive
449 PR_Sleep(100);
451 p1_.Shutdown();
452 p2_.Shutdown();
454 if (!bundle) {
455 // If we are doing bundle, allow the test-case to do this checking.
456 ASSERT_GE(p1_.GetAudioRtpCountSent(), 40);
457 ASSERT_EQ(p1_.GetAudioRtpCountReceived(), p2_.GetAudioRtpCountSent());
458 ASSERT_EQ(p1_.GetAudioRtpCountSent(), p2_.GetAudioRtpCountReceived());
460 // Calling ShutdownMedia_m on both pipelines does not stop the flow of
461 // RTCP. So, we might be off by one here.
462 ASSERT_LE(p2_.GetAudioRtcpCountReceived(), p1_.GetAudioRtcpCountSent());
463 ASSERT_GE(p2_.GetAudioRtcpCountReceived() + 1, p1_.GetAudioRtcpCountSent());
464 }
466 }
468 void TestAudioReceiverOffersBundle(bool bundle_accepted,
469 nsAutoPtr<MediaPipelineFilter> localFilter,
470 nsAutoPtr<MediaPipelineFilter> remoteFilter =
471 nsAutoPtr<MediaPipelineFilter>(nullptr),
472 unsigned int ms_until_answer = 500,
473 unsigned int ms_of_traffic_after_answer = 10000) {
474 TestAudioSend(true,
475 bundle_accepted,
476 localFilter,
477 remoteFilter,
478 ms_until_answer,
479 ms_of_traffic_after_answer);
480 }
481 protected:
482 TestAgentSend p1_;
483 TestAgentReceive p2_;
484 };
486 class MediaPipelineFilterTest : public ::testing::Test {
487 public:
488 bool Filter(MediaPipelineFilter& filter,
489 int32_t correlator,
490 uint32_t ssrc,
491 uint8_t payload_type) {
493 webrtc::RTPHeader header;
494 header.ssrc = ssrc;
495 header.payloadType = payload_type;
496 return filter.Filter(header, correlator);
497 }
498 };
500 TEST_F(MediaPipelineFilterTest, TestConstruct) {
501 MediaPipelineFilter filter;
502 }
504 TEST_F(MediaPipelineFilterTest, TestDefault) {
505 MediaPipelineFilter filter;
506 ASSERT_FALSE(Filter(filter, 0, 233, 110));
507 }
509 TEST_F(MediaPipelineFilterTest, TestSSRCFilter) {
510 MediaPipelineFilter filter;
511 filter.AddRemoteSSRC(555);
512 ASSERT_TRUE(Filter(filter, 0, 555, 110));
513 ASSERT_FALSE(Filter(filter, 0, 556, 110));
514 }
516 #define SSRC(ssrc) \
517 ((ssrc >> 24) & 0xFF), \
518 ((ssrc >> 16) & 0xFF), \
519 ((ssrc >> 8 ) & 0xFF), \
520 (ssrc & 0xFF)
522 #define REPORT_FRAGMENT(ssrc) \
523 SSRC(ssrc), \
524 0,0,0,0, \
525 0,0,0,0, \
526 0,0,0,0, \
527 0,0,0,0, \
528 0,0,0,0
530 #define RTCP_TYPEINFO(num_rrs, type, size) \
531 0x80 + num_rrs, type, 0, size
533 const unsigned char rtcp_rr_s16[] = {
534 // zero rrs, size 1 words
535 RTCP_TYPEINFO(0, MediaPipelineFilter::RECEIVER_REPORT_T, 1),
536 SSRC(16)
537 };
539 const unsigned char rtcp_rr_s16_r17[] = {
540 // one rr, 7 words
541 RTCP_TYPEINFO(1, MediaPipelineFilter::RECEIVER_REPORT_T, 7),
542 SSRC(16),
543 REPORT_FRAGMENT(17)
544 };
546 const unsigned char rtcp_rr_s16_r17_18[] = {
547 // two rrs, size 13 words
548 RTCP_TYPEINFO(2, MediaPipelineFilter::RECEIVER_REPORT_T, 13),
549 SSRC(16),
550 REPORT_FRAGMENT(17),
551 REPORT_FRAGMENT(18)
552 };
554 const unsigned char rtcp_sr_s16[] = {
555 // zero rrs, size 6 words
556 RTCP_TYPEINFO(0, MediaPipelineFilter::SENDER_REPORT_T, 6),
557 REPORT_FRAGMENT(16)
558 };
560 const unsigned char rtcp_sr_s16_r17[] = {
561 // one rr, size 12 words
562 RTCP_TYPEINFO(1, MediaPipelineFilter::SENDER_REPORT_T, 12),
563 REPORT_FRAGMENT(16),
564 REPORT_FRAGMENT(17)
565 };
567 const unsigned char rtcp_sr_s16_r17_18[] = {
568 // two rrs, size 18 words
569 RTCP_TYPEINFO(2, MediaPipelineFilter::SENDER_REPORT_T, 18),
570 REPORT_FRAGMENT(16),
571 REPORT_FRAGMENT(17),
572 REPORT_FRAGMENT(18)
573 };
575 const unsigned char unknown_type[] = {
576 RTCP_TYPEINFO(1, 222, 0)
577 };
579 TEST_F(MediaPipelineFilterTest, TestEmptyFilterReport0) {
580 MediaPipelineFilter filter;
581 ASSERT_EQ(MediaPipelineFilter::FAIL,
582 filter.FilterRTCP(rtcp_sr_s16, sizeof(rtcp_sr_s16)));
583 ASSERT_EQ(MediaPipelineFilter::FAIL,
584 filter.FilterRTCP(rtcp_rr_s16, sizeof(rtcp_rr_s16)));
585 }
587 TEST_F(MediaPipelineFilterTest, TestFilterReport0) {
588 MediaPipelineFilter filter;
589 filter.AddRemoteSSRC(16);
590 ASSERT_EQ(MediaPipelineFilter::PASS,
591 filter.FilterRTCP(rtcp_sr_s16, sizeof(rtcp_sr_s16)));
592 ASSERT_EQ(MediaPipelineFilter::PASS,
593 filter.FilterRTCP(rtcp_rr_s16, sizeof(rtcp_rr_s16)));
594 }
596 TEST_F(MediaPipelineFilterTest, TestFilterReport0SSRCTruncated) {
597 MediaPipelineFilter filter;
598 filter.AddRemoteSSRC(16);
599 const unsigned char data[] = {
600 RTCP_TYPEINFO(0, MediaPipelineFilter::RECEIVER_REPORT_T, 1),
601 0,0,0
602 };
603 ASSERT_EQ(MediaPipelineFilter::FAIL,
604 filter.FilterRTCP(data, sizeof(data)));
605 }
607 TEST_F(MediaPipelineFilterTest, TestFilterReport0PTTruncated) {
608 MediaPipelineFilter filter;
609 filter.AddRemoteSSRC(16);
610 const unsigned char data[] = {0x80};
611 ASSERT_EQ(MediaPipelineFilter::FAIL,
612 filter.FilterRTCP(data, sizeof(data)));
613 }
615 TEST_F(MediaPipelineFilterTest, TestFilterReport0CountTruncated) {
616 MediaPipelineFilter filter;
617 filter.AddRemoteSSRC(16);
618 const unsigned char data[] = {};
619 ASSERT_EQ(MediaPipelineFilter::FAIL,
620 filter.FilterRTCP(data, sizeof(data)));
621 }
623 TEST_F(MediaPipelineFilterTest, TestFilterReport1BothMatch) {
624 MediaPipelineFilter filter;
625 filter.AddRemoteSSRC(16);
626 filter.AddLocalSSRC(17);
627 ASSERT_EQ(MediaPipelineFilter::PASS,
628 filter.FilterRTCP(rtcp_sr_s16_r17, sizeof(rtcp_sr_s16_r17)));
629 ASSERT_EQ(MediaPipelineFilter::PASS,
630 filter.FilterRTCP(rtcp_rr_s16_r17, sizeof(rtcp_rr_s16_r17)));
631 }
633 TEST_F(MediaPipelineFilterTest, TestFilterReport1SSRCTruncated) {
634 MediaPipelineFilter filter;
635 filter.AddRemoteSSRC(16);
636 filter.AddLocalSSRC(17);
637 const unsigned char rr[] = {
638 RTCP_TYPEINFO(1, MediaPipelineFilter::RECEIVER_REPORT_T, 7),
639 SSRC(16),
640 0,0,0
641 };
642 ASSERT_EQ(MediaPipelineFilter::FAIL,
643 filter.FilterRTCP(rr, sizeof(rr)));
644 const unsigned char sr[] = {
645 RTCP_TYPEINFO(1, MediaPipelineFilter::RECEIVER_REPORT_T, 12),
646 REPORT_FRAGMENT(16),
647 0,0,0
648 };
649 ASSERT_EQ(MediaPipelineFilter::FAIL,
650 filter.FilterRTCP(sr, sizeof(rr)));
651 }
653 TEST_F(MediaPipelineFilterTest, TestFilterReport1BigSSRC) {
654 MediaPipelineFilter filter;
655 filter.AddRemoteSSRC(0x01020304);
656 filter.AddLocalSSRC(0x11121314);
657 const unsigned char rr[] = {
658 RTCP_TYPEINFO(1, MediaPipelineFilter::RECEIVER_REPORT_T, 7),
659 SSRC(0x01020304),
660 REPORT_FRAGMENT(0x11121314)
661 };
662 ASSERT_EQ(MediaPipelineFilter::PASS,
663 filter.FilterRTCP(rr, sizeof(rr)));
664 const unsigned char sr[] = {
665 RTCP_TYPEINFO(1, MediaPipelineFilter::RECEIVER_REPORT_T, 12),
666 SSRC(0x01020304),
667 REPORT_FRAGMENT(0x11121314)
668 };
669 ASSERT_EQ(MediaPipelineFilter::PASS,
670 filter.FilterRTCP(sr, sizeof(rr)));
671 }
673 TEST_F(MediaPipelineFilterTest, TestFilterReport1LocalMatch) {
674 MediaPipelineFilter filter;
675 filter.AddLocalSSRC(17);
676 ASSERT_EQ(MediaPipelineFilter::PASS,
677 filter.FilterRTCP(rtcp_sr_s16_r17, sizeof(rtcp_sr_s16_r17)));
678 ASSERT_EQ(MediaPipelineFilter::PASS,
679 filter.FilterRTCP(rtcp_rr_s16_r17, sizeof(rtcp_rr_s16_r17)));
680 }
682 TEST_F(MediaPipelineFilterTest, TestFilterReport1Inconsistent) {
683 MediaPipelineFilter filter;
684 filter.AddRemoteSSRC(16);
685 // We assume that the filter is exactly correct in terms of local ssrcs.
686 // So, when RTCP shows up with a remote SSRC that matches, and a local
687 // ssrc that doesn't, we assume the other end has messed up and put ssrcs
688 // from more than one m-line in the packet.
689 ASSERT_EQ(MediaPipelineFilter::FAIL,
690 filter.FilterRTCP(rtcp_sr_s16_r17, sizeof(rtcp_sr_s16_r17)));
691 ASSERT_EQ(MediaPipelineFilter::FAIL,
692 filter.FilterRTCP(rtcp_rr_s16_r17, sizeof(rtcp_rr_s16_r17)));
693 }
695 TEST_F(MediaPipelineFilterTest, TestFilterReport1NeitherMatch) {
696 MediaPipelineFilter filter;
697 filter.AddRemoteSSRC(17);
698 filter.AddLocalSSRC(18);
699 ASSERT_EQ(MediaPipelineFilter::PASS,
700 filter.FilterRTCP(rtcp_sr_s16_r17, sizeof(rtcp_sr_s16_r17)));
701 ASSERT_EQ(MediaPipelineFilter::PASS,
702 filter.FilterRTCP(rtcp_rr_s16_r17, sizeof(rtcp_rr_s16_r17)));
703 }
705 TEST_F(MediaPipelineFilterTest, TestFilterReport2AllMatch) {
706 MediaPipelineFilter filter;
707 filter.AddRemoteSSRC(16);
708 filter.AddLocalSSRC(17);
709 filter.AddLocalSSRC(18);
710 ASSERT_EQ(MediaPipelineFilter::PASS,
711 filter.FilterRTCP(rtcp_sr_s16_r17_18,
712 sizeof(rtcp_sr_s16_r17_18)));
713 }
715 TEST_F(MediaPipelineFilterTest, TestFilterReport2LocalMatch) {
716 MediaPipelineFilter filter;
717 filter.AddLocalSSRC(17);
718 filter.AddLocalSSRC(18);
719 ASSERT_EQ(MediaPipelineFilter::PASS,
720 filter.FilterRTCP(rtcp_sr_s16_r17_18,
721 sizeof(rtcp_sr_s16_r17_18)));
722 ASSERT_EQ(MediaPipelineFilter::PASS,
723 filter.FilterRTCP(rtcp_rr_s16_r17_18,
724 sizeof(rtcp_rr_s16_r17_18)));
725 }
727 TEST_F(MediaPipelineFilterTest, TestFilterReport2Inconsistent101) {
728 MediaPipelineFilter filter;
729 filter.AddRemoteSSRC(16);
730 filter.AddLocalSSRC(18);
731 ASSERT_EQ(MediaPipelineFilter::FAIL,
732 filter.FilterRTCP(rtcp_sr_s16_r17_18,
733 sizeof(rtcp_sr_s16_r17_18)));
734 ASSERT_EQ(MediaPipelineFilter::FAIL,
735 filter.FilterRTCP(rtcp_rr_s16_r17_18,
736 sizeof(rtcp_rr_s16_r17_18)));
737 }
739 TEST_F(MediaPipelineFilterTest, TestFilterReport2Inconsistent001) {
740 MediaPipelineFilter filter;
741 filter.AddLocalSSRC(18);
742 ASSERT_EQ(MediaPipelineFilter::FAIL,
743 filter.FilterRTCP(rtcp_sr_s16_r17_18,
744 sizeof(rtcp_sr_s16_r17_18)));
745 ASSERT_EQ(MediaPipelineFilter::FAIL,
746 filter.FilterRTCP(rtcp_rr_s16_r17_18,
747 sizeof(rtcp_rr_s16_r17_18)));
748 }
750 TEST_F(MediaPipelineFilterTest, TestFilterUnknownRTCPType) {
751 MediaPipelineFilter filter;
752 filter.AddLocalSSRC(18);
753 ASSERT_EQ(MediaPipelineFilter::UNSUPPORTED,
754 filter.FilterRTCP(unknown_type, sizeof(unknown_type)));
755 }
757 TEST_F(MediaPipelineFilterTest, TestCorrelatorFilter) {
758 MediaPipelineFilter filter;
759 filter.SetCorrelator(7777);
760 ASSERT_TRUE(Filter(filter, 7777, 16, 110));
761 ASSERT_FALSE(Filter(filter, 7778, 17, 110));
762 // This should also have resulted in the SSRC 16 being added to the filter
763 ASSERT_TRUE(Filter(filter, 0, 16, 110));
764 ASSERT_FALSE(Filter(filter, 0, 17, 110));
766 // rtcp_sr_s16 has 16 as an SSRC
767 ASSERT_EQ(MediaPipelineFilter::PASS,
768 filter.FilterRTCP(rtcp_sr_s16, sizeof(rtcp_sr_s16)));
769 ASSERT_EQ(MediaPipelineFilter::PASS,
770 filter.FilterRTCP(rtcp_rr_s16, sizeof(rtcp_rr_s16)));
771 }
773 TEST_F(MediaPipelineFilterTest, TestPayloadTypeFilter) {
774 MediaPipelineFilter filter;
775 filter.AddUniquePT(110);
776 ASSERT_TRUE(Filter(filter, 0, 555, 110));
777 ASSERT_FALSE(Filter(filter, 0, 556, 111));
778 }
780 TEST_F(MediaPipelineFilterTest, TestPayloadTypeFilterSSRCUpdate) {
781 MediaPipelineFilter filter;
782 filter.AddUniquePT(110);
783 ASSERT_TRUE(Filter(filter, 0, 16, 110));
785 // rtcp_sr_s16 has 16 as an SSRC
786 ASSERT_EQ(MediaPipelineFilter::PASS,
787 filter.FilterRTCP(rtcp_sr_s16, sizeof(rtcp_sr_s16)));
788 }
790 TEST_F(MediaPipelineFilterTest, TestAnswerAddsSSRCs) {
791 MediaPipelineFilter filter;
792 filter.SetCorrelator(7777);
793 ASSERT_TRUE(Filter(filter, 7777, 555, 110));
794 ASSERT_FALSE(Filter(filter, 7778, 556, 110));
795 // This should also have resulted in the SSRC 555 being added to the filter
796 ASSERT_TRUE(Filter(filter, 0, 555, 110));
797 ASSERT_FALSE(Filter(filter, 0, 556, 110));
799 // This sort of thing can happen when getting an answer with SSRC attrs
800 // The answer will not contain the correlator.
801 MediaPipelineFilter filter2;
802 filter2.AddRemoteSSRC(555);
803 filter2.AddRemoteSSRC(556);
804 filter2.AddRemoteSSRC(557);
806 filter.IncorporateRemoteDescription(filter2);
808 // Ensure that the old SSRC still works.
809 ASSERT_TRUE(Filter(filter, 0, 555, 110));
811 // Ensure that the new SSRCs work.
812 ASSERT_TRUE(Filter(filter, 0, 556, 110));
813 ASSERT_TRUE(Filter(filter, 0, 557, 110));
815 // Ensure that the correlator continues to work
816 ASSERT_TRUE(Filter(filter, 7777, 558, 110));
817 }
819 TEST_F(MediaPipelineFilterTest, TestSSRCMovedWithSDP) {
820 MediaPipelineFilter filter;
821 filter.SetCorrelator(7777);
822 filter.AddUniquePT(111);
823 ASSERT_TRUE(Filter(filter, 7777, 555, 110));
825 MediaPipelineFilter filter2;
826 filter2.AddRemoteSSRC(556);
828 filter.IncorporateRemoteDescription(filter2);
830 // Ensure that the old SSRC has been removed.
831 ASSERT_FALSE(Filter(filter, 0, 555, 110));
833 // Ensure that the new SSRC works.
834 ASSERT_TRUE(Filter(filter, 0, 556, 110));
836 // Ensure that the correlator continues to work
837 ASSERT_TRUE(Filter(filter, 7777, 558, 110));
839 // Ensure that the payload type mapping continues to work
840 ASSERT_TRUE(Filter(filter, 0, 559, 111));
841 }
843 TEST_F(MediaPipelineFilterTest, TestSSRCMovedWithCorrelator) {
844 MediaPipelineFilter filter;
845 filter.SetCorrelator(7777);
846 ASSERT_TRUE(Filter(filter, 7777, 555, 110));
847 ASSERT_TRUE(Filter(filter, 0, 555, 110));
848 ASSERT_FALSE(Filter(filter, 7778, 555, 110));
849 ASSERT_FALSE(Filter(filter, 0, 555, 110));
850 }
852 TEST_F(MediaPipelineFilterTest, TestRemoteSDPNoSSRCs) {
853 // If the remote SDP doesn't have SSRCs, right now this is a no-op and
854 // there is no point of even incorporating a filter, but we make the
855 // behavior consistent to avoid confusion.
856 MediaPipelineFilter filter;
857 filter.SetCorrelator(7777);
858 filter.AddUniquePT(111);
859 ASSERT_TRUE(Filter(filter, 7777, 555, 110));
861 MediaPipelineFilter filter2;
863 filter.IncorporateRemoteDescription(filter2);
865 // Ensure that the old SSRC still works.
866 ASSERT_TRUE(Filter(filter, 7777, 555, 110));
867 }
869 TEST_F(MediaPipelineTest, TestAudioSendNoMux) {
870 TestAudioSend(false);
871 }
873 TEST_F(MediaPipelineTest, TestAudioSendMux) {
874 TestAudioSend(true);
875 }
877 TEST_F(MediaPipelineTest, TestAudioSendBundleOfferedAndDeclined) {
878 nsAutoPtr<MediaPipelineFilter> filter(new MediaPipelineFilter);
879 TestAudioReceiverOffersBundle(false, filter);
880 }
882 TEST_F(MediaPipelineTest, TestAudioSendBundleOfferedAndAccepted) {
883 nsAutoPtr<MediaPipelineFilter> filter(new MediaPipelineFilter);
884 // These durations have to be _extremely_ long to have any assurance that
885 // some RTCP will be sent at all. This is because the first RTCP packet
886 // is sometimes sent before the transports are ready, which causes it to
887 // be dropped.
888 TestAudioReceiverOffersBundle(true,
889 filter,
890 // We do not specify the filter for the remote description, so it will be
891 // set to something sane after a short time.
892 nsAutoPtr<MediaPipelineFilter>(),
893 10000,
894 10000);
896 // Some packets should have been dropped, but not all
897 ASSERT_GT(p1_.GetAudioRtpCountSent(), p2_.GetAudioRtpCountReceived());
898 ASSERT_GT(p2_.GetAudioRtpCountReceived(), 40);
899 ASSERT_GT(p1_.GetAudioRtcpCountSent(), 1);
900 ASSERT_GT(p1_.GetAudioRtcpCountSent(), p2_.GetAudioRtcpCountReceived());
901 ASSERT_GT(p2_.GetAudioRtcpCountReceived(), 0);
902 }
904 TEST_F(MediaPipelineTest, TestAudioSendBundleOfferedAndAcceptedEmptyFilter) {
905 nsAutoPtr<MediaPipelineFilter> filter(new MediaPipelineFilter);
906 nsAutoPtr<MediaPipelineFilter> bad_answer_filter(new MediaPipelineFilter);
907 TestAudioReceiverOffersBundle(true, filter, bad_answer_filter);
908 // Filter is empty, so should drop everything.
909 ASSERT_EQ(0, p2_.GetAudioRtpCountReceived());
910 ASSERT_EQ(0, p2_.GetAudioRtcpCountReceived());
911 }
913 } // end namespace
916 int main(int argc, char **argv) {
917 test_utils = new MtransportTestUtils();
918 // Start the tests
919 NSS_NoDB_Init(nullptr);
920 NSS_SetDomesticPolicy();
921 ::testing::InitGoogleTest(&argc, argv);
923 int rv = RUN_ALL_TESTS();
924 delete test_utils;
925 return rv;
926 }