diff --git a/modules/desktop_capture/BUILD.gn b/modules/desktop_capture/BUILD.gn index 04d8cd5285..3aa1b982b6 100644 --- a/modules/desktop_capture/BUILD.gn +++ b/modules/desktop_capture/BUILD.gn @@ -478,8 +478,7 @@ rtc_library("desktop_capture_generic") { ] } - if (!is_win && !is_mac && !rtc_use_x11_extensions && !rtc_use_pipewire && - !is_fuchsia) { + if (!is_win && !is_mac && !rtc_use_x11_extensions && !rtc_use_pipewire) { sources += [ "mouse_cursor_monitor_null.cc", "screen_capturer_null.cc", @@ -510,23 +509,6 @@ rtc_library("desktop_capture_generic") { "../../system_wrappers:metrics", ] - if (is_fuchsia) { - sources += [ - "mouse_cursor_monitor_null.cc", - "screen_capturer_fuchsia.cc", - "screen_capturer_fuchsia.h", - "window_capturer_null.cc", - ] - deps += [ - "../../rtc_base:rtc_numerics", - "//third_party/fuchsia-sdk/sdk/fidl/fuchsia.sysmem", - "//third_party/fuchsia-sdk/sdk/fidl/fuchsia.ui.composition", - "//third_party/fuchsia-sdk/sdk/fidl/fuchsia.ui.scenic", - "//third_party/fuchsia-sdk/sdk/pkg/scenic_cpp", - "//third_party/fuchsia-sdk/sdk/pkg/sys_cpp", - ] - } - if (is_win) { sources += [ "cropping_window_capturer_win.cc", diff --git a/modules/desktop_capture/screen_capturer_fuchsia.cc b/modules/desktop_capture/screen_capturer_fuchsia.cc deleted file mode 100644 index 6ccde6d3ab..0000000000 --- a/modules/desktop_capture/screen_capturer_fuchsia.cc +++ /dev/null @@ -1,398 +0,0 @@ -/* - * Copyright 2022 The WebRTC project authors. All Rights Reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -#include "modules/desktop_capture/screen_capturer_fuchsia.h" - -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include "modules/desktop_capture/blank_detector_desktop_capturer_wrapper.h" -#include "modules/desktop_capture/desktop_capture_options.h" -#include "modules/desktop_capture/desktop_capture_types.h" -#include "modules/desktop_capture/desktop_capturer.h" -#include "modules/desktop_capture/desktop_frame.h" -#include "modules/desktop_capture/desktop_geometry.h" -#include "modules/desktop_capture/fallback_desktop_capturer_wrapper.h" -#include "rtc_base/checks.h" -#include "rtc_base/logging.h" -#include "rtc_base/numerics/divide_round.h" -#include "rtc_base/time_utils.h" - -namespace webrtc { - -namespace { - -static constexpr uint32_t kMinBufferCount = 2; -static constexpr uint32_t kFuchsiaBytesPerPixel = 4; -static constexpr DesktopCapturer::SourceId kFuchsiaScreenId = 1; -// 500 milliseconds -static constexpr zx::duration kEventDelay = zx::msec(500); -static constexpr fuchsia::sysmem::ColorSpaceType kSRGBColorSpace = - fuchsia::sysmem::ColorSpaceType::SRGB; -static constexpr fuchsia::sysmem::PixelFormatType kBGRA32PixelFormatType = - fuchsia::sysmem::PixelFormatType::BGRA32; - -// Round |value| up to the closest multiple of |multiple| -size_t RoundUpToMultiple(size_t value, size_t multiple) { - return DivideRoundUp(value, multiple) * multiple; -} - -} // namespace - -std::unique_ptr DesktopCapturer::CreateRawScreenCapturer( - const DesktopCaptureOptions& options) { - std::unique_ptr capturer(new ScreenCapturerFuchsia()); - return capturer; -} - -ScreenCapturerFuchsia::ScreenCapturerFuchsia() - : component_context_( - sys::ComponentContext::CreateAndServeOutgoingDirectory()) {} - -ScreenCapturerFuchsia::~ScreenCapturerFuchsia() { - // unmap virtual memory mapped pointers - uint32_t virt_mem_bytes = - buffer_collection_info_.settings.buffer_settings.size_bytes; - for (uint32_t buffer_index = 0; - buffer_index < buffer_collection_info_.buffer_count; buffer_index++) { - uintptr_t address = - reinterpret_cast(virtual_memory_mapped_addrs_[buffer_index]); - zx_status_t status = zx::vmar::root_self()->unmap(address, virt_mem_bytes); - RTC_DCHECK(status == ZX_OK); - } -} - -void ScreenCapturerFuchsia::Start(Callback* callback) { - RTC_DCHECK(!callback_); - RTC_DCHECK(callback); - callback_ = callback; - - fatal_error_ = false; - - SetupBuffers(); -} - -void ScreenCapturerFuchsia::CaptureFrame() { - if (fatal_error_) { - callback_->OnCaptureResult(Result::ERROR_PERMANENT, nullptr); - return; - } - - int64_t capture_start_time_nanos = rtc::TimeNanos(); - - zx::event event; - zx::event dup; - zx_status_t status = zx::event::create(0, &event); - if (status != ZX_OK) { - RTC_LOG(LS_ERROR) << "Failed to create event: " << status; - callback_->OnCaptureResult(Result::ERROR_TEMPORARY, nullptr); - return; - } - event.duplicate(ZX_RIGHT_SAME_RIGHTS, &dup); - - fuchsia::ui::composition::GetNextFrameArgs next_frame_args; - next_frame_args.set_event(std::move(dup)); - - fuchsia::ui::composition::ScreenCapture_GetNextFrame_Result result; - screen_capture_->GetNextFrame(std::move(next_frame_args), &result); - if (result.is_err()) { - RTC_LOG(LS_ERROR) << "fuchsia.ui.composition.GetNextFrame() failed: " - << result.err() << "\n"; - callback_->OnCaptureResult(Result::ERROR_TEMPORARY, nullptr); - return; - } - - status = event.wait_one(ZX_EVENT_SIGNALED, zx::deadline_after(kEventDelay), - nullptr); - if (status != ZX_OK) { - RTC_LOG(LS_ERROR) << "Timed out waiting for ScreenCapture to render frame: " - << status; - callback_->OnCaptureResult(Result::ERROR_TEMPORARY, nullptr); - return; - } - uint32_t buffer_index = result.response().buffer_id(); - - // TODO(bugs.webrtc.org/14097): Use SharedMemoryDesktopFrame and - // ScreenCaptureFrameQueue - std::unique_ptr frame( - new BasicDesktopFrame(DesktopSize(width_, height_))); - - uint32_t pixels_per_row = GetPixelsPerRow( - buffer_collection_info_.settings.image_format_constraints); - uint32_t stride = kFuchsiaBytesPerPixel * pixels_per_row; - frame->CopyPixelsFrom(virtual_memory_mapped_addrs_[buffer_index], stride, - DesktopRect::MakeWH(width_, height_)); - - fuchsia::ui::composition::ScreenCapture_ReleaseFrame_Result release_result; - screen_capture_->ReleaseFrame(buffer_index, &release_result); - if (release_result.is_err()) { - RTC_LOG(LS_ERROR) << "fuchsia.ui.composition.ReleaseFrame() failed: " - << release_result.err(); - } - - int capture_time_ms = (rtc::TimeNanos() - capture_start_time_nanos) / - rtc::kNumNanosecsPerMillisec; - frame->set_capture_time_ms(capture_time_ms); - callback_->OnCaptureResult(Result::SUCCESS, std::move(frame)); -} - -bool ScreenCapturerFuchsia::GetSourceList(SourceList* screens) { - RTC_DCHECK(screens->size() == 0); - // Fuchsia only supports single monitor display at this point - screens->push_back({kFuchsiaScreenId, std::string("Fuchsia monitor")}); - return true; -} - -bool ScreenCapturerFuchsia::SelectSource(SourceId id) { - if (id == kFuchsiaScreenId || id == kFullDesktopScreenId) { - return true; - } - return false; -} - -fuchsia::sysmem::BufferCollectionConstraints -ScreenCapturerFuchsia::GetBufferConstraints() { - fuchsia::sysmem::BufferCollectionConstraints constraints; - constraints.usage.cpu = - fuchsia::sysmem::cpuUsageRead | fuchsia::sysmem::cpuUsageWrite; - constraints.min_buffer_count = kMinBufferCount; - - constraints.has_buffer_memory_constraints = true; - constraints.buffer_memory_constraints.ram_domain_supported = true; - constraints.buffer_memory_constraints.cpu_domain_supported = true; - - constraints.image_format_constraints_count = 1; - fuchsia::sysmem::ImageFormatConstraints& image_constraints = - constraints.image_format_constraints[0]; - image_constraints.color_spaces_count = 1; - image_constraints.color_space[0] = - fuchsia::sysmem::ColorSpace{.type = kSRGBColorSpace}; - image_constraints.pixel_format.type = kBGRA32PixelFormatType; - image_constraints.pixel_format.has_format_modifier = true; - image_constraints.pixel_format.format_modifier.value = - fuchsia::sysmem::FORMAT_MODIFIER_LINEAR; - - image_constraints.required_min_coded_width = width_; - image_constraints.required_min_coded_height = height_; - image_constraints.required_max_coded_width = width_; - image_constraints.required_max_coded_height = height_; - - image_constraints.bytes_per_row_divisor = kFuchsiaBytesPerPixel; - - return constraints; -} - -void ScreenCapturerFuchsia::SetupBuffers() { - fuchsia::ui::scenic::ScenicSyncPtr scenic; - zx_status_t status = component_context_->svc()->Connect(scenic.NewRequest()); - if (status != ZX_OK) { - fatal_error_ = true; - RTC_LOG(LS_ERROR) << "Failed to connect to Scenic: " << status; - return; - } - - bool scenic_uses_flatland = false; - // TODO(fxbug.dev/100303): Remove when Flatland is the only API. - scenic->UsesFlatland(&scenic_uses_flatland); - if (!scenic_uses_flatland) { - fatal_error_ = true; - RTC_LOG(LS_ERROR) << "Screen capture not supported without Flatland."; - return; - } - - fuchsia::ui::gfx::DisplayInfo display_info; - status = scenic->GetDisplayInfo(&display_info); - if (status != ZX_OK) { - fatal_error_ = true; - RTC_LOG(LS_ERROR) << "Failed to connect to get display dimensions: " - << status; - return; - } - width_ = display_info.width_in_px; - height_ = display_info.height_in_px; - - status = component_context_->svc()->Connect(sysmem_allocator_.NewRequest()); - if (status != ZX_OK) { - fatal_error_ = true; - RTC_LOG(LS_ERROR) << "Failed to connect to Sysmem Allocator: " << status; - return; - } - - fuchsia::sysmem::BufferCollectionTokenSyncPtr sysmem_token; - status = - sysmem_allocator_->AllocateSharedCollection(sysmem_token.NewRequest()); - if (status != ZX_OK) { - fatal_error_ = true; - RTC_LOG(LS_ERROR) - << "fuchsia.sysmem.Allocator.AllocateSharedCollection() failed: " - << status; - return; - } - - fuchsia::sysmem::BufferCollectionTokenSyncPtr flatland_token; - status = sysmem_token->Duplicate(ZX_RIGHT_SAME_RIGHTS, - flatland_token.NewRequest()); - if (status != ZX_OK) { - fatal_error_ = true; - RTC_LOG(LS_ERROR) - << "fuchsia.sysmem.BufferCollectionToken.Duplicate() failed: " - << status; - return; - } - - status = sysmem_token->Sync(); - if (status != ZX_OK) { - fatal_error_ = true; - RTC_LOG(LS_ERROR) << "fuchsia.sysmem.BufferCollectionToken.Sync() failed: " - << status; - return; - } - - status = sysmem_allocator_->BindSharedCollection(std::move(sysmem_token), - collection_.NewRequest()); - if (status != ZX_OK) { - fatal_error_ = true; - RTC_LOG(LS_ERROR) - << "fuchsia.sysmem.Allocator.BindSharedCollection() failed: " << status; - return; - } - - status = collection_->SetConstraints(/*has_constraints=*/true, - GetBufferConstraints()); - if (status != ZX_OK) { - fatal_error_ = true; - RTC_LOG(LS_ERROR) - << "fuchsia.sysmem.BufferCollection.SetConstraints() failed: " - << status; - return; - } - - fuchsia::ui::composition::BufferCollectionImportToken import_token; - fuchsia::ui::composition::BufferCollectionExportToken export_token; - status = zx::eventpair::create(0, &export_token.value, &import_token.value); - if (status != ZX_OK) { - fatal_error_ = true; - RTC_LOG(LS_ERROR) - << "Failed to create BufferCollection import and export tokens: " - << status; - return; - } - - status = component_context_->svc()->Connect(flatland_allocator_.NewRequest()); - if (status != ZX_OK) { - fatal_error_ = true; - RTC_LOG(LS_ERROR) << "Failed to connect to Flatland Allocator: " << status; - return; - } - - fuchsia::ui::composition::RegisterBufferCollectionArgs buffer_collection_args; - buffer_collection_args.set_export_token(std::move(export_token)); - buffer_collection_args.set_buffer_collection_token(std::move(flatland_token)); - buffer_collection_args.set_usage( - fuchsia::ui::composition::RegisterBufferCollectionUsage::SCREENSHOT); - - fuchsia::ui::composition::Allocator_RegisterBufferCollection_Result - buffer_collection_result; - flatland_allocator_->RegisterBufferCollection( - std::move(buffer_collection_args), &buffer_collection_result); - if (buffer_collection_result.is_err()) { - fatal_error_ = true; - RTC_LOG(LS_ERROR) << "fuchsia.ui.composition.Allocator." - "RegisterBufferCollection() failed."; - return; - } - - zx_status_t allocation_status; - status = collection_->WaitForBuffersAllocated(&allocation_status, - &buffer_collection_info_); - if (status != ZX_OK) { - fatal_error_ = true; - RTC_LOG(LS_ERROR) << "Failed to wait for buffer collection info: " - << status; - return; - } - if (allocation_status != ZX_OK) { - fatal_error_ = true; - RTC_LOG(LS_ERROR) << "Failed to allocate buffer collection: " << status; - return; - } - status = collection_->Close(); - if (status != ZX_OK) { - fatal_error_ = true; - RTC_LOG(LS_ERROR) << "Failed to close buffer collection token: " << status; - return; - } - - status = component_context_->svc()->Connect(screen_capture_.NewRequest()); - if (status != ZX_OK) { - fatal_error_ = true; - RTC_LOG(LS_ERROR) << "Failed to connect to Screen Capture: " << status; - return; - } - - // Configure buffers in ScreenCapture client. - fuchsia::ui::composition::ScreenCaptureConfig configure_args; - configure_args.set_import_token(std::move(import_token)); - configure_args.set_buffer_count(buffer_collection_info_.buffer_count); - configure_args.set_size({width_, height_}); - - fuchsia::ui::composition::ScreenCapture_Configure_Result configure_result; - screen_capture_->Configure(std::move(configure_args), &configure_result); - if (configure_result.is_err()) { - fatal_error_ = true; - RTC_LOG(LS_ERROR) - << "fuchsia.ui.composition.ScreenCapture.Configure() failed: " - << configure_result.err(); - return; - } - - // We have a collection of virtual memory objects which the ScreenCapture - // client will write the frame data to when requested. We map each of these - // onto a pointer stored in virtual_memory_mapped_addrs_ which we can use to - // access this data. - uint32_t virt_mem_bytes = - buffer_collection_info_.settings.buffer_settings.size_bytes; - RTC_DCHECK(virt_mem_bytes > 0); - for (uint32_t buffer_index = 0; - buffer_index < buffer_collection_info_.buffer_count; buffer_index++) { - const zx::vmo& virt_mem = buffer_collection_info_.buffers[buffer_index].vmo; - virtual_memory_mapped_addrs_[buffer_index] = nullptr; - auto status = zx::vmar::root_self()->map( - ZX_VM_PERM_READ, /*vmar_offset*/ 0, virt_mem, - /*vmo_offset*/ 0, virt_mem_bytes, - reinterpret_cast( - &virtual_memory_mapped_addrs_[buffer_index])); - if (status != ZX_OK) { - fatal_error_ = true; - RTC_LOG(LS_ERROR) << "Failed to map virtual memory: " << status; - return; - } - } -} - -uint32_t ScreenCapturerFuchsia::GetPixelsPerRow( - const fuchsia::sysmem::ImageFormatConstraints& constraints) { - uint32_t stride = RoundUpToMultiple( - std::max(constraints.min_bytes_per_row, width_ * kFuchsiaBytesPerPixel), - constraints.bytes_per_row_divisor); - uint32_t pixels_per_row = stride / kFuchsiaBytesPerPixel; - - return pixels_per_row; -} - -} // namespace webrtc diff --git a/modules/desktop_capture/screen_capturer_fuchsia.h b/modules/desktop_capture/screen_capturer_fuchsia.h deleted file mode 100644 index 6e0f87cc58..0000000000 --- a/modules/desktop_capture/screen_capturer_fuchsia.h +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright 2022 The WebRTC project authors. All Rights Reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -#ifndef MODULES_DESKTOP_CAPTURE_SCREEN_CAPTURER_FUCHSIA_H_ -#define MODULES_DESKTOP_CAPTURE_SCREEN_CAPTURER_FUCHSIA_H_ - -#include -#include -#include - -#include -#include - -#include "modules/desktop_capture/desktop_capture_options.h" -#include "modules/desktop_capture/desktop_capturer.h" -#include "modules/desktop_capture/desktop_frame.h" - -namespace webrtc { - -class ScreenCapturerFuchsia final : public DesktopCapturer { - public: - ScreenCapturerFuchsia(); - ~ScreenCapturerFuchsia() override; - - // DesktopCapturer interface. - void Start(Callback* callback) override; - void CaptureFrame() override; - bool GetSourceList(SourceList* screens) override; - bool SelectSource(SourceId id) override; - - private: - fuchsia::sysmem::BufferCollectionConstraints GetBufferConstraints(); - void SetupBuffers(); - uint32_t GetPixelsPerRow( - const fuchsia::sysmem::ImageFormatConstraints& constraints); - - Callback* callback_ = nullptr; - - std::unique_ptr component_context_; - fuchsia::sysmem::AllocatorSyncPtr sysmem_allocator_; - fuchsia::ui::composition::AllocatorSyncPtr flatland_allocator_; - fuchsia::ui::composition::ScreenCaptureSyncPtr screen_capture_; - fuchsia::sysmem::BufferCollectionSyncPtr collection_; - fuchsia::sysmem::BufferCollectionInfo_2 buffer_collection_info_; - std::unordered_map virtual_memory_mapped_addrs_; - - bool fatal_error_; - - // Dimensions of the screen we are capturing - uint32_t width_; - uint32_t height_; -}; - -} // namespace webrtc - -#endif // MODULES_DESKTOP_CAPTURE_SCREEN_CAPTURER_FUCHSIA_H_