[Capture] Cleanup FrameSinkVideoCapturer.ChangeTarget
This patch cleans up the ChangeTarget API, adding appropriate
StructTraits and UnionTraits, as well as merging the parameters
into a new VideoCaptureTarget type.
Bug: 1264547, 1259398
Change-Id: I75c9f6cd585582631cea17c9d2b67a9c823bd56c
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3273346
Commit-Queue: Jordan Bayles <jophba@chromium.org>
Reviewed-by: Daniel Cheng <dcheng@chromium.org>
Reviewed-by: Jonathan Ross <jonross@chromium.org>
Reviewed-by: Elad Alon <eladalon@chromium.org>
Reviewed-by: Scott Violet <sky@chromium.org>
Reviewed-by: Danil Somsikov <dsv@chromium.org>
Cr-Commit-Position: refs/heads/main@{#942784}
diff --git a/ash/services/recording/video_capture_params.cc b/ash/services/recording/video_capture_params.cc
index 1832e81..20675dd 100644
--- a/ash/services/recording/video_capture_params.cc
+++ b/ash/services/recording/video_capture_params.cc
@@ -121,12 +121,8 @@
DCHECK_NE(frame_sink_id_, new_frame_sink_id);
frame_sink_id_ = new_frame_sink_id;
-
- auto sub_target =
- subtree_capture_id_.is_valid()
- ? viz::mojom::SubTarget::NewSubtreeCaptureId(subtree_capture_id_)
- : nullptr;
- capturer->ChangeTarget(frame_sink_id_, std::move(sub_target));
+ capturer->ChangeTarget(
+ viz::VideoCaptureTarget(frame_sink_id_, subtree_capture_id_));
// If the movement to another display results in changes in the frame sink
// size or DSF, OnVideoSizeMayHaveChanged() will be called by the below
@@ -293,12 +289,8 @@
// TODO(afakhry): Discuss with //media/ team the implications of color space
// conversions.
capturer->SetFormat(media::PIXEL_FORMAT_I420, kColorSpace);
-
- auto sub_target =
- subtree_capture_id_.is_valid()
- ? viz::mojom::SubTarget::NewSubtreeCaptureId(subtree_capture_id_)
- : nullptr;
- capturer->ChangeTarget(frame_sink_id_, std::move(sub_target));
+ capturer->ChangeTarget(
+ viz::VideoCaptureTarget(frame_sink_id_, subtree_capture_id_));
}
gfx::Rect VideoCaptureParams::GetVideoFrameVisibleRect(
diff --git a/components/viz/common/BUILD.gn b/components/viz/common/BUILD.gn
index 2ce3503..45bc802 100644
--- a/components/viz/common/BUILD.gn
+++ b/components/viz/common/BUILD.gn
@@ -293,6 +293,8 @@
"surfaces/surface_info.h",
"surfaces/surface_range.cc",
"surfaces/surface_range.h",
+ "surfaces/video_capture_target.cc",
+ "surfaces/video_capture_target.h",
"switches.cc",
"switches.h",
"traced_value.cc",
diff --git a/components/viz/common/surfaces/video_capture_target.cc b/components/viz/common/surfaces/video_capture_target.cc
new file mode 100644
index 0000000..0c67db64
--- /dev/null
+++ b/components/viz/common/surfaces/video_capture_target.cc
@@ -0,0 +1,47 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/viz/common/surfaces/video_capture_target.h"
+
+#include "base/logging.h"
+
+namespace viz {
+
+namespace {
+bool SubTargetIsValid(const VideoCaptureSubTarget& sub_target) {
+ if (absl::holds_alternative<absl::monostate>(sub_target)) {
+ return true;
+ }
+ if (const auto* crop_id = absl::get_if<RegionCaptureCropId>(&sub_target)) {
+ return !crop_id->is_zero();
+ }
+ const auto* capture_id = absl::get_if<SubtreeCaptureId>(&sub_target);
+ DCHECK(capture_id);
+ return capture_id->is_valid();
+}
+
+} // namespace
+
+VideoCaptureTarget::VideoCaptureTarget(FrameSinkId frame_sink_id)
+ : VideoCaptureTarget(frame_sink_id, VideoCaptureSubTarget()) {}
+VideoCaptureTarget::VideoCaptureTarget(FrameSinkId frame_sink_id,
+ VideoCaptureSubTarget sub_target)
+ : frame_sink_id(frame_sink_id),
+ sub_target(SubTargetIsValid(sub_target) ? sub_target
+ : VideoCaptureSubTarget{}) {
+ DCHECK(this->frame_sink_id.is_valid());
+}
+
+VideoCaptureTarget::VideoCaptureTarget() = default;
+VideoCaptureTarget::VideoCaptureTarget(const VideoCaptureTarget& other) =
+ default;
+VideoCaptureTarget::VideoCaptureTarget(VideoCaptureTarget&& other) = default;
+VideoCaptureTarget& VideoCaptureTarget::operator=(
+ const VideoCaptureTarget& other) = default;
+VideoCaptureTarget& VideoCaptureTarget::operator=(VideoCaptureTarget&& other) =
+ default;
+
+VideoCaptureTarget::~VideoCaptureTarget() = default;
+
+} // namespace viz
diff --git a/components/viz/common/surfaces/video_capture_target.h b/components/viz/common/surfaces/video_capture_target.h
new file mode 100644
index 0000000..4a1e537
--- /dev/null
+++ b/components/viz/common/surfaces/video_capture_target.h
@@ -0,0 +1,65 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_VIZ_COMMON_SURFACES_VIDEO_CAPTURE_TARGET_H_
+#define COMPONENTS_VIZ_COMMON_SURFACES_VIDEO_CAPTURE_TARGET_H_
+
+#include "base/token.h"
+#include "components/viz/common/surfaces/frame_sink_id.h"
+#include "components/viz/common/surfaces/region_capture_bounds.h"
+#include "components/viz/common/surfaces/subtree_capture_id.h"
+#include "components/viz/common/viz_common_export.h"
+#include "third_party/abseil-cpp/absl/types/variant.h"
+
+namespace viz {
+
+// Note about sub targets: subtree-capture and region-capture are mutually
+// exclusive. This is trivially guaranteed by subtree-capture only being
+// supported on window-capture, and region-capture only being supported on
+// tab-capture.
+using VideoCaptureSubTarget =
+ absl::variant<absl::monostate, SubtreeCaptureId, RegionCaptureCropId>;
+
+// All of the information necessary to select a target for capture.
+// If constructed, the |frame_sink_id| must be valid and |sub_target|
+// is optional. If not provided, this target is the root render pass of
+// the frame sink. If |sub_target| is a SubtreeCaptureId, this target is
+// a layer subtree under the root render pass. Else, if |sub_target| is
+// a RegionCaptureCropId, this target is the root render pass but only
+// a subset of the pixels are selected for capture.
+struct VIZ_COMMON_EXPORT VideoCaptureTarget {
+ explicit VideoCaptureTarget(FrameSinkId frame_sink_id);
+
+ // If an invalid sub target is provided, it will be internally converted to an
+ // absl::monostate, equivalent to calling the single argument constructor
+ // above.
+ VideoCaptureTarget(FrameSinkId frame_sink_id,
+ VideoCaptureSubTarget capture_sub_target);
+
+ VideoCaptureTarget();
+ ~VideoCaptureTarget();
+ VideoCaptureTarget(const VideoCaptureTarget& other);
+ VideoCaptureTarget(VideoCaptureTarget&& other);
+ VideoCaptureTarget& operator=(const VideoCaptureTarget& other);
+ VideoCaptureTarget& operator=(VideoCaptureTarget&& other);
+
+ inline bool operator==(const VideoCaptureTarget& other) const {
+ return frame_sink_id == other.frame_sink_id &&
+ sub_target == other.sub_target;
+ }
+
+ inline bool operator!=(const VideoCaptureTarget& other) const {
+ return !(*this == other);
+ }
+
+ // The target frame sink id. Must be valid.
+ FrameSinkId frame_sink_id;
+
+ // The sub target.
+ VideoCaptureSubTarget sub_target;
+};
+
+} // namespace viz
+
+#endif // COMPONENTS_VIZ_COMMON_SURFACES_VIDEO_CAPTURE_TARGET_H_
diff --git a/components/viz/host/client_frame_sink_video_capturer.cc b/components/viz/host/client_frame_sink_video_capturer.cc
index ac652ed..b2b21d9 100644
--- a/components/viz/host/client_frame_sink_video_capturer.cc
+++ b/components/viz/host/client_frame_sink_video_capturer.cc
@@ -72,15 +72,11 @@
}
void ClientFrameSinkVideoCapturer::ChangeTarget(
- const absl::optional<FrameSinkId>& frame_sink_id,
- mojom::SubTargetPtr sub_target) {
+ const absl::optional<VideoCaptureTarget>& target) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- target_ = frame_sink_id;
- sub_target_ = std::move(sub_target);
-
- capturer_remote_->ChangeTarget(frame_sink_id,
- sub_target_ ? sub_target_.Clone() : nullptr);
+ target_ = target;
+ capturer_remote_->ChangeTarget(target);
}
void ClientFrameSinkVideoCapturer::Start(
@@ -196,8 +192,7 @@
if (auto_throttling_enabled_)
capturer_remote_->SetAutoThrottlingEnabled(*auto_throttling_enabled_);
if (target_) {
- capturer_remote_->ChangeTarget(
- target_, sub_target_ ? sub_target_->Clone() : nullptr);
+ capturer_remote_->ChangeTarget(target_.value());
}
for (Overlay* overlay : overlays_)
overlay->EstablishConnection(capturer_remote_.get());
diff --git a/components/viz/host/client_frame_sink_video_capturer.h b/components/viz/host/client_frame_sink_video_capturer.h
index 6d319eae..210e8784 100644
--- a/components/viz/host/client_frame_sink_video_capturer.h
+++ b/components/viz/host/client_frame_sink_video_capturer.h
@@ -13,8 +13,7 @@
#include "base/sequence_checker.h"
#include "base/time/time.h"
#include "components/viz/common/surfaces/frame_sink_id.h"
-#include "components/viz/common/surfaces/region_capture_bounds.h"
-#include "components/viz/common/surfaces/subtree_capture_id.h"
+#include "components/viz/common/surfaces/video_capture_target.h"
#include "components/viz/host/viz_host_export.h"
#include "media/base/video_types.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
@@ -87,8 +86,7 @@
const gfx::Size& max_size,
bool use_fixed_aspect_ratio);
void SetAutoThrottlingEnabled(bool enabled);
- void ChangeTarget(const absl::optional<FrameSinkId>& frame_sink_id,
- mojom::SubTargetPtr sub_target);
+ void ChangeTarget(const absl::optional<VideoCaptureTarget>& target);
void Stop();
void RequestRefreshFrame();
@@ -155,8 +153,7 @@
absl::optional<base::TimeDelta> min_size_change_period_;
absl::optional<ResolutionConstraints> resolution_constraints_;
absl::optional<bool> auto_throttling_enabled_;
- absl::optional<FrameSinkId> target_;
- mojom::SubTargetPtr sub_target_;
+ absl::optional<VideoCaptureTarget> target_;
// Overlays are owned by the callers of CreateOverlay().
std::vector<Overlay*> overlays_;
bool is_started_ = false;
diff --git a/components/viz/service/BUILD.gn b/components/viz/service/BUILD.gn
index 972d8fc..f9d0c20 100644
--- a/components/viz/service/BUILD.gn
+++ b/components/viz/service/BUILD.gn
@@ -227,6 +227,7 @@
# Note that dependency on //gpu/ipc/client is for GpuMemoryBufferImpl. This
# dependency should not be in public_deps.
+ "//components/viz/common",
"//gpu/ipc/client",
"//gpu/ipc/common:common",
"//gpu/ipc/common:surface_handle_type",
diff --git a/components/viz/service/frame_sinks/compositor_frame_sink_support.cc b/components/viz/service/frame_sinks/compositor_frame_sink_support.cc
index 04df254..71c33b3 100644
--- a/components/viz/service/frame_sinks/compositor_frame_sink_support.cc
+++ b/components/viz/service/frame_sinks/compositor_frame_sink_support.cc
@@ -24,6 +24,7 @@
#include "components/viz/common/quads/compositor_render_pass.h"
#include "components/viz/common/resources/bitmap_allocation.h"
#include "components/viz/common/surfaces/surface_info.h"
+#include "components/viz/common/surfaces/video_capture_target.h"
#include "components/viz/service/display/display.h"
#include "components/viz/service/display/shared_bitmap_manager.h"
#include "components/viz/service/frame_sinks/frame_sink_bundle_impl.h"
@@ -944,7 +945,7 @@
}
gfx::Rect CompositorFrameSinkSupport::GetCopyOutputRequestRegion(
- const CapturableFrameSink::RegionSpecifier& specifier) const {
+ const VideoCaptureSubTarget& sub_target) const {
if (!last_activated_surface_id_.is_valid()) {
return {};
}
@@ -957,21 +958,21 @@
}
// We will either have a subtree ID or a region capture crop_id, but not both.
- if (absl::holds_alternative<RegionCaptureCropId>(specifier)) {
- return GetCaptureBounds(absl::get<RegionCaptureCropId>(specifier));
+ if (absl::holds_alternative<RegionCaptureCropId>(sub_target)) {
+ return GetCaptureBounds(absl::get<RegionCaptureCropId>(sub_target));
}
// We can exit early if there is no subtree, otherwise we need to
// intersect the bounds.
const CompositorFrame& frame = current_surface->GetActiveFrame();
- if (!absl::holds_alternative<SubtreeCaptureId>(specifier)) {
+ if (!absl::holds_alternative<SubtreeCaptureId>(sub_target)) {
return gfx::Rect(frame.size_in_pixels());
}
// Now we know we don't have a crop_id and we do have a subtree ID.
for (const auto& render_pass : frame.render_pass_list) {
if (render_pass->subtree_capture_id ==
- absl::get<SubtreeCaptureId>(specifier)) {
+ absl::get<SubtreeCaptureId>(sub_target)) {
return render_pass->subtree_size.IsEmpty()
? render_pass->output_rect
: gfx::Rect(render_pass->subtree_size);
diff --git a/components/viz/service/frame_sinks/compositor_frame_sink_support.h b/components/viz/service/frame_sinks/compositor_frame_sink_support.h
index 5360d22..2c2f504 100644
--- a/components/viz/service/frame_sinks/compositor_frame_sink_support.h
+++ b/components/viz/service/frame_sinks/compositor_frame_sink_support.h
@@ -22,6 +22,7 @@
#include "components/viz/common/surfaces/region_capture_bounds.h"
#include "components/viz/common/surfaces/surface_info.h"
#include "components/viz/common/surfaces/surface_range.h"
+#include "components/viz/common/surfaces/video_capture_target.h"
#include "components/viz/service/frame_sinks/begin_frame_tracker.h"
#include "components/viz/service/frame_sinks/surface_resource_holder.h"
#include "components/viz/service/frame_sinks/surface_resource_holder_client.h"
@@ -199,7 +200,7 @@
void AttachCaptureClient(CapturableFrameSink::Client* client) override;
void DetachCaptureClient(CapturableFrameSink::Client* client) override;
gfx::Rect GetCopyOutputRequestRegion(
- const CapturableFrameSink::RegionSpecifier& specifier) const override;
+ const VideoCaptureSubTarget& specifier) const override;
void OnClientCaptureStarted() override;
void OnClientCaptureStopped() override;
void RequestCopyOfOutput(
diff --git a/components/viz/service/frame_sinks/compositor_frame_sink_support_unittest.cc b/components/viz/service/frame_sinks/compositor_frame_sink_support_unittest.cc
index 09bbe6a..62ec925 100644
--- a/components/viz/service/frame_sinks/compositor_frame_sink_support_unittest.cc
+++ b/components/viz/service/frame_sinks/compositor_frame_sink_support_unittest.cc
@@ -1632,8 +1632,8 @@
TEST_F(CompositorFrameSinkSupportTest, GetCopyOutputRequestRegion) {
// No surface with active frame.
- EXPECT_EQ((gfx::Rect{}), support_->GetCopyOutputRequestRegion(
- CapturableFrameSink::RegionSpecifier()));
+ EXPECT_EQ((gfx::Rect{}),
+ support_->GetCopyOutputRequestRegion(VideoCaptureSubTarget()));
// Surface with active frame but no capture identifier.
ResourceId first_frame_ids[] = {ResourceId(1), ResourceId(2), ResourceId(3),
@@ -1641,8 +1641,7 @@
SubmitCompositorFrameWithResources(first_frame_ids,
base::size(first_frame_ids));
EXPECT_EQ((gfx::Rect{0, 0, 20, 20}),
- (support_->GetCopyOutputRequestRegion(
- CapturableFrameSink::RegionSpecifier())));
+ (support_->GetCopyOutputRequestRegion(VideoCaptureSubTarget())));
// Render pass with subtree size.
const SurfaceId surface_id(support_->frame_sink_id(), local_surface_id_);
diff --git a/components/viz/service/frame_sinks/frame_sink_bundle_impl_unittest.cc b/components/viz/service/frame_sinks/frame_sink_bundle_impl_unittest.cc
index db33b44..fad5c884 100644
--- a/components/viz/service/frame_sinks/frame_sink_bundle_impl_unittest.cc
+++ b/components/viz/service/frame_sinks/frame_sink_bundle_impl_unittest.cc
@@ -120,12 +120,12 @@
TestFrameSink(
FrameSinkManagerImpl& manager,
const FrameSinkId& id,
- const absl::optional<FrameSinkId>& parent_id,
+ const FrameSinkId& parent_id,
const absl::optional<FrameSinkBundleId>& bundle_id = absl::nullopt)
: manager_(manager), id_(id) {
manager_.RegisterFrameSinkId(id, /*report_activation=*/true);
- if (parent_id) {
- manager_.RegisterFrameSinkHierarchy(*parent_id, id);
+ if (parent_id.is_valid()) {
+ manager_.RegisterFrameSinkHierarchy(parent_id, id);
}
manager_.CreateCompositorFrameSink(
id, bundle_id, frame_sink.BindNewPipeAndPassReceiver(),
diff --git a/components/viz/service/frame_sinks/frame_sink_manager_impl.cc b/components/viz/service/frame_sinks/frame_sink_manager_impl.cc
index 9860f8ae..6fa971d 100644
--- a/components/viz/service/frame_sinks/frame_sink_manager_impl.cc
+++ b/components/viz/service/frame_sinks/frame_sink_manager_impl.cc
@@ -403,7 +403,8 @@
support_map_[frame_sink_id] = support;
for (auto& capturer : video_capturers_) {
- if (capturer->requested_target() == frame_sink_id)
+ if (capturer->target() &&
+ capturer->target()->frame_sink_id == frame_sink_id)
capturer->SetResolvedTarget(support);
}
@@ -423,7 +424,8 @@
observer.OnDestroyedCompositorFrameSink(frame_sink_id);
for (auto& capturer : video_capturers_) {
- if (capturer->requested_target() == frame_sink_id)
+ if (capturer->target() &&
+ capturer->target()->frame_sink_id == frame_sink_id)
capturer->OnTargetWillGoAway();
}
diff --git a/components/viz/service/frame_sinks/video_capture/capturable_frame_sink.h b/components/viz/service/frame_sinks/video_capture/capturable_frame_sink.h
index 8fedddb..8808169 100644
--- a/components/viz/service/frame_sinks/video_capture/capturable_frame_sink.h
+++ b/components/viz/service/frame_sinks/video_capture/capturable_frame_sink.h
@@ -7,6 +7,7 @@
#include "base/time/time.h"
#include "components/viz/common/surfaces/region_capture_bounds.h"
+#include "components/viz/common/surfaces/video_capture_target.h"
#include "components/viz/service/surfaces/pending_copy_output_request.h"
#include "third_party/abseil-cpp/absl/types/variant.h"
#include "ui/gfx/geometry/size.h"
@@ -64,10 +65,8 @@
// its associated bounds are set to empty or could not be found.
// NOTE: only one of |subtree_id| or |crop_id| should be set and valid, not
// both.
- using RegionSpecifier =
- absl::variant<absl::monostate, SubtreeCaptureId, RegionCaptureCropId>;
virtual gfx::Rect GetCopyOutputRequestRegion(
- const RegionSpecifier& specifier) const = 0;
+ const VideoCaptureSubTarget& sub_target) const = 0;
// Called when a video capture client starts or stops capturing.
virtual void OnClientCaptureStarted() = 0;
diff --git a/components/viz/service/frame_sinks/video_capture/frame_sink_video_capturer_impl.cc b/components/viz/service/frame_sinks/video_capture/frame_sink_video_capturer_impl.cc
index bf70c6f..d7ad719 100644
--- a/components/viz/service/frame_sinks/video_capture/frame_sink_video_capturer_impl.cc
+++ b/components/viz/service/frame_sinks/video_capture/frame_sink_video_capturer_impl.cc
@@ -229,26 +229,16 @@
}
void FrameSinkVideoCapturerImpl::ChangeTarget(
- const absl::optional<FrameSinkId>& frame_sink_id,
- mojom::SubTargetPtr sub_target) {
+ const absl::optional<VideoCaptureTarget>& target) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ target_ = target;
- if (frame_sink_id) {
- requested_target_ = *frame_sink_id;
- region_specifier_ =
- !sub_target ? CapturableFrameSink::RegionSpecifier()
- : sub_target->is_subtree_capture_id()
- ? sub_target->get_subtree_capture_id()
- : sub_target->is_region_capture_crop_id()
- ? sub_target->get_region_capture_crop_id()
- : CapturableFrameSink::RegionSpecifier();
- SetResolvedTarget(
- frame_sink_manager_->FindCapturableFrameSink(requested_target_));
- } else {
- requested_target_ = FrameSinkId();
- region_specifier_ = CapturableFrameSink::RegionSpecifier();
- SetResolvedTarget(nullptr);
+ CapturableFrameSink* resolved_target = nullptr;
+ if (target_) {
+ resolved_target =
+ frame_sink_manager_->FindCapturableFrameSink(target_->frame_sink_id);
}
+ SetResolvedTarget(resolved_target);
}
void FrameSinkVideoCapturerImpl::Start(
@@ -360,8 +350,9 @@
}
// Detect whether the source size changed before attempting capture.
+ DCHECK(target_);
const gfx::Rect capture_region =
- resolved_target_->GetCopyOutputRequestRegion(region_specifier_);
+ resolved_target_->GetCopyOutputRequestRegion(target_->sub_target);
if (capture_region.IsEmpty()) {
// If the capture region is empty, it means one of two things: the first
// frame has not been composited yet or the current region selected for
@@ -397,15 +388,16 @@
DCHECK(!damage_rect.IsEmpty());
DCHECK(!expected_display_time.is_null());
DCHECK(resolved_target_);
+ DCHECK(target_);
const gfx::Rect capture_region =
- resolved_target_->GetCopyOutputRequestRegion(region_specifier_);
+ resolved_target_->GetCopyOutputRequestRegion(target_->sub_target);
if (capture_region.IsEmpty()) {
return;
}
if (capture_region.size() == oracle_->source_size()) {
- if (!absl::holds_alternative<absl::monostate>(region_specifier_)) {
+ if (!absl::holds_alternative<absl::monostate>(target_->sub_target)) {
// The damage_rect may not be in the same coordinate space when we have
// a valid request subtree identifier, so to be safe we just invalidate
// the entire source.
@@ -485,6 +477,7 @@
const CompositorFrameMetadata& frame_metadata) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK(resolved_target_);
+ DCHECK(target_);
// Consult the oracle to determine whether this frame should be captured.
if (oracle_->ObserveEventAndDecideCapture(event, damage_rect, event_time)) {
@@ -678,7 +671,7 @@
// size of the capture region. If the capture region is empty, we shouldn't
// capture.
const gfx::Rect capture_region =
- resolved_target_->GetCopyOutputRequestRegion(region_specifier_);
+ resolved_target_->GetCopyOutputRequestRegion(target_->sub_target);
if (capture_region.IsEmpty()) {
return;
}
@@ -724,8 +717,8 @@
}
const SubtreeCaptureId subtree_id =
- absl::holds_alternative<SubtreeCaptureId>(region_specifier_)
- ? absl::get<SubtreeCaptureId>(region_specifier_)
+ absl::holds_alternative<SubtreeCaptureId>(target_->sub_target)
+ ? absl::get<SubtreeCaptureId>(target_->sub_target)
: SubtreeCaptureId();
resolved_target_->RequestCopyOfOutput(
diff --git a/components/viz/service/frame_sinks/video_capture/frame_sink_video_capturer_impl.h b/components/viz/service/frame_sinks/video_capture/frame_sink_video_capturer_impl.h
index 591cdf8..990ace8 100644
--- a/components/viz/service/frame_sinks/video_capture/frame_sink_video_capturer_impl.h
+++ b/components/viz/service/frame_sinks/video_capture/frame_sink_video_capturer_impl.h
@@ -21,7 +21,7 @@
#include "base/unguessable_token.h"
#include "components/viz/common/quads/compositor_frame_metadata.h"
#include "components/viz/common/surfaces/frame_sink_id.h"
-#include "components/viz/common/surfaces/subtree_capture_id.h"
+#include "components/viz/common/surfaces/video_capture_target.h"
#include "components/viz/service/frame_sinks/video_capture/capturable_frame_sink.h"
#include "components/viz/service/frame_sinks/video_capture/in_flight_frame_delivery.h"
#include "components/viz/service/frame_sinks/video_capture/shared_memory_video_frame_pool.h"
@@ -92,7 +92,7 @@
// The currently-requested frame sink for capture. The frame sink manager
// calls this when it learns of a new CapturableFrameSink to see if the target
// can be resolved.
- const FrameSinkId& requested_target() const { return requested_target_; }
+ const absl::optional<VideoCaptureTarget>& target() const { return target_; }
// Sets the resolved target, detaching this capturer from the previous target
// (if any), and attaching to the new target. This is called by the frame sink
@@ -115,8 +115,7 @@
const gfx::Size& max_size,
bool use_fixed_aspect_ratio) final;
void SetAutoThrottlingEnabled(bool enabled) final;
- void ChangeTarget(const absl::optional<FrameSinkId>& frame_sink_id,
- mojom::SubTargetPtr sub_target) final;
+ void ChangeTarget(const absl::optional<VideoCaptureTarget>& target) final;
void Start(mojo::PendingRemote<mojom::FrameSinkVideoConsumer> consumer) final;
void Stop() final;
void RequestRefreshFrame() final;
@@ -261,13 +260,8 @@
const std::unique_ptr<media::VideoCaptureOracle> oracle_;
// The target requested by the client, as provided in the last call to
- // ChangeTarget().
- FrameSinkId requested_target_;
-
- // A specifier that indicates what region of the layer should be captured.
- // If not valid, then the root render pass of the target frame sink should
- // be captured.
- CapturableFrameSink::RegionSpecifier region_specifier_;
+ // ChangeTarget(). May be nullopt if no target is currently set.
+ absl::optional<VideoCaptureTarget> target_;
// The resolved target of video capture, or null if the requested target does
// not yet exist (or no longer exists).
diff --git a/components/viz/service/frame_sinks/video_capture/frame_sink_video_capturer_impl_unittest.cc b/components/viz/service/frame_sinks/video_capture/frame_sink_video_capturer_impl_unittest.cc
index 09499a3..de8ca7c 100644
--- a/components/viz/service/frame_sinks/video_capture/frame_sink_video_capturer_impl_unittest.cc
+++ b/components/viz/service/frame_sinks/video_capture/frame_sink_video_capturer_impl_unittest.cc
@@ -20,6 +20,7 @@
#include "components/viz/common/frame_sinks/copy_output_result.h"
#include "components/viz/common/frame_sinks/copy_output_util.h"
#include "components/viz/common/surfaces/subtree_capture_id.h"
+#include "components/viz/common/surfaces/video_capture_target.h"
#include "components/viz/service/frame_sinks/video_capture/frame_sink_video_capturer_manager.h"
#include "media/base/limits.h"
#include "media/base/video_util.h"
@@ -258,17 +259,17 @@
}
gfx::Rect GetCopyOutputRequestRegion(
- const CapturableFrameSink::RegionSpecifier& specifier) const override {
- if (absl::holds_alternative<RegionCaptureCropId>(specifier)) {
+ const VideoCaptureSubTarget& sub_target) const override {
+ if (absl::holds_alternative<RegionCaptureCropId>(sub_target)) {
current_capture_id_ = SubtreeCaptureId();
- current_crop_id_ = absl::get<RegionCaptureCropId>(specifier);
+ current_crop_id_ = absl::get<RegionCaptureCropId>(sub_target);
if (!current_crop_id_.is_zero()) {
return crop_bounds_;
}
return {};
}
- if (absl::holds_alternative<SubtreeCaptureId>(specifier)) {
- current_capture_id_ = absl::get<SubtreeCaptureId>(specifier);
+ if (absl::holds_alternative<SubtreeCaptureId>(sub_target)) {
+ current_capture_id_ = absl::get<SubtreeCaptureId>(sub_target);
current_crop_id_ = RegionCaptureCropId();
if (current_capture_id_.is_valid()) {
return capture_bounds_;
@@ -582,9 +583,9 @@
EXPECT_CALL(frame_sink_manager_, FindCapturableFrameSink(kFrameSinkId))
.WillRepeatedly(Return(&frame_sink_));
- EXPECT_EQ(FrameSinkId(), capturer_->requested_target());
- capturer_->ChangeTarget(kFrameSinkId, nullptr);
- EXPECT_EQ(kFrameSinkId, capturer_->requested_target());
+ EXPECT_FALSE(capturer_->target());
+ capturer_->ChangeTarget(VideoCaptureTarget(kFrameSinkId));
+ EXPECT_EQ(kFrameSinkId, capturer_->target()->frame_sink_id);
EXPECT_EQ(capturer_.get(), frame_sink_.attached_client());
}
@@ -594,9 +595,9 @@
EXPECT_CALL(frame_sink_manager_, FindCapturableFrameSink(kFrameSinkId))
.WillRepeatedly(Return(nullptr));
- EXPECT_EQ(FrameSinkId(), capturer_->requested_target());
- capturer_->ChangeTarget(kFrameSinkId, nullptr);
- EXPECT_EQ(kFrameSinkId, capturer_->requested_target());
+ EXPECT_FALSE(capturer_->target());
+ capturer_->ChangeTarget(VideoCaptureTarget(kFrameSinkId));
+ EXPECT_EQ(kFrameSinkId, capturer_->target()->frame_sink_id);
EXPECT_EQ(nullptr, frame_sink_.attached_client());
capturer_->SetResolvedTarget(&frame_sink_);
@@ -630,7 +631,7 @@
// Now, set the target. As it resolves, the capturer will immediately attempt
// a refresh capture, which will cancel the timer and trigger a copy request.
- capturer_->ChangeTarget(kFrameSinkId, nullptr);
+ capturer_->ChangeTarget(VideoCaptureTarget(kFrameSinkId));
EXPECT_EQ(1, frame_sink_.num_copy_results());
EXPECT_FALSE(IsRefreshRetryTimerRunning());
@@ -646,7 +647,7 @@
EXPECT_CALL(frame_sink_manager_, FindCapturableFrameSink(kFrameSinkId))
.WillRepeatedly(Return(&frame_sink_));
- capturer_->ChangeTarget(kFrameSinkId, nullptr);
+ capturer_->ChangeTarget(VideoCaptureTarget(kFrameSinkId));
EXPECT_FALSE(IsRefreshRetryTimerRunning());
MockConsumer consumer;
@@ -741,7 +742,7 @@
EXPECT_CALL(frame_sink_manager_, FindCapturableFrameSink(kFrameSinkId))
.WillRepeatedly(Return(&frame_sink_));
- capturer_->ChangeTarget(kFrameSinkId, nullptr);
+ capturer_->ChangeTarget(VideoCaptureTarget(kFrameSinkId));
NiceMock<MockConsumer> consumer;
StartCapture(&consumer);
@@ -839,7 +840,7 @@
EXPECT_CALL(frame_sink_manager_, FindCapturableFrameSink(kFrameSinkId))
.WillRepeatedly(Return(&frame_sink_));
- capturer_->ChangeTarget(kFrameSinkId, nullptr);
+ capturer_->ChangeTarget(VideoCaptureTarget(kFrameSinkId));
NiceMock<MockConsumer> consumer;
StartCapture(&consumer);
@@ -896,7 +897,7 @@
EXPECT_CALL(frame_sink_manager_, FindCapturableFrameSink(kFrameSinkId))
.WillRepeatedly(Return(&frame_sink_));
- capturer_->ChangeTarget(kFrameSinkId, nullptr);
+ capturer_->ChangeTarget(VideoCaptureTarget(kFrameSinkId));
// Start capturing to the first consumer.
MockConsumer consumer;
@@ -983,7 +984,7 @@
EXPECT_CALL(frame_sink_manager_, FindCapturableFrameSink(kFrameSinkId))
.WillRepeatedly(Return(&frame_sink_));
- capturer_->ChangeTarget(kFrameSinkId, nullptr);
+ capturer_->ChangeTarget(VideoCaptureTarget(kFrameSinkId));
MockConsumer consumer;
const int num_refresh_frames = 2; // Initial, plus later refresh.
@@ -1039,7 +1040,7 @@
EXPECT_CALL(frame_sink_manager_, FindCapturableFrameSink(kFrameSinkId))
.WillRepeatedly(Return(&frame_sink_));
- capturer_->ChangeTarget(kFrameSinkId, nullptr);
+ capturer_->ChangeTarget(VideoCaptureTarget(kFrameSinkId));
MockConsumer consumer;
constexpr int num_refresh_frames = 3; // Initial, plus two refreshes after
@@ -1136,7 +1137,7 @@
TEST_F(FrameSinkVideoCapturerTest, CompositorFrameMetadataReachesConsumer) {
EXPECT_CALL(frame_sink_manager_, FindCapturableFrameSink(kFrameSinkId))
.WillRepeatedly(Return(&frame_sink_));
- capturer_->ChangeTarget(kFrameSinkId, nullptr);
+ capturer_->ChangeTarget(VideoCaptureTarget(kFrameSinkId));
MockConsumer consumer;
// Initial refresh frame for starting capture, plus later refresh.
@@ -1196,7 +1197,7 @@
TEST_F(FrameSinkVideoCapturerTest, DeliversUpdateRectAndCaptureCounter) {
EXPECT_CALL(frame_sink_manager_, FindCapturableFrameSink(kFrameSinkId))
.WillRepeatedly(Return(&frame_sink_));
- capturer_->ChangeTarget(kFrameSinkId, nullptr);
+ capturer_->ChangeTarget(VideoCaptureTarget(kFrameSinkId));
MockConsumer consumer;
StartCapture(&consumer);
@@ -1311,7 +1312,7 @@
TEST_F(FrameSinkVideoCapturerTest, CaptureCounterSkipsWhenFramesAreDropped) {
EXPECT_CALL(frame_sink_manager_, FindCapturableFrameSink(kFrameSinkId))
.WillRepeatedly(Return(&frame_sink_));
- capturer_->ChangeTarget(kFrameSinkId, nullptr);
+ capturer_->ChangeTarget(VideoCaptureTarget(kFrameSinkId));
MockConsumer consumer;
StartCapture(&consumer);
@@ -1363,7 +1364,7 @@
EXPECT_CALL(frame_sink_manager_, FindCapturableFrameSink(kFrameSinkId))
.WillRepeatedly(Return(&frame_sink_));
- capturer_->ChangeTarget(kFrameSinkId, nullptr);
+ capturer_->ChangeTarget(VideoCaptureTarget(kFrameSinkId));
EXPECT_EQ(frame_sink_.number_clients_capturing(), 0);
// Start capturing. frame_sink_ should now have one client capturing.
@@ -1380,14 +1381,13 @@
SwitchToSizeSet(kSizeSets[4]);
EXPECT_CALL(frame_sink_manager_, FindCapturableFrameSink(kFrameSinkId))
.WillRepeatedly(Return(&frame_sink_));
- capturer_->ChangeTarget(kFrameSinkId, nullptr);
+ capturer_->ChangeTarget(VideoCaptureTarget(kFrameSinkId));
EXPECT_EQ(frame_sink_.number_clients_capturing(), 0);
static const auto kCropId = RegionCaptureCropId::CreateRandom();
static const gfx::Rect kCropBounds{1, 2, 640, 478};
frame_sink_.set_crop_bounds(kCropBounds);
- capturer_->ChangeTarget(kFrameSinkId,
- mojom::SubTarget::NewRegionCaptureCropId(kCropId));
+ capturer_->ChangeTarget(VideoCaptureTarget(kFrameSinkId, kCropId));
// Start capturing. frame_sink_ should now have one client capturing.
NiceMock<MockConsumer> consumer;
@@ -1406,8 +1406,7 @@
static const gfx::Rect kCaptureBounds{1, 2, 1024, 768};
static const SubtreeCaptureId kCaptureId{1234567u};
frame_sink_.set_capture_bounds(kCaptureBounds);
- capturer_->ChangeTarget(kFrameSinkId,
- mojom::SubTarget::NewSubtreeCaptureId(kCaptureId));
+ capturer_->ChangeTarget(VideoCaptureTarget(kFrameSinkId, kCaptureId));
// Start capturing. frame_sink_ should now have one client capturing.
NiceMock<MockConsumer> consumer;
@@ -1427,7 +1426,7 @@
// The default cause is a target with no sub target, passed as nullptr. Since
// the SubTarget is a mojom variant, the default SubTarget::New() is actually
// a zero value subtree capture identifier.
- capturer_->ChangeTarget(kFrameSinkId, nullptr);
+ capturer_->ChangeTarget(VideoCaptureTarget(kFrameSinkId));
EXPECT_EQ(frame_sink_.number_clients_capturing(), 0);
// Start capturing. frame_sink_ should now have one client capturing.
diff --git a/content/browser/devtools/devtools_video_consumer.cc b/content/browser/devtools/devtools_video_consumer.cc
index 8098d0e..513bd8de 100644
--- a/content/browser/devtools/devtools_video_consumer.cc
+++ b/content/browser/devtools/devtools_video_consumer.cc
@@ -86,11 +86,7 @@
const viz::FrameSinkId& frame_sink_id) {
frame_sink_id_ = frame_sink_id;
if (capturer_) {
- capturer_->ChangeTarget(
- frame_sink_id_.is_valid()
- ? absl::make_optional<viz::FrameSinkId>(frame_sink_id_)
- : absl::nullopt,
- nullptr);
+ capturer_->ChangeTarget(viz::VideoCaptureTarget(frame_sink_id_));
}
}
@@ -132,7 +128,7 @@
kDefaultUseFixedAspectRatio);
capturer_->SetFormat(pixel_format_, color_space_);
if (frame_sink_id_.is_valid())
- capturer_->ChangeTarget(frame_sink_id_, nullptr);
+ capturer_->ChangeTarget(viz::VideoCaptureTarget(frame_sink_id_));
capturer_->Start(this);
}
diff --git a/content/browser/devtools/devtools_video_consumer_unittest.cc b/content/browser/devtools/devtools_video_consumer_unittest.cc
index bb20f060..6ed566ef 100644
--- a/content/browser/devtools/devtools_video_consumer_unittest.cc
+++ b/content/browser/devtools/devtools_video_consumer_unittest.cc
@@ -85,9 +85,9 @@
bool use_fixed_aspect_ratio));
// This is never called.
MOCK_METHOD1(SetAutoThrottlingEnabled, void(bool));
- void ChangeTarget(const absl::optional<viz::FrameSinkId>& frame_sink_id,
- viz::mojom::SubTargetPtr sub_target) final {
- frame_sink_id_ = frame_sink_id ? *frame_sink_id : viz::FrameSinkId();
+ void ChangeTarget(
+ const absl::optional<viz::VideoCaptureTarget>& target) final {
+ frame_sink_id_ = target ? target->frame_sink_id : viz::FrameSinkId();
MockChangeTarget(frame_sink_id_);
}
MOCK_METHOD1(MockChangeTarget, void(const viz::FrameSinkId& frame_sink_id));
diff --git a/content/browser/media/capture/aura_window_video_capture_device.cc b/content/browser/media/capture/aura_window_video_capture_device.cc
index 90fc150..3ff1aea 100644
--- a/content/browser/media/capture/aura_window_video_capture_device.cc
+++ b/content/browser/media/capture/aura_window_video_capture_device.cc
@@ -81,17 +81,19 @@
DCHECK(!target_window_);
target_window_ = DesktopMediaID::GetNativeWindowById(source_id);
- FrameSinkVideoCaptureDevice::VideoCaptureTarget target;
- if (target_window_) {
- target.frame_sink_id = target_window_->GetRootWindow()->GetFrameSinkId();
+ if (target_window_ &&
+ target_window_->GetRootWindow()->GetFrameSinkId().is_valid()) {
+ target_ = viz::VideoCaptureTarget(
+ target_window_->GetRootWindow()->GetFrameSinkId());
if (!target_window_->IsRootWindow()) {
capture_request_ = target_window_->MakeWindowCapturable();
- target.subtree_capture_id = capture_request_.GetCaptureId();
+ target_->sub_target = capture_request_.GetCaptureId();
}
+ } else {
+ target_ = absl::nullopt;
}
- if (target.frame_sink_id.is_valid()) {
- target_ = target;
+ if (target_) {
video_capture_lock_ = target_window_->GetHost()->CreateVideoCaptureLock();
#if BUILDFLAG(IS_CHROMEOS_ASH)
force_visible_.emplace(target_window_);
@@ -100,7 +102,7 @@
device_task_runner_->PostTask(
FROM_HERE,
base::BindOnce(&FrameSinkVideoCaptureDevice::OnTargetChanged, device_,
- std::move(target)));
+ target_));
// Note: The MouseCursorOverlayController runs on the UI thread. It's also
// important that SetTargetView() be called in the current stack while
// |target_window_| is known to be a valid pointer.
@@ -144,12 +146,13 @@
// Since the window is not destroyed, only re-parented, we can keep the
// same subtree ID and only update the FrameSinkId of the target.
- if (new_frame_sink_id != target_.frame_sink_id) {
- target_.frame_sink_id = new_frame_sink_id;
+ DCHECK(target_);
+ if (new_frame_sink_id != target_->frame_sink_id) {
+ target_->frame_sink_id = new_frame_sink_id;
device_task_runner_->PostTask(
FROM_HERE,
base::BindOnce(&FrameSinkVideoCaptureDevice::OnTargetChanged, device_,
- target_));
+ target_.value()));
}
}
#endif
@@ -173,7 +176,7 @@
#endif
aura::ScopedWindowCaptureRequest capture_request_;
- FrameSinkVideoCaptureDevice::VideoCaptureTarget target_;
+ absl::optional<viz::VideoCaptureTarget> target_;
std::unique_ptr<aura::WindowTreeHost::VideoCaptureLock> video_capture_lock_;
};
diff --git a/content/browser/media/capture/frame_sink_video_capture_device.cc b/content/browser/media/capture/frame_sink_video_capture_device.cc
index 5287252f8a..9dbbfad4 100644
--- a/content/browser/media/capture/frame_sink_video_capture_device.cc
+++ b/content/browser/media/capture/frame_sink_video_capture_device.cc
@@ -65,23 +65,6 @@
GetDeviceService().BindWakeLockProvider(std::move(receiver));
}
-viz::mojom::SubTargetPtr ToSubTargetPtr(
- const FrameSinkVideoCaptureDevice::VideoCaptureTarget& target) {
- // Recall that either |subtree_capture_id| or |crop_id| is set,
- // or neither, but never both. This was verified in |target|'s ctor,
- // but is reiterated here for clarity's sake.
- DCHECK(!target.subtree_capture_id.is_valid() || target.crop_id.is_zero());
-
- if (target.subtree_capture_id.is_valid()) {
- return viz::mojom::SubTarget::NewSubtreeCaptureId(
- target.subtree_capture_id);
- }
- if (!target.crop_id.is_zero()) {
- return viz::mojom::SubTarget::NewRegionCaptureCropId(target.crop_id);
- }
- return nullptr;
-}
-
} // namespace
#if !defined(OS_ANDROID)
@@ -137,8 +120,8 @@
constraints.max_frame_size,
constraints.fixed_aspect_ratio);
- if (target_.frame_sink_id.is_valid()) {
- capturer_->ChangeTarget(target_.frame_sink_id, ToSubTargetPtr(target_));
+ if (target_) {
+ capturer_->ChangeTarget(target_);
}
#if !defined(OS_ANDROID)
@@ -325,22 +308,17 @@
}
void FrameSinkVideoCaptureDevice::OnTargetChanged(
- const FrameSinkVideoCaptureDevice::VideoCaptureTarget& target) {
+ const absl::optional<viz::VideoCaptureTarget>& target) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
target_ = target;
if (capturer_) {
- capturer_->ChangeTarget(
- target_.frame_sink_id.is_valid()
- ? absl::make_optional<viz::FrameSinkId>(target_.frame_sink_id)
- : absl::nullopt,
- ToSubTargetPtr(target_));
+ capturer_->ChangeTarget(target_);
}
}
void FrameSinkVideoCaptureDevice::OnTargetPermanentlyLost() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-
- OnTargetChanged(VideoCaptureTarget());
+ OnTargetChanged(absl::nullopt);
OnFatalError("Capture target has been permanently lost.");
}
diff --git a/content/browser/media/capture/frame_sink_video_capture_device.h b/content/browser/media/capture/frame_sink_video_capture_device.h
index 5fd266be..c99d784 100644
--- a/content/browser/media/capture/frame_sink_video_capture_device.h
+++ b/content/browser/media/capture/frame_sink_video_capture_device.h
@@ -14,9 +14,9 @@
#include "base/check.h"
#include "base/memory/weak_ptr.h"
#include "base/sequence_checker.h"
-#include "base/token.h"
#include "build/build_config.h"
#include "components/viz/common/surfaces/frame_sink_id.h"
+#include "components/viz/common/surfaces/video_capture_target.h"
#include "components/viz/host/client_frame_sink_video_capturer.h"
#include "content/common/content_export.h"
#include "content/public/browser/browser_thread.h"
@@ -29,6 +29,7 @@
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "mojo/public/cpp/bindings/remote.h"
#include "services/device/public/mojom/wake_lock.mojom.h"
+#include "services/viz/public/cpp/compositing/video_capture_target_mojom_traits.h"
#include "third_party/abseil-cpp/absl/types/optional.h"
namespace content {
@@ -97,48 +98,11 @@
void OnStopped() final;
void OnLog(const std::string& message) final;
- // All of the information necessary to select a target for capture.
- struct VideoCaptureTarget {
- VideoCaptureTarget() = default;
- VideoCaptureTarget(viz::FrameSinkId frame_sink_id,
- viz::SubtreeCaptureId subtree_capture_id,
- const base::Token& crop_id)
- : frame_sink_id(frame_sink_id),
- subtree_capture_id(subtree_capture_id),
- crop_id(crop_id) {
- // Subtree-capture and region-capture are mutually exclusive.
- // This is trivially guaranteed by subtree-capture only being supported
- // on Aura window-capture, and region-capture only being supported on
- // tab-capture.
- DCHECK(!subtree_capture_id.is_valid() || crop_id.is_zero());
- }
-
- // The target frame sink id.
- viz::FrameSinkId frame_sink_id;
-
- // The subtree capture identifier--may be default initialized to indicate
- // that the entire frame sink (defined by |frame_sink_id|) should be
- // captured.
- viz::SubtreeCaptureId subtree_capture_id;
-
- // If |crop_id| is non-zero, it indicates that the video should be
- // cropped to coordinates identified by it.
- base::Token crop_id;
-
- inline bool operator==(const VideoCaptureTarget& other) const {
- return frame_sink_id == other.frame_sink_id &&
- subtree_capture_id == other.subtree_capture_id &&
- crop_id == other.crop_id;
- }
-
- inline bool operator!=(const VideoCaptureTarget& other) const {
- return !(*this == other);
- }
- };
-
// These are called to notify when the capture target has changed or was
- // permanently lost.
- virtual void OnTargetChanged(const VideoCaptureTarget& target);
+ // permanently lost. NOTE: a target can be temporarily absl::nullopt without
+ // being permanently lost.
+ virtual void OnTargetChanged(
+ const absl::optional<viz::VideoCaptureTarget>& target);
virtual void OnTargetPermanentlyLost();
protected:
@@ -188,7 +152,7 @@
// Current capture target. This is cached to resolve a race where
// OnTargetChanged() can be called before the |capturer_| is created in
// OnCapturerCreated().
- VideoCaptureTarget target_;
+ absl::optional<viz::VideoCaptureTarget> target_;
// The requested format, rate, and other capture constraints.
media::VideoCaptureParams capture_params_;
diff --git a/content/browser/media/capture/frame_sink_video_capture_device_unittest.cc b/content/browser/media/capture/frame_sink_video_capture_device_unittest.cc
index 6c1c06b..6f2d2fb 100644
--- a/content/browser/media/capture/frame_sink_video_capture_device_unittest.cc
+++ b/content/browser/media/capture/frame_sink_video_capture_device_unittest.cc
@@ -110,20 +110,13 @@
const gfx::Size& max_size,
bool use_fixed_aspect_ratio));
MOCK_METHOD1(SetAutoThrottlingEnabled, void(bool));
- void ChangeTarget(const absl::optional<viz::FrameSinkId>& frame_sink_id,
- viz::mojom::SubTargetPtr sub_target) final {
+ void ChangeTarget(
+ const absl::optional<viz::VideoCaptureTarget>& target) final {
DCHECK_NOT_ON_DEVICE_THREAD();
- viz::SubtreeCaptureId subtree_id;
- if (sub_target && sub_target->is_subtree_capture_id()) {
- subtree_id = sub_target->get_subtree_capture_id();
- }
- MockChangeTarget(FrameSinkVideoCaptureDevice::VideoCaptureTarget(
- frame_sink_id.value_or(viz::FrameSinkId{}), subtree_id,
- /*crop_id=*/base::Token()));
+ MockChangeTarget(target);
}
- MOCK_METHOD1(
- MockChangeTarget,
- void(const FrameSinkVideoCaptureDevice::VideoCaptureTarget& target));
+ MOCK_METHOD1(MockChangeTarget,
+ void(const absl::optional<viz::VideoCaptureTarget>& target));
void Start(
mojo::PendingRemote<viz::mojom::FrameSinkVideoConsumer> consumer) final {
DCHECK_NOT_ON_DEVICE_THREAD();
@@ -351,10 +344,10 @@
EXPECT_CALL(capturer_, SetMinCapturePeriod(kMinCapturePeriod));
EXPECT_CALL(capturer_,
SetResolutionConstraints(kResolution, kResolution, _));
- FrameSinkVideoCaptureDevice::VideoCaptureTarget target(
- viz::FrameSinkId{1, 1}, viz::SubtreeCaptureId(),
- /*crop_id=*/base::Token());
- EXPECT_CALL(capturer_, MockChangeTarget(target));
+ const viz::VideoCaptureTarget target(viz::FrameSinkId{1, 1});
+ EXPECT_CALL(
+ capturer_,
+ MockChangeTarget(absl::optional<viz::VideoCaptureTarget>(target)));
EXPECT_CALL(capturer_, MockStart(NotNull()));
EXPECT_FALSE(capturer_.is_bound());
@@ -602,9 +595,8 @@
// consumption, unbind the capturer, log an error with the VideoFrameReceiver,
// and destroy the VideoFrameReceiver.
{
- EXPECT_CALL(
- capturer_,
- MockChangeTarget(FrameSinkVideoCaptureDevice::VideoCaptureTarget()));
+ EXPECT_CALL(capturer_,
+ MockChangeTarget(absl::optional<viz::VideoCaptureTarget>()));
EXPECT_CALL(capturer_, MockStop());
POST_DEVICE_METHOD_CALL0(OnTargetPermanentlyLost);
WAIT_FOR_DEVICE_TASKS();
diff --git a/content/browser/media/capture/views_widget_video_capture_device_mac.cc b/content/browser/media/capture/views_widget_video_capture_device_mac.cc
index 8c2ce59..e1747db 100644
--- a/content/browser/media/capture/views_widget_video_capture_device_mac.cc
+++ b/content/browser/media/capture/views_widget_video_capture_device_mac.cc
@@ -55,9 +55,7 @@
FROM_HERE,
base::BindOnce(
&FrameSinkVideoCaptureDevice::OnTargetChanged, device_,
- FrameSinkVideoCaptureDevice::VideoCaptureTarget(
- scoped_cg_window_id_->GetFrameSinkId(),
- viz::SubtreeCaptureId(), /*crop_id=*/base::Token())));
+ viz::VideoCaptureTarget(scoped_cg_window_id_->GetFrameSinkId())));
} else {
// It is entirely possible (although unlikely) that the window
// corresponding to |cg_window_id| be destroyed between when the capture
diff --git a/content/browser/media/capture/web_contents_frame_tracker.cc b/content/browser/media/capture/web_contents_frame_tracker.cc
index 24b9c01..e4ed168 100644
--- a/content/browser/media/capture/web_contents_frame_tracker.cc
+++ b/content/browser/media/capture/web_contents_frame_tracker.cc
@@ -212,14 +212,16 @@
crop_id_ = crop_id;
- const FrameSinkVideoCaptureDevice::VideoCaptureTarget target(
- target_frame_sink_id_.value_or(viz::FrameSinkId()),
- viz::SubtreeCaptureId(), crop_id_);
+ // If we don't have a target yet, we can store the crop ID but cannot actually
+ // crop yet.
+ if (!target_frame_sink_id_.is_valid())
+ return;
+ const viz::VideoCaptureTarget target(target_frame_sink_id_, crop_id_);
device_task_runner_->PostTask(
FROM_HERE,
base::BindOnce(
- [](const FrameSinkVideoCaptureDevice::VideoCaptureTarget& target,
+ [](const viz::VideoCaptureTarget& target,
base::OnceCallback<void(media::mojom::CropRequestResult)> callback,
base::WeakPtr<WebContentsVideoCaptureDevice> device) {
if (!device) {
@@ -252,20 +254,26 @@
return;
}
- // TODO(crbug.com/1247761): Clear |crop_id_| when share-this-tab-instead
- // is clicked.
-
viz::FrameSinkId frame_sink_id;
if (context_) {
frame_sink_id = context_->GetFrameSinkIdForCapture();
}
+
+ // TODO(crbug.com/1247761): Clear |crop_id_| when share-this-tab-instead
+ // is clicked.
if (frame_sink_id != target_frame_sink_id_) {
target_frame_sink_id_ = frame_sink_id;
+ absl::optional<viz::VideoCaptureTarget> target;
+ if (frame_sink_id.is_valid()) {
+ target = viz::VideoCaptureTarget(frame_sink_id, crop_id_);
+ }
+
+ // The target may change to an invalid one, but we don't consider it
+ // permanently lost here yet.
device_task_runner_->PostTask(
FROM_HERE,
base::BindOnce(&WebContentsVideoCaptureDevice::OnTargetChanged, device_,
- FrameSinkVideoCaptureDevice::VideoCaptureTarget(
- frame_sink_id, viz::SubtreeCaptureId(), crop_id_)));
+ std::move(target)));
}
SetTargetView(web_contents()->GetNativeView());
diff --git a/content/browser/media/capture/web_contents_frame_tracker.h b/content/browser/media/capture/web_contents_frame_tracker.h
index 96c9e73..67a3884 100644
--- a/content/browser/media/capture/web_contents_frame_tracker.h
+++ b/content/browser/media/capture/web_contents_frame_tracker.h
@@ -129,7 +129,7 @@
// We may not have a frame sink ID target at all times.
std::unique_ptr<Context> context_;
- absl::optional<viz::FrameSinkId> target_frame_sink_id_;
+ viz::FrameSinkId target_frame_sink_id_;
base::Token crop_id_;
gfx::NativeView target_native_view_ = gfx::NativeView();
diff --git a/content/browser/media/capture/web_contents_frame_tracker_unittest.cc b/content/browser/media/capture/web_contents_frame_tracker_unittest.cc
index d58b1bb..41a5fab0 100644
--- a/content/browser/media/capture/web_contents_frame_tracker_unittest.cc
+++ b/content/browser/media/capture/web_contents_frame_tracker_unittest.cc
@@ -74,7 +74,7 @@
public:
using WebContentsVideoCaptureDevice::AsWeakPtr;
MOCK_METHOD1(OnTargetChanged,
- void(const FrameSinkVideoCaptureDevice::VideoCaptureTarget&));
+ void(const absl::optional<viz::VideoCaptureTarget>&));
MOCK_METHOD0(OnTargetPermanentlyLost, void());
};
@@ -315,11 +315,12 @@
// test the observer callbacks here.
TEST_F(WebContentsFrameTrackerTest, NotifiesOfTargetChanges) {
const viz::FrameSinkId kNewId(42, 1337);
- EXPECT_CALL(*device(),
- OnTargetChanged(FrameSinkVideoCaptureDevice::VideoCaptureTarget(
- kNewId, viz::SubtreeCaptureId(), /*crop_id=*/base::Token())))
- .Times(1);
SetFrameSinkId(kNewId);
+ EXPECT_CALL(
+ *device(),
+ OnTargetChanged(absl::make_optional<viz::VideoCaptureTarget>(kNewId)))
+ .Times(1);
+
// The tracker doesn't actually use the frame host information, just
// posts a possible target change.
tracker()->RenderFrameHostChanged(nullptr, nullptr);
@@ -341,8 +342,8 @@
// Expect OnTargetChanged() to be invoked once with the crop-ID.
EXPECT_CALL(*device(),
- OnTargetChanged(FrameSinkVideoCaptureDevice::VideoCaptureTarget(
- kInitSinkId, viz::SubtreeCaptureId(), kCropId)))
+ OnTargetChanged(absl::make_optional<viz::VideoCaptureTarget>(
+ kInitSinkId, kCropId)))
.Times(1);
tracker()->Crop(kCropId, std::move(callback));
diff --git a/content/browser/renderer_host/render_widget_host_view_base.cc b/content/browser/renderer_host/render_widget_host_view_base.cc
index 8f29a8a..0399fd1 100644
--- a/content/browser/renderer_host/render_widget_host_view_base.cc
+++ b/content/browser/renderer_host/render_widget_host_view_base.cc
@@ -303,7 +303,7 @@
RenderWidgetHostViewBase::CreateVideoCapturer() {
std::unique_ptr<viz::ClientFrameSinkVideoCapturer> video_capturer =
GetHostFrameSinkManager()->CreateVideoCapturer();
- video_capturer->ChangeTarget(GetFrameSinkId(), nullptr);
+ video_capturer->ChangeTarget(viz::VideoCaptureTarget(GetFrameSinkId()));
return video_capturer;
}
diff --git a/services/viz/privileged/mojom/compositing/BUILD.gn b/services/viz/privileged/mojom/compositing/BUILD.gn
index 65d5f75..ee3bcd1 100644
--- a/services/viz/privileged/mojom/compositing/BUILD.gn
+++ b/services/viz/privileged/mojom/compositing/BUILD.gn
@@ -29,7 +29,12 @@
"//ui/latency/mojom",
]
- traits_public_deps = [ "//ui/base:features" ]
+ parser_deps = [ "//components/viz/common" ]
+
+ traits_public_deps = [
+ "//components/viz/common",
+ "//ui/base:features",
+ ]
enabled_features = []
if (use_ozone) {
diff --git a/services/viz/privileged/mojom/compositing/frame_sink_video_capture.mojom b/services/viz/privileged/mojom/compositing/frame_sink_video_capture.mojom
index 24945b1..38deefc 100644
--- a/services/viz/privileged/mojom/compositing/frame_sink_video_capture.mojom
+++ b/services/viz/privileged/mojom/compositing/frame_sink_video_capture.mojom
@@ -30,12 +30,17 @@
};
// Provided with FrameSinkVideoConsumer::ChangeTarget() to indicate what
-// sub target specifier should be used, if any.
-union SubTarget {
+// target should be selected for capture.
+union VideoCaptureSubTarget {
SubtreeCaptureId subtree_capture_id;
mojo_base.mojom.Token region_capture_crop_id;
};
+struct VideoCaptureTarget {
+ FrameSinkId frame_sink_id;
+ VideoCaptureSubTarget? sub_target;
+};
+
// Interface for a consumer that receives frames and notifications related to
// capture of the source content. An instance that implements this interface is
// provided to FrameSinkVideoCapturer.Start().
@@ -127,8 +132,9 @@
SetAutoThrottlingEnabled(bool enabled);
// Targets a different compositor frame sink. This may be called anytime,
- // before or after Start(). If |frame_sink_id| is null, capture will suspend
- // until a new frame sink target is set.
+ // before or after Start(). If |target| is null, capture will suspend
+ // until a new frame sink target is set. If |target| is provided, the
+ // frame sink identifier associated with it must be valid.
// If the |sub_target| is a valid subtree capture id, the capturer will
// capture a render pass associated with a layer subtree under the target
// frame sink, which is identifiable by that
@@ -136,7 +142,7 @@
// crop id, only the region associated with that crop id will be captured.
// Otherwise, the capturer captures the root render pass of the target frame
// sink.
- ChangeTarget(FrameSinkId? frame_sink_id, SubTarget? sub_target);
+ ChangeTarget(VideoCaptureTarget? target);
// Starts emitting video frames to the given |consumer|.
Start(pending_remote<FrameSinkVideoConsumer> consumer);
@@ -150,7 +156,7 @@
// resolve occasional "picture loss" issues consumer-side.
RequestRefreshFrame();
- // Creates an overlay to be renderered within each captured video frame. The
+ // Creates an overlay to be rendered within each captured video frame. The
// |stacking_index| is an arbitrary value that determines whether to render
// this overlay before/after other overlays. Greater values mean "after" and
// "on top of" those with lesser values. Specifying the same index as an
diff --git a/services/viz/public/cpp/compositing/video_capture_target_mojom_traits.h b/services/viz/public/cpp/compositing/video_capture_target_mojom_traits.h
new file mode 100644
index 0000000..85e466de9
--- /dev/null
+++ b/services/viz/public/cpp/compositing/video_capture_target_mojom_traits.h
@@ -0,0 +1,104 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef SERVICES_VIZ_PUBLIC_CPP_COMPOSITING_VIDEO_CAPTURE_TARGET_MOJOM_TRAITS_H_
+#define SERVICES_VIZ_PUBLIC_CPP_COMPOSITING_VIDEO_CAPTURE_TARGET_MOJOM_TRAITS_H_
+
+#include <utility>
+
+#include "build/build_config.h"
+#include "components/viz/common/surfaces/video_capture_target.h"
+#include "mojo/public/cpp/base/token_mojom_traits.h"
+#include "services/viz/privileged/mojom/compositing/frame_sink_video_capture.mojom-shared.h"
+#include "services/viz/public/cpp/compositing/frame_sink_id_mojom_traits.h"
+#include "services/viz/public/cpp/compositing/subtree_capture_id_mojom_traits.h"
+
+namespace mojo {
+
+template <>
+struct UnionTraits<viz::mojom::VideoCaptureSubTargetDataView,
+ viz::VideoCaptureSubTarget> {
+ static bool IsNull(const viz::VideoCaptureSubTarget& data) {
+ return absl::holds_alternative<absl::monostate>(data);
+ }
+
+ static void SetToNull(viz::VideoCaptureSubTarget* data) {
+ *data = viz::VideoCaptureSubTarget();
+ }
+
+ static const viz::RegionCaptureCropId& region_capture_crop_id(
+ const viz::VideoCaptureSubTarget& data) {
+ return absl::get<viz::RegionCaptureCropId>(data);
+ }
+
+ static viz::SubtreeCaptureId subtree_capture_id(
+ const viz::VideoCaptureSubTarget& data) {
+ return absl::get<viz::SubtreeCaptureId>(data);
+ }
+
+ using Tag = viz::mojom::VideoCaptureSubTargetDataView::Tag;
+ static Tag GetTag(const viz::VideoCaptureSubTarget& data) {
+ if (absl::holds_alternative<viz::RegionCaptureCropId>(data)) {
+ return Tag::REGION_CAPTURE_CROP_ID;
+ }
+ DCHECK(absl::holds_alternative<viz::SubtreeCaptureId>(data));
+ return Tag::SUBTREE_CAPTURE_ID;
+ }
+
+ static bool Read(viz::mojom::VideoCaptureSubTargetDataView data,
+ viz::VideoCaptureSubTarget* out) {
+ switch (data.tag()) {
+ case Tag::REGION_CAPTURE_CROP_ID: {
+ viz::RegionCaptureCropId crop_id;
+ if (!data.ReadRegionCaptureCropId(&crop_id) || crop_id.is_zero())
+ return false;
+
+ *out = crop_id;
+ return true;
+ }
+ case Tag::SUBTREE_CAPTURE_ID: {
+ viz::SubtreeCaptureId capture_id;
+ if (!data.ReadSubtreeCaptureId(&capture_id) || !capture_id.is_valid())
+ return false;
+
+ *out = capture_id;
+ return true;
+ }
+ }
+
+ NOTREACHED();
+ return false;
+ }
+};
+
+template <>
+struct StructTraits<viz::mojom::VideoCaptureTargetDataView,
+ viz::VideoCaptureTarget> {
+ static viz::FrameSinkId frame_sink_id(const viz::VideoCaptureTarget& input) {
+ return input.frame_sink_id;
+ }
+
+ static const viz::VideoCaptureSubTarget& sub_target(
+ const viz::VideoCaptureTarget& input) {
+ return input.sub_target;
+ }
+
+ static bool Read(viz::mojom::VideoCaptureTargetDataView data,
+ viz::VideoCaptureTarget* out) {
+ viz::VideoCaptureTarget target;
+ if (!data.ReadSubTarget(&target.sub_target) ||
+ !data.ReadFrameSinkId(&target.frame_sink_id))
+ return false;
+
+ if (!target.frame_sink_id.is_valid())
+ return false;
+
+ *out = std::move(target);
+ return true;
+ }
+};
+
+} // namespace mojo
+
+#endif // SERVICES_VIZ_PUBLIC_CPP_COMPOSITING_VIDEO_CAPTURE_TARGET_MOJOM_TRAITS_H_
diff --git a/services/viz/public/mojom/BUILD.gn b/services/viz/public/mojom/BUILD.gn
index 2f766bed..7411af8 100644
--- a/services/viz/public/mojom/BUILD.gn
+++ b/services/viz/public/mojom/BUILD.gn
@@ -183,6 +183,24 @@
traits_headers = [ "//services/viz/public/cpp/compositing/vertical_scroll_direction_mojom_traits.h" ]
traits_public_deps = [ "//components/viz/common" ]
},
+ {
+ types = [
+ {
+ mojom = "viz.mojom.VideoCaptureTarget"
+ cpp = "::viz::VideoCaptureTarget"
+ },
+ {
+ mojom = "viz.mojom.VideoCaptureSubTarget"
+ cpp = "::viz::VideoCaptureSubTarget"
+ nullable_is_same_type = true
+ },
+ ]
+ traits_headers = [ "//services/viz/public/cpp/compositing/video_capture_target_mojom_traits.h" ]
+ traits_public_deps = [
+ "//components/viz/common",
+ "//ui/gfx/geometry/mojom",
+ ]
+ },
]
cpp_typemaps = shared_cpp_typemaps
cpp_typemaps += [