| 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
 | 
| 
 |