tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

mediapipeline_unittest.cpp (28034B)


      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 "logging.h"
      8 #include "nss.h"
      9 #include "ssl.h"
     10 
     11 #include "api/audio/builtin_audio_processing_builder.h"
     12 #include "api/audio_codecs/builtin_audio_decoder_factory.h"
     13 #include "api/environment/environment_factory.h"
     14 #include "api/scoped_refptr.h"
     15 #include "AudioSegment.h"
     16 #include "Canonicals.h"
     17 #include "modules/audio_device/include/fake_audio_device.h"
     18 #include "modules/audio_mixer/audio_mixer_impl.h"
     19 #include "modules/audio_processing/include/audio_processing.h"
     20 #include "mozilla/Mutex.h"
     21 #include "mozilla/RefPtr.h"
     22 #include "mozilla/SpinEventLoopUntil.h"
     23 #include "MediaConduitInterface.h"
     24 #include "MediaPipeline.h"
     25 #include "MediaPipelineFilter.h"
     26 #include "MediaTrackGraph.h"
     27 #include "MediaTrackListener.h"
     28 #include "mtransport_test_utils.h"
     29 #include "SharedBuffer.h"
     30 #include "MediaTransportHandler.h"
     31 #include "WebrtcCallWrapper.h"
     32 #include "WebrtcEnvironmentWrapper.h"
     33 #include "WebrtcTaskQueueWrapper.h"
     34 #include "PeerConnectionCtx.h"
     35 
     36 #define GTEST_HAS_RTTI 0
     37 #include "gtest/gtest.h"
     38 
     39 using namespace mozilla;
     40 MOZ_MTLOG_MODULE("transportbridge")
     41 
     42 static MtransportTestUtils* test_utils;
     43 
     44 namespace {
     45 class MainAsCurrent : public webrtc::TaskQueueBase {
     46 public:
     47  MainAsCurrent()
     48      : mTaskQueue(CreateWebrtcTaskQueueWrapper(
     49            do_AddRef(GetMainThreadSerialEventTarget()), "MainAsCurrent"_ns,
     50            false)),
     51        mWebrtcTaskQueue(([&] {
     52          // Shady but fine, as this raw pointer points to the WebrtcTaskQueue
     53          // owned and kept alive by mTaskQueue.
     54          webrtc::TaskQueueBase* queue{};
     55          MOZ_ALWAYS_SUCCEEDS(mTaskQueue->Dispatch(NS_NewRunnableFunction(
     56              "MainAsCurrent::Current",
     57              [&] { queue = webrtc::TaskQueueBase::Current(); })));
     58          NS_ProcessPendingEvents(nullptr);
     59          MOZ_RELEASE_ASSERT(queue);
     60          return queue;
     61        })()),
     62        mSetter(mWebrtcTaskQueue) {
     63    MOZ_RELEASE_ASSERT(NS_IsMainThread());
     64  }
     65 
     66  ~MainAsCurrent() = default;
     67 
     68  void Delete() override { delete this; }
     69 
     70  void PostTaskImpl(absl::AnyInvocable<void() &&> task,
     71                    const PostTaskTraits& traits,
     72                    const webrtc::Location& location) override {
     73    mWebrtcTaskQueue->PostTask(std::move(task), location);
     74  }
     75 
     76  void PostDelayedTaskImpl(absl::AnyInvocable<void() &&> task,
     77                           webrtc::TimeDelta delay,
     78                           const PostDelayedTaskTraits& traits,
     79                           const webrtc::Location& location) override {
     80    if (traits.high_precision) {
     81      mWebrtcTaskQueue->PostDelayedHighPrecisionTask(std::move(task), delay,
     82                                                     location);
     83      return;
     84    }
     85    mWebrtcTaskQueue->PostDelayedTask(std::move(task), delay, location);
     86  }
     87 
     88 private:
     89  RefPtr<TaskQueue> mTaskQueue;
     90  webrtc::TaskQueueBase* mWebrtcTaskQueue;
     91  CurrentTaskQueueSetter mSetter;
     92 };
     93 
     94 class FakeAudioTrack : public ProcessedMediaTrack {
     95 public:
     96  FakeAudioTrack()
     97      : ProcessedMediaTrack(44100, MediaSegment::AUDIO, nullptr),
     98        mMutex("Fake AudioTrack") {
     99    NS_NewTimerWithFuncCallback(getter_AddRefs(mTimer),
    100                                FakeAudioTrackGenerateData, this, 20,
    101                                nsITimer::TYPE_REPEATING_SLACK,
    102                                "FakeAudioTrack::FakeAudioTrackGenerateData"_ns,
    103                                test_utils->sts_target());
    104  }
    105 
    106  void Destroy() override {
    107    MutexAutoLock lock(mMutex);
    108    MOZ_RELEASE_ASSERT(!mMainThreadDestroyed);
    109    mMainThreadDestroyed = true;
    110    mTimer->Cancel();
    111    mTimer = nullptr;
    112  }
    113 
    114  void QueueSetAutoend(bool) override {}
    115 
    116  void AddListener(MediaTrackListener* aListener) override {
    117    MutexAutoLock lock(mMutex);
    118    MOZ_RELEASE_ASSERT(!mListener);
    119    mListener = aListener;
    120  }
    121 
    122  RefPtr<GenericPromise> RemoveListener(
    123      MediaTrackListener* aListener) override {
    124    MutexAutoLock lock(mMutex);
    125    MOZ_RELEASE_ASSERT(mListener == aListener);
    126    mListener = nullptr;
    127    return GenericPromise::CreateAndResolve(true, __func__);
    128  }
    129 
    130  void ProcessInput(GraphTime aFrom, GraphTime aTo, uint32_t aFlags) override {}
    131 
    132  uint32_t NumberOfChannels() const override { return NUM_CHANNELS; }
    133 
    134 private:
    135  Mutex mMutex MOZ_UNANNOTATED;
    136  MediaTrackListener* mListener = nullptr;
    137  nsCOMPtr<nsITimer> mTimer;
    138  int mCount = 0;
    139 
    140  static const int AUDIO_BUFFER_SIZE = 1600;
    141  static const int NUM_CHANNELS = 2;
    142  static void FakeAudioTrackGenerateData(nsITimer* timer, void* closure) {
    143    auto t = static_cast<FakeAudioTrack*>(closure);
    144    MutexAutoLock lock(t->mMutex);
    145    if (t->mMainThreadDestroyed) {
    146      return;
    147    }
    148    CheckedInt<size_t> bufferSize(sizeof(int16_t));
    149    bufferSize *= NUM_CHANNELS;
    150    bufferSize *= AUDIO_BUFFER_SIZE;
    151    RefPtr<SharedBuffer> samples = SharedBuffer::Create(bufferSize);
    152    int16_t* data = reinterpret_cast<int16_t*>(samples->Data());
    153    for (int i = 0; i < (AUDIO_BUFFER_SIZE * NUM_CHANNELS); i++) {
    154      // saw tooth audio sample
    155      data[i] = ((t->mCount % 8) * 4000) - (7 * 4000) / 2;
    156      t->mCount++;
    157    }
    158 
    159    AudioSegment segment;
    160    AutoTArray<const int16_t*, 1> channels;
    161    channels.AppendElement(data);
    162    segment.AppendFrames(samples.forget(), channels, AUDIO_BUFFER_SIZE,
    163                         PRINCIPAL_HANDLE_NONE);
    164 
    165    if (t->mListener) {
    166      t->mListener->NotifyQueuedChanges(nullptr, 0, segment);
    167    }
    168  }
    169 };
    170 
    171 template <typename Function>
    172 void RunOnSts(Function&& aFunction) {
    173  MOZ_ALWAYS_SUCCEEDS(test_utils->SyncDispatchToSTS(
    174      NS_NewRunnableFunction(__func__, [&] { aFunction(); })));
    175 }
    176 
    177 class LoopbackTransport : public MediaTransportHandler {
    178 public:
    179  LoopbackTransport() : MediaTransportHandler() {
    180    RunOnSts([&] {
    181      SetState("mux", TransportLayer::TS_INIT);
    182      SetRtcpState("mux", TransportLayer::TS_INIT);
    183      SetState("non-mux", TransportLayer::TS_INIT);
    184      SetRtcpState("non-mux", TransportLayer::TS_INIT);
    185    });
    186  }
    187 
    188  static void InitAndConnect(LoopbackTransport& client,
    189                             LoopbackTransport& server) {
    190    client.Connect(&server);
    191    server.Connect(&client);
    192  }
    193 
    194  void Connect(LoopbackTransport* peer) { peer_ = peer; }
    195 
    196  void Shutdown() { peer_ = nullptr; }
    197 
    198  RefPtr<IceLogPromise> GetIceLog(const nsCString& aPattern) override {
    199    return nullptr;
    200  }
    201 
    202  void ClearIceLog() override {}
    203  void EnterPrivateMode() override {}
    204  void ExitPrivateMode() override {}
    205 
    206  void CreateIceCtx(const std::string& aName) override {}
    207 
    208  nsresult SetIceConfig(const nsTArray<dom::RTCIceServer>& aIceServers,
    209                        dom::RTCIceTransportPolicy aIcePolicy) override {
    210    return NS_OK;
    211  }
    212 
    213  void Destroy() override {}
    214 
    215  // We will probably be able to move the proxy lookup stuff into
    216  // this class once we move mtransport to its own process.
    217  void SetProxyConfig(NrSocketProxyConfig&& aProxyConfig) override {}
    218 
    219  void EnsureProvisionalTransport(const std::string& aTransportId,
    220                                  const std::string& aLocalUfrag,
    221                                  const std::string& aLocalPwd,
    222                                  int aComponentCount) override {}
    223 
    224  void SetTargetForDefaultLocalAddressLookup(const std::string& aTargetIp,
    225                                             uint16_t aTargetPort) override {}
    226 
    227  // We set default-route-only as late as possible because it depends on what
    228  // capture permissions have been granted on the window, which could easily
    229  // change between Init (ie; when the PC is created) and StartIceGathering
    230  // (ie; when we set the local description).
    231  void StartIceGathering(bool aDefaultRouteOnly, bool aObfuscateAddresses,
    232                         // TODO: It probably makes sense to look
    233                         // this up internally
    234                         const nsTArray<NrIceStunAddr>& aStunAddrs) override {}
    235 
    236  void ActivateTransport(
    237      const std::string& aTransportId, const std::string& aLocalUfrag,
    238      const std::string& aLocalPwd, size_t aComponentCount,
    239      const std::string& aUfrag, const std::string& aPassword,
    240      const nsTArray<uint8_t>& aKeyDer, const nsTArray<uint8_t>& aCertDer,
    241      SSLKEAType aAuthType, bool aDtlsClient, const DtlsDigestList& aDigests,
    242      bool aPrivacyRequested) override {}
    243 
    244  void RemoveTransportsExcept(
    245      const std::set<std::string>& aTransportIds) override {}
    246 
    247  void StartIceChecks(bool aIsControlling,
    248                      const std::vector<std::string>& aIceOptions) override {}
    249 
    250  void AddIceCandidate(const std::string& aTransportId,
    251                       const std::string& aCandidate, const std::string& aUfrag,
    252                       const std::string& aObfuscatedAddress) override {}
    253 
    254  void UpdateNetworkState(bool aOnline) override {}
    255 
    256  RefPtr<dom::RTCStatsPromise> GetIceStats(const std::string& aTransportId,
    257                                           DOMHighResTimeStamp aNow) override {
    258    return nullptr;
    259  }
    260 
    261  void SendPacket(const std::string& aTransportId,
    262                  MediaPacket&& aPacket) override {
    263    peer_->LoopbackPacketReceived(aTransportId, aPacket);
    264  }
    265 
    266  void SetState(const std::string& aTransportId, TransportLayer::State aState) {
    267    MediaTransportHandler::OnStateChange(aTransportId, aState);
    268  }
    269 
    270  void SetRtcpState(const std::string& aTransportId,
    271                    TransportLayer::State aState) {
    272    MediaTransportHandler::OnRtcpStateChange(aTransportId, aState);
    273  }
    274 
    275  void LoopbackPacketReceived(const std::string& aTransportId,
    276                              const MediaPacket& aPacket) {
    277    if (aPacket.len() && aPacket.type() == MediaPacket::RTCP) {
    278      ++rtcp_packets_received_;
    279    }
    280    mRtpPacketReceived.Notify(aTransportId, aPacket);
    281  }
    282 
    283  int RtcpPacketsReceived() const { return rtcp_packets_received_; }
    284 
    285 private:
    286  RefPtr<LoopbackTransport> peer_;
    287  std::atomic<int> rtcp_packets_received_{0};
    288 };
    289 
    290 struct MediaPipelineTestOptions {
    291  bool is_rtcp_mux = true;
    292  bool activate_receive = true;
    293  unsigned int ms_until_filter_update = 500;
    294  unsigned int ms_of_traffic_after_answer = 10000;
    295 };
    296 
    297 class TestAgent {
    298 public:
    299  explicit TestAgent(const RefPtr<WebrtcEnvironmentWrapper>& aEnvWrapper,
    300                     const RefPtr<SharedWebrtcState>& aSharedState)
    301      : control_(aSharedState->mCallWorkerThread),
    302        audio_config_(109, "opus", 48000, 2, false),
    303        call_(WebrtcCallWrapper::Create(
    304            aEnvWrapper, mozilla::dom::RTCStatsTimestampMaker::Create(),
    305            nullptr, aSharedState)),
    306        audio_conduit_(
    307            AudioSessionConduit::Create(call_, test_utils->sts_target())),
    308        transport_(new LoopbackTransport) {
    309    (void)WaitFor(InvokeAsync(call_->mCallThread, __func__, [&] {
    310      audio_conduit_->InitControl(&control_);
    311      return GenericPromise::CreateAndResolve(true, "TestAgent()");
    312    }));
    313  }
    314 
    315  static void Connect(TestAgent* client, TestAgent* server) {
    316    LoopbackTransport::InitAndConnect(*client->transport_, *server->transport_);
    317  }
    318 
    319  virtual void CreatePipeline(const std::string& aTransportId,
    320                              const MediaPipelineTestOptions& aOptions) = 0;
    321 
    322  void SetState_s(const std::string& aTransportId,
    323                  TransportLayer::State aState) {
    324    transport_->SetState(aTransportId, aState);
    325  }
    326 
    327  void SetRtcpState_s(const std::string& aTransportId,
    328                      TransportLayer::State aState) {
    329    transport_->SetRtcpState(aTransportId, aState);
    330  }
    331 
    332  void UpdateTransport_s(const std::string& aTransportId,
    333                         UniquePtr<MediaPipelineFilter>&& aFilter) {
    334    audio_pipeline_->UpdateTransport_s(aTransportId, std::move(aFilter), false);
    335  }
    336 
    337  void Stop() {
    338    MOZ_MTLOG(ML_DEBUG, "Stopping");
    339 
    340    control_.Update([](auto& aControl) {
    341      aControl.mTransmitting = false;
    342      aControl.mReceiving = false;
    343    });
    344  }
    345 
    346  void Shutdown_s() { transport_->Shutdown(); }
    347 
    348  void Shutdown() {
    349    if (audio_pipeline_) {
    350      audio_pipeline_->Shutdown();
    351    }
    352    if (audio_conduit_) {
    353      (void)WaitFor(audio_conduit_->Shutdown());
    354    }
    355    if (call_) {
    356      call_->Destroy();
    357    }
    358    if (audio_track_) {
    359      audio_track_->Destroy();
    360      audio_track_ = nullptr;
    361    }
    362 
    363    test_utils->SyncDispatchToSTS(WrapRunnable(this, &TestAgent::Shutdown_s));
    364  }
    365 
    366  uint32_t GetRemoteSSRC() {
    367    return audio_conduit_->GetRemoteSSRC().valueOr(0);
    368  }
    369 
    370  uint32_t GetLocalSSRC() {
    371    std::vector<uint32_t> res;
    372    res = audio_conduit_->GetLocalSSRCs();
    373    return res.empty() ? 0 : res[0];
    374  }
    375 
    376  int GetAudioRtpCountSent() { return audio_pipeline_->RtpPacketsSent(); }
    377 
    378  int GetAudioRtpCountReceived() {
    379    return audio_pipeline_->RtpPacketsReceived();
    380  }
    381 
    382  int GetAudioRtcpCountSent() { return audio_pipeline_->RtcpPacketsSent(); }
    383 
    384  int GetAudioRtcpCountReceived() { return transport_->RtcpPacketsReceived(); }
    385 
    386 protected:
    387  ConcreteControl control_;
    388  AudioCodecConfig audio_config_;
    389  RefPtr<WebrtcCallWrapper> call_;
    390  RefPtr<AudioSessionConduit> audio_conduit_;
    391  RefPtr<FakeAudioTrack> audio_track_;
    392  // TODO(bcampen@mozilla.com): Right now this does not let us test RTCP in
    393  // both directions; only the sender's RTCP is sent, but the receiver should
    394  // be sending it too.
    395  RefPtr<MediaPipeline> audio_pipeline_;
    396  RefPtr<LoopbackTransport> transport_;
    397 };
    398 
    399 class TestAgentSend : public TestAgent {
    400 public:
    401  explicit TestAgentSend(const RefPtr<WebrtcEnvironmentWrapper>& aEnvWrapper,
    402                         const RefPtr<SharedWebrtcState>& aSharedState)
    403      : TestAgent(aEnvWrapper, aSharedState) {
    404    control_.Update([&](auto& aControl) {
    405      aControl.mAudioSendCodec = Some(audio_config_);
    406    });
    407    audio_track_ = new FakeAudioTrack();
    408  }
    409 
    410  virtual void CreatePipeline(const std::string& aTransportId,
    411                              const MediaPipelineTestOptions& aOptions) {
    412    std::string test_pc;
    413 
    414    RefPtr<MediaPipelineTransmit> audio_pipeline =
    415        MediaPipelineTransmit::Create(
    416            test_pc, transport_, AbstractThread::MainThread(),
    417            test_utils->sts_target(), false, audio_conduit_);
    418    (void)WaitFor(InvokeAsync(call_->mCallThread, __func__, [&] {
    419      audio_pipeline->InitControl(&control_);
    420      return GenericPromise::CreateAndResolve(true, __func__);
    421    }));
    422 
    423    audio_pipeline->SetSendTrackOverride(audio_track_);
    424    control_.Update([](auto& aControl) { aControl.mTransmitting = true; });
    425    audio_pipeline->UpdateTransport_m(aTransportId, nullptr, true);
    426    audio_pipeline_ = audio_pipeline;
    427  }
    428 };
    429 
    430 class TestAgentReceive : public TestAgent {
    431 public:
    432  explicit TestAgentReceive(const RefPtr<WebrtcEnvironmentWrapper>& aEnvWrapper,
    433                            const RefPtr<SharedWebrtcState>& aSharedState)
    434      : TestAgent(aEnvWrapper, aSharedState) {
    435    control_.Update([&](auto& aControl) {
    436      std::vector<AudioCodecConfig> codecs;
    437      codecs.push_back(audio_config_);
    438      aControl.mAudioRecvCodecs = codecs;
    439    });
    440  }
    441 
    442  virtual void CreatePipeline(const std::string& aTransportId,
    443                              const MediaPipelineTestOptions& aOptions) {
    444    std::string test_pc;
    445 
    446    auto audio_pipeline = MakeRefPtr<MediaPipelineReceiveAudio>(
    447        test_pc, transport_, AbstractThread::MainThread(),
    448        test_utils->sts_target(),
    449        static_cast<AudioSessionConduit*>(audio_conduit_.get()), nullptr,
    450        TrackingId(), PRINCIPAL_HANDLE_NONE, PrincipalPrivacy::NonPrivate);
    451    (void)WaitFor(InvokeAsync(call_->mCallThread, __func__, [&] {
    452      audio_pipeline->InitControl(&control_);
    453      return GenericPromise::CreateAndResolve(true, __func__);
    454    }));
    455 
    456    control_.Update([activate = aOptions.activate_receive](auto& aControl) {
    457      aControl.mReceiving = activate;
    458    });
    459    audio_pipeline->UpdateTransport_m(aTransportId, std::move(bundle_filter_),
    460                                      true);
    461    audio_pipeline_ = audio_pipeline;
    462  }
    463 
    464  void SetBundleFilter(UniquePtr<MediaPipelineFilter>&& filter) {
    465    bundle_filter_ = std::move(filter);
    466  }
    467 
    468  void UpdateTransport_s(const std::string& aTransportId,
    469                         UniquePtr<MediaPipelineFilter>&& filter) {
    470    audio_pipeline_->UpdateTransport_s(aTransportId, std::move(filter), false);
    471  }
    472 
    473 private:
    474  UniquePtr<MediaPipelineFilter> bundle_filter_;
    475 };
    476 
    477 void WaitFor(TimeDuration aDuration) {
    478  bool done = false;
    479  NS_DelayedDispatchToCurrentThread(
    480      NS_NewRunnableFunction(__func__, [&] { done = true; }),
    481      aDuration.ToMilliseconds());
    482  SpinEventLoopUntil<ProcessFailureBehavior::IgnoreAndContinue>(
    483      "WaitFor(TimeDuration aDuration)"_ns, [&] { return done; });
    484 }
    485 
    486 webrtc::AudioState::Config CreateAudioStateConfig(
    487    const webrtc::Environment& aEnv) {
    488  webrtc::AudioState::Config audio_state_config;
    489  audio_state_config.audio_mixer = webrtc::AudioMixerImpl::Create();
    490 
    491  webrtc::BuiltinAudioProcessingBuilder audio_processing_builder;
    492  audio_state_config.audio_processing = audio_processing_builder.Build(aEnv);
    493  audio_state_config.audio_device_module = new webrtc::FakeAudioDeviceModule();
    494  return audio_state_config;
    495 }
    496 
    497 class MediaPipelineTest : public ::testing::Test {
    498 public:
    499  explicit MediaPipelineTest(MediaPipelineTestOptions options = {})
    500      : main_task_queue_(
    501            std::unique_ptr<webrtc::TaskQueueBase, webrtc::TaskQueueDeleter>(
    502                new MainAsCurrent())),
    503        options_(options),
    504        env_wrapper_(WebrtcEnvironmentWrapper::Create(
    505            mozilla::dom::RTCStatsTimestampMaker::Create())),
    506        shared_state_(MakeAndAddRef<SharedWebrtcState>(
    507            AbstractThread::MainThread(),
    508            CreateAudioStateConfig(env_wrapper_->Environment()),
    509            already_AddRefed(
    510                webrtc::CreateBuiltinAudioDecoderFactory().release()),
    511            WrapUnique(new webrtc::MozTrialsConfig()))),
    512        p1_(env_wrapper_, shared_state_),
    513        p2_(env_wrapper_, shared_state_) {}
    514 
    515  ~MediaPipelineTest() {
    516    p1_.Shutdown();
    517    p2_.Shutdown();
    518  }
    519 
    520  static void SetUpTestCase() {
    521    test_utils = new MtransportTestUtils();
    522    NSS_NoDB_Init(nullptr);
    523    NSS_SetDomesticPolicy();
    524  }
    525 
    526  // Setup transport.
    527  void InitTransports() {
    528    test_utils->SyncDispatchToSTS(
    529        WrapRunnableNM(&TestAgent::Connect, &p2_, &p1_));
    530  }
    531 
    532  // Verify RTP and RTCP
    533  void TestAudioSend(MediaPipelineTestOptions options,
    534                     UniquePtr<MediaPipelineFilter>&& initialFilter = nullptr,
    535                     UniquePtr<MediaPipelineFilter>&& refinedFilter = nullptr) {
    536    bool bundle = !!(initialFilter);
    537    // We do not support testing bundle without rtcp mux, since that doesn't
    538    // make any sense.
    539    ASSERT_FALSE(!options.is_rtcp_mux && bundle);
    540 
    541    p2_.SetBundleFilter(std::move(initialFilter));
    542 
    543    // Setup transport flows
    544    InitTransports();
    545 
    546    std::string transportId = options.is_rtcp_mux ? "mux" : "non-mux";
    547    p1_.CreatePipeline(transportId, options);
    548    p2_.CreatePipeline(transportId, options);
    549 
    550    // Set state of transports to CONNECTING. MediaPipeline doesn't really care
    551    // about this transition, but we're trying to simluate what happens in a
    552    // real case.
    553    RunOnSts([&] {
    554      p1_.SetState_s(transportId, TransportLayer::TS_CONNECTING);
    555      p1_.SetRtcpState_s(transportId, TransportLayer::TS_CONNECTING);
    556      p2_.SetState_s(transportId, TransportLayer::TS_CONNECTING);
    557      p2_.SetRtcpState_s(transportId, TransportLayer::TS_CONNECTING);
    558    });
    559 
    560    WaitFor(TimeDuration::FromMilliseconds(10));
    561 
    562    // Set state of transports to OPEN (ie; connected). This should result in
    563    // media flowing.
    564    RunOnSts([&] {
    565      p1_.SetState_s(transportId, TransportLayer::TS_OPEN);
    566      p1_.SetRtcpState_s(transportId, TransportLayer::TS_OPEN);
    567      p2_.SetState_s(transportId, TransportLayer::TS_OPEN);
    568      p2_.SetRtcpState_s(transportId, TransportLayer::TS_OPEN);
    569    });
    570 
    571    if (bundle) {
    572      WaitFor(TimeDuration::FromMilliseconds(options.ms_until_filter_update));
    573 
    574      // Leaving refinedFilter not set implies we want to just update with
    575      // the other side's SSRC
    576      if (!refinedFilter) {
    577        refinedFilter = MakeUnique<MediaPipelineFilter>();
    578        // Might not be safe, strictly speaking.
    579        refinedFilter->AddRemoteSSRC(p1_.GetLocalSSRC());
    580      }
    581 
    582      RunOnSts([&] {
    583        p2_.UpdateTransport_s(transportId, std::move(refinedFilter));
    584      });
    585    }
    586 
    587    // wait for some RTP/RTCP tx and rx to happen
    588    WaitFor(TimeDuration::FromMilliseconds(options.ms_of_traffic_after_answer));
    589 
    590    p1_.Stop();
    591    p2_.Stop();
    592 
    593    // wait for any packets in flight to arrive
    594    WaitFor(TimeDuration::FromMilliseconds(200));
    595 
    596    p1_.Shutdown();
    597    p2_.Shutdown();
    598 
    599    if (!bundle) {
    600      // If we are filtering, allow the test-case to do this checking.
    601      ASSERT_GE(p1_.GetAudioRtpCountSent(), 40);
    602      ASSERT_EQ(p1_.GetAudioRtpCountReceived(), p2_.GetAudioRtpCountSent());
    603      ASSERT_EQ(p1_.GetAudioRtpCountSent(), p2_.GetAudioRtpCountReceived());
    604    }
    605 
    606    // No RTCP packets should have been dropped, because we do not filter them.
    607    // Calling ShutdownMedia_m on both pipelines does not stop the flow of
    608    // RTCP. So, we might be off by one here.
    609    ASSERT_LE(p2_.GetAudioRtcpCountReceived(), p1_.GetAudioRtcpCountSent());
    610    ASSERT_GE(p2_.GetAudioRtcpCountReceived() + 1, p1_.GetAudioRtcpCountSent());
    611  }
    612 
    613  void TestAudioReceiverBundle(
    614      UniquePtr<MediaPipelineFilter>&& initialFilter,
    615      UniquePtr<MediaPipelineFilter>&& refinedFilter = nullptr,
    616      MediaPipelineTestOptions options = {}) {
    617    TestAudioSend(options, std::move(initialFilter), std::move(refinedFilter));
    618  }
    619 
    620 protected:
    621  // main_task_queue_ has this type to make sure it goes through Delete() when
    622  // we're destroyed.
    623  std::unique_ptr<webrtc::TaskQueueBase, webrtc::TaskQueueDeleter>
    624      main_task_queue_;
    625  const MediaPipelineTestOptions options_;
    626  const RefPtr<WebrtcEnvironmentWrapper> env_wrapper_;
    627  const RefPtr<SharedWebrtcState> shared_state_;
    628  TestAgentSend p1_;
    629  TestAgentReceive p2_;
    630 };
    631 
    632 class MediaPipelineFilterTest : public ::testing::Test {
    633 public:
    634  bool Filter(MediaPipelineFilter& filter, uint32_t ssrc, uint8_t payload_type,
    635              const Maybe<std::string>& mid = Nothing()) {
    636    webrtc::RTPHeader header;
    637    header.ssrc = ssrc;
    638    header.payloadType = payload_type;
    639    mid.apply([&](const auto& mid) { header.extension.mid = mid; });
    640    return filter.Filter(header);
    641  }
    642 };
    643 
    644 TEST_F(MediaPipelineFilterTest, TestConstruct) { MediaPipelineFilter filter; }
    645 
    646 TEST_F(MediaPipelineFilterTest, TestDefault) {
    647  MediaPipelineFilter filter;
    648  EXPECT_FALSE(Filter(filter, 233, 110));
    649 }
    650 
    651 TEST_F(MediaPipelineFilterTest, TestSSRCFilter) {
    652  MediaPipelineFilter filter;
    653  filter.AddRemoteSSRC(555);
    654  EXPECT_TRUE(Filter(filter, 555, 110));
    655  EXPECT_FALSE(Filter(filter, 556, 110));
    656 }
    657 
    658 TEST_F(MediaPipelineFilterTest, TestSSRCFilterOverridesPayloadTypeFilter) {
    659  MediaPipelineFilter filter;
    660  filter.AddRemoteSSRC(555);
    661  filter.AddUniqueReceivePT(110);
    662  // We have a configured ssrc but still need to allow payload type matching.
    663  EXPECT_TRUE(Filter(filter, 556, 110));
    664  EXPECT_TRUE(Filter(filter, 555, 110));
    665 }
    666 
    667 #define SSRC(ssrc)                                                    \
    668  ((ssrc >> 24) & 0xFF), ((ssrc >> 16) & 0xFF), ((ssrc >> 8) & 0xFF), \
    669      (ssrc & 0xFF)
    670 #define REPORT_FRAGMENT(ssrc) \
    671  SSRC(ssrc), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
    672 
    673 #define RTCP_TYPEINFO(num_rrs, type, size) 0x80 + num_rrs, type, 0, size
    674 
    675 TEST_F(MediaPipelineFilterTest, TestMidFilter) {
    676  MediaPipelineFilter filter;
    677  const auto mid = Some(std::string("mid0"));
    678  filter.SetRemoteMediaStreamId(mid);
    679 
    680  EXPECT_FALSE(Filter(filter, 16, 110));
    681  EXPECT_TRUE(Filter(filter, 16, 110, mid));
    682  EXPECT_TRUE(Filter(filter, 16, 110));
    683  EXPECT_FALSE(Filter(filter, 17, 110));
    684 
    685  // The mid filter maintains a set of SSRCs. Adding a new SSRC should work
    686  // and still allow previous SSRCs to work. Unrecognized SSRCs should still be
    687  // filtered out.
    688  EXPECT_TRUE(Filter(filter, 18, 111, mid));
    689  EXPECT_TRUE(Filter(filter, 18, 111));
    690  EXPECT_TRUE(Filter(filter, 16, 110));
    691  EXPECT_FALSE(Filter(filter, 17, 110));
    692 }
    693 
    694 TEST_F(MediaPipelineFilterTest, TestPayloadTypeFilter) {
    695  MediaPipelineFilter filter;
    696  filter.AddUniqueReceivePT(110);
    697  EXPECT_TRUE(Filter(filter, 555, 110));
    698  EXPECT_FALSE(Filter(filter, 556, 111));
    699  // Matching based on unique payload type causes us to learn the ssrc.
    700  EXPECT_TRUE(Filter(filter, 555, 98));
    701  // Once we have learned an SSRC we still need to learn new ones
    702  // based on payload type.
    703  EXPECT_TRUE(Filter(filter, 557, 110));
    704 }
    705 
    706 TEST_F(MediaPipelineFilterTest, TestSSRCMovedWithMid) {
    707  MediaPipelineFilter filter;
    708  const auto mid0 = Some(std::string("mid0"));
    709  const auto mid1 = Some(std::string("mid1"));
    710  filter.SetRemoteMediaStreamId(mid0);
    711  ASSERT_TRUE(Filter(filter, 555, 110, mid0));
    712  ASSERT_TRUE(Filter(filter, 555, 110));
    713  // Present a new MID binding
    714  ASSERT_FALSE(Filter(filter, 555, 110, mid1));
    715  ASSERT_FALSE(Filter(filter, 555, 110));
    716 }
    717 
    718 TEST_F(MediaPipelineFilterTest, TestRemoteSDPNoSSRCs) {
    719  // If the remote SDP doesn't have SSRCs, right now this is a no-op and
    720  // there is no point of even incorporating a filter, but we make the
    721  // behavior consistent to avoid confusion.
    722  MediaPipelineFilter filter;
    723  const auto mid = Some(std::string("mid0"));
    724  filter.SetRemoteMediaStreamId(mid);
    725  filter.AddUniqueReceivePT(111);
    726  EXPECT_TRUE(Filter(filter, 555, 110, mid));
    727  EXPECT_TRUE(Filter(filter, 555, 110));
    728 
    729  // Update but remember binding./
    730  MediaPipelineFilter filter2;
    731 
    732  filter.Update(filter2, true);
    733 
    734  // Ensure that the old SSRC still works.
    735  EXPECT_TRUE(Filter(filter, 555, 110));
    736 
    737  // Forget the previous binding
    738  MediaPipelineFilter filter3;
    739  filter3.SetRemoteMediaStreamId(Some(std::string("mid1")));
    740  filter.Update(filter3, true);
    741 
    742  ASSERT_FALSE(Filter(filter, 555, 110));
    743 }
    744 
    745 TEST_F(MediaPipelineTest, TestAudioSendNoMux) {
    746  TestAudioSend({.is_rtcp_mux = false});
    747 }
    748 
    749 TEST_F(MediaPipelineTest, TestAudioSendMux) {
    750  TestAudioSend({.is_rtcp_mux = true});
    751 }
    752 
    753 TEST_F(MediaPipelineTest, TestAudioSendBundle) {
    754  auto filter = MakeUnique<MediaPipelineFilter>();
    755  // These durations have to be _extremely_ long to have any assurance that
    756  // some RTCP will be sent at all. This is because the first RTCP packet
    757  // is sometimes sent before the transports are ready, which causes it to
    758  // be dropped.
    759  TestAudioReceiverBundle(
    760      std::move(filter),
    761      // We do not specify the filter for the remote description, so it will be
    762      // set to something sane after a short time.
    763      nullptr,
    764      {.ms_until_filter_update = 10000, .ms_of_traffic_after_answer = 10000});
    765 
    766  // Some packets should have been dropped, but not all
    767  ASSERT_GT(p1_.GetAudioRtpCountSent(), p2_.GetAudioRtpCountReceived());
    768  ASSERT_GT(p2_.GetAudioRtpCountReceived(), 40);
    769  ASSERT_GT(p1_.GetAudioRtcpCountSent(), 1);
    770 }
    771 
    772 TEST_F(MediaPipelineTest, TestAudioSendEmptyBundleFilter) {
    773  auto filter = MakeUnique<MediaPipelineFilter>();
    774  auto bad_answer_filter = MakeUnique<MediaPipelineFilter>();
    775  TestAudioReceiverBundle(std::move(filter), std::move(bad_answer_filter));
    776  // Filter is empty, so should drop everything.
    777  ASSERT_EQ(0, p2_.GetAudioRtpCountReceived());
    778 }
    779 
    780 TEST_F(MediaPipelineTest, TestAudioInactiveNoRecv) {
    781  auto filter = MakeUnique<MediaPipelineFilter>();
    782  TestAudioReceiverBundle(std::move(filter), nullptr,
    783                          {.activate_receive = false,
    784                           .ms_until_filter_update = 200,
    785                           .ms_of_traffic_after_answer = 800});
    786 
    787  // Packets should have been sent but not received.
    788  ASSERT_NE(p1_.GetAudioRtpCountSent(), 0);
    789  ASSERT_EQ(p2_.GetAudioRtpCountReceived(), 0);
    790 }
    791 
    792 }  // end namespace