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

Unified Diff: content/renderer/media/media_stream_constraints_util_video_content.cc

Issue 2814063002: Update constraints algorithm for screen capture. (Closed)
Patch Set: maxmorin's comments and minor rearrangement of constants Created 3 years, 8 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 side-by-side diff with in-line comments
Download patch
Index: content/renderer/media/media_stream_constraints_util_video_content.cc
diff --git a/content/renderer/media/media_stream_constraints_util_video_content.cc b/content/renderer/media/media_stream_constraints_util_video_content.cc
index a47db2a2fbe72c0e75184fec687eac5dfac02dc9..2f9d0822af280d9469ad5dc32d06468404ab7239 100644
--- a/content/renderer/media/media_stream_constraints_util_video_content.cc
+++ b/content/renderer/media/media_stream_constraints_util_video_content.cc
@@ -4,6 +4,7 @@
#include "content/renderer/media/media_stream_constraints_util_video_content.h"
+#include <algorithm>
#include <cmath>
#include <utility>
#include <vector>
@@ -16,14 +17,27 @@
namespace content {
+const int kMinScreenCastDimension = 1;
+// Use kMaxDimension/2 as maximum to ensure selected resolutions have area less
+// than media::limits::kMaxCanvas.
+const int kMaxScreenCastDimension = media::limits::kMaxDimension / 2;
+static_assert(kMaxScreenCastDimension * kMaxScreenCastDimension <
+ media::limits::kMaxCanvas,
+ "Invalid kMaxScreenCastDimension");
+
const int kDefaultScreenCastWidth = 2880;
const int kDefaultScreenCastHeight = 1800;
const double kDefaultScreenCastAspectRatio =
static_cast<double>(kDefaultScreenCastWidth) / kDefaultScreenCastHeight;
+static_assert(kDefaultScreenCastWidth <= kMaxScreenCastDimension,
+ "Invalid kDefaultScreenCastWidth");
+static_assert(kDefaultScreenCastHeight <= kMaxScreenCastDimension,
+ "Invalid kDefaultScreenCastHeight");
+
+const double kMinScreenCastFrameRate = 1.0 / 60.0;
+const double kMaxScreenCastFrameRate = 120.0;
const double kDefaultScreenCastFrameRate =
MediaStreamVideoSource::kDefaultFrameRate;
-const int kMinScreenCastDimension = 1;
-const int kMaxScreenCastDimension = media::limits::kMaxDimension - 1;
namespace {
@@ -31,9 +45,6 @@ using Point = ResolutionSet::Point;
using StringSet = DiscreteSet<std::string>;
using BoolSet = DiscreteSet<bool>;
-// Hard upper and lower bound frame rates for tab/desktop capture.
-const double kMaxScreenCastFrameRate = 120.0;
-const double kMinScreenCastFrameRate = 1.0 / 60.0;
constexpr double kMinScreenCastAspectRatio =
static_cast<double>(kMinScreenCastDimension) /
@@ -65,15 +76,28 @@ using DoubleRangeSet = NumericRangeSet<double>;
class VideoContentCaptureCandidates {
public:
VideoContentCaptureCandidates()
- : device_id_set(StringSet::UniversalSet()),
- noise_reduction_set(BoolSet::UniversalSet()) {}
+ : has_explicit_max_height_(false),
+ has_explicit_max_width_(false),
+ has_explicit_max_frame_rate_(false),
+ device_id_set_(StringSet::UniversalSet()),
+ noise_reduction_set_(BoolSet::UniversalSet()) {}
explicit VideoContentCaptureCandidates(
const blink::WebMediaTrackConstraintSet& constraint_set)
- : resolution_set(ResolutionSet::FromConstraintSet(constraint_set)),
- frame_rate_set(
+ : resolution_set_(ResolutionSet::FromConstraintSet(constraint_set)),
+ has_explicit_max_height_(ConstraintHasMax(constraint_set.height) &&
+ ConstraintMax(constraint_set.height) <=
+ kMaxScreenCastDimension),
+ has_explicit_max_width_(ConstraintHasMax(constraint_set.width) &&
+ ConstraintMax(constraint_set.width) <=
+ kMaxScreenCastDimension),
+ frame_rate_set_(
DoubleRangeSet::FromConstraint(constraint_set.frame_rate)),
- device_id_set(StringSetFromConstraint(constraint_set.device_id)),
- noise_reduction_set(
+ has_explicit_max_frame_rate_(
+ ConstraintHasMax(constraint_set.frame_rate) &&
+ ConstraintMax(constraint_set.frame_rate) <=
+ kMaxScreenCastFrameRate),
+ device_id_set_(StringSetFromConstraint(constraint_set.device_id)),
+ noise_reduction_set_(
BoolSetFromConstraint(constraint_set.goog_noise_reduction)) {}
VideoContentCaptureCandidates(VideoContentCaptureCandidates&& other) =
@@ -82,28 +106,50 @@ class VideoContentCaptureCandidates {
VideoContentCaptureCandidates&& other) = default;
bool IsEmpty() const {
- return resolution_set.IsEmpty() || frame_rate_set.IsEmpty() ||
- device_id_set.IsEmpty() || noise_reduction_set.IsEmpty();
+ return resolution_set_.IsEmpty() || frame_rate_set_.IsEmpty() ||
+ device_id_set_.IsEmpty() || noise_reduction_set_.IsEmpty();
}
VideoContentCaptureCandidates Intersection(
const VideoContentCaptureCandidates& other) {
VideoContentCaptureCandidates intersection;
- intersection.resolution_set =
- resolution_set.Intersection(other.resolution_set);
- intersection.frame_rate_set =
- frame_rate_set.Intersection(other.frame_rate_set);
- intersection.device_id_set =
- device_id_set.Intersection(other.device_id_set);
- intersection.noise_reduction_set =
- noise_reduction_set.Intersection(other.noise_reduction_set);
+ intersection.resolution_set_ =
+ resolution_set_.Intersection(other.resolution_set_);
+ intersection.has_explicit_max_height_ =
+ has_explicit_max_height_ || other.has_explicit_max_height_;
+ intersection.has_explicit_max_width_ =
+ has_explicit_max_width_ || other.has_explicit_max_width_;
+ intersection.frame_rate_set_ =
+ frame_rate_set_.Intersection(other.frame_rate_set_);
+ intersection.has_explicit_max_frame_rate_ =
+ has_explicit_max_frame_rate_ || other.has_explicit_max_frame_rate_;
+ intersection.device_id_set_ =
+ device_id_set_.Intersection(other.device_id_set_);
+ intersection.noise_reduction_set_ =
+ noise_reduction_set_.Intersection(other.noise_reduction_set_);
return intersection;
}
- ResolutionSet resolution_set;
- DoubleRangeSet frame_rate_set;
- StringSet device_id_set;
- BoolSet noise_reduction_set;
+ const ResolutionSet& resolution_set() const { return resolution_set_; }
+ bool has_explicit_max_height() const { return has_explicit_max_height_; }
+ bool has_explicit_max_width() const { return has_explicit_max_width_; }
+ const DoubleRangeSet& frame_rate_set() const { return frame_rate_set_; }
+ bool has_explicit_max_frame_rate() const {
+ return has_explicit_max_frame_rate_;
+ }
+ const StringSet& device_id_set() const { return device_id_set_; }
+ const BoolSet& noise_reduction_set() const { return noise_reduction_set_; }
+ void set_resolution_set(const ResolutionSet& set) { resolution_set_ = set; }
+ void set_frame_rate_set(const DoubleRangeSet& set) { frame_rate_set_ = set; }
+
+ private:
+ ResolutionSet resolution_set_;
+ bool has_explicit_max_height_;
+ bool has_explicit_max_width_;
+ DoubleRangeSet frame_rate_set_;
+ bool has_explicit_max_frame_rate_;
+ StringSet device_id_set_;
+ BoolSet noise_reduction_set_;
};
ResolutionSet ScreenCastResolutionCapabilities() {
@@ -173,16 +219,16 @@ media::VideoCaptureParams SelectVideoCaptureParamsFromCandidates(
int default_width,
double default_frame_rate) {
double requested_frame_rate = SelectFrameRateFromCandidates(
- candidates.frame_rate_set, basic_constraint_set, default_frame_rate);
+ candidates.frame_rate_set(), basic_constraint_set, default_frame_rate);
Point requested_resolution =
- candidates.resolution_set.SelectClosestPointToIdeal(
+ candidates.resolution_set().SelectClosestPointToIdeal(
basic_constraint_set, default_height, default_width);
media::VideoCaptureParams params;
params.requested_format = media::VideoCaptureFormat(
ToGfxSize(requested_resolution), static_cast<float>(requested_frame_rate),
media::PIXEL_FORMAT_I420);
params.resolution_change_policy =
- SelectResolutionPolicyFromCandidates(candidates.resolution_set);
+ SelectResolutionPolicyFromCandidates(candidates.resolution_set());
// Content capture always uses default power-line frequency.
DCHECK(params.IsValid());
@@ -232,11 +278,19 @@ base::Optional<bool> SelectNoiseReductionFromCandidates(
return base::Optional<bool>(candidates.FirstElement());
}
+int ClampToValidDimension(int value) {
+ if (value > kMaxScreenCastDimension)
+ return kMaxScreenCastDimension;
+ else if (value < kMinScreenCastDimension)
+ return kMinScreenCastDimension;
+ return value;
+}
+
VideoCaptureSettings SelectResultFromCandidates(
const VideoContentCaptureCandidates& candidates,
const blink::WebMediaTrackConstraintSet& basic_constraint_set) {
- std::string device_id = SelectDeviceIDFromCandidates(candidates.device_id_set,
- basic_constraint_set);
+ std::string device_id = SelectDeviceIDFromCandidates(
+ candidates.device_id_set(), basic_constraint_set);
// If a maximum width or height is explicitly given, use them as default.
// If only one of them is given, use the default aspect ratio to determine the
// other default value.
@@ -244,55 +298,65 @@ VideoCaptureSettings SelectResultFromCandidates(
// http://crbug.com/257097
int default_height = kDefaultScreenCastHeight;
int default_width = kDefaultScreenCastWidth;
- bool has_explicit_max_height =
- candidates.resolution_set.max_height() < kMaxScreenCastDimension;
- bool has_explicit_max_width =
- candidates.resolution_set.max_width() < kMaxScreenCastDimension;
- if (has_explicit_max_height && has_explicit_max_width) {
- default_height = candidates.resolution_set.max_height();
- default_width = candidates.resolution_set.max_width();
- } else if (has_explicit_max_height) {
- default_height = candidates.resolution_set.max_height();
+ if (candidates.has_explicit_max_height() &&
+ candidates.has_explicit_max_width()) {
+ default_height = candidates.resolution_set().max_height();
+ default_width = candidates.resolution_set().max_width();
+ } else if (candidates.has_explicit_max_height()) {
+ default_height = candidates.resolution_set().max_height();
default_width = static_cast<int>(
std::round(default_height * kDefaultScreenCastAspectRatio));
- } else if (has_explicit_max_width) {
- default_width = candidates.resolution_set.max_width();
+ } else if (candidates.has_explicit_max_width()) {
+ default_width = candidates.resolution_set().max_width();
default_height = static_cast<int>(
std::round(default_width / kDefaultScreenCastAspectRatio));
}
+ // When the given maximum values are large, the computed values using default
+ // aspect ratio may fall out of range. Ensure the defaults are in the valid
+ // range.
+ default_height = ClampToValidDimension(default_height);
+ default_width = ClampToValidDimension(default_width);
+
+ // If a maximum frame rate is explicitly given, use it as default for
+ // better compatibility with the old constraints algorithm.
+ // TODO(guidou): Use the actual default when applications migrate to the new
+ // constraint syntax. http://crbug.com/710800
+ double default_frame_rate = candidates.has_explicit_max_frame_rate()
+ ? candidates.frame_rate_set().Max()
+ : kDefaultScreenCastFrameRate;
media::VideoCaptureParams capture_params =
SelectVideoCaptureParamsFromCandidates(candidates, basic_constraint_set,
default_height, default_width,
- kDefaultScreenCastFrameRate);
+ default_frame_rate);
base::Optional<bool> noise_reduction = SelectNoiseReductionFromCandidates(
- candidates.noise_reduction_set, basic_constraint_set);
+ candidates.noise_reduction_set(), basic_constraint_set);
auto track_adapter_settings = SelectVideoTrackAdapterSettings(
- basic_constraint_set, candidates.resolution_set,
- candidates.frame_rate_set, capture_params.requested_format);
+ basic_constraint_set, candidates.resolution_set(),
+ candidates.frame_rate_set(), capture_params.requested_format);
return VideoCaptureSettings(std::move(device_id), capture_params,
noise_reduction, track_adapter_settings,
- candidates.frame_rate_set.Min());
+ candidates.frame_rate_set().Min());
}
VideoCaptureSettings UnsatisfiedConstraintsResult(
const VideoContentCaptureCandidates& candidates,
const blink::WebMediaTrackConstraintSet& constraint_set) {
DCHECK(candidates.IsEmpty());
- if (candidates.resolution_set.IsHeightEmpty()) {
+ if (candidates.resolution_set().IsHeightEmpty()) {
return VideoCaptureSettings(constraint_set.height.GetName());
- } else if (candidates.resolution_set.IsWidthEmpty()) {
+ } else if (candidates.resolution_set().IsWidthEmpty()) {
return VideoCaptureSettings(constraint_set.width.GetName());
- } else if (candidates.resolution_set.IsAspectRatioEmpty()) {
+ } else if (candidates.resolution_set().IsAspectRatioEmpty()) {
return VideoCaptureSettings(constraint_set.aspect_ratio.GetName());
- } else if (candidates.frame_rate_set.IsEmpty()) {
+ } else if (candidates.frame_rate_set().IsEmpty()) {
return VideoCaptureSettings(constraint_set.frame_rate.GetName());
- } else if (candidates.noise_reduction_set.IsEmpty()) {
+ } else if (candidates.noise_reduction_set().IsEmpty()) {
return VideoCaptureSettings(constraint_set.goog_noise_reduction.GetName());
} else {
- DCHECK(candidates.device_id_set.IsEmpty());
+ DCHECK(candidates.device_id_set().IsEmpty());
return VideoCaptureSettings(constraint_set.device_id.GetName());
}
}
@@ -302,9 +366,9 @@ VideoCaptureSettings UnsatisfiedConstraintsResult(
VideoCaptureSettings SelectSettingsVideoContentCapture(
const blink::WebMediaConstraints& constraints) {
VideoContentCaptureCandidates candidates;
- candidates.resolution_set = ScreenCastResolutionCapabilities();
- candidates.frame_rate_set =
- DoubleRangeSet(kMinScreenCastFrameRate, kMaxScreenCastFrameRate);
+ candidates.set_resolution_set(ScreenCastResolutionCapabilities());
+ candidates.set_frame_rate_set(
+ DoubleRangeSet(kMinScreenCastFrameRate, kMaxScreenCastFrameRate));
// candidates.device_id_set and candidates.noise_reduction_set are
// automatically initialized with the universal set.

Powered by Google App Engine
This is Rietveld 408576698