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

Unified Diff: content/browser/renderer_host/media/in_process_buildable_video_capture_device.cc

Issue 2738763002: [Mojo Video Capture] Introduce abstraction BuildableVideoCaptureDevice (Closed)
Patch Set: Incorporated miu@'s suggestions from PatchSet 3 Created 3 years, 9 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/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 15%
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..f5b584411812cc9cc653bb0fb40567ede8dd03ed 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 2016 The Chromium Authors. All rights reserved.
emircan 2017/03/16 20:54:03 2017
chfremer 2017/03/16 22:02:29 Done.
// 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,
+ std::unique_ptr<content::Ownership> context_reference) {
+ SCOPED_UMA_HISTOGRAM_TIMER("Media.VideoCaptureManager.StopDeviceTime");
+ device->StopAndDeAllocate();
+ DVLOG(3) << "StopAndReleaseDeviceOnDeviceThread";
+ delete device;
}
// The maximum number of video frame buffers in-flight at any one time. This
@@ -135,540 +78,299 @@ 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* entry,
+ VideoCaptureController* controller,
+ const media::VideoCaptureParams& params,
+ BuildableDeviceCallbacks* callbacks,
+ std::unique_ptr<Ownership> context_reference) {
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);
-
- 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;
+ const int max_buffers = (entry->stream_type() == MEDIA_TAB_VIDEO_CAPTURE
+ ? kMaxNumberOfBuffersForTabCapture
+ : kMaxNumberOfBuffers);
-VideoCaptureManager::DeviceInfo::DeviceInfo(
- media::VideoCaptureDeviceDescriptor descriptor)
- : descriptor(descriptor) {}
+ auto device_client =
+ CreateDeviceClient(max_buffers, controller->GetWeakPtrForIOThread());
-VideoCaptureManager::DeviceInfo::DeviceInfo(
- const VideoCaptureManager::DeviceInfo& other) = default;
+ base::Closure start_capture_closure;
+ // Use of |this| is safe, because |context_reference| guarantees that |this|
emircan 2017/03/16 20:54:03 s/Use of |this| is safe/Use of Unretained() is saf
chfremer 2017/03/16 22:02:29 Done.
+ // stays alive.
+ ReceiveDeviceCallback after_start_capture_callback = media::BindToCurrentLoop(
+ base::Bind(&InProcessBuildableVideoCaptureDevice::OnDeviceStarted,
+ base::Unretained(this), entry, controller, callbacks,
+ base::Passed(&context_reference)));
-VideoCaptureManager::DeviceInfo::~DeviceInfo() = default;
-
-VideoCaptureManager::DeviceInfo& VideoCaptureManager::DeviceInfo::operator=(
- const VideoCaptureManager::DeviceInfo& other) = default;
+ switch (entry->stream_type()) {
+ case MEDIA_DEVICE_VIDEO_CAPTURE: {
+ const media::VideoCaptureDeviceDescriptor* descriptor =
+ callbacks->LookupDeviceDescriptor(entry->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);
+
+ 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(entry);
+ return;
+ }
+ break;
+ }
+ case MEDIA_TAB_VIDEO_CAPTURE:
+ start_capture_closure =
+ base::Bind(&InProcessBuildableVideoCaptureDevice::
+ DoStartTabCaptureOnDeviceThread,
+ base::Unretained(this), entry->device_id(), params,
+ base::Passed(std::move(device_client)),
+ std::move(after_start_capture_callback));
+ break;
-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) {
-}
+ case MEDIA_DESKTOP_VIDEO_CAPTURE:
+ start_capture_closure =
+ base::Bind(&InProcessBuildableVideoCaptureDevice::
+ DoStartDesktopCaptureOnDeviceThread,
+ base::Unretained(this), entry->device_id(), params,
+ base::Passed(std::move(device_client)),
+ std::move(after_start_capture_callback));
+ break;
-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)) {}
+ 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,
+ std::unique_ptr<Ownership>) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- capture_observers_.AddObserver(observer);
+ controller->SetConsumerFeedbackObserver(nullptr);
+ if (!device_)
+ return;
+ media::VideoCaptureDevice* device_ptr = device_.release();
+ auto device_task_runner_context_reference =
+ MakeScopedRefptrOwnership(device_task_runner_);
+ bool posting_task_succeeded = device_task_runner_->PostTask(
+ FROM_HERE,
+ base::Bind(&StopAndReleaseDeviceOnDeviceThread, device_ptr,
+ base::Passed(&device_task_runner_context_reference)));
+ 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, nullptr);
+ }
}
-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,
+ std::unique_ptr<Ownership> context_reference) {
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(&context_reference)));
}
-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* entry,
+ VideoCaptureController* controller,
+ BuildableDeviceCallbacks* callbacks,
+ std::unique_ptr<Ownership> context_reference,
+ 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(entry);
+ 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(entry);
}
-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,544 +391,30 @@ 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 &it;
- }
- 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,
+ std::unique_ptr<Ownership> context_reference) {
+ 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);
@@ -1234,104 +422,4 @@ void VideoCaptureManager::SetDesktopCaptureWindowIdOnDeviceThread(
#endif
}
-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

Powered by Google App Engine
This is Rietveld 408576698