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

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

Issue 2551193002: [Mojo Video Capture] Decouple VCController from VCBufferPool and VCDeviceClient (Closed)
Patch Set: Created 4 years 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/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 e1830eed9fa09a7704246e7d7ac534ed97e5d574..2532acf786544f34f279cf235bc00394b874f218 100644
--- a/content/browser/renderer_host/media/video_capture_manager.cc
+++ b/content/browser/renderer_host/media/video_capture_manager.cc
@@ -26,12 +26,17 @@
#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/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) && !defined(OS_ANDROID)
@@ -113,8 +118,11 @@ void ConsolidateCaptureFormats(media::VideoCaptureFormats* formats) {
}
}
-// The maximum number of buffers in the capture pipeline. See
-// VideoCaptureController ctor comments for more details.
+// 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
@@ -143,6 +151,11 @@ 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 {
@@ -153,36 +166,28 @@ namespace content {
// is no device present.
// Phase 2: When a request to "start" the entry comes in (via
// HandleQueuedStartRequest()), a VideoCaptureDevice::Client is created
-// via video_capture_controller()->NewDeviceClient() and is used to schedule the
+// via CreateDeviceClient() and is used to schedule the
// creation and start of a VideoCaptureDevice 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().
-class VideoCaptureManager::DeviceEntry {
+struct VideoCaptureManager::DeviceEntry {
public:
DeviceEntry(MediaStreamType stream_type,
const std::string& id,
std::unique_ptr<VideoCaptureController> controller,
const media::VideoCaptureParams& params);
~DeviceEntry();
+ std::unique_ptr<media::VideoCaptureDevice::Client> CreateDeviceClient();
+ std::unique_ptr<media::FrameBufferHost> CreateFrameBufferHost();
const int serial_id;
const MediaStreamType stream_type;
const std::string id;
const media::VideoCaptureParams parameters;
-
- VideoCaptureController* video_capture_controller() const;
- media::VideoCaptureDevice* video_capture_device() const;
-
- void SetVideoCaptureDevice(std::unique_ptr<VideoCaptureDevice> device);
- std::unique_ptr<VideoCaptureDevice> ReleaseVideoCaptureDevice();
-
- private:
- const std::unique_ptr<VideoCaptureController> video_capture_controller_;
-
- std::unique_ptr<VideoCaptureDevice> video_capture_device_;
-
- base::ThreadChecker thread_checker_;
+ const std::unique_ptr<VideoCaptureController> video_capture_controller;
+ scoped_refptr<media::VideoCaptureBufferPool> buffer_pool;
+ std::unique_ptr<media::VideoCaptureDevice> video_capture_device;
};
// Bundles a media::VideoCaptureDeviceDescriptor with corresponding supported
@@ -198,6 +203,28 @@ struct VideoCaptureManager::DeviceInfo {
media::VideoCaptureFormats supported_formats;
};
+class BufferPoolFrameBufferHost : public media::FrameBufferHost {
+ public:
+ BufferPoolFrameBufferHost(
+ scoped_refptr<media::VideoCaptureBufferPool> buffer_pool)
+ : buffer_pool_(std::move(buffer_pool)) {}
+
+ void SetBufferHold(int buffer_id) override {
+ buffer_pool_->HoldForConsumers(buffer_id, 1);
+ }
+
+ void ReleaseBufferHold(int buffer_id) override {
+ buffer_pool_->RelinquishConsumerHold(buffer_id, 1);
+ }
+
+ mojo::ScopedSharedBufferHandle GetHandleForTransit(int buffer_id) override {
+ return buffer_pool_->GetHandleForTransit(buffer_id);
+ }
+
+ private:
+ scoped_refptr<media::VideoCaptureBufferPool> buffer_pool_;
mcasas 2016/12/06 20:02:24 media::FrameBufferHost (and BufferPoolFrameBufferH
chfremer 2016/12/06 21:07:41 The reason is that I am trying to avoid shared own
+};
+
// Class used for queuing request for starting a device.
class VideoCaptureManager::CaptureDeviceStartRequest {
public:
@@ -231,38 +258,41 @@ VideoCaptureManager::DeviceEntry::DeviceEntry(
stream_type(stream_type),
id(id),
parameters(params),
- video_capture_controller_(std::move(controller)) {}
+ video_capture_controller(std::move(controller)) {}
VideoCaptureManager::DeviceEntry::~DeviceEntry() {
- DCHECK(thread_checker_.CalledOnValidThread());
// 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);
-}
-
-void VideoCaptureManager::DeviceEntry::SetVideoCaptureDevice(
- std::unique_ptr<VideoCaptureDevice> device) {
- DCHECK(thread_checker_.CalledOnValidThread());
- video_capture_device_.swap(device);
+ DCHECK(video_capture_device == nullptr);
}
-std::unique_ptr<media::VideoCaptureDevice>
-VideoCaptureManager::DeviceEntry::ReleaseVideoCaptureDevice() {
- DCHECK(thread_checker_.CalledOnValidThread());
- return std::move(video_capture_device_);
-}
+std::unique_ptr<media::VideoCaptureDevice::Client>
+VideoCaptureManager::DeviceEntry::CreateDeviceClient() {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
-VideoCaptureController*
-VideoCaptureManager::DeviceEntry::video_capture_controller() const {
- DCHECK(thread_checker_.CalledOnValidThread());
- return video_capture_controller_.get();
+ const int max_buffers = stream_type == MEDIA_TAB_VIDEO_CAPTURE
+ ? kMaxNumberOfBuffersForTabCapture
+ : kMaxNumberOfBuffers;
+ buffer_pool = new media::VideoCaptureBufferPoolImpl(
+ base::MakeUnique<media::VideoCaptureBufferTrackerFactoryImpl>(),
+ max_buffers);
+
+ return base::MakeUnique<media::VideoCaptureDeviceClient>(
+ base::MakeUnique<VideoFrameReceiverOnIOThread>(
+ video_capture_controller->GetWeakPtrForIOThread()),
+ buffer_pool,
+ base::Bind(
+ &CreateGpuJpegDecoder,
+ base::Bind(&media::VideoFrameReceiver::OnIncomingCapturedVideoFrame,
+ video_capture_controller->GetWeakPtrForIOThread())));
}
-media::VideoCaptureDevice*
-VideoCaptureManager::DeviceEntry::video_capture_device() const {
- DCHECK(thread_checker_.CalledOnValidThread());
- return video_capture_device_.get();
+std::unique_ptr<media::FrameBufferHost>
+VideoCaptureManager::DeviceEntry::CreateFrameBufferHost() {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ DCHECK(buffer_pool);
+ return base::MakeUnique<BufferPoolFrameBufferHost>(buffer_pool);
}
VideoCaptureManager::DeviceInfo::DeviceInfo() = default;
@@ -384,8 +414,7 @@ void VideoCaptureManager::Close(int capture_session_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->video_capture_controller->StopSession(capture_session_id);
// StopSession() may have removed the last client, so we might need to
// close the device.
@@ -433,17 +462,18 @@ void VideoCaptureManager::DoStopDevice(DeviceEntry* entry) {
DVLOG(3) << "DoStopDevice. Send stop request for device = " << entry->id
<< " serial_id = " << entry->serial_id << ".";
- entry->video_capture_controller()->OnLog(
+ entry->video_capture_controller->OnLog(
base::StringPrintf("Stopping device: id: %s", entry->id.c_str()));
- entry->video_capture_controller()->SetConsumerFeedbackObserver(nullptr);
+ entry->video_capture_controller->SetConsumerFeedbackObserver(nullptr);
+ entry->video_capture_controller->SetFrameBufferHost(nullptr);
// |entry->video_capture_device| can be null if creating the device has
// failed.
- if (entry->video_capture_device()) {
+ if (entry->video_capture_device) {
device_task_runner_->PostTask(
FROM_HERE,
base::Bind(&VideoCaptureManager::DoStopDeviceOnDeviceThread, this,
- base::Passed(entry->ReleaseVideoCaptureDevice())));
+ base::Passed(&entry->video_capture_device)));
mcasas 2016/12/06 20:02:24 std::move(entry->video_capture_device())
chfremer 2016/12/06 21:07:41 Hmm, I don't fully understand the documentation of
}
}
@@ -465,6 +495,11 @@ void VideoCaptureManager::HandleQueuedStartRequest() {
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();
+ std::unique_ptr<media::FrameBufferHost> frame_buffer_host =
+ entry->CreateFrameBufferHost();
+
base::Callback<std::unique_ptr<VideoCaptureDevice>(void)>
start_capture_function;
@@ -475,16 +510,16 @@ void VideoCaptureManager::HandleQueuedStartRequest() {
// held in the browser-side VideoCaptureDevice::Name structure.
const DeviceInfo* found = GetDeviceInfoById(entry->id);
if (found) {
- entry->video_capture_controller()->OnLog(
+ 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()));
- start_capture_function = base::Bind(
- &VideoCaptureManager::DoStartDeviceCaptureOnDeviceThread, this,
- found->descriptor, request->params(),
- base::Passed(entry->video_capture_controller()->NewDeviceClient()));
+ 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
@@ -495,8 +530,8 @@ void VideoCaptureManager::HandleQueuedStartRequest() {
"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();
+ entry->video_capture_controller->OnLog(log_message);
+ entry->video_capture_controller->OnError();
// Drop the failed start request.
device_start_queue_.pop_front();
@@ -507,15 +542,13 @@ void VideoCaptureManager::HandleQueuedStartRequest() {
case MEDIA_TAB_VIDEO_CAPTURE:
start_capture_function = base::Bind(
&VideoCaptureManager::DoStartTabCaptureOnDeviceThread, this,
- entry->id, request->params(),
- base::Passed(entry->video_capture_controller()->NewDeviceClient()));
+ 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(entry->video_capture_controller()->NewDeviceClient()));
+ entry->id, request->params(), base::Passed(std::move(device_client)));
break;
default: {
@@ -523,14 +556,17 @@ void VideoCaptureManager::HandleQueuedStartRequest() {
return;
}
}
+ // Passing raw pointer |device_client_ptr| is safe, because it will
+ // be owned by the device returned by |start_capture_function|.
base::PostTaskAndReplyWithResult(
device_task_runner_.get(), FROM_HERE, start_capture_function,
base::Bind(&VideoCaptureManager::OnDeviceStarted, this,
- request->serial_id()));
+ request->serial_id(), base::Passed(&frame_buffer_host)));
}
void VideoCaptureManager::OnDeviceStarted(
int serial_id,
+ std::unique_ptr<media::FrameBufferHost> frame_buffer_host,
std::unique_ptr<VideoCaptureDevice> device) {
DVLOG(3) << __func__;
DCHECK_CURRENTLY_ON(BrowserThread::IO);
@@ -551,15 +587,19 @@ void VideoCaptureManager::OnDeviceStarted(
} else {
DeviceEntry* const entry = GetDeviceEntryBySerialId(serial_id);
DCHECK(entry);
- DCHECK(!entry->video_capture_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->SetVideoCaptureDevice(std::move(device));
+ DCHECK(!entry->video_capture_device);
+ if (device) {
+ entry->video_capture_controller->SetFrameBufferHost(
+ std::move(frame_buffer_host));
+ // 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 =
@@ -572,8 +612,8 @@ void VideoCaptureManager::OnDeviceStarted(
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());
+ if (maybe_entry && maybe_entry->video_capture_device) {
+ request->second.Run(maybe_entry->video_capture_device.get());
photo_request_queue_.erase(request);
}
}
@@ -686,21 +726,21 @@ void VideoCaptureManager::StartCaptureForClient(
return;
}
- DCHECK(entry->video_capture_controller());
+ DCHECK(entry->video_capture_controller);
LogVideoCaptureEvent(VIDEO_CAPTURE_START_CAPTURE);
// First client starts the device.
- if (!entry->video_capture_controller()->HasActiveClient() &&
- !entry->video_capture_controller()->HasPausedClient()) {
+ 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);
+ done_cb.Run(entry->video_capture_controller->GetWeakPtrForIOThread());
+ entry->video_capture_controller->AddClient(client_id, client_handler,
+ session_id, params);
}
void VideoCaptureManager::StopCaptureForClient(
@@ -765,7 +805,7 @@ void VideoCaptureManager::PauseCaptureForClient(
controller->PauseClient(client_id, client_handler);
if (!had_active_client || controller->HasActiveClient())
return;
- if (media::VideoCaptureDevice* device = entry->video_capture_device()) {
+ if (media::VideoCaptureDevice* device = entry->video_capture_device.get()) {
device_task_runner_->PostTask(
FROM_HERE,
base::Bind(&VideoCaptureDevice::MaybeSuspend,
@@ -795,7 +835,7 @@ void VideoCaptureManager::ResumeCaptureForClient(
controller->ResumeClient(client_id, client_handler);
if (had_active_client || !controller->HasActiveClient())
return;
- if (media::VideoCaptureDevice* device = entry->video_capture_device()) {
+ if (media::VideoCaptureDevice* device = entry->video_capture_device.get()) {
device_task_runner_->PostTask(
FROM_HERE,
base::Bind(&VideoCaptureDevice::Resume,
@@ -812,7 +852,7 @@ void VideoCaptureManager::RequestRefreshFrameForClient(
DCHECK_CURRENTLY_ON(BrowserThread::IO);
if (DeviceEntry* entry = GetDeviceEntryByController(controller)) {
- if (media::VideoCaptureDevice* device = entry->video_capture_device()) {
+ if (media::VideoCaptureDevice* device = entry->video_capture_device.get()) {
device_task_runner_->PostTask(
FROM_HERE,
base::Bind(&VideoCaptureDevice::RequestRefreshFrame,
@@ -860,7 +900,7 @@ bool VideoCaptureManager::GetDeviceFormatsInUse(
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());
+ device_in_use->video_capture_controller->GetVideoCaptureFormat());
}
return true;
}
@@ -888,7 +928,7 @@ void VideoCaptureManager::MaybePostDesktopCaptureWindowId(
return;
}
- if (!existing_device->video_capture_device()) {
+ if (!existing_device->video_capture_device) {
DVLOG(2) << "Screen capture device not yet started.";
return;
}
@@ -910,8 +950,7 @@ void VideoCaptureManager::MaybePostDesktopCaptureWindowId(
device_task_runner_->PostTask(
FROM_HERE,
base::Bind(&VideoCaptureManager::SetDesktopCaptureWindowIdOnDeviceThread,
- this,
- existing_device->video_capture_device(),
+ this, existing_device->video_capture_device.get(),
window_id_it->second));
notification_window_ids_.erase(window_id_it);
@@ -925,7 +964,7 @@ void VideoCaptureManager::GetPhotoCapabilities(
const DeviceEntry* entry = GetDeviceEntryBySessionId(session_id);
if (!entry)
return;
- VideoCaptureDevice* device = entry->video_capture_device();
+ VideoCaptureDevice* device = entry->video_capture_device.get();
if (device) {
VideoCaptureManager::DoGetPhotoCapabilities(std::move(callback), device);
return;
@@ -945,7 +984,7 @@ void VideoCaptureManager::SetPhotoOptions(
const DeviceEntry* entry = GetDeviceEntryBySessionId(session_id);
if (!entry)
return;
- VideoCaptureDevice* device = entry->video_capture_device();
+ VideoCaptureDevice* device = entry->video_capture_device.get();
if (device) {
VideoCaptureManager::DoSetPhotoOptions(std::move(callback),
std::move(settings), device);
@@ -965,7 +1004,7 @@ void VideoCaptureManager::TakePhoto(
const DeviceEntry* entry = GetDeviceEntryBySessionId(session_id);
if (!entry)
return;
- VideoCaptureDevice* device = entry->video_capture_device();
+ VideoCaptureDevice* device = entry->video_capture_device.get();
if (device) {
VideoCaptureManager::DoTakePhoto(std::move(callback), device);
return;
@@ -1073,8 +1112,8 @@ void VideoCaptureManager::ConsolidateDevicesInfoOnDeviceThread(
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()) {
+ if (!entry->video_capture_controller->HasActiveClient() &&
+ !entry->video_capture_controller->HasPausedClient()) {
DVLOG(1) << "VideoCaptureManager stopping device (type = "
<< entry->stream_type << ", id = " << entry->id << ")";
@@ -1124,7 +1163,7 @@ VideoCaptureManager::GetDeviceEntryByController(
// Look up |controller| in |devices_|.
for (const std::unique_ptr<DeviceEntry>& device : devices_) {
- if (device->video_capture_controller() == controller)
+ if (device->video_capture_controller.get() == controller)
return device.get();
}
return nullptr;
@@ -1169,15 +1208,12 @@ VideoCaptureManager::DeviceEntry* VideoCaptureManager::GetOrCreateDeviceEntry(
return existing_device;
}
- const int max_buffers = device_info.type == MEDIA_TAB_VIDEO_CAPTURE ?
- kMaxNumberOfBuffersForTabCapture : kMaxNumberOfBuffers;
- std::unique_ptr<VideoCaptureController> video_capture_controller(
- new VideoCaptureController(max_buffers));
- DeviceEntry* new_device =
+ auto video_capture_controller = base::MakeUnique<VideoCaptureController>();
+ auto new_device_entry =
new DeviceEntry(device_info.type, device_info.id,
std::move(video_capture_controller), params);
- devices_.emplace_back(new_device);
- return new_device;
+ devices_.emplace_back(new_device_entry);
+ return new_device_entry;
}
void VideoCaptureManager::SetDesktopCaptureWindowIdOnDeviceThread(
@@ -1263,7 +1299,7 @@ void VideoCaptureManager::ResumeDevices() {
// 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())
+ entry->video_capture_device)
continue;
// Check if the device is already in the start queue.

Powered by Google App Engine
This is Rietveld 408576698