dom/media/MediaManager.h

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/dom/media/MediaManager.h	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,580 @@
     1.4 +/* This Source Code Form is subject to the terms of the Mozilla Public
     1.5 + * License, v. 2.0. If a copy of the MPL was not distributed with this file,
     1.6 + * You can obtain one at http://mozilla.org/MPL/2.0/. */
     1.7 +
     1.8 +#include "MediaEngine.h"
     1.9 +#include "mozilla/Services.h"
    1.10 +#include "mozilla/unused.h"
    1.11 +#include "nsIMediaManager.h"
    1.12 +
    1.13 +#include "nsHashKeys.h"
    1.14 +#include "nsGlobalWindow.h"
    1.15 +#include "nsClassHashtable.h"
    1.16 +#include "nsRefPtrHashtable.h"
    1.17 +#include "nsIObserver.h"
    1.18 +#include "nsIPrefService.h"
    1.19 +#include "nsIPrefBranch.h"
    1.20 +
    1.21 +#include "nsPIDOMWindow.h"
    1.22 +#include "nsIDOMNavigatorUserMedia.h"
    1.23 +#include "nsXULAppAPI.h"
    1.24 +#include "mozilla/Attributes.h"
    1.25 +#include "mozilla/Preferences.h"
    1.26 +#include "mozilla/StaticPtr.h"
    1.27 +#include "mozilla/dom/MediaStreamBinding.h"
    1.28 +#include "mozilla/dom/MediaStreamTrackBinding.h"
    1.29 +#include "prlog.h"
    1.30 +#include "DOMMediaStream.h"
    1.31 +
    1.32 +#ifdef MOZ_WEBRTC
    1.33 +#include "mtransport/runnable_utils.h"
    1.34 +#endif
    1.35 +
    1.36 +#ifdef MOZ_WIDGET_GONK
    1.37 +#include "DOMCameraManager.h"
    1.38 +#endif
    1.39 +
    1.40 +namespace mozilla {
    1.41 +namespace dom {
    1.42 +class MediaStreamConstraints;
    1.43 +class NavigatorUserMediaSuccessCallback;
    1.44 +class NavigatorUserMediaErrorCallback;
    1.45 +}
    1.46 +
    1.47 +#ifdef PR_LOGGING
    1.48 +extern PRLogModuleInfo* GetMediaManagerLog();
    1.49 +#define MM_LOG(msg) PR_LOG(GetMediaManagerLog(), PR_LOG_DEBUG, msg)
    1.50 +#else
    1.51 +#define MM_LOG(msg)
    1.52 +#endif
    1.53 +
    1.54 +/**
    1.55 + * This class is an implementation of MediaStreamListener. This is used
    1.56 + * to Start() and Stop() the underlying MediaEngineSource when MediaStreams
    1.57 + * are assigned and deassigned in content.
    1.58 + */
    1.59 +class GetUserMediaCallbackMediaStreamListener : public MediaStreamListener
    1.60 +{
    1.61 +public:
    1.62 +  // Create in an inactive state
    1.63 +  GetUserMediaCallbackMediaStreamListener(nsIThread *aThread,
    1.64 +    uint64_t aWindowID)
    1.65 +    : mMediaThread(aThread)
    1.66 +    , mWindowID(aWindowID)
    1.67 +    , mStopped(false)
    1.68 +    , mFinished(false)
    1.69 +    , mLock("mozilla::GUMCMSL")
    1.70 +    , mRemoved(false) {}
    1.71 +
    1.72 +  ~GetUserMediaCallbackMediaStreamListener()
    1.73 +  {
    1.74 +    // It's OK to release mStream on any thread; they have thread-safe
    1.75 +    // refcounts.
    1.76 +  }
    1.77 +
    1.78 +  void Activate(already_AddRefed<SourceMediaStream> aStream,
    1.79 +    MediaEngineSource* aAudioSource,
    1.80 +    MediaEngineSource* aVideoSource)
    1.81 +  {
    1.82 +    NS_ASSERTION(NS_IsMainThread(), "Only call on main thread");
    1.83 +    mStream = aStream;
    1.84 +    mAudioSource = aAudioSource;
    1.85 +    mVideoSource = aVideoSource;
    1.86 +    mLastEndTimeAudio = 0;
    1.87 +    mLastEndTimeVideo = 0;
    1.88 +
    1.89 +    mStream->AddListener(this);
    1.90 +  }
    1.91 +
    1.92 +  MediaStream *Stream() // Can be used to test if Activate was called
    1.93 +  {
    1.94 +    return mStream;
    1.95 +  }
    1.96 +  SourceMediaStream *GetSourceStream()
    1.97 +  {
    1.98 +    NS_ASSERTION(mStream,"Getting stream from never-activated GUMCMSListener");
    1.99 +    if (!mStream) {
   1.100 +      return nullptr;
   1.101 +    }
   1.102 +    return mStream->AsSourceStream();
   1.103 +  }
   1.104 +
   1.105 +  // mVideo/AudioSource are set by Activate(), so we assume they're capturing
   1.106 +  // if set and represent a real capture device.
   1.107 +  bool CapturingVideo()
   1.108 +  {
   1.109 +    NS_ASSERTION(NS_IsMainThread(), "Only call on main thread");
   1.110 +    return mVideoSource && !mStopped &&
   1.111 +           (!mVideoSource->IsFake() ||
   1.112 +            Preferences::GetBool("media.navigator.permission.fake"));
   1.113 +  }
   1.114 +  bool CapturingAudio()
   1.115 +  {
   1.116 +    NS_ASSERTION(NS_IsMainThread(), "Only call on main thread");
   1.117 +    return mAudioSource && !mStopped &&
   1.118 +           (!mAudioSource->IsFake() ||
   1.119 +            Preferences::GetBool("media.navigator.permission.fake"));
   1.120 +  }
   1.121 +
   1.122 +  void SetStopped()
   1.123 +  {
   1.124 +    mStopped = true;
   1.125 +  }
   1.126 +
   1.127 +  // implement in .cpp to avoid circular dependency with MediaOperationRunnable
   1.128 +  // Can be invoked from EITHER MainThread or MSG thread
   1.129 +  void Invalidate();
   1.130 +
   1.131 +  void
   1.132 +  AudioConfig(bool aEchoOn, uint32_t aEcho,
   1.133 +              bool aAgcOn, uint32_t aAGC,
   1.134 +              bool aNoiseOn, uint32_t aNoise,
   1.135 +              int32_t aPlayoutDelay)
   1.136 +  {
   1.137 +    if (mAudioSource) {
   1.138 +#ifdef MOZ_WEBRTC
   1.139 +      // Right now these configs are only of use if webrtc is available
   1.140 +      RUN_ON_THREAD(mMediaThread,
   1.141 +                    WrapRunnable(nsRefPtr<MediaEngineSource>(mAudioSource), // threadsafe
   1.142 +                                 &MediaEngineSource::Config,
   1.143 +                                 aEchoOn, aEcho, aAgcOn, aAGC, aNoiseOn, aNoise, aPlayoutDelay),
   1.144 +                    NS_DISPATCH_NORMAL);
   1.145 +#endif
   1.146 +    }
   1.147 +  }
   1.148 +
   1.149 +  void
   1.150 +  Remove()
   1.151 +  {
   1.152 +    NS_ASSERTION(NS_IsMainThread(), "Only call on main thread");
   1.153 +    // allow calling even if inactive (!mStream) for easier cleanup
   1.154 +    // Caller holds strong reference to us, so no death grip required
   1.155 +    MutexAutoLock lock(mLock); // protect access to mRemoved
   1.156 +    if (mStream && !mRemoved) {
   1.157 +      MM_LOG(("Listener removed on purpose, mFinished = %d", (int) mFinished));
   1.158 +      mRemoved = true; // RemoveListener is async, avoid races
   1.159 +      // If it's destroyed, don't call - listener will be removed and we'll be notified!
   1.160 +      if (!mStream->IsDestroyed()) {
   1.161 +        mStream->RemoveListener(this);
   1.162 +      }
   1.163 +    }
   1.164 +  }
   1.165 +
   1.166 +  // Proxy NotifyPull() to sources
   1.167 +  virtual void
   1.168 +  NotifyPull(MediaStreamGraph* aGraph, StreamTime aDesiredTime) MOZ_OVERRIDE
   1.169 +  {
   1.170 +    // Currently audio sources ignore NotifyPull, but they could
   1.171 +    // watch it especially for fake audio.
   1.172 +    if (mAudioSource) {
   1.173 +      mAudioSource->NotifyPull(aGraph, mStream, kAudioTrack, aDesiredTime, mLastEndTimeAudio);
   1.174 +    }
   1.175 +    if (mVideoSource) {
   1.176 +      mVideoSource->NotifyPull(aGraph, mStream, kVideoTrack, aDesiredTime, mLastEndTimeVideo);
   1.177 +    }
   1.178 +  }
   1.179 +
   1.180 +  virtual void
   1.181 +  NotifyFinished(MediaStreamGraph* aGraph) MOZ_OVERRIDE;
   1.182 +
   1.183 +  virtual void
   1.184 +  NotifyRemoved(MediaStreamGraph* aGraph) MOZ_OVERRIDE;
   1.185 +
   1.186 +private:
   1.187 +  // Set at construction
   1.188 +  nsCOMPtr<nsIThread> mMediaThread;
   1.189 +  uint64_t mWindowID;
   1.190 +
   1.191 +  bool mStopped; // MainThread only
   1.192 +
   1.193 +  // Set at Activate on MainThread
   1.194 +
   1.195 +  // Accessed from MediaStreamGraph thread, MediaManager thread, and MainThread
   1.196 +  // No locking needed as they're only addrefed except on the MediaManager thread
   1.197 +  nsRefPtr<MediaEngineSource> mAudioSource; // threadsafe refcnt
   1.198 +  nsRefPtr<MediaEngineSource> mVideoSource; // threadsafe refcnt
   1.199 +  nsRefPtr<SourceMediaStream> mStream; // threadsafe refcnt
   1.200 +  TrackTicks mLastEndTimeAudio;
   1.201 +  TrackTicks mLastEndTimeVideo;
   1.202 +  bool mFinished;
   1.203 +
   1.204 +  // Accessed from MainThread and MSG thread
   1.205 +  Mutex mLock; // protects mRemoved access from MainThread
   1.206 +  bool mRemoved;
   1.207 +};
   1.208 +
   1.209 +class GetUserMediaNotificationEvent: public nsRunnable
   1.210 +{
   1.211 +  public:
   1.212 +    enum GetUserMediaStatus {
   1.213 +      STARTING,
   1.214 +      STOPPING
   1.215 +    };
   1.216 +    GetUserMediaNotificationEvent(GetUserMediaCallbackMediaStreamListener* aListener,
   1.217 +                                  GetUserMediaStatus aStatus,
   1.218 +                                  bool aIsAudio, bool aIsVideo, uint64_t aWindowID)
   1.219 +    : mListener(aListener) , mStatus(aStatus) , mIsAudio(aIsAudio)
   1.220 +    , mIsVideo(aIsVideo), mWindowID(aWindowID) {}
   1.221 +
   1.222 +    GetUserMediaNotificationEvent(GetUserMediaStatus aStatus,
   1.223 +                                  already_AddRefed<DOMMediaStream> aStream,
   1.224 +                                  DOMMediaStream::OnTracksAvailableCallback* aOnTracksAvailableCallback,
   1.225 +                                  bool aIsAudio, bool aIsVideo, uint64_t aWindowID,
   1.226 +                                  already_AddRefed<nsIDOMGetUserMediaErrorCallback> aError)
   1.227 +    : mStream(aStream), mOnTracksAvailableCallback(aOnTracksAvailableCallback),
   1.228 +      mStatus(aStatus), mIsAudio(aIsAudio), mIsVideo(aIsVideo), mWindowID(aWindowID),
   1.229 +      mError(aError) {}
   1.230 +    virtual ~GetUserMediaNotificationEvent()
   1.231 +    {
   1.232 +
   1.233 +    }
   1.234 +
   1.235 +    NS_IMETHOD Run() MOZ_OVERRIDE;
   1.236 +
   1.237 +  protected:
   1.238 +    nsRefPtr<GetUserMediaCallbackMediaStreamListener> mListener; // threadsafe
   1.239 +    nsRefPtr<DOMMediaStream> mStream;
   1.240 +    nsAutoPtr<DOMMediaStream::OnTracksAvailableCallback> mOnTracksAvailableCallback;
   1.241 +    GetUserMediaStatus mStatus;
   1.242 +    bool mIsAudio;
   1.243 +    bool mIsVideo;
   1.244 +    uint64_t mWindowID;
   1.245 +    nsRefPtr<nsIDOMGetUserMediaErrorCallback> mError;
   1.246 +};
   1.247 +
   1.248 +typedef enum {
   1.249 +  MEDIA_START,
   1.250 +  MEDIA_STOP
   1.251 +} MediaOperation;
   1.252 +
   1.253 +class MediaManager;
   1.254 +class GetUserMediaRunnable;
   1.255 +
   1.256 +/**
   1.257 + * Send an error back to content. The error is the form a string.
   1.258 + * Do this only on the main thread. The success callback is also passed here
   1.259 + * so it can be released correctly.
   1.260 + */
   1.261 +class ErrorCallbackRunnable : public nsRunnable
   1.262 +{
   1.263 +public:
   1.264 +  ErrorCallbackRunnable(
   1.265 +    nsCOMPtr<nsIDOMGetUserMediaSuccessCallback>& aSuccess,
   1.266 +    nsCOMPtr<nsIDOMGetUserMediaErrorCallback>& aError,
   1.267 +    const nsAString& aErrorMsg, uint64_t aWindowID);
   1.268 +  NS_IMETHOD Run();
   1.269 +private:
   1.270 +  ~ErrorCallbackRunnable();
   1.271 +
   1.272 +  nsCOMPtr<nsIDOMGetUserMediaSuccessCallback> mSuccess;
   1.273 +  nsCOMPtr<nsIDOMGetUserMediaErrorCallback> mError;
   1.274 +  const nsString mErrorMsg;
   1.275 +  uint64_t mWindowID;
   1.276 +  nsRefPtr<MediaManager> mManager; // get ref to this when creating the runnable
   1.277 +};
   1.278 +
   1.279 +class ReleaseMediaOperationResource : public nsRunnable
   1.280 +{
   1.281 +public:
   1.282 +  ReleaseMediaOperationResource(already_AddRefed<DOMMediaStream> aStream,
   1.283 +    DOMMediaStream::OnTracksAvailableCallback* aOnTracksAvailableCallback):
   1.284 +    mStream(aStream),
   1.285 +    mOnTracksAvailableCallback(aOnTracksAvailableCallback) {}
   1.286 +  NS_IMETHOD Run() MOZ_OVERRIDE {return NS_OK;}
   1.287 +private:
   1.288 +  nsRefPtr<DOMMediaStream> mStream;
   1.289 +  nsAutoPtr<DOMMediaStream::OnTracksAvailableCallback> mOnTracksAvailableCallback;
   1.290 +};
   1.291 +
   1.292 +// Generic class for running long media operations like Start off the main
   1.293 +// thread, and then (because nsDOMMediaStreams aren't threadsafe),
   1.294 +// ProxyReleases mStream since it's cycle collected.
   1.295 +class MediaOperationRunnable : public nsRunnable
   1.296 +{
   1.297 +public:
   1.298 +  // so we can send Stop without AddRef()ing from the MSG thread
   1.299 +  MediaOperationRunnable(MediaOperation aType,
   1.300 +    GetUserMediaCallbackMediaStreamListener* aListener,
   1.301 +    DOMMediaStream* aStream,
   1.302 +    DOMMediaStream::OnTracksAvailableCallback* aOnTracksAvailableCallback,
   1.303 +    MediaEngineSource* aAudioSource,
   1.304 +    MediaEngineSource* aVideoSource,
   1.305 +    bool aNeedsFinish,
   1.306 +    uint64_t aWindowID,
   1.307 +    already_AddRefed<nsIDOMGetUserMediaErrorCallback> aError)
   1.308 +    : mType(aType)
   1.309 +    , mStream(aStream)
   1.310 +    , mOnTracksAvailableCallback(aOnTracksAvailableCallback)
   1.311 +    , mAudioSource(aAudioSource)
   1.312 +    , mVideoSource(aVideoSource)
   1.313 +    , mListener(aListener)
   1.314 +    , mFinish(aNeedsFinish)
   1.315 +    , mWindowID(aWindowID)
   1.316 +    , mError(aError)
   1.317 +  {}
   1.318 +
   1.319 +  ~MediaOperationRunnable()
   1.320 +  {
   1.321 +    // MediaStreams can be released on any thread.
   1.322 +  }
   1.323 +
   1.324 +  nsresult returnAndCallbackError(nsresult rv, const char* errorLog)
   1.325 +  {
   1.326 +    MM_LOG(("%s , rv=%d", errorLog, rv));
   1.327 +    NS_DispatchToMainThread(new ReleaseMediaOperationResource(mStream.forget(),
   1.328 +          mOnTracksAvailableCallback.forget()));
   1.329 +    nsString log;
   1.330 +
   1.331 +    log.AssignASCII(errorLog, strlen(errorLog));
   1.332 +    nsCOMPtr<nsIDOMGetUserMediaSuccessCallback> success;
   1.333 +    NS_DispatchToMainThread(new ErrorCallbackRunnable(success, mError,
   1.334 +      log, mWindowID));
   1.335 +    return NS_OK;
   1.336 +  }
   1.337 +
   1.338 +  NS_IMETHOD
   1.339 +  Run() MOZ_OVERRIDE
   1.340 +  {
   1.341 +    SourceMediaStream *source = mListener->GetSourceStream();
   1.342 +    // No locking between these is required as all the callbacks for the
   1.343 +    // same MediaStream will occur on the same thread.
   1.344 +    if (!source) // means the stream was never Activated()
   1.345 +      return NS_OK;
   1.346 +
   1.347 +    switch (mType) {
   1.348 +      case MEDIA_START:
   1.349 +        {
   1.350 +          NS_ASSERTION(!NS_IsMainThread(), "Never call on main thread");
   1.351 +          nsresult rv;
   1.352 +
   1.353 +          source->SetPullEnabled(true);
   1.354 +
   1.355 +          DOMMediaStream::TrackTypeHints expectedTracks = 0;
   1.356 +          if (mAudioSource) {
   1.357 +            rv = mAudioSource->Start(source, kAudioTrack);
   1.358 +            if (NS_SUCCEEDED(rv)) {
   1.359 +              expectedTracks |= DOMMediaStream::HINT_CONTENTS_AUDIO;
   1.360 +            } else {
   1.361 +              return returnAndCallbackError(rv, "Starting audio failed");
   1.362 +            }
   1.363 +          }
   1.364 +          if (mVideoSource) {
   1.365 +            rv = mVideoSource->Start(source, kVideoTrack);
   1.366 +            if (NS_SUCCEEDED(rv)) {
   1.367 +              expectedTracks |= DOMMediaStream::HINT_CONTENTS_VIDEO;
   1.368 +            } else {
   1.369 +              return returnAndCallbackError(rv, "Starting video failed");
   1.370 +            }
   1.371 +          }
   1.372 +
   1.373 +          mOnTracksAvailableCallback->SetExpectedTracks(expectedTracks);
   1.374 +
   1.375 +          MM_LOG(("started all sources"));
   1.376 +          // Forward mOnTracksAvailableCallback to GetUserMediaNotificationEvent,
   1.377 +          // because mOnTracksAvailableCallback needs to be added to mStream
   1.378 +          // on the main thread.
   1.379 +          nsIRunnable *event =
   1.380 +            new GetUserMediaNotificationEvent(GetUserMediaNotificationEvent::STARTING,
   1.381 +                                              mStream.forget(),
   1.382 +                                              mOnTracksAvailableCallback.forget(),
   1.383 +                                              mAudioSource != nullptr,
   1.384 +                                              mVideoSource != nullptr,
   1.385 +                                              mWindowID, mError.forget());
   1.386 +          // event must always be released on mainthread due to the JS callbacks
   1.387 +          // in the TracksAvailableCallback
   1.388 +          NS_DispatchToMainThread(event, NS_DISPATCH_NORMAL);
   1.389 +        }
   1.390 +        break;
   1.391 +
   1.392 +      case MEDIA_STOP:
   1.393 +        {
   1.394 +          NS_ASSERTION(!NS_IsMainThread(), "Never call on main thread");
   1.395 +          if (mAudioSource) {
   1.396 +            mAudioSource->Stop(source, kAudioTrack);
   1.397 +            mAudioSource->Deallocate();
   1.398 +          }
   1.399 +          if (mVideoSource) {
   1.400 +            mVideoSource->Stop(source, kVideoTrack);
   1.401 +            mVideoSource->Deallocate();
   1.402 +          }
   1.403 +          // Do this after stopping all tracks with EndTrack()
   1.404 +          if (mFinish) {
   1.405 +            source->Finish();
   1.406 +          }
   1.407 +          nsIRunnable *event =
   1.408 +            new GetUserMediaNotificationEvent(mListener,
   1.409 +                                              GetUserMediaNotificationEvent::STOPPING,
   1.410 +                                              mAudioSource != nullptr,
   1.411 +                                              mVideoSource != nullptr,
   1.412 +                                              mWindowID);
   1.413 +          // event must always be released on mainthread due to the JS callbacks
   1.414 +          // in the TracksAvailableCallback
   1.415 +          NS_DispatchToMainThread(event, NS_DISPATCH_NORMAL);
   1.416 +        }
   1.417 +        break;
   1.418 +
   1.419 +      default:
   1.420 +        MOZ_ASSERT(false,"invalid MediaManager operation");
   1.421 +        break;
   1.422 +    }
   1.423 +    return NS_OK;
   1.424 +  }
   1.425 +
   1.426 +private:
   1.427 +  MediaOperation mType;
   1.428 +  nsRefPtr<DOMMediaStream> mStream;
   1.429 +  nsAutoPtr<DOMMediaStream::OnTracksAvailableCallback> mOnTracksAvailableCallback;
   1.430 +  nsRefPtr<MediaEngineSource> mAudioSource; // threadsafe
   1.431 +  nsRefPtr<MediaEngineSource> mVideoSource; // threadsafe
   1.432 +  nsRefPtr<GetUserMediaCallbackMediaStreamListener> mListener; // threadsafe
   1.433 +  bool mFinish;
   1.434 +  uint64_t mWindowID;
   1.435 +  nsCOMPtr<nsIDOMGetUserMediaErrorCallback> mError;
   1.436 +};
   1.437 +
   1.438 +typedef nsTArray<nsRefPtr<GetUserMediaCallbackMediaStreamListener> > StreamListeners;
   1.439 +typedef nsClassHashtable<nsUint64HashKey, StreamListeners> WindowTable;
   1.440 +
   1.441 +class MediaDevice : public nsIMediaDevice
   1.442 +{
   1.443 +public:
   1.444 +  NS_DECL_THREADSAFE_ISUPPORTS
   1.445 +  NS_DECL_NSIMEDIADEVICE
   1.446 +
   1.447 +  static MediaDevice* Create(MediaEngineVideoSource* source);
   1.448 +  static MediaDevice* Create(MediaEngineAudioSource* source);
   1.449 +
   1.450 +  virtual ~MediaDevice() {}
   1.451 +protected:
   1.452 +  MediaDevice(MediaEngineSource* aSource);
   1.453 +  nsString mName;
   1.454 +  nsString mID;
   1.455 +  bool mHasFacingMode;
   1.456 +  dom::VideoFacingModeEnum mFacingMode;
   1.457 +  nsRefPtr<MediaEngineSource> mSource;
   1.458 +};
   1.459 +
   1.460 +class VideoDevice : public MediaDevice
   1.461 +{
   1.462 +public:
   1.463 +  VideoDevice(MediaEngineVideoSource* aSource);
   1.464 +  NS_IMETHOD GetType(nsAString& aType);
   1.465 +  MediaEngineVideoSource* GetSource();
   1.466 +};
   1.467 +
   1.468 +class AudioDevice : public MediaDevice
   1.469 +{
   1.470 +public:
   1.471 +  AudioDevice(MediaEngineAudioSource* aSource);
   1.472 +  NS_IMETHOD GetType(nsAString& aType);
   1.473 +  MediaEngineAudioSource* GetSource();
   1.474 +};
   1.475 +
   1.476 +// we could add MediaManager if needed
   1.477 +typedef void (*WindowListenerCallback)(MediaManager *aThis,
   1.478 +                                       uint64_t aWindowID,
   1.479 +                                       StreamListeners *aListeners,
   1.480 +                                       void *aData);
   1.481 +
   1.482 +class MediaManager MOZ_FINAL : public nsIMediaManagerService,
   1.483 +                               public nsIObserver
   1.484 +{
   1.485 +public:
   1.486 +  static already_AddRefed<MediaManager> GetInstance();
   1.487 +
   1.488 +  // NOTE: never Dispatch(....,NS_DISPATCH_SYNC) to the MediaManager
   1.489 +  // thread from the MainThread, as we NS_DISPATCH_SYNC to MainThread
   1.490 +  // from MediaManager thread.
   1.491 +  static MediaManager* Get();
   1.492 +
   1.493 +  static bool Exists()
   1.494 +  {
   1.495 +    return !!sSingleton;
   1.496 +  }
   1.497 +
   1.498 +  static nsIThread* GetThread() {
   1.499 +    return Get()->mMediaThread;
   1.500 +  }
   1.501 +
   1.502 +  static nsresult NotifyRecordingStatusChange(nsPIDOMWindow* aWindow,
   1.503 +                                              const nsString& aMsg,
   1.504 +                                              const bool& aIsAudio,
   1.505 +                                              const bool& aIsVideo);
   1.506 +
   1.507 +  NS_DECL_THREADSAFE_ISUPPORTS
   1.508 +  NS_DECL_NSIOBSERVER
   1.509 +  NS_DECL_NSIMEDIAMANAGERSERVICE
   1.510 +
   1.511 +  MediaEngine* GetBackend(uint64_t aWindowId = 0);
   1.512 +  StreamListeners *GetWindowListeners(uint64_t aWindowId) {
   1.513 +    NS_ASSERTION(NS_IsMainThread(), "Only access windowlist on main thread");
   1.514 +
   1.515 +    return mActiveWindows.Get(aWindowId);
   1.516 +  }
   1.517 +  void RemoveWindowID(uint64_t aWindowId) {
   1.518 +    mActiveWindows.Remove(aWindowId);
   1.519 +  }
   1.520 +  bool IsWindowStillActive(uint64_t aWindowId) {
   1.521 +    return !!GetWindowListeners(aWindowId);
   1.522 +  }
   1.523 +  // Note: also calls aListener->Remove(), even if inactive
   1.524 +  void RemoveFromWindowList(uint64_t aWindowID,
   1.525 +    GetUserMediaCallbackMediaStreamListener *aListener);
   1.526 +
   1.527 +  nsresult GetUserMedia(bool aPrivileged,
   1.528 +    nsPIDOMWindow* aWindow,
   1.529 +    const dom::MediaStreamConstraints& aRawConstraints,
   1.530 +    nsIDOMGetUserMediaSuccessCallback* onSuccess,
   1.531 +    nsIDOMGetUserMediaErrorCallback* onError);
   1.532 +
   1.533 +  nsresult GetUserMediaDevices(nsPIDOMWindow* aWindow,
   1.534 +    const dom::MediaStreamConstraints& aConstraints,
   1.535 +    nsIGetUserMediaDevicesSuccessCallback* onSuccess,
   1.536 +    nsIDOMGetUserMediaErrorCallback* onError,
   1.537 +    uint64_t aInnerWindowID = 0);
   1.538 +  void OnNavigation(uint64_t aWindowID);
   1.539 +
   1.540 +  MediaEnginePrefs mPrefs;
   1.541 +
   1.542 +private:
   1.543 +  WindowTable *GetActiveWindows() {
   1.544 +    NS_ASSERTION(NS_IsMainThread(), "Only access windowlist on main thread");
   1.545 +    return &mActiveWindows;
   1.546 +  }
   1.547 +
   1.548 +  void GetPref(nsIPrefBranch *aBranch, const char *aPref,
   1.549 +               const char *aData, int32_t *aVal);
   1.550 +  void GetPrefBool(nsIPrefBranch *aBranch, const char *aPref,
   1.551 +                   const char *aData, bool *aVal);
   1.552 +  void GetPrefs(nsIPrefBranch *aBranch, const char *aData);
   1.553 +
   1.554 +  // Make private because we want only one instance of this class
   1.555 +  MediaManager();
   1.556 +
   1.557 +  ~MediaManager() {}
   1.558 +
   1.559 +  void IterateWindowListeners(nsPIDOMWindow *aWindow,
   1.560 +                              WindowListenerCallback aCallback,
   1.561 +                              void *aData);
   1.562 +
   1.563 +  void StopMediaStreams();
   1.564 +
   1.565 +  // ONLY access from MainThread so we don't need to lock
   1.566 +  WindowTable mActiveWindows;
   1.567 +  nsRefPtrHashtable<nsStringHashKey, GetUserMediaRunnable> mActiveCallbacks;
   1.568 +  nsClassHashtable<nsUint64HashKey, nsTArray<nsString>> mCallIds;
   1.569 +  // Always exists
   1.570 +  nsCOMPtr<nsIThread> mMediaThread;
   1.571 +
   1.572 +  Mutex mMutex;
   1.573 +  // protected with mMutex:
   1.574 +  RefPtr<MediaEngine> mBackend;
   1.575 +
   1.576 +  static StaticRefPtr<MediaManager> sSingleton;
   1.577 +
   1.578 +#ifdef MOZ_B2G_CAMERA
   1.579 +  nsRefPtr<nsDOMCameraManager> mCameraManager;
   1.580 +#endif
   1.581 +};
   1.582 +
   1.583 +} // namespace mozilla

mercurial