| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved. | 2 * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved. |
| 3 * | 3 * |
| 4 * Use of this source code is governed by a BSD-style license | 4 * Use of this source code is governed by a BSD-style license |
| 5 * that can be found in the LICENSE file in the root of the source | 5 * that can be found in the LICENSE file in the root of the source |
| 6 * tree. An additional intellectual property rights grant can be found | 6 * tree. An additional intellectual property rights grant can be found |
| 7 * in the file PATENTS. All contributing project authors may | 7 * in the file PATENTS. All contributing project authors may |
| 8 * be found in the AUTHORS file in the root of the source tree. | 8 * be found in the AUTHORS file in the root of the source tree. |
| 9 */ | 9 */ |
| 10 | 10 |
| (...skipping 12 matching lines...) Expand all Loading... |
| 23 #include "webrtc/modules/desktop_capture/desktop_frame.h" | 23 #include "webrtc/modules/desktop_capture/desktop_frame.h" |
| 24 #include "webrtc/modules/desktop_capture/differ.h" | 24 #include "webrtc/modules/desktop_capture/differ.h" |
| 25 #include "webrtc/modules/desktop_capture/screen_capture_frame_queue.h" | 25 #include "webrtc/modules/desktop_capture/screen_capture_frame_queue.h" |
| 26 #include "webrtc/modules/desktop_capture/screen_capturer_helper.h" | 26 #include "webrtc/modules/desktop_capture/screen_capturer_helper.h" |
| 27 #include "webrtc/modules/desktop_capture/x11/x_server_pixel_buffer.h" | 27 #include "webrtc/modules/desktop_capture/x11/x_server_pixel_buffer.h" |
| 28 #include "webrtc/system_wrappers/interface/logging.h" | 28 #include "webrtc/system_wrappers/interface/logging.h" |
| 29 #include "webrtc/system_wrappers/interface/tick_util.h" | 29 #include "webrtc/system_wrappers/interface/tick_util.h" |
| 30 | 30 |
| 31 // TODO(sergeyu): Move this to a header where it can be shared. | 31 // TODO(sergeyu): Move this to a header where it can be shared. |
| 32 #if defined(NDEBUG) | 32 #if defined(NDEBUG) |
| 33 #define DCHECK(condition) (void)(condition) | 33 #define RTC_DCHECK(condition) (void)(condition) |
| 34 #else // NDEBUG | 34 #else // NDEBUG |
| 35 #define DCHECK(condition) if (!(condition)) {abort();} | 35 #define RTC_DCHECK(condition) \ |
| 36 if (!(condition)) { \ |
| 37 abort(); \ |
| 38 } |
| 36 #endif | 39 #endif |
| 37 | 40 |
| 38 namespace webrtc { | 41 namespace webrtc { |
| 39 | 42 |
| 40 namespace { | 43 namespace { |
| 41 | 44 |
| 42 // A class to perform video frame capturing for Linux. | 45 // A class to perform video frame capturing for Linux. |
| 43 class ScreenCapturerLinux : public ScreenCapturer, | 46 class ScreenCapturerLinux : public ScreenCapturer, |
| 44 public SharedXDisplay::XEventHandler { | 47 public SharedXDisplay::XEventHandler { |
| 45 public: | 48 public: |
| (...skipping 180 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 226 } | 229 } |
| 227 | 230 |
| 228 options_.x_display()->AddEventHandler( | 231 options_.x_display()->AddEventHandler( |
| 229 damage_event_base_ + XDamageNotify, this); | 232 damage_event_base_ + XDamageNotify, this); |
| 230 | 233 |
| 231 use_damage_ = true; | 234 use_damage_ = true; |
| 232 LOG(LS_INFO) << "Using XDamage extension."; | 235 LOG(LS_INFO) << "Using XDamage extension."; |
| 233 } | 236 } |
| 234 | 237 |
| 235 void ScreenCapturerLinux::Start(Callback* callback) { | 238 void ScreenCapturerLinux::Start(Callback* callback) { |
| 236 DCHECK(!callback_); | 239 RTC_DCHECK(!callback_); |
| 237 DCHECK(callback); | 240 RTC_DCHECK(callback); |
| 238 | 241 |
| 239 callback_ = callback; | 242 callback_ = callback; |
| 240 } | 243 } |
| 241 | 244 |
| 242 void ScreenCapturerLinux::Capture(const DesktopRegion& region) { | 245 void ScreenCapturerLinux::Capture(const DesktopRegion& region) { |
| 243 TickTime capture_start_time = TickTime::Now(); | 246 TickTime capture_start_time = TickTime::Now(); |
| 244 | 247 |
| 245 queue_.MoveToNextFrame(); | 248 queue_.MoveToNextFrame(); |
| 246 | 249 |
| 247 // Process XEvents for XDamage and cursor shape tracking. | 250 // Process XEvents for XDamage and cursor shape tracking. |
| (...skipping 30 matching lines...) Expand all Loading... |
| 278 } | 281 } |
| 279 | 282 |
| 280 DesktopFrame* result = CaptureScreen(); | 283 DesktopFrame* result = CaptureScreen(); |
| 281 last_invalid_region_ = result->updated_region(); | 284 last_invalid_region_ = result->updated_region(); |
| 282 result->set_capture_time_ms( | 285 result->set_capture_time_ms( |
| 283 (TickTime::Now() - capture_start_time).Milliseconds()); | 286 (TickTime::Now() - capture_start_time).Milliseconds()); |
| 284 callback_->OnCaptureCompleted(result); | 287 callback_->OnCaptureCompleted(result); |
| 285 } | 288 } |
| 286 | 289 |
| 287 bool ScreenCapturerLinux::GetScreenList(ScreenList* screens) { | 290 bool ScreenCapturerLinux::GetScreenList(ScreenList* screens) { |
| 288 DCHECK(screens->size() == 0); | 291 RTC_DCHECK(screens->size() == 0); |
| 289 // TODO(jiayl): implement screen enumeration. | 292 // TODO(jiayl): implement screen enumeration. |
| 290 Screen default_screen; | 293 Screen default_screen; |
| 291 default_screen.id = 0; | 294 default_screen.id = 0; |
| 292 screens->push_back(default_screen); | 295 screens->push_back(default_screen); |
| 293 return true; | 296 return true; |
| 294 } | 297 } |
| 295 | 298 |
| 296 bool ScreenCapturerLinux::SelectScreen(ScreenId id) { | 299 bool ScreenCapturerLinux::SelectScreen(ScreenId id) { |
| 297 // TODO(jiayl): implement screen selection. | 300 // TODO(jiayl): implement screen selection. |
| 298 return true; | 301 return true; |
| 299 } | 302 } |
| 300 | 303 |
| 301 bool ScreenCapturerLinux::HandleXEvent(const XEvent& event) { | 304 bool ScreenCapturerLinux::HandleXEvent(const XEvent& event) { |
| 302 if (use_damage_ && (event.type == damage_event_base_ + XDamageNotify)) { | 305 if (use_damage_ && (event.type == damage_event_base_ + XDamageNotify)) { |
| 303 const XDamageNotifyEvent* damage_event = | 306 const XDamageNotifyEvent* damage_event = |
| 304 reinterpret_cast<const XDamageNotifyEvent*>(&event); | 307 reinterpret_cast<const XDamageNotifyEvent*>(&event); |
| 305 if (damage_event->damage != damage_handle_) | 308 if (damage_event->damage != damage_handle_) |
| 306 return false; | 309 return false; |
| 307 DCHECK(damage_event->level == XDamageReportNonEmpty); | 310 RTC_DCHECK(damage_event->level == XDamageReportNonEmpty); |
| 308 return true; | 311 return true; |
| 309 } else if (event.type == ConfigureNotify) { | 312 } else if (event.type == ConfigureNotify) { |
| 310 ScreenConfigurationChanged(); | 313 ScreenConfigurationChanged(); |
| 311 return true; | 314 return true; |
| 312 } | 315 } |
| 313 return false; | 316 return false; |
| 314 } | 317 } |
| 315 | 318 |
| 316 DesktopFrame* ScreenCapturerLinux::CaptureScreen() { | 319 DesktopFrame* ScreenCapturerLinux::CaptureScreen() { |
| 317 DesktopFrame* frame = queue_.current_frame()->Share(); | 320 DesktopFrame* frame = queue_.current_frame()->Share(); |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 360 } | 363 } |
| 361 } else { | 364 } else { |
| 362 // Doing full-screen polling, or this is the first capture after a | 365 // Doing full-screen polling, or this is the first capture after a |
| 363 // screen-resolution change. In either case, need a full-screen capture. | 366 // screen-resolution change. In either case, need a full-screen capture. |
| 364 DesktopRect screen_rect = DesktopRect::MakeSize(frame->size()); | 367 DesktopRect screen_rect = DesktopRect::MakeSize(frame->size()); |
| 365 x_server_pixel_buffer_.CaptureRect(screen_rect, frame); | 368 x_server_pixel_buffer_.CaptureRect(screen_rect, frame); |
| 366 | 369 |
| 367 if (queue_.previous_frame()) { | 370 if (queue_.previous_frame()) { |
| 368 // Full-screen polling, so calculate the invalid rects here, based on the | 371 // Full-screen polling, so calculate the invalid rects here, based on the |
| 369 // changed pixels between current and previous buffers. | 372 // changed pixels between current and previous buffers. |
| 370 DCHECK(differ_.get() != NULL); | 373 RTC_DCHECK(differ_.get() != NULL); |
| 371 DCHECK(queue_.previous_frame()->data()); | 374 RTC_DCHECK(queue_.previous_frame()->data()); |
| 372 differ_->CalcDirtyRegion(queue_.previous_frame()->data(), | 375 differ_->CalcDirtyRegion(queue_.previous_frame()->data(), |
| 373 frame->data(), updated_region); | 376 frame->data(), updated_region); |
| 374 } else { | 377 } else { |
| 375 // No previous buffer, so always invalidate the whole screen, whether | 378 // No previous buffer, so always invalidate the whole screen, whether |
| 376 // or not DAMAGE is being used. DAMAGE doesn't necessarily send a | 379 // or not DAMAGE is being used. DAMAGE doesn't necessarily send a |
| 377 // full-screen notification after a screen-resolution change, so | 380 // full-screen notification after a screen-resolution change, so |
| 378 // this is done here. | 381 // this is done here. |
| 379 updated_region->SetRect(screen_rect); | 382 updated_region->SetRect(screen_rect); |
| 380 } | 383 } |
| 381 } | 384 } |
| (...skipping 14 matching lines...) Expand all Loading... |
| 396 | 399 |
| 397 void ScreenCapturerLinux::SynchronizeFrame() { | 400 void ScreenCapturerLinux::SynchronizeFrame() { |
| 398 // Synchronize the current buffer with the previous one since we do not | 401 // Synchronize the current buffer with the previous one since we do not |
| 399 // capture the entire desktop. Note that encoder may be reading from the | 402 // capture the entire desktop. Note that encoder may be reading from the |
| 400 // previous buffer at this time so thread access complaints are false | 403 // previous buffer at this time so thread access complaints are false |
| 401 // positives. | 404 // positives. |
| 402 | 405 |
| 403 // TODO(hclam): We can reduce the amount of copying here by subtracting | 406 // TODO(hclam): We can reduce the amount of copying here by subtracting |
| 404 // |capturer_helper_|s region from |last_invalid_region_|. | 407 // |capturer_helper_|s region from |last_invalid_region_|. |
| 405 // http://crbug.com/92354 | 408 // http://crbug.com/92354 |
| 406 DCHECK(queue_.previous_frame()); | 409 RTC_DCHECK(queue_.previous_frame()); |
| 407 | 410 |
| 408 DesktopFrame* current = queue_.current_frame(); | 411 DesktopFrame* current = queue_.current_frame(); |
| 409 DesktopFrame* last = queue_.previous_frame(); | 412 DesktopFrame* last = queue_.previous_frame(); |
| 410 DCHECK(current != last); | 413 RTC_DCHECK(current != last); |
| 411 for (DesktopRegion::Iterator it(last_invalid_region_); | 414 for (DesktopRegion::Iterator it(last_invalid_region_); |
| 412 !it.IsAtEnd(); it.Advance()) { | 415 !it.IsAtEnd(); it.Advance()) { |
| 413 current->CopyPixelsFrom(*last, it.rect().top_left(), it.rect()); | 416 current->CopyPixelsFrom(*last, it.rect().top_left(), it.rect()); |
| 414 } | 417 } |
| 415 } | 418 } |
| 416 | 419 |
| 417 void ScreenCapturerLinux::DeinitXlib() { | 420 void ScreenCapturerLinux::DeinitXlib() { |
| 418 if (gc_) { | 421 if (gc_) { |
| 419 XFreeGC(display(), gc_); | 422 XFreeGC(display(), gc_); |
| 420 gc_ = NULL; | 423 gc_ = NULL; |
| (...skipping 21 matching lines...) Expand all Loading... |
| 442 if (!options.x_display()) | 445 if (!options.x_display()) |
| 443 return NULL; | 446 return NULL; |
| 444 | 447 |
| 445 rtc::scoped_ptr<ScreenCapturerLinux> capturer(new ScreenCapturerLinux()); | 448 rtc::scoped_ptr<ScreenCapturerLinux> capturer(new ScreenCapturerLinux()); |
| 446 if (!capturer->Init(options)) | 449 if (!capturer->Init(options)) |
| 447 capturer.reset(); | 450 capturer.reset(); |
| 448 return capturer.release(); | 451 return capturer.release(); |
| 449 } | 452 } |
| 450 | 453 |
| 451 } // namespace webrtc | 454 } // namespace webrtc |
| OLD | NEW |