MediaEngineRemoteVideoSource.h (10298B)
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim: set sw=2 ts=8 et ft=cpp : */ 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 file, 5 * You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 #ifndef MEDIAENGINE_REMOTE_VIDEO_SOURCE_H_ 8 #define MEDIAENGINE_REMOTE_VIDEO_SOURCE_H_ 9 10 #include "CamerasChild.h" 11 #include "DOMMediaStream.h" 12 #include "MediaEngineSource.h" 13 #include "MediaTrackGraph.h" 14 #include "common_video/include/video_frame_buffer_pool.h" 15 #include "modules/video_capture/video_capture_defines.h" 16 #include "mozilla/Mutex.h" 17 #include "mozilla/dom/MediaStreamTrackBinding.h" 18 19 namespace webrtc { 20 using CaptureCapability = VideoCaptureCapability; 21 } 22 23 namespace mozilla { 24 namespace dom { 25 enum class VideoResizeModeEnum : uint8_t; 26 } 27 28 // Fitness distance is defined in 29 // https://w3c.github.io/mediacapture-main/getusermedia.html#dfn-selectsettings 30 31 // In contrast, feasibility distance — used in the implementatioon of 32 // crop_and_scale — effectively rounds width and height up to the nearest 33 // native width and height before calculating distance (sorta). 34 // 35 // Another difference is that if the constraint is required 36 // (min, 'max', or 'exact'), and the settings dictionary's 37 // value for the constraint does not satisfy the constraint, the fitness 38 // distance is positive infinity. Given a continuous space of settings 39 // dictionaries comprising all discrete combinations of dimension and frame-rate 40 // related properties, the feasibility distance is still in keeping with the 41 // constraints algorithm. 42 enum DistanceCalculation { kFitness, kFeasibility }; 43 44 /** 45 * The WebRTC implementation of the MediaEngine interface. 46 */ 47 class MediaEngineRemoteVideoSource : public MediaEngineSource, 48 public camera::FrameRelay { 49 ~MediaEngineRemoteVideoSource(); 50 51 struct CapabilityCandidate { 52 explicit CapabilityCandidate(webrtc::CaptureCapability aCapability, 53 uint32_t aDistance = 0) 54 : mCapability(aCapability), mDistance(aDistance) {} 55 56 const webrtc::CaptureCapability mCapability; 57 uint32_t mDistance; 58 }; 59 60 class CapabilityComparator { 61 public: 62 bool Equals(const CapabilityCandidate& aCandidate, 63 const webrtc::CaptureCapability& aCapability) const { 64 return aCandidate.mCapability == aCapability; 65 } 66 }; 67 68 bool ChooseCapability(const NormalizedConstraints& aConstraints, 69 const MediaEnginePrefs& aPrefs, 70 webrtc::CaptureCapability& aCapability, 71 const DistanceCalculation aCalculate, 72 const char** aOutBadConstraint); 73 74 uint32_t GetDistance(const webrtc::CaptureCapability& aCandidate, 75 const NormalizedConstraintSet& aConstraints, 76 const DistanceCalculation aCalculate) const; 77 78 uint32_t GetFitnessDistance( 79 const webrtc::CaptureCapability& aCandidate, 80 const NormalizedConstraintSet& aConstraints) const; 81 82 uint32_t GetFeasibilityDistance( 83 const webrtc::CaptureCapability& aCandidate, 84 const NormalizedConstraintSet& aConstraints) const; 85 86 static void TrimLessFitCandidates(nsTArray<CapabilityCandidate>& aSet); 87 88 public: 89 explicit MediaEngineRemoteVideoSource(const MediaDevice* aMediaDevice); 90 91 static already_AddRefed<MediaEngineRemoteVideoSource> CreateFrom( 92 const MediaEngineRemoteVideoSource* aSource, 93 const MediaDevice* aMediaDevice); 94 95 // ExternalRenderer 96 /** 97 * Signals that the capture stream has ended 98 **/ 99 void OnCaptureEnded() override; 100 int DeliverFrame(uint8_t* aBuffer, 101 const camera::VideoFrameProperties& aProps) override; 102 103 // MediaEngineSource 104 nsresult Allocate(const dom::MediaTrackConstraints& aConstraints, 105 const MediaEnginePrefs& aPrefs, uint64_t aWindowID, 106 const char** aOutBadConstraint) override; 107 nsresult Deallocate() override; 108 void SetTrack(const RefPtr<MediaTrack>& aTrack, 109 const PrincipalHandle& aPrincipal) override; 110 nsresult Start() override; 111 nsresult Reconfigure(const dom::MediaTrackConstraints& aConstraints, 112 const MediaEnginePrefs& aPrefs, 113 const char** aOutBadConstraint) override; 114 nsresult FocusOnSelectedSource() override; 115 nsresult Stop() override; 116 117 nsresult StartCapture(const NormalizedConstraints& aConstraints, 118 const dom::VideoResizeModeEnum& aResizeMode); 119 uint32_t GetBestFitnessDistance( 120 const nsTArray<const NormalizedConstraintSet*>& aConstraintSets, 121 const MediaEnginePrefs& aPrefs) const override; 122 void GetSettings(dom::MediaTrackSettings& aOutSettings) const override; 123 124 RefPtr<GenericNonExclusivePromise> GetFirstFramePromise() const override { 125 return mFirstFramePromise; 126 } 127 128 const TrackingId& GetTrackingId() const override; 129 130 static camera::CaptureEngine CaptureEngine(dom::MediaSourceEnum aMediaSource); 131 132 MediaEventSource<void>* CaptureEndedEvent() override { 133 return &mCaptureEndedEvent; 134 } 135 136 void GetCapabilities( 137 dom::MediaTrackCapabilities& aOutCapabilities) const override; 138 139 private: 140 /** 141 * Returns the number of capabilities for the underlying device. 142 * 143 * Guaranteed to return at least one capability. 144 */ 145 size_t NumCapabilities() const; 146 147 /** 148 * Returns the capability with index `aIndex` for our assigned device. 149 * 150 * It is an error to call this with `aIndex >= NumCapabilities()`. 151 * 152 * The lifetime of the returned capability is the same as for this source. 153 */ 154 webrtc::CaptureCapability& GetCapability(size_t aIndex) const; 155 156 int mCaptureId = -1; 157 const camera::CaptureEngine mCapEngine; // source of media (cam, screen etc) 158 159 // A tracking id used to uniquely identify the source of video frames. 160 // Set under mMutex on the owning thread. Accessed under one of the two. 161 TrackingId mTrackingId; 162 163 // Mirror of mTrackingId on the frame-delivering thread (Cameras IPC). 164 Maybe<TrackingId> mFrameDeliveringTrackingId; 165 166 // mMutex protects certain members on 3 threads: 167 // MediaManager, Cameras IPC and MediaTrackGraph. 168 mutable Mutex mMutex MOZ_UNANNOTATED; 169 170 // Current state of this source. 171 // Set under mMutex on the owning thread. Accessed under one of the two. 172 MediaEngineSourceState mState = kReleased; 173 174 // The source track that we feed video data to. 175 // Set under mMutex on the owning thread. Accessed under one of the two. 176 RefPtr<SourceMediaTrack> mTrack; 177 178 // The PrincipalHandle that gets attached to the frames we feed to mTrack. 179 // Set under mMutex on the owning thread. Accessed under one of the two. 180 PrincipalHandle mPrincipal = PRINCIPAL_HANDLE_NONE; 181 182 // Set in Start() and Deallocate() on the owning thread. 183 // Accessed in DeliverFrame() on the camera IPC thread, guaranteed to happen 184 // after Start() and before the end of Stop(). 185 RefPtr<layers::ImageContainer> mImageContainer; 186 187 // A buffer pool used to manage the temporary buffer used when rescaling 188 // incoming images. Cameras IPC thread only. 189 webrtc::VideoFrameBufferPool mRescalingBufferPool; 190 191 // The intrinsic size of the latest received image, before cropping and 192 // scaling down. So we can provide a decent guess to settings for desktop 193 // sources, since they don't provide capabilities. 194 // Set under mMutex on the Cameras IPC thread. Accessed under one of the two. 195 gfx::IntSize mIncomingImageSize = gfx::IntSize(0, 0); 196 197 // The intrinsic size of the latest processed image, after cropping and 198 // scaling down. So we can update settings on main thread in response to size 199 // changes. 200 // Set under mMutex on the Cameras IPC thread. Accessed under one of the two. 201 gfx::IntSize mScaledImageSize = gfx::IntSize(0, 0); 202 203 struct AtomicBool { 204 Atomic<bool> mValue; 205 }; 206 207 // True when resolution settings have been updated from a real frame's 208 // resolution. Threadsafe. Set to false on the owning thread. Set to true on 209 // main thread. 210 const RefPtr<media::Refcountable<AtomicBool>> mSettingsUpdatedByFrame; 211 212 // The current settings of this source. 213 // Note that these may be different from the settings of the underlying device 214 // since we scale frames to avoid fingerprinting. 215 // Members are main thread only. 216 const RefPtr<media::Refcountable<dom::MediaTrackSettings>> mSettings; 217 const RefPtr<media::Refcountable<dom::MediaTrackCapabilities>> 218 mTrackCapabilities; 219 MozPromiseHolder<GenericNonExclusivePromise> mFirstFramePromiseHolder; 220 RefPtr<GenericNonExclusivePromise> mFirstFramePromise; 221 222 // The capability currently chosen by constraints of the user of this source, 223 // and the distance calculation used when applying them. 224 // Set under mMutex on the owning thread. Accessed under one of the two. 225 webrtc::CaptureCapability mCapability; 226 DistanceCalculation mCalculation; 227 228 // The constraints we're currently operating under, for calculating incoming 229 // video resolution. 230 Maybe<NormalizedConstraints> mConstraints MOZ_GUARDED_BY(mMutex); 231 232 // Owning thread only. 233 UniquePtr<MediaEnginePrefs> mPrefs; 234 235 /** 236 * Capabilities that we choose between when applying constraints. 237 * 238 * This allows for memoization of capabilities as they're requested from the 239 * parent process. 240 * 241 * This is mutable so that the const methods NumCapabilities() and 242 * GetCapability() can reset it. Owning thread only. 243 */ 244 mutable nsTArray<UniquePtr<webrtc::CaptureCapability>> mCapabilities; 245 246 /** 247 * True if mCapabilities only contains hardcoded capabilities. This can happen 248 * if the underlying device is not reporting any capabilities. These can be 249 * affected by constraints, so they're evaluated in ChooseCapability() rather 250 * than GetCapability(). 251 * 252 * This is mutable so that the const methods NumCapabilities() and 253 * GetCapability() can reset it. Owning thread only. 254 */ 255 mutable bool mCapabilitiesAreHardcoded = false; 256 257 const RefPtr<const MediaDevice> mMediaDevice; 258 const nsCString mDeviceUUID; 259 Maybe<nsString> mFacingMode; 260 MediaEventProducer<void> mCaptureEndedEvent; 261 }; 262 263 } // namespace mozilla 264 265 #endif /* MEDIAENGINE_REMOTE_VIDEO_SOURCE_H_ */