| 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 |
| (...skipping 202 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 213 format_it = formats->erase(format_it); | 213 format_it = formats->erase(format_it); |
| 214 } else { | 214 } else { |
| 215 ++format_it; | 215 ++format_it; |
| 216 } | 216 } |
| 217 } | 217 } |
| 218 } | 218 } |
| 219 | 219 |
| 220 // Returns the media::VideoCaptureFormats that matches |constraints|. | 220 // Returns the media::VideoCaptureFormats that matches |constraints|. |
| 221 media::VideoCaptureFormats FilterFormats( | 221 media::VideoCaptureFormats FilterFormats( |
| 222 const blink::WebMediaConstraints& constraints, | 222 const blink::WebMediaConstraints& constraints, |
| 223 const media::VideoCaptureFormats& supported_formats) { | 223 const media::VideoCaptureFormats& supported_formats, |
| 224 blink::WebString* unsatisfied_constraint) { |
| 224 if (constraints.isNull()) { | 225 if (constraints.isNull()) { |
| 225 return supported_formats; | 226 return supported_formats; |
| 226 } | 227 } |
| 227 | 228 |
| 228 double max_aspect_ratio; | 229 double max_aspect_ratio; |
| 229 double min_aspect_ratio; | 230 double min_aspect_ratio; |
| 230 GetDesiredMinAndMaxAspectRatio(constraints, | 231 GetDesiredMinAndMaxAspectRatio(constraints, |
| 231 &min_aspect_ratio, | 232 &min_aspect_ratio, |
| 232 &max_aspect_ratio); | 233 &max_aspect_ratio); |
| 233 | 234 |
| (...skipping 29 matching lines...) Expand all Loading... |
| 263 DLOG(WARNING) << "Wrong requested frame rate."; | 264 DLOG(WARNING) << "Wrong requested frame rate."; |
| 264 return media::VideoCaptureFormats(); | 265 return media::VideoCaptureFormats(); |
| 265 } | 266 } |
| 266 } | 267 } |
| 267 | 268 |
| 268 blink::WebVector<blink::WebMediaConstraint> mandatory; | 269 blink::WebVector<blink::WebMediaConstraint> mandatory; |
| 269 blink::WebVector<blink::WebMediaConstraint> optional; | 270 blink::WebVector<blink::WebMediaConstraint> optional; |
| 270 constraints.getMandatoryConstraints(mandatory); | 271 constraints.getMandatoryConstraints(mandatory); |
| 271 constraints.getOptionalConstraints(optional); | 272 constraints.getOptionalConstraints(optional); |
| 272 media::VideoCaptureFormats candidates = supported_formats; | 273 media::VideoCaptureFormats candidates = supported_formats; |
| 273 for (size_t i = 0; i < mandatory.size(); ++i) | 274 for (size_t i = 0; i < mandatory.size(); ++i) { |
| 274 FilterFormatsByConstraint(mandatory[i], true, &candidates); | 275 FilterFormatsByConstraint(mandatory[i], true, &candidates); |
| 275 | 276 if (candidates.empty()) { |
| 276 if (candidates.empty()) | 277 *unsatisfied_constraint = mandatory[i].m_name; |
| 277 return candidates; | 278 return candidates; |
| 279 } |
| 280 } |
| 278 | 281 |
| 279 // Ok - all mandatory checked and we still have candidates. | 282 // Ok - all mandatory checked and we still have candidates. |
| 280 // Let's try filtering using the optional constraints. The optional | 283 // Let's try filtering using the optional constraints. The optional |
| 281 // constraints must be filtered in the order they occur in |optional|. | 284 // constraints must be filtered in the order they occur in |optional|. |
| 282 // But if a constraint produce zero candidates, the constraint is ignored and | 285 // But if a constraint produce zero candidates, the constraint is ignored and |
| 283 // the next constraint is tested. | 286 // the next constraint is tested. |
| 284 // http://dev.w3.org/2011/webrtc/editor/getusermedia.html#idl-def-Constraints | 287 // http://dev.w3.org/2011/webrtc/editor/getusermedia.html#idl-def-Constraints |
| 285 for (size_t i = 0; i < optional.size(); ++i) { | 288 for (size_t i = 0; i < optional.size(); ++i) { |
| 286 media::VideoCaptureFormats current_candidates = candidates; | 289 media::VideoCaptureFormats current_candidates = candidates; |
| 287 FilterFormatsByConstraint(optional[i], false, ¤t_candidates); | 290 FilterFormatsByConstraint(optional[i], false, ¤t_candidates); |
| (...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 398 } | 401 } |
| 399 case STARTING: | 402 case STARTING: |
| 400 case RETRIEVING_CAPABILITIES: { | 403 case RETRIEVING_CAPABILITIES: { |
| 401 // The |callback| will be triggered once the source has started or | 404 // The |callback| will be triggered once the source has started or |
| 402 // the capabilities have been retrieved. | 405 // the capabilities have been retrieved. |
| 403 break; | 406 break; |
| 404 } | 407 } |
| 405 case ENDED: | 408 case ENDED: |
| 406 case STARTED: { | 409 case STARTED: { |
| 407 // Currently, reconfiguring the source is not supported. | 410 // Currently, reconfiguring the source is not supported. |
| 408 FinalizeAddTrack(); | 411 FinalizeAddTrack(MEDIA_DEVICE_OK, ""); |
| 409 } | 412 } |
| 410 } | 413 } |
| 411 } | 414 } |
| 412 | 415 |
| 413 void MediaStreamVideoSource::RemoveTrack(MediaStreamVideoTrack* video_track) { | 416 void MediaStreamVideoSource::RemoveTrack(MediaStreamVideoTrack* video_track) { |
| 414 DCHECK(CalledOnValidThread()); | 417 DCHECK(CalledOnValidThread()); |
| 415 std::vector<MediaStreamVideoTrack*>::iterator it = | 418 std::vector<MediaStreamVideoTrack*>::iterator it = |
| 416 std::find(tracks_.begin(), tracks_.end(), video_track); | 419 std::find(tracks_.begin(), tracks_.end(), video_track); |
| 417 DCHECK(it != tracks_.end()); | 420 DCHECK(it != tracks_.end()); |
| 418 tracks_.erase(it); | 421 tracks_.erase(it); |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 450 state_ = ENDED; | 453 state_ = ENDED; |
| 451 SetReadyState(blink::WebMediaStreamSource::ReadyStateEnded); | 454 SetReadyState(blink::WebMediaStreamSource::ReadyStateEnded); |
| 452 } | 455 } |
| 453 | 456 |
| 454 void MediaStreamVideoSource::OnSupportedFormats( | 457 void MediaStreamVideoSource::OnSupportedFormats( |
| 455 const media::VideoCaptureFormats& formats) { | 458 const media::VideoCaptureFormats& formats) { |
| 456 DCHECK(CalledOnValidThread()); | 459 DCHECK(CalledOnValidThread()); |
| 457 DCHECK_EQ(RETRIEVING_CAPABILITIES, state_); | 460 DCHECK_EQ(RETRIEVING_CAPABILITIES, state_); |
| 458 | 461 |
| 459 supported_formats_ = formats; | 462 supported_formats_ = formats; |
| 463 blink::WebString unsatisfied_constraint; |
| 460 if (!FindBestFormatWithConstraints(supported_formats_, | 464 if (!FindBestFormatWithConstraints(supported_formats_, |
| 461 ¤t_format_)) { | 465 ¤t_format_, |
| 466 &unsatisfied_constraint)) { |
| 462 SetReadyState(blink::WebMediaStreamSource::ReadyStateEnded); | 467 SetReadyState(blink::WebMediaStreamSource::ReadyStateEnded); |
| 463 // This object can be deleted after calling FinalizeAddTrack. See comment | 468 // This object can be deleted after calling FinalizeAddTrack. See comment |
| 464 // in the header file. | 469 // in the header file. |
| 465 FinalizeAddTrack(); | 470 FinalizeAddTrack(MEDIA_DEVICE_CONSTRAINT_NOT_SATISFIED, |
| 471 unsatisfied_constraint); |
| 466 return; | 472 return; |
| 467 } | 473 } |
| 468 | 474 |
| 469 state_ = STARTING; | 475 state_ = STARTING; |
| 470 DVLOG(3) << "Starting the capturer with" | 476 DVLOG(3) << "Starting the capturer with" |
| 471 << " width = " << current_format_.frame_size.width() | 477 << " width = " << current_format_.frame_size.width() |
| 472 << " height = " << current_format_.frame_size.height() | 478 << " height = " << current_format_.frame_size.height() |
| 473 << " frame rate = " << current_format_.frame_rate | 479 << " frame rate = " << current_format_.frame_rate |
| 474 << " pixel format = " | 480 << " pixel format = " |
| 475 << media::VideoCaptureFormat::PixelFormatToString( | 481 << media::VideoCaptureFormat::PixelFormatToString( |
| 476 current_format_.pixel_format); | 482 current_format_.pixel_format); |
| 477 | 483 |
| 478 media::VideoCaptureParams params; | 484 media::VideoCaptureParams params; |
| 479 params.requested_format = current_format_; | 485 params.requested_format = current_format_; |
| 480 StartSourceImpl( | 486 StartSourceImpl( |
| 481 params, | 487 params, |
| 482 base::Bind(&VideoTrackAdapter::DeliverFrameOnIO, track_adapter_)); | 488 base::Bind(&VideoTrackAdapter::DeliverFrameOnIO, track_adapter_)); |
| 483 } | 489 } |
| 484 | 490 |
| 485 bool MediaStreamVideoSource::FindBestFormatWithConstraints( | 491 bool MediaStreamVideoSource::FindBestFormatWithConstraints( |
| 486 const media::VideoCaptureFormats& formats, | 492 const media::VideoCaptureFormats& formats, |
| 487 media::VideoCaptureFormat* best_format) { | 493 media::VideoCaptureFormat* best_format, |
| 494 blink::WebString* unsatisfied_constraint) { |
| 488 DCHECK(CalledOnValidThread()); | 495 DCHECK(CalledOnValidThread()); |
| 489 // Find the first constraints that we can fulfill. | 496 // Find the first constraints that we can fulfill. |
| 490 for (std::vector<RequestedConstraints>::iterator request_it = | 497 for (std::vector<RequestedConstraints>::iterator request_it = |
| 491 requested_constraints_.begin(); | 498 requested_constraints_.begin(); |
| 492 request_it != requested_constraints_.end(); ++request_it) { | 499 request_it != requested_constraints_.end(); ++request_it) { |
| 493 const blink::WebMediaConstraints& requested_constraints = | 500 const blink::WebMediaConstraints& requested_constraints = |
| 494 request_it->constraints; | 501 request_it->constraints; |
| 495 | 502 |
| 496 // If the source doesn't support capability enumeration it is still ok if | 503 // If the source doesn't support capability enumeration it is still ok if |
| 497 // no mandatory constraints have been specified. That just means that | 504 // no mandatory constraints have been specified. That just means that |
| 498 // we will start with whatever format is native to the source. | 505 // we will start with whatever format is native to the source. |
| 499 if (formats.empty() && !HasMandatoryConstraints(requested_constraints)) { | 506 if (formats.empty() && !HasMandatoryConstraints(requested_constraints)) { |
| 500 *best_format = media::VideoCaptureFormat(); | 507 *best_format = media::VideoCaptureFormat(); |
| 501 return true; | 508 return true; |
| 502 } | 509 } |
| 503 media::VideoCaptureFormats filtered_formats = | 510 media::VideoCaptureFormats filtered_formats = |
| 504 FilterFormats(requested_constraints, formats); | 511 FilterFormats(requested_constraints, formats, unsatisfied_constraint); |
| 505 if (filtered_formats.size() > 0) { | 512 if (filtered_formats.size() > 0) { |
| 506 // A request with constraints that can be fulfilled. | 513 // A request with constraints that can be fulfilled. |
| 507 GetBestCaptureFormat(filtered_formats, | 514 GetBestCaptureFormat(filtered_formats, |
| 508 requested_constraints, | 515 requested_constraints, |
| 509 best_format); | 516 best_format); |
| 510 return true; | 517 return true; |
| 511 } | 518 } |
| 512 } | 519 } |
| 513 return false; | 520 return false; |
| 514 } | 521 } |
| 515 | 522 |
| 516 void MediaStreamVideoSource::OnStartDone(bool success) { | 523 void MediaStreamVideoSource::OnStartDone(MediaStreamRequestResult result) { |
| 517 DCHECK(CalledOnValidThread()); | 524 DCHECK(CalledOnValidThread()); |
| 518 DVLOG(3) << "OnStartDone({success =" << success << "})"; | 525 DVLOG(3) << "OnStartDone({result =" << result << "})"; |
| 519 if (success) { | 526 if (result == MEDIA_DEVICE_OK) { |
| 520 DCHECK_EQ(STARTING, state_); | 527 DCHECK_EQ(STARTING, state_); |
| 521 state_ = STARTED; | 528 state_ = STARTED; |
| 522 SetReadyState(blink::WebMediaStreamSource::ReadyStateLive); | 529 SetReadyState(blink::WebMediaStreamSource::ReadyStateLive); |
| 523 } else { | 530 } else { |
| 524 StopSource(); | 531 StopSource(); |
| 525 } | 532 } |
| 526 | 533 |
| 527 // This object can be deleted after calling FinalizeAddTrack. See comment in | 534 // This object can be deleted after calling FinalizeAddTrack. See comment in |
| 528 // the header file. | 535 // the header file. |
| 529 FinalizeAddTrack(); | 536 FinalizeAddTrack(result, ""); |
| 530 } | 537 } |
| 531 | 538 |
| 532 void MediaStreamVideoSource::FinalizeAddTrack() { | 539 void MediaStreamVideoSource::FinalizeAddTrack( |
| 540 MediaStreamRequestResult result, |
| 541 const blink::WebString& result_name) { |
| 533 DCHECK(CalledOnValidThread()); | 542 DCHECK(CalledOnValidThread()); |
| 534 media::VideoCaptureFormats formats; | 543 media::VideoCaptureFormats formats; |
| 535 formats.push_back(current_format_); | 544 formats.push_back(current_format_); |
| 536 | 545 |
| 537 std::vector<RequestedConstraints> callbacks; | 546 std::vector<RequestedConstraints> callbacks; |
| 538 callbacks.swap(requested_constraints_); | 547 callbacks.swap(requested_constraints_); |
| 539 for (std::vector<RequestedConstraints>::iterator it = callbacks.begin(); | 548 for (std::vector<RequestedConstraints>::iterator it = callbacks.begin(); |
| 540 it != callbacks.end(); ++it) { | 549 it != callbacks.end(); ++it) { |
| 541 // The track has been added successfully if the source has started and | 550 if (result == MEDIA_DEVICE_OK) { |
| 542 // there are either no mandatory constraints and the source doesn't expose | |
| 543 // its format capabilities, or the constraints and the format match. | |
| 544 // For example, a remote source doesn't expose its format capabilities. | |
| 545 bool success = | |
| 546 state_ == STARTED && | |
| 547 ((!current_format_.IsValid() && !HasMandatoryConstraints( | |
| 548 it->constraints)) || | |
| 549 !FilterFormats(it->constraints, formats).empty()); | |
| 550 | |
| 551 if (success) { | |
| 552 int max_width; | 551 int max_width; |
| 553 int max_height; | 552 int max_height; |
| 554 GetDesiredMaxWidthAndHeight(it->constraints, &max_width, &max_height); | 553 GetDesiredMaxWidthAndHeight(it->constraints, &max_width, &max_height); |
| 555 double max_aspect_ratio; | 554 double max_aspect_ratio; |
| 556 double min_aspect_ratio; | 555 double min_aspect_ratio; |
| 557 GetDesiredMinAndMaxAspectRatio(it->constraints, | 556 GetDesiredMinAndMaxAspectRatio(it->constraints, |
| 558 &min_aspect_ratio, | 557 &min_aspect_ratio, |
| 559 &max_aspect_ratio); | 558 &max_aspect_ratio); |
| 560 double max_frame_rate = 0.0f; | 559 double max_frame_rate = 0.0f; |
| 561 GetConstraintValueAsDouble(it->constraints, | 560 GetConstraintValueAsDouble(it->constraints, |
| 562 kMaxFrameRate, &max_frame_rate); | 561 kMaxFrameRate, &max_frame_rate); |
| 563 | 562 |
| 564 VideoTrackAdapter::OnMutedCallback on_mute_callback = | 563 VideoTrackAdapter::OnMutedCallback on_mute_callback = |
| 565 media::BindToCurrentLoop(base::Bind( | 564 media::BindToCurrentLoop(base::Bind( |
| 566 &MediaStreamVideoSource::SetMutedState, | 565 &MediaStreamVideoSource::SetMutedState, |
| 567 weak_factory_.GetWeakPtr())); | 566 weak_factory_.GetWeakPtr())); |
| 568 track_adapter_->AddTrack(it->track, it->frame_callback, | 567 track_adapter_->AddTrack(it->track, it->frame_callback, |
| 569 max_width, max_height, | 568 max_width, max_height, |
| 570 min_aspect_ratio, max_aspect_ratio, | 569 min_aspect_ratio, max_aspect_ratio, |
| 571 max_frame_rate, current_format_.frame_rate, | 570 max_frame_rate, current_format_.frame_rate, |
| 572 on_mute_callback); | 571 on_mute_callback); |
| 573 } | 572 } |
| 574 | 573 |
| 575 DVLOG(3) << "FinalizeAddTrack() success " << success; | 574 DVLOG(3) << "FinalizeAddTrack() result " << result; |
| 576 | 575 |
| 577 if (!it->callback.is_null()) | 576 if (!it->callback.is_null()) |
| 578 it->callback.Run(this, success); | 577 it->callback.Run(this, result, result_name); |
| 579 } | 578 } |
| 580 } | 579 } |
| 581 | 580 |
| 582 void MediaStreamVideoSource::SetReadyState( | 581 void MediaStreamVideoSource::SetReadyState( |
| 583 blink::WebMediaStreamSource::ReadyState state) { | 582 blink::WebMediaStreamSource::ReadyState state) { |
| 584 DVLOG(3) << "MediaStreamVideoSource::SetReadyState state " << state; | 583 DVLOG(3) << "MediaStreamVideoSource::SetReadyState state " << state; |
| 585 DCHECK(CalledOnValidThread()); | 584 DCHECK(CalledOnValidThread()); |
| 586 if (!owner().isNull()) { | 585 if (!owner().isNull()) { |
| 587 owner().setReadyState(state); | 586 owner().setReadyState(state); |
| 588 } | 587 } |
| (...skipping 21 matching lines...) Expand all Loading... |
| 610 : track(track), | 609 : track(track), |
| 611 frame_callback(frame_callback), | 610 frame_callback(frame_callback), |
| 612 constraints(constraints), | 611 constraints(constraints), |
| 613 callback(callback) { | 612 callback(callback) { |
| 614 } | 613 } |
| 615 | 614 |
| 616 MediaStreamVideoSource::RequestedConstraints::~RequestedConstraints() { | 615 MediaStreamVideoSource::RequestedConstraints::~RequestedConstraints() { |
| 617 } | 616 } |
| 618 | 617 |
| 619 } // namespace content | 618 } // namespace content |
| OLD | NEW |