blob: 2cd76805d0e0dfeae4994bbb8f3520d7ffd61696 [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"
[email protected]b0b258f2011-11-08 00:34:2320#include "base/metrics/histogram.h"
acolwellb4034942014-08-28 15:42:4321#include "base/single_thread_task_runner.h"
[email protected]cf02541b2012-04-11 08:02:1722#include "base/synchronization/waitable_event.h"
wdzierzanowskifd4cd91c52015-12-02 23:50:2023#include "base/task_runner_util.h"
anujk.sharma2fa37a02015-04-30 05:51:3224#include "base/thread_task_runner_handle.h"
ssid9525f4672015-01-28 12:13:1525#include "base/trace_event/trace_event.h"
sandersd1e49fb62015-12-12 01:18:0626#include "build/build_config.h"
[email protected]38564622014-08-19 02:47:1827#include "cc/blink/web_layer_impl.h"
[email protected]21c3f7502013-03-23 03:29:5128#include "cc/layers/video_layer.h"
dongseong.hwang0c4e9d82015-01-08 20:11:1329#include "gpu/blink/webgraphicscontext3d_impl.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"
[email protected]090f7312011-08-05 23:26:4034#include "media/base/media_log.h"
sandersd1e49fb62015-12-12 01:18:0635#include "media/base/media_switches.h"
[email protected]8a561062013-11-22 01:19:3136#include "media/base/text_renderer.h"
watk9f9dfdc92015-09-04 21:33:2937#include "media/base/timestamp_constants.h"
[email protected]e81283bb2010-08-31 18:01:2138#include "media/base/video_frame.h"
acolwell9e0840d2014-09-06 19:01:3239#include "media/blink/texttrack_impl.h"
40#include "media/blink/webaudiosourceprovider_impl.h"
xhwang97de4202014-11-25 08:44:0141#include "media/blink/webcontentdecryptionmodule_impl.h"
acolwell9e0840d2014-09-06 19:01:3242#include "media/blink/webinbandtexttrack_impl.h"
43#include "media/blink/webmediaplayer_delegate.h"
acolwell9e0840d2014-09-06 19:01:3244#include "media/blink/webmediaplayer_util.h"
45#include "media/blink/webmediasource_impl.h"
[email protected]efe7cd22012-09-12 23:55:0146#include "media/filters/chunk_demuxer.h"
[email protected]ddbc6ff2013-04-19 15:28:3347#include "media/filters/ffmpeg_demuxer.h"
jrummellc9d8e532015-02-26 18:38:1948#include "third_party/WebKit/public/platform/WebEncryptedMediaTypes.h"
srirama.m26f864d02015-07-14 05:21:4649#include "third_party/WebKit/public/platform/WebMediaPlayerClient.h"
50#include "third_party/WebKit/public/platform/WebMediaPlayerEncryptedMediaClient.h"
[email protected]745746d2013-08-23 02:09:1651#include "third_party/WebKit/public/platform/WebMediaSource.h"
[email protected]c10884462013-05-30 00:22:0952#include "third_party/WebKit/public/platform/WebRect.h"
mek966863c2016-02-04 23:39:0553#include "third_party/WebKit/public/platform/WebSecurityOrigin.h"
[email protected]c10884462013-05-30 00:22:0954#include "third_party/WebKit/public/platform/WebSize.h"
55#include "third_party/WebKit/public/platform/WebString.h"
56#include "third_party/WebKit/public/platform/WebURL.h"
xhwang0acca44b2015-06-18 00:43:3157#include "third_party/WebKit/public/web/WebDocument.h"
58#include "third_party/WebKit/public/web/WebFrame.h"
[email protected]80504652014-04-18 04:41:5059#include "third_party/WebKit/public/web/WebLocalFrame.h"
[email protected]2255a9332013-06-17 05:12:3160#include "third_party/WebKit/public/web/WebView.h"
[email protected]b3f2b912009-04-09 16:18:5261
[email protected]180ef242013-11-07 06:50:4662using blink::WebCanvas;
63using blink::WebMediaPlayer;
64using blink::WebRect;
65using blink::WebSize;
66using blink::WebString;
hubbed5f36882016-01-15 22:40:3767using gpu::gles2::GLES2Interface;
68
danakj365175c2016-02-06 00:37:3769#define STATIC_ASSERT_ENUM(a, b) \
70 static_assert(static_cast<int>(a) == static_cast<int>(b), \
71 "mismatching enums: " #a)
72
hubbed5f36882016-01-15 22:40:3773namespace media {
[email protected]ec9212f2008-12-18 21:40:3674
[email protected]8931c41a2009-07-07 17:31:4975namespace {
76
[email protected]378f0b72009-08-11 17:11:4277// Limits the range of playback rate.
78//
79// TODO(kylep): Revisit these.
80//
81// Vista has substantially lower performance than XP or Windows7. If you speed
82// up a video too much, it can't keep up, and rendering stops updating except on
83// the time bar. For really high speeds, audio becomes a bottleneck and we just
84// use up the data we have, which may not achieve the speed requested, but will
85// not crash the tab.
86//
87// A very slow speed, ie 0.00000001x, causes the machine to lock up. (It seems
88// like a busy loop). It gets unresponsive, although its not completely dead.
89//
90// Also our timers are not very accurate (especially for ogg), which becomes
91// evident at low speeds and on Vista. Since other speeds are risky and outside
92// the norms, we think 1/16x to 16x is a safe and useful range for now.
[email protected]39bdde32013-04-17 17:44:2093const double kMinRate = 0.0625;
94const double kMaxRate = 16.0;
[email protected]378f0b72009-08-11 17:11:4295
hubbed5f36882016-01-15 22:40:3796void SetSinkIdOnMediaThread(scoped_refptr<WebAudioSourceProviderImpl> sink,
97 const std::string& device_id,
98 const url::Origin& security_origin,
99 const SwitchOutputDeviceCB& callback) {
guidouc7babef2015-10-22 00:42:35100 if (sink->GetOutputDevice()) {
101 sink->GetOutputDevice()->SwitchOutputDevice(device_id, security_origin,
102 callback);
103 } else {
hubbed5f36882016-01-15 22:40:37104 callback.Run(OUTPUT_DEVICE_STATUS_ERROR_INTERNAL);
guidouc7babef2015-10-22 00:42:35105 }
106}
107
dalecurtis0431cbf2016-03-12 01:19:43108bool IsSuspendUponHiddenEnabled() {
109#if !defined(OS_ANDROID)
110 // Suspend/Resume is only enabled by default on Android.
111 return base::CommandLine::ForCurrentProcess()->HasSwitch(
112 switches::kEnableMediaSuspend);
113#else
114 return !base::CommandLine::ForCurrentProcess()->HasSwitch(
115 switches::kDisableMediaSuspend);
116#endif
117}
118
[email protected]8931c41a2009-07-07 17:31:49119} // namespace
120
[email protected]6683e1b2014-04-10 01:45:38121class BufferedDataSourceHostImpl;
122
danakj365175c2016-02-06 00:37:37123STATIC_ASSERT_ENUM(WebMediaPlayer::CORSModeUnspecified,
124 UrlData::CORS_UNSPECIFIED);
125STATIC_ASSERT_ENUM(WebMediaPlayer::CORSModeAnonymous, UrlData::CORS_ANONYMOUS);
126STATIC_ASSERT_ENUM(WebMediaPlayer::CORSModeUseCredentials,
127 UrlData::CORS_USE_CREDENTIALS);
[email protected]a5a01102012-06-06 17:01:24128
[email protected]2c539b82012-08-18 04:10:19129#define BIND_TO_RENDER_LOOP(function) \
acolwellb4034942014-08-28 15:42:43130 (DCHECK(main_task_runner_->BelongsToCurrentThread()), \
acolwell9e0840d2014-09-06 19:01:32131 BindToCurrentLoop(base::Bind(function, AsWeakPtr())))
[email protected]5983adb2012-10-24 00:12:00132
[email protected]4e982192014-06-21 13:35:45133#define BIND_TO_RENDER_LOOP1(function, arg1) \
acolwellb4034942014-08-28 15:42:43134 (DCHECK(main_task_runner_->BelongsToCurrentThread()), \
acolwell9e0840d2014-09-06 19:01:32135 BindToCurrentLoop(base::Bind(function, AsWeakPtr(), arg1)))
[email protected]4e982192014-06-21 13:35:45136
[email protected]5b5bb9d2010-10-22 19:57:36137WebMediaPlayerImpl::WebMediaPlayerImpl(
[email protected]35b2a972014-04-04 15:50:22138 blink::WebLocalFrame* frame,
[email protected]180ef242013-11-07 06:50:46139 blink::WebMediaPlayerClient* client,
srirama.m26f864d02015-07-14 05:21:46140 blink::WebMediaPlayerEncryptedMediaClient* encrypted_client,
[email protected]b8976652011-10-26 23:46:55141 base::WeakPtr<WebMediaPlayerDelegate> delegate,
xhwang6fa356202014-12-11 00:44:12142 scoped_ptr<RendererFactory> renderer_factory,
hubbe5f0ad43b2015-12-14 20:57:26143 linked_ptr<UrlIndex> url_index,
[email protected]e82b2bd2013-01-02 17:47:57144 const WebMediaPlayerParams& params)
[email protected]f6af7592014-02-28 10:09:11145 : frame_(frame),
[email protected]ef405f66b2012-04-18 02:39:55146 network_state_(WebMediaPlayer::NetworkStateEmpty),
147 ready_state_(WebMediaPlayer::ReadyStateHaveNothing),
acolwella5081a42014-08-28 23:42:52148 preload_(BufferedDataSource::AUTO),
sandersdc6ab163a2015-12-12 03:56:13149 buffering_strategy_(
150 BufferedDataSourceInterface::BUFFERING_STRATEGY_NORMAL),
anujk.sharma2fa37a02015-04-30 05:51:32151 main_task_runner_(base::ThreadTaskRunnerHandle::Get()),
acolwell755d12d2014-08-30 01:09:19152 media_task_runner_(params.media_task_runner()),
dcastagna617d086b2015-08-20 01:39:30153 worker_task_runner_(params.worker_task_runner()),
acolwell755d12d2014-08-30 01:09:19154 media_log_(params.media_log()),
acolwellb4034942014-08-28 15:42:43155 pipeline_(media_task_runner_, media_log_.get()),
sandersd1c0bba02016-03-04 23:14:08156 pipeline_controller_(
157 &pipeline_,
158 base::Bind(&WebMediaPlayerImpl::CreateRenderer,
159 base::Unretained(this)),
160 base::Bind(&WebMediaPlayerImpl::OnPipelineSeeked, AsWeakPtr()),
161 base::Bind(&WebMediaPlayerImpl::OnPipelineSuspended, AsWeakPtr()),
162 base::Bind(&WebMediaPlayerImpl::OnPipelineResumed, AsWeakPtr()),
163 base::Bind(&WebMediaPlayerImpl::OnPipelineError, AsWeakPtr())),
[email protected]f988d9b2014-07-25 00:35:43164 load_type_(LoadTypeURL),
[email protected]75e145a2014-04-15 17:44:32165 opaque_(false),
wolenetz1b2ae7d2015-06-10 00:44:21166 playback_rate_(0.0),
[email protected]49480902009-07-14 20:23:43167 paused_(true),
[email protected]b3766a22010-12-22 17:34:13168 seeking_(false),
watkdee516f2016-02-18 02:22:19169 pending_suspend_resume_cycle_(false),
scherkusd2c745b2014-09-04 05:03:40170 ended_(false),
yoichio863bebf2016-03-04 07:56:58171 should_notify_time_changed_(false),
watkdee516f2016-02-18 02:22:19172 fullscreen_(false),
173 decoder_requires_restart_for_fullscreen_(false),
[email protected]5badb082010-06-11 17:40:15174 client_(client),
srirama.m26f864d02015-07-14 05:21:46175 encrypted_client_(encrypted_client),
[email protected]baff4512011-10-19 18:21:07176 delegate_(delegate),
dalecurtisbb3eaac2016-01-27 21:10:25177 delegate_id_(0),
[email protected]d726eddc2013-07-02 22:25:55178 defer_load_cb_(params.defer_load_cb()),
dongseong.hwang0c4e9d82015-01-08 20:11:13179 context_3d_cb_(params.context_3d_cb()),
dalecurtis83266c72015-10-29 18:43:20180 adjust_allocated_memory_cb_(params.adjust_allocated_memory_cb()),
181 last_reported_memory_usage_(0),
[email protected]132dd57c2012-08-10 23:24:34182 supports_save_(true),
[email protected]f5443ef72013-04-22 04:03:38183 chunk_demuxer_(NULL),
hubbe5f0ad43b2015-12-14 20:57:26184 url_index_(url_index),
Bartosz Fabianowski85a823812015-04-16 10:27:51185 // Threaded compositing isn't enabled universally yet.
186 compositor_task_runner_(
187 params.compositor_task_runner()
188 ? params.compositor_task_runner()
189 : base::MessageLoop::current()->task_runner()),
[email protected]dd061e12014-05-06 19:21:22190 compositor_(new VideoFrameCompositor(
Bartosz Fabianowski85a823812015-04-16 10:27:51191 compositor_task_runner_,
[email protected]75e145a2014-04-15 17:44:32192 BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnNaturalSizeChanged),
[email protected]dd061e12014-05-06 19:21:22193 BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnOpacityChanged))),
xhwang80739452016-01-13 00:48:00194 is_cdm_attached_(false),
hubbed5f36882016-01-15 22:40:37195#if defined(OS_ANDROID) // WMPI_CAST
dalecurtisbb3eaac2016-01-27 21:10:25196 cast_impl_(this, client_, params.context_3d_cb()),
hubbed5f36882016-01-15 22:40:37197#endif
dalecurtisbb3eaac2016-01-27 21:10:25198 volume_(1.0),
199 volume_multiplier_(1.0),
watkdee516f2016-02-18 02:22:19200 renderer_factory_(std::move(renderer_factory)),
dalecurtis2ff781da2016-03-03 01:52:13201 surface_manager_(params.surface_manager()),
202 suppress_destruction_errors_(false) {
dalecurtis83266c72015-10-29 18:43:20203 DCHECK(!adjust_allocated_memory_cb_.is_null());
xhwang59d4175a2016-01-14 03:19:30204 DCHECK(renderer_factory_);
dalecurtis83266c72015-10-29 18:43:20205
dalecurtisbb3eaac2016-01-27 21:10:25206 if (delegate_)
207 delegate_id_ = delegate_->AddObserver(this);
sandersd1e49fb62015-12-12 01:18:06208
[email protected]c93eb0a62011-08-09 22:47:24209 media_log_->AddEvent(
acolwell9e0840d2014-09-06 19:01:32210 media_log_->CreateEvent(MediaLogEvent::WEBMEDIAPLAYER_CREATED));
[email protected]4e6be3f2009-05-07 02:24:44211
xhwang0ad11e512014-11-25 23:43:09212 if (params.initial_cdm()) {
xhwang9bd8c732015-04-13 23:27:53213 SetCdm(base::Bind(&IgnoreCdmAttached),
214 ToWebContentDecryptionModuleImpl(params.initial_cdm())
215 ->GetCdmContext());
xhwang0ad11e512014-11-25 23:43:09216 }
217
xhwangf94a634d2014-10-22 22:07:27218 // TODO(xhwang): When we use an external Renderer, many methods won't work,
xhwang6fa356202014-12-11 00:44:12219 // e.g. GetCurrentFrameFromCompositor(). See http://crbug.com/434861
[email protected]c50edb962013-10-19 18:05:07220
[email protected]ddbc6ff2013-04-19 15:28:33221 // Use the null sink if no sink was provided.
[email protected]4a914882013-01-10 00:43:48222 audio_source_provider_ = new WebAudioSourceProviderImpl(
[email protected]ff875be52013-06-02 23:47:38223 params.audio_renderer_sink().get()
224 ? params.audio_renderer_sink()
acolwell9e0840d2014-09-06 19:01:32225 : new NullAudioSink(media_task_runner_));
[email protected]ec9212f2008-12-18 21:40:36226}
227
[email protected]4e6be3f2009-05-07 02:24:44228WebMediaPlayerImpl::~WebMediaPlayerImpl() {
[email protected]ce70c982013-12-20 17:04:32229 client_->setWebLayer(NULL);
[email protected]21c3f7502013-03-23 03:29:51230
acolwellb4034942014-08-28 15:42:43231 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]d43ed912009-02-03 04:52:53232
sandersd1e49fb62015-12-12 01:18:06233 if (delegate_) {
dalecurtisbb3eaac2016-01-27 21:10:25234 delegate_->PlayerGone(delegate_id_);
235 delegate_->RemoveObserver(delegate_id_);
sandersd1e49fb62015-12-12 01:18:06236 }
[email protected]baff4512011-10-19 18:21:07237
[email protected]f6af7592014-02-28 10:09:11238 // Abort any pending IO so stopping the pipeline doesn't get blocked.
dalecurtis2ff781da2016-03-03 01:52:13239 suppress_destruction_errors_ = true;
[email protected]f6af7592014-02-28 10:09:11240 if (data_source_)
241 data_source_->Abort();
242 if (chunk_demuxer_) {
243 chunk_demuxer_->Shutdown();
sandersd1c0bba02016-03-04 23:14:08244 chunk_demuxer_ = nullptr;
[email protected]f6af7592014-02-28 10:09:11245 }
246
xhwang6fa356202014-12-11 00:44:12247 renderer_factory_.reset();
[email protected]f6af7592014-02-28 10:09:11248
249 // Make sure to kill the pipeline so there's no more media threads running.
250 // Note: stopping the pipeline might block for a long time.
251 base::WaitableEvent waiter(false, false);
252 pipeline_.Stop(
253 base::Bind(&base::WaitableEvent::Signal, base::Unretained(&waiter)));
254 waiter.Wait();
255
dalecurtis83266c72015-10-29 18:43:20256 if (last_reported_memory_usage_)
257 adjust_allocated_memory_cb_.Run(-last_reported_memory_usage_);
258
[email protected]dd061e12014-05-06 19:21:22259 compositor_task_runner_->DeleteSoon(FROM_HERE, compositor_);
xhwangea8bb3562015-06-08 21:18:37260
261 media_log_->AddEvent(
262 media_log_->CreateEvent(MediaLogEvent::WEBMEDIAPLAYER_DESTROYED));
[email protected]ec9212f2008-12-18 21:40:36263}
264
[email protected]180ef242013-11-07 06:50:46265void WebMediaPlayerImpl::load(LoadType load_type, const blink::WebURL& url,
[email protected]62e5e682013-03-07 23:53:24266 CORSMode cors_mode) {
[email protected]2a06ca62014-06-04 13:59:52267 DVLOG(1) << __FUNCTION__ << "(" << load_type << ", " << url << ", "
268 << cors_mode << ")";
[email protected]d726eddc2013-07-02 22:25:55269 if (!defer_load_cb_.is_null()) {
270 defer_load_cb_.Run(base::Bind(
[email protected]ef8394c2013-08-21 20:26:30271 &WebMediaPlayerImpl::DoLoad, AsWeakPtr(), load_type, url, cors_mode));
[email protected]d726eddc2013-07-02 22:25:55272 return;
273 }
[email protected]ef8394c2013-08-21 20:26:30274 DoLoad(load_type, url, cors_mode);
[email protected]62e5e682013-03-07 23:53:24275}
276
watkdee516f2016-02-18 02:22:19277void WebMediaPlayerImpl::enteredFullscreen() {
278 fullscreen_ = true;
279 if (decoder_requires_restart_for_fullscreen_)
280 ScheduleRestart();
281}
282
283void WebMediaPlayerImpl::exitedFullscreen() {
284 fullscreen_ = false;
285 if (decoder_requires_restart_for_fullscreen_)
286 ScheduleRestart();
287}
288
[email protected]ef8394c2013-08-21 20:26:30289void WebMediaPlayerImpl::DoLoad(LoadType load_type,
[email protected]180ef242013-11-07 06:50:46290 const blink::WebURL& url,
[email protected]d726eddc2013-07-02 22:25:55291 CORSMode cors_mode) {
hubbed82bed52015-12-15 23:07:16292 DVLOG(1) << __FUNCTION__;
acolwellb4034942014-08-28 15:42:43293 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]d726eddc2013-07-02 22:25:55294
[email protected]62e5e682013-03-07 23:53:24295 GURL gurl(url);
Dana Jansens71331252016-03-09 20:57:22296 ReportMetrics(load_type, gurl, frame_->document().getSecurityOrigin());
[email protected]62e5e682013-03-07 23:53:24297
[email protected]926f8fd2013-04-12 20:27:53298 // Set subresource URL for crash reporting.
299 base::debug::SetCrashKeyValue("subresource_url", gurl.spec());
300
[email protected]ef8394c2013-08-21 20:26:30301 load_type_ = load_type;
302
[email protected]62e5e682013-03-07 23:53:24303 SetNetworkState(WebMediaPlayer::NetworkStateLoading);
304 SetReadyState(WebMediaPlayer::ReadyStateHaveNothing);
kinukof19cde72015-12-18 23:15:25305 media_log_->AddEvent(media_log_->CreateLoadEvent(url.string().utf8()));
[email protected]d726eddc2013-07-02 22:25:55306
307 // Media source pipelines can start immediately.
[email protected]ef8394c2013-08-21 20:26:30308 if (load_type == LoadTypeMediaSource) {
[email protected]d726eddc2013-07-02 22:25:55309 supports_save_ = false;
[email protected]ef8394c2013-08-21 20:26:30310 StartPipeline();
[email protected]d726eddc2013-07-02 22:25:55311 return;
312 }
313
hubbe2703d09e2016-02-10 23:17:18314 // TODO(hubbe): This experiment is temporary and should be removed once
315 // we have enough data to support the primacy of the new media cache.
316 // See http://crbug.com/514719 for details.
[email protected]d726eddc2013-07-02 22:25:55317 // Otherwise it's a regular request which requires resolving the URL first.
hubbe2703d09e2016-02-10 23:17:18318 if (base::FeatureList::IsEnabled(kUseNewMediaCache)) {
hubbe5f0ad43b2015-12-14 20:57:26319 // Remove this when MultiBufferDataSource becomes default.
320 LOG(WARNING) << "Using MultibufferDataSource";
321 data_source_.reset(new MultibufferDataSource(
322 url, static_cast<UrlData::CORSMode>(cors_mode), main_task_runner_,
323 url_index_, frame_, media_log_.get(), &buffered_data_source_host_,
324 base::Bind(&WebMediaPlayerImpl::NotifyDownloading, AsWeakPtr())));
325 } else {
326 data_source_.reset(new BufferedDataSource(
327 url, static_cast<BufferedResourceLoader::CORSMode>(cors_mode),
328 main_task_runner_, frame_, media_log_.get(),
329 &buffered_data_source_host_,
330 base::Bind(&WebMediaPlayerImpl::NotifyDownloading, AsWeakPtr())));
331 }
dalecurtis9157fc9e2015-01-16 01:09:11332 data_source_->SetPreload(preload_);
sandersdc6ab163a2015-12-12 03:56:13333 data_source_->SetBufferingStrategy(buffering_strategy_);
[email protected]d726eddc2013-07-02 22:25:55334 data_source_->Initialize(
[email protected]fee8a902014-06-03 13:43:36335 base::Bind(&WebMediaPlayerImpl::DataSourceInitialized, AsWeakPtr()));
hubbed5f36882016-01-15 22:40:37336
337#if defined(OS_ANDROID) // WMPI_CAST
dalecurtisbb3eaac2016-01-27 21:10:25338 cast_impl_.Initialize(url, frame_, delegate_id_);
hubbed5f36882016-01-15 22:40:37339#endif
[email protected]62e5e682013-03-07 23:53:24340}
341
[email protected]4e6be3f2009-05-07 02:24:44342void WebMediaPlayerImpl::play() {
[email protected]2a06ca62014-06-04 13:59:52343 DVLOG(1) << __FUNCTION__;
acolwellb4034942014-08-28 15:42:43344 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]d43ed912009-02-03 04:52:53345
hubbed5f36882016-01-15 22:40:37346#if defined(OS_ANDROID) // WMPI_CAST
347 if (isRemote()) {
dalecurtis6e2716d2016-01-21 04:49:15348 cast_impl_.play();
hubbed5f36882016-01-15 22:40:37349 return;
350 }
351#endif
352
dalecurtis0431cbf2016-03-12 01:19:43353 const bool was_paused = paused_;
[email protected]49480902009-07-14 20:23:43354 paused_ = false;
yoichio863bebf2016-03-04 07:56:58355 pipeline_.SetPlaybackRate(playback_rate_);
sandersd1c0bba02016-03-04 23:14:08356
[email protected]039b7542013-10-17 22:06:25357 if (data_source_)
358 data_source_->MediaIsPlaying();
[email protected]090f7312011-08-05 23:26:40359
acolwell9e0840d2014-09-06 19:01:32360 media_log_->AddEvent(media_log_->CreateEvent(MediaLogEvent::PLAY));
[email protected]baff4512011-10-19 18:21:07361
dalecurtis0431cbf2016-03-12 01:19:43362 if (playback_rate_ > 0 && was_paused) {
yoichio863bebf2016-03-04 07:56:58363 NotifyPlaybackStarted();
sandersd1c0bba02016-03-04 23:14:08364
dalecurtis0431cbf2016-03-12 01:19:43365 // Resume the player if allowed. We always call Resume() in case there is a
366 // pending suspend that should be aborted. If the pipeline is not suspended,
367 // Resume() will have no effect.
368 if (IsAutomaticResumeAllowed())
sandersd1c0bba02016-03-04 23:14:08369 pipeline_controller_.Resume();
dalecurtis5bbc487e2016-02-27 04:15:05370 }
[email protected]ec9212f2008-12-18 21:40:36371}
372
[email protected]4e6be3f2009-05-07 02:24:44373void WebMediaPlayerImpl::pause() {
[email protected]2a06ca62014-06-04 13:59:52374 DVLOG(1) << __FUNCTION__;
acolwellb4034942014-08-28 15:42:43375 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]d43ed912009-02-03 04:52:53376
dalecurtis6d269ed2014-09-11 21:18:13377 const bool was_already_paused = paused_ || playback_rate_ == 0;
[email protected]49480902009-07-14 20:23:43378 paused_ = true;
hubbed5f36882016-01-15 22:40:37379
380#if defined(OS_ANDROID) // WMPI_CAST
381 if (isRemote()) {
dalecurtis6e2716d2016-01-21 04:49:15382 cast_impl_.pause();
hubbed5f36882016-01-15 22:40:37383 return;
384 }
385#endif
386
a.berwal338bf002015-04-22 11:14:50387 pipeline_.SetPlaybackRate(0.0);
sandersd1c0bba02016-03-04 23:14:08388
389 // pause() may be called after playback has ended and the HTMLMediaElement
390 // requires that currentTime() == duration() after ending. We want to ensure
391 // |paused_time_| matches currentTime() in this case or a future seek() may
392 // incorrectly discard what it thinks is a seek to the existing time.
393 paused_time_ =
394 ended_ ? pipeline_.GetMediaDuration() : pipeline_.GetMediaTime();
[email protected]090f7312011-08-05 23:26:40395
acolwell9e0840d2014-09-06 19:01:32396 media_log_->AddEvent(media_log_->CreateEvent(MediaLogEvent::PAUSE));
[email protected]baff4512011-10-19 18:21:07397
dalecurtisbb3eaac2016-01-27 21:10:25398 if (!was_already_paused)
dalecurtis0f0097a2015-12-01 17:40:47399 NotifyPlaybackPaused();
[email protected]ec9212f2008-12-18 21:40:36400}
401
[email protected]574a1d62009-07-17 03:23:46402bool WebMediaPlayerImpl::supportsSave() const {
acolwellb4034942014-08-28 15:42:43403 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]132dd57c2012-08-10 23:24:34404 return supports_save_;
[email protected]574a1d62009-07-17 03:23:46405}
406
[email protected]39bdde32013-04-17 17:44:20407void WebMediaPlayerImpl::seek(double seconds) {
xhwang12d8d042014-12-01 21:48:57408 DVLOG(1) << __FUNCTION__ << "(" << seconds << "s)";
acolwellb4034942014-08-28 15:42:43409 DCHECK(main_task_runner_->BelongsToCurrentThread());
sandersd1c0bba02016-03-04 23:14:08410 DoSeek(base::TimeDelta::FromSecondsD(seconds), true);
411}
412
413void WebMediaPlayerImpl::DoSeek(base::TimeDelta time, bool time_updated) {
414 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]d43ed912009-02-03 04:52:53415
scherkusd2c745b2014-09-04 05:03:40416 ended_ = false;
417
hubbed5f36882016-01-15 22:40:37418#if defined(OS_ANDROID) // WMPI_CAST
419 if (isRemote()) {
sandersd1c0bba02016-03-04 23:14:08420 cast_impl_.seek(time);
hubbed5f36882016-01-15 22:40:37421 return;
422 }
423#endif
424
srirama.mccf671812015-01-08 11:59:13425 ReadyState old_state = ready_state_;
[email protected]1bb666802013-11-28 06:12:08426 if (ready_state_ > WebMediaPlayer::ReadyStateHaveMetadata)
427 SetReadyState(WebMediaPlayer::ReadyStateHaveMetadata);
428
sandersd1c0bba02016-03-04 23:14:08429 // When paused, we know exactly what the current time is and can elide seeks
430 // to it. However, there are two cases that are not elided:
431 // 1) When the pipeline state is not stable.
432 // In this case we just let |pipeline_controller_| decide what to do, as
433 // it has complete information.
434 // 2) For MSE.
435 // Because the buffers may have changed between seeks, MSE seeks are
436 // never elided.
437 if (paused_ && pipeline_controller_.IsStable() && paused_time_ == time &&
438 !chunk_demuxer_) {
439 // If the ready state was high enough before, we can indicate that the seek
440 // completed just by restoring it. Otherwise we will just wait for the real
441 // ready state change to eventually happen.
442 if (old_state == ReadyStateHaveEnoughData) {
srirama.m8f4a37562014-12-13 08:16:18443 main_task_runner_->PostTask(
srirama.m36ab2682014-12-11 04:20:01444 FROM_HERE,
445 base::Bind(&WebMediaPlayerImpl::OnPipelineBufferingStateChanged,
srirama.m8f4a37562014-12-13 08:16:18446 AsWeakPtr(), BUFFERING_HAVE_ENOUGH));
srirama.m36ab2682014-12-11 04:20:01447 }
sandersd1c0bba02016-03-04 23:14:08448 return;
srirama.m36ab2682014-12-11 04:20:01449 }
[email protected]44ff37c02009-10-24 01:03:03450
[email protected]b3766a22010-12-22 17:34:13451 seeking_ = true;
sandersd1c0bba02016-03-04 23:14:08452 seek_time_ = time;
453 if (paused_)
454 paused_time_ = time;
455 pipeline_controller_.Seek(time, time_updated);
[email protected]b3766a22010-12-22 17:34:13456
dalecurtis0431cbf2016-03-12 01:19:43457 // Resume the pipeline if allowed so that the correct frame is displayed. We
458 // always call Resume() in case there is a pending suspend that should be
459 // aborted. If the pipeline is not suspended, Resume() will have no effect.
460 if (IsAutomaticResumeAllowed())
sandersd1c0bba02016-03-04 23:14:08461 pipeline_controller_.Resume();
[email protected]ec9212f2008-12-18 21:40:36462}
463
[email protected]39bdde32013-04-17 17:44:20464void WebMediaPlayerImpl::setRate(double rate) {
[email protected]2a06ca62014-06-04 13:59:52465 DVLOG(1) << __FUNCTION__ << "(" << rate << ")";
acolwellb4034942014-08-28 15:42:43466 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]d43ed912009-02-03 04:52:53467
[email protected]378f0b72009-08-11 17:11:42468 // TODO(kylep): Remove when support for negatives is added. Also, modify the
469 // following checks so rewind uses reasonable values also.
[email protected]39bdde32013-04-17 17:44:20470 if (rate < 0.0)
[email protected]378f0b72009-08-11 17:11:42471 return;
472
473 // Limit rates to reasonable values by clamping.
[email protected]39bdde32013-04-17 17:44:20474 if (rate != 0.0) {
[email protected]378f0b72009-08-11 17:11:42475 if (rate < kMinRate)
476 rate = kMinRate;
477 else if (rate > kMaxRate)
478 rate = kMaxRate;
dalecurtisbb3eaac2016-01-27 21:10:25479 if (playback_rate_ == 0 && !paused_)
dalecurtis0f0097a2015-12-01 17:40:47480 NotifyPlaybackStarted();
dalecurtisbb3eaac2016-01-27 21:10:25481 } else if (playback_rate_ != 0 && !paused_) {
dalecurtis0f0097a2015-12-01 17:40:47482 NotifyPlaybackPaused();
[email protected]378f0b72009-08-11 17:11:42483 }
484
[email protected]49480902009-07-14 20:23:43485 playback_rate_ = rate;
486 if (!paused_) {
[email protected]f6af7592014-02-28 10:09:11487 pipeline_.SetPlaybackRate(rate);
[email protected]039b7542013-10-17 22:06:25488 if (data_source_)
489 data_source_->MediaPlaybackRateChanged(rate);
[email protected]49480902009-07-14 20:23:43490 }
[email protected]ec9212f2008-12-18 21:40:36491}
492
[email protected]39bdde32013-04-17 17:44:20493void WebMediaPlayerImpl::setVolume(double volume) {
[email protected]2a06ca62014-06-04 13:59:52494 DVLOG(1) << __FUNCTION__ << "(" << volume << ")";
acolwellb4034942014-08-28 15:42:43495 DCHECK(main_task_runner_->BelongsToCurrentThread());
dalecurtisbb3eaac2016-01-27 21:10:25496 volume_ = volume;
497 pipeline_.SetVolume(volume_ * volume_multiplier_);
[email protected]ec9212f2008-12-18 21:40:36498}
[email protected]f0a51fb52009-03-05 12:46:38499
guidouc7babef2015-10-22 00:42:35500void WebMediaPlayerImpl::setSinkId(
501 const blink::WebString& sink_id,
502 const blink::WebSecurityOrigin& security_origin,
503 blink::WebSetSinkIdCallbacks* web_callback) {
guidou69223ce2015-06-16 10:36:19504 DCHECK(main_task_runner_->BelongsToCurrentThread());
guidou5754e612015-07-31 08:09:41505 DVLOG(1) << __FUNCTION__;
guidouc7babef2015-10-22 00:42:35506
guidou5754e612015-07-31 08:09:41507 media::SwitchOutputDeviceCB callback =
508 media::ConvertToSwitchOutputDeviceCB(web_callback);
guidouc7babef2015-10-22 00:42:35509 media_task_runner_->PostTask(
510 FROM_HERE,
511 base::Bind(&SetSinkIdOnMediaThread, audio_source_provider_,
512 sink_id.utf8(), static_cast<url::Origin>(security_origin),
513 callback));
guidou69223ce2015-06-16 10:36:19514}
515
danakj365175c2016-02-06 00:37:37516STATIC_ASSERT_ENUM(WebMediaPlayer::PreloadNone, BufferedDataSource::NONE);
517STATIC_ASSERT_ENUM(WebMediaPlayer::PreloadMetaData,
518 BufferedDataSource::METADATA);
519STATIC_ASSERT_ENUM(WebMediaPlayer::PreloadAuto, BufferedDataSource::AUTO);
[email protected]23a8b1d82011-04-05 16:28:20520
[email protected]ef405f66b2012-04-18 02:39:55521void WebMediaPlayerImpl::setPreload(WebMediaPlayer::Preload preload) {
[email protected]2a06ca62014-06-04 13:59:52522 DVLOG(1) << __FUNCTION__ << "(" << preload << ")";
acolwellb4034942014-08-28 15:42:43523 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]4e6be3f2009-05-07 02:24:44524
acolwella5081a42014-08-28 23:42:52525 preload_ = static_cast<BufferedDataSource::Preload>(preload);
[email protected]b49beeb2013-03-01 20:04:00526 if (data_source_)
[email protected]09c60222014-08-07 16:42:31527 data_source_->SetPreload(preload_);
[email protected]4e6be3f2009-05-07 02:24:44528}
529
danakj365175c2016-02-06 00:37:37530STATIC_ASSERT_ENUM(WebMediaPlayer::BufferingStrategy::Normal,
531 BufferedDataSource::BUFFERING_STRATEGY_NORMAL);
532STATIC_ASSERT_ENUM(WebMediaPlayer::BufferingStrategy::Aggressive,
533 BufferedDataSource::BUFFERING_STRATEGY_AGGRESSIVE);
sandersdc6ab163a2015-12-12 03:56:13534
535void WebMediaPlayerImpl::setBufferingStrategy(
536 WebMediaPlayer::BufferingStrategy buffering_strategy) {
537 DVLOG(1) << __FUNCTION__;
538 DCHECK(main_task_runner_->BelongsToCurrentThread());
539
540 buffering_strategy_ =
541 static_cast<BufferedDataSource::BufferingStrategy>(buffering_strategy);
542 if (data_source_)
543 data_source_->SetBufferingStrategy(buffering_strategy_);
544}
545
[email protected]4e6be3f2009-05-07 02:24:44546bool WebMediaPlayerImpl::hasVideo() const {
acolwellb4034942014-08-28 15:42:43547 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]d43ed912009-02-03 04:52:53548
[email protected]b8877772014-03-26 20:17:15549 return pipeline_metadata_.has_video;
[email protected]d43ed912009-02-03 04:52:53550}
551
[email protected]fc367af2009-08-14 23:06:35552bool WebMediaPlayerImpl::hasAudio() const {
acolwellb4034942014-08-28 15:42:43553 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]fc367af2009-08-14 23:06:35554
[email protected]b8877772014-03-26 20:17:15555 return pipeline_metadata_.has_audio;
[email protected]fc367af2009-08-14 23:06:35556}
557
[email protected]180ef242013-11-07 06:50:46558blink::WebSize WebMediaPlayerImpl::naturalSize() const {
acolwellb4034942014-08-28 15:42:43559 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]d43ed912009-02-03 04:52:53560
[email protected]b8877772014-03-26 20:17:15561 return blink::WebSize(pipeline_metadata_.natural_size);
[email protected]d43ed912009-02-03 04:52:53562}
563
[email protected]4e6be3f2009-05-07 02:24:44564bool WebMediaPlayerImpl::paused() const {
acolwellb4034942014-08-28 15:42:43565 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]d43ed912009-02-03 04:52:53566
hubbed5f36882016-01-15 22:40:37567#if defined(OS_ANDROID) // WMPI_CAST
568 if (isRemote())
569 return cast_impl_.paused();
570#endif
[email protected]f6af7592014-02-28 10:09:11571 return pipeline_.GetPlaybackRate() == 0.0f;
[email protected]d43ed912009-02-03 04:52:53572}
573
[email protected]4e6be3f2009-05-07 02:24:44574bool WebMediaPlayerImpl::seeking() const {
acolwellb4034942014-08-28 15:42:43575 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]d43ed912009-02-03 04:52:53576
[email protected]ef405f66b2012-04-18 02:39:55577 if (ready_state_ == WebMediaPlayer::ReadyStateHaveNothing)
[email protected]0acebfa2009-08-21 22:45:40578 return false;
[email protected]67cd5052009-09-10 21:53:22579
[email protected]b3766a22010-12-22 17:34:13580 return seeking_;
[email protected]ec9212f2008-12-18 21:40:36581}
582
[email protected]39bdde32013-04-17 17:44:20583double WebMediaPlayerImpl::duration() const {
acolwellb4034942014-08-28 15:42:43584 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]39bdde32013-04-17 17:44:20585
586 if (ready_state_ == WebMediaPlayer::ReadyStateHaveNothing)
587 return std::numeric_limits<double>::quiet_NaN();
588
[email protected]39bdde32013-04-17 17:44:20589 return GetPipelineDuration();
[email protected]d43ed912009-02-03 04:52:53590}
591
[email protected]db66d0092014-04-16 07:15:12592double WebMediaPlayerImpl::timelineOffset() const {
acolwellb4034942014-08-28 15:42:43593 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]db66d0092014-04-16 07:15:12594
595 if (pipeline_metadata_.timeline_offset.is_null())
596 return std::numeric_limits<double>::quiet_NaN();
597
598 return pipeline_metadata_.timeline_offset.ToJsTime();
599}
600
[email protected]39bdde32013-04-17 17:44:20601double WebMediaPlayerImpl::currentTime() const {
acolwellb4034942014-08-28 15:42:43602 DCHECK(main_task_runner_->BelongsToCurrentThread());
scherkusd2c745b2014-09-04 05:03:40603 DCHECK_NE(ready_state_, WebMediaPlayer::ReadyStateHaveNothing);
604
605 // TODO(scherkus): Replace with an explicit ended signal to HTMLMediaElement,
606 // see http://crbug.com/409280
607 if (ended_)
608 return duration();
609
sandersd1c0bba02016-03-04 23:14:08610 if (seeking())
611 return seek_time_.InSecondsF();
wolenetz1b2ae7d2015-06-10 00:44:21612
hubbed5f36882016-01-15 22:40:37613#if defined(OS_ANDROID) // WMPI_CAST
sandersd1c0bba02016-03-04 23:14:08614 if (isRemote())
hubbed5f36882016-01-15 22:40:37615 return cast_impl_.currentTime();
hubbed5f36882016-01-15 22:40:37616#endif
617
sandersd1c0bba02016-03-04 23:14:08618 if (paused_)
hubbed5f36882016-01-15 22:40:37619 return paused_time_.InSecondsF();
hubbed5f36882016-01-15 22:40:37620
621 return pipeline_.GetMediaTime().InSecondsF();
[email protected]d43ed912009-02-03 04:52:53622}
623
danakj13afe0362016-02-27 01:22:50624WebMediaPlayer::NetworkState WebMediaPlayerImpl::getNetworkState() const {
acolwellb4034942014-08-28 15:42:43625 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]ddb1e5a2010-12-13 20:10:45626 return network_state_;
627}
628
danakj13afe0362016-02-27 01:22:50629WebMediaPlayer::ReadyState WebMediaPlayerImpl::getReadyState() const {
acolwellb4034942014-08-28 15:42:43630 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]ddb1e5a2010-12-13 20:10:45631 return ready_state_;
632}
633
[email protected]02022fc2014-05-16 00:05:31634blink::WebTimeRanges WebMediaPlayerImpl::buffered() const {
acolwellb4034942014-08-28 15:42:43635 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]779a8322014-08-22 21:28:37636
acolwell9e0840d2014-09-06 19:01:32637 Ranges<base::TimeDelta> buffered_time_ranges =
[email protected]02022fc2014-05-16 00:05:31638 pipeline_.GetBufferedTimeRanges();
[email protected]779a8322014-08-22 21:28:37639
640 const base::TimeDelta duration = pipeline_.GetMediaDuration();
acolwell9e0840d2014-09-06 19:01:32641 if (duration != kInfiniteDuration()) {
[email protected]779a8322014-08-22 21:28:37642 buffered_data_source_host_.AddBufferedTimeRanges(
643 &buffered_time_ranges, duration);
644 }
[email protected]02022fc2014-05-16 00:05:31645 return ConvertToWebTimeRanges(buffered_time_ranges);
646}
647
philipjb0e6f3f2014-09-30 09:51:53648blink::WebTimeRanges WebMediaPlayerImpl::seekable() const {
acolwellb4034942014-08-28 15:42:43649 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]39bdde32013-04-17 17:44:20650
dalecurtis56359cb2014-10-28 00:06:29651 if (ready_state_ < WebMediaPlayer::ReadyStateHaveMetadata)
philipjb0e6f3f2014-09-30 09:51:53652 return blink::WebTimeRanges();
653
dalecurtis56359cb2014-10-28 00:06:29654 const double seekable_end = duration();
655
656 // Allow a special exception for seeks to zero for streaming sources with a
657 // finite duration; this allows looping to work.
658 const bool allow_seek_to_zero = data_source_ && data_source_->IsStreaming() &&
mateuszs3371ab02015-04-24 13:20:23659 std::isfinite(seekable_end);
dalecurtis56359cb2014-10-28 00:06:29660
661 // TODO(dalecurtis): Technically this allows seeking on media which return an
662 // infinite duration so long as DataSource::IsStreaming() is false. While not
663 // expected, disabling this breaks semi-live players, http://crbug.com/427412.
664 const blink::WebTimeRange seekable_range(
665 0.0, allow_seek_to_zero ? 0.0 : seekable_end);
philipjb0e6f3f2014-09-30 09:51:53666 return blink::WebTimeRanges(&seekable_range, 1);
[email protected]ec9212f2008-12-18 21:40:36667}
668
[email protected]5d2b3e4c2014-05-12 23:27:30669bool WebMediaPlayerImpl::didLoadingProgress() {
acolwellb4034942014-08-28 15:42:43670 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]6683e1b2014-04-10 01:45:38671 bool pipeline_progress = pipeline_.DidLoadingProgress();
672 bool data_progress = buffered_data_source_host_.DidLoadingProgress();
673 return pipeline_progress || data_progress;
[email protected]d43ed912009-02-03 04:52:53674}
675
[email protected]dd5c7972014-08-21 15:00:37676void WebMediaPlayerImpl::paint(blink::WebCanvas* canvas,
677 const blink::WebRect& rect,
[email protected]dd5c7972014-08-21 15:00:37678 unsigned char alpha,
679 SkXfermode::Mode mode) {
acolwellb4034942014-08-28 15:42:43680 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]dd061e12014-05-06 19:21:22681 TRACE_EVENT0("media", "WebMediaPlayerImpl:paint");
[email protected]4e6be3f2009-05-07 02:24:44682
xhwang80739452016-01-13 00:48:00683 if (is_cdm_attached_)
684 return;
685
mcasasf1236fc22015-05-29 22:38:56686 scoped_refptr<VideoFrame> video_frame = GetCurrentFrameFromCompositor();
[email protected]0fe5d43b2014-01-24 23:32:45687
[email protected]b49beeb2013-03-01 20:04:00688 gfx::Rect gfx_rect(rect);
dongseong.hwang0c4e9d82015-01-08 20:11:13689 Context3D context_3d;
mcasas265bdbf82015-06-12 18:44:07690 if (video_frame.get() && video_frame->HasTextures()) {
mcasasf1236fc22015-05-29 22:38:56691 if (!context_3d_cb_.is_null())
dongseong.hwang0c4e9d82015-01-08 20:11:13692 context_3d = context_3d_cb_.Run();
dongseong.hwang0c4e9d82015-01-08 20:11:13693 // GPU Process crashed.
694 if (!context_3d.gl)
695 return;
696 }
danakj795f1732015-08-31 23:40:22697 skcanvas_video_renderer_.Paint(video_frame, canvas, gfx::RectF(gfx_rect),
698 alpha, mode, pipeline_metadata_.video_rotation,
699 context_3d);
[email protected]ec9212f2008-12-18 21:40:36700}
[email protected]5df51652009-01-17 00:03:00701
[email protected]38259a7a82009-07-29 21:49:49702bool WebMediaPlayerImpl::hasSingleSecurityOrigin() const {
[email protected]b49beeb2013-03-01 20:04:00703 if (data_source_)
704 return data_source_->HasSingleOrigin();
[email protected]fcdb7462009-10-21 21:05:11705 return true;
[email protected]38259a7a82009-07-29 21:49:49706}
707
[email protected]3fe27112012-06-07 04:00:01708bool WebMediaPlayerImpl::didPassCORSAccessCheck() const {
[email protected]b49beeb2013-03-01 20:04:00709 if (data_source_)
710 return data_source_->DidPassCORSAccessCheck();
711 return false;
[email protected]3fe27112012-06-07 04:00:01712}
713
[email protected]39bdde32013-04-17 17:44:20714double WebMediaPlayerImpl::mediaTimeForTimeValue(double timeValue) const {
qinminb4c39782015-08-10 18:43:24715 return base::TimeDelta::FromSecondsD(timeValue).InSecondsF();
[email protected]e06e16d82011-05-26 22:13:33716}
717
[email protected]d82b18ae2011-03-23 21:28:59718unsigned WebMediaPlayerImpl::decodedFrameCount() const {
acolwellb4034942014-08-28 15:42:43719 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]4c51bc662011-02-16 02:03:16720
acolwell9e0840d2014-09-06 19:01:32721 PipelineStatistics stats = pipeline_.GetStatistics();
[email protected]4c51bc662011-02-16 02:03:16722 return stats.video_frames_decoded;
723}
724
[email protected]d82b18ae2011-03-23 21:28:59725unsigned WebMediaPlayerImpl::droppedFrameCount() const {
acolwellb4034942014-08-28 15:42:43726 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]4c51bc662011-02-16 02:03:16727
acolwell9e0840d2014-09-06 19:01:32728 PipelineStatistics stats = pipeline_.GetStatistics();
[email protected]dd061e12014-05-06 19:21:22729 return stats.video_frames_dropped;
[email protected]4c51bc662011-02-16 02:03:16730}
731
chakshu.a94326b72016-03-08 05:11:44732size_t WebMediaPlayerImpl::audioDecodedByteCount() const {
acolwellb4034942014-08-28 15:42:43733 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]4c51bc662011-02-16 02:03:16734
acolwell9e0840d2014-09-06 19:01:32735 PipelineStatistics stats = pipeline_.GetStatistics();
[email protected]4c51bc662011-02-16 02:03:16736 return stats.audio_bytes_decoded;
737}
738
chakshu.a94326b72016-03-08 05:11:44739size_t WebMediaPlayerImpl::videoDecodedByteCount() const {
acolwellb4034942014-08-28 15:42:43740 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]4c51bc662011-02-16 02:03:16741
acolwell9e0840d2014-09-06 19:01:32742 PipelineStatistics stats = pipeline_.GetStatistics();
[email protected]4c51bc662011-02-16 02:03:16743 return stats.video_bytes_decoded;
744}
745
[email protected]6523b242013-03-13 11:10:07746bool WebMediaPlayerImpl::copyVideoTextureToPlatformTexture(
[email protected]180ef242013-11-07 06:50:46747 blink::WebGraphicsContext3D* web_graphics_context,
zmo57d577a2015-10-30 18:28:59748 unsigned int texture,
749 unsigned int internal_format,
750 unsigned int type,
751 bool premultiply_alpha,
752 bool flip_y) {
[email protected]bfc05f22013-10-19 17:55:16753 TRACE_EVENT0("media", "WebMediaPlayerImpl:copyVideoTextureToPlatformTexture");
754
mcasasf1236fc22015-05-29 22:38:56755 scoped_refptr<VideoFrame> video_frame = GetCurrentFrameFromCompositor();
[email protected]dd061e12014-05-06 19:21:22756
mcasas265bdbf82015-06-12 18:44:07757 if (!video_frame.get() || !video_frame->HasTextures() ||
dcastagna31a65d432015-06-11 19:01:00758 media::VideoFrame::NumPlanes(video_frame->format()) != 1) {
[email protected]e56f88c72013-06-25 22:31:29759 return false;
dongseong.hwang0c4e9d82015-01-08 20:11:13760 }
[email protected]df41e252014-02-03 23:39:50761
dongseong.hwang0c4e9d82015-01-08 20:11:13762 // TODO(dshwang): need more elegant way to convert WebGraphicsContext3D to
763 // GLES2Interface.
764 gpu::gles2::GLES2Interface* gl =
765 static_cast<gpu_blink::WebGraphicsContext3DImpl*>(web_graphics_context)
766 ->GetGLInterface();
dcastagna31a65d432015-06-11 19:01:00767 SkCanvasVideoRenderer::CopyVideoFrameSingleTextureToGLTexture(
zmo57d577a2015-10-30 18:28:59768 gl, video_frame.get(), texture, internal_format, type, premultiply_alpha,
769 flip_y);
[email protected]e56f88c72013-06-25 22:31:29770 return true;
[email protected]6523b242013-03-13 11:10:07771}
772
[email protected]7bce1832014-01-09 00:01:22773void WebMediaPlayerImpl::setContentDecryptionModule(
[email protected]9ebc3b03f2014-08-13 04:01:23774 blink::WebContentDecryptionModule* cdm,
775 blink::WebContentDecryptionModuleResult result) {
acolwellb4034942014-08-28 15:42:43776 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]9ebc3b03f2014-08-13 04:01:23777
jrummell06f27072015-06-08 18:12:38778 // Once the CDM is set it can't be cleared as there may be frames being
779 // decrypted on other threads. So fail this request.
780 // http://crbug.com/462365#c7.
xhwang97de4202014-11-25 08:44:01781 if (!cdm) {
782 result.completeWithError(
jrummell06f27072015-06-08 18:12:38783 blink::WebContentDecryptionModuleExceptionInvalidStateError, 0,
784 "The existing MediaKeys object cannot be removed at this time.");
xhwang97de4202014-11-25 08:44:01785 return;
786 }
787
jrummell89e61d82015-07-23 20:03:34788 // Create a local copy of |result| to avoid problems with the callback
789 // getting passed to the media thread and causing |result| to be destructed
jrummell4acbec912016-02-27 02:45:03790 // on the wrong thread in some failure conditions. Blink should prevent
791 // multiple simultaneous calls.
792 DCHECK(!set_cdm_result_);
jrummell89e61d82015-07-23 20:03:34793 set_cdm_result_.reset(new blink::WebContentDecryptionModuleResult(result));
794
795 SetCdm(BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnCdmAttached),
xhwang9bd8c732015-04-13 23:27:53796 ToWebContentDecryptionModuleImpl(cdm)->GetCdmContext());
xhwang97de4202014-11-25 08:44:01797}
798
xhwange8c4181a2014-12-06 08:10:01799void WebMediaPlayerImpl::OnEncryptedMediaInitData(
jrummellcf78967c2015-04-03 05:03:58800 EmeInitDataType init_data_type,
Avi Drissman97785ea2015-12-19 01:11:31801 const std::vector<uint8_t>& init_data) {
jrummellcf78967c2015-04-03 05:03:58802 DCHECK(init_data_type != EmeInitDataType::UNKNOWN);
xhwangbab66f52014-12-02 23:49:50803
ddorwin301ccdb2016-02-25 02:39:17804 // TODO(xhwang): Update this UMA name. https://crbug.com/589251
xhwangbab66f52014-12-02 23:49:50805 UMA_HISTOGRAM_COUNTS("Media.EME.NeedKey", 1);
806
srirama.m26f864d02015-07-14 05:21:46807 encrypted_client_->encrypted(
davidbenb50f00c2015-12-01 00:01:50808 ConvertToWebInitDataType(init_data_type), init_data.data(),
srirama.m26f864d02015-07-14 05:21:46809 base::saturated_cast<unsigned int>(init_data.size()));
xhwangbab66f52014-12-02 23:49:50810}
811
servolk81e01e02016-03-05 03:29:15812void WebMediaPlayerImpl::OnFFmpegMediaTracksUpdated(
813 scoped_ptr<MediaTracks> tracks) {
814 // For MSE/chunk_demuxer case the media track updates are handled by
815 // WebSourceBufferImpl.
816 DCHECK(demuxer_.get());
817 DCHECK(!chunk_demuxer_);
818}
819
jrummell74fc4f942015-03-02 22:48:27820void WebMediaPlayerImpl::OnWaitingForDecryptionKey() {
srirama.m26f864d02015-07-14 05:21:46821 encrypted_client_->didBlockPlaybackWaitingForKey();
jrummell74fc4f942015-03-02 22:48:27822
823 // TODO(jrummell): didResumePlaybackBlockedForKey() should only be called
824 // when a key has been successfully added (e.g. OnSessionKeysChange() with
825 // |has_additional_usable_key| = true). http://crbug.com/461903
srirama.m26f864d02015-07-14 05:21:46826 encrypted_client_->didResumePlaybackBlockedForKey();
jrummell74fc4f942015-03-02 22:48:27827}
828
xhwang9bd8c732015-04-13 23:27:53829void WebMediaPlayerImpl::SetCdm(const CdmAttachedCB& cdm_attached_cb,
830 CdmContext* cdm_context) {
xhwang80739452016-01-13 00:48:00831 if (!cdm_context) {
832 cdm_attached_cb.Run(false);
833 return;
834 }
835
jrummell87a2db52015-05-05 22:27:18836 // If CDM initialization succeeded, tell the pipeline about it.
xhwang80739452016-01-13 00:48:00837 pipeline_.SetCdm(cdm_context, cdm_attached_cb);
xhwang97de4202014-11-25 08:44:01838}
839
jrummell89e61d82015-07-23 20:03:34840void WebMediaPlayerImpl::OnCdmAttached(bool success) {
xhwang97de4202014-11-25 08:44:01841 if (success) {
jrummell89e61d82015-07-23 20:03:34842 set_cdm_result_->complete();
843 set_cdm_result_.reset();
xhwang80739452016-01-13 00:48:00844 is_cdm_attached_ = true;
xhwang97de4202014-11-25 08:44:01845 return;
846 }
847
jrummell89e61d82015-07-23 20:03:34848 set_cdm_result_->completeWithError(
xhwang97de4202014-11-25 08:44:01849 blink::WebContentDecryptionModuleExceptionNotSupportedError, 0,
850 "Unable to set MediaKeys object");
jrummell89e61d82015-07-23 20:03:34851 set_cdm_result_.reset();
[email protected]9ebc3b03f2014-08-13 04:01:23852}
853
sandersd1c0bba02016-03-04 23:14:08854void WebMediaPlayerImpl::OnPipelineSeeked(bool time_updated) {
[email protected]5d11eff2011-09-15 00:06:06855 seeking_ = false;
wolenetz1b2ae7d2015-06-10 00:44:21856 seek_time_ = base::TimeDelta();
[email protected]10a64d92012-04-10 21:08:02857 if (paused_)
sandersd1c0bba02016-03-04 23:14:08858 paused_time_ = pipeline_.GetMediaTime();
859 if (time_updated)
860 should_notify_time_changed_ = true;
[email protected]8931c41a2009-07-07 17:31:49861}
862
sandersd1c0bba02016-03-04 23:14:08863void WebMediaPlayerImpl::OnPipelineSuspended() {
hubbed5f36882016-01-15 22:40:37864#if defined(OS_ANDROID)
865 if (isRemote()) {
866 scoped_refptr<VideoFrame> frame = cast_impl_.GetCastingBanner();
867 if (frame) {
868 compositor_->PaintFrameUsingOldRenderingPath(frame);
869 }
870 }
871#endif
872
dalecurtis3a7d38f42016-03-07 21:17:13873 memory_usage_reporting_timer_.Stop();
874 ReportMemoryUsage();
sandersd1c0bba02016-03-04 23:14:08875
876 if (pending_suspend_resume_cycle_) {
watkdee516f2016-02-18 02:22:19877 pending_suspend_resume_cycle_ = false;
sandersd1c0bba02016-03-04 23:14:08878 pipeline_controller_.Resume();
sandersd1e49fb62015-12-12 01:18:06879 return;
880 }
881}
882
sandersd1c0bba02016-03-04 23:14:08883void WebMediaPlayerImpl::OnPipelineResumed() {
dalecurtis0431cbf2016-03-12 01:19:43884 if (playback_rate_ > 0 && !paused_) {
sandersd1c0bba02016-03-04 23:14:08885 NotifyPlaybackStarted();
dalecurtis0431cbf2016-03-12 01:19:43886 } else if (!playback_rate_ || paused_ || ended_) {
887 // Resend our paused notification so the pipeline is considered for idle
888 // resource reclamation; duplicate pause notifications are ignored.
889 NotifyPlaybackPaused();
890 }
sandersd1c0bba02016-03-04 23:14:08891}
892
[email protected]6954fe12013-01-03 03:22:32893void WebMediaPlayerImpl::OnPipelineEnded() {
[email protected]2a06ca62014-06-04 13:59:52894 DVLOG(1) << __FUNCTION__;
acolwellb4034942014-08-28 15:42:43895 DCHECK(main_task_runner_->BelongsToCurrentThread());
scherkusd2c745b2014-09-04 05:03:40896
sandersd1c0bba02016-03-04 23:14:08897 // Ignore state changes until we've completed all outstanding operations.
898 if (!pipeline_controller_.IsStable())
scherkusd2c745b2014-09-04 05:03:40899 return;
900
901 ended_ = true;
[email protected]ce70c982013-12-20 17:04:32902 client_->timeChanged();
[email protected]576537842009-08-12 23:52:05903}
904
[email protected]a9590c22011-03-16 16:57:02905void WebMediaPlayerImpl::OnPipelineError(PipelineStatus error) {
hubbed82bed52015-12-15 23:07:16906 DVLOG(1) << __FUNCTION__;
acolwellb4034942014-08-28 15:42:43907 DCHECK(main_task_runner_->BelongsToCurrentThread());
acolwell9e0840d2014-09-06 19:01:32908 DCHECK_NE(error, PIPELINE_OK);
[email protected]a8e2cb82012-08-17 00:02:39909
dalecurtis2ff781da2016-03-03 01:52:13910 if (suppress_destruction_errors_)
911 return;
912
913 media_log_->AddEvent(media_log_->CreatePipelineErrorEvent(error));
914
[email protected]a8e2cb82012-08-17 00:02:39915 if (ready_state_ == WebMediaPlayer::ReadyStateHaveNothing) {
916 // Any error that occurs before reaching ReadyStateHaveMetadata should
917 // be considered a format error.
918 SetNetworkState(WebMediaPlayer::NetworkStateFormatError);
[email protected]a8e2cb82012-08-17 00:02:39919 return;
920 }
921
[email protected]be57ee52013-05-28 22:27:27922 SetNetworkState(PipelineErrorToNetworkState(error));
[email protected]db190487d2009-07-30 18:51:52923}
924
[email protected]b8877772014-03-26 20:17:15925void WebMediaPlayerImpl::OnPipelineMetadata(
acolwell9e0840d2014-09-06 19:01:32926 PipelineMetadata metadata) {
[email protected]2a06ca62014-06-04 13:59:52927 DVLOG(1) << __FUNCTION__;
[email protected]a8e2cb82012-08-17 00:02:39928
[email protected]b8877772014-03-26 20:17:15929 pipeline_metadata_ = metadata;
[email protected]739847c02014-01-16 00:12:25930
dalecurtis849cf4b22015-03-27 18:35:45931 UMA_HISTOGRAM_ENUMERATION("Media.VideoRotation", metadata.video_rotation,
acolwell9e0840d2014-09-06 19:01:32932 VIDEO_ROTATION_MAX + 1);
[email protected]b8877772014-03-26 20:17:15933 SetReadyState(WebMediaPlayer::ReadyStateHaveMetadata);
[email protected]21c3f7502013-03-23 03:29:51934
[email protected]b8877772014-03-26 20:17:15935 if (hasVideo()) {
936 DCHECK(!video_weblayer_);
loyso0940d412016-03-14 01:30:31937 scoped_refptr<cc::VideoLayer> layer =
938 cc::VideoLayer::Create(compositor_, pipeline_metadata_.video_rotation);
[email protected]f78c3e82014-08-08 01:24:47939
acolwell9e0840d2014-09-06 19:01:32940 if (pipeline_metadata_.video_rotation == VIDEO_ROTATION_90 ||
941 pipeline_metadata_.video_rotation == VIDEO_ROTATION_270) {
[email protected]f78c3e82014-08-08 01:24:47942 gfx::Size size = pipeline_metadata_.natural_size;
943 pipeline_metadata_.natural_size = gfx::Size(size.height(), size.width());
944 }
945
[email protected]38564622014-08-19 02:47:18946 video_weblayer_.reset(new cc_blink::WebLayerImpl(layer));
jbauman952274d2015-09-10 23:23:36947 video_weblayer_->layer()->SetContentsOpaque(opaque_);
948 video_weblayer_->SetContentsOpaqueIsFixed(true);
[email protected]a7c4f582014-04-16 18:44:49949 client_->setWebLayer(video_weblayer_.get());
sandersdb96662f2016-01-09 00:46:06950
951 // If there is video and the frame is hidden, then it may be time to suspend
952 // playback.
953 if (delegate_ && delegate_->IsHidden())
dalecurtis0431cbf2016-03-12 01:19:43954 OnHidden();
[email protected]a8e2cb82012-08-17 00:02:39955 }
dalecurtis8e4dc682016-03-15 02:30:30956
957 // Tell the delegate we can now be safely suspended due to inactivity if a
958 // subsequent play event does not occur.
959 if (paused_)
960 NotifyPlaybackPaused();
[email protected]a8e2cb82012-08-17 00:02:39961}
962
[email protected]ba7d5f92014-06-24 05:37:40963void WebMediaPlayerImpl::OnPipelineBufferingStateChanged(
acolwell9e0840d2014-09-06 19:01:32964 BufferingState buffering_state) {
[email protected]ba7d5f92014-06-24 05:37:40965 DVLOG(1) << __FUNCTION__ << "(" << buffering_state << ")";
[email protected]b8877772014-03-26 20:17:15966
sandersd1c0bba02016-03-04 23:14:08967 // Ignore buffering state changes until we've completed all outstanding
968 // operations.
969 if (!pipeline_controller_.IsStable())
[email protected]ba7d5f92014-06-24 05:37:40970 return;
[email protected]b8877772014-03-26 20:17:15971
[email protected]ba7d5f92014-06-24 05:37:40972 // TODO(scherkus): Handle other buffering states when Pipeline starts using
973 // them and translate them ready state changes http://crbug.com/144683
acolwell9e0840d2014-09-06 19:01:32974 DCHECK_EQ(buffering_state, BUFFERING_HAVE_ENOUGH);
[email protected]ba7d5f92014-06-24 05:37:40975 SetReadyState(WebMediaPlayer::ReadyStateHaveEnoughData);
976
dalecurtis849cf4b22015-03-27 18:35:45977 // Let the DataSource know we have enough data. It may use this information to
978 // release unused network connections.
979 if (data_source_)
980 data_source_->OnBufferingHaveEnough();
981
[email protected]ba7d5f92014-06-24 05:37:40982 // Blink expects a timeChanged() in response to a seek().
983 if (should_notify_time_changed_)
984 client_->timeChanged();
dalecurtis0f0097a2015-12-01 17:40:47985
986 // Once we have enough, start reporting the total memory usage. We'll also
987 // report once playback starts.
988 ReportMemoryUsage();
[email protected]b8877772014-03-26 20:17:15989}
990
[email protected]ef8394c2013-08-21 20:26:30991void WebMediaPlayerImpl::OnDemuxerOpened() {
acolwellb4034942014-08-28 15:42:43992 DCHECK(main_task_runner_->BelongsToCurrentThread());
wolenetz1fb319d2015-07-14 17:49:04993 client_->mediaSourceOpened(
994 new WebMediaSourceImpl(chunk_demuxer_, media_log_));
[email protected]81bb3322011-07-21 15:55:50995}
996
[email protected]8a561062013-11-22 01:19:31997void WebMediaPlayerImpl::OnAddTextTrack(
acolwell9e0840d2014-09-06 19:01:32998 const TextTrackConfig& config,
999 const AddTextTrackDoneCB& done_cb) {
acolwellb4034942014-08-28 15:42:431000 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]71537722013-05-23 06:47:531001
[email protected]8a561062013-11-22 01:19:311002 const WebInbandTextTrackImpl::Kind web_kind =
1003 static_cast<WebInbandTextTrackImpl::Kind>(config.kind());
1004 const blink::WebString web_label =
1005 blink::WebString::fromUTF8(config.label());
1006 const blink::WebString web_language =
1007 blink::WebString::fromUTF8(config.language());
[email protected]427ff102013-11-26 23:45:401008 const blink::WebString web_id =
1009 blink::WebString::fromUTF8(config.id());
[email protected]71537722013-05-23 06:47:531010
[email protected]8a561062013-11-22 01:19:311011 scoped_ptr<WebInbandTextTrackImpl> web_inband_text_track(
henriks9cce5fa2014-12-12 09:35:301012 new WebInbandTextTrackImpl(web_kind, web_label, web_language, web_id));
[email protected]8a561062013-11-22 01:19:311013
acolwell9e0840d2014-09-06 19:01:321014 scoped_ptr<TextTrack> text_track(new TextTrackImpl(
dcheng652f5ff2015-12-27 08:54:001015 main_task_runner_, client_, std::move(web_inband_text_track)));
[email protected]8a561062013-11-22 01:19:311016
dcheng652f5ff2015-12-27 08:54:001017 done_cb.Run(std::move(text_track));
[email protected]71537722013-05-23 06:47:531018}
1019
dalecurtis0431cbf2016-03-12 01:19:431020void WebMediaPlayerImpl::OnHidden() {
sandersd1e49fb62015-12-12 01:18:061021 DCHECK(main_task_runner_->BelongsToCurrentThread());
dalecurtis0431cbf2016-03-12 01:19:431022 if (!IsSuspendUponHiddenEnabled())
sandersd1e49fb62015-12-12 01:18:061023 return;
sandersd1e49fb62015-12-12 01:18:061024
dalecurtis0431cbf2016-03-12 01:19:431025#if defined(OS_ANDROID) // WMPI_CAST
hubbed5f36882016-01-15 22:40:371026 // If we're remote, the pipeline should already be suspended.
1027 if (isRemote())
1028 return;
1029#endif
1030
dalecurtis0431cbf2016-03-12 01:19:431031 // Don't suspend players which only have audio and have not completed
1032 // playback. The user can still control these players via the MediaSession UI.
1033 // If the player has never started playback, OnSuspendRequested() will handle
1034 // release of any idle resources.
1035 if (!hasVideo() && !paused_ && !ended_)
1036 return;
1037
1038 pipeline_controller_.Suspend();
1039 if (delegate_)
1040 delegate_->PlayerGone(delegate_id_);
sandersd1e49fb62015-12-12 01:18:061041}
1042
1043void WebMediaPlayerImpl::OnShown() {
1044 DCHECK(main_task_runner_->BelongsToCurrentThread());
dalecurtis0431cbf2016-03-12 01:19:431045 if (!IsSuspendUponHiddenEnabled())
sandersd1e49fb62015-12-12 01:18:061046 return;
sandersd1e49fb62015-12-12 01:18:061047
dalecurtis0431cbf2016-03-12 01:19:431048#if defined(OS_ANDROID) // WMPI_CAST
hubbed5f36882016-01-15 22:40:371049 // If we're remote, the pipeline should stay suspended.
1050 if (isRemote())
1051 return;
1052#endif
1053
dalecurtis5bbc487e2016-02-27 04:15:051054 if (!ended_ && !paused_)
sandersd1c0bba02016-03-04 23:14:081055 pipeline_controller_.Resume();
sandersd1e49fb62015-12-12 01:18:061056}
1057
dalecurtis0431cbf2016-03-12 01:19:431058void WebMediaPlayerImpl::OnSuspendRequested(bool must_suspend) {
1059 DCHECK(main_task_runner_->BelongsToCurrentThread());
1060
1061#if defined(OS_ANDROID) // WMPI_CAST
1062 // If we're remote, the pipeline should already be suspended.
1063 if (isRemote())
1064 return;
1065#endif
1066
1067 // Suspend should never be requested unless required or we're already in an
1068 // idle state (paused or ended).
1069 DCHECK(must_suspend || paused_ || ended_);
1070
1071 // Always suspend, but only notify the delegate if we must; this allows any
1072 // exposed UI for player controls to continue to function even though the
1073 // player has now been suspended.
1074 pipeline_controller_.Suspend();
1075 if (must_suspend && delegate_)
1076 delegate_->PlayerGone(delegate_id_);
1077}
1078
dalecurtisbb3eaac2016-01-27 21:10:251079void WebMediaPlayerImpl::OnPlay() {
1080 play();
1081 client_->playbackStateChanged();
1082}
1083
1084void WebMediaPlayerImpl::OnPause() {
1085 pause();
1086 client_->playbackStateChanged();
1087}
1088
1089void WebMediaPlayerImpl::OnVolumeMultiplierUpdate(double multiplier) {
1090 volume_multiplier_ = multiplier;
1091 setVolume(volume_);
1092}
1093
watkdee516f2016-02-18 02:22:191094void WebMediaPlayerImpl::ScheduleRestart() {
sandersd1c0bba02016-03-04 23:14:081095 if (!pipeline_controller_.IsSuspended()) {
watkdee516f2016-02-18 02:22:191096 pending_suspend_resume_cycle_ = true;
sandersd1c0bba02016-03-04 23:14:081097 pipeline_controller_.Suspend();
watkdee516f2016-02-18 02:22:191098 }
1099}
1100
hubbed5f36882016-01-15 22:40:371101#if defined(OS_ANDROID) // WMPI_CAST
hubbed5f36882016-01-15 22:40:371102bool WebMediaPlayerImpl::isRemote() const {
1103 return cast_impl_.isRemote();
1104}
1105
1106void WebMediaPlayerImpl::SetMediaPlayerManager(
1107 RendererMediaPlayerManagerInterface* media_player_manager) {
1108 cast_impl_.SetMediaPlayerManager(media_player_manager);
1109}
1110
1111void WebMediaPlayerImpl::requestRemotePlayback() {
1112 cast_impl_.requestRemotePlayback();
1113}
1114
1115void WebMediaPlayerImpl::requestRemotePlaybackControl() {
1116 cast_impl_.requestRemotePlaybackControl();
1117}
1118
1119void WebMediaPlayerImpl::OnRemotePlaybackEnded() {
1120 DVLOG(1) << __FUNCTION__;
1121 DCHECK(main_task_runner_->BelongsToCurrentThread());
1122
1123 ended_ = true;
1124 client_->timeChanged();
1125}
1126
1127void WebMediaPlayerImpl::OnDisconnectedFromRemoteDevice(double t) {
sandersd1c0bba02016-03-04 23:14:081128 DoSeek(base::TimeDelta::FromSecondsD(t), false);
1129 if (delegate_ && !delegate_->IsHidden())
1130 pipeline_controller_.Resume();
hubbed5f36882016-01-15 22:40:371131
hubbed5f36882016-01-15 22:40:371132 // We already told the delegate we're paused when remoting started.
1133 client_->playbackStateChanged();
1134 client_->disconnectedFromRemoteDevice();
1135}
1136
1137void WebMediaPlayerImpl::SuspendForRemote() {
sandersd1c0bba02016-03-04 23:14:081138 if (!pipeline_controller_.IsSuspended()) {
1139 pipeline_controller_.Suspend();
1140 } else {
1141 // TODO(sandersd): If PipelineController::Suspend() called |suspended_cb|
1142 // when already suspended, we wouldn't need this case.
hubbed5f36882016-01-15 22:40:371143 scoped_refptr<VideoFrame> frame = cast_impl_.GetCastingBanner();
1144 if (frame) {
1145 compositor_->PaintFrameUsingOldRenderingPath(frame);
1146 }
1147 }
hubbed5f36882016-01-15 22:40:371148}
1149
1150gfx::Size WebMediaPlayerImpl::GetCanvasSize() const {
1151 if (!video_weblayer_)
1152 return pipeline_metadata_.natural_size;
1153
1154 return video_weblayer_->bounds();
1155}
1156
1157void WebMediaPlayerImpl::SetDeviceScaleFactor(float scale_factor) {
1158 cast_impl_.SetDeviceScaleFactor(scale_factor);
1159}
1160#endif // defined(OS_ANDROID) // WMPI_CAST
1161
[email protected]fee8a902014-06-03 13:43:361162void WebMediaPlayerImpl::DataSourceInitialized(bool success) {
hubbed82bed52015-12-15 23:07:161163 DVLOG(1) << __FUNCTION__;
acolwellb4034942014-08-28 15:42:431164 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]a9415292012-01-19 19:55:201165
[email protected]d250190da3b2012-07-23 22:57:301166 if (!success) {
[email protected]ef405f66b2012-04-18 02:39:551167 SetNetworkState(WebMediaPlayer::NetworkStateFormatError);
[email protected]a9415292012-01-19 19:55:201168 return;
1169 }
1170
[email protected]ef8394c2013-08-21 20:26:301171 StartPipeline();
[email protected]a9415292012-01-19 19:55:201172}
1173
[email protected]122f40252012-06-12 05:01:561174void WebMediaPlayerImpl::NotifyDownloading(bool is_downloading) {
hubbed82bed52015-12-15 23:07:161175 DVLOG(1) << __FUNCTION__;
[email protected]122f40252012-06-12 05:01:561176 if (!is_downloading && network_state_ == WebMediaPlayer::NetworkStateLoading)
1177 SetNetworkState(WebMediaPlayer::NetworkStateIdle);
1178 else if (is_downloading && network_state_ == WebMediaPlayer::NetworkStateIdle)
1179 SetNetworkState(WebMediaPlayer::NetworkStateLoading);
1180 media_log_->AddEvent(
1181 media_log_->CreateBooleanEvent(
acolwell9e0840d2014-09-06 19:01:321182 MediaLogEvent::NETWORK_ACTIVITY_SET,
[email protected]122f40252012-06-12 05:01:561183 "is_downloading_data", is_downloading));
1184}
1185
watkdee516f2016-02-18 02:22:191186// TODO(watk): Move this state management out of WMPI.
1187void WebMediaPlayerImpl::OnSurfaceRequested(
1188 const SurfaceCreatedCB& surface_created_cb) {
1189 DCHECK(main_task_runner_->BelongsToCurrentThread());
1190 DCHECK(surface_manager_);
1191
1192 // A null callback indicates that the decoder is going away.
1193 if (surface_created_cb.is_null()) {
1194 decoder_requires_restart_for_fullscreen_ = false;
1195 return;
1196 }
1197
1198 // If we're getting a surface request it means GVD is initializing, so until
1199 // we get a null surface request, GVD is the active decoder. While that's the
1200 // case we should restart the pipeline on fullscreen transitions so that when
1201 // we create a new GVD it will request a surface again and get the right kind
1202 // of surface for the fullscreen state.
1203 // TODO(watk): Don't require a pipeline restart to switch surfaces for
1204 // cases where it isn't necessary.
1205 decoder_requires_restart_for_fullscreen_ = true;
1206 if (fullscreen_) {
1207 surface_manager_->CreateFullscreenSurface(pipeline_metadata_.natural_size,
1208 surface_created_cb);
1209 } else {
1210 // Tell the decoder to create its own surface.
1211 surface_created_cb.Run(SurfaceManager::kNoSurfaceID);
1212 }
1213}
1214
sandersd1e49fb62015-12-12 01:18:061215scoped_ptr<Renderer> WebMediaPlayerImpl::CreateRenderer() {
watkdee516f2016-02-18 02:22:191216 RequestSurfaceCB request_surface_cb;
1217#if defined(OS_ANDROID)
1218 request_surface_cb =
1219 BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnSurfaceRequested);
1220#endif
sandersd1e49fb62015-12-12 01:18:061221 return renderer_factory_->CreateRenderer(
1222 media_task_runner_, worker_task_runner_, audio_source_provider_.get(),
watkdee516f2016-02-18 02:22:191223 compositor_, request_surface_cb);
sandersd1e49fb62015-12-12 01:18:061224}
1225
[email protected]ef8394c2013-08-21 20:26:301226void WebMediaPlayerImpl::StartPipeline() {
acolwellb4034942014-08-28 15:42:431227 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]ddbc6ff2013-04-19 15:28:331228
xhwange8c4181a2014-12-06 08:10:011229 Demuxer::EncryptedMediaInitDataCB encrypted_media_init_data_cb =
1230 BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnEncryptedMediaInitData);
[email protected]2b57e2e2014-05-09 11:07:251231
[email protected]ddbc6ff2013-04-19 15:28:331232 // Figure out which demuxer to use.
[email protected]ef8394c2013-08-21 20:26:301233 if (load_type_ != LoadTypeMediaSource) {
[email protected]ddbc6ff2013-04-19 15:28:331234 DCHECK(!chunk_demuxer_);
[email protected]f5443ef72013-04-22 04:03:381235 DCHECK(data_source_);
1236
j.isorcef6778e652015-11-16 17:14:251237#if !defined(MEDIA_DISABLE_FFMPEG)
servolk81e01e02016-03-05 03:29:151238 Demuxer::MediaTracksUpdatedCB media_tracks_updated_cb =
1239 base::Bind(&WebMediaPlayerImpl::OnFFmpegMediaTracksUpdated,
1240 base::Unretained(this));
1241
xhwange8c4181a2014-12-06 08:10:011242 demuxer_.reset(new FFmpegDemuxer(media_task_runner_, data_source_.get(),
servolk81e01e02016-03-05 03:29:151243 encrypted_media_init_data_cb,
1244 media_tracks_updated_cb, media_log_));
j.isorcef6778e652015-11-16 17:14:251245#else
1246 OnPipelineError(PipelineStatus::DEMUXER_ERROR_COULD_NOT_OPEN);
1247 return;
1248#endif
[email protected]ddbc6ff2013-04-19 15:28:331249 } else {
[email protected]f5443ef72013-04-22 04:03:381250 DCHECK(!chunk_demuxer_);
1251 DCHECK(!data_source_);
1252
acolwell9e0840d2014-09-06 19:01:321253 chunk_demuxer_ = new ChunkDemuxer(
[email protected]ef8394c2013-08-21 20:26:301254 BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnDemuxerOpened),
wolenetz1fb319d2015-07-14 17:49:041255 encrypted_media_init_data_cb, media_log_, true);
[email protected]f5443ef72013-04-22 04:03:381256 demuxer_.reset(chunk_demuxer_);
[email protected]ddbc6ff2013-04-19 15:28:331257 }
1258
sandersdb5e21462016-03-09 01:49:071259 // TODO(sandersd): FileSystem objects may also be non-static, but due to our
1260 // caching layer such situations are broken already. http://crbug.com/593159
1261 bool is_static = !chunk_demuxer_;
1262
[email protected]f5443ef72013-04-22 04:03:381263 // ... and we're ready to go!
[email protected]d228aeec2014-06-20 19:16:491264 seeking_ = true;
xhwangf94a634d2014-10-22 22:07:271265
sandersd1e49fb62015-12-12 01:18:061266 // TODO(sandersd): On Android, defer Start() if the tab is not visible.
sandersd1c0bba02016-03-04 23:14:081267 bool is_streaming = (data_source_ && data_source_->IsStreaming());
1268 pipeline_controller_.Start(
sandersdb5e21462016-03-09 01:49:071269 demuxer_.get(), is_streaming, is_static,
[email protected]f5443ef72013-04-22 04:03:381270 BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnPipelineEnded),
[email protected]b8877772014-03-26 20:17:151271 BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnPipelineMetadata),
[email protected]ba7d5f92014-06-24 05:37:401272 BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnPipelineBufferingStateChanged),
xhwang59805902014-08-29 01:44:151273 BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnDurationChanged),
jrummell74fc4f942015-03-02 22:48:271274 BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnAddTextTrack),
1275 BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnWaitingForDecryptionKey));
[email protected]f5443ef72013-04-22 04:03:381276}
1277
1278void WebMediaPlayerImpl::SetNetworkState(WebMediaPlayer::NetworkState state) {
[email protected]2a06ca62014-06-04 13:59:521279 DVLOG(1) << __FUNCTION__ << "(" << state << ")";
acolwellb4034942014-08-28 15:42:431280 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]f5443ef72013-04-22 04:03:381281 network_state_ = state;
1282 // Always notify to ensure client has the latest value.
[email protected]ce70c982013-12-20 17:04:321283 client_->networkStateChanged();
[email protected]f5443ef72013-04-22 04:03:381284}
1285
1286void WebMediaPlayerImpl::SetReadyState(WebMediaPlayer::ReadyState state) {
[email protected]2a06ca62014-06-04 13:59:521287 DVLOG(1) << __FUNCTION__ << "(" << state << ")";
acolwellb4034942014-08-28 15:42:431288 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]f5443ef72013-04-22 04:03:381289
[email protected]fee8a902014-06-03 13:43:361290 if (state == WebMediaPlayer::ReadyStateHaveEnoughData && data_source_ &&
1291 data_source_->assume_fully_buffered() &&
[email protected]f5443ef72013-04-22 04:03:381292 network_state_ == WebMediaPlayer::NetworkStateLoading)
1293 SetNetworkState(WebMediaPlayer::NetworkStateLoaded);
1294
1295 ready_state_ = state;
1296 // Always notify to ensure client has the latest value.
[email protected]ce70c982013-12-20 17:04:321297 client_->readyStateChanged();
[email protected]f5443ef72013-04-22 04:03:381298}
1299
Dana Jansens71331252016-03-09 20:57:221300blink::WebAudioSourceProvider* WebMediaPlayerImpl::getAudioSourceProvider() {
[email protected]ff875be52013-06-02 23:47:381301 return audio_source_provider_.get();
[email protected]f5443ef72013-04-22 04:03:381302}
1303
[email protected]f5443ef72013-04-22 04:03:381304double WebMediaPlayerImpl::GetPipelineDuration() const {
[email protected]f6af7592014-02-28 10:09:111305 base::TimeDelta duration = pipeline_.GetMediaDuration();
[email protected]f5443ef72013-04-22 04:03:381306
1307 // Return positive infinity if the resource is unbounded.
1308 // http://www.whatwg.org/specs/web-apps/current-work/multipage/video.html#dom-media-duration
acolwell9e0840d2014-09-06 19:01:321309 if (duration == kInfiniteDuration())
[email protected]f5443ef72013-04-22 04:03:381310 return std::numeric_limits<double>::infinity();
1311
1312 return duration.InSecondsF();
1313}
1314
[email protected]75e145a2014-04-15 17:44:321315void WebMediaPlayerImpl::OnDurationChanged() {
[email protected]f5443ef72013-04-22 04:03:381316 if (ready_state_ == WebMediaPlayer::ReadyStateHaveNothing)
1317 return;
1318
[email protected]ce70c982013-12-20 17:04:321319 client_->durationChanged();
[email protected]f5443ef72013-04-22 04:03:381320}
1321
[email protected]75e145a2014-04-15 17:44:321322void WebMediaPlayerImpl::OnNaturalSizeChanged(gfx::Size size) {
acolwellb4034942014-08-28 15:42:431323 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]739847c02014-01-16 00:12:251324 DCHECK_NE(ready_state_, WebMediaPlayer::ReadyStateHaveNothing);
1325 TRACE_EVENT0("media", "WebMediaPlayerImpl::OnNaturalSizeChanged");
1326
1327 media_log_->AddEvent(
1328 media_log_->CreateVideoSizeSetEvent(size.width(), size.height()));
[email protected]739847c02014-01-16 00:12:251329
watkdee516f2016-02-18 02:22:191330 if (fullscreen_ && surface_manager_ &&
1331 pipeline_metadata_.natural_size != size) {
1332 surface_manager_->NaturalSizeChanged(size);
1333 }
1334
1335 pipeline_metadata_.natural_size = size;
[email protected]739847c02014-01-16 00:12:251336 client_->sizeChanged();
1337}
1338
[email protected]75e145a2014-04-15 17:44:321339void WebMediaPlayerImpl::OnOpacityChanged(bool opaque) {
acolwellb4034942014-08-28 15:42:431340 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]75e145a2014-04-15 17:44:321341 DCHECK_NE(ready_state_, WebMediaPlayer::ReadyStateHaveNothing);
1342
1343 opaque_ = opaque;
jbauman952274d2015-09-10 23:23:361344 // Modify content opaqueness of cc::Layer directly so that
1345 // SetContentsOpaqueIsFixed is ignored.
[email protected]75e145a2014-04-15 17:44:321346 if (video_weblayer_)
jbauman952274d2015-09-10 23:23:361347 video_weblayer_->layer()->SetContentsOpaque(opaque_);
[email protected]75e145a2014-04-15 17:44:321348}
1349
[email protected]dd061e12014-05-06 19:21:221350static void GetCurrentFrameAndSignal(
1351 VideoFrameCompositor* compositor,
acolwell9e0840d2014-09-06 19:01:321352 scoped_refptr<VideoFrame>* video_frame_out,
[email protected]dd061e12014-05-06 19:21:221353 base::WaitableEvent* event) {
1354 TRACE_EVENT0("media", "GetCurrentFrameAndSignal");
dalecurtis44ce4de2015-05-11 18:42:071355 *video_frame_out = compositor->GetCurrentFrameAndUpdateIfStale();
[email protected]dd061e12014-05-06 19:21:221356 event->Signal();
1357}
1358
acolwell9e0840d2014-09-06 19:01:321359scoped_refptr<VideoFrame>
[email protected]dd061e12014-05-06 19:21:221360WebMediaPlayerImpl::GetCurrentFrameFromCompositor() {
1361 TRACE_EVENT0("media", "WebMediaPlayerImpl::GetCurrentFrameFromCompositor");
1362 if (compositor_task_runner_->BelongsToCurrentThread())
dalecurtis44ce4de2015-05-11 18:42:071363 return compositor_->GetCurrentFrameAndUpdateIfStale();
[email protected]dd061e12014-05-06 19:21:221364
1365 // Use a posted task and waitable event instead of a lock otherwise
1366 // WebGL/Canvas can see different content than what the compositor is seeing.
acolwell9e0840d2014-09-06 19:01:321367 scoped_refptr<VideoFrame> video_frame;
[email protected]dd061e12014-05-06 19:21:221368 base::WaitableEvent event(false, false);
1369 compositor_task_runner_->PostTask(FROM_HERE,
1370 base::Bind(&GetCurrentFrameAndSignal,
1371 base::Unretained(compositor_),
1372 &video_frame,
1373 &event));
1374 event.Wait();
1375 return video_frame;
1376}
1377
dalecurtis0f0097a2015-12-01 17:40:471378void WebMediaPlayerImpl::NotifyPlaybackStarted() {
hubbed5f36882016-01-15 22:40:371379#if defined(OS_ANDROID) // WMPI_CAST
dalecurtis5bbc487e2016-02-27 04:15:051380 // We do not tell our delegates about remote playback, because that would
hubbed5f36882016-01-15 22:40:371381 // keep the device awake, which is not what we want.
1382 if (isRemote())
1383 return;
1384#endif
dalecurtis5bbc487e2016-02-27 04:15:051385
sandersd1c0bba02016-03-04 23:14:081386 // NotifyPlaybackStarted() may be called by interactions while suspended,
1387 // (play/pause in particular). Those actions won't have any effect until the
1388 // pipeline is resumed.
1389 // TODO(dalecurtis): Should these be dropped at the call sites instead?
1390 // Alternatively, rename this method to include Maybe or Changed, and handle
1391 // multiple calls safely.
1392 if (pipeline_controller_.IsSuspended())
dalecurtis5bbc487e2016-02-27 04:15:051393 return;
1394
dalecurtisbb3eaac2016-01-27 21:10:251395 if (delegate_) {
1396 delegate_->DidPlay(delegate_id_, hasVideo(), hasAudio(), false,
1397 pipeline_.GetMediaDuration());
1398 }
dalecurtis0f0097a2015-12-01 17:40:471399 if (!memory_usage_reporting_timer_.IsRunning()) {
1400 memory_usage_reporting_timer_.Start(FROM_HERE,
1401 base::TimeDelta::FromSeconds(2), this,
1402 &WebMediaPlayerImpl::ReportMemoryUsage);
1403 }
1404}
1405
1406void WebMediaPlayerImpl::NotifyPlaybackPaused() {
hubbed5f36882016-01-15 22:40:371407#if defined(OS_ANDROID) // WMPI_CAST
1408 if (isRemote())
1409 return;
1410#endif
sandersd1c0bba02016-03-04 23:14:081411
1412 // Same as above, NotifyPlaybackPaused() may be called by interactions while
1413 // suspended, but those actions won't have any effect until the pipeline is
1414 // resumed.
1415 if (pipeline_controller_.IsSuspended())
1416 return;
1417
1418 if (delegate_)
dalecurtisbb3eaac2016-01-27 21:10:251419 delegate_->DidPause(delegate_id_, ended_);
dalecurtis0f0097a2015-12-01 17:40:471420 memory_usage_reporting_timer_.Stop();
1421 ReportMemoryUsage();
1422}
1423
dalecurtis83266c72015-10-29 18:43:201424void WebMediaPlayerImpl::ReportMemoryUsage() {
1425 DCHECK(main_task_runner_->BelongsToCurrentThread());
1426
wdzierzanowskifd4cd91c52015-12-02 23:50:201427 // About base::Unretained() usage below: We destroy |demuxer_| on the main
1428 // thread. Before that, however, ~WebMediaPlayerImpl() posts a task to the
1429 // media thread and waits for it to finish. Hence, the GetMemoryUsage() task
1430 // posted here must finish earlier.
1431
1432 if (demuxer_) {
1433 base::PostTaskAndReplyWithResult(
1434 media_task_runner_.get(), FROM_HERE,
1435 base::Bind(&Demuxer::GetMemoryUsage, base::Unretained(demuxer_.get())),
1436 base::Bind(&WebMediaPlayerImpl::FinishMemoryUsageReport, AsWeakPtr()));
1437 } else {
1438 FinishMemoryUsageReport(0);
1439 }
1440}
1441
1442void WebMediaPlayerImpl::FinishMemoryUsageReport(int64_t demuxer_memory_usage) {
1443 DCHECK(main_task_runner_->BelongsToCurrentThread());
1444
dalecurtis83266c72015-10-29 18:43:201445 const PipelineStatistics stats = pipeline_.GetStatistics();
1446 const int64_t current_memory_usage =
1447 stats.audio_memory_usage + stats.video_memory_usage +
1448 (data_source_ ? data_source_->GetMemoryUsage() : 0) +
wdzierzanowskifd4cd91c52015-12-02 23:50:201449 demuxer_memory_usage;
dalecurtis83266c72015-10-29 18:43:201450
dalecurtis3a7d38f42016-03-07 21:17:131451 // Note, this isn't entirely accurate, there may be VideoFrames held by the
1452 // compositor or other resources that we're unaware of.
1453
dalecurtis83266c72015-10-29 18:43:201454 DVLOG(2) << "Memory Usage -- Audio: " << stats.audio_memory_usage
1455 << ", Video: " << stats.video_memory_usage << ", DataSource: "
1456 << (data_source_ ? data_source_->GetMemoryUsage() : 0)
wdzierzanowskifd4cd91c52015-12-02 23:50:201457 << ", Demuxer: " << demuxer_memory_usage;
dalecurtis83266c72015-10-29 18:43:201458
1459 const int64_t delta = current_memory_usage - last_reported_memory_usage_;
1460 last_reported_memory_usage_ = current_memory_usage;
1461 adjust_allocated_memory_cb_.Run(delta);
1462}
1463
dalecurtis0431cbf2016-03-12 01:19:431464bool WebMediaPlayerImpl::IsAutomaticResumeAllowed() {
1465#if defined(OS_ANDROID)
1466 return !hasVideo() || (delegate_ && !delegate_->IsHidden());
1467#else
1468 // On non-Android platforms Resume() is always allowed.
1469 return true;
1470#endif
1471}
1472
acolwell9e0840d2014-09-06 19:01:321473} // namespace media