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

Side by Side 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 unified diff | Download patch
OLDNEW
1 // Copyright 2017 The Chromium Authors. All rights reserved. 1 // Copyright 2017 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "content/renderer/media/media_stream_constraints_util_video_content.h" 5 #include "content/renderer/media/media_stream_constraints_util_video_content.h"
6 6
7 #include <algorithm>
7 #include <cmath> 8 #include <cmath>
8 #include <utility> 9 #include <utility>
9 #include <vector> 10 #include <vector>
10 11
11 #include "content/renderer/media/media_stream_constraints_util_sets.h" 12 #include "content/renderer/media/media_stream_constraints_util_sets.h"
12 #include "content/renderer/media/media_stream_video_source.h" 13 #include "content/renderer/media/media_stream_video_source.h"
13 #include "media/base/limits.h" 14 #include "media/base/limits.h"
14 #include "third_party/WebKit/public/platform/WebMediaConstraints.h" 15 #include "third_party/WebKit/public/platform/WebMediaConstraints.h"
15 #include "third_party/WebKit/public/platform/WebString.h" 16 #include "third_party/WebKit/public/platform/WebString.h"
16 17
17 namespace content { 18 namespace content {
18 19
20 const int kMinScreenCastDimension = 1;
21 // Use kMaxDimension/2 as maximum to ensure selected resolutions have area less
22 // than media::limits::kMaxCanvas.
23 const int kMaxScreenCastDimension = media::limits::kMaxDimension / 2;
24 static_assert(kMaxScreenCastDimension * kMaxScreenCastDimension <
25 media::limits::kMaxCanvas,
26 "Invalid kMaxScreenCastDimension");
27
19 const int kDefaultScreenCastWidth = 2880; 28 const int kDefaultScreenCastWidth = 2880;
20 const int kDefaultScreenCastHeight = 1800; 29 const int kDefaultScreenCastHeight = 1800;
21 const double kDefaultScreenCastAspectRatio = 30 const double kDefaultScreenCastAspectRatio =
22 static_cast<double>(kDefaultScreenCastWidth) / kDefaultScreenCastHeight; 31 static_cast<double>(kDefaultScreenCastWidth) / kDefaultScreenCastHeight;
32 static_assert(kDefaultScreenCastWidth <= kMaxScreenCastDimension,
33 "Invalid kDefaultScreenCastWidth");
34 static_assert(kDefaultScreenCastHeight <= kMaxScreenCastDimension,
35 "Invalid kDefaultScreenCastHeight");
36
37 const double kMinScreenCastFrameRate = 1.0 / 60.0;
38 const double kMaxScreenCastFrameRate = 120.0;
23 const double kDefaultScreenCastFrameRate = 39 const double kDefaultScreenCastFrameRate =
24 MediaStreamVideoSource::kDefaultFrameRate; 40 MediaStreamVideoSource::kDefaultFrameRate;
25 const int kMinScreenCastDimension = 1;
26 const int kMaxScreenCastDimension = media::limits::kMaxDimension - 1;
27 41
28 namespace { 42 namespace {
29 43
30 using Point = ResolutionSet::Point; 44 using Point = ResolutionSet::Point;
31 using StringSet = DiscreteSet<std::string>; 45 using StringSet = DiscreteSet<std::string>;
32 using BoolSet = DiscreteSet<bool>; 46 using BoolSet = DiscreteSet<bool>;
33 47
34 // Hard upper and lower bound frame rates for tab/desktop capture.
35 const double kMaxScreenCastFrameRate = 120.0;
36 const double kMinScreenCastFrameRate = 1.0 / 60.0;
37 48
38 constexpr double kMinScreenCastAspectRatio = 49 constexpr double kMinScreenCastAspectRatio =
39 static_cast<double>(kMinScreenCastDimension) / 50 static_cast<double>(kMinScreenCastDimension) /
40 static_cast<double>(kMaxScreenCastDimension); 51 static_cast<double>(kMaxScreenCastDimension);
41 constexpr double kMaxScreenCastAspectRatio = 52 constexpr double kMaxScreenCastAspectRatio =
42 static_cast<double>(kMaxScreenCastDimension) / 53 static_cast<double>(kMaxScreenCastDimension) /
43 static_cast<double>(kMinScreenCastDimension); 54 static_cast<double>(kMinScreenCastDimension);
44 55
45 StringSet StringSetFromConstraint(const blink::StringConstraint& constraint) { 56 StringSet StringSetFromConstraint(const blink::StringConstraint& constraint) {
46 if (!constraint.HasExact()) 57 if (!constraint.HasExact())
(...skipping 11 matching lines...) Expand all
58 return BoolSet::UniversalSet(); 69 return BoolSet::UniversalSet();
59 70
60 return BoolSet({constraint.Exact()}); 71 return BoolSet({constraint.Exact()});
61 } 72 }
62 73
63 using DoubleRangeSet = NumericRangeSet<double>; 74 using DoubleRangeSet = NumericRangeSet<double>;
64 75
65 class VideoContentCaptureCandidates { 76 class VideoContentCaptureCandidates {
66 public: 77 public:
67 VideoContentCaptureCandidates() 78 VideoContentCaptureCandidates()
68 : device_id_set(StringSet::UniversalSet()), 79 : has_explicit_max_height_(false),
69 noise_reduction_set(BoolSet::UniversalSet()) {} 80 has_explicit_max_width_(false),
81 has_explicit_max_frame_rate_(false),
82 device_id_set_(StringSet::UniversalSet()),
83 noise_reduction_set_(BoolSet::UniversalSet()) {}
70 explicit VideoContentCaptureCandidates( 84 explicit VideoContentCaptureCandidates(
71 const blink::WebMediaTrackConstraintSet& constraint_set) 85 const blink::WebMediaTrackConstraintSet& constraint_set)
72 : resolution_set(ResolutionSet::FromConstraintSet(constraint_set)), 86 : resolution_set_(ResolutionSet::FromConstraintSet(constraint_set)),
73 frame_rate_set( 87 has_explicit_max_height_(ConstraintHasMax(constraint_set.height) &&
88 ConstraintMax(constraint_set.height) <=
89 kMaxScreenCastDimension),
90 has_explicit_max_width_(ConstraintHasMax(constraint_set.width) &&
91 ConstraintMax(constraint_set.width) <=
92 kMaxScreenCastDimension),
93 frame_rate_set_(
74 DoubleRangeSet::FromConstraint(constraint_set.frame_rate)), 94 DoubleRangeSet::FromConstraint(constraint_set.frame_rate)),
75 device_id_set(StringSetFromConstraint(constraint_set.device_id)), 95 has_explicit_max_frame_rate_(
76 noise_reduction_set( 96 ConstraintHasMax(constraint_set.frame_rate) &&
97 ConstraintMax(constraint_set.frame_rate) <=
98 kMaxScreenCastFrameRate),
99 device_id_set_(StringSetFromConstraint(constraint_set.device_id)),
100 noise_reduction_set_(
77 BoolSetFromConstraint(constraint_set.goog_noise_reduction)) {} 101 BoolSetFromConstraint(constraint_set.goog_noise_reduction)) {}
78 102
79 VideoContentCaptureCandidates(VideoContentCaptureCandidates&& other) = 103 VideoContentCaptureCandidates(VideoContentCaptureCandidates&& other) =
80 default; 104 default;
81 VideoContentCaptureCandidates& operator=( 105 VideoContentCaptureCandidates& operator=(
82 VideoContentCaptureCandidates&& other) = default; 106 VideoContentCaptureCandidates&& other) = default;
83 107
84 bool IsEmpty() const { 108 bool IsEmpty() const {
85 return resolution_set.IsEmpty() || frame_rate_set.IsEmpty() || 109 return resolution_set_.IsEmpty() || frame_rate_set_.IsEmpty() ||
86 device_id_set.IsEmpty() || noise_reduction_set.IsEmpty(); 110 device_id_set_.IsEmpty() || noise_reduction_set_.IsEmpty();
87 } 111 }
88 112
89 VideoContentCaptureCandidates Intersection( 113 VideoContentCaptureCandidates Intersection(
90 const VideoContentCaptureCandidates& other) { 114 const VideoContentCaptureCandidates& other) {
91 VideoContentCaptureCandidates intersection; 115 VideoContentCaptureCandidates intersection;
92 intersection.resolution_set = 116 intersection.resolution_set_ =
93 resolution_set.Intersection(other.resolution_set); 117 resolution_set_.Intersection(other.resolution_set_);
94 intersection.frame_rate_set = 118 intersection.has_explicit_max_height_ =
95 frame_rate_set.Intersection(other.frame_rate_set); 119 has_explicit_max_height_ || other.has_explicit_max_height_;
96 intersection.device_id_set = 120 intersection.has_explicit_max_width_ =
97 device_id_set.Intersection(other.device_id_set); 121 has_explicit_max_width_ || other.has_explicit_max_width_;
98 intersection.noise_reduction_set = 122 intersection.frame_rate_set_ =
99 noise_reduction_set.Intersection(other.noise_reduction_set); 123 frame_rate_set_.Intersection(other.frame_rate_set_);
124 intersection.has_explicit_max_frame_rate_ =
125 has_explicit_max_frame_rate_ || other.has_explicit_max_frame_rate_;
126 intersection.device_id_set_ =
127 device_id_set_.Intersection(other.device_id_set_);
128 intersection.noise_reduction_set_ =
129 noise_reduction_set_.Intersection(other.noise_reduction_set_);
100 return intersection; 130 return intersection;
101 } 131 }
102 132
103 ResolutionSet resolution_set; 133 const ResolutionSet& resolution_set() const { return resolution_set_; }
104 DoubleRangeSet frame_rate_set; 134 bool has_explicit_max_height() const { return has_explicit_max_height_; }
105 StringSet device_id_set; 135 bool has_explicit_max_width() const { return has_explicit_max_width_; }
106 BoolSet noise_reduction_set; 136 const DoubleRangeSet& frame_rate_set() const { return frame_rate_set_; }
137 bool has_explicit_max_frame_rate() const {
138 return has_explicit_max_frame_rate_;
139 }
140 const StringSet& device_id_set() const { return device_id_set_; }
141 const BoolSet& noise_reduction_set() const { return noise_reduction_set_; }
142 void set_resolution_set(const ResolutionSet& set) { resolution_set_ = set; }
143 void set_frame_rate_set(const DoubleRangeSet& set) { frame_rate_set_ = set; }
144
145 private:
146 ResolutionSet resolution_set_;
147 bool has_explicit_max_height_;
148 bool has_explicit_max_width_;
149 DoubleRangeSet frame_rate_set_;
150 bool has_explicit_max_frame_rate_;
151 StringSet device_id_set_;
152 BoolSet noise_reduction_set_;
107 }; 153 };
108 154
109 ResolutionSet ScreenCastResolutionCapabilities() { 155 ResolutionSet ScreenCastResolutionCapabilities() {
110 return ResolutionSet(kMinScreenCastDimension, kMaxScreenCastDimension, 156 return ResolutionSet(kMinScreenCastDimension, kMaxScreenCastDimension,
111 kMinScreenCastDimension, kMaxScreenCastDimension, 157 kMinScreenCastDimension, kMaxScreenCastDimension,
112 kMinScreenCastAspectRatio, kMaxScreenCastAspectRatio); 158 kMinScreenCastAspectRatio, kMaxScreenCastAspectRatio);
113 } 159 }
114 160
115 // TODO(guidou): Update this policy to better match the way 161 // TODO(guidou): Update this policy to better match the way
116 // WebContentsCaptureMachine::ComputeOptimalViewSize() interprets 162 // WebContentsCaptureMachine::ComputeOptimalViewSize() interprets
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
166 return frame_rate; 212 return frame_rate;
167 } 213 }
168 214
169 media::VideoCaptureParams SelectVideoCaptureParamsFromCandidates( 215 media::VideoCaptureParams SelectVideoCaptureParamsFromCandidates(
170 const VideoContentCaptureCandidates& candidates, 216 const VideoContentCaptureCandidates& candidates,
171 const blink::WebMediaTrackConstraintSet& basic_constraint_set, 217 const blink::WebMediaTrackConstraintSet& basic_constraint_set,
172 int default_height, 218 int default_height,
173 int default_width, 219 int default_width,
174 double default_frame_rate) { 220 double default_frame_rate) {
175 double requested_frame_rate = SelectFrameRateFromCandidates( 221 double requested_frame_rate = SelectFrameRateFromCandidates(
176 candidates.frame_rate_set, basic_constraint_set, default_frame_rate); 222 candidates.frame_rate_set(), basic_constraint_set, default_frame_rate);
177 Point requested_resolution = 223 Point requested_resolution =
178 candidates.resolution_set.SelectClosestPointToIdeal( 224 candidates.resolution_set().SelectClosestPointToIdeal(
179 basic_constraint_set, default_height, default_width); 225 basic_constraint_set, default_height, default_width);
180 media::VideoCaptureParams params; 226 media::VideoCaptureParams params;
181 params.requested_format = media::VideoCaptureFormat( 227 params.requested_format = media::VideoCaptureFormat(
182 ToGfxSize(requested_resolution), static_cast<float>(requested_frame_rate), 228 ToGfxSize(requested_resolution), static_cast<float>(requested_frame_rate),
183 media::PIXEL_FORMAT_I420); 229 media::PIXEL_FORMAT_I420);
184 params.resolution_change_policy = 230 params.resolution_change_policy =
185 SelectResolutionPolicyFromCandidates(candidates.resolution_set); 231 SelectResolutionPolicyFromCandidates(candidates.resolution_set());
186 // Content capture always uses default power-line frequency. 232 // Content capture always uses default power-line frequency.
187 DCHECK(params.IsValid()); 233 DCHECK(params.IsValid());
188 234
189 return params; 235 return params;
190 } 236 }
191 237
192 std::string SelectDeviceIDFromCandidates( 238 std::string SelectDeviceIDFromCandidates(
193 const StringSet& candidates, 239 const StringSet& candidates,
194 const blink::WebMediaTrackConstraintSet& basic_constraint_set) { 240 const blink::WebMediaTrackConstraintSet& basic_constraint_set) {
195 DCHECK(!candidates.IsEmpty()); 241 DCHECK(!candidates.IsEmpty());
(...skipping 29 matching lines...) Expand all
225 basic_constraint_set.goog_noise_reduction.Ideal()); 271 basic_constraint_set.goog_noise_reduction.Ideal());
226 } 272 }
227 273
228 if (candidates.is_universal()) 274 if (candidates.is_universal())
229 return base::Optional<bool>(); 275 return base::Optional<bool>();
230 276
231 // A non-universal BoolSet can have at most one element. 277 // A non-universal BoolSet can have at most one element.
232 return base::Optional<bool>(candidates.FirstElement()); 278 return base::Optional<bool>(candidates.FirstElement());
233 } 279 }
234 280
281 int ClampToValidDimension(int value) {
282 if (value > kMaxScreenCastDimension)
283 return kMaxScreenCastDimension;
284 else if (value < kMinScreenCastDimension)
285 return kMinScreenCastDimension;
286 return value;
287 }
288
235 VideoCaptureSettings SelectResultFromCandidates( 289 VideoCaptureSettings SelectResultFromCandidates(
236 const VideoContentCaptureCandidates& candidates, 290 const VideoContentCaptureCandidates& candidates,
237 const blink::WebMediaTrackConstraintSet& basic_constraint_set) { 291 const blink::WebMediaTrackConstraintSet& basic_constraint_set) {
238 std::string device_id = SelectDeviceIDFromCandidates(candidates.device_id_set, 292 std::string device_id = SelectDeviceIDFromCandidates(
239 basic_constraint_set); 293 candidates.device_id_set(), basic_constraint_set);
240 // If a maximum width or height is explicitly given, use them as default. 294 // If a maximum width or height is explicitly given, use them as default.
241 // If only one of them is given, use the default aspect ratio to determine the 295 // If only one of them is given, use the default aspect ratio to determine the
242 // other default value. 296 // other default value.
243 // TODO(guidou): Use native screen-capture resolution as default. 297 // TODO(guidou): Use native screen-capture resolution as default.
244 // http://crbug.com/257097 298 // http://crbug.com/257097
245 int default_height = kDefaultScreenCastHeight; 299 int default_height = kDefaultScreenCastHeight;
246 int default_width = kDefaultScreenCastWidth; 300 int default_width = kDefaultScreenCastWidth;
247 bool has_explicit_max_height = 301 if (candidates.has_explicit_max_height() &&
248 candidates.resolution_set.max_height() < kMaxScreenCastDimension; 302 candidates.has_explicit_max_width()) {
249 bool has_explicit_max_width = 303 default_height = candidates.resolution_set().max_height();
250 candidates.resolution_set.max_width() < kMaxScreenCastDimension; 304 default_width = candidates.resolution_set().max_width();
251 if (has_explicit_max_height && has_explicit_max_width) { 305 } else if (candidates.has_explicit_max_height()) {
252 default_height = candidates.resolution_set.max_height(); 306 default_height = candidates.resolution_set().max_height();
253 default_width = candidates.resolution_set.max_width();
254 } else if (has_explicit_max_height) {
255 default_height = candidates.resolution_set.max_height();
256 default_width = static_cast<int>( 307 default_width = static_cast<int>(
257 std::round(default_height * kDefaultScreenCastAspectRatio)); 308 std::round(default_height * kDefaultScreenCastAspectRatio));
258 } else if (has_explicit_max_width) { 309 } else if (candidates.has_explicit_max_width()) {
259 default_width = candidates.resolution_set.max_width(); 310 default_width = candidates.resolution_set().max_width();
260 default_height = static_cast<int>( 311 default_height = static_cast<int>(
261 std::round(default_width / kDefaultScreenCastAspectRatio)); 312 std::round(default_width / kDefaultScreenCastAspectRatio));
262 } 313 }
314 // When the given maximum values are large, the computed values using default
315 // aspect ratio may fall out of range. Ensure the defaults are in the valid
316 // range.
317 default_height = ClampToValidDimension(default_height);
318 default_width = ClampToValidDimension(default_width);
319
320 // If a maximum frame rate is explicitly given, use it as default for
321 // better compatibility with the old constraints algorithm.
322 // TODO(guidou): Use the actual default when applications migrate to the new
323 // constraint syntax. http://crbug.com/710800
324 double default_frame_rate = candidates.has_explicit_max_frame_rate()
325 ? candidates.frame_rate_set().Max()
326 : kDefaultScreenCastFrameRate;
263 media::VideoCaptureParams capture_params = 327 media::VideoCaptureParams capture_params =
264 SelectVideoCaptureParamsFromCandidates(candidates, basic_constraint_set, 328 SelectVideoCaptureParamsFromCandidates(candidates, basic_constraint_set,
265 default_height, default_width, 329 default_height, default_width,
266 kDefaultScreenCastFrameRate); 330 default_frame_rate);
267 331
268 base::Optional<bool> noise_reduction = SelectNoiseReductionFromCandidates( 332 base::Optional<bool> noise_reduction = SelectNoiseReductionFromCandidates(
269 candidates.noise_reduction_set, basic_constraint_set); 333 candidates.noise_reduction_set(), basic_constraint_set);
270 334
271 auto track_adapter_settings = SelectVideoTrackAdapterSettings( 335 auto track_adapter_settings = SelectVideoTrackAdapterSettings(
272 basic_constraint_set, candidates.resolution_set, 336 basic_constraint_set, candidates.resolution_set(),
273 candidates.frame_rate_set, capture_params.requested_format); 337 candidates.frame_rate_set(), capture_params.requested_format);
274 338
275 return VideoCaptureSettings(std::move(device_id), capture_params, 339 return VideoCaptureSettings(std::move(device_id), capture_params,
276 noise_reduction, track_adapter_settings, 340 noise_reduction, track_adapter_settings,
277 candidates.frame_rate_set.Min()); 341 candidates.frame_rate_set().Min());
278 } 342 }
279 343
280 VideoCaptureSettings UnsatisfiedConstraintsResult( 344 VideoCaptureSettings UnsatisfiedConstraintsResult(
281 const VideoContentCaptureCandidates& candidates, 345 const VideoContentCaptureCandidates& candidates,
282 const blink::WebMediaTrackConstraintSet& constraint_set) { 346 const blink::WebMediaTrackConstraintSet& constraint_set) {
283 DCHECK(candidates.IsEmpty()); 347 DCHECK(candidates.IsEmpty());
284 if (candidates.resolution_set.IsHeightEmpty()) { 348 if (candidates.resolution_set().IsHeightEmpty()) {
285 return VideoCaptureSettings(constraint_set.height.GetName()); 349 return VideoCaptureSettings(constraint_set.height.GetName());
286 } else if (candidates.resolution_set.IsWidthEmpty()) { 350 } else if (candidates.resolution_set().IsWidthEmpty()) {
287 return VideoCaptureSettings(constraint_set.width.GetName()); 351 return VideoCaptureSettings(constraint_set.width.GetName());
288 } else if (candidates.resolution_set.IsAspectRatioEmpty()) { 352 } else if (candidates.resolution_set().IsAspectRatioEmpty()) {
289 return VideoCaptureSettings(constraint_set.aspect_ratio.GetName()); 353 return VideoCaptureSettings(constraint_set.aspect_ratio.GetName());
290 } else if (candidates.frame_rate_set.IsEmpty()) { 354 } else if (candidates.frame_rate_set().IsEmpty()) {
291 return VideoCaptureSettings(constraint_set.frame_rate.GetName()); 355 return VideoCaptureSettings(constraint_set.frame_rate.GetName());
292 } else if (candidates.noise_reduction_set.IsEmpty()) { 356 } else if (candidates.noise_reduction_set().IsEmpty()) {
293 return VideoCaptureSettings(constraint_set.goog_noise_reduction.GetName()); 357 return VideoCaptureSettings(constraint_set.goog_noise_reduction.GetName());
294 } else { 358 } else {
295 DCHECK(candidates.device_id_set.IsEmpty()); 359 DCHECK(candidates.device_id_set().IsEmpty());
296 return VideoCaptureSettings(constraint_set.device_id.GetName()); 360 return VideoCaptureSettings(constraint_set.device_id.GetName());
297 } 361 }
298 } 362 }
299 363
300 } // namespace 364 } // namespace
301 365
302 VideoCaptureSettings SelectSettingsVideoContentCapture( 366 VideoCaptureSettings SelectSettingsVideoContentCapture(
303 const blink::WebMediaConstraints& constraints) { 367 const blink::WebMediaConstraints& constraints) {
304 VideoContentCaptureCandidates candidates; 368 VideoContentCaptureCandidates candidates;
305 candidates.resolution_set = ScreenCastResolutionCapabilities(); 369 candidates.set_resolution_set(ScreenCastResolutionCapabilities());
306 candidates.frame_rate_set = 370 candidates.set_frame_rate_set(
307 DoubleRangeSet(kMinScreenCastFrameRate, kMaxScreenCastFrameRate); 371 DoubleRangeSet(kMinScreenCastFrameRate, kMaxScreenCastFrameRate));
308 // candidates.device_id_set and candidates.noise_reduction_set are 372 // candidates.device_id_set and candidates.noise_reduction_set are
309 // automatically initialized with the universal set. 373 // automatically initialized with the universal set.
310 374
311 candidates = candidates.Intersection( 375 candidates = candidates.Intersection(
312 VideoContentCaptureCandidates(constraints.Basic())); 376 VideoContentCaptureCandidates(constraints.Basic()));
313 if (candidates.IsEmpty()) 377 if (candidates.IsEmpty())
314 return UnsatisfiedConstraintsResult(candidates, constraints.Basic()); 378 return UnsatisfiedConstraintsResult(candidates, constraints.Basic());
315 379
316 for (const auto& advanced_set : constraints.Advanced()) { 380 for (const auto& advanced_set : constraints.Advanced()) {
317 VideoContentCaptureCandidates advanced_candidates(advanced_set); 381 VideoContentCaptureCandidates advanced_candidates(advanced_set);
318 VideoContentCaptureCandidates intersection = 382 VideoContentCaptureCandidates intersection =
319 candidates.Intersection(advanced_candidates); 383 candidates.Intersection(advanced_candidates);
320 if (!intersection.IsEmpty()) 384 if (!intersection.IsEmpty())
321 candidates = std::move(intersection); 385 candidates = std::move(intersection);
322 } 386 }
323 387
324 DCHECK(!candidates.IsEmpty()); 388 DCHECK(!candidates.IsEmpty());
325 return SelectResultFromCandidates(candidates, constraints.Basic()); 389 return SelectResultFromCandidates(candidates, constraints.Basic());
326 } 390 }
327 391
328 } // namespace content 392 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698