Index: media/renderers/renderer_impl.cc |
diff --git a/media/renderers/renderer_impl.cc b/media/renderers/renderer_impl.cc |
index e81c97aec4996f8904ca330c128dfa984851982e..8088b07c7157d298c34283d4cd1ea3e7611ad645 100644 |
--- a/media/renderers/renderer_impl.cc |
+++ b/media/renderers/renderer_impl.cc |
@@ -7,18 +7,24 @@ |
#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" |
namespace media { |
+// See |video_underflow_threshold_|. |
+static const int kDefaultVideoUnderflowThresholdMs = 3000; |
+ |
RendererImpl::RendererImpl( |
const scoped_refptr<base::SingleThreadTaskRunner>& task_runner, |
scoped_ptr<AudioRenderer> audio_renderer, |
@@ -36,9 +42,22 @@ RendererImpl::RendererImpl( |
cdm_context_(nullptr), |
underflow_disabled_for_testing_(false), |
clockless_video_playback_enabled_for_testing_(false), |
+ video_underflow_threshold_( |
+ base::TimeDelta::FromMilliseconds(kDefaultVideoUnderflowThresholdMs)), |
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) { |
+ video_underflow_threshold_ = |
+ base::TimeDelta::FromMilliseconds(threshold_ms); |
+ } |
} |
RendererImpl::~RendererImpl() { |
@@ -336,7 +355,7 @@ void RendererImpl::OnVideoRendererInitializeDone(PipelineStatus status) { |
if (audio_renderer_) { |
time_source_ = audio_renderer_->GetTimeSource(); |
- } else { |
+ } else if (!time_source_) { |
wall_clock_time_source_.reset(new WallClockTimeSource()); |
time_source_ = wall_clock_time_source_.get(); |
} |
@@ -419,12 +438,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. |