Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/media/webrtc/signaling/gtest/mediapipeline_unittest.cpp
Line
Count
Source (jump to first uncovered line)
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/. */
4
5
// Original author: ekr@rtfm.com
6
7
#include <iostream>
8
9
#include "logging.h"
10
#include "nss.h"
11
12
#include "AudioSegment.h"
13
#include "AudioStreamTrack.h"
14
#include "DOMMediaStream.h"
15
#include "mozilla/Mutex.h"
16
#include "mozilla/RefPtr.h"
17
#include "MediaPipeline.h"
18
#include "MediaPipelineFilter.h"
19
#include "MediaStreamGraph.h"
20
#include "MediaStreamListener.h"
21
#include "MediaStreamTrack.h"
22
#include "transportflow.h"
23
#include "transportlayerloopback.h"
24
#include "transportlayerdtls.h"
25
#include "transportlayersrtp.h"
26
#include "mozilla/SyncRunnable.h"
27
#include "mtransport_test_utils.h"
28
#include "SharedBuffer.h"
29
30
#define GTEST_HAS_RTTI 0
31
#include "gtest/gtest.h"
32
33
using namespace mozilla;
34
MOZ_MTLOG_MODULE("mediapipeline")
35
36
static MtransportTestUtils *test_utils;
37
38
namespace {
39
40
class FakeSourceMediaStream : public mozilla::SourceMediaStream {
41
42
public:
43
44
  FakeSourceMediaStream()
45
    : SourceMediaStream()
46
0
  {
47
0
  }
48
49
  virtual ~FakeSourceMediaStream() override
50
0
  {
51
0
    mMainThreadDestroyed = true;
52
0
  }
53
54
  virtual bool AppendToTrack(TrackID aID, MediaSegment* aSegment, MediaSegment *aRawSegment = nullptr) override
55
0
  {
56
0
    return true;
57
0
  }
58
};
59
60
class FakeMediaStreamTrackSource : public mozilla::dom::MediaStreamTrackSource {
61
62
public:
63
64
  FakeMediaStreamTrackSource()
65
    : MediaStreamTrackSource(nullptr, nsString())
66
0
  {
67
0
  }
68
69
  virtual mozilla::dom::MediaSourceEnum GetMediaSource() const override
70
0
  {
71
0
    return mozilla::dom::MediaSourceEnum::Microphone;
72
0
  }
73
74
75
  virtual void Disable() override
76
0
  {
77
0
  }
78
79
  virtual void Enable() override
80
0
  {
81
0
  }
82
83
  virtual void Stop() override
84
0
  {
85
0
  }
86
87
};
88
89
class FakeAudioStreamTrack : public mozilla::dom::AudioStreamTrack {
90
91
public:
92
93
  FakeAudioStreamTrack()
94
    : AudioStreamTrack(new DOMMediaStream(nullptr, nullptr), 0, 1,
95
                       new FakeMediaStreamTrackSource())
96
    , mMutex("Fake AudioStreamTrack")
97
    , mStop(false)
98
    , mCount(0)
99
0
  {
100
0
    NS_NewTimerWithFuncCallback(getter_AddRefs(mTimer),
101
0
                                FakeAudioStreamTrackGenerateData, this, 20,
102
0
                                nsITimer::TYPE_REPEATING_SLACK,
103
0
                                "FakeAudioStreamTrack::FakeAudioStreamTrackGenerateData",
104
0
                                test_utils->sts_target());
105
0
106
0
  }
107
108
  void Stop()
109
0
  {
110
0
    mozilla::MutexAutoLock lock(mMutex);
111
0
    mStop = true;
112
0
    mTimer->Cancel();
113
0
  }
114
115
  virtual void AddListener(MediaStreamTrackListener* aListener) override
116
0
  {
117
0
    mozilla::MutexAutoLock lock(mMutex);
118
0
    mListeners.push_back(aListener);
119
0
  }
120
121
  virtual already_AddRefed<mozilla::dom::MediaStreamTrack> CloneInternal(DOMMediaStream* aOwningStream, TrackID aTrackID) override
122
0
  {
123
0
    return RefPtr<MediaStreamTrack>(new FakeAudioStreamTrack).forget();
124
0
  }
125
126
  private:
127
    std::vector<MediaStreamTrackListener*> mListeners;
128
    mozilla::Mutex mMutex;
129
    bool mStop;
130
    nsCOMPtr<nsITimer> mTimer;
131
    int mCount;
132
133
    static void FakeAudioStreamTrackGenerateData(nsITimer* timer, void* closure)
134
0
    {
135
0
      auto mst = static_cast<FakeAudioStreamTrack*>(closure);
136
0
      const int AUDIO_BUFFER_SIZE = 1600;
137
0
      const int NUM_CHANNELS      = 2;
138
0
139
0
      mozilla::MutexAutoLock lock(mst->mMutex);
140
0
      if (mst->mStop) {
141
0
        return;
142
0
      }
143
0
144
0
      RefPtr<mozilla::SharedBuffer> samples =
145
0
        mozilla::SharedBuffer::Create(AUDIO_BUFFER_SIZE * NUM_CHANNELS * sizeof(int16_t));
146
0
      int16_t* data = reinterpret_cast<int16_t *>(samples->Data());
147
0
      for(int i=0; i<(AUDIO_BUFFER_SIZE * NUM_CHANNELS); i++) {
148
0
        //saw tooth audio sample
149
0
        data[i] = ((mst->mCount % 8) * 4000) - (7*4000)/2;
150
0
        mst->mCount++;
151
0
      }
152
0
153
0
      mozilla::AudioSegment segment;
154
0
      AutoTArray<const int16_t *,1> channels;
155
0
      channels.AppendElement(data);
156
0
      segment.AppendFrames(samples.forget(),
157
0
                           channels,
158
0
                           AUDIO_BUFFER_SIZE,
159
0
                           PRINCIPAL_HANDLE_NONE);
160
0
161
0
      for (auto& listener: mst->mListeners) {
162
0
        listener->NotifyQueuedChanges(nullptr, 0, segment);
163
0
      }
164
0
    }
165
};
166
167
class TransportInfo {
168
 public:
169
  TransportInfo() :
170
    flow_(nullptr),
171
0
    loopback_(nullptr) {}
172
173
0
  static void InitAndConnect(TransportInfo &client, TransportInfo &server) {
174
0
    client.Init(true);
175
0
    server.Init(false);
176
0
    client.Connect(&server);
177
0
    server.Connect(&client);
178
0
  }
179
180
0
  void Init(bool client) {
181
0
    UniquePtr<TransportLayerLoopback> loopback(new TransportLayerLoopback);
182
0
    UniquePtr<TransportLayerDtls> dtls(new TransportLayerDtls);
183
0
    UniquePtr<TransportLayerSrtp> srtp(new TransportLayerSrtp(*dtls));
184
0
185
0
    std::vector<uint16_t> ciphers;
186
0
    ciphers.push_back(kDtlsSrtpAeadAes256Gcm);
187
0
    dtls->SetSrtpCiphers(ciphers);
188
0
    dtls->SetIdentity(DtlsIdentity::Generate());
189
0
    dtls->SetRole(client ? TransportLayerDtls::CLIENT :
190
0
      TransportLayerDtls::SERVER);
191
0
    dtls->SetVerificationAllowAll();
192
0
193
0
    ASSERT_EQ(NS_OK, loopback->Init());
194
0
    ASSERT_EQ(NS_OK, dtls->Init());
195
0
    ASSERT_EQ(NS_OK, srtp->Init());
196
0
197
0
    dtls->Chain(loopback.get());
198
0
    srtp->Chain(loopback.get());
199
0
200
0
    flow_ = new TransportFlow();
201
0
    loopback_ = loopback.release();
202
0
    flow_->PushLayer(loopback_);
203
0
    flow_->PushLayer(dtls.release());
204
0
    flow_->PushLayer(srtp.release());
205
0
  }
206
207
0
  void Connect(TransportInfo* peer) {
208
0
    MOZ_ASSERT(loopback_);
209
0
    MOZ_ASSERT(peer->loopback_);
210
0
211
0
    loopback_->Connect(peer->loopback_);
212
0
  }
213
214
0
  void Shutdown() {
215
0
    if (loopback_) {
216
0
      loopback_->Disconnect();
217
0
    }
218
0
    loopback_ = nullptr;
219
0
    flow_ = nullptr;
220
0
  }
221
222
  RefPtr<TransportFlow> flow_;
223
  TransportLayerLoopback *loopback_;
224
};
225
226
class TestAgent {
227
 public:
228
  TestAgent() :
229
      audio_config_(109, "opus", 48000, 960, 2, 64000, false),
230
      audio_conduit_(mozilla::AudioSessionConduit::Create()),
231
      audio_pipeline_(),
232
0
      use_bundle_(false) {
233
0
  }
234
235
0
  static void ConnectRtp(TestAgent *client, TestAgent *server) {
236
0
    TransportInfo::InitAndConnect(client->audio_rtp_transport_,
237
0
                                  server->audio_rtp_transport_);
238
0
  }
239
240
0
  static void ConnectRtcp(TestAgent *client, TestAgent *server) {
241
0
    TransportInfo::InitAndConnect(client->audio_rtcp_transport_,
242
0
                                  server->audio_rtcp_transport_);
243
0
  }
244
245
0
  static void ConnectBundle(TestAgent *client, TestAgent *server) {
246
0
    TransportInfo::InitAndConnect(client->bundle_transport_,
247
0
                                  server->bundle_transport_);
248
0
  }
249
250
  virtual void CreatePipeline(bool aIsRtcpMux) = 0;
251
252
0
  void Stop() {
253
0
    MOZ_MTLOG(ML_DEBUG, "Stopping");
254
0
255
0
    if (audio_pipeline_)
256
0
      audio_pipeline_->Stop();
257
0
  }
258
259
0
  void Shutdown_s() {
260
0
    audio_rtp_transport_.Shutdown();
261
0
    audio_rtcp_transport_.Shutdown();
262
0
    bundle_transport_.Shutdown();
263
0
  }
264
265
0
  void Shutdown() {
266
0
    if (audio_pipeline_)
267
0
      audio_pipeline_->Shutdown_m();
268
0
    if (audio_stream_track_)
269
0
      audio_stream_track_->Stop();
270
0
271
0
    mozilla::SyncRunnable::DispatchToThread(
272
0
      test_utils->sts_target(),
273
0
      WrapRunnable(this, &TestAgent::Shutdown_s));
274
0
  }
275
276
0
  uint32_t GetRemoteSSRC() {
277
0
    uint32_t res = 0;
278
0
    audio_conduit_->GetRemoteSSRC(&res);
279
0
    return res;
280
0
  }
281
282
0
  uint32_t GetLocalSSRC() {
283
0
    std::vector<uint32_t> res;
284
0
    res = audio_conduit_->GetLocalSSRCs();
285
0
    return res.empty() ? 0 : res[0];
286
0
  }
287
288
0
  int GetAudioRtpCountSent() {
289
0
    return audio_pipeline_->RtpPacketsSent();
290
0
  }
291
292
0
  int GetAudioRtpCountReceived() {
293
0
    return audio_pipeline_->RtpPacketsReceived();
294
0
  }
295
296
0
  int GetAudioRtcpCountSent() {
297
0
    return audio_pipeline_->RtcpPacketsSent();
298
0
  }
299
300
0
  int GetAudioRtcpCountReceived() {
301
0
    return audio_pipeline_->RtcpPacketsReceived();
302
0
  }
303
304
305
0
  void SetUsingBundle(bool use_bundle) {
306
0
    use_bundle_ = use_bundle;
307
0
  }
308
309
 protected:
310
  mozilla::AudioCodecConfig audio_config_;
311
  RefPtr<mozilla::MediaSessionConduit> audio_conduit_;
312
  RefPtr<FakeAudioStreamTrack> audio_stream_track_;
313
  // TODO(bcampen@mozilla.com): Right now this does not let us test RTCP in
314
  // both directions; only the sender's RTCP is sent, but the receiver should
315
  // be sending it too.
316
  RefPtr<mozilla::MediaPipeline> audio_pipeline_;
317
  TransportInfo audio_rtp_transport_;
318
  TransportInfo audio_rtcp_transport_;
319
  TransportInfo bundle_transport_;
320
  bool use_bundle_;
321
};
322
323
class TestAgentSend : public TestAgent {
324
 public:
325
0
  TestAgentSend() {
326
0
    mozilla::MediaConduitErrorCode err =
327
0
        static_cast<mozilla::AudioSessionConduit *>(audio_conduit_.get())->
328
0
        ConfigureSendMediaCodec(&audio_config_);
329
0
    EXPECT_EQ(mozilla::kMediaConduitNoError, err);
330
0
331
0
    audio_stream_track_ = new FakeAudioStreamTrack();
332
0
  }
333
334
0
  virtual void CreatePipeline(bool aIsRtcpMux) {
335
0
336
0
    std::string test_pc;
337
0
338
0
    if (aIsRtcpMux) {
339
0
      ASSERT_FALSE(audio_rtcp_transport_.flow_);
340
0
    }
341
0
342
0
    RefPtr<MediaPipelineTransmit> audio_pipeline =
343
0
      new mozilla::MediaPipelineTransmit(
344
0
        test_pc,
345
0
        nullptr,
346
0
        test_utils->sts_target(),
347
0
        false,
348
0
        audio_conduit_);
349
0
350
0
    audio_pipeline->SetTrack(audio_stream_track_.get());
351
0
    audio_pipeline->Start();
352
0
353
0
    audio_pipeline_ = audio_pipeline;
354
0
355
0
    RefPtr<TransportFlow> rtp(audio_rtp_transport_.flow_);
356
0
    RefPtr<TransportFlow> rtcp(audio_rtcp_transport_.flow_);
357
0
358
0
    if (use_bundle_) {
359
0
      rtp = bundle_transport_.flow_;
360
0
      rtcp = nullptr;
361
0
    }
362
0
363
0
    audio_pipeline_->UpdateTransport_m(
364
0
        rtp, rtcp, nsAutoPtr<MediaPipelineFilter>(nullptr));
365
0
  }
366
};
367
368
369
class TestAgentReceive : public TestAgent {
370
 public:
371
372
0
  TestAgentReceive() {
373
0
    std::vector<mozilla::AudioCodecConfig *> codecs;
374
0
    codecs.push_back(&audio_config_);
375
0
376
0
    mozilla::MediaConduitErrorCode err =
377
0
        static_cast<mozilla::AudioSessionConduit *>(audio_conduit_.get())->
378
0
        ConfigureRecvMediaCodecs(codecs);
379
0
    EXPECT_EQ(mozilla::kMediaConduitNoError, err);
380
0
  }
381
382
0
  virtual void CreatePipeline(bool aIsRtcpMux) {
383
0
    std::string test_pc;
384
0
385
0
    if (aIsRtcpMux) {
386
0
      ASSERT_FALSE(audio_rtcp_transport_.flow_);
387
0
    }
388
0
389
0
    audio_pipeline_ = new mozilla::MediaPipelineReceiveAudio(
390
0
        test_pc,
391
0
        nullptr,
392
0
        test_utils->sts_target(),
393
0
        static_cast<mozilla::AudioSessionConduit *>(audio_conduit_.get()),
394
0
        nullptr);
395
0
396
0
    audio_pipeline_->Start();
397
0
398
0
    RefPtr<TransportFlow> rtp(audio_rtp_transport_.flow_);
399
0
    RefPtr<TransportFlow> rtcp(audio_rtcp_transport_.flow_);
400
0
401
0
    if (use_bundle_) {
402
0
      rtp = bundle_transport_.flow_;
403
0
      rtcp = nullptr;
404
0
    }
405
0
406
0
    audio_pipeline_->UpdateTransport_m(rtp, rtcp, bundle_filter_);
407
0
  }
408
409
0
  void SetBundleFilter(nsAutoPtr<MediaPipelineFilter> filter) {
410
0
    bundle_filter_ = filter;
411
0
  }
412
413
  void UpdateFilter_s(
414
0
      nsAutoPtr<MediaPipelineFilter> filter) {
415
0
    audio_pipeline_->UpdateTransport_s(audio_rtp_transport_.flow_,
416
0
                                       audio_rtcp_transport_.flow_,
417
0
                                       filter);
418
0
  }
419
420
 private:
421
  nsAutoPtr<MediaPipelineFilter> bundle_filter_;
422
};
423
424
425
class MediaPipelineTest : public ::testing::Test {
426
 public:
427
0
  ~MediaPipelineTest() {
428
0
    p1_.Shutdown();
429
0
    p2_.Shutdown();
430
0
  }
431
432
0
  static void SetUpTestCase() {
433
0
    test_utils = new MtransportTestUtils();
434
0
    NSS_NoDB_Init(nullptr);
435
0
    NSS_SetDomesticPolicy();
436
0
  }
437
438
  // Setup transport.
439
0
  void InitTransports(bool aIsRtcpMux) {
440
0
    // RTP, p1_ is server, p2_ is client
441
0
    mozilla::SyncRunnable::DispatchToThread(
442
0
      test_utils->sts_target(),
443
0
      WrapRunnableNM(&TestAgent::ConnectRtp, &p2_, &p1_));
444
0
445
0
    // Create RTCP flows separately if we are not muxing them.
446
0
    if(!aIsRtcpMux) {
447
0
      // RTCP, p1_ is server, p2_ is client
448
0
      mozilla::SyncRunnable::DispatchToThread(
449
0
        test_utils->sts_target(),
450
0
        WrapRunnableNM(&TestAgent::ConnectRtcp, &p2_, &p1_));
451
0
    }
452
0
453
0
    // BUNDLE, p1_ is server, p2_ is client
454
0
    mozilla::SyncRunnable::DispatchToThread(
455
0
      test_utils->sts_target(),
456
0
      WrapRunnableNM(&TestAgent::ConnectBundle, &p2_, &p1_));
457
0
  }
458
459
  // Verify RTP and RTCP
460
  void TestAudioSend(bool aIsRtcpMux,
461
                     nsAutoPtr<MediaPipelineFilter> initialFilter =
462
                        nsAutoPtr<MediaPipelineFilter>(nullptr),
463
                     nsAutoPtr<MediaPipelineFilter> refinedFilter =
464
                        nsAutoPtr<MediaPipelineFilter>(nullptr),
465
                     unsigned int ms_until_filter_update = 500,
466
0
                     unsigned int ms_of_traffic_after_answer = 10000) {
467
0
468
0
    bool bundle = !!(initialFilter);
469
0
    // We do not support testing bundle without rtcp mux, since that doesn't
470
0
    // make any sense.
471
0
    ASSERT_FALSE(!aIsRtcpMux && bundle);
472
0
473
0
    p2_.SetBundleFilter(initialFilter);
474
0
475
0
    // Setup transport flows
476
0
    InitTransports(aIsRtcpMux);
477
0
478
0
    p1_.CreatePipeline(aIsRtcpMux);
479
0
    p2_.CreatePipeline(aIsRtcpMux);
480
0
481
0
    if (bundle) {
482
0
      PR_Sleep(ms_until_filter_update);
483
0
484
0
      // Leaving refinedFilter not set implies we want to just update with
485
0
      // the other side's SSRC
486
0
      if (!refinedFilter) {
487
0
        refinedFilter = new MediaPipelineFilter;
488
0
        // Might not be safe, strictly speaking.
489
0
        refinedFilter->AddRemoteSSRC(p1_.GetLocalSSRC());
490
0
      }
491
0
492
0
      mozilla::SyncRunnable::DispatchToThread(
493
0
          test_utils->sts_target(),
494
0
          WrapRunnable(&p2_,
495
0
                       &TestAgentReceive::UpdateFilter_s,
496
0
                       refinedFilter));
497
0
    }
498
0
499
0
    // wait for some RTP/RTCP tx and rx to happen
500
0
    PR_Sleep(ms_of_traffic_after_answer);
501
0
502
0
    p1_.Stop();
503
0
    p2_.Stop();
504
0
505
0
    // wait for any packets in flight to arrive
506
0
    PR_Sleep(100);
507
0
508
0
    p1_.Shutdown();
509
0
    p2_.Shutdown();
510
0
511
0
    if (!bundle) {
512
0
      // If we are filtering, allow the test-case to do this checking.
513
0
      ASSERT_GE(p1_.GetAudioRtpCountSent(), 40);
514
0
      ASSERT_EQ(p1_.GetAudioRtpCountReceived(), p2_.GetAudioRtpCountSent());
515
0
      ASSERT_EQ(p1_.GetAudioRtpCountSent(), p2_.GetAudioRtpCountReceived());
516
0
    }
517
0
518
0
    // No RTCP packets should have been dropped, because we do not filter them.
519
0
    // Calling ShutdownMedia_m on both pipelines does not stop the flow of
520
0
    // RTCP. So, we might be off by one here.
521
0
    ASSERT_LE(p2_.GetAudioRtcpCountReceived(), p1_.GetAudioRtcpCountSent());
522
0
    ASSERT_GE(p2_.GetAudioRtcpCountReceived() + 1, p1_.GetAudioRtcpCountSent());
523
0
  }
524
525
  void TestAudioReceiverBundle(bool bundle_accepted,
526
      nsAutoPtr<MediaPipelineFilter> initialFilter,
527
      nsAutoPtr<MediaPipelineFilter> refinedFilter =
528
          nsAutoPtr<MediaPipelineFilter>(nullptr),
529
      unsigned int ms_until_answer = 500,
530
0
      unsigned int ms_of_traffic_after_answer = 10000) {
531
0
    TestAudioSend(true,
532
0
                  initialFilter,
533
0
                  refinedFilter,
534
0
                  ms_until_answer,
535
0
                  ms_of_traffic_after_answer);
536
0
  }
537
protected:
538
  TestAgentSend p1_;
539
  TestAgentReceive p2_;
540
};
541
542
class MediaPipelineFilterTest : public ::testing::Test {
543
  public:
544
    bool Filter(MediaPipelineFilter& filter,
545
                int32_t correlator,
546
                uint32_t ssrc,
547
0
                uint8_t payload_type) {
548
0
549
0
      webrtc::RTPHeader header;
550
0
      header.ssrc = ssrc;
551
0
      header.payloadType = payload_type;
552
0
      return filter.Filter(header, correlator);
553
0
    }
554
};
555
556
0
TEST_F(MediaPipelineFilterTest, TestConstruct) {
557
0
  MediaPipelineFilter filter;
558
0
}
559
560
0
TEST_F(MediaPipelineFilterTest, TestDefault) {
561
0
  MediaPipelineFilter filter;
562
0
  ASSERT_FALSE(Filter(filter, 0, 233, 110));
563
0
}
564
565
0
TEST_F(MediaPipelineFilterTest, TestSSRCFilter) {
566
0
  MediaPipelineFilter filter;
567
0
  filter.AddRemoteSSRC(555);
568
0
  ASSERT_TRUE(Filter(filter, 0, 555, 110));
569
0
  ASSERT_FALSE(Filter(filter, 0, 556, 110));
570
0
}
571
572
#define SSRC(ssrc) \
573
  ((ssrc >> 24) & 0xFF), \
574
  ((ssrc >> 16) & 0xFF), \
575
  ((ssrc >> 8 ) & 0xFF), \
576
  (ssrc         & 0xFF)
577
578
#define REPORT_FRAGMENT(ssrc) \
579
  SSRC(ssrc), \
580
  0,0,0,0, \
581
  0,0,0,0, \
582
  0,0,0,0, \
583
  0,0,0,0, \
584
  0,0,0,0
585
586
#define RTCP_TYPEINFO(num_rrs, type, size) \
587
  0x80 + num_rrs, type, 0, size
588
589
0
TEST_F(MediaPipelineFilterTest, TestCorrelatorFilter) {
590
0
  MediaPipelineFilter filter;
591
0
  filter.SetCorrelator(7777);
592
0
  ASSERT_TRUE(Filter(filter, 7777, 16, 110));
593
0
  ASSERT_FALSE(Filter(filter, 7778, 17, 110));
594
0
  // This should also have resulted in the SSRC 16 being added to the filter
595
0
  ASSERT_TRUE(Filter(filter, 0, 16, 110));
596
0
  ASSERT_FALSE(Filter(filter, 0, 17, 110));
597
0
}
598
599
0
TEST_F(MediaPipelineFilterTest, TestPayloadTypeFilter) {
600
0
  MediaPipelineFilter filter;
601
0
  filter.AddUniquePT(110);
602
0
  ASSERT_TRUE(Filter(filter, 0, 555, 110));
603
0
  ASSERT_FALSE(Filter(filter, 0, 556, 111));
604
0
}
605
606
0
TEST_F(MediaPipelineFilterTest, TestSSRCMovedWithCorrelator) {
607
0
  MediaPipelineFilter filter;
608
0
  filter.SetCorrelator(7777);
609
0
  ASSERT_TRUE(Filter(filter, 7777, 555, 110));
610
0
  ASSERT_TRUE(Filter(filter, 0, 555, 110));
611
0
  ASSERT_FALSE(Filter(filter, 7778, 555, 110));
612
0
  ASSERT_FALSE(Filter(filter, 0, 555, 110));
613
0
}
614
615
0
TEST_F(MediaPipelineFilterTest, TestRemoteSDPNoSSRCs) {
616
0
  // If the remote SDP doesn't have SSRCs, right now this is a no-op and
617
0
  // there is no point of even incorporating a filter, but we make the
618
0
  // behavior consistent to avoid confusion.
619
0
  MediaPipelineFilter filter;
620
0
  filter.SetCorrelator(7777);
621
0
  filter.AddUniquePT(111);
622
0
  ASSERT_TRUE(Filter(filter, 7777, 555, 110));
623
0
624
0
  MediaPipelineFilter filter2;
625
0
626
0
  filter.Update(filter2);
627
0
628
0
  // Ensure that the old SSRC still works.
629
0
  ASSERT_TRUE(Filter(filter, 0, 555, 110));
630
0
}
631
632
0
TEST_F(MediaPipelineTest, TestAudioSendNoMux) {
633
0
  TestAudioSend(false);
634
0
}
635
636
0
TEST_F(MediaPipelineTest, TestAudioSendMux) {
637
0
  TestAudioSend(true);
638
0
}
639
640
0
TEST_F(MediaPipelineTest, TestAudioSendBundle) {
641
0
  nsAutoPtr<MediaPipelineFilter> filter(new MediaPipelineFilter);
642
0
  // These durations have to be _extremely_ long to have any assurance that
643
0
  // some RTCP will be sent at all. This is because the first RTCP packet
644
0
  // is sometimes sent before the transports are ready, which causes it to
645
0
  // be dropped.
646
0
  TestAudioReceiverBundle(true,
647
0
                          filter,
648
0
  // We do not specify the filter for the remote description, so it will be
649
0
  // set to something sane after a short time.
650
0
                          nsAutoPtr<MediaPipelineFilter>(),
651
0
                          10000,
652
0
                          10000);
653
0
654
0
  // Some packets should have been dropped, but not all
655
0
  ASSERT_GT(p1_.GetAudioRtpCountSent(), p2_.GetAudioRtpCountReceived());
656
0
  ASSERT_GT(p2_.GetAudioRtpCountReceived(), 40);
657
0
  ASSERT_GT(p1_.GetAudioRtcpCountSent(), 1);
658
0
}
659
660
0
TEST_F(MediaPipelineTest, TestAudioSendEmptyBundleFilter) {
661
0
  nsAutoPtr<MediaPipelineFilter> filter(new MediaPipelineFilter);
662
0
  nsAutoPtr<MediaPipelineFilter> bad_answer_filter(new MediaPipelineFilter);
663
0
  TestAudioReceiverBundle(true, filter, bad_answer_filter);
664
0
  // Filter is empty, so should drop everything.
665
0
  ASSERT_EQ(0, p2_.GetAudioRtpCountReceived());
666
0
}
667
668
}  // end namespace