Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(45)

Side by Side Diff: webrtc/modules/desktop_capture/win/screen_capturer_win_directx.cc

Issue 1988783003: Use std::unique_ptr<> to pass frame ownership in DesktopCapturer impls. (Closed) Base URL: https://chromium.googlesource.com/external/webrtc.git@master
Patch Set: Created 4 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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();
448 g_container->duplication.Reset(); 447 g_container->duplication.Reset();
449 } 448 }
450 449
451 return DuplicateOutput(); 450 return DuplicateOutput();
452 } 451 }
453 452
454 ScreenCapturerWinDirectx::ScreenCapturerWinDirectx( 453 ScreenCapturerWinDirectx::ScreenCapturerWinDirectx(
455 const DesktopCaptureOptions& options) 454 const DesktopCaptureOptions& options)
456 : callback_(nullptr), set_thread_execution_state_failed_(false) { 455 : callback_(nullptr), set_thread_execution_state_failed_(false) {
457 RTC_DCHECK(g_container && g_container->initialize_result); 456 RTC_DCHECK(g_container && g_container->initialize_result);
458 457
459 // Texture instance won't change forever. 458 // Texture instance won't change forever.
460 while (!surfaces_.current_frame()) { 459 while (!surfaces_.current_frame()) {
461 surfaces_.ReplaceCurrentFrame( 460 surfaces_.ReplaceCurrentFrame(std::unique_ptr<rtc::scoped_refptr<Texture>>(
462 new rtc::scoped_refptr<Texture>(new Texture())); 461 new rtc::scoped_refptr<Texture>(new Texture())));
463 surfaces_.MoveToNextFrame(); 462 surfaces_.MoveToNextFrame();
464 } 463 }
465 } 464 }
466 465
467 ScreenCapturerWinDirectx::~ScreenCapturerWinDirectx() {} 466 ScreenCapturerWinDirectx::~ScreenCapturerWinDirectx() {}
468 467
469 void ScreenCapturerWinDirectx::Start(Callback* callback) { 468 void ScreenCapturerWinDirectx::Start(Callback* callback) {
470 RTC_DCHECK(!callback_); 469 RTC_DCHECK(!callback_);
471 RTC_DCHECK(callback); 470 RTC_DCHECK(callback);
472 471
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after
586 // Current frame does not have a same size as last captured surface. 585 // Current frame does not have a same size as last captured surface.
587 std::unique_ptr<DesktopFrame> new_frame = 586 std::unique_ptr<DesktopFrame> new_frame =
588 SharedMemoryDesktopFrame::Create( 587 SharedMemoryDesktopFrame::Create(
589 surfaces_.current_frame()->get()->size(), 588 surfaces_.current_frame()->get()->size(),
590 shared_memory_factory_.get()); 589 shared_memory_factory_.get());
591 if (!new_frame) { 590 if (!new_frame) {
592 LOG(LS_ERROR) << "Failed to allocate a new SharedMemoryDesktopFrame"; 591 LOG(LS_ERROR) << "Failed to allocate a new SharedMemoryDesktopFrame";
593 return std::unique_ptr<DesktopFrame>(); 592 return std::unique_ptr<DesktopFrame>();
594 } 593 }
595 frames_.ReplaceCurrentFrame( 594 frames_.ReplaceCurrentFrame(
596 SharedDesktopFrame::Wrap(new_frame.release())); 595 SharedDesktopFrame::Wrap(std::move(new_frame)));
597 } 596 }
598 result.reset(frames_.current_frame()->Share()); 597 result = frames_.current_frame()->Share();
599 598
600 std::unique_ptr<DesktopFrame> frame( 599 std::unique_ptr<DesktopFrame> frame(
601 new DxgiDesktopFrame(*surfaces_.current_frame())); 600 new DxgiDesktopFrame(*surfaces_.current_frame()));
602 // Copy data into SharedMemory. 601 // Copy data into SharedMemory.
603 for (DesktopRegion::Iterator it( 602 for (DesktopRegion::Iterator it(
604 surfaces_.current_frame()->get()->copied_region()); 603 surfaces_.current_frame()->get()->copied_region());
605 !it.IsAtEnd(); 604 !it.IsAtEnd();
606 it.Advance()) { 605 it.Advance()) {
607 result->CopyPixelsFrom(*frame, it.rect().top_left(), it.rect()); 606 result->CopyPixelsFrom(*frame, it.rect().top_left(), it.rect());
608 } 607 }
609 result->set_dpi(frame->dpi()); 608 result->set_dpi(frame->dpi());
610 } else { 609 } else {
611 result.reset(new DxgiDesktopFrame(*surfaces_.current_frame())); 610 result.reset(new DxgiDesktopFrame(*surfaces_.current_frame()));
612 } 611 }
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
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(Result::ERROR_TEMPORARY, 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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698