16e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved.
26e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
36e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)// found in the LICENSE file.
46e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
56e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include "remoting/host/cast_video_capturer_adapter.h"
66e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
76e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include "third_party/webrtc/modules/desktop_capture/desktop_frame.h"
86e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
96e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)namespace remoting {
106e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
116e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)// Number of frames to be captured per second.
126e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)const int kFramesPerSec = 10;
136e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
146e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)CastVideoCapturerAdapter::CastVideoCapturerAdapter(
1503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    scoped_ptr<webrtc::DesktopCapturer> capturer)
1603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    : desktop_capturer_(capturer.Pass()) {
1703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  DCHECK(desktop_capturer_);
186e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
196e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  thread_checker_.DetachFromThread();
206e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
216e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  // Disable video adaptation since we don't intend to use it.
226e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  set_enable_video_adapter(false);
236e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)}
246e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
256e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)CastVideoCapturerAdapter::~CastVideoCapturerAdapter() {
266e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  DCHECK(!capture_timer_);
276e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)}
286e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
296e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)webrtc::SharedMemory* CastVideoCapturerAdapter::CreateSharedMemory(
306e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    size_t size) {
316e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  return NULL;
326e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)}
336e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
346e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)void CastVideoCapturerAdapter::OnCaptureCompleted(webrtc::DesktopFrame* frame) {
356e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  scoped_ptr<webrtc::DesktopFrame> owned_frame(frame);
366e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
376e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  // Drop the owned_frame if there were no changes.
386e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  if (!owned_frame || owned_frame->updated_region().is_empty()) {
396e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    owned_frame.reset();
406e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    return;
416e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  }
426e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
436e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  // Convert the webrtc::DesktopFrame to a cricket::CapturedFrame.
446e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  cricket::CapturedFrame captured_frame;
456e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  captured_frame.width = owned_frame->size().width();
466e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  captured_frame.height = owned_frame->size().height();
476e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  base::TimeTicks current_time = base::TimeTicks::Now();
486e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  captured_frame.elapsed_time = (current_time - start_time_).InMicroseconds() *
496e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                                base::Time::kNanosecondsPerMicrosecond;
506e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  captured_frame.time_stamp =
516e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      current_time.ToInternalValue() * base::Time::kNanosecondsPerMicrosecond;
526e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  captured_frame.data = owned_frame->data();
536e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
546e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  // The data_size attribute must be set. If multiple formats are supported,
556e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  // this should be set appropriately for each one.
566e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  captured_frame.data_size =
576e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      (captured_frame.width * webrtc::DesktopFrame::kBytesPerPixel * 8 + 7) /
586e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      8 * captured_frame.height;
596e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  captured_frame.fourcc = cricket::FOURCC_ARGB;
606e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
616e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  SignalFrameCaptured(this, &captured_frame);
626e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)}
636e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
646e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)bool CastVideoCapturerAdapter::GetBestCaptureFormat(
656e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    const cricket::VideoFormat& desired,
666e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    cricket::VideoFormat* best_format) {
676e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  DCHECK(thread_checker_.CalledOnValidThread());
686e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
696e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  // For now, just used the desired width and height.
706e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  best_format->width = desired.width;
716e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  best_format->height = desired.height;
726e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  best_format->fourcc = cricket::FOURCC_ARGB;
736e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  best_format->interval = FPS_TO_INTERVAL(kFramesPerSec);
746e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  return true;
756e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)}
766e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
776e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)cricket::CaptureState CastVideoCapturerAdapter::Start(
786e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    const cricket::VideoFormat& capture_format) {
796e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  DCHECK(thread_checker_.CalledOnValidThread());
806e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  DCHECK(!capture_timer_);
816e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  DCHECK_EQ(capture_format.fourcc, (static_cast<uint32>(cricket::FOURCC_ARGB)));
826e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
8303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  if (!desktop_capturer_) {
846e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    VLOG(1) << "CastVideoCapturerAdapter failed to start.";
856e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    return cricket::CS_FAILED;
866e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  }
876e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
886e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  // This is required to tell the cricket::VideoCapturer base class what the
896e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  // capture format will be.
906e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  SetCaptureFormat(&capture_format);
916e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
9203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  desktop_capturer_->Start(this);
936e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
9403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  // Save the Start() time of |desktop_capturer_|. This will be used
956e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  // to estimate the creation time of the frame source, to set the elapsed_time
966e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  // of future CapturedFrames in OnCaptureCompleted().
976e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  start_time_ = base::TimeTicks::Now();
986e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  capture_timer_.reset(new base::RepeatingTimer<CastVideoCapturerAdapter>());
996e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  capture_timer_->Start(FROM_HERE,
1006e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                        base::TimeDelta::FromMicroseconds(
1016e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                            GetCaptureFormat()->interval /
1026e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                            (base::Time::kNanosecondsPerMicrosecond)),
1036e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                        this,
1046e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                        &CastVideoCapturerAdapter::CaptureNextFrame);
1056e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
1066e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  return cricket::CS_RUNNING;
1076e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)}
1086e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
1096e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)// Similar to the base class implementation with some important differences:
1106e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)// 1. Does not call either Stop() or Start(), as those would affect the state of
11103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)// |desktop_capturer_|.
1126e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)// 2. Does not support unpausing after stopping the capturer. It is unclear
1136e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)// if that flow needs to be supported.
1146e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)bool CastVideoCapturerAdapter::Pause(bool pause) {
1156e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  DCHECK(thread_checker_.CalledOnValidThread());
1166e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
1176e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  if (pause) {
1186e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    if (capture_state() == cricket::CS_PAUSED)
1196e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      return true;
1206e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
1216e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    bool running = capture_state() == cricket::CS_STARTING ||
1226e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                   capture_state() == cricket::CS_RUNNING;
1236e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
1246e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    DCHECK_EQ(running, IsRunning());
1256e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
1266e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    if (!running) {
1276e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      LOG(ERROR)
1286e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)          << "Cannot pause CastVideoCapturerAdapter.";
1296e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      return false;
1306e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    }
1316e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
1326e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    // Stop |capture_timer_| and set capture state to cricket::CS_PAUSED.
1336e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    capture_timer_->Stop();
1346e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    SetCaptureState(cricket::CS_PAUSED);
1356e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
1366e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    VLOG(1) << "CastVideoCapturerAdapter paused.";
1376e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
1386e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    return true;
1396e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  } else {  // Unpausing.
1406e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    if (capture_state() != cricket::CS_PAUSED || !GetCaptureFormat() ||
1416e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)        !capture_timer_) {
1426e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      LOG(ERROR) << "Cannot unpause CastVideoCapturerAdapter.";
1436e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      return false;
1446e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    }
1456e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
1466e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    // Restart |capture_timer_| and set capture state to cricket::CS_RUNNING;
1476e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    capture_timer_->Start(FROM_HERE,
1486e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                          base::TimeDelta::FromMicroseconds(
1496e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                              GetCaptureFormat()->interval /
1506e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                              (base::Time::kNanosecondsPerMicrosecond)),
1516e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                          this,
1526e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                          &CastVideoCapturerAdapter::CaptureNextFrame);
1536e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    SetCaptureState(cricket::CS_RUNNING);
1546e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
1556e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    VLOG(1) << "CastVideoCapturerAdapter unpaused.";
1566e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  }
1576e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  return true;
1586e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)}
1596e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
1606e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)void CastVideoCapturerAdapter::Stop() {
1616e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  DCHECK(thread_checker_.CalledOnValidThread());
1626e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  DCHECK_NE(capture_state(), cricket::CS_STOPPED);
1636e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
1646e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  capture_timer_.reset();
1656e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
1666e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  SetCaptureFormat(NULL);
1676e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  SetCaptureState(cricket::CS_STOPPED);
1686e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
1696e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  VLOG(1) << "CastVideoCapturerAdapter stopped.";
1706e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)}
1716e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
1726e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
1736e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)bool CastVideoCapturerAdapter::IsRunning() {
1746e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  DCHECK(thread_checker_.CalledOnValidThread());
1756e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
1766e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  return capture_timer_->IsRunning();
1776e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)}
1786e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
1796e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)bool CastVideoCapturerAdapter::IsScreencast() const {
1806e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  return true;
1816e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)}
1826e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
1836e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)bool CastVideoCapturerAdapter::GetPreferredFourccs(
1846e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    std::vector<uint32>* fourccs) {
1856e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  DCHECK(thread_checker_.CalledOnValidThread());
1866e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  if (!fourccs)
1876e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    return false;
1886e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  fourccs->push_back(cricket::FOURCC_ARGB);
1896e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  return true;
1906e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)}
1916e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
1926e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)void CastVideoCapturerAdapter::CaptureNextFrame() {
1936e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  // If we are paused, then don't capture.
1946e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  if (!IsRunning())
1956e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    return;
1966e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
19703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  desktop_capturer_->Capture(webrtc::DesktopRegion());
1986e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)}
1996e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
2006e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)}  // namespace remoting
2016e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
202