Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1327)

Unified Diff: content/browser/media_stream/video_capture_manager.cc

Issue 6946001: VideoCaptureManager opens/closes, starts/stops and enumerates video capture devices. VideoCapture... (Closed) Base URL: http://src.chromium.org/svn/trunk/src/
Patch Set: Created 9 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
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,460 @@
+// 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 = 1};
+
+static ::base::LazyInstance<VideoCaptureManager> g_video_capture_manager(
+ base::LINKER_INITIALIZED);
+
+bool VideoCaptureManager::use_fake_device_ = false;
+
+VideoCaptureManager* VideoCaptureManager::Get() {
+ return g_video_capture_manager.Pointer();
+}
+
+void VideoCaptureManager::CreateTestManager() {
+ VideoCaptureManager* vcm = g_video_capture_manager.Pointer();
+ vcm->UseFakeDevice();
+}
+
+VideoCaptureManager::VideoCaptureManager()
+ : vc_device_thread_("VideoCaptureManagerThread"),
+ listener_(NULL),
+ new_capture_session_id_(kFirstSessionId),
+ devices_() {
+ vc_device_thread_.Start();
+}
+
+VideoCaptureManager::~VideoCaptureManager() {
+ vc_device_thread_.Stop();
+ devices_.clear();
+}
+
+int VideoCaptureManager::Register(MediaStreamType service_type,
+ MediaStreamProviderListener* listener) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ if (service_type != kVideoCapture) {
+ // Not a valid service type
+ return -1;
+ }
+ if (listener_) {
+ // Already registered, unregister first.
+ return -1;
+ }
+ listener_ = listener;
+ return 0;
+}
+
+void VideoCaptureManager::Unregister(MediaStreamType service_type,
+ MediaStreamProviderListener* listener) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ if (service_type != kVideoCapture) {
+ return;
+ }
+ listener_ = NULL;
+ return;
+}
+
+void VideoCaptureManager::EnumerateDevices(MediaStreamType service_type) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ if (listener_ == NULL) {
+ return;
+ }
+ if (service_type != kVideoCapture) {
+ PostOnError(-1, kInvalidMediaStreamType);
+ return;
+ }
+
+ vc_device_thread_.message_loop()->PostTask(
+ FROM_HERE,
+ NewRunnableMethod(this,
+ &VideoCaptureManager::OnEnumerateDevices));
+ return;
+}
+
+MediaCaptureSessionId VideoCaptureManager::Open(
+ MediaStreamType service_type, const MediaCaptureDeviceInfo& device) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ if (listener_ == NULL) {
+ return -1;
+ }
+ if (service_type != kVideoCapture) {
+ PostOnError(-1, kInvalidMediaStreamType);
+ return -1;
+ }
+
+ // 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(MediaStreamType service_type,
+ MediaCaptureSessionId capture_session_id) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ if (listener_ == NULL) {
+ return;
+ }
+ if (service_type != kVideoCapture) {
+ PostOnError(-1, kInvalidMediaStreamType);
+ return;
+ }
+
+ vc_device_thread_.message_loop()->PostTask(
+ FROM_HERE,
+ NewRunnableMethod(this,
+ &VideoCaptureManager::OnClose,
+ capture_session_id));
+ return;
+}
+
+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::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) {
wjia(left Chromium) 2011/05/06 00:11:31 one more space indent
mflodman1 2011/05/06 11:52:38 What is the indent-rule here? I thought it was 4 s
+ 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();
+
+ return;
+}
+
+void VideoCaptureManager::OnOpen(MediaCaptureSessionId capture_session_id,
+ const MediaCaptureDeviceInfo device) {
+ DCHECK(IsOnCaptureDeviceThread());
+ if (devices_.find(capture_session_id) != devices_.end()) {
+ // id already exists!
+ PostOnError(capture_session_id, kInvalidSession);
+ return;
+ }
+
+ // Check if another session has already opened this device, only one user per
+ // device is supported.
wjia(left Chromium) 2011/05/06 00:11:31 looks like you can use DeviceOpened() here.
mflodman1 2011/05/06 11:52:38 DeviceOpened has a different input type, but I cre
+ for (VideoCaptureDevices::iterator it = devices_.begin();
+ it != devices_.end();
+ it++) {
+ media::VideoCaptureDevice* vc_device = it->second;
+ if (vc_device != NULL) {
wjia(left Chromium) 2011/05/06 00:11:31 if vc_device == NULL here, is it an error?
mflodman1 2011/05/06 11:52:38 Removed. vc_device == null only if a device can't
+ if (device.device_id.compare(vc_device->device_name().unique_id) == 0) {
+ 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);
+ return;
+}
+
+void VideoCaptureManager::OnClose(
+ MediaCaptureSessionId capture_session_id) {
+ DCHECK(IsOnCaptureDeviceThread());
+ if (devices_.find(capture_session_id) == devices_.end()) {
+ return;
+ }
+
+ VideoCaptureDevices::iterator it = devices_.find(capture_session_id);
+ if (it == devices_.end()) {
+ // Device not opened
+ PostOnClosed(capture_session_id);
+ return;
+ }
+ // 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);
+ return;
+}
+
+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);
+ device_names.get()->clear();
wjia(left Chromium) 2011/05/06 00:11:31 clear() is not needed. scoped_ptr should take care
mflodman1 2011/05/06 11:52:38 Done.
+ }
+
+ 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 host
wjia(left Chromium) 2011/05/06 00:11:31 comment doesn't match.
mflodman1 2011/05/06 11:52:38 Comment updated.
+ video_capture_device->Allocate(capture_params.width, capture_params.height,
+ capture_params.frame_per_second,
+ video_capture_receiver);
+ video_capture_device->Start();
+ return;
+}
+
+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 by video_capture_device
wjia(left Chromium) 2011/05/06 00:11:31 comment doesn't match.
mflodman1 2011/05/06 11:52:38 Comment updated.
+ 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);
+ }
+ return;
+}
+
+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);
+ return;
+}
+
+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);
+ return;
+}
+
+void VideoCaptureManager::OnDevicesEnumerated(
+ const MediaCaptureDevices& devices) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ if (listener_ == NULL) {
+ // Listener has been removed
+ return;
+ }
+ listener_->DevicesEnumerated(kVideoCapture, devices);
+ return;
+}
+
+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);
+ return;
+}
+
+void VideoCaptureManager::PostOnOpened(
+ MediaCaptureSessionId capture_session_id) {
+ DCHECK(IsOnCaptureDeviceThread());
+
+ BrowserThread::PostTask(BrowserThread::IO,
+ FROM_HERE,
+ NewRunnableFunction(
+ &VideoCaptureManager::OnOpenedProxy,
+ capture_session_id));
wjia(left Chromium) 2011/05/06 00:11:31 there is no need for On*Proxy. You can use: Bro
mflodman1 2011/05/06 11:52:38 Done.
+ return;
+}
+
+void VideoCaptureManager::PostOnClosed(
+ MediaCaptureSessionId capture_session_id) {
+ DCHECK(IsOnCaptureDeviceThread());
+ BrowserThread::PostTask(BrowserThread::IO,
+ FROM_HERE,
+ NewRunnableFunction(
+ &VideoCaptureManager::OnClosedProxy,
+ capture_session_id));
+ return;
+}
+
+void VideoCaptureManager::PostOnDevicesEnumerated(
+ const MediaCaptureDevices& devices) {
+ DCHECK(IsOnCaptureDeviceThread());
+ BrowserThread::PostTask(BrowserThread::IO,
+ FROM_HERE,
+ NewRunnableFunction(
+ &VideoCaptureManager::OnDevicesEnumeratedProxy,
+ devices));
+ return;
+}
+
+void VideoCaptureManager::PostOnError(MediaCaptureSessionId capture_session_id,
+ MediaStreamProviderError error) {
+ DCHECK(IsOnCaptureDeviceThread());
+ BrowserThread::PostTask(BrowserThread::IO,
+ FROM_HERE,
+ NewRunnableFunction(
+ &VideoCaptureManager::OnErrorProxy,
+ capture_session_id,
+ error));
+ return;
+}
+
+void VideoCaptureManager::OnOpenedProxy(
+ MediaCaptureSessionId capture_session_id) {
+ Get()->OnOpened(capture_session_id);
+}
+
+void VideoCaptureManager::OnClosedProxy(
+ MediaCaptureSessionId capture_session_id) {
+ Get()->OnClosed(capture_session_id);
+}
+
+void VideoCaptureManager::OnDevicesEnumeratedProxy(
+ const MediaCaptureDevices devices) {
+ Get()->OnDevicesEnumerated(devices);
+}
+
+void VideoCaptureManager::OnErrorProxy(MediaCaptureSessionId capture_session_id,
+ MediaStreamProviderError error) {
+ Get()->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);
+ }
+ return;
+}
+
+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.compare(it->second->device_name().unique_id)
+ == 0 ) {
+ // We've found the device!
+ return true;
+ }
+ }
+ return false;
+}
+
+void VideoCaptureManager::UseFakeDevice() {
+ use_fake_device_ = true;
+}
+
+MessageLoop* VideoCaptureManager::GetMessageLoop() {
+ return vc_device_thread_.message_loop();
+}
+
+} // namespace media
mflodman1 2011/05/05 11:11:22 Will add newline in next upload.
mflodman1 2011/05/06 11:52:38 Done.

Powered by Google App Engine
This is Rietveld 408576698