OLD | NEW |
---|---|
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/debug/trace_event.h" | 11 #include "base/debug/trace_event.h" |
12 #include "base/logging.h" | 12 #include "base/logging.h" |
13 #include "base/strings/string_number_conversions.h" | 13 #include "base/strings/string_number_conversions.h" |
14 #include "content/renderer/media/media_stream_dependency_factory.h" | |
15 #include "content/renderer/media/media_stream_video_track.h" | 14 #include "content/renderer/media/media_stream_video_track.h" |
16 #include "content/renderer/media/video_frame_deliverer.h" | 15 #include "content/renderer/media/video_track_adapter.h" |
17 #include "content/renderer/media/webrtc/webrtc_video_capturer_adapter.h" | |
18 | 16 |
19 namespace content { | 17 namespace content { |
20 | 18 |
21 // Constraint keys. Specified by draft-alvestrand-constraints-resolution-00b | 19 // Constraint keys. Specified by draft-alvestrand-constraints-resolution-00b |
22 const char MediaStreamVideoSource::kMinAspectRatio[] = "minAspectRatio"; | 20 const char MediaStreamVideoSource::kMinAspectRatio[] = "minAspectRatio"; |
23 const char MediaStreamVideoSource::kMaxAspectRatio[] = "maxAspectRatio"; | 21 const char MediaStreamVideoSource::kMaxAspectRatio[] = "maxAspectRatio"; |
24 const char MediaStreamVideoSource::kMaxWidth[] = "maxWidth"; | 22 const char MediaStreamVideoSource::kMaxWidth[] = "maxWidth"; |
25 const char MediaStreamVideoSource::kMinWidth[] = "minWidth"; | 23 const char MediaStreamVideoSource::kMinWidth[] = "minWidth"; |
26 const char MediaStreamVideoSource::kMaxHeight[] = "maxHeight"; | 24 const char MediaStreamVideoSource::kMaxHeight[] = "maxHeight"; |
27 const char MediaStreamVideoSource::kMinHeight[] = "minHeight"; | 25 const char MediaStreamVideoSource::kMinHeight[] = "minHeight"; |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
82 return true; | 80 return true; |
83 } | 81 } |
84 | 82 |
85 // Ignore Chrome specific Tab capture constraints. | 83 // Ignore Chrome specific Tab capture constraints. |
86 if (constraint_name == kMediaStreamSource || | 84 if (constraint_name == kMediaStreamSource || |
87 constraint_name == kMediaStreamSourceId) | 85 constraint_name == kMediaStreamSourceId) |
88 return true; | 86 return true; |
89 | 87 |
90 if (constraint_name == MediaStreamVideoSource::kMinAspectRatio || | 88 if (constraint_name == MediaStreamVideoSource::kMinAspectRatio || |
91 constraint_name == MediaStreamVideoSource::kMaxAspectRatio) { | 89 constraint_name == MediaStreamVideoSource::kMaxAspectRatio) { |
92 double double_value = 0; | 90 return true; |
93 base::StringToDouble(constraint_value, &double_value); | |
94 | |
95 // The aspect ratio in |constraint.m_value| has been converted to a string | |
96 // and back to a double, so it may have a rounding error. | |
97 // E.g if the value 1/3 is converted to a string, the string will not have | |
98 // infinite length. | |
99 // We add a margin of 0.0005 which is high enough to detect the same aspect | |
100 // ratio but small enough to avoid matching wrong aspect ratios. | |
101 const double kRoundingTruncation = 0.0005; | |
102 double ratio = static_cast<double>(format->frame_size.width()) / | |
103 format->frame_size.height(); | |
104 if (constraint_name == MediaStreamVideoSource::kMinAspectRatio) | |
105 return (double_value <= ratio + kRoundingTruncation); | |
106 // Subtract 0.0005 to avoid rounding problems. Same as above. | |
107 return (double_value >= ratio - kRoundingTruncation); | |
108 } | 91 } |
109 | 92 |
110 int value; | 93 int value; |
111 if (!base::StringToInt(constraint_value, &value)) { | 94 if (!base::StringToInt(constraint_value, &value)) { |
112 DLOG(WARNING) << "Can't parse MediaStream constraint. Name:" | 95 DLOG(WARNING) << "Can't parse MediaStream constraint. Name:" |
113 << constraint_name << " Value:" << constraint_value; | 96 << constraint_name << " Value:" << constraint_value; |
114 return false; | 97 return false; |
115 } | 98 } |
116 if (constraint_name == MediaStreamVideoSource::kMinWidth) { | 99 if (constraint_name == MediaStreamVideoSource::kMinWidth) { |
117 return (value <= format->frame_size.width()); | 100 return (value <= format->frame_size.width()); |
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
210 int* value) { | 193 int* value) { |
211 blink::WebString value_str; | 194 blink::WebString value_str; |
212 bool ret = mandatory ? | 195 bool ret = mandatory ? |
213 constraints.getMandatoryConstraintValue(name, value_str) : | 196 constraints.getMandatoryConstraintValue(name, value_str) : |
214 constraints.getOptionalConstraintValue(name, value_str); | 197 constraints.getOptionalConstraintValue(name, value_str); |
215 if (ret) | 198 if (ret) |
216 base::StringToInt(value_str.utf8(), value); | 199 base::StringToInt(value_str.utf8(), value); |
217 return ret; | 200 return ret; |
218 } | 201 } |
219 | 202 |
203 bool GetConstraintValue(const blink::WebMediaConstraints& constraints, | |
204 bool mandatory, const blink::WebString& name, | |
205 double* value) { | |
206 blink::WebString value_str; | |
207 bool ret = mandatory ? | |
208 constraints.getMandatoryConstraintValue(name, value_str) : | |
209 constraints.getOptionalConstraintValue(name, value_str); | |
210 if (ret) | |
211 base::StringToDouble(value_str.utf8(), value); | |
212 return ret; | |
213 } | |
214 | |
220 // Returns true if |constraint| has mandatory constraints. | 215 // Returns true if |constraint| has mandatory constraints. |
221 bool HasMandatoryConstraints(const blink::WebMediaConstraints& constraints) { | 216 bool HasMandatoryConstraints(const blink::WebMediaConstraints& constraints) { |
222 blink::WebVector<blink::WebMediaConstraint> mandatory_constraints; | 217 blink::WebVector<blink::WebMediaConstraint> mandatory_constraints; |
223 constraints.getMandatoryConstraints(mandatory_constraints); | 218 constraints.getMandatoryConstraints(mandatory_constraints); |
224 return !mandatory_constraints.isEmpty(); | 219 return !mandatory_constraints.isEmpty(); |
225 } | 220 } |
226 | 221 |
227 // Retrieve the desired max width and height from |constraints|. | 222 // Retrieve the desired max width and height from |constraints|. If not set, |
223 // the |desired_width| and |desired_height| is to | |
224 // std::numeric_limits<int>::max(); | |
228 void GetDesiredMaxWidthAndHeight(const blink::WebMediaConstraints& constraints, | 225 void GetDesiredMaxWidthAndHeight(const blink::WebMediaConstraints& constraints, |
229 int* desired_width, int* desired_height) { | 226 int* desired_width, int* desired_height) { |
227 *desired_width = std::numeric_limits<int>::max(); | |
228 *desired_height = std::numeric_limits<int>::max();; | |
230 bool mandatory = GetConstraintValue(constraints, true, | 229 bool mandatory = GetConstraintValue(constraints, true, |
231 MediaStreamVideoSource::kMaxWidth, | 230 MediaStreamVideoSource::kMaxWidth, |
232 desired_width); | 231 desired_width); |
233 mandatory |= GetConstraintValue(constraints, true, | 232 mandatory |= GetConstraintValue(constraints, true, |
234 MediaStreamVideoSource::kMaxHeight, | 233 MediaStreamVideoSource::kMaxHeight, |
235 desired_height); | 234 desired_height); |
236 if (mandatory) | 235 if (mandatory) |
237 return; | 236 return; |
238 | 237 |
239 GetConstraintValue(constraints, false, MediaStreamVideoSource::kMaxWidth, | 238 GetConstraintValue(constraints, false, MediaStreamVideoSource::kMaxWidth, |
240 desired_width); | 239 desired_width); |
241 GetConstraintValue(constraints, false, MediaStreamVideoSource::kMaxHeight, | 240 GetConstraintValue(constraints, false, MediaStreamVideoSource::kMaxHeight, |
242 desired_height); | 241 desired_height); |
243 } | 242 } |
244 | 243 |
244 void GetDesiredMinAndMaxAspectRatio( | |
245 const blink::WebMediaConstraints& constraints, | |
246 double* min_aspect_ratio, | |
247 double* max_aspect_ratio) { | |
248 *min_aspect_ratio = 0; | |
249 *max_aspect_ratio = std::numeric_limits<double>::max(); | |
250 | |
251 bool mandatory = GetConstraintValue(constraints, true, | |
252 MediaStreamVideoSource::kMinAspectRatio, | |
253 min_aspect_ratio); | |
254 mandatory |= GetConstraintValue(constraints, true, | |
255 MediaStreamVideoSource::kMaxAspectRatio, | |
256 max_aspect_ratio); | |
257 if (!mandatory && | |
258 !GetConstraintValue(constraints, false, | |
259 MediaStreamVideoSource::kMinAspectRatio, | |
260 min_aspect_ratio) && | |
261 !GetConstraintValue(constraints, false, | |
262 MediaStreamVideoSource::kMaxAspectRatio, | |
263 max_aspect_ratio)) { | |
264 return; | |
265 } | |
266 // The aspect ratio in |constraint.m_value| has been converted to a string | |
267 // and back to a double, so it may have a rounding error. | |
268 // E.g if the value 1/3 is converted to a string, the string will not have | |
269 // infinite length. | |
270 // We add a margin of 0.0005 which is high enough to detect the same aspect | |
271 // ratio but small enough to avoid matching wrong aspect ratios. | |
272 const double kRoundingTruncation = 0.0005; | |
273 if (*min_aspect_ratio != 0) | |
mcasas
2014/05/07 14:10:43
|min_aspect_ratio| is a double, so this comparison
perkj_chrome
2014/05/08 11:29:47
Why would it be true? I set it to 0 at line 248?
mcasas
2014/05/09 07:46:24
A float cannot be 0.0 exactly, and the most likely
| |
274 *min_aspect_ratio += kRoundingTruncation; | |
275 if (*max_aspect_ratio != std::numeric_limits<double>::max()) | |
276 *max_aspect_ratio -= kRoundingTruncation; | |
277 } | |
278 | |
245 const media::VideoCaptureFormat& GetBestFormatBasedOnArea( | 279 const media::VideoCaptureFormat& GetBestFormatBasedOnArea( |
246 const media::VideoCaptureFormats& formats, | 280 const media::VideoCaptureFormats& formats, |
247 int area) { | 281 int area) { |
248 media::VideoCaptureFormats::const_iterator it = formats.begin(); | 282 media::VideoCaptureFormats::const_iterator it = formats.begin(); |
249 media::VideoCaptureFormats::const_iterator best_it = formats.begin(); | 283 media::VideoCaptureFormats::const_iterator best_it = formats.begin(); |
250 int best_diff = std::numeric_limits<int>::max(); | 284 int best_diff = std::numeric_limits<int>::max(); |
251 for (; it != formats.end(); ++it) { | 285 for (; it != formats.end(); ++it) { |
252 int diff = abs(area - it->frame_size.width() * it->frame_size.height()); | 286 int diff = abs(area - it->frame_size.width() * it->frame_size.height()); |
253 if (diff < best_diff) { | 287 if (diff < best_diff) { |
254 best_diff = diff; | 288 best_diff = diff; |
255 best_it = it; | 289 best_it = it; |
256 } | 290 } |
257 } | 291 } |
258 return *best_it; | 292 return *best_it; |
259 } | 293 } |
260 | 294 |
261 // Find the format that best matches the default video size. | 295 // Find the format that best matches the default video size. |
262 // This algorithm is chosen since a resolution must be picked even if no | 296 // This algorithm is chosen since a resolution must be picked even if no |
263 // constraints are provided. We don't just select the maximum supported | 297 // constraints are provided. We don't just select the maximum supported |
264 // resolution since higher resolutions cost more in terms of complexity and | 298 // resolution since higher resolutions cost more in terms of complexity and |
265 // many cameras have lower frame rate and have more noise in the image at | 299 // many cameras have lower frame rate and have more noise in the image at |
266 // their maximum supported resolution. | 300 // their maximum supported resolution. |
267 void GetBestCaptureFormat( | 301 void GetBestCaptureFormat( |
268 const media::VideoCaptureFormats& formats, | 302 const media::VideoCaptureFormats& formats, |
269 const blink::WebMediaConstraints& constraints, | 303 const blink::WebMediaConstraints& constraints, |
270 media::VideoCaptureFormat* capture_format, | 304 media::VideoCaptureFormat* capture_format) { |
271 gfx::Size* max_frame_output_size) { | |
272 DCHECK(!formats.empty()); | 305 DCHECK(!formats.empty()); |
273 DCHECK(max_frame_output_size); | |
274 | 306 |
275 int max_width = std::numeric_limits<int>::max(); | 307 int max_width = std::numeric_limits<int>::max(); |
276 int max_height = std::numeric_limits<int>::max();; | 308 int max_height = std::numeric_limits<int>::max();; |
277 GetDesiredMaxWidthAndHeight(constraints, &max_width, &max_height); | 309 GetDesiredMaxWidthAndHeight(constraints, &max_width, &max_height); |
278 | 310 |
279 *capture_format = GetBestFormatBasedOnArea( | 311 *capture_format = GetBestFormatBasedOnArea( |
280 formats, | 312 formats, |
281 std::min(max_width, MediaStreamVideoSource::kDefaultWidth) * | 313 std::min(max_width, MediaStreamVideoSource::kDefaultWidth) * |
282 std::min(max_height, MediaStreamVideoSource::kDefaultHeight)); | 314 std::min(max_height, MediaStreamVideoSource::kDefaultHeight)); |
283 | |
284 max_frame_output_size->set_width(max_width); | |
285 max_frame_output_size->set_height(max_height); | |
286 } | |
287 | |
288 // Empty method used for keeping a reference to the original media::VideoFrame | |
289 // in MediaStreamVideoSource::FrameDeliverer::DeliverFrameOnIO if cropping is | |
290 // needed. The reference to |frame| is kept in the closure that calls this | |
291 // method. | |
292 void ReleaseOriginalFrame( | |
293 const scoped_refptr<media::VideoFrame>& frame) { | |
294 } | 315 } |
295 | 316 |
296 } // anonymous namespace | 317 } // anonymous namespace |
297 | 318 |
298 // Helper class used for delivering video frames to all registered tracks | |
299 // on the IO-thread. | |
300 class MediaStreamVideoSource::FrameDeliverer : public VideoFrameDeliverer { | |
301 public: | |
302 FrameDeliverer( | |
303 const scoped_refptr<base::MessageLoopProxy>& io_message_loop) | |
304 : VideoFrameDeliverer(io_message_loop) { | |
305 } | |
306 | |
307 // Register |callback| to receive video frames of max size | |
308 // |max_frame_output_size| on the IO thread. | |
309 // TODO(perkj): Currently |max_frame_output_size| must be the same for all | |
310 // |callbacks|. | |
311 void AddCallback(void* id, | |
312 const VideoCaptureDeliverFrameCB& callback, | |
313 const gfx::Size& max_frame_output_size) { | |
314 DCHECK(thread_checker().CalledOnValidThread()); | |
315 io_message_loop()->PostTask( | |
316 FROM_HERE, | |
317 base::Bind( | |
318 &FrameDeliverer::AddCallbackWithResolutionOnIO, | |
319 this, id, callback, max_frame_output_size)); | |
320 } | |
321 | |
322 virtual void DeliverFrameOnIO( | |
323 const scoped_refptr<media::VideoFrame>& frame, | |
324 const media::VideoCaptureFormat& format) OVERRIDE { | |
325 DCHECK(io_message_loop()->BelongsToCurrentThread()); | |
326 TRACE_EVENT0("video", "MediaStreamVideoSource::DeliverFrameOnIO"); | |
327 if (max_output_size_.IsEmpty()) | |
328 return; // Frame received before the output has been decided. | |
329 | |
330 scoped_refptr<media::VideoFrame> video_frame(frame); | |
331 const gfx::Size& visible_size = frame->visible_rect().size(); | |
332 if (visible_size.width() > max_output_size_.width() || | |
333 visible_size.height() > max_output_size_.height()) { | |
334 // If |frame| is not the size that is expected, we need to crop it by | |
335 // providing a new |visible_rect|. The new visible rect must be within the | |
336 // original |visible_rect|. | |
337 gfx::Rect output_rect = frame->visible_rect(); | |
338 output_rect.ClampToCenteredSize(max_output_size_); | |
339 // TODO(perkj): Allow cropping of textures once http://crbug/362521 is | |
340 // fixed. | |
341 if (frame->format() != media::VideoFrame::NATIVE_TEXTURE) { | |
342 video_frame = media::VideoFrame::WrapVideoFrame( | |
343 frame, | |
344 output_rect, | |
345 output_rect.size(), | |
346 base::Bind(&ReleaseOriginalFrame, frame)); | |
347 } | |
348 } | |
349 VideoFrameDeliverer::DeliverFrameOnIO(video_frame, format); | |
350 } | |
351 | |
352 protected: | |
353 virtual ~FrameDeliverer() { | |
354 } | |
355 | |
356 void AddCallbackWithResolutionOnIO( | |
357 void* id, | |
358 const VideoCaptureDeliverFrameCB& callback, | |
359 const gfx::Size& max_frame_output_size) { | |
360 DCHECK(io_message_loop()->BelongsToCurrentThread()); | |
361 // Currently we only support one frame output size. | |
362 DCHECK(!max_frame_output_size.IsEmpty() && | |
363 (max_output_size_.IsEmpty() || | |
364 max_output_size_ == max_frame_output_size)); | |
365 max_output_size_ = max_frame_output_size; | |
366 VideoFrameDeliverer::AddCallbackOnIO(id, callback); | |
367 } | |
368 | |
369 private: | |
370 gfx::Size max_output_size_; | |
371 }; | |
372 | |
373 // static | 319 // static |
374 MediaStreamVideoSource* MediaStreamVideoSource::GetVideoSource( | 320 MediaStreamVideoSource* MediaStreamVideoSource::GetVideoSource( |
375 const blink::WebMediaStreamSource& source) { | 321 const blink::WebMediaStreamSource& source) { |
376 return static_cast<MediaStreamVideoSource*>(source.extraData()); | 322 return static_cast<MediaStreamVideoSource*>(source.extraData()); |
377 } | 323 } |
378 | 324 |
379 // static | 325 // static |
380 bool MediaStreamVideoSource::IsConstraintSupported(const std::string& name) { | 326 bool MediaStreamVideoSource::IsConstraintSupported(const std::string& name) { |
381 for (size_t i = 0; i < arraysize(kSupportedConstraints); ++i) { | 327 for (size_t i = 0; i < arraysize(kSupportedConstraints); ++i) { |
382 if (kSupportedConstraints[i] == name) | 328 if (kSupportedConstraints[i] == name) |
383 return true; | 329 return true; |
384 } | 330 } |
385 return false; | 331 return false; |
386 } | 332 } |
387 | 333 |
388 MediaStreamVideoSource::MediaStreamVideoSource( | 334 MediaStreamVideoSource::MediaStreamVideoSource( |
389 const scoped_refptr<base::MessageLoopProxy>& io_message_loop) | 335 const scoped_refptr<base::MessageLoopProxy>& io_message_loop) |
390 : state_(NEW), | 336 : state_(NEW), |
391 frame_deliverer_( | 337 track_adapter_( |
392 new MediaStreamVideoSource::FrameDeliverer(io_message_loop)), | 338 new VideoTrackAdapter(io_message_loop)), |
mcasas
2014/05/07 14:10:43
nit: Fits in one line.
perkj_chrome
2014/05/08 11:29:47
Done.
| |
393 weak_factory_(this) { | 339 weak_factory_(this) { |
394 } | 340 } |
395 | 341 |
396 MediaStreamVideoSource::~MediaStreamVideoSource() { | 342 MediaStreamVideoSource::~MediaStreamVideoSource() { |
397 DVLOG(3) << "~MediaStreamVideoSource()"; | 343 DVLOG(3) << "~MediaStreamVideoSource()"; |
398 } | 344 } |
399 | 345 |
400 void MediaStreamVideoSource::AddTrack( | 346 void MediaStreamVideoSource::AddTrack( |
401 MediaStreamVideoTrack* track, | 347 MediaStreamVideoTrack* track, |
402 const VideoCaptureDeliverFrameCB& frame_callback, | 348 const VideoCaptureDeliverFrameCB& frame_callback, |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
442 } | 388 } |
443 } | 389 } |
444 } | 390 } |
445 | 391 |
446 void MediaStreamVideoSource::RemoveTrack(MediaStreamVideoTrack* video_track) { | 392 void MediaStreamVideoSource::RemoveTrack(MediaStreamVideoTrack* video_track) { |
447 DCHECK(CalledOnValidThread()); | 393 DCHECK(CalledOnValidThread()); |
448 std::vector<MediaStreamVideoTrack*>::iterator it = | 394 std::vector<MediaStreamVideoTrack*>::iterator it = |
449 std::find(tracks_.begin(), tracks_.end(), video_track); | 395 std::find(tracks_.begin(), tracks_.end(), video_track); |
450 DCHECK(it != tracks_.end()); | 396 DCHECK(it != tracks_.end()); |
451 tracks_.erase(it); | 397 tracks_.erase(it); |
452 // Call |RemoveCallback| here even if adding the track has failed and | 398 |
453 // frame_deliverer_->AddCallback has not been called. | 399 // Check if the track is waiting for applying new constraints and remove |
454 frame_deliverer_->RemoveCallback(video_track); | 400 // it in that case. |
401 for (std::vector<RequestedConstraints>::iterator it = | |
402 requested_constraints_.begin(); | |
403 it != requested_constraints_.end(); ++it) { | |
404 if (it->track == video_track) { | |
405 requested_constraints_.erase(it); | |
406 break; | |
407 } | |
408 } | |
409 // Call |frame_adapter_->RemoveTrack| here even if adding the track has | |
410 // failed and |frame_adapter_->AddCallback| has not been called. | |
411 track_adapter_->RemoveTrack(video_track); | |
455 | 412 |
456 if (tracks_.empty()) | 413 if (tracks_.empty()) |
457 StopSource(); | 414 StopSource(); |
458 } | 415 } |
459 | 416 |
460 const scoped_refptr<base::MessageLoopProxy>& | 417 const scoped_refptr<base::MessageLoopProxy>& |
461 MediaStreamVideoSource::io_message_loop() const { | 418 MediaStreamVideoSource::io_message_loop() const { |
462 return frame_deliverer_->io_message_loop(); | 419 return track_adapter_->io_message_loop(); |
mcasas
2014/05/07 14:10:43
I think nobody uses this getter anymore.
perkj_chrome
2014/05/08 11:29:47
no- its used by a few of the classes that inherits
| |
463 } | 420 } |
464 | 421 |
465 void MediaStreamVideoSource::DoStopSource() { | 422 void MediaStreamVideoSource::DoStopSource() { |
466 DCHECK(CalledOnValidThread()); | 423 DCHECK(CalledOnValidThread()); |
467 DVLOG(3) << "DoStopSource()"; | 424 DVLOG(3) << "DoStopSource()"; |
468 if (state_ == ENDED) | 425 if (state_ == ENDED) |
469 return; | 426 return; |
470 StopSourceImpl(); | 427 StopSourceImpl(); |
471 state_ = ENDED; | 428 state_ = ENDED; |
472 SetReadyState(blink::WebMediaStreamSource::ReadyStateEnded); | 429 SetReadyState(blink::WebMediaStreamSource::ReadyStateEnded); |
473 } | 430 } |
474 | 431 |
475 void MediaStreamVideoSource::OnSupportedFormats( | 432 void MediaStreamVideoSource::OnSupportedFormats( |
476 const media::VideoCaptureFormats& formats) { | 433 const media::VideoCaptureFormats& formats) { |
477 DCHECK(CalledOnValidThread()); | 434 DCHECK(CalledOnValidThread()); |
478 DCHECK_EQ(RETRIEVING_CAPABILITIES, state_); | 435 DCHECK_EQ(RETRIEVING_CAPABILITIES, state_); |
479 | 436 |
480 supported_formats_ = formats; | 437 supported_formats_ = formats; |
481 if (!FindBestFormatWithConstraints(supported_formats_, | 438 if (!FindBestFormatWithConstraints(supported_formats_, |
482 ¤t_format_, | 439 ¤t_format_)) { |
483 &max_frame_output_size_, | |
484 ¤t_constraints_)) { | |
485 SetReadyState(blink::WebMediaStreamSource::ReadyStateEnded); | 440 SetReadyState(blink::WebMediaStreamSource::ReadyStateEnded); |
486 // This object can be deleted after calling FinalizeAddTrack. See comment | 441 // This object can be deleted after calling FinalizeAddTrack. See comment |
487 // in the header file. | 442 // in the header file. |
488 FinalizeAddTrack(); | 443 FinalizeAddTrack(); |
489 return; | 444 return; |
490 } | 445 } |
491 | 446 |
492 state_ = STARTING; | 447 state_ = STARTING; |
493 DVLOG(3) << "Starting the capturer with" | 448 DVLOG(3) << "Starting the capturer with" |
494 << " width = " << current_format_.frame_size.width() | 449 << " width = " << current_format_.frame_size.width() |
495 << " height = " << current_format_.frame_size.height() | 450 << " height = " << current_format_.frame_size.height() |
496 << " frame rate = " << current_format_.frame_rate; | 451 << " frame rate = " << current_format_.frame_rate; |
497 | 452 |
498 media::VideoCaptureParams params; | 453 media::VideoCaptureParams params; |
499 params.requested_format = current_format_; | 454 params.requested_format = current_format_; |
500 StartSourceImpl( | 455 StartSourceImpl( |
501 params, | 456 params, |
502 base::Bind(&MediaStreamVideoSource::FrameDeliverer::DeliverFrameOnIO, | 457 base::Bind(&VideoTrackAdapter::DeliverFrameOnIO, track_adapter_)); |
503 frame_deliverer_)); | |
504 } | 458 } |
505 | 459 |
506 bool MediaStreamVideoSource::FindBestFormatWithConstraints( | 460 bool MediaStreamVideoSource::FindBestFormatWithConstraints( |
507 const media::VideoCaptureFormats& formats, | 461 const media::VideoCaptureFormats& formats, |
508 media::VideoCaptureFormat* best_format, | 462 media::VideoCaptureFormat* best_format) { |
509 gfx::Size* max_frame_output_size, | |
510 blink::WebMediaConstraints* resulting_constraints) { | |
511 // Find the first constraints that we can fulfill. | 463 // Find the first constraints that we can fulfill. |
512 for (std::vector<RequestedConstraints>::iterator request_it = | 464 for (std::vector<RequestedConstraints>::iterator request_it = |
513 requested_constraints_.begin(); | 465 requested_constraints_.begin(); |
514 request_it != requested_constraints_.end(); ++request_it) { | 466 request_it != requested_constraints_.end(); ++request_it) { |
515 const blink::WebMediaConstraints& requested_constraints = | 467 const blink::WebMediaConstraints& requested_constraints = |
516 request_it->constraints; | 468 request_it->constraints; |
517 | 469 |
518 // If the source doesn't support capability enumeration it is still ok if | 470 // If the source doesn't support capability enumeration it is still ok if |
519 // no mandatory constraints have been specified. That just means that | 471 // no mandatory constraints have been specified. That just means that |
520 // we will start with whatever format is native to the source. | 472 // we will start with whatever format is native to the source. |
521 if (formats.empty() && !HasMandatoryConstraints(requested_constraints)) { | 473 if (formats.empty() && !HasMandatoryConstraints(requested_constraints)) { |
522 *best_format = media::VideoCaptureFormat(); | 474 *best_format = media::VideoCaptureFormat(); |
523 *resulting_constraints = requested_constraints; | |
524 *max_frame_output_size = gfx::Size(std::numeric_limits<int>::max(), | |
525 std::numeric_limits<int>::max()); | |
526 return true; | 475 return true; |
527 } | 476 } |
528 media::VideoCaptureFormats filtered_formats = | 477 media::VideoCaptureFormats filtered_formats = |
529 FilterFormats(requested_constraints, formats); | 478 FilterFormats(requested_constraints, formats); |
530 if (filtered_formats.size() > 0) { | 479 if (filtered_formats.size() > 0) { |
531 // A request with constraints that can be fulfilled. | 480 // A request with constraints that can be fulfilled. |
532 GetBestCaptureFormat(filtered_formats, | 481 GetBestCaptureFormat(filtered_formats, |
533 requested_constraints, | 482 requested_constraints, |
534 best_format, | 483 best_format); |
535 max_frame_output_size); | |
536 *resulting_constraints= requested_constraints; | |
537 return true; | 484 return true; |
538 } | 485 } |
539 } | 486 } |
540 return false; | 487 return false; |
541 } | 488 } |
542 | 489 |
543 void MediaStreamVideoSource::OnStartDone(bool success) { | 490 void MediaStreamVideoSource::OnStartDone(bool success) { |
544 DCHECK(CalledOnValidThread()); | 491 DCHECK(CalledOnValidThread()); |
545 DVLOG(3) << "OnStartDone({success =" << success << "})"; | 492 DVLOG(3) << "OnStartDone({success =" << success << "})"; |
546 if (success) { | 493 if (success) { |
(...skipping 21 matching lines...) Expand all Loading... | |
568 it != callbacks.end(); ++it) { | 515 it != callbacks.end(); ++it) { |
569 // The track has been added successfully if the source has started and | 516 // The track has been added successfully if the source has started and |
570 // there are either no mandatory constraints and the source doesn't expose | 517 // there are either no mandatory constraints and the source doesn't expose |
571 // its format capabilities, or the constraints and the format match. | 518 // its format capabilities, or the constraints and the format match. |
572 // For example, a remote source doesn't expose its format capabilities. | 519 // For example, a remote source doesn't expose its format capabilities. |
573 bool success = | 520 bool success = |
574 state_ == STARTED && | 521 state_ == STARTED && |
575 ((!current_format_.IsValid() && !HasMandatoryConstraints( | 522 ((!current_format_.IsValid() && !HasMandatoryConstraints( |
576 it->constraints)) || | 523 it->constraints)) || |
577 !FilterFormats(it->constraints, formats).empty()); | 524 !FilterFormats(it->constraints, formats).empty()); |
525 | |
578 if (success) { | 526 if (success) { |
579 frame_deliverer_->AddCallback(it->track, it->frame_callback, | 527 int max_width = std::numeric_limits<int>::max(); |
580 max_frame_output_size_); | 528 int max_height = std::numeric_limits<int>::max(); |
529 GetDesiredMaxWidthAndHeight(it->constraints, &max_width, &max_height); | |
mcasas
2014/05/07 14:10:43
nit: Inside GetDesiredMaxWidthAndHeight(), |max_wi
perkj_chrome
2014/05/08 11:29:47
done
| |
530 double max_aspect_ratio = std::numeric_limits<double>::max(); | |
531 double min_aspect_ratio = 0; | |
532 GetDesiredMinAndMaxAspectRatio(it->constraints, | |
533 &min_aspect_ratio, | |
534 &max_aspect_ratio); | |
535 track_adapter_->AddTrack(it->track,it->frame_callback, | |
536 max_width, max_height, | |
537 min_aspect_ratio, max_aspect_ratio); | |
581 } | 538 } |
539 | |
582 DVLOG(3) << "FinalizeAddTrack() success " << success; | 540 DVLOG(3) << "FinalizeAddTrack() success " << success; |
541 | |
583 if (!it->callback.is_null()) | 542 if (!it->callback.is_null()) |
584 it->callback.Run(this, success); | 543 it->callback.Run(this, success); |
585 } | 544 } |
586 } | 545 } |
587 | 546 |
588 void MediaStreamVideoSource::SetReadyState( | 547 void MediaStreamVideoSource::SetReadyState( |
589 blink::WebMediaStreamSource::ReadyState state) { | 548 blink::WebMediaStreamSource::ReadyState state) { |
590 if (!owner().isNull()) { | 549 if (!owner().isNull()) { |
591 owner().setReadyState(state); | 550 owner().setReadyState(state); |
592 } | 551 } |
(...skipping 11 matching lines...) Expand all Loading... | |
604 : track(track), | 563 : track(track), |
605 frame_callback(frame_callback), | 564 frame_callback(frame_callback), |
606 constraints(constraints), | 565 constraints(constraints), |
607 callback(callback) { | 566 callback(callback) { |
608 } | 567 } |
609 | 568 |
610 MediaStreamVideoSource::RequestedConstraints::~RequestedConstraints() { | 569 MediaStreamVideoSource::RequestedConstraints::~RequestedConstraints() { |
611 } | 570 } |
612 | 571 |
613 } // namespace content | 572 } // namespace content |
OLD | NEW |