1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4  * License, v. 2.0. If a copy of the MPL was not distributed with this
5  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 
7 #ifndef MediaEngineSource_h
8 #define MediaEngineSource_h
9 
10 #include "MediaSegment.h"
11 #include "MediaTrackConstraints.h"
12 #include "mozilla/dom/MediaStreamTrackBinding.h"
13 #include "mozilla/media/MediaUtils.h"
14 #include "mozilla/RefPtr.h"
15 #include "mozilla/ThreadSafeWeakPtr.h"
16 #include "nsStringFwd.h"
17 
18 namespace mozilla {
19 
20 namespace dom {
21 class Blob;
22 struct MediaTrackSettings;
23 }  // namespace dom
24 
25 namespace ipc {
26 class PrincipalInfo;
27 }  // namespace ipc
28 
29 class MediaEnginePhotoCallback;
30 class MediaEnginePrefs;
31 class SourceMediaTrack;
32 
33 /**
34  * Callback interface for TakePhoto(). Either PhotoComplete() or PhotoError()
35  * should be called.
36  */
37 class MediaEnginePhotoCallback {
38  public:
39   NS_INLINE_DECL_THREADSAFE_REFCOUNTING(MediaEnginePhotoCallback)
40 
41   // aBlob is the image captured by MediaEngineSource. It is
42   // called on main thread.
43   virtual nsresult PhotoComplete(already_AddRefed<dom::Blob> aBlob) = 0;
44 
45   // It is called on main thread. aRv is the error code.
46   virtual nsresult PhotoError(nsresult aRv) = 0;
47 
48  protected:
49   virtual ~MediaEnginePhotoCallback() = default;
50 };
51 
52 /**
53  * Lifecycle state of MediaEngineSource.
54  */
55 enum MediaEngineSourceState {
56   kAllocated,  // Allocated, not yet started.
57   kStarted,    // Previously allocated or stopped, then started.
58   kStopped,    // Previously started, then stopped.
59   kReleased    // Not allocated.
60 };
61 
62 /**
63  * The pure interface of a MediaEngineSource.
64  *
65  * Most sources are helped by the defaults implemented in MediaEngineSource.
66  */
67 class MediaEngineSourceInterface {
68  public:
69   /**
70    * Return true if this is a fake source. I.e., if it is generating media
71    * itself rather than being an interface to underlying hardware.
72    */
73   virtual bool IsFake() const = 0;
74 
75   /**
76    * Gets the human readable name of this device.
77    */
78   virtual nsString GetName() const = 0;
79 
80   /**
81    * Gets the raw (non-anonymous) UUID of this device.
82    */
83   virtual nsCString GetUUID() const = 0;
84 
85   /**
86    * Gets the raw Group id of this device.
87    */
88   virtual nsString GetGroupId() const = 0;
89 
90   /**
91    * Get the enum describing the underlying type of MediaSource.
92    */
93   virtual dom::MediaSourceEnum GetMediaSource() const = 0;
94 
95   /**
96    * Override w/true if source does end-run around cross origin restrictions.
97    */
98   virtual bool GetScary() const = 0;
99 
100   /**
101    * Override w/a promise if source has frames, in order to potentially allow
102    * deferring success of source acquisition until first frame has arrived.
103    */
GetFirstFramePromise()104   virtual RefPtr<GenericNonExclusivePromise> GetFirstFramePromise() const {
105     return nullptr;
106   }
107 
108   /**
109    * Called by MediaEngine to allocate an instance of this source.
110    */
111   virtual nsresult Allocate(const dom::MediaTrackConstraints& aConstraints,
112                             const MediaEnginePrefs& aPrefs, uint64_t aWindowID,
113                             const char** aOutBadConstraint) = 0;
114 
115   /**
116    * Called by MediaEngine when a SourceMediaTrack has been provided for the
117    * source to feed data to.
118    *
119    * This must be called before Start.
120    */
121   virtual void SetTrack(const RefPtr<SourceMediaTrack>& aTrack,
122                         const PrincipalHandle& aPrincipal) = 0;
123 
124   /**
125    * Called by MediaEngine to start feeding data to the track.
126    *
127    * NB: Audio sources handle the enabling of pulling themselves.
128    */
129   virtual nsresult Start() = 0;
130 
131   /**
132    * This brings focus to the selected source, e.g. to bring a captured window
133    * to the front.
134    *
135    * We return one of the following:
136    * NS_OK                    - Success.
137    * NS_ERROR_NOT_AVAILABLE   - For backends where focusing does not make sense.
138    * NS_ERROR_NOT_IMPLEMENTED - For backends where focusing makes sense, but
139    *                            is not yet implemented.
140    * NS_ERROR_FAILURE         - Failures reported from underlying code.
141    */
142   virtual nsresult FocusOnSelectedSource() = 0;
143 
144   /**
145    * Applies new constraints to the capability selection for the underlying
146    * device.
147    *
148    * Should the constraints lead to choosing a new capability while the device
149    * is actively being captured, the device will restart using the new
150    * capability.
151    *
152    * We return one of the following:
153    * NS_OK                - Successful reconfigure.
154    * NS_ERROR_INVALID_ARG - Couldn't find a capability fitting aConstraints.
155    *                        See aBadConstraint for details.
156    * NS_ERROR_UNEXPECTED  - Reconfiguring the underlying device failed
157    *                        unexpectedly. This leaves the device in a stopped
158    *                        state.
159    */
160   virtual nsresult Reconfigure(const dom::MediaTrackConstraints& aConstraints,
161                                const MediaEnginePrefs& aPrefs,
162                                const char** aOutBadConstraint) = 0;
163 
164   /**
165    * Called by MediaEngine to stop feeding data to the track.
166    *
167    * Double-stopping is allowed and will return NS_OK. This is necessary
168    * sometimes during shutdown.
169    *
170    * NB: Audio sources handle the disabling of pulling themselves.
171    */
172   virtual nsresult Stop() = 0;
173 
174   /**
175    * Called by MediaEngine to deallocate an underlying device.
176    */
177   virtual nsresult Deallocate() = 0;
178 
179   /**
180    * Called by MediaEngine when it knows this MediaEngineSource won't be used
181    * anymore. Use it to clean up anything that needs to be cleaned up.
182    */
183   virtual void Shutdown() = 0;
184 
185   /**
186    * If implementation of MediaEngineSource supports TakePhoto(), the picture
187    * should be returned via aCallback object. Otherwise, it returns
188    * NS_ERROR_NOT_IMPLEMENTED.
189    */
190   virtual nsresult TakePhoto(MediaEnginePhotoCallback* aCallback) = 0;
191 
192   /**
193    * GetBestFitnessDistance returns the best distance the capture device can
194    * offer as a whole, given an accumulated number of ConstraintSets. Ideal
195    * values are considered in the first ConstraintSet only. Plain values are
196    * treated as Ideal in the first ConstraintSet. Plain values are treated as
197    * Exact in subsequent ConstraintSets. Infinity = UINT32_MAX e.g. device
198    * cannot satisfy accumulated ConstraintSets. A finite result may be used to
199    * calculate this device's ranking as a choice.
200    */
201   virtual uint32_t GetBestFitnessDistance(
202       const nsTArray<const NormalizedConstraintSet*>& aConstraintSets)
203       const = 0;
204 
205   /**
206    * Returns the current settings of the underlying device.
207    *
208    * Note that this might not be the settings of the underlying hardware.
209    * In case of a camera where we intervene and scale frames to avoid
210    * leaking information from other documents than the current one,
211    * GetSettings() will return the scaled resolution. I.e., the
212    * device settings as seen by js.
213    */
214   virtual void GetSettings(dom::MediaTrackSettings& aOutSettings) const = 0;
215 };
216 
217 /**
218  * Abstract base class for MediaEngineSources.
219  *
220  * Implements defaults for some common MediaEngineSourceInterface methods below.
221  * Also implements RefPtr support and an owning-thread model for thread safety
222  * checks in subclasses.
223  */
224 class MediaEngineSource : public MediaEngineSourceInterface {
225  public:
226   // code inside webrtc.org assumes these sizes; don't use anything smaller
227   // without verifying it's ok
228   static const unsigned int kMaxDeviceNameLength = 128;
229   static const unsigned int kMaxUniqueIdLength = 256;
230 
231   /**
232    * Returns true if the given source type is for video, false otherwise.
233    * Only call with real types.
234    */
235   static bool IsVideo(dom::MediaSourceEnum aSource);
236 
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(MediaEngineSource)237   NS_INLINE_DECL_THREADSAFE_REFCOUNTING(MediaEngineSource)
238   NS_DECL_OWNINGTHREAD
239 
240   void AssertIsOnOwningThread() const {
241     NS_ASSERT_OWNINGTHREAD(MediaEngineSource);
242   }
243 
244   // Not fake by default.
245   bool IsFake() const override;
246 
247   // Not scary by default.
248   bool GetScary() const override;
249 
250   // Returns NS_ERROR_NOT_AVAILABLE by default.
251   nsresult FocusOnSelectedSource() override;
252 
253   // Shutdown does nothing by default.
254   void Shutdown() override;
255 
256   // TakePhoto returns NS_ERROR_NOT_IMPLEMENTED by default,
257   // to tell the caller to fallback to other methods.
258   nsresult TakePhoto(MediaEnginePhotoCallback* aCallback) override;
259 
260   // Returns a default distance of 0 for devices that don't have capabilities.
GetBestFitnessDistance(const nsTArray<const NormalizedConstraintSet * > & aConstraintSets)261   uint32_t GetBestFitnessDistance(
262       const nsTArray<const NormalizedConstraintSet*>& aConstraintSets)
263       const override {
264     return 0;
265   }
266 
267  protected:
268   virtual ~MediaEngineSource();
269 };
270 
271 }  // namespace mozilla
272 
273 #endif /* MediaEngineSource_h */
274