blob: 76fb82cc3c5fb939a04ace11650f56ae0b7a9af5 [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"
[email protected]32da1002010-03-03 21:57:3533#include "media/base/limits.h"
zqzhang5d8eab72016-08-26 20:34:3034#include "media/base/media_content_type.h"
jrummelle616ee92016-10-08 02:15:4435#include "media/base/media_keys.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
sandersd50a635e2016-04-04 22:50:09127bool IsNetworkStateError(blink::WebMediaPlayer::NetworkState state) {
128 bool result = state == blink::WebMediaPlayer::NetworkStateFormatError ||
129 state == blink::WebMediaPlayer::NetworkStateNetworkError ||
130 state == blink::WebMediaPlayer::NetworkStateDecodeError;
131 DCHECK_EQ(state > blink::WebMediaPlayer::NetworkStateLoaded, result);
132 return result;
133}
134
sandersd2c478422016-08-02 01:19:25135gfx::Size GetRotatedVideoSize(VideoRotation rotation, gfx::Size natural_size) {
136 if (rotation == VIDEO_ROTATION_90 || rotation == VIDEO_ROTATION_270)
137 return gfx::Size(natural_size.height(), natural_size.width());
138 return natural_size;
139}
140
dalecurtis04bdb582016-08-17 22:15:23141base::TimeDelta GetCurrentTimeInternal(WebMediaPlayerImpl* p_this) {
142 // We wrap currentTime() instead of using pipeline_.GetMediaTime() since there
143 // are a variety of cases in which that time is not accurate; e.g., while
144 // remoting and during a pause or seek.
145 return base::TimeDelta::FromSecondsD(p_this->currentTime());
146}
147
watkd026f792016-11-05 00:28:51148// How much time must have elapsed since loading last progressed before the
149// player is eligible for idle suspension.
150constexpr base::TimeDelta kLoadingToIdleTimeout =
151 base::TimeDelta::FromSeconds(3);
152
[email protected]8931c41a2009-07-07 17:31:49153} // namespace
154
[email protected]6683e1b2014-04-10 01:45:38155class BufferedDataSourceHostImpl;
156
danakj365175c2016-02-06 00:37:37157STATIC_ASSERT_ENUM(WebMediaPlayer::CORSModeUnspecified,
158 UrlData::CORS_UNSPECIFIED);
159STATIC_ASSERT_ENUM(WebMediaPlayer::CORSModeAnonymous, UrlData::CORS_ANONYMOUS);
160STATIC_ASSERT_ENUM(WebMediaPlayer::CORSModeUseCredentials,
161 UrlData::CORS_USE_CREDENTIALS);
[email protected]a5a01102012-06-06 17:01:24162
[email protected]2c539b82012-08-18 04:10:19163#define BIND_TO_RENDER_LOOP(function) \
acolwellb4034942014-08-28 15:42:43164 (DCHECK(main_task_runner_->BelongsToCurrentThread()), \
acolwell9e0840d2014-09-06 19:01:32165 BindToCurrentLoop(base::Bind(function, AsWeakPtr())))
[email protected]5983adb2012-10-24 00:12:00166
[email protected]4e982192014-06-21 13:35:45167#define BIND_TO_RENDER_LOOP1(function, arg1) \
acolwellb4034942014-08-28 15:42:43168 (DCHECK(main_task_runner_->BelongsToCurrentThread()), \
acolwell9e0840d2014-09-06 19:01:32169 BindToCurrentLoop(base::Bind(function, AsWeakPtr(), arg1)))
[email protected]4e982192014-06-21 13:35:45170
[email protected]5b5bb9d2010-10-22 19:57:36171WebMediaPlayerImpl::WebMediaPlayerImpl(
[email protected]35b2a972014-04-04 15:50:22172 blink::WebLocalFrame* frame,
[email protected]180ef242013-11-07 06:50:46173 blink::WebMediaPlayerClient* client,
srirama.m26f864d02015-07-14 05:21:46174 blink::WebMediaPlayerEncryptedMediaClient* encrypted_client,
[email protected]b8976652011-10-26 23:46:55175 base::WeakPtr<WebMediaPlayerDelegate> delegate,
dcheng3076abbf2016-04-22 20:42:39176 std::unique_ptr<RendererFactory> renderer_factory,
hubbe5f0ad43b2015-12-14 20:57:26177 linked_ptr<UrlIndex> url_index,
[email protected]e82b2bd2013-01-02 17:47:57178 const WebMediaPlayerParams& params)
[email protected]f6af7592014-02-28 10:09:11179 : frame_(frame),
sandersd50a635e2016-04-04 22:50:09180 delegate_state_(DelegateState::GONE),
181 is_idle_(false),
182 must_suspend_(false),
[email protected]ef405f66b2012-04-18 02:39:55183 network_state_(WebMediaPlayer::NetworkStateEmpty),
184 ready_state_(WebMediaPlayer::ReadyStateHaveNothing),
sandersd50a635e2016-04-04 22:50:09185 highest_ready_state_(WebMediaPlayer::ReadyStateHaveNothing),
dalecurtisb6e052f52016-08-25 00:35:55186 preload_(MultibufferDataSource::AUTO),
187 buffering_strategy_(MultibufferDataSource::BUFFERING_STRATEGY_NORMAL),
anujk.sharma2fa37a02015-04-30 05:51:32188 main_task_runner_(base::ThreadTaskRunnerHandle::Get()),
acolwell755d12d2014-08-30 01:09:19189 media_task_runner_(params.media_task_runner()),
dcastagna617d086b2015-08-20 01:39:30190 worker_task_runner_(params.worker_task_runner()),
acolwell755d12d2014-08-30 01:09:19191 media_log_(params.media_log()),
acolwellb4034942014-08-28 15:42:43192 pipeline_(media_task_runner_, media_log_.get()),
sandersd1c0bba02016-03-04 23:14:08193 pipeline_controller_(
194 &pipeline_,
195 base::Bind(&WebMediaPlayerImpl::CreateRenderer,
196 base::Unretained(this)),
197 base::Bind(&WebMediaPlayerImpl::OnPipelineSeeked, AsWeakPtr()),
198 base::Bind(&WebMediaPlayerImpl::OnPipelineSuspended, AsWeakPtr()),
alokp967c902452016-05-06 05:21:37199 base::Bind(&WebMediaPlayerImpl::OnError, AsWeakPtr())),
[email protected]f988d9b2014-07-25 00:35:43200 load_type_(LoadTypeURL),
[email protected]75e145a2014-04-15 17:44:32201 opaque_(false),
wolenetz1b2ae7d2015-06-10 00:44:21202 playback_rate_(0.0),
[email protected]49480902009-07-14 20:23:43203 paused_(true),
[email protected]b3766a22010-12-22 17:34:13204 seeking_(false),
watkdee516f2016-02-18 02:22:19205 pending_suspend_resume_cycle_(false),
scherkusd2c745b2014-09-04 05:03:40206 ended_(false),
yoichio863bebf2016-03-04 07:56:58207 should_notify_time_changed_(false),
tsunghungee562e92016-07-20 18:03:31208 overlay_enabled_(false),
209 decoder_requires_restart_for_overlay_(false),
[email protected]5badb082010-06-11 17:40:15210 client_(client),
srirama.m26f864d02015-07-14 05:21:46211 encrypted_client_(encrypted_client),
[email protected]baff4512011-10-19 18:21:07212 delegate_(delegate),
dalecurtisbb3eaac2016-01-27 21:10:25213 delegate_id_(0),
[email protected]d726eddc2013-07-02 22:25:55214 defer_load_cb_(params.defer_load_cb()),
dongseong.hwang0c4e9d82015-01-08 20:11:13215 context_3d_cb_(params.context_3d_cb()),
dalecurtis83266c72015-10-29 18:43:20216 adjust_allocated_memory_cb_(params.adjust_allocated_memory_cb()),
217 last_reported_memory_usage_(0),
[email protected]132dd57c2012-08-10 23:24:34218 supports_save_(true),
[email protected]f5443ef72013-04-22 04:03:38219 chunk_demuxer_(NULL),
hubbe5f0ad43b2015-12-14 20:57:26220 url_index_(url_index),
Bartosz Fabianowski85a823812015-04-16 10:27:51221 // Threaded compositing isn't enabled universally yet.
fdoraydb3ef7d2016-06-09 15:42:38222 compositor_task_runner_(params.compositor_task_runner()
223 ? params.compositor_task_runner()
224 : base::ThreadTaskRunnerHandle::Get()),
alokp5d86e9b2016-05-17 20:20:41225 compositor_(new VideoFrameCompositor(compositor_task_runner_)),
hubbed5f36882016-01-15 22:40:37226#if defined(OS_ANDROID) // WMPI_CAST
dalecurtisbb3eaac2016-01-27 21:10:25227 cast_impl_(this, client_, params.context_3d_cb()),
hubbed5f36882016-01-15 22:40:37228#endif
dalecurtisbb3eaac2016-01-27 21:10:25229 volume_(1.0),
230 volume_multiplier_(1.0),
watkdee516f2016-02-18 02:22:19231 renderer_factory_(std::move(renderer_factory)),
dalecurtis2ff781da2016-03-03 01:52:13232 surface_manager_(params.surface_manager()),
tsunghungee562e92016-07-20 18:03:31233 overlay_surface_id_(SurfaceManager::kNoSurfaceID),
dalecurtis7f366b2242016-04-13 01:16:17234 suppress_destruction_errors_(false),
dalecurtis04bdb582016-08-17 22:15:23235 can_suspend_state_(CanSuspendState::UNKNOWN),
tguilbert25a4d112016-10-13 21:56:51236 use_fallback_path_(false),
dalecurtis9d638a12016-08-30 06:20:55237 is_encrypted_(false),
xjzd3fe45a2016-10-12 18:26:37238 underflow_count_(0),
239 observer_(params.media_observer()) {
dalecurtis83266c72015-10-29 18:43:20240 DCHECK(!adjust_allocated_memory_cb_.is_null());
xhwang59d4175a2016-01-14 03:19:30241 DCHECK(renderer_factory_);
servolkef1e5ef2016-03-25 04:55:26242 DCHECK(client_);
dalecurtis83266c72015-10-29 18:43:20243
watkd026f792016-11-05 00:28:51244 tick_clock_.reset(new base::DefaultTickClock());
245
tsunghungee562e92016-07-20 18:03:31246 force_video_overlays_ = base::CommandLine::ForCurrentProcess()->HasSwitch(
247 switches::kForceVideoOverlays);
248
sandersd3d927e7a2016-09-01 00:14:43249 disable_fullscreen_video_overlays_ =
250 !base::FeatureList::IsEnabled(media::kOverlayFullscreenVideo);
251
dalecurtisbb3eaac2016-01-27 21:10:25252 if (delegate_)
253 delegate_id_ = delegate_->AddObserver(this);
sandersd1e49fb62015-12-12 01:18:06254
[email protected]c93eb0a62011-08-09 22:47:24255 media_log_->AddEvent(
acolwell9e0840d2014-09-06 19:01:32256 media_log_->CreateEvent(MediaLogEvent::WEBMEDIAPLAYER_CREATED));
[email protected]4e6be3f2009-05-07 02:24:44257
jrummelle616ee92016-10-08 02:15:44258 if (params.initial_cdm())
259 SetCdm(params.initial_cdm());
xhwang0ad11e512014-11-25 23:43:09260
xhwangf94a634d2014-10-22 22:07:27261 // TODO(xhwang): When we use an external Renderer, many methods won't work,
xhwang6fa356202014-12-11 00:44:12262 // e.g. GetCurrentFrameFromCompositor(). See http://crbug.com/434861
[email protected]c50edb962013-10-19 18:05:07263
guidou36e69302016-10-13 08:27:20264 // Use the null sink if no valid sink was provided.
[email protected]4a914882013-01-10 00:43:48265 audio_source_provider_ = new WebAudioSourceProviderImpl(
guidou36e69302016-10-13 08:27:20266 params.audio_renderer_sink().get() &&
267 params.audio_renderer_sink()
268 ->GetOutputDeviceInfo()
269 .device_status() == OUTPUT_DEVICE_STATUS_OK
[email protected]ff875be52013-06-02 23:47:38270 ? params.audio_renderer_sink()
acolwell9e0840d2014-09-06 19:01:32271 : new NullAudioSink(media_task_runner_));
[email protected]ec9212f2008-12-18 21:40:36272}
273
[email protected]4e6be3f2009-05-07 02:24:44274WebMediaPlayerImpl::~WebMediaPlayerImpl() {
acolwellb4034942014-08-28 15:42:43275 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]d43ed912009-02-03 04:52:53276
alokp1116967f2016-06-11 17:30:56277 suppress_destruction_errors_ = true;
sandersd1e49fb62015-12-12 01:18:06278 if (delegate_) {
dalecurtisbb3eaac2016-01-27 21:10:25279 delegate_->PlayerGone(delegate_id_);
280 delegate_->RemoveObserver(delegate_id_);
sandersd1e49fb62015-12-12 01:18:06281 }
[email protected]baff4512011-10-19 18:21:07282
dalecurtis04bdb582016-08-17 22:15:23283 // Finalize any watch time metrics before destroying the pipeline.
284 watch_time_reporter_.reset();
285
alokp967c902452016-05-06 05:21:37286 // Pipeline must be stopped before it is destroyed.
287 pipeline_.Stop();
[email protected]f6af7592014-02-28 10:09:11288
dalecurtis83266c72015-10-29 18:43:20289 if (last_reported_memory_usage_)
290 adjust_allocated_memory_cb_.Run(-last_reported_memory_usage_);
291
dalecurtise1edb312016-06-22 02:33:21292 // Destruct compositor resources in the proper order.
293 client_->setWebLayer(nullptr);
294 if (video_weblayer_)
295 static_cast<cc::VideoLayer*>(video_weblayer_->layer())->StopUsingProvider();
[email protected]dd061e12014-05-06 19:21:22296 compositor_task_runner_->DeleteSoon(FROM_HERE, compositor_);
xhwangea8bb3562015-06-08 21:18:37297
298 media_log_->AddEvent(
299 media_log_->CreateEvent(MediaLogEvent::WEBMEDIAPLAYER_DESTROYED));
[email protected]ec9212f2008-12-18 21:40:36300}
301
guidou9bfe4e2f2016-04-09 08:31:19302void WebMediaPlayerImpl::load(LoadType load_type,
303 const blink::WebMediaPlayerSource& source,
[email protected]62e5e682013-03-07 23:53:24304 CORSMode cors_mode) {
guidou9bfe4e2f2016-04-09 08:31:19305 // Only URL or MSE blob URL is supported.
306 DCHECK(source.isURL());
307 blink::WebURL url = source.getAsURL();
pkastingf5279482016-07-27 02:18:20308 DVLOG(1) << __func__ << "(" << load_type << ", " << url << ", " << cors_mode
309 << ")";
[email protected]d726eddc2013-07-02 22:25:55310 if (!defer_load_cb_.is_null()) {
311 defer_load_cb_.Run(base::Bind(
[email protected]ef8394c2013-08-21 20:26:30312 &WebMediaPlayerImpl::DoLoad, AsWeakPtr(), load_type, url, cors_mode));
[email protected]d726eddc2013-07-02 22:25:55313 return;
314 }
[email protected]ef8394c2013-08-21 20:26:30315 DoLoad(load_type, url, cors_mode);
[email protected]62e5e682013-03-07 23:53:24316}
317
watk9c87c6fa2016-05-06 20:36:51318bool WebMediaPlayerImpl::supportsOverlayFullscreenVideo() {
319#if defined(OS_ANDROID)
watkf835a792016-06-24 23:24:40320 return true;
watk9c87c6fa2016-05-06 20:36:51321#else
322 return false;
323#endif
324}
325
tsunghungee562e92016-07-20 18:03:31326void WebMediaPlayerImpl::EnableOverlay() {
327 overlay_enabled_ = true;
watkf835a792016-06-24 23:24:40328 if (surface_manager_) {
329 surface_created_cb_.Reset(
330 base::Bind(&WebMediaPlayerImpl::OnSurfaceCreated, AsWeakPtr()));
331 surface_manager_->CreateFullscreenSurface(pipeline_metadata_.natural_size,
332 surface_created_cb_.callback());
333 }
tsunghungee562e92016-07-20 18:03:31334
335 if (decoder_requires_restart_for_overlay_)
watkdee516f2016-02-18 02:22:19336 ScheduleRestart();
337}
338
tsunghungee562e92016-07-20 18:03:31339void WebMediaPlayerImpl::DisableOverlay() {
340 overlay_enabled_ = false;
watkf835a792016-06-24 23:24:40341 surface_created_cb_.Cancel();
tsunghungee562e92016-07-20 18:03:31342 overlay_surface_id_ = SurfaceManager::kNoSurfaceID;
343
344 if (decoder_requires_restart_for_overlay_)
watkdee516f2016-02-18 02:22:19345 ScheduleRestart();
346}
347
tsunghungee562e92016-07-20 18:03:31348void WebMediaPlayerImpl::enteredFullscreen() {
sandersd3d927e7a2016-09-01 00:14:43349 if (!force_video_overlays_ && !disable_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() {
sandersd3d927e7a2016-09-01 00:14:43356 if (!force_video_overlays_ && !disable_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
[email protected]ef8394c2013-08-21 20:26:30362void WebMediaPlayerImpl::DoLoad(LoadType load_type,
[email protected]180ef242013-11-07 06:50:46363 const blink::WebURL& url,
[email protected]d726eddc2013-07-02 22:25:55364 CORSMode cors_mode) {
pkastingf5279482016-07-27 02:18:20365 DVLOG(1) << __func__;
acolwellb4034942014-08-28 15:42:43366 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]d726eddc2013-07-02 22:25:55367
[email protected]62e5e682013-03-07 23:53:24368 GURL gurl(url);
xhwangbffbf452016-04-01 05:26:45369 ReportMetrics(load_type, gurl, frame_->getSecurityOrigin());
[email protected]62e5e682013-03-07 23:53:24370
[email protected]926f8fd2013-04-12 20:27:53371 // Set subresource URL for crash reporting.
372 base::debug::SetCrashKeyValue("subresource_url", gurl.spec());
373
tguilbert25a4d112016-10-13 21:56:51374 if (use_fallback_path_)
375 fallback_url_ = gurl;
376
[email protected]ef8394c2013-08-21 20:26:30377 load_type_ = load_type;
378
[email protected]62e5e682013-03-07 23:53:24379 SetNetworkState(WebMediaPlayer::NetworkStateLoading);
380 SetReadyState(WebMediaPlayer::ReadyStateHaveNothing);
kinukof19cde72015-12-18 23:15:25381 media_log_->AddEvent(media_log_->CreateLoadEvent(url.string().utf8()));
[email protected]d726eddc2013-07-02 22:25:55382
383 // Media source pipelines can start immediately.
[email protected]ef8394c2013-08-21 20:26:30384 if (load_type == LoadTypeMediaSource) {
[email protected]d726eddc2013-07-02 22:25:55385 supports_save_ = false;
[email protected]ef8394c2013-08-21 20:26:30386 StartPipeline();
hubbe5f0ad43b2015-12-14 20:57:26387 } else {
dalecurtisb6e052f52016-08-25 00:35:55388 data_source_.reset(new MultibufferDataSource(
389 url, static_cast<UrlData::CORSMode>(cors_mode), main_task_runner_,
390 url_index_, frame_, media_log_.get(), &buffered_data_source_host_,
391 base::Bind(&WebMediaPlayerImpl::NotifyDownloading, AsWeakPtr())));
avayvode46d7bef2016-03-30 23:18:26392 data_source_->SetPreload(preload_);
393 data_source_->SetBufferingStrategy(buffering_strategy_);
394 data_source_->Initialize(
395 base::Bind(&WebMediaPlayerImpl::DataSourceInitialized, AsWeakPtr()));
hubbe5f0ad43b2015-12-14 20:57:26396 }
hubbed5f36882016-01-15 22:40:37397
398#if defined(OS_ANDROID) // WMPI_CAST
dalecurtisbb3eaac2016-01-27 21:10:25399 cast_impl_.Initialize(url, frame_, delegate_id_);
hubbed5f36882016-01-15 22:40:37400#endif
[email protected]62e5e682013-03-07 23:53:24401}
402
[email protected]4e6be3f2009-05-07 02:24:44403void WebMediaPlayerImpl::play() {
pkastingf5279482016-07-27 02:18:20404 DVLOG(1) << __func__;
acolwellb4034942014-08-28 15:42:43405 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]d43ed912009-02-03 04:52:53406
hubbed5f36882016-01-15 22:40:37407#if defined(OS_ANDROID) // WMPI_CAST
408 if (isRemote()) {
dalecurtis6e2716d2016-01-21 04:49:15409 cast_impl_.play();
hubbed5f36882016-01-15 22:40:37410 return;
411 }
412#endif
[email protected]49480902009-07-14 20:23:43413 paused_ = false;
sandersd50a635e2016-04-04 22:50:09414 is_idle_ = false;
yoichio863bebf2016-03-04 07:56:58415 pipeline_.SetPlaybackRate(playback_rate_);
dalecurtis4619cd02016-09-22 21:39:10416 background_pause_timer_.Stop();
sandersd1c0bba02016-03-04 23:14:08417
[email protected]039b7542013-10-17 22:06:25418 if (data_source_)
419 data_source_->MediaIsPlaying();
[email protected]090f7312011-08-05 23:26:40420
dalecurtis04bdb582016-08-17 22:15:23421 DCHECK(watch_time_reporter_);
422 watch_time_reporter_->OnPlaying();
acolwell9e0840d2014-09-06 19:01:32423 media_log_->AddEvent(media_log_->CreateEvent(MediaLogEvent::PLAY));
sandersd50a635e2016-04-04 22:50:09424 UpdatePlayState();
[email protected]ec9212f2008-12-18 21:40:36425}
426
[email protected]4e6be3f2009-05-07 02:24:44427void WebMediaPlayerImpl::pause() {
pkastingf5279482016-07-27 02:18:20428 DVLOG(1) << __func__;
acolwellb4034942014-08-28 15:42:43429 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]d43ed912009-02-03 04:52:53430
sandersd50a635e2016-04-04 22:50:09431 // We update the paused state even when casting, since we expect pause() to be
432 // called when casting begins, and when we exit casting we should end up in a
433 // paused state.
[email protected]49480902009-07-14 20:23:43434 paused_ = true;
hubbed5f36882016-01-15 22:40:37435
436#if defined(OS_ANDROID) // WMPI_CAST
437 if (isRemote()) {
dalecurtis6e2716d2016-01-21 04:49:15438 cast_impl_.pause();
hubbed5f36882016-01-15 22:40:37439 return;
440 }
441#endif
442
a.berwal338bf002015-04-22 11:14:50443 pipeline_.SetPlaybackRate(0.0);
sandersd1c0bba02016-03-04 23:14:08444
445 // pause() may be called after playback has ended and the HTMLMediaElement
446 // requires that currentTime() == duration() after ending. We want to ensure
447 // |paused_time_| matches currentTime() in this case or a future seek() may
448 // incorrectly discard what it thinks is a seek to the existing time.
449 paused_time_ =
450 ended_ ? pipeline_.GetMediaDuration() : pipeline_.GetMediaTime();
[email protected]090f7312011-08-05 23:26:40451
dalecurtis04bdb582016-08-17 22:15:23452 DCHECK(watch_time_reporter_);
453 watch_time_reporter_->OnPaused();
acolwell9e0840d2014-09-06 19:01:32454 media_log_->AddEvent(media_log_->CreateEvent(MediaLogEvent::PAUSE));
sandersd50a635e2016-04-04 22:50:09455 UpdatePlayState();
[email protected]ec9212f2008-12-18 21:40:36456}
457
[email protected]574a1d62009-07-17 03:23:46458bool WebMediaPlayerImpl::supportsSave() const {
acolwellb4034942014-08-28 15:42:43459 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]132dd57c2012-08-10 23:24:34460 return supports_save_;
[email protected]574a1d62009-07-17 03:23:46461}
462
[email protected]39bdde32013-04-17 17:44:20463void WebMediaPlayerImpl::seek(double seconds) {
pkastingf5279482016-07-27 02:18:20464 DVLOG(1) << __func__ << "(" << seconds << "s)";
acolwellb4034942014-08-28 15:42:43465 DCHECK(main_task_runner_->BelongsToCurrentThread());
sandersd1c0bba02016-03-04 23:14:08466 DoSeek(base::TimeDelta::FromSecondsD(seconds), true);
467}
468
469void WebMediaPlayerImpl::DoSeek(base::TimeDelta time, bool time_updated) {
470 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]d43ed912009-02-03 04:52:53471
hubbed5f36882016-01-15 22:40:37472#if defined(OS_ANDROID) // WMPI_CAST
473 if (isRemote()) {
sandersd1c0bba02016-03-04 23:14:08474 cast_impl_.seek(time);
hubbed5f36882016-01-15 22:40:37475 return;
476 }
477#endif
478
srirama.mccf671812015-01-08 11:59:13479 ReadyState old_state = ready_state_;
[email protected]1bb666802013-11-28 06:12:08480 if (ready_state_ > WebMediaPlayer::ReadyStateHaveMetadata)
481 SetReadyState(WebMediaPlayer::ReadyStateHaveMetadata);
482
sandersd1c0bba02016-03-04 23:14:08483 // When paused, we know exactly what the current time is and can elide seeks
484 // to it. However, there are two cases that are not elided:
485 // 1) When the pipeline state is not stable.
486 // In this case we just let |pipeline_controller_| decide what to do, as
487 // it has complete information.
488 // 2) For MSE.
489 // Because the buffers may have changed between seeks, MSE seeks are
490 // never elided.
491 if (paused_ && pipeline_controller_.IsStable() && paused_time_ == time &&
492 !chunk_demuxer_) {
493 // If the ready state was high enough before, we can indicate that the seek
494 // completed just by restoring it. Otherwise we will just wait for the real
495 // ready state change to eventually happen.
496 if (old_state == ReadyStateHaveEnoughData) {
srirama.m8f4a37562014-12-13 08:16:18497 main_task_runner_->PostTask(
alokp967c902452016-05-06 05:21:37498 FROM_HERE, base::Bind(&WebMediaPlayerImpl::OnBufferingStateChange,
499 AsWeakPtr(), BUFFERING_HAVE_ENOUGH));
srirama.m36ab2682014-12-11 04:20:01500 }
sandersd1c0bba02016-03-04 23:14:08501 return;
srirama.m36ab2682014-12-11 04:20:01502 }
[email protected]44ff37c02009-10-24 01:03:03503
dalecurtis04bdb582016-08-17 22:15:23504 // Call this before setting |seeking_| so that the current media time can be
505 // recorded by the reporter.
506 if (watch_time_reporter_)
507 watch_time_reporter_->OnSeeking();
508
sandersd50a635e2016-04-04 22:50:09509 // TODO(sandersd): Ideally we would not clear the idle state if
510 // |pipeline_controller_| can elide the seek.
511 is_idle_ = false;
512 ended_ = false;
513
[email protected]b3766a22010-12-22 17:34:13514 seeking_ = true;
sandersd1c0bba02016-03-04 23:14:08515 seek_time_ = time;
516 if (paused_)
517 paused_time_ = time;
518 pipeline_controller_.Seek(time, time_updated);
[email protected]b3766a22010-12-22 17:34:13519
sandersd50a635e2016-04-04 22:50:09520 // This needs to be called after Seek() so that if a resume is triggered, it
521 // is to the correct time.
522 UpdatePlayState();
[email protected]ec9212f2008-12-18 21:40:36523}
524
[email protected]39bdde32013-04-17 17:44:20525void WebMediaPlayerImpl::setRate(double rate) {
pkastingf5279482016-07-27 02:18:20526 DVLOG(1) << __func__ << "(" << rate << ")";
acolwellb4034942014-08-28 15:42:43527 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]d43ed912009-02-03 04:52:53528
[email protected]378f0b72009-08-11 17:11:42529 // TODO(kylep): Remove when support for negatives is added. Also, modify the
530 // following checks so rewind uses reasonable values also.
[email protected]39bdde32013-04-17 17:44:20531 if (rate < 0.0)
[email protected]378f0b72009-08-11 17:11:42532 return;
533
534 // Limit rates to reasonable values by clamping.
[email protected]39bdde32013-04-17 17:44:20535 if (rate != 0.0) {
[email protected]378f0b72009-08-11 17:11:42536 if (rate < kMinRate)
537 rate = kMinRate;
538 else if (rate > kMaxRate)
539 rate = kMaxRate;
540 }
541
[email protected]49480902009-07-14 20:23:43542 playback_rate_ = rate;
543 if (!paused_) {
[email protected]f6af7592014-02-28 10:09:11544 pipeline_.SetPlaybackRate(rate);
[email protected]039b7542013-10-17 22:06:25545 if (data_source_)
546 data_source_->MediaPlaybackRateChanged(rate);
[email protected]49480902009-07-14 20:23:43547 }
[email protected]ec9212f2008-12-18 21:40:36548}
549
[email protected]39bdde32013-04-17 17:44:20550void WebMediaPlayerImpl::setVolume(double volume) {
pkastingf5279482016-07-27 02:18:20551 DVLOG(1) << __func__ << "(" << volume << ")";
acolwellb4034942014-08-28 15:42:43552 DCHECK(main_task_runner_->BelongsToCurrentThread());
dalecurtisbb3eaac2016-01-27 21:10:25553 volume_ = volume;
554 pipeline_.SetVolume(volume_ * volume_multiplier_);
dalecurtis04bdb582016-08-17 22:15:23555 if (watch_time_reporter_)
556 watch_time_reporter_->OnVolumeChange(volume);
mlamouri910111362016-11-04 11:28:24557
558 // The play state is updated because the player might have left the autoplay
559 // muted state.
560 UpdatePlayState();
[email protected]ec9212f2008-12-18 21:40:36561}
[email protected]f0a51fb52009-03-05 12:46:38562
guidouc7babef2015-10-22 00:42:35563void WebMediaPlayerImpl::setSinkId(
564 const blink::WebString& sink_id,
565 const blink::WebSecurityOrigin& security_origin,
566 blink::WebSetSinkIdCallbacks* web_callback) {
guidou69223ce2015-06-16 10:36:19567 DCHECK(main_task_runner_->BelongsToCurrentThread());
pkastingf5279482016-07-27 02:18:20568 DVLOG(1) << __func__;
guidouc7babef2015-10-22 00:42:35569
olka68b69392016-04-01 11:42:12570 media::OutputDeviceStatusCB callback =
571 media::ConvertToOutputDeviceStatusCB(web_callback);
guidouc7babef2015-10-22 00:42:35572 media_task_runner_->PostTask(
573 FROM_HERE,
574 base::Bind(&SetSinkIdOnMediaThread, audio_source_provider_,
575 sink_id.utf8(), static_cast<url::Origin>(security_origin),
576 callback));
guidou69223ce2015-06-16 10:36:19577}
578
dalecurtisb6e052f52016-08-25 00:35:55579STATIC_ASSERT_ENUM(WebMediaPlayer::PreloadNone, MultibufferDataSource::NONE);
danakj365175c2016-02-06 00:37:37580STATIC_ASSERT_ENUM(WebMediaPlayer::PreloadMetaData,
dalecurtisb6e052f52016-08-25 00:35:55581 MultibufferDataSource::METADATA);
582STATIC_ASSERT_ENUM(WebMediaPlayer::PreloadAuto, MultibufferDataSource::AUTO);
[email protected]23a8b1d82011-04-05 16:28:20583
[email protected]ef405f66b2012-04-18 02:39:55584void WebMediaPlayerImpl::setPreload(WebMediaPlayer::Preload preload) {
pkastingf5279482016-07-27 02:18:20585 DVLOG(1) << __func__ << "(" << preload << ")";
acolwellb4034942014-08-28 15:42:43586 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]4e6be3f2009-05-07 02:24:44587
dalecurtisb6e052f52016-08-25 00:35:55588 preload_ = static_cast<MultibufferDataSource::Preload>(preload);
[email protected]b49beeb2013-03-01 20:04:00589 if (data_source_)
[email protected]09c60222014-08-07 16:42:31590 data_source_->SetPreload(preload_);
[email protected]4e6be3f2009-05-07 02:24:44591}
592
danakj365175c2016-02-06 00:37:37593STATIC_ASSERT_ENUM(WebMediaPlayer::BufferingStrategy::Normal,
dalecurtisb6e052f52016-08-25 00:35:55594 MultibufferDataSource::BUFFERING_STRATEGY_NORMAL);
danakj365175c2016-02-06 00:37:37595STATIC_ASSERT_ENUM(WebMediaPlayer::BufferingStrategy::Aggressive,
dalecurtisb6e052f52016-08-25 00:35:55596 MultibufferDataSource::BUFFERING_STRATEGY_AGGRESSIVE);
sandersdc6ab163a2015-12-12 03:56:13597
598void WebMediaPlayerImpl::setBufferingStrategy(
599 WebMediaPlayer::BufferingStrategy buffering_strategy) {
pkastingf5279482016-07-27 02:18:20600 DVLOG(1) << __func__;
sandersdc6ab163a2015-12-12 03:56:13601 DCHECK(main_task_runner_->BelongsToCurrentThread());
602
dalecurtis37fe5862016-03-15 19:29:09603#if defined(OS_ANDROID)
604 // We disallow aggressive buffering on Android since it matches the behavior
605 // of the platform media player and may have data usage penalties.
606 // TODO(dalecurtis, hubbe): We should probably stop using "pause-and-buffer"
607 // everywhere. See http://crbug.com/594669 for more details.
dalecurtisb6e052f52016-08-25 00:35:55608 buffering_strategy_ = MultibufferDataSource::BUFFERING_STRATEGY_NORMAL;
dalecurtis37fe5862016-03-15 19:29:09609#else
sandersdc6ab163a2015-12-12 03:56:13610 buffering_strategy_ =
dalecurtisb6e052f52016-08-25 00:35:55611 static_cast<MultibufferDataSource::BufferingStrategy>(buffering_strategy);
dalecurtis37fe5862016-03-15 19:29:09612#endif
613
sandersdc6ab163a2015-12-12 03:56:13614 if (data_source_)
615 data_source_->SetBufferingStrategy(buffering_strategy_);
616}
617
[email protected]4e6be3f2009-05-07 02:24:44618bool WebMediaPlayerImpl::hasVideo() const {
acolwellb4034942014-08-28 15:42:43619 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]d43ed912009-02-03 04:52:53620
[email protected]b8877772014-03-26 20:17:15621 return pipeline_metadata_.has_video;
[email protected]d43ed912009-02-03 04:52:53622}
623
[email protected]fc367af2009-08-14 23:06:35624bool WebMediaPlayerImpl::hasAudio() const {
acolwellb4034942014-08-28 15:42:43625 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]fc367af2009-08-14 23:06:35626
[email protected]b8877772014-03-26 20:17:15627 return pipeline_metadata_.has_audio;
[email protected]fc367af2009-08-14 23:06:35628}
629
servolkf25ceed2016-07-01 03:44:38630void WebMediaPlayerImpl::enabledAudioTracksChanged(
631 const blink::WebVector<blink::WebMediaPlayer::TrackId>& enabledTrackIds) {
632 DCHECK(main_task_runner_->BelongsToCurrentThread());
633
634 std::ostringstream logstr;
635 std::vector<MediaTrack::Id> enabledMediaTrackIds;
636 for (const auto& blinkTrackId : enabledTrackIds) {
637 MediaTrack::Id track_id = blinkTrackId.utf8().data();
638 logstr << track_id << " ";
639 enabledMediaTrackIds.push_back(track_id);
640 }
641 MEDIA_LOG(INFO, media_log_) << "Enabled audio tracks: [" << logstr.str()
642 << "]";
643 pipeline_.OnEnabledAudioTracksChanged(enabledMediaTrackIds);
644}
645
646void WebMediaPlayerImpl::selectedVideoTrackChanged(
647 blink::WebMediaPlayer::TrackId* selectedTrackId) {
648 DCHECK(main_task_runner_->BelongsToCurrentThread());
649
650 std::ostringstream logstr;
651 std::vector<MediaTrack::Id> selectedVideoMediaTrackId;
652 if (selectedTrackId) {
653 selectedVideoMediaTrackId.push_back(selectedTrackId->utf8().data());
654 logstr << selectedVideoMediaTrackId[0];
655 }
656 MEDIA_LOG(INFO, media_log_) << "Selected video track: [" << logstr.str()
657 << "]";
658 pipeline_.OnSelectedVideoTrackChanged(selectedVideoMediaTrackId);
659}
660
[email protected]180ef242013-11-07 06:50:46661blink::WebSize WebMediaPlayerImpl::naturalSize() const {
acolwellb4034942014-08-28 15:42:43662 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]d43ed912009-02-03 04:52:53663
[email protected]b8877772014-03-26 20:17:15664 return blink::WebSize(pipeline_metadata_.natural_size);
[email protected]d43ed912009-02-03 04:52:53665}
666
[email protected]4e6be3f2009-05-07 02:24:44667bool WebMediaPlayerImpl::paused() const {
acolwellb4034942014-08-28 15:42:43668 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]d43ed912009-02-03 04:52:53669
hubbed5f36882016-01-15 22:40:37670#if defined(OS_ANDROID) // WMPI_CAST
671 if (isRemote())
672 return cast_impl_.paused();
673#endif
sandersd50a635e2016-04-04 22:50:09674
[email protected]f6af7592014-02-28 10:09:11675 return pipeline_.GetPlaybackRate() == 0.0f;
[email protected]d43ed912009-02-03 04:52:53676}
677
[email protected]4e6be3f2009-05-07 02:24:44678bool WebMediaPlayerImpl::seeking() const {
acolwellb4034942014-08-28 15:42:43679 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]d43ed912009-02-03 04:52:53680
[email protected]ef405f66b2012-04-18 02:39:55681 if (ready_state_ == WebMediaPlayer::ReadyStateHaveNothing)
[email protected]0acebfa2009-08-21 22:45:40682 return false;
[email protected]67cd5052009-09-10 21:53:22683
[email protected]b3766a22010-12-22 17:34:13684 return seeking_;
[email protected]ec9212f2008-12-18 21:40:36685}
686
[email protected]39bdde32013-04-17 17:44:20687double WebMediaPlayerImpl::duration() const {
acolwellb4034942014-08-28 15:42:43688 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]39bdde32013-04-17 17:44:20689
690 if (ready_state_ == WebMediaPlayer::ReadyStateHaveNothing)
691 return std::numeric_limits<double>::quiet_NaN();
692
[email protected]39bdde32013-04-17 17:44:20693 return GetPipelineDuration();
[email protected]d43ed912009-02-03 04:52:53694}
695
[email protected]db66d0092014-04-16 07:15:12696double WebMediaPlayerImpl::timelineOffset() const {
acolwellb4034942014-08-28 15:42:43697 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]db66d0092014-04-16 07:15:12698
699 if (pipeline_metadata_.timeline_offset.is_null())
700 return std::numeric_limits<double>::quiet_NaN();
701
702 return pipeline_metadata_.timeline_offset.ToJsTime();
703}
704
[email protected]39bdde32013-04-17 17:44:20705double WebMediaPlayerImpl::currentTime() const {
acolwellb4034942014-08-28 15:42:43706 DCHECK(main_task_runner_->BelongsToCurrentThread());
scherkusd2c745b2014-09-04 05:03:40707 DCHECK_NE(ready_state_, WebMediaPlayer::ReadyStateHaveNothing);
708
709 // TODO(scherkus): Replace with an explicit ended signal to HTMLMediaElement,
710 // see http://crbug.com/409280
711 if (ended_)
712 return duration();
713
sandersd1c0bba02016-03-04 23:14:08714 if (seeking())
715 return seek_time_.InSecondsF();
wolenetz1b2ae7d2015-06-10 00:44:21716
hubbed5f36882016-01-15 22:40:37717#if defined(OS_ANDROID) // WMPI_CAST
sandersd1c0bba02016-03-04 23:14:08718 if (isRemote())
hubbed5f36882016-01-15 22:40:37719 return cast_impl_.currentTime();
hubbed5f36882016-01-15 22:40:37720#endif
721
sandersd1c0bba02016-03-04 23:14:08722 if (paused_)
hubbed5f36882016-01-15 22:40:37723 return paused_time_.InSecondsF();
hubbed5f36882016-01-15 22:40:37724
725 return pipeline_.GetMediaTime().InSecondsF();
[email protected]d43ed912009-02-03 04:52:53726}
727
danakj13afe0362016-02-27 01:22:50728WebMediaPlayer::NetworkState WebMediaPlayerImpl::getNetworkState() const {
acolwellb4034942014-08-28 15:42:43729 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]ddb1e5a2010-12-13 20:10:45730 return network_state_;
731}
732
danakj13afe0362016-02-27 01:22:50733WebMediaPlayer::ReadyState WebMediaPlayerImpl::getReadyState() const {
acolwellb4034942014-08-28 15:42:43734 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]ddb1e5a2010-12-13 20:10:45735 return ready_state_;
736}
737
wolenetz4d39cc02016-04-05 19:54:41738blink::WebString WebMediaPlayerImpl::getErrorMessage() {
739 DCHECK(main_task_runner_->BelongsToCurrentThread());
740 return blink::WebString::fromUTF8(media_log_->GetLastErrorMessage());
741}
742
[email protected]02022fc2014-05-16 00:05:31743blink::WebTimeRanges WebMediaPlayerImpl::buffered() const {
acolwellb4034942014-08-28 15:42:43744 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]779a8322014-08-22 21:28:37745
acolwell9e0840d2014-09-06 19:01:32746 Ranges<base::TimeDelta> buffered_time_ranges =
[email protected]02022fc2014-05-16 00:05:31747 pipeline_.GetBufferedTimeRanges();
[email protected]779a8322014-08-22 21:28:37748
749 const base::TimeDelta duration = pipeline_.GetMediaDuration();
dalecurtis39a7f932016-07-19 18:34:59750 if (duration != kInfiniteDuration) {
[email protected]779a8322014-08-22 21:28:37751 buffered_data_source_host_.AddBufferedTimeRanges(
752 &buffered_time_ranges, duration);
753 }
[email protected]02022fc2014-05-16 00:05:31754 return ConvertToWebTimeRanges(buffered_time_ranges);
755}
756
philipjb0e6f3f2014-09-30 09:51:53757blink::WebTimeRanges WebMediaPlayerImpl::seekable() const {
acolwellb4034942014-08-28 15:42:43758 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]39bdde32013-04-17 17:44:20759
dalecurtis56359cb2014-10-28 00:06:29760 if (ready_state_ < WebMediaPlayer::ReadyStateHaveMetadata)
philipjb0e6f3f2014-09-30 09:51:53761 return blink::WebTimeRanges();
762
dalecurtis56359cb2014-10-28 00:06:29763 const double seekable_end = duration();
764
765 // Allow a special exception for seeks to zero for streaming sources with a
766 // finite duration; this allows looping to work.
767 const bool allow_seek_to_zero = data_source_ && data_source_->IsStreaming() &&
mateuszs3371ab02015-04-24 13:20:23768 std::isfinite(seekable_end);
dalecurtis56359cb2014-10-28 00:06:29769
770 // TODO(dalecurtis): Technically this allows seeking on media which return an
771 // infinite duration so long as DataSource::IsStreaming() is false. While not
772 // expected, disabling this breaks semi-live players, http://crbug.com/427412.
773 const blink::WebTimeRange seekable_range(
774 0.0, allow_seek_to_zero ? 0.0 : seekable_end);
philipjb0e6f3f2014-09-30 09:51:53775 return blink::WebTimeRanges(&seekable_range, 1);
[email protected]ec9212f2008-12-18 21:40:36776}
777
[email protected]5d2b3e4c2014-05-12 23:27:30778bool WebMediaPlayerImpl::didLoadingProgress() {
acolwellb4034942014-08-28 15:42:43779 DCHECK(main_task_runner_->BelongsToCurrentThread());
dalecurtise7120dc2016-09-03 02:54:35780
781 // Note: Separate variables used to ensure both methods are called every time.
782 const bool pipeline_progress = pipeline_.DidLoadingProgress();
783 const bool data_progress = buffered_data_source_host_.DidLoadingProgress();
784 const bool did_loading_progress = pipeline_progress || data_progress;
785
786 // If we've idle suspended before reaching kHaveFutureData and loading has
787 // progressed we need to spin up the renderer and figure out if we have enough
788 // data yet; |client_| may be waiting on this signal to trigger playback. The
789 // idle timeout is long enough that this is a low-cost operation.
790 if (highest_ready_state_ < ReadyState::ReadyStateHaveFutureData &&
791 pipeline_controller_.IsSuspended() && did_loading_progress && is_idle_) {
792 is_idle_ = false;
793 UpdatePlayState();
794 }
795
watkd026f792016-11-05 00:28:51796 if (did_loading_progress)
797 last_time_loading_progressed_ = tick_clock_->NowTicks();
798
dalecurtise7120dc2016-09-03 02:54:35799 return did_loading_progress;
[email protected]d43ed912009-02-03 04:52:53800}
801
[email protected]dd5c7972014-08-21 15:00:37802void WebMediaPlayerImpl::paint(blink::WebCanvas* canvas,
803 const blink::WebRect& rect,
xidachen0ebd94d2016-09-07 15:47:22804 SkPaint& paint) {
acolwellb4034942014-08-28 15:42:43805 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]dd061e12014-05-06 19:21:22806 TRACE_EVENT0("media", "WebMediaPlayerImpl:paint");
[email protected]4e6be3f2009-05-07 02:24:44807
xhwang213e50c2016-10-10 23:56:31808 // TODO(sandersd): Move this check into GetCurrentFrameFromCompositor() when
809 // we have other ways to check if decoder owns video frame.
810 // See http://crbug.com/595716 and http://crbug.com/602708
jrummelle616ee92016-10-08 02:15:44811 if (cdm_)
xhwang80739452016-01-13 00:48:00812 return;
813
mcasasf1236fc22015-05-29 22:38:56814 scoped_refptr<VideoFrame> video_frame = GetCurrentFrameFromCompositor();
[email protected]0fe5d43b2014-01-24 23:32:45815
[email protected]b49beeb2013-03-01 20:04:00816 gfx::Rect gfx_rect(rect);
dongseong.hwang0c4e9d82015-01-08 20:11:13817 Context3D context_3d;
mcasas265bdbf82015-06-12 18:44:07818 if (video_frame.get() && video_frame->HasTextures()) {
mcasasf1236fc22015-05-29 22:38:56819 if (!context_3d_cb_.is_null())
dongseong.hwang0c4e9d82015-01-08 20:11:13820 context_3d = context_3d_cb_.Run();
dongseong.hwang0c4e9d82015-01-08 20:11:13821 if (!context_3d.gl)
danakj53f7ec902016-05-21 01:30:10822 return; // Unable to get/create a shared main thread context.
823 if (!context_3d.gr_context)
824 return; // The context has been lost since and can't setup a GrContext.
dongseong.hwang0c4e9d82015-01-08 20:11:13825 }
danakj795f1732015-08-31 23:40:22826 skcanvas_video_renderer_.Paint(video_frame, canvas, gfx::RectF(gfx_rect),
xidachen0ebd94d2016-09-07 15:47:22827 paint, pipeline_metadata_.video_rotation,
danakj795f1732015-08-31 23:40:22828 context_3d);
[email protected]ec9212f2008-12-18 21:40:36829}
[email protected]5df51652009-01-17 00:03:00830
[email protected]38259a7a82009-07-29 21:49:49831bool WebMediaPlayerImpl::hasSingleSecurityOrigin() const {
[email protected]b49beeb2013-03-01 20:04:00832 if (data_source_)
833 return data_source_->HasSingleOrigin();
[email protected]fcdb7462009-10-21 21:05:11834 return true;
[email protected]38259a7a82009-07-29 21:49:49835}
836
[email protected]3fe27112012-06-07 04:00:01837bool WebMediaPlayerImpl::didPassCORSAccessCheck() const {
[email protected]b49beeb2013-03-01 20:04:00838 if (data_source_)
839 return data_source_->DidPassCORSAccessCheck();
840 return false;
[email protected]3fe27112012-06-07 04:00:01841}
842
[email protected]39bdde32013-04-17 17:44:20843double WebMediaPlayerImpl::mediaTimeForTimeValue(double timeValue) const {
qinminb4c39782015-08-10 18:43:24844 return base::TimeDelta::FromSecondsD(timeValue).InSecondsF();
[email protected]e06e16d82011-05-26 22:13:33845}
846
[email protected]d82b18ae2011-03-23 21:28:59847unsigned WebMediaPlayerImpl::decodedFrameCount() const {
acolwellb4034942014-08-28 15:42:43848 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]4c51bc662011-02-16 02:03:16849
acolwell9e0840d2014-09-06 19:01:32850 PipelineStatistics stats = pipeline_.GetStatistics();
[email protected]4c51bc662011-02-16 02:03:16851 return stats.video_frames_decoded;
852}
853
[email protected]d82b18ae2011-03-23 21:28:59854unsigned WebMediaPlayerImpl::droppedFrameCount() const {
acolwellb4034942014-08-28 15:42:43855 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]4c51bc662011-02-16 02:03:16856
acolwell9e0840d2014-09-06 19:01:32857 PipelineStatistics stats = pipeline_.GetStatistics();
[email protected]dd061e12014-05-06 19:21:22858 return stats.video_frames_dropped;
[email protected]4c51bc662011-02-16 02:03:16859}
860
chakshu.a94326b72016-03-08 05:11:44861size_t WebMediaPlayerImpl::audioDecodedByteCount() const {
acolwellb4034942014-08-28 15:42:43862 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]4c51bc662011-02-16 02:03:16863
acolwell9e0840d2014-09-06 19:01:32864 PipelineStatistics stats = pipeline_.GetStatistics();
[email protected]4c51bc662011-02-16 02:03:16865 return stats.audio_bytes_decoded;
866}
867
chakshu.a94326b72016-03-08 05:11:44868size_t WebMediaPlayerImpl::videoDecodedByteCount() const {
acolwellb4034942014-08-28 15:42:43869 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]4c51bc662011-02-16 02:03:16870
acolwell9e0840d2014-09-06 19:01:32871 PipelineStatistics stats = pipeline_.GetStatistics();
[email protected]4c51bc662011-02-16 02:03:16872 return stats.video_bytes_decoded;
873}
874
[email protected]6523b242013-03-13 11:10:07875bool WebMediaPlayerImpl::copyVideoTextureToPlatformTexture(
danakj46070b02016-03-28 21:54:11876 gpu::gles2::GLES2Interface* gl,
zmo57d577a2015-10-30 18:28:59877 unsigned int texture,
878 unsigned int internal_format,
879 unsigned int type,
880 bool premultiply_alpha,
881 bool flip_y) {
xhwang213e50c2016-10-10 23:56:31882 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]bfc05f22013-10-19 17:55:16883 TRACE_EVENT0("media", "WebMediaPlayerImpl:copyVideoTextureToPlatformTexture");
884
xhwang213e50c2016-10-10 23:56:31885 // TODO(sandersd): Move this check into GetCurrentFrameFromCompositor() when
886 // we have other ways to check if decoder owns video frame.
887 // See http://crbug.com/595716 and http://crbug.com/602708
888 if (cdm_)
889 return false;
[email protected]dd061e12014-05-06 19:21:22890
xhwang213e50c2016-10-10 23:56:31891 scoped_refptr<VideoFrame> video_frame = GetCurrentFrameFromCompositor();
jbauman581d041c2016-07-21 01:01:03892 if (!video_frame.get() || !video_frame->HasTextures()) {
[email protected]e56f88c72013-06-25 22:31:29893 return false;
dongseong.hwang0c4e9d82015-01-08 20:11:13894 }
[email protected]df41e252014-02-03 23:39:50895
jbauman581d041c2016-07-21 01:01:03896 Context3D context_3d;
897 if (!context_3d_cb_.is_null())
898 context_3d = context_3d_cb_.Run();
899 return skcanvas_video_renderer_.CopyVideoFrameTexturesToGLTexture(
900 context_3d, gl, video_frame.get(), texture, internal_format, type,
901 premultiply_alpha, flip_y);
[email protected]6523b242013-03-13 11:10:07902}
903
[email protected]7bce1832014-01-09 00:01:22904void WebMediaPlayerImpl::setContentDecryptionModule(
[email protected]9ebc3b03f2014-08-13 04:01:23905 blink::WebContentDecryptionModule* cdm,
906 blink::WebContentDecryptionModuleResult result) {
acolwellb4034942014-08-28 15:42:43907 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]9ebc3b03f2014-08-13 04:01:23908
jrummell06f27072015-06-08 18:12:38909 // Once the CDM is set it can't be cleared as there may be frames being
910 // decrypted on other threads. So fail this request.
911 // http://crbug.com/462365#c7.
xhwang97de4202014-11-25 08:44:01912 if (!cdm) {
913 result.completeWithError(
jrummell06f27072015-06-08 18:12:38914 blink::WebContentDecryptionModuleExceptionInvalidStateError, 0,
915 "The existing MediaKeys object cannot be removed at this time.");
xhwang97de4202014-11-25 08:44:01916 return;
917 }
918
jrummell89e61d82015-07-23 20:03:34919 // Create a local copy of |result| to avoid problems with the callback
920 // getting passed to the media thread and causing |result| to be destructed
jrummell4acbec912016-02-27 02:45:03921 // on the wrong thread in some failure conditions. Blink should prevent
922 // multiple simultaneous calls.
923 DCHECK(!set_cdm_result_);
jrummell89e61d82015-07-23 20:03:34924 set_cdm_result_.reset(new blink::WebContentDecryptionModuleResult(result));
925
dalecurtis04bdb582016-08-17 22:15:23926 // Recreate the watch time reporter if necessary.
927 const bool was_encrypted = is_encrypted_;
928 is_encrypted_ = true;
929 if (!was_encrypted && watch_time_reporter_)
930 CreateWatchTimeReporter();
931
jrummelle616ee92016-10-08 02:15:44932 SetCdm(cdm);
xhwang97de4202014-11-25 08:44:01933}
934
xhwange8c4181a2014-12-06 08:10:01935void WebMediaPlayerImpl::OnEncryptedMediaInitData(
jrummellcf78967c2015-04-03 05:03:58936 EmeInitDataType init_data_type,
Avi Drissman97785ea2015-12-19 01:11:31937 const std::vector<uint8_t>& init_data) {
jrummellcf78967c2015-04-03 05:03:58938 DCHECK(init_data_type != EmeInitDataType::UNKNOWN);
xhwangbab66f52014-12-02 23:49:50939
ddorwin301ccdb2016-02-25 02:39:17940 // TODO(xhwang): Update this UMA name. https://crbug.com/589251
xhwangbab66f52014-12-02 23:49:50941 UMA_HISTOGRAM_COUNTS("Media.EME.NeedKey", 1);
942
dalecurtis04bdb582016-08-17 22:15:23943 // Recreate the watch time reporter if necessary.
944 const bool was_encrypted = is_encrypted_;
945 is_encrypted_ = true;
946 if (!was_encrypted && watch_time_reporter_)
947 CreateWatchTimeReporter();
948
srirama.m26f864d02015-07-14 05:21:46949 encrypted_client_->encrypted(
davidbenb50f00c2015-12-01 00:01:50950 ConvertToWebInitDataType(init_data_type), init_data.data(),
srirama.m26f864d02015-07-14 05:21:46951 base::saturated_cast<unsigned int>(init_data.size()));
xhwangbab66f52014-12-02 23:49:50952}
953
servolk81e01e02016-03-05 03:29:15954void WebMediaPlayerImpl::OnFFmpegMediaTracksUpdated(
dcheng3076abbf2016-04-22 20:42:39955 std::unique_ptr<MediaTracks> tracks) {
servolk81e01e02016-03-05 03:29:15956 // For MSE/chunk_demuxer case the media track updates are handled by
957 // WebSourceBufferImpl.
958 DCHECK(demuxer_.get());
959 DCHECK(!chunk_demuxer_);
servolkef1e5ef2016-03-25 04:55:26960
961 // Report the media track information to blink.
962 for (const auto& track : tracks->tracks()) {
963 if (track->type() == MediaTrack::Audio) {
servolkfa5c37c2016-06-16 17:56:47964 client_->addAudioTrack(blink::WebString::fromUTF8(track->id()),
965 blink::WebMediaPlayerClient::AudioTrackKindMain,
966 blink::WebString::fromUTF8(track->label()),
967 blink::WebString::fromUTF8(track->language()),
968 /*enabled*/ true);
servolkef1e5ef2016-03-25 04:55:26969 } else if (track->type() == MediaTrack::Video) {
servolkfa5c37c2016-06-16 17:56:47970 client_->addVideoTrack(blink::WebString::fromUTF8(track->id()),
971 blink::WebMediaPlayerClient::VideoTrackKindMain,
972 blink::WebString::fromUTF8(track->label()),
973 blink::WebString::fromUTF8(track->language()),
974 /*selected*/ true);
servolkef1e5ef2016-03-25 04:55:26975 } else {
976 // Text tracks are not supported through this code path yet.
977 NOTREACHED();
978 }
979 }
servolk81e01e02016-03-05 03:29:15980}
981
jrummelle616ee92016-10-08 02:15:44982void WebMediaPlayerImpl::SetCdm(blink::WebContentDecryptionModule* cdm) {
983 DCHECK(main_task_runner_->BelongsToCurrentThread());
984 DCHECK(cdm);
985 scoped_refptr<MediaKeys> cdm_reference =
986 ToWebContentDecryptionModuleImpl(cdm)->GetCdm();
987 if (!cdm_reference) {
988 NOTREACHED();
989 OnCdmAttached(false);
xhwang80739452016-01-13 00:48:00990 return;
991 }
992
jrummelle616ee92016-10-08 02:15:44993 CdmContext* cdm_context = cdm_reference->GetCdmContext();
994 if (!cdm_context) {
995 OnCdmAttached(false);
996 return;
997 }
998
xjzd3fe45a2016-10-12 18:26:37999 if (observer_)
1000 observer_->OnSetCdm(cdm_context);
1001
jrummelle616ee92016-10-08 02:15:441002 // Keep the reference to the CDM, as it shouldn't be destroyed until
1003 // after the pipeline is done with the |cdm_context|.
1004 pending_cdm_ = std::move(cdm_reference);
1005 pipeline_.SetCdm(cdm_context,
1006 base::Bind(&WebMediaPlayerImpl::OnCdmAttached, AsWeakPtr()));
xhwang97de4202014-11-25 08:44:011007}
1008
jrummell89e61d82015-07-23 20:03:341009void WebMediaPlayerImpl::OnCdmAttached(bool success) {
jrummelle616ee92016-10-08 02:15:441010 DCHECK(main_task_runner_->BelongsToCurrentThread());
1011 DCHECK(pending_cdm_);
1012
1013 // If the CDM is set from the constructor there is no promise
1014 // (|set_cdm_result_|) to fulfill.
xhwang97de4202014-11-25 08:44:011015 if (success) {
jrummelle616ee92016-10-08 02:15:441016 // This will release the previously attached CDM (if any).
1017 cdm_ = std::move(pending_cdm_);
1018 if (set_cdm_result_) {
1019 set_cdm_result_->complete();
1020 set_cdm_result_.reset();
1021 }
1022
xhwang97de4202014-11-25 08:44:011023 return;
1024 }
1025
jrummelle616ee92016-10-08 02:15:441026 pending_cdm_ = nullptr;
1027 if (set_cdm_result_) {
1028 set_cdm_result_->completeWithError(
1029 blink::WebContentDecryptionModuleExceptionNotSupportedError, 0,
1030 "Unable to set MediaKeys object");
1031 set_cdm_result_.reset();
1032 }
[email protected]9ebc3b03f2014-08-13 04:01:231033}
1034
sandersd1c0bba02016-03-04 23:14:081035void WebMediaPlayerImpl::OnPipelineSeeked(bool time_updated) {
[email protected]5d11eff2011-09-15 00:06:061036 seeking_ = false;
wolenetz1b2ae7d2015-06-10 00:44:211037 seek_time_ = base::TimeDelta();
hubbe5a2dec022016-03-17 01:14:231038 if (paused_) {
1039#if defined(OS_ANDROID) // WMPI_CAST
1040 if (isRemote()) {
1041 paused_time_ = base::TimeDelta::FromSecondsD(cast_impl_.currentTime());
1042 } else {
1043 paused_time_ = pipeline_.GetMediaTime();
1044 }
1045#else
sandersd1c0bba02016-03-04 23:14:081046 paused_time_ = pipeline_.GetMediaTime();
hubbe5a2dec022016-03-17 01:14:231047#endif
dalecurtis04bdb582016-08-17 22:15:231048 } else {
1049 DCHECK(watch_time_reporter_);
1050 watch_time_reporter_->OnPlaying();
hubbe5a2dec022016-03-17 01:14:231051 }
sandersd1c0bba02016-03-04 23:14:081052 if (time_updated)
1053 should_notify_time_changed_ = true;
dalecurtisaf34d8712016-09-20 04:32:261054
1055 // Reset underflow count upon seek; this prevents looping videos and user
1056 // actions from artificially inflating the underflow count.
1057 underflow_count_ = 0;
[email protected]8931c41a2009-07-07 17:31:491058}
1059
sandersd1c0bba02016-03-04 23:14:081060void WebMediaPlayerImpl::OnPipelineSuspended() {
hubbed5f36882016-01-15 22:40:371061#if defined(OS_ANDROID)
1062 if (isRemote()) {
1063 scoped_refptr<VideoFrame> frame = cast_impl_.GetCastingBanner();
sandersd50a635e2016-04-04 22:50:091064 if (frame)
dalecurtise9c89e92016-05-20 19:38:001065 compositor_->PaintSingleFrame(frame);
hubbed5f36882016-01-15 22:40:371066 }
1067#endif
1068
dalecurtis37fe5862016-03-15 19:29:091069 // If we're not in an aggressive buffering state, tell the data source we have
1070 // enough data so that it may release the connection.
1071 if (buffering_strategy_ !=
dalecurtisb6e052f52016-08-25 00:35:551072 MultibufferDataSource::BUFFERING_STRATEGY_AGGRESSIVE) {
liberato3f9f32b2016-03-16 16:54:511073 if (data_source_)
1074 data_source_->OnBufferingHaveEnough(true);
dalecurtis37fe5862016-03-15 19:29:091075 }
1076
sandersd50a635e2016-04-04 22:50:091077 ReportMemoryUsage();
1078
sandersd1c0bba02016-03-04 23:14:081079 if (pending_suspend_resume_cycle_) {
watkdee516f2016-02-18 02:22:191080 pending_suspend_resume_cycle_ = false;
sandersd50a635e2016-04-04 22:50:091081 UpdatePlayState();
dalecurtis0431cbf2016-03-12 01:19:431082 }
sandersd1c0bba02016-03-04 23:14:081083}
1084
alokp967c902452016-05-06 05:21:371085void WebMediaPlayerImpl::OnDemuxerOpened() {
1086 DCHECK(main_task_runner_->BelongsToCurrentThread());
1087 client_->mediaSourceOpened(
1088 new WebMediaSourceImpl(chunk_demuxer_, media_log_));
1089}
1090
1091void WebMediaPlayerImpl::OnError(PipelineStatus status) {
pkastingf5279482016-07-27 02:18:201092 DVLOG(1) << __func__;
alokp967c902452016-05-06 05:21:371093 DCHECK(main_task_runner_->BelongsToCurrentThread());
1094 DCHECK_NE(status, PIPELINE_OK);
1095
1096 if (suppress_destruction_errors_)
1097 return;
1098
1099 ReportPipelineError(load_type_, frame_->getSecurityOrigin(), status);
1100 media_log_->AddEvent(media_log_->CreatePipelineErrorEvent(status));
1101
1102 if (ready_state_ == WebMediaPlayer::ReadyStateHaveNothing) {
1103 // Any error that occurs before reaching ReadyStateHaveMetadata should
1104 // be considered a format error.
1105 SetNetworkState(WebMediaPlayer::NetworkStateFormatError);
1106 } else {
1107 SetNetworkState(PipelineErrorToNetworkState(status));
1108 }
1109
1110 UpdatePlayState();
1111}
1112
1113void WebMediaPlayerImpl::OnEnded() {
pkastingf5279482016-07-27 02:18:201114 DVLOG(1) << __func__;
acolwellb4034942014-08-28 15:42:431115 DCHECK(main_task_runner_->BelongsToCurrentThread());
scherkusd2c745b2014-09-04 05:03:401116
sandersd1c0bba02016-03-04 23:14:081117 // Ignore state changes until we've completed all outstanding operations.
1118 if (!pipeline_controller_.IsStable())
scherkusd2c745b2014-09-04 05:03:401119 return;
1120
1121 ended_ = true;
[email protected]ce70c982013-12-20 17:04:321122 client_->timeChanged();
sandersd50a635e2016-04-04 22:50:091123
1124 // We don't actually want this to run until |client_| calls seek() or pause(),
1125 // but that should have already happened in timeChanged() and so this is
1126 // expected to be a no-op.
1127 UpdatePlayState();
[email protected]576537842009-08-12 23:52:051128}
1129
alokp967c902452016-05-06 05:21:371130void WebMediaPlayerImpl::OnMetadata(PipelineMetadata metadata) {
pkastingf5279482016-07-27 02:18:201131 DVLOG(1) << __func__;
acolwellb4034942014-08-28 15:42:431132 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]a8e2cb82012-08-17 00:02:391133
[email protected]b8877772014-03-26 20:17:151134 pipeline_metadata_ = metadata;
[email protected]739847c02014-01-16 00:12:251135
dalecurtis04bdb582016-08-17 22:15:231136 SetReadyState(WebMediaPlayer::ReadyStateHaveMetadata);
dalecurtis849cf4b22015-03-27 18:35:451137 UMA_HISTOGRAM_ENUMERATION("Media.VideoRotation", metadata.video_rotation,
acolwell9e0840d2014-09-06 19:01:321138 VIDEO_ROTATION_MAX + 1);
[email protected]21c3f7502013-03-23 03:29:511139
[email protected]b8877772014-03-26 20:17:151140 if (hasVideo()) {
sandersd2c478422016-08-02 01:19:251141 pipeline_metadata_.natural_size = GetRotatedVideoSize(
1142 pipeline_metadata_.video_rotation, pipeline_metadata_.natural_size);
[email protected]f78c3e82014-08-08 01:24:471143
tsunghungee562e92016-07-20 18:03:311144 if (overlay_enabled_ && surface_manager_)
watkf835a792016-06-24 23:24:401145 surface_manager_->NaturalSizeChanged(pipeline_metadata_.natural_size);
1146
1147 DCHECK(!video_weblayer_);
dalecurtise1edb312016-06-22 02:33:211148 video_weblayer_.reset(new cc_blink::WebLayerImpl(cc::VideoLayer::Create(
1149 compositor_, pipeline_metadata_.video_rotation)));
jbauman952274d2015-09-10 23:23:361150 video_weblayer_->layer()->SetContentsOpaque(opaque_);
1151 video_weblayer_->SetContentsOpaqueIsFixed(true);
[email protected]a7c4f582014-04-16 18:44:491152 client_->setWebLayer(video_weblayer_.get());
[email protected]a8e2cb82012-08-17 00:02:391153 }
dalecurtis8e4dc682016-03-15 02:30:301154
xjzd3fe45a2016-10-12 18:26:371155 if (observer_)
1156 observer_->OnMetadataChanged(metadata);
1157
dalecurtis04bdb582016-08-17 22:15:231158 CreateWatchTimeReporter();
sandersd50a635e2016-04-04 22:50:091159 UpdatePlayState();
[email protected]a8e2cb82012-08-17 00:02:391160}
1161
alokp967c902452016-05-06 05:21:371162void WebMediaPlayerImpl::OnBufferingStateChange(BufferingState state) {
pkastingf5279482016-07-27 02:18:201163 DVLOG(1) << __func__ << "(" << state << ")";
alokp967c902452016-05-06 05:21:371164 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]b8877772014-03-26 20:17:151165
sandersd1c0bba02016-03-04 23:14:081166 // Ignore buffering state changes until we've completed all outstanding
1167 // operations.
1168 if (!pipeline_controller_.IsStable())
[email protected]ba7d5f92014-06-24 05:37:401169 return;
[email protected]b8877772014-03-26 20:17:151170
chcunninghameb270c92016-07-15 01:00:451171 if (state == BUFFERING_HAVE_ENOUGH) {
dalecurtis821e803f2016-09-01 18:44:151172 if (data_source_ &&
1173 highest_ready_state_ < WebMediaPlayer::ReadyStateHaveEnoughData) {
1174 DCHECK_EQ(underflow_count_, 0);
1175 // Record a zero value for underflow histograms so that the histogram
1176 // includes playbacks which never encounter an underflow event.
1177 UMA_HISTOGRAM_COUNTS_100("Media.UnderflowCount", 0);
1178 UMA_HISTOGRAM_TIMES("Media.UnderflowDuration", base::TimeDelta());
1179 }
1180
chcunninghameb270c92016-07-15 01:00:451181 // TODO(chcunningham): Monitor playback position vs buffered. Potentially
1182 // transition to HAVE_FUTURE_DATA here if not enough is buffered.
1183 SetReadyState(WebMediaPlayer::ReadyStateHaveEnoughData);
[email protected]ba7d5f92014-06-24 05:37:401184
chcunninghameb270c92016-07-15 01:00:451185 // Let the DataSource know we have enough data. It may use this information
1186 // to release unused network connections.
1187 if (data_source_)
1188 data_source_->OnBufferingHaveEnough(false);
dalecurtis849cf4b22015-03-27 18:35:451189
chcunninghameb270c92016-07-15 01:00:451190 // Blink expects a timeChanged() in response to a seek().
1191 if (should_notify_time_changed_)
1192 client_->timeChanged();
dalecurtis0f0097a2015-12-01 17:40:471193
chcunninghameb270c92016-07-15 01:00:451194 // Once we have enough, start reporting the total memory usage. We'll also
1195 // report once playback starts.
1196 ReportMemoryUsage();
dalecurtis9d638a12016-08-30 06:20:551197
1198 // Report the amount of time it took to leave the underflow state. Don't
1199 // bother to report this for MSE playbacks since it's out of our control.
1200 if (underflow_timer_ && data_source_) {
1201 UMA_HISTOGRAM_TIMES("Media.UnderflowDuration",
1202 underflow_timer_->Elapsed());
1203 underflow_timer_.reset();
1204 }
chcunninghameb270c92016-07-15 01:00:451205 } else {
1206 // Buffering has underflowed.
1207 DCHECK_EQ(state, BUFFERING_HAVE_NOTHING);
dalecurtisacd77d62016-09-09 23:23:141208
1209 // Report the number of times we've entered the underflow state. Only report
1210 // for src= playback since for MSE it's out of our control. Ensure we only
1211 // report the value when transitioning from HAVE_ENOUGH to HAVE_NOTHING.
1212 if (data_source_ &&
1213 ready_state_ == WebMediaPlayer::ReadyStateHaveEnoughData) {
1214 UMA_HISTOGRAM_COUNTS_100("Media.UnderflowCount", ++underflow_count_);
1215 underflow_timer_.reset(new base::ElapsedTimer());
1216 }
1217
chcunninghameb270c92016-07-15 01:00:451218 // It shouldn't be possible to underflow if we've not advanced past
1219 // HAVE_CURRENT_DATA.
1220 DCHECK_GT(highest_ready_state_, WebMediaPlayer::ReadyStateHaveCurrentData);
1221 SetReadyState(WebMediaPlayer::ReadyStateHaveCurrentData);
1222 }
sandersd50a635e2016-04-04 22:50:091223
1224 UpdatePlayState();
[email protected]b8877772014-03-26 20:17:151225}
1226
alokp967c902452016-05-06 05:21:371227void WebMediaPlayerImpl::OnDurationChange() {
acolwellb4034942014-08-28 15:42:431228 DCHECK(main_task_runner_->BelongsToCurrentThread());
alokp967c902452016-05-06 05:21:371229
1230 // TODO(sandersd): We should call delegate_->DidPlay() with the new duration,
1231 // especially if it changed from <5s to >5s.
1232 if (ready_state_ == WebMediaPlayer::ReadyStateHaveNothing)
1233 return;
1234
1235 client_->durationChanged();
[email protected]81bb3322011-07-21 15:55:501236}
1237
alokp967c902452016-05-06 05:21:371238void WebMediaPlayerImpl::OnAddTextTrack(const TextTrackConfig& config,
1239 const AddTextTrackDoneCB& done_cb) {
acolwellb4034942014-08-28 15:42:431240 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]71537722013-05-23 06:47:531241
[email protected]8a561062013-11-22 01:19:311242 const WebInbandTextTrackImpl::Kind web_kind =
1243 static_cast<WebInbandTextTrackImpl::Kind>(config.kind());
1244 const blink::WebString web_label =
1245 blink::WebString::fromUTF8(config.label());
1246 const blink::WebString web_language =
1247 blink::WebString::fromUTF8(config.language());
[email protected]427ff102013-11-26 23:45:401248 const blink::WebString web_id =
1249 blink::WebString::fromUTF8(config.id());
[email protected]71537722013-05-23 06:47:531250
dcheng3076abbf2016-04-22 20:42:391251 std::unique_ptr<WebInbandTextTrackImpl> web_inband_text_track(
henriks9cce5fa2014-12-12 09:35:301252 new WebInbandTextTrackImpl(web_kind, web_label, web_language, web_id));
[email protected]8a561062013-11-22 01:19:311253
dcheng3076abbf2016-04-22 20:42:391254 std::unique_ptr<media::TextTrack> text_track(new TextTrackImpl(
dcheng652f5ff2015-12-27 08:54:001255 main_task_runner_, client_, std::move(web_inband_text_track)));
[email protected]8a561062013-11-22 01:19:311256
dcheng652f5ff2015-12-27 08:54:001257 done_cb.Run(std::move(text_track));
[email protected]71537722013-05-23 06:47:531258}
1259
alokp967c902452016-05-06 05:21:371260void WebMediaPlayerImpl::OnWaitingForDecryptionKey() {
1261 DCHECK(main_task_runner_->BelongsToCurrentThread());
1262
1263 encrypted_client_->didBlockPlaybackWaitingForKey();
1264 // TODO(jrummell): didResumePlaybackBlockedForKey() should only be called
1265 // when a key has been successfully added (e.g. OnSessionKeysChange() with
1266 // |has_additional_usable_key| = true). http://crbug.com/461903
1267 encrypted_client_->didResumePlaybackBlockedForKey();
1268}
1269
alokp5d86e9b2016-05-17 20:20:411270void WebMediaPlayerImpl::OnVideoNaturalSizeChange(const gfx::Size& size) {
1271 DCHECK(main_task_runner_->BelongsToCurrentThread());
1272 DCHECK_NE(ready_state_, WebMediaPlayer::ReadyStateHaveNothing);
1273
sandersd2c478422016-08-02 01:19:251274 gfx::Size rotated_size =
1275 GetRotatedVideoSize(pipeline_metadata_.video_rotation, size);
1276
1277 if (rotated_size == pipeline_metadata_.natural_size)
alokp5d86e9b2016-05-17 20:20:411278 return;
1279
1280 TRACE_EVENT0("media", "WebMediaPlayerImpl::OnNaturalSizeChanged");
sandersd2c478422016-08-02 01:19:251281 media_log_->AddEvent(media_log_->CreateVideoSizeSetEvent(
1282 rotated_size.width(), rotated_size.height()));
alokp5d86e9b2016-05-17 20:20:411283
tsunghungee562e92016-07-20 18:03:311284 if (overlay_enabled_ && surface_manager_)
sandersd2c478422016-08-02 01:19:251285 surface_manager_->NaturalSizeChanged(rotated_size);
alokp5d86e9b2016-05-17 20:20:411286
sandersd2c478422016-08-02 01:19:251287 pipeline_metadata_.natural_size = rotated_size;
alokp5d86e9b2016-05-17 20:20:411288 client_->sizeChanged();
1289}
1290
1291void WebMediaPlayerImpl::OnVideoOpacityChange(bool opaque) {
1292 DCHECK(main_task_runner_->BelongsToCurrentThread());
1293 DCHECK_NE(ready_state_, WebMediaPlayer::ReadyStateHaveNothing);
1294
1295 opaque_ = opaque;
1296 // Modify content opaqueness of cc::Layer directly so that
1297 // SetContentsOpaqueIsFixed is ignored.
1298 if (video_weblayer_)
1299 video_weblayer_->layer()->SetContentsOpaque(opaque_);
1300}
1301
dalecurtis0431cbf2016-03-12 01:19:431302void WebMediaPlayerImpl::OnHidden() {
sandersd1e49fb62015-12-12 01:18:061303 DCHECK(main_task_runner_->BelongsToCurrentThread());
dalecurtis04bdb582016-08-17 22:15:231304 if (watch_time_reporter_)
1305 watch_time_reporter_->OnHidden();
avayvod48a8be52016-08-04 19:52:501306
sandersd50a635e2016-04-04 22:50:091307 UpdatePlayState();
dalecurtis8b8505e72016-06-10 21:59:171308
1309 // Schedule suspended playing media to be paused if the user doesn't come back
1310 // to it within some timeout period to avoid any autoplay surprises.
1311 ScheduleIdlePauseTimer();
sandersd1e49fb62015-12-12 01:18:061312}
1313
1314void WebMediaPlayerImpl::OnShown() {
1315 DCHECK(main_task_runner_->BelongsToCurrentThread());
dalecurtis04bdb582016-08-17 22:15:231316 if (watch_time_reporter_)
1317 watch_time_reporter_->OnShown();
1318
sandersd50a635e2016-04-04 22:50:091319 must_suspend_ = false;
dalecurtis8b8505e72016-06-10 21:59:171320 background_pause_timer_.Stop();
avayvod48a8be52016-08-04 19:52:501321
sandersd50a635e2016-04-04 22:50:091322 UpdatePlayState();
sandersd1e49fb62015-12-12 01:18:061323}
1324
watkd026f792016-11-05 00:28:511325bool WebMediaPlayerImpl::OnSuspendRequested(bool must_suspend) {
dalecurtis0431cbf2016-03-12 01:19:431326 DCHECK(main_task_runner_->BelongsToCurrentThread());
1327
watkd026f792016-11-05 00:28:511328 if (must_suspend) {
sandersd50a635e2016-04-04 22:50:091329 must_suspend_ = true;
watkd026f792016-11-05 00:28:511330 UpdatePlayState();
1331 return true;
1332 }
sandersd50a635e2016-04-04 22:50:091333
watkd026f792016-11-05 00:28:511334 // If we're beyond HaveFutureData, we can safely suspend at any time.
1335 if (highest_ready_state_ >= WebMediaPlayer::ReadyStateHaveFutureData) {
1336 is_idle_ = true;
1337 UpdatePlayState();
1338 return true;
1339 }
1340
1341 // Before HaveFutureData blink will not call play(), so we must be careful to
1342 // only suspend if we'll eventually receive an event that will trigger a
1343 // resume. If the last time loading progressed was a while ago, and we still
1344 // haven't reached HaveFutureData, we assume that we're waiting on more data
1345 // to continue pre-rolling. When that data is loaded the pipeline will be
1346 // resumed by didLoadingProgress().
1347 if (last_time_loading_progressed_.is_null() ||
1348 (tick_clock_->NowTicks() - last_time_loading_progressed_) >
1349 kLoadingToIdleTimeout) {
1350 is_idle_ = true;
1351 UpdatePlayState();
1352 return true;
1353 }
1354
1355 return false;
dalecurtis0431cbf2016-03-12 01:19:431356}
1357
dalecurtisbb3eaac2016-01-27 21:10:251358void WebMediaPlayerImpl::OnPlay() {
1359 play();
1360 client_->playbackStateChanged();
1361}
1362
1363void WebMediaPlayerImpl::OnPause() {
1364 pause();
1365 client_->playbackStateChanged();
1366}
1367
1368void WebMediaPlayerImpl::OnVolumeMultiplierUpdate(double multiplier) {
1369 volume_multiplier_ = multiplier;
1370 setVolume(volume_);
1371}
1372
watkdee516f2016-02-18 02:22:191373void WebMediaPlayerImpl::ScheduleRestart() {
sandersd50a635e2016-04-04 22:50:091374 // TODO(watk): All restart logic should be moved into PipelineController.
1375 if (pipeline_.IsRunning() && !pipeline_controller_.IsPipelineSuspended()) {
watkdee516f2016-02-18 02:22:191376 pending_suspend_resume_cycle_ = true;
sandersd50a635e2016-04-04 22:50:091377 UpdatePlayState();
watkdee516f2016-02-18 02:22:191378 }
1379}
1380
hubbed5f36882016-01-15 22:40:371381#if defined(OS_ANDROID) // WMPI_CAST
hubbed5f36882016-01-15 22:40:371382bool WebMediaPlayerImpl::isRemote() const {
1383 return cast_impl_.isRemote();
1384}
1385
1386void WebMediaPlayerImpl::SetMediaPlayerManager(
1387 RendererMediaPlayerManagerInterface* media_player_manager) {
1388 cast_impl_.SetMediaPlayerManager(media_player_manager);
1389}
1390
1391void WebMediaPlayerImpl::requestRemotePlayback() {
1392 cast_impl_.requestRemotePlayback();
1393}
1394
1395void WebMediaPlayerImpl::requestRemotePlaybackControl() {
1396 cast_impl_.requestRemotePlaybackControl();
1397}
1398
avayvod8d8c53b2016-11-04 16:10:301399void WebMediaPlayerImpl::requestRemotePlaybackStop() {
1400 cast_impl_.requestRemotePlaybackStop();
1401}
1402
hubbed5f36882016-01-15 22:40:371403void WebMediaPlayerImpl::OnRemotePlaybackEnded() {
pkastingf5279482016-07-27 02:18:201404 DVLOG(1) << __func__;
hubbed5f36882016-01-15 22:40:371405 DCHECK(main_task_runner_->BelongsToCurrentThread());
1406
1407 ended_ = true;
1408 client_->timeChanged();
1409}
1410
1411void WebMediaPlayerImpl::OnDisconnectedFromRemoteDevice(double t) {
sandersd1c0bba02016-03-04 23:14:081412 DoSeek(base::TimeDelta::FromSecondsD(t), false);
hubbed5f36882016-01-15 22:40:371413
hubbed5f36882016-01-15 22:40:371414 // We already told the delegate we're paused when remoting started.
1415 client_->playbackStateChanged();
1416 client_->disconnectedFromRemoteDevice();
sandersd50a635e2016-04-04 22:50:091417
1418 UpdatePlayState();
hubbed5f36882016-01-15 22:40:371419}
1420
1421void WebMediaPlayerImpl::SuspendForRemote() {
sandersd50a635e2016-04-04 22:50:091422 if (pipeline_controller_.IsPipelineSuspended()) {
hubbed5f36882016-01-15 22:40:371423 scoped_refptr<VideoFrame> frame = cast_impl_.GetCastingBanner();
sandersd50a635e2016-04-04 22:50:091424 if (frame)
dalecurtise9c89e92016-05-20 19:38:001425 compositor_->PaintSingleFrame(frame);
hubbed5f36882016-01-15 22:40:371426 }
sandersd50a635e2016-04-04 22:50:091427
1428 UpdatePlayState();
hubbed5f36882016-01-15 22:40:371429}
1430
1431gfx::Size WebMediaPlayerImpl::GetCanvasSize() const {
1432 if (!video_weblayer_)
1433 return pipeline_metadata_.natural_size;
1434
1435 return video_weblayer_->bounds();
1436}
1437
1438void WebMediaPlayerImpl::SetDeviceScaleFactor(float scale_factor) {
1439 cast_impl_.SetDeviceScaleFactor(scale_factor);
1440}
hubbee4027f92016-05-19 05:18:131441
1442void WebMediaPlayerImpl::setPoster(const blink::WebURL& poster) {
1443 cast_impl_.setPoster(poster);
1444}
tguilbert25a4d112016-10-13 21:56:511445
1446void WebMediaPlayerImpl::SetUseFallbackPath(bool use_fallback_path) {
1447 use_fallback_path_ = use_fallback_path;
1448}
hubbed5f36882016-01-15 22:40:371449#endif // defined(OS_ANDROID) // WMPI_CAST
1450
[email protected]fee8a902014-06-03 13:43:361451void WebMediaPlayerImpl::DataSourceInitialized(bool success) {
pkastingf5279482016-07-27 02:18:201452 DVLOG(1) << __func__;
acolwellb4034942014-08-28 15:42:431453 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]a9415292012-01-19 19:55:201454
dalecurtisea27a3ed2016-06-24 01:41:301455#if defined(OS_ANDROID)
1456 // We can't play HLS URLs with WebMediaPlayerImpl, so in cases where they are
1457 // encountered, instruct the HTML media element to create a new WebMediaPlayer
1458 // instance with the correct URL to trigger WebMediaPlayerAndroid creation.
1459 //
1460 // TODO(tguilbert): Remove this code path once we have the ability to host a
1461 // MediaPlayer within a Mojo media renderer. http://crbug.com/580626
tguilbert25a4d112016-10-13 21:56:511462 if (data_source_ && !use_fallback_path_) {
dalecurtisea27a3ed2016-06-24 01:41:301463 const GURL url_after_redirects = data_source_->GetUrlAfterRedirects();
qinmin0d9521272016-10-10 20:43:191464 if (MediaCodecUtil::IsHLSURL(url_after_redirects)) {
dalecurtisea27a3ed2016-06-24 01:41:301465 client_->requestReload(url_after_redirects);
1466 // |this| may be destructed, do nothing after this.
1467 return;
1468 }
1469 }
1470#endif
1471
[email protected]d250190da3b2012-07-23 22:57:301472 if (!success) {
[email protected]ef405f66b2012-04-18 02:39:551473 SetNetworkState(WebMediaPlayer::NetworkStateFormatError);
sandersd50a635e2016-04-04 22:50:091474
1475 // Not really necessary, since the pipeline was never started, but it at
1476 // least this makes sure that the error handling code is in sync.
1477 UpdatePlayState();
1478
[email protected]a9415292012-01-19 19:55:201479 return;
1480 }
1481
[email protected]ef8394c2013-08-21 20:26:301482 StartPipeline();
[email protected]a9415292012-01-19 19:55:201483}
1484
[email protected]122f40252012-06-12 05:01:561485void WebMediaPlayerImpl::NotifyDownloading(bool is_downloading) {
pkastingf5279482016-07-27 02:18:201486 DVLOG(1) << __func__;
[email protected]122f40252012-06-12 05:01:561487 if (!is_downloading && network_state_ == WebMediaPlayer::NetworkStateLoading)
1488 SetNetworkState(WebMediaPlayer::NetworkStateIdle);
1489 else if (is_downloading && network_state_ == WebMediaPlayer::NetworkStateIdle)
1490 SetNetworkState(WebMediaPlayer::NetworkStateLoading);
1491 media_log_->AddEvent(
1492 media_log_->CreateBooleanEvent(
acolwell9e0840d2014-09-06 19:01:321493 MediaLogEvent::NETWORK_ACTIVITY_SET,
[email protected]122f40252012-06-12 05:01:561494 "is_downloading_data", is_downloading));
1495}
1496
watkf835a792016-06-24 23:24:401497void WebMediaPlayerImpl::OnSurfaceCreated(int surface_id) {
tsunghungee562e92016-07-20 18:03:311498 if (force_video_overlays_ && surface_id == SurfaceManager::kNoSurfaceID)
1499 LOG(ERROR) << "Create surface failed.";
1500
1501 overlay_surface_id_ = surface_id;
watkf835a792016-06-24 23:24:401502 if (!pending_surface_request_cb_.is_null())
1503 base::ResetAndReturn(&pending_surface_request_cb_).Run(surface_id);
1504}
1505
watkdee516f2016-02-18 02:22:191506// TODO(watk): Move this state management out of WMPI.
1507void WebMediaPlayerImpl::OnSurfaceRequested(
1508 const SurfaceCreatedCB& surface_created_cb) {
1509 DCHECK(main_task_runner_->BelongsToCurrentThread());
1510 DCHECK(surface_manager_);
tguilbert25a4d112016-10-13 21:56:511511 DCHECK(!use_fallback_path_);
watkdee516f2016-02-18 02:22:191512
1513 // A null callback indicates that the decoder is going away.
1514 if (surface_created_cb.is_null()) {
tsunghungee562e92016-07-20 18:03:311515 decoder_requires_restart_for_overlay_ = false;
watkf835a792016-06-24 23:24:401516 pending_surface_request_cb_.Reset();
watkdee516f2016-02-18 02:22:191517 return;
1518 }
1519
1520 // If we're getting a surface request it means GVD is initializing, so until
1521 // we get a null surface request, GVD is the active decoder. While that's the
1522 // case we should restart the pipeline on fullscreen transitions so that when
1523 // we create a new GVD it will request a surface again and get the right kind
1524 // of surface for the fullscreen state.
1525 // TODO(watk): Don't require a pipeline restart to switch surfaces for
1526 // cases where it isn't necessary.
tsunghungee562e92016-07-20 18:03:311527 decoder_requires_restart_for_overlay_ = true;
1528 if (overlay_enabled_) {
1529 if (overlay_surface_id_ != SurfaceManager::kNoSurfaceID)
1530 surface_created_cb.Run(overlay_surface_id_);
watkf835a792016-06-24 23:24:401531 else
1532 pending_surface_request_cb_ = surface_created_cb;
watkdee516f2016-02-18 02:22:191533 } else {
1534 // Tell the decoder to create its own surface.
1535 surface_created_cb.Run(SurfaceManager::kNoSurfaceID);
1536 }
1537}
1538
dcheng3076abbf2016-04-22 20:42:391539std::unique_ptr<Renderer> WebMediaPlayerImpl::CreateRenderer() {
tsunghungee562e92016-07-20 18:03:311540 if (force_video_overlays_)
1541 EnableOverlay();
1542
watkdee516f2016-02-18 02:22:191543 RequestSurfaceCB request_surface_cb;
1544#if defined(OS_ANDROID)
1545 request_surface_cb =
1546 BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnSurfaceRequested);
1547#endif
sandersd1e49fb62015-12-12 01:18:061548 return renderer_factory_->CreateRenderer(
1549 media_task_runner_, worker_task_runner_, audio_source_provider_.get(),
watkdee516f2016-02-18 02:22:191550 compositor_, request_surface_cb);
sandersd1e49fb62015-12-12 01:18:061551}
1552
[email protected]ef8394c2013-08-21 20:26:301553void WebMediaPlayerImpl::StartPipeline() {
acolwellb4034942014-08-28 15:42:431554 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]ddbc6ff2013-04-19 15:28:331555
xhwange8c4181a2014-12-06 08:10:011556 Demuxer::EncryptedMediaInitDataCB encrypted_media_init_data_cb =
1557 BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnEncryptedMediaInitData);
[email protected]2b57e2e2014-05-09 11:07:251558
tguilbert25a4d112016-10-13 21:56:511559 if (use_fallback_path_) {
tguilbert9881bc22016-10-27 03:13:411560 demuxer_.reset(
1561 new MediaUrlDemuxer(media_task_runner_, fallback_url_,
1562 frame_->document().firstPartyForCookies()));
tguilbert25a4d112016-10-13 21:56:511563 pipeline_controller_.Start(demuxer_.get(), this, false, false);
1564 return;
1565 }
1566
[email protected]ddbc6ff2013-04-19 15:28:331567 // Figure out which demuxer to use.
[email protected]ef8394c2013-08-21 20:26:301568 if (load_type_ != LoadTypeMediaSource) {
[email protected]ddbc6ff2013-04-19 15:28:331569 DCHECK(!chunk_demuxer_);
[email protected]f5443ef72013-04-22 04:03:381570 DCHECK(data_source_);
1571
j.isorcef6778e652015-11-16 17:14:251572#if !defined(MEDIA_DISABLE_FFMPEG)
servolk81e01e02016-03-05 03:29:151573 Demuxer::MediaTracksUpdatedCB media_tracks_updated_cb =
servolkef1e5ef2016-03-25 04:55:261574 BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnFFmpegMediaTracksUpdated);
servolk81e01e02016-03-05 03:29:151575
xhwange8c4181a2014-12-06 08:10:011576 demuxer_.reset(new FFmpegDemuxer(media_task_runner_, data_source_.get(),
servolk81e01e02016-03-05 03:29:151577 encrypted_media_init_data_cb,
1578 media_tracks_updated_cb, media_log_));
j.isorcef6778e652015-11-16 17:14:251579#else
alokp967c902452016-05-06 05:21:371580 OnError(PipelineStatus::DEMUXER_ERROR_COULD_NOT_OPEN);
j.isorcef6778e652015-11-16 17:14:251581 return;
1582#endif
[email protected]ddbc6ff2013-04-19 15:28:331583 } else {
[email protected]f5443ef72013-04-22 04:03:381584 DCHECK(!chunk_demuxer_);
1585 DCHECK(!data_source_);
1586
acolwell9e0840d2014-09-06 19:01:321587 chunk_demuxer_ = new ChunkDemuxer(
[email protected]ef8394c2013-08-21 20:26:301588 BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnDemuxerOpened),
chcunningham967db2f2016-11-02 20:47:171589 encrypted_media_init_data_cb, media_log_);
[email protected]f5443ef72013-04-22 04:03:381590 demuxer_.reset(chunk_demuxer_);
[email protected]ddbc6ff2013-04-19 15:28:331591 }
1592
sandersdb5e21462016-03-09 01:49:071593 // TODO(sandersd): FileSystem objects may also be non-static, but due to our
1594 // caching layer such situations are broken already. http://crbug.com/593159
1595 bool is_static = !chunk_demuxer_;
1596
[email protected]f5443ef72013-04-22 04:03:381597 // ... and we're ready to go!
[email protected]d228aeec2014-06-20 19:16:491598 seeking_ = true;
xhwangf94a634d2014-10-22 22:07:271599
sandersd1e49fb62015-12-12 01:18:061600 // TODO(sandersd): On Android, defer Start() if the tab is not visible.
sandersd1c0bba02016-03-04 23:14:081601 bool is_streaming = (data_source_ && data_source_->IsStreaming());
alokp967c902452016-05-06 05:21:371602 pipeline_controller_.Start(demuxer_.get(), this, is_streaming, is_static);
[email protected]f5443ef72013-04-22 04:03:381603}
1604
1605void WebMediaPlayerImpl::SetNetworkState(WebMediaPlayer::NetworkState state) {
pkastingf5279482016-07-27 02:18:201606 DVLOG(1) << __func__ << "(" << state << ")";
acolwellb4034942014-08-28 15:42:431607 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]f5443ef72013-04-22 04:03:381608 network_state_ = state;
1609 // Always notify to ensure client has the latest value.
[email protected]ce70c982013-12-20 17:04:321610 client_->networkStateChanged();
[email protected]f5443ef72013-04-22 04:03:381611}
1612
1613void WebMediaPlayerImpl::SetReadyState(WebMediaPlayer::ReadyState state) {
pkastingf5279482016-07-27 02:18:201614 DVLOG(1) << __func__ << "(" << state << ")";
acolwellb4034942014-08-28 15:42:431615 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]f5443ef72013-04-22 04:03:381616
[email protected]fee8a902014-06-03 13:43:361617 if (state == WebMediaPlayer::ReadyStateHaveEnoughData && data_source_ &&
1618 data_source_->assume_fully_buffered() &&
[email protected]f5443ef72013-04-22 04:03:381619 network_state_ == WebMediaPlayer::NetworkStateLoading)
1620 SetNetworkState(WebMediaPlayer::NetworkStateLoaded);
1621
1622 ready_state_ = state;
sandersd50a635e2016-04-04 22:50:091623 highest_ready_state_ = std::max(highest_ready_state_, ready_state_);
1624
[email protected]f5443ef72013-04-22 04:03:381625 // Always notify to ensure client has the latest value.
[email protected]ce70c982013-12-20 17:04:321626 client_->readyStateChanged();
[email protected]f5443ef72013-04-22 04:03:381627}
1628
Dana Jansens71331252016-03-09 20:57:221629blink::WebAudioSourceProvider* WebMediaPlayerImpl::getAudioSourceProvider() {
[email protected]ff875be52013-06-02 23:47:381630 return audio_source_provider_.get();
[email protected]f5443ef72013-04-22 04:03:381631}
1632
[email protected]f5443ef72013-04-22 04:03:381633double WebMediaPlayerImpl::GetPipelineDuration() const {
[email protected]f6af7592014-02-28 10:09:111634 base::TimeDelta duration = pipeline_.GetMediaDuration();
[email protected]f5443ef72013-04-22 04:03:381635
1636 // Return positive infinity if the resource is unbounded.
1637 // http://www.whatwg.org/specs/web-apps/current-work/multipage/video.html#dom-media-duration
dalecurtis39a7f932016-07-19 18:34:591638 if (duration == kInfiniteDuration)
[email protected]f5443ef72013-04-22 04:03:381639 return std::numeric_limits<double>::infinity();
1640
1641 return duration.InSecondsF();
1642}
1643
[email protected]dd061e12014-05-06 19:21:221644static void GetCurrentFrameAndSignal(
1645 VideoFrameCompositor* compositor,
acolwell9e0840d2014-09-06 19:01:321646 scoped_refptr<VideoFrame>* video_frame_out,
[email protected]dd061e12014-05-06 19:21:221647 base::WaitableEvent* event) {
1648 TRACE_EVENT0("media", "GetCurrentFrameAndSignal");
dalecurtis44ce4de2015-05-11 18:42:071649 *video_frame_out = compositor->GetCurrentFrameAndUpdateIfStale();
[email protected]dd061e12014-05-06 19:21:221650 event->Signal();
1651}
1652
acolwell9e0840d2014-09-06 19:01:321653scoped_refptr<VideoFrame>
[email protected]dd061e12014-05-06 19:21:221654WebMediaPlayerImpl::GetCurrentFrameFromCompositor() {
xhwang213e50c2016-10-10 23:56:311655 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]dd061e12014-05-06 19:21:221656 TRACE_EVENT0("media", "WebMediaPlayerImpl::GetCurrentFrameFromCompositor");
xhwang213e50c2016-10-10 23:56:311657
1658 // Needed when the |main_task_runner_| and |compositor_task_runner_| are the
1659 // same to avoid deadlock in the Wait() below.
[email protected]dd061e12014-05-06 19:21:221660 if (compositor_task_runner_->BelongsToCurrentThread())
dalecurtis44ce4de2015-05-11 18:42:071661 return compositor_->GetCurrentFrameAndUpdateIfStale();
[email protected]dd061e12014-05-06 19:21:221662
1663 // Use a posted task and waitable event instead of a lock otherwise
1664 // WebGL/Canvas can see different content than what the compositor is seeing.
acolwell9e0840d2014-09-06 19:01:321665 scoped_refptr<VideoFrame> video_frame;
gab0d77c7cb2016-06-02 00:00:231666 base::WaitableEvent event(base::WaitableEvent::ResetPolicy::AUTOMATIC,
1667 base::WaitableEvent::InitialState::NOT_SIGNALED);
[email protected]dd061e12014-05-06 19:21:221668 compositor_task_runner_->PostTask(FROM_HERE,
1669 base::Bind(&GetCurrentFrameAndSignal,
1670 base::Unretained(compositor_),
1671 &video_frame,
1672 &event));
1673 event.Wait();
1674 return video_frame;
1675}
1676
sandersd50a635e2016-04-04 22:50:091677void WebMediaPlayerImpl::UpdatePlayState() {
xhwang213e50c2016-10-10 23:56:311678 DCHECK(main_task_runner_->BelongsToCurrentThread());
1679
hubbed5f36882016-01-15 22:40:371680#if defined(OS_ANDROID) // WMPI_CAST
sandersd50a635e2016-04-04 22:50:091681 bool is_remote = isRemote();
1682#else
1683 bool is_remote = false;
hubbed5f36882016-01-15 22:40:371684#endif
xhwang213e50c2016-10-10 23:56:311685
dalecurtis8b8505e72016-06-10 21:59:171686 bool is_suspended = pipeline_controller_.IsSuspended();
sandersd50a635e2016-04-04 22:50:091687 bool is_backgrounded =
1688 IsBackgroundedSuspendEnabled() && delegate_ && delegate_->IsHidden();
dalecurtis8b8505e72016-06-10 21:59:171689 PlayState state = UpdatePlayState_ComputePlayState(is_remote, is_suspended,
1690 is_backgrounded);
sandersd50a635e2016-04-04 22:50:091691 SetDelegateState(state.delegate_state);
1692 SetMemoryReportingState(state.is_memory_reporting_enabled);
1693 SetSuspendState(state.is_suspended || pending_suspend_resume_cycle_);
1694}
dalecurtis5bbc487e2016-02-27 04:15:051695
sandersd50a635e2016-04-04 22:50:091696void WebMediaPlayerImpl::SetDelegateState(DelegateState new_state) {
mlamouri910111362016-11-04 11:28:241697 if (!delegate_)
dalecurtis5bbc487e2016-02-27 04:15:051698 return;
1699
mlamouri910111362016-11-04 11:28:241700 if (delegate_state_ == new_state) {
1701 if (delegate_state_ != DelegateState::PLAYING ||
1702 autoplay_muted_ == client_->isAutoplayingMuted()) {
1703 return;
1704 }
1705 }
1706
sandersd50a635e2016-04-04 22:50:091707 delegate_state_ = new_state;
1708
1709 switch (delegate_state_) {
1710 case DelegateState::GONE:
1711 delegate_->PlayerGone(delegate_id_);
1712 break;
mlamouri910111362016-11-04 11:28:241713 case DelegateState::PLAYING: {
1714 autoplay_muted_ = client_->isAutoplayingMuted();
1715 bool has_audio = autoplay_muted_ ? false : hasAudio();
zqzhang5d8eab72016-08-26 20:34:301716 delegate_->DidPlay(
mlamouri910111362016-11-04 11:28:241717 delegate_id_, hasVideo(), has_audio, false,
zqzhang5d8eab72016-08-26 20:34:301718 media::DurationToMediaContentType(pipeline_.GetMediaDuration()));
sandersd50a635e2016-04-04 22:50:091719 break;
mlamouri910111362016-11-04 11:28:241720 }
sandersd50a635e2016-04-04 22:50:091721 case DelegateState::PAUSED:
1722 delegate_->DidPause(delegate_id_, false);
1723 break;
1724 case DelegateState::ENDED:
1725 delegate_->DidPause(delegate_id_, true);
1726 break;
dalecurtis0f0097a2015-12-01 17:40:471727 }
1728}
1729
sandersd50a635e2016-04-04 22:50:091730void WebMediaPlayerImpl::SetMemoryReportingState(
1731 bool is_memory_reporting_enabled) {
1732 if (memory_usage_reporting_timer_.IsRunning() ==
1733 is_memory_reporting_enabled) {
hubbed5f36882016-01-15 22:40:371734 return;
sandersd50a635e2016-04-04 22:50:091735 }
sandersd1c0bba02016-03-04 23:14:081736
sandersd50a635e2016-04-04 22:50:091737 if (is_memory_reporting_enabled) {
1738 memory_usage_reporting_timer_.Start(FROM_HERE,
1739 base::TimeDelta::FromSeconds(2), this,
1740 &WebMediaPlayerImpl::ReportMemoryUsage);
1741 } else {
1742 memory_usage_reporting_timer_.Stop();
1743 ReportMemoryUsage();
1744 }
1745}
1746
1747void WebMediaPlayerImpl::SetSuspendState(bool is_suspended) {
xhwang213e50c2016-10-10 23:56:311748 DCHECK(main_task_runner_->BelongsToCurrentThread());
1749
sandersd50a635e2016-04-04 22:50:091750 // Do not change the state after an error has occurred.
1751 // TODO(sandersd): Update PipelineController to remove the need for this.
1752 if (IsNetworkStateError(network_state_))
sandersd1c0bba02016-03-04 23:14:081753 return;
1754
sandersdf1869d172016-11-01 22:10:181755#if !defined(OS_ANDROID) && !defined(OS_CHROMEOS) && !defined(OS_MACOSX)
halliwell6451e242016-06-01 15:00:241756 // TODO(sandersd): idle suspend is disabled if decoder owns video frame.
sandersdf1869d172016-11-01 22:10:181757 // Used on Windows+Chromecast. Since GetCurrentFrameFromCompositor is a
1758 // synchronous cross-thread post, avoid the cost on platforms that always
1759 // allow suspend. Need to find a better mechanism for this. See
1760 // http://crbug.com/602708
dalecurtis7f366b2242016-04-13 01:16:171761 if (can_suspend_state_ == CanSuspendState::UNKNOWN) {
1762 scoped_refptr<VideoFrame> frame = GetCurrentFrameFromCompositor();
1763 if (frame) {
1764 can_suspend_state_ =
1765 frame->metadata()->IsTrue(VideoFrameMetadata::DECODER_OWNS_FRAME)
1766 ? CanSuspendState::NO
1767 : CanSuspendState::YES;
1768 }
1769 }
1770#else
1771 can_suspend_state_ = CanSuspendState::YES;
1772#endif
1773
1774 if (can_suspend_state_ == CanSuspendState::NO)
1775 return;
1776
sandersd50a635e2016-04-04 22:50:091777 if (is_suspended) {
1778 pipeline_controller_.Suspend();
1779 } else {
1780 pipeline_controller_.Resume();
1781 }
1782}
1783
1784WebMediaPlayerImpl::PlayState
1785WebMediaPlayerImpl::UpdatePlayState_ComputePlayState(bool is_remote,
dalecurtis8b8505e72016-06-10 21:59:171786 bool is_suspended,
sandersd50a635e2016-04-04 22:50:091787 bool is_backgrounded) {
1788 PlayState result;
1789
1790 // This includes both data source (before pipeline startup) and pipeline
1791 // errors.
1792 bool has_error = IsNetworkStateError(network_state_);
1793
1794 // After HaveMetadata, we know which tracks are present and the duration.
1795 bool have_metadata = ready_state_ >= WebMediaPlayer::ReadyStateHaveMetadata;
1796
dalecurtiscc8baf72016-10-27 01:49:441797 // After HaveFutureData, Blink will call play() if the state is not paused;
1798 // prior to this point |paused_| is not accurate.
sandersd50a635e2016-04-04 22:50:091799 bool have_future_data =
1800 highest_ready_state_ >= WebMediaPlayer::ReadyStateHaveFutureData;
1801
dalecurtis8b8505e72016-06-10 21:59:171802 // Background suspend is not enabled for audio-only players unless paused,
1803 // though in the case of audio-only the session should be kept.
avayvod48a8be52016-08-04 19:52:501804 // Videos are not suspended if the user resumed the playback via the remote
1805 // controls earlier and it's still playing.
1806 bool is_backgrounded_video = is_backgrounded && have_metadata && hasVideo();
1807 bool can_play_backgrounded = is_backgrounded_video && !is_remote &&
1808 hasAudio() && IsResumeBackgroundVideosEnabled();
1809 bool is_background_playing =
1810 delegate_ && delegate_->IsPlayingBackgroundVideo();
1811 bool background_suspended = is_backgrounded_video &&
1812 !(can_play_backgrounded && is_background_playing);
dalecurtiscc8baf72016-10-27 01:49:441813 bool background_pause_suspended =
1814 is_backgrounded && paused_ && have_future_data;
sandersd50a635e2016-04-04 22:50:091815
dalecurtiscc8baf72016-10-27 01:49:441816 // Idle suspension is allowed prior to have future data since there exist
1817 // mechanisms to exit the idle state when the player is capable of reaching
1818 // the have future data state; see didLoadingProgress().
1819 //
sandersd50a635e2016-04-04 22:50:091820 // TODO(sandersd): Make the delegate suspend idle players immediately when
1821 // hidden.
dalecurtise7120dc2016-09-03 02:54:351822 bool idle_suspended = is_idle_ && paused_ && !seeking_ && !overlay_enabled_;
1823
1824 // If we're already suspended, see if we can wait for user interaction. Prior
1825 // to HaveFutureData, we require |is_idle_| to remain suspended. |is_idle_|
1826 // will be cleared when we receive data which may take us to HaveFutureData.
1827 bool can_stay_suspended =
1828 (is_idle_ || have_future_data) && is_suspended && paused_ && !seeking_;
sandersd50a635e2016-04-04 22:50:091829
1830 // Combined suspend state.
dalecurtise7120dc2016-09-03 02:54:351831 result.is_suspended = is_remote || must_suspend_ || idle_suspended ||
1832 background_suspended || background_pause_suspended ||
1833 can_stay_suspended;
sandersd50a635e2016-04-04 22:50:091834
1835 // We do not treat |playback_rate_| == 0 as paused. For the media session,
1836 // being paused implies displaying a play button, which is incorrect in this
1837 // case. For memory usage reporting, we just use the same definition (but we
1838 // don't have to).
1839 //
1840 // Similarly, we don't consider |ended_| to be paused. Blink will immediately
1841 // call pause() or seek(), so |ended_| should not affect the computation.
1842 // Despite that, |ended_| does result in a separate paused state, to simplfy
1843 // the contract for SetDelegateState().
1844 //
1845 // |has_session| is used to decide when to create a media session. Idle
1846 // suspension does not destroy the media session, because we expect that the
1847 // notification controls (and audio focus) remain. We also require:
1848 // - |have_metadata|, since the tracks and duration are passed to DidPlay().
1849 // - |have_future_data|, since we need to know whether we are paused to
1850 // correctly configure the session.
1851 //
1852 // TODO(sandersd): If Blink told us the paused state sooner, we could create
1853 // the media session sooner.
1854 bool can_play = !has_error && !is_remote && have_future_data;
avayvod48a8be52016-08-04 19:52:501855 bool has_session_playing =
1856 can_play && !must_suspend_ && !background_suspended;
1857
1858 // |has_session_suspended| means the player is suspended from the media
1859 // element point of view but paused and can be resumed from the delegate point
1860 // of view. Therefore it behaves like |paused_| for the delegate.
1861 bool has_session_suspended = can_play && !must_suspend_ &&
1862 background_suspended && can_play_backgrounded;
1863
1864 bool has_session = has_session_playing || has_session_suspended;
sandersd50a635e2016-04-04 22:50:091865
1866 if (!has_session) {
1867 result.delegate_state = DelegateState::GONE;
avayvod48a8be52016-08-04 19:52:501868 } else if (paused_ || has_session_suspended) {
dalecurtise7120dc2016-09-03 02:54:351869 result.delegate_state =
1870 ended_ ? DelegateState::ENDED : DelegateState::PAUSED;
sandersd50a635e2016-04-04 22:50:091871 } else {
1872 result.delegate_state = DelegateState::PLAYING;
1873 }
1874
dalecurtis8b8505e72016-06-10 21:59:171875 // It's not critical if some cases where memory usage can change are missed,
sandersd50a635e2016-04-04 22:50:091876 // since media memory changes are usually gradual.
1877 result.is_memory_reporting_enabled =
1878 can_play && !result.is_suspended && !paused_;
1879
1880 return result;
dalecurtis0f0097a2015-12-01 17:40:471881}
1882
dalecurtis83266c72015-10-29 18:43:201883void WebMediaPlayerImpl::ReportMemoryUsage() {
1884 DCHECK(main_task_runner_->BelongsToCurrentThread());
1885
wdzierzanowskifd4cd91c52015-12-02 23:50:201886 // About base::Unretained() usage below: We destroy |demuxer_| on the main
1887 // thread. Before that, however, ~WebMediaPlayerImpl() posts a task to the
1888 // media thread and waits for it to finish. Hence, the GetMemoryUsage() task
1889 // posted here must finish earlier.
1890
1891 if (demuxer_) {
1892 base::PostTaskAndReplyWithResult(
1893 media_task_runner_.get(), FROM_HERE,
1894 base::Bind(&Demuxer::GetMemoryUsage, base::Unretained(demuxer_.get())),
1895 base::Bind(&WebMediaPlayerImpl::FinishMemoryUsageReport, AsWeakPtr()));
1896 } else {
1897 FinishMemoryUsageReport(0);
1898 }
1899}
1900
1901void WebMediaPlayerImpl::FinishMemoryUsageReport(int64_t demuxer_memory_usage) {
1902 DCHECK(main_task_runner_->BelongsToCurrentThread());
1903
dalecurtis83266c72015-10-29 18:43:201904 const PipelineStatistics stats = pipeline_.GetStatistics();
1905 const int64_t current_memory_usage =
1906 stats.audio_memory_usage + stats.video_memory_usage +
1907 (data_source_ ? data_source_->GetMemoryUsage() : 0) +
wdzierzanowskifd4cd91c52015-12-02 23:50:201908 demuxer_memory_usage;
dalecurtis83266c72015-10-29 18:43:201909
dalecurtis3a7d38f42016-03-07 21:17:131910 // Note, this isn't entirely accurate, there may be VideoFrames held by the
1911 // compositor or other resources that we're unaware of.
1912
dalecurtis83266c72015-10-29 18:43:201913 DVLOG(2) << "Memory Usage -- Audio: " << stats.audio_memory_usage
1914 << ", Video: " << stats.video_memory_usage << ", DataSource: "
1915 << (data_source_ ? data_source_->GetMemoryUsage() : 0)
wdzierzanowskifd4cd91c52015-12-02 23:50:201916 << ", Demuxer: " << demuxer_memory_usage;
dalecurtis83266c72015-10-29 18:43:201917
1918 const int64_t delta = current_memory_usage - last_reported_memory_usage_;
1919 last_reported_memory_usage_ = current_memory_usage;
1920 adjust_allocated_memory_cb_.Run(delta);
1921}
1922
dalecurtis8b8505e72016-06-10 21:59:171923void WebMediaPlayerImpl::ScheduleIdlePauseTimer() {
dalecurtise7120dc2016-09-03 02:54:351924 // Only schedule the pause timer if we're playing and are suspended.
1925 if (paused_ || !pipeline_controller_.IsSuspended())
dalecurtis8b8505e72016-06-10 21:59:171926 return;
1927
1928#if defined(OS_ANDROID)
1929 // Remote players will be suspended and locally paused.
1930 if (isRemote())
1931 return;
1932#endif
1933
1934 // Idle timeout chosen arbitrarily.
1935 background_pause_timer_.Start(FROM_HERE, base::TimeDelta::FromSeconds(5),
1936 this, &WebMediaPlayerImpl::OnPause);
1937}
1938
dalecurtis04bdb582016-08-17 22:15:231939void WebMediaPlayerImpl::CreateWatchTimeReporter() {
1940 // Create the watch time reporter and synchronize its initial state.
1941 watch_time_reporter_.reset(new WatchTimeReporter(
1942 hasAudio(), hasVideo(), !!chunk_demuxer_, is_encrypted_, media_log_,
1943 pipeline_metadata_.natural_size,
1944 base::Bind(&GetCurrentTimeInternal, this)));
1945 watch_time_reporter_->OnVolumeChange(volume_);
1946 if (delegate_ && delegate_->IsHidden())
1947 watch_time_reporter_->OnHidden();
1948 else
1949 watch_time_reporter_->OnShown();
1950}
1951
acolwell9e0840d2014-09-06 19:01:321952} // namespace media