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 // VideoCaptureManager is used to open/close, start/stop, enumerate available
      6 // video capture devices, and manage VideoCaptureController's.
      7 // All functions are expected to be called from Browser::IO thread. Some helper
      8 // functions (*OnDeviceThread) will dispatch operations to the device thread.
      9 // VideoCaptureManager will open OS dependent instances of VideoCaptureDevice.
     10 // A device can only be opened once.
     11 
     12 #ifndef CONTENT_BROWSER_RENDERER_HOST_MEDIA_VIDEO_CAPTURE_MANAGER_H_
     13 #define CONTENT_BROWSER_RENDERER_HOST_MEDIA_VIDEO_CAPTURE_MANAGER_H_
     14 
     15 #include <map>
     16 #include <set>
     17 #include <string>
     18 
     19 #include "base/memory/ref_counted.h"
     20 #include "base/memory/weak_ptr.h"
     21 #include "base/message_loop/message_loop.h"
     22 #include "base/process/process_handle.h"
     23 #include "base/timer/elapsed_timer.h"
     24 #include "content/browser/renderer_host/media/media_stream_provider.h"
     25 #include "content/browser/renderer_host/media/video_capture_controller_event_handler.h"
     26 #include "content/common/content_export.h"
     27 #include "content/common/media/media_stream_options.h"
     28 #include "media/video/capture/video_capture_device.h"
     29 #include "media/video/capture/video_capture_device_factory.h"
     30 #include "media/video/capture/video_capture_types.h"
     31 
     32 namespace content {
     33 class VideoCaptureController;
     34 class VideoCaptureControllerEventHandler;
     35 
     36 // VideoCaptureManager opens/closes and start/stops video capture devices.
     37 class CONTENT_EXPORT VideoCaptureManager : public MediaStreamProvider {
     38  public:
     39   // Callback used to signal the completion of a controller lookup.
     40   typedef base::Callback<
     41       void(const base::WeakPtr<VideoCaptureController>&)> DoneCB;
     42 
     43   explicit VideoCaptureManager(
     44       scoped_ptr<media::VideoCaptureDeviceFactory> factory);
     45 
     46   // Implements MediaStreamProvider.
     47   virtual void Register(MediaStreamProviderListener* listener,
     48                         const scoped_refptr<base::SingleThreadTaskRunner>&
     49                             device_task_runner) OVERRIDE;
     50 
     51   virtual void Unregister() OVERRIDE;
     52 
     53   virtual void EnumerateDevices(MediaStreamType stream_type) OVERRIDE;
     54 
     55   virtual int Open(const StreamDeviceInfo& device) OVERRIDE;
     56 
     57   virtual void Close(int capture_session_id) OVERRIDE;
     58 
     59   // Called by VideoCaptureHost to locate a capture device for |capture_params|,
     60   // adding the Host as a client of the device's controller if successful. The
     61   // value of |session_id| controls which device is selected;
     62   // this value should be a session id previously returned by Open().
     63   //
     64   // If the device is not already started (i.e., no other client is currently
     65   // capturing from this device), this call will cause a VideoCaptureController
     66   // and VideoCaptureDevice to be created, possibly asynchronously.
     67   //
     68   // On success, the controller is returned via calling |done_cb|, indicating
     69   // that the client was successfully added. A NULL controller is passed to
     70   // the callback on failure.
     71   void StartCaptureForClient(media::VideoCaptureSessionId session_id,
     72                              const media::VideoCaptureParams& capture_params,
     73                              base::ProcessHandle client_render_process,
     74                              VideoCaptureControllerID client_id,
     75                              VideoCaptureControllerEventHandler* client_handler,
     76                              const DoneCB& done_cb);
     77 
     78   // Called by VideoCaptureHost to remove |client_handler|. If this is the last
     79   // client of the device, the |controller| and its VideoCaptureDevice may be
     80   // destroyed. The client must not access |controller| after calling this
     81   // function.
     82   void StopCaptureForClient(VideoCaptureController* controller,
     83                             VideoCaptureControllerID client_id,
     84                             VideoCaptureControllerEventHandler* client_handler,
     85                             bool aborted_due_to_error);
     86 
     87   // Called by VideoCaptureHost to pause to update video buffer specified by
     88   // |client_id| and |client_handler|. If all clients of |controller| are
     89   // paused, the corresponding device will be closed.
     90   void PauseCaptureForClient(
     91       VideoCaptureController* controller,
     92       VideoCaptureControllerID client_id,
     93       VideoCaptureControllerEventHandler* client_handler);
     94 
     95   // Called by VideoCaptureHost to resume to update video buffer specified by
     96   // |client_id| and |client_handler|. The |session_id| and |params| should be
     97   // same as those used in StartCaptureForClient().
     98   // If this is first active client of |controller|, device will be allocated
     99   // and it will take a little time to resume.
    100   // Allocating device could failed if other app holds the camera, the error
    101   // will be notified through VideoCaptureControllerEventHandler::OnError().
    102   void ResumeCaptureForClient(
    103       media::VideoCaptureSessionId session_id,
    104       const media::VideoCaptureParams& params,
    105       VideoCaptureController* controller,
    106       VideoCaptureControllerID client_id,
    107       VideoCaptureControllerEventHandler* client_handler);
    108 
    109   // Retrieves all capture supported formats for a particular device. Returns
    110   // false if the |capture_session_id| is not found. The supported formats are
    111   // cached during device(s) enumeration, and depending on the underlying
    112   // implementation, could be an empty list.
    113   bool GetDeviceSupportedFormats(
    114       media::VideoCaptureSessionId capture_session_id,
    115       media::VideoCaptureFormats* supported_formats);
    116 
    117   // Retrieves the format(s) currently in use.  Returns false if the
    118   // |capture_session_id| is not found. Returns true and |formats_in_use|
    119   // otherwise. |formats_in_use| is empty if the device is not in use.
    120   bool GetDeviceFormatsInUse(media::VideoCaptureSessionId capture_session_id,
    121                              media::VideoCaptureFormats* formats_in_use);
    122 
    123   // Sets the platform-dependent window ID for the desktop capture notification
    124   // UI for the given session.
    125   void SetDesktopCaptureWindowId(media::VideoCaptureSessionId session_id,
    126                                  gfx::NativeViewId window_id);
    127 
    128   // Gets a weak reference to the device factory, used for tests.
    129   media::VideoCaptureDeviceFactory* video_capture_device_factory() const {
    130     return video_capture_device_factory_.get();
    131   }
    132 
    133  private:
    134   virtual ~VideoCaptureManager();
    135   struct DeviceEntry;
    136 
    137   // This data structure is a convenient wrap of a devices' name and associated
    138   // video capture supported formats.
    139   struct DeviceInfo {
    140     DeviceInfo();
    141     DeviceInfo(const media::VideoCaptureDevice::Name& name,
    142                const media::VideoCaptureFormats& supported_formats);
    143     ~DeviceInfo();
    144 
    145     media::VideoCaptureDevice::Name name;
    146     media::VideoCaptureFormats supported_formats;
    147   };
    148   typedef std::vector<DeviceInfo> DeviceInfos;
    149 
    150   // Checks to see if |entry| has no clients left on its controller. If so,
    151   // remove it from the list of devices, and delete it asynchronously. |entry|
    152   // may be freed by this function.
    153   void DestroyDeviceEntryIfNoClients(DeviceEntry* entry);
    154 
    155   // Helpers to report an event to our Listener.
    156   void OnOpened(MediaStreamType type,
    157                 media::VideoCaptureSessionId capture_session_id);
    158   void OnClosed(MediaStreamType type,
    159                 media::VideoCaptureSessionId capture_session_id);
    160   void OnDevicesInfoEnumerated(MediaStreamType stream_type,
    161                                base::ElapsedTimer* timer,
    162                                const DeviceInfos& new_devices_info_cache);
    163 
    164   // Finds a DeviceEntry by its device ID and type, if it is already opened.
    165   DeviceEntry* GetDeviceEntryForMediaStreamDevice(
    166       const MediaStreamDevice& device_info);
    167 
    168   // Finds a DeviceEntry entry for the indicated session, creating a fresh one
    169   // if necessary. Returns NULL if the session id is invalid.
    170   DeviceEntry* GetOrCreateDeviceEntry(
    171       media::VideoCaptureSessionId capture_session_id);
    172 
    173   // Finds the DeviceEntry that owns a particular controller pointer.
    174   DeviceEntry* GetDeviceEntryForController(
    175       const VideoCaptureController* controller) const;
    176 
    177   bool IsOnDeviceThread() const;
    178 
    179   // Consolidates the cached devices list with the list of currently connected
    180   // devices in the system |names_snapshot|. Retrieves the supported formats of
    181   // the new devices and sends the new cache to OnDevicesInfoEnumerated().
    182   void ConsolidateDevicesInfoOnDeviceThread(
    183       base::Callback<void(const DeviceInfos&)> on_devices_enumerated_callback,
    184       MediaStreamType stream_type,
    185       const DeviceInfos& old_device_info_cache,
    186       scoped_ptr<media::VideoCaptureDevice::Names> names_snapshot);
    187 
    188   // Creates and Starts a new VideoCaptureDevice, storing the result in
    189   // |entry->video_capture_device|. Ownership of |client| passes to
    190   // the device.
    191   void DoStartDeviceOnDeviceThread(
    192       media::VideoCaptureSessionId session_id,
    193       DeviceEntry* entry,
    194       const media::VideoCaptureParams& params,
    195       scoped_ptr<media::VideoCaptureDevice::Client> client);
    196 
    197   // Stops and destroys the VideoCaptureDevice held in
    198   // |entry->video_capture_device|.
    199   void DoStopDeviceOnDeviceThread(DeviceEntry* entry);
    200 
    201   DeviceInfo* FindDeviceInfoById(const std::string& id,
    202                                  DeviceInfos& device_vector);
    203 
    204   void SetDesktopCaptureWindowIdOnDeviceThread(DeviceEntry* entry,
    205                                                gfx::NativeViewId window_id);
    206 
    207   void SaveDesktopCaptureWindowIdOnDeviceThread(
    208       media::VideoCaptureSessionId session_id,
    209       gfx::NativeViewId window_id);
    210 
    211   // The message loop of media stream device thread, where VCD's live.
    212   scoped_refptr<base::SingleThreadTaskRunner> device_task_runner_;
    213 
    214   // Only accessed on Browser::IO thread.
    215   MediaStreamProviderListener* listener_;
    216   media::VideoCaptureSessionId new_capture_session_id_;
    217 
    218   typedef std::map<media::VideoCaptureSessionId, MediaStreamDevice> SessionMap;
    219   // An entry is kept in this map for every session that has been created via
    220   // the Open() entry point. The keys are session_id's. This map is used to
    221   // determine which device to use when StartCaptureForClient() occurs. Used
    222   // only on the IO thread.
    223   SessionMap sessions_;
    224 
    225   // An entry, kept in a map, that owns a VideoCaptureDevice and its associated
    226   // VideoCaptureController. VideoCaptureManager owns all VideoCaptureDevices
    227   // and VideoCaptureControllers and is responsible for deleting the instances
    228   // when they are not used any longer.
    229   //
    230   // The set of currently started VideoCaptureDevice and VideoCaptureController
    231   // objects is only accessed from IO thread, though the DeviceEntry instances
    232   // themselves may visit to the device thread for device creation and
    233   // destruction.
    234   struct DeviceEntry {
    235     DeviceEntry(MediaStreamType stream_type,
    236                 const std::string& id,
    237                 scoped_ptr<VideoCaptureController> controller);
    238     ~DeviceEntry();
    239 
    240     const MediaStreamType stream_type;
    241     const std::string id;
    242 
    243     // The controller. Only used from the IO thread.
    244     scoped_ptr<VideoCaptureController> video_capture_controller;
    245 
    246     // The capture device. Only used from the device thread.
    247     scoped_ptr<media::VideoCaptureDevice> video_capture_device;
    248   };
    249   typedef std::set<DeviceEntry*> DeviceEntries;
    250   DeviceEntries devices_;
    251 
    252   // Device creation factory injected on construction from MediaStreamManager or
    253   // from the test harness.
    254   scoped_ptr<media::VideoCaptureDeviceFactory> video_capture_device_factory_;
    255 
    256   // Local cache of the enumerated video capture devices' names and capture
    257   // supported formats. A snapshot of the current devices and their capabilities
    258   // is composed in VideoCaptureDeviceFactory::EnumerateDeviceNames() and
    259   // ConsolidateDevicesInfoOnDeviceThread(), and this snapshot is used to update
    260   // this list in OnDevicesInfoEnumerated(). GetDeviceSupportedFormats() will
    261   // use this list if the device is not started, otherwise it will retrieve the
    262   // active device capture format from the VideoCaptureController associated.
    263   DeviceInfos devices_info_cache_;
    264 
    265   // Accessed on the device thread only.
    266   std::map<media::VideoCaptureSessionId, gfx::NativeViewId>
    267       notification_window_ids_;
    268 
    269   DISALLOW_COPY_AND_ASSIGN(VideoCaptureManager);
    270 };
    271 
    272 }  // namespace content
    273 
    274 #endif  // CONTENT_BROWSER_RENDERER_HOST_MEDIA_VIDEO_CAPTURE_MANAGER_H_
    275