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

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

Issue 1617243005: Apply new-style constraints to video_source. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Add <vector> include Created 4 years, 11 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 <string> 9 #include <string>
10 10
11 #include "base/logging.h" 11 #include "base/logging.h"
12 #include "base/macros.h" 12 #include "base/macros.h"
13 #include "base/strings/string_number_conversions.h" 13 #include "base/strings/string_number_conversions.h"
14 #include "base/trace_event/trace_event.h" 14 #include "base/trace_event/trace_event.h"
15 #include "content/child/child_process.h" 15 #include "content/child/child_process.h"
16 #include "content/renderer/media/media_stream_constraints_util.h"
17 #include "content/renderer/media/media_stream_video_track.h" 16 #include "content/renderer/media/media_stream_video_track.h"
18 #include "content/renderer/media/video_track_adapter.h" 17 #include "content/renderer/media/video_track_adapter.h"
19 18
20 namespace content { 19 namespace content {
21 20
22 // Constraint keys. Specified by draft-alvestrand-constraints-resolution-00b 21 // Constraint keys. Specified by draft-alvestrand-constraints-resolution-00b
23 const char MediaStreamVideoSource::kMinAspectRatio[] = "minAspectRatio"; 22 const char MediaStreamVideoSource::kMinAspectRatio[] = "minAspectRatio";
24 const char MediaStreamVideoSource::kMaxAspectRatio[] = "maxAspectRatio"; 23 const char MediaStreamVideoSource::kMaxAspectRatio[] = "maxAspectRatio";
25 const char MediaStreamVideoSource::kMaxWidth[] = "maxWidth"; 24 const char MediaStreamVideoSource::kMaxWidth[] = "maxWidth";
26 const char MediaStreamVideoSource::kMinWidth[] = "minWidth"; 25 const char MediaStreamVideoSource::kMinWidth[] = "minWidth";
27 const char MediaStreamVideoSource::kMaxHeight[] = "maxHeight"; 26 const char MediaStreamVideoSource::kMaxHeight[] = "maxHeight";
28 const char MediaStreamVideoSource::kMinHeight[] = "minHeight"; 27 const char MediaStreamVideoSource::kMinHeight[] = "minHeight";
29 const char MediaStreamVideoSource::kMaxFrameRate[] = "maxFrameRate"; 28 const char MediaStreamVideoSource::kMaxFrameRate[] = "maxFrameRate";
30 const char MediaStreamVideoSource::kMinFrameRate[] = "minFrameRate"; 29 const char MediaStreamVideoSource::kMinFrameRate[] = "minFrameRate";
31 30
32 // TODO(mcasas): Find a way to guarantee all constraints are added to the array. 31 // TODO(mcasas): Find a way to guarantee all constraints are added to the array.
33 const char* kSupportedConstraints[] = { 32 const char* kSupportedConstraints[] = {
34 MediaStreamVideoSource::kMaxAspectRatio, 33 MediaStreamVideoSource::kMaxAspectRatio,
35 MediaStreamVideoSource::kMinAspectRatio, 34 MediaStreamVideoSource::kMinAspectRatio,
36 MediaStreamVideoSource::kMaxWidth, 35 MediaStreamVideoSource::kMaxWidth,
37 MediaStreamVideoSource::kMinWidth, 36 MediaStreamVideoSource::kMinWidth,
38 MediaStreamVideoSource::kMaxHeight, 37 MediaStreamVideoSource::kMaxHeight,
39 MediaStreamVideoSource::kMinHeight, 38 MediaStreamVideoSource::kMinHeight,
40 MediaStreamVideoSource::kMaxFrameRate, 39 MediaStreamVideoSource::kMaxFrameRate,
41 MediaStreamVideoSource::kMinFrameRate, 40 MediaStreamVideoSource::kMinFrameRate,
42 }; 41 };
43 42
44 namespace { 43 namespace {
45 44
45 const char* kLegalVideoConstraints[] = {
46 "width", "height", "aspectRatio", "frameRate",
47 "facingMode", "deviceId", "groupId", "mediaStreamSource",
48 };
49
46 // Google-specific key prefix. Constraints with this prefix are ignored if they 50 // Google-specific key prefix. Constraints with this prefix are ignored if they
47 // are unknown. 51 // are unknown.
48 const char kGooglePrefix[] = "goog"; 52 // const char kGooglePrefix[] = "goog";
mcasas 2016/01/26 16:08:02 Remove.
hta - Chromium 2016/01/26 19:35:24 Done.
49 53
50 // Returns true if |constraint| has mandatory constraints. 54 // Returns true if |constraint| has mandatory constraints.
51 bool HasMandatoryConstraints(const blink::WebMediaConstraints& constraints) { 55 bool HasMandatoryConstraints(const blink::WebMediaConstraints& constraints) {
52 blink::WebVector<blink::WebMediaConstraint> mandatory_constraints; 56 return constraints.basic().hasMandatory();
53 constraints.getMandatoryConstraints(mandatory_constraints);
54 return !mandatory_constraints.isEmpty();
55 } 57 }
56 58
57 // Retrieve the desired max width and height from |constraints|. If not set, 59 // Retrieve the desired max width and height from |constraints|. If not set,
58 // the |desired_width| and |desired_height| are set to 60 // the |desired_width| and |desired_height| are set to
59 // std::numeric_limits<int>::max(); 61 // std::numeric_limits<int>::max();
60 // If either max width or height is set as a mandatory constraint, the optional 62 // If either max width or height is set as a mandatory constraint, the optional
61 // constraints are not checked. 63 // constraints are not checked.
62 void GetDesiredMaxWidthAndHeight(const blink::WebMediaConstraints& constraints, 64 void GetDesiredMaxWidthAndHeight(const blink::WebMediaConstraints& constraints,
63 int* desired_width, int* desired_height) { 65 int* desired_width, int* desired_height) {
64 *desired_width = std::numeric_limits<int>::max(); 66 *desired_width = std::numeric_limits<int>::max();
65 *desired_height = std::numeric_limits<int>::max(); 67 *desired_height = std::numeric_limits<int>::max();
66 68
67 bool mandatory = GetMandatoryConstraintValueAsInteger( 69 const auto& basic_constraints = constraints.basic();
68 constraints, 70 if (basic_constraints.width.hasMax() || basic_constraints.height.hasMax()) {
69 MediaStreamVideoSource::kMaxWidth, 71 if (basic_constraints.width.hasMax())
70 desired_width); 72 *desired_width = basic_constraints.width.max();
71 mandatory |= GetMandatoryConstraintValueAsInteger( 73 if (basic_constraints.height.hasMax())
72 constraints, 74 *desired_height = basic_constraints.height.max();
73 MediaStreamVideoSource::kMaxHeight,
74 desired_height);
75 if (mandatory)
76 return; 75 return;
76 }
77 77
78 GetOptionalConstraintValueAsInteger(constraints, 78 for (const auto& constraint_set : constraints.advanced()) {
79 MediaStreamVideoSource::kMaxWidth, 79 if (constraint_set.width.hasMax())
80 desired_width); 80 *desired_width = constraint_set.width.max();
81 GetOptionalConstraintValueAsInteger(constraints, 81 if (constraint_set.height.hasMax())
82 MediaStreamVideoSource::kMaxHeight, 82 *desired_height = constraint_set.height.max();
83 desired_height); 83 }
84 } 84 }
85 85
86 // Retrieve the desired max and min aspect ratio from |constraints|. If not set, 86 // Retrieve the desired max and min aspect ratio from |constraints|. If not set,
87 // the |min_aspect_ratio| is set to 0 and |max_aspect_ratio| is set to 87 // the |min_aspect_ratio| is set to 0 and |max_aspect_ratio| is set to
88 // std::numeric_limits<double>::max(); 88 // std::numeric_limits<double>::max();
89 // If either min or max aspect ratio is set as a mandatory constraint, the 89 // If either min or max aspect ratio is set as a mandatory constraint, the
90 // optional constraints are not checked. 90 // optional constraints are not checked.
91 void GetDesiredMinAndMaxAspectRatio( 91 void GetDesiredMinAndMaxAspectRatio(
92 const blink::WebMediaConstraints& constraints, 92 const blink::WebMediaConstraints& constraints,
93 double* min_aspect_ratio, 93 double* min_aspect_ratio,
94 double* max_aspect_ratio) { 94 double* max_aspect_ratio) {
95 *min_aspect_ratio = 0; 95 *min_aspect_ratio = 0;
96 *max_aspect_ratio = std::numeric_limits<double>::max(); 96 *max_aspect_ratio = std::numeric_limits<double>::max();
97 97
98 bool mandatory = GetMandatoryConstraintValueAsDouble( 98 if (constraints.basic().aspectRatio.hasMin() ||
99 constraints, 99 constraints.basic().aspectRatio.hasMax()) {
100 MediaStreamVideoSource::kMinAspectRatio, 100 if (constraints.basic().aspectRatio.hasMin())
101 min_aspect_ratio); 101 *min_aspect_ratio = constraints.basic().aspectRatio.min();
102 mandatory |= GetMandatoryConstraintValueAsDouble( 102 if (constraints.basic().aspectRatio.hasMax())
103 constraints, 103 *max_aspect_ratio = constraints.basic().aspectRatio.max();
104 MediaStreamVideoSource::kMaxAspectRatio,
105 max_aspect_ratio);
106 if (mandatory)
107 return; 104 return;
108 105 // Note - the code will ignore attempts at successive refinement
109 GetOptionalConstraintValueAsDouble(constraints, 106 // of the aspect ratio with advanced constraint. This may be wrong.
110 MediaStreamVideoSource::kMinAspectRatio, 107 }
111 min_aspect_ratio); 108 // Note - the code below will potentially pick min and max from different
112 GetOptionalConstraintValueAsDouble(constraints, 109 // constraint sets, some of which might have been ignored.
113 MediaStreamVideoSource::kMaxAspectRatio, 110 for (const auto& constraint_set : constraints.advanced()) {
114 max_aspect_ratio); 111 if (constraint_set.aspectRatio.hasMin()) {
112 *min_aspect_ratio = constraint_set.aspectRatio.min();
113 break;
114 }
115 }
116 for (const auto& constraint_set : constraints.advanced()) {
117 if (constraint_set.aspectRatio.hasMax()) {
118 *max_aspect_ratio = constraint_set.aspectRatio.max();
119 break;
120 }
121 }
115 } 122 }
116 123
117 // Returns true if |constraint| is fulfilled. |format| can be changed by a 124 // Returns true if |constraint| is fulfilled. |format| can be changed by a
mcasas 2016/01/26 16:08:01 Update comment: |constraint| is no longer there.
hta - Chromium 2016/01/26 19:35:24 Done.
118 // constraint, e.g. the frame rate can be changed by setting maxFrameRate. 125 // constraint, e.g. the frame rate can be changed by setting maxFrameRate.
119 bool UpdateFormatForConstraint(const blink::WebMediaConstraint& constraint, 126 bool UpdateFormatForConstraints(
120 bool mandatory, 127 const blink::WebMediaTrackConstraintSet& constraints,
121 media::VideoCaptureFormat* format) { 128 media::VideoCaptureFormat* format,
129 blink::WebString* failing_constraint_name_out) {
122 DCHECK(format != NULL); 130 DCHECK(format != NULL);
123 131
124 if (!format->IsValid()) 132 if (!format->IsValid())
125 return false; 133 return false;
126 134
127 const std::string constraint_name = constraint.m_name.utf8(); 135 const char* failing_constraint_name = nullptr;
128 const std::string constraint_value = constraint.m_value.utf8();
129 136
130 if (constraint_name.find(kGooglePrefix) == 0) { 137 DVLOG(3) << "Checking constraints against source with width "
131 // These are actually options, not constraints, so they can be satisfied 138 << format->frame_size.width() << ", height "
132 // regardless of the format. 139 << format->frame_size.height();
133 return true; 140 if (constraints.width.hasMin())
134 } 141 DVLOG(3) << "Constraint width min is " << constraints.width.min();
mcasas 2016/01/26 16:08:02 Prefer DVLOG_IF(3, constraints.width.hasMin()) <<
hta - Chromium 2016/01/26 19:35:24 Removed.
135 142 // The width and height are matched based on cropping occuring later:
136 if (constraint_name == MediaStreamSource::kSourceId) { 143 // min width/height has to be >= the size of the frame (no upscale).
137 // This is a constraint that doesn't affect the format. 144 // max width/height just has to be > 0 (we can crop anything too large).
138 return true; 145 if ((constraints.width.hasMin() &&
139 } 146 constraints.width.min() > format->frame_size.width()) ||
140 147 (constraints.width.hasMax() && constraints.width.max() <= 0))
jochen (gone - plz use gerrit) 2016/01/26 17:10:13 please add {} around bodies
hta - Chromium 2016/01/26 19:35:24 Removed instead.
141 // Ignore Chrome specific Tab capture constraints. 148 failing_constraint_name = constraints.width.name();
142 if (constraint_name == kMediaStreamSource || 149 else if ((constraints.height.hasMin() &&
143 constraint_name == kMediaStreamSourceId) 150 constraints.height.min() > format->frame_size.height()) ||
151 (constraints.height.hasMax() && constraints.height.max() <= 0))
152 failing_constraint_name = constraints.height.name();
153 else if (!constraints.frameRate.matches(format->frame_rate)) {
154 if (constraints.frameRate.hasMax()) {
155 double value = constraints.frameRate.max();
mcasas 2016/01/26 16:08:01 const
hta - Chromium 2016/01/26 19:35:24 Done.
156 // TODO(hta): Check if handling of max = 0.0 is relevant.
157 // (old handling was to set rate to 1.0 if 0.0 was specified)
158 if (constraints.frameRate.matches(value)) {
159 format->frame_rate =
160 (format->frame_rate > value) ? value : format->frame_rate;
161 return true;
162 }
163 }
164 failing_constraint_name = constraints.frameRate.name();
165 } else
144 return true; 166 return true;
mcasas 2016/01/26 16:08:01 If one side of the conditional has {}, the other m
145 167
146 if (constraint_name == MediaStreamVideoSource::kMinAspectRatio || 168 DCHECK(failing_constraint_name);
147 constraint_name == MediaStreamVideoSource::kMaxAspectRatio) { 169 if (failing_constraint_name_out)
148 // These constraints are handled by cropping if the camera outputs the wrong 170 *failing_constraint_name_out =
149 // aspect ratio. 171 blink::WebString::fromUTF8(failing_constraint_name);
mcasas 2016/01/26 16:08:01 Multi-line if bodies must have {}
hta - Chromium 2016/01/26 19:35:24 It wasn't a multiline body until git cl format tou
150 double value;
151 return base::StringToDouble(constraint_value, &value);
152 }
153 172
154 double value = 0.0; 173 DVLOG(3) << "UpdateFormatForConstraints failing on "
155 if (!base::StringToDouble(constraint_value, &value)) { 174 << failing_constraint_name;
mcasas 2016/01/26 16:08:01 What about DLOG(ERROR) or DLOG(WARNING)?
hta - Chromium 2016/01/26 19:35:24 Removed. It's a normal thing - happens for every f
156 DLOG(WARNING) << "Can't parse MediaStream constraint. Name:" 175 return false;
157 << constraint_name << " Value:" << constraint_value;
158 return false;
159 }
160
161 if (constraint_name == MediaStreamVideoSource::kMinWidth) {
162 return (value <= format->frame_size.width());
163 } else if (constraint_name == MediaStreamVideoSource::kMaxWidth) {
164 return value > 0.0;
165 } else if (constraint_name == MediaStreamVideoSource::kMinHeight) {
166 return (value <= format->frame_size.height());
167 } else if (constraint_name == MediaStreamVideoSource::kMaxHeight) {
168 return value > 0.0;
169 } else if (constraint_name == MediaStreamVideoSource::kMinFrameRate) {
170 return (value > 0.0) && (value <= format->frame_rate);
171 } else if (constraint_name == MediaStreamVideoSource::kMaxFrameRate) {
172 if (value <= 0.0) {
173 // The frame rate is set by constraint.
174 // Don't allow 0 as frame rate if it is a mandatory constraint.
175 // Set the frame rate to 1 if it is not mandatory.
176 if (mandatory) {
177 return false;
178 } else {
179 value = 1.0;
180 }
181 }
182 format->frame_rate =
183 (format->frame_rate > value) ? value : format->frame_rate;
184 return true;
185 } else {
186 LOG(WARNING) << "Found unknown MediaStream constraint. Name:"
187 << constraint_name << " Value:" << constraint_value;
188 return false;
189 }
190 } 176 }
191 177
192 // Removes media::VideoCaptureFormats from |formats| that don't meet 178 // Removes media::VideoCaptureFormats from |formats| that don't meet
193 // |constraint|. 179 // |constraint|.
mcasas 2016/01/26 16:08:02 Update comment.
hta - Chromium 2016/01/26 19:35:24 Done.
194 void FilterFormatsByConstraint(const blink::WebMediaConstraint& constraint, 180 void FilterFormatsByConstraints(
195 bool mandatory, 181 const blink::WebMediaTrackConstraintSet& constraints,
196 media::VideoCaptureFormats* formats) { 182 media::VideoCaptureFormats* formats,
197 DVLOG(3) << "FilterFormatsByConstraint(" 183 blink::WebString* failing_constraint_name) {
198 << "{ constraint.m_name = " << constraint.m_name.utf8()
199 << " constraint.m_value = " << constraint.m_value.utf8()
200 << " mandatory = " << mandatory << "})";
201 media::VideoCaptureFormats::iterator format_it = formats->begin(); 184 media::VideoCaptureFormats::iterator format_it = formats->begin();
202 while (format_it != formats->end()) { 185 while (format_it != formats->end()) {
203 // Modify the format_it to fulfill the constraint if possible. 186 // Modify the format_it to fulfill the constraint if possible.
204 // Delete it otherwise. 187 // Delete it otherwise.
205 if (!UpdateFormatForConstraint(constraint, mandatory, &(*format_it))) 188 if (!UpdateFormatForConstraints(constraints, &(*format_it),
189 failing_constraint_name)) {
206 format_it = formats->erase(format_it); 190 format_it = formats->erase(format_it);
207 else 191 DVLOG(3) << "FilterFormatsByConstraints eliminating one";
192 } else {
208 ++format_it; 193 ++format_it;
194 }
209 } 195 }
mcasas 2016/01/26 16:08:01 Couldn't we use something like: std::remove_if(
hta - Chromium 2016/01/26 19:35:24 UpdateFormatsForConstraints has two parameters, re
210 } 196 }
211 197
212 // Returns the media::VideoCaptureFormats that matches |constraints|. 198 // Returns the media::VideoCaptureFormats that matches |constraints|.
213 media::VideoCaptureFormats FilterFormats( 199 media::VideoCaptureFormats FilterFormats(
214 const blink::WebMediaConstraints& constraints, 200 const blink::WebMediaConstraints& constraints,
215 const media::VideoCaptureFormats& supported_formats, 201 const media::VideoCaptureFormats& supported_formats,
216 blink::WebString* unsatisfied_constraint) { 202 blink::WebString* unsatisfied_constraint) {
217 if (constraints.isNull()) 203 if (constraints.isNull())
218 return supported_formats; 204 return supported_formats;
219 205
206 const auto& basic = constraints.basic();
207
208 // Do some checks that won't be done when filtering candidates.
209
210 if (basic.width.hasMin() && basic.width.hasMax() &&
211 basic.width.min() > basic.width.max()) {
212 if (unsatisfied_constraint)
213 *unsatisfied_constraint = blink::WebString::fromUTF8(basic.width.name());
214 return media::VideoCaptureFormats();
215 }
216
217 if (basic.height.hasMin() && basic.height.hasMax() &&
218 basic.height.min() > basic.height.max()) {
219 if (unsatisfied_constraint)
220 *unsatisfied_constraint = blink::WebString::fromUTF8(basic.height.name());
221 return media::VideoCaptureFormats();
222 }
223
220 double max_aspect_ratio; 224 double max_aspect_ratio;
221 double min_aspect_ratio; 225 double min_aspect_ratio;
222 GetDesiredMinAndMaxAspectRatio(constraints, 226 GetDesiredMinAndMaxAspectRatio(constraints,
223 &min_aspect_ratio, 227 &min_aspect_ratio,
224 &max_aspect_ratio); 228 &max_aspect_ratio);
225 229
226 if (min_aspect_ratio > max_aspect_ratio || max_aspect_ratio < 0.05f) { 230 if (min_aspect_ratio > max_aspect_ratio || max_aspect_ratio < 0.05f) {
mcasas 2016/01/26 16:08:02 Shouldn't |0.05f| be a constant defined in an anon
hta - Chromium 2016/01/26 19:35:24 Probably should. And 1:20 is a strange limit - the
227 DLOG(WARNING) << "Wrong requested aspect ratio."; 231 DLOG(WARNING) << "Wrong requested aspect ratio: min " << min_aspect_ratio
232 << " max " << max_aspect_ratio;
233 if (unsatisfied_constraint)
234 *unsatisfied_constraint =
235 blink::WebString::fromUTF8(basic.aspectRatio.name());
mcasas 2016/01/26 16:08:01 Multi line bodies should be inside {}
hta - Chromium 2016/01/26 19:35:24 Done. But those 3 lines should really be a helper.
228 return media::VideoCaptureFormats(); 236 return media::VideoCaptureFormats();
229 } 237 }
230 238
231 int min_width = 0; 239 std::vector<std::string> temp(
232 GetMandatoryConstraintValueAsInteger(constraints, 240 &kLegalVideoConstraints[0],
233 MediaStreamVideoSource::kMinWidth, 241 &kLegalVideoConstraints[sizeof(kLegalVideoConstraints) /
234 &min_width); 242 sizeof(kLegalVideoConstraints[0])]);
235 int min_height = 0; 243 std::string failing_name;
236 GetMandatoryConstraintValueAsInteger(constraints, 244 if (basic.hasMandatoryOutsideSet(temp, failing_name)) {
237 MediaStreamVideoSource::kMinHeight, 245 if (unsatisfied_constraint)
238 &min_height); 246 *unsatisfied_constraint = blink::WebString::fromUTF8(failing_name);
239 int max_width;
240 int max_height;
241 GetDesiredMaxWidthAndHeight(constraints, &max_width, &max_height);
242
243 if (min_width > max_width || min_height > max_height)
244 return media::VideoCaptureFormats(); 247 return media::VideoCaptureFormats();
245
246 double min_frame_rate = 0.0f;
247 double max_frame_rate = 0.0f;
248 if (GetConstraintValueAsDouble(constraints,
249 MediaStreamVideoSource::kMaxFrameRate,
250 &max_frame_rate) &&
251 GetConstraintValueAsDouble(constraints,
252 MediaStreamVideoSource::kMinFrameRate,
253 &min_frame_rate)) {
254 if (min_frame_rate > max_frame_rate) {
255 DLOG(WARNING) << "Wrong requested frame rate.";
256 return media::VideoCaptureFormats();
257 }
258 } 248 }
259 249
260 blink::WebVector<blink::WebMediaConstraint> mandatory;
261 blink::WebVector<blink::WebMediaConstraint> optional;
262 constraints.getMandatoryConstraints(mandatory);
263 constraints.getOptionalConstraints(optional);
264 media::VideoCaptureFormats candidates = supported_formats; 250 media::VideoCaptureFormats candidates = supported_formats;
265 for (const auto& constraint : mandatory) { 251 FilterFormatsByConstraints(basic, &candidates, unsatisfied_constraint);
266 FilterFormatsByConstraint(constraint, true, &candidates);
267 if (candidates.empty()) {
268 *unsatisfied_constraint = constraint.m_name;
269 return candidates;
270 }
271 }
272 252
273 if (candidates.empty()) 253 if (candidates.empty())
274 return candidates; 254 return candidates;
275 255
276 // Ok - all mandatory checked and we still have candidates. 256 // Ok - all mandatory checked and we still have candidates.
277 // Let's try filtering using the optional constraints. The optional 257 // Let's try filtering using the advanced constraints. The advanced
278 // constraints must be filtered in the order they occur in |optional|. 258 // constraints must be filtered in the order they occur in |advanced|.
279 // But if a constraint produce zero candidates, the constraint is ignored and 259 // But if a constraint produce zero candidates, the constraint is ignored and
280 // the next constraint is tested. 260 // the next constraint is tested.
281 // http://dev.w3.org/2011/webrtc/editor/getusermedia.html#idl-def-Constraints 261 // http://dev.w3.org/2011/webrtc/editor/getusermedia.html#idl-def-Constraints
mcasas 2016/01/26 16:08:01 Perhaps update this ref, might be stale. (2011 :?
hta - Chromium 2016/01/26 19:35:24 The 2011 is part of the W3C naming system for stab
282 for (const auto& constraint : optional) { 262 const blink::WebVector<blink::WebMediaTrackConstraintSet>& advanced =
263 constraints.advanced();
264
265 for (const auto& constraint_set : advanced) {
283 media::VideoCaptureFormats current_candidates = candidates; 266 media::VideoCaptureFormats current_candidates = candidates;
284 FilterFormatsByConstraint(constraint, false, &current_candidates); 267 FilterFormatsByConstraints(constraint_set, &current_candidates, nullptr);
285 if (!current_candidates.empty()) 268 if (!current_candidates.empty())
286 candidates = current_candidates; 269 candidates = current_candidates;
287 } 270 }
288 271
289 // We have done as good as we can to filter the supported resolutions. 272 // We have done as good as we can to filter the supported resolutions.
290 return candidates; 273 return candidates;
291 } 274 }
292 275
293 media::VideoCaptureFormat GetBestFormatBasedOnArea( 276 media::VideoCaptureFormat GetBestFormatBasedOnArea(
294 const media::VideoCaptureFormats& formats, 277 const media::VideoCaptureFormats& formats,
295 int area) { 278 int area) {
296 DCHECK(!formats.empty()); 279 DCHECK(!formats.empty());
297 const media::VideoCaptureFormat* best_format = nullptr; 280 const media::VideoCaptureFormat* best_format = nullptr;
298 int best_diff = std::numeric_limits<int>::max(); 281 int best_diff = std::numeric_limits<int>::max();
299 for (const auto& format : formats) { 282 for (const auto& format : formats) {
300 const int diff = abs(area - format.frame_size.GetArea()); 283 const int diff = abs(area - format.frame_size.GetArea());
301 if (diff < best_diff) { 284 if (diff < best_diff) {
302 best_diff = diff; 285 best_diff = diff;
303 best_format = &format; 286 best_format = &format;
304 } 287 }
305 } 288 }
289 DVLOG(3) << "GetBestFormatBasedOnArea chose format "
290 << media::VideoCaptureFormat::ToString(*best_format);
306 return *best_format; 291 return *best_format;
307 } 292 }
308 293
309 // Find the format that best matches the default video size. 294 // Find the format that best matches the default video size.
310 // This algorithm is chosen since a resolution must be picked even if no 295 // This algorithm is chosen since a resolution must be picked even if no
311 // constraints are provided. We don't just select the maximum supported 296 // constraints are provided. We don't just select the maximum supported
312 // resolution since higher resolutions cost more in terms of complexity and 297 // resolution since higher resolutions cost more in terms of complexity and
313 // many cameras have lower frame rate and have more noise in the image at 298 // many cameras have lower frame rate and have more noise in the image at
314 // their maximum supported resolution. 299 // their maximum supported resolution.
315 media::VideoCaptureFormat GetBestCaptureFormat( 300 media::VideoCaptureFormat GetBestCaptureFormat(
(...skipping 14 matching lines...) Expand all
330 } 315 }
331 316
332 } // anonymous namespace 317 } // anonymous namespace
333 318
334 // static 319 // static
335 MediaStreamVideoSource* MediaStreamVideoSource::GetVideoSource( 320 MediaStreamVideoSource* MediaStreamVideoSource::GetVideoSource(
336 const blink::WebMediaStreamSource& source) { 321 const blink::WebMediaStreamSource& source) {
337 return static_cast<MediaStreamVideoSource*>(source.extraData()); 322 return static_cast<MediaStreamVideoSource*>(source.extraData());
338 } 323 }
339 324
340 // static 325 // static, deprecated
341 bool MediaStreamVideoSource::IsConstraintSupported(const std::string& name) { 326 bool MediaStreamVideoSource::IsConstraintSupported(const std::string& name) {
342 return std::find(kSupportedConstraints, 327 return std::find(kSupportedConstraints,
343 kSupportedConstraints + arraysize(kSupportedConstraints), 328 kSupportedConstraints + arraysize(kSupportedConstraints),
344 name) != 329 name) !=
345 kSupportedConstraints + arraysize(kSupportedConstraints); 330 kSupportedConstraints + arraysize(kSupportedConstraints);
346 } 331 }
347 332
348 MediaStreamVideoSource::MediaStreamVideoSource() 333 MediaStreamVideoSource::MediaStreamVideoSource()
349 : state_(NEW), 334 : state_(NEW),
350 track_adapter_( 335 track_adapter_(
(...skipping 16 matching lines...) Expand all
367 tracks_.push_back(track); 352 tracks_.push_back(track);
368 353
369 track_descriptors_.push_back( 354 track_descriptors_.push_back(
370 TrackDescriptor(track, frame_callback, constraints, callback)); 355 TrackDescriptor(track, frame_callback, constraints, callback));
371 356
372 switch (state_) { 357 switch (state_) {
373 case NEW: { 358 case NEW: {
374 // Tab capture and Screen capture needs the maximum requested height 359 // Tab capture and Screen capture needs the maximum requested height
375 // and width to decide on the resolution. 360 // and width to decide on the resolution.
376 int max_requested_width = 0; 361 int max_requested_width = 0;
377 GetMandatoryConstraintValueAsInteger(constraints, kMaxWidth, 362 if (constraints.basic().width.hasMax())
378 &max_requested_width); 363 max_requested_width = constraints.basic().width.max();
379 364
380 int max_requested_height = 0; 365 int max_requested_height = 0;
381 GetMandatoryConstraintValueAsInteger(constraints, kMaxHeight, 366 if (constraints.basic().height.hasMax())
382 &max_requested_height); 367 max_requested_height = constraints.basic().height.max();
383 368
384 double max_requested_frame_rate = kDefaultFrameRate; 369 double max_requested_frame_rate = kDefaultFrameRate;
385 GetConstraintValueAsDouble(constraints, kMaxFrameRate, 370 if (constraints.basic().frameRate.hasMax())
386 &max_requested_frame_rate); 371 max_requested_frame_rate = constraints.basic().frameRate.max();
387 372
388 state_ = RETRIEVING_CAPABILITIES; 373 state_ = RETRIEVING_CAPABILITIES;
389 GetCurrentSupportedFormats( 374 GetCurrentSupportedFormats(
390 max_requested_width, 375 max_requested_width,
391 max_requested_height, 376 max_requested_height,
392 max_requested_frame_rate, 377 max_requested_frame_rate,
393 base::Bind(&MediaStreamVideoSource::OnSupportedFormats, 378 base::Bind(&MediaStreamVideoSource::OnSupportedFormats,
394 weak_factory_.GetWeakPtr())); 379 weak_factory_.GetWeakPtr()));
395 380
396 break; 381 break;
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
446 StopSourceImpl(); 431 StopSourceImpl();
447 state_ = ENDED; 432 state_ = ENDED;
448 SetReadyState(blink::WebMediaStreamSource::ReadyStateEnded); 433 SetReadyState(blink::WebMediaStreamSource::ReadyStateEnded);
449 } 434 }
450 435
451 void MediaStreamVideoSource::OnSupportedFormats( 436 void MediaStreamVideoSource::OnSupportedFormats(
452 const media::VideoCaptureFormats& formats) { 437 const media::VideoCaptureFormats& formats) {
453 DCHECK(CalledOnValidThread()); 438 DCHECK(CalledOnValidThread());
454 DCHECK_EQ(RETRIEVING_CAPABILITIES, state_); 439 DCHECK_EQ(RETRIEVING_CAPABILITIES, state_);
455 440
441 DVLOG(3) << "MediastreamVideoSource::OnSupportedFormats()";
mcasas 2016/01/26 16:08:01 I'd rather use DVLOG(3) << __FUNCTION__; and in th
hta - Chromium 2016/01/26 19:35:24 Removed.
456 supported_formats_ = formats; 442 supported_formats_ = formats;
457 blink::WebMediaConstraints fulfilled_constraints; 443 blink::WebMediaConstraints fulfilled_constraints;
458 if (!FindBestFormatWithConstraints(supported_formats_, 444 if (!FindBestFormatWithConstraints(supported_formats_,
459 &current_format_, 445 &current_format_,
460 &fulfilled_constraints)) { 446 &fulfilled_constraints)) {
461 SetReadyState(blink::WebMediaStreamSource::ReadyStateEnded); 447 SetReadyState(blink::WebMediaStreamSource::ReadyStateEnded);
448 DVLOG(3) << "OnSupportedFormats failed to find an usable format";
462 // This object can be deleted after calling FinalizeAddTrack. See comment 449 // This object can be deleted after calling FinalizeAddTrack. See comment
463 // in the header file. 450 // in the header file.
464 FinalizeAddTrack(); 451 FinalizeAddTrack();
465 return; 452 return;
466 } 453 }
467 454
468 state_ = STARTING; 455 state_ = STARTING;
469 DVLOG(3) << "Starting the capturer with " 456 DVLOG(3) << "Starting the capturer with "
470 << media::VideoCaptureFormat::ToString(current_format_); 457 << media::VideoCaptureFormat::ToString(current_format_);
471 458
472 StartSourceImpl( 459 StartSourceImpl(
473 current_format_, 460 current_format_,
474 fulfilled_constraints, 461 fulfilled_constraints,
475 base::Bind(&VideoTrackAdapter::DeliverFrameOnIO, track_adapter_)); 462 base::Bind(&VideoTrackAdapter::DeliverFrameOnIO, track_adapter_));
476 } 463 }
477 464
478 bool MediaStreamVideoSource::FindBestFormatWithConstraints( 465 bool MediaStreamVideoSource::FindBestFormatWithConstraints(
479 const media::VideoCaptureFormats& formats, 466 const media::VideoCaptureFormats& formats,
480 media::VideoCaptureFormat* best_format, 467 media::VideoCaptureFormat* best_format,
481 blink::WebMediaConstraints* fulfilled_constraints) { 468 blink::WebMediaConstraints* fulfilled_constraints) {
482 DCHECK(CalledOnValidThread()); 469 DCHECK(CalledOnValidThread());
483 // Find the first constraints that we can fulfill. 470 DVLOG(3) << "MediaStreamVideoSource::FindBestFormatWithConstraints "
471 << "with " << formats.size() << " formats";
472 // Find the first track descriptor that can fulfil the constraints.
484 for (const auto& track : track_descriptors_) { 473 for (const auto& track : track_descriptors_) {
485 const blink::WebMediaConstraints& track_constraints = track.constraints; 474 const blink::WebMediaConstraints& track_constraints = track.constraints;
486 475
487 // If the source doesn't support capability enumeration it is still ok if 476 // If the source doesn't support capability enumeration it is still ok if
488 // no mandatory constraints have been specified. That just means that 477 // no mandatory constraints have been specified. That just means that
489 // we will start with whatever format is native to the source. 478 // we will start with whatever format is native to the source.
490 if (formats.empty() && !HasMandatoryConstraints(track_constraints)) { 479 if (formats.empty() && !HasMandatoryConstraints(track_constraints)) {
480 DVLOG(3) << "No mandatory constraints and no formats";
491 *fulfilled_constraints = track_constraints; 481 *fulfilled_constraints = track_constraints;
492 *best_format = media::VideoCaptureFormat(); 482 *best_format = media::VideoCaptureFormat();
493 return true; 483 return true;
494 } 484 }
495 blink::WebString unsatisfied_constraint; 485 blink::WebString unsatisfied_constraint;
496 const media::VideoCaptureFormats filtered_formats = 486 const media::VideoCaptureFormats filtered_formats =
497 FilterFormats(track_constraints, formats, &unsatisfied_constraint); 487 FilterFormats(track_constraints, formats, &unsatisfied_constraint);
498 if (filtered_formats.empty()) 488 if (filtered_formats.empty())
499 continue; 489 continue;
500 490
501 // A request with constraints that can be fulfilled. 491 // A request with constraints that can be fulfilled.
502 *fulfilled_constraints = track_constraints; 492 *fulfilled_constraints = track_constraints;
503 *best_format = GetBestCaptureFormat(filtered_formats, track_constraints); 493 *best_format = GetBestCaptureFormat(filtered_formats, track_constraints);
494 DVLOG(3) << "Found a track that matches the constraints";
504 return true; 495 return true;
505 } 496 }
497 DVLOG(3) << "No usable format found";
506 return false; 498 return false;
507 } 499 }
508 500
509 void MediaStreamVideoSource::OnStartDone(MediaStreamRequestResult result) { 501 void MediaStreamVideoSource::OnStartDone(MediaStreamRequestResult result) {
510 DCHECK(CalledOnValidThread()); 502 DCHECK(CalledOnValidThread());
511 DVLOG(3) << "OnStartDone({result =" << result << "})"; 503 DVLOG(3) << "OnStartDone({result =" << result << "})";
512 if (result == MEDIA_DEVICE_OK) { 504 if (result == MEDIA_DEVICE_OK) {
513 DCHECK_EQ(STARTING, state_); 505 DCHECK_EQ(STARTING, state_);
514 state_ = STARTED; 506 state_ = STARTED;
515 SetReadyState(blink::WebMediaStreamSource::ReadyStateLive); 507 SetReadyState(blink::WebMediaStreamSource::ReadyStateLive);
(...skipping 19 matching lines...) Expand all
535 std::vector<TrackDescriptor> track_descriptors; 527 std::vector<TrackDescriptor> track_descriptors;
536 track_descriptors.swap(track_descriptors_); 528 track_descriptors.swap(track_descriptors_);
537 for (const auto& track : track_descriptors) { 529 for (const auto& track : track_descriptors) {
538 MediaStreamRequestResult result = MEDIA_DEVICE_OK; 530 MediaStreamRequestResult result = MEDIA_DEVICE_OK;
539 blink::WebString unsatisfied_constraint; 531 blink::WebString unsatisfied_constraint;
540 532
541 if (HasMandatoryConstraints(track.constraints) && 533 if (HasMandatoryConstraints(track.constraints) &&
542 FilterFormats(track.constraints, formats, &unsatisfied_constraint) 534 FilterFormats(track.constraints, formats, &unsatisfied_constraint)
543 .empty()) { 535 .empty()) {
544 result = MEDIA_DEVICE_CONSTRAINT_NOT_SATISFIED; 536 result = MEDIA_DEVICE_CONSTRAINT_NOT_SATISFIED;
537 DVLOG(3) << "FinalizeAddTrack() ignoring device on constraint "
538 << unsatisfied_constraint.utf8();
545 } 539 }
546 540
547 if (state_ != STARTED && result == MEDIA_DEVICE_OK) 541 if (state_ != STARTED && result == MEDIA_DEVICE_OK)
548 result = MEDIA_DEVICE_TRACK_START_FAILURE; 542 result = MEDIA_DEVICE_TRACK_START_FAILURE;
549 543
550 if (result == MEDIA_DEVICE_OK) { 544 if (result == MEDIA_DEVICE_OK) {
551 int max_width; 545 int max_width;
552 int max_height; 546 int max_height;
553 GetDesiredMaxWidthAndHeight(track.constraints, &max_width, &max_height); 547 GetDesiredMaxWidthAndHeight(track.constraints, &max_width, &max_height);
554 double max_aspect_ratio; 548 double max_aspect_ratio;
555 double min_aspect_ratio; 549 double min_aspect_ratio;
556 GetDesiredMinAndMaxAspectRatio(track.constraints, 550 GetDesiredMinAndMaxAspectRatio(track.constraints,
557 &min_aspect_ratio, 551 &min_aspect_ratio,
558 &max_aspect_ratio); 552 &max_aspect_ratio);
559 double max_frame_rate = 0.0f; 553 double max_frame_rate = 0.0f;
560 GetConstraintValueAsDouble(track.constraints, 554 if (track.constraints.basic().frameRate.hasMax())
561 kMaxFrameRate, &max_frame_rate); 555 max_frame_rate = track.constraints.basic().frameRate.max();
562 556
563 track_adapter_->AddTrack(track.track, track.frame_callback, max_width, 557 track_adapter_->AddTrack(track.track, track.frame_callback, max_width,
564 max_height, min_aspect_ratio, max_aspect_ratio, 558 max_height, min_aspect_ratio, max_aspect_ratio,
565 max_frame_rate); 559 max_frame_rate);
566 } 560 }
567 561
568 DVLOG(3) << "FinalizeAddTrack() result " << result; 562 DVLOG(3) << "FinalizeAddTrack() result " << result;
569 563
570 if (!track.callback.is_null()) 564 if (!track.callback.is_null())
571 track.callback.Run(this, result, unsatisfied_constraint); 565 track.callback.Run(this, result, unsatisfied_constraint);
(...skipping 28 matching lines...) Expand all
600 : track(track), 594 : track(track),
601 frame_callback(frame_callback), 595 frame_callback(frame_callback),
602 constraints(constraints), 596 constraints(constraints),
603 callback(callback) { 597 callback(callback) {
604 } 598 }
605 599
606 MediaStreamVideoSource::TrackDescriptor::~TrackDescriptor() { 600 MediaStreamVideoSource::TrackDescriptor::~TrackDescriptor() {
607 } 601 }
608 602
609 } // namespace content 603 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698