blob: ad18408fa366b1718d04d48e4b490cc7e68dfd6b [file] [log] [blame]
[email protected]85a37afd2013-05-30 22:51:151// Copyright 2013 The Chromium Authors. All rights reserved.
[email protected]891acc92009-04-27 19:56:412// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
[email protected]ec9212f2008-12-18 21:40:364
acolwell9e0840d2014-09-06 19:01:325#include "media/blink/webmediaplayer_impl.h"
[email protected]8931c41a2009-07-07 17:31:496
[email protected]c2a45e242013-02-15 20:24:587#include <algorithm>
mateuszs3371ab02015-04-24 13:20:238#include <cmath>
[email protected]47b06ceb2010-08-04 22:41:119#include <limits>
guidouc7babef2015-10-22 00:42:3510#include <string>
dcheng652f5ff2015-12-27 08:54:0011#include <utility>
[email protected]47b06ceb2010-08-04 22:41:1112
[email protected]08273c7b2011-09-17 00:33:5113#include "base/bind.h"
sandersd1c0bba02016-03-04 23:14:0814#include "base/bind_helpers.h"
[email protected]2041cf342010-02-19 03:15:5915#include "base/callback.h"
[email protected]7502ef12014-01-25 01:19:2716#include "base/callback_helpers.h"
sandersd1e49fb62015-12-12 01:18:0617#include "base/command_line.h"
[email protected]ca04095f2014-02-07 10:23:5618#include "base/debug/alias.h"
[email protected]926f8fd2013-04-12 20:27:5319#include "base/debug/crash_logging.h"
fdoraydb3ef7d2016-06-09 15:42:3820#include "base/location.h"
servolkf94b4602017-01-31 16:44:2721#include "base/memory/ptr_util.h"
asvitkine30330812016-08-30 04:01:0822#include "base/metrics/histogram_macros.h"
acolwellb4034942014-08-28 15:42:4323#include "base/single_thread_task_runner.h"
servolka233f832016-06-10 20:39:0424#include "base/strings/string_number_conversions.h"
wdzierzanowskifd4cd91c52015-12-02 23:50:2025#include "base/task_runner_util.h"
Matt Wolenetz95af6362018-01-04 20:23:4226#include "base/task_scheduler/post_task.h"
gabba14a442016-05-11 20:10:2027#include "base/threading/thread_task_runner_handle.h"
ssid9525f4672015-01-28 12:13:1528#include "base/trace_event/trace_event.h"
sandersd1e49fb62015-12-12 01:18:0629#include "build/build_config.h"
[email protected]38564622014-08-19 02:47:1830#include "cc/blink/web_layer_impl.h"
[email protected]21c3f7502013-03-23 03:29:5131#include "cc/layers/video_layer.h"
CJ DiMeglioc60a5cf2017-09-27 20:08:4132#include "components/viz/common/gpu/context_provider.h"
[email protected]e4fc09e2012-04-06 03:17:4433#include "media/audio/null_audio_sink.h"
[email protected]2eccbed2014-01-10 05:15:5334#include "media/base/bind_to_current_loop.h"
xhwang0ad11e512014-11-25 23:43:0935#include "media/base/cdm_context.h"
xhwang79b193042016-12-13 18:52:4336#include "media/base/content_decryption_module.h"
[email protected]32da1002010-03-03 21:57:3537#include "media/base/limits.h"
zqzhang5d8eab72016-08-26 20:34:3038#include "media/base/media_content_type.h"
[email protected]090f7312011-08-05 23:26:4039#include "media/base/media_log.h"
sandersd1e49fb62015-12-12 01:18:0640#include "media/base/media_switches.h"
tguilbert25a4d112016-10-13 21:56:5141#include "media/base/media_url_demuxer.h"
[email protected]8a561062013-11-22 01:19:3142#include "media/base/text_renderer.h"
watk9f9dfdc92015-09-04 21:33:2943#include "media/base/timestamp_constants.h"
[email protected]e81283bb2010-08-31 18:01:2144#include "media/base/video_frame.h"
acolwell9e0840d2014-09-06 19:01:3245#include "media/blink/texttrack_impl.h"
Chris Cunninghamd9df58e2017-08-29 00:04:2346#include "media/blink/video_decode_stats_reporter.h"
dalecurtis04bdb582016-08-17 22:15:2347#include "media/blink/watch_time_reporter.h"
acolwell9e0840d2014-09-06 19:01:3248#include "media/blink/webaudiosourceprovider_impl.h"
xhwang97de4202014-11-25 08:44:0149#include "media/blink/webcontentdecryptionmodule_impl.h"
acolwell9e0840d2014-09-06 19:01:3250#include "media/blink/webinbandtexttrack_impl.h"
51#include "media/blink/webmediaplayer_delegate.h"
acolwell9e0840d2014-09-06 19:01:3252#include "media/blink/webmediaplayer_util.h"
53#include "media/blink/webmediasource_impl.h"
[email protected]efe7cd22012-09-12 23:55:0154#include "media/filters/chunk_demuxer.h"
[email protected]ddbc6ff2013-04-19 15:28:3355#include "media/filters/ffmpeg_demuxer.h"
jrummellc9d8e532015-02-26 18:38:1956#include "third_party/WebKit/public/platform/WebEncryptedMediaTypes.h"
srirama.m26f864d02015-07-14 05:21:4657#include "third_party/WebKit/public/platform/WebMediaPlayerClient.h"
58#include "third_party/WebKit/public/platform/WebMediaPlayerEncryptedMediaClient.h"
guidou9bfe4e2f2016-04-09 08:31:1959#include "third_party/WebKit/public/platform/WebMediaPlayerSource.h"
[email protected]745746d2013-08-23 02:09:1660#include "third_party/WebKit/public/platform/WebMediaSource.h"
[email protected]c10884462013-05-30 00:22:0961#include "third_party/WebKit/public/platform/WebRect.h"
nverne61d2da872017-05-24 10:15:3062#include "third_party/WebKit/public/platform/WebRuntimeFeatures.h"
mek966863c2016-02-04 23:39:0563#include "third_party/WebKit/public/platform/WebSecurityOrigin.h"
[email protected]c10884462013-05-30 00:22:0964#include "third_party/WebKit/public/platform/WebSize.h"
65#include "third_party/WebKit/public/platform/WebString.h"
lethalantidote7f6009d2017-07-07 21:47:3966#include "third_party/WebKit/public/platform/WebSurfaceLayerBridge.h"
[email protected]c10884462013-05-30 00:22:0967#include "third_party/WebKit/public/platform/WebURL.h"
tguilbert9881bc22016-10-27 03:13:4168#include "third_party/WebKit/public/web/WebDocument.h"
xhwang0acca44b2015-06-18 00:43:3169#include "third_party/WebKit/public/web/WebFrame.h"
[email protected]80504652014-04-18 04:41:5070#include "third_party/WebKit/public/web/WebLocalFrame.h"
avayvod65fad272017-02-24 01:00:4871#include "third_party/WebKit/public/web/WebUserGestureIndicator.h"
[email protected]2255a9332013-06-17 05:12:3172#include "third_party/WebKit/public/web/WebView.h"
[email protected]b3f2b912009-04-09 16:18:5273
dalecurtisea27a3ed2016-06-24 01:41:3074#if defined(OS_ANDROID)
75#include "media/base/android/media_codec_util.h"
76#endif
77
[email protected]180ef242013-11-07 06:50:4678using blink::WebCanvas;
79using blink::WebMediaPlayer;
80using blink::WebRect;
81using blink::WebSize;
82using blink::WebString;
hubbed5f36882016-01-15 22:40:3783using gpu::gles2::GLES2Interface;
84
danakj365175c2016-02-06 00:37:3785#define STATIC_ASSERT_ENUM(a, b) \
86 static_assert(static_cast<int>(a) == static_cast<int>(b), \
87 "mismatching enums: " #a)
88
hubbed5f36882016-01-15 22:40:3789namespace media {
[email protected]ec9212f2008-12-18 21:40:3690
[email protected]8931c41a2009-07-07 17:31:4991namespace {
92
hubbed5f36882016-01-15 22:40:3793void SetSinkIdOnMediaThread(scoped_refptr<WebAudioSourceProviderImpl> sink,
94 const std::string& device_id,
95 const url::Origin& security_origin,
olka68b69392016-04-01 11:42:1296 const OutputDeviceStatusCB& callback) {
97 sink->SwitchOutputDevice(device_id, security_origin, callback);
guidouc7babef2015-10-22 00:42:3598}
99
sandersd50a635e2016-04-04 22:50:09100bool IsBackgroundedSuspendEnabled() {
dalecurtis0431cbf2016-03-12 01:19:43101#if !defined(OS_ANDROID)
102 // Suspend/Resume is only enabled by default on Android.
103 return base::CommandLine::ForCurrentProcess()->HasSwitch(
104 switches::kEnableMediaSuspend);
105#else
106 return !base::CommandLine::ForCurrentProcess()->HasSwitch(
107 switches::kDisableMediaSuspend);
108#endif
109}
110
avayvod48a8be52016-08-04 19:52:50111bool IsResumeBackgroundVideosEnabled() {
112 return base::FeatureList::IsEnabled(kResumeBackgroundVideo);
113}
114
avayvod39c102402016-11-23 21:43:13115bool IsBackgroundVideoTrackOptimizationEnabled() {
116 return base::FeatureList::IsEnabled(kBackgroundVideoTrackOptimization);
117}
118
avayvod01201332017-04-14 00:27:15119bool IsBackgroundVideoPauseOptimizationEnabled() {
120 return base::FeatureList::IsEnabled(kBackgroundVideoPauseOptimization);
121}
122
avayvod82729272017-05-29 21:58:39123bool IsNewRemotePlaybackPipelineEnabled() {
124 return base::FeatureList::IsEnabled(kNewRemotePlaybackPipeline);
125}
126
sandersd50a635e2016-04-04 22:50:09127bool IsNetworkStateError(blink::WebMediaPlayer::NetworkState state) {
Blink Reformat1c4d759e2017-04-09 16:34:54128 bool result = state == blink::WebMediaPlayer::kNetworkStateFormatError ||
129 state == blink::WebMediaPlayer::kNetworkStateNetworkError ||
130 state == blink::WebMediaPlayer::kNetworkStateDecodeError;
131 DCHECK_EQ(state > blink::WebMediaPlayer::kNetworkStateLoaded, result);
sandersd50a635e2016-04-04 22:50:09132 return result;
133}
134
sandersd2c478422016-08-02 01:19:25135gfx::Size GetRotatedVideoSize(VideoRotation rotation, gfx::Size natural_size) {
136 if (rotation == VIDEO_ROTATION_90 || rotation == VIDEO_ROTATION_270)
137 return gfx::Size(natural_size.height(), natural_size.width());
138 return natural_size;
139}
140
Xiaohan Wangf63505d2017-10-21 08:00:53141void RecordEncryptedEvent(bool encrypted_event_fired) {
142 UMA_HISTOGRAM_BOOLEAN("Media.EME.EncryptedEvent", encrypted_event_fired);
143}
144
sandersd35d2c3f2017-01-14 02:04:42145// How much time must have elapsed since loading last progressed before we
146// assume that the decoder will have had time to complete preroll.
147constexpr base::TimeDelta kPrerollAttemptTimeout =
watkd026f792016-11-05 00:28:51148 base::TimeDelta::FromSeconds(3);
149
Matt Wolenetz6010f6c2017-10-18 00:44:36150// Maximum number, per-WMPI, of media logs of playback rate changes.
151constexpr int kMaxNumPlaybackRateLogs = 10;
152
[email protected]8931c41a2009-07-07 17:31:49153} // namespace
154
[email protected]6683e1b2014-04-10 01:45:38155class BufferedDataSourceHostImpl;
156
Blink Reformat1c4d759e2017-04-09 16:34:54157STATIC_ASSERT_ENUM(WebMediaPlayer::kCORSModeUnspecified,
danakj365175c2016-02-06 00:37:37158 UrlData::CORS_UNSPECIFIED);
Blink Reformat1c4d759e2017-04-09 16:34:54159STATIC_ASSERT_ENUM(WebMediaPlayer::kCORSModeAnonymous, UrlData::CORS_ANONYMOUS);
160STATIC_ASSERT_ENUM(WebMediaPlayer::kCORSModeUseCredentials,
danakj365175c2016-02-06 00:37:37161 UrlData::CORS_USE_CREDENTIALS);
[email protected]a5a01102012-06-06 17:01:24162
[email protected]5b5bb9d2010-10-22 19:57:36163WebMediaPlayerImpl::WebMediaPlayerImpl(
[email protected]35b2a972014-04-04 15:50:22164 blink::WebLocalFrame* frame,
[email protected]180ef242013-11-07 06:50:46165 blink::WebMediaPlayerClient* client,
srirama.m26f864d02015-07-14 05:21:46166 blink::WebMediaPlayerEncryptedMediaClient* encrypted_client,
tguilbert1bb1c782017-01-23 21:15:11167 WebMediaPlayerDelegate* delegate,
tguilbert70d2a00a2017-04-25 00:30:44168 std::unique_ptr<RendererFactorySelector> renderer_factory_selector,
Alok Priyadarshi7166d4d2017-07-29 04:04:25169 UrlIndex* url_index,
CJ DiMegliod7ac6772017-11-10 00:19:06170 std::unique_ptr<VideoFrameCompositor> compositor,
dalecurtis9cddc0b2017-04-19 21:23:38171 std::unique_ptr<WebMediaPlayerParams> params)
[email protected]f6af7592014-02-28 10:09:11172 : frame_(frame),
sandersd50a635e2016-04-04 22:50:09173 delegate_state_(DelegateState::GONE),
sandersd35d2c3f2017-01-14 02:04:42174 delegate_has_audio_(false),
Blink Reformat1c4d759e2017-04-09 16:34:54175 network_state_(WebMediaPlayer::kNetworkStateEmpty),
176 ready_state_(WebMediaPlayer::kReadyStateHaveNothing),
177 highest_ready_state_(WebMediaPlayer::kReadyStateHaveNothing),
Jennifer Apacible69e12d52017-10-26 02:03:54178 preload_(MultibufferDataSource::METADATA),
Dan Sanderscd8981c2017-08-31 22:37:02179 has_poster_(false),
Alexander Timin310368112017-09-13 10:01:44180 main_task_runner_(
181 frame->GetTaskRunner(blink::TaskType::kMediaElementEvent)),
dalecurtis9cddc0b2017-04-19 21:23:38182 media_task_runner_(params->media_task_runner()),
183 worker_task_runner_(params->worker_task_runner()),
184 media_log_(params->take_media_log()),
sandersd1c0bba02016-03-04 23:14:08185 pipeline_controller_(
tguilbert350936ff2017-02-24 05:39:27186 base::MakeUnique<PipelineImpl>(media_task_runner_, media_log_.get()),
sandersd1c0bba02016-03-04 23:14:08187 base::Bind(&WebMediaPlayerImpl::CreateRenderer,
188 base::Unretained(this)),
189 base::Bind(&WebMediaPlayerImpl::OnPipelineSeeked, AsWeakPtr()),
190 base::Bind(&WebMediaPlayerImpl::OnPipelineSuspended, AsWeakPtr()),
avayvod2135a642017-01-13 00:17:14191 base::Bind(&WebMediaPlayerImpl::OnBeforePipelineResume, AsWeakPtr()),
192 base::Bind(&WebMediaPlayerImpl::OnPipelineResumed, AsWeakPtr()),
alokp967c902452016-05-06 05:21:37193 base::Bind(&WebMediaPlayerImpl::OnError, AsWeakPtr())),
Blink Reformat1c4d759e2017-04-09 16:34:54194 load_type_(kLoadTypeURL),
[email protected]75e145a2014-04-15 17:44:32195 opaque_(false),
wolenetz1b2ae7d2015-06-10 00:44:21196 playback_rate_(0.0),
Matt Wolenetz6010f6c2017-10-18 00:44:36197 num_playback_rate_logs_(0),
[email protected]49480902009-07-14 20:23:43198 paused_(true),
avayvodeb9098d2017-01-07 00:33:03199 paused_when_hidden_(false),
[email protected]b3766a22010-12-22 17:34:13200 seeking_(false),
watkdee516f2016-02-18 02:22:19201 pending_suspend_resume_cycle_(false),
scherkusd2c745b2014-09-04 05:03:40202 ended_(false),
yoichio863bebf2016-03-04 07:56:58203 should_notify_time_changed_(false),
tsunghungee562e92016-07-20 18:03:31204 overlay_enabled_(false),
205 decoder_requires_restart_for_overlay_(false),
[email protected]5badb082010-06-11 17:40:15206 client_(client),
srirama.m26f864d02015-07-14 05:21:46207 encrypted_client_(encrypted_client),
[email protected]baff4512011-10-19 18:21:07208 delegate_(delegate),
dalecurtisbb3eaac2016-01-27 21:10:25209 delegate_id_(0),
dalecurtis9cddc0b2017-04-19 21:23:38210 defer_load_cb_(params->defer_load_cb()),
dalecurtis9cddc0b2017-04-19 21:23:38211 adjust_allocated_memory_cb_(params->adjust_allocated_memory_cb()),
dalecurtis83266c72015-10-29 18:43:20212 last_reported_memory_usage_(0),
[email protected]f5443ef72013-04-22 04:03:38213 chunk_demuxer_(NULL),
tzik2c963b872017-12-07 06:57:24214 tick_clock_(base::DefaultTickClock::GetInstance()),
hubbeb2d3efd2017-05-05 23:26:38215 buffered_data_source_host_(
216 base::Bind(&WebMediaPlayerImpl::OnProgress, AsWeakPtr()),
tzik2c963b872017-12-07 06:57:24217 tick_clock_),
hubbe5f0ad43b2015-12-14 20:57:26218 url_index_(url_index),
CJ DiMeglioc60a5cf2017-09-27 20:08:41219 context_provider_(params->context_provider()),
CJ DiMegliod7ac6772017-11-10 00:19:06220 vfc_task_runner_(params->video_frame_compositor_task_runner()),
221 compositor_(std::move(compositor)),
hubbed5f36882016-01-15 22:40:37222#if defined(OS_ANDROID) // WMPI_CAST
CJ DiMeglioc60a5cf2017-09-27 20:08:41223 cast_impl_(this, client_, params->context_provider()),
hubbed5f36882016-01-15 22:40:37224#endif
dalecurtisbb3eaac2016-01-27 21:10:25225 volume_(1.0),
226 volume_multiplier_(1.0),
tguilbert70d2a00a2017-04-25 00:30:44227 renderer_factory_selector_(std::move(renderer_factory_selector)),
dalecurtis9cddc0b2017-04-19 21:23:38228 surface_manager_(params->surface_manager()),
tsunghungee562e92016-07-20 18:03:31229 overlay_surface_id_(SurfaceManager::kNoSurfaceID),
dalecurtis7f366b2242016-04-13 01:16:17230 suppress_destruction_errors_(false),
dalecurtis9d638a12016-08-30 06:20:55231 is_encrypted_(false),
sandersd35d2c3f2017-01-14 02:04:42232 preroll_attempt_pending_(false),
dalecurtis9cddc0b2017-04-19 21:23:38233 observer_(params->media_observer()),
avayvod590011e32017-01-20 02:01:00234 max_keyframe_distance_to_disable_background_video_(
dalecurtis9cddc0b2017-04-19 21:23:38235 params->max_keyframe_distance_to_disable_background_video()),
avayvode85ec422017-04-14 00:11:33236 max_keyframe_distance_to_disable_background_video_mse_(
dalecurtis9cddc0b2017-04-19 21:23:38237 params->max_keyframe_distance_to_disable_background_video_mse()),
servolkf94b4602017-01-31 16:44:27238 enable_instant_source_buffer_gc_(
dalecurtis9cddc0b2017-04-19 21:23:38239 params->enable_instant_source_buffer_gc()),
shaktisahu24189c12017-03-11 17:42:55240 embedded_media_experience_enabled_(
liberato2ff93ad2017-05-17 07:28:24241 params->embedded_media_experience_enabled()),
lethalantidote7f6009d2017-07-07 21:47:39242 surface_layer_for_video_enabled_(
243 base::FeatureList::IsEnabled(media::kUseSurfaceLayerForVideo)),
liberato2ff93ad2017-05-17 07:28:24244 request_routing_token_cb_(params->request_routing_token_cb()),
Dale Curtis1adbe6a2017-08-02 02:09:13245 overlay_routing_token_(OverlayInfo::RoutingToken()),
Dale Curtis7e8a510d2017-12-14 19:19:48246 media_metrics_provider_(params->take_metrics_provider()) {
xhwang51139732017-02-24 19:36:08247 DVLOG(1) << __func__;
dalecurtis83266c72015-10-29 18:43:20248 DCHECK(!adjust_allocated_memory_cb_.is_null());
tguilbert70d2a00a2017-04-25 00:30:44249 DCHECK(renderer_factory_selector_);
servolkef1e5ef2016-03-25 04:55:26250 DCHECK(client_);
tguilbert1bb1c782017-01-23 21:15:11251 DCHECK(delegate_);
dalecurtis83266c72015-10-29 18:43:20252
CJ DiMegliod7ac6772017-11-10 00:19:06253 if (surface_layer_for_video_enabled_)
CJ DiMeglio2302d202017-08-31 08:38:04254 bridge_ = params->create_bridge_callback().Run(this);
CJ DiMeglio2302d202017-08-31 08:38:04255
256 if (surface_layer_for_video_enabled_) {
257 vfc_task_runner_->PostTask(
258 FROM_HERE, base::Bind(&VideoFrameCompositor::EnableSubmission,
259 base::Unretained(compositor_.get()),
260 bridge_->GetFrameSinkId()));
261 }
lethalantidote7f6009d2017-07-07 21:47:39262
[email protected]c8d574722017-08-30 20:53:43263 // If we're supposed to force video overlays, then make sure that they're
264 // enabled all the time.
265 always_enable_overlays_ = base::CommandLine::ForCurrentProcess()->HasSwitch(
tsunghungee562e92016-07-20 18:03:31266 switches::kForceVideoOverlays);
267
liberato2ff93ad2017-05-17 07:28:24268 if (base::FeatureList::IsEnabled(media::kOverlayFullscreenVideo)) {
269 bool use_android_overlay =
270 base::FeatureList::IsEnabled(media::kUseAndroidOverlay);
271 overlay_mode_ = use_android_overlay ? OverlayMode::kUseAndroidOverlay
272 : OverlayMode::kUseContentVideoView;
273 } else {
274 overlay_mode_ = OverlayMode::kNoOverlays;
275 }
ampea73f792017-01-19 04:05:39276
tguilbert1bb1c782017-01-23 21:15:11277 delegate_id_ = delegate_->AddObserver(this);
278 delegate_->SetIdle(delegate_id_, true);
sandersd1e49fb62015-12-12 01:18:06279
dalecurtis2cff7f372017-05-24 08:30:08280 media_log_->AddEvent(media_log_->CreateCreatedEvent(
281 url::Origin(frame_->GetSecurityOrigin()).GetURL().spec()));
sandersd72683f252017-07-07 23:20:46282 media_log_->SetStringProperty("frame_url",
283 frame_->GetDocument().Url().GetString().Utf8());
284 media_log_->SetStringProperty("frame_title",
285 frame_->GetDocument().Title().Utf8());
[email protected]4e6be3f2009-05-07 02:24:44286
dalecurtis9cddc0b2017-04-19 21:23:38287 if (params->initial_cdm())
288 SetCdm(params->initial_cdm());
xhwang0ad11e512014-11-25 23:43:09289
Xiaohan Wangf63505d2017-10-21 08:00:53290 // Report a false "EncrytpedEvent" here as a baseline.
291 RecordEncryptedEvent(false);
292
xhwangf94a634d2014-10-22 22:07:27293 // TODO(xhwang): When we use an external Renderer, many methods won't work,
xhwang6fa356202014-12-11 00:44:12294 // e.g. GetCurrentFrameFromCompositor(). See http://crbug.com/434861
dalecurtis9cddc0b2017-04-19 21:23:38295 audio_source_provider_ = new WebAudioSourceProviderImpl(
296 params->audio_renderer_sink(), media_log_.get());
xjz4e5d4bf32017-02-15 21:26:35297
298 if (observer_)
299 observer_->SetClient(this);
Hajime Hoshi8bb37dc2017-12-19 09:35:10300
301 memory_usage_reporting_timer_.SetTaskRunner(
302 frame_->GetTaskRunner(blink::TaskType::kUnthrottled));
[email protected]ec9212f2008-12-18 21:40:36303}
304
[email protected]4e6be3f2009-05-07 02:24:44305WebMediaPlayerImpl::~WebMediaPlayerImpl() {
xhwang51139732017-02-24 19:36:08306 DVLOG(1) << __func__;
acolwellb4034942014-08-28 15:42:43307 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]d43ed912009-02-03 04:52:53308
xhwang51139732017-02-24 19:36:08309 if (set_cdm_result_) {
310 DVLOG(2) << "Resolve pending SetCdm() when media player is destroyed.";
Blink Reformat1c4d759e2017-04-09 16:34:54311 set_cdm_result_->Complete();
xhwang51139732017-02-24 19:36:08312 set_cdm_result_.reset();
313 }
314
alokp1116967f2016-06-11 17:30:56315 suppress_destruction_errors_ = true;
tguilbert1bb1c782017-01-23 21:15:11316
317 delegate_->PlayerGone(delegate_id_);
318 delegate_->RemoveObserver(delegate_id_);
[email protected]baff4512011-10-19 18:21:07319
dalecurtis04bdb582016-08-17 22:15:23320 // Finalize any watch time metrics before destroying the pipeline.
321 watch_time_reporter_.reset();
322
tguilbert350936ff2017-02-24 05:39:27323 // The underlying Pipeline must be stopped before it is destroyed.
324 pipeline_controller_.Stop();
[email protected]f6af7592014-02-28 10:09:11325
dalecurtis83266c72015-10-29 18:43:20326 if (last_reported_memory_usage_)
327 adjust_allocated_memory_cb_.Run(-last_reported_memory_usage_);
328
dalecurtise1edb312016-06-22 02:33:21329 // Destruct compositor resources in the proper order.
Blink Reformat1c4d759e2017-04-09 16:34:54330 client_->SetWebLayer(nullptr);
CJ DiMeglio2302d202017-08-31 08:38:04331
Xiangjun Zhang87299142017-09-13 20:35:03332 client_->MediaRemotingStopped();
333
lethalantidote7f6009d2017-07-07 21:47:39334 if (!surface_layer_for_video_enabled_ && video_weblayer_) {
dalecurtise1edb312016-06-22 02:33:21335 static_cast<cc::VideoLayer*>(video_weblayer_->layer())->StopUsingProvider();
lethalantidote7f6009d2017-07-07 21:47:39336 }
CJ DiMeglio2302d202017-08-31 08:38:04337
338 vfc_task_runner_->DeleteSoon(FROM_HERE, std::move(compositor_));
xhwangea8bb3562015-06-08 21:18:37339
Matt Wolenetz95af6362018-01-04 20:23:42340 if (chunk_demuxer_) {
341 // Continue destruction of |chunk_demuxer_| on the |media_task_runner_| to
342 // avoid racing other pending tasks on |chunk_demuxer_| on that runner while
343 // not further blocking |main_task_runner_| to perform the destruction.
344 media_task_runner_->PostTask(
345 FROM_HERE, base::BindOnce(&WebMediaPlayerImpl::DemuxerDestructionHelper,
346 media_task_runner_, std::move(demuxer_)));
347 }
348
xhwangea8bb3562015-06-08 21:18:37349 media_log_->AddEvent(
350 media_log_->CreateEvent(MediaLogEvent::WEBMEDIAPLAYER_DESTROYED));
[email protected]ec9212f2008-12-18 21:40:36351}
352
Matt Wolenetz95af6362018-01-04 20:23:42353// static
354void WebMediaPlayerImpl::DemuxerDestructionHelper(
355 scoped_refptr<base::SingleThreadTaskRunner> task_runner,
356 std::unique_ptr<Demuxer> demuxer) {
357 DCHECK(task_runner->BelongsToCurrentThread());
358 // ChunkDemuxer's streams may contain much buffered, compressed media that may
359 // need to be paged back in during destruction. Paging delay may exceed the
360 // renderer hang monitor's threshold on at least Windows while also blocking
361 // other work on the renderer main thread, so we do the actual destruction in
362 // the background without blocking WMPI destruction or |task_runner|. On
363 // advice of task_scheduler OWNERS, MayBlock() is not used because virtual
364 // memory overhead is not considered blocking I/O; and CONTINUE_ON_SHUTDOWN is
365 // used to allow process termination to not block on completing the task.
366 base::PostTaskWithTraits(
367 FROM_HERE,
368 {base::TaskPriority::BACKGROUND,
369 base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN},
370 base::BindOnce(
371 [](std::unique_ptr<Demuxer> demuxer_to_destroy) {
372 SCOPED_UMA_HISTOGRAM_TIMER("Media.MSE.DemuxerDestructionTime");
373 demuxer_to_destroy.reset();
374 },
375 std::move(demuxer)));
376}
377
Blink Reformat1c4d759e2017-04-09 16:34:54378void WebMediaPlayerImpl::Load(LoadType load_type,
guidou9bfe4e2f2016-04-09 08:31:19379 const blink::WebMediaPlayerSource& source,
[email protected]62e5e682013-03-07 23:53:24380 CORSMode cors_mode) {
xhwang51139732017-02-24 19:36:08381 DVLOG(1) << __func__;
guidou9bfe4e2f2016-04-09 08:31:19382 // Only URL or MSE blob URL is supported.
Blink Reformat1c4d759e2017-04-09 16:34:54383 DCHECK(source.IsURL());
384 blink::WebURL url = source.GetAsURL();
Xiaohan Wang81fd0022017-07-11 17:45:24385 DVLOG(1) << __func__ << "(" << load_type << ", " << GURL(url) << ", "
386 << cors_mode << ")";
[email protected]d726eddc2013-07-02 22:25:55387 if (!defer_load_cb_.is_null()) {
tguilbert350936ff2017-02-24 05:39:27388 defer_load_cb_.Run(base::Bind(&WebMediaPlayerImpl::DoLoad, AsWeakPtr(),
389 load_type, url, cors_mode));
[email protected]d726eddc2013-07-02 22:25:55390 return;
391 }
[email protected]ef8394c2013-08-21 20:26:30392 DoLoad(load_type, url, cors_mode);
[email protected]62e5e682013-03-07 23:53:24393}
394
CJ DiMeglio013d4c472017-11-21 03:27:30395void WebMediaPlayerImpl::OnWebLayerUpdated() {}
396
397void WebMediaPlayerImpl::RegisterContentsLayer(blink::WebLayer* web_layer) {
CJ DiMeglio2302d202017-08-31 08:38:04398 DCHECK(bridge_);
399 bridge_->GetWebLayer()->CcLayer()->SetContentsOpaque(opaque_);
CJ DiMegliof04c41c2017-09-14 01:21:08400 bridge_->GetWebLayer()->SetContentsOpaqueIsFixed(true);
CJ DiMeglio2302d202017-08-31 08:38:04401 // TODO(lethalantidote): Figure out how to pass along rotation information.
402 // https://crbug/750313.
CJ DiMeglio013d4c472017-11-21 03:27:30403 client_->SetWebLayer(web_layer);
404}
405
406void WebMediaPlayerImpl::UnregisterContentsLayer(blink::WebLayer* web_layer) {
407 // |client_| will unregister its WebLayer if given a nullptr.
408 client_->SetWebLayer(nullptr);
CJ DiMeglio2302d202017-08-31 08:38:04409}
410
Blink Reformat1c4d759e2017-04-09 16:34:54411bool WebMediaPlayerImpl::SupportsOverlayFullscreenVideo() {
watk9c87c6fa2016-05-06 20:36:51412#if defined(OS_ANDROID)
[email protected]68ec57f2017-06-27 22:10:05413 return !using_media_player_renderer_ &&
414 overlay_mode_ == OverlayMode::kUseContentVideoView;
watk9c87c6fa2016-05-06 20:36:51415#else
416 return false;
417#endif
418}
419
tsunghungee562e92016-07-20 18:03:31420void WebMediaPlayerImpl::EnableOverlay() {
421 overlay_enabled_ = true;
liberato2ff93ad2017-05-17 07:28:24422 if (surface_manager_ && overlay_mode_ == OverlayMode::kUseContentVideoView) {
liberatoe8e3f43d2017-05-01 22:23:11423 overlay_surface_id_.reset();
watkf835a792016-06-24 23:24:40424 surface_created_cb_.Reset(
425 base::Bind(&WebMediaPlayerImpl::OnSurfaceCreated, AsWeakPtr()));
426 surface_manager_->CreateFullscreenSurface(pipeline_metadata_.natural_size,
427 surface_created_cb_.callback());
liberato2ff93ad2017-05-17 07:28:24428 } else if (request_routing_token_cb_ &&
429 overlay_mode_ == OverlayMode::kUseAndroidOverlay) {
liberatofe8f9692017-06-08 19:17:36430 overlay_routing_token_is_pending_ = true;
liberato2ff93ad2017-05-17 07:28:24431 token_available_cb_.Reset(
432 base::Bind(&WebMediaPlayerImpl::OnOverlayRoutingToken, AsWeakPtr()));
433 request_routing_token_cb_.Run(token_available_cb_.callback());
watkf835a792016-06-24 23:24:40434 }
tsunghungee562e92016-07-20 18:03:31435
liberato2ff93ad2017-05-17 07:28:24436 // We have requested (and maybe already have) overlay information. If the
437 // restarted decoder requests overlay information, then we'll defer providing
438 // it if it hasn't arrived yet. Otherwise, this would be a race, since we
439 // don't know if the request for overlay info or restart will complete first.
tsunghungee562e92016-07-20 18:03:31440 if (decoder_requires_restart_for_overlay_)
watkdee516f2016-02-18 02:22:19441 ScheduleRestart();
442}
443
tsunghungee562e92016-07-20 18:03:31444void WebMediaPlayerImpl::DisableOverlay() {
445 overlay_enabled_ = false;
liberato2ff93ad2017-05-17 07:28:24446 if (overlay_mode_ == OverlayMode::kUseContentVideoView) {
447 surface_created_cb_.Cancel();
448 overlay_surface_id_ = SurfaceManager::kNoSurfaceID;
449 } else if (overlay_mode_ == OverlayMode::kUseAndroidOverlay) {
450 token_available_cb_.Cancel();
liberatofe8f9692017-06-08 19:17:36451 overlay_routing_token_is_pending_ = false;
452 overlay_routing_token_ = OverlayInfo::RoutingToken();
liberato2ff93ad2017-05-17 07:28:24453 }
tsunghungee562e92016-07-20 18:03:31454
455 if (decoder_requires_restart_for_overlay_)
watkdee516f2016-02-18 02:22:19456 ScheduleRestart();
liberato2ff93ad2017-05-17 07:28:24457 else
458 MaybeSendOverlayInfoToDecoder();
watkdee516f2016-02-18 02:22:19459}
460
Blink Reformat1c4d759e2017-04-09 16:34:54461void WebMediaPlayerImpl::EnteredFullscreen() {
liberatofe8f9692017-06-08 19:17:36462 overlay_info_.is_fullscreen = true;
463
[email protected]c8d574722017-08-30 20:53:43464 // |always_enable_overlays_| implies that we're already in overlay mode, so
465 // take no action here. Otherwise, switch to an overlay if it's allowed and
466 // if it will display properly.
467 if (!always_enable_overlays_ && overlay_mode_ != OverlayMode::kNoOverlays &&
liberato2fd111be2017-01-04 00:25:06468 DoesOverlaySupportMetadata()) {
tsunghungee562e92016-07-20 18:03:31469 EnableOverlay();
liberato2fd111be2017-01-04 00:25:06470 }
liberato2ff93ad2017-05-17 07:28:24471
liberatofe8f9692017-06-08 19:17:36472 // We send this only if we can send multiple calls. Otherwise, either (a)
473 // we already sent it and we don't have a callback anyway (we reset it when
474 // it's called in restart mode), or (b) we'll send this later when the surface
475 // actually arrives. GVD assumes that the first overlay info will have the
476 // routing information. Note that we set |is_fullscreen_| earlier, so that
477 // if EnableOverlay() can include fullscreen info in case it sends the overlay
478 // info before returning.
479 if (!decoder_requires_restart_for_overlay_)
480 MaybeSendOverlayInfoToDecoder();
tsunghungee562e92016-07-20 18:03:31481}
482
Blink Reformat1c4d759e2017-04-09 16:34:54483void WebMediaPlayerImpl::ExitedFullscreen() {
liberatofe8f9692017-06-08 19:17:36484 overlay_info_.is_fullscreen = false;
485
[email protected]c8d574722017-08-30 20:53:43486 // If we're in overlay mode, then exit it unless we're supposed to allow
487 // overlays all the time.
488 if (!always_enable_overlays_ && overlay_enabled_)
tsunghungee562e92016-07-20 18:03:31489 DisableOverlay();
liberato2ff93ad2017-05-17 07:28:24490
liberatofe8f9692017-06-08 19:17:36491 // See EnteredFullscreen for why we do this.
492 if (!decoder_requires_restart_for_overlay_)
493 MaybeSendOverlayInfoToDecoder();
tsunghungee562e92016-07-20 18:03:31494}
495
Blink Reformat1c4d759e2017-04-09 16:34:54496void WebMediaPlayerImpl::BecameDominantVisibleContent(bool isDominant) {
xjzcdbbe732016-12-03 20:47:42497 if (observer_)
498 observer_->OnBecameDominantVisibleContent(isDominant);
499}
500
Blink Reformat1c4d759e2017-04-09 16:34:54501void WebMediaPlayerImpl::SetIsEffectivelyFullscreen(
zqzhangabc08242017-03-02 16:07:14502 bool isEffectivelyFullscreen) {
503 delegate_->SetIsEffectivelyFullscreen(delegate_id_, isEffectivelyFullscreen);
504}
505
Mounir Lamouri41a79c62017-06-06 12:53:16506void WebMediaPlayerImpl::OnHasNativeControlsChanged(bool has_native_controls) {
507 if (!watch_time_reporter_)
508 return;
509
510 if (has_native_controls)
511 watch_time_reporter_->OnNativeControlsEnabled();
512 else
513 watch_time_reporter_->OnNativeControlsDisabled();
514}
515
Mounir Lamourif9af74e72017-06-19 19:31:45516void WebMediaPlayerImpl::OnDisplayTypeChanged(
517 WebMediaPlayer::DisplayType display_type) {
518 if (!watch_time_reporter_)
519 return;
520
521 switch (display_type) {
522 case WebMediaPlayer::DisplayType::kInline:
523 watch_time_reporter_->OnDisplayTypeInline();
524 break;
525 case WebMediaPlayer::DisplayType::kFullscreen:
526 watch_time_reporter_->OnDisplayTypeFullscreen();
527 break;
528 case WebMediaPlayer::DisplayType::kPictureInPicture:
529 watch_time_reporter_->OnDisplayTypePictureInPicture();
530 break;
531 }
532}
533
[email protected]ef8394c2013-08-21 20:26:30534void WebMediaPlayerImpl::DoLoad(LoadType load_type,
[email protected]180ef242013-11-07 06:50:46535 const blink::WebURL& url,
[email protected]d726eddc2013-07-02 22:25:55536 CORSMode cors_mode) {
John Chen5b164a02017-11-01 00:36:09537 TRACE_EVENT1("media", "WebMediaPlayerImpl::DoLoad", "id", media_log_->id());
pkastingf5279482016-07-27 02:18:20538 DVLOG(1) << __func__;
acolwellb4034942014-08-28 15:42:43539 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]d726eddc2013-07-02 22:25:55540
[email protected]62e5e682013-03-07 23:53:24541 GURL gurl(url);
dalecurtis9cddc0b2017-04-19 21:23:38542 ReportMetrics(load_type, gurl, frame_->GetSecurityOrigin(), media_log_.get());
[email protected]62e5e682013-03-07 23:53:24543
Dan Sanderscd8981c2017-08-31 22:37:02544 // Report poster availability for SRC=.
545 if (load_type == kLoadTypeURL) {
546 if (preload_ == MultibufferDataSource::METADATA) {
547 UMA_HISTOGRAM_BOOLEAN("Media.SRC.PreloadMetaDataHasPoster", has_poster_);
548 } else if (preload_ == MultibufferDataSource::AUTO) {
549 UMA_HISTOGRAM_BOOLEAN("Media.SRC.PreloadAutoHasPoster", has_poster_);
550 }
551 }
552
[email protected]926f8fd2013-04-12 20:27:53553 // Set subresource URL for crash reporting.
Robert Sesekc5e91df2017-12-12 21:11:03554 static base::debug::CrashKeyString* subresource_url =
555 base::debug::AllocateCrashKeyString("subresource_url",
556 base::debug::CrashKeySize::Size256);
557 base::debug::SetCrashKeyString(subresource_url, gurl.spec());
[email protected]926f8fd2013-04-12 20:27:53558
tguilbert75e2bf62017-04-26 20:13:12559 // Used for HLS playback.
560 loaded_url_ = gurl;
tguilbert25a4d112016-10-13 21:56:51561
[email protected]ef8394c2013-08-21 20:26:30562 load_type_ = load_type;
563
Blink Reformat1c4d759e2017-04-09 16:34:54564 SetNetworkState(WebMediaPlayer::kNetworkStateLoading);
565 SetReadyState(WebMediaPlayer::kReadyStateHaveNothing);
566 media_log_->AddEvent(media_log_->CreateLoadEvent(url.GetString().Utf8()));
[email protected]d726eddc2013-07-02 22:25:55567
Dale Curtis74612b72017-12-14 20:56:19568 // URL is used for UKM reporting. Privacy requires we only report origin of
569 // the top frame. |is_top_frame| signals how to interpret the origin.
570 // TODO(crbug.com/787209): Stop getting origin from the renderer.
571 media_metrics_provider_->Initialize(load_type == kLoadTypeMediaSource,
572 frame_ == frame_->Top(),
573 frame_->Top()->GetSecurityOrigin());
574
[email protected]d726eddc2013-07-02 22:25:55575 // Media source pipelines can start immediately.
Blink Reformat1c4d759e2017-04-09 16:34:54576 if (load_type == kLoadTypeMediaSource) {
[email protected]ef8394c2013-08-21 20:26:30577 StartPipeline();
hubbe5f0ad43b2015-12-14 20:57:26578 } else {
dalecurtisb6e052f52016-08-25 00:35:55579 data_source_.reset(new MultibufferDataSource(
Alok Priyadarshib8f30542017-07-22 00:16:25580 main_task_runner_,
581 url_index_->GetByUrl(url, static_cast<UrlData::CORSMode>(cors_mode)),
582 media_log_.get(), &buffered_data_source_host_,
dalecurtisb6e052f52016-08-25 00:35:55583 base::Bind(&WebMediaPlayerImpl::NotifyDownloading, AsWeakPtr())));
avayvode46d7bef2016-03-30 23:18:26584 data_source_->SetPreload(preload_);
Yoav Weissc34fb0d2018-01-08 05:37:27585 data_source_->SetIsClientAudioElement(client_->IsAudioElement());
avayvode46d7bef2016-03-30 23:18:26586 data_source_->Initialize(
587 base::Bind(&WebMediaPlayerImpl::DataSourceInitialized, AsWeakPtr()));
hubbe5f0ad43b2015-12-14 20:57:26588 }
hubbed5f36882016-01-15 22:40:37589
590#if defined(OS_ANDROID) // WMPI_CAST
dalecurtisbb3eaac2016-01-27 21:10:25591 cast_impl_.Initialize(url, frame_, delegate_id_);
hubbed5f36882016-01-15 22:40:37592#endif
[email protected]62e5e682013-03-07 23:53:24593}
594
Blink Reformat1c4d759e2017-04-09 16:34:54595void WebMediaPlayerImpl::Play() {
pkastingf5279482016-07-27 02:18:20596 DVLOG(1) << __func__;
acolwellb4034942014-08-28 15:42:43597 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]d43ed912009-02-03 04:52:53598
avayvod65fad272017-02-24 01:00:48599 // User initiated play unlocks background video playback.
Mustaq Ahmede473e4352017-11-04 01:04:25600 if (blink::WebUserGestureIndicator::IsProcessingUserGesture(frame_))
avayvod65fad272017-02-24 01:00:48601 video_locked_when_paused_when_hidden_ = false;
602
hubbed5f36882016-01-15 22:40:37603#if defined(OS_ANDROID) // WMPI_CAST
Blink Reformat1c4d759e2017-04-09 16:34:54604 if (IsRemote()) {
dalecurtis6e2716d2016-01-21 04:49:15605 cast_impl_.play();
hubbed5f36882016-01-15 22:40:37606 return;
607 }
608#endif
sandersd35d2c3f2017-01-14 02:04:42609 // TODO(sandersd): Do we want to reset the idle timer here?
tguilbert1bb1c782017-01-23 21:15:11610 delegate_->SetIdle(delegate_id_, false);
[email protected]49480902009-07-14 20:23:43611 paused_ = false;
tguilbert350936ff2017-02-24 05:39:27612 pipeline_controller_.SetPlaybackRate(playback_rate_);
dalecurtis4619cd02016-09-22 21:39:10613 background_pause_timer_.Stop();
sandersd1c0bba02016-03-04 23:14:08614
[email protected]039b7542013-10-17 22:06:25615 if (data_source_)
616 data_source_->MediaIsPlaying();
[email protected]090f7312011-08-05 23:26:40617
xjz48a9cb72016-12-20 04:02:49618 if (observer_)
619 observer_->OnPlaying();
620
Dale Curtis051fdf62017-08-05 00:21:13621 // If we're seeking we'll trigger the watch time reporter upon seek completed;
622 // we don't want to start it here since the seek time is unstable. E.g., when
623 // playing content with a positive start time we would have a zero seek time.
624 if (!Seeking()) {
625 DCHECK(watch_time_reporter_);
626 watch_time_reporter_->OnPlaying();
627 }
628
Chris Cunninghamd9df58e2017-08-29 00:04:23629 if (video_decode_stats_reporter_)
630 video_decode_stats_reporter_->OnPlaying();
631
acolwell9e0840d2014-09-06 19:01:32632 media_log_->AddEvent(media_log_->CreateEvent(MediaLogEvent::PLAY));
sandersd50a635e2016-04-04 22:50:09633 UpdatePlayState();
[email protected]ec9212f2008-12-18 21:40:36634}
635
Blink Reformat1c4d759e2017-04-09 16:34:54636void WebMediaPlayerImpl::Pause() {
pkastingf5279482016-07-27 02:18:20637 DVLOG(1) << __func__;
acolwellb4034942014-08-28 15:42:43638 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]d43ed912009-02-03 04:52:53639
sandersd50a635e2016-04-04 22:50:09640 // We update the paused state even when casting, since we expect pause() to be
641 // called when casting begins, and when we exit casting we should end up in a
642 // paused state.
[email protected]49480902009-07-14 20:23:43643 paused_ = true;
hubbed5f36882016-01-15 22:40:37644
avayvodeb9098d2017-01-07 00:33:03645 // No longer paused because it was hidden.
646 paused_when_hidden_ = false;
647
avayvod65fad272017-02-24 01:00:48648 // User initiated pause locks background videos.
Mustaq Ahmede473e4352017-11-04 01:04:25649 if (blink::WebUserGestureIndicator::IsProcessingUserGesture(frame_))
avayvod65fad272017-02-24 01:00:48650 video_locked_when_paused_when_hidden_ = true;
651
hubbed5f36882016-01-15 22:40:37652#if defined(OS_ANDROID) // WMPI_CAST
Blink Reformat1c4d759e2017-04-09 16:34:54653 if (IsRemote()) {
dalecurtis6e2716d2016-01-21 04:49:15654 cast_impl_.pause();
hubbed5f36882016-01-15 22:40:37655 return;
656 }
657#endif
658
tguilbert350936ff2017-02-24 05:39:27659 pipeline_controller_.SetPlaybackRate(0.0);
Dale Curtis051fdf62017-08-05 00:21:13660 paused_time_ = pipeline_controller_.GetMediaTime();
[email protected]090f7312011-08-05 23:26:40661
xjz48a9cb72016-12-20 04:02:49662 if (observer_)
663 observer_->OnPaused();
664
dalecurtis04bdb582016-08-17 22:15:23665 DCHECK(watch_time_reporter_);
666 watch_time_reporter_->OnPaused();
Chris Cunninghamd9df58e2017-08-29 00:04:23667
668 if (video_decode_stats_reporter_)
669 video_decode_stats_reporter_->OnPaused();
670
acolwell9e0840d2014-09-06 19:01:32671 media_log_->AddEvent(media_log_->CreateEvent(MediaLogEvent::PAUSE));
avayvod2135a642017-01-13 00:17:14672
sandersd50a635e2016-04-04 22:50:09673 UpdatePlayState();
[email protected]ec9212f2008-12-18 21:40:36674}
675
Blink Reformat1c4d759e2017-04-09 16:34:54676void WebMediaPlayerImpl::Seek(double seconds) {
pkastingf5279482016-07-27 02:18:20677 DVLOG(1) << __func__ << "(" << seconds << "s)";
acolwellb4034942014-08-28 15:42:43678 DCHECK(main_task_runner_->BelongsToCurrentThread());
servolk86b3d88fb2017-03-18 02:50:28679 media_log_->AddEvent(media_log_->CreateSeekEvent(seconds));
sandersd1c0bba02016-03-04 23:14:08680 DoSeek(base::TimeDelta::FromSecondsD(seconds), true);
681}
682
683void WebMediaPlayerImpl::DoSeek(base::TimeDelta time, bool time_updated) {
684 DCHECK(main_task_runner_->BelongsToCurrentThread());
John Chen5b164a02017-11-01 00:36:09685 TRACE_EVENT2("media", "WebMediaPlayerImpl::DoSeek", "target",
686 time.InSecondsF(), "id", media_log_->id());
[email protected]d43ed912009-02-03 04:52:53687
hubbed5f36882016-01-15 22:40:37688#if defined(OS_ANDROID) // WMPI_CAST
Blink Reformat1c4d759e2017-04-09 16:34:54689 if (IsRemote()) {
sandersd1c0bba02016-03-04 23:14:08690 cast_impl_.seek(time);
hubbed5f36882016-01-15 22:40:37691 return;
692 }
693#endif
694
srirama.mccf671812015-01-08 11:59:13695 ReadyState old_state = ready_state_;
Blink Reformat1c4d759e2017-04-09 16:34:54696 if (ready_state_ > WebMediaPlayer::kReadyStateHaveMetadata)
697 SetReadyState(WebMediaPlayer::kReadyStateHaveMetadata);
[email protected]1bb666802013-11-28 06:12:08698
Dale Curtis051fdf62017-08-05 00:21:13699 // When paused or ended, we know exactly what the current time is and can
700 // elide seeks to it. However, there are two cases that are not elided:
sandersd1c0bba02016-03-04 23:14:08701 // 1) When the pipeline state is not stable.
702 // In this case we just let |pipeline_controller_| decide what to do, as
703 // it has complete information.
704 // 2) For MSE.
705 // Because the buffers may have changed between seeks, MSE seeks are
706 // never elided.
Dale Curtis051fdf62017-08-05 00:21:13707 if (paused_ && pipeline_controller_.IsStable() &&
708 (paused_time_ == time ||
709 (ended_ && time == base::TimeDelta::FromSecondsD(Duration()))) &&
sandersd1c0bba02016-03-04 23:14:08710 !chunk_demuxer_) {
711 // If the ready state was high enough before, we can indicate that the seek
712 // completed just by restoring it. Otherwise we will just wait for the real
713 // ready state change to eventually happen.
Blink Reformat1c4d759e2017-04-09 16:34:54714 if (old_state == kReadyStateHaveEnoughData) {
srirama.m8f4a37562014-12-13 08:16:18715 main_task_runner_->PostTask(
alokp967c902452016-05-06 05:21:37716 FROM_HERE, base::Bind(&WebMediaPlayerImpl::OnBufferingStateChange,
717 AsWeakPtr(), BUFFERING_HAVE_ENOUGH));
srirama.m36ab2682014-12-11 04:20:01718 }
sandersd1c0bba02016-03-04 23:14:08719 return;
srirama.m36ab2682014-12-11 04:20:01720 }
[email protected]44ff37c02009-10-24 01:03:03721
dalecurtis04bdb582016-08-17 22:15:23722 // Call this before setting |seeking_| so that the current media time can be
723 // recorded by the reporter.
724 if (watch_time_reporter_)
725 watch_time_reporter_->OnSeeking();
726
dalecurtis1af3c1a2017-04-11 00:53:49727 // Clear any new frame processed callbacks on seek; otherwise we'll end up
728 // logging a time long after the seek completes.
729 frame_time_report_cb_.Cancel();
730
sandersd35d2c3f2017-01-14 02:04:42731 // TODO(sandersd): Move |seeking_| to PipelineController.
732 // TODO(sandersd): Do we want to reset the idle timer here?
tguilbert1bb1c782017-01-23 21:15:11733 delegate_->SetIdle(delegate_id_, false);
sandersd50a635e2016-04-04 22:50:09734 ended_ = false;
[email protected]b3766a22010-12-22 17:34:13735 seeking_ = true;
sandersd1c0bba02016-03-04 23:14:08736 seek_time_ = time;
737 if (paused_)
738 paused_time_ = time;
739 pipeline_controller_.Seek(time, time_updated);
[email protected]b3766a22010-12-22 17:34:13740
sandersd50a635e2016-04-04 22:50:09741 // This needs to be called after Seek() so that if a resume is triggered, it
742 // is to the correct time.
743 UpdatePlayState();
[email protected]ec9212f2008-12-18 21:40:36744}
745
Blink Reformat1c4d759e2017-04-09 16:34:54746void WebMediaPlayerImpl::SetRate(double rate) {
pkastingf5279482016-07-27 02:18:20747 DVLOG(1) << __func__ << "(" << rate << ")";
acolwellb4034942014-08-28 15:42:43748 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]d43ed912009-02-03 04:52:53749
Matt Wolenetz6010f6c2017-10-18 00:44:36750 if (rate != playback_rate_) {
751 LIMITED_MEDIA_LOG(INFO, media_log_.get(), num_playback_rate_logs_,
752 kMaxNumPlaybackRateLogs)
753 << "Effective playback rate changed from " << playback_rate_ << " to "
754 << rate;
755 }
756
[email protected]49480902009-07-14 20:23:43757 playback_rate_ = rate;
758 if (!paused_) {
tguilbert350936ff2017-02-24 05:39:27759 pipeline_controller_.SetPlaybackRate(rate);
[email protected]039b7542013-10-17 22:06:25760 if (data_source_)
761 data_source_->MediaPlaybackRateChanged(rate);
[email protected]49480902009-07-14 20:23:43762 }
[email protected]ec9212f2008-12-18 21:40:36763}
764
Blink Reformat1c4d759e2017-04-09 16:34:54765void WebMediaPlayerImpl::SetVolume(double volume) {
pkastingf5279482016-07-27 02:18:20766 DVLOG(1) << __func__ << "(" << volume << ")";
acolwellb4034942014-08-28 15:42:43767 DCHECK(main_task_runner_->BelongsToCurrentThread());
dalecurtisbb3eaac2016-01-27 21:10:25768 volume_ = volume;
tguilbert350936ff2017-02-24 05:39:27769 pipeline_controller_.SetVolume(volume_ * volume_multiplier_);
dalecurtis04bdb582016-08-17 22:15:23770 if (watch_time_reporter_)
771 watch_time_reporter_->OnVolumeChange(volume);
Becca Hughes9f6fd4b82017-06-15 10:01:40772 delegate_->DidPlayerMutedStatusChange(delegate_id_, volume == 0.0);
mlamouri910111362016-11-04 11:28:24773
774 // The play state is updated because the player might have left the autoplay
775 // muted state.
776 UpdatePlayState();
[email protected]ec9212f2008-12-18 21:40:36777}
[email protected]f0a51fb52009-03-05 12:46:38778
Blink Reformat1c4d759e2017-04-09 16:34:54779void WebMediaPlayerImpl::SetSinkId(
guidouc7babef2015-10-22 00:42:35780 const blink::WebString& sink_id,
781 const blink::WebSecurityOrigin& security_origin,
782 blink::WebSetSinkIdCallbacks* web_callback) {
guidou69223ce2015-06-16 10:36:19783 DCHECK(main_task_runner_->BelongsToCurrentThread());
pkastingf5279482016-07-27 02:18:20784 DVLOG(1) << __func__;
guidouc7babef2015-10-22 00:42:35785
olka68b69392016-04-01 11:42:12786 media::OutputDeviceStatusCB callback =
787 media::ConvertToOutputDeviceStatusCB(web_callback);
guidouc7babef2015-10-22 00:42:35788 media_task_runner_->PostTask(
789 FROM_HERE,
790 base::Bind(&SetSinkIdOnMediaThread, audio_source_provider_,
Blink Reformat1c4d759e2017-04-09 16:34:54791 sink_id.Utf8(), static_cast<url::Origin>(security_origin),
guidouc7babef2015-10-22 00:42:35792 callback));
guidou69223ce2015-06-16 10:36:19793}
794
Blink Reformat1c4d759e2017-04-09 16:34:54795STATIC_ASSERT_ENUM(WebMediaPlayer::kPreloadNone, MultibufferDataSource::NONE);
796STATIC_ASSERT_ENUM(WebMediaPlayer::kPreloadMetaData,
dalecurtisb6e052f52016-08-25 00:35:55797 MultibufferDataSource::METADATA);
Blink Reformat1c4d759e2017-04-09 16:34:54798STATIC_ASSERT_ENUM(WebMediaPlayer::kPreloadAuto, MultibufferDataSource::AUTO);
[email protected]23a8b1d82011-04-05 16:28:20799
Blink Reformat1c4d759e2017-04-09 16:34:54800void WebMediaPlayerImpl::SetPreload(WebMediaPlayer::Preload preload) {
pkastingf5279482016-07-27 02:18:20801 DVLOG(1) << __func__ << "(" << preload << ")";
acolwellb4034942014-08-28 15:42:43802 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]4e6be3f2009-05-07 02:24:44803
dalecurtisb6e052f52016-08-25 00:35:55804 preload_ = static_cast<MultibufferDataSource::Preload>(preload);
[email protected]b49beeb2013-03-01 20:04:00805 if (data_source_)
[email protected]09c60222014-08-07 16:42:31806 data_source_->SetPreload(preload_);
[email protected]4e6be3f2009-05-07 02:24:44807}
808
Blink Reformat1c4d759e2017-04-09 16:34:54809bool WebMediaPlayerImpl::HasVideo() const {
acolwellb4034942014-08-28 15:42:43810 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]d43ed912009-02-03 04:52:53811
[email protected]b8877772014-03-26 20:17:15812 return pipeline_metadata_.has_video;
[email protected]d43ed912009-02-03 04:52:53813}
814
Blink Reformat1c4d759e2017-04-09 16:34:54815bool WebMediaPlayerImpl::HasAudio() const {
acolwellb4034942014-08-28 15:42:43816 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]fc367af2009-08-14 23:06:35817
[email protected]b8877772014-03-26 20:17:15818 return pipeline_metadata_.has_audio;
[email protected]fc367af2009-08-14 23:06:35819}
820
Blink Reformat1c4d759e2017-04-09 16:34:54821void WebMediaPlayerImpl::EnabledAudioTracksChanged(
servolkf25ceed2016-07-01 03:44:38822 const blink::WebVector<blink::WebMediaPlayer::TrackId>& enabledTrackIds) {
823 DCHECK(main_task_runner_->BelongsToCurrentThread());
824
825 std::ostringstream logstr;
826 std::vector<MediaTrack::Id> enabledMediaTrackIds;
827 for (const auto& blinkTrackId : enabledTrackIds) {
Blink Reformat1c4d759e2017-04-09 16:34:54828 MediaTrack::Id track_id = blinkTrackId.Utf8().data();
servolkf25ceed2016-07-01 03:44:38829 logstr << track_id << " ";
830 enabledMediaTrackIds.push_back(track_id);
831 }
dalecurtis9cddc0b2017-04-19 21:23:38832 MEDIA_LOG(INFO, media_log_.get())
833 << "Enabled audio tracks: [" << logstr.str() << "]";
tguilbert350936ff2017-02-24 05:39:27834 pipeline_controller_.OnEnabledAudioTracksChanged(enabledMediaTrackIds);
servolkf25ceed2016-07-01 03:44:38835}
836
Blink Reformat1c4d759e2017-04-09 16:34:54837void WebMediaPlayerImpl::SelectedVideoTrackChanged(
servolkf25ceed2016-07-01 03:44:38838 blink::WebMediaPlayer::TrackId* selectedTrackId) {
839 DCHECK(main_task_runner_->BelongsToCurrentThread());
840
servolk9bed6602017-02-24 01:20:11841 base::Optional<MediaTrack::Id> selected_video_track_id;
842 if (selectedTrackId && !video_track_disabled_)
Blink Reformat1c4d759e2017-04-09 16:34:54843 selected_video_track_id = MediaTrack::Id(selectedTrackId->Utf8().data());
dalecurtis9cddc0b2017-04-19 21:23:38844 MEDIA_LOG(INFO, media_log_.get())
845 << "Selected video track: [" << selected_video_track_id.value_or("")
846 << "]";
tguilbert350936ff2017-02-24 05:39:27847 pipeline_controller_.OnSelectedVideoTrackChanged(selected_video_track_id);
servolkf25ceed2016-07-01 03:44:38848}
849
Blink Reformat1c4d759e2017-04-09 16:34:54850blink::WebSize WebMediaPlayerImpl::NaturalSize() const {
acolwellb4034942014-08-28 15:42:43851 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]d43ed912009-02-03 04:52:53852
[email protected]b8877772014-03-26 20:17:15853 return blink::WebSize(pipeline_metadata_.natural_size);
[email protected]d43ed912009-02-03 04:52:53854}
855
Jiajia Qin82acdc02017-07-31 09:55:14856blink::WebSize WebMediaPlayerImpl::VisibleRect() const {
857 DCHECK(main_task_runner_->BelongsToCurrentThread());
858 scoped_refptr<VideoFrame> video_frame = GetCurrentFrameFromCompositor();
859 if (!video_frame)
860 return blink::WebSize();
861
862 const gfx::Rect& visible_rect = video_frame->visible_rect();
863 return blink::WebSize(visible_rect.width(), visible_rect.height());
864}
865
Blink Reformat1c4d759e2017-04-09 16:34:54866bool WebMediaPlayerImpl::Paused() const {
acolwellb4034942014-08-28 15:42:43867 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]d43ed912009-02-03 04:52:53868
hubbed5f36882016-01-15 22:40:37869#if defined(OS_ANDROID) // WMPI_CAST
Blink Reformat1c4d759e2017-04-09 16:34:54870 if (IsRemote())
danakj4f1fd6a2017-01-06 21:15:17871 return cast_impl_.IsPaused();
hubbed5f36882016-01-15 22:40:37872#endif
sandersd50a635e2016-04-04 22:50:09873
tguilbert350936ff2017-02-24 05:39:27874 return pipeline_controller_.GetPlaybackRate() == 0.0f;
[email protected]d43ed912009-02-03 04:52:53875}
876
Blink Reformat1c4d759e2017-04-09 16:34:54877bool WebMediaPlayerImpl::Seeking() const {
acolwellb4034942014-08-28 15:42:43878 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]d43ed912009-02-03 04:52:53879
Blink Reformat1c4d759e2017-04-09 16:34:54880 if (ready_state_ == WebMediaPlayer::kReadyStateHaveNothing)
[email protected]0acebfa2009-08-21 22:45:40881 return false;
[email protected]67cd5052009-09-10 21:53:22882
[email protected]b3766a22010-12-22 17:34:13883 return seeking_;
[email protected]ec9212f2008-12-18 21:40:36884}
885
Blink Reformat1c4d759e2017-04-09 16:34:54886double WebMediaPlayerImpl::Duration() const {
acolwellb4034942014-08-28 15:42:43887 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]39bdde32013-04-17 17:44:20888
Blink Reformat1c4d759e2017-04-09 16:34:54889 if (ready_state_ == WebMediaPlayer::kReadyStateHaveNothing)
[email protected]39bdde32013-04-17 17:44:20890 return std::numeric_limits<double>::quiet_NaN();
891
chcunninghamb92d5062017-01-10 21:50:22892 // Use duration from ChunkDemuxer when present. MSE allows users to specify
893 // duration as a double. This propagates to the rest of the pipeline as a
894 // TimeDelta with potentially reduced precision (limited to Microseconds).
895 // ChunkDemuxer returns the full-precision user-specified double. This ensures
896 // users can "get" the exact duration they "set".
897 if (chunk_demuxer_)
898 return chunk_demuxer_->GetDuration();
899
avayvodcc273dd2017-01-19 19:35:12900 base::TimeDelta pipeline_duration = GetPipelineMediaDuration();
chcunninghamb92d5062017-01-10 21:50:22901 return pipeline_duration == kInfiniteDuration
902 ? std::numeric_limits<double>::infinity()
903 : pipeline_duration.InSecondsF();
[email protected]d43ed912009-02-03 04:52:53904}
905
[email protected]db66d0092014-04-16 07:15:12906double WebMediaPlayerImpl::timelineOffset() const {
acolwellb4034942014-08-28 15:42:43907 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]db66d0092014-04-16 07:15:12908
909 if (pipeline_metadata_.timeline_offset.is_null())
910 return std::numeric_limits<double>::quiet_NaN();
911
912 return pipeline_metadata_.timeline_offset.ToJsTime();
913}
914
Dale Curtis051fdf62017-08-05 00:21:13915base::TimeDelta WebMediaPlayerImpl::GetCurrentTimeInternal() const {
916 DCHECK(main_task_runner_->BelongsToCurrentThread());
917 DCHECK_NE(ready_state_, WebMediaPlayer::kReadyStateHaveNothing);
918
919 base::TimeDelta current_time;
920 if (Seeking())
921 current_time = seek_time_;
922#if defined(OS_ANDROID) // WMPI_CAST
923 else if (IsRemote())
924 current_time = cast_impl_.currentTime();
925#endif
926 else if (paused_)
927 current_time = paused_time_;
928 else
929 current_time = pipeline_controller_.GetMediaTime();
930
931 DCHECK_NE(current_time, kInfiniteDuration);
932 DCHECK_GE(current_time, base::TimeDelta());
933 return current_time;
934}
935
Blink Reformat1c4d759e2017-04-09 16:34:54936double WebMediaPlayerImpl::CurrentTime() const {
acolwellb4034942014-08-28 15:42:43937 DCHECK(main_task_runner_->BelongsToCurrentThread());
Blink Reformat1c4d759e2017-04-09 16:34:54938 DCHECK_NE(ready_state_, WebMediaPlayer::kReadyStateHaveNothing);
scherkusd2c745b2014-09-04 05:03:40939
940 // TODO(scherkus): Replace with an explicit ended signal to HTMLMediaElement,
941 // see http://crbug.com/409280
Dale Curtis051fdf62017-08-05 00:21:13942 // Note: Duration() may be infinity.
josephlolak918863bc2017-11-15 08:54:33943 return (ended_ && !std::isinf(Duration()))
944 ? Duration()
945 : GetCurrentTimeInternal().InSecondsF();
[email protected]d43ed912009-02-03 04:52:53946}
947
Blink Reformat1c4d759e2017-04-09 16:34:54948WebMediaPlayer::NetworkState WebMediaPlayerImpl::GetNetworkState() const {
acolwellb4034942014-08-28 15:42:43949 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]ddb1e5a2010-12-13 20:10:45950 return network_state_;
951}
952
Blink Reformat1c4d759e2017-04-09 16:34:54953WebMediaPlayer::ReadyState WebMediaPlayerImpl::GetReadyState() const {
acolwellb4034942014-08-28 15:42:43954 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]ddb1e5a2010-12-13 20:10:45955 return ready_state_;
956}
957
wolenetzed8e7092017-04-21 16:28:59958blink::WebString WebMediaPlayerImpl::GetErrorMessage() const {
wolenetz4d39cc02016-04-05 19:54:41959 DCHECK(main_task_runner_->BelongsToCurrentThread());
wolenetzed8e7092017-04-21 16:28:59960 return blink::WebString::FromUTF8(media_log_->GetErrorMessage());
wolenetz4d39cc02016-04-05 19:54:41961}
962
Blink Reformat1c4d759e2017-04-09 16:34:54963blink::WebTimeRanges WebMediaPlayerImpl::Buffered() const {
acolwellb4034942014-08-28 15:42:43964 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]779a8322014-08-22 21:28:37965
acolwell9e0840d2014-09-06 19:01:32966 Ranges<base::TimeDelta> buffered_time_ranges =
tguilbert350936ff2017-02-24 05:39:27967 pipeline_controller_.GetBufferedTimeRanges();
[email protected]779a8322014-08-22 21:28:37968
avayvodcc273dd2017-01-19 19:35:12969 const base::TimeDelta duration = GetPipelineMediaDuration();
dalecurtis39a7f932016-07-19 18:34:59970 if (duration != kInfiniteDuration) {
tguilbert350936ff2017-02-24 05:39:27971 buffered_data_source_host_.AddBufferedTimeRanges(&buffered_time_ranges,
972 duration);
[email protected]779a8322014-08-22 21:28:37973 }
[email protected]02022fc2014-05-16 00:05:31974 return ConvertToWebTimeRanges(buffered_time_ranges);
975}
976
Blink Reformat1c4d759e2017-04-09 16:34:54977blink::WebTimeRanges WebMediaPlayerImpl::Seekable() const {
acolwellb4034942014-08-28 15:42:43978 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]39bdde32013-04-17 17:44:20979
Blink Reformat1c4d759e2017-04-09 16:34:54980 if (ready_state_ < WebMediaPlayer::kReadyStateHaveMetadata)
philipjb0e6f3f2014-09-30 09:51:53981 return blink::WebTimeRanges();
982
Blink Reformat1c4d759e2017-04-09 16:34:54983 const double seekable_end = Duration();
dalecurtis56359cb2014-10-28 00:06:29984
985 // Allow a special exception for seeks to zero for streaming sources with a
986 // finite duration; this allows looping to work.
tguilbertade2bcb2017-01-07 02:57:45987 const bool is_finite_stream = data_source_ && data_source_->IsStreaming() &&
988 std::isfinite(seekable_end);
989
tguilbert75e2bf62017-04-26 20:13:12990 // Do not change the seekable range when using the MediaPlayerRenderer. It
991 // will take care of dropping invalid seeks.
992 const bool force_seeks_to_zero =
993 !using_media_player_renderer_ && is_finite_stream;
dalecurtis56359cb2014-10-28 00:06:29994
995 // TODO(dalecurtis): Technically this allows seeking on media which return an
tguilbertade2bcb2017-01-07 02:57:45996 // infinite duration so long as DataSource::IsStreaming() is false. While not
dalecurtis56359cb2014-10-28 00:06:29997 // expected, disabling this breaks semi-live players, http://crbug.com/427412.
998 const blink::WebTimeRange seekable_range(
tguilbertade2bcb2017-01-07 02:57:45999 0.0, force_seeks_to_zero ? 0.0 : seekable_end);
philipjb0e6f3f2014-09-30 09:51:531000 return blink::WebTimeRanges(&seekable_range, 1);
[email protected]ec9212f2008-12-18 21:40:361001}
1002
sandersd35d2c3f2017-01-14 02:04:421003bool WebMediaPlayerImpl::IsPrerollAttemptNeeded() {
1004 // TODO(sandersd): Replace with |highest_ready_state_since_seek_| if we need
1005 // to ensure that preroll always gets a chance to complete.
1006 // See http://crbug.com/671525.
Blink Reformat1c4d759e2017-04-09 16:34:541007 if (highest_ready_state_ >= ReadyState::kReadyStateHaveFutureData)
sandersd35d2c3f2017-01-14 02:04:421008 return false;
1009
Fredrik Hubinette4cfb4412017-08-23 00:03:071010 // To suspend before we reach kReadyStateHaveCurrentData is only ok
1011 // if we know we're going to get woken up when we get more data, which
1012 // will only happen if the network is in the "Loading" state.
1013 // This happens when the network is fast, but multiple videos are loading
1014 // and multiplexing gets held up waiting for available threads.
1015 if (highest_ready_state_ <= ReadyState::kReadyStateHaveMetadata &&
1016 network_state_ != WebMediaPlayer::kNetworkStateLoading) {
1017 return true;
1018 }
1019
sandersd35d2c3f2017-01-14 02:04:421020 if (preroll_attempt_pending_)
1021 return true;
1022
1023 // Freshly initialized; there has never been any loading progress. (Otherwise
1024 // |preroll_attempt_pending_| would be true when the start time is null.)
1025 if (preroll_attempt_start_time_.is_null())
1026 return false;
1027
1028 base::TimeDelta preroll_attempt_duration =
1029 tick_clock_->NowTicks() - preroll_attempt_start_time_;
1030 return preroll_attempt_duration < kPrerollAttemptTimeout;
1031}
1032
Blink Reformat1c4d759e2017-04-09 16:34:541033bool WebMediaPlayerImpl::DidLoadingProgress() {
acolwellb4034942014-08-28 15:42:431034 DCHECK(main_task_runner_->BelongsToCurrentThread());
dalecurtise7120dc2016-09-03 02:54:351035
1036 // Note: Separate variables used to ensure both methods are called every time.
tguilbert350936ff2017-02-24 05:39:271037 const bool pipeline_progress = pipeline_controller_.DidLoadingProgress();
dalecurtise7120dc2016-09-03 02:54:351038 const bool data_progress = buffered_data_source_host_.DidLoadingProgress();
hubbeb2d3efd2017-05-05 23:26:381039 return pipeline_progress || data_progress;
[email protected]d43ed912009-02-03 04:52:531040}
1041
Blink Reformat1c4d759e2017-04-09 16:34:541042void WebMediaPlayerImpl::Paint(blink::WebCanvas* canvas,
[email protected]dd5c7972014-08-21 15:00:371043 const blink::WebRect& rect,
Kai Ninomiya9e8ae29b2017-09-06 23:45:161044 cc::PaintFlags& flags,
1045 int already_uploaded_id,
1046 VideoFrameUploadMetadata* out_metadata) {
acolwellb4034942014-08-28 15:42:431047 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]dd061e12014-05-06 19:21:221048 TRACE_EVENT0("media", "WebMediaPlayerImpl:paint");
[email protected]4e6be3f2009-05-07 02:24:441049
watkd16bb3e2017-04-25 01:18:311050 // We can't copy from protected frames.
jrummelle616ee92016-10-08 02:15:441051 if (cdm_)
xhwang80739452016-01-13 00:48:001052 return;
1053
mcasasf1236fc22015-05-29 22:38:561054 scoped_refptr<VideoFrame> video_frame = GetCurrentFrameFromCompositor();
[email protected]0fe5d43b2014-01-24 23:32:451055
[email protected]b49beeb2013-03-01 20:04:001056 gfx::Rect gfx_rect(rect);
dongseong.hwang0c4e9d82015-01-08 20:11:131057 Context3D context_3d;
mcasas265bdbf82015-06-12 18:44:071058 if (video_frame.get() && video_frame->HasTextures()) {
CJ DiMeglioc60a5cf2017-09-27 20:08:411059 if (context_provider_) {
1060 context_3d = Context3D(context_provider_->ContextGL(),
1061 context_provider_->GrContext());
1062 }
dongseong.hwang0c4e9d82015-01-08 20:11:131063 if (!context_3d.gl)
danakj53f7ec902016-05-21 01:30:101064 return; // Unable to get/create a shared main thread context.
1065 if (!context_3d.gr_context)
1066 return; // The context has been lost since and can't setup a GrContext.
dongseong.hwang0c4e9d82015-01-08 20:11:131067 }
Kai Ninomiyaef8c9e02017-09-27 04:07:401068 if (out_metadata && video_frame) {
Kai Ninomiya9e8ae29b2017-09-06 23:45:161069 // WebGL last-uploaded-frame-metadata API enabled. https://crbug.com/639174
1070 ComputeFrameUploadMetadata(video_frame.get(), already_uploaded_id,
1071 out_metadata);
1072 if (out_metadata->skipped) {
1073 // Skip uploading this frame.
1074 return;
1075 }
1076 }
zhuoyu.qian4689dde22017-10-16 04:11:481077 video_renderer_.Paint(
Julien Isorce6c83d8de2017-10-12 13:11:291078 video_frame, canvas, gfx::RectF(gfx_rect), flags,
1079 pipeline_metadata_.video_decoder_config.video_rotation(), context_3d);
[email protected]ec9212f2008-12-18 21:40:361080}
[email protected]5df51652009-01-17 00:03:001081
Blink Reformat1c4d759e2017-04-09 16:34:541082bool WebMediaPlayerImpl::HasSingleSecurityOrigin() const {
[email protected]b49beeb2013-03-01 20:04:001083 if (data_source_)
1084 return data_source_->HasSingleOrigin();
[email protected]fcdb7462009-10-21 21:05:111085 return true;
[email protected]38259a7a82009-07-29 21:49:491086}
1087
Blink Reformat1c4d759e2017-04-09 16:34:541088bool WebMediaPlayerImpl::DidPassCORSAccessCheck() const {
[email protected]b49beeb2013-03-01 20:04:001089 if (data_source_)
1090 return data_source_->DidPassCORSAccessCheck();
1091 return false;
[email protected]3fe27112012-06-07 04:00:011092}
1093
Blink Reformat1c4d759e2017-04-09 16:34:541094double WebMediaPlayerImpl::MediaTimeForTimeValue(double timeValue) const {
qinminb4c39782015-08-10 18:43:241095 return base::TimeDelta::FromSecondsD(timeValue).InSecondsF();
[email protected]e06e16d82011-05-26 22:13:331096}
1097
Blink Reformat1c4d759e2017-04-09 16:34:541098unsigned WebMediaPlayerImpl::DecodedFrameCount() const {
acolwellb4034942014-08-28 15:42:431099 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]4c51bc662011-02-16 02:03:161100
avayvodc4bfb0e62017-01-13 01:07:011101 PipelineStatistics stats = GetPipelineStatistics();
[email protected]4c51bc662011-02-16 02:03:161102 return stats.video_frames_decoded;
1103}
1104
Blink Reformat1c4d759e2017-04-09 16:34:541105unsigned WebMediaPlayerImpl::DroppedFrameCount() const {
acolwellb4034942014-08-28 15:42:431106 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]4c51bc662011-02-16 02:03:161107
avayvodc4bfb0e62017-01-13 01:07:011108 PipelineStatistics stats = GetPipelineStatistics();
[email protected]dd061e12014-05-06 19:21:221109 return stats.video_frames_dropped;
[email protected]4c51bc662011-02-16 02:03:161110}
1111
Blink Reformat1c4d759e2017-04-09 16:34:541112size_t WebMediaPlayerImpl::AudioDecodedByteCount() const {
acolwellb4034942014-08-28 15:42:431113 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]4c51bc662011-02-16 02:03:161114
avayvodc4bfb0e62017-01-13 01:07:011115 PipelineStatistics stats = GetPipelineStatistics();
[email protected]4c51bc662011-02-16 02:03:161116 return stats.audio_bytes_decoded;
1117}
1118
Blink Reformat1c4d759e2017-04-09 16:34:541119size_t WebMediaPlayerImpl::VideoDecodedByteCount() const {
acolwellb4034942014-08-28 15:42:431120 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]4c51bc662011-02-16 02:03:161121
avayvodc4bfb0e62017-01-13 01:07:011122 PipelineStatistics stats = GetPipelineStatistics();
[email protected]4c51bc662011-02-16 02:03:161123 return stats.video_bytes_decoded;
1124}
1125
Blink Reformat1c4d759e2017-04-09 16:34:541126bool WebMediaPlayerImpl::CopyVideoTextureToPlatformTexture(
danakj46070b02016-03-28 21:54:111127 gpu::gles2::GLES2Interface* gl,
jiajia.qinc2943162017-05-12 01:34:391128 unsigned int target,
zmo57d577a2015-10-30 18:28:591129 unsigned int texture,
kbr0986e622017-04-13 02:34:581130 unsigned internal_format,
1131 unsigned format,
1132 unsigned type,
jiajia.qinc2943162017-05-12 01:34:391133 int level,
zmo57d577a2015-10-30 18:28:591134 bool premultiply_alpha,
Kai Ninomiya9e8ae29b2017-09-06 23:45:161135 bool flip_y,
1136 int already_uploaded_id,
1137 VideoFrameUploadMetadata* out_metadata) {
xhwang213e50c2016-10-10 23:56:311138 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]bfc05f22013-10-19 17:55:161139 TRACE_EVENT0("media", "WebMediaPlayerImpl:copyVideoTextureToPlatformTexture");
1140
watkd16bb3e2017-04-25 01:18:311141 // We can't copy from protected frames.
xhwang213e50c2016-10-10 23:56:311142 if (cdm_)
1143 return false;
[email protected]dd061e12014-05-06 19:21:221144
xhwang213e50c2016-10-10 23:56:311145 scoped_refptr<VideoFrame> video_frame = GetCurrentFrameFromCompositor();
jbauman581d041c2016-07-21 01:01:031146 if (!video_frame.get() || !video_frame->HasTextures()) {
[email protected]e56f88c72013-06-25 22:31:291147 return false;
dongseong.hwang0c4e9d82015-01-08 20:11:131148 }
Kai Ninomiya9e8ae29b2017-09-06 23:45:161149 if (out_metadata) {
1150 // WebGL last-uploaded-frame-metadata API is enabled.
1151 // https://crbug.com/639174
1152 ComputeFrameUploadMetadata(video_frame.get(), already_uploaded_id,
1153 out_metadata);
1154 if (out_metadata->skipped) {
1155 // Skip uploading this frame.
1156 return true;
1157 }
1158 }
[email protected]df41e252014-02-03 23:39:501159
jbauman581d041c2016-07-21 01:01:031160 Context3D context_3d;
CJ DiMeglioc60a5cf2017-09-27 20:08:411161 if (context_provider_) {
1162 context_3d = Context3D(context_provider_->ContextGL(),
1163 context_provider_->GrContext());
1164 }
zhuoyu.qian4689dde22017-10-16 04:11:481165 return video_renderer_.CopyVideoFrameTexturesToGLTexture(
jiajia.qinc2943162017-05-12 01:34:391166 context_3d, gl, video_frame.get(), target, texture, internal_format,
1167 format, type, level, premultiply_alpha, flip_y);
[email protected]6523b242013-03-13 11:10:071168}
1169
Matt Wolenetz95af6362018-01-04 20:23:421170// static
Kai Ninomiya9e8ae29b2017-09-06 23:45:161171void WebMediaPlayerImpl::ComputeFrameUploadMetadata(
1172 VideoFrame* frame,
1173 int already_uploaded_id,
1174 VideoFrameUploadMetadata* out_metadata) {
1175 DCHECK(out_metadata);
Kai Ninomiyaef8c9e02017-09-27 04:07:401176 DCHECK(frame);
Kai Ninomiya9e8ae29b2017-09-06 23:45:161177 out_metadata->frame_id = frame->unique_id();
1178 out_metadata->visible_rect = frame->visible_rect();
1179 out_metadata->timestamp = frame->timestamp();
1180 bool skip_possible = already_uploaded_id != -1;
1181 bool same_frame_id = frame->unique_id() == already_uploaded_id;
1182 out_metadata->skipped = skip_possible && same_frame_id;
1183}
1184
Blink Reformat1c4d759e2017-04-09 16:34:541185void WebMediaPlayerImpl::SetContentDecryptionModule(
[email protected]9ebc3b03f2014-08-13 04:01:231186 blink::WebContentDecryptionModule* cdm,
1187 blink::WebContentDecryptionModuleResult result) {
xhwang51139732017-02-24 19:36:081188 DVLOG(1) << __func__ << ": cdm = " << cdm;
acolwellb4034942014-08-28 15:42:431189 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]9ebc3b03f2014-08-13 04:01:231190
jrummell06f27072015-06-08 18:12:381191 // Once the CDM is set it can't be cleared as there may be frames being
1192 // decrypted on other threads. So fail this request.
1193 // http://crbug.com/462365#c7.
xhwang97de4202014-11-25 08:44:011194 if (!cdm) {
Blink Reformat1c4d759e2017-04-09 16:34:541195 result.CompleteWithError(
1196 blink::kWebContentDecryptionModuleExceptionInvalidStateError, 0,
xhwang79b193042016-12-13 18:52:431197 "The existing ContentDecryptionModule object cannot be removed at this "
1198 "time.");
xhwang97de4202014-11-25 08:44:011199 return;
1200 }
1201
jrummell89e61d82015-07-23 20:03:341202 // Create a local copy of |result| to avoid problems with the callback
1203 // getting passed to the media thread and causing |result| to be destructed
jrummell4acbec912016-02-27 02:45:031204 // on the wrong thread in some failure conditions. Blink should prevent
1205 // multiple simultaneous calls.
1206 DCHECK(!set_cdm_result_);
jrummell89e61d82015-07-23 20:03:341207 set_cdm_result_.reset(new blink::WebContentDecryptionModuleResult(result));
1208
dalecurtis04bdb582016-08-17 22:15:231209 // Recreate the watch time reporter if necessary.
1210 const bool was_encrypted = is_encrypted_;
1211 is_encrypted_ = true;
1212 if (!was_encrypted && watch_time_reporter_)
1213 CreateWatchTimeReporter();
1214
Chris Cunninghamd9df58e2017-08-29 00:04:231215 // For now MediaCapabilities only handles clear content.
1216 video_decode_stats_reporter_.reset();
1217
jrummelle616ee92016-10-08 02:15:441218 SetCdm(cdm);
xhwang97de4202014-11-25 08:44:011219}
1220
xhwange8c4181a2014-12-06 08:10:011221void WebMediaPlayerImpl::OnEncryptedMediaInitData(
jrummellcf78967c2015-04-03 05:03:581222 EmeInitDataType init_data_type,
Avi Drissman97785ea2015-12-19 01:11:311223 const std::vector<uint8_t>& init_data) {
jrummellcf78967c2015-04-03 05:03:581224 DCHECK(init_data_type != EmeInitDataType::UNKNOWN);
xhwangbab66f52014-12-02 23:49:501225
Xiaohan Wangf63505d2017-10-21 08:00:531226 RecordEncryptedEvent(true);
xhwangbab66f52014-12-02 23:49:501227
dalecurtis04bdb582016-08-17 22:15:231228 // Recreate the watch time reporter if necessary.
1229 const bool was_encrypted = is_encrypted_;
1230 is_encrypted_ = true;
1231 if (!was_encrypted && watch_time_reporter_)
1232 CreateWatchTimeReporter();
1233
Chris Cunninghamd9df58e2017-08-29 00:04:231234 // For now MediaCapabilities only handles clear content.
1235 video_decode_stats_reporter_.reset();
1236
Blink Reformat1c4d759e2017-04-09 16:34:541237 encrypted_client_->Encrypted(
davidbenb50f00c2015-12-01 00:01:501238 ConvertToWebInitDataType(init_data_type), init_data.data(),
srirama.m26f864d02015-07-14 05:21:461239 base::saturated_cast<unsigned int>(init_data.size()));
xhwangbab66f52014-12-02 23:49:501240}
1241
servolk81e01e02016-03-05 03:29:151242void WebMediaPlayerImpl::OnFFmpegMediaTracksUpdated(
dcheng3076abbf2016-04-22 20:42:391243 std::unique_ptr<MediaTracks> tracks) {
servolk81e01e02016-03-05 03:29:151244 // For MSE/chunk_demuxer case the media track updates are handled by
1245 // WebSourceBufferImpl.
1246 DCHECK(demuxer_.get());
1247 DCHECK(!chunk_demuxer_);
servolkef1e5ef2016-03-25 04:55:261248
servolk16e8bdf82017-04-11 17:00:391249 // Report the media track information to blink. Only the first audio track and
1250 // the first video track are enabled by default to match blink logic.
1251 bool is_first_audio_track = true;
1252 bool is_first_video_track = true;
servolkef1e5ef2016-03-25 04:55:261253 for (const auto& track : tracks->tracks()) {
1254 if (track->type() == MediaTrack::Audio) {
Blink Reformat1c4d759e2017-04-09 16:34:541255 client_->AddAudioTrack(blink::WebString::FromUTF8(track->id()),
1256 blink::WebMediaPlayerClient::kAudioTrackKindMain,
1257 blink::WebString::FromUTF8(track->label()),
1258 blink::WebString::FromUTF8(track->language()),
servolk16e8bdf82017-04-11 17:00:391259 is_first_audio_track);
1260 is_first_audio_track = false;
servolkef1e5ef2016-03-25 04:55:261261 } else if (track->type() == MediaTrack::Video) {
Blink Reformat1c4d759e2017-04-09 16:34:541262 client_->AddVideoTrack(blink::WebString::FromUTF8(track->id()),
1263 blink::WebMediaPlayerClient::kVideoTrackKindMain,
1264 blink::WebString::FromUTF8(track->label()),
1265 blink::WebString::FromUTF8(track->language()),
servolk16e8bdf82017-04-11 17:00:391266 is_first_video_track);
1267 is_first_video_track = false;
servolkef1e5ef2016-03-25 04:55:261268 } else {
1269 // Text tracks are not supported through this code path yet.
1270 NOTREACHED();
1271 }
1272 }
servolk81e01e02016-03-05 03:29:151273}
1274
jrummelle616ee92016-10-08 02:15:441275void WebMediaPlayerImpl::SetCdm(blink::WebContentDecryptionModule* cdm) {
1276 DCHECK(main_task_runner_->BelongsToCurrentThread());
1277 DCHECK(cdm);
xhwang79b193042016-12-13 18:52:431278 scoped_refptr<ContentDecryptionModule> cdm_reference =
jrummelle616ee92016-10-08 02:15:441279 ToWebContentDecryptionModuleImpl(cdm)->GetCdm();
1280 if (!cdm_reference) {
1281 NOTREACHED();
1282 OnCdmAttached(false);
xhwang80739452016-01-13 00:48:001283 return;
1284 }
1285
jrummelle616ee92016-10-08 02:15:441286 CdmContext* cdm_context = cdm_reference->GetCdmContext();
1287 if (!cdm_context) {
1288 OnCdmAttached(false);
1289 return;
1290 }
1291
xjzd3fe45a2016-10-12 18:26:371292 if (observer_)
1293 observer_->OnSetCdm(cdm_context);
1294
jrummelle616ee92016-10-08 02:15:441295 // Keep the reference to the CDM, as it shouldn't be destroyed until
1296 // after the pipeline is done with the |cdm_context|.
1297 pending_cdm_ = std::move(cdm_reference);
tguilbert350936ff2017-02-24 05:39:271298 pipeline_controller_.SetCdm(
1299 cdm_context, base::Bind(&WebMediaPlayerImpl::OnCdmAttached, AsWeakPtr()));
xhwang97de4202014-11-25 08:44:011300}
1301
jrummell89e61d82015-07-23 20:03:341302void WebMediaPlayerImpl::OnCdmAttached(bool success) {
xhwang51139732017-02-24 19:36:081303 DVLOG(1) << __func__ << ": success = " << success;
jrummelle616ee92016-10-08 02:15:441304 DCHECK(main_task_runner_->BelongsToCurrentThread());
1305 DCHECK(pending_cdm_);
1306
1307 // If the CDM is set from the constructor there is no promise
1308 // (|set_cdm_result_|) to fulfill.
xhwang97de4202014-11-25 08:44:011309 if (success) {
xhwang29c5ad202017-04-14 07:02:191310 media_log_->SetBooleanProperty("has_cdm", true);
1311
jrummelle616ee92016-10-08 02:15:441312 // This will release the previously attached CDM (if any).
1313 cdm_ = std::move(pending_cdm_);
1314 if (set_cdm_result_) {
Blink Reformat1c4d759e2017-04-09 16:34:541315 set_cdm_result_->Complete();
jrummelle616ee92016-10-08 02:15:441316 set_cdm_result_.reset();
1317 }
1318
xhwang97de4202014-11-25 08:44:011319 return;
1320 }
1321
jrummelle616ee92016-10-08 02:15:441322 pending_cdm_ = nullptr;
1323 if (set_cdm_result_) {
Blink Reformat1c4d759e2017-04-09 16:34:541324 set_cdm_result_->CompleteWithError(
1325 blink::kWebContentDecryptionModuleExceptionNotSupportedError, 0,
xhwang79b193042016-12-13 18:52:431326 "Unable to set ContentDecryptionModule object");
jrummelle616ee92016-10-08 02:15:441327 set_cdm_result_.reset();
1328 }
[email protected]9ebc3b03f2014-08-13 04:01:231329}
1330
sandersd1c0bba02016-03-04 23:14:081331void WebMediaPlayerImpl::OnPipelineSeeked(bool time_updated) {
John Chen5b164a02017-11-01 00:36:091332 TRACE_EVENT2("media", "WebMediaPlayerImpl::OnPipelineSeeked", "target",
1333 seek_time_.InSecondsF(), "id", media_log_->id());
[email protected]5d11eff2011-09-15 00:06:061334 seeking_ = false;
wolenetz1b2ae7d2015-06-10 00:44:211335 seek_time_ = base::TimeDelta();
avayvod2135a642017-01-13 00:17:141336
hubbe5a2dec022016-03-17 01:14:231337 if (paused_) {
1338#if defined(OS_ANDROID) // WMPI_CAST
Blink Reformat1c4d759e2017-04-09 16:34:541339 if (IsRemote()) {
Dale Curtis051fdf62017-08-05 00:21:131340 paused_time_ = cast_impl_.currentTime();
hubbe5a2dec022016-03-17 01:14:231341 } else {
tguilbert350936ff2017-02-24 05:39:271342 paused_time_ = pipeline_controller_.GetMediaTime();
hubbe5a2dec022016-03-17 01:14:231343 }
1344#else
tguilbert350936ff2017-02-24 05:39:271345 paused_time_ = pipeline_controller_.GetMediaTime();
hubbe5a2dec022016-03-17 01:14:231346#endif
dalecurtis04bdb582016-08-17 22:15:231347 } else {
1348 DCHECK(watch_time_reporter_);
1349 watch_time_reporter_->OnPlaying();
hubbe5a2dec022016-03-17 01:14:231350 }
sandersd1c0bba02016-03-04 23:14:081351 if (time_updated)
1352 should_notify_time_changed_ = true;
dalecurtisaf34d8712016-09-20 04:32:261353
dalecurtis4f6d14d2017-02-22 17:42:221354 // Reset underflow duration upon seek; this prevents looping videos and user
1355 // actions from artificially inflating the duration.
1356 underflow_timer_.reset();
avayvod56e1f3942017-01-21 02:06:311357
1358 // Background video optimizations are delayed when shown/hidden if pipeline
1359 // is seeking.
1360 UpdateBackgroundVideoOptimizationState();
[email protected]8931c41a2009-07-07 17:31:491361}
1362
sandersd1c0bba02016-03-04 23:14:081363void WebMediaPlayerImpl::OnPipelineSuspended() {
hubbed5f36882016-01-15 22:40:371364#if defined(OS_ANDROID)
avayvod82729272017-05-29 21:58:391365 if (IsRemote() && !IsNewRemotePlaybackPipelineEnabled()) {
hubbed5f36882016-01-15 22:40:371366 scoped_refptr<VideoFrame> frame = cast_impl_.GetCastingBanner();
sandersd50a635e2016-04-04 22:50:091367 if (frame)
dalecurtise9c89e92016-05-20 19:38:001368 compositor_->PaintSingleFrame(frame);
hubbed5f36882016-01-15 22:40:371369 }
1370#endif
1371
sandersd2f5bb6152017-03-29 22:57:531372 // Tell the data source we have enough data so that it may release the
1373 // connection.
1374 if (data_source_)
1375 data_source_->OnBufferingHaveEnough(true);
dalecurtis37fe5862016-03-15 19:29:091376
sandersd50a635e2016-04-04 22:50:091377 ReportMemoryUsage();
1378
sandersd1c0bba02016-03-04 23:14:081379 if (pending_suspend_resume_cycle_) {
watkdee516f2016-02-18 02:22:191380 pending_suspend_resume_cycle_ = false;
sandersd50a635e2016-04-04 22:50:091381 UpdatePlayState();
dalecurtis0431cbf2016-03-12 01:19:431382 }
sandersd1c0bba02016-03-04 23:14:081383}
1384
avayvod2135a642017-01-13 00:17:141385void WebMediaPlayerImpl::OnBeforePipelineResume() {
1386 // Enable video track if we disabled it in the background - this way the new
1387 // renderer will attach its callbacks to the video stream properly.
1388 // TODO(avayvod): Remove this when disabling and enabling video tracks in
1389 // non-playing state works correctly. See https://crbug.com/678374.
1390 EnableVideoTrackIfNeeded();
1391 is_pipeline_resuming_ = true;
1392}
1393
1394void WebMediaPlayerImpl::OnPipelineResumed() {
1395 is_pipeline_resuming_ = false;
1396
avayvod56e1f3942017-01-21 02:06:311397 UpdateBackgroundVideoOptimizationState();
avayvod2135a642017-01-13 00:17:141398}
1399
alokp967c902452016-05-06 05:21:371400void WebMediaPlayerImpl::OnDemuxerOpened() {
1401 DCHECK(main_task_runner_->BelongsToCurrentThread());
dalecurtis9cddc0b2017-04-19 21:23:381402 client_->MediaSourceOpened(new WebMediaSourceImpl(chunk_demuxer_));
alokp967c902452016-05-06 05:21:371403}
1404
servolkf94b4602017-01-31 16:44:271405void WebMediaPlayerImpl::OnMemoryPressure(
1406 base::MemoryPressureListener::MemoryPressureLevel memory_pressure_level) {
1407 DVLOG(2) << __func__ << " memory_pressure_level=" << memory_pressure_level;
1408 DCHECK(main_task_runner_->BelongsToCurrentThread());
1409 DCHECK(base::FeatureList::IsEnabled(kMemoryPressureBasedSourceBufferGC));
1410 DCHECK(chunk_demuxer_);
1411
1412 // The new value of |memory_pressure_level| will take effect on the next
1413 // garbage collection. Typically this means the next SourceBuffer append()
1414 // operation, since per MSE spec, the garbage collection must only occur
1415 // during SourceBuffer append(). But if memory pressure is critical it might
1416 // be better to perform GC immediately rather than wait for the next append
1417 // and potentially get killed due to out-of-memory.
1418 // So if this experiment is enabled and pressure level is critical, we'll pass
1419 // down force_instant_gc==true, which will force immediate GC on
1420 // SourceBufferStreams.
1421 bool force_instant_gc =
1422 (enable_instant_source_buffer_gc_ &&
1423 memory_pressure_level ==
1424 base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL);
1425
Matt Wolenetz95af6362018-01-04 20:23:421426 // base::Unretained is safe, since |chunk_demuxer_| is actually owned by
1427 // |this| via this->demuxer_. Note the destruction of |chunk_demuxer_| is done
1428 // from ~WMPI by first hopping to |media_task_runner_| to prevent race with
1429 // this task.
servolkf94b4602017-01-31 16:44:271430 media_task_runner_->PostTask(
1431 FROM_HERE, base::Bind(&ChunkDemuxer::OnMemoryPressure,
1432 base::Unretained(chunk_demuxer_),
Blink Reformat1c4d759e2017-04-09 16:34:541433 base::TimeDelta::FromSecondsD(CurrentTime()),
servolkf94b4602017-01-31 16:44:271434 memory_pressure_level, force_instant_gc));
1435}
1436
alokp967c902452016-05-06 05:21:371437void WebMediaPlayerImpl::OnError(PipelineStatus status) {
pkastingf5279482016-07-27 02:18:201438 DVLOG(1) << __func__;
alokp967c902452016-05-06 05:21:371439 DCHECK(main_task_runner_->BelongsToCurrentThread());
1440 DCHECK_NE(status, PIPELINE_OK);
1441
1442 if (suppress_destruction_errors_)
1443 return;
1444
Thomas Guilbert6b6be3d2017-08-18 03:17:271445#if defined(OS_ANDROID)
1446 if (status == PipelineStatus::DEMUXER_ERROR_DETECTED_HLS) {
1447 renderer_factory_selector_->SetUseMediaPlayer(true);
1448
1449 pipeline_controller_.Stop();
Dale Curtis8a6281322017-08-31 00:35:531450 SetMemoryReportingState(false);
Thomas Guilbert6b6be3d2017-08-18 03:17:271451
1452 main_task_runner_->PostTask(
1453 FROM_HERE, base::Bind(&WebMediaPlayerImpl::StartPipeline, AsWeakPtr()));
1454 return;
1455 }
1456#endif
1457
dalecurtis9cddc0b2017-04-19 21:23:381458 ReportPipelineError(load_type_, status, media_log_.get());
alokp967c902452016-05-06 05:21:371459 media_log_->AddEvent(media_log_->CreatePipelineErrorEvent(status));
Dale Curtis74612b72017-12-14 20:56:191460 media_metrics_provider_->OnError(status);
Dale Curtisccfd0cca2017-08-31 01:27:561461 if (watch_time_reporter_)
1462 watch_time_reporter_->OnError(status);
alokp967c902452016-05-06 05:21:371463
Blink Reformat1c4d759e2017-04-09 16:34:541464 if (ready_state_ == WebMediaPlayer::kReadyStateHaveNothing) {
alokp967c902452016-05-06 05:21:371465 // Any error that occurs before reaching ReadyStateHaveMetadata should
1466 // be considered a format error.
Blink Reformat1c4d759e2017-04-09 16:34:541467 SetNetworkState(WebMediaPlayer::kNetworkStateFormatError);
alokp967c902452016-05-06 05:21:371468 } else {
1469 SetNetworkState(PipelineErrorToNetworkState(status));
1470 }
1471
Thomas Guilbert2e591392017-08-12 00:56:381472 // PipelineController::Stop() is idempotent.
1473 pipeline_controller_.Stop();
1474
alokp967c902452016-05-06 05:21:371475 UpdatePlayState();
1476}
1477
1478void WebMediaPlayerImpl::OnEnded() {
John Chen5b164a02017-11-01 00:36:091479 TRACE_EVENT2("media", "WebMediaPlayerImpl::OnEnded", "duration", Duration(),
1480 "id", media_log_->id());
pkastingf5279482016-07-27 02:18:201481 DVLOG(1) << __func__;
acolwellb4034942014-08-28 15:42:431482 DCHECK(main_task_runner_->BelongsToCurrentThread());
scherkusd2c745b2014-09-04 05:03:401483
sandersd1c0bba02016-03-04 23:14:081484 // Ignore state changes until we've completed all outstanding operations.
1485 if (!pipeline_controller_.IsStable())
scherkusd2c745b2014-09-04 05:03:401486 return;
1487
1488 ended_ = true;
Blink Reformat1c4d759e2017-04-09 16:34:541489 client_->TimeChanged();
sandersd50a635e2016-04-04 22:50:091490
dalecurtis1af3c1a2017-04-11 00:53:491491 // Clear any new frame processed callbacks on end; otherwise we'll end up
1492 // logging a time long after playback ends.
1493 frame_time_report_cb_.Cancel();
1494
sandersd50a635e2016-04-04 22:50:091495 // We don't actually want this to run until |client_| calls seek() or pause(),
1496 // but that should have already happened in timeChanged() and so this is
1497 // expected to be a no-op.
1498 UpdatePlayState();
[email protected]576537842009-08-12 23:52:051499}
1500
alokp967c902452016-05-06 05:21:371501void WebMediaPlayerImpl::OnMetadata(PipelineMetadata metadata) {
pkastingf5279482016-07-27 02:18:201502 DVLOG(1) << __func__;
acolwellb4034942014-08-28 15:42:431503 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]a8e2cb82012-08-17 00:02:391504
[email protected]b8877772014-03-26 20:17:151505 pipeline_metadata_ = metadata;
[email protected]739847c02014-01-16 00:12:251506
Blink Reformat1c4d759e2017-04-09 16:34:541507 SetReadyState(WebMediaPlayer::kReadyStateHaveMetadata);
Julien Isorce6c83d8de2017-10-12 13:11:291508 UMA_HISTOGRAM_ENUMERATION("Media.VideoRotation",
1509 metadata.video_decoder_config.video_rotation(),
acolwell9e0840d2014-09-06 19:01:321510 VIDEO_ROTATION_MAX + 1);
[email protected]21c3f7502013-03-23 03:29:511511
Blink Reformat1c4d759e2017-04-09 16:34:541512 if (HasVideo()) {
liberato2fd111be2017-01-04 00:25:061513 if (overlay_enabled_) {
1514 // SurfaceView doesn't support rotated video, so transition back if
[email protected]c8d574722017-08-30 20:53:431515 // the video is now rotated. If |always_enable_overlays_|, we keep the
liberato2fd111be2017-01-04 00:25:061516 // overlay anyway so that the state machine keeps working.
[email protected]c8d574722017-08-30 20:53:431517 // TODO(liberato): verify if compositor feedback catches this. If so,
1518 // then we don't need this check.
1519 if (!always_enable_overlays_ && !DoesOverlaySupportMetadata())
liberato2fd111be2017-01-04 00:25:061520 DisableOverlay();
1521 else if (surface_manager_)
1522 surface_manager_->NaturalSizeChanged(pipeline_metadata_.natural_size);
1523 }
watkf835a792016-06-24 23:24:401524
lethalantidote7f6009d2017-07-07 21:47:391525 if (!surface_layer_for_video_enabled_) {
1526 DCHECK(!video_weblayer_);
1527 video_weblayer_.reset(new cc_blink::WebLayerImpl(cc::VideoLayer::Create(
Julien Isorce6c83d8de2017-10-12 13:11:291528 compositor_.get(),
1529 pipeline_metadata_.video_decoder_config.video_rotation())));
lethalantidote7f6009d2017-07-07 21:47:391530 video_weblayer_->layer()->SetContentsOpaque(opaque_);
1531 video_weblayer_->SetContentsOpaqueIsFixed(true);
1532 client_->SetWebLayer(video_weblayer_.get());
lethalantidote7f6009d2017-07-07 21:47:391533 }
[email protected]a8e2cb82012-08-17 00:02:391534 }
dalecurtis8e4dc682016-03-15 02:30:301535
xjzd3fe45a2016-10-12 18:26:371536 if (observer_)
xjz15b483f2017-01-12 00:21:361537 observer_->OnMetadataChanged(pipeline_metadata_);
xjzd3fe45a2016-10-12 18:26:371538
dalecurtis04bdb582016-08-17 22:15:231539 CreateWatchTimeReporter();
Chris Cunninghamd9df58e2017-08-29 00:04:231540 CreateVideoDecodeStatsReporter();
sandersd50a635e2016-04-04 22:50:091541 UpdatePlayState();
[email protected]a8e2cb82012-08-17 00:02:391542}
1543
Chris Cunninghamd9df58e2017-08-29 00:04:231544void WebMediaPlayerImpl::CreateVideoDecodeStatsReporter() {
1545 // TODO(chcunningham): destroy reporter if we initially have video but the
1546 // track gets disabled. Currently not possible in default desktop Chrome.
1547 if (!HasVideo())
1548 return;
1549
1550 // Stats reporter requires a valid config. We may not have one for HLS cases
1551 // where URL demuxer doesn't know details of the stream.
1552 if (!pipeline_metadata_.video_decoder_config.IsValidConfig())
1553 return;
1554
1555 // For now MediaCapabilities only handles clear content.
1556 // TODO(chcunningham): Report encrypted stats.
1557 if (is_encrypted_)
1558 return;
1559
Dale Curtis7e8a510d2017-12-14 19:19:481560 mojom::VideoDecodeStatsRecorderPtr recorder;
1561 media_metrics_provider_->AcquireVideoDecodeStatsRecorder(
Dale Curtis7e8a510d2017-12-14 19:19:481562 mojo::MakeRequest(&recorder));
Chris Cunninghamc7c6a6d2017-11-23 14:06:451563
Chris Cunninghamd9df58e2017-08-29 00:04:231564 // Create capabilities reporter and synchronize its initial state.
1565 video_decode_stats_reporter_.reset(new VideoDecodeStatsReporter(
Chris Cunninghamc7c6a6d2017-11-23 14:06:451566 std::move(recorder),
Chris Cunninghamd9df58e2017-08-29 00:04:231567 base::Bind(&WebMediaPlayerImpl::GetPipelineStatistics,
1568 base::Unretained(this)),
Hajime Hoshi6c3194b52017-12-15 03:02:111569 pipeline_metadata_.video_decoder_config,
1570 frame_->GetTaskRunner(blink::TaskType::kUnthrottled)));
Chris Cunninghamd9df58e2017-08-29 00:04:231571
1572 if (delegate_->IsFrameHidden())
1573 video_decode_stats_reporter_->OnHidden();
1574 else
1575 video_decode_stats_reporter_->OnShown();
1576
1577 if (paused_)
1578 video_decode_stats_reporter_->OnPaused();
1579 else
1580 video_decode_stats_reporter_->OnPlaying();
1581}
1582
hubbeb2d3efd2017-05-05 23:26:381583void WebMediaPlayerImpl::OnProgress() {
Chris Watkins1ffabc5f2017-05-10 20:52:091584 DVLOG(4) << __func__;
hubbeb2d3efd2017-05-05 23:26:381585 if (highest_ready_state_ < ReadyState::kReadyStateHaveFutureData) {
1586 // Reset the preroll attempt clock.
1587 preroll_attempt_pending_ = true;
1588 preroll_attempt_start_time_ = base::TimeTicks();
1589
1590 // Clear any 'stale' flag and give the pipeline a chance to resume. If we
1591 // are already resumed, this will cause |preroll_attempt_start_time_| to
1592 // be set.
1593 delegate_->ClearStaleFlag(delegate_id_);
1594 UpdatePlayState();
1595 } else if (ready_state_ == ReadyState::kReadyStateHaveFutureData &&
1596 CanPlayThrough()) {
1597 SetReadyState(WebMediaPlayer::kReadyStateHaveEnoughData);
1598 }
1599}
1600
1601bool WebMediaPlayerImpl::CanPlayThrough() {
1602 if (!base::FeatureList::IsEnabled(kSpecCompliantCanPlayThrough))
1603 return true;
1604 if (chunk_demuxer_)
1605 return true;
1606 if (data_source_ && data_source_->assume_fully_buffered())
1607 return true;
1608 // If we're not currently downloading, we have as much buffer as
1609 // we're ever going to get, which means we say we can play through.
1610 if (network_state_ == WebMediaPlayer::kNetworkStateIdle)
1611 return true;
1612 return buffered_data_source_host_.CanPlayThrough(
1613 base::TimeDelta::FromSecondsD(CurrentTime()),
1614 base::TimeDelta::FromSecondsD(Duration()),
1615 playback_rate_ == 0.0 ? 1.0 : playback_rate_);
1616}
1617
alokp967c902452016-05-06 05:21:371618void WebMediaPlayerImpl::OnBufferingStateChange(BufferingState state) {
pkastingf5279482016-07-27 02:18:201619 DVLOG(1) << __func__ << "(" << state << ")";
alokp967c902452016-05-06 05:21:371620 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]b8877772014-03-26 20:17:151621
sandersd1c0bba02016-03-04 23:14:081622 // Ignore buffering state changes until we've completed all outstanding
1623 // operations.
1624 if (!pipeline_controller_.IsStable())
[email protected]ba7d5f92014-06-24 05:37:401625 return;
[email protected]b8877772014-03-26 20:17:151626
dalecurtis869bf2f2017-01-10 18:01:101627 media_log_->AddEvent(media_log_->CreateBufferingStateChangedEvent(
1628 "pipeline_buffering_state", state));
1629
chcunninghameb270c92016-07-15 01:00:451630 if (state == BUFFERING_HAVE_ENOUGH) {
John Chen5b164a02017-11-01 00:36:091631 TRACE_EVENT1("media", "WebMediaPlayerImpl::BufferingHaveEnough", "id",
1632 media_log_->id());
hubbeb2d3efd2017-05-05 23:26:381633 SetReadyState(CanPlayThrough() ? WebMediaPlayer::kReadyStateHaveEnoughData
1634 : WebMediaPlayer::kReadyStateHaveFutureData);
[email protected]ba7d5f92014-06-24 05:37:401635
chcunninghameb270c92016-07-15 01:00:451636 // Let the DataSource know we have enough data. It may use this information
1637 // to release unused network connections.
1638 if (data_source_)
1639 data_source_->OnBufferingHaveEnough(false);
dalecurtis849cf4b22015-03-27 18:35:451640
chcunninghameb270c92016-07-15 01:00:451641 // Blink expects a timeChanged() in response to a seek().
sandersd35d2c3f2017-01-14 02:04:421642 if (should_notify_time_changed_) {
1643 should_notify_time_changed_ = false;
Blink Reformat1c4d759e2017-04-09 16:34:541644 client_->TimeChanged();
sandersd35d2c3f2017-01-14 02:04:421645 }
dalecurtis0f0097a2015-12-01 17:40:471646
chcunninghameb270c92016-07-15 01:00:451647 // Once we have enough, start reporting the total memory usage. We'll also
1648 // report once playback starts.
1649 ReportMemoryUsage();
dalecurtis9d638a12016-08-30 06:20:551650
dalecurtis4f6d14d2017-02-22 17:42:221651 // Report the amount of time it took to leave the underflow state.
1652 if (underflow_timer_) {
1653 RecordUnderflowDuration(underflow_timer_->Elapsed());
dalecurtis9d638a12016-08-30 06:20:551654 underflow_timer_.reset();
1655 }
chcunninghameb270c92016-07-15 01:00:451656 } else {
1657 // Buffering has underflowed.
1658 DCHECK_EQ(state, BUFFERING_HAVE_NOTHING);
dalecurtisacd77d62016-09-09 23:23:141659
dalecurtisd06eabc2017-02-24 23:43:291660 // Report the number of times we've entered the underflow state. Ensure we
1661 // only report the value when transitioning from HAVE_ENOUGH to
1662 // HAVE_NOTHING.
Dale Curtis6995b862017-05-31 22:20:081663 if (ready_state_ == WebMediaPlayer::kReadyStateHaveEnoughData &&
1664 !seeking_) {
dalecurtisacd77d62016-09-09 23:23:141665 underflow_timer_.reset(new base::ElapsedTimer());
Dale Curtis6995b862017-05-31 22:20:081666 watch_time_reporter_->OnUnderflow();
1667 }
dalecurtisacd77d62016-09-09 23:23:141668
chcunninghameb270c92016-07-15 01:00:451669 // It shouldn't be possible to underflow if we've not advanced past
1670 // HAVE_CURRENT_DATA.
Blink Reformat1c4d759e2017-04-09 16:34:541671 DCHECK_GT(highest_ready_state_, WebMediaPlayer::kReadyStateHaveCurrentData);
1672 SetReadyState(WebMediaPlayer::kReadyStateHaveCurrentData);
chcunninghameb270c92016-07-15 01:00:451673 }
sandersd50a635e2016-04-04 22:50:091674
1675 UpdatePlayState();
[email protected]b8877772014-03-26 20:17:151676}
1677
alokp967c902452016-05-06 05:21:371678void WebMediaPlayerImpl::OnDurationChange() {
acolwellb4034942014-08-28 15:42:431679 DCHECK(main_task_runner_->BelongsToCurrentThread());
alokp967c902452016-05-06 05:21:371680
1681 // TODO(sandersd): We should call delegate_->DidPlay() with the new duration,
1682 // especially if it changed from <5s to >5s.
Blink Reformat1c4d759e2017-04-09 16:34:541683 if (ready_state_ == WebMediaPlayer::kReadyStateHaveNothing)
alokp967c902452016-05-06 05:21:371684 return;
1685
Blink Reformat1c4d759e2017-04-09 16:34:541686 client_->DurationChanged();
[email protected]81bb3322011-07-21 15:55:501687}
1688
alokp967c902452016-05-06 05:21:371689void WebMediaPlayerImpl::OnAddTextTrack(const TextTrackConfig& config,
1690 const AddTextTrackDoneCB& done_cb) {
acolwellb4034942014-08-28 15:42:431691 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]71537722013-05-23 06:47:531692
[email protected]8a561062013-11-22 01:19:311693 const WebInbandTextTrackImpl::Kind web_kind =
1694 static_cast<WebInbandTextTrackImpl::Kind>(config.kind());
Blink Reformat1c4d759e2017-04-09 16:34:541695 const blink::WebString web_label = blink::WebString::FromUTF8(config.label());
[email protected]8a561062013-11-22 01:19:311696 const blink::WebString web_language =
Blink Reformat1c4d759e2017-04-09 16:34:541697 blink::WebString::FromUTF8(config.language());
1698 const blink::WebString web_id = blink::WebString::FromUTF8(config.id());
[email protected]71537722013-05-23 06:47:531699
dcheng3076abbf2016-04-22 20:42:391700 std::unique_ptr<WebInbandTextTrackImpl> web_inband_text_track(
henriks9cce5fa2014-12-12 09:35:301701 new WebInbandTextTrackImpl(web_kind, web_label, web_language, web_id));
[email protected]8a561062013-11-22 01:19:311702
dcheng3076abbf2016-04-22 20:42:391703 std::unique_ptr<media::TextTrack> text_track(new TextTrackImpl(
dcheng652f5ff2015-12-27 08:54:001704 main_task_runner_, client_, std::move(web_inband_text_track)));
[email protected]8a561062013-11-22 01:19:311705
dcheng652f5ff2015-12-27 08:54:001706 done_cb.Run(std::move(text_track));
[email protected]71537722013-05-23 06:47:531707}
1708
alokp967c902452016-05-06 05:21:371709void WebMediaPlayerImpl::OnWaitingForDecryptionKey() {
1710 DCHECK(main_task_runner_->BelongsToCurrentThread());
1711
Blink Reformat1c4d759e2017-04-09 16:34:541712 encrypted_client_->DidBlockPlaybackWaitingForKey();
alokp967c902452016-05-06 05:21:371713 // TODO(jrummell): didResumePlaybackBlockedForKey() should only be called
1714 // when a key has been successfully added (e.g. OnSessionKeysChange() with
1715 // |has_additional_usable_key| = true). http://crbug.com/461903
Blink Reformat1c4d759e2017-04-09 16:34:541716 encrypted_client_->DidResumePlaybackBlockedForKey();
alokp967c902452016-05-06 05:21:371717}
1718
alokp5d86e9b2016-05-17 20:20:411719void WebMediaPlayerImpl::OnVideoNaturalSizeChange(const gfx::Size& size) {
1720 DCHECK(main_task_runner_->BelongsToCurrentThread());
Blink Reformat1c4d759e2017-04-09 16:34:541721 DCHECK_NE(ready_state_, WebMediaPlayer::kReadyStateHaveNothing);
alokp5d86e9b2016-05-17 20:20:411722
Chris Cunningham038548b2017-07-10 22:36:301723 TRACE_EVENT0("media", "WebMediaPlayerImpl::OnVideoNaturalSizeChange");
xhwang60802652017-04-19 07:29:581724
xjz15b483f2017-01-12 00:21:361725 // The input |size| is from the decoded video frame, which is the original
1726 // natural size and need to be rotated accordingly.
Julien Isorce6c83d8de2017-10-12 13:11:291727 gfx::Size rotated_size = GetRotatedVideoSize(
1728 pipeline_metadata_.video_decoder_config.video_rotation(), size);
sandersd2c478422016-08-02 01:19:251729
xhwang60802652017-04-19 07:29:581730 RecordVideoNaturalSize(rotated_size);
1731
1732 gfx::Size old_size = pipeline_metadata_.natural_size;
1733 if (rotated_size == old_size)
alokp5d86e9b2016-05-17 20:20:411734 return;
1735
xjz516ef6d2017-01-07 00:23:061736 pipeline_metadata_.natural_size = rotated_size;
Dale Curtisccfd0cca2017-08-31 01:27:561737 CreateWatchTimeReporter();
dalecurtis25405562017-04-14 23:35:111738
Chris Cunninghamd9df58e2017-08-29 00:04:231739 if (video_decode_stats_reporter_)
1740 video_decode_stats_reporter_->OnNaturalSizeChanged(rotated_size);
1741
liberato2ff93ad2017-05-17 07:28:241742 if (overlay_enabled_ && surface_manager_ &&
1743 overlay_mode_ == OverlayMode::kUseContentVideoView) {
xhwang60802652017-04-19 07:29:581744 surface_manager_->NaturalSizeChanged(rotated_size);
liberato2ff93ad2017-05-17 07:28:241745 }
xhwang60802652017-04-19 07:29:581746
Blink Reformat1c4d759e2017-04-09 16:34:541747 client_->SizeChanged();
xjz516ef6d2017-01-07 00:23:061748
xjz15b483f2017-01-12 00:21:361749 if (observer_)
1750 observer_->OnMetadataChanged(pipeline_metadata_);
peconn257951522017-06-09 18:24:591751
1752 delegate_->DidPlayerSizeChange(delegate_id_, NaturalSize());
alokp5d86e9b2016-05-17 20:20:411753}
1754
1755void WebMediaPlayerImpl::OnVideoOpacityChange(bool opaque) {
1756 DCHECK(main_task_runner_->BelongsToCurrentThread());
Blink Reformat1c4d759e2017-04-09 16:34:541757 DCHECK_NE(ready_state_, WebMediaPlayer::kReadyStateHaveNothing);
alokp5d86e9b2016-05-17 20:20:411758
1759 opaque_ = opaque;
1760 // Modify content opaqueness of cc::Layer directly so that
1761 // SetContentsOpaqueIsFixed is ignored.
lethalantidote7f6009d2017-07-07 21:47:391762 if (!surface_layer_for_video_enabled_) {
1763 if (video_weblayer_)
1764 video_weblayer_->layer()->SetContentsOpaque(opaque_);
1765 } else if (bridge_->GetWebLayer()) {
1766 bridge_->GetWebLayer()->CcLayer()->SetContentsOpaque(opaque_);
1767 }
alokp5d86e9b2016-05-17 20:20:411768}
1769
Chris Cunningham038548b2017-07-10 22:36:301770void WebMediaPlayerImpl::OnAudioConfigChange(const AudioDecoderConfig& config) {
1771 DCHECK(main_task_runner_->BelongsToCurrentThread());
1772 DCHECK_NE(ready_state_, WebMediaPlayer::kReadyStateHaveNothing);
1773
Dale Curtisccfd0cca2017-08-31 01:27:561774 const bool codec_change =
1775 pipeline_metadata_.audio_decoder_config.codec() != config.codec();
Chris Cunningham038548b2017-07-10 22:36:301776 pipeline_metadata_.audio_decoder_config = config;
1777
1778 if (observer_)
1779 observer_->OnMetadataChanged(pipeline_metadata_);
Dale Curtisccfd0cca2017-08-31 01:27:561780
1781 if (codec_change)
1782 CreateWatchTimeReporter();
Chris Cunningham038548b2017-07-10 22:36:301783}
1784
1785void WebMediaPlayerImpl::OnVideoConfigChange(const VideoDecoderConfig& config) {
1786 DCHECK(main_task_runner_->BelongsToCurrentThread());
1787 DCHECK_NE(ready_state_, WebMediaPlayer::kReadyStateHaveNothing);
1788
Dale Curtisccfd0cca2017-08-31 01:27:561789 const bool codec_change =
1790 pipeline_metadata_.video_decoder_config.codec() != config.codec();
1791
Chris Cunningham038548b2017-07-10 22:36:301792 // TODO(chcunningham): Observe changes to video codec profile to signal
1793 // beginning of a new Media Capabilities playback report.
1794 pipeline_metadata_.video_decoder_config = config;
1795
1796 if (observer_)
1797 observer_->OnMetadataChanged(pipeline_metadata_);
Chris Cunninghamd9df58e2017-08-29 00:04:231798
1799 if (video_decode_stats_reporter_)
1800 video_decode_stats_reporter_->OnVideoConfigChanged(config);
Dale Curtisccfd0cca2017-08-31 01:27:561801
1802 if (codec_change)
1803 CreateWatchTimeReporter();
Chris Cunningham038548b2017-07-10 22:36:301804}
1805
avayvodeecec52c2017-02-14 01:25:091806void WebMediaPlayerImpl::OnVideoAverageKeyframeDistanceUpdate() {
1807 UpdateBackgroundVideoOptimizationState();
1808}
1809
sandersd35d2c3f2017-01-14 02:04:421810void WebMediaPlayerImpl::OnFrameHidden() {
sandersd1e49fb62015-12-12 01:18:061811 DCHECK(main_task_runner_->BelongsToCurrentThread());
avayvod39c102402016-11-23 21:43:131812
avayvod65fad272017-02-24 01:00:481813 // Backgrounding a video requires a user gesture to resume playback.
1814 if (IsHidden())
1815 video_locked_when_paused_when_hidden_ = true;
1816
dalecurtis04bdb582016-08-17 22:15:231817 if (watch_time_reporter_)
1818 watch_time_reporter_->OnHidden();
avayvod48a8be52016-08-04 19:52:501819
Chris Cunninghamd9df58e2017-08-29 00:04:231820 if (video_decode_stats_reporter_)
1821 video_decode_stats_reporter_->OnHidden();
1822
avayvod65fad272017-02-24 01:00:481823 UpdateBackgroundVideoOptimizationState();
sandersd50a635e2016-04-04 22:50:091824 UpdatePlayState();
dalecurtis8b8505e72016-06-10 21:59:171825
1826 // Schedule suspended playing media to be paused if the user doesn't come back
1827 // to it within some timeout period to avoid any autoplay surprises.
1828 ScheduleIdlePauseTimer();
sandersd1e49fb62015-12-12 01:18:061829}
1830
sandersd35d2c3f2017-01-14 02:04:421831void WebMediaPlayerImpl::OnFrameClosed() {
sandersd1e49fb62015-12-12 01:18:061832 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]28347e72017-06-27 17:30:111833
sandersd35d2c3f2017-01-14 02:04:421834 UpdatePlayState();
1835}
1836
1837void WebMediaPlayerImpl::OnFrameShown() {
1838 DCHECK(main_task_runner_->BelongsToCurrentThread());
1839 background_pause_timer_.Stop();
1840
avayvod65fad272017-02-24 01:00:481841 // Foreground videos don't require user gesture to continue playback.
1842 video_locked_when_paused_when_hidden_ = false;
1843
dalecurtis04bdb582016-08-17 22:15:231844 if (watch_time_reporter_)
1845 watch_time_reporter_->OnShown();
1846
Chris Cunninghamd9df58e2017-08-29 00:04:231847 if (video_decode_stats_reporter_)
1848 video_decode_stats_reporter_->OnShown();
1849
avayvodcc273dd2017-01-19 19:35:121850 // Only track the time to the first frame if playing or about to play because
1851 // of being shown and only for videos we would optimize background playback
1852 // for.
1853 if ((!paused_ && IsBackgroundOptimizationCandidate()) ||
1854 paused_when_hidden_) {
dalecurtis1af3c1a2017-04-11 00:53:491855 frame_time_report_cb_.Reset(
1856 base::Bind(&WebMediaPlayerImpl::ReportTimeFromForegroundToFirstFrame,
1857 AsWeakPtr(), base::TimeTicks::Now()));
CJ DiMeglio2302d202017-08-31 08:38:041858 vfc_task_runner_->PostTask(
avayvodcc273dd2017-01-19 19:35:121859 FROM_HERE,
1860 base::Bind(&VideoFrameCompositor::SetOnNewProcessedFrameCallback,
CJ DiMeglio2302d202017-08-31 08:38:041861 base::Unretained(compositor_.get()),
dalecurtis1af3c1a2017-04-11 00:53:491862 BindToCurrentLoop(frame_time_report_cb_.callback())));
avayvodcc273dd2017-01-19 19:35:121863 }
avayvodac607d652017-01-06 03:16:431864
Dale Curtisdcbb81a2017-08-18 01:06:121865 UpdateBackgroundVideoOptimizationState();
avayvod65fad272017-02-24 01:00:481866
avayvod2135a642017-01-13 00:17:141867 if (paused_when_hidden_) {
1868 paused_when_hidden_ = false;
1869 OnPlay(); // Calls UpdatePlayState() so return afterwards.
1870 return;
1871 }
1872
sandersd50a635e2016-04-04 22:50:091873 UpdatePlayState();
sandersd1e49fb62015-12-12 01:18:061874}
1875
sandersd35d2c3f2017-01-14 02:04:421876void WebMediaPlayerImpl::OnIdleTimeout() {
dalecurtis0431cbf2016-03-12 01:19:431877 DCHECK(main_task_runner_->BelongsToCurrentThread());
1878
sandersd35d2c3f2017-01-14 02:04:421879 // If we are attempting preroll, clear the stale flag.
1880 if (IsPrerollAttemptNeeded()) {
tguilbert1bb1c782017-01-23 21:15:111881 delegate_->ClearStaleFlag(delegate_id_);
sandersd35d2c3f2017-01-14 02:04:421882 return;
watkd026f792016-11-05 00:28:511883 }
sandersd50a635e2016-04-04 22:50:091884
sandersd35d2c3f2017-01-14 02:04:421885 UpdatePlayState();
dalecurtis0431cbf2016-03-12 01:19:431886}
1887
dalecurtisbb3eaac2016-01-27 21:10:251888void WebMediaPlayerImpl::OnPlay() {
Blink Reformat1c4d759e2017-04-09 16:34:541889 Play();
1890 client_->PlaybackStateChanged();
dalecurtisbb3eaac2016-01-27 21:10:251891}
1892
1893void WebMediaPlayerImpl::OnPause() {
Blink Reformat1c4d759e2017-04-09 16:34:541894 Pause();
1895 client_->PlaybackStateChanged();
dalecurtisbb3eaac2016-01-27 21:10:251896}
1897
Alec Douglas316cce42017-10-31 13:28:081898void WebMediaPlayerImpl::OnSeekForward(double seconds) {
1899 DCHECK_GE(seconds, 0) << "Attempted to seek by a negative number of seconds";
1900 client_->RequestSeek(CurrentTime() + seconds);
1901}
1902
1903void WebMediaPlayerImpl::OnSeekBackward(double seconds) {
1904 DCHECK_GE(seconds, 0) << "Attempted to seek by a negative number of seconds";
1905 client_->RequestSeek(CurrentTime() - seconds);
1906}
1907
dalecurtisbb3eaac2016-01-27 21:10:251908void WebMediaPlayerImpl::OnVolumeMultiplierUpdate(double multiplier) {
1909 volume_multiplier_ = multiplier;
Blink Reformat1c4d759e2017-04-09 16:34:541910 SetVolume(volume_);
dalecurtisbb3eaac2016-01-27 21:10:251911}
1912
zqzhang8ac49002017-03-16 21:51:351913void WebMediaPlayerImpl::OnBecamePersistentVideo(bool value) {
Blink Reformat1c4d759e2017-04-09 16:34:541914 client_->OnBecamePersistentVideo(value);
zqzhang8ac49002017-03-16 21:51:351915}
1916
watkdee516f2016-02-18 02:22:191917void WebMediaPlayerImpl::ScheduleRestart() {
sandersd50a635e2016-04-04 22:50:091918 // TODO(watk): All restart logic should be moved into PipelineController.
tguilbert350936ff2017-02-24 05:39:271919 if (pipeline_controller_.IsPipelineRunning() &&
1920 !pipeline_controller_.IsPipelineSuspended()) {
watkdee516f2016-02-18 02:22:191921 pending_suspend_resume_cycle_ = true;
sandersd50a635e2016-04-04 22:50:091922 UpdatePlayState();
watkdee516f2016-02-18 02:22:191923 }
1924}
1925
Blink Reformat1c4d759e2017-04-09 16:34:541926void WebMediaPlayerImpl::RequestRemotePlaybackDisabled(bool disabled) {
miu77f914c2016-11-19 23:56:181927 if (observer_)
1928 observer_->OnRemotePlaybackDisabled(disabled);
1929}
1930
hubbed5f36882016-01-15 22:40:371931#if defined(OS_ANDROID) // WMPI_CAST
Blink Reformat1c4d759e2017-04-09 16:34:541932bool WebMediaPlayerImpl::IsRemote() const {
hubbed5f36882016-01-15 22:40:371933 return cast_impl_.isRemote();
1934}
1935
1936void WebMediaPlayerImpl::SetMediaPlayerManager(
1937 RendererMediaPlayerManagerInterface* media_player_manager) {
1938 cast_impl_.SetMediaPlayerManager(media_player_manager);
1939}
1940
Blink Reformat1c4d759e2017-04-09 16:34:541941void WebMediaPlayerImpl::RequestRemotePlayback() {
hubbed5f36882016-01-15 22:40:371942 cast_impl_.requestRemotePlayback();
1943}
1944
Blink Reformat1c4d759e2017-04-09 16:34:541945void WebMediaPlayerImpl::RequestRemotePlaybackControl() {
hubbed5f36882016-01-15 22:40:371946 cast_impl_.requestRemotePlaybackControl();
1947}
1948
Blink Reformat1c4d759e2017-04-09 16:34:541949void WebMediaPlayerImpl::RequestRemotePlaybackStop() {
avayvod8d8c53b2016-11-04 16:10:301950 cast_impl_.requestRemotePlaybackStop();
1951}
1952
hubbed5f36882016-01-15 22:40:371953void WebMediaPlayerImpl::OnRemotePlaybackEnded() {
pkastingf5279482016-07-27 02:18:201954 DVLOG(1) << __func__;
hubbed5f36882016-01-15 22:40:371955 DCHECK(main_task_runner_->BelongsToCurrentThread());
1956
1957 ended_ = true;
Blink Reformat1c4d759e2017-04-09 16:34:541958 client_->TimeChanged();
hubbed5f36882016-01-15 22:40:371959}
1960
1961void WebMediaPlayerImpl::OnDisconnectedFromRemoteDevice(double t) {
sandersd1c0bba02016-03-04 23:14:081962 DoSeek(base::TimeDelta::FromSecondsD(t), false);
hubbed5f36882016-01-15 22:40:371963
Chris Cunninghamd9df58e2017-08-29 00:04:231964 // Capabilities reporting can resume now that playback is local.
1965 CreateVideoDecodeStatsReporter();
1966
Anton Vayvodfad2f3ea2017-07-19 21:45:271967 // |client_| might destroy us in methods below.
1968 UpdatePlayState();
1969
hubbed5f36882016-01-15 22:40:371970 // We already told the delegate we're paused when remoting started.
Blink Reformat1c4d759e2017-04-09 16:34:541971 client_->PlaybackStateChanged();
1972 client_->DisconnectedFromRemoteDevice();
hubbed5f36882016-01-15 22:40:371973}
1974
1975void WebMediaPlayerImpl::SuspendForRemote() {
Chris Cunninghamd9df58e2017-08-29 00:04:231976 // Capabilities reporting should only be performed for local playbacks.
1977 video_decode_stats_reporter_.reset();
1978
avayvod82729272017-05-29 21:58:391979 if (pipeline_controller_.IsPipelineSuspended() &&
1980 !IsNewRemotePlaybackPipelineEnabled()) {
hubbed5f36882016-01-15 22:40:371981 scoped_refptr<VideoFrame> frame = cast_impl_.GetCastingBanner();
sandersd50a635e2016-04-04 22:50:091982 if (frame)
dalecurtise9c89e92016-05-20 19:38:001983 compositor_->PaintSingleFrame(frame);
hubbed5f36882016-01-15 22:40:371984 }
sandersd50a635e2016-04-04 22:50:091985
1986 UpdatePlayState();
hubbed5f36882016-01-15 22:40:371987}
1988
1989gfx::Size WebMediaPlayerImpl::GetCanvasSize() const {
lethalantidote7f6009d2017-07-07 21:47:391990 if (!surface_layer_for_video_enabled_) {
1991 if (!video_weblayer_)
1992 return pipeline_metadata_.natural_size;
1993
1994 return video_weblayer_->Bounds();
1995 }
1996 if (!bridge_->GetWebLayer())
hubbed5f36882016-01-15 22:40:371997 return pipeline_metadata_.natural_size;
1998
lethalantidote7f6009d2017-07-07 21:47:391999 return bridge_->GetWebLayer()->Bounds();
hubbed5f36882016-01-15 22:40:372000}
2001
2002void WebMediaPlayerImpl::SetDeviceScaleFactor(float scale_factor) {
2003 cast_impl_.SetDeviceScaleFactor(scale_factor);
2004}
Dan Sanderscd8981c2017-08-31 22:37:022005#endif // defined(OS_ANDROID) // WMPI_CAST
hubbee4027f92016-05-19 05:18:132006
Blink Reformat1c4d759e2017-04-09 16:34:542007void WebMediaPlayerImpl::SetPoster(const blink::WebURL& poster) {
Dan Sanderscd8981c2017-08-31 22:37:022008 has_poster_ = !poster.IsEmpty();
2009#if defined(OS_ANDROID) // WMPI_CAST
xjzc102fd82017-01-04 20:13:532010 cast_impl_.setPoster(poster);
xjz2504c4da2017-04-18 18:50:142011#endif // defined(OS_ANDROID) // WMPI_CAST
Dan Sanderscd8981c2017-08-31 22:37:022012}
xjzc102fd82017-01-04 20:13:532013
[email protected]fee8a902014-06-03 13:43:362014void WebMediaPlayerImpl::DataSourceInitialized(bool success) {
pkastingf5279482016-07-27 02:18:202015 DVLOG(1) << __func__;
acolwellb4034942014-08-28 15:42:432016 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]a9415292012-01-19 19:55:202017
Anton Vayvod09fa66e2017-07-20 23:02:122018 if (observer_ && IsNewRemotePlaybackPipelineEnabled() && data_source_)
2019 observer_->OnDataSourceInitialized(data_source_->GetUrlAfterRedirects());
2020
[email protected]d250190da3b2012-07-23 22:57:302021 if (!success) {
Blink Reformat1c4d759e2017-04-09 16:34:542022 SetNetworkState(WebMediaPlayer::kNetworkStateFormatError);
Dale Curtis74612b72017-12-14 20:56:192023 media_metrics_provider_->OnError(PIPELINE_ERROR_NETWORK);
sandersd50a635e2016-04-04 22:50:092024
2025 // Not really necessary, since the pipeline was never started, but it at
2026 // least this makes sure that the error handling code is in sync.
2027 UpdatePlayState();
2028
[email protected]a9415292012-01-19 19:55:202029 return;
2030 }
2031
hubbee2cc88c092017-07-14 23:10:412032 // No point in preloading data as we'll probably just throw it away anyways.
2033 if (IsStreaming() && preload_ > MultibufferDataSource::METADATA) {
2034 data_source_->SetPreload(MultibufferDataSource::METADATA);
2035 }
2036
[email protected]ef8394c2013-08-21 20:26:302037 StartPipeline();
[email protected]a9415292012-01-19 19:55:202038}
2039
[email protected]122f40252012-06-12 05:01:562040void WebMediaPlayerImpl::NotifyDownloading(bool is_downloading) {
hubbeb2d3efd2017-05-05 23:26:382041 DVLOG(1) << __func__ << "(" << is_downloading << ")";
Blink Reformat1c4d759e2017-04-09 16:34:542042 if (!is_downloading && network_state_ == WebMediaPlayer::kNetworkStateLoading)
2043 SetNetworkState(WebMediaPlayer::kNetworkStateIdle);
2044 else if (is_downloading &&
2045 network_state_ == WebMediaPlayer::kNetworkStateIdle)
2046 SetNetworkState(WebMediaPlayer::kNetworkStateLoading);
hubbeb2d3efd2017-05-05 23:26:382047 if (ready_state_ == ReadyState::kReadyStateHaveFutureData && !is_downloading)
2048 SetReadyState(WebMediaPlayer::kReadyStateHaveEnoughData);
[email protected]122f40252012-06-12 05:01:562049}
2050
watkf835a792016-06-24 23:24:402051void WebMediaPlayerImpl::OnSurfaceCreated(int surface_id) {
liberato2ff93ad2017-05-17 07:28:242052 DCHECK(overlay_mode_ == OverlayMode::kUseContentVideoView);
tsunghungee562e92016-07-20 18:03:312053 overlay_surface_id_ = surface_id;
liberato2ff93ad2017-05-17 07:28:242054 MaybeSendOverlayInfoToDecoder();
watkf835a792016-06-24 23:24:402055}
2056
liberato2ff93ad2017-05-17 07:28:242057void WebMediaPlayerImpl::OnOverlayRoutingToken(
2058 const base::UnguessableToken& token) {
2059 DCHECK(overlay_mode_ == OverlayMode::kUseAndroidOverlay);
liberatofe8f9692017-06-08 19:17:362060 // TODO(liberato): |token| should already be a RoutingToken.
2061 overlay_routing_token_is_pending_ = false;
2062 overlay_routing_token_ = OverlayInfo::RoutingToken(token);
liberato2ff93ad2017-05-17 07:28:242063 MaybeSendOverlayInfoToDecoder();
2064}
2065
2066void WebMediaPlayerImpl::OnOverlayInfoRequested(
dalecurtis4b632fce22016-11-10 00:52:172067 bool decoder_requires_restart_for_overlay,
liberato2ff93ad2017-05-17 07:28:242068 const ProvideOverlayInfoCB& provide_overlay_info_cb) {
watkdee516f2016-02-18 02:22:192069 DCHECK(main_task_runner_->BelongsToCurrentThread());
2070 DCHECK(surface_manager_);
2071
Chris Watkins557f84d2017-09-16 02:31:462072 // If we get a non-null cb, a decoder is initializing and requires overlay
2073 // info. If we get a null cb, a previously initialized decoder is
2074 // unregistering for overlay info updates.
liberato2ff93ad2017-05-17 07:28:242075 if (provide_overlay_info_cb.is_null()) {
tsunghungee562e92016-07-20 18:03:312076 decoder_requires_restart_for_overlay_ = false;
liberato2ff93ad2017-05-17 07:28:242077 provide_overlay_info_cb_.Reset();
watkdee516f2016-02-18 02:22:192078 return;
2079 }
2080
dalecurtis4b632fce22016-11-10 00:52:172081 // If |decoder_requires_restart_for_overlay| is true, we must restart the
2082 // pipeline for fullscreen transitions. The decoder is unable to switch
2083 // surfaces otherwise. If false, we simply need to tell the decoder about the
2084 // new surface and it will handle things seamlessly.
Chris Watkins557f84d2017-09-16 02:31:462085 // For encrypted video we pretend that the decoder doesn't require a restart
2086 // because it needs an overlay all the time anyway. We'll switch into
2087 // |always_enable_overlays_| mode below.
2088 decoder_requires_restart_for_overlay_ =
2089 (overlay_mode_ == OverlayMode::kUseAndroidOverlay && is_encrypted_)
2090 ? false
2091 : decoder_requires_restart_for_overlay;
liberato2ff93ad2017-05-17 07:28:242092 provide_overlay_info_cb_ = provide_overlay_info_cb;
dalecurtis4b632fce22016-11-10 00:52:172093
Chris Watkins557f84d2017-09-16 02:31:462094 // If the decoder doesn't require restarts for surface transitions, and we're
2095 // using AndroidOverlay mode, we can always enable the overlay and the decoder
2096 // can choose whether or not to use it. Otherwise, we'll restart the decoder
2097 // and enable the overlay on fullscreen transitions.
[email protected]77568482017-06-21 21:16:522098 if (overlay_mode_ == OverlayMode::kUseAndroidOverlay &&
Chris Watkins557f84d2017-09-16 02:31:462099 !decoder_requires_restart_for_overlay_) {
[email protected]c8d574722017-08-30 20:53:432100 always_enable_overlays_ = true;
[email protected]77568482017-06-21 21:16:522101 if (!overlay_enabled_)
2102 EnableOverlay();
2103 }
2104
Chris Watkins557f84d2017-09-16 02:31:462105 // Send the overlay info if we already have it. If not, it will be sent later.
liberato2ff93ad2017-05-17 07:28:242106 MaybeSendOverlayInfoToDecoder();
2107}
2108
2109void WebMediaPlayerImpl::MaybeSendOverlayInfoToDecoder() {
2110 // If the decoder didn't request overlay info, then don't send it.
2111 if (!provide_overlay_info_cb_)
dalecurtis4b632fce22016-11-10 00:52:172112 return;
2113
liberato2ff93ad2017-05-17 07:28:242114 // We should send the overlay info as long as we know it. This includes the
2115 // case where |!overlay_enabled_|, since we want to tell the decoder to avoid
2116 // using overlays. Assuming that the decoder has requested info, the only
2117 // case in which we don't want to send something is if we've requested the
2118 // info but not received it yet. Then, we should wait until we do.
liberatofe8f9692017-06-08 19:17:362119 //
2120 // Initialization requires this; AVDA should start with enough info to make an
2121 // overlay, so that (pre-M) the initial codec is created with the right output
2122 // surface; it can't switch later.
liberato2ff93ad2017-05-17 07:28:242123 if (overlay_mode_ == OverlayMode::kUseContentVideoView) {
2124 if (!overlay_surface_id_.has_value())
2125 return;
liberatofe8f9692017-06-08 19:17:362126
2127 overlay_info_.surface_id = *overlay_surface_id_;
liberato2ff93ad2017-05-17 07:28:242128 } else if (overlay_mode_ == OverlayMode::kUseAndroidOverlay) {
liberatofe8f9692017-06-08 19:17:362129 if (overlay_routing_token_is_pending_)
liberato2ff93ad2017-05-17 07:28:242130 return;
liberatofe8f9692017-06-08 19:17:362131
2132 overlay_info_.routing_token = overlay_routing_token_;
liberato2ff93ad2017-05-17 07:28:242133 }
2134
liberato2ff93ad2017-05-17 07:28:242135 // If restart is required, the callback is one-shot only.
2136 if (decoder_requires_restart_for_overlay_) {
liberatofe8f9692017-06-08 19:17:362137 base::ResetAndReturn(&provide_overlay_info_cb_).Run(overlay_info_);
liberato2ff93ad2017-05-17 07:28:242138 } else {
liberatofe8f9692017-06-08 19:17:362139 provide_overlay_info_cb_.Run(overlay_info_);
liberato2ff93ad2017-05-17 07:28:242140 }
watkdee516f2016-02-18 02:22:192141}
2142
dcheng3076abbf2016-04-22 20:42:392143std::unique_ptr<Renderer> WebMediaPlayerImpl::CreateRenderer() {
dcheng37b415b92017-01-27 20:17:432144 DCHECK(main_task_runner_->BelongsToCurrentThread());
2145
[email protected]c8d574722017-08-30 20:53:432146 // Make sure that overlays are enabled if they're always allowed.
2147 if (always_enable_overlays_)
tsunghungee562e92016-07-20 18:03:312148 EnableOverlay();
2149
liberato2ff93ad2017-05-17 07:28:242150 RequestOverlayInfoCB request_overlay_info_cb;
watkdee516f2016-02-18 02:22:192151#if defined(OS_ANDROID)
liberato2ff93ad2017-05-17 07:28:242152 request_overlay_info_cb = BindToCurrentLoop(
2153 base::Bind(&WebMediaPlayerImpl::OnOverlayInfoRequested, AsWeakPtr()));
watkdee516f2016-02-18 02:22:192154#endif
tguilbert70d2a00a2017-04-25 00:30:442155 return renderer_factory_selector_->GetCurrentFactory()->CreateRenderer(
sandersd1e49fb62015-12-12 01:18:062156 media_task_runner_, worker_task_runner_, audio_source_provider_.get(),
CJ DiMeglio2302d202017-08-31 08:38:042157 compositor_.get(), request_overlay_info_cb, client_->TargetColorSpace());
sandersd1e49fb62015-12-12 01:18:062158}
2159
[email protected]ef8394c2013-08-21 20:26:302160void WebMediaPlayerImpl::StartPipeline() {
acolwellb4034942014-08-28 15:42:432161 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]ddbc6ff2013-04-19 15:28:332162
xhwange8c4181a2014-12-06 08:10:012163 Demuxer::EncryptedMediaInitDataCB encrypted_media_init_data_cb =
dcheng37b415b92017-01-27 20:17:432164 BindToCurrentLoop(base::Bind(
2165 &WebMediaPlayerImpl::OnEncryptedMediaInitData, AsWeakPtr()));
[email protected]2b57e2e2014-05-09 11:07:252166
tguilbert75e2bf62017-04-26 20:13:122167 if (renderer_factory_selector_->GetCurrentFactory()
2168 ->GetRequiredMediaResourceType() == MediaResource::Type::URL) {
2169 if (data_source_)
2170 loaded_url_ = data_source_->GetUrlAfterRedirects();
2171
2172 // MediaPlayerRendererClient factory is the only factory that a
2173 // MediaResource::Type::URL for the moment. This might no longer be true
2174 // when we remove WebMediaPlayerCast.
2175 //
2176 // TODO(tguilbert/avayvod): Update this flag when removing |cast_impl_|.
2177 using_media_player_renderer_ = true;
2178
Chris Cunninghamd9df58e2017-08-29 00:04:232179 // MediaPlayerRenderer does not provide pipeline stats, so nuke capabilities
2180 // reporter.
2181 video_decode_stats_reporter_.reset();
2182
Mike Westb85da8ed2017-08-10 14:16:462183 demuxer_.reset(new MediaUrlDemuxer(media_task_runner_, loaded_url_,
2184 frame_->GetDocument().SiteForCookies()));
tguilbert25a4d112016-10-13 21:56:512185 pipeline_controller_.Start(demuxer_.get(), this, false, false);
2186 return;
2187 }
2188
[email protected]ddbc6ff2013-04-19 15:28:332189 // Figure out which demuxer to use.
Blink Reformat1c4d759e2017-04-09 16:34:542190 if (load_type_ != kLoadTypeMediaSource) {
[email protected]ddbc6ff2013-04-19 15:28:332191 DCHECK(!chunk_demuxer_);
[email protected]f5443ef72013-04-22 04:03:382192 DCHECK(data_source_);
2193
j.isorcef6778e652015-11-16 17:14:252194#if !defined(MEDIA_DISABLE_FFMPEG)
servolk81e01e02016-03-05 03:29:152195 Demuxer::MediaTracksUpdatedCB media_tracks_updated_cb =
dcheng37b415b92017-01-27 20:17:432196 BindToCurrentLoop(base::Bind(
2197 &WebMediaPlayerImpl::OnFFmpegMediaTracksUpdated, AsWeakPtr()));
servolk81e01e02016-03-05 03:29:152198
dalecurtis9cddc0b2017-04-19 21:23:382199 demuxer_.reset(new FFmpegDemuxer(
2200 media_task_runner_, data_source_.get(), encrypted_media_init_data_cb,
2201 media_tracks_updated_cb, media_log_.get()));
j.isorcef6778e652015-11-16 17:14:252202#else
alokp967c902452016-05-06 05:21:372203 OnError(PipelineStatus::DEMUXER_ERROR_COULD_NOT_OPEN);
j.isorcef6778e652015-11-16 17:14:252204 return;
2205#endif
[email protected]ddbc6ff2013-04-19 15:28:332206 } else {
[email protected]f5443ef72013-04-22 04:03:382207 DCHECK(!chunk_demuxer_);
2208 DCHECK(!data_source_);
2209
acolwell9e0840d2014-09-06 19:01:322210 chunk_demuxer_ = new ChunkDemuxer(
dcheng37b415b92017-01-27 20:17:432211 BindToCurrentLoop(
2212 base::Bind(&WebMediaPlayerImpl::OnDemuxerOpened, AsWeakPtr())),
Dan Sanders42311b52017-08-10 23:41:032213 BindToCurrentLoop(
2214 base::Bind(&WebMediaPlayerImpl::OnProgress, AsWeakPtr())),
dalecurtis9cddc0b2017-04-19 21:23:382215 encrypted_media_init_data_cb, media_log_.get());
[email protected]f5443ef72013-04-22 04:03:382216 demuxer_.reset(chunk_demuxer_);
servolkf94b4602017-01-31 16:44:272217
2218 if (base::FeatureList::IsEnabled(kMemoryPressureBasedSourceBufferGC)) {
2219 // base::Unretained is safe because |this| owns memory_pressure_listener_.
2220 memory_pressure_listener_ =
2221 base::MakeUnique<base::MemoryPressureListener>(base::Bind(
2222 &WebMediaPlayerImpl::OnMemoryPressure, base::Unretained(this)));
2223 }
[email protected]ddbc6ff2013-04-19 15:28:332224 }
2225
sandersdb5e21462016-03-09 01:49:072226 // TODO(sandersd): FileSystem objects may also be non-static, but due to our
2227 // caching layer such situations are broken already. http://crbug.com/593159
2228 bool is_static = !chunk_demuxer_;
avayvod102cdb62017-01-07 03:11:092229 bool is_streaming = IsStreaming();
sandersdb8eb5f1d2016-11-19 04:04:022230 UMA_HISTOGRAM_BOOLEAN("Media.IsStreaming", is_streaming);
sandersdb5e21462016-03-09 01:49:072231
[email protected]f5443ef72013-04-22 04:03:382232 // ... and we're ready to go!
sandersd1e49fb62015-12-12 01:18:062233 // TODO(sandersd): On Android, defer Start() if the tab is not visible.
sandersdb8eb5f1d2016-11-19 04:04:022234 seeking_ = true;
alokp967c902452016-05-06 05:21:372235 pipeline_controller_.Start(demuxer_.get(), this, is_streaming, is_static);
[email protected]f5443ef72013-04-22 04:03:382236}
2237
2238void WebMediaPlayerImpl::SetNetworkState(WebMediaPlayer::NetworkState state) {
pkastingf5279482016-07-27 02:18:202239 DVLOG(1) << __func__ << "(" << state << ")";
acolwellb4034942014-08-28 15:42:432240 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]f5443ef72013-04-22 04:03:382241 network_state_ = state;
2242 // Always notify to ensure client has the latest value.
Blink Reformat1c4d759e2017-04-09 16:34:542243 client_->NetworkStateChanged();
[email protected]f5443ef72013-04-22 04:03:382244}
2245
2246void WebMediaPlayerImpl::SetReadyState(WebMediaPlayer::ReadyState state) {
pkastingf5279482016-07-27 02:18:202247 DVLOG(1) << __func__ << "(" << state << ")";
acolwellb4034942014-08-28 15:42:432248 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]f5443ef72013-04-22 04:03:382249
Blink Reformat1c4d759e2017-04-09 16:34:542250 if (state == WebMediaPlayer::kReadyStateHaveEnoughData && data_source_ &&
[email protected]fee8a902014-06-03 13:43:362251 data_source_->assume_fully_buffered() &&
Blink Reformat1c4d759e2017-04-09 16:34:542252 network_state_ == WebMediaPlayer::kNetworkStateLoading)
2253 SetNetworkState(WebMediaPlayer::kNetworkStateLoaded);
[email protected]f5443ef72013-04-22 04:03:382254
2255 ready_state_ = state;
sandersd50a635e2016-04-04 22:50:092256 highest_ready_state_ = std::max(highest_ready_state_, ready_state_);
2257
[email protected]f5443ef72013-04-22 04:03:382258 // Always notify to ensure client has the latest value.
Blink Reformat1c4d759e2017-04-09 16:34:542259 client_->ReadyStateChanged();
[email protected]f5443ef72013-04-22 04:03:382260}
2261
Blink Reformat1c4d759e2017-04-09 16:34:542262blink::WebAudioSourceProvider* WebMediaPlayerImpl::GetAudioSourceProvider() {
[email protected]ff875be52013-06-02 23:47:382263 return audio_source_provider_.get();
[email protected]f5443ef72013-04-22 04:03:382264}
2265
Jiajia Qin82acdc02017-07-31 09:55:142266scoped_refptr<VideoFrame> WebMediaPlayerImpl::GetCurrentFrameFromCompositor()
2267 const {
xhwang213e50c2016-10-10 23:56:312268 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]dd061e12014-05-06 19:21:222269 TRACE_EVENT0("media", "WebMediaPlayerImpl::GetCurrentFrameFromCompositor");
xhwang213e50c2016-10-10 23:56:312270
Thomas Guilbertd85407412017-11-08 05:03:462271 // Can be null.
2272 scoped_refptr<VideoFrame> video_frame =
2273 compositor_->GetCurrentFrameOnAnyThread();
[email protected]dd061e12014-05-06 19:21:222274
Thomas Guilbertd85407412017-11-08 05:03:462275 // base::Unretained is safe here because |compositor_| is destroyed on
2276 // |vfc_task_runner_|. The destruction is queued from |this|' destructor,
2277 // which also runs on |main_task_runner_|, which makes it impossible for
2278 // UpdateCurrentFrameIfStale() to be queued after |compositor_|'s dtor.
CJ DiMeglio2302d202017-08-31 08:38:042279 vfc_task_runner_->PostTask(
Thomas Guilbertd85407412017-11-08 05:03:462280 FROM_HERE, base::Bind(&VideoFrameCompositor::UpdateCurrentFrameIfStale,
2281 base::Unretained(compositor_.get())));
kainino36eeff82017-03-30 00:55:302282
[email protected]dd061e12014-05-06 19:21:222283 return video_frame;
2284}
2285
sandersd50a635e2016-04-04 22:50:092286void WebMediaPlayerImpl::UpdatePlayState() {
xhwang213e50c2016-10-10 23:56:312287 DCHECK(main_task_runner_->BelongsToCurrentThread());
2288
hubbed5f36882016-01-15 22:40:372289#if defined(OS_ANDROID) // WMPI_CAST
Blink Reformat1c4d759e2017-04-09 16:34:542290 bool is_remote = IsRemote();
xjz4e5d4bf32017-02-15 21:26:352291 bool can_auto_suspend = true;
sandersd50a635e2016-04-04 22:50:092292#else
2293 bool is_remote = false;
hubbee2cc88c092017-07-14 23:10:412294 bool can_auto_suspend = !disable_pipeline_auto_suspend_;
2295 // For streaming videos, we only allow suspending at the very beginning of the
2296 // video, and only if we know the length of the video. (If we don't know
2297 // the length, it might be a dynamically generated video, and suspending
2298 // will not work at all.)
2299 if (IsStreaming()) {
2300 bool at_beginning =
2301 ready_state_ == WebMediaPlayer::kReadyStateHaveNothing ||
2302 CurrentTime() == 0.0;
2303 if (!at_beginning || GetPipelineMediaDuration() == kInfiniteDuration)
2304 can_auto_suspend = false;
2305 }
hubbed5f36882016-01-15 22:40:372306#endif
xhwang213e50c2016-10-10 23:56:312307
dalecurtis8b8505e72016-06-10 21:59:172308 bool is_suspended = pipeline_controller_.IsSuspended();
avayvod39c102402016-11-23 21:43:132309 bool is_backgrounded = IsBackgroundedSuspendEnabled() && IsHidden();
sandersdaaff1a652016-11-17 01:47:252310 PlayState state = UpdatePlayState_ComputePlayState(
xjz4e5d4bf32017-02-15 21:26:352311 is_remote, can_auto_suspend, is_suspended, is_backgrounded);
sandersd35d2c3f2017-01-14 02:04:422312 SetDelegateState(state.delegate_state, state.is_idle);
sandersd50a635e2016-04-04 22:50:092313 SetMemoryReportingState(state.is_memory_reporting_enabled);
2314 SetSuspendState(state.is_suspended || pending_suspend_resume_cycle_);
2315}
dalecurtis5bbc487e2016-02-27 04:15:052316
sandersd35d2c3f2017-01-14 02:04:422317void WebMediaPlayerImpl::SetDelegateState(DelegateState new_state,
2318 bool is_idle) {
tguilbert1bb1c782017-01-23 21:15:112319 DCHECK(delegate_);
dalecurtis5bbc487e2016-02-27 04:15:052320
sandersd35d2c3f2017-01-14 02:04:422321 // Prevent duplicate delegate calls.
2322 // TODO(sandersd): Move this deduplication into the delegate itself.
2323 // TODO(sandersd): WebContentsObserverSanityChecker does not allow sending the
2324 // 'playing' IPC more than once in a row, even if the metadata has changed.
2325 // Figure out whether it should.
Blink Reformat1c4d759e2017-04-09 16:34:542326 bool has_audio = HasAudio() && !client_->IsAutoplayingMuted();
sandersd35d2c3f2017-01-14 02:04:422327 if (delegate_state_ == new_state &&
2328 (delegate_state_ != DelegateState::PLAYING ||
2329 delegate_has_audio_ == has_audio)) {
2330 return;
mlamouri910111362016-11-04 11:28:242331 }
sandersd50a635e2016-04-04 22:50:092332 delegate_state_ = new_state;
sandersd35d2c3f2017-01-14 02:04:422333 delegate_has_audio_ = has_audio;
sandersd50a635e2016-04-04 22:50:092334
sandersd35d2c3f2017-01-14 02:04:422335 switch (new_state) {
sandersd50a635e2016-04-04 22:50:092336 case DelegateState::GONE:
2337 delegate_->PlayerGone(delegate_id_);
2338 break;
mlamouri910111362016-11-04 11:28:242339 case DelegateState::PLAYING: {
peconn257951522017-06-09 18:24:592340 if (HasVideo())
2341 delegate_->DidPlayerSizeChange(delegate_id_, NaturalSize());
zqzhang5d8eab72016-08-26 20:34:302342 delegate_->DidPlay(
Blink Reformat1c4d759e2017-04-09 16:34:542343 delegate_id_, HasVideo(), has_audio,
avayvodcc273dd2017-01-19 19:35:122344 media::DurationToMediaContentType(GetPipelineMediaDuration()));
sandersd50a635e2016-04-04 22:50:092345 break;
mlamouri910111362016-11-04 11:28:242346 }
sandersd50a635e2016-04-04 22:50:092347 case DelegateState::PAUSED:
sandersd35d2c3f2017-01-14 02:04:422348 delegate_->DidPause(delegate_id_);
sandersd50a635e2016-04-04 22:50:092349 break;
dalecurtis0f0097a2015-12-01 17:40:472350 }
sandersd35d2c3f2017-01-14 02:04:422351
2352 delegate_->SetIdle(delegate_id_, is_idle);
dalecurtis0f0097a2015-12-01 17:40:472353}
2354
sandersd50a635e2016-04-04 22:50:092355void WebMediaPlayerImpl::SetMemoryReportingState(
2356 bool is_memory_reporting_enabled) {
2357 if (memory_usage_reporting_timer_.IsRunning() ==
2358 is_memory_reporting_enabled) {
hubbed5f36882016-01-15 22:40:372359 return;
sandersd50a635e2016-04-04 22:50:092360 }
sandersd1c0bba02016-03-04 23:14:082361
sandersd50a635e2016-04-04 22:50:092362 if (is_memory_reporting_enabled) {
2363 memory_usage_reporting_timer_.Start(FROM_HERE,
2364 base::TimeDelta::FromSeconds(2), this,
2365 &WebMediaPlayerImpl::ReportMemoryUsage);
2366 } else {
2367 memory_usage_reporting_timer_.Stop();
2368 ReportMemoryUsage();
2369 }
2370}
2371
2372void WebMediaPlayerImpl::SetSuspendState(bool is_suspended) {
xhwang213e50c2016-10-10 23:56:312373 DCHECK(main_task_runner_->BelongsToCurrentThread());
2374
sandersd50a635e2016-04-04 22:50:092375 // Do not change the state after an error has occurred.
2376 // TODO(sandersd): Update PipelineController to remove the need for this.
2377 if (IsNetworkStateError(network_state_))
sandersd1c0bba02016-03-04 23:14:082378 return;
2379
jameswest451a5bb2017-01-27 03:59:392380 if (is_suspended) {
sandersd35d2c3f2017-01-14 02:04:422381 // If we were not resumed for long enough to satisfy the preroll attempt,
2382 // reset the clock.
2383 if (!preroll_attempt_pending_ && IsPrerollAttemptNeeded()) {
2384 preroll_attempt_pending_ = true;
2385 preroll_attempt_start_time_ = base::TimeTicks();
2386 }
sandersd50a635e2016-04-04 22:50:092387 pipeline_controller_.Suspend();
2388 } else {
sandersd35d2c3f2017-01-14 02:04:422389 // When resuming, start the preroll attempt clock.
2390 if (preroll_attempt_pending_) {
2391 preroll_attempt_pending_ = false;
2392 preroll_attempt_start_time_ = tick_clock_->NowTicks();
2393 }
sandersd50a635e2016-04-04 22:50:092394 pipeline_controller_.Resume();
2395 }
2396}
2397
2398WebMediaPlayerImpl::PlayState
2399WebMediaPlayerImpl::UpdatePlayState_ComputePlayState(bool is_remote,
xjz4e5d4bf32017-02-15 21:26:352400 bool can_auto_suspend,
dalecurtis8b8505e72016-06-10 21:59:172401 bool is_suspended,
sandersd50a635e2016-04-04 22:50:092402 bool is_backgrounded) {
2403 PlayState result;
2404
tguilbert1bb1c782017-01-23 21:15:112405 bool must_suspend = delegate_->IsFrameClosed();
2406 bool is_stale = delegate_->IsStale(delegate_id_);
sandersd35d2c3f2017-01-14 02:04:422407
sandersd50a635e2016-04-04 22:50:092408 // This includes both data source (before pipeline startup) and pipeline
2409 // errors.
2410 bool has_error = IsNetworkStateError(network_state_);
2411
dalecurtiscc8baf72016-10-27 01:49:442412 // After HaveFutureData, Blink will call play() if the state is not paused;
2413 // prior to this point |paused_| is not accurate.
sandersd50a635e2016-04-04 22:50:092414 bool have_future_data =
Blink Reformat1c4d759e2017-04-09 16:34:542415 highest_ready_state_ >= WebMediaPlayer::kReadyStateHaveFutureData;
sandersd50a635e2016-04-04 22:50:092416
avayvod65fad272017-02-24 01:00:482417 // Background suspend is only enabled for paused players.
2418 // In the case of players with audio the session should be kept.
2419 bool background_suspended =
xjz4e5d4bf32017-02-15 21:26:352420 can_auto_suspend && is_backgrounded && paused_ && have_future_data;
sandersd50a635e2016-04-04 22:50:092421
dalecurtiscc8baf72016-10-27 01:49:442422 // Idle suspension is allowed prior to have future data since there exist
2423 // mechanisms to exit the idle state when the player is capable of reaching
2424 // the have future data state; see didLoadingProgress().
2425 //
sandersd50a635e2016-04-04 22:50:092426 // TODO(sandersd): Make the delegate suspend idle players immediately when
2427 // hidden.
sandersdaaff1a652016-11-17 01:47:252428 bool idle_suspended =
xjz4e5d4bf32017-02-15 21:26:352429 can_auto_suspend && is_stale && paused_ && !seeking_ && !overlay_enabled_;
dalecurtise7120dc2016-09-03 02:54:352430
2431 // If we're already suspended, see if we can wait for user interaction. Prior
sandersd35d2c3f2017-01-14 02:04:422432 // to HaveFutureData, we require |is_stale| to remain suspended. |is_stale|
dalecurtise7120dc2016-09-03 02:54:352433 // will be cleared when we receive data which may take us to HaveFutureData.
2434 bool can_stay_suspended =
sandersd35d2c3f2017-01-14 02:04:422435 (is_stale || have_future_data) && is_suspended && paused_ && !seeking_;
sandersd50a635e2016-04-04 22:50:092436
2437 // Combined suspend state.
sandersd35d2c3f2017-01-14 02:04:422438 result.is_suspended = is_remote || must_suspend || idle_suspended ||
avayvod65fad272017-02-24 01:00:482439 background_suspended || can_stay_suspended;
sandersd50a635e2016-04-04 22:50:092440
2441 // We do not treat |playback_rate_| == 0 as paused. For the media session,
2442 // being paused implies displaying a play button, which is incorrect in this
2443 // case. For memory usage reporting, we just use the same definition (but we
2444 // don't have to).
2445 //
2446 // Similarly, we don't consider |ended_| to be paused. Blink will immediately
2447 // call pause() or seek(), so |ended_| should not affect the computation.
2448 // Despite that, |ended_| does result in a separate paused state, to simplfy
2449 // the contract for SetDelegateState().
2450 //
avayvod65fad272017-02-24 01:00:482451 // |has_remote_controls| indicates if the player can be controlled outside the
2452 // page (e.g. via the notification controls or by audio focus events). Idle
sandersd50a635e2016-04-04 22:50:092453 // suspension does not destroy the media session, because we expect that the
avayvod5f34b642017-03-23 03:14:042454 // notification controls (and audio focus) remain. With some exceptions for
2455 // background videos, the player only needs to have audio to have controls
2456 // (requires |have_future_data|).
2457 //
2458 // |alive| indicates if the player should be present (not |GONE|) to the
2459 // delegate, either paused or playing. The following must be true for the
2460 // player:
sandersd50a635e2016-04-04 22:50:092461 // - |have_future_data|, since we need to know whether we are paused to
avayvod65fad272017-02-24 01:00:482462 // correctly configure the session and also because the tracks and
avayvod5f34b642017-03-23 03:14:042463 // duration are passed to DidPlay(),
2464 // - |is_remote| is false as remote playback is not handled by the delegate,
2465 // - |has_error| is false as player should have no errors,
2466 // - |background_suspended| is false, otherwise |has_remote_controls| must
2467 // be true.
sandersd50a635e2016-04-04 22:50:092468 //
avayvod65fad272017-02-24 01:00:482469 // TODO(sandersd): If Blink told us the paused state sooner, we could detect
2470 // if the remote controls are available sooner.
2471
2472 // Background videos with audio don't have remote controls if background
2473 // suspend is enabled and resuming background videos is not (original Android
2474 // behavior).
2475 bool backgrounded_video_has_no_remote_controls =
2476 IsBackgroundedSuspendEnabled() && !IsResumeBackgroundVideosEnabled() &&
Blink Reformat1c4d759e2017-04-09 16:34:542477 is_backgrounded && HasVideo();
sandersd50a635e2016-04-04 22:50:092478 bool can_play = !has_error && !is_remote && have_future_data;
avayvod5f34b642017-03-23 03:14:042479 bool has_remote_controls =
Blink Reformat1c4d759e2017-04-09 16:34:542480 HasAudio() && !backgrounded_video_has_no_remote_controls;
avayvod5f34b642017-03-23 03:14:042481 bool alive = can_play && !must_suspend &&
2482 (!background_suspended || has_remote_controls);
2483 if (!alive) {
sandersd50a635e2016-04-04 22:50:092484 result.delegate_state = DelegateState::GONE;
tguilbert1bb1c782017-01-23 21:15:112485 result.is_idle = delegate_->IsIdle(delegate_id_);
avayvod65fad272017-02-24 01:00:482486 } else if (paused_) {
sandersd35d2c3f2017-01-14 02:04:422487 // TODO(sandersd): Is it possible to have a suspended session, be ended,
2488 // and not be paused? If so we should be in a PLAYING state.
dalecurtise7120dc2016-09-03 02:54:352489 result.delegate_state =
sandersd35d2c3f2017-01-14 02:04:422490 ended_ ? DelegateState::GONE : DelegateState::PAUSED;
2491 result.is_idle = !seeking_;
sandersd50a635e2016-04-04 22:50:092492 } else {
2493 result.delegate_state = DelegateState::PLAYING;
sandersd35d2c3f2017-01-14 02:04:422494 result.is_idle = false;
sandersd50a635e2016-04-04 22:50:092495 }
2496
dalecurtis8b8505e72016-06-10 21:59:172497 // It's not critical if some cases where memory usage can change are missed,
sandersd50a635e2016-04-04 22:50:092498 // since media memory changes are usually gradual.
2499 result.is_memory_reporting_enabled =
Dale Curtis8a6281322017-08-31 00:35:532500 !has_error && can_play && !result.is_suspended && (!paused_ || seeking_);
sandersd50a635e2016-04-04 22:50:092501
2502 return result;
dalecurtis0f0097a2015-12-01 17:40:472503}
2504
dalecurtis83266c72015-10-29 18:43:202505void WebMediaPlayerImpl::ReportMemoryUsage() {
2506 DCHECK(main_task_runner_->BelongsToCurrentThread());
2507
wdzierzanowskifd4cd91c52015-12-02 23:50:202508 // About base::Unretained() usage below: We destroy |demuxer_| on the main
2509 // thread. Before that, however, ~WebMediaPlayerImpl() posts a task to the
2510 // media thread and waits for it to finish. Hence, the GetMemoryUsage() task
2511 // posted here must finish earlier.
Dale Curtis8a6281322017-08-31 00:35:532512 //
2513 // The exception to the above is when OnError() has been called. If we're in
2514 // the error state we've already shut down the pipeline and can't rely on it
2515 // to cycle the media thread before we destroy |demuxer_|. In this case skip
2516 // collection of the demuxer memory stats.
2517 if (demuxer_ && !IsNetworkStateError(network_state_)) {
wdzierzanowskifd4cd91c52015-12-02 23:50:202518 base::PostTaskAndReplyWithResult(
2519 media_task_runner_.get(), FROM_HERE,
2520 base::Bind(&Demuxer::GetMemoryUsage, base::Unretained(demuxer_.get())),
2521 base::Bind(&WebMediaPlayerImpl::FinishMemoryUsageReport, AsWeakPtr()));
2522 } else {
2523 FinishMemoryUsageReport(0);
2524 }
2525}
2526
2527void WebMediaPlayerImpl::FinishMemoryUsageReport(int64_t demuxer_memory_usage) {
2528 DCHECK(main_task_runner_->BelongsToCurrentThread());
2529
avayvodc4bfb0e62017-01-13 01:07:012530 const PipelineStatistics stats = GetPipelineStatistics();
servolk639473e492016-12-15 04:14:202531 const int64_t data_source_memory_usage =
2532 data_source_ ? data_source_->GetMemoryUsage() : 0;
dalecurtisecc76612017-04-19 00:31:202533
2534 // If we have video and no video memory usage, assume the VideoFrameCompositor
2535 // is holding onto the last frame after we've suspended the pipeline; which
2536 // thus reports zero memory usage from the video renderer.
2537 //
2538 // Technically this should use the coded size, but that requires us to hop to
2539 // the compositor to get and byte-perfect accuracy isn't important here.
2540 const int64_t video_memory_usage =
2541 stats.video_memory_usage +
2542 (pipeline_metadata_.has_video && !stats.video_memory_usage
Miguel Casas9e7766022018-01-08 16:13:132543 ? VideoFrame::AllocationSize(PIXEL_FORMAT_I420,
dalecurtisecc76612017-04-19 00:31:202544 pipeline_metadata_.natural_size)
2545 : 0);
2546
dalecurtis83266c72015-10-29 18:43:202547 const int64_t current_memory_usage =
dalecurtisecc76612017-04-19 00:31:202548 stats.audio_memory_usage + video_memory_usage + data_source_memory_usage +
2549 demuxer_memory_usage;
dalecurtis83266c72015-10-29 18:43:202550
dalecurtisecc76612017-04-19 00:31:202551 DVLOG(2) << "Memory Usage -- Total: " << current_memory_usage
2552 << " Audio: " << stats.audio_memory_usage
2553 << ", Video: " << video_memory_usage
servolk639473e492016-12-15 04:14:202554 << ", DataSource: " << data_source_memory_usage
wdzierzanowskifd4cd91c52015-12-02 23:50:202555 << ", Demuxer: " << demuxer_memory_usage;
dalecurtis83266c72015-10-29 18:43:202556
2557 const int64_t delta = current_memory_usage - last_reported_memory_usage_;
2558 last_reported_memory_usage_ = current_memory_usage;
2559 adjust_allocated_memory_cb_.Run(delta);
servolk639473e492016-12-15 04:14:202560
Blink Reformat1c4d759e2017-04-09 16:34:542561 if (HasAudio()) {
servolk639473e492016-12-15 04:14:202562 UMA_HISTOGRAM_MEMORY_KB("Media.WebMediaPlayerImpl.Memory.Audio",
2563 stats.audio_memory_usage / 1024);
2564 }
Blink Reformat1c4d759e2017-04-09 16:34:542565 if (HasVideo()) {
servolk639473e492016-12-15 04:14:202566 UMA_HISTOGRAM_MEMORY_KB("Media.WebMediaPlayerImpl.Memory.Video",
dalecurtisecc76612017-04-19 00:31:202567 video_memory_usage / 1024);
servolk639473e492016-12-15 04:14:202568 }
2569 if (data_source_) {
2570 UMA_HISTOGRAM_MEMORY_KB("Media.WebMediaPlayerImpl.Memory.DataSource",
2571 data_source_memory_usage / 1024);
2572 }
2573 if (demuxer_) {
2574 UMA_HISTOGRAM_MEMORY_KB("Media.WebMediaPlayerImpl.Memory.Demuxer",
2575 demuxer_memory_usage / 1024);
2576 }
dalecurtis83266c72015-10-29 18:43:202577}
2578
dalecurtis8b8505e72016-06-10 21:59:172579void WebMediaPlayerImpl::ScheduleIdlePauseTimer() {
avayvod65fad272017-02-24 01:00:482580 // Only schedule the pause timer if we're not paused or paused but going to
avayvod52efd282017-03-07 21:13:042581 // resume when foregrounded, and are suspended and have audio.
2582 if ((paused_ && !paused_when_hidden_) ||
Blink Reformat1c4d759e2017-04-09 16:34:542583 !pipeline_controller_.IsSuspended() || !HasAudio()) {
dalecurtis8b8505e72016-06-10 21:59:172584 return;
avayvod52efd282017-03-07 21:13:042585 }
dalecurtis8b8505e72016-06-10 21:59:172586
2587#if defined(OS_ANDROID)
2588 // Remote players will be suspended and locally paused.
Blink Reformat1c4d759e2017-04-09 16:34:542589 if (IsRemote())
dalecurtis8b8505e72016-06-10 21:59:172590 return;
2591#endif
2592
2593 // Idle timeout chosen arbitrarily.
2594 background_pause_timer_.Start(FROM_HERE, base::TimeDelta::FromSeconds(5),
2595 this, &WebMediaPlayerImpl::OnPause);
2596}
2597
dalecurtis04bdb582016-08-17 22:15:232598void WebMediaPlayerImpl::CreateWatchTimeReporter() {
wdzierzanowskia78fa9b2017-06-13 18:12:102599 if (!HasVideo() && !HasAudio())
2600 return;
2601
dalecurtis04bdb582016-08-17 22:15:232602 // Create the watch time reporter and synchronize its initial state.
Dale Curtis1adbe6a2017-08-02 02:09:132603 watch_time_reporter_.reset(new WatchTimeReporter(
2604 mojom::PlaybackProperties::New(
2605 pipeline_metadata_.audio_decoder_config.codec(),
2606 pipeline_metadata_.video_decoder_config.codec(),
Dale Curtisef3893f2017-12-06 23:28:102607 pipeline_metadata_.has_audio, pipeline_metadata_.has_video, false,
Dale Curtis1adbe6a2017-08-02 02:09:132608 !!chunk_demuxer_, is_encrypted_, embedded_media_experience_enabled_,
Dale Curtis74612b72017-12-14 20:56:192609 pipeline_metadata_.natural_size),
Dale Curtis051fdf62017-08-05 00:21:132610 base::BindRepeating(&WebMediaPlayerImpl::GetCurrentTimeInternal,
2611 base::Unretained(this)),
Hajime Hoshi8bb37dc2017-12-19 09:35:102612 media_metrics_provider_.get(),
2613 frame_->GetTaskRunner(blink::TaskType::kUnthrottled)));
dalecurtis04bdb582016-08-17 22:15:232614 watch_time_reporter_->OnVolumeChange(volume_);
Mounir Lamourif9af74e72017-06-19 19:31:452615
tguilbert1bb1c782017-01-23 21:15:112616 if (delegate_->IsFrameHidden())
dalecurtis04bdb582016-08-17 22:15:232617 watch_time_reporter_->OnHidden();
2618 else
2619 watch_time_reporter_->OnShown();
Mounir Lamourif9af74e72017-06-19 19:31:452620
Mounir Lamouri41a79c62017-06-06 12:53:162621 if (client_->HasNativeControls())
2622 watch_time_reporter_->OnNativeControlsEnabled();
2623 else
2624 watch_time_reporter_->OnNativeControlsDisabled();
Mounir Lamourif9af74e72017-06-19 19:31:452625
2626 switch (client_->DisplayType()) {
2627 case WebMediaPlayer::DisplayType::kInline:
2628 watch_time_reporter_->OnDisplayTypeInline();
2629 break;
2630 case WebMediaPlayer::DisplayType::kFullscreen:
2631 watch_time_reporter_->OnDisplayTypeFullscreen();
2632 break;
2633 case WebMediaPlayer::DisplayType::kPictureInPicture:
2634 watch_time_reporter_->OnDisplayTypePictureInPicture();
2635 break;
2636 }
dalecurtis04bdb582016-08-17 22:15:232637}
2638
avayvod39c102402016-11-23 21:43:132639bool WebMediaPlayerImpl::IsHidden() const {
2640 DCHECK(main_task_runner_->BelongsToCurrentThread());
2641
tguilbert1bb1c782017-01-23 21:15:112642 return delegate_->IsFrameHidden() && !delegate_->IsFrameClosed();
avayvod39c102402016-11-23 21:43:132643}
2644
avayvod102cdb62017-01-07 03:11:092645bool WebMediaPlayerImpl::IsStreaming() const {
2646 return data_source_ && data_source_->IsStreaming();
2647}
2648
liberato2fd111be2017-01-04 00:25:062649bool WebMediaPlayerImpl::DoesOverlaySupportMetadata() const {
Julien Isorce6c83d8de2017-10-12 13:11:292650 return pipeline_metadata_.video_decoder_config.video_rotation() ==
2651 VIDEO_ROTATION_0;
liberato2fd111be2017-01-04 00:25:062652}
2653
xjzaf29d4182016-12-16 01:52:322654void WebMediaPlayerImpl::ActivateViewportIntersectionMonitoring(bool activate) {
2655 DCHECK(main_task_runner_->BelongsToCurrentThread());
2656
Blink Reformat1c4d759e2017-04-09 16:34:542657 client_->ActivateViewportIntersectionMonitoring(activate);
xjzaf29d4182016-12-16 01:52:322658}
2659
Anton Vayvod09fa66e2017-07-20 23:02:122660void WebMediaPlayerImpl::UpdateRemotePlaybackCompatibility(bool is_compatible) {
2661 DCHECK(main_task_runner_->BelongsToCurrentThread());
2662
2663 client_->RemotePlaybackCompatibilityChanged(loaded_url_, is_compatible);
2664}
2665
avayvodcc273dd2017-01-19 19:35:122666bool WebMediaPlayerImpl::ShouldPauseVideoWhenHidden() const {
avayvod65fad272017-02-24 01:00:482667 // If suspending background video, pause any video that's not remoted or
2668 // not unlocked to play in the background.
2669 if (IsBackgroundedSuspendEnabled()) {
Blink Reformat1c4d759e2017-04-09 16:34:542670 if (!HasVideo())
avayvod65fad272017-02-24 01:00:482671 return false;
2672
2673#if defined(OS_ANDROID)
Blink Reformat1c4d759e2017-04-09 16:34:542674 if (IsRemote())
avayvod65fad272017-02-24 01:00:482675 return false;
avayvodcc273dd2017-01-19 19:35:122676#endif
avayvodeb9098d2017-01-07 00:33:032677
Blink Reformat1c4d759e2017-04-09 16:34:542678 return !HasAudio() || (IsResumeBackgroundVideosEnabled() &&
2679 video_locked_when_paused_when_hidden_);
avayvod65fad272017-02-24 01:00:482680 }
2681
2682 // Otherwise only pause if the optimization is on and it's a video-only
2683 // optimization candidate.
avayvod01201332017-04-14 00:27:152684 return IsBackgroundVideoPauseOptimizationEnabled() && !HasAudio() &&
avayvod65fad272017-02-24 01:00:482685 IsBackgroundOptimizationCandidate();
avayvodeb9098d2017-01-07 00:33:032686}
2687
avayvod2135a642017-01-13 00:17:142688bool WebMediaPlayerImpl::ShouldDisableVideoWhenHidden() const {
avayvodcc273dd2017-01-19 19:35:122689 // This optimization is behind the flag on all platforms.
2690 if (!IsBackgroundVideoTrackOptimizationEnabled())
avayvodc4bfb0e62017-01-13 01:07:012691 return false;
avayvodc4bfb0e62017-01-13 01:07:012692
avayvodcc273dd2017-01-19 19:35:122693 // Disable video track only for players with audio that match the criteria for
2694 // being optimized.
Blink Reformat1c4d759e2017-04-09 16:34:542695 return HasAudio() && IsBackgroundOptimizationCandidate();
avayvodcc273dd2017-01-19 19:35:122696}
2697
2698bool WebMediaPlayerImpl::IsBackgroundOptimizationCandidate() const {
2699 DCHECK(main_task_runner_->BelongsToCurrentThread());
2700
avayvodcc273dd2017-01-19 19:35:122701#if defined(OS_ANDROID) // WMPI_CAST
avayvodac1a8522017-01-20 19:02:502702 // Don't optimize players being Cast.
Blink Reformat1c4d759e2017-04-09 16:34:542703 if (IsRemote())
avayvodcc273dd2017-01-19 19:35:122704 return false;
2705#endif // defined(OS_ANDROID)
2706
2707 // Don't optimize audio-only or streaming players.
Blink Reformat1c4d759e2017-04-09 16:34:542708 if (!HasVideo() || IsStreaming())
avayvodcc273dd2017-01-19 19:35:122709 return false;
2710
Dale Curtis3f4935b2017-09-09 00:11:592711 // Video-only players are always optimized (paused).
2712 // Don't check the keyframe distance and duration.
2713 if (!HasAudio() && HasVideo())
2714 return true;
2715
avayvodcc273dd2017-01-19 19:35:122716 // Videos shorter than the maximum allowed keyframe distance can be optimized.
2717 base::TimeDelta duration = GetPipelineMediaDuration();
avayvode85ec422017-04-14 00:11:332718 base::TimeDelta max_keyframe_distance =
2719 (load_type_ == kLoadTypeMediaSource)
2720 ? max_keyframe_distance_to_disable_background_video_mse_
2721 : max_keyframe_distance_to_disable_background_video_;
2722 if (duration < max_keyframe_distance)
avayvodcc273dd2017-01-19 19:35:122723 return true;
2724
2725 // Otherwise, only optimize videos with shorter average keyframe distance.
avayvodc4bfb0e62017-01-13 01:07:012726 PipelineStatistics stats = GetPipelineStatistics();
avayvode85ec422017-04-14 00:11:332727 return stats.video_keyframe_distance_average < max_keyframe_distance;
avayvod2135a642017-01-13 00:17:142728}
2729
avayvod56e1f3942017-01-21 02:06:312730void WebMediaPlayerImpl::UpdateBackgroundVideoOptimizationState() {
2731 if (IsHidden()) {
Dale Curtisa75a7892017-08-09 20:21:512732 if (ShouldPauseVideoWhenHidden()) {
avayvod56e1f3942017-01-21 02:06:312733 PauseVideoIfNeeded();
Dale Curtisa75a7892017-08-09 20:21:512734 } else if (update_background_status_cb_.IsCancelled()) {
2735 // Only trigger updates when we don't have one already scheduled.
2736 update_background_status_cb_.Reset(
2737 base::Bind(&WebMediaPlayerImpl::DisableVideoTrackIfNeeded,
2738 base::Unretained(this)));
2739
2740 // Defer disable track until we're sure the clip will be backgrounded for
2741 // some time. Resuming may take half a second, so frequent tab switches
2742 // will yield a poor user experience otherwise. http://crbug.com/709302
2743 // may also cause AV sync issues if disable/enable happens too fast.
2744 main_task_runner_->PostDelayedTask(
2745 FROM_HERE, update_background_status_cb_.callback(),
2746 base::TimeDelta::FromSeconds(10));
2747 }
avayvod56e1f3942017-01-21 02:06:312748 } else {
Dale Curtisa75a7892017-08-09 20:21:512749 update_background_status_cb_.Cancel();
avayvod56e1f3942017-01-21 02:06:312750 EnableVideoTrackIfNeeded();
2751 }
2752}
2753
2754void WebMediaPlayerImpl::PauseVideoIfNeeded() {
2755 DCHECK(IsHidden());
2756
2757 // Don't pause video while the pipeline is stopped, resuming or seeking.
2758 // Also if the video is paused already.
tguilbert350936ff2017-02-24 05:39:272759 if (!pipeline_controller_.IsPipelineRunning() || is_pipeline_resuming_ ||
2760 seeking_ || paused_)
avayvod56e1f3942017-01-21 02:06:312761 return;
2762
2763 // OnPause() will set |paused_when_hidden_| to false and call
2764 // UpdatePlayState(), so set the flag to true after and then return.
2765 OnPause();
2766 paused_when_hidden_ = true;
2767}
2768
avayvod2135a642017-01-13 00:17:142769void WebMediaPlayerImpl::EnableVideoTrackIfNeeded() {
avayvod56e1f3942017-01-21 02:06:312770 // Don't change video track while the pipeline is stopped, resuming or
2771 // seeking.
tguilbert350936ff2017-02-24 05:39:272772 if (!pipeline_controller_.IsPipelineRunning() || is_pipeline_resuming_ ||
2773 seeking_)
avayvod2135a642017-01-13 00:17:142774 return;
2775
2776 if (video_track_disabled_) {
2777 video_track_disabled_ = false;
Blink Reformat1c4d759e2017-04-09 16:34:542778 if (client_->HasSelectedVideoTrack()) {
2779 WebMediaPlayer::TrackId trackId = client_->GetSelectedVideoTrackId();
2780 SelectedVideoTrackChanged(&trackId);
avayvod2135a642017-01-13 00:17:142781 }
2782 }
2783}
2784
2785void WebMediaPlayerImpl::DisableVideoTrackIfNeeded() {
2786 DCHECK(IsHidden());
2787
2788 // Don't change video track while the pipeline is resuming or seeking.
2789 if (is_pipeline_resuming_ || seeking_)
2790 return;
2791
2792 if (!video_track_disabled_ && ShouldDisableVideoWhenHidden()) {
2793 video_track_disabled_ = true;
Blink Reformat1c4d759e2017-04-09 16:34:542794 SelectedVideoTrackChanged(nullptr);
avayvod2135a642017-01-13 00:17:142795 }
2796}
2797
avayvodc4bfb0e62017-01-13 01:07:012798void WebMediaPlayerImpl::SetPipelineStatisticsForTest(
2799 const PipelineStatistics& stats) {
2800 pipeline_statistics_for_test_ = base::make_optional(stats);
2801}
2802
2803PipelineStatistics WebMediaPlayerImpl::GetPipelineStatistics() const {
2804 DCHECK(main_task_runner_->BelongsToCurrentThread());
2805
tguilbert350936ff2017-02-24 05:39:272806 return pipeline_statistics_for_test_.value_or(
2807 pipeline_controller_.GetStatistics());
avayvodc4bfb0e62017-01-13 01:07:012808}
2809
avayvodcc273dd2017-01-19 19:35:122810void WebMediaPlayerImpl::SetPipelineMediaDurationForTest(
2811 base::TimeDelta duration) {
2812 pipeline_media_duration_for_test_ = base::make_optional(duration);
2813}
2814
2815base::TimeDelta WebMediaPlayerImpl::GetPipelineMediaDuration() const {
2816 DCHECK(main_task_runner_->BelongsToCurrentThread());
2817
2818 return pipeline_media_duration_for_test_.value_or(
tguilbert350936ff2017-02-24 05:39:272819 pipeline_controller_.GetMediaDuration());
avayvodcc273dd2017-01-19 19:35:122820}
2821
2822void WebMediaPlayerImpl::ReportTimeFromForegroundToFirstFrame(
2823 base::TimeTicks foreground_time,
2824 base::TimeTicks new_frame_time) {
2825 base::TimeDelta time_to_first_frame = new_frame_time - foreground_time;
Blink Reformat1c4d759e2017-04-09 16:34:542826 if (HasAudio()) {
avayvodcc273dd2017-01-19 19:35:122827 UMA_HISTOGRAM_TIMES(
2828 "Media.Video.TimeFromForegroundToFirstFrame.DisableTrack",
2829 time_to_first_frame);
2830 } else {
2831 UMA_HISTOGRAM_TIMES("Media.Video.TimeFromForegroundToFirstFrame.Paused",
2832 time_to_first_frame);
2833 }
2834}
Xiangjun Zhangba8724f482017-08-03 06:43:252835
2836void WebMediaPlayerImpl::SwitchToRemoteRenderer(
2837 const std::string& remote_device_friendly_name) {
xjz4e5d4bf32017-02-15 21:26:352838 DCHECK(main_task_runner_->BelongsToCurrentThread());
Xiangjun Zhangba8724f482017-08-03 06:43:252839 disable_pipeline_auto_suspend_ = true;
Chris Cunninghamd9df58e2017-08-29 00:04:232840
2841 // Capabilities reporting should only be performed for local playbacks.
2842 video_decode_stats_reporter_.reset();
2843
Xiangjun Zhangba8724f482017-08-03 06:43:252844 // Requests to restart media pipeline. A remote renderer will be created via
2845 // the |renderer_factory_selector_|.
xjz4e5d4bf32017-02-15 21:26:352846 ScheduleRestart();
xjzdf9b67e2017-04-13 23:28:252847 if (client_) {
Xiangjun Zhangba8724f482017-08-03 06:43:252848 client_->MediaRemotingStarted(
2849 WebString::FromUTF8(remote_device_friendly_name));
xjzdf9b67e2017-04-13 23:28:252850 }
xjz4e5d4bf32017-02-15 21:26:352851}
2852
Xiangjun Zhangba8724f482017-08-03 06:43:252853void WebMediaPlayerImpl::SwitchToLocalRenderer() {
2854 DCHECK(main_task_runner_->BelongsToCurrentThread());
2855 disable_pipeline_auto_suspend_ = false;
Chris Cunninghamd9df58e2017-08-29 00:04:232856
2857 // Capabilities reporting may resume now that playback is local.
2858 CreateVideoDecodeStatsReporter();
2859
Xiangjun Zhangba8724f482017-08-03 06:43:252860 // Requests to restart media pipeline. A local renderer will be created via
2861 // the |renderer_factory_selector_|.
2862 ScheduleRestart();
2863 if (client_)
2864 client_->MediaRemotingStopped();
2865}
2866
dalecurtis4f6d14d2017-02-22 17:42:222867void WebMediaPlayerImpl::RecordUnderflowDuration(base::TimeDelta duration) {
2868 DCHECK(data_source_ || chunk_demuxer_);
xhwang68b3fab82017-05-17 21:31:462869
dalecurtis4f6d14d2017-02-22 17:42:222870 if (data_source_)
Jennifer Apacible82e25c92017-08-07 18:15:272871 UMA_HISTOGRAM_TIMES("Media.UnderflowDuration2.SRC", duration);
dalecurtis4f6d14d2017-02-22 17:42:222872 else
Jennifer Apacible82e25c92017-08-07 18:15:272873 UMA_HISTOGRAM_TIMES("Media.UnderflowDuration2.MSE", duration);
xhwang68b3fab82017-05-17 21:31:462874
2875 if (is_encrypted_)
Jennifer Apacible82e25c92017-08-07 18:15:272876 UMA_HISTOGRAM_TIMES("Media.UnderflowDuration2.EME", duration);
dalecurtis4f6d14d2017-02-22 17:42:222877}
2878
xhwang60802652017-04-19 07:29:582879#define UMA_HISTOGRAM_VIDEO_HEIGHT(name, sample) \
2880 UMA_HISTOGRAM_CUSTOM_COUNTS(name, sample, 100, 10000, 50)
2881
2882void WebMediaPlayerImpl::RecordVideoNaturalSize(const gfx::Size& natural_size) {
2883 // Always report video natural size to MediaLog.
2884 media_log_->AddEvent(media_log_->CreateVideoSizeSetEvent(
2885 natural_size.width(), natural_size.height()));
2886
2887 if (initial_video_height_recorded_)
2888 return;
2889
2890 initial_video_height_recorded_ = true;
2891
2892 int height = natural_size.height();
2893
2894 if (load_type_ == kLoadTypeURL)
2895 UMA_HISTOGRAM_VIDEO_HEIGHT("Media.VideoHeight.Initial.SRC", height);
2896 else if (load_type_ == kLoadTypeMediaSource)
2897 UMA_HISTOGRAM_VIDEO_HEIGHT("Media.VideoHeight.Initial.MSE", height);
2898
2899 if (is_encrypted_)
2900 UMA_HISTOGRAM_VIDEO_HEIGHT("Media.VideoHeight.Initial.EME", height);
2901
2902 UMA_HISTOGRAM_VIDEO_HEIGHT("Media.VideoHeight.Initial.All", height);
2903}
2904
2905#undef UMA_HISTOGRAM_VIDEO_HEIGHT
2906
hubbeb2d3efd2017-05-05 23:26:382907void WebMediaPlayerImpl::SetTickClockForTest(base::TickClock* tick_clock) {
tzik2c963b872017-12-07 06:57:242908 tick_clock_ = tick_clock;
hubbeb2d3efd2017-05-05 23:26:382909 buffered_data_source_host_.SetTickClockForTest(tick_clock);
2910}
2911
acolwell9e0840d2014-09-06 19:01:322912} // namespace media