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

Unified Diff: media/capture/service/video_capture_handler_impl.cc

Issue 1699553002: Mojo Video Capture service in media/capture (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: perkj@s and magjed@s comments Created 4 years, 10 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: media/capture/service/video_capture_handler_impl.cc
diff --git a/media/capture/service/video_capture_handler_impl.cc b/media/capture/service/video_capture_handler_impl.cc
new file mode 100644
index 0000000000000000000000000000000000000000..2d0587701b85c4ac7155025a720106925c3c65dd
--- /dev/null
+++ b/media/capture/service/video_capture_handler_impl.cc
@@ -0,0 +1,189 @@
+// Copyright 2016 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 "media/capture/service/video_capture_handler_impl.h"
+
+#include <string>
+
+#include "base/bind.h"
+#include "base/guid.h"
+#include "base/logging.h"
+#include "base/thread_task_runner_handle.h"
+#include "base/trace_event/trace_event.h"
+#include "media/base/video_capture_types.h"
+#include "media/capture/service/stream_impl.h"
+#include "media/capture/service/video_capture_device_client_impl.h"
+#include "media/capture/video/video_capture_device_factory.h"
+#include "mojo/converters/geometry/geometry_type_converters.h"
+
+namespace media {
+
+VideoCaptureHandlerImpl::VideoCaptureHandlerImpl(mojo::ApplicationImpl* app)
+ : app_(app),
+ video_capture_device_factory_(
+ media::VideoCaptureDeviceFactory::CreateFactory(
+ base::ThreadTaskRunnerHandle::Get())),
+ weak_factory_(this) {
+ // Enumerating devices is something that takes a while (up to hundred of ms in
+ // certain OSs).
+ // TODO(mcasas): Add a UMA like in VideoCaptureManager::EnumerateDevices().
+ TRACE_EVENT_ASYNC_BEGIN0("video_capture", "EnumerateDeviceNames",
+ this /* id */);
+ video_capture_device_factory_->EnumerateDeviceNames(
+ base::Bind(&VideoCaptureHandlerImpl::OnVideoCaptureDevicesEnumerated,
+ weak_factory_.GetWeakPtr()));
+
+ // Sadly this SystemMonitor does not do much for Video devices unless someone
+ // notifies of changes.
+ // TODO(mcasas): monitor http://crbug.com/584817 and perhaps launch the
+ // appropriate DeviceMonitor from here.
+ base::SystemMonitor::Get()->AddDevicesChangedObserver(this);
+}
+
+VideoCaptureHandlerImpl::~VideoCaptureHandlerImpl() {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ for (const auto& id_and_device_and_stream : device_and_streams_)
+ id_and_device_and_stream.second.first->StopAndDeAllocate();
+
+ base::SystemMonitor::Get()->RemoveDevicesChangedObserver(this);
+}
+
+void VideoCaptureHandlerImpl::EnumerateDevices(
+ const EnumerateDevicesCallback& callback) {
+ DVLOG(1) << __FUNCTION__;
+ DCHECK(thread_checker_.CalledOnValidThread());
+
+ mojo::Array<mojom::VideoCaptureDeviceInfoPtr> reply;
+ if (!device_names_->empty()) {
+ for (const auto& device_name : *device_names_) {
+ mojom::VideoCaptureDeviceInfoPtr video_capture_device_info =
+ mojom::VideoCaptureDeviceInfo::New();
+
+ // Send a GUID of the Video Capture id to hide sensitive information.
+ const std::string guid = base::GenerateGUID();
+ public_to_private_id_map_[guid] = device_name.id();
+ video_capture_device_info->device_id = guid;
+ video_capture_device_info->name = device_name.GetNameAndModel();
+
+ reply.push_back(std::move(video_capture_device_info));
+ }
+ }
+ callback.Run(std::move(reply));
+}
+
+void VideoCaptureHandlerImpl::RequestVideoCaptureStream(
+ mojom::VideoCaptureOptionsPtr options,
+ const RequestVideoCaptureStreamCallback& callback) {
+ DVLOG(1) << __FUNCTION__ << " device guid: " << options->device_id;
+ DCHECK(thread_checker_.CalledOnValidThread());
+
+ const std::string& guid = options->device_id;
+ if (!ContainsKey(public_to_private_id_map_, guid)) {
+ DLOG(ERROR) << "Device identified as " << guid << " not found!";
+ return;
+ }
+
+ // Try to find |options->id| in the list of devices. If not found -> return.
+ const std::string& id = public_to_private_id_map_[guid];
+ auto name = std::find_if(device_names_->begin(), device_names_->end(),
+ [id](const media::VideoCaptureDevice::Name& name) {
+ return name.id() == id;
+ });
+ if (name == device_names_->end()) {
+ DLOG(ERROR) << "device " << options->device_id << " not found.";
+ callback.Run(nullptr);
+ return;
+ }
+
+ // TODO(mcasas): At this point we need to ask the user for permission to use
+ // this device if it hasn't been granted before or elsewhere. Soldier on for
+ // the time being and revisit this part later on.
+
+ media::VideoCaptureParams params;
+ params.requested_format.frame_size = options->capture_size.To<gfx::Size>();
+ params.requested_format.frame_rate = options->frame_rate;
+ params.requested_format.pixel_format = media::PIXEL_FORMAT_I420;
+
+ mojom::VideoCaptureStreamPtr stream_ptr;
+ scoped_ptr<StreamImpl> stream = make_scoped_ptr(new StreamImpl(
+ mojo::GetProxy(&stream_ptr), base::Bind(&VideoCaptureHandlerImpl::OnStart,
+ weak_factory_.GetWeakPtr(), id),
+ base::Bind(&VideoCaptureHandlerImpl::OnStopOrError,
+ weak_factory_.GetWeakPtr(), id),
+ base::Bind(&VideoCaptureHandlerImpl::OnStopOrError,
+ weak_factory_.GetWeakPtr(), id)));
+
+ // Create the found device and Start() with the chosen VideoCaptureParameters.
+ scoped_ptr<media::VideoCaptureDevice> video_capture_device =
+ video_capture_device_factory_->Create(*name);
+ if (!video_capture_device) {
+ DLOG(ERROR) << "device " << id << " could not be created.";
+ callback.Run(nullptr);
+ return;
+ }
+
+ // Create a VideoCaptureDeviceClientImpl using |stream_| as Delegate.
+ scoped_ptr<media::VideoCaptureDevice::Client> device_client(
+ new VideoCaptureDeviceClientImpl(stream.get()));
+ video_capture_device->AllocateAndStart(params, std::move(device_client));
+
+ device_and_streams_.insert(make_pair(
+ id, make_pair(std::move(video_capture_device), std::move(stream))));
+
+ callback.Run(std::move(stream_ptr));
+}
+
+void VideoCaptureHandlerImpl::OnDevicesChanged(
+ base::SystemMonitor::DeviceType device_type) {
+ DVLOG(1) << __FUNCTION__;
+ DCHECK(thread_checker_.CalledOnValidThread());
+
+ // NOTE: This method is only called in response to physical audio/video device
+ // changes (from the operating system).
+
+ if (device_type != base::SystemMonitor::DEVTYPE_VIDEO_CAPTURE)
+ return; // Uninteresting device change.
+
+ TRACE_EVENT_ASYNC_BEGIN0("video_capture", "EnumerateDeviceNames",
+ this /* id */);
+ // Always do enumeration even though some enumeration is in progress, because
+ // those enumeration commands could be sent before these devices change.
+ video_capture_device_factory_->EnumerateDeviceNames(
+ base::Bind(&VideoCaptureHandlerImpl::OnVideoCaptureDevicesEnumerated,
+ weak_factory_.GetWeakPtr()));
+}
+
+void VideoCaptureHandlerImpl::OnVideoCaptureDevicesEnumerated(
+ scoped_ptr<media::VideoCaptureDevice::Names> device_names) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ TRACE_EVENT_ASYNC_END0("video_capture", "EnumerateDeviceNames", this);
+ device_names_ = std::move(device_names);
+
+#if !defined(NDEBUG)
+ for (const auto& device_name : *device_names_) {
+ DVLOG(1) << "device: id: " << device_name.id()
+ << ", name: " << device_name.GetNameAndModel()
+ << ", api: " << device_name.GetCaptureApiTypeString();
+ }
+#endif
+}
+
+void VideoCaptureHandlerImpl::OnStart(const std::string& id) {
+ DVLOG(1) << __FUNCTION__ << " " << id;
+ DCHECK(thread_checker_.CalledOnValidThread());
+ // TODO(mcasas): update some tracking saying that |id| is started ?
+}
+
+void VideoCaptureHandlerImpl::OnStopOrError(const std::string& id) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ const auto& entry = device_and_streams_.find(id);
+ DLOG_IF(ERROR, entry == device_and_streams_.end()) << "Device id " << id
+ << " not found!";
+ if (entry == device_and_streams_.end())
+ return;
+ entry->second.first->StopAndDeAllocate();
+ device_and_streams_.erase(entry);
+}
+
+} // namespace media

Powered by Google App Engine
This is Rietveld 408576698