Chromium Code Reviews| Index: media/renderers/renderer_impl.cc |
| diff --git a/media/renderers/renderer_impl.cc b/media/renderers/renderer_impl.cc |
| index e81c97aec4996f8904ca330c128dfa984851982e..c9a851a76a1e658eb480345739be748d2bacb6c4 100644 |
| --- a/media/renderers/renderer_impl.cc |
| +++ b/media/renderers/renderer_impl.cc |
| @@ -7,12 +7,15 @@ |
| #include "base/bind.h" |
| #include "base/callback.h" |
| #include "base/callback_helpers.h" |
| +#include "base/command_line.h" |
| #include "base/compiler_specific.h" |
| #include "base/location.h" |
| #include "base/single_thread_task_runner.h" |
| +#include "base/strings/string_number_conversions.h" |
| #include "media/base/audio_renderer.h" |
| #include "media/base/bind_to_current_loop.h" |
| #include "media/base/demuxer_stream_provider.h" |
| +#include "media/base/media_switches.h" |
| #include "media/base/time_source.h" |
| #include "media/base/video_renderer.h" |
| #include "media/base/wall_clock_time_source.h" |
| @@ -36,9 +39,21 @@ RendererImpl::RendererImpl( |
| cdm_context_(nullptr), |
| underflow_disabled_for_testing_(false), |
| clockless_video_playback_enabled_for_testing_(false), |
| + video_underflow_threshold_(base::TimeDelta::FromSeconds(3)), |
|
xhwang
2015/03/26 21:24:43
You can still use a file scope const instead of a
DaleCurtis
2015/03/26 21:36:08
This allows overriding for testing much more easil
xhwang
2015/03/28 00:32:40
You can declare this in the header file so it's av
|
| weak_factory_(this) { |
| weak_this_ = weak_factory_.GetWeakPtr(); |
| DVLOG(1) << __FUNCTION__; |
| + |
| + // TODO(dalecurtis): Remove once experiments for http://crbug.com/470940 are |
| + // complete. |
| + int threshold_ms = 0; |
| + std::string threshold_ms_str( |
| + base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII( |
| + switches::kVideoUnderflowThresholdMs)); |
| + if (base::StringToInt(threshold_ms_str, &threshold_ms) && threshold_ms > 0) { |
|
xhwang
2015/03/26 21:24:43
s/>/>=?
We should be able to set the threshold to
|
| + video_underflow_threshold_ = |
| + base::TimeDelta::FromMilliseconds(threshold_ms); |
| + } |
| } |
| RendererImpl::~RendererImpl() { |
| @@ -336,7 +351,7 @@ void RendererImpl::OnVideoRendererInitializeDone(PipelineStatus status) { |
| if (audio_renderer_) { |
| time_source_ = audio_renderer_->GetTimeSource(); |
| - } else { |
| + } else if (!time_source_) { |
|
xhwang
2015/03/26 21:24:43
hmm, why we need this?
DaleCurtis
2015/03/26 21:36:08
Because I'm overriding the TimeSource for testing,
xhwang
2015/03/28 00:32:40
Thanks for the explanation. Maybe worth a comment.
|
| wall_clock_time_source_.reset(new WallClockTimeSource()); |
| time_source_ = wall_clock_time_source_.get(); |
| } |
| @@ -419,12 +434,37 @@ void RendererImpl::OnUpdateStatistics(const PipelineStatistics& stats) { |
| void RendererImpl::OnBufferingStateChanged(BufferingState* buffering_state, |
| BufferingState new_buffering_state) { |
| + const bool is_audio = buffering_state == &audio_buffering_state_; |
| DVLOG(1) << __FUNCTION__ << "(" << *buffering_state << ", " |
| - << new_buffering_state << ") " |
| - << (buffering_state == &audio_buffering_state_ ? "audio" : "video"); |
| + << new_buffering_state << ") " << (is_audio ? "audio" : "video"); |
| DCHECK(task_runner_->BelongsToCurrentThread()); |
| + |
| bool was_waiting_for_enough_data = WaitingForEnoughData(); |
| + // When audio is present, defer underflow callbacks for some time to avoid |
| + // unnecessary glitches in audio; see http://crbug.com/144683#c53. |
| + if (audio_renderer_ && !is_audio && state_ == STATE_PLAYING) { |
| + if (video_buffering_state_ == BUFFERING_HAVE_ENOUGH && |
| + new_buffering_state == BUFFERING_HAVE_NOTHING && |
| + deferred_underflow_cb_.IsCancelled()) { |
| + deferred_underflow_cb_.Reset(base::Bind( |
| + &RendererImpl::OnBufferingStateChanged, weak_factory_.GetWeakPtr(), |
| + buffering_state, new_buffering_state)); |
| + task_runner_->PostDelayedTask(FROM_HERE, |
| + deferred_underflow_cb_.callback(), |
| + video_underflow_threshold_); |
| + return; |
| + } |
| + |
| + deferred_underflow_cb_.Cancel(); |
| + } else if (!deferred_underflow_cb_.IsCancelled() && is_audio && |
| + new_buffering_state == BUFFERING_HAVE_NOTHING) { |
| + // If audio underflows while we have a deferred video underflow in progress |
| + // we want to mark video as underflowed immediately and cancel the deferral. |
| + deferred_underflow_cb_.Cancel(); |
| + video_buffering_state_ = BUFFERING_HAVE_NOTHING; |
| + } |
| + |
| *buffering_state = new_buffering_state; |
| // Disable underflow by ignoring updates that renderers have ran out of data. |