| 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..78bd724f89d84a89f0e7df709ae79174e1628d79
|
| --- /dev/null
|
| +++ b/media/capture/service/video_capture_handler_impl.cc
|
| @@ -0,0 +1,192 @@
|
| +// 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::RequestMediaDevices(
|
| + const RequestMediaDevicesCallback& callback) {
|
| + DVLOG(1) << __FUNCTION__;
|
| + DCHECK(thread_checker_.CalledOnValidThread());
|
| +
|
| + mojo::Array<mojom::WebSourceInfoPtr> reply;
|
| + if (!device_names_->empty()) {
|
| + for (const auto& device_name : *device_names_) {
|
| + mojom::WebSourceInfoPtr web_source_info = mojom::WebSourceInfo::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();
|
| + web_source_info->device_id = guid;
|
| +
|
| + web_source_info->label = device_name.GetNameAndModel();
|
| + web_source_info->kind = mojom::SourceKind::Video;
|
| + web_source_info->facing_mode = mojom::VideoFacingMode::None;
|
| +
|
| + reply.push_back(std::move(web_source_info));
|
| + }
|
| + }
|
| + callback.Run(std::move(reply));
|
| +}
|
| +
|
| +void VideoCaptureHandlerImpl::RequestStream(
|
| + mojom::StreamOptionsPtr options,
|
| + const mojo::String& security_origin,
|
| + const RequestStreamCallback& 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::StreamPtr 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
|
|
|