| 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/video_track_adapter.h" | 5 #include "content/renderer/media/video_track_adapter.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 #include <limits> | 8 #include <limits> |
| 9 #include <utility> | 9 #include <utility> |
| 10 | 10 |
| (...skipping 11 matching lines...) Expand all Loading... |
| 22 // Amount of frame intervals to wait before considering the source as muted, for | 22 // Amount of frame intervals to wait before considering the source as muted, for |
| 23 // the first frame and under normal conditions, respectively. First frame might | 23 // the first frame and under normal conditions, respectively. First frame might |
| 24 // take longer to arrive due to source startup. | 24 // take longer to arrive due to source startup. |
| 25 const float kFirstFrameTimeoutInFrameIntervals = 100.0f; | 25 const float kFirstFrameTimeoutInFrameIntervals = 100.0f; |
| 26 const float kNormalFrameTimeoutInFrameIntervals = 25.0f; | 26 const float kNormalFrameTimeoutInFrameIntervals = 25.0f; |
| 27 | 27 |
| 28 // Min delta time between two frames allowed without being dropped if a max | 28 // Min delta time between two frames allowed without being dropped if a max |
| 29 // frame rate is specified. | 29 // frame rate is specified. |
| 30 const int kMinTimeInMsBetweenFrames = 5; | 30 const int kMinTimeInMsBetweenFrames = 5; |
| 31 | 31 |
| 32 const int kNumberOfFramesInFrameRateCalculation = 20; |
| 33 |
| 32 // Empty method used for keeping a reference to the original media::VideoFrame | 34 // Empty method used for keeping a reference to the original media::VideoFrame |
| 33 // in VideoFrameResolutionAdapter::DeliverFrame if cropping is needed. | 35 // in VideoFrameResolutionAdapter::DeliverFrame if cropping is needed. |
| 34 // The reference to |frame| is kept in the closure that calls this method. | 36 // The reference to |frame| is kept in the closure that calls this method. |
| 35 void ReleaseOriginalFrame( | 37 void ReleaseOriginalFrame( |
| 36 const scoped_refptr<media::VideoFrame>& frame) { | 38 const scoped_refptr<media::VideoFrame>& frame) { |
| 37 } | 39 } |
| 38 | 40 |
| 39 void ResetCallbackOnMainRenderThread( | 41 void ResetCallbackOnMainRenderThread( |
| 40 scoped_ptr<VideoCaptureDeliverFrameCB> callback) { | 42 scoped_ptr<VideoCaptureDeliverFrameCB> callback) { |
| 41 // |callback| will be deleted when this exits. | 43 // |callback| will be deleted when this exits. |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 98 | 100 |
| 99 // The task runner where we will release VideoCaptureDeliverFrameCB | 101 // The task runner where we will release VideoCaptureDeliverFrameCB |
| 100 // registered in AddCallback. | 102 // registered in AddCallback. |
| 101 scoped_refptr<base::SingleThreadTaskRunner> renderer_task_runner_; | 103 scoped_refptr<base::SingleThreadTaskRunner> renderer_task_runner_; |
| 102 | 104 |
| 103 gfx::Size max_frame_size_; | 105 gfx::Size max_frame_size_; |
| 104 double min_aspect_ratio_; | 106 double min_aspect_ratio_; |
| 105 double max_aspect_ratio_; | 107 double max_aspect_ratio_; |
| 106 | 108 |
| 107 double frame_rate_; | 109 double frame_rate_; |
| 110 int number_of_dropped_frames_; |
| 108 base::TimeDelta last_time_stamp_; | 111 base::TimeDelta last_time_stamp_; |
| 109 double max_frame_rate_; | 112 double max_frame_rate_; |
| 110 double keep_frame_counter_; | 113 double keep_frame_counter_; |
| 111 | 114 |
| 112 typedef std::pair<const void*, VideoCaptureDeliverFrameCB> | 115 typedef std::pair<const void*, VideoCaptureDeliverFrameCB> |
| 113 VideoIdCallbackPair; | 116 VideoIdCallbackPair; |
| 114 std::vector<VideoIdCallbackPair> callbacks_; | 117 std::vector<VideoIdCallbackPair> callbacks_; |
| 115 | 118 |
| 116 DISALLOW_COPY_AND_ASSIGN(VideoFrameResolutionAdapter); | 119 DISALLOW_COPY_AND_ASSIGN(VideoFrameResolutionAdapter); |
| 117 }; | 120 }; |
| (...skipping 212 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 330 bool VideoTrackAdapter::VideoFrameResolutionAdapter::IsEmpty() const { | 333 bool VideoTrackAdapter::VideoFrameResolutionAdapter::IsEmpty() const { |
| 331 DCHECK(io_thread_checker_.CalledOnValidThread()); | 334 DCHECK(io_thread_checker_.CalledOnValidThread()); |
| 332 return callbacks_.empty(); | 335 return callbacks_.empty(); |
| 333 } | 336 } |
| 334 | 337 |
| 335 VideoTrackAdapter::VideoTrackAdapter( | 338 VideoTrackAdapter::VideoTrackAdapter( |
| 336 const scoped_refptr<base::MessageLoopProxy>& io_message_loop) | 339 const scoped_refptr<base::MessageLoopProxy>& io_message_loop) |
| 337 : io_message_loop_(io_message_loop), | 340 : io_message_loop_(io_message_loop), |
| 338 renderer_task_runner_(base::MessageLoopProxy::current()), | 341 renderer_task_runner_(base::MessageLoopProxy::current()), |
| 339 monitoring_frame_rate_(false), | 342 monitoring_frame_rate_(false), |
| 340 muted_state_(false), | |
| 341 frame_counter_(0), | 343 frame_counter_(0), |
| 342 source_frame_rate_(0.0f) { | 344 source_frame_rate_(0.0f), |
| 345 dropped_frames_counter_(0) { |
| 343 DCHECK(io_message_loop_.get()); | 346 DCHECK(io_message_loop_.get()); |
| 344 } | 347 } |
| 345 | 348 |
| 346 VideoTrackAdapter::~VideoTrackAdapter() { | 349 VideoTrackAdapter::~VideoTrackAdapter() { |
| 347 DCHECK(adapters_.empty()); | 350 DCHECK(adapters_.empty()); |
| 348 } | 351 } |
| 349 | 352 |
| 350 void VideoTrackAdapter::AddTrack( | 353 void VideoTrackAdapter::AddTrack( |
| 351 const MediaStreamVideoTrack* track, | 354 const MediaStreamVideoTrack* track, |
| 352 VideoCaptureDeliverFrameCB frame_callback, | 355 VideoCaptureDeliverFrameCB frame_callback, |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 395 | 398 |
| 396 void VideoTrackAdapter::RemoveTrack(const MediaStreamVideoTrack* track) { | 399 void VideoTrackAdapter::RemoveTrack(const MediaStreamVideoTrack* track) { |
| 397 DCHECK(thread_checker_.CalledOnValidThread()); | 400 DCHECK(thread_checker_.CalledOnValidThread()); |
| 398 io_message_loop_->PostTask( | 401 io_message_loop_->PostTask( |
| 399 FROM_HERE, | 402 FROM_HERE, |
| 400 base::Bind(&VideoTrackAdapter::RemoveTrackOnIO, this, track)); | 403 base::Bind(&VideoTrackAdapter::RemoveTrackOnIO, this, track)); |
| 401 } | 404 } |
| 402 | 405 |
| 403 void VideoTrackAdapter::StartFrameMonitoring( | 406 void VideoTrackAdapter::StartFrameMonitoring( |
| 404 double source_frame_rate, | 407 double source_frame_rate, |
| 405 const OnMutedCallback& on_muted_callback) { | 408 const OnFrameRateCallback& on_muted_callback) { |
| 406 DCHECK(thread_checker_.CalledOnValidThread()); | 409 DCHECK(thread_checker_.CalledOnValidThread()); |
| 407 | 410 |
| 408 VideoTrackAdapter::OnMutedCallback bound_on_muted_callback = | 411 VideoTrackAdapter::OnFrameRateCallback bound_on_muted_callback = |
| 409 media::BindToCurrentLoop(on_muted_callback); | 412 media::BindToCurrentLoop(on_muted_callback); |
| 410 | 413 |
| 414 media::BindToCurrentLoop(on_muted_callback); |
| 415 |
| 411 io_message_loop_->PostTask( | 416 io_message_loop_->PostTask( |
| 412 FROM_HERE, | 417 FROM_HERE, |
| 413 base::Bind(&VideoTrackAdapter::StartFrameMonitoringOnIO, | 418 base::Bind(&VideoTrackAdapter::StartFrameMonitoringOnIO, |
| 414 this, bound_on_muted_callback, source_frame_rate)); | 419 this, bound_on_muted_callback, source_frame_rate)); |
| 415 } | 420 } |
| 416 | 421 |
| 417 void VideoTrackAdapter::StartFrameMonitoringOnIO( | 422 void VideoTrackAdapter::StartFrameMonitoringOnIO( |
| 418 const OnMutedCallback& on_muted_callback, | 423 const OnFrameRateCallback& on_muted_callback, |
| 419 double source_frame_rate) { | 424 double source_frame_rate) { |
| 420 DCHECK(io_message_loop_->BelongsToCurrentThread()); | 425 DCHECK(io_message_loop_->BelongsToCurrentThread()); |
| 421 DCHECK(!monitoring_frame_rate_); | 426 DCHECK(!monitoring_frame_rate_); |
| 422 | 427 |
| 423 monitoring_frame_rate_ = true; | 428 monitoring_frame_rate_ = true; |
| 424 | 429 |
| 425 // If the source does not know the frame rate, set one by default. | 430 // If the source does not know the frame rate, set one by default. |
| 426 if (source_frame_rate == 0.0f) | 431 if (source_frame_rate == 0.0f) |
| 427 source_frame_rate = MediaStreamVideoSource::kDefaultFrameRate; | 432 source_frame_rate = MediaStreamVideoSource::kDefaultFrameRate; |
| 433 |
| 428 source_frame_rate_ = source_frame_rate; | 434 source_frame_rate_ = source_frame_rate; |
| 429 DVLOG(1) << "Monitoring frame creation, first (large) delay: " | 435 DVLOG(1) << "Monitoring frame creation, first (large) delay: " |
| 430 << (kFirstFrameTimeoutInFrameIntervals / source_frame_rate_) << "s"; | 436 << (kFirstFrameTimeoutInFrameIntervals / source_frame_rate_) << "s"; |
| 431 io_message_loop_->PostDelayedTask(FROM_HERE, | 437 io_message_loop_->PostDelayedTask(FROM_HERE, |
| 432 base::Bind(&VideoTrackAdapter::CheckFramesReceivedOnIO, this, | 438 base::Bind(&VideoTrackAdapter::CheckFramesReceivedOnIO, this, |
| 433 on_muted_callback, frame_counter_), | 439 on_muted_callback, frame_counter_, dropped_frames_counter_), |
| 434 base::TimeDelta::FromSecondsD(kFirstFrameTimeoutInFrameIntervals / | 440 base::TimeDelta::FromSecondsD(kFirstFrameTimeoutInFrameIntervals / |
| 435 source_frame_rate_)); | 441 source_frame_rate_)); |
| 436 } | 442 } |
| 437 | 443 |
| 438 void VideoTrackAdapter::StopFrameMonitoring() { | 444 void VideoTrackAdapter::StopFrameMonitoring() { |
| 439 DCHECK(thread_checker_.CalledOnValidThread()); | 445 DCHECK(thread_checker_.CalledOnValidThread()); |
| 440 io_message_loop_->PostTask( | 446 io_message_loop_->PostTask( |
| 441 FROM_HERE, | 447 FROM_HERE, |
| 442 base::Bind(&VideoTrackAdapter::StopFrameMonitoringOnIO, this)); | 448 base::Bind(&VideoTrackAdapter::StopFrameMonitoringOnIO, this)); |
| 443 } | 449 } |
| (...skipping 15 matching lines...) Expand all Loading... |
| 459 } | 465 } |
| 460 } | 466 } |
| 461 | 467 |
| 462 void VideoTrackAdapter::DeliverFrameOnIO( | 468 void VideoTrackAdapter::DeliverFrameOnIO( |
| 463 const scoped_refptr<media::VideoFrame>& frame, | 469 const scoped_refptr<media::VideoFrame>& frame, |
| 464 const media::VideoCaptureFormat& format, | 470 const media::VideoCaptureFormat& format, |
| 465 const base::TimeTicks& estimated_capture_time) { | 471 const base::TimeTicks& estimated_capture_time) { |
| 466 DCHECK(io_message_loop_->BelongsToCurrentThread()); | 472 DCHECK(io_message_loop_->BelongsToCurrentThread()); |
| 467 TRACE_EVENT0("video", "VideoTrackAdapter::DeliverFrameOnIO"); | 473 TRACE_EVENT0("video", "VideoTrackAdapter::DeliverFrameOnIO"); |
| 468 ++frame_counter_; | 474 ++frame_counter_; |
| 475 UpdateFrameRateOnIO(frame->timestamp());; |
| 476 dropped_frames_counter_ = format.number_of_dropped_frames; |
| 477 |
| 469 for (FrameAdapters::iterator it = adapters_.begin(); | 478 for (FrameAdapters::iterator it = adapters_.begin(); |
| 470 it != adapters_.end(); ++it) { | 479 it != adapters_.end(); ++it) { |
| 471 (*it)->DeliverFrame(frame, format, estimated_capture_time); | 480 (*it)->DeliverFrame(frame, format, estimated_capture_time); |
| 472 } | 481 } |
| 473 } | 482 } |
| 474 | 483 |
| 484 void VideoTrackAdapter::UpdateFrameRateOnIO(base::TimeDelta timestamp) { |
| 485 DCHECK(io_message_loop_->BelongsToCurrentThread()); |
| 486 |
| 487 frame_timestamps_.push(timestamp); |
| 488 if (frame_timestamps_.size() > kNumberOfFramesInFrameRateCalculation) |
| 489 frame_timestamps_.pop(); |
| 490 } |
| 491 |
| 492 float VideoTrackAdapter::GetFrameRateOnIO() { |
| 493 if (frame_timestamps_.size() < 2) |
| 494 return 0; |
| 495 return frame_timestamps_.size() / |
| 496 (frame_timestamps_.back() - frame_timestamps_.front()).InSecondsF(); |
| 497 } |
| 498 |
| 475 void VideoTrackAdapter::CheckFramesReceivedOnIO( | 499 void VideoTrackAdapter::CheckFramesReceivedOnIO( |
| 476 const OnMutedCallback& set_muted_state_callback, | 500 const OnFrameRateCallback& set_muted_state_callback, |
| 477 uint64 old_frame_counter_snapshot) { | 501 uint64 old_frame_counter_snapshot, |
| 502 int old_dropped_frame_counter_snapshot) { |
| 478 DCHECK(io_message_loop_->BelongsToCurrentThread()); | 503 DCHECK(io_message_loop_->BelongsToCurrentThread()); |
| 479 | 504 |
| 480 if (!monitoring_frame_rate_) | 505 if (!monitoring_frame_rate_) |
| 481 return; | 506 return; |
| 482 | 507 |
| 483 DVLOG_IF(1, old_frame_counter_snapshot == frame_counter_) | 508 DVLOG_IF(1, old_frame_counter_snapshot == frame_counter_) |
| 484 << "No frames have passed, setting source as Muted."; | 509 << "No frames have passed, setting source as Muted."; |
| 485 | 510 |
| 486 bool muted_state = old_frame_counter_snapshot == frame_counter_; | 511 bool muted_state = old_frame_counter_snapshot == frame_counter_; |
| 487 if (muted_state_ != muted_state) { | 512 if (muted_state) { |
| 488 set_muted_state_callback.Run(muted_state); | 513 frame_timestamps_ = std::queue<base::TimeDelta>(); |
| 489 muted_state_ = muted_state; | |
| 490 } | 514 } |
| 515 set_muted_state_callback.Run( |
| 516 GetFrameRateOnIO(), |
| 517 dropped_frames_counter_ - old_dropped_frame_counter_snapshot); |
| 491 | 518 |
| 492 io_message_loop_->PostDelayedTask(FROM_HERE, | 519 io_message_loop_->PostDelayedTask(FROM_HERE, |
| 493 base::Bind(&VideoTrackAdapter::CheckFramesReceivedOnIO, this, | 520 base::Bind(&VideoTrackAdapter::CheckFramesReceivedOnIO, this, |
| 494 set_muted_state_callback, frame_counter_), | 521 set_muted_state_callback, frame_counter_, dropped_frames_counter_), |
| 495 base::TimeDelta::FromSecondsD(kNormalFrameTimeoutInFrameIntervals / | 522 base::TimeDelta::FromSecondsD(kNormalFrameTimeoutInFrameIntervals / |
| 496 source_frame_rate_)); | 523 source_frame_rate_)); |
| 497 } | 524 } |
| 498 | 525 |
| 499 } // namespace content | 526 } // namespace content |
| OLD | NEW |