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