Fix mouse warp with 2x displays
[chromium-blink-merge.git] / remoting / host / cast_video_capturer_adapter.cc
blob37d36fe418e2aff939503b12009fcae0a4b01704
1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "remoting/host/cast_video_capturer_adapter.h"
7 #include "third_party/webrtc/modules/desktop_capture/desktop_frame.h"
9 namespace remoting {
11 // Number of frames to be captured per second.
12 const int kFramesPerSec = 10;
14 CastVideoCapturerAdapter::CastVideoCapturerAdapter(
15 scoped_ptr<webrtc::DesktopCapturer> capturer)
16 : desktop_capturer_(capturer.Pass()) {
17 DCHECK(desktop_capturer_);
19 thread_checker_.DetachFromThread();
21 // Disable video adaptation since we don't intend to use it.
22 set_enable_video_adapter(false);
25 CastVideoCapturerAdapter::~CastVideoCapturerAdapter() {
26 DCHECK(!capture_timer_);
29 webrtc::SharedMemory* CastVideoCapturerAdapter::CreateSharedMemory(
30 size_t size) {
31 return nullptr;
34 void CastVideoCapturerAdapter::OnCaptureCompleted(webrtc::DesktopFrame* frame) {
35 scoped_ptr<webrtc::DesktopFrame> owned_frame(frame);
37 // Drop the owned_frame if there were no changes.
38 if (!owned_frame || owned_frame->updated_region().is_empty()) {
39 owned_frame.reset();
40 return;
43 // Convert the webrtc::DesktopFrame to a cricket::CapturedFrame.
44 cricket::CapturedFrame captured_frame;
45 captured_frame.width = owned_frame->size().width();
46 captured_frame.height = owned_frame->size().height();
47 base::TimeTicks current_time = base::TimeTicks::Now();
48 captured_frame.elapsed_time = (current_time - start_time_).InMicroseconds() *
49 base::Time::kNanosecondsPerMicrosecond;
50 captured_frame.time_stamp =
51 current_time.ToInternalValue() * base::Time::kNanosecondsPerMicrosecond;
52 captured_frame.data = owned_frame->data();
54 // The data_size attribute must be set. If multiple formats are supported,
55 // this should be set appropriately for each one.
56 captured_frame.data_size =
57 (captured_frame.width * webrtc::DesktopFrame::kBytesPerPixel * 8 + 7) /
58 8 * captured_frame.height;
59 captured_frame.fourcc = cricket::FOURCC_ARGB;
61 SignalFrameCaptured(this, &captured_frame);
64 bool CastVideoCapturerAdapter::GetBestCaptureFormat(
65 const cricket::VideoFormat& desired,
66 cricket::VideoFormat* best_format) {
67 DCHECK(thread_checker_.CalledOnValidThread());
69 // For now, just used the desired width and height.
70 best_format->width = desired.width;
71 best_format->height = desired.height;
72 best_format->fourcc = cricket::FOURCC_ARGB;
73 best_format->interval = FPS_TO_INTERVAL(kFramesPerSec);
74 return true;
77 cricket::CaptureState CastVideoCapturerAdapter::Start(
78 const cricket::VideoFormat& capture_format) {
79 DCHECK(thread_checker_.CalledOnValidThread());
80 DCHECK(!capture_timer_);
81 DCHECK_EQ(capture_format.fourcc, (static_cast<uint32>(cricket::FOURCC_ARGB)));
83 if (!desktop_capturer_) {
84 VLOG(1) << "CastVideoCapturerAdapter failed to start.";
85 return cricket::CS_FAILED;
88 // This is required to tell the cricket::VideoCapturer base class what the
89 // capture format will be.
90 SetCaptureFormat(&capture_format);
92 desktop_capturer_->Start(this);
94 // Save the Start() time of |desktop_capturer_|. This will be used
95 // to estimate the creation time of the frame source, to set the elapsed_time
96 // of future CapturedFrames in OnCaptureCompleted().
97 start_time_ = base::TimeTicks::Now();
98 capture_timer_.reset(new base::RepeatingTimer<CastVideoCapturerAdapter>());
99 capture_timer_->Start(FROM_HERE,
100 base::TimeDelta::FromMicroseconds(
101 GetCaptureFormat()->interval /
102 (base::Time::kNanosecondsPerMicrosecond)),
103 this,
104 &CastVideoCapturerAdapter::CaptureNextFrame);
106 return cricket::CS_RUNNING;
109 // Similar to the base class implementation with some important differences:
110 // 1. Does not call either Stop() or Start(), as those would affect the state of
111 // |desktop_capturer_|.
112 // 2. Does not support unpausing after stopping the capturer. It is unclear
113 // if that flow needs to be supported.
114 bool CastVideoCapturerAdapter::Pause(bool pause) {
115 DCHECK(thread_checker_.CalledOnValidThread());
117 if (pause) {
118 if (capture_state() == cricket::CS_PAUSED)
119 return true;
121 bool running = capture_state() == cricket::CS_STARTING ||
122 capture_state() == cricket::CS_RUNNING;
124 DCHECK_EQ(running, IsRunning());
126 if (!running) {
127 LOG(ERROR)
128 << "Cannot pause CastVideoCapturerAdapter.";
129 return false;
132 // Stop |capture_timer_| and set capture state to cricket::CS_PAUSED.
133 capture_timer_->Stop();
134 SetCaptureState(cricket::CS_PAUSED);
136 VLOG(1) << "CastVideoCapturerAdapter paused.";
138 return true;
139 } else { // Unpausing.
140 if (capture_state() != cricket::CS_PAUSED || !GetCaptureFormat() ||
141 !capture_timer_) {
142 LOG(ERROR) << "Cannot unpause CastVideoCapturerAdapter.";
143 return false;
146 // Restart |capture_timer_| and set capture state to cricket::CS_RUNNING;
147 capture_timer_->Start(FROM_HERE,
148 base::TimeDelta::FromMicroseconds(
149 GetCaptureFormat()->interval /
150 (base::Time::kNanosecondsPerMicrosecond)),
151 this,
152 &CastVideoCapturerAdapter::CaptureNextFrame);
153 SetCaptureState(cricket::CS_RUNNING);
155 VLOG(1) << "CastVideoCapturerAdapter unpaused.";
157 return true;
160 void CastVideoCapturerAdapter::Stop() {
161 DCHECK(thread_checker_.CalledOnValidThread());
162 DCHECK_NE(capture_state(), cricket::CS_STOPPED);
164 capture_timer_.reset();
166 SetCaptureFormat(nullptr);
167 SetCaptureState(cricket::CS_STOPPED);
169 VLOG(1) << "CastVideoCapturerAdapter stopped.";
173 bool CastVideoCapturerAdapter::IsRunning() {
174 DCHECK(thread_checker_.CalledOnValidThread());
176 return capture_timer_->IsRunning();
179 bool CastVideoCapturerAdapter::IsScreencast() const {
180 return true;
183 bool CastVideoCapturerAdapter::GetPreferredFourccs(
184 std::vector<uint32>* fourccs) {
185 DCHECK(thread_checker_.CalledOnValidThread());
186 if (!fourccs)
187 return false;
188 fourccs->push_back(cricket::FOURCC_ARGB);
189 return true;
192 void CastVideoCapturerAdapter::CaptureNextFrame() {
193 // If we are paused, then don't capture.
194 if (!IsRunning())
195 return;
197 desktop_capturer_->Capture(webrtc::DesktopRegion());
200 } // namespace remoting