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 |
11 #include "base/bind.h" | 11 #include "base/bind.h" |
12 #include "base/debug/trace_event.h" | 12 #include "base/debug/trace_event.h" |
13 #include "base/location.h" | 13 #include "base/location.h" |
14 #include "media/base/video_util.h" | 14 #include "media/base/video_util.h" |
15 | 15 |
16 namespace content { | 16 namespace content { |
17 | 17 |
18 namespace { | 18 namespace { |
19 | 19 |
| 20 // Amount of frame intervals to wait before considering the source as muted, for |
| 21 // the first frame and under normal conditions, respectively. First frame might |
| 22 // take longer to arrive due to source startup. |
| 23 const float kFirstFrameTimeoutInFrameIntervals = 100.0f; |
| 24 const float kNormalFrameTimeoutInFrameIntervals = 25.0f; |
| 25 |
20 // Empty method used for keeping a reference to the original media::VideoFrame | 26 // Empty method used for keeping a reference to the original media::VideoFrame |
21 // in VideoFrameResolutionAdapter::DeliverFrame if cropping is needed. | 27 // in VideoFrameResolutionAdapter::DeliverFrame if cropping is needed. |
22 // The reference to |frame| is kept in the closure that calls this method. | 28 // The reference to |frame| is kept in the closure that calls this method. |
23 void ReleaseOriginalFrame( | 29 void ReleaseOriginalFrame( |
24 const scoped_refptr<media::VideoFrame>& frame) { | 30 const scoped_refptr<media::VideoFrame>& frame) { |
25 } | 31 } |
26 | 32 |
27 void ResetCallbackOnMainRenderThread( | 33 void ResetCallbackOnMainRenderThread( |
28 scoped_ptr<VideoCaptureDeliverFrameCB> callback) { | 34 scoped_ptr<VideoCaptureDeliverFrameCB> callback) { |
29 // |callback| will be deleted when this exits. | 35 // |callback| will be deleted when this exits. |
(...skipping 264 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
294 } | 300 } |
295 | 301 |
296 bool VideoTrackAdapter::VideoFrameResolutionAdapter::IsEmpty() const { | 302 bool VideoTrackAdapter::VideoFrameResolutionAdapter::IsEmpty() const { |
297 DCHECK(io_thread_checker_.CalledOnValidThread()); | 303 DCHECK(io_thread_checker_.CalledOnValidThread()); |
298 return callbacks_.empty(); | 304 return callbacks_.empty(); |
299 } | 305 } |
300 | 306 |
301 VideoTrackAdapter::VideoTrackAdapter( | 307 VideoTrackAdapter::VideoTrackAdapter( |
302 const scoped_refptr<base::MessageLoopProxy>& io_message_loop) | 308 const scoped_refptr<base::MessageLoopProxy>& io_message_loop) |
303 : io_message_loop_(io_message_loop), | 309 : io_message_loop_(io_message_loop), |
304 renderer_task_runner_(base::MessageLoopProxy::current()) { | 310 renderer_task_runner_(base::MessageLoopProxy::current()), |
| 311 frame_counter_(0), |
| 312 source_frame_rate_(0.0f) { |
305 DCHECK(io_message_loop_); | 313 DCHECK(io_message_loop_); |
306 } | 314 } |
307 | 315 |
308 VideoTrackAdapter::~VideoTrackAdapter() { | 316 VideoTrackAdapter::~VideoTrackAdapter() { |
309 DCHECK(adapters_.empty()); | 317 DCHECK(adapters_.empty()); |
310 } | 318 } |
311 | 319 |
312 void VideoTrackAdapter::AddTrack(const MediaStreamVideoTrack* track, | 320 void VideoTrackAdapter::AddTrack( |
313 VideoCaptureDeliverFrameCB frame_callback, | 321 const MediaStreamVideoTrack* track, |
314 int max_width, | 322 VideoCaptureDeliverFrameCB frame_callback, |
315 int max_height, | 323 int max_width, |
316 double min_aspect_ratio, | 324 int max_height, |
317 double max_aspect_ratio, | 325 double min_aspect_ratio, |
318 double max_frame_rate) { | 326 double max_aspect_ratio, |
| 327 double max_frame_rate, |
| 328 double source_frame_rate, |
| 329 const OnMutedCallback& on_muted_state_callback) { |
319 DCHECK(thread_checker_.CalledOnValidThread()); | 330 DCHECK(thread_checker_.CalledOnValidThread()); |
| 331 // Track monitoring should be scheduled before AddTrackOnIO() so it can find |
| 332 // |adapters_| empty. |
| 333 io_message_loop_->PostTask( |
| 334 FROM_HERE, |
| 335 base::Bind(&VideoTrackAdapter::StartTrackMonitoringOnIO, |
| 336 this, on_muted_state_callback, source_frame_rate)); |
320 io_message_loop_->PostTask( | 337 io_message_loop_->PostTask( |
321 FROM_HERE, | 338 FROM_HERE, |
322 base::Bind(&VideoTrackAdapter::AddTrackOnIO, | 339 base::Bind(&VideoTrackAdapter::AddTrackOnIO, |
323 this, track, frame_callback, gfx::Size(max_width, max_height), | 340 this, track, frame_callback, gfx::Size(max_width, max_height), |
324 min_aspect_ratio, max_aspect_ratio, max_frame_rate)); | 341 min_aspect_ratio, max_aspect_ratio, max_frame_rate)); |
325 } | 342 } |
326 | 343 |
327 void VideoTrackAdapter::AddTrackOnIO( | 344 void VideoTrackAdapter::AddTrackOnIO( |
328 const MediaStreamVideoTrack* track, | 345 const MediaStreamVideoTrack* track, |
329 VideoCaptureDeliverFrameCB frame_callback, | 346 VideoCaptureDeliverFrameCB frame_callback, |
(...skipping 23 matching lines...) Expand all Loading... |
353 adapter->AddCallback(track, frame_callback); | 370 adapter->AddCallback(track, frame_callback); |
354 } | 371 } |
355 | 372 |
356 void VideoTrackAdapter::RemoveTrack(const MediaStreamVideoTrack* track) { | 373 void VideoTrackAdapter::RemoveTrack(const MediaStreamVideoTrack* track) { |
357 DCHECK(thread_checker_.CalledOnValidThread()); | 374 DCHECK(thread_checker_.CalledOnValidThread()); |
358 io_message_loop_->PostTask( | 375 io_message_loop_->PostTask( |
359 FROM_HERE, | 376 FROM_HERE, |
360 base::Bind(&VideoTrackAdapter::RemoveTrackOnIO, this, track)); | 377 base::Bind(&VideoTrackAdapter::RemoveTrackOnIO, this, track)); |
361 } | 378 } |
362 | 379 |
| 380 void VideoTrackAdapter::StartTrackMonitoringOnIO( |
| 381 const OnMutedCallback& on_muted_state_callback, |
| 382 double source_frame_rate) { |
| 383 DCHECK(io_message_loop_->BelongsToCurrentThread()); |
| 384 // Only trigger monitoring for the first Track. |
| 385 if (!adapters_.empty()) |
| 386 return; |
| 387 // If the source does not know the frame rate, set one by default. |
| 388 if (source_frame_rate == 0.0f) |
| 389 source_frame_rate = MediaStreamVideoSource::kDefaultFrameRate; |
| 390 source_frame_rate_ = source_frame_rate; |
| 391 DVLOG(1) << "Monitoring frame creation, first (large) delay: " |
| 392 << (kFirstFrameTimeoutInFrameIntervals / source_frame_rate_) << "s"; |
| 393 io_message_loop_->PostDelayedTask(FROM_HERE, |
| 394 base::Bind(&VideoTrackAdapter::CheckFramesReceivedOnIO, this, |
| 395 on_muted_state_callback, frame_counter_), |
| 396 base::TimeDelta::FromSecondsD(kFirstFrameTimeoutInFrameIntervals / |
| 397 source_frame_rate_)); |
| 398 } |
| 399 |
363 void VideoTrackAdapter::RemoveTrackOnIO(const MediaStreamVideoTrack* track) { | 400 void VideoTrackAdapter::RemoveTrackOnIO(const MediaStreamVideoTrack* track) { |
364 DCHECK(io_message_loop_->BelongsToCurrentThread()); | 401 DCHECK(io_message_loop_->BelongsToCurrentThread()); |
365 for (FrameAdapters::iterator it = adapters_.begin(); | 402 for (FrameAdapters::iterator it = adapters_.begin(); |
366 it != adapters_.end(); ++it) { | 403 it != adapters_.end(); ++it) { |
367 (*it)->RemoveCallback(track); | 404 (*it)->RemoveCallback(track); |
368 if ((*it)->IsEmpty()) { | 405 if ((*it)->IsEmpty()) { |
369 adapters_.erase(it); | 406 adapters_.erase(it); |
370 break; | 407 break; |
371 } | 408 } |
372 } | 409 } |
373 } | 410 } |
374 | 411 |
375 void VideoTrackAdapter::DeliverFrameOnIO( | 412 void VideoTrackAdapter::DeliverFrameOnIO( |
376 const scoped_refptr<media::VideoFrame>& frame, | 413 const scoped_refptr<media::VideoFrame>& frame, |
377 const media::VideoCaptureFormat& format, | 414 const media::VideoCaptureFormat& format, |
378 const base::TimeTicks& estimated_capture_time) { | 415 const base::TimeTicks& estimated_capture_time) { |
379 DCHECK(io_message_loop_->BelongsToCurrentThread()); | 416 DCHECK(io_message_loop_->BelongsToCurrentThread()); |
380 TRACE_EVENT0("video", "VideoTrackAdapter::DeliverFrameOnIO"); | 417 TRACE_EVENT0("video", "VideoTrackAdapter::DeliverFrameOnIO"); |
| 418 ++frame_counter_; |
381 for (FrameAdapters::iterator it = adapters_.begin(); | 419 for (FrameAdapters::iterator it = adapters_.begin(); |
382 it != adapters_.end(); ++it) { | 420 it != adapters_.end(); ++it) { |
383 (*it)->DeliverFrame(frame, format, estimated_capture_time); | 421 (*it)->DeliverFrame(frame, format, estimated_capture_time); |
384 } | 422 } |
385 } | 423 } |
386 | 424 |
| 425 void VideoTrackAdapter::CheckFramesReceivedOnIO( |
| 426 const OnMutedCallback& set_muted_state_callback, |
| 427 uint64 old_frame_counter_snapshot) { |
| 428 DCHECK(io_message_loop_->BelongsToCurrentThread()); |
| 429 DVLOG_IF(1, old_frame_counter_snapshot == frame_counter_) |
| 430 << "No frames have passed, setting source as Muted."; |
| 431 set_muted_state_callback.Run(old_frame_counter_snapshot == frame_counter_); |
| 432 |
| 433 // Rearm the monitoring while there are active Tracks, i.e. as long as the |
| 434 // owner MediaStreamSource is active. |
| 435 io_message_loop_->PostDelayedTask(FROM_HERE, |
| 436 base::Bind(&VideoTrackAdapter::CheckFramesReceivedOnIO, this, |
| 437 set_muted_state_callback, frame_counter_), |
| 438 base::TimeDelta::FromSecondsD(kNormalFrameTimeoutInFrameIntervals / |
| 439 source_frame_rate_)); |
| 440 } |
| 441 |
387 } // namespace content | 442 } // namespace content |
OLD | NEW |