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

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

Issue 172003004: Fixit: Move tab and desktop capture code to new location. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: rebase Created 6 years, 10 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/desktop_capture_device.cc
diff --git a/content/browser/renderer_host/media/desktop_capture_device.cc b/content/browser/renderer_host/media/desktop_capture_device.cc
deleted file mode 100644
index 74ecd80fbb8db1b1fd20c4c93f56fd546f156c00..0000000000000000000000000000000000000000
--- a/content/browser/renderer_host/media/desktop_capture_device.cc
+++ /dev/null
@@ -1,421 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/browser/renderer_host/media/desktop_capture_device.h"
-
-#include "base/bind.h"
-#include "base/location.h"
-#include "base/logging.h"
-#include "base/sequenced_task_runner.h"
-#include "base/strings/string_number_conversions.h"
-#include "base/synchronization/lock.h"
-#include "base/threading/sequenced_worker_pool.h"
-#include "content/public/browser/browser_thread.h"
-#include "content/public/browser/desktop_media_id.h"
-#include "media/base/video_util.h"
-#include "third_party/libyuv/include/libyuv/scale_argb.h"
-#include "third_party/webrtc/modules/desktop_capture/desktop_and_cursor_composer.h"
-#include "third_party/webrtc/modules/desktop_capture/desktop_capture_options.h"
-#include "third_party/webrtc/modules/desktop_capture/desktop_capturer.h"
-#include "third_party/webrtc/modules/desktop_capture/desktop_frame.h"
-#include "third_party/webrtc/modules/desktop_capture/mouse_cursor_monitor.h"
-#include "third_party/webrtc/modules/desktop_capture/screen_capturer.h"
-#include "third_party/webrtc/modules/desktop_capture/window_capturer.h"
-
-namespace content {
-
-namespace {
-
-// Maximum CPU time percentage of a single core that can be consumed for desktop
-// capturing. This means that on systems where screen scraping is slow we may
-// need to capture at frame rate lower than requested. This is necessary to keep
-// UI responsive.
-const int kMaximumCpuConsumptionPercentage = 50;
-
-webrtc::DesktopRect ComputeLetterboxRect(
- const webrtc::DesktopSize& max_size,
- const webrtc::DesktopSize& source_size) {
- gfx::Rect result = media::ComputeLetterboxRegion(
- gfx::Rect(0, 0, max_size.width(), max_size.height()),
- gfx::Size(source_size.width(), source_size.height()));
- return webrtc::DesktopRect::MakeLTRB(
- result.x(), result.y(), result.right(), result.bottom());
-}
-
-} // namespace
-
-class DesktopCaptureDevice::Core
- : public base::RefCountedThreadSafe<Core>,
- public webrtc::DesktopCapturer::Callback {
- public:
- Core(scoped_refptr<base::SequencedTaskRunner> task_runner,
- scoped_ptr<webrtc::DesktopCapturer> capturer);
-
- // Implementation of VideoCaptureDevice methods.
- void AllocateAndStart(const media::VideoCaptureParams& params,
- scoped_ptr<Client> client);
- void StopAndDeAllocate();
-
- private:
- friend class base::RefCountedThreadSafe<Core>;
- virtual ~Core();
-
- // webrtc::DesktopCapturer::Callback interface
- virtual webrtc::SharedMemory* CreateSharedMemory(size_t size) OVERRIDE;
- virtual void OnCaptureCompleted(webrtc::DesktopFrame* frame) OVERRIDE;
-
- // Helper methods that run on the |task_runner_|. Posted from the
- // corresponding public methods.
- void DoAllocateAndStart(const media::VideoCaptureParams& params,
- scoped_ptr<Client> client);
- void DoStopAndDeAllocate();
-
- // Chooses new output properties based on the supplied source size and the
- // properties requested to Allocate(), and dispatches OnFrameInfo[Changed]
- // notifications.
- void RefreshCaptureFormat(const webrtc::DesktopSize& frame_size);
-
- // Method that is scheduled on |task_runner_| to be called on regular interval
- // to capture a frame.
- void OnCaptureTimer();
-
- // Captures a frame and schedules timer for the next one.
- void CaptureFrameAndScheduleNext();
-
- // Captures a single frame.
- void DoCapture();
-
- // Task runner used for capturing operations.
- scoped_refptr<base::SequencedTaskRunner> task_runner_;
-
- // The underlying DesktopCapturer instance used to capture frames.
- scoped_ptr<webrtc::DesktopCapturer> desktop_capturer_;
-
- // The device client which proxies device events to the controller. Accessed
- // on the task_runner_ thread.
- scoped_ptr<Client> client_;
-
- // Requested video capture format (width, height, frame rate, etc).
- media::VideoCaptureParams requested_params_;
-
- // Actual video capture format being generated.
- media::VideoCaptureFormat capture_format_;
-
- // Size of frame most recently captured from the source.
- webrtc::DesktopSize previous_frame_size_;
-
- // DesktopFrame into which captured frames are down-scaled and/or letterboxed,
- // depending upon the caller's requested capture capabilities. If frames can
- // be returned to the caller directly then this is NULL.
- scoped_ptr<webrtc::DesktopFrame> output_frame_;
-
- // Sub-rectangle of |output_frame_| into which the source will be scaled
- // and/or letterboxed.
- webrtc::DesktopRect output_rect_;
-
- // True when we have delayed OnCaptureTimer() task posted on
- // |task_runner_|.
- bool capture_task_posted_;
-
- // True when waiting for |desktop_capturer_| to capture current frame.
- bool capture_in_progress_;
-
- DISALLOW_COPY_AND_ASSIGN(Core);
-};
-
-DesktopCaptureDevice::Core::Core(
- scoped_refptr<base::SequencedTaskRunner> task_runner,
- scoped_ptr<webrtc::DesktopCapturer> capturer)
- : task_runner_(task_runner),
- desktop_capturer_(capturer.Pass()),
- capture_task_posted_(false),
- capture_in_progress_(false) {}
-
-DesktopCaptureDevice::Core::~Core() {
-}
-
-void DesktopCaptureDevice::Core::AllocateAndStart(
- const media::VideoCaptureParams& params,
- scoped_ptr<Client> client) {
- DCHECK_GT(params.requested_format.frame_size.GetArea(), 0);
- DCHECK_GT(params.requested_format.frame_rate, 0);
-
- task_runner_->PostTask(
- FROM_HERE,
- base::Bind(
- &Core::DoAllocateAndStart, this, params, base::Passed(&client)));
-}
-
-void DesktopCaptureDevice::Core::StopAndDeAllocate() {
- task_runner_->PostTask(FROM_HERE,
- base::Bind(&Core::DoStopAndDeAllocate, this));
-}
-
-webrtc::SharedMemory*
-DesktopCaptureDevice::Core::CreateSharedMemory(size_t size) {
- return NULL;
-}
-
-void DesktopCaptureDevice::Core::OnCaptureCompleted(
- webrtc::DesktopFrame* frame) {
- DCHECK(task_runner_->RunsTasksOnCurrentThread());
- DCHECK(capture_in_progress_);
-
- capture_in_progress_ = false;
-
- if (!frame) {
- std::string log("Failed to capture a frame.");
- LOG(ERROR) << log;
- client_->OnError(log);
- return;
- }
-
- if (!client_)
- return;
-
- scoped_ptr<webrtc::DesktopFrame> owned_frame(frame);
-
- // Handle initial frame size and size changes.
- RefreshCaptureFormat(frame->size());
-
- webrtc::DesktopSize output_size(capture_format_.frame_size.width(),
- capture_format_.frame_size.height());
- size_t output_bytes = output_size.width() * output_size.height() *
- webrtc::DesktopFrame::kBytesPerPixel;
- const uint8_t* output_data = NULL;
- scoped_ptr<uint8_t[]> flipped_frame_buffer;
-
- if (frame->size().equals(output_size)) {
- // If the captured frame matches the output size, we can return the pixel
- // data directly, without scaling.
- output_data = frame->data();
-
- // If the |frame| generated by the screen capturer is inverted then we need
- // to flip |frame|.
- // This happens only on a specific platform. Refer to crbug.com/306876.
- if (frame->stride() < 0) {
- int height = frame->size().height();
- int bytes_per_row =
- frame->size().width() * webrtc::DesktopFrame::kBytesPerPixel;
- flipped_frame_buffer.reset(new uint8_t[output_bytes]);
- uint8_t* dest = flipped_frame_buffer.get();
- for (int row = 0; row < height; ++row) {
- memcpy(dest, output_data, bytes_per_row);
- dest += bytes_per_row;
- output_data += frame->stride();
- }
- output_data = flipped_frame_buffer.get();
- }
- } else {
- // Otherwise we need to down-scale and/or letterbox to the target format.
-
- // Allocate a buffer of the correct size to scale the frame into.
- // |output_frame_| is cleared whenever |output_rect_| changes, so we don't
- // need to worry about clearing out stale pixel data in letterboxed areas.
- if (!output_frame_) {
- output_frame_.reset(new webrtc::BasicDesktopFrame(output_size));
- memset(output_frame_->data(), 0, output_bytes);
- }
- DCHECK(output_frame_->size().equals(output_size));
-
- // TODO(wez): Optimize this to scale only changed portions of the output,
- // using ARGBScaleClip().
- uint8_t* output_rect_data = output_frame_->data() +
- output_frame_->stride() * output_rect_.top() +
- webrtc::DesktopFrame::kBytesPerPixel * output_rect_.left();
- libyuv::ARGBScale(frame->data(), frame->stride(),
- frame->size().width(), frame->size().height(),
- output_rect_data, output_frame_->stride(),
- output_rect_.width(), output_rect_.height(),
- libyuv::kFilterBilinear);
- output_data = output_frame_->data();
- }
-
- client_->OnIncomingCapturedFrame(
- output_data, output_bytes, base::TimeTicks::Now(), 0, capture_format_);
-}
-
-void DesktopCaptureDevice::Core::DoAllocateAndStart(
- const media::VideoCaptureParams& params,
- scoped_ptr<Client> client) {
- DCHECK(task_runner_->RunsTasksOnCurrentThread());
- DCHECK(desktop_capturer_);
- DCHECK(client.get());
- DCHECK(!client_.get());
-
- client_ = client.Pass();
- requested_params_ = params;
-
- capture_format_ = requested_params_.requested_format;
-
- // This capturer always outputs ARGB, non-interlaced.
- capture_format_.pixel_format = media::PIXEL_FORMAT_ARGB;
-
- desktop_capturer_->Start(this);
-
- CaptureFrameAndScheduleNext();
-}
-
-void DesktopCaptureDevice::Core::DoStopAndDeAllocate() {
- DCHECK(task_runner_->RunsTasksOnCurrentThread());
- client_.reset();
- output_frame_.reset();
- previous_frame_size_.set(0, 0);
- desktop_capturer_.reset();
-}
-
-void DesktopCaptureDevice::Core::RefreshCaptureFormat(
- const webrtc::DesktopSize& frame_size) {
- if (previous_frame_size_.equals(frame_size))
- return;
-
- // Clear the output frame, if any, since it will either need resizing, or
- // clearing of stale data in letterbox areas, anyway.
- output_frame_.reset();
-
- if (previous_frame_size_.is_empty() ||
- requested_params_.allow_resolution_change) {
- // If this is the first frame, or the receiver supports variable resolution
- // then determine the output size by treating the requested width & height
- // as maxima.
- if (frame_size.width() >
- requested_params_.requested_format.frame_size.width() ||
- frame_size.height() >
- requested_params_.requested_format.frame_size.height()) {
- output_rect_ = ComputeLetterboxRect(
- webrtc::DesktopSize(
- requested_params_.requested_format.frame_size.width(),
- requested_params_.requested_format.frame_size.height()),
- frame_size);
- output_rect_.Translate(-output_rect_.left(), -output_rect_.top());
- } else {
- output_rect_ = webrtc::DesktopRect::MakeSize(frame_size);
- }
- capture_format_.frame_size.SetSize(output_rect_.width(),
- output_rect_.height());
- } else {
- // Otherwise the output frame size cannot change, so just scale and
- // letterbox.
- output_rect_ = ComputeLetterboxRect(
- webrtc::DesktopSize(capture_format_.frame_size.width(),
- capture_format_.frame_size.height()),
- frame_size);
- }
-
- previous_frame_size_ = frame_size;
-}
-
-void DesktopCaptureDevice::Core::OnCaptureTimer() {
- DCHECK(capture_task_posted_);
- capture_task_posted_ = false;
-
- if (!client_)
- return;
-
- CaptureFrameAndScheduleNext();
-}
-
-void DesktopCaptureDevice::Core::CaptureFrameAndScheduleNext() {
- DCHECK(task_runner_->RunsTasksOnCurrentThread());
- DCHECK(!capture_task_posted_);
-
- base::TimeTicks started_time = base::TimeTicks::Now();
- DoCapture();
- base::TimeDelta last_capture_duration = base::TimeTicks::Now() - started_time;
-
- // Limit frame-rate to reduce CPU consumption.
- base::TimeDelta capture_period = std::max(
- (last_capture_duration * 100) / kMaximumCpuConsumptionPercentage,
- base::TimeDelta::FromSeconds(1) / capture_format_.frame_rate);
-
- // Schedule a task for the next frame.
- capture_task_posted_ = true;
- task_runner_->PostDelayedTask(
- FROM_HERE, base::Bind(&Core::OnCaptureTimer, this),
- capture_period - last_capture_duration);
-}
-
-void DesktopCaptureDevice::Core::DoCapture() {
- DCHECK(task_runner_->RunsTasksOnCurrentThread());
- DCHECK(!capture_in_progress_);
-
- capture_in_progress_ = true;
- desktop_capturer_->Capture(webrtc::DesktopRegion());
-
- // Currently only synchronous implementations of DesktopCapturer are
- // supported.
- DCHECK(!capture_in_progress_);
-}
-
-// static
-scoped_ptr<media::VideoCaptureDevice> DesktopCaptureDevice::Create(
- const DesktopMediaID& source) {
- scoped_refptr<base::SequencedWorkerPool> blocking_pool =
- BrowserThread::GetBlockingPool();
- scoped_refptr<base::SequencedTaskRunner> task_runner =
- blocking_pool->GetSequencedTaskRunner(
- blocking_pool->GetSequenceToken());
-
- webrtc::DesktopCaptureOptions options =
- webrtc::DesktopCaptureOptions::CreateDefault();
- // Leave desktop effects enabled during WebRTC captures.
- options.set_disable_effects(false);
-
- scoped_ptr<webrtc::DesktopCapturer> capturer;
-
- switch (source.type) {
- case DesktopMediaID::TYPE_SCREEN: {
- scoped_ptr<webrtc::ScreenCapturer> screen_capturer;
- screen_capturer.reset(webrtc::ScreenCapturer::Create(options));
- if (screen_capturer && screen_capturer->SelectScreen(source.id)) {
- capturer.reset(new webrtc::DesktopAndCursorComposer(
- screen_capturer.release(),
- webrtc::MouseCursorMonitor::CreateForScreen(options, source.id)));
- }
- break;
- }
-
- case DesktopMediaID::TYPE_WINDOW: {
- scoped_ptr<webrtc::WindowCapturer> window_capturer(
- webrtc::WindowCapturer::Create(options));
- if (window_capturer && window_capturer->SelectWindow(source.id)) {
- capturer.reset(new webrtc::DesktopAndCursorComposer(
- window_capturer.release(),
- webrtc::MouseCursorMonitor::CreateForWindow(options, source.id)));
- }
- break;
- }
-
- default: {
- NOTREACHED();
- }
- }
-
- scoped_ptr<media::VideoCaptureDevice> result;
- if (capturer)
- result.reset(new DesktopCaptureDevice(task_runner, capturer.Pass()));
-
- return result.Pass();
-}
-
-DesktopCaptureDevice::DesktopCaptureDevice(
- scoped_refptr<base::SequencedTaskRunner> task_runner,
- scoped_ptr<webrtc::DesktopCapturer> capturer)
- : core_(new Core(task_runner, capturer.Pass())) {}
-
-DesktopCaptureDevice::~DesktopCaptureDevice() {
- StopAndDeAllocate();
-}
-
-void DesktopCaptureDevice::AllocateAndStart(
- const media::VideoCaptureParams& params,
- scoped_ptr<Client> client) {
- core_->AllocateAndStart(params, client.Pass());
-}
-
-void DesktopCaptureDevice::StopAndDeAllocate() {
- core_->StopAndDeAllocate();
-}
-
-} // namespace content

Powered by Google App Engine
This is Rietveld 408576698