| Index: content/browser/renderer_host/media/video_capture_manager.cc
|
| diff --git a/content/browser/renderer_host/media/video_capture_manager.cc b/content/browser/renderer_host/media/video_capture_manager.cc
|
| index 2118857ecee7866c2e984854298eaee4c37e217e..641bb6fd35329d4ae3bf9444219c1ba4e0061f3c 100644
|
| --- a/content/browser/renderer_host/media/video_capture_manager.cc
|
| +++ b/content/browser/renderer_host/media/video_capture_manager.cc
|
| @@ -25,10 +25,9 @@
|
| #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/in_process_buildable_video_capture_device.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"
|
| @@ -59,27 +58,6 @@
|
|
|
| namespace {
|
|
|
| -class VideoFrameConsumerFeedbackObserverOnTaskRunner
|
| - : public media::VideoFrameConsumerFeedbackObserver {
|
| - public:
|
| - VideoFrameConsumerFeedbackObserverOnTaskRunner(
|
| - media::VideoFrameConsumerFeedbackObserver* observer,
|
| - scoped_refptr<base::SingleThreadTaskRunner> task_runner)
|
| - : observer_(observer), task_runner_(std::move(task_runner)) {}
|
| -
|
| - void OnUtilizationReport(int frame_feedback_id, double utilization) override {
|
| - task_runner_->PostTask(
|
| - FROM_HERE,
|
| - base::Bind(
|
| - &media::VideoFrameConsumerFeedbackObserver::OnUtilizationReport,
|
| - base::Unretained(observer_), frame_feedback_id, utilization));
|
| - }
|
| -
|
| - private:
|
| - media::VideoFrameConsumerFeedbackObserver* const observer_;
|
| - 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
|
| @@ -125,16 +103,6 @@ void ConsolidateCaptureFormats(media::VideoCaptureFormats* formats) {
|
| }
|
| }
|
|
|
| -// The maximum number of video frame buffers in-flight at any one time. This
|
| -// value should be based on the logical capacity of the capture pipeline, and
|
| -// not on hardware performance. For example, tab capture requires more buffers
|
| -// than webcam capture because the pipeline is longer (it includes read-backs
|
| -// pending in the GPU pipeline).
|
| -const int kMaxNumberOfBuffers = 3;
|
| -// TODO(miu): The value for tab capture should be determined programmatically.
|
| -// 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.
|
| @@ -148,56 +116,16 @@ enum VideoCaptureEvent {
|
| };
|
|
|
| void LogVideoCaptureEvent(VideoCaptureEvent event) {
|
| - UMA_HISTOGRAM_ENUMERATION("Media.VideoCaptureManager.Event",
|
| - 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
|
|
|
| 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 {
|
| @@ -235,44 +163,6 @@ class VideoCaptureManager::CaptureDeviceStartRequest {
|
| 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) {}
|
| -
|
| -VideoCaptureManager::DeviceEntry::~DeviceEntry() {
|
| - 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);
|
| -}
|
| -
|
| -std::unique_ptr<media::VideoCaptureDevice::Client>
|
| -VideoCaptureManager::DeviceEntry::CreateDeviceClient() {
|
| - 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;
|
|
|
| VideoCaptureManager::DeviceInfo::DeviceInfo(
|
| @@ -294,8 +184,7 @@ VideoCaptureManager::CaptureDeviceStartRequest::CaptureDeviceStartRequest(
|
| : serial_id_(serial_id),
|
| session_id_(session_id),
|
| params_(params),
|
| - abort_start_(false) {
|
| -}
|
| + abort_start_(false) {}
|
|
|
| VideoCaptureManager::VideoCaptureManager(
|
| std::unique_ptr<media::VideoCaptureDeviceFactory> factory,
|
| @@ -305,7 +194,7 @@ VideoCaptureManager::VideoCaptureManager(
|
| video_capture_device_factory_(std::move(factory)) {}
|
|
|
| VideoCaptureManager::~VideoCaptureManager() {
|
| - DCHECK(devices_.empty());
|
| + DCHECK(controllers_.empty());
|
| DCHECK(device_start_queue_.empty());
|
| }
|
|
|
| @@ -365,6 +254,12 @@ void VideoCaptureManager::EnumerateDevices(
|
| devices_enumerated_callback));
|
| }
|
|
|
| +const media::VideoCaptureDeviceDescriptor*
|
| +VideoCaptureManager::LookupDeviceDescriptor(const std::string& id) {
|
| + const DeviceInfo* info = GetDeviceInfoById(id);
|
| + return info ? (&info->descriptor) : nullptr;
|
| +}
|
| +
|
| int VideoCaptureManager::Open(const MediaStreamDevice& device) {
|
| DCHECK_CURRENTLY_ON(BrowserThread::IO);
|
|
|
| @@ -397,16 +292,16 @@ void VideoCaptureManager::Close(int capture_session_id) {
|
| return;
|
| }
|
|
|
| - DeviceEntry* const existing_device =
|
| - GetDeviceEntryByTypeAndId(session_it->second.type, session_it->second.id);
|
| + VideoCaptureController* const existing_device = LookupControllerByTypeAndId(
|
| + 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);
|
| + existing_device->StopSession(capture_session_id);
|
|
|
| // StopSession() may have removed the last client, so we might need to
|
| // close the device.
|
| - DestroyDeviceEntryIfNoClients(existing_device);
|
| + DestroyControllerIfNoClients(existing_device);
|
| }
|
|
|
| // Notify listeners asynchronously, and forget the session.
|
| @@ -418,55 +313,57 @@ void VideoCaptureManager::Close(int capture_session_id) {
|
|
|
| void VideoCaptureManager::QueueStartDevice(
|
| media::VideoCaptureSessionId session_id,
|
| - DeviceEntry* entry,
|
| + VideoCaptureController* controller,
|
| const media::VideoCaptureParams& params) {
|
| DCHECK_CURRENTLY_ON(BrowserThread::IO);
|
| device_start_queue_.push_back(
|
| - CaptureDeviceStartRequest(entry->serial_id, session_id, params));
|
| + CaptureDeviceStartRequest(controller->serial_id(), session_id, params));
|
| if (device_start_queue_.size() == 1)
|
| HandleQueuedStartRequest();
|
| }
|
|
|
| -void VideoCaptureManager::DoStopDevice(DeviceEntry* entry) {
|
| +void VideoCaptureManager::DoStopDevice(VideoCaptureController* controller) {
|
| 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());
|
| + DCHECK(std::find_if(
|
| + controllers_.begin(), controllers_.end(),
|
| + [controller](
|
| + const scoped_refptr<VideoCaptureController>& device_entry) {
|
| + return device_entry.get() == controller;
|
| + }) != controllers_.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) {
|
| + if (request->serial_id() == controller->serial_id()) {
|
| request->set_abort_start();
|
| DVLOG(3) << "DoStopDevice, aborting start request for device "
|
| - << entry->id << " serial_id = " << entry->serial_id;
|
| + << controller->device_id()
|
| + << " serial_id = " << controller->serial_id();
|
| return;
|
| }
|
| }
|
|
|
| - const DeviceInfo* device_info = GetDeviceInfoById(entry->id);
|
| + const DeviceInfo* device_info = GetDeviceInfoById(controller->device_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)));
|
| + DVLOG(3) << "DoStopDevice. Send stop request for device = "
|
| + << controller->device_id()
|
| + << " serial_id = " << controller->serial_id() << ".";
|
| + controller->OnLog(base::StringPrintf("Stopping device: id: %s",
|
| + controller->device_id().c_str()));
|
| +
|
| + if (controller->IsDeviceAlive()) {
|
| + // Since we may be removing |controller| from |controllers_| while
|
| + // ReleaseDeviceAsnyc() is executing, we pass it shared ownership to
|
| + // |controller|.
|
| + controller->ReleaseDeviceAsync(base::Bind(
|
| + [](scoped_refptr<VideoCaptureController>) {},
|
| + GetControllerSharedRefFromSerialId(controller->serial_id())));
|
| }
|
| }
|
|
|
| @@ -474,7 +371,7 @@ void VideoCaptureManager::HandleQueuedStartRequest() {
|
| 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_.begin()->abort_start()) {
|
| device_start_queue_.pop_front();
|
| }
|
| DeviceStartQueue::iterator request = device_start_queue_.begin();
|
| @@ -482,115 +379,50 @@ void VideoCaptureManager::HandleQueuedStartRequest() {
|
| return;
|
|
|
| const int serial_id = request->serial_id();
|
| - DeviceEntry* const entry = GetDeviceEntryBySerialId(serial_id);
|
| - DCHECK(entry);
|
| + VideoCaptureController* const controller =
|
| + LookupControllerBySerialId(serial_id);
|
| + DCHECK(controller);
|
|
|
| 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;
|
| -
|
| - default: {
|
| - NOTIMPLEMENTED();
|
| - return;
|
| - }
|
| - }
|
| - base::PostTaskAndReplyWithResult(
|
| - device_task_runner_.get(), FROM_HERE, start_capture_function,
|
| - base::Bind(&VideoCaptureManager::OnDeviceStarted, this,
|
| - request->serial_id()));
|
| -}
|
| -
|
| -void VideoCaptureManager::OnDeviceStarted(
|
| - int serial_id,
|
| - std::unique_ptr<VideoCaptureDevice> device) {
|
| + << controller->device_id()
|
| + << " start id = " << controller->serial_id();
|
| +
|
| + // The method CreateAndStartDeviceAsync() is going to run asynchronously.
|
| + // Since we may be removing the controller while it is executing, we need to
|
| + // pass it shared ownership to itself so that it stays alive while executing.
|
| + // And since the execution may make callbacks into |this|, we also need
|
| + // to pass it shared ownership to |this|.
|
| + // TODO(chfremer): Check if request->params() can actually be different from
|
| + // controller->parameters, and simplify if this is not the case.
|
| + controller->CreateAndStartDeviceAsync(
|
| + request->params(),
|
| + static_cast<BuildableVideoCaptureDevice::Callbacks*>(this),
|
| + base::Bind([](scoped_refptr<VideoCaptureManager>,
|
| + scoped_refptr<VideoCaptureController>) {},
|
| + scoped_refptr<VideoCaptureManager>(this),
|
| + GetControllerSharedRefFromSerialId(serial_id)));
|
| +}
|
| +
|
| +void VideoCaptureManager::WillStartDevice(media::VideoFacingMode facing_mode) {
|
| + for (auto& observer : capture_observers_)
|
| + observer.OnVideoCaptureStarted(facing_mode);
|
| +}
|
| +
|
| +void VideoCaptureManager::DidStartDevice(VideoCaptureController* controller) {
|
| DVLOG(3) << __func__;
|
| DCHECK_CURRENTLY_ON(BrowserThread::IO);
|
| - DCHECK_EQ(serial_id, device_start_queue_.begin()->serial_id());
|
| - // |device| can be null if creation failed in
|
| - // DoStartDeviceCaptureOnDeviceThread.
|
| + DCHECK(controller);
|
| + DCHECK_EQ(controller->serial_id(), device_start_queue_.begin()->serial_id());
|
| 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();
|
| - }
|
| + // A request to release the device may have arrived during the asynchronous
|
| + // device startup.
|
| + DVLOG(3) << "Device release request has been issued while device was "
|
| + << "starting up asynchronously.";
|
| + controller->ReleaseDeviceAsync(base::Bind(
|
| + [](scoped_refptr<VideoCaptureController>) {},
|
| + GetControllerSharedRefFromSerialId(controller->serial_id())));
|
| } 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) {
|
| + if (controller->stream_type() == MEDIA_DESKTOP_VIDEO_CAPTURE) {
|
| const media::VideoCaptureSessionId session_id =
|
| device_start_queue_.front().session_id();
|
| DCHECK(session_id != kFakeSessionId);
|
| @@ -600,9 +432,10 @@ void VideoCaptureManager::OnDeviceStarted(
|
| 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());
|
| + VideoCaptureController* maybe_entry =
|
| + LookupControllerBySessionId(request->first);
|
| + if (maybe_entry && maybe_entry->IsDeviceAlive()) {
|
| + request->second.Run();
|
| photo_request_queue_.erase(request);
|
| }
|
| }
|
| @@ -612,97 +445,17 @@ void VideoCaptureManager::OnDeviceStarted(
|
| HandleQueuedStartRequest();
|
| }
|
|
|
| -std::unique_ptr<media::VideoCaptureDevice>
|
| -VideoCaptureManager::DoStartDeviceCaptureOnDeviceThread(
|
| - const VideoCaptureDeviceDescriptor& descriptor,
|
| - const media::VideoCaptureParams& params,
|
| - std::unique_ptr<VideoCaptureDevice::Client> device_client) {
|
| - SCOPED_UMA_HISTOGRAM_TIMER("Media.VideoCaptureManager.StartDeviceTime");
|
| - DCHECK(IsOnDeviceThread());
|
| -
|
| - std::unique_ptr<VideoCaptureDevice> video_capture_device;
|
| - video_capture_device =
|
| - video_capture_device_factory_->CreateDevice(descriptor);
|
| -
|
| - 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;
|
| -}
|
| -
|
| -std::unique_ptr<media::VideoCaptureDevice>
|
| -VideoCaptureManager::DoStartTabCaptureOnDeviceThread(
|
| - const std::string& id,
|
| - const media::VideoCaptureParams& params,
|
| - std::unique_ptr<VideoCaptureDevice::Client> device_client) {
|
| - SCOPED_UMA_HISTOGRAM_TIMER("Media.VideoCaptureManager.StartDeviceTime");
|
| - DCHECK(IsOnDeviceThread());
|
| -
|
| - std::unique_ptr<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;
|
| - }
|
| -
|
| - video_capture_device->AllocateAndStart(params, std::move(device_client));
|
| - return video_capture_device;
|
| -}
|
| -
|
| -std::unique_ptr<media::VideoCaptureDevice>
|
| -VideoCaptureManager::DoStartDesktopCaptureOnDeviceThread(
|
| - const std::string& id,
|
| - const media::VideoCaptureParams& params,
|
| - std::unique_ptr<VideoCaptureDevice::Client> device_client) {
|
| - SCOPED_UMA_HISTOGRAM_TIMER("Media.VideoCaptureManager.StartDeviceTime");
|
| - DCHECK(IsOnDeviceThread());
|
| -
|
| - std::unique_ptr<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;
|
| - }
|
| -
|
| - if (desktop_id.type == DesktopMediaID::TYPE_WEB_CONTENTS) {
|
| -#if defined(OS_LINUX) || defined(OS_MACOSX) || defined(OS_WIN)
|
| - video_capture_device = WebContentsVideoCaptureDevice::Create(id);
|
| - IncrementDesktopCaptureCounter(TAB_VIDEO_CAPTURER_CREATED);
|
| - if (desktop_id.audio_share) {
|
| - IncrementDesktopCaptureCounter(TAB_VIDEO_CAPTURER_CREATED_WITH_AUDIO);
|
| - } else {
|
| - IncrementDesktopCaptureCounter(TAB_VIDEO_CAPTURER_CREATED_WITHOUT_AUDIO);
|
| - }
|
| -#endif
|
| - } else {
|
| -#if defined(OS_ANDROID)
|
| - video_capture_device = base::MakeUnique<ScreenCaptureDeviceAndroid>();
|
| -#else
|
| -#if defined(USE_AURA)
|
| - 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);
|
| -#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;
|
| - }
|
| +void VideoCaptureManager::OnDeviceStartFailed(
|
| + VideoCaptureController* controller) {
|
| + const std::string log_message = base::StringPrintf(
|
| + "Starting device %s has failed. Maybe recently disconnected?",
|
| + controller->device_id().c_str());
|
| + DLOG(ERROR) << log_message;
|
| + controller->OnLog(log_message);
|
| + controller->OnError();
|
|
|
| - video_capture_device->AllocateAndStart(params, std::move(device_client));
|
| - return video_capture_device;
|
| + device_start_queue_.pop_front();
|
| + HandleQueuedStartRequest();
|
| }
|
|
|
| void VideoCaptureManager::StartCaptureForClient(
|
| @@ -715,8 +468,9 @@ void VideoCaptureManager::StartCaptureForClient(
|
| DVLOG(1) << __func__ << ", session_id = " << session_id << ", request: "
|
| << media::VideoCaptureFormat::ToString(params.requested_format);
|
|
|
| - DeviceEntry* entry = GetOrCreateDeviceEntry(session_id, params);
|
| - if (!entry) {
|
| + VideoCaptureController* controller =
|
| + GetOrCreateController(session_id, params);
|
| + if (!controller) {
|
| done_cb.Run(base::WeakPtr<VideoCaptureController>());
|
| return;
|
| }
|
| @@ -724,16 +478,14 @@ void VideoCaptureManager::StartCaptureForClient(
|
| 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);
|
| + if (!controller->HasActiveClient() && !controller->HasPausedClient()) {
|
| + DVLOG(1) << "VideoCaptureManager starting device (id = "
|
| + << controller->device_id() << ")";
|
| + QueueStartDevice(session_id, controller, 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);
|
| + done_cb.Run(controller->GetWeakPtrForIOThread());
|
| + controller->AddClient(client_id, client_handler, session_id, params);
|
| }
|
|
|
| void VideoCaptureManager::StopCaptureForClient(
|
| @@ -745,15 +497,14 @@ void VideoCaptureManager::StopCaptureForClient(
|
| DCHECK(controller);
|
| DCHECK(client_handler);
|
|
|
| - DeviceEntry* entry = GetDeviceEntryByController(controller);
|
| - if (!entry) {
|
| + if (!IsControllerPointerValid(controller)) {
|
| 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) {
|
| + } else if (controller->stream_type() == MEDIA_DEVICE_VIDEO_CAPTURE) {
|
| LogVideoCaptureEvent(
|
| VIDEO_CAPTURE_STOP_CAPTURE_OK_NO_FRAMES_PRODUCED_BY_DEVICE);
|
| } else {
|
| @@ -763,12 +514,12 @@ void VideoCaptureManager::StopCaptureForClient(
|
| } 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) {
|
| + if (it.second.type == controller->stream_type() &&
|
| + it.second.id == controller->device_id()) {
|
| for (auto& listener : listeners_)
|
| listener.Aborted(it.second.type, it.first);
|
| - // Aborted() call might synchronously destroy |entry|, recheck.
|
| - entry = GetDeviceEntryByController(controller);
|
| - if (!entry)
|
| + // Aborted() call might synchronously destroy |controller|, recheck.
|
| + if (!IsControllerPointerValid(controller))
|
| return;
|
| break;
|
| }
|
| @@ -781,7 +532,7 @@ void VideoCaptureManager::StopCaptureForClient(
|
| DVLOG(1) << __func__ << ", session_id = " << session_id;
|
|
|
| // If controller has no more clients, delete controller and device.
|
| - DestroyDeviceEntryIfNoClients(entry);
|
| + DestroyControllerIfNoClients(controller);
|
| }
|
|
|
| void VideoCaptureManager::PauseCaptureForClient(
|
| @@ -791,24 +542,16 @@ void VideoCaptureManager::PauseCaptureForClient(
|
| DCHECK_CURRENTLY_ON(BrowserThread::IO);
|
| DCHECK(controller);
|
| DCHECK(client_handler);
|
| - DeviceEntry* entry = GetDeviceEntryByController(controller);
|
| - if (!entry)
|
| - NOTREACHED() << "Got Null entry while pausing capture";
|
| + if (!IsControllerPointerValid(controller))
|
| + NOTREACHED() << "Got Null controller 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)));
|
| - }
|
| + if (!controller->IsDeviceAlive())
|
| + return;
|
| + controller->MaybeSuspend();
|
| }
|
|
|
| void VideoCaptureManager::ResumeCaptureForClient(
|
| @@ -821,41 +564,26 @@ void VideoCaptureManager::ResumeCaptureForClient(
|
| DCHECK(controller);
|
| DCHECK(client_handler);
|
|
|
| - DeviceEntry* entry = GetDeviceEntryByController(controller);
|
| - if (!entry)
|
| - NOTREACHED() << "Got Null entry while resuming capture";
|
| + if (!IsControllerPointerValid(controller))
|
| + NOTREACHED() << "Got Null controller 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)));
|
| - }
|
| + if (!controller->IsDeviceAlive())
|
| + return;
|
| + controller->Resume();
|
| }
|
|
|
| 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)));
|
| - }
|
| + if (IsControllerPointerValid(controller)) {
|
| + if (!controller->IsDeviceAlive())
|
| + return;
|
| + controller->RequestRefreshFrame();
|
| }
|
| }
|
|
|
| @@ -907,12 +635,11 @@ bool VideoCaptureManager::GetDeviceFormatsInUse(
|
| 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);
|
| + VideoCaptureController* device_in_use =
|
| + LookupControllerByTypeAndId(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());
|
| + formats_in_use->push_back(device_in_use->GetVideoCaptureFormat());
|
| }
|
| return true;
|
| }
|
| @@ -933,20 +660,20 @@ void VideoCaptureManager::MaybePostDesktopCaptureWindowId(
|
| if (session_it == sessions_.end())
|
| return;
|
|
|
| - DeviceEntry* const existing_device =
|
| - GetDeviceEntryByTypeAndId(session_it->second.type, session_it->second.id);
|
| + VideoCaptureController* const existing_device = LookupControllerByTypeAndId(
|
| + 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) {
|
| + if (!existing_device->IsDeviceAlive()) {
|
| 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);
|
| + DCHECK_EQ(MEDIA_DESKTOP_VIDEO_CAPTURE, existing_device->stream_type());
|
| + DesktopMediaID id = DesktopMediaID::Parse(existing_device->device_id());
|
| if (id.is_null())
|
| return;
|
|
|
| @@ -956,83 +683,70 @@ void VideoCaptureManager::MaybePostDesktopCaptureWindowId(
|
| 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));
|
| -
|
| + existing_device->SetDesktopCaptureWindowIdAsync(
|
| + window_id_it->second,
|
| + base::Bind([](scoped_refptr<VideoCaptureManager>) {},
|
| + scoped_refptr<VideoCaptureManager>(this)));
|
| notification_window_ids_.erase(window_id_it);
|
| }
|
|
|
| void VideoCaptureManager::GetPhotoCapabilities(
|
| int session_id,
|
| - VideoCaptureDevice::GetPhotoCapabilitiesCallback callback) {
|
| + media::VideoCaptureDevice::GetPhotoCapabilitiesCallback callback) {
|
| DCHECK_CURRENTLY_ON(BrowserThread::IO);
|
|
|
| - const DeviceEntry* entry = GetDeviceEntryBySessionId(session_id);
|
| - if (!entry)
|
| + const VideoCaptureController* controller =
|
| + LookupControllerBySessionId(session_id);
|
| + if (!controller)
|
| return;
|
| - VideoCaptureDevice* device = entry->video_capture_device.get();
|
| - if (device) {
|
| - VideoCaptureManager::DoGetPhotoCapabilities(std::move(callback), device);
|
| + if (controller->IsDeviceAlive()) {
|
| + controller->GetPhotoCapabilities(std::move(callback));
|
| return;
|
| }
|
| - // |entry| is known but |device| is nullptr, queue up a request for later.
|
| + // Queue up a request for later.
|
| photo_request_queue_.emplace_back(
|
| - session_id, base::Bind(&VideoCaptureManager::DoGetPhotoCapabilities, this,
|
| - base::Passed(&callback)));
|
| + session_id,
|
| + base::Bind(&VideoCaptureController::GetPhotoCapabilities,
|
| + base::Unretained(controller), base::Passed(&callback)));
|
| }
|
|
|
| void VideoCaptureManager::SetPhotoOptions(
|
| int session_id,
|
| media::mojom::PhotoSettingsPtr settings,
|
| - VideoCaptureDevice::SetPhotoOptionsCallback callback) {
|
| + media::VideoCaptureDevice::SetPhotoOptionsCallback callback) {
|
| DCHECK_CURRENTLY_ON(BrowserThread::IO);
|
|
|
| - const DeviceEntry* entry = GetDeviceEntryBySessionId(session_id);
|
| - if (!entry)
|
| + VideoCaptureController* controller = LookupControllerBySessionId(session_id);
|
| + if (!controller)
|
| return;
|
| - VideoCaptureDevice* device = entry->video_capture_device.get();
|
| - if (device) {
|
| - VideoCaptureManager::DoSetPhotoOptions(std::move(callback),
|
| - std::move(settings), device);
|
| + if (controller->IsDeviceAlive()) {
|
| + controller->SetPhotoOptions(std::move(settings), std::move(callback));
|
| return;
|
| }
|
| - // |entry| is known but |device| is nullptr, queue up a request for later.
|
| + // Queue up a request for later.
|
| photo_request_queue_.emplace_back(
|
| - session_id, base::Bind(&VideoCaptureManager::DoSetPhotoOptions, this,
|
| - base::Passed(&callback), base::Passed(&settings)));
|
| + session_id, base::Bind(&VideoCaptureController::SetPhotoOptions,
|
| + base::Unretained(controller),
|
| + base::Passed(&settings), base::Passed(&callback)));
|
| }
|
|
|
| void VideoCaptureManager::TakePhoto(
|
| int session_id,
|
| - VideoCaptureDevice::TakePhotoCallback callback) {
|
| + media::VideoCaptureDevice::TakePhotoCallback callback) {
|
| DCHECK_CURRENTLY_ON(BrowserThread::IO);
|
|
|
| - const DeviceEntry* entry = GetDeviceEntryBySessionId(session_id);
|
| - if (!entry)
|
| + VideoCaptureController* controller = LookupControllerBySessionId(session_id);
|
| + if (!controller)
|
| return;
|
| - VideoCaptureDevice* device = entry->video_capture_device.get();
|
| - if (device) {
|
| - VideoCaptureManager::DoTakePhoto(std::move(callback), device);
|
| + if (controller->IsDeviceAlive()) {
|
| + controller->TakePhoto(std::move(callback));
|
| return;
|
| }
|
| - // |entry| is known but |device| is nullptr, queue up a request for later.
|
| + // 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";
|
| + session_id,
|
| + base::Bind(&VideoCaptureController::TakePhoto,
|
| + base::Unretained(controller), base::Passed(&callback)));
|
| }
|
|
|
| void VideoCaptureManager::OnOpened(
|
| @@ -1070,9 +784,6 @@ void VideoCaptureManager::OnDevicesInfoEnumerated(
|
| 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);
|
| }
|
| @@ -1080,16 +791,12 @@ void VideoCaptureManager::OnDevicesInfoEnumerated(
|
| 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());
|
| + DCHECK(device_task_runner_->BelongsToCurrentThread());
|
| // 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.
|
| @@ -1118,73 +825,79 @@ void VideoCaptureManager::ConsolidateDevicesInfoOnDeviceThread(
|
| on_devices_enumerated_callback.Run(new_devices_info_cache);
|
| }
|
|
|
| -void VideoCaptureManager::DestroyDeviceEntryIfNoClients(DeviceEntry* entry) {
|
| +void VideoCaptureManager::DestroyControllerIfNoClients(
|
| + VideoCaptureController* controller) {
|
| DCHECK_CURRENTLY_ON(BrowserThread::IO);
|
| // Removal of the last client stops the device.
|
| - if (!entry->video_capture_controller.HasActiveClient() &&
|
| - !entry->video_capture_controller.HasPausedClient()) {
|
| + if (!controller->HasActiveClient() && !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);
|
| + << controller->stream_type()
|
| + << ", id = " << controller->device_id() << ")";
|
| +
|
| + // The VideoCaptureController is removed from |controllers_| 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 VideoCaptureController,
|
| + // VideoCaptureController, and VideoCaptureDevice.
|
| + DoStopDevice(controller);
|
| // 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);
|
| + auto controller_iter = std::find_if(
|
| + controllers_.begin(), controllers_.end(),
|
| + [controller](
|
| + const scoped_refptr<VideoCaptureController>& device_entry) {
|
| + return device_entry.get() == controller;
|
| + });
|
| + controllers_.erase(controller_iter);
|
| }
|
| }
|
|
|
| -VideoCaptureManager::DeviceEntry*
|
| -VideoCaptureManager::GetDeviceEntryBySessionId(int session_id) {
|
| +VideoCaptureController* VideoCaptureManager::LookupControllerBySessionId(
|
| + 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);
|
| + return LookupControllerByTypeAndId(session_it->second.type,
|
| + session_it->second.id);
|
| }
|
|
|
| -VideoCaptureManager::DeviceEntry*
|
| -VideoCaptureManager::GetDeviceEntryByTypeAndId(
|
| +VideoCaptureController* VideoCaptureManager::LookupControllerByTypeAndId(
|
| 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();
|
| + for (const auto& entry : controllers_) {
|
| + if (type == entry->stream_type() && device_id == entry->device_id())
|
| + return entry.get();
|
| }
|
| return nullptr;
|
| }
|
|
|
| -VideoCaptureManager::DeviceEntry*
|
| -VideoCaptureManager::GetDeviceEntryByController(
|
| +bool VideoCaptureManager::IsControllerPointerValid(
|
| const VideoCaptureController* controller) const {
|
| DCHECK_CURRENTLY_ON(BrowserThread::IO);
|
| + return base::ContainsValue(controllers_, controller);
|
| +}
|
|
|
| - // Look up |controller| in |devices_|.
|
| - for (const std::unique_ptr<DeviceEntry>& device : devices_) {
|
| - if (&device->video_capture_controller == controller)
|
| - return device.get();
|
| +VideoCaptureController* VideoCaptureManager::LookupControllerBySerialId(
|
| + int serial_id) const {
|
| + DCHECK_CURRENTLY_ON(BrowserThread::IO);
|
| +
|
| + for (const auto& entry : controllers_) {
|
| + if (entry->serial_id() == serial_id)
|
| + return entry.get();
|
| }
|
| return nullptr;
|
| }
|
|
|
| -VideoCaptureManager::DeviceEntry* VideoCaptureManager::GetDeviceEntryBySerialId(
|
| - int serial_id) const {
|
| +scoped_refptr<VideoCaptureController>
|
| +VideoCaptureManager::GetControllerSharedRefFromSerialId(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();
|
| + for (const auto& entry : controllers_) {
|
| + if (entry->serial_id() == serial_id)
|
| + return entry;
|
| }
|
| return nullptr;
|
| }
|
| @@ -1198,7 +911,7 @@ VideoCaptureManager::DeviceInfo* VideoCaptureManager::GetDeviceInfoById(
|
| return nullptr;
|
| }
|
|
|
| -VideoCaptureManager::DeviceEntry* VideoCaptureManager::GetOrCreateDeviceEntry(
|
| +VideoCaptureController* VideoCaptureManager::GetOrCreateController(
|
| media::VideoCaptureSessionId capture_session_id,
|
| const media::VideoCaptureParams& params) {
|
| DCHECK_CURRENTLY_ON(BrowserThread::IO);
|
| @@ -1210,63 +923,19 @@ VideoCaptureManager::DeviceEntry* VideoCaptureManager::GetOrCreateDeviceEntry(
|
|
|
| // 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);
|
| + VideoCaptureController* const existing_device =
|
| + LookupControllerByTypeAndId(device_info.type, device_info.id);
|
| if (existing_device) {
|
| - DCHECK_EQ(device_info.type, existing_device->stream_type);
|
| + 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();
|
| -}
|
| -
|
| -void VideoCaptureManager::SetDesktopCaptureWindowIdOnDeviceThread(
|
| - media::VideoCaptureDevice* device,
|
| - gfx::NativeViewId window_id) {
|
| - DCHECK(IsOnDeviceThread());
|
| -#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
|
| -}
|
| -
|
| -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)));
|
| + VideoCaptureController* new_device_entry = new VideoCaptureController(
|
| + device_info.id, device_info.type, params,
|
| + base::MakeUnique<InProcessBuildableVideoCaptureDevice>(
|
| + device_task_runner_, video_capture_device_factory_.get()));
|
| + controllers_.emplace_back(new_device_entry);
|
| + return new_device_entry;
|
| }
|
|
|
| base::Optional<CameraCalibration> VideoCaptureManager::GetCameraCalibration(
|
| @@ -1297,29 +966,29 @@ void VideoCaptureManager::OnApplicationStateChange(
|
| void VideoCaptureManager::ReleaseDevices() {
|
| DCHECK_CURRENTLY_ON(BrowserThread::IO);
|
|
|
| - for (auto& entry : devices_) {
|
| + for (auto& controller : controllers_) {
|
| // Do not stop Content Video Capture devices, e.g. Tab or Screen capture.
|
| - if (entry->stream_type != MEDIA_DEVICE_VIDEO_CAPTURE)
|
| + if (controller->stream_type() != MEDIA_DEVICE_VIDEO_CAPTURE)
|
| continue;
|
|
|
| - DoStopDevice(entry.get());
|
| + DoStopDevice(controller.get());
|
| }
|
| }
|
|
|
| void VideoCaptureManager::ResumeDevices() {
|
| DCHECK_CURRENTLY_ON(BrowserThread::IO);
|
|
|
| - for (auto& entry : devices_) {
|
| + for (auto& controller : controllers_) {
|
| // 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)
|
| + if (controller->stream_type() != MEDIA_DEVICE_VIDEO_CAPTURE ||
|
| + controller->IsDeviceAlive())
|
| 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) {
|
| + if (request.serial_id() == controller->serial_id()) {
|
| device_in_queue = true;
|
| break;
|
| }
|
| @@ -1328,7 +997,8 @@ void VideoCaptureManager::ResumeDevices() {
|
| 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);
|
| + QueueStartDevice(kFakeSessionId, controller.get(),
|
| + controller->parameters());
|
| }
|
| }
|
| }
|
|
|