Home | History | Annotate | Download | only in media
      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