OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) 2011 Ericsson AB. All rights reserved. | 2 * Copyright (C) 2011 Ericsson AB. All rights reserved. |
3 * Copyright (C) 2012 Google Inc. All rights reserved. | 3 * Copyright (C) 2012 Google Inc. All rights reserved. |
4 * | 4 * |
5 * Redistribution and use in source and binary forms, with or without | 5 * Redistribution and use in source and binary forms, with or without |
6 * modification, are permitted provided that the following conditions | 6 * modification, are permitted provided that the following conditions |
7 * are met: | 7 * are met: |
8 * | 8 * |
9 * 1. Redistributions of source code must retain the above copyright | 9 * 1. Redistributions of source code must retain the above copyright |
10 * notice, this list of conditions and the following disclaimer. | 10 * notice, this list of conditions and the following disclaimer. |
(...skipping 13 matching lines...) Expand all Loading... |
24 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | 24 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
25 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | 25 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
26 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 26 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
27 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 27 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
29 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 29 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
30 */ | 30 */ |
31 | 31 |
32 #include "modules/mediastream/UserMediaRequest.h" | 32 #include "modules/mediastream/UserMediaRequest.h" |
33 | 33 |
| 34 #include <type_traits> |
| 35 |
34 #include "bindings/core/v8/Dictionary.h" | 36 #include "bindings/core/v8/Dictionary.h" |
35 #include "bindings/core/v8/ExceptionMessages.h" | 37 #include "bindings/core/v8/ExceptionMessages.h" |
36 #include "bindings/core/v8/ExceptionState.h" | 38 #include "bindings/core/v8/ExceptionState.h" |
37 #include "core/dom/Document.h" | 39 #include "core/dom/Document.h" |
38 #include "core/dom/ExceptionCode.h" | 40 #include "core/dom/ExceptionCode.h" |
39 #include "core/dom/SpaceSplitString.h" | 41 #include "core/dom/SpaceSplitString.h" |
40 #include "core/frame/Deprecation.h" | 42 #include "core/frame/Deprecation.h" |
41 #include "core/frame/HostsUsingFeatures.h" | 43 #include "core/frame/HostsUsingFeatures.h" |
42 #include "modules/mediastream/MediaConstraintsImpl.h" | 44 #include "modules/mediastream/MediaConstraintsImpl.h" |
43 #include "modules/mediastream/MediaStream.h" | 45 #include "modules/mediastream/MediaStream.h" |
44 #include "modules/mediastream/MediaStreamConstraints.h" | 46 #include "modules/mediastream/MediaStreamConstraints.h" |
45 #include "modules/mediastream/MediaTrackConstraints.h" | 47 #include "modules/mediastream/MediaTrackConstraints.h" |
46 #include "modules/mediastream/UserMediaController.h" | 48 #include "modules/mediastream/UserMediaController.h" |
47 #include "platform/mediastream/MediaStreamCenter.h" | 49 #include "platform/mediastream/MediaStreamCenter.h" |
48 #include "platform/mediastream/MediaStreamDescriptor.h" | 50 #include "platform/mediastream/MediaStreamDescriptor.h" |
49 | 51 |
50 namespace blink { | 52 namespace blink { |
51 | 53 |
52 static WebMediaConstraints ParseOptions( | 54 namespace { |
53 ExecutionContext* context, | 55 |
54 const BooleanOrMediaTrackConstraints& options, | 56 template <typename NumericConstraint> |
55 MediaErrorState& error_state) { | 57 bool SetUsesNumericConstraint( |
| 58 const WebMediaTrackConstraintSet& set, |
| 59 NumericConstraint WebMediaTrackConstraintSet::*field) { |
| 60 return (set.*field).HasExact() || (set.*field).HasIdeal() || |
| 61 (set.*field).HasMin() || (set.*field).HasMax(); |
| 62 } |
| 63 |
| 64 template <typename DiscreteConstraint> |
| 65 bool SetUsesDiscreteConstraint( |
| 66 const WebMediaTrackConstraintSet& set, |
| 67 DiscreteConstraint WebMediaTrackConstraintSet::*field) { |
| 68 return (set.*field).HasExact() || (set.*field).HasIdeal(); |
| 69 } |
| 70 |
| 71 template <typename NumericConstraint> |
| 72 bool RequestUsesNumericConstraint( |
| 73 const WebMediaConstraints& constraints, |
| 74 NumericConstraint WebMediaTrackConstraintSet::*field) { |
| 75 if (SetUsesNumericConstraint(constraints.Basic(), field)) |
| 76 return true; |
| 77 for (const auto& advanced_set : constraints.Advanced()) { |
| 78 if (SetUsesNumericConstraint(advanced_set, field)) |
| 79 return true; |
| 80 } |
| 81 return false; |
| 82 } |
| 83 |
| 84 template <typename DiscreteConstraint> |
| 85 bool RequestUsesDiscreteConstraint( |
| 86 const WebMediaConstraints& constraints, |
| 87 DiscreteConstraint WebMediaTrackConstraintSet::*field) { |
| 88 static_assert( |
| 89 std::is_same<decltype(field), |
| 90 StringConstraint WebMediaTrackConstraintSet::*>::value || |
| 91 std::is_same<decltype(field), |
| 92 BooleanConstraint WebMediaTrackConstraintSet::*>::value, |
| 93 "Must use StringConstraint or BooleanConstraint"); |
| 94 if (SetUsesDiscreteConstraint(constraints.Basic(), field)) |
| 95 return true; |
| 96 for (const auto& advanced_set : constraints.Advanced()) { |
| 97 if (SetUsesDiscreteConstraint(advanced_set, field)) |
| 98 return true; |
| 99 } |
| 100 return false; |
| 101 } |
| 102 |
| 103 class FeatureCounter { |
| 104 WTF_MAKE_NONCOPYABLE(FeatureCounter); |
| 105 |
| 106 public: |
| 107 FeatureCounter(ExecutionContext* context) |
| 108 : context_(context), is_unconstrained_(true) {} |
| 109 void Count(UseCounter::Feature feature) { |
| 110 UseCounter::Count(context_, feature); |
| 111 is_unconstrained_ = false; |
| 112 } |
| 113 bool IsUnconstrained() { return is_unconstrained_; } |
| 114 |
| 115 private: |
| 116 Persistent<ExecutionContext> context_; |
| 117 bool is_unconstrained_; |
| 118 }; |
| 119 |
| 120 void CountAudioConstraintUses(ExecutionContext* context, |
| 121 const WebMediaConstraints& constraints) { |
| 122 FeatureCounter counter(context); |
| 123 if (RequestUsesNumericConstraint(constraints, |
| 124 &WebMediaTrackConstraintSet::sample_rate)) { |
| 125 counter.Count(UseCounter::kMediaStreamConstraintsSampleRate); |
| 126 } |
| 127 if (RequestUsesNumericConstraint(constraints, |
| 128 &WebMediaTrackConstraintSet::sample_size)) { |
| 129 counter.Count(UseCounter::kMediaStreamConstraintsSampleSize); |
| 130 } |
| 131 if (RequestUsesDiscreteConstraint( |
| 132 constraints, &WebMediaTrackConstraintSet::echo_cancellation)) { |
| 133 counter.Count(UseCounter::kMediaStreamConstraintsEchoCancellation); |
| 134 } |
| 135 if (RequestUsesNumericConstraint(constraints, |
| 136 &WebMediaTrackConstraintSet::latency)) { |
| 137 counter.Count(UseCounter::kMediaStreamConstraintsLatency); |
| 138 } |
| 139 if (RequestUsesNumericConstraint( |
| 140 constraints, &WebMediaTrackConstraintSet::channel_count)) { |
| 141 counter.Count(UseCounter::kMediaStreamConstraintsChannelCount); |
| 142 } |
| 143 if (RequestUsesDiscreteConstraint(constraints, |
| 144 &WebMediaTrackConstraintSet::device_id)) { |
| 145 counter.Count(UseCounter::kMediaStreamConstraintsDeviceIdAudio); |
| 146 } |
| 147 if (RequestUsesDiscreteConstraint( |
| 148 constraints, &WebMediaTrackConstraintSet::disable_local_echo)) { |
| 149 counter.Count(UseCounter::kMediaStreamConstraintsDisableLocalEcho); |
| 150 } |
| 151 if (RequestUsesDiscreteConstraint(constraints, |
| 152 &WebMediaTrackConstraintSet::group_id)) { |
| 153 counter.Count(UseCounter::kMediaStreamConstraintsGroupIdAudio); |
| 154 } |
| 155 if (RequestUsesDiscreteConstraint( |
| 156 constraints, &WebMediaTrackConstraintSet::media_stream_source)) { |
| 157 counter.Count(UseCounter::kMediaStreamConstraintsMediaStreamSourceAudio); |
| 158 } |
| 159 if (RequestUsesDiscreteConstraint( |
| 160 constraints, |
| 161 &WebMediaTrackConstraintSet::render_to_associated_sink)) { |
| 162 counter.Count(UseCounter::kMediaStreamConstraintsRenderToAssociatedSink); |
| 163 } |
| 164 if (RequestUsesDiscreteConstraint( |
| 165 constraints, &WebMediaTrackConstraintSet::hotword_enabled)) { |
| 166 counter.Count(UseCounter::kMediaStreamConstraintsHotwordEnabled); |
| 167 } |
| 168 if (RequestUsesDiscreteConstraint( |
| 169 constraints, &WebMediaTrackConstraintSet::goog_echo_cancellation)) { |
| 170 counter.Count(UseCounter::kMediaStreamConstraintsGoogEchoCancellation); |
| 171 } |
| 172 if (RequestUsesDiscreteConstraint( |
| 173 constraints, |
| 174 &WebMediaTrackConstraintSet::goog_experimental_echo_cancellation)) { |
| 175 counter.Count( |
| 176 UseCounter::kMediaStreamConstraintsGoogExperimentalEchoCancellation); |
| 177 } |
| 178 if (RequestUsesDiscreteConstraint( |
| 179 constraints, &WebMediaTrackConstraintSet::goog_auto_gain_control)) { |
| 180 counter.Count(UseCounter::kMediaStreamConstraintsGoogAutoGainControl); |
| 181 } |
| 182 if (RequestUsesDiscreteConstraint( |
| 183 constraints, |
| 184 &WebMediaTrackConstraintSet::goog_experimental_auto_gain_control)) { |
| 185 counter.Count( |
| 186 UseCounter::kMediaStreamConstraintsGoogExperimentalAutoGainControl); |
| 187 } |
| 188 if (RequestUsesDiscreteConstraint( |
| 189 constraints, &WebMediaTrackConstraintSet::goog_noise_suppression)) { |
| 190 counter.Count(UseCounter::kMediaStreamConstraintsGoogNoiseSuppression); |
| 191 } |
| 192 if (RequestUsesDiscreteConstraint( |
| 193 constraints, &WebMediaTrackConstraintSet::goog_highpass_filter)) { |
| 194 counter.Count(UseCounter::kMediaStreamConstraintsGoogHighpassFilter); |
| 195 } |
| 196 if (RequestUsesDiscreteConstraint( |
| 197 constraints, |
| 198 &WebMediaTrackConstraintSet::goog_typing_noise_detection)) { |
| 199 counter.Count(UseCounter::kMediaStreamConstraintsGoogTypingNoiseDetection); |
| 200 } |
| 201 if (RequestUsesDiscreteConstraint( |
| 202 constraints, |
| 203 &WebMediaTrackConstraintSet::goog_experimental_noise_suppression)) { |
| 204 counter.Count( |
| 205 UseCounter::kMediaStreamConstraintsGoogExperimentalNoiseSuppression); |
| 206 } |
| 207 if (RequestUsesDiscreteConstraint( |
| 208 constraints, &WebMediaTrackConstraintSet::goog_beamforming)) { |
| 209 counter.Count(UseCounter::kMediaStreamConstraintsGoogBeamforming); |
| 210 } |
| 211 if (RequestUsesDiscreteConstraint( |
| 212 constraints, &WebMediaTrackConstraintSet::goog_array_geometry)) { |
| 213 counter.Count(UseCounter::kMediaStreamConstraintsGoogArrayGeometry); |
| 214 } |
| 215 if (RequestUsesDiscreteConstraint( |
| 216 constraints, &WebMediaTrackConstraintSet::goog_audio_mirroring)) { |
| 217 counter.Count(UseCounter::kMediaStreamConstraintsGoogAudioMirroring); |
| 218 } |
| 219 if (RequestUsesDiscreteConstraint( |
| 220 constraints, |
| 221 &WebMediaTrackConstraintSet::goog_da_echo_cancellation)) { |
| 222 counter.Count(UseCounter::kMediaStreamConstraintsGoogDAEchoCancellation); |
| 223 } |
| 224 |
| 225 UseCounter::Count(context, UseCounter::kMediaStreamConstraintsAudio); |
| 226 if (counter.IsUnconstrained()) { |
| 227 UseCounter::Count(context, |
| 228 UseCounter::kMediaStreamConstraintsAudioUnconstrained); |
| 229 } |
| 230 } |
| 231 |
| 232 void CountVideoConstraintUses(ExecutionContext* context, |
| 233 const WebMediaConstraints& constraints) { |
| 234 FeatureCounter counter(context); |
| 235 if (RequestUsesNumericConstraint(constraints, |
| 236 &WebMediaTrackConstraintSet::width)) { |
| 237 counter.Count(UseCounter::kMediaStreamConstraintsWidth); |
| 238 } |
| 239 if (RequestUsesNumericConstraint(constraints, |
| 240 &WebMediaTrackConstraintSet::height)) { |
| 241 counter.Count(UseCounter::kMediaStreamConstraintsHeight); |
| 242 } |
| 243 if (RequestUsesNumericConstraint(constraints, |
| 244 &WebMediaTrackConstraintSet::aspect_ratio)) { |
| 245 counter.Count(UseCounter::kMediaStreamConstraintsAspectRatio); |
| 246 } |
| 247 if (RequestUsesNumericConstraint(constraints, |
| 248 &WebMediaTrackConstraintSet::frame_rate)) { |
| 249 counter.Count(UseCounter::kMediaStreamConstraintsFrameRate); |
| 250 } |
| 251 if (RequestUsesDiscreteConstraint(constraints, |
| 252 &WebMediaTrackConstraintSet::facing_mode)) { |
| 253 counter.Count(UseCounter::kMediaStreamConstraintsFacingMode); |
| 254 } |
| 255 if (RequestUsesDiscreteConstraint(constraints, |
| 256 &WebMediaTrackConstraintSet::device_id)) { |
| 257 counter.Count(UseCounter::kMediaStreamConstraintsDeviceIdVideo); |
| 258 } |
| 259 if (RequestUsesDiscreteConstraint(constraints, |
| 260 &WebMediaTrackConstraintSet::group_id)) { |
| 261 counter.Count(UseCounter::kMediaStreamConstraintsGroupIdVideo); |
| 262 } |
| 263 if (RequestUsesDiscreteConstraint(constraints, |
| 264 &WebMediaTrackConstraintSet::video_kind)) { |
| 265 counter.Count(UseCounter::kMediaStreamConstraintsVideoKind); |
| 266 } |
| 267 if (RequestUsesNumericConstraint(constraints, |
| 268 &WebMediaTrackConstraintSet::depth_near)) { |
| 269 counter.Count(UseCounter::kMediaStreamConstraintsDepthNear); |
| 270 } |
| 271 if (RequestUsesNumericConstraint(constraints, |
| 272 &WebMediaTrackConstraintSet::depth_far)) { |
| 273 counter.Count(UseCounter::kMediaStreamConstraintsDepthFar); |
| 274 } |
| 275 if (RequestUsesNumericConstraint( |
| 276 constraints, &WebMediaTrackConstraintSet::focal_length_x)) { |
| 277 counter.Count(UseCounter::kMediaStreamConstraintsFocalLengthX); |
| 278 } |
| 279 if (RequestUsesNumericConstraint( |
| 280 constraints, &WebMediaTrackConstraintSet::focal_length_y)) { |
| 281 counter.Count(UseCounter::kMediaStreamConstraintsFocalLengthY); |
| 282 } |
| 283 if (RequestUsesDiscreteConstraint( |
| 284 constraints, &WebMediaTrackConstraintSet::media_stream_source)) { |
| 285 counter.Count(UseCounter::kMediaStreamConstraintsMediaStreamSourceVideo); |
| 286 } |
| 287 if (RequestUsesDiscreteConstraint( |
| 288 constraints, &WebMediaTrackConstraintSet::goog_noise_reduction)) { |
| 289 counter.Count(UseCounter::kMediaStreamConstraintsGoogNoiseReduction); |
| 290 } |
| 291 if (RequestUsesNumericConstraint( |
| 292 constraints, |
| 293 &WebMediaTrackConstraintSet::goog_power_line_frequency)) { |
| 294 counter.Count(UseCounter::kMediaStreamConstraintsGoogPowerLineFrequency); |
| 295 } |
| 296 |
| 297 UseCounter::Count(context, UseCounter::kMediaStreamConstraintsVideo); |
| 298 if (counter.IsUnconstrained()) { |
| 299 UseCounter::Count(context, |
| 300 UseCounter::kMediaStreamConstraintsVideoUnconstrained); |
| 301 } |
| 302 } |
| 303 |
| 304 WebMediaConstraints ParseOptions(ExecutionContext* context, |
| 305 const BooleanOrMediaTrackConstraints& options, |
| 306 MediaErrorState& error_state) { |
56 WebMediaConstraints constraints; | 307 WebMediaConstraints constraints; |
57 | 308 |
58 Dictionary constraints_dictionary; | 309 Dictionary constraints_dictionary; |
59 if (options.isNull()) { | 310 if (options.isNull()) { |
60 // Do nothing. | 311 // Do nothing. |
61 } else if (options.isMediaTrackConstraints()) { | 312 } else if (options.isMediaTrackConstraints()) { |
62 constraints = MediaConstraintsImpl::Create( | 313 constraints = MediaConstraintsImpl::Create( |
63 context, options.getAsMediaTrackConstraints(), error_state); | 314 context, options.getAsMediaTrackConstraints(), error_state); |
64 } else { | 315 } else { |
65 DCHECK(options.isBoolean()); | 316 DCHECK(options.isBoolean()); |
66 if (options.getAsBoolean()) { | 317 if (options.getAsBoolean()) { |
67 constraints = MediaConstraintsImpl::Create(); | 318 constraints = MediaConstraintsImpl::Create(); |
68 } | 319 } |
69 } | 320 } |
70 | 321 |
71 return constraints; | 322 return constraints; |
72 } | 323 } |
73 | 324 |
| 325 } // namespace |
| 326 |
74 UserMediaRequest* UserMediaRequest::Create( | 327 UserMediaRequest* UserMediaRequest::Create( |
75 ExecutionContext* context, | 328 ExecutionContext* context, |
76 UserMediaController* controller, | 329 UserMediaController* controller, |
77 const MediaStreamConstraints& options, | 330 const MediaStreamConstraints& options, |
78 NavigatorUserMediaSuccessCallback* success_callback, | 331 NavigatorUserMediaSuccessCallback* success_callback, |
79 NavigatorUserMediaErrorCallback* error_callback, | 332 NavigatorUserMediaErrorCallback* error_callback, |
80 MediaErrorState& error_state) { | 333 MediaErrorState& error_state) { |
81 WebMediaConstraints audio = | 334 WebMediaConstraints audio = |
82 ParseOptions(context, options.audio(), error_state); | 335 ParseOptions(context, options.audio(), error_state); |
83 if (error_state.HadException()) | 336 if (error_state.HadException()) |
84 return nullptr; | 337 return nullptr; |
85 | 338 |
86 WebMediaConstraints video = | 339 WebMediaConstraints video = |
87 ParseOptions(context, options.video(), error_state); | 340 ParseOptions(context, options.video(), error_state); |
88 if (error_state.HadException()) | 341 if (error_state.HadException()) |
89 return nullptr; | 342 return nullptr; |
90 | 343 |
91 if (audio.IsNull() && video.IsNull()) { | 344 if (audio.IsNull() && video.IsNull()) { |
92 error_state.ThrowTypeError( | 345 error_state.ThrowTypeError( |
93 "At least one of audio and video must be requested"); | 346 "At least one of audio and video must be requested"); |
94 return nullptr; | 347 return nullptr; |
95 } | 348 } |
96 | 349 |
| 350 if (!audio.IsNull()) |
| 351 CountAudioConstraintUses(context, audio); |
| 352 if (!video.IsNull()) |
| 353 CountVideoConstraintUses(context, video); |
| 354 |
97 return new UserMediaRequest(context, controller, audio, video, | 355 return new UserMediaRequest(context, controller, audio, video, |
98 success_callback, error_callback); | 356 success_callback, error_callback); |
99 } | 357 } |
100 | 358 |
101 UserMediaRequest* UserMediaRequest::CreateForTesting( | 359 UserMediaRequest* UserMediaRequest::CreateForTesting( |
102 const WebMediaConstraints& audio, | 360 const WebMediaConstraints& audio, |
103 const WebMediaConstraints& video) { | 361 const WebMediaConstraints& video) { |
104 return new UserMediaRequest(nullptr, nullptr, audio, video, nullptr, nullptr); | 362 return new UserMediaRequest(nullptr, nullptr, audio, video, nullptr, nullptr); |
105 } | 363 } |
106 | 364 |
(...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
232 } | 490 } |
233 | 491 |
234 DEFINE_TRACE(UserMediaRequest) { | 492 DEFINE_TRACE(UserMediaRequest) { |
235 visitor->Trace(controller_); | 493 visitor->Trace(controller_); |
236 visitor->Trace(success_callback_); | 494 visitor->Trace(success_callback_); |
237 visitor->Trace(error_callback_); | 495 visitor->Trace(error_callback_); |
238 ContextLifecycleObserver::Trace(visitor); | 496 ContextLifecycleObserver::Trace(visitor); |
239 } | 497 } |
240 | 498 |
241 } // namespace blink | 499 } // namespace blink |
OLD | NEW |