OLD | NEW |
1 /* | 1 /* |
2 * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. | 2 * Copyright (c) 2016 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 395 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
406 rtc::CritScope lock(&g_container->duplication_lock); | 406 rtc::CritScope lock(&g_container->duplication_lock); |
407 // Make sure nobody is using current instance. | 407 // Make sure nobody is using current instance. |
408 rtc::CritScope lock2(&g_container->acquire_lock); | 408 rtc::CritScope lock2(&g_container->acquire_lock); |
409 if (g_container->duplication) { | 409 if (g_container->duplication) { |
410 return true; | 410 return true; |
411 } | 411 } |
412 | 412 |
413 _com_error error = g_container->output1->DuplicateOutput( | 413 _com_error error = g_container->output1->DuplicateOutput( |
414 static_cast<IUnknown*>(g_container->device), | 414 static_cast<IUnknown*>(g_container->device), |
415 g_container->duplication.GetAddressOf()); | 415 g_container->duplication.GetAddressOf()); |
416 if (error.Error() == S_OK && g_container->duplication) { | 416 if (error.Error() != S_OK || !g_container->duplication) { |
417 memset(&g_container->duplication_desc, 0, sizeof(DXGI_OUTDUPL_DESC)); | |
418 g_container->duplication->GetDesc(&g_container->duplication_desc); | |
419 if (g_container->duplication_desc.ModeDesc.Format != | |
420 DXGI_FORMAT_B8G8R8A8_UNORM) { | |
421 g_container->duplication.Reset(); | |
422 LOG(LS_ERROR) << "IDXGIDuplicateOutput does not use RGBA (8 bit) " | |
423 "format, which is required by downstream components, " | |
424 "format is " | |
425 << g_container->duplication_desc.ModeDesc.Format; | |
426 return false; | |
427 } | |
428 return true; | |
429 } else { | |
430 // Make sure we have correct signal and duplicate the output next time. | |
431 g_container->duplication.Reset(); | 417 g_container->duplication.Reset(); |
432 LOG(LS_WARNING) << "Failed to duplicate output from IDXGIOutput1, error " | 418 LOG(LS_WARNING) << "Failed to duplicate output from IDXGIOutput1, error " |
433 << error.ErrorMessage() << ", with code " | 419 << error.ErrorMessage() << ", with code " |
434 << error.Error(); | 420 << error.Error(); |
| 421 return false; |
435 } | 422 } |
436 | 423 |
437 return false; | 424 memset(&g_container->duplication_desc, 0, sizeof(DXGI_OUTDUPL_DESC)); |
| 425 g_container->duplication->GetDesc(&g_container->duplication_desc); |
| 426 if (g_container->duplication_desc.ModeDesc.Format != |
| 427 DXGI_FORMAT_B8G8R8A8_UNORM) { |
| 428 g_container->duplication.Reset(); |
| 429 LOG(LS_ERROR) << "IDXGIDuplicateOutput does not use RGBA (8 bit) " |
| 430 "format, which is required by downstream components, " |
| 431 "format is " |
| 432 << g_container->duplication_desc.ModeDesc.Format; |
| 433 return false; |
| 434 } |
| 435 |
| 436 return true; |
438 } | 437 } |
439 | 438 |
440 bool ScreenCapturerWinDirectx::ForceDuplicateOutput() { | 439 bool ScreenCapturerWinDirectx::ForceDuplicateOutput() { |
441 // We are updating the instance. | 440 // We are updating the instance. |
442 rtc::CritScope lock(&g_container->duplication_lock); | 441 rtc::CritScope lock(&g_container->duplication_lock); |
443 // Make sure nobody is using current instance. | 442 // Make sure nobody is using current instance. |
444 rtc::CritScope lock2(&g_container->acquire_lock); | 443 rtc::CritScope lock2(&g_container->acquire_lock); |
445 | 444 |
446 if (g_container->duplication) { | 445 if (g_container->duplication) { |
447 g_container->duplication->ReleaseFrame(); | 446 g_container->duplication->ReleaseFrame(); |
(...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
613 RTC_DCHECK(result); | 612 RTC_DCHECK(result); |
614 *result->mutable_updated_region() = | 613 *result->mutable_updated_region() = |
615 surfaces_.current_frame()->get()->updated_region(); | 614 surfaces_.current_frame()->get()->updated_region(); |
616 return result; | 615 return result; |
617 } | 616 } |
618 | 617 |
619 void ScreenCapturerWinDirectx::Capture(const DesktopRegion& region) { | 618 void ScreenCapturerWinDirectx::Capture(const DesktopRegion& region) { |
620 RTC_DCHECK(callback_); | 619 RTC_DCHECK(callback_); |
621 | 620 |
622 if (!g_container->duplication && !DuplicateOutput()) { | 621 if (!g_container->duplication && !DuplicateOutput()) { |
623 // Receive a capture request when application is shutting down, or between | 622 // Failed to initialize desktop duplication. |
624 // mode change. | 623 callback_->OnCaptureResult(Result::ERROR_PERMANENT, nullptr); |
625 callback_->OnCaptureCompleted(nullptr); | |
626 return; | 624 return; |
627 } | 625 } |
628 | 626 |
629 RTC_DCHECK(g_container->duplication); | 627 RTC_DCHECK(g_container->duplication); |
630 int64_t capture_start_time_nanos = rtc::TimeNanos(); | 628 int64_t capture_start_time_nanos = rtc::TimeNanos(); |
631 | 629 |
632 if (!SetThreadExecutionState(ES_DISPLAY_REQUIRED | ES_SYSTEM_REQUIRED)) { | 630 if (!SetThreadExecutionState(ES_DISPLAY_REQUIRED | ES_SYSTEM_REQUIRED)) { |
633 if (!set_thread_execution_state_failed_) { | 631 if (!set_thread_execution_state_failed_) { |
634 set_thread_execution_state_failed_ = true; | 632 set_thread_execution_state_failed_ = true; |
635 LOG(LS_WARNING) << "Failed to make system & display power assertion: " | 633 LOG(LS_WARNING) << "Failed to make system & display power assertion: " |
(...skipping 13 matching lines...) Expand all Loading... |
649 EmitCurrentFrame(); | 647 EmitCurrentFrame(); |
650 return; | 648 return; |
651 } | 649 } |
652 | 650 |
653 if (error.Error() != S_OK) { | 651 if (error.Error() != S_OK) { |
654 LOG(LS_ERROR) << "Failed to capture frame, error " << error.ErrorMessage() | 652 LOG(LS_ERROR) << "Failed to capture frame, error " << error.ErrorMessage() |
655 << ", code " << error.Error(); | 653 << ", code " << error.Error(); |
656 if (ForceDuplicateOutput()) { | 654 if (ForceDuplicateOutput()) { |
657 EmitCurrentFrame(); | 655 EmitCurrentFrame(); |
658 } else { | 656 } else { |
659 callback_->OnCaptureCompleted(nullptr); | 657 callback_->OnCaptureResult(Result::ERROR_TEMPORARY, nullptr); |
660 } | 658 } |
661 return; | 659 return; |
662 } | 660 } |
663 | 661 |
664 if (frame_info.AccumulatedFrames == 0) { | 662 if (frame_info.AccumulatedFrames == 0) { |
665 g_container->duplication->ReleaseFrame(); | 663 g_container->duplication->ReleaseFrame(); |
666 EmitCurrentFrame(); | 664 EmitCurrentFrame(); |
667 return; | 665 return; |
668 } | 666 } |
669 | 667 |
670 // Everything looks good so far, build next frame. | 668 // Everything looks good so far, build next frame. |
671 std::unique_ptr<DesktopFrame> result = | 669 std::unique_ptr<DesktopFrame> result = |
672 ProcessFrame(frame_info, resource.Get()); | 670 ProcessFrame(frame_info, resource.Get()); |
673 // DetectUpdatedRegion may release last g_container->duplication. But | 671 // DetectUpdatedRegion may release last g_container->duplication. But |
674 // ForctDuplicateOutput function will always release last frame, so there is | 672 // ForctDuplicateOutput function will always release last frame, so there is |
675 // no potential leak. | 673 // no potential leak. |
676 if (g_container->duplication) { | 674 if (g_container->duplication) { |
677 g_container->duplication->ReleaseFrame(); | 675 g_container->duplication->ReleaseFrame(); |
678 } | 676 } |
679 if (!result) { | 677 if (!result) { |
680 callback_->OnCaptureCompleted(nullptr); | 678 callback_->OnCaptureResult(nullptr); |
681 return; | 679 return; |
682 } | 680 } |
683 | 681 |
684 result->set_capture_time_ms( | 682 result->set_capture_time_ms( |
685 (rtc::TimeNanos() - capture_start_time_nanos) / | 683 (rtc::TimeNanos() - capture_start_time_nanos) / |
686 rtc::kNumNanosecsPerMillisec); | 684 rtc::kNumNanosecsPerMillisec); |
687 callback_->OnCaptureCompleted(result.release()); | 685 callback_->OnCaptureResult(Result::SUCCESS, std::move(result)); |
688 } | 686 } |
689 | 687 |
690 bool ScreenCapturerWinDirectx::GetScreenList(ScreenList* screens) { | 688 bool ScreenCapturerWinDirectx::GetScreenList(ScreenList* screens) { |
691 return true; | 689 return true; |
692 } | 690 } |
693 | 691 |
694 bool ScreenCapturerWinDirectx::SelectScreen(ScreenId id) { | 692 bool ScreenCapturerWinDirectx::SelectScreen(ScreenId id) { |
695 // Only full desktop capture is supported. | 693 // Only full desktop capture is supported. |
696 return id == kFullDesktopScreenId; | 694 return id == kFullDesktopScreenId; |
697 } | 695 } |
698 | 696 |
699 void ScreenCapturerWinDirectx::EmitCurrentFrame() { | 697 void ScreenCapturerWinDirectx::EmitCurrentFrame() { |
700 if (!surfaces_.current_frame()->get()->bits()) { | 698 if (!surfaces_.current_frame()->get()->bits()) { |
701 // At the very begining, we have not captured any frames. | 699 // At the very begining, we have not captured any frames. |
702 callback_->OnCaptureCompleted(nullptr); | 700 callback_->OnCaptureResult(Result::ERROR_TEMPORARY, nullptr); |
703 return; | 701 return; |
704 } | 702 } |
705 | 703 |
706 if (shared_memory_factory_) { | 704 if (shared_memory_factory_) { |
707 // If shared_memory_factory_ is provided, last frame is stored in frames_ | 705 // If shared_memory_factory_ is provided, last frame is stored in frames_ |
708 // queue. If there is not an existing frame (at the very begining), we can | 706 // queue. If there is not an existing frame (at the very begining), we can |
709 // only return a nullptr. | 707 // only return a nullptr. |
710 if (frames_.current_frame()) { | 708 if (frames_.current_frame()) { |
711 std::unique_ptr<SharedDesktopFrame> frame( | 709 std::unique_ptr<SharedDesktopFrame> frame = |
712 frames_.current_frame()->Share()); | 710 frames_.current_frame()->Share(); |
713 frame->mutable_updated_region()->Clear(); | 711 frame->mutable_updated_region()->Clear(); |
714 callback_->OnCaptureCompleted(frame.release()); | 712 callback_->OnCaptureResult(Result::SUCCESS, std::move(frame)); |
715 } else { | 713 } else { |
716 callback_->OnCaptureCompleted(nullptr); | 714 callback_->OnCaptureResult(Result::ERROR_TEMPORARY, nullptr); |
717 } | 715 } |
718 return; | 716 return; |
719 } | 717 } |
720 | 718 |
721 // If there is no shared_memory_factory_, last frame is stored in surfaces_ | 719 // If there is no shared_memory_factory_, last frame is stored in surfaces_ |
722 // queue. | 720 // queue. |
723 std::unique_ptr<DesktopFrame> frame( | 721 std::unique_ptr<DesktopFrame> frame( |
724 new DxgiDesktopFrame(*surfaces_.current_frame())); | 722 new DxgiDesktopFrame(*surfaces_.current_frame())); |
725 callback_->OnCaptureCompleted(frame.release()); | 723 callback_->OnCaptureResult(Result::SUCCESS, std::move(frame)); |
726 } | 724 } |
727 | 725 |
728 } // namespace webrtc | 726 } // namespace webrtc |
OLD | NEW |