summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorxians@chromium.org <xians@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-07-06 12:03:05 +0000
committerxians@chromium.org <xians@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-07-06 12:03:05 +0000
commit5a309716dd90e1812016255f6ab06e6819d84fc8 (patch)
treeb5abd4c8e254b684ae5a452c3ff15bd2111b3c18
parent3919f5403f926c501b6802214340f4f7b7872e56 (diff)
downloadchromium_src-5a309716dd90e1812016255f6ab06e6819d84fc8.zip
chromium_src-5a309716dd90e1812016255f6ab06e6819d84fc8.tar.gz
chromium_src-5a309716dd90e1812016255f6ab06e6819d84fc8.tar.bz2
Pepper needs to repeatedly call enumeration API in order to get a synchronous up-to-date device list. This heavily loads the IO thread since the enumeration is done on IO thread.
This patch moves the device thread from VideoCaptureManager to MediaStreamManager, so that audio and video can share one device thread, and also allow running audio device API on this shared device thread. BUG=132701,130113 TEST=content_unittests Review URL: https://chromiumcodereview.appspot.com/10662049 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@145584 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--content/browser/browser_main_loop.cc18
-rw-r--r--content/browser/browser_main_loop.h6
-rw-r--r--content/browser/renderer_host/media/audio_input_device_manager.cc62
-rw-r--r--content/browser/renderer_host/media/audio_input_device_manager.h21
-rw-r--r--content/browser/renderer_host/media/audio_input_device_manager_unittest.cc18
-rw-r--r--content/browser/renderer_host/media/audio_input_renderer_host.cc20
-rw-r--r--content/browser/renderer_host/media/audio_input_renderer_host.h19
-rw-r--r--content/browser/renderer_host/media/media_stream_device_settings.cc1
-rw-r--r--content/browser/renderer_host/media/media_stream_dispatcher_host.cc30
-rw-r--r--content/browser/renderer_host/media/media_stream_dispatcher_host.h15
-rw-r--r--content/browser/renderer_host/media/media_stream_dispatcher_host_unittest.cc86
-rw-r--r--content/browser/renderer_host/media/media_stream_manager.cc57
-rw-r--r--content/browser/renderer_host/media/media_stream_manager.h49
-rw-r--r--content/browser/renderer_host/media/media_stream_provider.h11
-rw-r--r--content/browser/renderer_host/media/video_capture_controller_unittest.cc5
-rw-r--r--content/browser/renderer_host/media/video_capture_host.cc11
-rw-r--r--content/browser/renderer_host/media/video_capture_host.h20
-rw-r--r--content/browser/renderer_host/media/video_capture_host_unittest.cc79
-rw-r--r--content/browser/renderer_host/media/video_capture_manager.cc70
-rw-r--r--content/browser/renderer_host/media/video_capture_manager.h32
-rw-r--r--content/browser/renderer_host/media/video_capture_manager_unittest.cc73
-rw-r--r--content/browser/renderer_host/render_process_host_impl.cc11
-rw-r--r--content/test/webrtc_audio_device_test.cc23
-rw-r--r--media/video/capture/win/video_capture_device_win.cc12
-rw-r--r--media/video/capture/win/video_capture_device_win.h8
25 files changed, 366 insertions, 391 deletions
diff --git a/content/browser/browser_main_loop.cc b/content/browser/browser_main_loop.cc
index 2932aeb..90e0f12 100644
--- a/content/browser/browser_main_loop.cc
+++ b/content/browser/browser_main_loop.cc
@@ -25,6 +25,9 @@
#include "content/browser/in_process_webkit/webkit_thread.h"
#include "content/browser/net/browser_online_state_observer.h"
#include "content/browser/plugin_service_impl.h"
+#include "content/browser/renderer_host/media/audio_input_device_manager.h"
+#include "content/browser/renderer_host/media/media_stream_manager.h"
+#include "content/browser/renderer_host/media/video_capture_manager.h"
#include "content/browser/renderer_host/resource_dispatcher_host_impl.h"
#include "content/browser/speech/speech_recognition_manager_impl.h"
#include "content/browser/trace_controller_impl.h"
@@ -210,6 +213,10 @@ media::AudioManager* BrowserMainLoop::GetAudioManager() {
return g_current_browser_main_loop->audio_manager_.get();
}
+// static
+media_stream::MediaStreamManager* BrowserMainLoop::GetMediaStreamManager() {
+ return g_current_browser_main_loop->media_stream_manager_.get();
+}
// BrowserMainLoop construction / destruction =============================
BrowserMainLoop::BrowserMainLoop(const content::MainFunctionParams& parameters)
@@ -325,6 +332,13 @@ void BrowserMainLoop::MainMessageLoopStart() {
network_change_notifier_.reset(net::NetworkChangeNotifier::Create());
audio_manager_.reset(media::AudioManager::Create());
online_state_observer_.reset(new BrowserOnlineStateObserver);
+ scoped_refptr<media_stream::AudioInputDeviceManager>
+ audio_input_device_manager(
+ new media_stream::AudioInputDeviceManager(audio_manager_.get()));
+ scoped_refptr<media_stream::VideoCaptureManager> video_capture_manager(
+ new media_stream::VideoCaptureManager());
+ media_stream_manager_.reset(new media_stream::MediaStreamManager(
+ audio_input_device_manager, video_capture_manager));
#if defined(OS_WIN)
system_message_window_.reset(new SystemMessageWindowWin);
@@ -470,6 +484,10 @@ void BrowserMainLoop::ShutdownThreadsAndCleanUp() {
speech_recognition_manager_.reset();
+ // MediaStreamManager needs to be deleted on IO thread in order to unregister
+ // itself as the listener to VideoCaptureManager and AudioInputDeviceManager.
+ BrowserThread::DeleteOnIOThread::Destruct(media_stream_manager_.release());
+
#if defined(USE_AURA)
ImageTransportFactory::Terminate();
#endif
diff --git a/content/browser/browser_main_loop.h b/content/browser/browser_main_loop.h
index 6905431..9ecc61c 100644
--- a/content/browser/browser_main_loop.h
+++ b/content/browser/browser_main_loop.h
@@ -28,6 +28,10 @@ namespace media {
class AudioManager;
}
+namespace media_stream {
+class MediaStreamManager;
+}
+
namespace net {
class NetworkChangeNotifier;
}
@@ -73,6 +77,7 @@ class BrowserMainLoop {
// Can be called on any thread.
static media::AudioManager* GetAudioManager();
+ static media_stream::MediaStreamManager* GetMediaStreamManager();
private:
// For ShutdownThreadsAndCleanUp.
@@ -96,6 +101,7 @@ class BrowserMainLoop {
scoped_ptr<HighResolutionTimerManager> hi_res_timer_manager_;
scoped_ptr<net::NetworkChangeNotifier> network_change_notifier_;
scoped_ptr<media::AudioManager> audio_manager_;
+ scoped_ptr<media_stream::MediaStreamManager> media_stream_manager_;
// Per-process listener for online state changes.
scoped_ptr<BrowserOnlineStateObserver> online_state_observer_;
#if defined(OS_WIN)
diff --git a/content/browser/renderer_host/media/audio_input_device_manager.cc b/content/browser/renderer_host/media/audio_input_device_manager.cc
index 00e37f9a..76eca28 100644
--- a/content/browser/renderer_host/media/audio_input_device_manager.cc
+++ b/content/browser/renderer_host/media/audio_input_device_manager.cc
@@ -31,10 +31,14 @@ AudioInputDeviceManager::AudioInputDeviceManager(
AudioInputDeviceManager::~AudioInputDeviceManager() {
}
-void AudioInputDeviceManager::Register(MediaStreamProviderListener* listener) {
+void AudioInputDeviceManager::Register(
+ MediaStreamProviderListener* listener,
+ base::MessageLoopProxy* device_thread_loop) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
DCHECK(!listener_);
+ DCHECK(!device_loop_);
listener_ = listener;
+ device_loop_ = device_thread_loop;
}
void AudioInputDeviceManager::Unregister() {
@@ -47,6 +51,36 @@ void AudioInputDeviceManager::EnumerateDevices() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
DCHECK(listener_);
+ device_loop_->PostTask(
+ FROM_HERE,
+ base::Bind(&AudioInputDeviceManager::EnumerateOnDeviceThread, this));
+}
+
+int AudioInputDeviceManager::Open(const StreamDeviceInfo& device) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ // Generates a new id for this device.
+ int session_id = next_capture_session_id_++;
+ device_loop_->PostTask(
+ FROM_HERE,
+ base::Bind(&AudioInputDeviceManager::OpenOnDeviceThread,
+ this, session_id, device));
+
+ return session_id;
+}
+
+void AudioInputDeviceManager::Close(int session_id) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ DCHECK(listener_);
+ device_loop_->PostTask(
+ FROM_HERE,
+ base::Bind(&AudioInputDeviceManager::CloseOnDeviceThread,
+ this, session_id));
+}
+
+void AudioInputDeviceManager::EnumerateOnDeviceThread() {
+ DCHECK(IsOnDeviceThread());
+ // AudioManager is guaranteed to outlive MediaStreamManager in
+ // BrowserMainloop.
media::AudioDeviceNames device_names;
audio_manager_->GetAudioInputDeviceNames(&device_names);
@@ -69,19 +103,14 @@ void AudioInputDeviceManager::EnumerateDevices() {
devices));
}
-int AudioInputDeviceManager::Open(const StreamDeviceInfo& device) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
-
- // Generates a new id for this device.
- int session_id = next_capture_session_id_++;
+void AudioInputDeviceManager::OpenOnDeviceThread(
+ int session_id, const StreamDeviceInfo& device) {
+ DCHECK(IsOnDeviceThread());
DCHECK(devices_.find(session_id) == devices_.end());
- media::AudioDeviceName audio_input_device_name;
- audio_input_device_name.device_name = device.name;
- audio_input_device_name.unique_id = device.device_id;
-
// Adds the session_id and device to the list.
- devices_[session_id] = audio_input_device_name;
+ media::AudioDeviceName target_device(device.name, device.device_id);
+ devices_[session_id] = target_device;
// Returns the |session_id| through the listener by posting a task on
// IO thread since MediaStreamManager handles the callback asynchronously.
@@ -90,13 +119,10 @@ int AudioInputDeviceManager::Open(const StreamDeviceInfo& device) {
base::Bind(&AudioInputDeviceManager::OpenedOnIOThread,
this,
session_id));
-
- return session_id;
}
-void AudioInputDeviceManager::Close(int session_id) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
- DCHECK(listener_);
+void AudioInputDeviceManager::CloseOnDeviceThread(int session_id) {
+ DCHECK(IsOnDeviceThread());
if (devices_.find(session_id) != devices_.end())
devices_.erase(session_id);
@@ -181,4 +207,8 @@ void AudioInputDeviceManager::ClosedOnIOThread(int session_id) {
session_id);
}
+bool AudioInputDeviceManager::IsOnDeviceThread() const {
+ return device_loop_->BelongsToCurrentThread();
+}
+
} // namespace media_stream
diff --git a/content/browser/renderer_host/media/audio_input_device_manager.h b/content/browser/renderer_host/media/audio_input_device_manager.h
index 96bff65..3d79dc9 100644
--- a/content/browser/renderer_host/media/audio_input_device_manager.h
+++ b/content/browser/renderer_host/media/audio_input_device_manager.h
@@ -6,8 +6,8 @@
// communicates with MediaStreamManager and AudioInputRendererHost on the
// browser IO thread, handles queries like enumerate/open/close from
// MediaStreamManager and start/stop from AudioInputRendererHost.
-
-// All the queries and work are handled on the IO thread.
+// The work for enumerate/open/close is handled asynchronously on Media Stream
+// device thread, while start/stop are synchronous on the IO thread.
#ifndef CONTENT_BROWSER_RENDERER_HOST_MEDIA_AUDIO_INPUT_DEVICE_MANAGER_H_
#define CONTENT_BROWSER_RENDERER_HOST_MEDIA_AUDIO_INPUT_DEVICE_MANAGER_H_
@@ -44,7 +44,8 @@ class CONTENT_EXPORT AudioInputDeviceManager
explicit AudioInputDeviceManager(media::AudioManager* audio_manager);
// MediaStreamProvider implementation, called on IO thread.
- virtual void Register(MediaStreamProviderListener* listener) OVERRIDE;
+ virtual void Register(MediaStreamProviderListener* listener,
+ base::MessageLoopProxy* device_thread_loop) OVERRIDE;
virtual void Unregister() OVERRIDE;
virtual void EnumerateDevices() OVERRIDE;
virtual int Open(const StreamDeviceInfo& device) OVERRIDE;
@@ -61,21 +62,33 @@ class CONTENT_EXPORT AudioInputDeviceManager
friend class base::RefCountedThreadSafe<AudioInputDeviceManager>;
virtual ~AudioInputDeviceManager();
+ // Executed on media stream device thread.
+ void EnumerateOnDeviceThread();
+ void OpenOnDeviceThread(int session_id, const StreamDeviceInfo& device);
+ void CloseOnDeviceThread(int session_id);
+
// Executed on IO thread to call Listener.
void DevicesEnumeratedOnIOThread(StreamDeviceInfoArray* devices);
void OpenedOnIOThread(int session_id);
void ClosedOnIOThread(int session_id);
void ErrorOnIOThread(int session_id, MediaStreamProviderError error);
+ bool IsOnDeviceThread() const;
+
+ // Only accessed on Browser::IO thread.
MediaStreamProviderListener* listener_;
int next_capture_session_id_;
typedef std::map<int, AudioInputDeviceManagerEventHandler*> EventHandlerMap;
EventHandlerMap event_handlers_;
+
+ // Only accessed from media stream device thread.
typedef std::map<int, media::AudioDeviceName> AudioInputDeviceMap;
AudioInputDeviceMap devices_;
- // TODO(tommi): Is it necessary to store this as a member?
media::AudioManager* audio_manager_;
+ // The message loop of media stream device thread that this object runs on.
+ scoped_refptr<base::MessageLoopProxy> device_loop_;
+
DISALLOW_COPY_AND_ASSIGN(AudioInputDeviceManager);
};
diff --git a/content/browser/renderer_host/media/audio_input_device_manager_unittest.cc b/content/browser/renderer_host/media/audio_input_device_manager_unittest.cc
index fe57150..257cec7 100644
--- a/content/browser/renderer_host/media/audio_input_device_manager_unittest.cc
+++ b/content/browser/renderer_host/media/audio_input_device_manager_unittest.cc
@@ -87,12 +87,7 @@ ACTION_P(ExitMessageLoop, message_loop) {
class AudioInputDeviceManagerTest : public testing::Test {
public:
- AudioInputDeviceManagerTest()
- : message_loop_(),
- io_thread_(),
- manager_(),
- audio_input_listener_() {
- }
+ AudioInputDeviceManagerTest() {}
// Returns true iff machine has an audio input device.
bool CanRunAudioInputDeviceTests() {
@@ -100,27 +95,28 @@ class AudioInputDeviceManagerTest : public testing::Test {
}
protected:
- virtual void SetUp() {
+ virtual void SetUp() OVERRIDE {
// The test must run on Browser::IO.
message_loop_.reset(new MessageLoop(MessageLoop::TYPE_IO));
io_thread_.reset(new BrowserThreadImpl(BrowserThread::IO,
message_loop_.get()));
- audio_manager_.reset(media::AudioManager::Create());
+ audio_manager_.reset(media::AudioManager::Create());
manager_ = new AudioInputDeviceManager(audio_manager_.get());
audio_input_listener_.reset(new MockAudioInputDeviceManagerListener());
- manager_->Register(audio_input_listener_.get());
+ manager_->Register(audio_input_listener_.get(),
+ message_loop_->message_loop_proxy());
// Gets the enumerated device list from the AudioInputDeviceManager.
manager_->EnumerateDevices();
EXPECT_CALL(*audio_input_listener_, DevicesEnumerated(_))
.Times(1);
- // Waits for the callback.
+ // Wait until we get the list.
message_loop_->RunAllPending();
}
- virtual void TearDown() {
+ virtual void TearDown() OVERRIDE {
manager_->Unregister();
io_thread_.reset();
}
diff --git a/content/browser/renderer_host/media/audio_input_renderer_host.cc b/content/browser/renderer_host/media/audio_input_renderer_host.cc
index 8362330..4af7b61 100644
--- a/content/browser/renderer_host/media/audio_input_renderer_host.cc
+++ b/content/browser/renderer_host/media/audio_input_renderer_host.cc
@@ -24,10 +24,10 @@ AudioInputRendererHost::AudioEntry::AudioEntry()
AudioInputRendererHost::AudioEntry::~AudioEntry() {}
AudioInputRendererHost::AudioInputRendererHost(
- content::ResourceContext* resource_context,
- media::AudioManager* audio_manager)
- : resource_context_(resource_context),
- audio_manager_(audio_manager) {
+ media::AudioManager* audio_manager,
+ media_stream::MediaStreamManager* media_stream_manager)
+ : audio_manager_(audio_manager),
+ media_stream_manager_(media_stream_manager) {
}
AudioInputRendererHost::~AudioInputRendererHost() {
@@ -182,17 +182,12 @@ void AudioInputRendererHost::OnStartDevice(int stream_id, int session_id) {
VLOG(1) << "AudioInputRendererHost::OnStartDevice(stream_id="
<< stream_id << ", session_id = " << session_id << ")";
- // Get access to the AudioInputDeviceManager to start the device.
- media_stream::AudioInputDeviceManager* audio_input_man =
- media_stream::MediaStreamManager::GetForResourceContext(
- resource_context_, audio_manager_)->audio_input_device_manager();
-
// Add the session entry to the map.
session_entries_[session_id] = stream_id;
// Start the device with the session_id. If the device is started
// successfully, OnDeviceStarted() callback will be triggered.
- audio_input_man->Start(session_id, this);
+ media_stream_manager_->audio_input_device_manager()->Start(session_id, this);
}
void AudioInputRendererHost::OnCreateStream(
@@ -349,10 +344,7 @@ void AudioInputRendererHost::OnDeviceStopped(int session_id) {
void AudioInputRendererHost::StopAndDeleteDevice(int session_id) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
- media_stream::AudioInputDeviceManager* audio_input_man =
- media_stream::MediaStreamManager::GetForResourceContext(
- resource_context_, audio_manager_)->audio_input_device_manager();
- audio_input_man->Stop(session_id);
+ media_stream_manager_->audio_input_device_manager()->Stop(session_id);
// Delete the session entry.
session_entries_.erase(session_id);
diff --git a/content/browser/renderer_host/media/audio_input_renderer_host.h b/content/browser/renderer_host/media/audio_input_renderer_host.h
index e8bec46..0cfba06 100644
--- a/content/browser/renderer_host/media/audio_input_renderer_host.h
+++ b/content/browser/renderer_host/media/audio_input_renderer_host.h
@@ -64,15 +64,15 @@
#include "media/audio/audio_io.h"
#include "media/audio/simple_sources.h"
-namespace content {
-class ResourceContext;
-}
-
namespace media {
class AudioManager;
class AudioParameters;
}
+namespace media_stream {
+class MediaStreamManager;
+}
+
class CONTENT_EXPORT AudioInputRendererHost
: public content::BrowserMessageFilter,
public media::AudioInputController::EventHandler,
@@ -100,8 +100,9 @@ class CONTENT_EXPORT AudioInputRendererHost
};
// Called from UI thread from the owner of this object.
- AudioInputRendererHost(content::ResourceContext* resource_context,
- media::AudioManager* audio_manager);
+ AudioInputRendererHost(
+ media::AudioManager* audio_manager,
+ media_stream::MediaStreamManager* media_stream_manager);
// content::BrowserMessageFilter implementation.
virtual void OnChannelClosing() OVERRIDE;
@@ -197,10 +198,12 @@ class CONTENT_EXPORT AudioInputRendererHost
// Returns 0 if not found.
int LookupSessionById(int stream_id);
- // Used to get an instance of AudioInputDeviceManager.
- content::ResourceContext* resource_context_;
+ // Used to create an AudioInputController.
media::AudioManager* audio_manager_;
+ // Used to access to AudioInputDeviceManager.
+ media_stream::MediaStreamManager* media_stream_manager_;
+
// A map of stream IDs to audio sources.
typedef std::map<int, AudioEntry*> AudioEntryMap;
AudioEntryMap audio_entries_;
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 f16818b..c3a3350 100644
--- a/content/browser/renderer_host/media/media_stream_device_settings.cc
+++ b/content/browser/renderer_host/media/media_stream_device_settings.cc
@@ -137,7 +137,6 @@ MediaStreamDeviceSettings::MediaStreamDeviceSettings(
: requester_(requester),
use_fake_ui_(false) {
DCHECK(requester_);
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
}
MediaStreamDeviceSettings::~MediaStreamDeviceSettings() {
diff --git a/content/browser/renderer_host/media/media_stream_dispatcher_host.cc b/content/browser/renderer_host/media/media_stream_dispatcher_host.cc
index 7ae8e2d..27a628f 100644
--- a/content/browser/renderer_host/media/media_stream_dispatcher_host.cc
+++ b/content/browser/renderer_host/media/media_stream_dispatcher_host.cc
@@ -4,10 +4,12 @@
#include "content/browser/renderer_host/media/media_stream_dispatcher_host.h"
+#include "content/browser/browser_main_loop.h"
#include "content/common/media/media_stream_messages.h"
#include "content/common/media/media_stream_options.h"
#include "googleurl/src/gurl.h"
+using content::BrowserMainLoop;
using content::BrowserMessageFilter;
using content::BrowserThread;
@@ -24,13 +26,8 @@ struct MediaStreamDispatcherHost::StreamRequest {
int page_request_id;
};
-MediaStreamDispatcherHost::MediaStreamDispatcherHost(
- content::ResourceContext* resource_context,
- int render_process_id,
- media::AudioManager* audio_manager)
- : resource_context_(resource_context),
- render_process_id_(render_process_id),
- audio_manager_(audio_manager) {
+MediaStreamDispatcherHost::MediaStreamDispatcherHost(int render_process_id)
+ : render_process_id_(render_process_id) {
}
void MediaStreamDispatcherHost::StreamGenerated(
@@ -178,12 +175,12 @@ void MediaStreamDispatcherHost::OnChannelClosing() {
// Since the IPC channel is gone, cancel pending requests and close all
// requested VideoCaptureDevices.
- manager()->CancelRequests(this);
+ GetManager()->CancelRequests(this);
for (StreamMap::iterator it = streams_.begin();
it != streams_.end();
it++) {
std::string label = it->first;
- manager()->StopGeneratedStream(label);
+ GetManager()->StopGeneratedStream(label);
}
}
@@ -203,7 +200,7 @@ void MediaStreamDispatcherHost::OnGenerateStream(
<< security_origin.spec() << ")";
std::string label;
- manager()->GenerateStream(this, render_process_id_, render_view_id,
+ GetManager()->GenerateStream(this, render_process_id_, render_view_id,
components, security_origin, &label);
DCHECK(!label.empty());
streams_[label] = StreamRequest(render_view_id, page_request_id);
@@ -218,7 +215,7 @@ void MediaStreamDispatcherHost::OnCancelGenerateStream(int render_view_id,
for (StreamMap::iterator it = streams_.begin(); it != streams_.end(); ++it) {
if (it->second.render_view_id == render_view_id &&
it->second.page_request_id == page_request_id) {
- manager()->CancelGenerateStream(it->first);
+ GetManager()->CancelGenerateStream(it->first);
}
}
}
@@ -230,7 +227,7 @@ void MediaStreamDispatcherHost::OnStopGeneratedStream(
StreamMap::iterator it = streams_.find(label);
DCHECK(it != streams_.end());
- manager()->StopGeneratedStream(label);
+ GetManager()->StopGeneratedStream(label);
streams_.erase(it);
}
@@ -246,7 +243,7 @@ void MediaStreamDispatcherHost::OnEnumerateDevices(
<< security_origin.spec() << ")";
std::string label;
- manager()->EnumerateDevices(this, render_process_id_, render_view_id,
+ GetManager()->EnumerateDevices(this, render_process_id_, render_view_id,
type, security_origin, &label);
DCHECK(!label.empty());
streams_[label] = StreamRequest(render_view_id, page_request_id);
@@ -266,15 +263,14 @@ void MediaStreamDispatcherHost::OnOpenDevice(
<< security_origin.spec() << ")";
std::string label;
- manager()->OpenDevice(this, render_process_id_, render_view_id,
+ GetManager()->OpenDevice(this, render_process_id_, render_view_id,
device_id, type, security_origin, &label);
DCHECK(!label.empty());
streams_[label] = StreamRequest(render_view_id, page_request_id);
}
-MediaStreamManager* MediaStreamDispatcherHost::manager() {
- return MediaStreamManager::GetForResourceContext(
- resource_context_, audio_manager_);
+MediaStreamManager* MediaStreamDispatcherHost::GetManager() {
+ return BrowserMainLoop::GetMediaStreamManager();
}
} // namespace media_stream
diff --git a/content/browser/renderer_host/media/media_stream_dispatcher_host.h b/content/browser/renderer_host/media/media_stream_dispatcher_host.h
index 4218d7c..8ed45a0 100644
--- a/content/browser/renderer_host/media/media_stream_dispatcher_host.h
+++ b/content/browser/renderer_host/media/media_stream_dispatcher_host.h
@@ -15,10 +15,6 @@
#include "content/common/media/media_stream_options.h"
#include "content/public/browser/browser_message_filter.h"
-namespace content {
-class ResourceContext;
-} // namespace content
-
namespace media_stream {
// MediaStreamDispatcherHost is a delegate for Media Stream API messages used by
@@ -28,9 +24,7 @@ class CONTENT_EXPORT MediaStreamDispatcherHost
: public content::BrowserMessageFilter,
public MediaStreamRequester {
public:
- MediaStreamDispatcherHost(content::ResourceContext* resource_context,
- int render_process_id,
- media::AudioManager* audio_manager);
+ explicit MediaStreamDispatcherHost(int render_process_id);
// MediaStreamRequester implementation.
virtual void StreamGenerated(
@@ -78,12 +72,11 @@ class CONTENT_EXPORT MediaStreamDispatcherHost
const GURL& security_origin);
// Returns the media stream manager to forward events to,
- // creating one if needed.
- MediaStreamManager* manager();
+ // creating one if needed. It is a virtual function so that the unit tests
+ // can inject their own MediaStreamManager.
+ virtual MediaStreamManager* GetManager();
- content::ResourceContext* resource_context_;
int render_process_id_;
- media::AudioManager* audio_manager_;
struct StreamRequest;
typedef std::map<std::string, StreamRequest> StreamMap;
diff --git a/content/browser/renderer_host/media/media_stream_dispatcher_host_unittest.cc b/content/browser/renderer_host/media/media_stream_dispatcher_host_unittest.cc
index 0539bb8..8c6d1b0 100644
--- a/content/browser/renderer_host/media/media_stream_dispatcher_host_unittest.cc
+++ b/content/browser/renderer_host/media/media_stream_dispatcher_host_unittest.cc
@@ -7,6 +7,7 @@
#include "base/bind.h"
#include "base/message_loop.h"
#include "content/browser/browser_thread_impl.h"
+#include "content/browser/renderer_host/media/audio_input_device_manager.h"
#include "content/browser/renderer_host/media/media_stream_dispatcher_host.h"
#include "content/browser/renderer_host/media/media_stream_manager.h"
#include "content/browser/renderer_host/media/mock_media_observer.h"
@@ -39,11 +40,11 @@ namespace media_stream {
class MockMediaStreamDispatcherHost : public MediaStreamDispatcherHost,
public content::TestContentBrowserClient {
public:
- MockMediaStreamDispatcherHost(content::ResourceContext* resource_context,
- MessageLoop* message_loop,
- media::AudioManager* audio_manager)
- : MediaStreamDispatcherHost(resource_context, kProcessId, audio_manager),
- message_loop_(message_loop) {}
+ MockMediaStreamDispatcherHost(MessageLoop* message_loop,
+ MediaStreamManager* manager)
+ : MediaStreamDispatcherHost(kProcessId),
+ message_loop_(message_loop),
+ manager_(manager) {}
// A list of mock methods.
MOCK_METHOD4(OnStreamGenerated,
@@ -80,7 +81,7 @@ class MockMediaStreamDispatcherHost : public MediaStreamDispatcherHost,
// This method is used to dispatch IPC messages to the renderer. We intercept
// these messages here and dispatch to our mock methods to verify the
// conversation between this object and the renderer.
- virtual bool Send(IPC::Message* message) {
+ virtual bool Send(IPC::Message* message) OVERRIDE {
CHECK(message);
// In this method we dispatch the messages to the according handlers as if
@@ -102,6 +103,11 @@ class MockMediaStreamDispatcherHost : public MediaStreamDispatcherHost,
return true;
}
+ // Use our own MediaStreamManager.
+ virtual MediaStreamManager* GetManager() OVERRIDE {
+ return manager_;
+ }
+
// These handler methods do minimal things and delegate to the mock methods.
void OnStreamGenerated(
const IPC::Message& msg,
@@ -141,38 +147,43 @@ class MockMediaStreamDispatcherHost : public MediaStreamDispatcherHost,
}
MessageLoop* message_loop_;
+ MediaStreamManager* manager_;
};
class MediaStreamDispatcherHostTest : public testing::Test {
public:
MediaStreamDispatcherHostTest() : old_client_(NULL),
old_browser_client_(NULL) {}
+ virtual ~MediaStreamDispatcherHostTest() {}
void WaitForResult() {
message_loop_->Run();
}
protected:
- virtual void SetUp() {
- message_loop_.reset(new MessageLoop(MessageLoop::TYPE_IO));
- // ResourceContext must be created on UI thread.
- ui_thread_.reset(new BrowserThreadImpl(BrowserThread::UI,
- message_loop_.get()));
+ virtual void SetUp() OVERRIDE {
// MediaStreamManager must be created and called on IO thread.
+ message_loop_.reset(new MessageLoop(MessageLoop::TYPE_IO));
io_thread_.reset(new BrowserThreadImpl(BrowserThread::IO,
message_loop_.get()));
- audio_manager_.reset(media::AudioManager::Create());
-
// Create our own media observer.
media_observer_.reset(new MockMediaObserver());
+ // Create our own MediaStreamManager.
+ audio_manager_.reset(media::AudioManager::Create());
+ scoped_refptr<media_stream::AudioInputDeviceManager>
+ audio_input_device_manager(
+ new media_stream::AudioInputDeviceManager(audio_manager_.get()));
+ scoped_refptr<media_stream::VideoCaptureManager> video_capture_manager(
+ new media_stream::VideoCaptureManager());
+ media_stream_manager_.reset(new media_stream::MediaStreamManager(
+ audio_input_device_manager, video_capture_manager));
// Make sure we use fake devices to avoid long delays.
- MediaStreamManager::GetForResourceContext(
- &resource_context_, audio_manager_.get())->UseFakeDevice();
+ media_stream_manager_->UseFakeDevice();
- host_ = new MockMediaStreamDispatcherHost(
- &resource_context_, message_loop_.get(), audio_manager_.get());
+ host_ = new MockMediaStreamDispatcherHost(message_loop_.get(),
+ media_stream_manager_.get());
// Use the fake content client and browser.
old_client_ = content::GetContentClient();
@@ -182,9 +193,8 @@ class MediaStreamDispatcherHostTest : public testing::Test {
content_client_->set_browser_for_testing(host_);
}
- virtual void TearDown() {
- // Needed to make sure the manager finishes all tasks on its own thread.
- SyncWithVideoCaptureManagerThread();
+ virtual void TearDown() OVERRIDE {
+ message_loop_->RunAllPending();
// Recover the old browser client and content client.
content::GetContentClient()->set_browser_for_testing(old_browser_client_);
@@ -192,41 +202,11 @@ class MediaStreamDispatcherHostTest : public testing::Test {
content_client_.reset();
}
- // Called on the VideoCaptureManager thread.
- static void PostQuitMessageLoop(MessageLoop* message_loop) {
- message_loop->PostTask(FROM_HERE, MessageLoop::QuitClosure());
- }
-
- // Called on the main thread.
- static void PostQuitOnVideoCaptureManagerThread(
- MessageLoop* message_loop,
- media_stream::MediaStreamManager* media_stream_manager) {
- media_stream_manager->video_capture_manager()->GetMessageLoop()->
- PostTask(FROM_HERE,
- base::Bind(&PostQuitMessageLoop, message_loop));
- }
-
- // SyncWithVideoCaptureManagerThread() waits until all pending tasks on the
- // video_capture_manager thread are executed while also processing pending
- // task in message_loop_ on the current thread. It is used to synchronize
- // with the video capture manager thread when we are stopping a video
- // capture device.
- void SyncWithVideoCaptureManagerThread() {
- message_loop_->PostTask(
- FROM_HERE,
- base::Bind(&PostQuitOnVideoCaptureManagerThread,
- message_loop_.get(),
- MediaStreamManager::GetForResourceContext(
- &resource_context_, audio_manager_.get())));
- message_loop_->Run();
- }
-
scoped_refptr<MockMediaStreamDispatcherHost> host_;
scoped_ptr<MessageLoop> message_loop_;
- scoped_ptr<BrowserThreadImpl> ui_thread_;
scoped_ptr<BrowserThreadImpl> io_thread_;
scoped_ptr<media::AudioManager> audio_manager_;
- content::MockResourceContext resource_context_;
+ scoped_ptr<MediaStreamManager> media_stream_manager_;
content::ContentClient* old_client_;
content::ContentBrowserClient* old_browser_client_;
scoped_ptr<content::ContentClient> content_client_;
@@ -346,9 +326,7 @@ TEST_F(MediaStreamDispatcherHostTest, FailDevice) {
EXPECT_CALL(*host_, OnVideoDeviceFailed(kRenderId, 0));
int session_id = host_->video_devices_[0].session_id;
- MediaStreamManager::GetForResourceContext(
- &resource_context_, audio_manager_.get())->
- video_capture_manager()->Error(session_id);
+ media_stream_manager_->video_capture_manager()->Error(session_id);
WaitForResult();
EXPECT_EQ(host_->video_devices_.size(), 0u);
EXPECT_EQ(host_->NumberOfStreams(), 1u);
diff --git a/content/browser/renderer_host/media/media_stream_manager.cc b/content/browser/renderer_host/media/media_stream_manager.cc
index d6b2e60..3f5a804 100644
--- a/content/browser/renderer_host/media/media_stream_manager.cc
+++ b/content/browser/renderer_host/media/media_stream_manager.cc
@@ -14,18 +14,14 @@
#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/browser/resource_context_impl.h"
#include "content/common/media/media_stream_options.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/content_browser_client.h"
#include "content/public/browser/media_observer.h"
#include "googleurl/src/gurl.h"
-#include "media/audio/audio_manager.h"
using content::BrowserThread;
-static const char* kMediaStreamManagerKeyName = "content_media_stream_manager";
-
namespace media_stream {
// Creates a random label used to identify requests.
@@ -116,50 +112,36 @@ struct MediaStreamManager::DeviceRequest {
StreamDeviceInfoArray video_devices;
};
-// static
-MediaStreamManager* MediaStreamManager::GetForResourceContext(
- content::ResourceContext* resource_context,
- media::AudioManager* audio_manager) {
- MediaStreamManager* rv = static_cast<MediaStreamManager*>(
- resource_context->GetUserData(kMediaStreamManagerKeyName));
- if (!rv) {
- rv = new MediaStreamManager(audio_manager);
- resource_context->SetUserData(kMediaStreamManagerKeyName, rv);
- }
- return rv;
-}
-
-MediaStreamManager::MediaStreamManager(media::AudioManager* audio_manager)
+MediaStreamManager::MediaStreamManager(
+ AudioInputDeviceManager* audio_input_device_manager,
+ VideoCaptureManager* video_capture_manager)
: ALLOW_THIS_IN_INITIALIZER_LIST(
device_settings_(new MediaStreamDeviceSettings(this))),
- enumeration_in_progress_(content::NUM_MEDIA_STREAM_DEVICE_TYPES, false),
- audio_manager_(audio_manager) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ audio_input_device_manager_(audio_input_device_manager),
+ video_capture_manager_(video_capture_manager),
+ enumeration_in_progress_(content::NUM_MEDIA_STREAM_DEVICE_TYPES, false) {
}
MediaStreamManager::~MediaStreamManager() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
- if (video_capture_manager_.get())
+ if (device_thread_.get()) {
video_capture_manager_->Unregister();
- if (audio_input_device_manager_.get())
audio_input_device_manager_->Unregister();
+ device_thread_->Stop();
+ }
}
VideoCaptureManager* MediaStreamManager::video_capture_manager() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
- if (!video_capture_manager_.get()) {
- video_capture_manager_ = new VideoCaptureManager();
- video_capture_manager_->Register(this);
- }
+ DCHECK(video_capture_manager_.get());
+ EnsureDeviceThreadAndListener();
return video_capture_manager_.get();
}
AudioInputDeviceManager* MediaStreamManager::audio_input_device_manager() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
- if (!audio_input_device_manager_.get()) {
- audio_input_device_manager_ = new AudioInputDeviceManager(audio_manager_);
- audio_input_device_manager_->Register(this);
- }
+ DCHECK(audio_input_device_manager_.get());
+ EnsureDeviceThreadAndListener();
return audio_input_device_manager_.get();
}
@@ -367,6 +349,19 @@ void MediaStreamManager::StartEnumeration(
(*label) = request_label;
}
+void MediaStreamManager::EnsureDeviceThreadAndListener() {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ if (device_thread_.get())
+ return;
+
+ device_thread_.reset(new DeviceThread("MediaStreamDeviceThread"));
+ CHECK(device_thread_->Start());
+
+ audio_input_device_manager_->Register(this,
+ device_thread_->message_loop_proxy());
+ video_capture_manager_->Register(this, device_thread_->message_loop_proxy());
+}
+
void MediaStreamManager::Opened(MediaStreamType stream_type,
int capture_session_id) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
diff --git a/content/browser/renderer_host/media/media_stream_manager.h b/content/browser/renderer_host/media/media_stream_manager.h
index 17f863e..3082ac0 100644
--- a/content/browser/renderer_host/media/media_stream_manager.h
+++ b/content/browser/renderer_host/media/media_stream_manager.h
@@ -29,19 +29,15 @@
#include "base/basictypes.h"
#include "base/memory/scoped_ptr.h"
#include "base/memory/ref_counted.h"
-#include "base/supports_user_data.h"
+#include "base/threading/thread.h"
+#include "base/win/scoped_com_initializer.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"
#include "content/common/content_export.h"
+#include "content/public/browser/browser_thread.h"
-namespace content {
-class ResourceContext;
-}
-
-namespace media {
-class AudioManager;
-}
+using base::win::ScopedCOMInitializer;
namespace media_stream {
@@ -50,22 +46,31 @@ class MediaStreamDeviceSettings;
class MediaStreamRequester;
class VideoCaptureManager;
+// Thread that enters MTA on windows, and is base::Thread on linux and mac.
+class DeviceThread : public base::Thread {
+ public:
+ explicit DeviceThread(const char* name)
+ : base::Thread(name),
+ com_init_(ScopedCOMInitializer::kMTA) {}
+
+ private:
+ ScopedCOMInitializer com_init_;
+ DISALLOW_COPY_AND_ASSIGN(DeviceThread);
+};
+
// 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 CONTENT_EXPORT MediaStreamManager
: public MediaStreamProviderListener,
- public SettingsRequester,
- public base::SupportsUserData::Data {
+ public SettingsRequester {
public:
- // Returns the MediaStreamManager for the given ResourceContext. If it hasn't
- // been created yet, it will be constructed with the given AudioManager.
- static MediaStreamManager* GetForResourceContext(
- content::ResourceContext* resource_context,
- media::AudioManager* audio_manager);
+ // This class takes the ownerships of the |audio_input_device_manager|
+ // and |video_capture_manager|.
+ MediaStreamManager(AudioInputDeviceManager* audio_input_device_manager,
+ VideoCaptureManager* video_capture_manager);
- explicit MediaStreamManager(media::AudioManager* audio_manager);
virtual ~MediaStreamManager();
// Used to access VideoCaptureManager.
@@ -130,6 +135,8 @@ class CONTENT_EXPORT MediaStreamManager
// Used by unit test to make sure fake devices are used instead of a real
// devices, which is needed for server based testing.
+ // TODO(xians): Remove this hack since we can create our own
+ // MediaStreamManager in our unit tests.
void UseFakeDevice();
private:
@@ -149,9 +156,16 @@ class CONTENT_EXPORT MediaStreamManager
void StartEnumeration(DeviceRequest* new_request,
std::string* label);
+ // Helper to ensure the device thread and pass the message loop to device
+ // managers, it also register itself as the listener to the device managers.
+ void EnsureDeviceThreadAndListener();
+
+ // Device thread shared by VideoCaptureManager and AudioInputDeviceManager.
+ scoped_ptr<base::Thread> device_thread_;
+
scoped_ptr<MediaStreamDeviceSettings> device_settings_;
- scoped_refptr<VideoCaptureManager> video_capture_manager_;
scoped_refptr<AudioInputDeviceManager> audio_input_device_manager_;
+ scoped_refptr<VideoCaptureManager> video_capture_manager_;
// Keeps track of device types currently being enumerated to not enumerate
// when not necessary.
@@ -160,7 +174,6 @@ class CONTENT_EXPORT MediaStreamManager
// All non-closed request.
typedef std::map<std::string, DeviceRequest> DeviceRequests;
DeviceRequests requests_;
- media::AudioManager* audio_manager_;
DISALLOW_COPY_AND_ASSIGN(MediaStreamManager);
};
diff --git a/content/browser/renderer_host/media/media_stream_provider.h b/content/browser/renderer_host/media/media_stream_provider.h
index cab027a..6218b2e 100644
--- a/content/browser/renderer_host/media/media_stream_provider.h
+++ b/content/browser/renderer_host/media/media_stream_provider.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// 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.
@@ -18,6 +18,10 @@
#include "content/common/content_export.h"
#include "content/common/media/media_stream_options.h"
+namespace base {
+class MessageLoopProxy;
+}
+
namespace media_stream {
enum MediaStreamProviderError {
@@ -59,8 +63,9 @@ class CONTENT_EXPORT MediaStreamProviderListener {
// Implemented by a manager class providing captured media.
class CONTENT_EXPORT MediaStreamProvider {
public:
- // Registers a listener, only one listener is allowed.
- virtual void Register(MediaStreamProviderListener* listener) = 0;
+ // Registers a listener and a device message loop.
+ virtual void Register(MediaStreamProviderListener* listener,
+ base::MessageLoopProxy* device_thread_loop) = 0;
// Unregisters the previously registered listener.
virtual void Unregister() = 0;
diff --git a/content/browser/renderer_host/media/video_capture_controller_unittest.cc b/content/browser/renderer_host/media/video_capture_controller_unittest.cc
index 47c0c29..449d4c4 100644
--- a/content/browser/renderer_host/media/video_capture_controller_unittest.cc
+++ b/content/browser/renderer_host/media/video_capture_controller_unittest.cc
@@ -151,7 +151,7 @@ class VideoCaptureControllerTest : public testing::Test {
virtual ~VideoCaptureControllerTest() {}
protected:
- virtual void SetUp() {
+ virtual void SetUp() OVERRIDE {
message_loop_.reset(new MessageLoop(MessageLoop::TYPE_IO));
file_thread_.reset(new BrowserThreadImpl(BrowserThread::FILE,
message_loop_.get()));
@@ -166,8 +166,7 @@ class VideoCaptureControllerTest : public testing::Test {
message_loop_.get()));
}
- virtual void TearDown() {
- }
+ virtual void TearDown() OVERRIDE {}
scoped_ptr<MessageLoop> message_loop_;
scoped_ptr<BrowserThreadImpl> file_thread_;
diff --git a/content/browser/renderer_host/media/video_capture_host.cc b/content/browser/renderer_host/media/video_capture_host.cc
index 97da80d..4bf69f1 100644
--- a/content/browser/renderer_host/media/video_capture_host.cc
+++ b/content/browser/renderer_host/media/video_capture_host.cc
@@ -7,10 +7,12 @@
#include "base/bind.h"
#include "base/memory/scoped_ptr.h"
#include "base/stl_util.h"
+#include "content/browser/browser_main_loop.h"
#include "content/browser/renderer_host/media/media_stream_manager.h"
#include "content/browser/renderer_host/media/video_capture_manager.h"
#include "content/common/media/video_capture_messages.h"
+using content::BrowserMainLoop;
using content::BrowserMessageFilter;
using content::BrowserThread;
@@ -23,11 +25,7 @@ struct VideoCaptureHost::Entry {
scoped_refptr<VideoCaptureController> controller;
};
-VideoCaptureHost::VideoCaptureHost(content::ResourceContext* resource_context,
- media::AudioManager* audio_manager)
- : resource_context_(resource_context),
- audio_manager_(audio_manager) {
-}
+VideoCaptureHost::VideoCaptureHost() {}
VideoCaptureHost::~VideoCaptureHost() {}
@@ -281,6 +279,5 @@ void VideoCaptureHost::DeleteVideoCaptureControllerOnIOThread(
media_stream::VideoCaptureManager* VideoCaptureHost::GetVideoCaptureManager() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
- return media_stream::MediaStreamManager::GetForResourceContext(
- resource_context_, audio_manager_)->video_capture_manager();
+ return BrowserMainLoop::GetMediaStreamManager()->video_capture_manager();
}
diff --git a/content/browser/renderer_host/media/video_capture_host.h b/content/browser/renderer_host/media/video_capture_host.h
index a66f475..dbb8cbe 100644
--- a/content/browser/renderer_host/media/video_capture_host.h
+++ b/content/browser/renderer_host/media/video_capture_host.h
@@ -45,20 +45,11 @@
#include "content/public/browser/browser_message_filter.h"
#include "ipc/ipc_message.h"
-namespace content {
-class ResourceContext;
-} // namespace content
-
-namespace media {
-class AudioManager;
-}
-
class CONTENT_EXPORT VideoCaptureHost
: public content::BrowserMessageFilter,
public VideoCaptureControllerEventHandler {
public:
- explicit VideoCaptureHost(content::ResourceContext* resource_context,
- media::AudioManager* audio_manager);
+ VideoCaptureHost();
// content::BrowserMessageFilter implementation.
virtual void OnChannelClosing() OVERRIDE;
@@ -140,18 +131,15 @@ class CONTENT_EXPORT VideoCaptureHost
void DeleteVideoCaptureControllerOnIOThread(
const VideoCaptureControllerID& controller_id);
- // Helpers.
- media_stream::VideoCaptureManager* GetVideoCaptureManager();
+ // Returns the video capture manager. This is a virtual function so that
+ // the unit tests can inject their own MediaStreamManager.
+ virtual media_stream::VideoCaptureManager* GetVideoCaptureManager();
struct Entry;
typedef std::map<VideoCaptureControllerID, Entry*> EntryMap;
// A map of VideoCaptureControllerID to its state and VideoCaptureController.
EntryMap entries_;
- // Used to get a pointer to VideoCaptureManager to start/stop capture devices.
- content::ResourceContext* resource_context_;
- media::AudioManager* audio_manager_;
-
DISALLOW_COPY_AND_ASSIGN(VideoCaptureHost);
};
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 f7f31e6..4aca90b 100644
--- a/content/browser/renderer_host/media/video_capture_host_unittest.cc
+++ b/content/browser/renderer_host/media/video_capture_host_unittest.cc
@@ -13,6 +13,7 @@
#include "base/stl_util.h"
#include "base/stringprintf.h"
#include "content/browser/browser_thread_impl.h"
+#include "content/browser/renderer_host/media/audio_input_device_manager.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"
@@ -71,11 +72,11 @@ class DumpVideo {
class MockVideoCaptureHost : public VideoCaptureHost {
public:
- MockVideoCaptureHost(content::ResourceContext* resource_context,
- media::AudioManager* audio_manager)
- : VideoCaptureHost(resource_context, audio_manager),
+ MockVideoCaptureHost(media_stream::MediaStreamManager* manager)
+ : VideoCaptureHost(),
return_buffers_(false),
- dump_video_(false) {}
+ dump_video_(false),
+ manager_(manager) {}
// A list of mock methods.
MOCK_METHOD4(OnNewBufferCreated,
@@ -125,7 +126,7 @@ class MockVideoCaptureHost : public VideoCaptureHost {
// This method is used to dispatch IPC messages to the renderer. We intercept
// these messages here and dispatch to our mock methods to verify the
// conversation between this object and the renderer.
- virtual bool Send(IPC::Message* message) {
+ virtual bool Send(IPC::Message* message) OVERRIDE {
CHECK(message);
// In this method we dispatch the messages to the according handlers as if
@@ -144,6 +145,10 @@ class MockVideoCaptureHost : public VideoCaptureHost {
return true;
}
+ virtual media_stream::VideoCaptureManager* GetVideoCaptureManager() OVERRIDE {
+ return manager_->video_capture_manager();
+ }
+
// These handler methods do minimal things and delegate to the mock methods.
void OnNewBufferCreatedDispatch(int device_id,
base::SharedMemoryHandle handle,
@@ -185,6 +190,7 @@ class MockVideoCaptureHost : public VideoCaptureHost {
bool return_buffers_;
bool dump_video_;
DumpVideo dumper_;
+ media_stream::MediaStreamManager* manager_;
};
ACTION_P(ExitMessageLoop, message_loop) {
@@ -196,32 +202,35 @@ class VideoCaptureHostTest : public testing::Test {
VideoCaptureHostTest() {}
protected:
- virtual void SetUp() {
+ virtual void SetUp() OVERRIDE {
// Create a message loop so VideoCaptureHostTest can use it.
message_loop_.reset(new MessageLoop(MessageLoop::TYPE_IO));
- // ResourceContext must be created on the UI thread.
- ui_thread_.reset(new BrowserThreadImpl(BrowserThread::UI,
- message_loop_.get()));
-
// MediaStreamManager must be created on the IO thread.
io_thread_.reset(new BrowserThreadImpl(BrowserThread::IO,
message_loop_.get()));
+ // Create our own MediaStreamManager.
audio_manager_.reset(media::AudioManager::Create());
+ scoped_refptr<media_stream::AudioInputDeviceManager>
+ audio_input_device_manager(
+ new media_stream::AudioInputDeviceManager(audio_manager_.get()));
+ scoped_refptr<media_stream::VideoCaptureManager> video_capture_manager(
+ new media_stream::VideoCaptureManager());
+ media_stream_manager_.reset(new media_stream::MediaStreamManager(
+ audio_input_device_manager, video_capture_manager));
#ifndef TEST_REAL_CAPTURE_DEVICE
- media_stream::MediaStreamManager::GetForResourceContext(
- &resource_context_, audio_manager_.get())->UseFakeDevice();
+ media_stream_manager_->UseFakeDevice();
#endif
- host_ = new MockVideoCaptureHost(&resource_context_, audio_manager_.get());
+ host_ = new MockVideoCaptureHost(media_stream_manager_.get());
// Simulate IPC channel connected.
host_->OnChannelConnected(base::GetCurrentProcId());
}
- virtual void TearDown() {
+ virtual void TearDown() OVERRIDE {
// Verifies and removes the expectations on host_ and
// returns true iff successful.
Mock::VerifyAndClearExpectations(host_);
@@ -238,36 +247,7 @@ class VideoCaptureHostTest : public testing::Test {
host_ = NULL;
// We need to continue running message_loop_ to complete all destructions.
- SyncWithVideoCaptureManagerThread();
- }
-
- // Called on the VideoCaptureManager thread.
- static void PostQuitMessageLoop(MessageLoop* message_loop) {
- message_loop->PostTask(FROM_HERE, MessageLoop::QuitClosure());
- }
-
- // Called on the main thread.
- static void PostQuitOnVideoCaptureManagerThread(
- MessageLoop* message_loop, content::ResourceContext* resource_context,
- media:: AudioManager* audio_manager) {
- media_stream::MediaStreamManager* manager =
- media_stream::MediaStreamManager::GetForResourceContext(
- resource_context, audio_manager);
- manager->video_capture_manager()->GetMessageLoop()->PostTask(
- FROM_HERE, base::Bind(&PostQuitMessageLoop, message_loop));
- }
-
- // SyncWithVideoCaptureManagerThread() waits until all pending tasks on the
- // video_capture_manager thread are executed while also processing pending
- // task in message_loop_ on the current thread. It is used to synchronize
- // with the video capture manager thread when we are stopping a video
- // capture device.
- void SyncWithVideoCaptureManagerThread() {
- message_loop_->PostTask(
- FROM_HERE,
- base::Bind(&PostQuitOnVideoCaptureManagerThread, message_loop_.get(),
- &resource_context_, audio_manager_.get()));
- message_loop_->Run();
+ message_loop_->RunAllPending();
}
void StartCapture() {
@@ -325,13 +305,14 @@ class VideoCaptureHostTest : public testing::Test {
void StopCapture() {
EXPECT_CALL(*host_, OnStateChanged(kDeviceId,
video_capture::kStopped))
- .Times(AtLeast(1));
+ .WillOnce(ExitMessageLoop(message_loop_.get()));
host_->OnStopCapture(kDeviceId);
host_->SetReturnReceviedDibs(true);
host_->ReturnReceivedDibs(kDeviceId);
- SyncWithVideoCaptureManagerThread();
+ message_loop_->Run();
+
host_->SetReturnReceviedDibs(false);
// Expect the VideoCaptureDevice has been stopped
EXPECT_EQ(0u, host_->entries_.size());
@@ -356,17 +337,17 @@ class VideoCaptureHostTest : public testing::Test {
.Times(1);
VideoCaptureControllerID id(kDeviceId);
host_->OnError(id);
- SyncWithVideoCaptureManagerThread();
+ // Wait for the error callback.
+ message_loop_->RunAllPending();
}
scoped_refptr<MockVideoCaptureHost> host_;
private:
scoped_ptr<MessageLoop> message_loop_;
- scoped_ptr<BrowserThreadImpl> ui_thread_;
scoped_ptr<BrowserThreadImpl> io_thread_;
scoped_ptr<media::AudioManager> audio_manager_;
- content::MockResourceContext resource_context_;
+ scoped_ptr<media_stream::MediaStreamManager> media_stream_manager_;
DISALLOW_COPY_AND_ASSIGN(VideoCaptureHostTest);
};
diff --git a/content/browser/renderer_host/media/video_capture_manager.cc b/content/browser/renderer_host/media/video_capture_manager.cc
index be5738d..3786efa 100644
--- a/content/browser/renderer_host/media/video_capture_manager.cc
+++ b/content/browser/renderer_host/media/video_capture_manager.cc
@@ -39,23 +39,23 @@ struct VideoCaptureManager::Controller {
};
VideoCaptureManager::VideoCaptureManager()
- : vc_device_thread_("VideoCaptureManagerThread"),
- listener_(NULL),
- new_capture_session_id_(kFirstSessionId),
- use_fake_device_(false) {
- vc_device_thread_.Start();
+ : listener_(NULL),
+ new_capture_session_id_(kFirstSessionId),
+ use_fake_device_(false) {
}
VideoCaptureManager::~VideoCaptureManager() {
- vc_device_thread_.Stop();
DCHECK(devices_.empty());
DCHECK(controllers_.empty());
}
-void VideoCaptureManager::Register(MediaStreamProviderListener* listener) {
+void VideoCaptureManager::Register(MediaStreamProviderListener* listener,
+ base::MessageLoopProxy* device_thread_loop) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
DCHECK(!listener_);
+ DCHECK(!device_loop_);
listener_ = listener;
+ device_loop_ = device_thread_loop;
}
void VideoCaptureManager::Unregister() {
@@ -67,8 +67,7 @@ void VideoCaptureManager::Unregister() {
void VideoCaptureManager::EnumerateDevices() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
DCHECK(listener_);
-
- vc_device_thread_.message_loop()->PostTask(
+ device_loop_->PostTask(
FROM_HERE,
base::Bind(&VideoCaptureManager::OnEnumerateDevices, this));
}
@@ -80,7 +79,7 @@ int VideoCaptureManager::Open(const StreamDeviceInfo& device) {
// Generate a new id for this device.
int video_capture_session_id = new_capture_session_id_++;
- vc_device_thread_.message_loop()->PostTask(
+ device_loop_->PostTask(
FROM_HERE,
base::Bind(&VideoCaptureManager::OnOpen, this, video_capture_session_id,
device));
@@ -91,8 +90,7 @@ int VideoCaptureManager::Open(const StreamDeviceInfo& device) {
void VideoCaptureManager::Close(int capture_session_id) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
DCHECK(listener_);
-
- vc_device_thread_.message_loop()->PostTask(
+ device_loop_->PostTask(
FROM_HERE,
base::Bind(&VideoCaptureManager::OnClose, this, capture_session_id));
}
@@ -101,8 +99,7 @@ void VideoCaptureManager::Start(
const media::VideoCaptureParams& capture_params,
media::VideoCaptureDevice::EventHandler* video_capture_receiver) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
-
- vc_device_thread_.message_loop()->PostTask(
+ device_loop_->PostTask(
FROM_HERE,
base::Bind(&VideoCaptureManager::OnStart, this, capture_params,
video_capture_receiver));
@@ -112,8 +109,7 @@ void VideoCaptureManager::Stop(
const media::VideoCaptureSessionId& capture_session_id,
base::Closure stopped_cb) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
-
- vc_device_thread_.message_loop()->PostTask(
+ device_loop_->PostTask(
FROM_HERE,
base::Bind(&VideoCaptureManager::OnStop, this, capture_session_id,
stopped_cb));
@@ -128,12 +124,8 @@ void VideoCaptureManager::UseFakeDevice() {
use_fake_device_ = true;
}
-MessageLoop* VideoCaptureManager::GetMessageLoop() {
- return vc_device_thread_.message_loop();
-}
-
void VideoCaptureManager::OnEnumerateDevices() {
- DCHECK(IsOnCaptureDeviceThread());
+ DCHECK(IsOnDeviceThread());
media::VideoCaptureDevice::Names device_names;
GetAvailableDevices(&device_names);
@@ -152,7 +144,7 @@ void VideoCaptureManager::OnEnumerateDevices() {
void VideoCaptureManager::OnOpen(int capture_session_id,
const StreamDeviceInfo& device) {
- DCHECK(IsOnCaptureDeviceThread());
+ DCHECK(IsOnDeviceThread());
DCHECK(devices_.find(capture_session_id) == devices_.end());
DVLOG(1) << "VideoCaptureManager::OnOpen, id " << capture_session_id;
@@ -186,7 +178,7 @@ void VideoCaptureManager::OnOpen(int capture_session_id,
}
void VideoCaptureManager::OnClose(int capture_session_id) {
- DCHECK(IsOnCaptureDeviceThread());
+ DCHECK(IsOnDeviceThread());
DVLOG(1) << "VideoCaptureManager::OnClose, id " << capture_session_id;
media::VideoCaptureDevice* video_capture_device = NULL;
@@ -222,7 +214,7 @@ void VideoCaptureManager::OnClose(int capture_session_id) {
void VideoCaptureManager::OnStart(
const media::VideoCaptureParams capture_params,
media::VideoCaptureDevice::EventHandler* video_capture_receiver) {
- DCHECK(IsOnCaptureDeviceThread());
+ DCHECK(IsOnDeviceThread());
DCHECK(video_capture_receiver != NULL);
DVLOG(1) << "VideoCaptureManager::OnStart, (" << capture_params.width
<< ", " << capture_params.height
@@ -253,7 +245,7 @@ void VideoCaptureManager::OnStart(
void VideoCaptureManager::OnStop(
const media::VideoCaptureSessionId capture_session_id,
base::Closure stopped_cb) {
- DCHECK(IsOnCaptureDeviceThread());
+ DCHECK(IsOnDeviceThread());
DVLOG(1) << "VideoCaptureManager::OnStop, id " << capture_session_id;
VideoCaptureDevices::iterator it = devices_.find(capture_session_id);
@@ -325,7 +317,7 @@ void VideoCaptureManager::OnError(int capture_session_id,
}
void VideoCaptureManager::PostOnOpened(int capture_session_id) {
- DCHECK(IsOnCaptureDeviceThread());
+ DCHECK(IsOnDeviceThread());
BrowserThread::PostTask(BrowserThread::IO,
FROM_HERE,
base::Bind(&VideoCaptureManager::OnOpened, this,
@@ -333,7 +325,7 @@ void VideoCaptureManager::PostOnOpened(int capture_session_id) {
}
void VideoCaptureManager::PostOnClosed(int capture_session_id) {
- DCHECK(IsOnCaptureDeviceThread());
+ DCHECK(IsOnDeviceThread());
BrowserThread::PostTask(BrowserThread::IO,
FROM_HERE,
base::Bind(&VideoCaptureManager::OnClosed, this,
@@ -342,7 +334,7 @@ void VideoCaptureManager::PostOnClosed(int capture_session_id) {
void VideoCaptureManager::PostOnDevicesEnumerated(
const StreamDeviceInfoArray& devices) {
- DCHECK(IsOnCaptureDeviceThread());
+ DCHECK(IsOnDeviceThread());
BrowserThread::PostTask(BrowserThread::IO,
FROM_HERE,
base::Bind(&VideoCaptureManager::OnDevicesEnumerated,
@@ -359,13 +351,13 @@ void VideoCaptureManager::PostOnError(int capture_session_id,
capture_session_id, error));
}
-bool VideoCaptureManager::IsOnCaptureDeviceThread() const {
- return MessageLoop::current() == vc_device_thread_.message_loop();
+bool VideoCaptureManager::IsOnDeviceThread() const {
+ return device_loop_->BelongsToCurrentThread();
}
void VideoCaptureManager::GetAvailableDevices(
media::VideoCaptureDevice::Names* device_names) {
- DCHECK(IsOnCaptureDeviceThread());
+ DCHECK(IsOnDeviceThread());
if (!use_fake_device_) {
media::VideoCaptureDevice::GetDeviceNames(device_names);
@@ -376,7 +368,7 @@ void VideoCaptureManager::GetAvailableDevices(
bool VideoCaptureManager::DeviceOpened(
const media::VideoCaptureDevice::Name& device_name) {
- DCHECK(IsOnCaptureDeviceThread());
+ DCHECK(IsOnDeviceThread());
for (VideoCaptureDevices::iterator it = devices_.begin();
it != devices_.end(); ++it) {
@@ -390,7 +382,7 @@ bool VideoCaptureManager::DeviceOpened(
media::VideoCaptureDevice* VideoCaptureManager::GetOpenedDevice(
const StreamDeviceInfo& device_info) {
- DCHECK(IsOnCaptureDeviceThread());
+ DCHECK(IsOnDeviceThread());
for (VideoCaptureDevices::iterator it = devices_.begin();
it != devices_.end(); it++) {
@@ -403,7 +395,7 @@ media::VideoCaptureDevice* VideoCaptureManager::GetOpenedDevice(
bool VideoCaptureManager::DeviceInUse(
const media::VideoCaptureDevice* video_capture_device) {
- DCHECK(IsOnCaptureDeviceThread());
+ DCHECK(IsOnDeviceThread());
for (VideoCaptureDevices::iterator it = devices_.begin();
it != devices_.end(); ++it) {
@@ -420,7 +412,7 @@ void VideoCaptureManager::AddController(
VideoCaptureControllerEventHandler* handler,
base::Callback<void(VideoCaptureController*)> added_cb) {
DCHECK(handler);
- vc_device_thread_.message_loop()->PostTask(
+ device_loop_->PostTask(
FROM_HERE,
base::Bind(&VideoCaptureManager::DoAddControllerOnDeviceThread,
this, capture_params, handler, added_cb));
@@ -430,7 +422,7 @@ void VideoCaptureManager::DoAddControllerOnDeviceThread(
const media::VideoCaptureParams capture_params,
VideoCaptureControllerEventHandler* handler,
base::Callback<void(VideoCaptureController*)> added_cb) {
- DCHECK(IsOnCaptureDeviceThread());
+ DCHECK(IsOnDeviceThread());
media::VideoCaptureDevice* video_capture_device =
GetDeviceInternal(capture_params.session_id);
@@ -452,7 +444,7 @@ void VideoCaptureManager::RemoveController(
VideoCaptureController* controller,
VideoCaptureControllerEventHandler* handler) {
DCHECK(handler);
- vc_device_thread_.message_loop()->PostTask(
+ device_loop_->PostTask(
FROM_HERE,
base::Bind(&VideoCaptureManager::DoRemoveControllerOnDeviceThread, this,
make_scoped_refptr(controller), handler));
@@ -461,7 +453,7 @@ void VideoCaptureManager::RemoveController(
void VideoCaptureManager::DoRemoveControllerOnDeviceThread(
VideoCaptureController* controller,
VideoCaptureControllerEventHandler* handler) {
- DCHECK(IsOnCaptureDeviceThread());
+ DCHECK(IsOnDeviceThread());
for (Controllers::iterator cit = controllers_.begin();
cit != controllers_.end(); ++cit) {
@@ -485,7 +477,7 @@ void VideoCaptureManager::DoRemoveControllerOnDeviceThread(
media::VideoCaptureDevice* VideoCaptureManager::GetDeviceInternal(
int capture_session_id) {
- DCHECK(IsOnCaptureDeviceThread());
+ DCHECK(IsOnDeviceThread());
VideoCaptureDevices::iterator dit = devices_.find(capture_session_id);
if (dit != devices_.end()) {
return dit->second;
diff --git a/content/browser/renderer_host/media/video_capture_manager.h b/content/browser/renderer_host/media/video_capture_manager.h
index 1a06287..4a2f554 100644
--- a/content/browser/renderer_host/media/video_capture_manager.h
+++ b/content/browser/renderer_host/media/video_capture_manager.h
@@ -15,7 +15,6 @@
#include <map>
#include "base/memory/ref_counted.h"
-#include "base/threading/thread.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"
@@ -30,13 +29,8 @@ class VideoCaptureControllerEventHandler;
namespace media_stream {
// VideoCaptureManager opens/closes and start/stops video capture devices.
-// It is deleted on the FILE thread so that it can call base::Thread::Stop()
-// there without blocking UI/IO threads. This is also needed for incognito
-// window. When incognito window is closed, IO thread is not in shutdown mode
-// and base::Thread::Stop() can't be called on IO thread.
class CONTENT_EXPORT VideoCaptureManager
- : public base::RefCountedThreadSafe<VideoCaptureManager,
- content::BrowserThread::DeleteOnFileThread>,
+ : public base::RefCountedThreadSafe<VideoCaptureManager>,
public MediaStreamProvider {
public:
// Calling |Start| of this id will open the first device, even though open has
@@ -47,7 +41,8 @@ class CONTENT_EXPORT VideoCaptureManager
VideoCaptureManager();
// Implements MediaStreamProvider.
- virtual void Register(MediaStreamProviderListener* listener) OVERRIDE;
+ virtual void Register(MediaStreamProviderListener* listener,
+ base::MessageLoopProxy* device_thread_loop) OVERRIDE;
virtual void Unregister() OVERRIDE;
@@ -78,7 +73,6 @@ class CONTENT_EXPORT VideoCaptureManager
// video capture device. Due to timing requirements, the function must be
// called before EnumerateDevices and Open.
void UseFakeDevice();
- MessageLoop* GetMessageLoop();
// Called by VideoCaptureHost to get a controller for |capture_params|.
// The controller is returned via calling |added_cb|.
@@ -93,18 +87,14 @@ class CONTENT_EXPORT VideoCaptureManager
private:
friend class ::MockVideoCaptureManager;
- friend struct content::BrowserThread::DeleteOnThread<
- content::BrowserThread::FILE>;
- friend class base::DeleteHelper<VideoCaptureManager>;
- friend class base::RefCountedThreadSafe<VideoCaptureManager,
- content::BrowserThread::DeleteOnFileThread>;
+ friend class base::RefCountedThreadSafe<VideoCaptureManager>;
virtual ~VideoCaptureManager();
typedef std::list<VideoCaptureControllerEventHandler*> Handlers;
struct Controller;
- // Called by the public functions, executed on vc_device_thread_.
+ // Called by the public functions, executed on device thread.
void OnEnumerateDevices();
void OnOpen(int capture_session_id, const StreamDeviceInfo& device);
void OnClose(int capture_session_id);
@@ -126,7 +116,7 @@ class CONTENT_EXPORT VideoCaptureManager
void OnDevicesEnumerated(const StreamDeviceInfoArray& devices);
void OnError(int capture_session_id, MediaStreamProviderError error);
- // Executed on vc_device_thread_ to make sure Listener is called from
+ // Executed on device thread to make sure Listener is called from
// Browser::IO thread.
void PostOnOpened(int capture_session_id);
void PostOnClosed(int capture_session_id);
@@ -139,17 +129,17 @@ class CONTENT_EXPORT VideoCaptureManager
bool DeviceInUse(const media::VideoCaptureDevice* video_capture_device);
media::VideoCaptureDevice* GetOpenedDevice(
const StreamDeviceInfo& device_info);
- bool IsOnCaptureDeviceThread() const;
+ bool IsOnDeviceThread() const;
media::VideoCaptureDevice* GetDeviceInternal(int capture_session_id);
- // Thread for all calls to VideoCaptureDevice.
- base::Thread vc_device_thread_;
+ // The message loop of media stream device thread that this object runs on.
+ scoped_refptr<base::MessageLoopProxy> device_loop_;
// Only accessed on Browser::IO thread.
MediaStreamProviderListener* listener_;
int new_capture_session_id_;
- // Only accessed from vc_device_thread_.
+ // Only accessed from device thread.
// VideoCaptureManager owns all VideoCaptureDevices and is responsible for
// deleting the instances when they are not used any longer.
typedef std::map<int, media::VideoCaptureDevice*> VideoCaptureDevices;
@@ -158,7 +148,7 @@ class CONTENT_EXPORT VideoCaptureManager
// Set to true if using fake devices for testing, false by default.
bool use_fake_device_;
- // Only accessed from vc_device_thread_.
+ // Only accessed from device thread.
// VideoCaptureManager owns all VideoCaptureController's and is responsible
// for deleting the instances when they are not used any longer.
// VideoCaptureDevice is one-to-one mapped to VideoCaptureController.
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 9b18576..2b063b3 100644
--- a/content/browser/renderer_host/media/video_capture_manager_unittest.cc
+++ b/content/browser/renderer_host/media/video_capture_manager_unittest.cc
@@ -43,8 +43,9 @@ class MockMediaStreamProviderListener : public MediaStreamProviderListener {
MOCK_METHOD3(Error, void(MediaStreamType, int,
MediaStreamProviderError));
- virtual void DevicesEnumerated(MediaStreamType stream_type,
- const StreamDeviceInfoArray& devices) {
+ virtual void DevicesEnumerated(
+ MediaStreamType stream_type,
+ const StreamDeviceInfoArray& devices) OVERRIDE {
devices_.clear();
for (StreamDeviceInfoArray::const_iterator it = devices.begin();
it != devices.end();
@@ -62,66 +63,34 @@ class MockMediaStreamProviderListener : public MediaStreamProviderListener {
namespace {
// Needed as an input argument to Start().
-class MockFrameObserver: public media::VideoCaptureDevice::EventHandler {
+class MockFrameObserver : public media::VideoCaptureDevice::EventHandler {
public:
- virtual void OnError() {}
+ virtual void OnError() OVERRIDE {}
void OnFrameInfo(const media::VideoCaptureCapability& info) {}
virtual void OnIncomingCapturedFrame(const uint8* data, int length,
- base::Time timestamp) {}
+ base::Time timestamp) OVERRIDE {}
};
// Test class
class VideoCaptureManagerTest : public testing::Test {
public:
- VideoCaptureManagerTest()
- : vcm_(),
- listener_(),
- message_loop_(),
- io_thread_(),
- frame_observer_() {
- }
+ VideoCaptureManagerTest() {}
virtual ~VideoCaptureManagerTest() {}
protected:
- virtual void SetUp() {
+ virtual void SetUp() OVERRIDE {
listener_.reset(new media_stream::MockMediaStreamProviderListener());
message_loop_.reset(new MessageLoop(MessageLoop::TYPE_IO));
io_thread_.reset(new BrowserThreadImpl(BrowserThread::IO,
message_loop_.get()));
vcm_ = new media_stream::VideoCaptureManager();
vcm_->UseFakeDevice();
- vcm_->Register(listener_.get());
+ vcm_->Register(listener_.get(), message_loop_->message_loop_proxy());
frame_observer_.reset(new MockFrameObserver());
}
- virtual void TearDown() {
- io_thread_.reset();
- }
-
- // Called on the VideoCaptureManager thread.
- static void PostQuitMessageLoop(MessageLoop* message_loop) {
- message_loop->PostTask(FROM_HERE, MessageLoop::QuitClosure());
- }
+ virtual void TearDown() OVERRIDE {}
- // Called on the main thread.
- static void PostQuitOnVideoCaptureManagerThread(
- MessageLoop* message_loop, media_stream::VideoCaptureManager* vcm) {
- vcm->GetMessageLoop()->PostTask(
- FROM_HERE, base::Bind(&PostQuitMessageLoop, message_loop));
- }
-
- // SyncWithVideoCaptureManagerThread() waits until all pending tasks on the
- // video_capture_manager internal thread are executed while also processing
- // pending task in message_loop_ on the current thread. It is used to
- // synchronize with the video capture manager thread when we are stopping a
- // video capture device.
- void SyncWithVideoCaptureManagerThread() {
- message_loop_->PostTask(
- FROM_HERE, base::Bind(&PostQuitOnVideoCaptureManagerThread,
- message_loop_.get(),
- vcm_));
- message_loop_->Run();
- }
scoped_refptr<media_stream::VideoCaptureManager> vcm_;
scoped_ptr<media_stream::MockMediaStreamProviderListener> listener_;
scoped_ptr<MessageLoop> message_loop_;
@@ -149,7 +118,7 @@ TEST_F(VideoCaptureManagerTest, CreateAndClose) {
vcm_->EnumerateDevices();
// Wait to get device callback.
- SyncWithVideoCaptureManagerThread();
+ message_loop_->RunAllPending();
int video_session_id = vcm_->Open(listener_->devices_.front());
@@ -164,7 +133,7 @@ TEST_F(VideoCaptureManagerTest, CreateAndClose) {
vcm_->Close(video_session_id);
// Wait to check callbacks before removing the listener.
- SyncWithVideoCaptureManagerThread();
+ message_loop_->RunAllPending();
vcm_->Unregister();
}
@@ -183,7 +152,7 @@ TEST_F(VideoCaptureManagerTest, OpenTwice) {
vcm_->EnumerateDevices();
// Wait to get device callback.
- SyncWithVideoCaptureManagerThread();
+ message_loop_->RunAllPending();
int video_session_id_first = vcm_->Open(listener_->devices_.front());
@@ -196,7 +165,7 @@ TEST_F(VideoCaptureManagerTest, OpenTwice) {
vcm_->Close(video_session_id_second);
// Wait to check callbacks before removing the listener.
- SyncWithVideoCaptureManagerThread();
+ message_loop_->RunAllPending();
vcm_->Unregister();
}
@@ -215,7 +184,7 @@ TEST_F(VideoCaptureManagerTest, OpenTwo) {
vcm_->EnumerateDevices();
// Wait to get device callback.
- SyncWithVideoCaptureManagerThread();
+ message_loop_->RunAllPending();
media_stream::StreamDeviceInfoArray::iterator it =
listener_->devices_.begin();
@@ -228,7 +197,7 @@ TEST_F(VideoCaptureManagerTest, OpenTwo) {
vcm_->Close(video_session_id_second);
// Wait to check callbacks before removing the listener.
- SyncWithVideoCaptureManagerThread();
+ message_loop_->RunAllPending();
vcm_->Unregister();
}
@@ -244,7 +213,7 @@ TEST_F(VideoCaptureManagerTest, OpenNotExisting) {
vcm_->EnumerateDevices();
// Wait to get device callback.
- SyncWithVideoCaptureManagerThread();
+ message_loop_->RunAllPending();
media_stream::MediaStreamType stream_type =
content::MEDIA_STREAM_DEVICE_TYPE_VIDEO_CAPTURE;
@@ -257,7 +226,7 @@ TEST_F(VideoCaptureManagerTest, OpenNotExisting) {
vcm_->Open(dummy_device);
// Wait to check callbacks before removing the listener.
- SyncWithVideoCaptureManagerThread();
+ message_loop_->RunAllPending();
vcm_->Unregister();
}
@@ -286,7 +255,7 @@ TEST_F(VideoCaptureManagerTest, StartUsingId) {
base::Closure());
// Wait to check callbacks before removing the listener.
- SyncWithVideoCaptureManagerThread();
+ message_loop_->RunAllPending();
vcm_->Unregister();
}
@@ -305,7 +274,7 @@ TEST_F(VideoCaptureManagerTest, CloseWithoutStop) {
vcm_->EnumerateDevices();
// Wait to get device callback.
- SyncWithVideoCaptureManagerThread();
+ message_loop_->RunAllPending();
int video_session_id = vcm_->Open(listener_->devices_.front());
@@ -322,7 +291,7 @@ TEST_F(VideoCaptureManagerTest, CloseWithoutStop) {
vcm_->Stop(video_session_id, base::Closure());
// Wait to check callbacks before removing the listener
- SyncWithVideoCaptureManagerThread();
+ message_loop_->RunAllPending();
vcm_->Unregister();
}
diff --git a/content/browser/renderer_host/render_process_host_impl.cc b/content/browser/renderer_host/render_process_host_impl.cc
index 89ce30b..2335831 100644
--- a/content/browser/renderer_host/render_process_host_impl.cc
+++ b/content/browser/renderer_host/render_process_host_impl.cc
@@ -526,10 +526,12 @@ void RenderProcessHostImpl::CreateMessageFilters() {
// TODO(dtrainor, klobag): Enable this when BrowserMainLoop gets
// included in Android builds. Tracked via 115941.
media::AudioManager* audio_manager = BrowserMainLoop::GetAudioManager();
- channel_->AddFilter(new AudioInputRendererHost(
- resource_context, audio_manager));
+ media_stream::MediaStreamManager* media_stream_manager =
+ BrowserMainLoop::GetMediaStreamManager();
+ channel_->AddFilter(new AudioInputRendererHost(audio_manager,
+ media_stream_manager));
channel_->AddFilter(new AudioRendererHost(audio_manager, media_observer));
- channel_->AddFilter(new VideoCaptureHost(resource_context, audio_manager));
+ channel_->AddFilter(new VideoCaptureHost());
#endif
channel_->AddFilter(new AppCacheDispatcherHost(
static_cast<ChromeAppCacheService*>(
@@ -547,8 +549,7 @@ void RenderProcessHostImpl::CreateMessageFilters() {
gpu_message_filter_ = new GpuMessageFilter(GetID(), widget_helper_.get());
channel_->AddFilter(gpu_message_filter_);
#if defined(ENABLE_WEBRTC)
- channel_->AddFilter(new media_stream::MediaStreamDispatcherHost(
- resource_context, GetID(), BrowserMainLoop::GetAudioManager()));
+ channel_->AddFilter(new media_stream::MediaStreamDispatcherHost(GetID()));
#endif
channel_->AddFilter(
GetContentClient()->browser()->AllowPepperPrivateFileAPI() ?
diff --git a/content/test/webrtc_audio_device_test.cc b/content/test/webrtc_audio_device_test.cc
index 44bc1cb..0e84a97 100644
--- a/content/test/webrtc_audio_device_test.cc
+++ b/content/test/webrtc_audio_device_test.cc
@@ -12,10 +12,12 @@
#include "base/synchronization/waitable_event.h"
#include "base/test/test_timeouts.h"
#include "base/win/scoped_com_initializer.h"
+#include "content/browser/renderer_host/media/audio_input_device_manager.h"
#include "content/browser/renderer_host/media/audio_input_renderer_host.h"
#include "content/browser/renderer_host/media/audio_renderer_host.h"
#include "content/browser/renderer_host/media/media_stream_manager.h"
#include "content/browser/renderer_host/media/mock_media_observer.h"
+#include "content/browser/renderer_host/media/video_capture_manager.h"
#include "content/common/view_messages.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/common/content_paths.h"
@@ -50,13 +52,13 @@ class WebRTCMockRenderProcess : public RenderProcess {
virtual ~WebRTCMockRenderProcess() {}
// RenderProcess implementation.
- virtual skia::PlatformCanvas* GetDrawingCanvas(TransportDIB** memory,
- const gfx::Rect& rect) {
+ virtual skia::PlatformCanvas* GetDrawingCanvas(
+ TransportDIB** memory, const gfx::Rect& rect) OVERRIDE {
return NULL;
}
- virtual void ReleaseTransportDIB(TransportDIB* memory) {}
- virtual bool UseInProcessPlugins() const { return false; }
- virtual void AddBindings(int bindings) {}
+ virtual void ReleaseTransportDIB(TransportDIB* memory) OVERRIDE {}
+ virtual bool UseInProcessPlugins() const OVERRIDE { return false; }
+ virtual void AddBindings(int bindings) OVERRIDE {}
virtual int GetEnabledBindings() const { return 0; }
virtual bool HasInitializedMediaLibrary() const { return false; }
@@ -197,6 +199,14 @@ void WebRTCAudioDeviceTest::InitializeIOThread(const char* thread_name) {
audio_manager_.reset(media::AudioManager::Create());
+ scoped_refptr<media_stream::AudioInputDeviceManager>
+ audio_input_device_manager(new media_stream::AudioInputDeviceManager(
+ audio_manager_.get()));
+ scoped_refptr<media_stream::VideoCaptureManager> video_capture_manager(
+ new media_stream::VideoCaptureManager());
+ media_stream_manager_.reset(new media_stream::MediaStreamManager(
+ audio_input_device_manager, video_capture_manager));
+
// Populate our resource context.
test_request_context_.reset(new TestURLRequestContext());
MockResourceContext* resource_context =
@@ -214,6 +224,7 @@ void WebRTCAudioDeviceTest::InitializeIOThread(const char* thread_name) {
void WebRTCAudioDeviceTest::UninitializeIOThread() {
resource_context_.reset();
+ media_stream_manager_.reset();
audio_manager_.reset();
test_request_context_.reset();
initialize_com_.reset();
@@ -226,7 +237,7 @@ void WebRTCAudioDeviceTest::CreateChannel(const char* name) {
audio_render_host_->OnChannelConnected(base::GetCurrentProcId());
audio_input_renderer_host_ = new AudioInputRendererHost(
- resource_context_.get(), audio_manager_.get());
+ audio_manager_.get(), media_stream_manager_.get());
audio_input_renderer_host_->OnChannelConnected(base::GetCurrentProcId());
channel_.reset(new IPC::Channel(name, IPC::Channel::MODE_SERVER, this));
diff --git a/media/video/capture/win/video_capture_device_win.cc b/media/video/capture/win/video_capture_device_win.cc
index 55b5a16..05d5b43 100644
--- a/media/video/capture/win/video_capture_device_win.cc
+++ b/media/video/capture/win/video_capture_device_win.cc
@@ -180,7 +180,6 @@ static const char kGoogleCameraAdapter[] = "google camera adapter";
void VideoCaptureDevice::GetDeviceNames(Names* device_names) {
DCHECK(device_names);
- base::win::ScopedCOMInitializer coinit;
ScopedComPtr<ICreateDevEnum> dev_enum;
HRESULT hr = dev_enum.CreateInstance(CLSID_SystemDeviceEnum, NULL,
CLSCTX_INPROC);
@@ -255,9 +254,11 @@ VideoCaptureDeviceWin::VideoCaptureDeviceWin(const Name& device_name)
: device_name_(device_name),
state_(kIdle),
observer_(NULL) {
+ DetachFromThread();
}
VideoCaptureDeviceWin::~VideoCaptureDeviceWin() {
+ DCHECK(CalledOnValidThread());
if (media_control_)
media_control_->Stop();
@@ -276,6 +277,7 @@ VideoCaptureDeviceWin::~VideoCaptureDeviceWin() {
}
bool VideoCaptureDeviceWin::Init() {
+ DCHECK(CalledOnValidThread());
HRESULT hr = GetDeviceFilter(device_name_, capture_filter_.Receive());
if (!capture_filter_) {
DVLOG(2) << "Failed to create capture filter.";
@@ -331,6 +333,7 @@ void VideoCaptureDeviceWin::Allocate(
int height,
int frame_rate,
VideoCaptureDevice::EventHandler* observer) {
+ DCHECK(CalledOnValidThread());
if (state_ != kIdle)
return;
@@ -427,6 +430,7 @@ void VideoCaptureDeviceWin::Allocate(
}
void VideoCaptureDeviceWin::Start() {
+ DCHECK(CalledOnValidThread());
if (state_ != kAllocated)
return;
@@ -440,6 +444,7 @@ void VideoCaptureDeviceWin::Start() {
}
void VideoCaptureDeviceWin::Stop() {
+ DCHECK(CalledOnValidThread());
if (state_ != kCapturing)
return;
@@ -453,6 +458,7 @@ void VideoCaptureDeviceWin::Stop() {
}
void VideoCaptureDeviceWin::DeAllocate() {
+ DCHECK(CalledOnValidThread());
if (state_ == kIdle)
return;
@@ -475,6 +481,7 @@ void VideoCaptureDeviceWin::DeAllocate() {
}
const VideoCaptureDevice::Name& VideoCaptureDeviceWin::device_name() {
+ DCHECK(CalledOnValidThread());
return device_name_;
}
@@ -485,6 +492,7 @@ void VideoCaptureDeviceWin::FrameReceived(const uint8* buffer,
}
bool VideoCaptureDeviceWin::CreateCapabilityMap() {
+ DCHECK(CalledOnValidThread());
ScopedComPtr<IAMStreamConfig> stream_config;
HRESULT hr = output_capture_pin_.QueryInterface(stream_config.Receive());
if (FAILED(hr)) {
@@ -594,6 +602,7 @@ bool VideoCaptureDeviceWin::CreateCapabilityMap() {
int VideoCaptureDeviceWin::GetBestMatchedCapability(int requested_width,
int requested_height,
int requested_frame_rate) {
+ DCHECK(CalledOnValidThread());
std::list<ResolutionDiff> diff_list;
// Loop through the candidates to create a list of differentials between the
@@ -653,6 +662,7 @@ int VideoCaptureDeviceWin::GetBestMatchedCapability(int requested_width,
}
void VideoCaptureDeviceWin::SetErrorState(const char* reason) {
+ DCHECK(CalledOnValidThread());
DVLOG(1) << reason;
state_ = kError;
observer_->OnError();
diff --git a/media/video/capture/win/video_capture_device_win.h b/media/video/capture/win/video_capture_device_win.h
index 1f7e03a..7e9f65b 100644
--- a/media/video/capture/win/video_capture_device_win.h
+++ b/media/video/capture/win/video_capture_device_win.h
@@ -17,8 +17,8 @@
#include <map>
#include <string>
+#include "base/threading/non_thread_safe.h"
#include "base/threading/thread.h"
-#include "base/win/scoped_com_initializer.h"
#include "base/win/scoped_comptr.h"
#include "media/video/capture/video_capture_device.h"
#include "media/video/capture/video_capture_types.h"
@@ -27,8 +27,10 @@
namespace media {
+// All the methods in the class can only be run on a COM initialized thread.
class VideoCaptureDeviceWin
- : public VideoCaptureDevice,
+ : public base::NonThreadSafe,
+ public VideoCaptureDevice,
public SinkFilterObserver {
public:
explicit VideoCaptureDeviceWin(const Name& device_name);
@@ -64,8 +66,6 @@ class VideoCaptureDeviceWin
int GetBestMatchedCapability(int width, int height, int frame_rate);
void SetErrorState(const char* reason);
- base::win::ScopedCOMInitializer initialize_com_;
-
Name device_name_;
InternalState state_;
VideoCaptureDevice::EventHandler* observer_;