media/webrtc/signaling/src/peerconnection/PeerConnectionMedia.cpp

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

     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 #include <string>
     6 #include "CSFLog.h"
     8 #include "nspr.h"
     9 #include "cc_constants.h"
    11 #include "nricectx.h"
    12 #include "nricemediastream.h"
    13 #include "PeerConnectionImpl.h"
    14 #include "PeerConnectionMedia.h"
    15 #include "AudioConduit.h"
    16 #include "VideoConduit.h"
    17 #include "runnable_utils.h"
    19 #ifdef MOZILLA_INTERNAL_API
    20 #include "MediaStreamList.h"
    21 #include "nsIScriptGlobalObject.h"
    22 #include "mozilla/Preferences.h"
    23 #include "mozilla/dom/RTCStatsReportBinding.h"
    24 #endif
    26 using namespace mozilla;
    27 using namespace mozilla::dom;
    29 namespace sipcc {
    31 static const char* logTag = "PeerConnectionMedia";
    32 static const mozilla::TrackID TRACK_AUDIO = 0;
    33 static const mozilla::TrackID TRACK_VIDEO = 1;
    35 /* If the ExpectAudio hint is on we will add a track at the default first
    36  * audio track ID (0)
    37  * FIX - Do we need to iterate over the tracks instead of taking these hints?
    38  */
    39 void
    40 LocalSourceStreamInfo::ExpectAudio(const mozilla::TrackID aID)
    41 {
    42   mAudioTracks.AppendElement(aID);
    43 }
    45 // If the ExpectVideo hint is on we will add a track at the default first
    46 // video track ID (1).
    47 void
    48 LocalSourceStreamInfo::ExpectVideo(const mozilla::TrackID aID)
    49 {
    50   mVideoTracks.AppendElement(aID);
    51 }
    53 unsigned
    54 LocalSourceStreamInfo::AudioTrackCount()
    55 {
    56   return mAudioTracks.Length();
    57 }
    59 unsigned
    60 LocalSourceStreamInfo::VideoTrackCount()
    61 {
    62   return mVideoTracks.Length();
    63 }
    65 void LocalSourceStreamInfo::DetachTransport_s()
    66 {
    67   ASSERT_ON_THREAD(mParent->GetSTSThread());
    68   // walk through all the MediaPipelines and call the shutdown
    69   // functions for transport. Must be on the STS thread.
    70   for (std::map<int, mozilla::RefPtr<mozilla::MediaPipeline> >::iterator it =
    71            mPipelines.begin(); it != mPipelines.end();
    72        ++it) {
    73     it->second->ShutdownTransport_s();
    74   }
    75 }
    77 void LocalSourceStreamInfo::DetachMedia_m()
    78 {
    79   ASSERT_ON_THREAD(mParent->GetMainThread());
    80   // walk through all the MediaPipelines and call the shutdown
    81   // functions. Must be on the main thread.
    82   for (std::map<int, mozilla::RefPtr<mozilla::MediaPipeline> >::iterator it =
    83            mPipelines.begin(); it != mPipelines.end();
    84        ++it) {
    85     it->second->ShutdownMedia_m();
    86   }
    87   mAudioTracks.Clear();
    88   mVideoTracks.Clear();
    89   mMediaStream = nullptr;
    90 }
    92 void RemoteSourceStreamInfo::DetachTransport_s()
    93 {
    94   ASSERT_ON_THREAD(mParent->GetSTSThread());
    95   // walk through all the MediaPipelines and call the shutdown
    96   // transport functions. Must be on the STS thread.
    97   for (std::map<int, mozilla::RefPtr<mozilla::MediaPipeline> >::iterator it =
    98            mPipelines.begin(); it != mPipelines.end();
    99        ++it) {
   100     it->second->ShutdownTransport_s();
   101   }
   102 }
   104 void RemoteSourceStreamInfo::DetachMedia_m()
   105 {
   106   ASSERT_ON_THREAD(mParent->GetMainThread());
   108   // walk through all the MediaPipelines and call the shutdown
   109   // media functions. Must be on the main thread.
   110   for (std::map<int, mozilla::RefPtr<mozilla::MediaPipeline> >::iterator it =
   111            mPipelines.begin(); it != mPipelines.end();
   112        ++it) {
   113     it->second->ShutdownMedia_m();
   114   }
   115   mMediaStream = nullptr;
   116 }
   118 already_AddRefed<PeerConnectionImpl>
   119 PeerConnectionImpl::Constructor(const dom::GlobalObject& aGlobal, ErrorResult& rv)
   120 {
   121   nsRefPtr<PeerConnectionImpl> pc = new PeerConnectionImpl(&aGlobal);
   123   CSFLogDebug(logTag, "Created PeerConnection: %p", pc.get());
   125   return pc.forget();
   126 }
   128 PeerConnectionImpl* PeerConnectionImpl::CreatePeerConnection()
   129 {
   130   PeerConnectionImpl *pc = new PeerConnectionImpl();
   132   CSFLogDebug(logTag, "Created PeerConnection: %p", pc);
   134   return pc;
   135 }
   138 PeerConnectionMedia::PeerConnectionMedia(PeerConnectionImpl *parent)
   139     : mParent(parent),
   140       mLocalSourceStreamsLock("PeerConnectionMedia.mLocalSourceStreamsLock"),
   141       mIceCtx(nullptr),
   142       mDNSResolver(new mozilla::NrIceResolver()),
   143       mMainThread(mParent->GetMainThread()),
   144       mSTSThread(mParent->GetSTSThread()) {}
   146 nsresult PeerConnectionMedia::Init(const std::vector<NrIceStunServer>& stun_servers,
   147                                    const std::vector<NrIceTurnServer>& turn_servers)
   148 {
   149   // TODO(ekr@rtfm.com): need some way to set not offerer later
   150   // Looks like a bug in the NrIceCtx API.
   151   mIceCtx = NrIceCtx::Create("PC:" + mParent->GetName(), true);
   152   if(!mIceCtx) {
   153     CSFLogError(logTag, "%s: Failed to create Ice Context", __FUNCTION__);
   154     return NS_ERROR_FAILURE;
   155   }
   156   nsresult rv;
   157   if (NS_FAILED(rv = mIceCtx->SetStunServers(stun_servers))) {
   158     CSFLogError(logTag, "%s: Failed to set stun servers", __FUNCTION__);
   159     return rv;
   160   }
   161   // Give us a way to globally turn off TURN support
   162 #ifdef MOZILLA_INTERNAL_API
   163   bool disabled = Preferences::GetBool("media.peerconnection.turn.disable", false);
   164 #else
   165   bool disabled = false;
   166 #endif
   167   if (!disabled) {
   168     if (NS_FAILED(rv = mIceCtx->SetTurnServers(turn_servers))) {
   169       CSFLogError(logTag, "%s: Failed to set turn servers", __FUNCTION__);
   170       return rv;
   171     }
   172   } else if (turn_servers.size() != 0) {
   173     CSFLogError(logTag, "%s: Setting turn servers disabled", __FUNCTION__);
   174   }
   175   if (NS_FAILED(rv = mDNSResolver->Init())) {
   176     CSFLogError(logTag, "%s: Failed to initialize dns resolver", __FUNCTION__);
   177     return rv;
   178   }
   179   if (NS_FAILED(rv = mIceCtx->SetResolver(mDNSResolver->AllocateResolver()))) {
   180     CSFLogError(logTag, "%s: Failed to get dns resolver", __FUNCTION__);
   181     return rv;
   182   }
   183   mIceCtx->SignalGatheringStateChange.connect(
   184       this,
   185       &PeerConnectionMedia::IceGatheringStateChange_s);
   186   mIceCtx->SignalConnectionStateChange.connect(
   187       this,
   188       &PeerConnectionMedia::IceConnectionStateChange_s);
   190   // Create three streams to start with.
   191   // One each for audio, video and DataChannel
   192   // TODO: this will be re-visited
   193   RefPtr<NrIceMediaStream> audioStream =
   194     mIceCtx->CreateStream((mParent->GetName()+": stream1/audio").c_str(), 2);
   195   RefPtr<NrIceMediaStream> videoStream =
   196     mIceCtx->CreateStream((mParent->GetName()+": stream2/video").c_str(), 2);
   197   RefPtr<NrIceMediaStream> dcStream =
   198     mIceCtx->CreateStream((mParent->GetName()+": stream3/data").c_str(), 2);
   200   if (!audioStream) {
   201     CSFLogError(logTag, "%s: audio stream is NULL", __FUNCTION__);
   202     return NS_ERROR_FAILURE;
   203   } else {
   204     mIceStreams.push_back(audioStream);
   205   }
   207   if (!videoStream) {
   208     CSFLogError(logTag, "%s: video stream is NULL", __FUNCTION__);
   209     return NS_ERROR_FAILURE;
   210   } else {
   211     mIceStreams.push_back(videoStream);
   212   }
   214   if (!dcStream) {
   215     CSFLogError(logTag, "%s: datachannel stream is NULL", __FUNCTION__);
   216     return NS_ERROR_FAILURE;
   217   } else {
   218     mIceStreams.push_back(dcStream);
   219   }
   221   // TODO(ekr@rtfm.com): This is not connected to the PCCimpl.
   222   // Will need to do that later.
   223   for (std::size_t i=0; i<mIceStreams.size(); i++) {
   224     mIceStreams[i]->SignalReady.connect(this, &PeerConnectionMedia::IceStreamReady);
   225   }
   227   // TODO(ekr@rtfm.com): When we have a generic error reporting mechanism,
   228   // figure out how to report that StartGathering failed. Bug 827982.
   229   RUN_ON_THREAD(mIceCtx->thread(),
   230                 WrapRunnable(mIceCtx, &NrIceCtx::StartGathering), NS_DISPATCH_NORMAL);
   232   return NS_OK;
   233 }
   235 nsresult
   236 PeerConnectionMedia::AddStream(nsIDOMMediaStream* aMediaStream, uint32_t *stream_id)
   237 {
   238   if (!aMediaStream) {
   239     CSFLogError(logTag, "%s - aMediaStream is NULL", __FUNCTION__);
   240     return NS_ERROR_FAILURE;
   241   }
   243   DOMMediaStream* stream = static_cast<DOMMediaStream*>(aMediaStream);
   245   CSFLogDebug(logTag, "%s: MediaStream: %p",
   246     __FUNCTION__, aMediaStream);
   248   // Adding tracks here based on nsDOMMediaStream expectation settings
   249   uint32_t hints = stream->GetHintContents();
   250 #ifdef MOZILLA_INTERNAL_API
   251   if (!Preferences::GetBool("media.peerconnection.video.enabled", true)) {
   252     hints &= ~(DOMMediaStream::HINT_CONTENTS_VIDEO);
   253   }
   254 #endif
   256   if (!(hints & (DOMMediaStream::HINT_CONTENTS_AUDIO |
   257         DOMMediaStream::HINT_CONTENTS_VIDEO))) {
   258     CSFLogDebug(logTag, "Empty Stream !!");
   259     return NS_OK;
   260   }
   262   // Now see if we already have a stream of this type, since we only
   263   // allow one of each.
   264   // TODO(ekr@rtfm.com): remove this when multiple of each stream
   265   // is allowed
   266   mozilla::MutexAutoLock lock(mLocalSourceStreamsLock);
   267   for (uint32_t u = 0; u < mLocalSourceStreams.Length(); u++) {
   268     nsRefPtr<LocalSourceStreamInfo> localSourceStream = mLocalSourceStreams[u];
   270     if (localSourceStream->GetMediaStream()->GetHintContents() & hints) {
   271       CSFLogError(logTag, "Only one stream of any given type allowed");
   272       return NS_ERROR_FAILURE;
   273     }
   274   }
   276   // OK, we're good to add
   277   nsRefPtr<LocalSourceStreamInfo> localSourceStream =
   278       new LocalSourceStreamInfo(stream, this);
   279   *stream_id = mLocalSourceStreams.Length();
   281   if (hints & DOMMediaStream::HINT_CONTENTS_AUDIO) {
   282     localSourceStream->ExpectAudio(TRACK_AUDIO);
   283   }
   285   if (hints & DOMMediaStream::HINT_CONTENTS_VIDEO) {
   286     localSourceStream->ExpectVideo(TRACK_VIDEO);
   287   }
   289   mLocalSourceStreams.AppendElement(localSourceStream);
   291   return NS_OK;
   292 }
   294 nsresult
   295 PeerConnectionMedia::RemoveStream(nsIDOMMediaStream* aMediaStream, uint32_t *stream_id)
   296 {
   297   MOZ_ASSERT(aMediaStream);
   299   DOMMediaStream* stream = static_cast<DOMMediaStream*>(aMediaStream);
   301   CSFLogDebug(logTag, "%s: MediaStream: %p",
   302     __FUNCTION__, aMediaStream);
   304   mozilla::MutexAutoLock lock(mLocalSourceStreamsLock);
   305   for (uint32_t u = 0; u < mLocalSourceStreams.Length(); u++) {
   306     nsRefPtr<LocalSourceStreamInfo> localSourceStream = mLocalSourceStreams[u];
   307     if (localSourceStream->GetMediaStream() == stream) {
   308       *stream_id = u;
   309       return NS_OK;
   310     }
   311   }
   313   return NS_ERROR_ILLEGAL_VALUE;
   314 }
   316 void
   317 PeerConnectionMedia::SelfDestruct()
   318 {
   319   ASSERT_ON_THREAD(mMainThread);
   321   CSFLogDebug(logTag, "%s: ", __FUNCTION__);
   323   // Shut down the media
   324   for (uint32_t i=0; i < mLocalSourceStreams.Length(); ++i) {
   325     mLocalSourceStreams[i]->DetachMedia_m();
   326   }
   328   for (uint32_t i=0; i < mRemoteSourceStreams.Length(); ++i) {
   329     mRemoteSourceStreams[i]->DetachMedia_m();
   330   }
   332   // Shutdown the transport (async)
   333   RUN_ON_THREAD(mSTSThread, WrapRunnable(
   334       this, &PeerConnectionMedia::ShutdownMediaTransport_s),
   335                 NS_DISPATCH_NORMAL);
   337   CSFLogDebug(logTag, "%s: Media shut down", __FUNCTION__);
   338 }
   340 void
   341 PeerConnectionMedia::SelfDestruct_m()
   342 {
   343   CSFLogDebug(logTag, "%s: ", __FUNCTION__);
   345   ASSERT_ON_THREAD(mMainThread);
   346   mLocalSourceStreams.Clear();
   347   mRemoteSourceStreams.Clear();
   349   // Final self-destruct.
   350   this->Release();
   351 }
   353 void
   354 PeerConnectionMedia::ShutdownMediaTransport_s()
   355 {
   356   ASSERT_ON_THREAD(mSTSThread);
   358   CSFLogDebug(logTag, "%s: ", __FUNCTION__);
   360   for (uint32_t i=0; i < mLocalSourceStreams.Length(); ++i) {
   361     mLocalSourceStreams[i]->DetachTransport_s();
   362   }
   364   for (uint32_t i=0; i < mRemoteSourceStreams.Length(); ++i) {
   365     mRemoteSourceStreams[i]->DetachTransport_s();
   366   }
   368   disconnect_all();
   369   mTransportFlows.clear();
   370   mIceStreams.clear();
   371   mIceCtx = nullptr;
   373   mMainThread->Dispatch(WrapRunnable(this, &PeerConnectionMedia::SelfDestruct_m),
   374                         NS_DISPATCH_NORMAL);
   375 }
   377 LocalSourceStreamInfo*
   378 PeerConnectionMedia::GetLocalStream(int aIndex)
   379 {
   380   if(aIndex < 0 || aIndex >= (int) mLocalSourceStreams.Length()) {
   381     return nullptr;
   382   }
   384   MOZ_ASSERT(mLocalSourceStreams[aIndex]);
   385   return mLocalSourceStreams[aIndex];
   386 }
   388 RemoteSourceStreamInfo*
   389 PeerConnectionMedia::GetRemoteStream(int aIndex)
   390 {
   391   if(aIndex < 0 || aIndex >= (int) mRemoteSourceStreams.Length()) {
   392     return nullptr;
   393   }
   395   MOZ_ASSERT(mRemoteSourceStreams[aIndex]);
   396   return mRemoteSourceStreams[aIndex];
   397 }
   399 bool
   400 PeerConnectionMedia::SetUsingBundle_m(int level, bool decision)
   401 {
   402   ASSERT_ON_THREAD(mMainThread);
   403   for (size_t i = 0; i < mRemoteSourceStreams.Length(); ++i) {
   404     if (mRemoteSourceStreams[i]->SetUsingBundle_m(level, decision)) {
   405       // Found the MediaPipeline for |level|
   406       return true;
   407     }
   408   }
   409   CSFLogWarn(logTag, "Could not locate level %d to set bundle flag to %s",
   410                      static_cast<int>(level),
   411                      decision ? "true" : "false");
   412   return false;
   413 }
   415 static void
   416 UpdateFilterFromRemoteDescription_s(
   417   RefPtr<mozilla::MediaPipeline> receive,
   418   RefPtr<mozilla::MediaPipeline> transmit,
   419   nsAutoPtr<mozilla::MediaPipelineFilter> filter) {
   421   // Update filter, and make a copy of the final version.
   422   mozilla::MediaPipelineFilter *finalFilter(
   423     receive->UpdateFilterFromRemoteDescription_s(filter));
   425   if (finalFilter) {
   426     filter = new mozilla::MediaPipelineFilter(*finalFilter);
   427   }
   429   // Set same filter on transmit pipeline too.
   430   transmit->UpdateFilterFromRemoteDescription_s(filter);
   431 }
   433 bool
   434 PeerConnectionMedia::UpdateFilterFromRemoteDescription_m(
   435     int level,
   436     nsAutoPtr<mozilla::MediaPipelineFilter> filter)
   437 {
   438   ASSERT_ON_THREAD(mMainThread);
   440   RefPtr<mozilla::MediaPipeline> receive;
   441   for (size_t i = 0; !receive && i < mRemoteSourceStreams.Length(); ++i) {
   442     receive = mRemoteSourceStreams[i]->GetPipelineByLevel_m(level);
   443   }
   445   RefPtr<mozilla::MediaPipeline> transmit;
   446   for (size_t i = 0; !transmit && i < mLocalSourceStreams.Length(); ++i) {
   447     transmit = mLocalSourceStreams[i]->GetPipelineByLevel_m(level);
   448   }
   450   if (receive && transmit) {
   451     // GetPipelineByLevel_m will return nullptr if shutdown is in progress;
   452     // since shutdown is initiated in main, and involves a dispatch to STS
   453     // before the pipelines are released, our dispatch to STS will complete
   454     // before any release can happen due to a shutdown that hasn't started yet.
   455     RUN_ON_THREAD(GetSTSThread(),
   456                   WrapRunnableNM(
   457                       &UpdateFilterFromRemoteDescription_s,
   458                       receive,
   459                       transmit,
   460                       filter
   461                   ),
   462                   NS_DISPATCH_NORMAL);
   463     return true;
   464   } else {
   465     CSFLogWarn(logTag, "Could not locate level %d to update filter",
   466         static_cast<int>(level));
   467   }
   468   return false;
   469 }
   471 nsresult
   472 PeerConnectionMedia::AddRemoteStream(nsRefPtr<RemoteSourceStreamInfo> aInfo,
   473   int *aIndex)
   474 {
   475   MOZ_ASSERT(aIndex);
   477   *aIndex = mRemoteSourceStreams.Length();
   479   mRemoteSourceStreams.AppendElement(aInfo);
   481   return NS_OK;
   482 }
   484 nsresult
   485 PeerConnectionMedia::AddRemoteStreamHint(int aIndex, bool aIsVideo)
   486 {
   487   if (aIndex < 0 ||
   488       static_cast<unsigned int>(aIndex) >= mRemoteSourceStreams.Length()) {
   489     return NS_ERROR_ILLEGAL_VALUE;
   490   }
   492   RemoteSourceStreamInfo *pInfo = mRemoteSourceStreams.ElementAt(aIndex);
   493   MOZ_ASSERT(pInfo);
   495   if (aIsVideo) {
   496     pInfo->mTrackTypeHints |= DOMMediaStream::HINT_CONTENTS_VIDEO;
   497   } else {
   498     pInfo->mTrackTypeHints |= DOMMediaStream::HINT_CONTENTS_AUDIO;
   499   }
   501   return NS_OK;
   502 }
   505 void
   506 PeerConnectionMedia::IceGatheringStateChange_s(NrIceCtx* ctx,
   507                                                NrIceCtx::GatheringState state)
   508 {
   509   ASSERT_ON_THREAD(mSTSThread);
   510   // ShutdownMediaTransport_s has not run yet because it unhooks this function
   511   // from its signal, which means that SelfDestruct_m has not been dispatched
   512   // yet either, so this PCMedia will still be around when this dispatch reaches
   513   // main.
   514   GetMainThread()->Dispatch(
   515     WrapRunnable(this,
   516                  &PeerConnectionMedia::IceGatheringStateChange_m,
   517                  ctx,
   518                  state),
   519     NS_DISPATCH_NORMAL);
   520 }
   522 void
   523 PeerConnectionMedia::IceConnectionStateChange_s(NrIceCtx* ctx,
   524                                                 NrIceCtx::ConnectionState state)
   525 {
   526   ASSERT_ON_THREAD(mSTSThread);
   527   // ShutdownMediaTransport_s has not run yet because it unhooks this function
   528   // from its signal, which means that SelfDestruct_m has not been dispatched
   529   // yet either, so this PCMedia will still be around when this dispatch reaches
   530   // main.
   531   GetMainThread()->Dispatch(
   532     WrapRunnable(this,
   533                  &PeerConnectionMedia::IceConnectionStateChange_m,
   534                  ctx,
   535                  state),
   536     NS_DISPATCH_NORMAL);
   537 }
   539 void
   540 PeerConnectionMedia::IceGatheringStateChange_m(NrIceCtx* ctx,
   541                                                NrIceCtx::GatheringState state)
   542 {
   543   ASSERT_ON_THREAD(mMainThread);
   544   SignalIceGatheringStateChange(ctx, state);
   545 }
   547 void
   548 PeerConnectionMedia::IceConnectionStateChange_m(NrIceCtx* ctx,
   549                                                 NrIceCtx::ConnectionState state)
   550 {
   551   ASSERT_ON_THREAD(mMainThread);
   552   SignalIceConnectionStateChange(ctx, state);
   553 }
   555 void
   556 PeerConnectionMedia::IceStreamReady(NrIceMediaStream *aStream)
   557 {
   558   MOZ_ASSERT(aStream);
   560   CSFLogDebug(logTag, "%s: %s", __FUNCTION__, aStream->name().c_str());
   561 }
   563 void
   564 LocalSourceStreamInfo::StorePipeline(int aTrack,
   565   mozilla::RefPtr<mozilla::MediaPipeline> aPipeline)
   566 {
   567   MOZ_ASSERT(mPipelines.find(aTrack) == mPipelines.end());
   568   if (mPipelines.find(aTrack) != mPipelines.end()) {
   569     CSFLogError(logTag, "%s: Storing duplicate track", __FUNCTION__);
   570     return;
   571   }
   572   //TODO: Revisit once we start supporting multiple streams or multiple tracks
   573   // of same type
   574   mPipelines[aTrack] = aPipeline;
   575 }
   577 void
   578 RemoteSourceStreamInfo::StorePipeline(int aTrack,
   579                                       bool aIsVideo,
   580                                       mozilla::RefPtr<mozilla::MediaPipeline> aPipeline)
   581 {
   582   MOZ_ASSERT(mPipelines.find(aTrack) == mPipelines.end());
   583   if (mPipelines.find(aTrack) != mPipelines.end()) {
   584     CSFLogError(logTag, "%s: Request to store duplicate track %d", __FUNCTION__, aTrack);
   585     return;
   586   }
   587   CSFLogDebug(logTag, "%s track %d %s = %p", __FUNCTION__, aTrack, aIsVideo ? "video" : "audio",
   588               aPipeline.get());
   589   // See if we have both audio and video here, and if so cross the streams and sync them
   590   // XXX Needs to be adjusted when we support multiple streams of the same type
   591   for (std::map<int, bool>::iterator it = mTypes.begin(); it != mTypes.end(); ++it) {
   592     if (it->second != aIsVideo) {
   593       // Ok, we have one video, one non-video - cross the streams!
   594       mozilla::WebrtcAudioConduit *audio_conduit = static_cast<mozilla::WebrtcAudioConduit*>
   595                                                    (aIsVideo ?
   596                                                     mPipelines[it->first]->Conduit() :
   597                                                     aPipeline->Conduit());
   598       mozilla::WebrtcVideoConduit *video_conduit = static_cast<mozilla::WebrtcVideoConduit*>
   599                                                    (aIsVideo ?
   600                                                     aPipeline->Conduit() :
   601                                                     mPipelines[it->first]->Conduit());
   602       video_conduit->SyncTo(audio_conduit);
   603       CSFLogDebug(logTag, "Syncing %p to %p, %d to %d", video_conduit, audio_conduit,
   604                   aTrack, it->first);
   605     }
   606   }
   607   //TODO: Revisit once we start supporting multiple streams or multiple tracks
   608   // of same type
   609   mPipelines[aTrack] = aPipeline;
   610   //TODO: move to attribute on Pipeline
   611   mTypes[aTrack] = aIsVideo;
   612 }
   614 RefPtr<MediaPipeline> SourceStreamInfo::GetPipelineByLevel_m(int level) {
   615   ASSERT_ON_THREAD(mParent->GetMainThread());
   617   // Refuse to hand out references if we're tearing down.
   618   // (Since teardown involves a dispatch to and from STS before MediaPipelines
   619   // are released, it is safe to start other dispatches to and from STS with a
   620   // RefPtr<MediaPipeline>, since that reference won't be the last one
   621   // standing)
   622   if (mMediaStream) {
   623     for (auto p = mPipelines.begin(); p != mPipelines.end(); ++p) {
   624       if (p->second->level() == level) {
   625         return p->second;
   626       }
   627     }
   628   }
   630   return nullptr;
   631 }
   633 bool RemoteSourceStreamInfo::SetUsingBundle_m(int aLevel, bool decision) {
   634   ASSERT_ON_THREAD(mParent->GetMainThread());
   636   RefPtr<MediaPipeline> pipeline(GetPipelineByLevel_m(aLevel));
   638   if (pipeline) {
   639     RUN_ON_THREAD(mParent->GetSTSThread(),
   640                   WrapRunnable(
   641                       pipeline,
   642                       &MediaPipeline::SetUsingBundle_s,
   643                       decision
   644                   ),
   645                   NS_DISPATCH_NORMAL);
   646     return true;
   647   }
   648   return false;
   649 }
   651 }  // namespace sipcc

mercurial