1 // Copyright 2014 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef THIRD_PARTY_BLINK_PUBLIC_WEB_MODULES_MEDIASTREAM_MEDIA_STREAM_VIDEO_SOURCE_H_ 6 #define THIRD_PARTY_BLINK_PUBLIC_WEB_MODULES_MEDIASTREAM_MEDIA_STREAM_VIDEO_SOURCE_H_ 7 8 #include <memory> 9 #include <string> 10 #include <vector> 11 12 #include "base/compiler_specific.h" 13 #include "base/macros.h" 14 #include "base/memory/weak_ptr.h" 15 #include "base/optional.h" 16 #include "base/threading/thread_checker.h" 17 #include "media/base/video_frame.h" 18 #include "media/capture/video_capture_types.h" 19 #include "third_party/blink/public/common/media/video_capture.h" 20 #include "third_party/blink/public/mojom/mediastream/media_stream.mojom-shared.h" 21 #include "third_party/blink/public/platform/modules/mediastream/media_stream_types.h" 22 #include "third_party/blink/public/platform/modules/mediastream/secure_display_link_tracker.h" 23 #include "third_party/blink/public/platform/modules/mediastream/web_platform_media_stream_source.h" 24 #include "third_party/blink/public/platform/web_common.h" 25 #include "third_party/blink/public/platform/web_media_stream_source.h" 26 #include "third_party/blink/public/platform/web_media_stream_track.h" 27 #include "third_party/blink/public/web/modules/mediastream/encoded_video_frame.h" 28 29 namespace base { 30 class SingleThreadTaskRunner; 31 } 32 33 namespace blink { 34 35 class MediaStreamVideoTrack; 36 class VideoTrackAdapter; 37 class VideoTrackAdapterSettings; 38 39 // MediaStreamVideoSource is an interface used for sending video frames to a 40 // MediaStreamVideoTrack. 41 // https://dev.w3.org/2011/webrtc/editor/getusermedia.html 42 // The purpose of this base class is to be able to implement different 43 // MediaStreamVideoSources such as local video capture, video sources received 44 // on a PeerConnection or a source created in NaCl. 45 // All methods calls will be done from the main render thread. 46 class BLINK_MODULES_EXPORT MediaStreamVideoSource 47 : public WebPlatformMediaStreamSource { 48 public: 49 enum { 50 // Default resolution. If no constraints are specified and the delegate 51 // support it, this is the resolution that will be used. 52 kDefaultWidth = 640, 53 kDefaultHeight = 480, 54 55 kDefaultFrameRate = 30, 56 kUnknownFrameRate = 0, 57 }; 58 59 enum class RestartResult { IS_RUNNING, IS_STOPPED, INVALID_STATE }; 60 // RestartCallback is used for both the StopForRestart and Restart operations. 61 using RestartCallback = base::OnceCallback<void(RestartResult)>; 62 63 MediaStreamVideoSource(); 64 ~MediaStreamVideoSource() override; 65 66 // Returns the MediaStreamVideoSource object owned by |source|. 67 static MediaStreamVideoSource* GetVideoSource( 68 const WebMediaStreamSource& source); 69 70 // Puts |track| in the registered tracks list. 71 void AddTrack(MediaStreamVideoTrack* track, 72 const VideoTrackAdapterSettings& track_adapter_settings, 73 const VideoCaptureDeliverFrameCB& frame_callback, 74 const EncodedVideoFrameCB& encoded_frame_callback, 75 const VideoTrackSettingsCallback& settings_callback, 76 const VideoTrackFormatCallback& format_callback, 77 ConstraintsOnceCallback callback); 78 void RemoveTrack(MediaStreamVideoTrack* track, base::OnceClosure callback); 79 80 // Reconfigures this MediaStreamVideoSource to use |adapter_settings| on 81 // |track|, as long as |track| is connected to this source. 82 // Do not invoke if |track| is connected to a different source, as the 83 // internal state of |track| might become inconsistent with that of its 84 // source. 85 void ReconfigureTrack(MediaStreamVideoTrack* track, 86 const VideoTrackAdapterSettings& adapter_settings); 87 88 // Tries to temporarily stop this source so that it can be later restarted 89 // with a different video format. Unlike MediaStreamVideoSource::StopSource(), 90 // a temporary stop for restart does not change the ready state of the source. 91 // Once the attempt to temporarily stop the source is completed, |callback| 92 // is invoked with IS_STOPPED if the source actually stopped, or IS_RUNNING 93 // if the source did not stop and is still running. 94 // This method can only be called after a source has started. This can be 95 // verified by checking that the IsRunning() method returns true. 96 // Any attempt to invoke StopForRestart() before the source has started 97 // results in no action and |callback| invoked with INVALID_STATE. 98 void StopForRestart(RestartCallback callback); 99 100 // Tries to restart a source that was previously temporarily stopped using the 101 // supplied |new_format|. This method can be invoked only after a successful 102 // call to StopForRestart(). 103 // Once the attempt to restart the source is completed, |callback| is invoked 104 // with IS_RUNNING if the source restarted and IS_STOPPED if the source 105 // remained stopped. Note that it is not guaranteed that the source actually 106 // restarts using |new_format| as its configuration. After a successful 107 // restart, the actual configured format for the source (if available) can be 108 // obtained with a call to GetCurrentFormat(). 109 // Note also that, since frames are delivered on a different thread, it is 110 // possible that frames using the old format are delivered for a while after 111 // a successful restart. Code relying on Restart() cannot assume that new 112 // frames are guaranteed to arrive in the new format until the first frame in 113 // the new format is received. 114 // This method can only be called after a successful stop for restart (i.e., 115 // after the callback passed to StopForRestart() is invoked with a value of 116 // IS_STOPPED). Any attempt to invoke Restart() when the source is not in this 117 // state results in no action and |callback| invoked with INVALID_STATE. 118 void Restart(const media::VideoCaptureFormat& new_format, 119 RestartCallback callback); 120 121 // Called by |track| to notify the source whether it has any paths to a 122 // consuming endpoint. 123 void UpdateHasConsumers(MediaStreamVideoTrack* track, bool has_consumers); 124 125 void UpdateCapturingLinkSecure(MediaStreamVideoTrack* track, bool is_secure); 126 127 // Request underlying source to capture a new frame. RequestRefreshFrame()128 virtual void RequestRefreshFrame() {} 129 130 // Optionally overridden by subclasses to implement handling frame drop 131 // events. OnFrameDropped(media::VideoCaptureFrameDropReason reason)132 virtual void OnFrameDropped(media::VideoCaptureFrameDropReason reason) {} 133 134 // Optionally overridden by subclasses to implement handling log messages. OnLog(const std::string & message)135 virtual void OnLog(const std::string& message) {} 136 137 // Enables or disables an heuristic to detect frames from rotated devices. 138 void SetDeviceRotationDetection(bool enabled); 139 140 // Returns the task runner where video frames will be delivered on. 141 base::SingleThreadTaskRunner* io_task_runner() const; 142 143 // Implementations must return the capture format if available. 144 // Implementations supporting devices of type MEDIA_DEVICE_VIDEO_CAPTURE 145 // must return a value. 146 virtual base::Optional<media::VideoCaptureFormat> GetCurrentFormat() const; 147 148 // Implementations must return the capture parameters if available. 149 // Implementations supporting devices of type MEDIA_DEVICE_VIDEO_CAPTURE 150 // must return a value. The format in the returned VideoCaptureParams must 151 // coincide with the value returned by GetCurrentFormat(). 152 virtual base::Optional<media::VideoCaptureParams> GetCurrentCaptureParams() 153 const; 154 155 // Returns true if encoded output can be enabled in the source. 156 virtual bool SupportsEncodedOutput() const; 157 158 // Notifies the source about that the number of encoded sinks have been 159 // updated. Note: Can only be called if the number of encoded sinks have 160 // actually changed! 161 void UpdateNumEncodedSinks(); 162 IsRunning()163 bool IsRunning() const { return state_ == STARTED; } 164 NumTracks()165 size_t NumTracks() const { 166 DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); 167 return tracks_.size(); 168 } 169 GetWeakPtr()170 base::WeakPtr<MediaStreamVideoSource> GetWeakPtr() { 171 return weak_factory_.GetWeakPtr(); 172 } 173 174 protected: 175 // MediaStreamSource implementation. 176 void DoChangeSource(const MediaStreamDevice& new_device) override; 177 void DoStopSource() override; 178 179 // Sets ready state and notifies the ready state to all registered tracks. 180 virtual void SetReadyState(WebMediaStreamSource::ReadyState state); 181 182 // Sets muted state and notifies it to all registered tracks. 183 virtual void SetMutedState(bool state); 184 185 // An implementation must start capturing frames after this method is called. 186 // When the source has started or failed to start OnStartDone must be called. 187 // An implementation must call |frame_callback| on the IO thread with the 188 // captured frames, and |encoded_frame_callback| with encoded frames if 189 // supported and enabled via OnEncodedSinkEnabled. 190 virtual void StartSourceImpl(VideoCaptureDeliverFrameCB frame_callback, 191 EncodedVideoFrameCB encoded_frame_callback) = 0; 192 void OnStartDone(mojom::MediaStreamRequestResult result); 193 194 // A subclass that supports restart must override this method such that it 195 // immediately stop producing video frames after this method is called. 196 // The stop is intended to be temporary and to be followed by a restart. Thus, 197 // connected tracks should not be disconnected or notified about the source no 198 // longer producing frames. Once the source is stopped, the implementation 199 // must invoke OnStopForRestartDone() with true. If the source cannot stop, 200 // OnStopForRestartDone() must invoked with false. 201 // It can be assumed that this method is invoked only when the source is 202 // running. 203 // Note that if this method is overridden, RestartSourceImpl() must also be 204 // overridden following the respective contract. Otherwise, behavior is 205 // undefined. 206 // The default implementation does not support restart and just calls 207 // OnStopForRestartDone() with false. 208 virtual void StopSourceForRestartImpl(); 209 210 // This method should be called by implementations once an attempt to stop 211 // for restart using StopSourceForRestartImpl() is completed. 212 // |did_stop_for_restart| must true if the source is stopped and false if 213 // the source is running. 214 void OnStopForRestartDone(bool did_stop_for_restart); 215 216 // A subclass that supports restart must override this method such that it 217 // tries to start producing frames after this method is called. If successful, 218 // the source should return to the same state as if it was started normally 219 // and invoke OnRestartDone() with true. The implementation should preferably 220 // restart to produce frames with the format specified in |new_format|. 221 // However, if this is not possible, the implementation is allowed to restart 222 // using a different format. In this case OnRestartDone() should be invoked 223 // with true as well. If it is impossible to restart the source with any 224 // format, the source should remain stopped and OnRestartDone() should be 225 // invoked with false. 226 // This method can only be invoked when the source is temporarily stopped 227 // after a successful OnStopForRestartDone(). Otherwise behavior is undefined. 228 // Note that if this method is overridden, StopSourceForRestartImpl() must 229 // also be overridden following the respective contract. Otherwise, behavior 230 // is undefined. 231 virtual void RestartSourceImpl(const media::VideoCaptureFormat& new_format); 232 233 // This method should be called by implementations once an attempt to restart 234 // the source completes. |did_restart| must be true if the source is running 235 // and false if the source is stopped. 236 void OnRestartDone(bool did_restart); 237 238 // An implementation must immediately stop producing video frames after this 239 // method has been called. After this method has been called, 240 // MediaStreamVideoSource may be deleted. 241 virtual void StopSourceImpl() = 0; 242 243 // Optionally overridden by subclasses to act on whether there are any 244 // consumers present. When none are present, the source can stop delivering 245 // frames, giving it the option of running in an "idle" state to minimize 246 // resource usage. OnHasConsumers(bool has_consumers)247 virtual void OnHasConsumers(bool has_consumers) {} 248 249 // Optionally overridden by subclasses to act on whether the capturing link 250 // has become secure or insecure. OnCapturingLinkSecured(bool is_secure)251 virtual void OnCapturingLinkSecured(bool is_secure) {} 252 253 // Optionally overridden by subclasses to implement changing source. ChangeSourceImpl(const MediaStreamDevice & new_device)254 virtual void ChangeSourceImpl(const MediaStreamDevice& new_device) {} 255 256 // Optionally override by subclasses to implement encoded source control. 257 // The method is called when at least one encoded sink has been added. OnEncodedSinkEnabled()258 virtual void OnEncodedSinkEnabled() {} 259 260 // Optionally override by subclasses to implement encoded source control. 261 // The method is called when the last encoded sink has been removed. OnEncodedSinkDisabled()262 virtual void OnEncodedSinkDisabled() {} 263 264 enum State { 265 NEW, 266 STARTING, 267 STOPPING_FOR_RESTART, 268 STOPPED_FOR_RESTART, 269 RESTARTING, 270 STARTED, 271 ENDED 272 }; state()273 State state() const { return state_; } 274 275 THREAD_CHECKER(thread_checker_); 276 277 private: 278 // Trigger all cached callbacks from AddTrack. AddTrack is successful 279 // if the capture delegate has started and the constraints provided in 280 // AddTrack match the format that was used to start the device. 281 // Note that it must be ok to delete the MediaStreamVideoSource object 282 // in the context of the callback. If gUM fails, the implementation will 283 // simply drop the references to the blink source and track which will lead 284 // to this object being deleted. 285 void FinalizeAddPendingTracks(); 286 287 // Actually adds |track| to this source, provided the source has started. 288 void FinalizeAddTrack(MediaStreamVideoTrack* track, 289 const VideoCaptureDeliverFrameCB& frame_callback, 290 const VideoTrackAdapterSettings& adapter_settings); 291 void StartFrameMonitoring(); 292 void UpdateTrackSettings(MediaStreamVideoTrack* track, 293 const VideoTrackAdapterSettings& adapter_settings); 294 void DidStopSource(RestartResult result); 295 void NotifyCapturingLinkSecured(size_t num_encoded_sinks); 296 size_t CountEncodedSinks() const; 297 298 State state_; 299 300 struct PendingTrackInfo { 301 PendingTrackInfo( 302 MediaStreamVideoTrack* track, 303 const VideoCaptureDeliverFrameCB& frame_callback, 304 const EncodedVideoFrameCB& encoded_frame_callback, 305 const VideoTrackSettingsCallback& settings_callback, 306 const VideoTrackFormatCallback& format_callback, 307 std::unique_ptr<VideoTrackAdapterSettings> adapter_settings, 308 ConstraintsOnceCallback callback); 309 PendingTrackInfo(PendingTrackInfo&& other); 310 PendingTrackInfo& operator=(PendingTrackInfo&& other); 311 ~PendingTrackInfo(); 312 313 MediaStreamVideoTrack* track; 314 VideoCaptureDeliverFrameCB frame_callback; 315 EncodedVideoFrameCB encoded_frame_callback; 316 VideoTrackSettingsCallback settings_callback; 317 VideoTrackFormatCallback format_callback; 318 // TODO(guidou): Make |adapter_settings| a regular field instead of a 319 // unique_ptr. 320 std::unique_ptr<VideoTrackAdapterSettings> adapter_settings; 321 ConstraintsOnceCallback callback; 322 }; 323 std::vector<PendingTrackInfo> pending_tracks_; 324 325 // |restart_callback_| is used for notifying both StopForRestart and Restart, 326 // since it is impossible to have a situation where there can be callbacks 327 // for both at the same time. 328 RestartCallback restart_callback_; 329 330 // |track_adapter_| delivers video frames to the tracks on the IO-thread. 331 scoped_refptr<VideoTrackAdapter> track_adapter_; 332 333 // Tracks that currently are connected to this source. 334 std::vector<MediaStreamVideoTrack*> tracks_; 335 336 // Tracks that have no paths to a consuming endpoint, and so do not need 337 // frames delivered from the source. This is a subset of |tracks_|. 338 std::vector<MediaStreamVideoTrack*> suspended_tracks_; 339 340 // This is used for tracking if all connected video sinks are secure. 341 SecureDisplayLinkTracker<MediaStreamVideoTrack> secure_tracker_; 342 343 // This flag enables a heuristic to detect device rotation based on frame 344 // size. 345 bool enable_device_rotation_detection_ = false; 346 347 // Callback that needs to trigger after removing the track. If this object 348 // died before this callback is resolved, we still need to trigger the 349 // callback to notify the caller that the request is canceled. 350 base::OnceClosure remove_last_track_callback_; 351 352 // NOTE: Weak pointers must be invalidated before all other member variables. 353 base::WeakPtrFactory<MediaStreamVideoSource> weak_factory_{this}; 354 355 DISALLOW_COPY_AND_ASSIGN(MediaStreamVideoSource); 356 }; 357 358 } // namespace blink 359 360 #endif // THIRD_PARTY_BLINK_PUBLIC_WEB_MODULES_MEDIASTREAM_MEDIA_STREAM_VIDEO_SOURCE_H_ 361