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