summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--content/browser/renderer_host/media/media_stream_device_settings.cc5
-rw-r--r--content/browser/renderer_host/media/media_stream_manager.cc426
-rw-r--r--content/browser/renderer_host/media/media_stream_manager.h132
-rw-r--r--content/browser/renderer_host/media/media_stream_requester.h39
-rw-r--r--content/browser/renderer_host/media/media_stream_settings_requester.h5
-rw-r--r--content/browser/renderer_host/media/video_capture_controller.cc10
-rw-r--r--content/browser/renderer_host/media/video_capture_host_unittest.cc15
-rw-r--r--content/browser/renderer_host/media/video_capture_manager.cc7
-rw-r--r--content/browser/renderer_host/media/video_capture_manager.h11
-rw-r--r--content/browser/renderer_host/media/video_capture_manager_unittest.cc87
-rw-r--r--content/common/media/media_stream_options.h3
-rw-r--r--content/content_browser.gypi3
12 files changed, 656 insertions, 87 deletions
diff --git a/content/browser/renderer_host/media/media_stream_device_settings.cc b/content/browser/renderer_host/media/media_stream_device_settings.cc
index 86d397d..096e5c8 100644
--- a/content/browser/renderer_host/media/media_stream_device_settings.cc
+++ b/content/browser/renderer_host/media/media_stream_device_settings.cc
@@ -44,7 +44,6 @@ MediaStreamDeviceSettings::MediaStreamDeviceSettings(
}
MediaStreamDeviceSettings::~MediaStreamDeviceSettings() {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
STLDeleteValues(&requests_);
}
@@ -55,7 +54,7 @@ void MediaStreamDeviceSettings::RequestCaptureDeviceUsage(
if (requests_.find(label) != requests_.end()) {
// Request with this id already exists.
- requester_->Error(label);
+ requester_->SettingsError(label);
return;
}
@@ -81,7 +80,7 @@ void MediaStreamDeviceSettings::AvailableDevices(
SettingsRequests::iterator request_it = requests_.find(label);
if (request_it == requests_.end()) {
// Request with this id doesn't exist.
- requester_->Error(label);
+ requester_->SettingsError(label);
return;
}
diff --git a/content/browser/renderer_host/media/media_stream_manager.cc b/content/browser/renderer_host/media/media_stream_manager.cc
new file mode 100644
index 0000000..e9c49f1
--- /dev/null
+++ b/content/browser/renderer_host/media/media_stream_manager.cc
@@ -0,0 +1,426 @@
+// Copyright (c) 2011 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.
+
+#include "content/browser/renderer_host/media/media_stream_manager.h"
+
+#include <list>
+
+#include "base/lazy_instance.h"
+#include "base/logging.h"
+#include "base/rand_util.h"
+#include "content/browser/browser_thread.h"
+#include "content/browser/renderer_host/media/media_stream_device_settings.h"
+#include "content/browser/renderer_host/media/media_stream_requester.h"
+#include "content/browser/renderer_host/media/video_capture_manager.h"
+#include "content/common/media/media_stream_options.h"
+
+namespace media_stream {
+
+// TODO(mflodman) Find out who should own MediaStreamManager.
+base::LazyInstance<MediaStreamManager> g_media_stream_manager(
+ base::LINKER_INITIALIZED);
+
+// Creates a random label used to identify requests.
+static std::string RandomLabel() {
+ // Alphbet according to WhatWG standard, i.e. containing 36 characters from
+ // range: U+0021, U+0023 to U+0027, U+002A to U+002B, U+002D to U+002E,
+ // U+0030 to U+0039, U+0041 to U+005A, U+005E to U+007E.
+ static const char alphabet[] = "!#$%&\'*+-.0123456789"
+ "abcdefghijklmnopqrstuvwxyz^_`ABCDEFGHIJKLMNOPQRSTUVWXYZ{|}~";
+
+ std::string label(36, ' ');
+ for (size_t i = 0; i < label.size(); ++i) {
+ int random_char = base::RandGenerator(sizeof(alphabet) - 1);
+ label[i] = alphabet[random_char];
+ }
+ return label;
+}
+
+// Helper to verify if a media stream type is part of options or not.
+static bool Requested(const StreamOptions& options,
+ MediaStreamType stream_type) {
+ if (stream_type == kVideoCapture &&
+ (options.video_option != StreamOptions::kNoCamera)) {
+ return true;
+ } else if (stream_type == kAudioCapture && options.audio == true) {
+ return true;
+ }
+ return false;
+}
+
+MediaStreamManager* MediaStreamManager::Get() {
+ return g_media_stream_manager.Pointer();
+}
+
+MediaStreamManager::~MediaStreamManager() {
+ delete device_settings_;
+ delete video_capture_manager_;
+}
+
+VideoCaptureManager* MediaStreamManager::video_capture_manager() {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ return video_capture_manager_;
+}
+
+void MediaStreamManager::GenerateStream(MediaStreamRequester* requester,
+ int render_process_id,
+ int render_view_id,
+ const StreamOptions& options,
+ const std::string& security_origin,
+ std::string* label) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+
+ // TODO(mflodman) Remove next line when audio is supported.
+ (const_cast<StreamOptions&>(options)).audio = false;
+
+ // Create a new request based on options.
+ DeviceRequest new_request = DeviceRequest(requester, options);
+ if (Requested(new_request.options, kAudioCapture)) {
+ new_request.state[kAudioCapture] = DeviceRequest::kRequested;
+ }
+ if (Requested(new_request.options, kVideoCapture)) {
+ new_request.state[kVideoCapture] = DeviceRequest::kRequested;
+ }
+
+ // Create a label for this request and verify it is unique.
+ std::string request_label;
+ do {
+ request_label = RandomLabel();
+ } while (requests_.find(request_label) != requests_.end());
+
+ requests_.insert(std::make_pair(request_label, new_request));
+
+ // Get user confirmation to use capture devices.
+ device_settings_->RequestCaptureDeviceUsage(request_label, render_process_id,
+ render_view_id, options,
+ security_origin);
+ (*label) = request_label;
+}
+
+void MediaStreamManager::CancelRequests(MediaStreamRequester* requester) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ DeviceRequests::iterator it = requests_.begin();
+ while (it != requests_.end()) {
+ if (it->second.requester == requester && !RequestDone(it->second)) {
+ // The request isn't complete, but there might be some devices already
+ // opened -> close them.
+ DeviceRequest* request = &(it->second);
+ if (request->state[kAudioCapture] == DeviceRequest::kOpening) {
+ for (StreamDeviceInfoArray::iterator it =
+ request->audio_devices.begin(); it != request->audio_devices.end();
+ ++it) {
+ if (it->in_use == true) {
+ // TODO(mflodman) Add when audio input device manager is available.
+ }
+ }
+ }
+ if (request->state[kVideoCapture] == DeviceRequest::kOpening) {
+ for (StreamDeviceInfoArray::iterator it =
+ request->video_devices.begin(); it != request->video_devices.end();
+ ++it) {
+ if (it->in_use == true) {
+ video_capture_manager_->Close(it->session_id);
+ }
+ }
+ }
+ requests_.erase(it++);
+ } else {
+ ++it;
+ }
+ }
+}
+
+void MediaStreamManager::StopGeneratedStream(const std::string& label) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ // Find the request and close all open devices for the request.
+ DeviceRequests::iterator it = requests_.find(label);
+ if (it != requests_.end()) {
+ for (StreamDeviceInfoArray::iterator audio_it =
+ it->second.audio_devices.begin();
+ audio_it != it->second.audio_devices.end(); ++audio_it) {
+ // TODO(mflodman) Add code when audio input manager exists.
+ NOTREACHED();
+ }
+ for (StreamDeviceInfoArray::iterator video_it =
+ it->second.video_devices.begin();
+ video_it != it->second.video_devices.end(); ++video_it) {
+ video_capture_manager_->Close(video_it->session_id);
+ }
+ requests_.erase(it);
+ return;
+ }
+}
+
+void MediaStreamManager::Opened(MediaStreamType stream_type,
+ int capture_session_id) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+
+ // Find the request containing this device and mark it as used.
+ DeviceRequest* request = NULL;
+ StreamDeviceInfoArray* devices = NULL;
+ std::string label;
+ for (DeviceRequests::iterator request_it = requests_.begin();
+ request_it != requests_.end() && request == NULL; ++request_it) {
+ if (stream_type == kAudioCapture) {
+ devices = &(request_it->second.audio_devices);
+ } else if (stream_type == kVideoCapture) {
+ devices = &(request_it->second.video_devices);
+ } else {
+ NOTREACHED();
+ }
+
+ for (StreamDeviceInfoArray::iterator device_it = devices->begin();
+ device_it != devices->end(); ++device_it) {
+ if (device_it->session_id == capture_session_id) {
+ // We've found the request.
+ device_it->in_use = true;
+ label = request_it->first;
+ request = &(request_it->second);
+ break;
+ }
+ }
+ }
+ if (request == NULL) {
+ // The request doesn't exist.
+ return;
+ }
+
+ DCHECK_NE(request->state[stream_type], DeviceRequest::kRequested);
+
+ // Check if all devices for this stream type are opened. Update the state if
+ // they are.
+ for (StreamDeviceInfoArray::iterator device_it = devices->begin();
+ device_it != devices->end(); ++device_it) {
+ if (device_it->in_use == false) {
+ // Wait for more devices to be opened before we're done.
+ return;
+ }
+ }
+ request->state[stream_type] = DeviceRequest::kDone;
+
+ if (!RequestDone(*request)) {
+ // This stream_type is done, but not the other type.
+ return;
+ }
+
+ request->requester->StreamGenerated(label, request->audio_devices,
+ request->video_devices);
+}
+
+void MediaStreamManager::Closed(MediaStreamType stream_type,
+ int capture_session_id) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+}
+
+void MediaStreamManager::DevicesEnumerated(
+ MediaStreamType stream_type, const StreamDeviceInfoArray& devices) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+
+ // Publish the result for all requests waiting for device list(s).
+ // Find the requests waiting for this device list, store their labels and
+ // release the iterator before calling device settings. We might get a call
+ // back from device_settings that will need to iterate through devices.
+ std::list<std::string> label_list;
+ for (DeviceRequests::iterator it = requests_.begin(); it != requests_.end();
+ ++it) {
+ if (it->second.state[stream_type] == DeviceRequest::kRequested &&
+ Requested(it->second.options, stream_type)) {
+ label_list.push_back(it->first);
+ }
+ }
+ for (std::list<std::string>::iterator it = label_list.begin();
+ it != label_list.end(); ++it) {
+ device_settings_->AvailableDevices(*it, stream_type, devices);
+ }
+ label_list.clear();
+ enumeration_in_progress_[stream_type] = false;
+}
+
+void MediaStreamManager::Error(MediaStreamType stream_type,
+ int capture_session_id,
+ MediaStreamProviderError error) {
+ // Find the device for the error call.
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ for (DeviceRequests::iterator it = requests_.begin(); it != requests_.end();
+ ++it) {
+ StreamDeviceInfoArray* devices = NULL;
+ if (stream_type == kAudioCapture) {
+ devices = &(it->second.audio_devices);
+ } else if (stream_type == kVideoCapture) {
+ devices = &(it->second.video_devices);
+ } else {
+ NOTREACHED();
+ }
+
+ int device_idx = 0;
+ for (StreamDeviceInfoArray::iterator device_it = devices->begin();
+ device_it != devices->end(); ++device_it, ++device_idx) {
+ if (device_it->session_id == capture_session_id) {
+ // We've found the failing device. Find the error case:
+ if (it->second.state[stream_type] == DeviceRequest::kDone) {
+ // 1. Already opened -> signal device failure and close device.
+ // Use device_idx to signal which of the devices encountered an
+ // error.
+ if (stream_type == kAudioCapture) {
+ it->second.requester->AudioDeviceFailed(it->first, device_idx);
+ } else if (stream_type == kVideoCapture) {
+ it->second.requester->VideoDeviceFailed(it->first, device_idx);
+ }
+ GetDeviceManager(stream_type)->Close(capture_session_id);
+ devices->erase(device_it);
+ } else if (it->second.audio_devices.size()
+ + it->second.video_devices.size() <= 1) {
+ // 2. Device not opened and no other devices for this request ->
+ // signal stream error and remove the request.
+ it->second.requester->StreamGenerationFailed(it->first);
+ requests_.erase(it);
+ } else {
+ // 3. Not opened but other devices exists for this request -> remove
+ // device from list, but don't signal an error.
+ devices->erase(device_it);
+ }
+ return;
+ }
+ }
+ }
+}
+
+void MediaStreamManager::GetDevices(const std::string& label,
+ MediaStreamType stream_type) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ if (!enumeration_in_progress_[stream_type]) {
+ enumeration_in_progress_[stream_type] = true;
+ GetDeviceManager(stream_type)->EnumerateDevices();
+ }
+}
+
+void MediaStreamManager::DevicesAccepted(const std::string& label,
+ const StreamDeviceInfoArray& devices) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ DeviceRequests::iterator request_it = requests_.find(label);
+ if (request_it != requests_.end()) {
+ if (devices.empty()) {
+ // No available devices or user didn't accept device usage.
+ request_it->second.requester->StreamGenerationFailed(request_it->first);
+ requests_.erase(request_it);
+ return;
+ }
+
+ // Loop through all device types for this request.
+ for (StreamDeviceInfoArray::const_iterator device_it = devices.begin();
+ device_it != devices.end(); ++device_it) {
+ StreamDeviceInfo device_info = *device_it;
+
+ // Set in_use to false to be able to track if this device has been
+ // opened. in_use might be true if the device type can be used in more
+ // than one session.
+ device_info.in_use = false;
+ device_info.session_id =
+ GetDeviceManager(device_info.stream_type)->Open(device_info);
+ request_it->second.state[device_it->stream_type] =
+ DeviceRequest::kOpening;
+ if (device_info.stream_type == kAudioCapture) {
+ request_it->second.audio_devices.push_back(device_info);
+ } else if (device_info.stream_type == kVideoCapture) {
+ request_it->second.video_devices.push_back(device_info);
+ } else {
+ NOTREACHED();
+ }
+ }
+ // Check if we received all stream types requested.
+ if (Requested(request_it->second.options, kAudioCapture) &&
+ request_it->second.audio_devices.size() == 0) {
+ request_it->second.state[kAudioCapture] = DeviceRequest::kError;
+ }
+ if (Requested(request_it->second.options, kVideoCapture) &&
+ request_it->second.video_devices.size() == 0) {
+ request_it->second.state[kVideoCapture] = DeviceRequest::kError;
+ }
+ return;
+ }
+}
+
+void MediaStreamManager::SettingsError(const std::string& label) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ // Erase this request and report an error.
+ DeviceRequests::iterator it = requests_.find(label);
+ if (it != requests_.end()) {
+ it->second.requester->StreamGenerationFailed(label);
+ requests_.erase(it);
+ return;
+ }
+}
+
+void MediaStreamManager::UseFakeDevice() {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ video_capture_manager_->UseFakeDevice();
+ // TODO(mflodman) Add audio manager when available.
+}
+
+bool MediaStreamManager::RequestDone(const DeviceRequest& request) const {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ // Check if all devices are opened.
+ if (Requested(request.options, kAudioCapture)) {
+ for (StreamDeviceInfoArray::const_iterator it =
+ request.audio_devices.begin(); it != request.audio_devices.end();
+ ++it) {
+ if (it->in_use == false) {
+ return false;
+ }
+ }
+ }
+ if (Requested(request.options, kVideoCapture)) {
+ for (StreamDeviceInfoArray::const_iterator it =
+ request.video_devices.begin(); it != request.video_devices.end();
+ ++it) {
+ if (it->in_use == false) {
+ return false;
+ }
+ }
+ }
+ return true;
+}
+
+// Called to get media capture device manager of specified type.
+MediaStreamProvider* MediaStreamManager::GetDeviceManager(
+ MediaStreamType stream_type) const {
+ if (stream_type == kVideoCapture) {
+ return video_capture_manager_;
+ } else if (stream_type == kAudioCapture) {
+ // TODO(mflodman) Add support when audio input manager is available.
+ NOTREACHED();
+ return NULL;
+ }
+ NOTREACHED();
+ return NULL;
+}
+
+MediaStreamManager::MediaStreamManager()
+ : video_capture_manager_(new VideoCaptureManager()),
+ enumeration_in_progress_(kNumMediaStreamTypes, false),
+ requests_(),
+ device_settings_(NULL) {
+ device_settings_ = new MediaStreamDeviceSettings(this);
+ video_capture_manager_->Register(this);
+ // TODO(mflodman) Add when audio input manager is available.
+}
+
+MediaStreamManager::DeviceRequest::DeviceRequest()
+ : requester(NULL),
+ state(kNumMediaStreamTypes, kNotRequested) {
+ options.audio = false;
+ options.video_option = StreamOptions::kNoCamera;
+}
+
+MediaStreamManager::DeviceRequest::DeviceRequest(
+ MediaStreamRequester* requester, const StreamOptions& request_options)
+ : requester(requester),
+ options(request_options),
+ state(kNumMediaStreamTypes, kNotRequested) {
+ DCHECK(requester);
+}
+
+MediaStreamManager::DeviceRequest::~DeviceRequest() {}
+
+} // namespace media_stream
diff --git a/content/browser/renderer_host/media/media_stream_manager.h b/content/browser/renderer_host/media/media_stream_manager.h
new file mode 100644
index 0000000..108cafe
--- /dev/null
+++ b/content/browser/renderer_host/media/media_stream_manager.h
@@ -0,0 +1,132 @@
+// Copyright (c) 2011 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 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 MediaStreamDeviceSettings for permission to
+// use devices and for which device to use.
+// 3. MediaStreamDeviceSettings will request list(s) of available devices, the
+// requests will be relayed to the corresponding media device manager and the
+// result will be given to MediaStreamDeviceSettings.
+// 4. MediaStreamDeviceSettings will, by using user settings, pick devices which
+// devices to use and let MediaStreamManager know the result.
+// 5. MediaStreamManager will call the proper media device manager to open the
+// device and let the MediaStreamRequester know it has been done.
+
+#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 <vector>
+
+#include "base/lazy_instance.h"
+#include "content/browser/renderer_host/media/media_stream_provider.h"
+#include "content/browser/renderer_host/media/media_stream_settings_requester.h"
+#include "content/common/media/media_stream_options.h"
+
+namespace media_stream {
+
+class MediaStreamDeviceSettings;
+class MediaStreamRequester;
+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
+// MediaStreamManager::Listener.
+class MediaStreamManager : public MediaStreamProviderListener,
+ public SettingsRequester {
+ public:
+ typedef MediaStreamManager* (AccessorMethod)();
+ static MediaStreamManager* Get();
+ virtual ~MediaStreamManager();
+
+ // Used to access VideoCaptuerManager.
+ VideoCaptureManager* video_capture_manager();
+
+ // GenerateStream opens new media devices according to |components|. The
+ // request is identified using |label|, which is pointing to an already
+ // created std::string.
+ void GenerateStream(MediaStreamRequester* requester, int render_process_id,
+ int render_view_id, const StreamOptions& options,
+ const std::string& security_origin, std::string* label);
+
+ // Cancels all non-finished GenerateStream request, i.e. request for which
+ // StreamGenerated hasn't been called.
+ void CancelRequests(MediaStreamRequester* requester);
+
+ // Closes generated stream.
+ void StopGeneratedStream(const std::string& label);
+
+ // Implements MediaStreamProviderListener.
+ virtual void Opened(MediaStreamType stream_type, int capture_session_id);
+ virtual void Closed(MediaStreamType stream_type, int capture_session_id);
+ virtual void DevicesEnumerated(MediaStreamType stream_type,
+ const StreamDeviceInfoArray& devices);
+ virtual void Error(MediaStreamType stream_type, int capture_session_id,
+ MediaStreamProviderError error);
+
+ // Implements SettingsRequester.
+ virtual void GetDevices(const std::string& label,
+ MediaStreamType stream_type);
+ virtual void DevicesAccepted(const std::string& label,
+ const StreamDeviceInfoArray& devices);
+ virtual void SettingsError(const std::string& label);
+
+ // Used by unit test to make sure fake devices are used instead of a real
+ // devices, which is needed for server based testing.
+ void UseFakeDevice();
+
+ private:
+ // Contains all data needed to keep track of requests.
+ struct DeviceRequest {
+ DeviceRequest();
+ DeviceRequest(MediaStreamRequester* requester,
+ const StreamOptions& request_options);
+ ~DeviceRequest();
+ enum RequestState {
+ kNotRequested = 0,
+ kRequested,
+ kOpening,
+ kDone,
+ kError
+ };
+
+ MediaStreamRequester* requester;
+ StreamOptions options;
+ std::vector<RequestState> state;
+ StreamDeviceInfoArray audio_devices;
+ StreamDeviceInfoArray video_devices;
+ };
+
+ // Helpers.
+ bool RequestDone(const MediaStreamManager::DeviceRequest& request) const;
+ MediaStreamProvider* GetDeviceManager(MediaStreamType stream_type) const;
+
+ // Private constructor to enforce singleton.
+ friend struct base::DefaultLazyInstanceTraits<MediaStreamManager>;
+ MediaStreamManager();
+
+ VideoCaptureManager* video_capture_manager_;
+ // TODO(mflodman) Add AudioInputManager.
+
+ // Keeps track of device types currently being enumerated to not enumerate
+ // when not necessary.
+ std::vector<bool> enumeration_in_progress_;
+
+ // All non-closed request.
+ typedef std::map<std::string, DeviceRequest> DeviceRequests;
+ DeviceRequests requests_;
+
+ MediaStreamDeviceSettings* device_settings_;
+
+ DISALLOW_COPY_AND_ASSIGN(MediaStreamManager);
+};
+
+} // namespace media_stream
+
+#endif // CONTENT_BROWSER_RENDERER_HOST_MEDIA_MEDIA_STREAM_MANAGER_H_
diff --git a/content/browser/renderer_host/media/media_stream_requester.h b/content/browser/renderer_host/media/media_stream_requester.h
new file mode 100644
index 0000000..da879fa5
--- /dev/null
+++ b/content/browser/renderer_host/media/media_stream_requester.h
@@ -0,0 +1,39 @@
+// Copyright (c) 2011 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.
+
+#ifndef CONTENT_BROWSER_RENDERER_HOST_MEDIA_MEDIA_STREAM_REQUESTER_H_
+#define CONTENT_BROWSER_RENDERER_HOST_MEDIA_MEDIA_STREAM_REQUESTER_H_
+
+#include <string>
+
+#include "content/common/media/media_stream_options.h"
+
+namespace media_stream {
+
+// MediaStreamRequester must be implemented by the class requesting a new media
+// stream to be opened. MediaStreamManager will use this interface to signal
+// success and error for a request.
+class MediaStreamRequester {
+ public:
+ // Called as a reply of a successful call to GenerateStream.
+ virtual void StreamGenerated(const std::string& label,
+ const StreamDeviceInfoArray& audio_devices,
+ const StreamDeviceInfoArray& video_devices) = 0;
+ // Called if GenerateStream failed.
+ virtual void StreamGenerationFailed(const std::string& label) = 0;
+ // AudioDeviceFailed is called if an already opened audio device encounters
+ // an error.
+ virtual void AudioDeviceFailed(const std::string& label, int index) = 0;
+ // VideoDeviceFailed is called if an already opened video device encounters
+ // an error.
+ virtual void VideoDeviceFailed(const std::string& label, int index) = 0;
+
+ protected:
+ virtual ~MediaStreamRequester() {
+ }
+};
+
+} // namespace media_stream
+
+#endif // CONTENT_BROWSER_RENDERER_HOST_MEDIA_MEDIA_STREAM_REQUESTER_H_
diff --git a/content/browser/renderer_host/media/media_stream_settings_requester.h b/content/browser/renderer_host/media/media_stream_settings_requester.h
index 46e2540..267cc95 100644
--- a/content/browser/renderer_host/media/media_stream_settings_requester.h
+++ b/content/browser/renderer_host/media/media_stream_settings_requester.h
@@ -7,7 +7,6 @@
#include <string>
-#include "base/task.h"
#include "content/common/media/media_stream_options.h"
namespace media_stream {
@@ -27,7 +26,7 @@ class SettingsRequester {
const StreamDeviceInfoArray& devices) = 0;
// An error for specified |request_id| has occurred.
- virtual void Error(const std::string& label) = 0;
+ virtual void SettingsError(const std::string& label) = 0;
protected:
virtual ~SettingsRequester() {}
@@ -35,6 +34,4 @@ class SettingsRequester {
} // namespace media_stream
-DISABLE_RUNNABLE_METHOD_REFCOUNT(media_stream::SettingsRequester);
-
#endif // CONTENT_BROWSER_RENDERER_HOST_MEDIA_MEDIA_STREAM_SETTINGS_REQUESTER_H_
diff --git a/content/browser/renderer_host/media/video_capture_controller.cc b/content/browser/renderer_host/media/video_capture_controller.cc
index 8eb4ca5..7d84ea1 100644
--- a/content/browser/renderer_host/media/video_capture_controller.cc
+++ b/content/browser/renderer_host/media/video_capture_controller.cc
@@ -6,6 +6,7 @@
#include "base/stl_util-inl.h"
#include "content/browser/browser_thread.h"
+#include "content/browser/renderer_host/media/media_stream_manager.h"
#include "content/browser/renderer_host/media/video_capture_manager.h"
#include "media/base/yuv_convert.h"
@@ -34,8 +35,8 @@ void VideoCaptureController::StartCapture(
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
params_ = params;
- media_stream::VideoCaptureManager* manager =
- media_stream::VideoCaptureManager::Get();
+ media_stream::VideoCaptureManager* manager =
+ media_stream::MediaStreamManager::Get()->video_capture_manager();
// Order the manager to start the actual capture.
manager->Start(params, this);
}
@@ -44,7 +45,7 @@ void VideoCaptureController::StopCapture(Task* stopped_task) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
media_stream::VideoCaptureManager* manager =
- media_stream::VideoCaptureManager::Get();
+ media_stream::MediaStreamManager::Get()->video_capture_manager();
manager->Stop(params_.session_id,
NewRunnableMethod(this,
&VideoCaptureController::OnDeviceStopped,
@@ -156,7 +157,8 @@ void VideoCaptureController::OnIncomingCapturedFrame(const uint8* data,
void VideoCaptureController::OnError() {
event_handler_->OnError(id_);
- media_stream::VideoCaptureManager::Get()->Error(params_.session_id);
+ media_stream::MediaStreamManager::Get()->video_capture_manager()->
+ Error(params_.session_id);
}
void VideoCaptureController::OnFrameInfo(
diff --git a/content/browser/renderer_host/media/video_capture_host_unittest.cc b/content/browser/renderer_host/media/video_capture_host_unittest.cc
index 0ba1262..088e2f3 100644
--- a/content/browser/renderer_host/media/video_capture_host_unittest.cc
+++ b/content/browser/renderer_host/media/video_capture_host_unittest.cc
@@ -12,6 +12,7 @@
#include "base/stl_util-inl.h"
#include "base/stringprintf.h"
#include "content/browser/browser_thread.h"
+#include "content/browser/renderer_host/media/media_stream_manager.h"
#include "content/browser/renderer_host/media/video_capture_host.h"
#include "content/browser/renderer_host/media/video_capture_manager.h"
#include "content/common/media/video_capture_messages.h"
@@ -187,15 +188,15 @@ class VideoCaptureHostTest : public testing::Test {
protected:
virtual void SetUp() {
+ // Create a message loop so VideoCaptureHostTest can use it.
+ message_loop_.reset(new MessageLoop(MessageLoop::TYPE_IO));
+ io_thread_.reset(new BrowserThread(BrowserThread::IO, message_loop_.get()));
// Setup the VideoCaptureManager to use fake video capture device.
#ifndef TEST_REAL_CAPTURE_DEVICE
media_stream::VideoCaptureManager* manager =
- media_stream::VideoCaptureManager::Get();
+ media_stream::MediaStreamManager::Get()->video_capture_manager();
manager->UseFakeDevice();
#endif
- // Create a message loop so VideoCaptureHostTest can use it.
- message_loop_.reset(new MessageLoop(MessageLoop::TYPE_IO));
- io_thread_.reset(new BrowserThread(BrowserThread::IO, message_loop_.get()));
host_ = new MockVideoCaptureHost();
// Simulate IPC channel connected.
@@ -231,8 +232,10 @@ class VideoCaptureHostTest : public testing::Test {
// Called on the main thread.
static void PostQuitOnVideoCaptureManagerThread(MessageLoop* message_loop) {
- media_stream::VideoCaptureManager::Get()->GetMessageLoop()->PostTask(
- FROM_HERE, NewRunnableFunction(&PostQuitMessageLoop, message_loop));
+ media_stream::MediaStreamManager::Get()->video_capture_manager()->
+ GetMessageLoop()->PostTask(FROM_HERE,
+ NewRunnableFunction(
+ &PostQuitMessageLoop, message_loop));
}
// SyncWithVideoCaptureManagerThread() waits until all pending tasks on the
diff --git a/content/browser/renderer_host/media/video_capture_manager.cc b/content/browser/renderer_host/media/video_capture_manager.cc
index a6dafd0..0571b3f 100644
--- a/content/browser/renderer_host/media/video_capture_manager.cc
+++ b/content/browser/renderer_host/media/video_capture_manager.cc
@@ -16,13 +16,6 @@ namespace media_stream {
// explicitly calling open device.
enum { kFirstSessionId = VideoCaptureManager::kStartOpenSessionId + 1 };
-static ::base::LazyInstance<VideoCaptureManager> g_video_capture_manager(
- base::LINKER_INITIALIZED);
-
-VideoCaptureManager* VideoCaptureManager::Get() {
- return g_video_capture_manager.Pointer();
-}
-
VideoCaptureManager::VideoCaptureManager()
: vc_device_thread_("VideoCaptureManagerThread"),
listener_(NULL),
diff --git a/content/browser/renderer_host/media/video_capture_manager.h b/content/browser/renderer_host/media/video_capture_manager.h
index 751a3bf..581efa6 100644
--- a/content/browser/renderer_host/media/video_capture_manager.h
+++ b/content/browser/renderer_host/media/video_capture_manager.h
@@ -12,7 +12,6 @@
#include <map>
-#include "base/lazy_instance.h"
#include "base/threading/thread.h"
#include "content/browser/renderer_host/media/media_stream_provider.h"
#include "content/common/media/media_stream_options.h"
@@ -29,8 +28,8 @@ class VideoCaptureManager : public MediaStreamProvider {
// before MediaStream is implemented in Chrome and WebKit.
enum { kStartOpenSessionId = 1 };
- // Called to get a pointer to the singleton.
- static VideoCaptureManager* Get();
+ VideoCaptureManager();
+ virtual ~VideoCaptureManager();
// Implements MediaStreamProvider.
virtual void Register(MediaStreamProviderListener* listener);
@@ -59,8 +58,6 @@ class VideoCaptureManager : public MediaStreamProvider {
// won't stream any more captured frames.
void Error(const media::VideoCaptureSessionId& capture_session_id);
- virtual ~VideoCaptureManager();
-
// Used by unit test to make sure a fake device is used instead of a real
// video capture device. Due to timing requirements, the function must be
// called before EnumerateDevices and Open.
@@ -68,10 +65,6 @@ class VideoCaptureManager : public MediaStreamProvider {
MessageLoop* GetMessageLoop();
private:
- friend struct base::DefaultLazyInstanceTraits<VideoCaptureManager>;
-
- VideoCaptureManager();
-
// Called by the public functions, executed on vc_device_thread_.
void OnEnumerateDevices();
void OnOpen(int capture_session_id, const StreamDeviceInfo& device);
diff --git a/content/browser/renderer_host/media/video_capture_manager_unittest.cc b/content/browser/renderer_host/media/video_capture_manager_unittest.cc
index 348c2a6..1a4b7a0 100644
--- a/content/browser/renderer_host/media/video_capture_manager_unittest.cc
+++ b/content/browser/renderer_host/media/video_capture_manager_unittest.cc
@@ -69,7 +69,8 @@ class MockFrameObserver: public media::VideoCaptureDevice::EventHandler {
class VideoCaptureManagerTest : public testing::Test {
public:
VideoCaptureManagerTest()
- : listener_(),
+ : vcm_(),
+ listener_(),
message_loop_(),
io_thread_(),
frame_observer_() {
@@ -81,6 +82,9 @@ class VideoCaptureManagerTest : public testing::Test {
listener_.reset(new media_stream::MockMediaStreamProviderListener());
message_loop_.reset(new MessageLoop(MessageLoop::TYPE_IO));
io_thread_.reset(new BrowserThread(BrowserThread::IO, message_loop_.get()));
+ vcm_.reset(new media_stream::VideoCaptureManager());
+ vcm_->UseFakeDevice();
+ vcm_->Register(listener_.get());
frame_observer_.reset(new MockFrameObserver());
}
@@ -94,8 +98,9 @@ class VideoCaptureManagerTest : public testing::Test {
}
// Called on the main thread.
- static void PostQuitOnVideoCaptureManagerThread(MessageLoop* message_loop) {
- media_stream::VideoCaptureManager::Get()->GetMessageLoop()->PostTask(
+ static void PostQuitOnVideoCaptureManagerThread(
+ MessageLoop* message_loop, media_stream::VideoCaptureManager* vcm) {
+ vcm->GetMessageLoop()->PostTask(
FROM_HERE, NewRunnableFunction(&PostQuitMessageLoop, message_loop));
}
@@ -107,9 +112,11 @@ class VideoCaptureManagerTest : public testing::Test {
void SyncWithVideoCaptureManagerThread() {
message_loop_->PostTask(
FROM_HERE, NewRunnableFunction(&PostQuitOnVideoCaptureManagerThread,
- message_loop_.get()));
+ message_loop_.get(),
+ vcm_.get()));
message_loop_->Run();
}
+ scoped_ptr<media_stream::VideoCaptureManager> vcm_;
scoped_ptr<media_stream::MockMediaStreamProviderListener> listener_;
scoped_ptr<MessageLoop> message_loop_;
scoped_ptr<BrowserThread> io_thread_;
@@ -131,31 +138,26 @@ TEST_F(VideoCaptureManagerTest, CreateAndClose) {
EXPECT_CALL(*listener_, Closed(media_stream::kVideoCapture, _))
.Times(1);
- media_stream::VideoCaptureManager* vcm =
- media_stream::VideoCaptureManager::Get();
- // Make sure fake devices are used
- vcm->UseFakeDevice();
- vcm->Register(listener_.get());
- vcm->EnumerateDevices();
+ vcm_->EnumerateDevices();
// Wait to get device callback...
SyncWithVideoCaptureManagerThread();
- int video_session_id = vcm->Open(listener_->devices_.front());
+ int video_session_id = vcm_->Open(listener_->devices_.front());
media::VideoCaptureParams capture_params;
capture_params.session_id = video_session_id;
capture_params.width = 320;
capture_params.height = 240;
capture_params.frame_per_second = 30;
- vcm->Start(capture_params, frame_observer_.get());
+ vcm_->Start(capture_params, frame_observer_.get());
- vcm->Stop(video_session_id, NULL);
- vcm->Close(video_session_id);
+ vcm_->Stop(video_session_id, NULL);
+ vcm_->Close(video_session_id);
// Wait to check callbacks before removing the listener
SyncWithVideoCaptureManagerThread();
- vcm->Unregister();
+ vcm_->Unregister();
}
// Open the same device twice, should fail.
@@ -171,26 +173,21 @@ TEST_F(VideoCaptureManagerTest, OpenTwice) {
EXPECT_CALL(*listener_, Closed(media_stream::kVideoCapture, _))
.Times(1);
- media_stream::VideoCaptureManager* vcm =
- media_stream::VideoCaptureManager::Get();
- // Make sure fake devices are used
- vcm->UseFakeDevice();
- vcm->Register(listener_.get());
- vcm->EnumerateDevices();
+ vcm_->EnumerateDevices();
// Wait to get device callback...
SyncWithVideoCaptureManagerThread();
- int video_session_id = vcm->Open(listener_->devices_.front());
+ int video_session_id = vcm_->Open(listener_->devices_.front());
// This should trigger an error callback with error code 'kDeviceAlreadyInUse'
- vcm->Open(listener_->devices_.front());
+ vcm_->Open(listener_->devices_.front());
- vcm->Close(video_session_id);
+ vcm_->Close(video_session_id);
// Wait to check callbacks before removing the listener
SyncWithVideoCaptureManagerThread();
- vcm->Unregister();
+ vcm_->Unregister();
}
// Open two different devices.
@@ -203,12 +200,7 @@ TEST_F(VideoCaptureManagerTest, OpenTwo) {
EXPECT_CALL(*listener_, Closed(media_stream::kVideoCapture, _))
.Times(2);
- media_stream::VideoCaptureManager* vcm =
- media_stream::VideoCaptureManager::Get();
- // Make sure fake devices are used
- vcm->UseFakeDevice();
- vcm->Register(listener_.get());
- vcm->EnumerateDevices();
+ vcm_->EnumerateDevices();
// Wait to get device callback...
SyncWithVideoCaptureManagerThread();
@@ -216,18 +208,18 @@ TEST_F(VideoCaptureManagerTest, OpenTwo) {
media_stream::StreamDeviceInfoArray::iterator it =
listener_->devices_.begin();
- int video_session_id_first = vcm->Open(*it);
+ int video_session_id_first = vcm_->Open(*it);
// This should trigger an error callback with error code 'kDeviceAlreadyInUse'
++it;
- int video_session_id_second = vcm->Open(*it);
+ int video_session_id_second = vcm_->Open(*it);
- vcm->Close(video_session_id_first);
- vcm->Close(video_session_id_second);
+ vcm_->Close(video_session_id_first);
+ vcm_->Close(video_session_id_second);
// Wait to check callbacks before removing the listener
SyncWithVideoCaptureManagerThread();
- vcm->Unregister();
+ vcm_->Unregister();
}
// Try open a non-existing device.
@@ -239,12 +231,7 @@ TEST_F(VideoCaptureManagerTest, OpenNotExisting) {
media_stream::kDeviceNotAvailable))
.Times(1);
- media_stream::VideoCaptureManager* vcm =
- media_stream::VideoCaptureManager::Get();
- // Make sure fake devices are used
- vcm->UseFakeDevice();
- vcm->Register(listener_.get());
- vcm->EnumerateDevices();
+ vcm_->EnumerateDevices();
// Wait to get device callback...
SyncWithVideoCaptureManagerThread();
@@ -256,11 +243,11 @@ TEST_F(VideoCaptureManagerTest, OpenNotExisting) {
device_id, false);
// This should fail with error code 'kDeviceNotAvailable'
- vcm->Open(dummy_device);
+ vcm_->Open(dummy_device);
// Wait to check callbacks before removing the listener
SyncWithVideoCaptureManagerThread();
- vcm->Unregister();
+ vcm_->Unregister();
}
// Start a device using "magic" id, i.e. call Start without calling Open.
@@ -271,12 +258,6 @@ TEST_F(VideoCaptureManagerTest, StartUsingId) {
EXPECT_CALL(*listener_, Closed(media_stream::kVideoCapture, _))
.Times(1);
- media_stream::VideoCaptureManager* vcm =
- media_stream::VideoCaptureManager::Get();
- // Make sure fake devices are used
- vcm->UseFakeDevice();
- vcm->Register(listener_.get());
-
media::VideoCaptureParams capture_params;
capture_params.session_id =
media_stream::VideoCaptureManager::kStartOpenSessionId;
@@ -284,14 +265,14 @@ TEST_F(VideoCaptureManagerTest, StartUsingId) {
capture_params.height = 240;
capture_params.frame_per_second = 30;
// Start shall trigger the Open callback
- vcm->Start(capture_params, frame_observer_.get());
+ vcm_->Start(capture_params, frame_observer_.get());
// Stop shall trigger the Close callback
- vcm->Stop(media_stream::VideoCaptureManager::kStartOpenSessionId, NULL);
+ vcm_->Stop(media_stream::VideoCaptureManager::kStartOpenSessionId, NULL);
// Wait to check callbacks before removing the listener
SyncWithVideoCaptureManagerThread();
- vcm->Unregister();
+ vcm_->Unregister();
}
} // namespace
diff --git a/content/common/media/media_stream_options.h b/content/common/media/media_stream_options.h
index 8ba92f6..7569fdc 100644
--- a/content/common/media/media_stream_options.h
+++ b/content/common/media/media_stream_options.h
@@ -36,7 +36,8 @@ struct StreamOptions {
enum MediaStreamType {
kNoService = 0,
kAudioCapture,
- kVideoCapture
+ kVideoCapture,
+ kNumMediaStreamTypes
};
// StreamDeviceInfo describes information about a device.
diff --git a/content/content_browser.gypi b/content/content_browser.gypi
index 342722c2..64b635a 100644
--- a/content/content_browser.gypi
+++ b/content/content_browser.gypi
@@ -268,7 +268,10 @@
'browser/renderer_host/media/audio_sync_reader.h',
'browser/renderer_host/media/media_stream_device_settings.cc',
'browser/renderer_host/media/media_stream_device_settings.h',
+ 'browser/renderer_host/media/media_stream_manager.cc',
+ 'browser/renderer_host/media/media_stream_manager.h',
'browser/renderer_host/media/media_stream_provider.h',
+ 'browser/renderer_host/media/media_stream_requester.h',
'browser/renderer_host/media/media_stream_settings_requester.h',
'browser/renderer_host/media/video_capture_controller.cc',
'browser/renderer_host/media/video_capture_controller.h',