Commit b9487f88 authored by hta's avatar hta Committed by Commit bot

Apply new-style constraints to video_source.

This CL reimplements the algorithms presently used for selection
in terms of the new form constraints.
A new mock constraints factory is also added.

BUG=543997

Review URL: https://codereview.chromium.org/1617243005

Cr-Commit-Position: refs/heads/master@{#372082}
parent a9422c2d
...@@ -780,6 +780,7 @@ ...@@ -780,6 +780,7 @@
'renderer/media/media_stream_video_renderer_sink_unittest.cc', 'renderer/media/media_stream_video_renderer_sink_unittest.cc',
'renderer/media/media_stream_video_source_unittest.cc', 'renderer/media/media_stream_video_source_unittest.cc',
'renderer/media/media_stream_video_track_unittest.cc', 'renderer/media/media_stream_video_track_unittest.cc',
'renderer/media/mock_constraint_factory.cc',
'renderer/media/mock_media_constraint_factory.cc', 'renderer/media/mock_media_constraint_factory.cc',
'renderer/media/mock_media_stream_registry.cc', 'renderer/media/mock_media_stream_registry.cc',
'renderer/media/mock_media_stream_registry.h', 'renderer/media/mock_media_stream_registry.h',
......
...@@ -13,7 +13,6 @@ ...@@ -13,7 +13,6 @@
#include "base/strings/string_number_conversions.h" #include "base/strings/string_number_conversions.h"
#include "base/trace_event/trace_event.h" #include "base/trace_event/trace_event.h"
#include "content/child/child_process.h" #include "content/child/child_process.h"
#include "content/renderer/media/media_stream_constraints_util.h"
#include "content/renderer/media/media_stream_video_track.h" #include "content/renderer/media/media_stream_video_track.h"
#include "content/renderer/media/video_track_adapter.h" #include "content/renderer/media/video_track_adapter.h"
...@@ -43,15 +42,14 @@ const char* kSupportedConstraints[] = { ...@@ -43,15 +42,14 @@ const char* kSupportedConstraints[] = {
namespace { namespace {
// Google-specific key prefix. Constraints with this prefix are ignored if they const char* kLegalVideoConstraints[] = {
// are unknown. "width", "height", "aspectRatio", "frameRate",
const char kGooglePrefix[] = "goog"; "facingMode", "deviceId", "groupId", "mediaStreamSource",
};
// Returns true if |constraint| has mandatory constraints. // Returns true if |constraint| has mandatory constraints.
bool HasMandatoryConstraints(const blink::WebMediaConstraints& constraints) { bool HasMandatoryConstraints(const blink::WebMediaConstraints& constraints) {
blink::WebVector<blink::WebMediaConstraint> mandatory_constraints; return constraints.basic().hasMandatory();
constraints.getMandatoryConstraints(mandatory_constraints);
return !mandatory_constraints.isEmpty();
} }
// Retrieve the desired max width and height from |constraints|. If not set, // Retrieve the desired max width and height from |constraints|. If not set,
...@@ -64,23 +62,21 @@ void GetDesiredMaxWidthAndHeight(const blink::WebMediaConstraints& constraints, ...@@ -64,23 +62,21 @@ void GetDesiredMaxWidthAndHeight(const blink::WebMediaConstraints& constraints,
*desired_width = std::numeric_limits<int>::max(); *desired_width = std::numeric_limits<int>::max();
*desired_height = std::numeric_limits<int>::max(); *desired_height = std::numeric_limits<int>::max();
bool mandatory = GetMandatoryConstraintValueAsInteger( const auto& basic_constraints = constraints.basic();
constraints, if (basic_constraints.width.hasMax() || basic_constraints.height.hasMax()) {
MediaStreamVideoSource::kMaxWidth, if (basic_constraints.width.hasMax())
desired_width); *desired_width = basic_constraints.width.max();
mandatory |= GetMandatoryConstraintValueAsInteger( if (basic_constraints.height.hasMax())
constraints, *desired_height = basic_constraints.height.max();
MediaStreamVideoSource::kMaxHeight,
desired_height);
if (mandatory)
return; return;
}
GetOptionalConstraintValueAsInteger(constraints, for (const auto& constraint_set : constraints.advanced()) {
MediaStreamVideoSource::kMaxWidth, if (constraint_set.width.hasMax())
desired_width); *desired_width = constraint_set.width.max();
GetOptionalConstraintValueAsInteger(constraints, if (constraint_set.height.hasMax())
MediaStreamVideoSource::kMaxHeight, *desired_height = constraint_set.height.max();
desired_height); }
} }
// Retrieve the desired max and min aspect ratio from |constraints|. If not set, // Retrieve the desired max and min aspect ratio from |constraints|. If not set,
...@@ -95,128 +91,119 @@ void GetDesiredMinAndMaxAspectRatio( ...@@ -95,128 +91,119 @@ void GetDesiredMinAndMaxAspectRatio(
*min_aspect_ratio = 0; *min_aspect_ratio = 0;
*max_aspect_ratio = std::numeric_limits<double>::max(); *max_aspect_ratio = std::numeric_limits<double>::max();
bool mandatory = GetMandatoryConstraintValueAsDouble( if (constraints.basic().aspectRatio.hasMin() ||
constraints, constraints.basic().aspectRatio.hasMax()) {
MediaStreamVideoSource::kMinAspectRatio, if (constraints.basic().aspectRatio.hasMin())
min_aspect_ratio); *min_aspect_ratio = constraints.basic().aspectRatio.min();
mandatory |= GetMandatoryConstraintValueAsDouble( if (constraints.basic().aspectRatio.hasMax())
constraints, *max_aspect_ratio = constraints.basic().aspectRatio.max();
MediaStreamVideoSource::kMaxAspectRatio,
max_aspect_ratio);
if (mandatory)
return; return;
// Note - the code will ignore attempts at successive refinement
GetOptionalConstraintValueAsDouble(constraints, // of the aspect ratio with advanced constraint. This may be wrong.
MediaStreamVideoSource::kMinAspectRatio, }
min_aspect_ratio); // Note - the code below will potentially pick min and max from different
GetOptionalConstraintValueAsDouble(constraints, // constraint sets, some of which might have been ignored.
MediaStreamVideoSource::kMaxAspectRatio, for (const auto& constraint_set : constraints.advanced()) {
max_aspect_ratio); if (constraint_set.aspectRatio.hasMin()) {
*min_aspect_ratio = constraint_set.aspectRatio.min();
break;
}
}
for (const auto& constraint_set : constraints.advanced()) {
if (constraint_set.aspectRatio.hasMax()) {
*max_aspect_ratio = constraint_set.aspectRatio.max();
break;
}
}
} }
// Returns true if |constraint| is fulfilled. |format| can be changed by a // Returns true if |constraints| are fulfilled. |format| can be changed by a
// constraint, e.g. the frame rate can be changed by setting maxFrameRate. // constraint, e.g. the frame rate can be changed by setting maxFrameRate.
bool UpdateFormatForConstraint(const blink::WebMediaConstraint& constraint, bool UpdateFormatForConstraints(
bool mandatory, const blink::WebMediaTrackConstraintSet& constraints,
media::VideoCaptureFormat* format) { media::VideoCaptureFormat* format,
std::string* failing_constraint_name) {
DCHECK(format != NULL); DCHECK(format != NULL);
if (!format->IsValid()) if (!format->IsValid())
return false; return false;
const std::string constraint_name = constraint.m_name.utf8(); // The width and height are matched based on cropping occuring later:
const std::string constraint_value = constraint.m_value.utf8(); // min width/height has to be >= the size of the frame (no upscale).
// max width/height just has to be > 0 (we can crop anything too large).
if (constraint_name.find(kGooglePrefix) == 0) { if ((constraints.width.hasMin() &&
// These are actually options, not constraints, so they can be satisfied constraints.width.min() > format->frame_size.width()) ||
// regardless of the format. (constraints.width.hasMax() && constraints.width.max() <= 0)) {
*failing_constraint_name = constraints.width.name();
} else if ((constraints.height.hasMin() &&
constraints.height.min() > format->frame_size.height()) ||
(constraints.height.hasMax() && constraints.height.max() <= 0)) {
*failing_constraint_name = constraints.height.name();
} else if (!constraints.frameRate.matches(format->frame_rate)) {
if (constraints.frameRate.hasMax()) {
const double value = constraints.frameRate.max();
// TODO(hta): Check if handling of max = 0.0 is relevant.
// (old handling was to set rate to 1.0 if 0.0 was specified)
if (constraints.frameRate.matches(value)) {
format->frame_rate =
(format->frame_rate > value) ? value : format->frame_rate;
return true; return true;
} }
if (constraint_name == MediaStreamSource::kSourceId) {
// This is a constraint that doesn't affect the format.
return true;
} }
*failing_constraint_name = constraints.frameRate.name();
// Ignore Chrome specific Tab capture constraints. } else {
if (constraint_name == kMediaStreamSource ||
constraint_name == kMediaStreamSourceId)
return true; return true;
if (constraint_name == MediaStreamVideoSource::kMinAspectRatio ||
constraint_name == MediaStreamVideoSource::kMaxAspectRatio) {
// These constraints are handled by cropping if the camera outputs the wrong
// aspect ratio.
double value;
return base::StringToDouble(constraint_value, &value);
}
double value = 0.0;
if (!base::StringToDouble(constraint_value, &value)) {
DLOG(WARNING) << "Can't parse MediaStream constraint. Name:"
<< constraint_name << " Value:" << constraint_value;
return false;
} }
if (constraint_name == MediaStreamVideoSource::kMinWidth) { DCHECK(!failing_constraint_name->empty());
return (value <= format->frame_size.width());
} else if (constraint_name == MediaStreamVideoSource::kMaxWidth) {
return value > 0.0;
} else if (constraint_name == MediaStreamVideoSource::kMinHeight) {
return (value <= format->frame_size.height());
} else if (constraint_name == MediaStreamVideoSource::kMaxHeight) {
return value > 0.0;
} else if (constraint_name == MediaStreamVideoSource::kMinFrameRate) {
return (value > 0.0) && (value <= format->frame_rate);
} else if (constraint_name == MediaStreamVideoSource::kMaxFrameRate) {
if (value <= 0.0) {
// The frame rate is set by constraint.
// Don't allow 0 as frame rate if it is a mandatory constraint.
// Set the frame rate to 1 if it is not mandatory.
if (mandatory) {
return false; return false;
} else {
value = 1.0;
}
}
format->frame_rate =
(format->frame_rate > value) ? value : format->frame_rate;
return true;
} else {
LOG(WARNING) << "Found unknown MediaStream constraint. Name:"
<< constraint_name << " Value:" << constraint_value;
return false;
}
} }
// Removes media::VideoCaptureFormats from |formats| that don't meet // Removes media::VideoCaptureFormats from |formats| that don't meet
// |constraint|. // |constraints|.
void FilterFormatsByConstraint(const blink::WebMediaConstraint& constraint, void FilterFormatsByConstraints(
bool mandatory, const blink::WebMediaTrackConstraintSet& constraints,
media::VideoCaptureFormats* formats) { media::VideoCaptureFormats* formats,
DVLOG(3) << "FilterFormatsByConstraint(" std::string* failing_constraint_name) {
<< "{ constraint.m_name = " << constraint.m_name.utf8()
<< " constraint.m_value = " << constraint.m_value.utf8()
<< " mandatory = " << mandatory << "})";
media::VideoCaptureFormats::iterator format_it = formats->begin(); media::VideoCaptureFormats::iterator format_it = formats->begin();
while (format_it != formats->end()) { while (format_it != formats->end()) {
// Modify the format_it to fulfill the constraint if possible. // Modify |format_it| to fulfill the constraint if possible.
// Delete it otherwise. // Delete it otherwise.
if (!UpdateFormatForConstraint(constraint, mandatory, &(*format_it))) if (!UpdateFormatForConstraints(constraints, &(*format_it),
failing_constraint_name)) {
format_it = formats->erase(format_it); format_it = formats->erase(format_it);
else } else {
++format_it; ++format_it;
} }
}
} }
// Returns the media::VideoCaptureFormats that matches |constraints|. // Returns the media::VideoCaptureFormats that matches |constraints|.
// If the return value is empty, and the reason is a specific constraint,
// |unsatisfied_constraint| returns the name of the constraint.
media::VideoCaptureFormats FilterFormats( media::VideoCaptureFormats FilterFormats(
const blink::WebMediaConstraints& constraints, const blink::WebMediaConstraints& constraints,
const media::VideoCaptureFormats& supported_formats, const media::VideoCaptureFormats& supported_formats,
blink::WebString* unsatisfied_constraint) { std::string* unsatisfied_constraint) {
if (constraints.isNull()) if (constraints.isNull())
return supported_formats; return supported_formats;
const auto& basic = constraints.basic();
// Do some checks that won't be done when filtering candidates.
if (basic.width.hasMin() && basic.width.hasMax() &&
basic.width.min() > basic.width.max()) {
*unsatisfied_constraint = basic.width.name();
return media::VideoCaptureFormats();
}
if (basic.height.hasMin() && basic.height.hasMax() &&
basic.height.min() > basic.height.max()) {
*unsatisfied_constraint = basic.height.name();
return media::VideoCaptureFormats();
}
double max_aspect_ratio; double max_aspect_ratio;
double min_aspect_ratio; double min_aspect_ratio;
GetDesiredMinAndMaxAspectRatio(constraints, GetDesiredMinAndMaxAspectRatio(constraints,
...@@ -224,64 +211,39 @@ media::VideoCaptureFormats FilterFormats( ...@@ -224,64 +211,39 @@ media::VideoCaptureFormats FilterFormats(
&max_aspect_ratio); &max_aspect_ratio);
if (min_aspect_ratio > max_aspect_ratio || max_aspect_ratio < 0.05f) { if (min_aspect_ratio > max_aspect_ratio || max_aspect_ratio < 0.05f) {
DLOG(WARNING) << "Wrong requested aspect ratio."; DLOG(WARNING) << "Wrong requested aspect ratio: min " << min_aspect_ratio
<< " max " << max_aspect_ratio;
*unsatisfied_constraint = basic.aspectRatio.name();
return media::VideoCaptureFormats(); return media::VideoCaptureFormats();
} }
int min_width = 0; std::vector<std::string> temp(
GetMandatoryConstraintValueAsInteger(constraints, &kLegalVideoConstraints[0],
MediaStreamVideoSource::kMinWidth, &kLegalVideoConstraints[sizeof(kLegalVideoConstraints) /
&min_width); sizeof(kLegalVideoConstraints[0])]);
int min_height = 0; std::string failing_name;
GetMandatoryConstraintValueAsInteger(constraints, if (basic.hasMandatoryOutsideSet(temp, failing_name)) {
MediaStreamVideoSource::kMinHeight, *unsatisfied_constraint = failing_name;
&min_height);
int max_width;
int max_height;
GetDesiredMaxWidthAndHeight(constraints, &max_width, &max_height);
if (min_width > max_width || min_height > max_height)
return media::VideoCaptureFormats();
double min_frame_rate = 0.0f;
double max_frame_rate = 0.0f;
if (GetConstraintValueAsDouble(constraints,
MediaStreamVideoSource::kMaxFrameRate,
&max_frame_rate) &&
GetConstraintValueAsDouble(constraints,
MediaStreamVideoSource::kMinFrameRate,
&min_frame_rate)) {
if (min_frame_rate > max_frame_rate) {
DLOG(WARNING) << "Wrong requested frame rate.";
return media::VideoCaptureFormats(); return media::VideoCaptureFormats();
} }
}
blink::WebVector<blink::WebMediaConstraint> mandatory;
blink::WebVector<blink::WebMediaConstraint> optional;
constraints.getMandatoryConstraints(mandatory);
constraints.getOptionalConstraints(optional);
media::VideoCaptureFormats candidates = supported_formats; media::VideoCaptureFormats candidates = supported_formats;
for (const auto& constraint : mandatory) { FilterFormatsByConstraints(basic, &candidates, unsatisfied_constraint);
FilterFormatsByConstraint(constraint, true, &candidates);
if (candidates.empty()) {
*unsatisfied_constraint = constraint.m_name;
return candidates;
}
}
if (candidates.empty()) if (candidates.empty())
return candidates; return candidates;
// Ok - all mandatory checked and we still have candidates. // Ok - all mandatory checked and we still have candidates.
// Let's try filtering using the optional constraints. The optional // Let's try filtering using the advanced constraints. The advanced
// constraints must be filtered in the order they occur in |optional|. // constraints must be filtered in the order they occur in |advanced|.
// But if a constraint produce zero candidates, the constraint is ignored and // But if a constraint produce zero candidates, the constraint is ignored and
// the next constraint is tested. // the next constraint is tested.
// http://dev.w3.org/2011/webrtc/editor/getusermedia.html#idl-def-Constraints // http://w3c.github.io/mediacapture-main/getusermedia.html#dfn-selectsettings
for (const auto& constraint : optional) { for (const auto& constraint_set : constraints.advanced()) {
media::VideoCaptureFormats current_candidates = candidates; media::VideoCaptureFormats current_candidates = candidates;
FilterFormatsByConstraint(constraint, false, &current_candidates); std::string unsatisfied_constraint;
FilterFormatsByConstraints(constraint_set, &current_candidates,
&unsatisfied_constraint);
if (!current_candidates.empty()) if (!current_candidates.empty())
candidates = current_candidates; candidates = current_candidates;
} }
...@@ -303,6 +265,8 @@ media::VideoCaptureFormat GetBestFormatBasedOnArea( ...@@ -303,6 +265,8 @@ media::VideoCaptureFormat GetBestFormatBasedOnArea(
best_format = &format; best_format = &format;
} }
} }
DVLOG(3) << "GetBestFormatBasedOnArea chose format "
<< media::VideoCaptureFormat::ToString(*best_format);
return *best_format; return *best_format;
} }
...@@ -337,7 +301,7 @@ MediaStreamVideoSource* MediaStreamVideoSource::GetVideoSource( ...@@ -337,7 +301,7 @@ MediaStreamVideoSource* MediaStreamVideoSource::GetVideoSource(
return static_cast<MediaStreamVideoSource*>(source.extraData()); return static_cast<MediaStreamVideoSource*>(source.extraData());
} }
// static // static, deprecated
bool MediaStreamVideoSource::IsConstraintSupported(const std::string& name) { bool MediaStreamVideoSource::IsConstraintSupported(const std::string& name) {
return std::find(kSupportedConstraints, return std::find(kSupportedConstraints,
kSupportedConstraints + arraysize(kSupportedConstraints), kSupportedConstraints + arraysize(kSupportedConstraints),
...@@ -374,16 +338,16 @@ void MediaStreamVideoSource::AddTrack( ...@@ -374,16 +338,16 @@ void MediaStreamVideoSource::AddTrack(
// Tab capture and Screen capture needs the maximum requested height // Tab capture and Screen capture needs the maximum requested height
// and width to decide on the resolution. // and width to decide on the resolution.
int max_requested_width = 0; int max_requested_width = 0;
GetMandatoryConstraintValueAsInteger(constraints, kMaxWidth, if (constraints.basic().width.hasMax())
&max_requested_width); max_requested_width = constraints.basic().width.max();
int max_requested_height = 0; int max_requested_height = 0;
GetMandatoryConstraintValueAsInteger(constraints, kMaxHeight, if (constraints.basic().height.hasMax())
&max_requested_height); max_requested_height = constraints.basic().height.max();
double max_requested_frame_rate = kDefaultFrameRate; double max_requested_frame_rate = kDefaultFrameRate;
GetConstraintValueAsDouble(constraints, kMaxFrameRate, if (constraints.basic().frameRate.hasMax())
&max_requested_frame_rate); max_requested_frame_rate = constraints.basic().frameRate.max();
state_ = RETRIEVING_CAPABILITIES; state_ = RETRIEVING_CAPABILITIES;
GetCurrentSupportedFormats( GetCurrentSupportedFormats(
...@@ -459,6 +423,7 @@ void MediaStreamVideoSource::OnSupportedFormats( ...@@ -459,6 +423,7 @@ void MediaStreamVideoSource::OnSupportedFormats(
&current_format_, &current_format_,
&fulfilled_constraints)) { &fulfilled_constraints)) {
SetReadyState(blink::WebMediaStreamSource::ReadyStateEnded); SetReadyState(blink::WebMediaStreamSource::ReadyStateEnded);
DVLOG(3) << "OnSupportedFormats failed to find an usable format";
// This object can be deleted after calling FinalizeAddTrack. See comment // This object can be deleted after calling FinalizeAddTrack. See comment
// in the header file. // in the header file.
FinalizeAddTrack(); FinalizeAddTrack();
...@@ -480,7 +445,9 @@ bool MediaStreamVideoSource::FindBestFormatWithConstraints( ...@@ -480,7 +445,9 @@ bool MediaStreamVideoSource::FindBestFormatWithConstraints(
media::VideoCaptureFormat* best_format, media::VideoCaptureFormat* best_format,
blink::WebMediaConstraints* fulfilled_constraints) { blink::WebMediaConstraints* fulfilled_constraints) {
DCHECK(CalledOnValidThread()); DCHECK(CalledOnValidThread());
// Find the first constraints that we can fulfill. DVLOG(3) << "MediaStreamVideoSource::FindBestFormatWithConstraints "
<< "with " << formats.size() << " formats";
// Find the first track descriptor that can fulfil the constraints.
for (const auto& track : track_descriptors_) { for (const auto& track : track_descriptors_) {
const blink::WebMediaConstraints& track_constraints = track.constraints; const blink::WebMediaConstraints& track_constraints = track.constraints;
...@@ -488,11 +455,12 @@ bool MediaStreamVideoSource::FindBestFormatWithConstraints( ...@@ -488,11 +455,12 @@ bool MediaStreamVideoSource::FindBestFormatWithConstraints(
// no mandatory constraints have been specified. That just means that // no mandatory constraints have been specified. That just means that
// we will start with whatever format is native to the source. // we will start with whatever format is native to the source.
if (formats.empty() && !HasMandatoryConstraints(track_constraints)) { if (formats.empty() && !HasMandatoryConstraints(track_constraints)) {
DVLOG(3) << "No mandatory constraints and no formats";
*fulfilled_constraints = track_constraints; *fulfilled_constraints = track_constraints;
*best_format = media::VideoCaptureFormat(); *best_format = media::VideoCaptureFormat();
return true; return true;
} }
blink::WebString unsatisfied_constraint; std::string unsatisfied_constraint;
const media::VideoCaptureFormats filtered_formats = const media::VideoCaptureFormats filtered_formats =
FilterFormats(track_constraints, formats, &unsatisfied_constraint); FilterFormats(track_constraints, formats, &unsatisfied_constraint);
if (filtered_formats.empty()) if (filtered_formats.empty())
...@@ -501,8 +469,10 @@ bool MediaStreamVideoSource::FindBestFormatWithConstraints( ...@@ -501,8 +469,10 @@ bool MediaStreamVideoSource::FindBestFormatWithConstraints(
// A request with constraints that can be fulfilled. // A request with constraints that can be fulfilled.
*fulfilled_constraints = track_constraints; *fulfilled_constraints = track_constraints;
*best_format = GetBestCaptureFormat(filtered_formats, track_constraints); *best_format = GetBestCaptureFormat(filtered_formats, track_constraints);
DVLOG(3) << "Found a track that matches the constraints";
return true; return true;
} }
DVLOG(3) << "No usable format found";
return false; return false;
} }
...@@ -536,12 +506,14 @@ void MediaStreamVideoSource::FinalizeAddTrack() { ...@@ -536,12 +506,14 @@ void MediaStreamVideoSource::FinalizeAddTrack() {
track_descriptors.swap(track_descriptors_); track_descriptors.swap(track_descriptors_);
for (const auto& track : track_descriptors) { for (const auto& track : track_descriptors) {
MediaStreamRequestResult result = MEDIA_DEVICE_OK; MediaStreamRequestResult result = MEDIA_DEVICE_OK;
blink::WebString unsatisfied_constraint; std::string unsatisfied_constraint;
if (HasMandatoryConstraints(track.constraints) && if (HasMandatoryConstraints(track.constraints) &&
FilterFormats(track.constraints, formats, &unsatisfied_constraint) FilterFormats(track.constraints, formats, &unsatisfied_constraint)
.empty()) { .empty()) {
result = MEDIA_DEVICE_CONSTRAINT_NOT_SATISFIED; result = MEDIA_DEVICE_CONSTRAINT_NOT_SATISFIED;
DVLOG(3) << "FinalizeAddTrack() ignoring device on constraint "
<< unsatisfied_constraint;
} }
if (state_ != STARTED && result == MEDIA_DEVICE_OK) if (state_ != STARTED && result == MEDIA_DEVICE_OK)
...@@ -557,8 +529,8 @@ void MediaStreamVideoSource::FinalizeAddTrack() { ...@@ -557,8 +529,8 @@ void MediaStreamVideoSource::FinalizeAddTrack() {
&min_aspect_ratio, &min_aspect_ratio,
&max_aspect_ratio); &max_aspect_ratio);
double max_frame_rate = 0.0f; double max_frame_rate = 0.0f;
GetConstraintValueAsDouble(track.constraints, if (track.constraints.basic().frameRate.hasMax())
kMaxFrameRate, &max_frame_rate); max_frame_rate = track.constraints.basic().frameRate.max();
track_adapter_->AddTrack(track.track, track.frame_callback, max_width, track_adapter_->AddTrack(track.track, track.frame_callback, max_width,
max_height, min_aspect_ratio, max_aspect_ratio, max_height, min_aspect_ratio, max_aspect_ratio,
...@@ -568,7 +540,8 @@ void MediaStreamVideoSource::FinalizeAddTrack() { ...@@ -568,7 +540,8 @@ void MediaStreamVideoSource::FinalizeAddTrack() {
DVLOG(3) << "FinalizeAddTrack() result " << result; DVLOG(3) << "FinalizeAddTrack() result " << result;
if (!track.callback.is_null()) if (!track.callback.is_null())
track.callback.Run(this, result, unsatisfied_constraint); track.callback.Run(this, result,
blink::WebString::fromUTF8(unsatisfied_constraint));
} }
} }
......
...@@ -13,9 +13,10 @@ ...@@ -13,9 +13,10 @@
#include "content/child/child_process.h" #include "content/child/child_process.h"
#include "content/renderer/media/media_stream_video_source.h" #include "content/renderer/media/media_stream_video_source.h"
#include "content/renderer/media/media_stream_video_track.h" #include "content/renderer/media/media_stream_video_track.h"
#include "content/renderer/media/mock_media_constraint_factory.h" #include "content/renderer/media/mock_constraint_factory.h"
#include "content/renderer/media/mock_media_stream_video_sink.h" #include "content/renderer/media/mock_media_stream_video_sink.h"
#include "content/renderer/media/mock_media_stream_video_source.h" #include "content/renderer/media/mock_media_stream_video_source.h"
#include "media/base/limits.h"
#include "media/base/video_frame.h" #include "media/base/video_frame.h"
#include "testing/gtest/include/gtest/gtest.h" #include "testing/gtest/include/gtest/gtest.h"
#include "third_party/WebKit/public/web/WebHeap.h" #include "third_party/WebKit/public/web/WebHeap.h"
...@@ -296,10 +297,10 @@ TEST_F(MediaStreamVideoSourceTest, AddTwoTracksBeforeGetSupportedFormats) { ...@@ -296,10 +297,10 @@ TEST_F(MediaStreamVideoSourceTest, AddTwoTracksBeforeGetSupportedFormats) {
// Test that the capture output is CIF if we set max constraints to CIF. // Test that the capture output is CIF if we set max constraints to CIF.
// and the capture device support CIF. // and the capture device support CIF.
TEST_F(MediaStreamVideoSourceTest, MandatoryConstraintCif5Fps) { TEST_F(MediaStreamVideoSourceTest, MandatoryConstraintCif5Fps) {
MockMediaConstraintFactory factory; MockConstraintFactory factory;
factory.AddMandatory(MediaStreamVideoSource::kMaxWidth, 352); factory.basic().width.setMax(352);
factory.AddMandatory(MediaStreamVideoSource::kMaxHeight, 288); factory.basic().height.setMax(288);
factory.AddMandatory(MediaStreamVideoSource::kMaxFrameRate, 5); factory.basic().frameRate.setMax(5.0);
CreateTrackAndStartSource(factory.CreateWebMediaConstraints(), 352, 288, 5); CreateTrackAndStartSource(factory.CreateWebMediaConstraints(), 352, 288, 5);
} }
...@@ -307,11 +308,11 @@ TEST_F(MediaStreamVideoSourceTest, MandatoryConstraintCif5Fps) { ...@@ -307,11 +308,11 @@ TEST_F(MediaStreamVideoSourceTest, MandatoryConstraintCif5Fps) {
// Test that the capture output is 720P if the camera support it and the // Test that the capture output is 720P if the camera support it and the
// optional constraint is set to 720P. // optional constraint is set to 720P.
TEST_F(MediaStreamVideoSourceTest, MandatoryMinVgaOptional720P) { TEST_F(MediaStreamVideoSourceTest, MandatoryMinVgaOptional720P) {
MockMediaConstraintFactory factory; MockConstraintFactory factory;
factory.AddMandatory(MediaStreamVideoSource::kMinWidth, 640); factory.basic().width.setMin(640);
factory.AddMandatory(MediaStreamVideoSource::kMinHeight, 480); factory.basic().height.setMin(480);
factory.AddOptional(MediaStreamVideoSource::kMinWidth, 1280); factory.AddAdvanced().width.setMin(1280);
factory.AddOptional(MediaStreamVideoSource::kMinAspectRatio, 1280.0 / 720); factory.AddAdvanced().aspectRatio.setMin(1280.0 / 720);
CreateTrackAndStartSource(factory.CreateWebMediaConstraints(), 1280, 720, 30); CreateTrackAndStartSource(factory.CreateWebMediaConstraints(), 1280, 720, 30);
} }
...@@ -320,11 +321,11 @@ TEST_F(MediaStreamVideoSourceTest, MandatoryMinVgaOptional720P) { ...@@ -320,11 +321,11 @@ TEST_F(MediaStreamVideoSourceTest, MandatoryMinVgaOptional720P) {
// require it even if an optional constraint request a higher resolution // require it even if an optional constraint request a higher resolution
// that don't have this aspect ratio. // that don't have this aspect ratio.
TEST_F(MediaStreamVideoSourceTest, MandatoryAspectRatio4To3) { TEST_F(MediaStreamVideoSourceTest, MandatoryAspectRatio4To3) {
MockMediaConstraintFactory factory; MockConstraintFactory factory;
factory.AddMandatory(MediaStreamVideoSource::kMinWidth, 640); factory.basic().width.setMin(640);
factory.AddMandatory(MediaStreamVideoSource::kMinHeight, 480); factory.basic().height.setMin(480);
factory.AddMandatory(MediaStreamVideoSource::kMaxAspectRatio, 640.0 / 480); factory.basic().aspectRatio.setMax(640.0 / 480);
factory.AddOptional(MediaStreamVideoSource::kMinWidth, 1280); factory.AddAdvanced().width.setMin(1280);
TestSourceCropFrame(1280, 720, TestSourceCropFrame(1280, 720,
factory.CreateWebMediaConstraints(), 960, 720); factory.CreateWebMediaConstraints(), 960, 720);
...@@ -332,8 +333,8 @@ TEST_F(MediaStreamVideoSourceTest, MandatoryAspectRatio4To3) { ...@@ -332,8 +333,8 @@ TEST_F(MediaStreamVideoSourceTest, MandatoryAspectRatio4To3) {
// Test that AddTrack succeeds if the mandatory min aspect ratio it set to 2. // Test that AddTrack succeeds if the mandatory min aspect ratio it set to 2.
TEST_F(MediaStreamVideoSourceTest, MandatoryAspectRatio2) { TEST_F(MediaStreamVideoSourceTest, MandatoryAspectRatio2) {
MockMediaConstraintFactory factory; MockConstraintFactory factory;
factory.AddMandatory(MediaStreamVideoSource::kMinAspectRatio, 2); factory.basic().aspectRatio.setMin(2.0);
TestSourceCropFrame(MediaStreamVideoSource::kDefaultWidth, TestSourceCropFrame(MediaStreamVideoSource::kDefaultWidth,
MediaStreamVideoSource::kDefaultHeight, MediaStreamVideoSource::kDefaultHeight,
...@@ -341,18 +342,9 @@ TEST_F(MediaStreamVideoSourceTest, MandatoryAspectRatio2) { ...@@ -341,18 +342,9 @@ TEST_F(MediaStreamVideoSourceTest, MandatoryAspectRatio2) {
} }
TEST_F(MediaStreamVideoSourceTest, MinAspectRatioLargerThanMaxAspectRatio) { TEST_F(MediaStreamVideoSourceTest, MinAspectRatioLargerThanMaxAspectRatio) {
MockMediaConstraintFactory factory; MockConstraintFactory factory;
factory.AddMandatory(MediaStreamVideoSource::kMinAspectRatio, 2); factory.basic().aspectRatio.setMin(2.0);
factory.AddMandatory(MediaStreamVideoSource::kMaxAspectRatio, 1); factory.basic().aspectRatio.setMax(1.0);
blink::WebMediaStreamTrack track = CreateTrack(
"123", factory.CreateWebMediaConstraints());
mock_source()->CompleteGetSupportedFormats();
EXPECT_EQ(1, NumberOfFailedConstraintsCallbacks());
}
TEST_F(MediaStreamVideoSourceTest, MaxAspectRatioZero) {
MockMediaConstraintFactory factory;
factory.AddOptional(MediaStreamVideoSource::kMaxAspectRatio, 0);
blink::WebMediaStreamTrack track = CreateTrack( blink::WebMediaStreamTrack track = CreateTrack(
"123", factory.CreateWebMediaConstraints()); "123", factory.CreateWebMediaConstraints());
mock_source()->CompleteGetSupportedFormats(); mock_source()->CompleteGetSupportedFormats();
...@@ -360,9 +352,9 @@ TEST_F(MediaStreamVideoSourceTest, MaxAspectRatioZero) { ...@@ -360,9 +352,9 @@ TEST_F(MediaStreamVideoSourceTest, MaxAspectRatioZero) {
} }
TEST_F(MediaStreamVideoSourceTest, MinWidthLargerThanMaxWidth) { TEST_F(MediaStreamVideoSourceTest, MinWidthLargerThanMaxWidth) {
MockMediaConstraintFactory factory; MockConstraintFactory factory;
factory.AddMandatory(MediaStreamVideoSource::kMinWidth, 640); factory.basic().width.setMin(640);
factory.AddMandatory(MediaStreamVideoSource::kMaxWidth, 320); factory.basic().width.setMax(320);
blink::WebMediaStreamTrack track = CreateTrack( blink::WebMediaStreamTrack track = CreateTrack(
"123", factory.CreateWebMediaConstraints()); "123", factory.CreateWebMediaConstraints());
mock_source()->CompleteGetSupportedFormats(); mock_source()->CompleteGetSupportedFormats();
...@@ -370,9 +362,10 @@ TEST_F(MediaStreamVideoSourceTest, MinWidthLargerThanMaxWidth) { ...@@ -370,9 +362,10 @@ TEST_F(MediaStreamVideoSourceTest, MinWidthLargerThanMaxWidth) {
} }
TEST_F(MediaStreamVideoSourceTest, MinHeightLargerThanMaxHeight) { TEST_F(MediaStreamVideoSourceTest, MinHeightLargerThanMaxHeight) {
MockMediaConstraintFactory factory; MockConstraintFactory factory;
factory.AddMandatory(MediaStreamVideoSource::kMinHeight, 480); factory.basic().height.setMin(480);
factory.AddMandatory(MediaStreamVideoSource::kMaxHeight, 360); factory.basic().height.setMax(360);
blink::WebMediaStreamTrack track = CreateTrack( blink::WebMediaStreamTrack track = CreateTrack(
"123", factory.CreateWebMediaConstraints()); "123", factory.CreateWebMediaConstraints());
mock_source()->CompleteGetSupportedFormats(); mock_source()->CompleteGetSupportedFormats();
...@@ -380,9 +373,9 @@ TEST_F(MediaStreamVideoSourceTest, MinHeightLargerThanMaxHeight) { ...@@ -380,9 +373,9 @@ TEST_F(MediaStreamVideoSourceTest, MinHeightLargerThanMaxHeight) {
} }
TEST_F(MediaStreamVideoSourceTest, MinFrameRateLargerThanMaxFrameRate) { TEST_F(MediaStreamVideoSourceTest, MinFrameRateLargerThanMaxFrameRate) {
MockMediaConstraintFactory factory; MockConstraintFactory factory;
factory.AddMandatory(MediaStreamVideoSource::kMinFrameRate, 25); factory.basic().frameRate.setMin(25);
factory.AddMandatory(MediaStreamVideoSource::kMaxFrameRate, 15); factory.basic().frameRate.setMax(15);
blink::WebMediaStreamTrack track = CreateTrack( blink::WebMediaStreamTrack track = CreateTrack(
"123", factory.CreateWebMediaConstraints()); "123", factory.CreateWebMediaConstraints());
mock_source()->CompleteGetSupportedFormats(); mock_source()->CompleteGetSupportedFormats();
...@@ -392,7 +385,7 @@ TEST_F(MediaStreamVideoSourceTest, MinFrameRateLargerThanMaxFrameRate) { ...@@ -392,7 +385,7 @@ TEST_F(MediaStreamVideoSourceTest, MinFrameRateLargerThanMaxFrameRate) {
// Test that its safe to release the last reference of a blink track and the // Test that its safe to release the last reference of a blink track and the
// source during the callback if adding a track succeeds. // source during the callback if adding a track succeeds.
TEST_F(MediaStreamVideoSourceTest, ReleaseTrackAndSourceOnSuccessCallBack) { TEST_F(MediaStreamVideoSourceTest, ReleaseTrackAndSourceOnSuccessCallBack) {
MockMediaConstraintFactory factory; MockConstraintFactory factory;
{ {
blink::WebMediaStreamTrack track = blink::WebMediaStreamTrack track =
CreateTrack("123", factory.CreateWebMediaConstraints()); CreateTrack("123", factory.CreateWebMediaConstraints());
...@@ -406,8 +399,8 @@ TEST_F(MediaStreamVideoSourceTest, ReleaseTrackAndSourceOnSuccessCallBack) { ...@@ -406,8 +399,8 @@ TEST_F(MediaStreamVideoSourceTest, ReleaseTrackAndSourceOnSuccessCallBack) {
// Test that its safe to release the last reference of a blink track and the // Test that its safe to release the last reference of a blink track and the
// source during the callback if adding a track fails. // source during the callback if adding a track fails.
TEST_F(MediaStreamVideoSourceTest, ReleaseTrackAndSourceOnFailureCallBack) { TEST_F(MediaStreamVideoSourceTest, ReleaseTrackAndSourceOnFailureCallBack) {
MockMediaConstraintFactory factory; MockConstraintFactory factory;
factory.AddMandatory(MediaStreamVideoSource::kMinWidth, 99999); factory.basic().width.setMin(99999);
{ {
blink::WebMediaStreamTrack track = blink::WebMediaStreamTrack track =
CreateTrack("123", factory.CreateWebMediaConstraints()); CreateTrack("123", factory.CreateWebMediaConstraints());
...@@ -420,8 +413,8 @@ TEST_F(MediaStreamVideoSourceTest, ReleaseTrackAndSourceOnFailureCallBack) { ...@@ -420,8 +413,8 @@ TEST_F(MediaStreamVideoSourceTest, ReleaseTrackAndSourceOnFailureCallBack) {
// Test that the source ignores an optional aspect ratio that is higher than // Test that the source ignores an optional aspect ratio that is higher than
// supported. // supported.
TEST_F(MediaStreamVideoSourceTest, OptionalAspectRatioTooHigh) { TEST_F(MediaStreamVideoSourceTest, OptionalAspectRatioTooHigh) {
MockMediaConstraintFactory factory; MockConstraintFactory factory;
factory.AddOptional(MediaStreamVideoSource::kMinAspectRatio, 2); factory.AddAdvanced().aspectRatio.setMin(2.0);
blink::WebMediaStreamTrack track = CreateTrack( blink::WebMediaStreamTrack track = CreateTrack(
"123", factory.CreateWebMediaConstraints()); "123", factory.CreateWebMediaConstraints());
mock_source()->CompleteGetSupportedFormats(); mock_source()->CompleteGetSupportedFormats();
...@@ -452,20 +445,21 @@ TEST_F(MediaStreamVideoSourceTest, DefaultCapability) { ...@@ -452,20 +445,21 @@ TEST_F(MediaStreamVideoSourceTest, DefaultCapability) {
} }
TEST_F(MediaStreamVideoSourceTest, InvalidMandatoryConstraint) { TEST_F(MediaStreamVideoSourceTest, InvalidMandatoryConstraint) {
MockMediaConstraintFactory factory; MockConstraintFactory factory;
factory.AddMandatory("weird key", 640); // Use a constraint that is only known for audio.
factory.basic().echoCancellation.setExact(true);
blink::WebMediaStreamTrack track = CreateTrack( blink::WebMediaStreamTrack track = CreateTrack(
"123", factory.CreateWebMediaConstraints()); "123", factory.CreateWebMediaConstraints());
mock_source()->CompleteGetSupportedFormats(); mock_source()->CompleteGetSupportedFormats();
EXPECT_EQ(MEDIA_DEVICE_CONSTRAINT_NOT_SATISFIED, error_type()); EXPECT_EQ(MEDIA_DEVICE_CONSTRAINT_NOT_SATISFIED, error_type());
EXPECT_EQ("weird key", error_name()); EXPECT_EQ("echoCancellation", error_name());
EXPECT_EQ(1, NumberOfFailedConstraintsCallbacks()); EXPECT_EQ(1, NumberOfFailedConstraintsCallbacks());
} }
// Test that the source ignores an unknown optional constraint. // Test that the source ignores an unknown optional constraint.
TEST_F(MediaStreamVideoSourceTest, InvalidOptionalConstraint) { TEST_F(MediaStreamVideoSourceTest, InvalidOptionalConstraint) {
MockMediaConstraintFactory factory; MockConstraintFactory factory;
factory.AddOptional("weird key", 640); factory.AddAdvanced().echoCancellation.setExact(true);
CreateTrackAndStartSource(factory.CreateWebMediaConstraints(), CreateTrackAndStartSource(factory.CreateWebMediaConstraints(),
MediaStreamVideoSource::kDefaultWidth, MediaStreamVideoSource::kDefaultWidth,
...@@ -480,9 +474,9 @@ TEST_F(MediaStreamVideoSourceTest, ScreencastResolutionWithConstraint) { ...@@ -480,9 +474,9 @@ TEST_F(MediaStreamVideoSourceTest, ScreencastResolutionWithConstraint) {
formats.push_back(media::VideoCaptureFormat( formats.push_back(media::VideoCaptureFormat(
gfx::Size(480, 270), 30, media::PIXEL_FORMAT_I420)); gfx::Size(480, 270), 30, media::PIXEL_FORMAT_I420));
mock_source()->SetSupportedFormats(formats); mock_source()->SetSupportedFormats(formats);
MockMediaConstraintFactory factory; MockConstraintFactory factory;
factory.AddMandatory(MediaStreamVideoSource::kMaxWidth, 480); factory.basic().width.setMax(480);
factory.AddMandatory(MediaStreamVideoSource::kMaxHeight, 270); factory.basic().height.setMax(270);
blink::WebMediaStreamTrack track = CreateTrackAndStartSource( blink::WebMediaStreamTrack track = CreateTrackAndStartSource(
factory.CreateWebMediaConstraints(), 480, 270, 30); factory.CreateWebMediaConstraints(), 480, 270, 30);
...@@ -492,75 +486,75 @@ TEST_F(MediaStreamVideoSourceTest, ScreencastResolutionWithConstraint) { ...@@ -492,75 +486,75 @@ TEST_F(MediaStreamVideoSourceTest, ScreencastResolutionWithConstraint) {
// Test that optional constraints are applied in order. // Test that optional constraints are applied in order.
TEST_F(MediaStreamVideoSourceTest, OptionalConstraints) { TEST_F(MediaStreamVideoSourceTest, OptionalConstraints) {
MockMediaConstraintFactory factory; MockConstraintFactory factory;
// Min width of 2056 pixels can not be fulfilled. // Min width of 2056 pixels can not be fulfilled.
factory.AddOptional(MediaStreamVideoSource::kMinWidth, 2056); factory.AddAdvanced().width.setMin(2056);
factory.AddOptional(MediaStreamVideoSource::kMinWidth, 641); factory.AddAdvanced().width.setMin(641);
// Since min width is set to 641 pixels, max width 640 can not be fulfilled. // Since min width is set to 641 pixels, max width 640 can not be fulfilled.
factory.AddOptional(MediaStreamVideoSource::kMaxWidth, 640); factory.AddAdvanced().width.setMax(640);
CreateTrackAndStartSource(factory.CreateWebMediaConstraints(), 1280, 720, 30); CreateTrackAndStartSource(factory.CreateWebMediaConstraints(), 1280, 720, 30);
} }
// Test that the source crops to the requested max width and // Test that the source crops to the requested max width and
// height even though the camera delivers a larger frame. // height even though the camera delivers a larger frame.
TEST_F(MediaStreamVideoSourceTest, DeliverCroppedVideoFrameOptional640360) { TEST_F(MediaStreamVideoSourceTest, DeliverCroppedVideoFrameOptional640360) {
MockMediaConstraintFactory factory; MockConstraintFactory factory;
factory.AddOptional(MediaStreamVideoSource::kMaxWidth, 640); factory.AddAdvanced().width.setMax(640);
factory.AddOptional(MediaStreamVideoSource::kMaxHeight, 360); factory.AddAdvanced().height.setMax(360);
TestSourceCropFrame(640, 480, factory.CreateWebMediaConstraints(), 640, 360); TestSourceCropFrame(640, 480, factory.CreateWebMediaConstraints(), 640, 360);
} }
TEST_F(MediaStreamVideoSourceTest, DeliverCroppedVideoFrameMandatory640360) { TEST_F(MediaStreamVideoSourceTest, DeliverCroppedVideoFrameMandatory640360) {
MockMediaConstraintFactory factory; MockConstraintFactory factory;
factory.AddMandatory(MediaStreamVideoSource::kMaxWidth, 640); factory.basic().width.setMax(640);
factory.AddMandatory(MediaStreamVideoSource::kMaxHeight, 360); factory.basic().height.setMax(360);
TestSourceCropFrame(640, 480, factory.CreateWebMediaConstraints(), 640, 360); TestSourceCropFrame(640, 480, factory.CreateWebMediaConstraints(), 640, 360);
} }
TEST_F(MediaStreamVideoSourceTest, DeliverCroppedVideoFrameMandatory732489) { TEST_F(MediaStreamVideoSourceTest, DeliverCroppedVideoFrameMandatory732489) {
MockMediaConstraintFactory factory; MockConstraintFactory factory;
factory.AddMandatory(MediaStreamVideoSource::kMaxWidth, 732); factory.basic().width.setMax(732);
factory.AddMandatory(MediaStreamVideoSource::kMaxHeight, 489); factory.basic().height.setMax(489);
factory.AddMandatory(MediaStreamVideoSource::kMinWidth, 732); factory.basic().width.setMin(732);
factory.AddMandatory(MediaStreamVideoSource::kMinWidth, 489); factory.basic().height.setMin(489);
TestSourceCropFrame(1280, 720, factory.CreateWebMediaConstraints(), 732, 489); TestSourceCropFrame(1280, 720, factory.CreateWebMediaConstraints(), 732, 489);
} }
// Test that the source crops to the requested max width and // Test that the source crops to the requested max width and
// height even though the requested frame has odd size. // height even though the requested frame has odd size.
TEST_F(MediaStreamVideoSourceTest, DeliverCroppedVideoFrame637359) { TEST_F(MediaStreamVideoSourceTest, DeliverCroppedVideoFrame637359) {
MockMediaConstraintFactory factory; MockConstraintFactory factory;
factory.AddOptional(MediaStreamVideoSource::kMaxWidth, 637); factory.AddAdvanced().width.setMax(637);
factory.AddOptional(MediaStreamVideoSource::kMaxHeight, 359); factory.AddAdvanced().height.setMax(359);
TestSourceCropFrame(640, 480, factory.CreateWebMediaConstraints(), 637, 359); TestSourceCropFrame(640, 480, factory.CreateWebMediaConstraints(), 637, 359);
} }
TEST_F(MediaStreamVideoSourceTest, DeliverCroppedVideoFrame320320) { TEST_F(MediaStreamVideoSourceTest, DeliverCroppedVideoFrame320320) {
MockMediaConstraintFactory factory; MockConstraintFactory factory;
factory.AddMandatory(MediaStreamVideoSource::kMaxWidth, 320); factory.basic().width.setMax(320);
factory.AddMandatory(MediaStreamVideoSource::kMaxHeight, 320); factory.basic().height.setMax(320);
factory.AddMandatory(MediaStreamVideoSource::kMinHeight, 320); factory.basic().height.setMin(320);
factory.AddMandatory(MediaStreamVideoSource::kMinWidth, 320); factory.basic().width.setMax(320);
TestSourceCropFrame(640, 480, factory.CreateWebMediaConstraints(), 320, 320); TestSourceCropFrame(640, 480, factory.CreateWebMediaConstraints(), 320, 320);
} }
TEST_F(MediaStreamVideoSourceTest, DeliverSmallerSizeWhenTooLargeMax) { TEST_F(MediaStreamVideoSourceTest, DeliverSmallerSizeWhenTooLargeMax) {
MockMediaConstraintFactory factory; MockConstraintFactory factory;
factory.AddOptional(MediaStreamVideoSource::kMaxWidth, 1920); factory.AddAdvanced().width.setMax(1920);
factory.AddOptional(MediaStreamVideoSource::kMaxHeight, 1080); factory.AddAdvanced().height.setMax(1080);
factory.AddOptional(MediaStreamVideoSource::kMinWidth, 1280); factory.AddAdvanced().width.setMin(1280);
factory.AddOptional(MediaStreamVideoSource::kMinHeight, 720); factory.AddAdvanced().height.setMin(720);
TestSourceCropFrame(1280, 720, factory.CreateWebMediaConstraints(), TestSourceCropFrame(1280, 720, factory.CreateWebMediaConstraints(),
1280, 720); 1280, 720);
} }
TEST_F(MediaStreamVideoSourceTest, TwoTracksWithVGAAndWVGA) { TEST_F(MediaStreamVideoSourceTest, TwoTracksWithVGAAndWVGA) {
MockMediaConstraintFactory factory1; MockConstraintFactory factory1;
factory1.AddOptional(MediaStreamVideoSource::kMaxWidth, 640); factory1.AddAdvanced().width.setMax(640);
factory1.AddOptional(MediaStreamVideoSource::kMaxHeight, 480); factory1.AddAdvanced().height.setMax(480);
MockMediaConstraintFactory factory2; MockConstraintFactory factory2;
factory2.AddOptional(MediaStreamVideoSource::kMaxHeight, 360); factory2.AddAdvanced().height.setMax(360);
TestTwoTracksWithDifferentConstraints(factory1.CreateWebMediaConstraints(), TestTwoTracksWithDifferentConstraints(factory1.CreateWebMediaConstraints(),
factory2.CreateWebMediaConstraints(), factory2.CreateWebMediaConstraints(),
...@@ -570,14 +564,13 @@ TEST_F(MediaStreamVideoSourceTest, TwoTracksWithVGAAndWVGA) { ...@@ -570,14 +564,13 @@ TEST_F(MediaStreamVideoSourceTest, TwoTracksWithVGAAndWVGA) {
} }
TEST_F(MediaStreamVideoSourceTest, TwoTracksWith720AndWVGA) { TEST_F(MediaStreamVideoSourceTest, TwoTracksWith720AndWVGA) {
MockMediaConstraintFactory factory1; MockConstraintFactory factory1;
factory1.AddOptional(MediaStreamVideoSource::kMinWidth, 1280); factory1.AddAdvanced().width.setMin(1280);
factory1.AddOptional(MediaStreamVideoSource::kMinHeight, 720); factory1.AddAdvanced().height.setMin(720);
MockMediaConstraintFactory factory2; MockConstraintFactory factory2;
factory2.AddMandatory(MediaStreamVideoSource::kMaxWidth, 640); factory2.basic().width.setMax(640);
factory2.AddMandatory(MediaStreamVideoSource::kMaxHeight, 360); factory2.basic().height.setMax(360);
TestTwoTracksWithDifferentConstraints(factory1.CreateWebMediaConstraints(), TestTwoTracksWithDifferentConstraints(factory1.CreateWebMediaConstraints(),
factory2.CreateWebMediaConstraints(), factory2.CreateWebMediaConstraints(),
...@@ -587,13 +580,13 @@ TEST_F(MediaStreamVideoSourceTest, TwoTracksWith720AndWVGA) { ...@@ -587,13 +580,13 @@ TEST_F(MediaStreamVideoSourceTest, TwoTracksWith720AndWVGA) {
} }
TEST_F(MediaStreamVideoSourceTest, TwoTracksWith720AndW700H700) { TEST_F(MediaStreamVideoSourceTest, TwoTracksWith720AndW700H700) {
MockMediaConstraintFactory factory1; MockConstraintFactory factory1;
factory1.AddOptional(MediaStreamVideoSource::kMinWidth, 1280); factory1.AddAdvanced().width.setMin(1280);
factory1.AddOptional(MediaStreamVideoSource::kMinHeight, 720); factory1.AddAdvanced().height.setMin(720);
MockMediaConstraintFactory factory2; MockConstraintFactory factory2;
factory2.AddMandatory(MediaStreamVideoSource::kMaxWidth, 700); factory2.basic().width.setMax(700);
factory2.AddMandatory(MediaStreamVideoSource::kMaxHeight, 700); factory2.basic().height.setMax(700);
TestTwoTracksWithDifferentConstraints(factory1.CreateWebMediaConstraints(), TestTwoTracksWithDifferentConstraints(factory1.CreateWebMediaConstraints(),
factory2.CreateWebMediaConstraints(), factory2.CreateWebMediaConstraints(),
...@@ -603,12 +596,12 @@ TEST_F(MediaStreamVideoSourceTest, TwoTracksWith720AndW700H700) { ...@@ -603,12 +596,12 @@ TEST_F(MediaStreamVideoSourceTest, TwoTracksWith720AndW700H700) {
} }
TEST_F(MediaStreamVideoSourceTest, TwoTracksWith720AndMaxAspectRatio4To3) { TEST_F(MediaStreamVideoSourceTest, TwoTracksWith720AndMaxAspectRatio4To3) {
MockMediaConstraintFactory factory1; MockConstraintFactory factory1;
factory1.AddOptional(MediaStreamVideoSource::kMinWidth, 1280); factory1.AddAdvanced().width.setMin(1280);
factory1.AddOptional(MediaStreamVideoSource::kMinHeight, 720); factory1.AddAdvanced().height.setMin(720);
MockMediaConstraintFactory factory2; MockConstraintFactory factory2;
factory2.AddMandatory(MediaStreamVideoSource::kMaxAspectRatio, 640.0 / 480); factory2.basic().aspectRatio.setMax(640.0 / 480);
TestTwoTracksWithDifferentConstraints(factory1.CreateWebMediaConstraints(), TestTwoTracksWithDifferentConstraints(factory1.CreateWebMediaConstraints(),
factory2.CreateWebMediaConstraints(), factory2.CreateWebMediaConstraints(),
...@@ -618,12 +611,12 @@ TEST_F(MediaStreamVideoSourceTest, TwoTracksWith720AndMaxAspectRatio4To3) { ...@@ -618,12 +611,12 @@ TEST_F(MediaStreamVideoSourceTest, TwoTracksWith720AndMaxAspectRatio4To3) {
} }
TEST_F(MediaStreamVideoSourceTest, TwoTracksWithVgaAndMinAspectRatio) { TEST_F(MediaStreamVideoSourceTest, TwoTracksWithVgaAndMinAspectRatio) {
MockMediaConstraintFactory factory1; MockConstraintFactory factory1;
factory1.AddOptional(MediaStreamVideoSource::kMaxWidth, 640); factory1.AddAdvanced().width.setMax(640);
factory1.AddOptional(MediaStreamVideoSource::kMaxHeight, 480); factory1.AddAdvanced().height.setMax(480);
MockMediaConstraintFactory factory2; MockConstraintFactory factory2;
factory2.AddMandatory(MediaStreamVideoSource::kMinAspectRatio, 640.0 / 360); factory2.basic().aspectRatio.setMin(640.0 / 360);
TestTwoTracksWithDifferentConstraints(factory1.CreateWebMediaConstraints(), TestTwoTracksWithDifferentConstraints(factory1.CreateWebMediaConstraints(),
factory2.CreateWebMediaConstraints(), factory2.CreateWebMediaConstraints(),
...@@ -634,9 +627,9 @@ TEST_F(MediaStreamVideoSourceTest, TwoTracksWithVgaAndMinAspectRatio) { ...@@ -634,9 +627,9 @@ TEST_F(MediaStreamVideoSourceTest, TwoTracksWithVgaAndMinAspectRatio) {
TEST_F(MediaStreamVideoSourceTest, TEST_F(MediaStreamVideoSourceTest,
TwoTracksWithSecondTrackFrameRateHigherThanFirst) { TwoTracksWithSecondTrackFrameRateHigherThanFirst) {
MockMediaConstraintFactory factory1; MockConstraintFactory factory1;
factory1.AddMandatory(MediaStreamVideoSource::kMinFrameRate, 15); factory1.basic().frameRate.setMin(15);
factory1.AddMandatory(MediaStreamVideoSource::kMaxFrameRate, 15); factory1.basic().frameRate.setMax(15);
blink::WebMediaStreamTrack track1 = blink::WebMediaStreamTrack track1 =
CreateTrackAndStartSource(factory1.CreateWebMediaConstraints(), CreateTrackAndStartSource(factory1.CreateWebMediaConstraints(),
...@@ -644,8 +637,8 @@ TEST_F(MediaStreamVideoSourceTest, ...@@ -644,8 +637,8 @@ TEST_F(MediaStreamVideoSourceTest,
MediaStreamVideoSource::kDefaultHeight, MediaStreamVideoSource::kDefaultHeight,
15); 15);
MockMediaConstraintFactory factory2; MockConstraintFactory factory2;
factory2.AddMandatory(MediaStreamVideoSource::kMinFrameRate, 30); factory2.basic().frameRate.setMin(30);
blink::WebMediaStreamTrack track2 = CreateTrack( blink::WebMediaStreamTrack track2 = CreateTrack(
"123", factory2.CreateWebMediaConstraints()); "123", factory2.CreateWebMediaConstraints());
EXPECT_EQ(1, NumberOfFailedConstraintsCallbacks()); EXPECT_EQ(1, NumberOfFailedConstraintsCallbacks());
...@@ -655,9 +648,9 @@ TEST_F(MediaStreamVideoSourceTest, ...@@ -655,9 +648,9 @@ TEST_F(MediaStreamVideoSourceTest,
// tracks sinks get the new frame size unless constraints force the frame to be // tracks sinks get the new frame size unless constraints force the frame to be
// cropped. // cropped.
TEST_F(MediaStreamVideoSourceTest, SourceChangeFrameSize) { TEST_F(MediaStreamVideoSourceTest, SourceChangeFrameSize) {
MockMediaConstraintFactory factory; MockConstraintFactory factory;
factory.AddOptional(MediaStreamVideoSource::kMaxWidth, 800); factory.AddAdvanced().width.setMax(800);
factory.AddOptional(MediaStreamVideoSource::kMaxHeight, 700); factory.AddAdvanced().height.setMax(700);
// Expect the source to start capture with the supported resolution. // Expect the source to start capture with the supported resolution.
blink::WebMediaStreamTrack track = blink::WebMediaStreamTrack track =
...@@ -746,18 +739,20 @@ TEST_F(MediaStreamVideoSourceTest, Use0FpsSupportedFormat) { ...@@ -746,18 +739,20 @@ TEST_F(MediaStreamVideoSourceTest, Use0FpsSupportedFormat) {
// Test that a source producing no frames change the source readyState to muted. // Test that a source producing no frames change the source readyState to muted.
// that in a reasonable time frame the muted state turns to false. // that in a reasonable time frame the muted state turns to false.
TEST_F(MediaStreamVideoSourceTest, MutedSource) { TEST_F(MediaStreamVideoSourceTest, MutedSource) {
// Setup the source for support a frame rate of 2000fps in order to test // Setup the source for support a frame rate of 999 fps in order to test
// the muted event faster. This is since the frame monitoring uses // the muted event faster. This is since the frame monitoring uses
// PostDelayedTask that is dependent on the source frame rate. // PostDelayedTask that is dependent on the source frame rate.
// Note that media::limits::kMaxFramesPerSecond is 1000.
media::VideoCaptureFormats formats; media::VideoCaptureFormats formats;
formats.push_back(media::VideoCaptureFormat( formats.push_back(media::VideoCaptureFormat(
gfx::Size(640, 480), 2000, media::PIXEL_FORMAT_I420)); gfx::Size(640, 480), media::limits::kMaxFramesPerSecond - 1,
media::PIXEL_FORMAT_I420));
SetSourceSupportedFormats(formats); SetSourceSupportedFormats(formats);
MockMediaConstraintFactory factory; MockConstraintFactory factory;
blink::WebMediaStreamTrack track = blink::WebMediaStreamTrack track =
CreateTrackAndStartSource(factory.CreateWebMediaConstraints(), CreateTrackAndStartSource(factory.CreateWebMediaConstraints(), 640, 480,
640, 480, 2000); media::limits::kMaxFramesPerSecond - 1);
MockMediaStreamVideoSink sink; MockMediaStreamVideoSink sink;
MediaStreamVideoSink::AddToVideoTrack(&sink, sink.GetDeliverFrameCB(), track); MediaStreamVideoSink::AddToVideoTrack(&sink, sink.GetDeliverFrameCB(), track);
EXPECT_EQ(track.source().readyState(), EXPECT_EQ(track.source().readyState(),
......
// Copyright 2016 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 <stddef.h>
#include "base/macros.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/utf_string_conversions.h"
#include "content/renderer/media/media_stream_audio_processor_options.h"
#include "content/renderer/media/mock_constraint_factory.h"
#include "third_party/libjingle/source/talk/app/webrtc/mediaconstraintsinterface.h"
namespace content {
MockConstraintFactory::MockConstraintFactory() {}
MockConstraintFactory::~MockConstraintFactory() {}
blink::WebMediaTrackConstraintSet& MockConstraintFactory::AddAdvanced() {
advanced_.emplace_back();
return advanced_.back();
}
blink::WebMediaConstraints MockConstraintFactory::CreateWebMediaConstraints()
const {
blink::WebMediaConstraints constraints;
constraints.initialize(basic_, advanced_);
return constraints;
}
} // namespace content
// Copyright 2016 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 CONTENT_RENDERER_MEDIA_MOCK_CONSTRAINT_FACTORY_H_
#define CONTENT_RENDERER_MEDIA_MOCK_CONSTRAINT_FACTORY_H_
#include <string>
#include <vector>
#include "third_party/WebKit/public/platform/WebMediaConstraints.h"
namespace content {
class MockConstraintFactory {
public:
MockConstraintFactory();
~MockConstraintFactory();
blink::WebMediaConstraints CreateWebMediaConstraints() const;
blink::WebMediaTrackConstraintSet& basic() { return basic_; }
blink::WebMediaTrackConstraintSet& AddAdvanced();
private:
blink::WebMediaTrackConstraintSet basic_;
std::vector<blink::WebMediaTrackConstraintSet> advanced_;
DISALLOW_COPY_AND_ASSIGN(MockConstraintFactory);
};
} // namespace content
#endif // CONTENT_RENDERER_MEDIA_MOCK_CONSTRAINT_FACTORY_H_
...@@ -334,7 +334,7 @@ ...@@ -334,7 +334,7 @@
} }
function failedCallback(error) { function failedCallback(error) {
failTest('GetUserMedia call failed with code ' + error.code); failTest('GetUserMedia call failed with error name ' + error.name);
} }
function attachMediaStream(stream, videoElement) { function attachMediaStream(stream, videoElement) {
...@@ -502,7 +502,8 @@ ...@@ -502,7 +502,8 @@
if (++attempt > maxAttempts) { if (++attempt > maxAttempts) {
clearInterval(detectorInterval); clearInterval(detectorInterval);
failTest("Aspect ratio corrupted. X " + maxLightGreenPixelsX + failTest("Aspect ratio corrupted. X " + maxLightGreenPixelsX +
" Y " + maxLightGreenPixelsY); " Y " + maxLightGreenPixelsY + " width " + width +
" height " + height);
} }
else { else {
// We have a bad aspect ratio now; give a chance to shape up. // We have a bad aspect ratio now; give a chance to shape up.
......
...@@ -72,3 +72,21 @@ TEST(MediaTrackConstraintsTest, ConstraintName) ...@@ -72,3 +72,21 @@ TEST(MediaTrackConstraintsTest, ConstraintName)
blink::BooleanConstraint boolConstraint(theName); blink::BooleanConstraint boolConstraint(theName);
EXPECT_EQ(theName, boolConstraint.name()); EXPECT_EQ(theName, boolConstraint.name());
} }
TEST(MediaTrackConstraintsTest, MandatoryChecks)
{
blink::WebMediaTrackConstraintSet theSet;
std::string foundName;
EXPECT_FALSE(theSet.hasMandatory());
EXPECT_FALSE(theSet.hasMandatoryOutsideSet({ "width" }, foundName));
EXPECT_FALSE(theSet.width.hasMandatory());
theSet.width.setMax(240);
EXPECT_TRUE(theSet.width.hasMandatory());
EXPECT_TRUE(theSet.hasMandatory());
EXPECT_FALSE(theSet.hasMandatoryOutsideSet({ "width" }, foundName));
EXPECT_TRUE(theSet.hasMandatoryOutsideSet({ "height" }, foundName));
EXPECT_EQ("width", foundName);
theSet.googPayloadPadding.setExact(true);
EXPECT_TRUE(theSet.hasMandatoryOutsideSet({ "width" }, foundName));
EXPECT_EQ("googPayloadPadding", foundName);
}
...@@ -186,6 +186,11 @@ bool LongConstraint::isEmpty() const ...@@ -186,6 +186,11 @@ bool LongConstraint::isEmpty() const
return !m_hasMin && !m_hasMax && !m_hasExact && !m_hasIdeal; return !m_hasMin && !m_hasMax && !m_hasExact && !m_hasIdeal;
} }
bool LongConstraint::hasMandatory() const
{
return m_hasMin || m_hasMax || m_hasExact;
}
const double DoubleConstraint::kConstraintEpsilon = 0.00001; const double DoubleConstraint::kConstraintEpsilon = 0.00001;
DoubleConstraint::DoubleConstraint(const char* name) DoubleConstraint::DoubleConstraint(const char* name)
...@@ -220,6 +225,11 @@ bool DoubleConstraint::isEmpty() const ...@@ -220,6 +225,11 @@ bool DoubleConstraint::isEmpty() const
return !m_hasMin && !m_hasMax && !m_hasExact && !m_hasIdeal; return !m_hasMin && !m_hasMax && !m_hasExact && !m_hasIdeal;
} }
bool DoubleConstraint::hasMandatory() const
{
return m_hasMin || m_hasMax || m_hasExact;
}
StringConstraint::StringConstraint(const char* name) StringConstraint::StringConstraint(const char* name)
: BaseConstraint(name) : BaseConstraint(name)
, m_exact() , m_exact()
...@@ -245,6 +255,11 @@ bool StringConstraint::isEmpty() const ...@@ -245,6 +255,11 @@ bool StringConstraint::isEmpty() const
return m_exact.isEmpty() && m_ideal.isEmpty(); return m_exact.isEmpty() && m_ideal.isEmpty();
} }
bool StringConstraint::hasMandatory() const
{
return !m_exact.isEmpty();
}
const WebVector<WebString>& StringConstraint::exact() const const WebVector<WebString>& StringConstraint::exact() const
{ {
return m_exact; return m_exact;
...@@ -277,6 +292,11 @@ bool BooleanConstraint::isEmpty() const ...@@ -277,6 +292,11 @@ bool BooleanConstraint::isEmpty() const
return !m_hasIdeal && !m_hasExact; return !m_hasIdeal && !m_hasExact;
} }
bool BooleanConstraint::hasMandatory() const
{
return m_hasExact;
}
WebMediaTrackConstraintSet::WebMediaTrackConstraintSet() WebMediaTrackConstraintSet::WebMediaTrackConstraintSet()
: width("width") : width("width")
, height("height") , height("height")
...@@ -332,24 +352,59 @@ WebMediaTrackConstraintSet::WebMediaTrackConstraintSet() ...@@ -332,24 +352,59 @@ WebMediaTrackConstraintSet::WebMediaTrackConstraintSet()
{ {
} }
std::vector<const BaseConstraint*> WebMediaTrackConstraintSet::allConstraints() const
{
const BaseConstraint* temp[] = {
&width, &height, &aspectRatio, &frameRate, &facingMode, &volume,
&sampleRate, &sampleSize, &echoCancellation, &latency, &channelCount,
&deviceId, &groupId, &mediaStreamSource, &renderToAssociatedSink,
&hotwordEnabled, &googEchoCancellation,
&googExperimentalEchoCancellation, &googAutoGainControl,
&googExperimentalAutoGainControl, &googNoiseSuppression,
&googHighpassFilter, &googTypingNoiseDetection,
&googExperimentalNoiseSuppression, &googBeamforming,
&googArrayGeometry, &googAudioMirroring, &googDAEchoCancellation,
&googAecDump, &googNoiseReduction, &offerToReceiveAudio,
&offerToReceiveVideo, &voiceActivityDetection, &iceRestart,
&googUseRtpMux, &enableDtlsSrtp, &enableRtpDataChannels,
&enableDscp, &enableIPv6, &googEnableVideoSuspendBelowMinBitrate,
&googNumUnsignalledRecvStreams, &googCombinedAudioVideoBwe,
&googScreencastMinBitrate, &googCpuOveruseDetection,
&googCpuUnderuseThreshold, &googCpuOveruseThreshold,
&googCpuUnderuseEncodeRsdThreshold, &googCpuOveruseEncodeRsdThreshold,
&googCpuOveruseEncodeUsage, &googHighStartBitrate, &googPayloadPadding
};
const int elementCount = sizeof(temp) / sizeof(temp[0]);
return std::vector<const BaseConstraint*>(&temp[0], &temp[elementCount]);
}
bool WebMediaTrackConstraintSet::isEmpty() const bool WebMediaTrackConstraintSet::isEmpty() const
{ {
return width.isEmpty() && height.isEmpty() && aspectRatio.isEmpty() for (const auto& constraint : allConstraints()) {
&& frameRate.isEmpty() && facingMode.isEmpty() && volume.isEmpty() if (!constraint->isEmpty())
&& sampleRate.isEmpty() && sampleSize.isEmpty() return false;
&& echoCancellation.isEmpty() && latency.isEmpty() }
&& channelCount.isEmpty() && deviceId.isEmpty() && groupId.isEmpty() return true;
&& mediaStreamSource.isEmpty() && renderToAssociatedSink.isEmpty() }
&& hotwordEnabled.isEmpty() && googEchoCancellation.isEmpty()
&& googExperimentalEchoCancellation.isEmpty() bool WebMediaTrackConstraintSet::hasMandatoryOutsideSet(const std::vector<std::string>& goodNames, std::string& foundName) const
&& googAutoGainControl.isEmpty() {
&& googExperimentalAutoGainControl.isEmpty() for (const auto& constraint : allConstraints()) {
&& googNoiseSuppression.isEmpty() if (constraint->hasMandatory()) {
&& googHighpassFilter.isEmpty() if (std::find(goodNames.begin(), goodNames.end(), constraint->name())
&& googTypingNoiseDetection.isEmpty() == goodNames.end()) {
&& googExperimentalNoiseSuppression.isEmpty() foundName = constraint->name();
&& googBeamforming.isEmpty() && googArrayGeometry.isEmpty() return true;
&& googAudioMirroring.isEmpty(); }
}
}
return false;
}
bool WebMediaTrackConstraintSet::hasMandatory() const
{
std::string dummyString;
return hasMandatoryOutsideSet(std::vector<std::string>(), dummyString);
} }
// WebMediaConstraints // WebMediaConstraints
......
...@@ -37,6 +37,8 @@ ...@@ -37,6 +37,8 @@
#include "WebString.h" #include "WebString.h"
#include "WebVector.h" #include "WebVector.h"
#include <vector>
namespace blink { namespace blink {
class WebMediaConstraintsPrivate; class WebMediaConstraintsPrivate;
...@@ -46,7 +48,8 @@ public: ...@@ -46,7 +48,8 @@ public:
explicit BaseConstraint(const char* name); explicit BaseConstraint(const char* name);
virtual ~BaseConstraint(); virtual ~BaseConstraint();
virtual bool isEmpty() const = 0; virtual bool isEmpty() const = 0;
const char* name() virtual bool hasMandatory() const = 0;
const char* name() const
{ {
return m_name; return m_name;
} }
...@@ -84,6 +87,11 @@ public: ...@@ -84,6 +87,11 @@ public:
bool matches(long value) const; bool matches(long value) const;
bool isEmpty() const override; bool isEmpty() const override;
bool hasMandatory() const override;
bool hasMin() const { return m_hasMin; }
long min() const { return m_min; }
bool hasMax() const { return m_hasMax; }
long max() const { return m_max; }
private: private:
long m_min; long m_min;
...@@ -131,6 +139,11 @@ public: ...@@ -131,6 +139,11 @@ public:
bool matches(double value) const; bool matches(double value) const;
bool isEmpty() const override; bool isEmpty() const override;
bool hasMandatory() const override;
bool hasMin() const { return m_hasMin; }
double min() const { return m_min; }
bool hasMax() const { return m_hasMax; }
double max() const { return m_max; }
private: private:
double m_min; double m_min;
...@@ -167,6 +180,7 @@ public: ...@@ -167,6 +180,7 @@ public:
bool matches(WebString value) const; bool matches(WebString value) const;
bool isEmpty() const override; bool isEmpty() const override;
bool hasMandatory() const override;
const WebVector<WebString>& exact() const; const WebVector<WebString>& exact() const;
const WebVector<WebString>& ideal() const; const WebVector<WebString>& ideal() const;
...@@ -193,6 +207,7 @@ public: ...@@ -193,6 +207,7 @@ public:
bool matches(bool value) const; bool matches(bool value) const;
bool isEmpty() const override; bool isEmpty() const override;
bool hasMandatory() const override;
private: private:
unsigned m_ideal : 1; unsigned m_ideal : 1;
...@@ -260,6 +275,11 @@ public: ...@@ -260,6 +275,11 @@ public:
BooleanConstraint googPayloadPadding; BooleanConstraint googPayloadPadding;
BLINK_PLATFORM_EXPORT bool isEmpty() const; BLINK_PLATFORM_EXPORT bool isEmpty() const;
BLINK_PLATFORM_EXPORT bool hasMandatory() const;
BLINK_PLATFORM_EXPORT bool hasMandatoryOutsideSet(const std::vector<std::string>&, std::string&) const;
private:
std::vector<const BaseConstraint*> allConstraints() const;
}; };
// Old type/value form of constraint. Will be deprecated. // Old type/value form of constraint. Will be deprecated.
......
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