| Index: content/browser/media_stream/video_capture_manager.cc
|
| ===================================================================
|
| --- content/browser/media_stream/video_capture_manager.cc (revision 0)
|
| +++ content/browser/media_stream/video_capture_manager.cc (revision 0)
|
| @@ -0,0 +1,382 @@
|
| +// 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/media_stream/video_capture_manager.h"
|
| +
|
| +#include "base/memory/scoped_ptr.h"
|
| +#include "content/browser/browser_thread.h"
|
| +#include "media/video/capture/fake_video_capture_device.h"
|
| +#include "media/video/capture/video_capture_device.h"
|
| +
|
| +namespace media_stream {
|
| +
|
| +// Starting id for the first capture session
|
| +enum { kFirstSessionId = 2};
|
| +
|
| +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),
|
| + new_capture_session_id_(kFirstSessionId),
|
| + devices_(),
|
| + use_fake_device_(false) {
|
| + vc_device_thread_.Start();
|
| +}
|
| +
|
| +VideoCaptureManager::~VideoCaptureManager() {
|
| + vc_device_thread_.Stop();
|
| +}
|
| +
|
| +bool VideoCaptureManager::Register(MediaStreamProviderListener* listener) {
|
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
|
| + DCHECK(!listener_);
|
| + listener_ = listener;
|
| + return true;
|
| +}
|
| +
|
| +void VideoCaptureManager::Unregister() {
|
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
|
| + listener_ = NULL;
|
| +}
|
| +
|
| +void VideoCaptureManager::EnumerateDevices() {
|
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
|
| + DCHECK(listener_);
|
| +
|
| + vc_device_thread_.message_loop()->PostTask(
|
| + FROM_HERE,
|
| + NewRunnableMethod(this,
|
| + &VideoCaptureManager::OnEnumerateDevices));
|
| +}
|
| +
|
| +MediaCaptureSessionId VideoCaptureManager::Open(
|
| + const MediaCaptureDeviceInfo& device) {
|
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
|
| + DCHECK(listener_);
|
| +
|
| + // Generate a new id for this device
|
| + MediaCaptureSessionId video_capture_session_id = new_capture_session_id_++;
|
| +
|
| + vc_device_thread_.message_loop()->PostTask(
|
| + FROM_HERE,
|
| + NewRunnableMethod(this,
|
| + &VideoCaptureManager::OnOpen,
|
| + video_capture_session_id,
|
| + device));
|
| +
|
| + return video_capture_session_id;
|
| +}
|
| +
|
| +void VideoCaptureManager::Close(MediaCaptureSessionId capture_session_id) {
|
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
|
| + DCHECK(listener_);
|
| +
|
| + vc_device_thread_.message_loop()->PostTask(
|
| + FROM_HERE,
|
| + NewRunnableMethod(this,
|
| + &VideoCaptureManager::OnClose,
|
| + capture_session_id));
|
| +}
|
| +
|
| +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(
|
| + FROM_HERE,
|
| + NewRunnableMethod(this,
|
| + &VideoCaptureManager::OnStart,
|
| + capture_params,
|
| + video_capture_receiver));
|
| +}
|
| +
|
| +void VideoCaptureManager::Stop(
|
| + const media::VideoCaptureSessionId capture_session_id, Task* stopped_task) {
|
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
|
| +
|
| + vc_device_thread_.message_loop()->PostTask(
|
| + FROM_HERE,
|
| + NewRunnableMethod(this,
|
| + &VideoCaptureManager::OnStop,
|
| + capture_session_id,
|
| + stopped_task));
|
| +}
|
| +
|
| +void VideoCaptureManager::UseFakeDevice() {
|
| + use_fake_device_ = true;
|
| +}
|
| +
|
| +MessageLoop* VideoCaptureManager::GetMessageLoop() {
|
| + return vc_device_thread_.message_loop();
|
| +}
|
| +
|
| +void VideoCaptureManager::OnEnumerateDevices() {
|
| + DCHECK(IsOnCaptureDeviceThread());
|
| +
|
| + scoped_ptr<media::VideoCaptureDevice::Names> device_names(
|
| + new media::VideoCaptureDevice::Names());
|
| + GetAvailableDevices(device_names.get());
|
| +
|
| + MediaCaptureDevices devices;
|
| + for (media::VideoCaptureDevice::Names::iterator it =
|
| + device_names.get()->begin(); it != device_names.get()->end(); ++it) {
|
| + bool opened = DeviceOpened(*it);
|
| + devices.push_back(MediaCaptureDeviceInfo(kVideoCapture, it->device_name,
|
| + it->unique_id, opened));
|
| + }
|
| +
|
| + // Let the listener know the result
|
| + PostOnDevicesEnumerated(devices);
|
| +
|
| + // Clean-up
|
| + devices.clear();
|
| + device_names.get()->clear();
|
| +}
|
| +
|
| +void VideoCaptureManager::OnOpen(MediaCaptureSessionId capture_session_id,
|
| + const MediaCaptureDeviceInfo device) {
|
| + DCHECK(IsOnCaptureDeviceThread());
|
| + DCHECK(devices_.find(capture_session_id) == devices_.end());
|
| +
|
| + // Check if another session has already opened this device, only one user per
|
| + // device is supported.
|
| + if (DeviceOpened(device)) {
|
| + PostOnError(capture_session_id, kDeviceAlreadyInUse);
|
| + return;
|
| + }
|
| +
|
| + // Open the device
|
| + media::VideoCaptureDevice::Name vc_device_name;
|
| + vc_device_name.device_name = device.name;
|
| + vc_device_name.unique_id = device.device_id;
|
| +
|
| + media::VideoCaptureDevice* video_capture_device = NULL;
|
| + if (!use_fake_device_) {
|
| + video_capture_device = media::VideoCaptureDevice::Create(vc_device_name);
|
| + } else {
|
| + video_capture_device =
|
| + media::FakeVideoCaptureDevice::Create(vc_device_name);
|
| + }
|
| + if (video_capture_device == NULL) {
|
| + PostOnError(capture_session_id, kDeviceNotAvailable);
|
| + return;
|
| + }
|
| +
|
| + devices_[capture_session_id] = video_capture_device;
|
| + PostOnOpened(capture_session_id);
|
| +}
|
| +
|
| +void VideoCaptureManager::OnClose(
|
| + MediaCaptureSessionId capture_session_id) {
|
| + DCHECK(IsOnCaptureDeviceThread());
|
| +
|
| + VideoCaptureDevices::iterator it = devices_.find(capture_session_id);
|
| + if (it != devices_.end()) {
|
| + // Deallocate (if not done already) and delete the device
|
| + media::VideoCaptureDevice* video_capture_device = it->second;
|
| + video_capture_device->DeAllocate();
|
| + delete video_capture_device;
|
| + devices_.erase(it);
|
| + }
|
| +
|
| + PostOnClosed(capture_session_id);
|
| +}
|
| +
|
| +void VideoCaptureManager::OnStart(
|
| + const media::VideoCaptureParams capture_params,
|
| + media::VideoCaptureDevice::EventHandler* video_capture_receiver) {
|
| + DCHECK(IsOnCaptureDeviceThread());
|
| +
|
| + // Solution for not using MediaStreamManager
|
| + // This session id won't be returned by Open()
|
| + if (capture_params.session_id == kStartOpenSessionId) {
|
| + // Start() is called without using Open(), we need to open a device
|
| + scoped_ptr<media::VideoCaptureDevice::Names> device_names(
|
| + new media::VideoCaptureDevice::Names());
|
| + GetAvailableDevices(device_names.get());
|
| +
|
| + MediaCaptureDeviceInfo device(kVideoCapture,
|
| + device_names.get()->front().device_name,
|
| + device_names.get()->front().unique_id, false);
|
| +
|
| + // Call OnOpen to open using the first device in the list
|
| + OnOpen(capture_params.session_id, device);
|
| + }
|
| +
|
| + VideoCaptureDevices::iterator it = devices_.find(capture_params.session_id);
|
| + if (it == devices_.end()) {
|
| + // Invalid session id
|
| + video_capture_receiver->OnError();
|
| + return;
|
| + }
|
| + media::VideoCaptureDevice* video_capture_device = it->second;
|
| +
|
| + // Possible errors are signaled to video_capture_receiver by
|
| + // video_capture_device. video_capture_receiver to perform actions.
|
| + video_capture_device->Allocate(capture_params.width, capture_params.height,
|
| + capture_params.frame_per_second,
|
| + video_capture_receiver);
|
| + video_capture_device->Start();
|
| +}
|
| +
|
| +void VideoCaptureManager::OnStop(
|
| + const media::VideoCaptureSessionId capture_session_id,
|
| + Task* stopped_task) {
|
| + DCHECK(IsOnCaptureDeviceThread());
|
| +
|
| + VideoCaptureDevices::iterator it = devices_.find(capture_session_id);
|
| + if (it != devices_.end()) {
|
| + media::VideoCaptureDevice* video_capture_device = it->second;
|
| + // Possible errors are signaled to video_capture_receiver by
|
| + // video_capture_device. video_capture_receiver to perform actions.
|
| + video_capture_device->Stop();
|
| + video_capture_device->DeAllocate();
|
| + }
|
| +
|
| + if (stopped_task) {
|
| + stopped_task->Run();
|
| + delete stopped_task;
|
| + }
|
| +
|
| + if (capture_session_id == kStartOpenSessionId) {
|
| + // This device was opened from Start(), not Open(). Close it!
|
| + OnClose(capture_session_id);
|
| + }
|
| +}
|
| +
|
| +void VideoCaptureManager::OnOpened(
|
| + MediaCaptureSessionId capture_session_id) {
|
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
|
| + if (listener_ == NULL) {
|
| + // Listener has been removed
|
| + return;
|
| + }
|
| + listener_->Opened(kVideoCapture, capture_session_id);
|
| +}
|
| +
|
| +void VideoCaptureManager::OnClosed(
|
| + MediaCaptureSessionId capture_session_id) {
|
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
|
| + if (listener_ == NULL) {
|
| + // Listener has been removed
|
| + return;
|
| + }
|
| + listener_->Closed(kVideoCapture, capture_session_id);
|
| +}
|
| +
|
| +void VideoCaptureManager::OnDevicesEnumerated(
|
| + const MediaCaptureDevices& devices) {
|
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
|
| + if (listener_ == NULL) {
|
| + // Listener has been removed
|
| + return;
|
| + }
|
| + listener_->DevicesEnumerated(kVideoCapture, devices);
|
| +}
|
| +
|
| +void VideoCaptureManager::OnError(MediaCaptureSessionId capture_session_id,
|
| + MediaStreamProviderError error) {
|
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
|
| + if (listener_ == NULL) {
|
| + // Listener has been removed
|
| + return;
|
| + }
|
| + listener_->Error(kVideoCapture, capture_session_id, error);
|
| +}
|
| +
|
| +void VideoCaptureManager::PostOnOpened(
|
| + MediaCaptureSessionId capture_session_id) {
|
| + DCHECK(IsOnCaptureDeviceThread());
|
| + BrowserThread::PostTask(BrowserThread::IO,
|
| + FROM_HERE,
|
| + NewRunnableMethod(this,
|
| + &VideoCaptureManager::OnOpened,
|
| + capture_session_id));
|
| +}
|
| +
|
| +void VideoCaptureManager::PostOnClosed(
|
| + MediaCaptureSessionId capture_session_id) {
|
| + DCHECK(IsOnCaptureDeviceThread());
|
| + BrowserThread::PostTask(BrowserThread::IO,
|
| + FROM_HERE,
|
| + NewRunnableMethod(this,
|
| + &VideoCaptureManager::OnClosed,
|
| + capture_session_id));
|
| +}
|
| +
|
| +void VideoCaptureManager::PostOnDevicesEnumerated(MediaCaptureDevices devices) {
|
| + DCHECK(IsOnCaptureDeviceThread());
|
| +
|
| + BrowserThread::PostTask(BrowserThread::IO,
|
| + FROM_HERE,
|
| + NewRunnableMethod(
|
| + this,
|
| + &VideoCaptureManager::OnDevicesEnumerated,
|
| + devices));
|
| +}
|
| +
|
| +void VideoCaptureManager::PostOnError(MediaCaptureSessionId capture_session_id,
|
| + MediaStreamProviderError error) {
|
| + // Don't check thread here, can be called from both IO thread and device
|
| + // thread.
|
| + BrowserThread::PostTask(BrowserThread::IO,
|
| + FROM_HERE,
|
| + NewRunnableMethod(this,
|
| + &VideoCaptureManager::OnError,
|
| + capture_session_id,
|
| + error));
|
| +}
|
| +
|
| +bool VideoCaptureManager::IsOnCaptureDeviceThread() const {
|
| + return MessageLoop::current() == vc_device_thread_.message_loop();
|
| +}
|
| +
|
| +void VideoCaptureManager::GetAvailableDevices(
|
| + media::VideoCaptureDevice::Names* device_names) {
|
| + DCHECK(IsOnCaptureDeviceThread());
|
| +
|
| + if (!use_fake_device_) {
|
| + media::VideoCaptureDevice::GetDeviceNames(device_names);
|
| + } else {
|
| + media::FakeVideoCaptureDevice::GetDeviceNames(device_names);
|
| + }
|
| +}
|
| +
|
| +bool VideoCaptureManager::DeviceOpened(
|
| + const media::VideoCaptureDevice::Name& device_name) {
|
| + DCHECK(IsOnCaptureDeviceThread());
|
| +
|
| + for (VideoCaptureDevices::iterator it = devices_.begin();
|
| + it != devices_.end();
|
| + ++it) {
|
| + if (device_name.unique_id == it->second->device_name().unique_id) {
|
| + // We've found the device!
|
| + return true;
|
| + }
|
| + }
|
| + return false;
|
| +}
|
| +
|
| +bool VideoCaptureManager::DeviceOpened(
|
| + const MediaCaptureDeviceInfo& device_info) {
|
| + DCHECK(IsOnCaptureDeviceThread());
|
| +
|
| + for (VideoCaptureDevices::iterator it = devices_.begin();
|
| + it != devices_.end();
|
| + it++) {
|
| + if (device_info.device_id == it->second->device_name().unique_id) {
|
| + return true;
|
| + }
|
| + }
|
| + return false;
|
| +}
|
| +
|
| +} // namespace media
|
|
|