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