LCOV - code coverage report
Current view: top level - dom/media/webrtc - MediaEngine.h (source / functions) Hit Total Coverage
Test: output.info Lines: 0 112 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 40 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       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             : #ifndef MEDIAENGINE_H_
       6             : #define MEDIAENGINE_H_
       7             : 
       8             : #include "mozilla/RefPtr.h"
       9             : #include "DOMMediaStream.h"
      10             : #include "MediaStreamGraph.h"
      11             : #include "MediaTrackConstraints.h"
      12             : #include "mozilla/dom/MediaStreamTrackBinding.h"
      13             : #include "mozilla/dom/VideoStreamTrack.h"
      14             : #include "mozilla/ipc/PBackgroundSharedTypes.h"
      15             : #include "mozilla/media/DeviceChangeCallback.h"
      16             : 
      17             : namespace mozilla {
      18             : 
      19             : namespace dom {
      20             : class Blob;
      21             : } // namespace dom
      22             : 
      23             : enum {
      24             :   kVideoTrack = 1,
      25             :   kAudioTrack = 2,
      26             :   kTrackCount
      27             : };
      28             : 
      29             : /**
      30             :  * Abstract interface for managing audio and video devices. Each platform
      31             :  * must implement a concrete class that will map these classes and methods
      32             :  * to the appropriate backend. For example, on Desktop platforms, these will
      33             :  * correspond to equivalent webrtc (GIPS) calls, and on B2G they will map to
      34             :  * a Gonk interface.
      35             :  */
      36             : class MediaEngineVideoSource;
      37             : class MediaEngineAudioSource;
      38             : 
      39             : enum MediaEngineState {
      40             :   kAllocated,
      41             :   kStarted,
      42             :   kStopped,
      43             :   kReleased
      44             : };
      45             : 
      46           0 : class MediaEngine : public DeviceChangeCallback
      47             : {
      48             : public:
      49           0 :   NS_INLINE_DECL_THREADSAFE_REFCOUNTING(MediaEngine)
      50             : 
      51             :   static const int DEFAULT_VIDEO_FPS = 30;
      52             :   static const int DEFAULT_VIDEO_MIN_FPS = 10;
      53             :   static const int DEFAULT_43_VIDEO_WIDTH = 640;
      54             :   static const int DEFAULT_43_VIDEO_HEIGHT = 480;
      55             :   static const int DEFAULT_169_VIDEO_WIDTH = 1280;
      56             :   static const int DEFAULT_169_VIDEO_HEIGHT = 720;
      57             : 
      58             : #ifndef MOZ_B2G
      59             :   static const int DEFAULT_SAMPLE_RATE = 32000;
      60             : #else
      61             :   static const int DEFAULT_SAMPLE_RATE = 16000;
      62             : #endif
      63             :   // This allows using whatever rate the graph is using for the
      64             :   // MediaStreamTrack. This is useful for microphone data, we know it's already
      65             :   // at the correct rate for insertion in the MSG.
      66             :   static const int USE_GRAPH_RATE = -1;
      67             : 
      68             :   /* Populate an array of video sources in the nsTArray. Also include devices
      69             :    * that are currently unavailable. */
      70             :   virtual void EnumerateVideoDevices(dom::MediaSourceEnum,
      71             :                                      nsTArray<RefPtr<MediaEngineVideoSource> >*) = 0;
      72             : 
      73             :   /* Populate an array of audio sources in the nsTArray. Also include devices
      74             :    * that are currently unavailable. */
      75             :   virtual void EnumerateAudioDevices(dom::MediaSourceEnum,
      76             :                                      nsTArray<RefPtr<MediaEngineAudioSource> >*) = 0;
      77             : 
      78             :   virtual void Shutdown() = 0;
      79             : 
      80           0 :   virtual void SetFakeDeviceChangeEvents() {}
      81             : 
      82             : protected:
      83           0 :   virtual ~MediaEngine() {}
      84             : };
      85             : 
      86             : /**
      87             :  * Video source and friends.
      88             :  */
      89             : class MediaEnginePrefs {
      90             : public:
      91           0 :   MediaEnginePrefs()
      92           0 :     : mWidth(0)
      93             :     , mHeight(0)
      94             :     , mFPS(0)
      95             :     , mMinFPS(0)
      96             :     , mFreq(0)
      97             :     , mAecOn(false)
      98             :     , mAgcOn(false)
      99             :     , mNoiseOn(false)
     100             :     , mAec(0)
     101             :     , mAgc(0)
     102             :     , mNoise(0)
     103             :     , mPlayoutDelay(0)
     104             :     , mFullDuplex(false)
     105             :     , mExtendedFilter(false)
     106             :     , mDelayAgnostic(false)
     107             :     , mFakeDeviceChangeEventOn(false)
     108           0 :     , mChannels(0)
     109           0 :   {}
     110             : 
     111             :   int32_t mWidth;
     112             :   int32_t mHeight;
     113             :   int32_t mFPS;
     114             :   int32_t mMinFPS;
     115             :   int32_t mFreq; // for test tones (fake:true)
     116             :   bool mAecOn;
     117             :   bool mAgcOn;
     118             :   bool mNoiseOn;
     119             :   int32_t mAec;
     120             :   int32_t mAgc;
     121             :   int32_t mNoise;
     122             :   int32_t mPlayoutDelay;
     123             :   bool mFullDuplex;
     124             :   bool mExtendedFilter;
     125             :   bool mDelayAgnostic;
     126             :   bool mFakeDeviceChangeEventOn;
     127             :   int32_t mChannels;
     128             : 
     129             :   // mWidth and/or mHeight may be zero (=adaptive default), so use functions.
     130             : 
     131           0 :   int32_t GetWidth(bool aHD = false) const {
     132           0 :     return mWidth? mWidth : (mHeight?
     133           0 :                              (mHeight * GetDefWidth(aHD)) / GetDefHeight(aHD) :
     134           0 :                              GetDefWidth(aHD));
     135             :   }
     136             : 
     137           0 :   int32_t GetHeight(bool aHD = false) const {
     138           0 :     return mHeight? mHeight : (mWidth?
     139           0 :                                (mWidth * GetDefHeight(aHD)) / GetDefWidth(aHD) :
     140           0 :                                GetDefHeight(aHD));
     141             :   }
     142             : private:
     143           0 :   static int32_t GetDefWidth(bool aHD = false) {
     144             :     // It'd be nice if we could use the ternary operator here, but we can't
     145             :     // because of bug 1002729.
     146           0 :     if (aHD) {
     147           0 :       return MediaEngine::DEFAULT_169_VIDEO_WIDTH;
     148             :     }
     149             : 
     150           0 :     return MediaEngine::DEFAULT_43_VIDEO_WIDTH;
     151             :   }
     152             : 
     153           0 :   static int32_t GetDefHeight(bool aHD = false) {
     154             :     // It'd be nice if we could use the ternary operator here, but we can't
     155             :     // because of bug 1002729.
     156           0 :     if (aHD) {
     157           0 :       return MediaEngine::DEFAULT_169_VIDEO_HEIGHT;
     158             :     }
     159             : 
     160           0 :     return MediaEngine::DEFAULT_43_VIDEO_HEIGHT;
     161             :   }
     162             : };
     163             : 
     164             : /**
     165             :  * Callback interface for TakePhoto(). Either PhotoComplete() or PhotoError()
     166             :  * should be called.
     167             :  */
     168           0 : class MediaEnginePhotoCallback {
     169             : public:
     170           0 :   NS_INLINE_DECL_THREADSAFE_REFCOUNTING(MediaEnginePhotoCallback)
     171             : 
     172             :   // aBlob is the image captured by MediaEngineSource. It is
     173             :   // called on main thread.
     174             :   virtual nsresult PhotoComplete(already_AddRefed<dom::Blob> aBlob) = 0;
     175             : 
     176             :   // It is called on main thread. aRv is the error code.
     177             :   virtual nsresult PhotoError(nsresult aRv) = 0;
     178             : 
     179             : protected:
     180           0 :   virtual ~MediaEnginePhotoCallback() {}
     181             : };
     182             : 
     183             : /**
     184             :  * Common abstract base class for audio and video sources.
     185             :  *
     186             :  * By default, the base class implements Allocate and Deallocate using its
     187             :  * UpdateSingleSource pattern, which manages allocation handles and calculates
     188             :  * net constraints from competing allocations and updates a single shared device.
     189             :  *
     190             :  * Classes that don't operate as a single shared device can override Allocate
     191             :  * and Deallocate and simply not pass the methods up.
     192             :  */
     193             : class MediaEngineSource : public nsISupports,
     194             :                           protected MediaConstraintsHelper
     195             : {
     196             : public:
     197             :   // code inside webrtc.org assumes these sizes; don't use anything smaller
     198             :   // without verifying it's ok
     199             :   static const unsigned int kMaxDeviceNameLength = 128;
     200             :   static const unsigned int kMaxUniqueIdLength = 256;
     201             : 
     202           0 :   virtual ~MediaEngineSource()
     203           0 :   {
     204           0 :     if (!mInShutdown) {
     205           0 :       Shutdown();
     206             :     }
     207           0 :   }
     208             : 
     209           0 :   virtual void Shutdown()
     210             :   {
     211           0 :     mInShutdown = true;
     212           0 :   };
     213             : 
     214             :   /* Populate the human readable name of this device in the nsAString */
     215             :   virtual void GetName(nsAString&) const = 0;
     216             : 
     217             :   /* Populate the UUID of this device in the nsACString */
     218             :   virtual void GetUUID(nsACString&) const = 0;
     219             : 
     220             :   /* Override w/true if source does end-run around cross origin restrictions. */
     221           0 :   virtual bool GetScary() const { return false; };
     222             : 
     223             :   class AllocationHandle
     224             :   {
     225             :   public:
     226           0 :     NS_INLINE_DECL_THREADSAFE_REFCOUNTING(AllocationHandle);
     227             :   protected:
     228           0 :     ~AllocationHandle() {}
     229             :   public:
     230           0 :     AllocationHandle(const dom::MediaTrackConstraints& aConstraints,
     231             :                      const mozilla::ipc::PrincipalInfo& aPrincipalInfo,
     232             :                      const MediaEnginePrefs& aPrefs,
     233             :                      const nsString& aDeviceId)
     234             : 
     235           0 :     : mConstraints(aConstraints),
     236             :       mPrincipalInfo(aPrincipalInfo),
     237             :       mPrefs(aPrefs),
     238           0 :       mDeviceId(aDeviceId) {}
     239             :   public:
     240             :     NormalizedConstraints mConstraints;
     241             :     mozilla::ipc::PrincipalInfo mPrincipalInfo;
     242             :     MediaEnginePrefs mPrefs;
     243             :     nsString mDeviceId;
     244             :   };
     245             : 
     246             :   /* Release the device back to the system. */
     247           0 :   virtual nsresult Deallocate(AllocationHandle* aHandle)
     248             :   {
     249           0 :     MOZ_ASSERT(aHandle);
     250           0 :     RefPtr<AllocationHandle> handle = aHandle;
     251             : 
     252             :     class Comparator {
     253             :     public:
     254           0 :       static bool Equals(const RefPtr<AllocationHandle>& a,
     255             :                          const RefPtr<AllocationHandle>& b) {
     256           0 :         return a.get() == b.get();
     257             :       }
     258             :     };
     259             : 
     260           0 :     auto ix = mRegisteredHandles.IndexOf(handle, 0, Comparator());
     261           0 :     if (ix == mRegisteredHandles.NoIndex) {
     262           0 :       MOZ_ASSERT(false);
     263             :       return NS_ERROR_FAILURE;
     264             :     }
     265             : 
     266           0 :     mRegisteredHandles.RemoveElementAt(ix);
     267           0 :     if (mRegisteredHandles.Length() && !mInShutdown) {
     268             :       // Whenever constraints are removed, other parties may get closer to ideal.
     269           0 :       auto& first = mRegisteredHandles[0];
     270           0 :       const char* badConstraint = nullptr;
     271           0 :       return ReevaluateAllocation(nullptr, nullptr, first->mPrefs,
     272           0 :                                   first->mDeviceId, &badConstraint);
     273             :     }
     274           0 :     return NS_OK;
     275             :   }
     276             : 
     277             :   /* Start the device and add the track to the provided SourceMediaStream, with
     278             :    * the provided TrackID. You may start appending data to the track
     279             :    * immediately after. */
     280             :   virtual nsresult Start(SourceMediaStream*, TrackID, const PrincipalHandle&) = 0;
     281             : 
     282             :   /* tell the source if there are any direct listeners attached */
     283             :   virtual void SetDirectListeners(bool) = 0;
     284             : 
     285             :   /* Called when the stream wants more data */
     286             :   virtual void NotifyPull(MediaStreamGraph* aGraph,
     287             :                           SourceMediaStream *aSource,
     288             :                           TrackID aId,
     289             :                           StreamTime aDesiredTime,
     290             :                           const PrincipalHandle& aPrincipalHandle) = 0;
     291             : 
     292             :   /* Stop the device and release the corresponding MediaStream */
     293             :   virtual nsresult Stop(SourceMediaStream *aSource, TrackID aID) = 0;
     294             : 
     295             :   /* Restart with new capability */
     296             :   virtual nsresult Restart(AllocationHandle* aHandle,
     297             :                            const dom::MediaTrackConstraints& aConstraints,
     298             :                            const MediaEnginePrefs &aPrefs,
     299             :                            const nsString& aDeviceId,
     300             :                            const char** aOutBadConstraint) = 0;
     301             : 
     302             :   /* Returns true if a source represents a fake capture device and
     303             :    * false otherwise
     304             :    */
     305             :   virtual bool IsFake() = 0;
     306             : 
     307             :   /* Returns the type of media source (camera, microphone, screen, window, etc) */
     308             :   virtual dom::MediaSourceEnum GetMediaSource() const = 0;
     309             : 
     310             :   /* If implementation of MediaEngineSource supports TakePhoto(), the picture
     311             :    * should be return via aCallback object. Otherwise, it returns NS_ERROR_NOT_IMPLEMENTED.
     312             :    * Currently, only Gonk MediaEngineSource implementation supports it.
     313             :    */
     314             :   virtual nsresult TakePhoto(MediaEnginePhotoCallback* aCallback) = 0;
     315             : 
     316             :   /* Return false if device is currently allocated or started */
     317           0 :   bool IsAvailable() {
     318           0 :     if (mState == kAllocated || mState == kStarted) {
     319           0 :       return false;
     320             :     } else {
     321           0 :       return true;
     322             :     }
     323             :   }
     324             : 
     325             :   /* It is an error to call Start() before an Allocate(), and Stop() before
     326             :    * a Start(). Only Allocate() may be called after a Deallocate(). */
     327             : 
     328             :   /* This call reserves but does not start the device. */
     329           0 :   virtual nsresult Allocate(const dom::MediaTrackConstraints &aConstraints,
     330             :                             const MediaEnginePrefs &aPrefs,
     331             :                             const nsString& aDeviceId,
     332             :                             const mozilla::ipc::PrincipalInfo& aPrincipalInfo,
     333             :                             AllocationHandle** aOutHandle,
     334             :                             const char** aOutBadConstraint)
     335             :   {
     336           0 :     AssertIsOnOwningThread();
     337           0 :     MOZ_ASSERT(aOutHandle);
     338             :     RefPtr<AllocationHandle> handle =
     339           0 :       new AllocationHandle(aConstraints, aPrincipalInfo, aPrefs, aDeviceId);
     340           0 :     nsresult rv = ReevaluateAllocation(handle, nullptr, aPrefs, aDeviceId,
     341           0 :                                        aOutBadConstraint);
     342           0 :     if (NS_FAILED(rv)) {
     343           0 :       return rv;
     344             :     }
     345           0 :     mRegisteredHandles.AppendElement(handle);
     346           0 :     handle.forget(aOutHandle);
     347           0 :     return NS_OK;
     348             :   }
     349             : 
     350             :   virtual uint32_t GetBestFitnessDistance(
     351             :       const nsTArray<const NormalizedConstraintSet*>& aConstraintSets,
     352             :       const nsString& aDeviceId) const = 0;
     353             : 
     354           0 :   void GetSettings(dom::MediaTrackSettings& aOutSettings)
     355             :   {
     356           0 :     MOZ_ASSERT(NS_IsMainThread());
     357           0 :     aOutSettings = mSettings;
     358           0 :   }
     359             : 
     360             : protected:
     361             :   // Only class' own members can be initialized in constructor initializer list.
     362           0 :   explicit MediaEngineSource(MediaEngineState aState)
     363           0 :     : mState(aState)
     364           0 :     , mInShutdown(false)
     365           0 :   {}
     366             : 
     367             :   /* UpdateSingleSource - Centralized abstract function to implement in those
     368             :    * cases where a single device is being shared between users. Should apply net
     369             :    * constraints and restart the device as needed.
     370             :    *
     371             :    * aHandle           - New or existing handle, or null to update after removal.
     372             :    * aNetConstraints   - Net constraints to be applied to the single device.
     373             :    * aPrefs            - As passed in (in case of changes in about:config).
     374             :    * aDeviceId         - As passed in (origin dependent).
     375             :    * aOutBadConstraint - Result: nonzero if failed to apply. Name of culprit.
     376             :    */
     377             : 
     378             :   virtual nsresult
     379           0 :   UpdateSingleSource(const AllocationHandle* aHandle,
     380             :                      const NormalizedConstraints& aNetConstraints,
     381             :                      const MediaEnginePrefs& aPrefs,
     382             :                      const nsString& aDeviceId,
     383             :                      const char** aOutBadConstraint) {
     384           0 :     return NS_ERROR_NOT_IMPLEMENTED;
     385             :   };
     386             : 
     387             :   /* ReevaluateAllocation - Call to change constraints for an allocation of
     388             :    * a single device. Manages allocation handles, calculates net constraints
     389             :    * from all competing allocations, and calls UpdateSingleSource with the net
     390             :    * result, to restart the single device as needed.
     391             :    *
     392             :    * aHandle            - New or existing handle, or null to update after removal.
     393             :    * aConstraintsUpdate - Constraints to be applied to existing handle, or null.
     394             :    * aPrefs             - As passed in (in case of changes from about:config).
     395             :    * aDeviceId          - As passed in (origin-dependent id).
     396             :    * aOutBadConstraint  - Result: nonzero if failed to apply. Name of culprit.
     397             :    */
     398             : 
     399             :   nsresult
     400           0 :   ReevaluateAllocation(AllocationHandle* aHandle,
     401             :                        NormalizedConstraints* aConstraintsUpdate,
     402             :                        const MediaEnginePrefs& aPrefs,
     403             :                        const nsString& aDeviceId,
     404             :                        const char** aOutBadConstraint)
     405             :   {
     406             :     // aHandle and/or aConstraintsUpdate may be nullptr (see below)
     407             : 
     408           0 :     AutoTArray<const NormalizedConstraints*, 10> allConstraints;
     409           0 :     for (auto& registered : mRegisteredHandles) {
     410           0 :       if (aConstraintsUpdate && registered.get() == aHandle) {
     411           0 :         continue; // Don't count old constraints
     412             :       }
     413           0 :       allConstraints.AppendElement(&registered->mConstraints);
     414             :     }
     415           0 :     if (aConstraintsUpdate) {
     416           0 :       allConstraints.AppendElement(aConstraintsUpdate);
     417           0 :     } else if (aHandle) {
     418             :       // In the case of AddShareOfSingleSource, the handle isn't registered yet.
     419           0 :       allConstraints.AppendElement(&aHandle->mConstraints);
     420             :     }
     421             : 
     422           0 :     NormalizedConstraints netConstraints(allConstraints);
     423           0 :     if (netConstraints.mBadConstraint) {
     424           0 :       *aOutBadConstraint = netConstraints.mBadConstraint;
     425           0 :       return NS_ERROR_FAILURE;
     426             :     }
     427             : 
     428             :     nsresult rv = UpdateSingleSource(aHandle, netConstraints, aPrefs, aDeviceId,
     429           0 :                                      aOutBadConstraint);
     430           0 :     if (NS_FAILED(rv)) {
     431           0 :       return rv;
     432             :     }
     433           0 :     if (aHandle && aConstraintsUpdate) {
     434           0 :       aHandle->mConstraints = *aConstraintsUpdate;
     435             :     }
     436           0 :     return NS_OK;
     437             :   }
     438             : 
     439           0 :   void AssertIsOnOwningThread()
     440             :   {
     441           0 :     NS_ASSERT_OWNINGTHREAD(MediaEngineSource);
     442           0 :   }
     443             : 
     444             :   MediaEngineState mState;
     445             : 
     446             :   NS_DECL_OWNINGTHREAD
     447             : 
     448             :   nsTArray<RefPtr<AllocationHandle>> mRegisteredHandles;
     449             :   bool mInShutdown;
     450             : 
     451             :   // Main-thread only:
     452             :   dom::MediaTrackSettings mSettings;
     453             : };
     454             : 
     455             : class MediaEngineVideoSource : public MediaEngineSource
     456             : {
     457             : public:
     458           0 :   virtual ~MediaEngineVideoSource() {}
     459             : 
     460             : protected:
     461           0 :   explicit MediaEngineVideoSource(MediaEngineState aState)
     462           0 :     : MediaEngineSource(aState) {}
     463           0 :   MediaEngineVideoSource()
     464           0 :     : MediaEngineSource(kReleased) {}
     465             : };
     466             : 
     467             : /**
     468             :  * Audio source and friends.
     469             :  */
     470             : class MediaEngineAudioSource : public MediaEngineSource,
     471             :                                public AudioDataListenerInterface
     472             : {
     473             : public:
     474           0 :   virtual ~MediaEngineAudioSource() {}
     475             : 
     476             : protected:
     477           0 :   explicit MediaEngineAudioSource(MediaEngineState aState)
     478           0 :     : MediaEngineSource(aState) {}
     479             :   MediaEngineAudioSource()
     480             :     : MediaEngineSource(kReleased) {}
     481             : 
     482             : };
     483             : 
     484             : } // namespace mozilla
     485             : 
     486             : #endif /* MEDIAENGINE_H_ */

Generated by: LCOV version 1.13