1 // Copyright (c) 2012 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 // MediaStreamManager is used to open/enumerate media capture devices (video 6 // supported now). Call flow: 7 // 1. GenerateStream is called when a render process wants to use a capture 8 // device. 9 // 2. MediaStreamManager will ask MediaStreamUIController for permission to 10 // use devices and for which device to use. 11 // 3. MediaStreamManager will request the corresponding media device manager(s) 12 // to enumerate available devices. The result will be given to 13 // MediaStreamUIController. 14 // 4. MediaStreamUIController will, by posting the request to UI, let the 15 // users to select which devices to use and send callback to 16 // MediaStreamManager with the result. 17 // 5. MediaStreamManager will call the proper media device manager to open the 18 // device and let the MediaStreamRequester know it has been done. 19 20 // When enumeration and open are done in separate operations, 21 // MediaStreamUIController is not involved as in steps. 22 23 #ifndef CONTENT_BROWSER_RENDERER_HOST_MEDIA_MEDIA_STREAM_MANAGER_H_ 24 #define CONTENT_BROWSER_RENDERER_HOST_MEDIA_MEDIA_STREAM_MANAGER_H_ 25 26 #include <map> 27 #include <string> 28 29 #include "base/basictypes.h" 30 #include "base/memory/ref_counted.h" 31 #include "base/memory/scoped_ptr.h" 32 #include "base/message_loop/message_loop.h" 33 #include "base/system_monitor/system_monitor.h" 34 #include "content/browser/renderer_host/media/media_stream_provider.h" 35 #include "content/common/content_export.h" 36 #include "content/common/media/media_stream_options.h" 37 #include "content/public/browser/media_request_state.h" 38 #include "content/public/browser/resource_context.h" 39 40 namespace base { 41 class Thread; 42 } 43 44 namespace media { 45 class AudioManager; 46 } 47 48 namespace content { 49 50 class AudioInputDeviceManager; 51 class FakeMediaStreamUIProxy; 52 class MediaStreamDeviceSettings; 53 class MediaStreamRequester; 54 class MediaStreamUIProxy; 55 class VideoCaptureManager; 56 57 // MediaStreamManager is used to generate and close new media devices, not to 58 // start the media flow. The classes requesting new media streams are answered 59 // using MediaStreamRequester. 60 class CONTENT_EXPORT MediaStreamManager 61 : public MediaStreamProviderListener, 62 public base::MessageLoop::DestructionObserver, 63 public base::SystemMonitor::DevicesChangedObserver { 64 public: 65 // Callback to deliver the result of a media request. 66 typedef base::Callback<void(const MediaStreamDevices& devices, 67 scoped_ptr<MediaStreamUIProxy> ui)> 68 MediaRequestResponseCallback; 69 70 explicit MediaStreamManager(media::AudioManager* audio_manager); 71 virtual ~MediaStreamManager(); 72 73 // Used to access VideoCaptureManager. 74 VideoCaptureManager* video_capture_manager(); 75 76 // Used to access AudioInputDeviceManager. 77 AudioInputDeviceManager* audio_input_device_manager(); 78 79 // Creates a new media access request which is identified by a unique string 80 // that's returned to the caller. This will trigger the infobar and ask users 81 // for access to the device. |render_process_id| and |render_view_id| refer 82 // to the view where the infobar will appear to the user. |callback| is 83 // used to send the selected device to the clients. An empty list of device 84 // will be returned if the users deny the access. 85 std::string MakeMediaAccessRequest( 86 int render_process_id, 87 int render_view_id, 88 int page_request_id, 89 const StreamOptions& options, 90 const GURL& security_origin, 91 const MediaRequestResponseCallback& callback); 92 93 // GenerateStream opens new media devices according to |components|. It 94 // creates a new request which is identified by a unique string that's 95 // returned to the caller. |render_process_id| and |render_view_id| refer to 96 // the view where the infobar will appear to the user. 97 void GenerateStream(MediaStreamRequester* requester, 98 int render_process_id, 99 int render_view_id, 100 const ResourceContext::SaltCallback& sc, 101 int page_request_id, 102 const StreamOptions& components, 103 const GURL& security_origin); 104 105 void CancelRequest(int render_process_id, 106 int render_view_id, 107 int page_request_id); 108 109 // Cancel an open request identified by |label|. 110 virtual void CancelRequest(const std::string& label); 111 112 // Cancel all requests for the given |render_process_id|. 113 void CancelAllRequests(int render_process_id); 114 115 // Closes the stream device for a certain render view. The stream must have 116 // been opened by a call to GenerateStream. 117 void StopStreamDevice(int render_process_id, 118 int render_view_id, 119 const std::string& device_id); 120 121 // Gets a list of devices of |type|, which must be MEDIA_DEVICE_AUDIO_CAPTURE 122 // or MEDIA_DEVICE_VIDEO_CAPTURE. 123 // The request is identified using the string returned to the caller. 124 // When the |requester| is NULL, MediaStreamManager will enumerate both audio 125 // and video devices and also start monitoring device changes, such as 126 // plug/unplug. The new device lists will be delivered via media observer to 127 // MediaCaptureDevicesDispatcher. 128 virtual std::string EnumerateDevices(MediaStreamRequester* requester, 129 int render_process_id, 130 int render_view_id, 131 const ResourceContext::SaltCallback& sc, 132 int page_request_id, 133 MediaStreamType type, 134 const GURL& security_origin); 135 136 // Open a device identified by |device_id|. |type| must be either 137 // MEDIA_DEVICE_AUDIO_CAPTURE or MEDIA_DEVICE_VIDEO_CAPTURE. 138 // The request is identified using string returned to the caller. 139 void OpenDevice(MediaStreamRequester* requester, 140 int render_process_id, 141 int render_view_id, 142 const ResourceContext::SaltCallback& sc, 143 int page_request_id, 144 const std::string& device_id, 145 MediaStreamType type, 146 const GURL& security_origin); 147 148 // Called by UI to make sure the device monitor is started so that UI receive 149 // notifications about device changes. 150 void EnsureDeviceMonitorStarted(); 151 152 // Implements MediaStreamProviderListener. 153 virtual void Opened(MediaStreamType stream_type, 154 int capture_session_id) OVERRIDE; 155 virtual void Closed(MediaStreamType stream_type, 156 int capture_session_id) OVERRIDE; 157 virtual void DevicesEnumerated(MediaStreamType stream_type, 158 const StreamDeviceInfoArray& devices) OVERRIDE; 159 160 // Implements base::SystemMonitor::DevicesChangedObserver. 161 virtual void OnDevicesChanged( 162 base::SystemMonitor::DeviceType device_type) OVERRIDE; 163 164 // Used by unit test to make sure fake devices are used instead of a real 165 // devices, which is needed for server based testing or certain tests (which 166 // can pass --use-fake-device-for-media-stream). 167 void UseFakeDevice(); 168 169 // Called by the tests to specify a fake UI that should be used for next 170 // generated stream (or when using --use-fake-ui-for-media-stream). 171 void UseFakeUI(scoped_ptr<FakeMediaStreamUIProxy> fake_ui); 172 173 // Returns all devices currently opened by a request with label |label|. 174 // If no request with |label| exist, an empty array is returned. 175 StreamDeviceInfoArray GetDevicesOpenedByRequest( 176 const std::string& label) const; 177 178 // This object gets deleted on the UI thread after the IO thread has been 179 // destroyed. So we need to know when IO thread is being destroyed so that 180 // we can delete VideoCaptureManager and AudioInputDeviceManager. Normally 181 // this is handled by 182 // base::MessageLoop::DestructionObserver::WillDestroyCurrentMessageLoop. 183 // But for some tests which use TestBrowserThreadBundle, we need to call 184 // WillDestroyCurrentMessageLoop explicitly because the notification happens 185 // too late. (see http://crbug.com/247525#c14). 186 virtual void WillDestroyCurrentMessageLoop() OVERRIDE; 187 188 protected: 189 // Used for testing. 190 MediaStreamManager(); 191 192 private: 193 // Contains all data needed to keep track of requests. 194 class DeviceRequest; 195 196 // Cache enumerated device list. 197 struct EnumerationCache { 198 EnumerationCache(); 199 ~EnumerationCache(); 200 201 bool valid; 202 StreamDeviceInfoArray devices; 203 }; 204 205 typedef std::map<std::string, DeviceRequest*> DeviceRequests; 206 207 // Initializes the device managers on IO thread. Auto-starts the device 208 // thread and registers this as a listener with the device managers. 209 void InitializeDeviceManagersOnIOThread(); 210 211 // Helper for sending up-to-date device lists to media observer when a 212 // capture device is plugged in or unplugged. 213 void NotifyDevicesChanged(MediaStreamType stream_type, 214 const StreamDeviceInfoArray& devices); 215 216 void HandleAccessRequestResponse(const std::string& label, 217 const MediaStreamDevices& devices); 218 void StopMediaStreamFromBrowser(const std::string& label); 219 220 void DoEnumerateDevices(const std::string& label); 221 222 // Helpers. 223 // Checks if all devices that was requested in the request identififed by 224 // |label| has been opened and set the request state accordingly. 225 void HandleRequestDone(const std::string& label, 226 DeviceRequest* request); 227 // Stop the use of the device associated with |session_id| of type |type| in 228 // all |requests_|. The device is removed from the request. If a request 229 /// doesn't use any devices as a consequence, the request is deleted. 230 void StopDevice(MediaStreamType type, int session_id); 231 // Calls the correct capture manager and close the device with |session_id|. 232 // All requests that uses the device are updated. 233 void CloseDevice(MediaStreamType type, int session_id); 234 // Returns true if a request for devices has been completed and the devices 235 // has either been opened or an error has occurred. 236 bool RequestDone(const DeviceRequest& request) const; 237 MediaStreamProvider* GetDeviceManager(MediaStreamType stream_type); 238 void StartEnumeration(DeviceRequest* request); 239 std::string AddRequest(DeviceRequest* request); 240 DeviceRequest* FindRequest(const std::string& label) const; 241 void DeleteRequest(const std::string& label); 242 void ClearEnumerationCache(EnumerationCache* cache); 243 // Prepare the request with label |label| by starting device enumeration if 244 // needed. 245 void SetupRequest(const std::string& label); 246 // Prepare |request| of type MEDIA_DEVICE_AUDIO_CAPTURE and/or 247 // MEDIA_DEVICE_VIDEO_CAPTURE for being posted to the UI by parsing 248 // StreamOptions::Constraints for requested device IDs. 249 bool SetupDeviceCaptureRequest(DeviceRequest* request); 250 // Prepare |request| of type MEDIA_TAB_AUDIO_CAPTURE and/or 251 // MEDIA_TAB_VIDEO_CAPTURE for being posted to the UI by parsing 252 // StreamOptions::Constraints for requested tab capture IDs. 253 bool SetupTabCaptureRequest(DeviceRequest* request); 254 // Prepare |request| of type MEDIA_LOOPBACK_AUDIO_CAPTURE and/or 255 // MEDIA_DESKTOP_VIDEO_CAPTURE for being posted to the UI by parsing 256 // StreamOptions::Constraints for the requested desktop ID. 257 bool SetupScreenCaptureRequest(DeviceRequest* request); 258 // Called when a request has been setup and devices have been enumerated if 259 // needed. 260 void PostRequestToUI(const std::string& label, DeviceRequest* request); 261 // Returns true if a device with |device_id| has already been requested with 262 // a render procecss_id and render_view_id and type equal to the the values 263 // in |request|. If it has been requested, |device_info| contain information 264 // about the device. 265 bool FindExistingRequestedDeviceInfo( 266 const DeviceRequest& new_request, 267 const MediaStreamDevice& new_device_info, 268 StreamDeviceInfo* existing_device_info, 269 MediaRequestState* existing_request_state) const; 270 271 void FinalizeGenerateStream(const std::string& label, 272 DeviceRequest* request); 273 void FinalizeRequestFailed(const std::string& label, 274 DeviceRequest* request); 275 void FinalizeOpenDevice(const std::string& label, 276 DeviceRequest* request); 277 void FinalizeMediaAccessRequest(const std::string& label, 278 DeviceRequest* request, 279 const MediaStreamDevices& devices); 280 void FinalizeEnumerateDevices(const std::string& label, 281 DeviceRequest* request); 282 283 // This method is called when an audio or video device is plugged in or 284 // removed. It make sure all MediaStreams that use a removed device is 285 // stopped and that the render process is notified. |old_devices| is the list 286 // of previously available devices. |new_devices| is the new 287 // list of currently available devices. 288 void StopRemovedDevices(const StreamDeviceInfoArray& old_devices, 289 const StreamDeviceInfoArray& new_devices); 290 // Helper method used by StopRemovedDevices to stop the use of a certain 291 // device. 292 void StopRemovedDevice(const MediaStreamDevice& device); 293 294 // Helpers to start and stop monitoring devices. 295 void StartMonitoring(); 296 void StopMonitoring(); 297 298 // Finds the requested device id from constraints. The requested device type 299 // must be MEDIA_DEVICE_AUDIO_CAPTURE or MEDIA_DEVICE_VIDEO_CAPTURE. 300 bool GetRequestedDeviceCaptureId(const DeviceRequest* request, 301 MediaStreamType type, 302 std::string* device_id) const; 303 304 void TranslateDeviceIdToSourceId(DeviceRequest* request, 305 MediaStreamDevice* device); 306 307 // Finds and returns the device id corresponding to the given 308 // |source_id|. Returns true if there was a raw device id that matched the 309 // given |source_id|, false if nothing matched it. 310 bool TranslateSourceIdToDeviceId( 311 MediaStreamType stream_type, 312 const ResourceContext::SaltCallback& rc, 313 const GURL& security_origin, 314 const std::string& source_id, 315 std::string* device_id) const; 316 317 // Device thread shared by VideoCaptureManager and AudioInputDeviceManager. 318 scoped_ptr<base::Thread> device_thread_; 319 320 media::AudioManager* const audio_manager_; // not owned 321 scoped_refptr<AudioInputDeviceManager> audio_input_device_manager_; 322 scoped_refptr<VideoCaptureManager> video_capture_manager_; 323 324 // Indicator of device monitoring state. 325 bool monitoring_started_; 326 327 // Stores most recently enumerated device lists. The cache is cleared when 328 // monitoring is stopped or there is no request for that type of device. 329 EnumerationCache audio_enumeration_cache_; 330 EnumerationCache video_enumeration_cache_; 331 332 // Keeps track of live enumeration commands sent to VideoCaptureManager or 333 // AudioInputDeviceManager, in order to only enumerate when necessary. 334 int active_enumeration_ref_count_[NUM_MEDIA_TYPES]; 335 336 // All non-closed request. 337 DeviceRequests requests_; 338 339 // Hold a pointer to the IO loop to check we delete the device thread and 340 // managers on the right thread. 341 base::MessageLoop* io_loop_; 342 343 bool use_fake_ui_; 344 scoped_ptr<FakeMediaStreamUIProxy> fake_ui_; 345 346 DISALLOW_COPY_AND_ASSIGN(MediaStreamManager); 347 }; 348 349 } // namespace content 350 351 #endif // CONTENT_BROWSER_RENDERER_HOST_MEDIA_MEDIA_STREAM_MANAGER_H_ 352