| Index: content/browser/renderer_host/media/in_process_buildable_video_capture_device.cc
|
| diff --git a/content/browser/renderer_host/media/video_capture_manager.cc b/content/browser/renderer_host/media/in_process_buildable_video_capture_device.cc
|
| similarity index 14%
|
| copy from content/browser/renderer_host/media/video_capture_manager.cc
|
| copy to content/browser/renderer_host/media/in_process_buildable_video_capture_device.cc
|
| index 2118857ecee7866c2e984854298eaee4c37e217e..4536b5335044f3cd6155ae5249eb24d2e1d03ce9 100644
|
| --- a/content/browser/renderer_host/media/video_capture_manager.cc
|
| +++ b/content/browser/renderer_host/media/in_process_buildable_video_capture_device.cc
|
| @@ -1,62 +1,36 @@
|
| -// Copyright (c) 2012 The Chromium Authors. All rights reserved.
|
| +// Copyright 2017 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/renderer_host/media/video_capture_manager.h"
|
| +#include "content/browser/renderer_host/media/in_process_buildable_video_capture_device.h"
|
|
|
| -#include <algorithm>
|
| -#include <set>
|
| -#include <utility>
|
| -
|
| -#include "base/bind.h"
|
| -#include "base/bind_helpers.h"
|
| -#include "base/command_line.h"
|
| -#include "base/location.h"
|
| -#include "base/logging.h"
|
| -#include "base/memory/ptr_util.h"
|
| #include "base/metrics/histogram_macros.h"
|
| -#include "base/single_thread_task_runner.h"
|
| -#include "base/stl_util.h"
|
| #include "base/strings/stringprintf.h"
|
| -#include "base/task_runner_util.h"
|
| -#include "base/threading/sequenced_worker_pool.h"
|
| -#include "base/threading/thread_task_runner_handle.h"
|
| -#include "build/build_config.h"
|
| #include "content/browser/media/capture/desktop_capture_device_uma_types.h"
|
| #include "content/browser/media/capture/web_contents_video_capture_device.h"
|
| -#include "content/browser/media/media_internals.h"
|
| #include "content/browser/renderer_host/media/video_capture_controller.h"
|
| -#include "content/browser/renderer_host/media/video_capture_controller_event_handler.h"
|
| #include "content/browser/renderer_host/media/video_capture_gpu_jpeg_decoder.h"
|
| #include "content/browser/renderer_host/media/video_frame_receiver_on_io_thread.h"
|
| #include "content/public/browser/browser_thread.h"
|
| #include "content/public/browser/desktop_media_id.h"
|
| #include "content/public/common/media_stream_request.h"
|
| #include "media/base/bind_to_current_loop.h"
|
| -#include "media/base/media_switches.h"
|
| -#include "media/base/video_facing.h"
|
| #include "media/capture/video/video_capture_buffer_pool_impl.h"
|
| #include "media/capture/video/video_capture_buffer_tracker_factory_impl.h"
|
| -#include "media/capture/video/video_capture_device.h"
|
| #include "media/capture/video/video_capture_device_client.h"
|
| -#include "media/capture/video/video_capture_device_factory.h"
|
| -
|
| -#if defined(ENABLE_SCREEN_CAPTURE)
|
| +#include "media/capture/video/video_frame_receiver.h"
|
|
|
| -#if BUILDFLAG(ENABLE_WEBRTC) && !defined(OS_ANDROID)
|
| +#if defined(ENABLE_SCREEN_CAPTURE) && !defined(OS_ANDROID)
|
| #include "content/browser/media/capture/desktop_capture_device.h"
|
| -#endif
|
| -
|
| #if defined(USE_AURA)
|
| #include "content/browser/media/capture/desktop_capture_device_aura.h"
|
| #endif
|
| +#endif
|
|
|
| -#if defined(OS_ANDROID)
|
| +#if defined(ENABLE_SCREEN_CAPTURE) && defined(OS_ANDROID)
|
| #include "content/browser/media/capture/screen_capture_device_android.h"
|
| #endif
|
|
|
| -#endif // defined(ENABLE_SCREEN_CAPTURE)
|
| -
|
| namespace {
|
|
|
| class VideoFrameConsumerFeedbackObserverOnTaskRunner
|
| @@ -80,49 +54,18 @@ class VideoFrameConsumerFeedbackObserverOnTaskRunner
|
| const scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
|
| };
|
|
|
| -// Compares two VideoCaptureFormat by checking smallest frame_size area, then
|
| -// by _largest_ frame_rate. Used to order a VideoCaptureFormats vector so that
|
| -// the first entry for a given resolution has the largest frame rate, as needed
|
| -// by the ConsolidateCaptureFormats() method.
|
| -bool IsCaptureFormatSmaller(const media::VideoCaptureFormat& format1,
|
| - const media::VideoCaptureFormat& format2) {
|
| - DCHECK(format1.frame_size.GetCheckedArea().IsValid());
|
| - DCHECK(format2.frame_size.GetCheckedArea().IsValid());
|
| - if (format1.frame_size.GetCheckedArea().ValueOrDefault(0) ==
|
| - format2.frame_size.GetCheckedArea().ValueOrDefault(0)) {
|
| - return format1.frame_rate > format2.frame_rate;
|
| - }
|
| - return format1.frame_size.GetCheckedArea().ValueOrDefault(0) <
|
| - format2.frame_size.GetCheckedArea().ValueOrDefault(0);
|
| -}
|
| -
|
| -bool IsCaptureFormatSizeEqual(const media::VideoCaptureFormat& format1,
|
| - const media::VideoCaptureFormat& format2) {
|
| - DCHECK(format1.frame_size.GetCheckedArea().IsValid());
|
| - DCHECK(format2.frame_size.GetCheckedArea().IsValid());
|
| - return format1.frame_size.GetCheckedArea().ValueOrDefault(0) ==
|
| - format2.frame_size.GetCheckedArea().ValueOrDefault(0);
|
| +std::unique_ptr<media::VideoCaptureJpegDecoder> CreateGpuJpegDecoder(
|
| + const media::VideoCaptureJpegDecoder::DecodeDoneCB& decode_done_cb) {
|
| + return base::MakeUnique<content::VideoCaptureGpuJpegDecoder>(decode_done_cb);
|
| }
|
|
|
| -// This function receives a list of capture formats, removes duplicated
|
| -// resolutions while keeping the highest frame rate for each, and forcing I420
|
| -// pixel format.
|
| -void ConsolidateCaptureFormats(media::VideoCaptureFormats* formats) {
|
| - if (formats->empty())
|
| - return;
|
| - std::sort(formats->begin(), formats->end(), IsCaptureFormatSmaller);
|
| - // Due to the ordering imposed, the largest frame_rate is kept while removing
|
| - // duplicated resolutions.
|
| - media::VideoCaptureFormats::iterator last =
|
| - std::unique(formats->begin(), formats->end(), IsCaptureFormatSizeEqual);
|
| - formats->erase(last, formats->end());
|
| - // Mark all formats as I420, since this is what the renderer side will get
|
| - // anyhow: the actual pixel format is decided at the device level.
|
| - // Don't do this for Y16 format as it is handled separatelly.
|
| - for (auto& format : *formats) {
|
| - if (format.pixel_format != media::PIXEL_FORMAT_Y16)
|
| - format.pixel_format = media::PIXEL_FORMAT_I420;
|
| - }
|
| +void StopAndReleaseDeviceOnDeviceThread(media::VideoCaptureDevice* device,
|
| + base::OnceClosure done_cb) {
|
| + SCOPED_UMA_HISTOGRAM_TIMER("Media.VideoCaptureManager.StopDeviceTime");
|
| + device->StopAndDeAllocate();
|
| + DVLOG(3) << "StopAndReleaseDeviceOnDeviceThread";
|
| + delete device;
|
| + std::move(done_cb).Run();
|
| }
|
|
|
| // The maximum number of video frame buffers in-flight at any one time. This
|
| @@ -135,540 +78,315 @@ const int kMaxNumberOfBuffers = 3;
|
| // http://crbug.com/460318
|
| const int kMaxNumberOfBuffersForTabCapture = 10;
|
|
|
| -// Used for logging capture events.
|
| -// Elements in this enum should not be deleted or rearranged; the only
|
| -// permitted operation is to add new elements before NUM_VIDEO_CAPTURE_EVENT.
|
| -enum VideoCaptureEvent {
|
| - VIDEO_CAPTURE_START_CAPTURE = 0,
|
| - VIDEO_CAPTURE_STOP_CAPTURE_OK = 1,
|
| - VIDEO_CAPTURE_STOP_CAPTURE_DUE_TO_ERROR = 2,
|
| - VIDEO_CAPTURE_STOP_CAPTURE_OK_NO_FRAMES_PRODUCED_BY_DEVICE = 3,
|
| - VIDEO_CAPTURE_STOP_CAPTURE_OK_NO_FRAMES_PRODUCED_BY_DESKTOP_OR_TAB = 4,
|
| - NUM_VIDEO_CAPTURE_EVENT
|
| -};
|
| -
|
| -void LogVideoCaptureEvent(VideoCaptureEvent event) {
|
| - UMA_HISTOGRAM_ENUMERATION("Media.VideoCaptureManager.Event",
|
| - event,
|
| - NUM_VIDEO_CAPTURE_EVENT);
|
| -}
|
| -
|
| -// Counter used for identifying a DeviceRequest to start a capture device.
|
| -static int g_device_start_id = 0;
|
| -
|
| -const media::VideoCaptureSessionId kFakeSessionId = -1;
|
| -
|
| -std::unique_ptr<media::VideoCaptureJpegDecoder> CreateGpuJpegDecoder(
|
| - const media::VideoCaptureJpegDecoder::DecodeDoneCB& decode_done_cb) {
|
| - return base::MakeUnique<content::VideoCaptureGpuJpegDecoder>(decode_done_cb);
|
| -}
|
| -
|
| -} // namespace
|
| +} // anonymous namespace
|
|
|
| namespace content {
|
|
|
| -// Instances of this struct go through several different phases during their
|
| -// lifetime.
|
| -// Phase 1: When first created (in GetOrCreateDeviceEntry()), this consists of
|
| -// only the |video_capture_controller|. Clients can already connect to the
|
| -// controller, but there is no |video_capture_device| present.
|
| -// Phase 2: When a request to "start" the entry comes in (via
|
| -// HandleQueuedStartRequest()), creation of |video_capture_device| is scheduled
|
| -// to run asynchronously on the Device Thread.
|
| -// Phase 3: As soon as the creation of the VideoCaptureDevice is complete, this
|
| -// newly created VideoCaptureDevice instance is connected to the
|
| -// VideoCaptureController via SetConsumerFeedbackObserver().
|
| -// Phase 4: This phase can only be reached on Android. When the application goes
|
| -// to the background, the |video_capture_device| is asynchronously stopped and
|
| -// released on the Device Thread. When the application is resumed, we
|
| -// transition to Phase 2.
|
| -struct VideoCaptureManager::DeviceEntry {
|
| - public:
|
| - DeviceEntry(MediaStreamType stream_type,
|
| - const std::string& id,
|
| - const media::VideoCaptureParams& params);
|
| - ~DeviceEntry();
|
| - std::unique_ptr<media::VideoCaptureDevice::Client> CreateDeviceClient();
|
| -
|
| - const int serial_id;
|
| - const MediaStreamType stream_type;
|
| - const std::string id;
|
| - const media::VideoCaptureParams parameters;
|
| - VideoCaptureController video_capture_controller;
|
| - std::unique_ptr<media::VideoCaptureDevice> video_capture_device;
|
| -};
|
| -
|
| -// Bundles a media::VideoCaptureDeviceDescriptor with corresponding supported
|
| -// video formats.
|
| -struct VideoCaptureManager::DeviceInfo {
|
| - DeviceInfo();
|
| - DeviceInfo(media::VideoCaptureDeviceDescriptor descriptor);
|
| - DeviceInfo(const DeviceInfo& other);
|
| - ~DeviceInfo();
|
| - DeviceInfo& operator=(const DeviceInfo& other);
|
| -
|
| - media::VideoCaptureDeviceDescriptor descriptor;
|
| - media::VideoCaptureFormats supported_formats;
|
| -};
|
| -
|
| -// Class used for queuing request for starting a device.
|
| -class VideoCaptureManager::CaptureDeviceStartRequest {
|
| - public:
|
| - CaptureDeviceStartRequest(int serial_id,
|
| - media::VideoCaptureSessionId session_id,
|
| - const media::VideoCaptureParams& params);
|
| - int serial_id() const { return serial_id_; }
|
| - media::VideoCaptureSessionId session_id() const { return session_id_; }
|
| - media::VideoCaptureParams params() const { return params_; }
|
| -
|
| - // Set to true if the device should be stopped before it has successfully
|
| - // been started.
|
| - bool abort_start() const { return abort_start_; }
|
| - void set_abort_start() { abort_start_ = true; }
|
| -
|
| - private:
|
| - const int serial_id_;
|
| - const media::VideoCaptureSessionId session_id_;
|
| - const media::VideoCaptureParams params_;
|
| - // Set to true if the device should be stopped before it has successfully
|
| - // been started.
|
| - bool abort_start_;
|
| -};
|
| -
|
| -VideoCaptureManager::DeviceEntry::DeviceEntry(
|
| - MediaStreamType stream_type,
|
| - const std::string& id,
|
| - const media::VideoCaptureParams& params)
|
| - : serial_id(g_device_start_id++),
|
| - stream_type(stream_type),
|
| - id(id),
|
| - parameters(params) {}
|
| +InProcessBuildableVideoCaptureDevice::InProcessBuildableVideoCaptureDevice(
|
| + scoped_refptr<base::SingleThreadTaskRunner> device_task_runner,
|
| + media::VideoCaptureDeviceFactory* device_factory)
|
| + : device_task_runner_(std::move(device_task_runner)),
|
| + device_factory_(device_factory) {}
|
|
|
| -VideoCaptureManager::DeviceEntry::~DeviceEntry() {
|
| +InProcessBuildableVideoCaptureDevice::~InProcessBuildableVideoCaptureDevice() {
|
| DCHECK_CURRENTLY_ON(BrowserThread::IO);
|
| - // DCHECK that this DeviceEntry does not still own a
|
| - // media::VideoCaptureDevice. media::VideoCaptureDevice must be deleted on
|
| - // the device thread.
|
| - DCHECK(video_capture_device == nullptr);
|
| + DCHECK(!device_);
|
| }
|
|
|
| -std::unique_ptr<media::VideoCaptureDevice::Client>
|
| -VideoCaptureManager::DeviceEntry::CreateDeviceClient() {
|
| +void InProcessBuildableVideoCaptureDevice::CreateAndStartDeviceAsync(
|
| + VideoCaptureController* controller,
|
| + const media::VideoCaptureParams& params,
|
| + BuildableDeviceCallbacks* callbacks,
|
| + base::OnceClosure done_cb) {
|
| DCHECK_CURRENTLY_ON(BrowserThread::IO);
|
|
|
| - const int max_buffers = stream_type == MEDIA_TAB_VIDEO_CAPTURE
|
| - ? kMaxNumberOfBuffersForTabCapture
|
| - : kMaxNumberOfBuffers;
|
| - scoped_refptr<media::VideoCaptureBufferPool> buffer_pool =
|
| - new media::VideoCaptureBufferPoolImpl(
|
| - base::MakeUnique<media::VideoCaptureBufferTrackerFactoryImpl>(),
|
| - max_buffers);
|
| + const int max_buffers = (controller->stream_type() == MEDIA_TAB_VIDEO_CAPTURE
|
| + ? kMaxNumberOfBuffersForTabCapture
|
| + : kMaxNumberOfBuffers);
|
|
|
| - return base::MakeUnique<media::VideoCaptureDeviceClient>(
|
| - base::MakeUnique<VideoFrameReceiverOnIOThread>(
|
| - video_capture_controller.GetWeakPtrForIOThread()),
|
| - std::move(buffer_pool),
|
| - base::Bind(&CreateGpuJpegDecoder,
|
| - base::Bind(&media::VideoFrameReceiver::OnFrameReadyInBuffer,
|
| - video_capture_controller.GetWeakPtrForIOThread())));
|
| -}
|
| -
|
| -VideoCaptureManager::DeviceInfo::DeviceInfo() = default;
|
| -
|
| -VideoCaptureManager::DeviceInfo::DeviceInfo(
|
| - media::VideoCaptureDeviceDescriptor descriptor)
|
| - : descriptor(descriptor) {}
|
| -
|
| -VideoCaptureManager::DeviceInfo::DeviceInfo(
|
| - const VideoCaptureManager::DeviceInfo& other) = default;
|
| + auto device_client =
|
| + CreateDeviceClient(max_buffers, controller->GetWeakPtrForIOThread());
|
|
|
| -VideoCaptureManager::DeviceInfo::~DeviceInfo() = default;
|
| -
|
| -VideoCaptureManager::DeviceInfo& VideoCaptureManager::DeviceInfo::operator=(
|
| - const VideoCaptureManager::DeviceInfo& other) = default;
|
| -
|
| -VideoCaptureManager::CaptureDeviceStartRequest::CaptureDeviceStartRequest(
|
| - int serial_id,
|
| - media::VideoCaptureSessionId session_id,
|
| - const media::VideoCaptureParams& params)
|
| - : serial_id_(serial_id),
|
| - session_id_(session_id),
|
| - params_(params),
|
| - abort_start_(false) {
|
| -}
|
| -
|
| -VideoCaptureManager::VideoCaptureManager(
|
| - std::unique_ptr<media::VideoCaptureDeviceFactory> factory,
|
| - scoped_refptr<base::SingleThreadTaskRunner> device_task_runner)
|
| - : device_task_runner_(std::move(device_task_runner)),
|
| - new_capture_session_id_(1),
|
| - video_capture_device_factory_(std::move(factory)) {}
|
| + base::Closure start_capture_closure;
|
| + switch (controller->stream_type()) {
|
| + case MEDIA_DEVICE_VIDEO_CAPTURE: {
|
| + const media::VideoCaptureDeviceDescriptor* descriptor =
|
| + callbacks->LookupDeviceDescriptor(controller->device_id());
|
| + if (descriptor) {
|
| + controller->OnLog(
|
| + base::StringPrintf("Starting device: id: %s, name: %s, api: %s",
|
| + descriptor->device_id.c_str(),
|
| + descriptor->GetNameAndModel().c_str(),
|
| + descriptor->GetCaptureApiTypeString()));
|
| +
|
| + callbacks->WillStartDevice(descriptor->facing);
|
| +
|
| + // Use of Unretained() is safe, because |context_reference| guarantees
|
| + // that |this| stays alive.
|
| + ReceiveDeviceCallback after_start_capture_callback =
|
| + media::BindToCurrentLoop(base::Bind(
|
| + &InProcessBuildableVideoCaptureDevice::OnDeviceStarted,
|
| + base::Unretained(this), controller, callbacks,
|
| + base::Passed(&done_cb)));
|
| + start_capture_closure =
|
| + base::Bind(&InProcessBuildableVideoCaptureDevice::
|
| + DoStartDeviceCaptureOnDeviceThread,
|
| + base::Unretained(this), *descriptor, params,
|
| + base::Passed(std::move(device_client)),
|
| + std::move(after_start_capture_callback));
|
| + } else {
|
| + callbacks->OnDeviceStartFailed(controller);
|
| + std::move(done_cb).Run();
|
| + return;
|
| + }
|
| + break;
|
| + }
|
| + case MEDIA_TAB_VIDEO_CAPTURE: {
|
| + // Use of Unretained() is safe, because |context_reference| guarantees
|
| + // that |this| stays alive.
|
| + ReceiveDeviceCallback after_start_capture_callback =
|
| + media::BindToCurrentLoop(
|
| + base::Bind(&InProcessBuildableVideoCaptureDevice::OnDeviceStarted,
|
| + base::Unretained(this), controller, callbacks,
|
| + base::Passed(&done_cb)));
|
| + start_capture_closure =
|
| + base::Bind(&InProcessBuildableVideoCaptureDevice::
|
| + DoStartTabCaptureOnDeviceThread,
|
| + base::Unretained(this), controller->device_id(), params,
|
| + base::Passed(std::move(device_client)),
|
| + std::move(after_start_capture_callback));
|
| + break;
|
| + }
|
| + case MEDIA_DESKTOP_VIDEO_CAPTURE: {
|
| + // Use of Unretained() is safe, because |context_reference| guarantees
|
| + // that |this| stays alive.
|
| + ReceiveDeviceCallback after_start_capture_callback =
|
| + media::BindToCurrentLoop(
|
| + base::Bind(&InProcessBuildableVideoCaptureDevice::OnDeviceStarted,
|
| + base::Unretained(this), controller, callbacks,
|
| + base::Passed(&done_cb)));
|
| + start_capture_closure =
|
| + base::Bind(&InProcessBuildableVideoCaptureDevice::
|
| + DoStartDesktopCaptureOnDeviceThread,
|
| + base::Unretained(this), controller->device_id(), params,
|
| + base::Passed(std::move(device_client)),
|
| + std::move(after_start_capture_callback));
|
| + break;
|
| + }
|
| + default: {
|
| + NOTIMPLEMENTED();
|
| + return;
|
| + }
|
| + }
|
|
|
| -VideoCaptureManager::~VideoCaptureManager() {
|
| - DCHECK(devices_.empty());
|
| - DCHECK(device_start_queue_.empty());
|
| + device_task_runner_->PostTask(FROM_HERE, start_capture_closure);
|
| }
|
|
|
| -void VideoCaptureManager::AddVideoCaptureObserver(
|
| - media::VideoCaptureObserver* observer) {
|
| - DCHECK(observer);
|
| +void InProcessBuildableVideoCaptureDevice::ReleaseDeviceAsync(
|
| + VideoCaptureController* controller,
|
| + base::OnceClosure done_cb) {
|
| DCHECK_CURRENTLY_ON(BrowserThread::IO);
|
| - capture_observers_.AddObserver(observer);
|
| + controller->SetConsumerFeedbackObserver(nullptr);
|
| + if (!device_)
|
| + return;
|
| + media::VideoCaptureDevice* device_ptr = device_.release();
|
| +
|
| + bool posting_task_succeeded = device_task_runner_->PostTask(
|
| + FROM_HERE,
|
| + base::Bind(&StopAndReleaseDeviceOnDeviceThread, device_ptr,
|
| + base::Bind([](scoped_refptr<base::SingleThreadTaskRunner>) {},
|
| + device_task_runner_)));
|
| + if (posting_task_succeeded == false) {
|
| + // Since posting to the task runner has failed, we attempt doing it on
|
| + // the calling thread instead.
|
| + StopAndReleaseDeviceOnDeviceThread(device_ptr, base::Bind([]() {}));
|
| + }
|
| + std::move(done_cb).Run();
|
| }
|
|
|
| -void VideoCaptureManager::RemoveAllVideoCaptureObservers() {
|
| +bool InProcessBuildableVideoCaptureDevice::IsDeviceAlive() const {
|
| DCHECK_CURRENTLY_ON(BrowserThread::IO);
|
| - capture_observers_.Clear();
|
| + return device_ != nullptr;
|
| }
|
|
|
| -void VideoCaptureManager::RegisterListener(
|
| - MediaStreamProviderListener* listener) {
|
| +void InProcessBuildableVideoCaptureDevice::GetPhotoCapabilities(
|
| + media::VideoCaptureDevice::GetPhotoCapabilitiesCallback callback) const {
|
| DCHECK_CURRENTLY_ON(BrowserThread::IO);
|
| - DCHECK(listener);
|
| - DCHECK(device_task_runner_);
|
| - listeners_.AddObserver(listener);
|
| -#if defined(OS_ANDROID)
|
| - application_state_has_running_activities_ = true;
|
| - app_status_listener_.reset(new base::android::ApplicationStatusListener(
|
| - base::Bind(&VideoCaptureManager::OnApplicationStateChange,
|
| - base::Unretained(this))));
|
| -#endif
|
| + // Unretained() is safe to use here because |device| would be null if it
|
| + // was scheduled for shutdown and destruction, and because this task is
|
| + // guaranteed to run before the task that destroys the |device|.
|
| + device_task_runner_->PostTask(
|
| + FROM_HERE,
|
| + base::Bind(&media::VideoCaptureDevice::GetPhotoCapabilities,
|
| + base::Unretained(device_.get()), base::Passed(&callback)));
|
| }
|
|
|
| -void VideoCaptureManager::UnregisterListener(
|
| - MediaStreamProviderListener* listener) {
|
| +void InProcessBuildableVideoCaptureDevice::SetPhotoOptions(
|
| + media::mojom::PhotoSettingsPtr settings,
|
| + media::VideoCaptureDevice::SetPhotoOptionsCallback callback) {
|
| DCHECK_CURRENTLY_ON(BrowserThread::IO);
|
| - listeners_.RemoveObserver(listener);
|
| + // Unretained() is safe to use here because |device| would be null if it
|
| + // was scheduled for shutdown and destruction, and because this task is
|
| + // guaranteed to run before the task that destroys the |device|.
|
| + device_task_runner_->PostTask(
|
| + FROM_HERE, base::Bind(&media::VideoCaptureDevice::SetPhotoOptions,
|
| + base::Unretained(device_.get()),
|
| + base::Passed(&settings), base::Passed(&callback)));
|
| }
|
|
|
| -void VideoCaptureManager::EnumerateDevices(
|
| - const EnumerationCallback& client_callback) {
|
| +void InProcessBuildableVideoCaptureDevice::TakePhoto(
|
| + media::VideoCaptureDevice::TakePhotoCallback callback) {
|
| DCHECK_CURRENTLY_ON(BrowserThread::IO);
|
| - DVLOG(1) << "VideoCaptureManager::EnumerateDevices";
|
| -
|
| - // Bind a callback to ConsolidateDevicesInfoOnDeviceThread() with an argument
|
| - // for another callback to OnDevicesInfoEnumerated() to be run in the current
|
| - // loop, i.e. IO loop. Pass a timer for UMA histogram collection.
|
| - base::Callback<void(std::unique_ptr<VideoCaptureDeviceDescriptors>)>
|
| - devices_enumerated_callback = base::Bind(
|
| - &VideoCaptureManager::ConsolidateDevicesInfoOnDeviceThread, this,
|
| - media::BindToCurrentLoop(base::Bind(
|
| - &VideoCaptureManager::OnDevicesInfoEnumerated, this,
|
| - base::Owned(new base::ElapsedTimer()), client_callback)),
|
| - devices_info_cache_);
|
| - // OK to use base::Unretained() since we own the VCDFactory and |this| is
|
| - // bound in |devices_enumerated_callback|.
|
| + // Unretained() is safe to use here because |device| would be null if it
|
| + // was scheduled for shutdown and destruction, and because this task is
|
| + // guaranteed to run before the task that destroys the |device|.
|
| device_task_runner_->PostTask(
|
| FROM_HERE,
|
| - base::Bind(&media::VideoCaptureDeviceFactory::EnumerateDeviceDescriptors,
|
| - base::Unretained(video_capture_device_factory_.get()),
|
| - devices_enumerated_callback));
|
| + base::Bind(&media::VideoCaptureDevice::TakePhoto,
|
| + base::Unretained(device_.get()), base::Passed(&callback)));
|
| }
|
|
|
| -int VideoCaptureManager::Open(const MediaStreamDevice& device) {
|
| +void InProcessBuildableVideoCaptureDevice::MaybeSuspendDevice() {
|
| DCHECK_CURRENTLY_ON(BrowserThread::IO);
|
| -
|
| - // Generate a new id for the session being opened.
|
| - const media::VideoCaptureSessionId capture_session_id =
|
| - new_capture_session_id_++;
|
| -
|
| - DCHECK(sessions_.find(capture_session_id) == sessions_.end());
|
| - DVLOG(1) << "VideoCaptureManager::Open, id " << capture_session_id;
|
| -
|
| - // We just save the stream info for processing later.
|
| - sessions_[capture_session_id] = device;
|
| -
|
| - // Notify our listener asynchronously; this ensures that we return
|
| - // |capture_session_id| to the caller of this function before using that same
|
| - // id in a listener event.
|
| - base::ThreadTaskRunnerHandle::Get()->PostTask(
|
| - FROM_HERE, base::Bind(&VideoCaptureManager::OnOpened, this, device.type,
|
| - capture_session_id));
|
| - return capture_session_id;
|
| + // Unretained() is safe to use here because |device| would be null if it
|
| + // was scheduled for shutdown and destruction, and because this task is
|
| + // guaranteed to run before the task that destroys the |device|.
|
| + device_task_runner_->PostTask(
|
| + FROM_HERE, base::Bind(&media::VideoCaptureDevice::MaybeSuspend,
|
| + base::Unretained(device_.get())));
|
| }
|
|
|
| -void VideoCaptureManager::Close(int capture_session_id) {
|
| +void InProcessBuildableVideoCaptureDevice::ResumeDevice() {
|
| DCHECK_CURRENTLY_ON(BrowserThread::IO);
|
| - DVLOG(1) << "VideoCaptureManager::Close, id " << capture_session_id;
|
| -
|
| - SessionMap::iterator session_it = sessions_.find(capture_session_id);
|
| - if (session_it == sessions_.end()) {
|
| - NOTREACHED();
|
| - return;
|
| - }
|
| -
|
| - DeviceEntry* const existing_device =
|
| - GetDeviceEntryByTypeAndId(session_it->second.type, session_it->second.id);
|
| - if (existing_device) {
|
| - // Remove any client that is still using the session. This is safe to call
|
| - // even if there are no clients using the session.
|
| - existing_device->video_capture_controller.StopSession(capture_session_id);
|
| -
|
| - // StopSession() may have removed the last client, so we might need to
|
| - // close the device.
|
| - DestroyDeviceEntryIfNoClients(existing_device);
|
| - }
|
| -
|
| - // Notify listeners asynchronously, and forget the session.
|
| - base::ThreadTaskRunnerHandle::Get()->PostTask(
|
| - FROM_HERE, base::Bind(&VideoCaptureManager::OnClosed, this,
|
| - session_it->second.type, capture_session_id));
|
| - sessions_.erase(session_it);
|
| + // Unretained() is safe to use here because |device| would be null if it
|
| + // was scheduled for shutdown and destruction, and because this task is
|
| + // guaranteed to run before the task that destroys the |device|.
|
| + device_task_runner_->PostTask(FROM_HERE,
|
| + base::Bind(&media::VideoCaptureDevice::Resume,
|
| + base::Unretained(device_.get())));
|
| }
|
|
|
| -void VideoCaptureManager::QueueStartDevice(
|
| - media::VideoCaptureSessionId session_id,
|
| - DeviceEntry* entry,
|
| - const media::VideoCaptureParams& params) {
|
| +void InProcessBuildableVideoCaptureDevice::RequestRefreshFrame() {
|
| DCHECK_CURRENTLY_ON(BrowserThread::IO);
|
| - device_start_queue_.push_back(
|
| - CaptureDeviceStartRequest(entry->serial_id, session_id, params));
|
| - if (device_start_queue_.size() == 1)
|
| - HandleQueuedStartRequest();
|
| + // Unretained() is safe to use here because |device| would be null if it
|
| + // was scheduled for shutdown and destruction, and because this task is
|
| + // guaranteed to run before the task that destroys the |device|.
|
| + device_task_runner_->PostTask(
|
| + FROM_HERE, base::Bind(&media::VideoCaptureDevice::RequestRefreshFrame,
|
| + base::Unretained(device_.get())));
|
| }
|
|
|
| -void VideoCaptureManager::DoStopDevice(DeviceEntry* entry) {
|
| +void InProcessBuildableVideoCaptureDevice::SetDesktopCaptureWindowIdAsync(
|
| + gfx::NativeViewId window_id,
|
| + base::OnceClosure done_cb) {
|
| DCHECK_CURRENTLY_ON(BrowserThread::IO);
|
| - // TODO(mcasas): use a helper function https://crbug.com/624854.
|
| - DCHECK(
|
| - std::find_if(devices_.begin(), devices_.end(),
|
| - [entry](const std::unique_ptr<DeviceEntry>& device_entry) {
|
| - return device_entry.get() == entry;
|
| - }) != devices_.end());
|
| -
|
| - // Find the matching start request.
|
| - for (DeviceStartQueue::reverse_iterator request =
|
| - device_start_queue_.rbegin();
|
| - request != device_start_queue_.rend(); ++request) {
|
| - if (request->serial_id() == entry->serial_id) {
|
| - request->set_abort_start();
|
| - DVLOG(3) << "DoStopDevice, aborting start request for device "
|
| - << entry->id << " serial_id = " << entry->serial_id;
|
| - return;
|
| - }
|
| - }
|
| -
|
| - const DeviceInfo* device_info = GetDeviceInfoById(entry->id);
|
| - if (device_info != nullptr) {
|
| - for (auto& observer : capture_observers_)
|
| - observer.OnVideoCaptureStopped(device_info->descriptor.facing);
|
| - }
|
| -
|
| - DVLOG(3) << "DoStopDevice. Send stop request for device = " << entry->id
|
| - << " serial_id = " << entry->serial_id << ".";
|
| - entry->video_capture_controller.OnLog(
|
| - base::StringPrintf("Stopping device: id: %s", entry->id.c_str()));
|
| - entry->video_capture_controller.SetConsumerFeedbackObserver(nullptr);
|
| -
|
| - // |entry->video_capture_device| can be null if creating the device has
|
| - // failed.
|
| - if (entry->video_capture_device) {
|
| - device_task_runner_->PostTask(
|
| - FROM_HERE,
|
| - base::Bind(&VideoCaptureManager::DoStopDeviceOnDeviceThread, this,
|
| - base::Passed(&entry->video_capture_device)));
|
| - }
|
| + // Post |device_| to the the device_task_runner_. This is safe since the
|
| + // device is destroyed on the device_task_runner_ and |context_reference|
|
| + // guarantees that |this| stays alive.
|
| + device_task_runner_->PostTask(
|
| + FROM_HERE, base::Bind(&InProcessBuildableVideoCaptureDevice::
|
| + SetDesktopCaptureWindowIdOnDeviceThread,
|
| + base::Unretained(this), device_.get(), window_id,
|
| + base::Passed(&done_cb)));
|
| }
|
|
|
| -void VideoCaptureManager::HandleQueuedStartRequest() {
|
| +std::unique_ptr<media::VideoCaptureDeviceClient>
|
| +InProcessBuildableVideoCaptureDevice::CreateDeviceClient(
|
| + int buffer_pool_max_buffer_count,
|
| + base::WeakPtr<media::VideoFrameReceiver> receiver) {
|
| DCHECK_CURRENTLY_ON(BrowserThread::IO);
|
| - // Remove all start requests that have been aborted.
|
| - while (device_start_queue_.begin() != device_start_queue_.end() &&
|
| - device_start_queue_.begin()->abort_start()) {
|
| - device_start_queue_.pop_front();
|
| - }
|
| - DeviceStartQueue::iterator request = device_start_queue_.begin();
|
| - if (request == device_start_queue_.end())
|
| - return;
|
| -
|
| - const int serial_id = request->serial_id();
|
| - DeviceEntry* const entry = GetDeviceEntryBySerialId(serial_id);
|
| - DCHECK(entry);
|
| -
|
| - DVLOG(3) << "HandleQueuedStartRequest, Post start to device thread, device = "
|
| - << entry->id << " start id = " << entry->serial_id;
|
| -
|
| - std::unique_ptr<media::VideoCaptureDevice::Client> device_client =
|
| - entry->CreateDeviceClient();
|
|
|
| - base::Callback<std::unique_ptr<VideoCaptureDevice>(void)>
|
| - start_capture_function;
|
| -
|
| - switch (entry->stream_type) {
|
| - case MEDIA_DEVICE_VIDEO_CAPTURE: {
|
| - // We look up the device id from the renderer in our local enumeration
|
| - // since the renderer does not have all the information that might be
|
| - // held in the browser-side VideoCaptureDevice::Name structure.
|
| - const DeviceInfo* found = GetDeviceInfoById(entry->id);
|
| - if (found) {
|
| - entry->video_capture_controller.OnLog(
|
| - base::StringPrintf("Starting device: id: %s, name: %s, api: %s",
|
| - found->descriptor.device_id.c_str(),
|
| - found->descriptor.GetNameAndModel().c_str(),
|
| - found->descriptor.GetCaptureApiTypeString()));
|
| -
|
| - for (auto& observer : capture_observers_)
|
| - observer.OnVideoCaptureStarted(found->descriptor.facing);
|
| -
|
| - start_capture_function =
|
| - base::Bind(&VideoCaptureManager::DoStartDeviceCaptureOnDeviceThread,
|
| - this, found->descriptor, request->params(),
|
| - base::Passed(std::move(device_client)));
|
| - } else {
|
| - // Errors from DoStartDeviceCaptureOnDeviceThread go via
|
| - // VideoCaptureDeviceClient::OnError, which needs some thread
|
| - // dancing to get errors processed on the IO thread. But since
|
| - // we're on that thread, we call VideoCaptureController
|
| - // methods directly.
|
| - const std::string log_message = base::StringPrintf(
|
| - "Error on %s:%d: device %s unknown. Maybe recently disconnected?",
|
| - __FILE__, __LINE__, entry->id.c_str());
|
| - DLOG(ERROR) << log_message;
|
| - entry->video_capture_controller.OnLog(log_message);
|
| - entry->video_capture_controller.OnError();
|
| - // Drop the failed start request.
|
| - device_start_queue_.pop_front();
|
| -
|
| - return;
|
| - }
|
| - break;
|
| - }
|
| - case MEDIA_TAB_VIDEO_CAPTURE:
|
| - start_capture_function = base::Bind(
|
| - &VideoCaptureManager::DoStartTabCaptureOnDeviceThread, this,
|
| - entry->id, request->params(), base::Passed(std::move(device_client)));
|
| - break;
|
| -
|
| - case MEDIA_DESKTOP_VIDEO_CAPTURE:
|
| - start_capture_function = base::Bind(
|
| - &VideoCaptureManager::DoStartDesktopCaptureOnDeviceThread, this,
|
| - entry->id, request->params(), base::Passed(std::move(device_client)));
|
| - break;
|
| + scoped_refptr<media::VideoCaptureBufferPool> buffer_pool_ =
|
| + new media::VideoCaptureBufferPoolImpl(
|
| + base::MakeUnique<media::VideoCaptureBufferTrackerFactoryImpl>(),
|
| + buffer_pool_max_buffer_count);
|
|
|
| - default: {
|
| - NOTIMPLEMENTED();
|
| - return;
|
| - }
|
| - }
|
| - base::PostTaskAndReplyWithResult(
|
| - device_task_runner_.get(), FROM_HERE, start_capture_function,
|
| - base::Bind(&VideoCaptureManager::OnDeviceStarted, this,
|
| - request->serial_id()));
|
| + return base::MakeUnique<media::VideoCaptureDeviceClient>(
|
| + base::MakeUnique<VideoFrameReceiverOnIOThread>(receiver), buffer_pool_,
|
| + base::Bind(&CreateGpuJpegDecoder,
|
| + base::Bind(&media::VideoFrameReceiver::OnFrameReadyInBuffer,
|
| + receiver)));
|
| }
|
|
|
| -void VideoCaptureManager::OnDeviceStarted(
|
| - int serial_id,
|
| - std::unique_ptr<VideoCaptureDevice> device) {
|
| - DVLOG(3) << __func__;
|
| +void InProcessBuildableVideoCaptureDevice::OnDeviceStarted(
|
| + VideoCaptureController* controller,
|
| + BuildableDeviceCallbacks* callbacks,
|
| + base::OnceClosure done_cb,
|
| + std::unique_ptr<media::VideoCaptureDevice> device) {
|
| DCHECK_CURRENTLY_ON(BrowserThread::IO);
|
| - DCHECK_EQ(serial_id, device_start_queue_.begin()->serial_id());
|
| - // |device| can be null if creation failed in
|
| - // DoStartDeviceCaptureOnDeviceThread.
|
| - if (device_start_queue_.front().abort_start()) {
|
| - // The device is no longer wanted. Stop the device again.
|
| - DVLOG(3) << "OnDeviceStarted but start request have been aborted.";
|
| - media::VideoCaptureDevice* device_ptr = device.get();
|
| - base::Closure closure =
|
| - base::Bind(&VideoCaptureManager::DoStopDeviceOnDeviceThread, this,
|
| - base::Passed(&device));
|
| - if (device_ptr && !device_task_runner_->PostTask(FROM_HERE, closure)) {
|
| - // PostTask failed. The device must be stopped anyway.
|
| - device_ptr->StopAndDeAllocate();
|
| - }
|
| - } else {
|
| - DeviceEntry* const entry = GetDeviceEntryBySerialId(serial_id);
|
| - DCHECK(entry);
|
| - DCHECK(!entry->video_capture_device);
|
| - if (device) {
|
| - // Passing raw pointer |device.get()| to the controller is safe,
|
| - // because we transfer ownership of it to |entry|. We are calling
|
| - // SetConsumerFeedbackObserver(nullptr) before releasing
|
| - // |entry->video_capture_device_| on the |device_task_runner_|.
|
| - entry->video_capture_controller.SetConsumerFeedbackObserver(
|
| - base::MakeUnique<VideoFrameConsumerFeedbackObserverOnTaskRunner>(
|
| - device.get(), device_task_runner_));
|
| - }
|
| - entry->video_capture_device = std::move(device);
|
| -
|
| - if (entry->stream_type == MEDIA_DESKTOP_VIDEO_CAPTURE) {
|
| - const media::VideoCaptureSessionId session_id =
|
| - device_start_queue_.front().session_id();
|
| - DCHECK(session_id != kFakeSessionId);
|
| - MaybePostDesktopCaptureWindowId(session_id);
|
| - }
|
| -
|
| - auto it = photo_request_queue_.begin();
|
| - while (it != photo_request_queue_.end()) {
|
| - auto request = it++;
|
| - DeviceEntry* maybe_entry = GetDeviceEntryBySessionId(request->first);
|
| - if (maybe_entry && maybe_entry->video_capture_device) {
|
| - request->second.Run(maybe_entry->video_capture_device.get());
|
| - photo_request_queue_.erase(request);
|
| - }
|
| - }
|
| + if (!device) {
|
| + callbacks->OnDeviceStartFailed(controller);
|
| + std::move(done_cb).Run();
|
| + return;
|
| }
|
| -
|
| - device_start_queue_.pop_front();
|
| - HandleQueuedStartRequest();
|
| + // Passing raw pointer |device.get()| to the controller is safe,
|
| + // because we take ownership of |device| and we call
|
| + // controller->SetConsumerFeedbackObserver(nullptr) before releasing |device|.
|
| + controller->SetConsumerFeedbackObserver(
|
| + base::MakeUnique<VideoFrameConsumerFeedbackObserverOnTaskRunner>(
|
| + device.get(), device_task_runner_));
|
| + device_ = std::move(device);
|
| + callbacks->DidStartDevice(controller);
|
| + std::move(done_cb).Run();
|
| }
|
|
|
| -std::unique_ptr<media::VideoCaptureDevice>
|
| -VideoCaptureManager::DoStartDeviceCaptureOnDeviceThread(
|
| - const VideoCaptureDeviceDescriptor& descriptor,
|
| +void InProcessBuildableVideoCaptureDevice::DoStartDeviceCaptureOnDeviceThread(
|
| + const media::VideoCaptureDeviceDescriptor& descriptor,
|
| const media::VideoCaptureParams& params,
|
| - std::unique_ptr<VideoCaptureDevice::Client> device_client) {
|
| + std::unique_ptr<media::VideoCaptureDeviceClient> device_client,
|
| + ReceiveDeviceCallback result_callback) {
|
| SCOPED_UMA_HISTOGRAM_TIMER("Media.VideoCaptureManager.StartDeviceTime");
|
| - DCHECK(IsOnDeviceThread());
|
| + DCHECK(device_task_runner_->BelongsToCurrentThread());
|
|
|
| - std::unique_ptr<VideoCaptureDevice> video_capture_device;
|
| - video_capture_device =
|
| - video_capture_device_factory_->CreateDevice(descriptor);
|
| + std::unique_ptr<media::VideoCaptureDevice> video_capture_device =
|
| + device_factory_->CreateDevice(descriptor);
|
|
|
| if (!video_capture_device) {
|
| - device_client->OnError(FROM_HERE, "Could not create capture device");
|
| - return nullptr;
|
| + result_callback.Run(nullptr);
|
| + return;
|
| }
|
|
|
| video_capture_device->AllocateAndStart(params, std::move(device_client));
|
| - return video_capture_device;
|
| + result_callback.Run(std::move(video_capture_device));
|
| }
|
|
|
| -std::unique_ptr<media::VideoCaptureDevice>
|
| -VideoCaptureManager::DoStartTabCaptureOnDeviceThread(
|
| +void InProcessBuildableVideoCaptureDevice::DoStartTabCaptureOnDeviceThread(
|
| const std::string& id,
|
| const media::VideoCaptureParams& params,
|
| - std::unique_ptr<VideoCaptureDevice::Client> device_client) {
|
| + std::unique_ptr<media::VideoCaptureDeviceClient> device_client,
|
| + ReceiveDeviceCallback result_callback) {
|
| SCOPED_UMA_HISTOGRAM_TIMER("Media.VideoCaptureManager.StartDeviceTime");
|
| - DCHECK(IsOnDeviceThread());
|
| + DCHECK(device_task_runner_->BelongsToCurrentThread());
|
|
|
| - std::unique_ptr<VideoCaptureDevice> video_capture_device;
|
| + std::unique_ptr<media::VideoCaptureDevice> video_capture_device;
|
| #if defined(OS_LINUX) || defined(OS_MACOSX) || defined(OS_WIN)
|
| video_capture_device = WebContentsVideoCaptureDevice::Create(id);
|
| #endif
|
|
|
| if (!video_capture_device) {
|
| - device_client->OnError(FROM_HERE, "Could not create capture device");
|
| - return nullptr;
|
| + result_callback.Run(nullptr);
|
| + return;
|
| }
|
|
|
| video_capture_device->AllocateAndStart(params, std::move(device_client));
|
| - return video_capture_device;
|
| + result_callback.Run(std::move(video_capture_device));
|
| }
|
|
|
| -std::unique_ptr<media::VideoCaptureDevice>
|
| -VideoCaptureManager::DoStartDesktopCaptureOnDeviceThread(
|
| +void InProcessBuildableVideoCaptureDevice::DoStartDesktopCaptureOnDeviceThread(
|
| const std::string& id,
|
| const media::VideoCaptureParams& params,
|
| - std::unique_ptr<VideoCaptureDevice::Client> device_client) {
|
| + std::unique_ptr<media::VideoCaptureDeviceClient> device_client,
|
| + ReceiveDeviceCallback result_callback) {
|
| SCOPED_UMA_HISTOGRAM_TIMER("Media.VideoCaptureManager.StartDeviceTime");
|
| - DCHECK(IsOnDeviceThread());
|
| + DCHECK(device_task_runner_->BelongsToCurrentThread());
|
|
|
| - std::unique_ptr<VideoCaptureDevice> video_capture_device;
|
| + std::unique_ptr<media::VideoCaptureDevice> video_capture_device;
|
| #if defined(ENABLE_SCREEN_CAPTURE)
|
| DesktopMediaID desktop_id = DesktopMediaID::Parse(id);
|
| if (desktop_id.is_null()) {
|
| - device_client->OnError(FROM_HERE, "Desktop media ID is null");
|
| - return nullptr;
|
| + DLOG(ERROR) << "Desktop media ID is null";
|
| + result_callback.Run(nullptr);
|
| + return;
|
| }
|
|
|
| if (desktop_id.type == DesktopMediaID::TYPE_WEB_CONTENTS) {
|
| @@ -689,649 +407,35 @@ VideoCaptureManager::DoStartDesktopCaptureOnDeviceThread(
|
| video_capture_device = DesktopCaptureDeviceAura::Create(desktop_id);
|
| #endif // defined(USE_AURA)
|
| #if BUILDFLAG(ENABLE_WEBRTC)
|
| - if (!video_capture_device)
|
| - video_capture_device = DesktopCaptureDevice::Create(desktop_id);
|
| + if (!video_capture_device)
|
| + video_capture_device = DesktopCaptureDevice::Create(desktop_id);
|
| #endif // BUILDFLAG(ENABLE_WEBRTC)
|
| #endif // defined (OS_ANDROID)
|
| }
|
| #endif // defined(ENABLE_SCREEN_CAPTURE)
|
|
|
| if (!video_capture_device) {
|
| - device_client->OnError(FROM_HERE, "Could not create capture device");
|
| - return nullptr;
|
| - }
|
| -
|
| - video_capture_device->AllocateAndStart(params, std::move(device_client));
|
| - return video_capture_device;
|
| -}
|
| -
|
| -void VideoCaptureManager::StartCaptureForClient(
|
| - media::VideoCaptureSessionId session_id,
|
| - const media::VideoCaptureParams& params,
|
| - VideoCaptureControllerID client_id,
|
| - VideoCaptureControllerEventHandler* client_handler,
|
| - const DoneCB& done_cb) {
|
| - DCHECK_CURRENTLY_ON(BrowserThread::IO);
|
| - DVLOG(1) << __func__ << ", session_id = " << session_id << ", request: "
|
| - << media::VideoCaptureFormat::ToString(params.requested_format);
|
| -
|
| - DeviceEntry* entry = GetOrCreateDeviceEntry(session_id, params);
|
| - if (!entry) {
|
| - done_cb.Run(base::WeakPtr<VideoCaptureController>());
|
| + result_callback.Run(nullptr);
|
| return;
|
| }
|
|
|
| - LogVideoCaptureEvent(VIDEO_CAPTURE_START_CAPTURE);
|
| -
|
| - // First client starts the device.
|
| - if (!entry->video_capture_controller.HasActiveClient() &&
|
| - !entry->video_capture_controller.HasPausedClient()) {
|
| - DVLOG(1) << "VideoCaptureManager starting device (type = "
|
| - << entry->stream_type << ", id = " << entry->id << ")";
|
| - QueueStartDevice(session_id, entry, params);
|
| - }
|
| - // Run the callback first, as AddClient() may trigger OnFrameInfo().
|
| - done_cb.Run(entry->video_capture_controller.GetWeakPtrForIOThread());
|
| - entry->video_capture_controller.AddClient(client_id, client_handler,
|
| - session_id, params);
|
| -}
|
| -
|
| -void VideoCaptureManager::StopCaptureForClient(
|
| - VideoCaptureController* controller,
|
| - VideoCaptureControllerID client_id,
|
| - VideoCaptureControllerEventHandler* client_handler,
|
| - bool aborted_due_to_error) {
|
| - DCHECK_CURRENTLY_ON(BrowserThread::IO);
|
| - DCHECK(controller);
|
| - DCHECK(client_handler);
|
| -
|
| - DeviceEntry* entry = GetDeviceEntryByController(controller);
|
| - if (!entry) {
|
| - NOTREACHED();
|
| - return;
|
| - }
|
| - if (!aborted_due_to_error) {
|
| - if (controller->has_received_frames()) {
|
| - LogVideoCaptureEvent(VIDEO_CAPTURE_STOP_CAPTURE_OK);
|
| - } else if (entry->stream_type == MEDIA_DEVICE_VIDEO_CAPTURE) {
|
| - LogVideoCaptureEvent(
|
| - VIDEO_CAPTURE_STOP_CAPTURE_OK_NO_FRAMES_PRODUCED_BY_DEVICE);
|
| - } else {
|
| - LogVideoCaptureEvent(
|
| - VIDEO_CAPTURE_STOP_CAPTURE_OK_NO_FRAMES_PRODUCED_BY_DESKTOP_OR_TAB);
|
| - }
|
| - } else {
|
| - LogVideoCaptureEvent(VIDEO_CAPTURE_STOP_CAPTURE_DUE_TO_ERROR);
|
| - for (auto it : sessions_) {
|
| - if (it.second.type == entry->stream_type && it.second.id == entry->id) {
|
| - for (auto& listener : listeners_)
|
| - listener.Aborted(it.second.type, it.first);
|
| - // Aborted() call might synchronously destroy |entry|, recheck.
|
| - entry = GetDeviceEntryByController(controller);
|
| - if (!entry)
|
| - return;
|
| - break;
|
| - }
|
| - }
|
| - }
|
| -
|
| - // Detach client from controller.
|
| - const media::VideoCaptureSessionId session_id =
|
| - controller->RemoveClient(client_id, client_handler);
|
| - DVLOG(1) << __func__ << ", session_id = " << session_id;
|
| -
|
| - // If controller has no more clients, delete controller and device.
|
| - DestroyDeviceEntryIfNoClients(entry);
|
| -}
|
| -
|
| -void VideoCaptureManager::PauseCaptureForClient(
|
| - VideoCaptureController* controller,
|
| - VideoCaptureControllerID client_id,
|
| - VideoCaptureControllerEventHandler* client_handler) {
|
| - DCHECK_CURRENTLY_ON(BrowserThread::IO);
|
| - DCHECK(controller);
|
| - DCHECK(client_handler);
|
| - DeviceEntry* entry = GetDeviceEntryByController(controller);
|
| - if (!entry)
|
| - NOTREACHED() << "Got Null entry while pausing capture";
|
| -
|
| - const bool had_active_client = controller->HasActiveClient();
|
| - controller->PauseClient(client_id, client_handler);
|
| - if (!had_active_client || controller->HasActiveClient())
|
| - return;
|
| - if (media::VideoCaptureDevice* device = entry->video_capture_device.get()) {
|
| - device_task_runner_->PostTask(
|
| - FROM_HERE,
|
| - base::Bind(&VideoCaptureDevice::MaybeSuspend,
|
| - // Unretained is safe to use here because |device| would be
|
| - // null if it was scheduled for shutdown and destruction, and
|
| - // because this task is guaranteed to run before the task
|
| - // that destroys the |device|.
|
| - base::Unretained(device)));
|
| - }
|
| -}
|
| -
|
| -void VideoCaptureManager::ResumeCaptureForClient(
|
| - media::VideoCaptureSessionId session_id,
|
| - const media::VideoCaptureParams& params,
|
| - VideoCaptureController* controller,
|
| - VideoCaptureControllerID client_id,
|
| - VideoCaptureControllerEventHandler* client_handler) {
|
| - DCHECK_CURRENTLY_ON(BrowserThread::IO);
|
| - DCHECK(controller);
|
| - DCHECK(client_handler);
|
| -
|
| - DeviceEntry* entry = GetDeviceEntryByController(controller);
|
| - if (!entry)
|
| - NOTREACHED() << "Got Null entry while resuming capture";
|
| -
|
| - const bool had_active_client = controller->HasActiveClient();
|
| - controller->ResumeClient(client_id, client_handler);
|
| - if (had_active_client || !controller->HasActiveClient())
|
| - return;
|
| - if (media::VideoCaptureDevice* device = entry->video_capture_device.get()) {
|
| - device_task_runner_->PostTask(
|
| - FROM_HERE,
|
| - base::Bind(&VideoCaptureDevice::Resume,
|
| - // Unretained is safe to use here because |device| would be
|
| - // null if it was scheduled for shutdown and destruction, and
|
| - // because this task is guaranteed to run before the task
|
| - // that destroys the |device|.
|
| - base::Unretained(device)));
|
| - }
|
| -}
|
| -
|
| -void VideoCaptureManager::RequestRefreshFrameForClient(
|
| - VideoCaptureController* controller) {
|
| - DCHECK_CURRENTLY_ON(BrowserThread::IO);
|
| -
|
| - if (DeviceEntry* entry = GetDeviceEntryByController(controller)) {
|
| - if (media::VideoCaptureDevice* device = entry->video_capture_device.get()) {
|
| - device_task_runner_->PostTask(
|
| - FROM_HERE,
|
| - base::Bind(&VideoCaptureDevice::RequestRefreshFrame,
|
| - // Unretained is safe to use here because |device| would be
|
| - // null if it was scheduled for shutdown and destruction,
|
| - // and because this task is guaranteed to run before the
|
| - // task that destroys the |device|.
|
| - base::Unretained(device)));
|
| - }
|
| - }
|
| -}
|
| -
|
| -bool VideoCaptureManager::GetDeviceSupportedFormats(
|
| - media::VideoCaptureSessionId capture_session_id,
|
| - media::VideoCaptureFormats* supported_formats) {
|
| - DCHECK_CURRENTLY_ON(BrowserThread::IO);
|
| - DCHECK(supported_formats->empty());
|
| -
|
| - SessionMap::iterator it = sessions_.find(capture_session_id);
|
| - if (it == sessions_.end())
|
| - return false;
|
| - DVLOG(1) << "GetDeviceSupportedFormats for device: " << it->second.name;
|
| -
|
| - return GetDeviceSupportedFormats(it->second.id, supported_formats);
|
| -}
|
| -
|
| -bool VideoCaptureManager::GetDeviceSupportedFormats(
|
| - const std::string& device_id,
|
| - media::VideoCaptureFormats* supported_formats) {
|
| - DCHECK_CURRENTLY_ON(BrowserThread::IO);
|
| - DCHECK(supported_formats->empty());
|
| -
|
| - // Return all available formats of the device, regardless its started state.
|
| - DeviceInfo* existing_device = GetDeviceInfoById(device_id);
|
| - if (existing_device)
|
| - *supported_formats = existing_device->supported_formats;
|
| - return true;
|
| -}
|
| -
|
| -bool VideoCaptureManager::GetDeviceFormatsInUse(
|
| - media::VideoCaptureSessionId capture_session_id,
|
| - media::VideoCaptureFormats* formats_in_use) {
|
| - DCHECK_CURRENTLY_ON(BrowserThread::IO);
|
| - DCHECK(formats_in_use->empty());
|
| -
|
| - SessionMap::iterator it = sessions_.find(capture_session_id);
|
| - if (it == sessions_.end())
|
| - return false;
|
| - DVLOG(1) << "GetDeviceFormatsInUse for device: " << it->second.name;
|
| -
|
| - return GetDeviceFormatsInUse(it->second.type, it->second.id, formats_in_use);
|
| -}
|
| -
|
| -bool VideoCaptureManager::GetDeviceFormatsInUse(
|
| - MediaStreamType stream_type,
|
| - const std::string& device_id,
|
| - media::VideoCaptureFormats* formats_in_use) {
|
| - DCHECK_CURRENTLY_ON(BrowserThread::IO);
|
| - DCHECK(formats_in_use->empty());
|
| - // Return the currently in-use format(s) of the device, if it's started.
|
| - DeviceEntry* device_in_use =
|
| - GetDeviceEntryByTypeAndId(stream_type, device_id);
|
| - if (device_in_use) {
|
| - // Currently only one format-in-use is supported at the VCC level.
|
| - formats_in_use->push_back(
|
| - device_in_use->video_capture_controller.GetVideoCaptureFormat());
|
| - }
|
| - return true;
|
| -}
|
| -
|
| -void VideoCaptureManager::SetDesktopCaptureWindowId(
|
| - media::VideoCaptureSessionId session_id,
|
| - gfx::NativeViewId window_id) {
|
| - DCHECK_CURRENTLY_ON(BrowserThread::IO);
|
| - VLOG(2) << "SetDesktopCaptureWindowId called for session " << session_id;
|
| -
|
| - notification_window_ids_[session_id] = window_id;
|
| - MaybePostDesktopCaptureWindowId(session_id);
|
| -}
|
| -
|
| -void VideoCaptureManager::MaybePostDesktopCaptureWindowId(
|
| - media::VideoCaptureSessionId session_id) {
|
| - SessionMap::iterator session_it = sessions_.find(session_id);
|
| - if (session_it == sessions_.end())
|
| - return;
|
| -
|
| - DeviceEntry* const existing_device =
|
| - GetDeviceEntryByTypeAndId(session_it->second.type, session_it->second.id);
|
| - if (!existing_device) {
|
| - DVLOG(2) << "Failed to find an existing screen capture device.";
|
| - return;
|
| - }
|
| -
|
| - if (!existing_device->video_capture_device) {
|
| - DVLOG(2) << "Screen capture device not yet started.";
|
| - return;
|
| - }
|
| -
|
| - DCHECK_EQ(MEDIA_DESKTOP_VIDEO_CAPTURE, existing_device->stream_type);
|
| - DesktopMediaID id = DesktopMediaID::Parse(existing_device->id);
|
| - if (id.is_null())
|
| - return;
|
| -
|
| - auto window_id_it = notification_window_ids_.find(session_id);
|
| - if (window_id_it == notification_window_ids_.end()) {
|
| - DVLOG(2) << "Notification window id not set for screen capture.";
|
| - return;
|
| - }
|
| -
|
| - // Post |existing_device->video_capture_device| to the VideoCaptureDevice to
|
| - // the device_task_runner_. This is safe since the device is destroyed on the
|
| - // device_task_runner_.
|
| - device_task_runner_->PostTask(
|
| - FROM_HERE,
|
| - base::Bind(&VideoCaptureManager::SetDesktopCaptureWindowIdOnDeviceThread,
|
| - this, existing_device->video_capture_device.get(),
|
| - window_id_it->second));
|
| -
|
| - notification_window_ids_.erase(window_id_it);
|
| -}
|
| -
|
| -void VideoCaptureManager::GetPhotoCapabilities(
|
| - int session_id,
|
| - VideoCaptureDevice::GetPhotoCapabilitiesCallback callback) {
|
| - DCHECK_CURRENTLY_ON(BrowserThread::IO);
|
| -
|
| - const DeviceEntry* entry = GetDeviceEntryBySessionId(session_id);
|
| - if (!entry)
|
| - return;
|
| - VideoCaptureDevice* device = entry->video_capture_device.get();
|
| - if (device) {
|
| - VideoCaptureManager::DoGetPhotoCapabilities(std::move(callback), device);
|
| - return;
|
| - }
|
| - // |entry| is known but |device| is nullptr, queue up a request for later.
|
| - photo_request_queue_.emplace_back(
|
| - session_id, base::Bind(&VideoCaptureManager::DoGetPhotoCapabilities, this,
|
| - base::Passed(&callback)));
|
| -}
|
| -
|
| -void VideoCaptureManager::SetPhotoOptions(
|
| - int session_id,
|
| - media::mojom::PhotoSettingsPtr settings,
|
| - VideoCaptureDevice::SetPhotoOptionsCallback callback) {
|
| - DCHECK_CURRENTLY_ON(BrowserThread::IO);
|
| -
|
| - const DeviceEntry* entry = GetDeviceEntryBySessionId(session_id);
|
| - if (!entry)
|
| - return;
|
| - VideoCaptureDevice* device = entry->video_capture_device.get();
|
| - if (device) {
|
| - VideoCaptureManager::DoSetPhotoOptions(std::move(callback),
|
| - std::move(settings), device);
|
| - return;
|
| - }
|
| - // |entry| is known but |device| is nullptr, queue up a request for later.
|
| - photo_request_queue_.emplace_back(
|
| - session_id, base::Bind(&VideoCaptureManager::DoSetPhotoOptions, this,
|
| - base::Passed(&callback), base::Passed(&settings)));
|
| -}
|
| -
|
| -void VideoCaptureManager::TakePhoto(
|
| - int session_id,
|
| - VideoCaptureDevice::TakePhotoCallback callback) {
|
| - DCHECK_CURRENTLY_ON(BrowserThread::IO);
|
| -
|
| - const DeviceEntry* entry = GetDeviceEntryBySessionId(session_id);
|
| - if (!entry)
|
| - return;
|
| - VideoCaptureDevice* device = entry->video_capture_device.get();
|
| - if (device) {
|
| - VideoCaptureManager::DoTakePhoto(std::move(callback), device);
|
| - return;
|
| - }
|
| - // |entry| is known but |device| is nullptr, queue up a request for later.
|
| - photo_request_queue_.emplace_back(
|
| - session_id, base::Bind(&VideoCaptureManager::DoTakePhoto, this,
|
| - base::Passed(&callback)));
|
| -}
|
| -
|
| -void VideoCaptureManager::DoStopDeviceOnDeviceThread(
|
| - std::unique_ptr<VideoCaptureDevice> device) {
|
| - SCOPED_UMA_HISTOGRAM_TIMER("Media.VideoCaptureManager.StopDeviceTime");
|
| - DCHECK(IsOnDeviceThread());
|
| - device->StopAndDeAllocate();
|
| - DVLOG(3) << "DoStopDeviceOnDeviceThread";
|
| -}
|
| -
|
| -void VideoCaptureManager::OnOpened(
|
| - MediaStreamType stream_type,
|
| - media::VideoCaptureSessionId capture_session_id) {
|
| - DCHECK_CURRENTLY_ON(BrowserThread::IO);
|
| - for (auto& listener : listeners_)
|
| - listener.Opened(stream_type, capture_session_id);
|
| -}
|
| -
|
| -void VideoCaptureManager::OnClosed(
|
| - MediaStreamType stream_type,
|
| - media::VideoCaptureSessionId capture_session_id) {
|
| - DCHECK_CURRENTLY_ON(BrowserThread::IO);
|
| - for (auto& listener : listeners_)
|
| - listener.Closed(stream_type, capture_session_id);
|
| -}
|
| -
|
| -void VideoCaptureManager::OnDevicesInfoEnumerated(
|
| - base::ElapsedTimer* timer,
|
| - const EnumerationCallback& client_callback,
|
| - const VideoCaptureManager::DeviceInfos& new_devices_info_cache) {
|
| - DCHECK_CURRENTLY_ON(BrowserThread::IO);
|
| - UMA_HISTOGRAM_TIMES(
|
| - "Media.VideoCaptureManager.GetAvailableDevicesInfoOnDeviceThreadTime",
|
| - timer->Elapsed());
|
| - devices_info_cache_ = new_devices_info_cache;
|
| -
|
| - // Walk the |devices_info_cache_| and produce a
|
| - // media::VideoCaptureDeviceDescriptors for return purposes.
|
| - media::VideoCaptureDeviceDescriptors devices;
|
| - std::vector<std::tuple<media::VideoCaptureDeviceDescriptor,
|
| - media::VideoCaptureFormats>>
|
| - descriptors_and_formats;
|
| - for (const auto& it : devices_info_cache_) {
|
| - devices.emplace_back(it.descriptor);
|
| - descriptors_and_formats.emplace_back(it.descriptor, it.supported_formats);
|
| - }
|
| -
|
| - if (!descriptors_and_formats.empty()) {
|
| - MediaInternals::GetInstance()->UpdateVideoCaptureDeviceCapabilities(
|
| - descriptors_and_formats);
|
| - }
|
| -
|
| - client_callback.Run(devices);
|
| -}
|
| -
|
| -bool VideoCaptureManager::IsOnDeviceThread() const {
|
| - return device_task_runner_->BelongsToCurrentThread();
|
| -}
|
| -
|
| -void VideoCaptureManager::ConsolidateDevicesInfoOnDeviceThread(
|
| - base::Callback<void(const VideoCaptureManager::DeviceInfos&)>
|
| - on_devices_enumerated_callback,
|
| - const VideoCaptureManager::DeviceInfos& old_device_info_cache,
|
| - std::unique_ptr<VideoCaptureDeviceDescriptors> descriptors_snapshot) {
|
| - DCHECK(IsOnDeviceThread());
|
| - // Construct |new_devices_info_cache| with the cached devices that are still
|
| - // present in the system, and remove their names from |names_snapshot|, so we
|
| - // keep there the truly new devices.
|
| - VideoCaptureManager::DeviceInfos new_devices_info_cache;
|
| - for (const auto& device_info : old_device_info_cache) {
|
| - for (VideoCaptureDeviceDescriptors::iterator it =
|
| - descriptors_snapshot->begin();
|
| - it != descriptors_snapshot->end(); ++it) {
|
| - if (device_info.descriptor.device_id == it->device_id) {
|
| - new_devices_info_cache.push_back(device_info);
|
| - descriptors_snapshot->erase(it);
|
| - break;
|
| - }
|
| - }
|
| - }
|
| -
|
| - // Get the device info for the new devices in |names_snapshot|.
|
| - for (const auto& it : *descriptors_snapshot) {
|
| - DeviceInfo device_info(it);
|
| - video_capture_device_factory_->GetSupportedFormats(
|
| - it, &device_info.supported_formats);
|
| - ConsolidateCaptureFormats(&device_info.supported_formats);
|
| - new_devices_info_cache.push_back(device_info);
|
| - }
|
| -
|
| - on_devices_enumerated_callback.Run(new_devices_info_cache);
|
| -}
|
| -
|
| -void VideoCaptureManager::DestroyDeviceEntryIfNoClients(DeviceEntry* entry) {
|
| - DCHECK_CURRENTLY_ON(BrowserThread::IO);
|
| - // Removal of the last client stops the device.
|
| - if (!entry->video_capture_controller.HasActiveClient() &&
|
| - !entry->video_capture_controller.HasPausedClient()) {
|
| - DVLOG(1) << "VideoCaptureManager stopping device (type = "
|
| - << entry->stream_type << ", id = " << entry->id << ")";
|
| -
|
| - // The DeviceEntry is removed from |devices_| immediately. The controller is
|
| - // deleted immediately, and the device is freed asynchronously. After this
|
| - // point, subsequent requests to open this same device ID will create a new
|
| - // DeviceEntry, VideoCaptureController, and VideoCaptureDevice.
|
| - DoStopDevice(entry);
|
| - // TODO(mcasas): use a helper function https://crbug.com/624854.
|
| - DeviceEntries::iterator device_it =
|
| - std::find_if(devices_.begin(), devices_.end(),
|
| - [entry](const std::unique_ptr<DeviceEntry>& device_entry) {
|
| - return device_entry.get() == entry;
|
| - });
|
| - devices_.erase(device_it);
|
| - }
|
| -}
|
| -
|
| -VideoCaptureManager::DeviceEntry*
|
| -VideoCaptureManager::GetDeviceEntryBySessionId(int session_id) {
|
| - DCHECK_CURRENTLY_ON(BrowserThread::IO);
|
| - SessionMap::const_iterator session_it = sessions_.find(session_id);
|
| - if (session_it == sessions_.end())
|
| - return nullptr;
|
| -
|
| - return GetDeviceEntryByTypeAndId(session_it->second.type,
|
| - session_it->second.id);
|
| -}
|
| -
|
| -VideoCaptureManager::DeviceEntry*
|
| -VideoCaptureManager::GetDeviceEntryByTypeAndId(
|
| - MediaStreamType type,
|
| - const std::string& device_id) const {
|
| - DCHECK_CURRENTLY_ON(BrowserThread::IO);
|
| -
|
| - for (const std::unique_ptr<DeviceEntry>& device : devices_) {
|
| - if (type == device->stream_type && device_id == device->id)
|
| - return device.get();
|
| - }
|
| - return nullptr;
|
| -}
|
| -
|
| -VideoCaptureManager::DeviceEntry*
|
| -VideoCaptureManager::GetDeviceEntryByController(
|
| - const VideoCaptureController* controller) const {
|
| - DCHECK_CURRENTLY_ON(BrowserThread::IO);
|
| -
|
| - // Look up |controller| in |devices_|.
|
| - for (const std::unique_ptr<DeviceEntry>& device : devices_) {
|
| - if (&device->video_capture_controller == controller)
|
| - return device.get();
|
| - }
|
| - return nullptr;
|
| -}
|
| -
|
| -VideoCaptureManager::DeviceEntry* VideoCaptureManager::GetDeviceEntryBySerialId(
|
| - int serial_id) const {
|
| - DCHECK_CURRENTLY_ON(BrowserThread::IO);
|
| -
|
| - for (const std::unique_ptr<DeviceEntry>& device : devices_) {
|
| - if (device->serial_id == serial_id)
|
| - return device.get();
|
| - }
|
| - return nullptr;
|
| -}
|
| -
|
| -VideoCaptureManager::DeviceInfo* VideoCaptureManager::GetDeviceInfoById(
|
| - const std::string& id) {
|
| - for (auto& it : devices_info_cache_) {
|
| - if (it.descriptor.device_id == id)
|
| - return ⁢
|
| - }
|
| - return nullptr;
|
| -}
|
| -
|
| -VideoCaptureManager::DeviceEntry* VideoCaptureManager::GetOrCreateDeviceEntry(
|
| - media::VideoCaptureSessionId capture_session_id,
|
| - const media::VideoCaptureParams& params) {
|
| - DCHECK_CURRENTLY_ON(BrowserThread::IO);
|
| -
|
| - SessionMap::iterator session_it = sessions_.find(capture_session_id);
|
| - if (session_it == sessions_.end())
|
| - return nullptr;
|
| - const MediaStreamDevice& device_info = session_it->second;
|
| -
|
| - // Check if another session has already opened this device. If so, just
|
| - // use that opened device.
|
| - DeviceEntry* const existing_device =
|
| - GetDeviceEntryByTypeAndId(device_info.type, device_info.id);
|
| - if (existing_device) {
|
| - DCHECK_EQ(device_info.type, existing_device->stream_type);
|
| - return existing_device;
|
| - }
|
| -
|
| - devices_.emplace_back(
|
| - new DeviceEntry(device_info.type, device_info.id, params));
|
| - return devices_.back().get();
|
| + video_capture_device->AllocateAndStart(params, std::move(device_client));
|
| + result_callback.Run(std::move(video_capture_device));
|
| }
|
|
|
| -void VideoCaptureManager::SetDesktopCaptureWindowIdOnDeviceThread(
|
| - media::VideoCaptureDevice* device,
|
| - gfx::NativeViewId window_id) {
|
| - DCHECK(IsOnDeviceThread());
|
| -#if defined(ENABLE_SCREEN_CAPTURE) && BUILDFLAG(ENABLE_WEBRTC) && !defined(OS_ANDROID)
|
| +void InProcessBuildableVideoCaptureDevice::
|
| + SetDesktopCaptureWindowIdOnDeviceThread(media::VideoCaptureDevice* device,
|
| + gfx::NativeViewId window_id,
|
| + base::OnceClosure done_cb) {
|
| + DCHECK(device_task_runner_->BelongsToCurrentThread());
|
| +#if defined(ENABLE_SCREEN_CAPTURE) && BUILDFLAG(ENABLE_WEBRTC) && \
|
| + !defined(OS_ANDROID)
|
| DesktopCaptureDevice* desktop_device =
|
| static_cast<DesktopCaptureDevice*>(device);
|
| desktop_device->SetNotificationWindowId(window_id);
|
| VLOG(2) << "Screen capture notification window passed on device thread.";
|
| #endif
|
| + std::move(done_cb).Run();
|
| }
|
|
|
| -void VideoCaptureManager::DoGetPhotoCapabilities(
|
| - VideoCaptureDevice::GetPhotoCapabilitiesCallback callback,
|
| - VideoCaptureDevice* device) {
|
| - // Unretained() is safe to use here because |device| would be null if it
|
| - // was scheduled for shutdown and destruction, and because this task is
|
| - // guaranteed to run before the task that destroys the |device|.
|
| - device_task_runner_->PostTask(
|
| - FROM_HERE, base::Bind(&VideoCaptureDevice::GetPhotoCapabilities,
|
| - base::Unretained(device), base::Passed(&callback)));
|
| -}
|
| -
|
| -void VideoCaptureManager::DoSetPhotoOptions(
|
| - VideoCaptureDevice::SetPhotoOptionsCallback callback,
|
| - media::mojom::PhotoSettingsPtr settings,
|
| - VideoCaptureDevice* device) {
|
| - // Unretained() is safe to use here because |device| would be null if it
|
| - // was scheduled for shutdown and destruction, and because this task is
|
| - // guaranteed to run before the task that destroys the |device|.
|
| - device_task_runner_->PostTask(
|
| - FROM_HERE,
|
| - base::Bind(&VideoCaptureDevice::SetPhotoOptions, base::Unretained(device),
|
| - base::Passed(&settings), base::Passed(&callback)));
|
| -}
|
| -
|
| -void VideoCaptureManager::DoTakePhoto(
|
| - VideoCaptureDevice::TakePhotoCallback callback,
|
| - VideoCaptureDevice* device) {
|
| - // Unretained() is safe to use here because |device| would be null if it
|
| - // was scheduled for shutdown and destruction, and because this task is
|
| - // guaranteed to run before the task that destroys the |device|.
|
| - device_task_runner_->PostTask(
|
| - FROM_HERE, base::Bind(&VideoCaptureDevice::TakePhoto,
|
| - base::Unretained(device), base::Passed(&callback)));
|
| -}
|
| -
|
| -base::Optional<CameraCalibration> VideoCaptureManager::GetCameraCalibration(
|
| - const std::string& device_id) {
|
| - VideoCaptureManager::DeviceInfo* info = GetDeviceInfoById(device_id);
|
| - if (!info)
|
| - return base::Optional<CameraCalibration>();
|
| - return info->descriptor.camera_calibration;
|
| -}
|
| -
|
| -#if defined(OS_ANDROID)
|
| -void VideoCaptureManager::OnApplicationStateChange(
|
| - base::android::ApplicationState state) {
|
| - DCHECK_CURRENTLY_ON(BrowserThread::IO);
|
| -
|
| - // Only release/resume devices when the Application state changes from
|
| - // RUNNING->STOPPED->RUNNING.
|
| - if (state == base::android::APPLICATION_STATE_HAS_RUNNING_ACTIVITIES &&
|
| - !application_state_has_running_activities_) {
|
| - ResumeDevices();
|
| - application_state_has_running_activities_ = true;
|
| - } else if (state == base::android::APPLICATION_STATE_HAS_STOPPED_ACTIVITIES) {
|
| - ReleaseDevices();
|
| - application_state_has_running_activities_ = false;
|
| - }
|
| -}
|
| -
|
| -void VideoCaptureManager::ReleaseDevices() {
|
| - DCHECK_CURRENTLY_ON(BrowserThread::IO);
|
| -
|
| - for (auto& entry : devices_) {
|
| - // Do not stop Content Video Capture devices, e.g. Tab or Screen capture.
|
| - if (entry->stream_type != MEDIA_DEVICE_VIDEO_CAPTURE)
|
| - continue;
|
| -
|
| - DoStopDevice(entry.get());
|
| - }
|
| -}
|
| -
|
| -void VideoCaptureManager::ResumeDevices() {
|
| - DCHECK_CURRENTLY_ON(BrowserThread::IO);
|
| -
|
| - for (auto& entry : devices_) {
|
| - // Do not resume Content Video Capture devices, e.g. Tab or Screen capture.
|
| - // Do not try to restart already running devices.
|
| - if (entry->stream_type != MEDIA_DEVICE_VIDEO_CAPTURE ||
|
| - entry->video_capture_device)
|
| - continue;
|
| -
|
| - // Check if the device is already in the start queue.
|
| - bool device_in_queue = false;
|
| - for (auto& request : device_start_queue_) {
|
| - if (request.serial_id() == entry->serial_id) {
|
| - device_in_queue = true;
|
| - break;
|
| - }
|
| - }
|
| -
|
| - if (!device_in_queue) {
|
| - // Session ID is only valid for Screen capture. So we can fake it to
|
| - // resume video capture devices here.
|
| - QueueStartDevice(kFakeSessionId, entry.get(), entry->parameters);
|
| - }
|
| - }
|
| -}
|
| -#endif // defined(OS_ANDROID)
|
| -
|
| } // namespace content
|
|
|