blob: 654ba89050299e2a31ec49243c759482815edc6c [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"
asvitkine30330812016-08-30 04:01:0821#include "base/metrics/histogram_macros.h"
acolwellb4034942014-08-28 15:42:4322#include "base/single_thread_task_runner.h"
servolka233f832016-06-10 20:39:0423#include "base/strings/string_number_conversions.h"
wdzierzanowskifd4cd91c52015-12-02 23:50:2024#include "base/task_runner_util.h"
gabba14a442016-05-11 20:10:2025#include "base/threading/thread_task_runner_handle.h"
ssid9525f4672015-01-28 12:13:1526#include "base/trace_event/trace_event.h"
sandersd1e49fb62015-12-12 01:18:0627#include "build/build_config.h"
[email protected]38564622014-08-19 02:47:1828#include "cc/blink/web_layer_impl.h"
[email protected]21c3f7502013-03-23 03:29:5129#include "cc/layers/video_layer.h"
[email protected]e4fc09e2012-04-06 03:17:4430#include "media/audio/null_audio_sink.h"
[email protected]2eccbed2014-01-10 05:15:5331#include "media/base/bind_to_current_loop.h"
xhwang0ad11e512014-11-25 23:43:0932#include "media/base/cdm_context.h"
xhwang79b193042016-12-13 18:52:4333#include "media/base/content_decryption_module.h"
[email protected]32da1002010-03-03 21:57:3534#include "media/base/limits.h"
zqzhang5d8eab72016-08-26 20:34:3035#include "media/base/media_content_type.h"
[email protected]090f7312011-08-05 23:26:4036#include "media/base/media_log.h"
sandersd1e49fb62015-12-12 01:18:0637#include "media/base/media_switches.h"
tguilbert25a4d112016-10-13 21:56:5138#include "media/base/media_url_demuxer.h"
[email protected]8a561062013-11-22 01:19:3139#include "media/base/text_renderer.h"
watk9f9dfdc92015-09-04 21:33:2940#include "media/base/timestamp_constants.h"
[email protected]e81283bb2010-08-31 18:01:2141#include "media/base/video_frame.h"
acolwell9e0840d2014-09-06 19:01:3242#include "media/blink/texttrack_impl.h"
dalecurtis04bdb582016-08-17 22:15:2343#include "media/blink/watch_time_reporter.h"
acolwell9e0840d2014-09-06 19:01:3244#include "media/blink/webaudiosourceprovider_impl.h"
xhwang97de4202014-11-25 08:44:0145#include "media/blink/webcontentdecryptionmodule_impl.h"
acolwell9e0840d2014-09-06 19:01:3246#include "media/blink/webinbandtexttrack_impl.h"
47#include "media/blink/webmediaplayer_delegate.h"
acolwell9e0840d2014-09-06 19:01:3248#include "media/blink/webmediaplayer_util.h"
49#include "media/blink/webmediasource_impl.h"
[email protected]efe7cd22012-09-12 23:55:0150#include "media/filters/chunk_demuxer.h"
[email protected]ddbc6ff2013-04-19 15:28:3351#include "media/filters/ffmpeg_demuxer.h"
jrummellc9d8e532015-02-26 18:38:1952#include "third_party/WebKit/public/platform/WebEncryptedMediaTypes.h"
srirama.m26f864d02015-07-14 05:21:4653#include "third_party/WebKit/public/platform/WebMediaPlayerClient.h"
54#include "third_party/WebKit/public/platform/WebMediaPlayerEncryptedMediaClient.h"
guidou9bfe4e2f2016-04-09 08:31:1955#include "third_party/WebKit/public/platform/WebMediaPlayerSource.h"
[email protected]745746d2013-08-23 02:09:1656#include "third_party/WebKit/public/platform/WebMediaSource.h"
[email protected]c10884462013-05-30 00:22:0957#include "third_party/WebKit/public/platform/WebRect.h"
mek966863c2016-02-04 23:39:0558#include "third_party/WebKit/public/platform/WebSecurityOrigin.h"
[email protected]c10884462013-05-30 00:22:0959#include "third_party/WebKit/public/platform/WebSize.h"
60#include "third_party/WebKit/public/platform/WebString.h"
61#include "third_party/WebKit/public/platform/WebURL.h"
tguilbert9881bc22016-10-27 03:13:4162#include "third_party/WebKit/public/web/WebDocument.h"
xhwang0acca44b2015-06-18 00:43:3163#include "third_party/WebKit/public/web/WebFrame.h"
[email protected]80504652014-04-18 04:41:5064#include "third_party/WebKit/public/web/WebLocalFrame.h"
[email protected]2255a9332013-06-17 05:12:3165#include "third_party/WebKit/public/web/WebView.h"
[email protected]b3f2b912009-04-09 16:18:5266
dalecurtisea27a3ed2016-06-24 01:41:3067#if defined(OS_ANDROID)
68#include "media/base/android/media_codec_util.h"
69#endif
70
[email protected]180ef242013-11-07 06:50:4671using blink::WebCanvas;
72using blink::WebMediaPlayer;
73using blink::WebRect;
74using blink::WebSize;
75using blink::WebString;
hubbed5f36882016-01-15 22:40:3776using gpu::gles2::GLES2Interface;
77
danakj365175c2016-02-06 00:37:3778#define STATIC_ASSERT_ENUM(a, b) \
79 static_assert(static_cast<int>(a) == static_cast<int>(b), \
80 "mismatching enums: " #a)
81
hubbed5f36882016-01-15 22:40:3782namespace media {
[email protected]ec9212f2008-12-18 21:40:3683
[email protected]8931c41a2009-07-07 17:31:4984namespace {
85
[email protected]378f0b72009-08-11 17:11:4286// Limits the range of playback rate.
87//
88// TODO(kylep): Revisit these.
89//
90// Vista has substantially lower performance than XP or Windows7. If you speed
91// up a video too much, it can't keep up, and rendering stops updating except on
92// the time bar. For really high speeds, audio becomes a bottleneck and we just
93// use up the data we have, which may not achieve the speed requested, but will
94// not crash the tab.
95//
96// A very slow speed, ie 0.00000001x, causes the machine to lock up. (It seems
97// like a busy loop). It gets unresponsive, although its not completely dead.
98//
99// Also our timers are not very accurate (especially for ogg), which becomes
100// evident at low speeds and on Vista. Since other speeds are risky and outside
101// the norms, we think 1/16x to 16x is a safe and useful range for now.
[email protected]39bdde32013-04-17 17:44:20102const double kMinRate = 0.0625;
103const double kMaxRate = 16.0;
[email protected]378f0b72009-08-11 17:11:42104
hubbed5f36882016-01-15 22:40:37105void SetSinkIdOnMediaThread(scoped_refptr<WebAudioSourceProviderImpl> sink,
106 const std::string& device_id,
107 const url::Origin& security_origin,
olka68b69392016-04-01 11:42:12108 const OutputDeviceStatusCB& callback) {
109 sink->SwitchOutputDevice(device_id, security_origin, callback);
guidouc7babef2015-10-22 00:42:35110}
111
sandersd50a635e2016-04-04 22:50:09112bool IsBackgroundedSuspendEnabled() {
dalecurtis0431cbf2016-03-12 01:19:43113#if !defined(OS_ANDROID)
114 // Suspend/Resume is only enabled by default on Android.
115 return base::CommandLine::ForCurrentProcess()->HasSwitch(
116 switches::kEnableMediaSuspend);
117#else
118 return !base::CommandLine::ForCurrentProcess()->HasSwitch(
119 switches::kDisableMediaSuspend);
120#endif
121}
122
avayvod48a8be52016-08-04 19:52:50123bool IsResumeBackgroundVideosEnabled() {
124 return base::FeatureList::IsEnabled(kResumeBackgroundVideo);
125}
126
avayvod39c102402016-11-23 21:43:13127bool IsBackgroundVideoTrackOptimizationEnabled() {
128 return base::FeatureList::IsEnabled(kBackgroundVideoTrackOptimization);
129}
130
sandersd50a635e2016-04-04 22:50:09131bool IsNetworkStateError(blink::WebMediaPlayer::NetworkState state) {
132 bool result = state == blink::WebMediaPlayer::NetworkStateFormatError ||
133 state == blink::WebMediaPlayer::NetworkStateNetworkError ||
134 state == blink::WebMediaPlayer::NetworkStateDecodeError;
135 DCHECK_EQ(state > blink::WebMediaPlayer::NetworkStateLoaded, result);
136 return result;
137}
138
sandersd2c478422016-08-02 01:19:25139gfx::Size GetRotatedVideoSize(VideoRotation rotation, gfx::Size natural_size) {
140 if (rotation == VIDEO_ROTATION_90 || rotation == VIDEO_ROTATION_270)
141 return gfx::Size(natural_size.height(), natural_size.width());
142 return natural_size;
143}
144
dalecurtis04bdb582016-08-17 22:15:23145base::TimeDelta GetCurrentTimeInternal(WebMediaPlayerImpl* p_this) {
146 // We wrap currentTime() instead of using pipeline_.GetMediaTime() since there
147 // are a variety of cases in which that time is not accurate; e.g., while
148 // remoting and during a pause or seek.
149 return base::TimeDelta::FromSecondsD(p_this->currentTime());
150}
151
watkd026f792016-11-05 00:28:51152// How much time must have elapsed since loading last progressed before the
153// player is eligible for idle suspension.
154constexpr base::TimeDelta kLoadingToIdleTimeout =
155 base::TimeDelta::FromSeconds(3);
156
[email protected]8931c41a2009-07-07 17:31:49157} // namespace
158
[email protected]6683e1b2014-04-10 01:45:38159class BufferedDataSourceHostImpl;
160
danakj365175c2016-02-06 00:37:37161STATIC_ASSERT_ENUM(WebMediaPlayer::CORSModeUnspecified,
162 UrlData::CORS_UNSPECIFIED);
163STATIC_ASSERT_ENUM(WebMediaPlayer::CORSModeAnonymous, UrlData::CORS_ANONYMOUS);
164STATIC_ASSERT_ENUM(WebMediaPlayer::CORSModeUseCredentials,
165 UrlData::CORS_USE_CREDENTIALS);
[email protected]a5a01102012-06-06 17:01:24166
[email protected]2c539b82012-08-18 04:10:19167#define BIND_TO_RENDER_LOOP(function) \
acolwellb4034942014-08-28 15:42:43168 (DCHECK(main_task_runner_->BelongsToCurrentThread()), \
acolwell9e0840d2014-09-06 19:01:32169 BindToCurrentLoop(base::Bind(function, AsWeakPtr())))
[email protected]5983adb2012-10-24 00:12:00170
[email protected]4e982192014-06-21 13:35:45171#define BIND_TO_RENDER_LOOP1(function, arg1) \
acolwellb4034942014-08-28 15:42:43172 (DCHECK(main_task_runner_->BelongsToCurrentThread()), \
acolwell9e0840d2014-09-06 19:01:32173 BindToCurrentLoop(base::Bind(function, AsWeakPtr(), arg1)))
[email protected]4e982192014-06-21 13:35:45174
[email protected]5b5bb9d2010-10-22 19:57:36175WebMediaPlayerImpl::WebMediaPlayerImpl(
[email protected]35b2a972014-04-04 15:50:22176 blink::WebLocalFrame* frame,
[email protected]180ef242013-11-07 06:50:46177 blink::WebMediaPlayerClient* client,
srirama.m26f864d02015-07-14 05:21:46178 blink::WebMediaPlayerEncryptedMediaClient* encrypted_client,
[email protected]b8976652011-10-26 23:46:55179 base::WeakPtr<WebMediaPlayerDelegate> delegate,
dcheng3076abbf2016-04-22 20:42:39180 std::unique_ptr<RendererFactory> renderer_factory,
hubbe5f0ad43b2015-12-14 20:57:26181 linked_ptr<UrlIndex> url_index,
[email protected]e82b2bd2013-01-02 17:47:57182 const WebMediaPlayerParams& params)
[email protected]f6af7592014-02-28 10:09:11183 : frame_(frame),
sandersd50a635e2016-04-04 22:50:09184 delegate_state_(DelegateState::GONE),
185 is_idle_(false),
186 must_suspend_(false),
[email protected]ef405f66b2012-04-18 02:39:55187 network_state_(WebMediaPlayer::NetworkStateEmpty),
188 ready_state_(WebMediaPlayer::ReadyStateHaveNothing),
sandersd50a635e2016-04-04 22:50:09189 highest_ready_state_(WebMediaPlayer::ReadyStateHaveNothing),
dalecurtisb6e052f52016-08-25 00:35:55190 preload_(MultibufferDataSource::AUTO),
191 buffering_strategy_(MultibufferDataSource::BUFFERING_STRATEGY_NORMAL),
altiminbf328382016-12-07 14:28:31192 main_task_runner_(frame->loadingTaskRunner()),
acolwell755d12d2014-08-30 01:09:19193 media_task_runner_(params.media_task_runner()),
dcastagna617d086b2015-08-20 01:39:30194 worker_task_runner_(params.worker_task_runner()),
acolwell755d12d2014-08-30 01:09:19195 media_log_(params.media_log()),
acolwellb4034942014-08-28 15:42:43196 pipeline_(media_task_runner_, media_log_.get()),
sandersd1c0bba02016-03-04 23:14:08197 pipeline_controller_(
198 &pipeline_,
199 base::Bind(&WebMediaPlayerImpl::CreateRenderer,
200 base::Unretained(this)),
201 base::Bind(&WebMediaPlayerImpl::OnPipelineSeeked, AsWeakPtr()),
202 base::Bind(&WebMediaPlayerImpl::OnPipelineSuspended, AsWeakPtr()),
alokp967c902452016-05-06 05:21:37203 base::Bind(&WebMediaPlayerImpl::OnError, AsWeakPtr())),
[email protected]f988d9b2014-07-25 00:35:43204 load_type_(LoadTypeURL),
[email protected]75e145a2014-04-15 17:44:32205 opaque_(false),
wolenetz1b2ae7d2015-06-10 00:44:21206 playback_rate_(0.0),
[email protected]49480902009-07-14 20:23:43207 paused_(true),
[email protected]b3766a22010-12-22 17:34:13208 seeking_(false),
watkdee516f2016-02-18 02:22:19209 pending_suspend_resume_cycle_(false),
scherkusd2c745b2014-09-04 05:03:40210 ended_(false),
yoichio863bebf2016-03-04 07:56:58211 should_notify_time_changed_(false),
tsunghungee562e92016-07-20 18:03:31212 overlay_enabled_(false),
213 decoder_requires_restart_for_overlay_(false),
[email protected]5badb082010-06-11 17:40:15214 client_(client),
srirama.m26f864d02015-07-14 05:21:46215 encrypted_client_(encrypted_client),
[email protected]baff4512011-10-19 18:21:07216 delegate_(delegate),
dalecurtisbb3eaac2016-01-27 21:10:25217 delegate_id_(0),
[email protected]d726eddc2013-07-02 22:25:55218 defer_load_cb_(params.defer_load_cb()),
dongseong.hwang0c4e9d82015-01-08 20:11:13219 context_3d_cb_(params.context_3d_cb()),
dalecurtis83266c72015-10-29 18:43:20220 adjust_allocated_memory_cb_(params.adjust_allocated_memory_cb()),
221 last_reported_memory_usage_(0),
[email protected]132dd57c2012-08-10 23:24:34222 supports_save_(true),
[email protected]f5443ef72013-04-22 04:03:38223 chunk_demuxer_(NULL),
hubbe5f0ad43b2015-12-14 20:57:26224 url_index_(url_index),
Bartosz Fabianowski85a823812015-04-16 10:27:51225 // Threaded compositing isn't enabled universally yet.
fdoraydb3ef7d2016-06-09 15:42:38226 compositor_task_runner_(params.compositor_task_runner()
227 ? params.compositor_task_runner()
228 : base::ThreadTaskRunnerHandle::Get()),
alokp5d86e9b2016-05-17 20:20:41229 compositor_(new VideoFrameCompositor(compositor_task_runner_)),
hubbed5f36882016-01-15 22:40:37230#if defined(OS_ANDROID) // WMPI_CAST
dalecurtisbb3eaac2016-01-27 21:10:25231 cast_impl_(this, client_, params.context_3d_cb()),
hubbed5f36882016-01-15 22:40:37232#endif
dalecurtisbb3eaac2016-01-27 21:10:25233 volume_(1.0),
234 volume_multiplier_(1.0),
watkdee516f2016-02-18 02:22:19235 renderer_factory_(std::move(renderer_factory)),
dalecurtis2ff781da2016-03-03 01:52:13236 surface_manager_(params.surface_manager()),
tsunghungee562e92016-07-20 18:03:31237 overlay_surface_id_(SurfaceManager::kNoSurfaceID),
dalecurtis7f366b2242016-04-13 01:16:17238 suppress_destruction_errors_(false),
dalecurtis04bdb582016-08-17 22:15:23239 can_suspend_state_(CanSuspendState::UNKNOWN),
tguilbert25a4d112016-10-13 21:56:51240 use_fallback_path_(false),
dalecurtis9d638a12016-08-30 06:20:55241 is_encrypted_(false),
xjzd3fe45a2016-10-12 18:26:37242 underflow_count_(0),
243 observer_(params.media_observer()) {
dalecurtis83266c72015-10-29 18:43:20244 DCHECK(!adjust_allocated_memory_cb_.is_null());
xhwang59d4175a2016-01-14 03:19:30245 DCHECK(renderer_factory_);
servolkef1e5ef2016-03-25 04:55:26246 DCHECK(client_);
dalecurtis83266c72015-10-29 18:43:20247
watkd026f792016-11-05 00:28:51248 tick_clock_.reset(new base::DefaultTickClock());
249
tsunghungee562e92016-07-20 18:03:31250 force_video_overlays_ = base::CommandLine::ForCurrentProcess()->HasSwitch(
251 switches::kForceVideoOverlays);
252
dalecurtisbb3eaac2016-01-27 21:10:25253 if (delegate_)
254 delegate_id_ = delegate_->AddObserver(this);
sandersd1e49fb62015-12-12 01:18:06255
[email protected]c93eb0a62011-08-09 22:47:24256 media_log_->AddEvent(
acolwell9e0840d2014-09-06 19:01:32257 media_log_->CreateEvent(MediaLogEvent::WEBMEDIAPLAYER_CREATED));
[email protected]4e6be3f2009-05-07 02:24:44258
jrummelle616ee92016-10-08 02:15:44259 if (params.initial_cdm())
260 SetCdm(params.initial_cdm());
xhwang0ad11e512014-11-25 23:43:09261
xhwangf94a634d2014-10-22 22:07:27262 // TODO(xhwang): When we use an external Renderer, many methods won't work,
xhwang6fa356202014-12-11 00:44:12263 // e.g. GetCurrentFrameFromCompositor(). See http://crbug.com/434861
olkae4ba2ed82016-12-06 16:34:51264 audio_source_provider_ =
265 new WebAudioSourceProviderImpl(params.audio_renderer_sink(), media_log_);
[email protected]ec9212f2008-12-18 21:40:36266}
267
[email protected]4e6be3f2009-05-07 02:24:44268WebMediaPlayerImpl::~WebMediaPlayerImpl() {
acolwellb4034942014-08-28 15:42:43269 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]d43ed912009-02-03 04:52:53270
alokp1116967f2016-06-11 17:30:56271 suppress_destruction_errors_ = true;
sandersd1e49fb62015-12-12 01:18:06272 if (delegate_) {
dalecurtisbb3eaac2016-01-27 21:10:25273 delegate_->PlayerGone(delegate_id_);
274 delegate_->RemoveObserver(delegate_id_);
sandersd1e49fb62015-12-12 01:18:06275 }
[email protected]baff4512011-10-19 18:21:07276
dalecurtis04bdb582016-08-17 22:15:23277 // Finalize any watch time metrics before destroying the pipeline.
278 watch_time_reporter_.reset();
279
alokp967c902452016-05-06 05:21:37280 // Pipeline must be stopped before it is destroyed.
281 pipeline_.Stop();
[email protected]f6af7592014-02-28 10:09:11282
dalecurtis83266c72015-10-29 18:43:20283 if (last_reported_memory_usage_)
284 adjust_allocated_memory_cb_.Run(-last_reported_memory_usage_);
285
dalecurtise1edb312016-06-22 02:33:21286 // Destruct compositor resources in the proper order.
287 client_->setWebLayer(nullptr);
288 if (video_weblayer_)
289 static_cast<cc::VideoLayer*>(video_weblayer_->layer())->StopUsingProvider();
[email protected]dd061e12014-05-06 19:21:22290 compositor_task_runner_->DeleteSoon(FROM_HERE, compositor_);
xhwangea8bb3562015-06-08 21:18:37291
292 media_log_->AddEvent(
293 media_log_->CreateEvent(MediaLogEvent::WEBMEDIAPLAYER_DESTROYED));
[email protected]ec9212f2008-12-18 21:40:36294}
295
guidou9bfe4e2f2016-04-09 08:31:19296void WebMediaPlayerImpl::load(LoadType load_type,
297 const blink::WebMediaPlayerSource& source,
[email protected]62e5e682013-03-07 23:53:24298 CORSMode cors_mode) {
guidou9bfe4e2f2016-04-09 08:31:19299 // Only URL or MSE blob URL is supported.
300 DCHECK(source.isURL());
301 blink::WebURL url = source.getAsURL();
pkastingf5279482016-07-27 02:18:20302 DVLOG(1) << __func__ << "(" << load_type << ", " << url << ", " << cors_mode
303 << ")";
[email protected]d726eddc2013-07-02 22:25:55304 if (!defer_load_cb_.is_null()) {
305 defer_load_cb_.Run(base::Bind(
[email protected]ef8394c2013-08-21 20:26:30306 &WebMediaPlayerImpl::DoLoad, AsWeakPtr(), load_type, url, cors_mode));
[email protected]d726eddc2013-07-02 22:25:55307 return;
308 }
[email protected]ef8394c2013-08-21 20:26:30309 DoLoad(load_type, url, cors_mode);
[email protected]62e5e682013-03-07 23:53:24310}
311
amp2ff7bf42d2016-12-17 00:06:52312void WebMediaPlayerImpl::SetEnableFullscreenOverlays(bool enable_overlays) {
313 enable_fullscreen_video_overlays_ = enable_overlays;
314}
315
watk9c87c6fa2016-05-06 20:36:51316bool WebMediaPlayerImpl::supportsOverlayFullscreenVideo() {
317#if defined(OS_ANDROID)
watkf835a792016-06-24 23:24:40318 return true;
watk9c87c6fa2016-05-06 20:36:51319#else
320 return false;
321#endif
322}
323
tsunghungee562e92016-07-20 18:03:31324void WebMediaPlayerImpl::EnableOverlay() {
325 overlay_enabled_ = true;
watkf835a792016-06-24 23:24:40326 if (surface_manager_) {
327 surface_created_cb_.Reset(
328 base::Bind(&WebMediaPlayerImpl::OnSurfaceCreated, AsWeakPtr()));
329 surface_manager_->CreateFullscreenSurface(pipeline_metadata_.natural_size,
330 surface_created_cb_.callback());
331 }
tsunghungee562e92016-07-20 18:03:31332
333 if (decoder_requires_restart_for_overlay_)
watkdee516f2016-02-18 02:22:19334 ScheduleRestart();
335}
336
tsunghungee562e92016-07-20 18:03:31337void WebMediaPlayerImpl::DisableOverlay() {
338 overlay_enabled_ = false;
watkf835a792016-06-24 23:24:40339 surface_created_cb_.Cancel();
tsunghungee562e92016-07-20 18:03:31340 overlay_surface_id_ = SurfaceManager::kNoSurfaceID;
341
342 if (decoder_requires_restart_for_overlay_)
watkdee516f2016-02-18 02:22:19343 ScheduleRestart();
dalecurtis4b632fce22016-11-10 00:52:17344 else if (!set_surface_cb_.is_null())
345 set_surface_cb_.Run(overlay_surface_id_);
watkdee516f2016-02-18 02:22:19346}
347
tsunghungee562e92016-07-20 18:03:31348void WebMediaPlayerImpl::enteredFullscreen() {
amp2ff7bf42d2016-12-17 00:06:52349 if (!force_video_overlays_ && enable_fullscreen_video_overlays_)
tsunghungee562e92016-07-20 18:03:31350 EnableOverlay();
xjzd3fe45a2016-10-12 18:26:37351 if (observer_)
352 observer_->OnEnteredFullscreen();
tsunghungee562e92016-07-20 18:03:31353}
354
355void WebMediaPlayerImpl::exitedFullscreen() {
amp2ff7bf42d2016-12-17 00:06:52356 if (!force_video_overlays_ && enable_fullscreen_video_overlays_)
tsunghungee562e92016-07-20 18:03:31357 DisableOverlay();
xjzd3fe45a2016-10-12 18:26:37358 if (observer_)
359 observer_->OnExitedFullscreen();
tsunghungee562e92016-07-20 18:03:31360}
361
xjzcdbbe732016-12-03 20:47:42362void WebMediaPlayerImpl::becameDominantVisibleContent(bool isDominant) {
363 if (observer_)
364 observer_->OnBecameDominantVisibleContent(isDominant);
365}
366
[email protected]ef8394c2013-08-21 20:26:30367void WebMediaPlayerImpl::DoLoad(LoadType load_type,
[email protected]180ef242013-11-07 06:50:46368 const blink::WebURL& url,
[email protected]d726eddc2013-07-02 22:25:55369 CORSMode cors_mode) {
pkastingf5279482016-07-27 02:18:20370 DVLOG(1) << __func__;
acolwellb4034942014-08-28 15:42:43371 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]d726eddc2013-07-02 22:25:55372
[email protected]62e5e682013-03-07 23:53:24373 GURL gurl(url);
xhwangbffbf452016-04-01 05:26:45374 ReportMetrics(load_type, gurl, frame_->getSecurityOrigin());
[email protected]62e5e682013-03-07 23:53:24375
[email protected]926f8fd2013-04-12 20:27:53376 // Set subresource URL for crash reporting.
377 base::debug::SetCrashKeyValue("subresource_url", gurl.spec());
378
tguilbert25a4d112016-10-13 21:56:51379 if (use_fallback_path_)
380 fallback_url_ = gurl;
381
[email protected]ef8394c2013-08-21 20:26:30382 load_type_ = load_type;
383
[email protected]62e5e682013-03-07 23:53:24384 SetNetworkState(WebMediaPlayer::NetworkStateLoading);
385 SetReadyState(WebMediaPlayer::ReadyStateHaveNothing);
kinukof19cde72015-12-18 23:15:25386 media_log_->AddEvent(media_log_->CreateLoadEvent(url.string().utf8()));
[email protected]d726eddc2013-07-02 22:25:55387
388 // Media source pipelines can start immediately.
[email protected]ef8394c2013-08-21 20:26:30389 if (load_type == LoadTypeMediaSource) {
[email protected]d726eddc2013-07-02 22:25:55390 supports_save_ = false;
[email protected]ef8394c2013-08-21 20:26:30391 StartPipeline();
hubbe5f0ad43b2015-12-14 20:57:26392 } else {
dalecurtisb6e052f52016-08-25 00:35:55393 data_source_.reset(new MultibufferDataSource(
394 url, static_cast<UrlData::CORSMode>(cors_mode), main_task_runner_,
395 url_index_, frame_, media_log_.get(), &buffered_data_source_host_,
396 base::Bind(&WebMediaPlayerImpl::NotifyDownloading, AsWeakPtr())));
avayvode46d7bef2016-03-30 23:18:26397 data_source_->SetPreload(preload_);
398 data_source_->SetBufferingStrategy(buffering_strategy_);
399 data_source_->Initialize(
400 base::Bind(&WebMediaPlayerImpl::DataSourceInitialized, AsWeakPtr()));
hubbe5f0ad43b2015-12-14 20:57:26401 }
hubbed5f36882016-01-15 22:40:37402
403#if defined(OS_ANDROID) // WMPI_CAST
dalecurtisbb3eaac2016-01-27 21:10:25404 cast_impl_.Initialize(url, frame_, delegate_id_);
hubbed5f36882016-01-15 22:40:37405#endif
[email protected]62e5e682013-03-07 23:53:24406}
407
[email protected]4e6be3f2009-05-07 02:24:44408void WebMediaPlayerImpl::play() {
pkastingf5279482016-07-27 02:18:20409 DVLOG(1) << __func__;
acolwellb4034942014-08-28 15:42:43410 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]d43ed912009-02-03 04:52:53411
hubbed5f36882016-01-15 22:40:37412#if defined(OS_ANDROID) // WMPI_CAST
413 if (isRemote()) {
dalecurtis6e2716d2016-01-21 04:49:15414 cast_impl_.play();
hubbed5f36882016-01-15 22:40:37415 return;
416 }
417#endif
[email protected]49480902009-07-14 20:23:43418 paused_ = false;
sandersd50a635e2016-04-04 22:50:09419 is_idle_ = false;
yoichio863bebf2016-03-04 07:56:58420 pipeline_.SetPlaybackRate(playback_rate_);
dalecurtis4619cd02016-09-22 21:39:10421 background_pause_timer_.Stop();
sandersd1c0bba02016-03-04 23:14:08422
[email protected]039b7542013-10-17 22:06:25423 if (data_source_)
424 data_source_->MediaIsPlaying();
[email protected]090f7312011-08-05 23:26:40425
xjz48a9cb72016-12-20 04:02:49426 if (observer_)
427 observer_->OnPlaying();
428
dalecurtis04bdb582016-08-17 22:15:23429 DCHECK(watch_time_reporter_);
430 watch_time_reporter_->OnPlaying();
acolwell9e0840d2014-09-06 19:01:32431 media_log_->AddEvent(media_log_->CreateEvent(MediaLogEvent::PLAY));
sandersd50a635e2016-04-04 22:50:09432 UpdatePlayState();
[email protected]ec9212f2008-12-18 21:40:36433}
434
[email protected]4e6be3f2009-05-07 02:24:44435void WebMediaPlayerImpl::pause() {
pkastingf5279482016-07-27 02:18:20436 DVLOG(1) << __func__;
acolwellb4034942014-08-28 15:42:43437 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]d43ed912009-02-03 04:52:53438
sandersd50a635e2016-04-04 22:50:09439 // We update the paused state even when casting, since we expect pause() to be
440 // called when casting begins, and when we exit casting we should end up in a
441 // paused state.
[email protected]49480902009-07-14 20:23:43442 paused_ = true;
hubbed5f36882016-01-15 22:40:37443
444#if defined(OS_ANDROID) // WMPI_CAST
445 if (isRemote()) {
dalecurtis6e2716d2016-01-21 04:49:15446 cast_impl_.pause();
hubbed5f36882016-01-15 22:40:37447 return;
448 }
449#endif
450
a.berwal338bf002015-04-22 11:14:50451 pipeline_.SetPlaybackRate(0.0);
sandersd1c0bba02016-03-04 23:14:08452
453 // pause() may be called after playback has ended and the HTMLMediaElement
454 // requires that currentTime() == duration() after ending. We want to ensure
455 // |paused_time_| matches currentTime() in this case or a future seek() may
456 // incorrectly discard what it thinks is a seek to the existing time.
457 paused_time_ =
458 ended_ ? pipeline_.GetMediaDuration() : pipeline_.GetMediaTime();
[email protected]090f7312011-08-05 23:26:40459
xjz48a9cb72016-12-20 04:02:49460 if (observer_)
461 observer_->OnPaused();
462
dalecurtis04bdb582016-08-17 22:15:23463 DCHECK(watch_time_reporter_);
464 watch_time_reporter_->OnPaused();
acolwell9e0840d2014-09-06 19:01:32465 media_log_->AddEvent(media_log_->CreateEvent(MediaLogEvent::PAUSE));
sandersd50a635e2016-04-04 22:50:09466 UpdatePlayState();
[email protected]ec9212f2008-12-18 21:40:36467}
468
[email protected]574a1d62009-07-17 03:23:46469bool WebMediaPlayerImpl::supportsSave() const {
acolwellb4034942014-08-28 15:42:43470 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]132dd57c2012-08-10 23:24:34471 return supports_save_;
[email protected]574a1d62009-07-17 03:23:46472}
473
[email protected]39bdde32013-04-17 17:44:20474void WebMediaPlayerImpl::seek(double seconds) {
pkastingf5279482016-07-27 02:18:20475 DVLOG(1) << __func__ << "(" << seconds << "s)";
acolwellb4034942014-08-28 15:42:43476 DCHECK(main_task_runner_->BelongsToCurrentThread());
sandersd1c0bba02016-03-04 23:14:08477 DoSeek(base::TimeDelta::FromSecondsD(seconds), true);
478}
479
480void WebMediaPlayerImpl::DoSeek(base::TimeDelta time, bool time_updated) {
481 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]d43ed912009-02-03 04:52:53482
hubbed5f36882016-01-15 22:40:37483#if defined(OS_ANDROID) // WMPI_CAST
484 if (isRemote()) {
sandersd1c0bba02016-03-04 23:14:08485 cast_impl_.seek(time);
hubbed5f36882016-01-15 22:40:37486 return;
487 }
488#endif
489
srirama.mccf671812015-01-08 11:59:13490 ReadyState old_state = ready_state_;
[email protected]1bb666802013-11-28 06:12:08491 if (ready_state_ > WebMediaPlayer::ReadyStateHaveMetadata)
492 SetReadyState(WebMediaPlayer::ReadyStateHaveMetadata);
493
sandersd1c0bba02016-03-04 23:14:08494 // When paused, we know exactly what the current time is and can elide seeks
495 // to it. However, there are two cases that are not elided:
496 // 1) When the pipeline state is not stable.
497 // In this case we just let |pipeline_controller_| decide what to do, as
498 // it has complete information.
499 // 2) For MSE.
500 // Because the buffers may have changed between seeks, MSE seeks are
501 // never elided.
502 if (paused_ && pipeline_controller_.IsStable() && paused_time_ == time &&
503 !chunk_demuxer_) {
504 // If the ready state was high enough before, we can indicate that the seek
505 // completed just by restoring it. Otherwise we will just wait for the real
506 // ready state change to eventually happen.
507 if (old_state == ReadyStateHaveEnoughData) {
srirama.m8f4a37562014-12-13 08:16:18508 main_task_runner_->PostTask(
alokp967c902452016-05-06 05:21:37509 FROM_HERE, base::Bind(&WebMediaPlayerImpl::OnBufferingStateChange,
510 AsWeakPtr(), BUFFERING_HAVE_ENOUGH));
srirama.m36ab2682014-12-11 04:20:01511 }
sandersd1c0bba02016-03-04 23:14:08512 return;
srirama.m36ab2682014-12-11 04:20:01513 }
[email protected]44ff37c02009-10-24 01:03:03514
dalecurtis04bdb582016-08-17 22:15:23515 // Call this before setting |seeking_| so that the current media time can be
516 // recorded by the reporter.
517 if (watch_time_reporter_)
518 watch_time_reporter_->OnSeeking();
519
sandersd50a635e2016-04-04 22:50:09520 // TODO(sandersd): Ideally we would not clear the idle state if
521 // |pipeline_controller_| can elide the seek.
522 is_idle_ = false;
523 ended_ = false;
524
[email protected]b3766a22010-12-22 17:34:13525 seeking_ = true;
sandersd1c0bba02016-03-04 23:14:08526 seek_time_ = time;
527 if (paused_)
528 paused_time_ = time;
529 pipeline_controller_.Seek(time, time_updated);
[email protected]b3766a22010-12-22 17:34:13530
sandersd50a635e2016-04-04 22:50:09531 // This needs to be called after Seek() so that if a resume is triggered, it
532 // is to the correct time.
533 UpdatePlayState();
[email protected]ec9212f2008-12-18 21:40:36534}
535
[email protected]39bdde32013-04-17 17:44:20536void WebMediaPlayerImpl::setRate(double rate) {
pkastingf5279482016-07-27 02:18:20537 DVLOG(1) << __func__ << "(" << rate << ")";
acolwellb4034942014-08-28 15:42:43538 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]d43ed912009-02-03 04:52:53539
[email protected]378f0b72009-08-11 17:11:42540 // TODO(kylep): Remove when support for negatives is added. Also, modify the
541 // following checks so rewind uses reasonable values also.
[email protected]39bdde32013-04-17 17:44:20542 if (rate < 0.0)
[email protected]378f0b72009-08-11 17:11:42543 return;
544
545 // Limit rates to reasonable values by clamping.
[email protected]39bdde32013-04-17 17:44:20546 if (rate != 0.0) {
[email protected]378f0b72009-08-11 17:11:42547 if (rate < kMinRate)
548 rate = kMinRate;
549 else if (rate > kMaxRate)
550 rate = kMaxRate;
551 }
552
[email protected]49480902009-07-14 20:23:43553 playback_rate_ = rate;
554 if (!paused_) {
[email protected]f6af7592014-02-28 10:09:11555 pipeline_.SetPlaybackRate(rate);
[email protected]039b7542013-10-17 22:06:25556 if (data_source_)
557 data_source_->MediaPlaybackRateChanged(rate);
[email protected]49480902009-07-14 20:23:43558 }
[email protected]ec9212f2008-12-18 21:40:36559}
560
[email protected]39bdde32013-04-17 17:44:20561void WebMediaPlayerImpl::setVolume(double volume) {
pkastingf5279482016-07-27 02:18:20562 DVLOG(1) << __func__ << "(" << volume << ")";
acolwellb4034942014-08-28 15:42:43563 DCHECK(main_task_runner_->BelongsToCurrentThread());
dalecurtisbb3eaac2016-01-27 21:10:25564 volume_ = volume;
565 pipeline_.SetVolume(volume_ * volume_multiplier_);
dalecurtis04bdb582016-08-17 22:15:23566 if (watch_time_reporter_)
567 watch_time_reporter_->OnVolumeChange(volume);
mlamouri910111362016-11-04 11:28:24568
569 // The play state is updated because the player might have left the autoplay
570 // muted state.
571 UpdatePlayState();
[email protected]ec9212f2008-12-18 21:40:36572}
[email protected]f0a51fb52009-03-05 12:46:38573
guidouc7babef2015-10-22 00:42:35574void WebMediaPlayerImpl::setSinkId(
575 const blink::WebString& sink_id,
576 const blink::WebSecurityOrigin& security_origin,
577 blink::WebSetSinkIdCallbacks* web_callback) {
guidou69223ce2015-06-16 10:36:19578 DCHECK(main_task_runner_->BelongsToCurrentThread());
pkastingf5279482016-07-27 02:18:20579 DVLOG(1) << __func__;
guidouc7babef2015-10-22 00:42:35580
olka68b69392016-04-01 11:42:12581 media::OutputDeviceStatusCB callback =
582 media::ConvertToOutputDeviceStatusCB(web_callback);
guidouc7babef2015-10-22 00:42:35583 media_task_runner_->PostTask(
584 FROM_HERE,
585 base::Bind(&SetSinkIdOnMediaThread, audio_source_provider_,
586 sink_id.utf8(), static_cast<url::Origin>(security_origin),
587 callback));
guidou69223ce2015-06-16 10:36:19588}
589
dalecurtisb6e052f52016-08-25 00:35:55590STATIC_ASSERT_ENUM(WebMediaPlayer::PreloadNone, MultibufferDataSource::NONE);
danakj365175c2016-02-06 00:37:37591STATIC_ASSERT_ENUM(WebMediaPlayer::PreloadMetaData,
dalecurtisb6e052f52016-08-25 00:35:55592 MultibufferDataSource::METADATA);
593STATIC_ASSERT_ENUM(WebMediaPlayer::PreloadAuto, MultibufferDataSource::AUTO);
[email protected]23a8b1d82011-04-05 16:28:20594
[email protected]ef405f66b2012-04-18 02:39:55595void WebMediaPlayerImpl::setPreload(WebMediaPlayer::Preload preload) {
pkastingf5279482016-07-27 02:18:20596 DVLOG(1) << __func__ << "(" << preload << ")";
acolwellb4034942014-08-28 15:42:43597 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]4e6be3f2009-05-07 02:24:44598
dalecurtisb6e052f52016-08-25 00:35:55599 preload_ = static_cast<MultibufferDataSource::Preload>(preload);
[email protected]b49beeb2013-03-01 20:04:00600 if (data_source_)
[email protected]09c60222014-08-07 16:42:31601 data_source_->SetPreload(preload_);
[email protected]4e6be3f2009-05-07 02:24:44602}
603
danakj365175c2016-02-06 00:37:37604STATIC_ASSERT_ENUM(WebMediaPlayer::BufferingStrategy::Normal,
dalecurtisb6e052f52016-08-25 00:35:55605 MultibufferDataSource::BUFFERING_STRATEGY_NORMAL);
danakj365175c2016-02-06 00:37:37606STATIC_ASSERT_ENUM(WebMediaPlayer::BufferingStrategy::Aggressive,
dalecurtisb6e052f52016-08-25 00:35:55607 MultibufferDataSource::BUFFERING_STRATEGY_AGGRESSIVE);
sandersdc6ab163a2015-12-12 03:56:13608
609void WebMediaPlayerImpl::setBufferingStrategy(
610 WebMediaPlayer::BufferingStrategy buffering_strategy) {
pkastingf5279482016-07-27 02:18:20611 DVLOG(1) << __func__;
sandersdc6ab163a2015-12-12 03:56:13612 DCHECK(main_task_runner_->BelongsToCurrentThread());
613
dalecurtis37fe5862016-03-15 19:29:09614#if defined(OS_ANDROID)
615 // We disallow aggressive buffering on Android since it matches the behavior
616 // of the platform media player and may have data usage penalties.
617 // TODO(dalecurtis, hubbe): We should probably stop using "pause-and-buffer"
618 // everywhere. See http://crbug.com/594669 for more details.
dalecurtisb6e052f52016-08-25 00:35:55619 buffering_strategy_ = MultibufferDataSource::BUFFERING_STRATEGY_NORMAL;
dalecurtis37fe5862016-03-15 19:29:09620#else
sandersdc6ab163a2015-12-12 03:56:13621 buffering_strategy_ =
dalecurtisb6e052f52016-08-25 00:35:55622 static_cast<MultibufferDataSource::BufferingStrategy>(buffering_strategy);
dalecurtis37fe5862016-03-15 19:29:09623#endif
624
sandersdc6ab163a2015-12-12 03:56:13625 if (data_source_)
626 data_source_->SetBufferingStrategy(buffering_strategy_);
627}
628
[email protected]4e6be3f2009-05-07 02:24:44629bool WebMediaPlayerImpl::hasVideo() const {
acolwellb4034942014-08-28 15:42:43630 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]d43ed912009-02-03 04:52:53631
[email protected]b8877772014-03-26 20:17:15632 return pipeline_metadata_.has_video;
[email protected]d43ed912009-02-03 04:52:53633}
634
[email protected]fc367af2009-08-14 23:06:35635bool WebMediaPlayerImpl::hasAudio() const {
acolwellb4034942014-08-28 15:42:43636 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]fc367af2009-08-14 23:06:35637
[email protected]b8877772014-03-26 20:17:15638 return pipeline_metadata_.has_audio;
[email protected]fc367af2009-08-14 23:06:35639}
640
servolkf25ceed2016-07-01 03:44:38641void WebMediaPlayerImpl::enabledAudioTracksChanged(
642 const blink::WebVector<blink::WebMediaPlayer::TrackId>& enabledTrackIds) {
643 DCHECK(main_task_runner_->BelongsToCurrentThread());
644
645 std::ostringstream logstr;
646 std::vector<MediaTrack::Id> enabledMediaTrackIds;
647 for (const auto& blinkTrackId : enabledTrackIds) {
648 MediaTrack::Id track_id = blinkTrackId.utf8().data();
649 logstr << track_id << " ";
650 enabledMediaTrackIds.push_back(track_id);
651 }
652 MEDIA_LOG(INFO, media_log_) << "Enabled audio tracks: [" << logstr.str()
653 << "]";
654 pipeline_.OnEnabledAudioTracksChanged(enabledMediaTrackIds);
655}
656
657void WebMediaPlayerImpl::selectedVideoTrackChanged(
658 blink::WebMediaPlayer::TrackId* selectedTrackId) {
659 DCHECK(main_task_runner_->BelongsToCurrentThread());
660
661 std::ostringstream logstr;
662 std::vector<MediaTrack::Id> selectedVideoMediaTrackId;
avayvod39c102402016-11-23 21:43:13663 bool canAddVideoTrack =
664 !IsBackgroundVideoTrackOptimizationEnabled() || !IsHidden();
665 if (selectedTrackId && canAddVideoTrack) {
servolkf25ceed2016-07-01 03:44:38666 selectedVideoMediaTrackId.push_back(selectedTrackId->utf8().data());
667 logstr << selectedVideoMediaTrackId[0];
668 }
669 MEDIA_LOG(INFO, media_log_) << "Selected video track: [" << logstr.str()
670 << "]";
671 pipeline_.OnSelectedVideoTrackChanged(selectedVideoMediaTrackId);
672}
673
[email protected]180ef242013-11-07 06:50:46674blink::WebSize WebMediaPlayerImpl::naturalSize() const {
acolwellb4034942014-08-28 15:42:43675 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]d43ed912009-02-03 04:52:53676
[email protected]b8877772014-03-26 20:17:15677 return blink::WebSize(pipeline_metadata_.natural_size);
[email protected]d43ed912009-02-03 04:52:53678}
679
[email protected]4e6be3f2009-05-07 02:24:44680bool WebMediaPlayerImpl::paused() const {
acolwellb4034942014-08-28 15:42:43681 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]d43ed912009-02-03 04:52:53682
hubbed5f36882016-01-15 22:40:37683#if defined(OS_ANDROID) // WMPI_CAST
684 if (isRemote())
685 return cast_impl_.paused();
686#endif
sandersd50a635e2016-04-04 22:50:09687
[email protected]f6af7592014-02-28 10:09:11688 return pipeline_.GetPlaybackRate() == 0.0f;
[email protected]d43ed912009-02-03 04:52:53689}
690
[email protected]4e6be3f2009-05-07 02:24:44691bool WebMediaPlayerImpl::seeking() const {
acolwellb4034942014-08-28 15:42:43692 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]d43ed912009-02-03 04:52:53693
[email protected]ef405f66b2012-04-18 02:39:55694 if (ready_state_ == WebMediaPlayer::ReadyStateHaveNothing)
[email protected]0acebfa2009-08-21 22:45:40695 return false;
[email protected]67cd5052009-09-10 21:53:22696
[email protected]b3766a22010-12-22 17:34:13697 return seeking_;
[email protected]ec9212f2008-12-18 21:40:36698}
699
[email protected]39bdde32013-04-17 17:44:20700double WebMediaPlayerImpl::duration() const {
acolwellb4034942014-08-28 15:42:43701 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]39bdde32013-04-17 17:44:20702
703 if (ready_state_ == WebMediaPlayer::ReadyStateHaveNothing)
704 return std::numeric_limits<double>::quiet_NaN();
705
[email protected]39bdde32013-04-17 17:44:20706 return GetPipelineDuration();
[email protected]d43ed912009-02-03 04:52:53707}
708
[email protected]db66d0092014-04-16 07:15:12709double WebMediaPlayerImpl::timelineOffset() const {
acolwellb4034942014-08-28 15:42:43710 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]db66d0092014-04-16 07:15:12711
712 if (pipeline_metadata_.timeline_offset.is_null())
713 return std::numeric_limits<double>::quiet_NaN();
714
715 return pipeline_metadata_.timeline_offset.ToJsTime();
716}
717
[email protected]39bdde32013-04-17 17:44:20718double WebMediaPlayerImpl::currentTime() const {
acolwellb4034942014-08-28 15:42:43719 DCHECK(main_task_runner_->BelongsToCurrentThread());
scherkusd2c745b2014-09-04 05:03:40720 DCHECK_NE(ready_state_, WebMediaPlayer::ReadyStateHaveNothing);
721
722 // TODO(scherkus): Replace with an explicit ended signal to HTMLMediaElement,
723 // see http://crbug.com/409280
724 if (ended_)
725 return duration();
726
sandersd1c0bba02016-03-04 23:14:08727 if (seeking())
728 return seek_time_.InSecondsF();
wolenetz1b2ae7d2015-06-10 00:44:21729
hubbed5f36882016-01-15 22:40:37730#if defined(OS_ANDROID) // WMPI_CAST
sandersd1c0bba02016-03-04 23:14:08731 if (isRemote())
hubbed5f36882016-01-15 22:40:37732 return cast_impl_.currentTime();
hubbed5f36882016-01-15 22:40:37733#endif
734
sandersd1c0bba02016-03-04 23:14:08735 if (paused_)
hubbed5f36882016-01-15 22:40:37736 return paused_time_.InSecondsF();
hubbed5f36882016-01-15 22:40:37737
738 return pipeline_.GetMediaTime().InSecondsF();
[email protected]d43ed912009-02-03 04:52:53739}
740
danakj13afe0362016-02-27 01:22:50741WebMediaPlayer::NetworkState WebMediaPlayerImpl::getNetworkState() const {
acolwellb4034942014-08-28 15:42:43742 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]ddb1e5a2010-12-13 20:10:45743 return network_state_;
744}
745
danakj13afe0362016-02-27 01:22:50746WebMediaPlayer::ReadyState WebMediaPlayerImpl::getReadyState() const {
acolwellb4034942014-08-28 15:42:43747 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]ddb1e5a2010-12-13 20:10:45748 return ready_state_;
749}
750
wolenetz4d39cc02016-04-05 19:54:41751blink::WebString WebMediaPlayerImpl::getErrorMessage() {
752 DCHECK(main_task_runner_->BelongsToCurrentThread());
753 return blink::WebString::fromUTF8(media_log_->GetLastErrorMessage());
754}
755
[email protected]02022fc2014-05-16 00:05:31756blink::WebTimeRanges WebMediaPlayerImpl::buffered() const {
acolwellb4034942014-08-28 15:42:43757 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]779a8322014-08-22 21:28:37758
acolwell9e0840d2014-09-06 19:01:32759 Ranges<base::TimeDelta> buffered_time_ranges =
[email protected]02022fc2014-05-16 00:05:31760 pipeline_.GetBufferedTimeRanges();
[email protected]779a8322014-08-22 21:28:37761
762 const base::TimeDelta duration = pipeline_.GetMediaDuration();
dalecurtis39a7f932016-07-19 18:34:59763 if (duration != kInfiniteDuration) {
[email protected]779a8322014-08-22 21:28:37764 buffered_data_source_host_.AddBufferedTimeRanges(
765 &buffered_time_ranges, duration);
766 }
[email protected]02022fc2014-05-16 00:05:31767 return ConvertToWebTimeRanges(buffered_time_ranges);
768}
769
philipjb0e6f3f2014-09-30 09:51:53770blink::WebTimeRanges WebMediaPlayerImpl::seekable() const {
acolwellb4034942014-08-28 15:42:43771 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]39bdde32013-04-17 17:44:20772
dalecurtis56359cb2014-10-28 00:06:29773 if (ready_state_ < WebMediaPlayer::ReadyStateHaveMetadata)
philipjb0e6f3f2014-09-30 09:51:53774 return blink::WebTimeRanges();
775
dalecurtis56359cb2014-10-28 00:06:29776 const double seekable_end = duration();
777
778 // Allow a special exception for seeks to zero for streaming sources with a
779 // finite duration; this allows looping to work.
780 const bool allow_seek_to_zero = data_source_ && data_source_->IsStreaming() &&
mateuszs3371ab02015-04-24 13:20:23781 std::isfinite(seekable_end);
dalecurtis56359cb2014-10-28 00:06:29782
783 // TODO(dalecurtis): Technically this allows seeking on media which return an
784 // infinite duration so long as DataSource::IsStreaming() is false. While not
785 // expected, disabling this breaks semi-live players, http://crbug.com/427412.
786 const blink::WebTimeRange seekable_range(
787 0.0, allow_seek_to_zero ? 0.0 : seekable_end);
philipjb0e6f3f2014-09-30 09:51:53788 return blink::WebTimeRanges(&seekable_range, 1);
[email protected]ec9212f2008-12-18 21:40:36789}
790
[email protected]5d2b3e4c2014-05-12 23:27:30791bool WebMediaPlayerImpl::didLoadingProgress() {
acolwellb4034942014-08-28 15:42:43792 DCHECK(main_task_runner_->BelongsToCurrentThread());
dalecurtise7120dc2016-09-03 02:54:35793
794 // Note: Separate variables used to ensure both methods are called every time.
795 const bool pipeline_progress = pipeline_.DidLoadingProgress();
796 const bool data_progress = buffered_data_source_host_.DidLoadingProgress();
797 const bool did_loading_progress = pipeline_progress || data_progress;
798
799 // If we've idle suspended before reaching kHaveFutureData and loading has
800 // progressed we need to spin up the renderer and figure out if we have enough
801 // data yet; |client_| may be waiting on this signal to trigger playback. The
802 // idle timeout is long enough that this is a low-cost operation.
803 if (highest_ready_state_ < ReadyState::ReadyStateHaveFutureData &&
804 pipeline_controller_.IsSuspended() && did_loading_progress && is_idle_) {
805 is_idle_ = false;
806 UpdatePlayState();
807 }
808
watkd026f792016-11-05 00:28:51809 if (did_loading_progress)
810 last_time_loading_progressed_ = tick_clock_->NowTicks();
811
dalecurtise7120dc2016-09-03 02:54:35812 return did_loading_progress;
[email protected]d43ed912009-02-03 04:52:53813}
814
[email protected]dd5c7972014-08-21 15:00:37815void WebMediaPlayerImpl::paint(blink::WebCanvas* canvas,
816 const blink::WebRect& rect,
xidachen0ebd94d2016-09-07 15:47:22817 SkPaint& paint) {
acolwellb4034942014-08-28 15:42:43818 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]dd061e12014-05-06 19:21:22819 TRACE_EVENT0("media", "WebMediaPlayerImpl:paint");
[email protected]4e6be3f2009-05-07 02:24:44820
xhwang213e50c2016-10-10 23:56:31821 // TODO(sandersd): Move this check into GetCurrentFrameFromCompositor() when
822 // we have other ways to check if decoder owns video frame.
823 // See http://crbug.com/595716 and http://crbug.com/602708
jrummelle616ee92016-10-08 02:15:44824 if (cdm_)
xhwang80739452016-01-13 00:48:00825 return;
826
mcasasf1236fc22015-05-29 22:38:56827 scoped_refptr<VideoFrame> video_frame = GetCurrentFrameFromCompositor();
[email protected]0fe5d43b2014-01-24 23:32:45828
[email protected]b49beeb2013-03-01 20:04:00829 gfx::Rect gfx_rect(rect);
dongseong.hwang0c4e9d82015-01-08 20:11:13830 Context3D context_3d;
mcasas265bdbf82015-06-12 18:44:07831 if (video_frame.get() && video_frame->HasTextures()) {
mcasasf1236fc22015-05-29 22:38:56832 if (!context_3d_cb_.is_null())
dongseong.hwang0c4e9d82015-01-08 20:11:13833 context_3d = context_3d_cb_.Run();
dongseong.hwang0c4e9d82015-01-08 20:11:13834 if (!context_3d.gl)
danakj53f7ec902016-05-21 01:30:10835 return; // Unable to get/create a shared main thread context.
836 if (!context_3d.gr_context)
837 return; // The context has been lost since and can't setup a GrContext.
dongseong.hwang0c4e9d82015-01-08 20:11:13838 }
danakj795f1732015-08-31 23:40:22839 skcanvas_video_renderer_.Paint(video_frame, canvas, gfx::RectF(gfx_rect),
xidachen0ebd94d2016-09-07 15:47:22840 paint, pipeline_metadata_.video_rotation,
danakj795f1732015-08-31 23:40:22841 context_3d);
[email protected]ec9212f2008-12-18 21:40:36842}
[email protected]5df51652009-01-17 00:03:00843
[email protected]38259a7a82009-07-29 21:49:49844bool WebMediaPlayerImpl::hasSingleSecurityOrigin() const {
[email protected]b49beeb2013-03-01 20:04:00845 if (data_source_)
846 return data_source_->HasSingleOrigin();
[email protected]fcdb7462009-10-21 21:05:11847 return true;
[email protected]38259a7a82009-07-29 21:49:49848}
849
[email protected]3fe27112012-06-07 04:00:01850bool WebMediaPlayerImpl::didPassCORSAccessCheck() const {
[email protected]b49beeb2013-03-01 20:04:00851 if (data_source_)
852 return data_source_->DidPassCORSAccessCheck();
853 return false;
[email protected]3fe27112012-06-07 04:00:01854}
855
[email protected]39bdde32013-04-17 17:44:20856double WebMediaPlayerImpl::mediaTimeForTimeValue(double timeValue) const {
qinminb4c39782015-08-10 18:43:24857 return base::TimeDelta::FromSecondsD(timeValue).InSecondsF();
[email protected]e06e16d82011-05-26 22:13:33858}
859
[email protected]d82b18ae2011-03-23 21:28:59860unsigned WebMediaPlayerImpl::decodedFrameCount() const {
acolwellb4034942014-08-28 15:42:43861 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]4c51bc662011-02-16 02:03:16862
acolwell9e0840d2014-09-06 19:01:32863 PipelineStatistics stats = pipeline_.GetStatistics();
[email protected]4c51bc662011-02-16 02:03:16864 return stats.video_frames_decoded;
865}
866
[email protected]d82b18ae2011-03-23 21:28:59867unsigned WebMediaPlayerImpl::droppedFrameCount() const {
acolwellb4034942014-08-28 15:42:43868 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]4c51bc662011-02-16 02:03:16869
acolwell9e0840d2014-09-06 19:01:32870 PipelineStatistics stats = pipeline_.GetStatistics();
[email protected]dd061e12014-05-06 19:21:22871 return stats.video_frames_dropped;
[email protected]4c51bc662011-02-16 02:03:16872}
873
chakshu.a94326b72016-03-08 05:11:44874size_t WebMediaPlayerImpl::audioDecodedByteCount() const {
acolwellb4034942014-08-28 15:42:43875 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]4c51bc662011-02-16 02:03:16876
acolwell9e0840d2014-09-06 19:01:32877 PipelineStatistics stats = pipeline_.GetStatistics();
[email protected]4c51bc662011-02-16 02:03:16878 return stats.audio_bytes_decoded;
879}
880
chakshu.a94326b72016-03-08 05:11:44881size_t WebMediaPlayerImpl::videoDecodedByteCount() const {
acolwellb4034942014-08-28 15:42:43882 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]4c51bc662011-02-16 02:03:16883
acolwell9e0840d2014-09-06 19:01:32884 PipelineStatistics stats = pipeline_.GetStatistics();
[email protected]4c51bc662011-02-16 02:03:16885 return stats.video_bytes_decoded;
886}
887
[email protected]6523b242013-03-13 11:10:07888bool WebMediaPlayerImpl::copyVideoTextureToPlatformTexture(
danakj46070b02016-03-28 21:54:11889 gpu::gles2::GLES2Interface* gl,
zmo57d577a2015-10-30 18:28:59890 unsigned int texture,
891 unsigned int internal_format,
892 unsigned int type,
893 bool premultiply_alpha,
894 bool flip_y) {
xhwang213e50c2016-10-10 23:56:31895 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]bfc05f22013-10-19 17:55:16896 TRACE_EVENT0("media", "WebMediaPlayerImpl:copyVideoTextureToPlatformTexture");
897
xhwang213e50c2016-10-10 23:56:31898 // TODO(sandersd): Move this check into GetCurrentFrameFromCompositor() when
899 // we have other ways to check if decoder owns video frame.
900 // See http://crbug.com/595716 and http://crbug.com/602708
901 if (cdm_)
902 return false;
[email protected]dd061e12014-05-06 19:21:22903
xhwang213e50c2016-10-10 23:56:31904 scoped_refptr<VideoFrame> video_frame = GetCurrentFrameFromCompositor();
jbauman581d041c2016-07-21 01:01:03905 if (!video_frame.get() || !video_frame->HasTextures()) {
[email protected]e56f88c72013-06-25 22:31:29906 return false;
dongseong.hwang0c4e9d82015-01-08 20:11:13907 }
[email protected]df41e252014-02-03 23:39:50908
jbauman581d041c2016-07-21 01:01:03909 Context3D context_3d;
910 if (!context_3d_cb_.is_null())
911 context_3d = context_3d_cb_.Run();
912 return skcanvas_video_renderer_.CopyVideoFrameTexturesToGLTexture(
913 context_3d, gl, video_frame.get(), texture, internal_format, type,
914 premultiply_alpha, flip_y);
[email protected]6523b242013-03-13 11:10:07915}
916
[email protected]7bce1832014-01-09 00:01:22917void WebMediaPlayerImpl::setContentDecryptionModule(
[email protected]9ebc3b03f2014-08-13 04:01:23918 blink::WebContentDecryptionModule* cdm,
919 blink::WebContentDecryptionModuleResult result) {
acolwellb4034942014-08-28 15:42:43920 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]9ebc3b03f2014-08-13 04:01:23921
jrummell06f27072015-06-08 18:12:38922 // Once the CDM is set it can't be cleared as there may be frames being
923 // decrypted on other threads. So fail this request.
924 // http://crbug.com/462365#c7.
xhwang97de4202014-11-25 08:44:01925 if (!cdm) {
926 result.completeWithError(
jrummell06f27072015-06-08 18:12:38927 blink::WebContentDecryptionModuleExceptionInvalidStateError, 0,
xhwang79b193042016-12-13 18:52:43928 "The existing ContentDecryptionModule object cannot be removed at this "
929 "time.");
xhwang97de4202014-11-25 08:44:01930 return;
931 }
932
jrummell89e61d82015-07-23 20:03:34933 // Create a local copy of |result| to avoid problems with the callback
934 // getting passed to the media thread and causing |result| to be destructed
jrummell4acbec912016-02-27 02:45:03935 // on the wrong thread in some failure conditions. Blink should prevent
936 // multiple simultaneous calls.
937 DCHECK(!set_cdm_result_);
jrummell89e61d82015-07-23 20:03:34938 set_cdm_result_.reset(new blink::WebContentDecryptionModuleResult(result));
939
dalecurtis04bdb582016-08-17 22:15:23940 // Recreate the watch time reporter if necessary.
941 const bool was_encrypted = is_encrypted_;
942 is_encrypted_ = true;
943 if (!was_encrypted && watch_time_reporter_)
944 CreateWatchTimeReporter();
945
jrummelle616ee92016-10-08 02:15:44946 SetCdm(cdm);
xhwang97de4202014-11-25 08:44:01947}
948
xhwange8c4181a2014-12-06 08:10:01949void WebMediaPlayerImpl::OnEncryptedMediaInitData(
jrummellcf78967c2015-04-03 05:03:58950 EmeInitDataType init_data_type,
Avi Drissman97785ea2015-12-19 01:11:31951 const std::vector<uint8_t>& init_data) {
jrummellcf78967c2015-04-03 05:03:58952 DCHECK(init_data_type != EmeInitDataType::UNKNOWN);
xhwangbab66f52014-12-02 23:49:50953
ddorwin301ccdb2016-02-25 02:39:17954 // TODO(xhwang): Update this UMA name. https://crbug.com/589251
xhwangbab66f52014-12-02 23:49:50955 UMA_HISTOGRAM_COUNTS("Media.EME.NeedKey", 1);
956
dalecurtis04bdb582016-08-17 22:15:23957 // Recreate the watch time reporter if necessary.
958 const bool was_encrypted = is_encrypted_;
959 is_encrypted_ = true;
960 if (!was_encrypted && watch_time_reporter_)
961 CreateWatchTimeReporter();
962
srirama.m26f864d02015-07-14 05:21:46963 encrypted_client_->encrypted(
davidbenb50f00c2015-12-01 00:01:50964 ConvertToWebInitDataType(init_data_type), init_data.data(),
srirama.m26f864d02015-07-14 05:21:46965 base::saturated_cast<unsigned int>(init_data.size()));
xhwangbab66f52014-12-02 23:49:50966}
967
servolk81e01e02016-03-05 03:29:15968void WebMediaPlayerImpl::OnFFmpegMediaTracksUpdated(
dcheng3076abbf2016-04-22 20:42:39969 std::unique_ptr<MediaTracks> tracks) {
servolk81e01e02016-03-05 03:29:15970 // For MSE/chunk_demuxer case the media track updates are handled by
971 // WebSourceBufferImpl.
972 DCHECK(demuxer_.get());
973 DCHECK(!chunk_demuxer_);
servolkef1e5ef2016-03-25 04:55:26974
975 // Report the media track information to blink.
976 for (const auto& track : tracks->tracks()) {
977 if (track->type() == MediaTrack::Audio) {
servolkfa5c37c2016-06-16 17:56:47978 client_->addAudioTrack(blink::WebString::fromUTF8(track->id()),
979 blink::WebMediaPlayerClient::AudioTrackKindMain,
980 blink::WebString::fromUTF8(track->label()),
981 blink::WebString::fromUTF8(track->language()),
982 /*enabled*/ true);
servolkef1e5ef2016-03-25 04:55:26983 } else if (track->type() == MediaTrack::Video) {
servolkfa5c37c2016-06-16 17:56:47984 client_->addVideoTrack(blink::WebString::fromUTF8(track->id()),
985 blink::WebMediaPlayerClient::VideoTrackKindMain,
986 blink::WebString::fromUTF8(track->label()),
987 blink::WebString::fromUTF8(track->language()),
988 /*selected*/ true);
servolkef1e5ef2016-03-25 04:55:26989 } else {
990 // Text tracks are not supported through this code path yet.
991 NOTREACHED();
992 }
993 }
servolk81e01e02016-03-05 03:29:15994}
995
jrummelle616ee92016-10-08 02:15:44996void WebMediaPlayerImpl::SetCdm(blink::WebContentDecryptionModule* cdm) {
997 DCHECK(main_task_runner_->BelongsToCurrentThread());
998 DCHECK(cdm);
xhwang79b193042016-12-13 18:52:43999 scoped_refptr<ContentDecryptionModule> cdm_reference =
jrummelle616ee92016-10-08 02:15:441000 ToWebContentDecryptionModuleImpl(cdm)->GetCdm();
1001 if (!cdm_reference) {
1002 NOTREACHED();
1003 OnCdmAttached(false);
xhwang80739452016-01-13 00:48:001004 return;
1005 }
1006
jrummelle616ee92016-10-08 02:15:441007 CdmContext* cdm_context = cdm_reference->GetCdmContext();
1008 if (!cdm_context) {
1009 OnCdmAttached(false);
1010 return;
1011 }
1012
xjzd3fe45a2016-10-12 18:26:371013 if (observer_)
1014 observer_->OnSetCdm(cdm_context);
1015
jrummelle616ee92016-10-08 02:15:441016 // Keep the reference to the CDM, as it shouldn't be destroyed until
1017 // after the pipeline is done with the |cdm_context|.
1018 pending_cdm_ = std::move(cdm_reference);
1019 pipeline_.SetCdm(cdm_context,
1020 base::Bind(&WebMediaPlayerImpl::OnCdmAttached, AsWeakPtr()));
xhwang97de4202014-11-25 08:44:011021}
1022
jrummell89e61d82015-07-23 20:03:341023void WebMediaPlayerImpl::OnCdmAttached(bool success) {
jrummelle616ee92016-10-08 02:15:441024 DCHECK(main_task_runner_->BelongsToCurrentThread());
1025 DCHECK(pending_cdm_);
1026
1027 // If the CDM is set from the constructor there is no promise
1028 // (|set_cdm_result_|) to fulfill.
xhwang97de4202014-11-25 08:44:011029 if (success) {
jrummelle616ee92016-10-08 02:15:441030 // This will release the previously attached CDM (if any).
1031 cdm_ = std::move(pending_cdm_);
1032 if (set_cdm_result_) {
1033 set_cdm_result_->complete();
1034 set_cdm_result_.reset();
1035 }
1036
xhwang97de4202014-11-25 08:44:011037 return;
1038 }
1039
jrummelle616ee92016-10-08 02:15:441040 pending_cdm_ = nullptr;
1041 if (set_cdm_result_) {
1042 set_cdm_result_->completeWithError(
1043 blink::WebContentDecryptionModuleExceptionNotSupportedError, 0,
xhwang79b193042016-12-13 18:52:431044 "Unable to set ContentDecryptionModule object");
jrummelle616ee92016-10-08 02:15:441045 set_cdm_result_.reset();
1046 }
[email protected]9ebc3b03f2014-08-13 04:01:231047}
1048
sandersd1c0bba02016-03-04 23:14:081049void WebMediaPlayerImpl::OnPipelineSeeked(bool time_updated) {
[email protected]5d11eff2011-09-15 00:06:061050 seeking_ = false;
wolenetz1b2ae7d2015-06-10 00:44:211051 seek_time_ = base::TimeDelta();
hubbe5a2dec022016-03-17 01:14:231052 if (paused_) {
1053#if defined(OS_ANDROID) // WMPI_CAST
1054 if (isRemote()) {
1055 paused_time_ = base::TimeDelta::FromSecondsD(cast_impl_.currentTime());
1056 } else {
1057 paused_time_ = pipeline_.GetMediaTime();
1058 }
1059#else
sandersd1c0bba02016-03-04 23:14:081060 paused_time_ = pipeline_.GetMediaTime();
hubbe5a2dec022016-03-17 01:14:231061#endif
dalecurtis04bdb582016-08-17 22:15:231062 } else {
1063 DCHECK(watch_time_reporter_);
1064 watch_time_reporter_->OnPlaying();
hubbe5a2dec022016-03-17 01:14:231065 }
sandersd1c0bba02016-03-04 23:14:081066 if (time_updated)
1067 should_notify_time_changed_ = true;
dalecurtisaf34d8712016-09-20 04:32:261068
1069 // Reset underflow count upon seek; this prevents looping videos and user
1070 // actions from artificially inflating the underflow count.
1071 underflow_count_ = 0;
[email protected]8931c41a2009-07-07 17:31:491072}
1073
sandersd1c0bba02016-03-04 23:14:081074void WebMediaPlayerImpl::OnPipelineSuspended() {
hubbed5f36882016-01-15 22:40:371075#if defined(OS_ANDROID)
1076 if (isRemote()) {
1077 scoped_refptr<VideoFrame> frame = cast_impl_.GetCastingBanner();
sandersd50a635e2016-04-04 22:50:091078 if (frame)
dalecurtise9c89e92016-05-20 19:38:001079 compositor_->PaintSingleFrame(frame);
hubbed5f36882016-01-15 22:40:371080 }
1081#endif
1082
dalecurtis37fe5862016-03-15 19:29:091083 // If we're not in an aggressive buffering state, tell the data source we have
1084 // enough data so that it may release the connection.
1085 if (buffering_strategy_ !=
dalecurtisb6e052f52016-08-25 00:35:551086 MultibufferDataSource::BUFFERING_STRATEGY_AGGRESSIVE) {
liberato3f9f32b2016-03-16 16:54:511087 if (data_source_)
1088 data_source_->OnBufferingHaveEnough(true);
dalecurtis37fe5862016-03-15 19:29:091089 }
1090
sandersd50a635e2016-04-04 22:50:091091 ReportMemoryUsage();
1092
sandersd1c0bba02016-03-04 23:14:081093 if (pending_suspend_resume_cycle_) {
watkdee516f2016-02-18 02:22:191094 pending_suspend_resume_cycle_ = false;
sandersd50a635e2016-04-04 22:50:091095 UpdatePlayState();
dalecurtis0431cbf2016-03-12 01:19:431096 }
sandersd1c0bba02016-03-04 23:14:081097}
1098
alokp967c902452016-05-06 05:21:371099void WebMediaPlayerImpl::OnDemuxerOpened() {
1100 DCHECK(main_task_runner_->BelongsToCurrentThread());
1101 client_->mediaSourceOpened(
1102 new WebMediaSourceImpl(chunk_demuxer_, media_log_));
1103}
1104
1105void WebMediaPlayerImpl::OnError(PipelineStatus status) {
pkastingf5279482016-07-27 02:18:201106 DVLOG(1) << __func__;
alokp967c902452016-05-06 05:21:371107 DCHECK(main_task_runner_->BelongsToCurrentThread());
1108 DCHECK_NE(status, PIPELINE_OK);
1109
1110 if (suppress_destruction_errors_)
1111 return;
1112
1113 ReportPipelineError(load_type_, frame_->getSecurityOrigin(), status);
1114 media_log_->AddEvent(media_log_->CreatePipelineErrorEvent(status));
1115
1116 if (ready_state_ == WebMediaPlayer::ReadyStateHaveNothing) {
1117 // Any error that occurs before reaching ReadyStateHaveMetadata should
1118 // be considered a format error.
1119 SetNetworkState(WebMediaPlayer::NetworkStateFormatError);
1120 } else {
1121 SetNetworkState(PipelineErrorToNetworkState(status));
1122 }
1123
1124 UpdatePlayState();
1125}
1126
1127void WebMediaPlayerImpl::OnEnded() {
pkastingf5279482016-07-27 02:18:201128 DVLOG(1) << __func__;
acolwellb4034942014-08-28 15:42:431129 DCHECK(main_task_runner_->BelongsToCurrentThread());
scherkusd2c745b2014-09-04 05:03:401130
sandersd1c0bba02016-03-04 23:14:081131 // Ignore state changes until we've completed all outstanding operations.
1132 if (!pipeline_controller_.IsStable())
scherkusd2c745b2014-09-04 05:03:401133 return;
1134
1135 ended_ = true;
[email protected]ce70c982013-12-20 17:04:321136 client_->timeChanged();
sandersd50a635e2016-04-04 22:50:091137
1138 // We don't actually want this to run until |client_| calls seek() or pause(),
1139 // but that should have already happened in timeChanged() and so this is
1140 // expected to be a no-op.
1141 UpdatePlayState();
[email protected]576537842009-08-12 23:52:051142}
1143
alokp967c902452016-05-06 05:21:371144void WebMediaPlayerImpl::OnMetadata(PipelineMetadata metadata) {
pkastingf5279482016-07-27 02:18:201145 DVLOG(1) << __func__;
acolwellb4034942014-08-28 15:42:431146 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]a8e2cb82012-08-17 00:02:391147
[email protected]b8877772014-03-26 20:17:151148 pipeline_metadata_ = metadata;
[email protected]739847c02014-01-16 00:12:251149
dalecurtis04bdb582016-08-17 22:15:231150 SetReadyState(WebMediaPlayer::ReadyStateHaveMetadata);
dalecurtis849cf4b22015-03-27 18:35:451151 UMA_HISTOGRAM_ENUMERATION("Media.VideoRotation", metadata.video_rotation,
acolwell9e0840d2014-09-06 19:01:321152 VIDEO_ROTATION_MAX + 1);
[email protected]21c3f7502013-03-23 03:29:511153
[email protected]b8877772014-03-26 20:17:151154 if (hasVideo()) {
sandersd2c478422016-08-02 01:19:251155 pipeline_metadata_.natural_size = GetRotatedVideoSize(
1156 pipeline_metadata_.video_rotation, pipeline_metadata_.natural_size);
[email protected]f78c3e82014-08-08 01:24:471157
tsunghungee562e92016-07-20 18:03:311158 if (overlay_enabled_ && surface_manager_)
watkf835a792016-06-24 23:24:401159 surface_manager_->NaturalSizeChanged(pipeline_metadata_.natural_size);
1160
1161 DCHECK(!video_weblayer_);
dalecurtise1edb312016-06-22 02:33:211162 video_weblayer_.reset(new cc_blink::WebLayerImpl(cc::VideoLayer::Create(
1163 compositor_, pipeline_metadata_.video_rotation)));
jbauman952274d2015-09-10 23:23:361164 video_weblayer_->layer()->SetContentsOpaque(opaque_);
1165 video_weblayer_->SetContentsOpaqueIsFixed(true);
[email protected]a7c4f582014-04-16 18:44:491166 client_->setWebLayer(video_weblayer_.get());
[email protected]a8e2cb82012-08-17 00:02:391167 }
dalecurtis8e4dc682016-03-15 02:30:301168
xjzd3fe45a2016-10-12 18:26:371169 if (observer_)
1170 observer_->OnMetadataChanged(metadata);
1171
dalecurtis04bdb582016-08-17 22:15:231172 CreateWatchTimeReporter();
sandersd50a635e2016-04-04 22:50:091173 UpdatePlayState();
[email protected]a8e2cb82012-08-17 00:02:391174}
1175
alokp967c902452016-05-06 05:21:371176void WebMediaPlayerImpl::OnBufferingStateChange(BufferingState state) {
pkastingf5279482016-07-27 02:18:201177 DVLOG(1) << __func__ << "(" << state << ")";
alokp967c902452016-05-06 05:21:371178 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]b8877772014-03-26 20:17:151179
sandersd1c0bba02016-03-04 23:14:081180 // Ignore buffering state changes until we've completed all outstanding
1181 // operations.
1182 if (!pipeline_controller_.IsStable())
[email protected]ba7d5f92014-06-24 05:37:401183 return;
[email protected]b8877772014-03-26 20:17:151184
chcunninghameb270c92016-07-15 01:00:451185 if (state == BUFFERING_HAVE_ENOUGH) {
dalecurtis821e803f2016-09-01 18:44:151186 if (data_source_ &&
1187 highest_ready_state_ < WebMediaPlayer::ReadyStateHaveEnoughData) {
1188 DCHECK_EQ(underflow_count_, 0);
1189 // Record a zero value for underflow histograms so that the histogram
1190 // includes playbacks which never encounter an underflow event.
1191 UMA_HISTOGRAM_COUNTS_100("Media.UnderflowCount", 0);
1192 UMA_HISTOGRAM_TIMES("Media.UnderflowDuration", base::TimeDelta());
1193 }
1194
chcunninghameb270c92016-07-15 01:00:451195 // TODO(chcunningham): Monitor playback position vs buffered. Potentially
1196 // transition to HAVE_FUTURE_DATA here if not enough is buffered.
1197 SetReadyState(WebMediaPlayer::ReadyStateHaveEnoughData);
[email protected]ba7d5f92014-06-24 05:37:401198
chcunninghameb270c92016-07-15 01:00:451199 // Let the DataSource know we have enough data. It may use this information
1200 // to release unused network connections.
1201 if (data_source_)
1202 data_source_->OnBufferingHaveEnough(false);
dalecurtis849cf4b22015-03-27 18:35:451203
chcunninghameb270c92016-07-15 01:00:451204 // Blink expects a timeChanged() in response to a seek().
1205 if (should_notify_time_changed_)
1206 client_->timeChanged();
dalecurtis0f0097a2015-12-01 17:40:471207
chcunninghameb270c92016-07-15 01:00:451208 // Once we have enough, start reporting the total memory usage. We'll also
1209 // report once playback starts.
1210 ReportMemoryUsage();
dalecurtis9d638a12016-08-30 06:20:551211
1212 // Report the amount of time it took to leave the underflow state. Don't
1213 // bother to report this for MSE playbacks since it's out of our control.
1214 if (underflow_timer_ && data_source_) {
1215 UMA_HISTOGRAM_TIMES("Media.UnderflowDuration",
1216 underflow_timer_->Elapsed());
1217 underflow_timer_.reset();
1218 }
chcunninghameb270c92016-07-15 01:00:451219 } else {
1220 // Buffering has underflowed.
1221 DCHECK_EQ(state, BUFFERING_HAVE_NOTHING);
dalecurtisacd77d62016-09-09 23:23:141222
1223 // Report the number of times we've entered the underflow state. Only report
1224 // for src= playback since for MSE it's out of our control. Ensure we only
1225 // report the value when transitioning from HAVE_ENOUGH to HAVE_NOTHING.
1226 if (data_source_ &&
1227 ready_state_ == WebMediaPlayer::ReadyStateHaveEnoughData) {
1228 UMA_HISTOGRAM_COUNTS_100("Media.UnderflowCount", ++underflow_count_);
1229 underflow_timer_.reset(new base::ElapsedTimer());
1230 }
1231
chcunninghameb270c92016-07-15 01:00:451232 // It shouldn't be possible to underflow if we've not advanced past
1233 // HAVE_CURRENT_DATA.
1234 DCHECK_GT(highest_ready_state_, WebMediaPlayer::ReadyStateHaveCurrentData);
1235 SetReadyState(WebMediaPlayer::ReadyStateHaveCurrentData);
1236 }
sandersd50a635e2016-04-04 22:50:091237
1238 UpdatePlayState();
[email protected]b8877772014-03-26 20:17:151239}
1240
alokp967c902452016-05-06 05:21:371241void WebMediaPlayerImpl::OnDurationChange() {
acolwellb4034942014-08-28 15:42:431242 DCHECK(main_task_runner_->BelongsToCurrentThread());
alokp967c902452016-05-06 05:21:371243
1244 // TODO(sandersd): We should call delegate_->DidPlay() with the new duration,
1245 // especially if it changed from <5s to >5s.
1246 if (ready_state_ == WebMediaPlayer::ReadyStateHaveNothing)
1247 return;
1248
1249 client_->durationChanged();
[email protected]81bb3322011-07-21 15:55:501250}
1251
alokp967c902452016-05-06 05:21:371252void WebMediaPlayerImpl::OnAddTextTrack(const TextTrackConfig& config,
1253 const AddTextTrackDoneCB& done_cb) {
acolwellb4034942014-08-28 15:42:431254 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]71537722013-05-23 06:47:531255
[email protected]8a561062013-11-22 01:19:311256 const WebInbandTextTrackImpl::Kind web_kind =
1257 static_cast<WebInbandTextTrackImpl::Kind>(config.kind());
1258 const blink::WebString web_label =
1259 blink::WebString::fromUTF8(config.label());
1260 const blink::WebString web_language =
1261 blink::WebString::fromUTF8(config.language());
[email protected]427ff102013-11-26 23:45:401262 const blink::WebString web_id =
1263 blink::WebString::fromUTF8(config.id());
[email protected]71537722013-05-23 06:47:531264
dcheng3076abbf2016-04-22 20:42:391265 std::unique_ptr<WebInbandTextTrackImpl> web_inband_text_track(
henriks9cce5fa2014-12-12 09:35:301266 new WebInbandTextTrackImpl(web_kind, web_label, web_language, web_id));
[email protected]8a561062013-11-22 01:19:311267
dcheng3076abbf2016-04-22 20:42:391268 std::unique_ptr<media::TextTrack> text_track(new TextTrackImpl(
dcheng652f5ff2015-12-27 08:54:001269 main_task_runner_, client_, std::move(web_inband_text_track)));
[email protected]8a561062013-11-22 01:19:311270
dcheng652f5ff2015-12-27 08:54:001271 done_cb.Run(std::move(text_track));
[email protected]71537722013-05-23 06:47:531272}
1273
alokp967c902452016-05-06 05:21:371274void WebMediaPlayerImpl::OnWaitingForDecryptionKey() {
1275 DCHECK(main_task_runner_->BelongsToCurrentThread());
1276
1277 encrypted_client_->didBlockPlaybackWaitingForKey();
1278 // TODO(jrummell): didResumePlaybackBlockedForKey() should only be called
1279 // when a key has been successfully added (e.g. OnSessionKeysChange() with
1280 // |has_additional_usable_key| = true). http://crbug.com/461903
1281 encrypted_client_->didResumePlaybackBlockedForKey();
1282}
1283
alokp5d86e9b2016-05-17 20:20:411284void WebMediaPlayerImpl::OnVideoNaturalSizeChange(const gfx::Size& size) {
1285 DCHECK(main_task_runner_->BelongsToCurrentThread());
1286 DCHECK_NE(ready_state_, WebMediaPlayer::ReadyStateHaveNothing);
1287
sandersd2c478422016-08-02 01:19:251288 gfx::Size rotated_size =
1289 GetRotatedVideoSize(pipeline_metadata_.video_rotation, size);
1290
1291 if (rotated_size == pipeline_metadata_.natural_size)
alokp5d86e9b2016-05-17 20:20:411292 return;
1293
1294 TRACE_EVENT0("media", "WebMediaPlayerImpl::OnNaturalSizeChanged");
sandersd2c478422016-08-02 01:19:251295 media_log_->AddEvent(media_log_->CreateVideoSizeSetEvent(
1296 rotated_size.width(), rotated_size.height()));
alokp5d86e9b2016-05-17 20:20:411297
tsunghungee562e92016-07-20 18:03:311298 if (overlay_enabled_ && surface_manager_)
sandersd2c478422016-08-02 01:19:251299 surface_manager_->NaturalSizeChanged(rotated_size);
alokp5d86e9b2016-05-17 20:20:411300
tguilbert796a40e2016-11-09 01:11:421301 if (pipeline_metadata_.natural_size.IsEmpty()) {
1302 // WatchTimeReporter doesn't report metrics for empty videos. Re-create
1303 // |watch_time_reporter_| if we didn't originally know the video size.
1304 CreateWatchTimeReporter();
1305 }
1306
sandersd2c478422016-08-02 01:19:251307 pipeline_metadata_.natural_size = rotated_size;
alokp5d86e9b2016-05-17 20:20:411308 client_->sizeChanged();
1309}
1310
1311void WebMediaPlayerImpl::OnVideoOpacityChange(bool opaque) {
1312 DCHECK(main_task_runner_->BelongsToCurrentThread());
1313 DCHECK_NE(ready_state_, WebMediaPlayer::ReadyStateHaveNothing);
1314
1315 opaque_ = opaque;
1316 // Modify content opaqueness of cc::Layer directly so that
1317 // SetContentsOpaqueIsFixed is ignored.
1318 if (video_weblayer_)
1319 video_weblayer_->layer()->SetContentsOpaque(opaque_);
1320}
1321
dalecurtis0431cbf2016-03-12 01:19:431322void WebMediaPlayerImpl::OnHidden() {
sandersd1e49fb62015-12-12 01:18:061323 DCHECK(main_task_runner_->BelongsToCurrentThread());
avayvod39c102402016-11-23 21:43:131324
1325 if (IsBackgroundVideoTrackOptimizationEnabled())
1326 selectedVideoTrackChanged(nullptr);
1327
dalecurtis04bdb582016-08-17 22:15:231328 if (watch_time_reporter_)
1329 watch_time_reporter_->OnHidden();
avayvod48a8be52016-08-04 19:52:501330
sandersd50a635e2016-04-04 22:50:091331 UpdatePlayState();
dalecurtis8b8505e72016-06-10 21:59:171332
1333 // Schedule suspended playing media to be paused if the user doesn't come back
1334 // to it within some timeout period to avoid any autoplay surprises.
1335 ScheduleIdlePauseTimer();
sandersd1e49fb62015-12-12 01:18:061336}
1337
1338void WebMediaPlayerImpl::OnShown() {
1339 DCHECK(main_task_runner_->BelongsToCurrentThread());
dalecurtis04bdb582016-08-17 22:15:231340 if (watch_time_reporter_)
1341 watch_time_reporter_->OnShown();
1342
avayvod39c102402016-11-23 21:43:131343 if (IsBackgroundVideoTrackOptimizationEnabled() &&
1344 client_->hasSelectedVideoTrack()) {
1345 WebMediaPlayer::TrackId trackId = client_->getSelectedVideoTrackId();
1346 selectedVideoTrackChanged(&trackId);
1347 }
1348
sandersd50a635e2016-04-04 22:50:091349 must_suspend_ = false;
dalecurtis8b8505e72016-06-10 21:59:171350 background_pause_timer_.Stop();
avayvod48a8be52016-08-04 19:52:501351
sandersd50a635e2016-04-04 22:50:091352 UpdatePlayState();
sandersd1e49fb62015-12-12 01:18:061353}
1354
watkd026f792016-11-05 00:28:511355bool WebMediaPlayerImpl::OnSuspendRequested(bool must_suspend) {
dalecurtis0431cbf2016-03-12 01:19:431356 DCHECK(main_task_runner_->BelongsToCurrentThread());
1357
watkd026f792016-11-05 00:28:511358 if (must_suspend) {
sandersd50a635e2016-04-04 22:50:091359 must_suspend_ = true;
watkd026f792016-11-05 00:28:511360 UpdatePlayState();
1361 return true;
1362 }
sandersd50a635e2016-04-04 22:50:091363
watkd026f792016-11-05 00:28:511364 // If we're beyond HaveFutureData, we can safely suspend at any time.
1365 if (highest_ready_state_ >= WebMediaPlayer::ReadyStateHaveFutureData) {
1366 is_idle_ = true;
1367 UpdatePlayState();
1368 return true;
1369 }
1370
1371 // Before HaveFutureData blink will not call play(), so we must be careful to
1372 // only suspend if we'll eventually receive an event that will trigger a
1373 // resume. If the last time loading progressed was a while ago, and we still
1374 // haven't reached HaveFutureData, we assume that we're waiting on more data
1375 // to continue pre-rolling. When that data is loaded the pipeline will be
1376 // resumed by didLoadingProgress().
1377 if (last_time_loading_progressed_.is_null() ||
1378 (tick_clock_->NowTicks() - last_time_loading_progressed_) >
1379 kLoadingToIdleTimeout) {
1380 is_idle_ = true;
1381 UpdatePlayState();
1382 return true;
1383 }
1384
1385 return false;
dalecurtis0431cbf2016-03-12 01:19:431386}
1387
dalecurtisbb3eaac2016-01-27 21:10:251388void WebMediaPlayerImpl::OnPlay() {
1389 play();
1390 client_->playbackStateChanged();
1391}
1392
1393void WebMediaPlayerImpl::OnPause() {
1394 pause();
1395 client_->playbackStateChanged();
1396}
1397
1398void WebMediaPlayerImpl::OnVolumeMultiplierUpdate(double multiplier) {
1399 volume_multiplier_ = multiplier;
1400 setVolume(volume_);
1401}
1402
watkdee516f2016-02-18 02:22:191403void WebMediaPlayerImpl::ScheduleRestart() {
sandersd50a635e2016-04-04 22:50:091404 // TODO(watk): All restart logic should be moved into PipelineController.
1405 if (pipeline_.IsRunning() && !pipeline_controller_.IsPipelineSuspended()) {
watkdee516f2016-02-18 02:22:191406 pending_suspend_resume_cycle_ = true;
sandersd50a635e2016-04-04 22:50:091407 UpdatePlayState();
watkdee516f2016-02-18 02:22:191408 }
1409}
1410
miu77f914c2016-11-19 23:56:181411void WebMediaPlayerImpl::requestRemotePlaybackDisabled(bool disabled) {
1412 if (observer_)
1413 observer_->OnRemotePlaybackDisabled(disabled);
1414}
1415
hubbed5f36882016-01-15 22:40:371416#if defined(OS_ANDROID) // WMPI_CAST
hubbed5f36882016-01-15 22:40:371417bool WebMediaPlayerImpl::isRemote() const {
1418 return cast_impl_.isRemote();
1419}
1420
1421void WebMediaPlayerImpl::SetMediaPlayerManager(
1422 RendererMediaPlayerManagerInterface* media_player_manager) {
1423 cast_impl_.SetMediaPlayerManager(media_player_manager);
1424}
1425
1426void WebMediaPlayerImpl::requestRemotePlayback() {
1427 cast_impl_.requestRemotePlayback();
1428}
1429
1430void WebMediaPlayerImpl::requestRemotePlaybackControl() {
1431 cast_impl_.requestRemotePlaybackControl();
1432}
1433
avayvod8d8c53b2016-11-04 16:10:301434void WebMediaPlayerImpl::requestRemotePlaybackStop() {
1435 cast_impl_.requestRemotePlaybackStop();
1436}
1437
hubbed5f36882016-01-15 22:40:371438void WebMediaPlayerImpl::OnRemotePlaybackEnded() {
pkastingf5279482016-07-27 02:18:201439 DVLOG(1) << __func__;
hubbed5f36882016-01-15 22:40:371440 DCHECK(main_task_runner_->BelongsToCurrentThread());
1441
1442 ended_ = true;
1443 client_->timeChanged();
1444}
1445
1446void WebMediaPlayerImpl::OnDisconnectedFromRemoteDevice(double t) {
sandersd1c0bba02016-03-04 23:14:081447 DoSeek(base::TimeDelta::FromSecondsD(t), false);
hubbed5f36882016-01-15 22:40:371448
hubbed5f36882016-01-15 22:40:371449 // We already told the delegate we're paused when remoting started.
1450 client_->playbackStateChanged();
1451 client_->disconnectedFromRemoteDevice();
sandersd50a635e2016-04-04 22:50:091452
1453 UpdatePlayState();
hubbed5f36882016-01-15 22:40:371454}
1455
1456void WebMediaPlayerImpl::SuspendForRemote() {
sandersd50a635e2016-04-04 22:50:091457 if (pipeline_controller_.IsPipelineSuspended()) {
hubbed5f36882016-01-15 22:40:371458 scoped_refptr<VideoFrame> frame = cast_impl_.GetCastingBanner();
sandersd50a635e2016-04-04 22:50:091459 if (frame)
dalecurtise9c89e92016-05-20 19:38:001460 compositor_->PaintSingleFrame(frame);
hubbed5f36882016-01-15 22:40:371461 }
sandersd50a635e2016-04-04 22:50:091462
1463 UpdatePlayState();
hubbed5f36882016-01-15 22:40:371464}
1465
1466gfx::Size WebMediaPlayerImpl::GetCanvasSize() const {
1467 if (!video_weblayer_)
1468 return pipeline_metadata_.natural_size;
1469
1470 return video_weblayer_->bounds();
1471}
1472
1473void WebMediaPlayerImpl::SetDeviceScaleFactor(float scale_factor) {
1474 cast_impl_.SetDeviceScaleFactor(scale_factor);
1475}
hubbee4027f92016-05-19 05:18:131476
1477void WebMediaPlayerImpl::setPoster(const blink::WebURL& poster) {
1478 cast_impl_.setPoster(poster);
1479}
tguilbert25a4d112016-10-13 21:56:511480
1481void WebMediaPlayerImpl::SetUseFallbackPath(bool use_fallback_path) {
1482 use_fallback_path_ = use_fallback_path;
1483}
hubbed5f36882016-01-15 22:40:371484#endif // defined(OS_ANDROID) // WMPI_CAST
1485
[email protected]fee8a902014-06-03 13:43:361486void WebMediaPlayerImpl::DataSourceInitialized(bool success) {
pkastingf5279482016-07-27 02:18:201487 DVLOG(1) << __func__;
acolwellb4034942014-08-28 15:42:431488 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]a9415292012-01-19 19:55:201489
dalecurtisea27a3ed2016-06-24 01:41:301490#if defined(OS_ANDROID)
1491 // We can't play HLS URLs with WebMediaPlayerImpl, so in cases where they are
1492 // encountered, instruct the HTML media element to create a new WebMediaPlayer
1493 // instance with the correct URL to trigger WebMediaPlayerAndroid creation.
1494 //
1495 // TODO(tguilbert): Remove this code path once we have the ability to host a
1496 // MediaPlayer within a Mojo media renderer. http://crbug.com/580626
tguilbert25a4d112016-10-13 21:56:511497 if (data_source_ && !use_fallback_path_) {
dalecurtisea27a3ed2016-06-24 01:41:301498 const GURL url_after_redirects = data_source_->GetUrlAfterRedirects();
qinmin0d9521272016-10-10 20:43:191499 if (MediaCodecUtil::IsHLSURL(url_after_redirects)) {
dalecurtisea27a3ed2016-06-24 01:41:301500 client_->requestReload(url_after_redirects);
1501 // |this| may be destructed, do nothing after this.
1502 return;
1503 }
1504 }
1505#endif
1506
[email protected]d250190da3b2012-07-23 22:57:301507 if (!success) {
[email protected]ef405f66b2012-04-18 02:39:551508 SetNetworkState(WebMediaPlayer::NetworkStateFormatError);
sandersd50a635e2016-04-04 22:50:091509
1510 // Not really necessary, since the pipeline was never started, but it at
1511 // least this makes sure that the error handling code is in sync.
1512 UpdatePlayState();
1513
[email protected]a9415292012-01-19 19:55:201514 return;
1515 }
1516
[email protected]ef8394c2013-08-21 20:26:301517 StartPipeline();
[email protected]a9415292012-01-19 19:55:201518}
1519
[email protected]122f40252012-06-12 05:01:561520void WebMediaPlayerImpl::NotifyDownloading(bool is_downloading) {
pkastingf5279482016-07-27 02:18:201521 DVLOG(1) << __func__;
[email protected]122f40252012-06-12 05:01:561522 if (!is_downloading && network_state_ == WebMediaPlayer::NetworkStateLoading)
1523 SetNetworkState(WebMediaPlayer::NetworkStateIdle);
1524 else if (is_downloading && network_state_ == WebMediaPlayer::NetworkStateIdle)
1525 SetNetworkState(WebMediaPlayer::NetworkStateLoading);
1526 media_log_->AddEvent(
1527 media_log_->CreateBooleanEvent(
acolwell9e0840d2014-09-06 19:01:321528 MediaLogEvent::NETWORK_ACTIVITY_SET,
[email protected]122f40252012-06-12 05:01:561529 "is_downloading_data", is_downloading));
1530}
1531
watkf835a792016-06-24 23:24:401532void WebMediaPlayerImpl::OnSurfaceCreated(int surface_id) {
tsunghungee562e92016-07-20 18:03:311533 overlay_surface_id_ = surface_id;
dalecurtis4b632fce22016-11-10 00:52:171534 if (!set_surface_cb_.is_null()) {
1535 // If restart is required, the callback is one-shot only.
1536 if (decoder_requires_restart_for_overlay_)
1537 base::ResetAndReturn(&set_surface_cb_).Run(surface_id);
1538 else
1539 set_surface_cb_.Run(surface_id);
1540 }
watkf835a792016-06-24 23:24:401541}
1542
watkdee516f2016-02-18 02:22:191543void WebMediaPlayerImpl::OnSurfaceRequested(
dalecurtis4b632fce22016-11-10 00:52:171544 bool decoder_requires_restart_for_overlay,
1545 const SurfaceCreatedCB& set_surface_cb) {
watkdee516f2016-02-18 02:22:191546 DCHECK(main_task_runner_->BelongsToCurrentThread());
1547 DCHECK(surface_manager_);
tguilbert25a4d112016-10-13 21:56:511548 DCHECK(!use_fallback_path_);
watkdee516f2016-02-18 02:22:191549
1550 // A null callback indicates that the decoder is going away.
dalecurtis4b632fce22016-11-10 00:52:171551 if (set_surface_cb.is_null()) {
tsunghungee562e92016-07-20 18:03:311552 decoder_requires_restart_for_overlay_ = false;
dalecurtis4b632fce22016-11-10 00:52:171553 set_surface_cb_.Reset();
watkdee516f2016-02-18 02:22:191554 return;
1555 }
1556
dalecurtis4b632fce22016-11-10 00:52:171557 // If we get a surface request it means GpuVideoDecoder is initializing, so
1558 // until we get a null surface request, GVD is the active decoder.
1559 //
1560 // If |decoder_requires_restart_for_overlay| is true, we must restart the
1561 // pipeline for fullscreen transitions. The decoder is unable to switch
1562 // surfaces otherwise. If false, we simply need to tell the decoder about the
1563 // new surface and it will handle things seamlessly.
1564 decoder_requires_restart_for_overlay_ = decoder_requires_restart_for_overlay;
1565 set_surface_cb_ = set_surface_cb;
1566
1567 // If we're waiting for the surface to arrive, OnSurfaceCreated() will be
1568 // called later when it arrives; so do nothing for now.
1569 if (overlay_enabled_ && overlay_surface_id_ == SurfaceManager::kNoSurfaceID)
1570 return;
1571
1572 OnSurfaceCreated(overlay_surface_id_);
watkdee516f2016-02-18 02:22:191573}
1574
dcheng3076abbf2016-04-22 20:42:391575std::unique_ptr<Renderer> WebMediaPlayerImpl::CreateRenderer() {
tsunghungee562e92016-07-20 18:03:311576 if (force_video_overlays_)
1577 EnableOverlay();
1578
watkdee516f2016-02-18 02:22:191579 RequestSurfaceCB request_surface_cb;
1580#if defined(OS_ANDROID)
1581 request_surface_cb =
1582 BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnSurfaceRequested);
1583#endif
sandersd1e49fb62015-12-12 01:18:061584 return renderer_factory_->CreateRenderer(
1585 media_task_runner_, worker_task_runner_, audio_source_provider_.get(),
watkdee516f2016-02-18 02:22:191586 compositor_, request_surface_cb);
sandersd1e49fb62015-12-12 01:18:061587}
1588
[email protected]ef8394c2013-08-21 20:26:301589void WebMediaPlayerImpl::StartPipeline() {
acolwellb4034942014-08-28 15:42:431590 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]ddbc6ff2013-04-19 15:28:331591
xhwange8c4181a2014-12-06 08:10:011592 Demuxer::EncryptedMediaInitDataCB encrypted_media_init_data_cb =
1593 BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnEncryptedMediaInitData);
[email protected]2b57e2e2014-05-09 11:07:251594
tguilbert25a4d112016-10-13 21:56:511595 if (use_fallback_path_) {
tguilbert9881bc22016-10-27 03:13:411596 demuxer_.reset(
1597 new MediaUrlDemuxer(media_task_runner_, fallback_url_,
1598 frame_->document().firstPartyForCookies()));
tguilbert25a4d112016-10-13 21:56:511599 pipeline_controller_.Start(demuxer_.get(), this, false, false);
1600 return;
1601 }
1602
[email protected]ddbc6ff2013-04-19 15:28:331603 // Figure out which demuxer to use.
[email protected]ef8394c2013-08-21 20:26:301604 if (load_type_ != LoadTypeMediaSource) {
[email protected]ddbc6ff2013-04-19 15:28:331605 DCHECK(!chunk_demuxer_);
[email protected]f5443ef72013-04-22 04:03:381606 DCHECK(data_source_);
1607
j.isorcef6778e652015-11-16 17:14:251608#if !defined(MEDIA_DISABLE_FFMPEG)
servolk81e01e02016-03-05 03:29:151609 Demuxer::MediaTracksUpdatedCB media_tracks_updated_cb =
servolkef1e5ef2016-03-25 04:55:261610 BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnFFmpegMediaTracksUpdated);
servolk81e01e02016-03-05 03:29:151611
xhwange8c4181a2014-12-06 08:10:011612 demuxer_.reset(new FFmpegDemuxer(media_task_runner_, data_source_.get(),
servolk81e01e02016-03-05 03:29:151613 encrypted_media_init_data_cb,
1614 media_tracks_updated_cb, media_log_));
j.isorcef6778e652015-11-16 17:14:251615#else
alokp967c902452016-05-06 05:21:371616 OnError(PipelineStatus::DEMUXER_ERROR_COULD_NOT_OPEN);
j.isorcef6778e652015-11-16 17:14:251617 return;
1618#endif
[email protected]ddbc6ff2013-04-19 15:28:331619 } else {
[email protected]f5443ef72013-04-22 04:03:381620 DCHECK(!chunk_demuxer_);
1621 DCHECK(!data_source_);
1622
acolwell9e0840d2014-09-06 19:01:321623 chunk_demuxer_ = new ChunkDemuxer(
[email protected]ef8394c2013-08-21 20:26:301624 BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnDemuxerOpened),
chcunningham967db2f2016-11-02 20:47:171625 encrypted_media_init_data_cb, media_log_);
[email protected]f5443ef72013-04-22 04:03:381626 demuxer_.reset(chunk_demuxer_);
[email protected]ddbc6ff2013-04-19 15:28:331627 }
1628
sandersdb5e21462016-03-09 01:49:071629 // TODO(sandersd): FileSystem objects may also be non-static, but due to our
1630 // caching layer such situations are broken already. http://crbug.com/593159
1631 bool is_static = !chunk_demuxer_;
sandersdb8eb5f1d2016-11-19 04:04:021632 bool is_streaming = data_source_ && data_source_->IsStreaming();
1633 UMA_HISTOGRAM_BOOLEAN("Media.IsStreaming", is_streaming);
sandersdb5e21462016-03-09 01:49:071634
[email protected]f5443ef72013-04-22 04:03:381635 // ... and we're ready to go!
sandersd1e49fb62015-12-12 01:18:061636 // TODO(sandersd): On Android, defer Start() if the tab is not visible.
sandersdb8eb5f1d2016-11-19 04:04:021637 seeking_ = true;
alokp967c902452016-05-06 05:21:371638 pipeline_controller_.Start(demuxer_.get(), this, is_streaming, is_static);
[email protected]f5443ef72013-04-22 04:03:381639}
1640
1641void WebMediaPlayerImpl::SetNetworkState(WebMediaPlayer::NetworkState state) {
pkastingf5279482016-07-27 02:18:201642 DVLOG(1) << __func__ << "(" << state << ")";
acolwellb4034942014-08-28 15:42:431643 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]f5443ef72013-04-22 04:03:381644 network_state_ = state;
1645 // Always notify to ensure client has the latest value.
[email protected]ce70c982013-12-20 17:04:321646 client_->networkStateChanged();
[email protected]f5443ef72013-04-22 04:03:381647}
1648
1649void WebMediaPlayerImpl::SetReadyState(WebMediaPlayer::ReadyState state) {
pkastingf5279482016-07-27 02:18:201650 DVLOG(1) << __func__ << "(" << state << ")";
acolwellb4034942014-08-28 15:42:431651 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]f5443ef72013-04-22 04:03:381652
[email protected]fee8a902014-06-03 13:43:361653 if (state == WebMediaPlayer::ReadyStateHaveEnoughData && data_source_ &&
1654 data_source_->assume_fully_buffered() &&
[email protected]f5443ef72013-04-22 04:03:381655 network_state_ == WebMediaPlayer::NetworkStateLoading)
1656 SetNetworkState(WebMediaPlayer::NetworkStateLoaded);
1657
1658 ready_state_ = state;
sandersd50a635e2016-04-04 22:50:091659 highest_ready_state_ = std::max(highest_ready_state_, ready_state_);
1660
[email protected]f5443ef72013-04-22 04:03:381661 // Always notify to ensure client has the latest value.
[email protected]ce70c982013-12-20 17:04:321662 client_->readyStateChanged();
[email protected]f5443ef72013-04-22 04:03:381663}
1664
Dana Jansens71331252016-03-09 20:57:221665blink::WebAudioSourceProvider* WebMediaPlayerImpl::getAudioSourceProvider() {
[email protected]ff875be52013-06-02 23:47:381666 return audio_source_provider_.get();
[email protected]f5443ef72013-04-22 04:03:381667}
1668
[email protected]f5443ef72013-04-22 04:03:381669double WebMediaPlayerImpl::GetPipelineDuration() const {
[email protected]f6af7592014-02-28 10:09:111670 base::TimeDelta duration = pipeline_.GetMediaDuration();
[email protected]f5443ef72013-04-22 04:03:381671
1672 // Return positive infinity if the resource is unbounded.
1673 // http://www.whatwg.org/specs/web-apps/current-work/multipage/video.html#dom-media-duration
dalecurtis39a7f932016-07-19 18:34:591674 if (duration == kInfiniteDuration)
[email protected]f5443ef72013-04-22 04:03:381675 return std::numeric_limits<double>::infinity();
1676
1677 return duration.InSecondsF();
1678}
1679
[email protected]dd061e12014-05-06 19:21:221680static void GetCurrentFrameAndSignal(
1681 VideoFrameCompositor* compositor,
acolwell9e0840d2014-09-06 19:01:321682 scoped_refptr<VideoFrame>* video_frame_out,
[email protected]dd061e12014-05-06 19:21:221683 base::WaitableEvent* event) {
1684 TRACE_EVENT0("media", "GetCurrentFrameAndSignal");
dalecurtis44ce4de2015-05-11 18:42:071685 *video_frame_out = compositor->GetCurrentFrameAndUpdateIfStale();
[email protected]dd061e12014-05-06 19:21:221686 event->Signal();
1687}
1688
acolwell9e0840d2014-09-06 19:01:321689scoped_refptr<VideoFrame>
[email protected]dd061e12014-05-06 19:21:221690WebMediaPlayerImpl::GetCurrentFrameFromCompositor() {
xhwang213e50c2016-10-10 23:56:311691 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]dd061e12014-05-06 19:21:221692 TRACE_EVENT0("media", "WebMediaPlayerImpl::GetCurrentFrameFromCompositor");
xhwang213e50c2016-10-10 23:56:311693
1694 // Needed when the |main_task_runner_| and |compositor_task_runner_| are the
1695 // same to avoid deadlock in the Wait() below.
[email protected]dd061e12014-05-06 19:21:221696 if (compositor_task_runner_->BelongsToCurrentThread())
dalecurtis44ce4de2015-05-11 18:42:071697 return compositor_->GetCurrentFrameAndUpdateIfStale();
[email protected]dd061e12014-05-06 19:21:221698
1699 // Use a posted task and waitable event instead of a lock otherwise
1700 // WebGL/Canvas can see different content than what the compositor is seeing.
acolwell9e0840d2014-09-06 19:01:321701 scoped_refptr<VideoFrame> video_frame;
gab0d77c7cb2016-06-02 00:00:231702 base::WaitableEvent event(base::WaitableEvent::ResetPolicy::AUTOMATIC,
1703 base::WaitableEvent::InitialState::NOT_SIGNALED);
[email protected]dd061e12014-05-06 19:21:221704 compositor_task_runner_->PostTask(FROM_HERE,
1705 base::Bind(&GetCurrentFrameAndSignal,
1706 base::Unretained(compositor_),
1707 &video_frame,
1708 &event));
1709 event.Wait();
1710 return video_frame;
1711}
1712
sandersd50a635e2016-04-04 22:50:091713void WebMediaPlayerImpl::UpdatePlayState() {
xhwang213e50c2016-10-10 23:56:311714 DCHECK(main_task_runner_->BelongsToCurrentThread());
1715
hubbed5f36882016-01-15 22:40:371716#if defined(OS_ANDROID) // WMPI_CAST
sandersd50a635e2016-04-04 22:50:091717 bool is_remote = isRemote();
sandersdaaff1a652016-11-17 01:47:251718 bool is_streaming = false;
sandersd50a635e2016-04-04 22:50:091719#else
1720 bool is_remote = false;
sandersdaaff1a652016-11-17 01:47:251721 bool is_streaming = data_source_ && data_source_->IsStreaming();
hubbed5f36882016-01-15 22:40:371722#endif
xhwang213e50c2016-10-10 23:56:311723
dalecurtis8b8505e72016-06-10 21:59:171724 bool is_suspended = pipeline_controller_.IsSuspended();
avayvod39c102402016-11-23 21:43:131725 bool is_backgrounded = IsBackgroundedSuspendEnabled() && IsHidden();
sandersdaaff1a652016-11-17 01:47:251726 PlayState state = UpdatePlayState_ComputePlayState(
1727 is_remote, is_streaming, is_suspended, is_backgrounded);
sandersd50a635e2016-04-04 22:50:091728 SetDelegateState(state.delegate_state);
1729 SetMemoryReportingState(state.is_memory_reporting_enabled);
1730 SetSuspendState(state.is_suspended || pending_suspend_resume_cycle_);
1731}
dalecurtis5bbc487e2016-02-27 04:15:051732
sandersd50a635e2016-04-04 22:50:091733void WebMediaPlayerImpl::SetDelegateState(DelegateState new_state) {
mlamouri910111362016-11-04 11:28:241734 if (!delegate_)
dalecurtis5bbc487e2016-02-27 04:15:051735 return;
1736
mlamouri910111362016-11-04 11:28:241737 if (delegate_state_ == new_state) {
1738 if (delegate_state_ != DelegateState::PLAYING ||
1739 autoplay_muted_ == client_->isAutoplayingMuted()) {
1740 return;
1741 }
1742 }
1743
sandersd50a635e2016-04-04 22:50:091744 delegate_state_ = new_state;
1745
1746 switch (delegate_state_) {
1747 case DelegateState::GONE:
1748 delegate_->PlayerGone(delegate_id_);
1749 break;
mlamouri910111362016-11-04 11:28:241750 case DelegateState::PLAYING: {
1751 autoplay_muted_ = client_->isAutoplayingMuted();
1752 bool has_audio = autoplay_muted_ ? false : hasAudio();
zqzhang5d8eab72016-08-26 20:34:301753 delegate_->DidPlay(
mlamouri910111362016-11-04 11:28:241754 delegate_id_, hasVideo(), has_audio, false,
zqzhang5d8eab72016-08-26 20:34:301755 media::DurationToMediaContentType(pipeline_.GetMediaDuration()));
sandersd50a635e2016-04-04 22:50:091756 break;
mlamouri910111362016-11-04 11:28:241757 }
sandersd50a635e2016-04-04 22:50:091758 case DelegateState::PAUSED:
1759 delegate_->DidPause(delegate_id_, false);
1760 break;
1761 case DelegateState::ENDED:
1762 delegate_->DidPause(delegate_id_, true);
1763 break;
dalecurtis0f0097a2015-12-01 17:40:471764 }
1765}
1766
sandersd50a635e2016-04-04 22:50:091767void WebMediaPlayerImpl::SetMemoryReportingState(
1768 bool is_memory_reporting_enabled) {
1769 if (memory_usage_reporting_timer_.IsRunning() ==
1770 is_memory_reporting_enabled) {
hubbed5f36882016-01-15 22:40:371771 return;
sandersd50a635e2016-04-04 22:50:091772 }
sandersd1c0bba02016-03-04 23:14:081773
sandersd50a635e2016-04-04 22:50:091774 if (is_memory_reporting_enabled) {
1775 memory_usage_reporting_timer_.Start(FROM_HERE,
1776 base::TimeDelta::FromSeconds(2), this,
1777 &WebMediaPlayerImpl::ReportMemoryUsage);
1778 } else {
1779 memory_usage_reporting_timer_.Stop();
1780 ReportMemoryUsage();
1781 }
1782}
1783
1784void WebMediaPlayerImpl::SetSuspendState(bool is_suspended) {
xhwang213e50c2016-10-10 23:56:311785 DCHECK(main_task_runner_->BelongsToCurrentThread());
1786
sandersd50a635e2016-04-04 22:50:091787 // Do not change the state after an error has occurred.
1788 // TODO(sandersd): Update PipelineController to remove the need for this.
1789 if (IsNetworkStateError(network_state_))
sandersd1c0bba02016-03-04 23:14:081790 return;
1791
jbauman2438e872016-11-15 04:45:191792#if defined(OS_LINUX)
halliwell6451e242016-06-01 15:00:241793 // TODO(sandersd): idle suspend is disabled if decoder owns video frame.
jbauman2438e872016-11-15 04:45:191794 // Used on Chromecast. Since GetCurrentFrameFromCompositor is a synchronous
1795 // cross-thread post, avoid the cost on platforms that always allow suspend.
1796 // Need to find a better mechanism for this. See http://crbug.com/602708
dalecurtis7f366b2242016-04-13 01:16:171797 if (can_suspend_state_ == CanSuspendState::UNKNOWN) {
1798 scoped_refptr<VideoFrame> frame = GetCurrentFrameFromCompositor();
1799 if (frame) {
1800 can_suspend_state_ =
1801 frame->metadata()->IsTrue(VideoFrameMetadata::DECODER_OWNS_FRAME)
1802 ? CanSuspendState::NO
1803 : CanSuspendState::YES;
1804 }
1805 }
1806#else
1807 can_suspend_state_ = CanSuspendState::YES;
1808#endif
1809
1810 if (can_suspend_state_ == CanSuspendState::NO)
1811 return;
1812
sandersd50a635e2016-04-04 22:50:091813 if (is_suspended) {
1814 pipeline_controller_.Suspend();
1815 } else {
1816 pipeline_controller_.Resume();
1817 }
1818}
1819
1820WebMediaPlayerImpl::PlayState
1821WebMediaPlayerImpl::UpdatePlayState_ComputePlayState(bool is_remote,
sandersdaaff1a652016-11-17 01:47:251822 bool is_streaming,
dalecurtis8b8505e72016-06-10 21:59:171823 bool is_suspended,
sandersd50a635e2016-04-04 22:50:091824 bool is_backgrounded) {
1825 PlayState result;
1826
1827 // This includes both data source (before pipeline startup) and pipeline
1828 // errors.
1829 bool has_error = IsNetworkStateError(network_state_);
1830
1831 // After HaveMetadata, we know which tracks are present and the duration.
1832 bool have_metadata = ready_state_ >= WebMediaPlayer::ReadyStateHaveMetadata;
1833
dalecurtiscc8baf72016-10-27 01:49:441834 // After HaveFutureData, Blink will call play() if the state is not paused;
1835 // prior to this point |paused_| is not accurate.
sandersd50a635e2016-04-04 22:50:091836 bool have_future_data =
1837 highest_ready_state_ >= WebMediaPlayer::ReadyStateHaveFutureData;
1838
dalecurtis8b8505e72016-06-10 21:59:171839 // Background suspend is not enabled for audio-only players unless paused,
1840 // though in the case of audio-only the session should be kept.
avayvod48a8be52016-08-04 19:52:501841 // Videos are not suspended if the user resumed the playback via the remote
1842 // controls earlier and it's still playing.
1843 bool is_backgrounded_video = is_backgrounded && have_metadata && hasVideo();
1844 bool can_play_backgrounded = is_backgrounded_video && !is_remote &&
1845 hasAudio() && IsResumeBackgroundVideosEnabled();
1846 bool is_background_playing =
1847 delegate_ && delegate_->IsPlayingBackgroundVideo();
sandersdaaff1a652016-11-17 01:47:251848 bool background_suspended = !is_streaming && is_backgrounded_video &&
avayvod48a8be52016-08-04 19:52:501849 !(can_play_backgrounded && is_background_playing);
dalecurtiscc8baf72016-10-27 01:49:441850 bool background_pause_suspended =
sandersdaaff1a652016-11-17 01:47:251851 !is_streaming && is_backgrounded && paused_ && have_future_data;
sandersd50a635e2016-04-04 22:50:091852
dalecurtiscc8baf72016-10-27 01:49:441853 // Idle suspension is allowed prior to have future data since there exist
1854 // mechanisms to exit the idle state when the player is capable of reaching
1855 // the have future data state; see didLoadingProgress().
1856 //
sandersd50a635e2016-04-04 22:50:091857 // TODO(sandersd): Make the delegate suspend idle players immediately when
1858 // hidden.
sandersdaaff1a652016-11-17 01:47:251859 bool idle_suspended =
1860 !is_streaming && is_idle_ && paused_ && !seeking_ && !overlay_enabled_;
dalecurtise7120dc2016-09-03 02:54:351861
1862 // If we're already suspended, see if we can wait for user interaction. Prior
1863 // to HaveFutureData, we require |is_idle_| to remain suspended. |is_idle_|
1864 // will be cleared when we receive data which may take us to HaveFutureData.
1865 bool can_stay_suspended =
1866 (is_idle_ || have_future_data) && is_suspended && paused_ && !seeking_;
sandersd50a635e2016-04-04 22:50:091867
1868 // Combined suspend state.
dalecurtise7120dc2016-09-03 02:54:351869 result.is_suspended = is_remote || must_suspend_ || idle_suspended ||
1870 background_suspended || background_pause_suspended ||
1871 can_stay_suspended;
sandersd50a635e2016-04-04 22:50:091872
1873 // We do not treat |playback_rate_| == 0 as paused. For the media session,
1874 // being paused implies displaying a play button, which is incorrect in this
1875 // case. For memory usage reporting, we just use the same definition (but we
1876 // don't have to).
1877 //
1878 // Similarly, we don't consider |ended_| to be paused. Blink will immediately
1879 // call pause() or seek(), so |ended_| should not affect the computation.
1880 // Despite that, |ended_| does result in a separate paused state, to simplfy
1881 // the contract for SetDelegateState().
1882 //
1883 // |has_session| is used to decide when to create a media session. Idle
1884 // suspension does not destroy the media session, because we expect that the
1885 // notification controls (and audio focus) remain. We also require:
1886 // - |have_metadata|, since the tracks and duration are passed to DidPlay().
1887 // - |have_future_data|, since we need to know whether we are paused to
1888 // correctly configure the session.
1889 //
1890 // TODO(sandersd): If Blink told us the paused state sooner, we could create
1891 // the media session sooner.
1892 bool can_play = !has_error && !is_remote && have_future_data;
avayvod48a8be52016-08-04 19:52:501893 bool has_session_playing =
1894 can_play && !must_suspend_ && !background_suspended;
1895
1896 // |has_session_suspended| means the player is suspended from the media
1897 // element point of view but paused and can be resumed from the delegate point
1898 // of view. Therefore it behaves like |paused_| for the delegate.
1899 bool has_session_suspended = can_play && !must_suspend_ &&
1900 background_suspended && can_play_backgrounded;
1901
1902 bool has_session = has_session_playing || has_session_suspended;
sandersd50a635e2016-04-04 22:50:091903
1904 if (!has_session) {
1905 result.delegate_state = DelegateState::GONE;
avayvod48a8be52016-08-04 19:52:501906 } else if (paused_ || has_session_suspended) {
dalecurtise7120dc2016-09-03 02:54:351907 result.delegate_state =
1908 ended_ ? DelegateState::ENDED : DelegateState::PAUSED;
sandersd50a635e2016-04-04 22:50:091909 } else {
1910 result.delegate_state = DelegateState::PLAYING;
1911 }
1912
dalecurtis8b8505e72016-06-10 21:59:171913 // It's not critical if some cases where memory usage can change are missed,
sandersd50a635e2016-04-04 22:50:091914 // since media memory changes are usually gradual.
1915 result.is_memory_reporting_enabled =
1916 can_play && !result.is_suspended && !paused_;
1917
1918 return result;
dalecurtis0f0097a2015-12-01 17:40:471919}
1920
dalecurtis83266c72015-10-29 18:43:201921void WebMediaPlayerImpl::ReportMemoryUsage() {
1922 DCHECK(main_task_runner_->BelongsToCurrentThread());
1923
wdzierzanowskifd4cd91c52015-12-02 23:50:201924 // About base::Unretained() usage below: We destroy |demuxer_| on the main
1925 // thread. Before that, however, ~WebMediaPlayerImpl() posts a task to the
1926 // media thread and waits for it to finish. Hence, the GetMemoryUsage() task
1927 // posted here must finish earlier.
1928
1929 if (demuxer_) {
1930 base::PostTaskAndReplyWithResult(
1931 media_task_runner_.get(), FROM_HERE,
1932 base::Bind(&Demuxer::GetMemoryUsage, base::Unretained(demuxer_.get())),
1933 base::Bind(&WebMediaPlayerImpl::FinishMemoryUsageReport, AsWeakPtr()));
1934 } else {
1935 FinishMemoryUsageReport(0);
1936 }
1937}
1938
1939void WebMediaPlayerImpl::FinishMemoryUsageReport(int64_t demuxer_memory_usage) {
1940 DCHECK(main_task_runner_->BelongsToCurrentThread());
1941
dalecurtis83266c72015-10-29 18:43:201942 const PipelineStatistics stats = pipeline_.GetStatistics();
servolk639473e492016-12-15 04:14:201943 const int64_t data_source_memory_usage =
1944 data_source_ ? data_source_->GetMemoryUsage() : 0;
dalecurtis83266c72015-10-29 18:43:201945 const int64_t current_memory_usage =
1946 stats.audio_memory_usage + stats.video_memory_usage +
servolk639473e492016-12-15 04:14:201947 data_source_memory_usage + demuxer_memory_usage;
dalecurtis83266c72015-10-29 18:43:201948
dalecurtis3a7d38f42016-03-07 21:17:131949 // Note, this isn't entirely accurate, there may be VideoFrames held by the
1950 // compositor or other resources that we're unaware of.
1951
dalecurtis83266c72015-10-29 18:43:201952 DVLOG(2) << "Memory Usage -- Audio: " << stats.audio_memory_usage
servolk639473e492016-12-15 04:14:201953 << ", Video: " << stats.video_memory_usage
1954 << ", DataSource: " << data_source_memory_usage
wdzierzanowskifd4cd91c52015-12-02 23:50:201955 << ", Demuxer: " << demuxer_memory_usage;
dalecurtis83266c72015-10-29 18:43:201956
1957 const int64_t delta = current_memory_usage - last_reported_memory_usage_;
1958 last_reported_memory_usage_ = current_memory_usage;
1959 adjust_allocated_memory_cb_.Run(delta);
servolk639473e492016-12-15 04:14:201960
1961 if (hasAudio()) {
1962 UMA_HISTOGRAM_MEMORY_KB("Media.WebMediaPlayerImpl.Memory.Audio",
1963 stats.audio_memory_usage / 1024);
1964 }
1965 if (hasVideo()) {
1966 UMA_HISTOGRAM_MEMORY_KB("Media.WebMediaPlayerImpl.Memory.Video",
1967 stats.video_memory_usage / 1024);
1968 }
1969 if (data_source_) {
1970 UMA_HISTOGRAM_MEMORY_KB("Media.WebMediaPlayerImpl.Memory.DataSource",
1971 data_source_memory_usage / 1024);
1972 }
1973 if (demuxer_) {
1974 UMA_HISTOGRAM_MEMORY_KB("Media.WebMediaPlayerImpl.Memory.Demuxer",
1975 demuxer_memory_usage / 1024);
1976 }
dalecurtis83266c72015-10-29 18:43:201977}
1978
dalecurtis8b8505e72016-06-10 21:59:171979void WebMediaPlayerImpl::ScheduleIdlePauseTimer() {
dalecurtise7120dc2016-09-03 02:54:351980 // Only schedule the pause timer if we're playing and are suspended.
1981 if (paused_ || !pipeline_controller_.IsSuspended())
dalecurtis8b8505e72016-06-10 21:59:171982 return;
1983
1984#if defined(OS_ANDROID)
1985 // Remote players will be suspended and locally paused.
1986 if (isRemote())
1987 return;
1988#endif
1989
1990 // Idle timeout chosen arbitrarily.
1991 background_pause_timer_.Start(FROM_HERE, base::TimeDelta::FromSeconds(5),
1992 this, &WebMediaPlayerImpl::OnPause);
1993}
1994
dalecurtis04bdb582016-08-17 22:15:231995void WebMediaPlayerImpl::CreateWatchTimeReporter() {
1996 // Create the watch time reporter and synchronize its initial state.
1997 watch_time_reporter_.reset(new WatchTimeReporter(
1998 hasAudio(), hasVideo(), !!chunk_demuxer_, is_encrypted_, media_log_,
1999 pipeline_metadata_.natural_size,
2000 base::Bind(&GetCurrentTimeInternal, this)));
2001 watch_time_reporter_->OnVolumeChange(volume_);
avayvod39c102402016-11-23 21:43:132002 if (IsHidden())
dalecurtis04bdb582016-08-17 22:15:232003 watch_time_reporter_->OnHidden();
2004 else
2005 watch_time_reporter_->OnShown();
2006}
2007
avayvod39c102402016-11-23 21:43:132008bool WebMediaPlayerImpl::IsHidden() const {
2009 DCHECK(main_task_runner_->BelongsToCurrentThread());
2010
2011 return delegate_ && delegate_->IsHidden();
2012}
2013
xjzaf29d4182016-12-16 01:52:322014void WebMediaPlayerImpl::ActivateViewportIntersectionMonitoring(bool activate) {
2015 DCHECK(main_task_runner_->BelongsToCurrentThread());
2016
2017 client_->activateViewportIntersectionMonitoring(activate);
2018}
2019
acolwell9e0840d2014-09-06 19:01:322020} // namespace media