Commit 323cdb00 authored by Guido Urdaneta's avatar Guido Urdaneta Committed by Commit Bot

Add support for the resizeMode constraint in screen capture.

Since screen capture does not have a clear concept of native resolution,
rescaling will be enabled by default and will be disabled only if
explicitly requested.
This maintains existing behavior in all existing applications that use
content capture.

This CL concludes the resizeMode series.

Bug: 854980
Change-Id: I8658e36f22501f18d1d9dc9b6b0fe6e24063140b
Reviewed-on: https://chromium-review.googlesource.com/c/1310716
Commit-Queue: Guido Urdaneta <guidou@chromium.org>
Reviewed-by: default avatarHenrik Boström <hbos@chromium.org>
Cr-Commit-Position: refs/heads/master@{#610149}
parent a6c1687b
......@@ -73,7 +73,9 @@ class VideoContentCaptureCandidates {
device_id_set_(media_constraints::StringSetFromConstraint(
constraint_set.device_id)),
noise_reduction_set_(media_constraints::BoolSetFromConstraint(
constraint_set.goog_noise_reduction)) {}
constraint_set.goog_noise_reduction)),
rescale_set_(media_constraints::RescaleSetFromConstraint(
constraint_set.resize_mode)) {}
VideoContentCaptureCandidates(VideoContentCaptureCandidates&& other) =
default;
......@@ -82,7 +84,8 @@ class VideoContentCaptureCandidates {
bool IsEmpty() const {
return resolution_set_.IsEmpty() || frame_rate_set_.IsEmpty() ||
device_id_set_.IsEmpty() || noise_reduction_set_.IsEmpty();
device_id_set_.IsEmpty() || noise_reduction_set_.IsEmpty() ||
rescale_set_.IsEmpty();
}
VideoContentCaptureCandidates Intersection(
......@@ -100,6 +103,7 @@ class VideoContentCaptureCandidates {
device_id_set_.Intersection(other.device_id_set_);
intersection.noise_reduction_set_ =
noise_reduction_set_.Intersection(other.noise_reduction_set_);
intersection.rescale_set_ = rescale_set_.Intersection(other.rescale_set_);
return intersection;
}
......@@ -109,6 +113,7 @@ class VideoContentCaptureCandidates {
const DoubleRangeSet& frame_rate_set() const { return frame_rate_set_; }
const StringSet& device_id_set() const { return device_id_set_; }
const BoolSet& noise_reduction_set() const { return noise_reduction_set_; }
const BoolSet& rescale_set() const { return rescale_set_; }
void set_resolution_set(const ResolutionSet& set) { resolution_set_ = set; }
void set_frame_rate_set(const DoubleRangeSet& set) { frame_rate_set_ = set; }
......@@ -119,6 +124,7 @@ class VideoContentCaptureCandidates {
DoubleRangeSet frame_rate_set_;
StringSet device_id_set_;
BoolSet noise_reduction_set_;
BoolSet rescale_set_;
};
ResolutionSet ScreenCastResolutionCapabilities() {
......@@ -249,6 +255,30 @@ base::Optional<bool> SelectNoiseReductionFromCandidates(
return base::Optional<bool>(candidates.FirstElement());
}
bool SelectRescaleFromCandidates(
const BoolSet& candidates,
const blink::WebMediaTrackConstraintSet& basic_constraint_set) {
DCHECK(!candidates.IsEmpty());
if (basic_constraint_set.resize_mode.HasIdeal()) {
for (const auto& ideal_resize_value :
basic_constraint_set.resize_mode.Ideal()) {
if (ideal_resize_value == blink::WebMediaStreamTrack::kResizeModeNone &&
candidates.Contains(false)) {
return false;
} else if (ideal_resize_value ==
blink::WebMediaStreamTrack::kResizeModeRescale &&
candidates.Contains(true)) {
return true;
}
}
}
DCHECK(!candidates.HasExplicitElements() ||
candidates.elements().size() == 1);
// Rescaling is the default for content capture.
return candidates.HasExplicitElements() ? candidates.FirstElement() : true;
}
int ClampToValidScreenCastDimension(int value) {
if (value > kMaxScreenCastDimension)
return kMaxScreenCastDimension;
......@@ -312,10 +342,13 @@ VideoCaptureSettings SelectResultFromCandidates(
base::Optional<bool> noise_reduction = SelectNoiseReductionFromCandidates(
candidates.noise_reduction_set(), basic_constraint_set);
bool enable_rescale = SelectRescaleFromCandidates(candidates.rescale_set(),
basic_constraint_set);
auto track_adapter_settings = SelectVideoTrackAdapterSettings(
basic_constraint_set, candidates.resolution_set(),
candidates.frame_rate_set(), capture_params.requested_format,
true /* enable_rescale */);
enable_rescale);
return VideoCaptureSettings(std::move(device_id), capture_params,
noise_reduction, track_adapter_settings,
......@@ -337,6 +370,8 @@ VideoCaptureSettings UnsatisfiedConstraintsResult(
return VideoCaptureSettings(constraint_set.frame_rate.GetName());
} else if (candidates.noise_reduction_set().IsEmpty()) {
return VideoCaptureSettings(constraint_set.goog_noise_reduction.GetName());
} else if (candidates.rescale_set().IsEmpty()) {
return VideoCaptureSettings(constraint_set.resize_mode.GetName());
} else {
DCHECK(candidates.device_id_set().IsEmpty());
return VideoCaptureSettings(constraint_set.device_id.GetName());
......
......@@ -39,6 +39,7 @@ void CheckNonFrameRateDefaults(const VideoCaptureSettings& result) {
void CheckTrackAdapterSettingsEqualsFormat(const VideoCaptureSettings& result) {
// For content capture, resolution and frame rate should always be the same
// for source and track.
EXPECT_TRUE(result.track_adapter_settings().target_size().has_value());
EXPECT_EQ(result.Width(), result.track_adapter_settings().target_width());
EXPECT_EQ(result.Height(), result.track_adapter_settings().target_height());
EXPECT_EQ(0.0, result.track_adapter_settings().max_frame_rate());
......@@ -180,6 +181,28 @@ TEST_F(MediaStreamConstraintsUtilVideoContentTest, OverconstrainedOnFrameRate) {
result.failed_constraint_name());
}
TEST_F(MediaStreamConstraintsUtilVideoContentTest,
OverconstrainedOnInvalidResizeMode) {
constraint_factory_.Reset();
constraint_factory_.basic().resize_mode.SetExact(
blink::WebString::FromASCII("invalid"));
auto result = SelectSettings();
EXPECT_FALSE(result.HasValue());
EXPECT_EQ(constraint_factory_.basic().resize_mode.GetName(),
result.failed_constraint_name());
}
TEST_F(MediaStreamConstraintsUtilVideoContentTest,
OverconstrainedOnEmptyResizeMode) {
constraint_factory_.Reset();
constraint_factory_.basic().resize_mode.SetExact(
blink::WebString::FromASCII(""));
auto result = SelectSettings();
EXPECT_FALSE(result.HasValue());
EXPECT_EQ(constraint_factory_.basic().resize_mode.GetName(),
result.failed_constraint_name());
}
// The "Mandatory" and "Ideal" tests check that various selection criteria work
// for each individual constraint in the basic constraint set.
TEST_F(MediaStreamConstraintsUtilVideoContentTest, MandatoryDeviceID) {
......@@ -1510,6 +1533,32 @@ TEST_F(MediaStreamConstraintsUtilVideoContentTest, IdealFrameRate) {
}
}
TEST_F(MediaStreamConstraintsUtilVideoContentTest, MandatoryResizeMode) {
const int kIdealWidth = 641;
const int kIdealHeight = 480;
constraint_factory_.Reset();
constraint_factory_.basic().width.SetIdeal(kIdealWidth);
constraint_factory_.basic().height.SetIdeal(kIdealHeight);
constraint_factory_.basic().resize_mode.SetExact(
blink::WebString::FromASCII("none"));
auto result = SelectSettings();
EXPECT_TRUE(result.HasValue());
// Screen capture will proceed at 641x480, which will be considered "native".
// No rescaling will occur since it is explicitly disabled.
EXPECT_EQ(result.Width(), kIdealWidth);
EXPECT_EQ(result.Height(), kIdealHeight);
EXPECT_FALSE(result.track_adapter_settings().target_size().has_value());
constraint_factory_.basic().resize_mode.SetExact(
blink::WebString::FromASCII("crop-and-scale"));
result = SelectSettings();
EXPECT_TRUE(result.HasValue());
EXPECT_EQ(result.Width(), kIdealWidth);
EXPECT_EQ(result.Height(), kIdealHeight);
EXPECT_EQ(result.track_adapter_settings().target_width(), kIdealWidth);
EXPECT_EQ(result.track_adapter_settings().target_height(), kIdealHeight);
}
// The "Advanced" tests check selection criteria involving advanced constraint
// sets.
TEST_F(MediaStreamConstraintsUtilVideoContentTest,
......@@ -2037,6 +2086,37 @@ TEST_F(MediaStreamConstraintsUtilVideoContentTest, AdvancedIdealDeviceID) {
CheckTrackAdapterSettingsEqualsFormatDefaultAspectRatio(result);
}
TEST_F(MediaStreamConstraintsUtilVideoContentTest, AdvancedResizeMode) {
const int kIdealWidth = 641;
const int kIdealHeight = 480;
constraint_factory_.Reset();
constraint_factory_.basic().width.SetIdeal(kIdealWidth);
constraint_factory_.basic().height.SetIdeal(kIdealHeight);
blink::WebMediaTrackConstraintSet& advanced =
constraint_factory_.AddAdvanced();
advanced.resize_mode.SetExact(blink::WebString::FromASCII("none"));
auto result = SelectSettings();
EXPECT_TRUE(result.HasValue());
// Screen capture will proceed at 641x480, which will be considered "native".
// No rescaling will occur since it is explicitly disabled in the advanced
// constraint set.
EXPECT_EQ(result.Width(), kIdealWidth);
EXPECT_EQ(result.Height(), kIdealHeight);
EXPECT_FALSE(result.track_adapter_settings().target_size().has_value());
advanced.resize_mode.SetExact(blink::WebString::FromASCII("crop-and-scale"));
result = SelectSettings();
EXPECT_TRUE(result.HasValue());
// Screen capture will proceed at 641x480, which will be considered "native".
// No rescaling will occur since it is explicitly disabled in the advanced
// constraint set.
EXPECT_EQ(result.Width(), kIdealWidth);
EXPECT_EQ(result.Height(), kIdealHeight);
EXPECT_TRUE(result.track_adapter_settings().target_size().has_value());
EXPECT_EQ(result.track_adapter_settings().target_width(), kIdealWidth);
EXPECT_EQ(result.track_adapter_settings().target_height(), kIdealHeight);
}
TEST_F(MediaStreamConstraintsUtilVideoContentTest, ResolutionChangePolicy) {
{
constraint_factory_.Reset();
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment