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

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

Powered by Google App Engine
This is Rietveld 408576698