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

Side by Side Diff: content/renderer/media/media_stream_video_source.cc

Issue 2964003002: Remove support for old getUserMedia video constraints algorithm. (Closed)
Patch Set: rebase and address hbos@ comments Created 3 years, 5 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 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 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_video_source.h" 5 #include "content/renderer/media/media_stream_video_source.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 #include <limits> 8 #include <limits>
9 #include <memory> 9 #include <memory>
10 #include <string> 10 #include <string>
11 #include <utility> 11 #include <utility>
12 12
13 #include "base/feature_list.h" 13 #include "base/feature_list.h"
14 #include "base/logging.h" 14 #include "base/logging.h"
15 #include "base/macros.h" 15 #include "base/macros.h"
16 #include "base/strings/string_number_conversions.h" 16 #include "base/strings/string_number_conversions.h"
17 #include "base/trace_event/trace_event.h" 17 #include "base/trace_event/trace_event.h"
18 #include "content/child/child_process.h" 18 #include "content/child/child_process.h"
19 #include "content/public/common/content_features.h" 19 #include "content/public/common/content_features.h"
20 #include "content/renderer/media/media_stream_constraints_util_video_device.h" 20 #include "content/renderer/media/media_stream_constraints_util_video_device.h"
21 #include "content/renderer/media/media_stream_video_track.h" 21 #include "content/renderer/media/media_stream_video_track.h"
22 #include "content/renderer/media/video_track_adapter.h" 22 #include "content/renderer/media/video_track_adapter.h"
23 23
24 namespace content { 24 namespace content {
25 25
26 namespace {
27
28 const char* const kLegalVideoConstraints[] = {"width",
29 "height",
30 "aspectRatio",
31 "frameRate",
32 "facingMode",
33 "deviceId",
34 "groupId",
35 "mediaStreamSource",
36 "googNoiseReduction",
37 "videoKind"};
38
39 // Returns true if |constraint| has mandatory constraints.
40 bool HasMandatoryConstraints(const blink::WebMediaConstraints& constraints) {
41 return constraints.Basic().HasMandatory();
42 }
43
44 // Retrieve the desired max width and height from |constraints|. If not set,
45 // the |desired_width| and |desired_height| are set to
46 // std::numeric_limits<int>::max();
47 // If either max or exact width or height is set as a mandatory constraint,
48 // the advanced constraints are not checked.
49 void GetDesiredMaxWidthAndHeight(const blink::WebMediaConstraints& constraints,
50 int* desired_width, int* desired_height) {
51 *desired_width = std::numeric_limits<int>::max();
52 *desired_height = std::numeric_limits<int>::max();
53
54 const auto& basic_constraints = constraints.Basic();
55
56 if (basic_constraints.width.HasMax() || basic_constraints.height.HasMax() ||
57 basic_constraints.width.HasExact() ||
58 basic_constraints.height.HasExact()) {
59 if (basic_constraints.width.HasMax())
60 *desired_width = basic_constraints.width.Max();
61 if (basic_constraints.height.HasMax())
62 *desired_height = basic_constraints.height.Max();
63 // Exact constraints override max constraints if both are specified.
64 // Specifying both in the same structure is meaningless.
65 if (basic_constraints.width.HasExact())
66 *desired_width = basic_constraints.width.Exact();
67 if (basic_constraints.height.HasExact())
68 *desired_height = basic_constraints.height.Exact();
69 return;
70 }
71
72 for (const auto& constraint_set : constraints.Advanced()) {
73 if (constraint_set.width.HasMax())
74 *desired_width = constraint_set.width.Max();
75 if (constraint_set.height.HasMax())
76 *desired_height = constraint_set.height.Max();
77 if (constraint_set.width.HasExact())
78 *desired_width = constraint_set.width.Exact();
79 if (constraint_set.height.HasExact())
80 *desired_height = constraint_set.height.Exact();
81 }
82 }
83
84 // Retrieve the desired max and min aspect ratio from |constraints|. If not set,
85 // the |min_aspect_ratio| is set to 0 and |max_aspect_ratio| is set to
86 // std::numeric_limits<double>::max();
87 // If either min or max aspect ratio is set as a mandatory constraint, the
88 // optional constraints are not checked.
89 void GetDesiredMinAndMaxAspectRatio(
90 const blink::WebMediaConstraints& constraints,
91 double* min_aspect_ratio,
92 double* max_aspect_ratio) {
93 *min_aspect_ratio = 0;
94 *max_aspect_ratio = std::numeric_limits<double>::max();
95
96 if (constraints.Basic().aspect_ratio.HasMin() ||
97 constraints.Basic().aspect_ratio.HasMax()) {
98 if (constraints.Basic().aspect_ratio.HasMin())
99 *min_aspect_ratio = constraints.Basic().aspect_ratio.Min();
100 if (constraints.Basic().aspect_ratio.HasMax())
101 *max_aspect_ratio = constraints.Basic().aspect_ratio.Max();
102 return;
103 // Note - the code will ignore attempts at successive refinement
104 // of the aspect ratio with advanced constraint. This may be wrong.
105 }
106 // Note - the code below will potentially pick min and max from different
107 // constraint sets, some of which might have been ignored.
108 for (const auto& constraint_set : constraints.Advanced()) {
109 if (constraint_set.aspect_ratio.HasMin()) {
110 *min_aspect_ratio = constraint_set.aspect_ratio.Min();
111 break;
112 }
113 }
114 for (const auto& constraint_set : constraints.Advanced()) {
115 // Advanced constraint sets with max aspect ratio 0 are unsatisfiable and
116 // must be ignored.
117 if (constraint_set.aspect_ratio.HasMax() &&
118 constraint_set.aspect_ratio.Max() > 0) {
119 *max_aspect_ratio = constraint_set.aspect_ratio.Max();
120 break;
121 }
122 }
123 }
124
125 // Returns true if |constraints| are fulfilled. |format| can be changed by a
126 // constraint, e.g. the frame rate can be changed by setting maxFrameRate.
127 bool UpdateFormatForConstraints(
128 const blink::WebMediaTrackConstraintSet& constraints,
129 media::VideoCaptureFormat* format,
130 std::string* failing_constraint_name) {
131 DCHECK(format != NULL);
132
133 if (!format->IsValid())
134 return false;
135
136 // The width and height are matched based on cropping occuring later:
137 // min width/height has to be >= the size of the frame (no upscale).
138 // max width/height just has to be > 0 (we can crop anything too large).
139 if ((constraints.width.HasMin() &&
140 constraints.width.Min() > format->frame_size.width()) ||
141 (constraints.width.HasMax() && constraints.width.Max() <= 0) ||
142 (constraints.width.HasExact() &&
143 constraints.width.Exact() > format->frame_size.width())) {
144 *failing_constraint_name = constraints.width.GetName();
145 } else if ((constraints.height.HasMin() &&
146 constraints.height.Min() > format->frame_size.height()) ||
147 (constraints.height.HasMax() && constraints.height.Max() <= 0) ||
148 (constraints.height.HasExact() &&
149 constraints.height.Exact() > format->frame_size.height())) {
150 *failing_constraint_name = constraints.height.GetName();
151 } else if (constraints.video_kind.HasExact() &&
152 !constraints.video_kind.Matches(GetVideoKindForFormat(*format))) {
153 *failing_constraint_name = constraints.video_kind.GetName();
154 } else if (!constraints.frame_rate.Matches(format->frame_rate)) {
155 if (constraints.frame_rate.HasMax()) {
156 const double value = constraints.frame_rate.Max();
157 // TODO(hta): Check if handling of max = 0.0 is relevant.
158 // (old handling was to set rate to 1.0 if 0.0 was specified)
159 if (constraints.frame_rate.Matches(value)) {
160 format->frame_rate =
161 (format->frame_rate > value) ? value : format->frame_rate;
162 return true;
163 }
164 }
165 *failing_constraint_name = constraints.frame_rate.GetName();
166 } else {
167 return true;
168 }
169
170 DCHECK(!failing_constraint_name->empty());
171 return false;
172 }
173
174 // Removes media::VideoCaptureFormats from |formats| that don't meet
175 // |constraints|.
176 void FilterFormatsByConstraints(
177 const blink::WebMediaTrackConstraintSet& constraints,
178 media::VideoCaptureFormats* formats,
179 std::string* failing_constraint_name) {
180 media::VideoCaptureFormats::iterator format_it = formats->begin();
181 while (format_it != formats->end()) {
182 // Modify |format_it| to fulfill the constraint if possible.
183 // Delete it otherwise.
184 if (!UpdateFormatForConstraints(constraints, &(*format_it),
185 failing_constraint_name)) {
186 DVLOG(2) << "Format filter: Discarding format "
187 << format_it->frame_size.width() << "x"
188 << format_it->frame_size.height() << "@"
189 << format_it->frame_rate;
190 format_it = formats->erase(format_it);
191 } else {
192 ++format_it;
193 }
194 }
195 }
196
197 // Returns the media::VideoCaptureFormats that matches |constraints|.
198 // If the return value is empty, and the reason is a specific constraint,
199 // |unsatisfied_constraint| returns the name of the constraint.
200 media::VideoCaptureFormats FilterFormats(
201 const blink::WebMediaConstraints& constraints,
202 const media::VideoCaptureFormats& supported_formats,
203 std::string* unsatisfied_constraint) {
204 if (constraints.IsNull())
205 return supported_formats;
206
207 const auto& basic = constraints.Basic();
208
209 // Do some checks that won't be done when filtering candidates.
210
211 if (basic.width.HasMin() && basic.width.HasMax() &&
212 basic.width.Min() > basic.width.Max()) {
213 *unsatisfied_constraint = basic.width.GetName();
214 return media::VideoCaptureFormats();
215 }
216
217 if (basic.height.HasMin() && basic.height.HasMax() &&
218 basic.height.Min() > basic.height.Max()) {
219 *unsatisfied_constraint = basic.height.GetName();
220 return media::VideoCaptureFormats();
221 }
222
223 double max_aspect_ratio;
224 double min_aspect_ratio;
225 GetDesiredMinAndMaxAspectRatio(constraints,
226 &min_aspect_ratio,
227 &max_aspect_ratio);
228
229 if (min_aspect_ratio > max_aspect_ratio || max_aspect_ratio < 0.05f) {
230 DLOG(WARNING) << "Wrong requested aspect ratio: min " << min_aspect_ratio
231 << " max " << max_aspect_ratio;
232 *unsatisfied_constraint = basic.aspect_ratio.GetName();
233 return media::VideoCaptureFormats();
234 }
235
236 std::vector<std::string> temp(
237 &kLegalVideoConstraints[0],
238 &kLegalVideoConstraints[sizeof(kLegalVideoConstraints) /
239 sizeof(kLegalVideoConstraints[0])]);
240 std::string failing_name;
241 if (basic.HasMandatoryOutsideSet(temp, failing_name)) {
242 *unsatisfied_constraint = failing_name;
243 return media::VideoCaptureFormats();
244 }
245
246 media::VideoCaptureFormats candidates = supported_formats;
247 FilterFormatsByConstraints(basic, &candidates, unsatisfied_constraint);
248
249 if (candidates.empty())
250 return candidates;
251
252 // Ok - all mandatory checked and we still have candidates.
253 // Let's try filtering using the advanced constraints. The advanced
254 // constraints must be filtered in the order they occur in |advanced|.
255 // But if a constraint produce zero candidates, the constraint is ignored and
256 // the next constraint is tested.
257 // http://w3c.github.io/mediacapture-main/getusermedia.html#dfn-selectsettings
258 for (const auto& constraint_set : constraints.Advanced()) {
259 media::VideoCaptureFormats current_candidates = candidates;
260 std::string unsatisfied_constraint;
261 FilterFormatsByConstraints(constraint_set, &current_candidates,
262 &unsatisfied_constraint);
263 if (!current_candidates.empty())
264 candidates = current_candidates;
265 }
266
267 // We have done as good as we can to filter the supported resolutions.
268 return candidates;
269 }
270
271 media::VideoCaptureFormat GetBestFormatBasedOnArea(
272 const media::VideoCaptureFormats& formats,
273 int area) {
274 DCHECK(!formats.empty());
275 const media::VideoCaptureFormat* best_format = nullptr;
276 int best_diff = std::numeric_limits<int>::max();
277 for (const auto& format : formats) {
278 const int diff = abs(area - format.frame_size.GetArea());
279 if (diff < best_diff) {
280 best_diff = diff;
281 best_format = &format;
282 }
283 }
284 DVLOG(3) << "GetBestFormatBasedOnArea chose format "
285 << media::VideoCaptureFormat::ToString(*best_format);
286 return *best_format;
287 }
288
289 // Find the format that best matches the default video size.
290 // This algorithm is chosen since a resolution must be picked even if no
291 // constraints are provided. We don't just select the maximum supported
292 // resolution since higher resolutions cost more in terms of complexity and
293 // many cameras have lower frame rate and have more noise in the image at
294 // their maximum supported resolution.
295 media::VideoCaptureFormat GetBestCaptureFormat(
296 const media::VideoCaptureFormats& formats,
297 const blink::WebMediaConstraints& constraints) {
298 DCHECK(!formats.empty());
299
300 int max_width;
301 int max_height;
302 GetDesiredMaxWidthAndHeight(constraints, &max_width, &max_height);
303 const int area =
304 std::min(max_width,
305 static_cast<int>(MediaStreamVideoSource::kDefaultWidth)) *
306 std::min(max_height,
307 static_cast<int>(MediaStreamVideoSource::kDefaultHeight));
308
309 return GetBestFormatBasedOnArea(formats, area);
310 }
311
312 } // anonymous namespace
313
314 bool IsOldVideoConstraints() {
315 return base::FeatureList::IsEnabled(
316 features::kMediaStreamOldVideoConstraints);
317 }
318
319 // static 26 // static
320 MediaStreamVideoSource* MediaStreamVideoSource::GetVideoSource( 27 MediaStreamVideoSource* MediaStreamVideoSource::GetVideoSource(
321 const blink::WebMediaStreamSource& source) { 28 const blink::WebMediaStreamSource& source) {
322 if (source.IsNull() || 29 if (source.IsNull() ||
323 source.GetType() != blink::WebMediaStreamSource::kTypeVideo) { 30 source.GetType() != blink::WebMediaStreamSource::kTypeVideo) {
324 return nullptr; 31 return nullptr;
325 } 32 }
326 return static_cast<MediaStreamVideoSource*>(source.GetExtraData()); 33 return static_cast<MediaStreamVideoSource*>(source.GetExtraData());
327 } 34 }
328 35
329 MediaStreamVideoSource::MediaStreamVideoSource() 36 MediaStreamVideoSource::MediaStreamVideoSource()
330 : state_(NEW), 37 : state_(NEW),
331 track_adapter_( 38 track_adapter_(
332 new VideoTrackAdapter(ChildProcess::current()->io_task_runner())), 39 new VideoTrackAdapter(ChildProcess::current()->io_task_runner())),
333 weak_factory_(this) {} 40 weak_factory_(this) {}
334 41
335 MediaStreamVideoSource::~MediaStreamVideoSource() { 42 MediaStreamVideoSource::~MediaStreamVideoSource() {
336 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); 43 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
337 } 44 }
338 45
339 void MediaStreamVideoSource::AddTrackLegacy(
340 MediaStreamVideoTrack* track,
341 const VideoCaptureDeliverFrameCB& frame_callback,
342 const blink::WebMediaConstraints& constraints,
343 const ConstraintsCallback& callback) {
344 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
345 DCHECK(IsOldVideoConstraints());
346 DCHECK(!constraints.IsNull());
347 DCHECK(std::find(tracks_.begin(), tracks_.end(), track) == tracks_.end());
348 tracks_.push_back(track);
349 secure_tracker_.Add(track, true);
350
351 track_descriptors_.push_back(
352 TrackDescriptor(track, frame_callback, constraints, callback));
353
354 switch (state_) {
355 case NEW: {
356 // Tab capture and Screen capture needs the maximum requested height
357 // and width to decide on the resolution.
358 // NOTE: Optional constraints are deliberately ignored.
359 int max_requested_width = 0;
360 if (constraints.Basic().width.HasMax())
361 max_requested_width = constraints.Basic().width.Max();
362
363 int max_requested_height = 0;
364 if (constraints.Basic().height.HasMax())
365 max_requested_height = constraints.Basic().height.Max();
366
367 double max_requested_frame_rate = kDefaultFrameRate;
368 if (constraints.Basic().frame_rate.HasMax())
369 max_requested_frame_rate = constraints.Basic().frame_rate.Max();
370
371 state_ = RETRIEVING_CAPABILITIES;
372 GetCurrentSupportedFormats(
373 max_requested_width,
374 max_requested_height,
375 max_requested_frame_rate,
376 base::Bind(&MediaStreamVideoSource::OnSupportedFormats,
377 weak_factory_.GetWeakPtr()));
378
379 break;
380 }
381 case STARTING:
382 case RETRIEVING_CAPABILITIES: {
383 // The |callback| will be triggered once the source has started or
384 // the capabilities have been retrieved.
385 break;
386 }
387 case ENDED:
388 case STARTED: {
389 // Currently, reconfiguring the source is not supported.
390 FinalizeAddTrackLegacy();
391 }
392 }
393 }
394
395 void MediaStreamVideoSource::AddTrack( 46 void MediaStreamVideoSource::AddTrack(
396 MediaStreamVideoTrack* track, 47 MediaStreamVideoTrack* track,
397 const VideoTrackAdapterSettings& track_adapter_settings, 48 const VideoTrackAdapterSettings& track_adapter_settings,
398 const VideoCaptureDeliverFrameCB& frame_callback, 49 const VideoCaptureDeliverFrameCB& frame_callback,
399 const ConstraintsCallback& callback) { 50 const ConstraintsCallback& callback) {
400 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); 51 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
401 DCHECK(std::find(tracks_.begin(), tracks_.end(), track) == tracks_.end()); 52 DCHECK(std::find(tracks_.begin(), tracks_.end(), track) == tracks_.end());
402 tracks_.push_back(track); 53 tracks_.push_back(track);
403 secure_tracker_.Add(track, true); 54 secure_tracker_.Add(track, true);
404 55
405 track_descriptors_.push_back(TrackDescriptor( 56 track_descriptors_.push_back(TrackDescriptor(
406 track, frame_callback, 57 track, frame_callback,
407 base::MakeUnique<VideoTrackAdapterSettings>(track_adapter_settings), 58 base::MakeUnique<VideoTrackAdapterSettings>(track_adapter_settings),
408 callback)); 59 callback));
409 60
410 switch (state_) { 61 switch (state_) {
411 case NEW: { 62 case NEW: {
412 state_ = STARTING; 63 state_ = STARTING;
413 blink::WebMediaConstraints ignored_constraints; 64 blink::WebMediaConstraints ignored_constraints;
414 StartSourceImpl( 65 StartSourceImpl(
415 media::VideoCaptureFormat() /* ignored */, ignored_constraints, 66 media::VideoCaptureFormat() /* ignored */, ignored_constraints,
416 base::Bind(&VideoTrackAdapter::DeliverFrameOnIO, track_adapter_)); 67 base::Bind(&VideoTrackAdapter::DeliverFrameOnIO, track_adapter_));
417 break; 68 break;
418 } 69 }
419 case STARTING: { 70 case STARTING: {
420 break; 71 break;
421 } 72 }
422 case RETRIEVING_CAPABILITIES: {
423 NOTREACHED();
424 break;
425 }
426 case ENDED: 73 case ENDED:
427 case STARTED: { 74 case STARTED: {
428 // Currently, reconfiguring the source is not supported. 75 // Currently, reconfiguring the source is not supported.
429 FinalizeAddTrack(); 76 FinalizeAddTrack();
430 } 77 }
431 } 78 }
432 } 79 }
433 80
434 void MediaStreamVideoSource::RemoveTrack(MediaStreamVideoTrack* video_track) { 81 void MediaStreamVideoSource::RemoveTrack(MediaStreamVideoTrack* video_track) {
435 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); 82 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
478 } 125 }
479 126
480 base::SingleThreadTaskRunner* MediaStreamVideoSource::io_task_runner() const { 127 base::SingleThreadTaskRunner* MediaStreamVideoSource::io_task_runner() const {
481 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); 128 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
482 return track_adapter_->io_task_runner(); 129 return track_adapter_->io_task_runner();
483 } 130 }
484 131
485 base::Optional<media::VideoCaptureFormat> 132 base::Optional<media::VideoCaptureFormat>
486 MediaStreamVideoSource::GetCurrentFormat() const { 133 MediaStreamVideoSource::GetCurrentFormat() const {
487 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); 134 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
488 if (IsOldVideoConstraints()) { 135 return GetCurrentFormatImpl();
489 if (state_ == STARTING || state_ == STARTED)
490 return current_format_;
491 return base::Optional<media::VideoCaptureFormat>();
492 } else {
493 return GetCurrentFormatImpl();
494 }
495 } 136 }
496 137
497 base::Optional<media::VideoCaptureFormat> 138 base::Optional<media::VideoCaptureFormat>
498 MediaStreamVideoSource::GetCurrentFormatImpl() const { 139 MediaStreamVideoSource::GetCurrentFormatImpl() const {
499 return base::Optional<media::VideoCaptureFormat>(); 140 return base::Optional<media::VideoCaptureFormat>();
500 } 141 }
501 142
502 void MediaStreamVideoSource::DoStopSource() { 143 void MediaStreamVideoSource::DoStopSource() {
503 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); 144 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
504 DVLOG(3) << "DoStopSource()"; 145 DVLOG(3) << "DoStopSource()";
505 if (state_ == ENDED) 146 if (state_ == ENDED)
506 return; 147 return;
507 track_adapter_->StopFrameMonitoring(); 148 track_adapter_->StopFrameMonitoring();
508 StopSourceImpl(); 149 StopSourceImpl();
509 state_ = ENDED; 150 state_ = ENDED;
510 SetReadyState(blink::WebMediaStreamSource::kReadyStateEnded); 151 SetReadyState(blink::WebMediaStreamSource::kReadyStateEnded);
511 } 152 }
512 153
513 void MediaStreamVideoSource::OnSupportedFormats(
514 const media::VideoCaptureFormats& formats) {
515 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
516 DCHECK(IsOldVideoConstraints());
517 DCHECK_EQ(RETRIEVING_CAPABILITIES, state_);
518
519 supported_formats_ = formats;
520 blink::WebMediaConstraints fulfilled_constraints;
521 if (!FindBestFormatWithConstraints(supported_formats_,
522 &current_format_,
523 &fulfilled_constraints)) {
524 SetReadyState(blink::WebMediaStreamSource::kReadyStateEnded);
525 DVLOG(3) << "OnSupportedFormats failed to find an usable format";
526 // This object can be deleted after calling FinalizeAddTrack. See comment
527 // in the header file.
528 FinalizeAddTrackLegacy();
529 return;
530 }
531
532 state_ = STARTING;
533 DVLOG(3) << "Starting the capturer with "
534 << media::VideoCaptureFormat::ToString(current_format_);
535
536 StartSourceImpl(
537 current_format_,
538 fulfilled_constraints,
539 base::Bind(&VideoTrackAdapter::DeliverFrameOnIO, track_adapter_));
540 }
541
542 bool MediaStreamVideoSource::FindBestFormatWithConstraints(
543 const media::VideoCaptureFormats& formats,
544 media::VideoCaptureFormat* best_format,
545 blink::WebMediaConstraints* fulfilled_constraints) {
546 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
547 DVLOG(3) << "MediaStreamVideoSource::FindBestFormatWithConstraints "
548 << "with " << formats.size() << " formats";
549 // Find the first track descriptor that can fulfil the constraints.
550 for (const auto& track : track_descriptors_) {
551 const blink::WebMediaConstraints& track_constraints = track.constraints;
552
553 // If the source doesn't support capability enumeration it is still ok if
554 // no mandatory constraints have been specified. That just means that
555 // we will start with whatever format is native to the source.
556 if (formats.empty() && !HasMandatoryConstraints(track_constraints)) {
557 DVLOG(3) << "No mandatory constraints and no formats";
558 *fulfilled_constraints = track_constraints;
559 *best_format = media::VideoCaptureFormat();
560 return true;
561 }
562 std::string unsatisfied_constraint;
563 const media::VideoCaptureFormats filtered_formats =
564 FilterFormats(track_constraints, formats, &unsatisfied_constraint);
565 if (filtered_formats.empty())
566 continue;
567
568 // A request with constraints that can be fulfilled.
569 *fulfilled_constraints = track_constraints;
570 media::VideoCaptureFormat best_format_candidate =
571 GetBestCaptureFormat(filtered_formats, track_constraints);
572 if (!best_format_candidate.IsValid())
573 continue;
574
575 *best_format = best_format_candidate;
576 DVLOG(3) << "Found a track that matches the constraints";
577 return true;
578 }
579 DVLOG(3) << "No usable format found";
580 return false;
581 }
582
583 void MediaStreamVideoSource::OnStartDone(MediaStreamRequestResult result) { 154 void MediaStreamVideoSource::OnStartDone(MediaStreamRequestResult result) {
584 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); 155 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
585 DVLOG(3) << "OnStartDone({result =" << result << "})"; 156 DVLOG(3) << "OnStartDone({result =" << result << "})";
586 if (result == MEDIA_DEVICE_OK) { 157 if (result == MEDIA_DEVICE_OK) {
587 DCHECK_EQ(STARTING, state_); 158 DCHECK_EQ(STARTING, state_);
588 state_ = STARTED; 159 state_ = STARTED;
589 SetReadyState(blink::WebMediaStreamSource::kReadyStateLive); 160 SetReadyState(blink::WebMediaStreamSource::kReadyStateLive);
590 double frame_rate = 161 double frame_rate =
591 GetCurrentFormat() ? GetCurrentFormat()->frame_rate : 0.0; 162 GetCurrentFormat() ? GetCurrentFormat()->frame_rate : 0.0;
592 track_adapter_->StartFrameMonitoring( 163 track_adapter_->StartFrameMonitoring(
593 frame_rate, base::Bind(&MediaStreamVideoSource::SetMutedState, 164 frame_rate, base::Bind(&MediaStreamVideoSource::SetMutedState,
594 weak_factory_.GetWeakPtr())); 165 weak_factory_.GetWeakPtr()));
595 } else { 166 } else {
596 StopSource(); 167 StopSource();
597 } 168 }
598 169
599 // This object can be deleted after calling FinalizeAddTrack. See comment in 170 // This object can be deleted after calling FinalizeAddTrack. See comment in
600 // the header file. 171 // the header file.
601 if (IsOldVideoConstraints()) 172 FinalizeAddTrack();
602 FinalizeAddTrackLegacy();
603 else
604 FinalizeAddTrack();
605 }
606
607 void MediaStreamVideoSource::FinalizeAddTrackLegacy() {
608 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
609 DCHECK(IsOldVideoConstraints());
610 const media::VideoCaptureFormats formats(1, current_format_);
611
612 std::vector<TrackDescriptor> track_descriptors;
613 track_descriptors.swap(track_descriptors_);
614 for (const auto& track : track_descriptors) {
615 MediaStreamRequestResult result = MEDIA_DEVICE_OK;
616 std::string unsatisfied_constraint;
617
618 if (HasMandatoryConstraints(track.constraints) &&
619 FilterFormats(track.constraints, formats, &unsatisfied_constraint)
620 .empty()) {
621 result = MEDIA_DEVICE_CONSTRAINT_NOT_SATISFIED;
622 DVLOG(3) << "FinalizeAddTrackLegacy() ignoring device on constraint "
623 << unsatisfied_constraint;
624 }
625
626 if (state_ != STARTED && result == MEDIA_DEVICE_OK)
627 result = MEDIA_DEVICE_TRACK_START_FAILURE;
628
629 if (result == MEDIA_DEVICE_OK) {
630 int max_width;
631 int max_height;
632 GetDesiredMaxWidthAndHeight(track.constraints, &max_width, &max_height);
633 double max_aspect_ratio;
634 double min_aspect_ratio;
635 GetDesiredMinAndMaxAspectRatio(track.constraints,
636 &min_aspect_ratio,
637 &max_aspect_ratio);
638 double max_frame_rate = 0.0f;
639 // Note: Optional and ideal constraints are ignored; this is
640 // purely a hard max limit.
641 if (track.constraints.Basic().frame_rate.HasMax())
642 max_frame_rate = track.constraints.Basic().frame_rate.Max();
643
644 track_adapter_->AddTrack(
645 track.track, track.frame_callback,
646 VideoTrackAdapterSettings(max_width, max_height, min_aspect_ratio,
647 max_aspect_ratio, max_frame_rate,
648 base::Optional<gfx::Size>()));
649 // Calculate resulting frame size if the source delivers frames
650 // according to the current format. Note: Format may change later.
651 gfx::Size desired_size;
652 VideoTrackAdapter::CalculateTargetSize(
653 false /* is_rotated */, current_format_.frame_size,
654 gfx::Size(max_width, max_height), min_aspect_ratio, max_aspect_ratio,
655 &desired_size);
656 track.track->SetTargetSizeAndFrameRate(
657 desired_size.width(), desired_size.height(), max_frame_rate);
658 }
659
660 DVLOG(3) << "FinalizeAddTrackLegacy() result " << result;
661
662 if (!track.callback.is_null())
663 track.callback.Run(this, result,
664 blink::WebString::FromUTF8(unsatisfied_constraint));
665 }
666 } 173 }
667 174
668 void MediaStreamVideoSource::FinalizeAddTrack() { 175 void MediaStreamVideoSource::FinalizeAddTrack() {
669 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); 176 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
670 DCHECK(!IsOldVideoConstraints());
671 std::vector<TrackDescriptor> track_descriptors; 177 std::vector<TrackDescriptor> track_descriptors;
672 track_descriptors.swap(track_descriptors_); 178 track_descriptors.swap(track_descriptors_);
673 for (const auto& track : track_descriptors) { 179 for (const auto& track : track_descriptors) {
674 MediaStreamRequestResult result = MEDIA_DEVICE_OK; 180 MediaStreamRequestResult result = MEDIA_DEVICE_OK;
675 if (state_ != STARTED) 181 if (state_ != STARTED)
676 result = MEDIA_DEVICE_TRACK_START_FAILURE; 182 result = MEDIA_DEVICE_TRACK_START_FAILURE;
677 183
678 if (result == MEDIA_DEVICE_OK) { 184 if (result == MEDIA_DEVICE_OK) {
679 track_adapter_->AddTrack(track.track, track.frame_callback, 185 track_adapter_->AddTrack(track.track, track.frame_callback,
680 *track.adapter_settings); 186 *track.adapter_settings);
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
717 if (!Owner().IsNull()) { 223 if (!Owner().IsNull()) {
718 Owner().SetReadyState(muted_state 224 Owner().SetReadyState(muted_state
719 ? blink::WebMediaStreamSource::kReadyStateMuted 225 ? blink::WebMediaStreamSource::kReadyStateMuted
720 : blink::WebMediaStreamSource::kReadyStateLive); 226 : blink::WebMediaStreamSource::kReadyStateLive);
721 } 227 }
722 } 228 }
723 229
724 MediaStreamVideoSource::TrackDescriptor::TrackDescriptor( 230 MediaStreamVideoSource::TrackDescriptor::TrackDescriptor(
725 MediaStreamVideoTrack* track, 231 MediaStreamVideoTrack* track,
726 const VideoCaptureDeliverFrameCB& frame_callback, 232 const VideoCaptureDeliverFrameCB& frame_callback,
727 const blink::WebMediaConstraints& constraints,
728 const ConstraintsCallback& callback)
729 : track(track),
730 frame_callback(frame_callback),
731 constraints(constraints),
732 callback(callback) {
733 DCHECK(IsOldVideoConstraints());
734 }
735
736 MediaStreamVideoSource::TrackDescriptor::TrackDescriptor(
737 MediaStreamVideoTrack* track,
738 const VideoCaptureDeliverFrameCB& frame_callback,
739 std::unique_ptr<VideoTrackAdapterSettings> adapter_settings, 233 std::unique_ptr<VideoTrackAdapterSettings> adapter_settings,
740 const ConstraintsCallback& callback) 234 const ConstraintsCallback& callback)
741 : track(track), 235 : track(track),
742 frame_callback(frame_callback), 236 frame_callback(frame_callback),
743 adapter_settings(std::move(adapter_settings)), 237 adapter_settings(std::move(adapter_settings)),
744 callback(callback) { 238 callback(callback) {}
745 DCHECK(!IsOldVideoConstraints());
746 }
747 239
748 MediaStreamVideoSource::TrackDescriptor::TrackDescriptor( 240 MediaStreamVideoSource::TrackDescriptor::TrackDescriptor(
749 TrackDescriptor&& other) = default; 241 TrackDescriptor&& other) = default;
750 MediaStreamVideoSource::TrackDescriptor& 242 MediaStreamVideoSource::TrackDescriptor&
751 MediaStreamVideoSource::TrackDescriptor::operator=( 243 MediaStreamVideoSource::TrackDescriptor::operator=(
752 MediaStreamVideoSource::TrackDescriptor&& other) = default; 244 MediaStreamVideoSource::TrackDescriptor&& other) = default;
753 245
754 MediaStreamVideoSource::TrackDescriptor::~TrackDescriptor() { 246 MediaStreamVideoSource::TrackDescriptor::~TrackDescriptor() {
755 } 247 }
756 248
757 } // namespace content 249 } // namespace content
OLDNEW
« no previous file with comments | « content/renderer/media/media_stream_video_source.h ('k') | content/renderer/media/media_stream_video_source_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698