Add the ability to suspend preload=metadata playbacks in some cases.
This adds a base::Feature, kPreloadMetadataSuspend, for suspending
preload=metadata players that are either audio-only or have video
and have a poster image.
Given the uncertainty and issues with canplay, canplaythrough, the
current version of this feature signals HAVE_ENOUGH when after a
suspended startup successfull completes.
This also fixes a minor issue where streams with a positive start
time were not suspending at the right time.
BUG=694855
TEST=enabling feature still passes all bots. More layout tests,
which are disabled by default in this CL since the feature is
disabled by default for now.
Change-Id: Iccd79eddbd7a3b03933b3090eb99ad19c2fed768
Reviewed-on: https://chromium-review.googlesource.com/978867
Reviewed-by: Frank Liberato <[email protected]>
Reviewed-by: Dan Sanders <[email protected]>
Commit-Queue: Dale Curtis <[email protected]>
Cr-Commit-Position: refs/heads/master@{#545817}
diff --git a/media/blink/webmediaplayer_impl.cc b/media/blink/webmediaplayer_impl.cc
index 507ee26..5cabd56 100644
--- a/media/blink/webmediaplayer_impl.cc
+++ b/media/blink/webmediaplayer_impl.cc
@@ -1370,6 +1370,26 @@
// Background video optimizations are delayed when shown/hidden if pipeline
// is seeking.
UpdateBackgroundVideoOptimizationState();
+
+ // If we successfully completed a suspended startup, lie about our buffering
+ // state for the time being. While ultimately we want to avoid lying about the
+ // buffering state, for the initial test of true preload=metadata, signal
+ // BUFFERING_HAVE_ENOUGH so that canplay and canplaythrough fire correctly.
+ //
+ // Later we can experiment with the impact of removing this lie; initial data
+ // suggests high disruption since we've also made preload=metadata the
+ // default. Most sites are not prepared for a lack of canplay; even many of
+ // our own tests don't function correctly. See https://crbug.com/694855.
+ //
+ // Note: This call is dual purpose, it is also responsible for triggering an
+ // UpdatePlayState() call which may need to resume the pipeline once Blink
+ // has been told about the ReadyState change.
+ if (attempting_suspended_start_ &&
+ pipeline_controller_.IsPipelineSuspended()) {
+ OnBufferingStateChangeInternal(BUFFERING_HAVE_ENOUGH, true);
+ }
+
+ attempting_suspended_start_ = false;
}
void WebMediaPlayerImpl::OnPipelineSuspended() {
@@ -1567,6 +1587,10 @@
UpdatePlayState();
}
+void WebMediaPlayerImpl::OnBufferingStateChange(BufferingState state) {
+ OnBufferingStateChangeInternal(state, false);
+}
+
void WebMediaPlayerImpl::CreateVideoDecodeStatsReporter() {
// TODO(chcunningham): destroy reporter if we initially have video but the
// track gets disabled. Currently not possible in default desktop Chrome.
@@ -1641,13 +1665,14 @@
playback_rate_ == 0.0 ? 1.0 : playback_rate_);
}
-void WebMediaPlayerImpl::OnBufferingStateChange(BufferingState state) {
+void WebMediaPlayerImpl::OnBufferingStateChangeInternal(BufferingState state,
+ bool force_update) {
DVLOG(1) << __func__ << "(" << state << ")";
DCHECK(main_task_runner_->BelongsToCurrentThread());
// Ignore buffering state changes until we've completed all outstanding
- // operations.
- if (!pipeline_controller_.IsStable())
+ // operations unless we've been asked to force the update.
+ if (!pipeline_controller_.IsStable() && !force_update)
return;
media_log_->AddEvent(media_log_->CreateBufferingStateChangedEvent(
@@ -2306,11 +2331,21 @@
bool is_streaming = IsStreaming();
UMA_HISTOGRAM_BOOLEAN("Media.IsStreaming", is_streaming);
+ // If possible attempt to avoid decoder spool up until playback starts.
+ Pipeline::StartType start_type = Pipeline::StartType::kNormal;
+ if (base::FeatureList::IsEnabled(kPreloadMetadataSuspend) &&
+ !chunk_demuxer_ && preload_ == MultibufferDataSource::METADATA) {
+ start_type = has_poster_
+ ? Pipeline::StartType::kSuspendAfterMetadata
+ : Pipeline::StartType::kSuspendAfterMetadataForAudioOnly;
+ attempting_suspended_start_ = true;
+ }
+
// ... and we're ready to go!
// TODO(sandersd): On Android, defer Start() if the tab is not visible.
seeking_ = true;
- pipeline_controller_.Start(Pipeline::StartType::kNormal, demuxer_.get(), this,
- is_streaming, is_static);
+ pipeline_controller_.Start(start_type, demuxer_.get(), this, is_streaming,
+ is_static);
}
void WebMediaPlayerImpl::SetNetworkState(WebMediaPlayer::NetworkState state) {