blob: 3c7ee12e6e75e12e6c4b362c3747c8cc6521d14c [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"
dalecurtis6e3901e2016-03-16 20:51:0820#include "base/debug/dump_without_crashing.h"
[email protected]b0b258f2011-11-08 00:34:2321#include "base/metrics/histogram.h"
dalecurtis6e3901e2016-03-16 20:51:0822#include "base/rand_util.h"
acolwellb4034942014-08-28 15:42:4323#include "base/single_thread_task_runner.h"
[email protected]cf02541b2012-04-11 08:02:1724#include "base/synchronization/waitable_event.h"
wdzierzanowskifd4cd91c52015-12-02 23:50:2025#include "base/task_runner_util.h"
anujk.sharma2fa37a02015-04-30 05:51:3226#include "base/thread_task_runner_handle.h"
ssid9525f4672015-01-28 12:13:1527#include "base/trace_event/trace_event.h"
sandersd1e49fb62015-12-12 01:18:0628#include "build/build_config.h"
[email protected]38564622014-08-19 02:47:1829#include "cc/blink/web_layer_impl.h"
[email protected]21c3f7502013-03-23 03:29:5130#include "cc/layers/video_layer.h"
dongseong.hwang0c4e9d82015-01-08 20:11:1331#include "gpu/blink/webgraphicscontext3d_impl.h"
[email protected]e4fc09e2012-04-06 03:17:4432#include "media/audio/null_audio_sink.h"
[email protected]2eccbed2014-01-10 05:15:5333#include "media/base/bind_to_current_loop.h"
xhwang0ad11e512014-11-25 23:43:0934#include "media/base/cdm_context.h"
[email protected]32da1002010-03-03 21:57:3535#include "media/base/limits.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"
[email protected]8a561062013-11-22 01:19:3138#include "media/base/text_renderer.h"
watk9f9dfdc92015-09-04 21:33:2939#include "media/base/timestamp_constants.h"
[email protected]e81283bb2010-08-31 18:01:2140#include "media/base/video_frame.h"
acolwell9e0840d2014-09-06 19:01:3241#include "media/blink/texttrack_impl.h"
42#include "media/blink/webaudiosourceprovider_impl.h"
xhwang97de4202014-11-25 08:44:0143#include "media/blink/webcontentdecryptionmodule_impl.h"
acolwell9e0840d2014-09-06 19:01:3244#include "media/blink/webinbandtexttrack_impl.h"
45#include "media/blink/webmediaplayer_delegate.h"
acolwell9e0840d2014-09-06 19:01:3246#include "media/blink/webmediaplayer_util.h"
47#include "media/blink/webmediasource_impl.h"
[email protected]efe7cd22012-09-12 23:55:0148#include "media/filters/chunk_demuxer.h"
[email protected]ddbc6ff2013-04-19 15:28:3349#include "media/filters/ffmpeg_demuxer.h"
jrummellc9d8e532015-02-26 18:38:1950#include "third_party/WebKit/public/platform/WebEncryptedMediaTypes.h"
srirama.m26f864d02015-07-14 05:21:4651#include "third_party/WebKit/public/platform/WebMediaPlayerClient.h"
52#include "third_party/WebKit/public/platform/WebMediaPlayerEncryptedMediaClient.h"
[email protected]745746d2013-08-23 02:09:1653#include "third_party/WebKit/public/platform/WebMediaSource.h"
[email protected]c10884462013-05-30 00:22:0954#include "third_party/WebKit/public/platform/WebRect.h"
mek966863c2016-02-04 23:39:0555#include "third_party/WebKit/public/platform/WebSecurityOrigin.h"
[email protected]c10884462013-05-30 00:22:0956#include "third_party/WebKit/public/platform/WebSize.h"
57#include "third_party/WebKit/public/platform/WebString.h"
58#include "third_party/WebKit/public/platform/WebURL.h"
xhwang0acca44b2015-06-18 00:43:3159#include "third_party/WebKit/public/web/WebFrame.h"
[email protected]80504652014-04-18 04:41:5060#include "third_party/WebKit/public/web/WebLocalFrame.h"
[email protected]2255a9332013-06-17 05:12:3161#include "third_party/WebKit/public/web/WebView.h"
[email protected]b3f2b912009-04-09 16:18:5262
[email protected]180ef242013-11-07 06:50:4663using blink::WebCanvas;
64using blink::WebMediaPlayer;
65using blink::WebRect;
66using blink::WebSize;
67using blink::WebString;
hubbed5f36882016-01-15 22:40:3768using gpu::gles2::GLES2Interface;
69
danakj365175c2016-02-06 00:37:3770#define STATIC_ASSERT_ENUM(a, b) \
71 static_assert(static_cast<int>(a) == static_cast<int>(b), \
72 "mismatching enums: " #a)
73
hubbed5f36882016-01-15 22:40:3774namespace media {
[email protected]ec9212f2008-12-18 21:40:3675
[email protected]8931c41a2009-07-07 17:31:4976namespace {
77
[email protected]378f0b72009-08-11 17:11:4278// Limits the range of playback rate.
79//
80// TODO(kylep): Revisit these.
81//
82// Vista has substantially lower performance than XP or Windows7. If you speed
83// up a video too much, it can't keep up, and rendering stops updating except on
84// the time bar. For really high speeds, audio becomes a bottleneck and we just
85// use up the data we have, which may not achieve the speed requested, but will
86// not crash the tab.
87//
88// A very slow speed, ie 0.00000001x, causes the machine to lock up. (It seems
89// like a busy loop). It gets unresponsive, although its not completely dead.
90//
91// Also our timers are not very accurate (especially for ogg), which becomes
92// evident at low speeds and on Vista. Since other speeds are risky and outside
93// the norms, we think 1/16x to 16x is a safe and useful range for now.
[email protected]39bdde32013-04-17 17:44:2094const double kMinRate = 0.0625;
95const double kMaxRate = 16.0;
[email protected]378f0b72009-08-11 17:11:4296
hubbed5f36882016-01-15 22:40:3797void SetSinkIdOnMediaThread(scoped_refptr<WebAudioSourceProviderImpl> sink,
98 const std::string& device_id,
99 const url::Origin& security_origin,
100 const SwitchOutputDeviceCB& callback) {
guidouc7babef2015-10-22 00:42:35101 if (sink->GetOutputDevice()) {
102 sink->GetOutputDevice()->SwitchOutputDevice(device_id, security_origin,
103 callback);
104 } else {
hubbed5f36882016-01-15 22:40:37105 callback.Run(OUTPUT_DEVICE_STATUS_ERROR_INTERNAL);
guidouc7babef2015-10-22 00:42:35106 }
107}
108
dalecurtis0431cbf2016-03-12 01:19:43109bool IsSuspendUponHiddenEnabled() {
110#if !defined(OS_ANDROID)
111 // Suspend/Resume is only enabled by default on Android.
112 return base::CommandLine::ForCurrentProcess()->HasSwitch(
113 switches::kEnableMediaSuspend);
114#else
115 return !base::CommandLine::ForCurrentProcess()->HasSwitch(
116 switches::kDisableMediaSuspend);
117#endif
118}
119
[email protected]8931c41a2009-07-07 17:31:49120} // namespace
121
[email protected]6683e1b2014-04-10 01:45:38122class BufferedDataSourceHostImpl;
123
danakj365175c2016-02-06 00:37:37124STATIC_ASSERT_ENUM(WebMediaPlayer::CORSModeUnspecified,
125 UrlData::CORS_UNSPECIFIED);
126STATIC_ASSERT_ENUM(WebMediaPlayer::CORSModeAnonymous, UrlData::CORS_ANONYMOUS);
127STATIC_ASSERT_ENUM(WebMediaPlayer::CORSModeUseCredentials,
128 UrlData::CORS_USE_CREDENTIALS);
[email protected]a5a01102012-06-06 17:01:24129
[email protected]2c539b82012-08-18 04:10:19130#define BIND_TO_RENDER_LOOP(function) \
acolwellb4034942014-08-28 15:42:43131 (DCHECK(main_task_runner_->BelongsToCurrentThread()), \
acolwell9e0840d2014-09-06 19:01:32132 BindToCurrentLoop(base::Bind(function, AsWeakPtr())))
[email protected]5983adb2012-10-24 00:12:00133
[email protected]4e982192014-06-21 13:35:45134#define BIND_TO_RENDER_LOOP1(function, arg1) \
acolwellb4034942014-08-28 15:42:43135 (DCHECK(main_task_runner_->BelongsToCurrentThread()), \
acolwell9e0840d2014-09-06 19:01:32136 BindToCurrentLoop(base::Bind(function, AsWeakPtr(), arg1)))
[email protected]4e982192014-06-21 13:35:45137
[email protected]5b5bb9d2010-10-22 19:57:36138WebMediaPlayerImpl::WebMediaPlayerImpl(
[email protected]35b2a972014-04-04 15:50:22139 blink::WebLocalFrame* frame,
[email protected]180ef242013-11-07 06:50:46140 blink::WebMediaPlayerClient* client,
srirama.m26f864d02015-07-14 05:21:46141 blink::WebMediaPlayerEncryptedMediaClient* encrypted_client,
[email protected]b8976652011-10-26 23:46:55142 base::WeakPtr<WebMediaPlayerDelegate> delegate,
xhwang6fa356202014-12-11 00:44:12143 scoped_ptr<RendererFactory> renderer_factory,
hubbe5f0ad43b2015-12-14 20:57:26144 linked_ptr<UrlIndex> url_index,
[email protected]e82b2bd2013-01-02 17:47:57145 const WebMediaPlayerParams& params)
[email protected]f6af7592014-02-28 10:09:11146 : frame_(frame),
[email protected]ef405f66b2012-04-18 02:39:55147 network_state_(WebMediaPlayer::NetworkStateEmpty),
148 ready_state_(WebMediaPlayer::ReadyStateHaveNothing),
acolwella5081a42014-08-28 23:42:52149 preload_(BufferedDataSource::AUTO),
sandersdc6ab163a2015-12-12 03:56:13150 buffering_strategy_(
151 BufferedDataSourceInterface::BUFFERING_STRATEGY_NORMAL),
anujk.sharma2fa37a02015-04-30 05:51:32152 main_task_runner_(base::ThreadTaskRunnerHandle::Get()),
acolwell755d12d2014-08-30 01:09:19153 media_task_runner_(params.media_task_runner()),
dcastagna617d086b2015-08-20 01:39:30154 worker_task_runner_(params.worker_task_runner()),
acolwell755d12d2014-08-30 01:09:19155 media_log_(params.media_log()),
acolwellb4034942014-08-28 15:42:43156 pipeline_(media_task_runner_, media_log_.get()),
sandersd1c0bba02016-03-04 23:14:08157 pipeline_controller_(
158 &pipeline_,
159 base::Bind(&WebMediaPlayerImpl::CreateRenderer,
160 base::Unretained(this)),
161 base::Bind(&WebMediaPlayerImpl::OnPipelineSeeked, AsWeakPtr()),
162 base::Bind(&WebMediaPlayerImpl::OnPipelineSuspended, AsWeakPtr()),
163 base::Bind(&WebMediaPlayerImpl::OnPipelineResumed, AsWeakPtr()),
164 base::Bind(&WebMediaPlayerImpl::OnPipelineError, AsWeakPtr())),
[email protected]f988d9b2014-07-25 00:35:43165 load_type_(LoadTypeURL),
[email protected]75e145a2014-04-15 17:44:32166 opaque_(false),
wolenetz1b2ae7d2015-06-10 00:44:21167 playback_rate_(0.0),
[email protected]49480902009-07-14 20:23:43168 paused_(true),
[email protected]b3766a22010-12-22 17:34:13169 seeking_(false),
watkdee516f2016-02-18 02:22:19170 pending_suspend_resume_cycle_(false),
scherkusd2c745b2014-09-04 05:03:40171 ended_(false),
yoichio863bebf2016-03-04 07:56:58172 should_notify_time_changed_(false),
watkdee516f2016-02-18 02:22:19173 fullscreen_(false),
174 decoder_requires_restart_for_fullscreen_(false),
[email protected]5badb082010-06-11 17:40:15175 client_(client),
srirama.m26f864d02015-07-14 05:21:46176 encrypted_client_(encrypted_client),
[email protected]baff4512011-10-19 18:21:07177 delegate_(delegate),
dalecurtisbb3eaac2016-01-27 21:10:25178 delegate_id_(0),
[email protected]d726eddc2013-07-02 22:25:55179 defer_load_cb_(params.defer_load_cb()),
dongseong.hwang0c4e9d82015-01-08 20:11:13180 context_3d_cb_(params.context_3d_cb()),
dalecurtis83266c72015-10-29 18:43:20181 adjust_allocated_memory_cb_(params.adjust_allocated_memory_cb()),
182 last_reported_memory_usage_(0),
[email protected]132dd57c2012-08-10 23:24:34183 supports_save_(true),
[email protected]f5443ef72013-04-22 04:03:38184 chunk_demuxer_(NULL),
hubbe5f0ad43b2015-12-14 20:57:26185 url_index_(url_index),
Bartosz Fabianowski85a823812015-04-16 10:27:51186 // Threaded compositing isn't enabled universally yet.
187 compositor_task_runner_(
188 params.compositor_task_runner()
189 ? params.compositor_task_runner()
190 : base::MessageLoop::current()->task_runner()),
[email protected]dd061e12014-05-06 19:21:22191 compositor_(new VideoFrameCompositor(
Bartosz Fabianowski85a823812015-04-16 10:27:51192 compositor_task_runner_,
[email protected]75e145a2014-04-15 17:44:32193 BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnNaturalSizeChanged),
[email protected]dd061e12014-05-06 19:21:22194 BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnOpacityChanged))),
xhwang80739452016-01-13 00:48:00195 is_cdm_attached_(false),
hubbed5f36882016-01-15 22:40:37196#if defined(OS_ANDROID) // WMPI_CAST
dalecurtisbb3eaac2016-01-27 21:10:25197 cast_impl_(this, client_, params.context_3d_cb()),
hubbed5f36882016-01-15 22:40:37198#endif
dalecurtisbb3eaac2016-01-27 21:10:25199 volume_(1.0),
200 volume_multiplier_(1.0),
watkdee516f2016-02-18 02:22:19201 renderer_factory_(std::move(renderer_factory)),
dalecurtis2ff781da2016-03-03 01:52:13202 surface_manager_(params.surface_manager()),
203 suppress_destruction_errors_(false) {
dalecurtis83266c72015-10-29 18:43:20204 DCHECK(!adjust_allocated_memory_cb_.is_null());
xhwang59d4175a2016-01-14 03:19:30205 DCHECK(renderer_factory_);
servolkef1e5ef2016-03-25 04:55:26206 DCHECK(client_);
dalecurtis83266c72015-10-29 18:43:20207
dalecurtisbb3eaac2016-01-27 21:10:25208 if (delegate_)
209 delegate_id_ = delegate_->AddObserver(this);
sandersd1e49fb62015-12-12 01:18:06210
[email protected]c93eb0a62011-08-09 22:47:24211 media_log_->AddEvent(
acolwell9e0840d2014-09-06 19:01:32212 media_log_->CreateEvent(MediaLogEvent::WEBMEDIAPLAYER_CREATED));
[email protected]4e6be3f2009-05-07 02:24:44213
xhwang0ad11e512014-11-25 23:43:09214 if (params.initial_cdm()) {
xhwang9bd8c732015-04-13 23:27:53215 SetCdm(base::Bind(&IgnoreCdmAttached),
216 ToWebContentDecryptionModuleImpl(params.initial_cdm())
217 ->GetCdmContext());
xhwang0ad11e512014-11-25 23:43:09218 }
219
xhwangf94a634d2014-10-22 22:07:27220 // TODO(xhwang): When we use an external Renderer, many methods won't work,
xhwang6fa356202014-12-11 00:44:12221 // e.g. GetCurrentFrameFromCompositor(). See http://crbug.com/434861
[email protected]c50edb962013-10-19 18:05:07222
[email protected]ddbc6ff2013-04-19 15:28:33223 // Use the null sink if no sink was provided.
[email protected]4a914882013-01-10 00:43:48224 audio_source_provider_ = new WebAudioSourceProviderImpl(
[email protected]ff875be52013-06-02 23:47:38225 params.audio_renderer_sink().get()
226 ? params.audio_renderer_sink()
acolwell9e0840d2014-09-06 19:01:32227 : new NullAudioSink(media_task_runner_));
[email protected]ec9212f2008-12-18 21:40:36228}
229
[email protected]4e6be3f2009-05-07 02:24:44230WebMediaPlayerImpl::~WebMediaPlayerImpl() {
[email protected]ce70c982013-12-20 17:04:32231 client_->setWebLayer(NULL);
[email protected]21c3f7502013-03-23 03:29:51232
acolwellb4034942014-08-28 15:42:43233 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]d43ed912009-02-03 04:52:53234
sandersd1e49fb62015-12-12 01:18:06235 if (delegate_) {
dalecurtisbb3eaac2016-01-27 21:10:25236 delegate_->PlayerGone(delegate_id_);
237 delegate_->RemoveObserver(delegate_id_);
sandersd1e49fb62015-12-12 01:18:06238 }
[email protected]baff4512011-10-19 18:21:07239
[email protected]f6af7592014-02-28 10:09:11240 // Abort any pending IO so stopping the pipeline doesn't get blocked.
dalecurtis2ff781da2016-03-03 01:52:13241 suppress_destruction_errors_ = true;
[email protected]f6af7592014-02-28 10:09:11242 if (data_source_)
243 data_source_->Abort();
244 if (chunk_demuxer_) {
245 chunk_demuxer_->Shutdown();
sandersd1c0bba02016-03-04 23:14:08246 chunk_demuxer_ = nullptr;
[email protected]f6af7592014-02-28 10:09:11247 }
248
xhwang6fa356202014-12-11 00:44:12249 renderer_factory_.reset();
[email protected]f6af7592014-02-28 10:09:11250
251 // Make sure to kill the pipeline so there's no more media threads running.
252 // Note: stopping the pipeline might block for a long time.
253 base::WaitableEvent waiter(false, false);
254 pipeline_.Stop(
255 base::Bind(&base::WaitableEvent::Signal, base::Unretained(&waiter)));
256 waiter.Wait();
257
dalecurtis83266c72015-10-29 18:43:20258 if (last_reported_memory_usage_)
259 adjust_allocated_memory_cb_.Run(-last_reported_memory_usage_);
260
[email protected]dd061e12014-05-06 19:21:22261 compositor_task_runner_->DeleteSoon(FROM_HERE, compositor_);
xhwangea8bb3562015-06-08 21:18:37262
263 media_log_->AddEvent(
264 media_log_->CreateEvent(MediaLogEvent::WEBMEDIAPLAYER_DESTROYED));
[email protected]ec9212f2008-12-18 21:40:36265}
266
[email protected]180ef242013-11-07 06:50:46267void WebMediaPlayerImpl::load(LoadType load_type, const blink::WebURL& url,
[email protected]62e5e682013-03-07 23:53:24268 CORSMode cors_mode) {
[email protected]2a06ca62014-06-04 13:59:52269 DVLOG(1) << __FUNCTION__ << "(" << load_type << ", " << url << ", "
270 << cors_mode << ")";
[email protected]d726eddc2013-07-02 22:25:55271 if (!defer_load_cb_.is_null()) {
272 defer_load_cb_.Run(base::Bind(
[email protected]ef8394c2013-08-21 20:26:30273 &WebMediaPlayerImpl::DoLoad, AsWeakPtr(), load_type, url, cors_mode));
[email protected]d726eddc2013-07-02 22:25:55274 return;
275 }
[email protected]ef8394c2013-08-21 20:26:30276 DoLoad(load_type, url, cors_mode);
[email protected]62e5e682013-03-07 23:53:24277}
278
watkdee516f2016-02-18 02:22:19279void WebMediaPlayerImpl::enteredFullscreen() {
280 fullscreen_ = true;
281 if (decoder_requires_restart_for_fullscreen_)
282 ScheduleRestart();
283}
284
285void WebMediaPlayerImpl::exitedFullscreen() {
286 fullscreen_ = false;
287 if (decoder_requires_restart_for_fullscreen_)
288 ScheduleRestart();
289}
290
[email protected]ef8394c2013-08-21 20:26:30291void WebMediaPlayerImpl::DoLoad(LoadType load_type,
[email protected]180ef242013-11-07 06:50:46292 const blink::WebURL& url,
[email protected]d726eddc2013-07-02 22:25:55293 CORSMode cors_mode) {
hubbed82bed52015-12-15 23:07:16294 DVLOG(1) << __FUNCTION__;
acolwellb4034942014-08-28 15:42:43295 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]d726eddc2013-07-02 22:25:55296
[email protected]62e5e682013-03-07 23:53:24297 GURL gurl(url);
xhwangbffbf452016-04-01 05:26:45298 ReportMetrics(load_type, gurl, frame_->getSecurityOrigin());
[email protected]62e5e682013-03-07 23:53:24299
[email protected]926f8fd2013-04-12 20:27:53300 // Set subresource URL for crash reporting.
301 base::debug::SetCrashKeyValue("subresource_url", gurl.spec());
302
[email protected]ef8394c2013-08-21 20:26:30303 load_type_ = load_type;
304
[email protected]62e5e682013-03-07 23:53:24305 SetNetworkState(WebMediaPlayer::NetworkStateLoading);
306 SetReadyState(WebMediaPlayer::ReadyStateHaveNothing);
kinukof19cde72015-12-18 23:15:25307 media_log_->AddEvent(media_log_->CreateLoadEvent(url.string().utf8()));
[email protected]d726eddc2013-07-02 22:25:55308
309 // Media source pipelines can start immediately.
[email protected]ef8394c2013-08-21 20:26:30310 if (load_type == LoadTypeMediaSource) {
[email protected]d726eddc2013-07-02 22:25:55311 supports_save_ = false;
[email protected]ef8394c2013-08-21 20:26:30312 StartPipeline();
hubbe5f0ad43b2015-12-14 20:57:26313 } else {
avayvode46d7bef2016-03-30 23:18:26314 // 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.
317 // Otherwise it's a regular request which requires resolving the URL first.
318 if (base::FeatureList::IsEnabled(kUseNewMediaCache)) {
319 // 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 }
332 data_source_->SetPreload(preload_);
333 data_source_->SetBufferingStrategy(buffering_strategy_);
334 data_source_->Initialize(
335 base::Bind(&WebMediaPlayerImpl::DataSourceInitialized, AsWeakPtr()));
hubbe5f0ad43b2015-12-14 20:57:26336 }
hubbed5f36882016-01-15 22:40:37337
338#if defined(OS_ANDROID) // WMPI_CAST
dalecurtisbb3eaac2016-01-27 21:10:25339 cast_impl_.Initialize(url, frame_, delegate_id_);
hubbed5f36882016-01-15 22:40:37340#endif
[email protected]62e5e682013-03-07 23:53:24341}
342
[email protected]4e6be3f2009-05-07 02:24:44343void WebMediaPlayerImpl::play() {
[email protected]2a06ca62014-06-04 13:59:52344 DVLOG(1) << __FUNCTION__;
acolwellb4034942014-08-28 15:42:43345 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]d43ed912009-02-03 04:52:53346
hubbed5f36882016-01-15 22:40:37347#if defined(OS_ANDROID) // WMPI_CAST
348 if (isRemote()) {
dalecurtis6e2716d2016-01-21 04:49:15349 cast_impl_.play();
hubbed5f36882016-01-15 22:40:37350 return;
351 }
352#endif
353
dalecurtis0431cbf2016-03-12 01:19:43354 const bool was_paused = paused_;
[email protected]49480902009-07-14 20:23:43355 paused_ = false;
yoichio863bebf2016-03-04 07:56:58356 pipeline_.SetPlaybackRate(playback_rate_);
sandersd1c0bba02016-03-04 23:14:08357
[email protected]039b7542013-10-17 22:06:25358 if (data_source_)
359 data_source_->MediaIsPlaying();
[email protected]090f7312011-08-05 23:26:40360
acolwell9e0840d2014-09-06 19:01:32361 media_log_->AddEvent(media_log_->CreateEvent(MediaLogEvent::PLAY));
[email protected]baff4512011-10-19 18:21:07362
dalecurtis0431cbf2016-03-12 01:19:43363 if (playback_rate_ > 0 && was_paused) {
yoichio863bebf2016-03-04 07:56:58364 NotifyPlaybackStarted();
sandersd1c0bba02016-03-04 23:14:08365
dalecurtis0431cbf2016-03-12 01:19:43366 // Resume the player if allowed. We always call Resume() in case there is a
367 // pending suspend that should be aborted. If the pipeline is not suspended,
368 // Resume() will have no effect.
369 if (IsAutomaticResumeAllowed())
sandersd1c0bba02016-03-04 23:14:08370 pipeline_controller_.Resume();
dalecurtis5bbc487e2016-02-27 04:15:05371 }
[email protected]ec9212f2008-12-18 21:40:36372}
373
[email protected]4e6be3f2009-05-07 02:24:44374void WebMediaPlayerImpl::pause() {
[email protected]2a06ca62014-06-04 13:59:52375 DVLOG(1) << __FUNCTION__;
acolwellb4034942014-08-28 15:42:43376 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]d43ed912009-02-03 04:52:53377
dalecurtis6d269ed2014-09-11 21:18:13378 const bool was_already_paused = paused_ || playback_rate_ == 0;
[email protected]49480902009-07-14 20:23:43379 paused_ = true;
hubbed5f36882016-01-15 22:40:37380
381#if defined(OS_ANDROID) // WMPI_CAST
382 if (isRemote()) {
dalecurtis6e2716d2016-01-21 04:49:15383 cast_impl_.pause();
hubbed5f36882016-01-15 22:40:37384 return;
385 }
386#endif
387
a.berwal338bf002015-04-22 11:14:50388 pipeline_.SetPlaybackRate(0.0);
sandersd1c0bba02016-03-04 23:14:08389
390 // pause() may be called after playback has ended and the HTMLMediaElement
391 // requires that currentTime() == duration() after ending. We want to ensure
392 // |paused_time_| matches currentTime() in this case or a future seek() may
393 // incorrectly discard what it thinks is a seek to the existing time.
394 paused_time_ =
395 ended_ ? pipeline_.GetMediaDuration() : pipeline_.GetMediaTime();
[email protected]090f7312011-08-05 23:26:40396
acolwell9e0840d2014-09-06 19:01:32397 media_log_->AddEvent(media_log_->CreateEvent(MediaLogEvent::PAUSE));
[email protected]baff4512011-10-19 18:21:07398
dalecurtisbb3eaac2016-01-27 21:10:25399 if (!was_already_paused)
dalecurtis0f0097a2015-12-01 17:40:47400 NotifyPlaybackPaused();
[email protected]ec9212f2008-12-18 21:40:36401}
402
[email protected]574a1d62009-07-17 03:23:46403bool WebMediaPlayerImpl::supportsSave() const {
acolwellb4034942014-08-28 15:42:43404 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]132dd57c2012-08-10 23:24:34405 return supports_save_;
[email protected]574a1d62009-07-17 03:23:46406}
407
[email protected]39bdde32013-04-17 17:44:20408void WebMediaPlayerImpl::seek(double seconds) {
xhwang12d8d042014-12-01 21:48:57409 DVLOG(1) << __FUNCTION__ << "(" << seconds << "s)";
acolwellb4034942014-08-28 15:42:43410 DCHECK(main_task_runner_->BelongsToCurrentThread());
sandersd1c0bba02016-03-04 23:14:08411 DoSeek(base::TimeDelta::FromSecondsD(seconds), true);
412}
413
414void WebMediaPlayerImpl::DoSeek(base::TimeDelta time, bool time_updated) {
415 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]d43ed912009-02-03 04:52:53416
scherkusd2c745b2014-09-04 05:03:40417 ended_ = false;
418
hubbed5f36882016-01-15 22:40:37419#if defined(OS_ANDROID) // WMPI_CAST
420 if (isRemote()) {
sandersd1c0bba02016-03-04 23:14:08421 cast_impl_.seek(time);
hubbed5f36882016-01-15 22:40:37422 return;
423 }
424#endif
425
srirama.mccf671812015-01-08 11:59:13426 ReadyState old_state = ready_state_;
[email protected]1bb666802013-11-28 06:12:08427 if (ready_state_ > WebMediaPlayer::ReadyStateHaveMetadata)
428 SetReadyState(WebMediaPlayer::ReadyStateHaveMetadata);
429
sandersd1c0bba02016-03-04 23:14:08430 // When paused, we know exactly what the current time is and can elide seeks
431 // to it. However, there are two cases that are not elided:
432 // 1) When the pipeline state is not stable.
433 // In this case we just let |pipeline_controller_| decide what to do, as
434 // it has complete information.
435 // 2) For MSE.
436 // Because the buffers may have changed between seeks, MSE seeks are
437 // never elided.
438 if (paused_ && pipeline_controller_.IsStable() && paused_time_ == time &&
439 !chunk_demuxer_) {
440 // If the ready state was high enough before, we can indicate that the seek
441 // completed just by restoring it. Otherwise we will just wait for the real
442 // ready state change to eventually happen.
443 if (old_state == ReadyStateHaveEnoughData) {
srirama.m8f4a37562014-12-13 08:16:18444 main_task_runner_->PostTask(
srirama.m36ab2682014-12-11 04:20:01445 FROM_HERE,
446 base::Bind(&WebMediaPlayerImpl::OnPipelineBufferingStateChanged,
srirama.m8f4a37562014-12-13 08:16:18447 AsWeakPtr(), BUFFERING_HAVE_ENOUGH));
srirama.m36ab2682014-12-11 04:20:01448 }
sandersd1c0bba02016-03-04 23:14:08449 return;
srirama.m36ab2682014-12-11 04:20:01450 }
[email protected]44ff37c02009-10-24 01:03:03451
[email protected]b3766a22010-12-22 17:34:13452 seeking_ = true;
sandersd1c0bba02016-03-04 23:14:08453 seek_time_ = time;
454 if (paused_)
455 paused_time_ = time;
456 pipeline_controller_.Seek(time, time_updated);
[email protected]b3766a22010-12-22 17:34:13457
dalecurtis0431cbf2016-03-12 01:19:43458 // Resume the pipeline if allowed so that the correct frame is displayed. We
459 // always call Resume() in case there is a pending suspend that should be
460 // aborted. If the pipeline is not suspended, Resume() will have no effect.
461 if (IsAutomaticResumeAllowed())
sandersd1c0bba02016-03-04 23:14:08462 pipeline_controller_.Resume();
[email protected]ec9212f2008-12-18 21:40:36463}
464
[email protected]39bdde32013-04-17 17:44:20465void WebMediaPlayerImpl::setRate(double rate) {
[email protected]2a06ca62014-06-04 13:59:52466 DVLOG(1) << __FUNCTION__ << "(" << rate << ")";
acolwellb4034942014-08-28 15:42:43467 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]d43ed912009-02-03 04:52:53468
[email protected]378f0b72009-08-11 17:11:42469 // TODO(kylep): Remove when support for negatives is added. Also, modify the
470 // following checks so rewind uses reasonable values also.
[email protected]39bdde32013-04-17 17:44:20471 if (rate < 0.0)
[email protected]378f0b72009-08-11 17:11:42472 return;
473
474 // Limit rates to reasonable values by clamping.
[email protected]39bdde32013-04-17 17:44:20475 if (rate != 0.0) {
[email protected]378f0b72009-08-11 17:11:42476 if (rate < kMinRate)
477 rate = kMinRate;
478 else if (rate > kMaxRate)
479 rate = kMaxRate;
dalecurtisbb3eaac2016-01-27 21:10:25480 if (playback_rate_ == 0 && !paused_)
dalecurtis0f0097a2015-12-01 17:40:47481 NotifyPlaybackStarted();
dalecurtisbb3eaac2016-01-27 21:10:25482 } else if (playback_rate_ != 0 && !paused_) {
dalecurtis0f0097a2015-12-01 17:40:47483 NotifyPlaybackPaused();
[email protected]378f0b72009-08-11 17:11:42484 }
485
[email protected]49480902009-07-14 20:23:43486 playback_rate_ = rate;
487 if (!paused_) {
[email protected]f6af7592014-02-28 10:09:11488 pipeline_.SetPlaybackRate(rate);
[email protected]039b7542013-10-17 22:06:25489 if (data_source_)
490 data_source_->MediaPlaybackRateChanged(rate);
[email protected]49480902009-07-14 20:23:43491 }
[email protected]ec9212f2008-12-18 21:40:36492}
493
[email protected]39bdde32013-04-17 17:44:20494void WebMediaPlayerImpl::setVolume(double volume) {
[email protected]2a06ca62014-06-04 13:59:52495 DVLOG(1) << __FUNCTION__ << "(" << volume << ")";
acolwellb4034942014-08-28 15:42:43496 DCHECK(main_task_runner_->BelongsToCurrentThread());
dalecurtisbb3eaac2016-01-27 21:10:25497 volume_ = volume;
498 pipeline_.SetVolume(volume_ * volume_multiplier_);
[email protected]ec9212f2008-12-18 21:40:36499}
[email protected]f0a51fb52009-03-05 12:46:38500
guidouc7babef2015-10-22 00:42:35501void WebMediaPlayerImpl::setSinkId(
502 const blink::WebString& sink_id,
503 const blink::WebSecurityOrigin& security_origin,
504 blink::WebSetSinkIdCallbacks* web_callback) {
guidou69223ce2015-06-16 10:36:19505 DCHECK(main_task_runner_->BelongsToCurrentThread());
guidou5754e612015-07-31 08:09:41506 DVLOG(1) << __FUNCTION__;
guidouc7babef2015-10-22 00:42:35507
guidou5754e612015-07-31 08:09:41508 media::SwitchOutputDeviceCB callback =
509 media::ConvertToSwitchOutputDeviceCB(web_callback);
guidouc7babef2015-10-22 00:42:35510 media_task_runner_->PostTask(
511 FROM_HERE,
512 base::Bind(&SetSinkIdOnMediaThread, audio_source_provider_,
513 sink_id.utf8(), static_cast<url::Origin>(security_origin),
514 callback));
guidou69223ce2015-06-16 10:36:19515}
516
danakj365175c2016-02-06 00:37:37517STATIC_ASSERT_ENUM(WebMediaPlayer::PreloadNone, BufferedDataSource::NONE);
518STATIC_ASSERT_ENUM(WebMediaPlayer::PreloadMetaData,
519 BufferedDataSource::METADATA);
520STATIC_ASSERT_ENUM(WebMediaPlayer::PreloadAuto, BufferedDataSource::AUTO);
[email protected]23a8b1d82011-04-05 16:28:20521
[email protected]ef405f66b2012-04-18 02:39:55522void WebMediaPlayerImpl::setPreload(WebMediaPlayer::Preload preload) {
[email protected]2a06ca62014-06-04 13:59:52523 DVLOG(1) << __FUNCTION__ << "(" << preload << ")";
acolwellb4034942014-08-28 15:42:43524 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]4e6be3f2009-05-07 02:24:44525
acolwella5081a42014-08-28 23:42:52526 preload_ = static_cast<BufferedDataSource::Preload>(preload);
[email protected]b49beeb2013-03-01 20:04:00527 if (data_source_)
[email protected]09c60222014-08-07 16:42:31528 data_source_->SetPreload(preload_);
[email protected]4e6be3f2009-05-07 02:24:44529}
530
danakj365175c2016-02-06 00:37:37531STATIC_ASSERT_ENUM(WebMediaPlayer::BufferingStrategy::Normal,
532 BufferedDataSource::BUFFERING_STRATEGY_NORMAL);
533STATIC_ASSERT_ENUM(WebMediaPlayer::BufferingStrategy::Aggressive,
534 BufferedDataSource::BUFFERING_STRATEGY_AGGRESSIVE);
sandersdc6ab163a2015-12-12 03:56:13535
536void WebMediaPlayerImpl::setBufferingStrategy(
537 WebMediaPlayer::BufferingStrategy buffering_strategy) {
538 DVLOG(1) << __FUNCTION__;
539 DCHECK(main_task_runner_->BelongsToCurrentThread());
540
dalecurtis37fe5862016-03-15 19:29:09541#if defined(OS_ANDROID)
542 // We disallow aggressive buffering on Android since it matches the behavior
543 // of the platform media player and may have data usage penalties.
544 // TODO(dalecurtis, hubbe): We should probably stop using "pause-and-buffer"
545 // everywhere. See http://crbug.com/594669 for more details.
546 buffering_strategy_ = BufferedDataSource::BUFFERING_STRATEGY_NORMAL;
547#else
sandersdc6ab163a2015-12-12 03:56:13548 buffering_strategy_ =
549 static_cast<BufferedDataSource::BufferingStrategy>(buffering_strategy);
dalecurtis37fe5862016-03-15 19:29:09550#endif
551
sandersdc6ab163a2015-12-12 03:56:13552 if (data_source_)
553 data_source_->SetBufferingStrategy(buffering_strategy_);
554}
555
[email protected]4e6be3f2009-05-07 02:24:44556bool WebMediaPlayerImpl::hasVideo() const {
acolwellb4034942014-08-28 15:42:43557 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]d43ed912009-02-03 04:52:53558
[email protected]b8877772014-03-26 20:17:15559 return pipeline_metadata_.has_video;
[email protected]d43ed912009-02-03 04:52:53560}
561
[email protected]fc367af2009-08-14 23:06:35562bool WebMediaPlayerImpl::hasAudio() const {
acolwellb4034942014-08-28 15:42:43563 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]fc367af2009-08-14 23:06:35564
[email protected]b8877772014-03-26 20:17:15565 return pipeline_metadata_.has_audio;
[email protected]fc367af2009-08-14 23:06:35566}
567
[email protected]180ef242013-11-07 06:50:46568blink::WebSize WebMediaPlayerImpl::naturalSize() const {
acolwellb4034942014-08-28 15:42:43569 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]d43ed912009-02-03 04:52:53570
[email protected]b8877772014-03-26 20:17:15571 return blink::WebSize(pipeline_metadata_.natural_size);
[email protected]d43ed912009-02-03 04:52:53572}
573
[email protected]4e6be3f2009-05-07 02:24:44574bool WebMediaPlayerImpl::paused() const {
acolwellb4034942014-08-28 15:42:43575 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]d43ed912009-02-03 04:52:53576
hubbed5f36882016-01-15 22:40:37577#if defined(OS_ANDROID) // WMPI_CAST
578 if (isRemote())
579 return cast_impl_.paused();
580#endif
[email protected]f6af7592014-02-28 10:09:11581 return pipeline_.GetPlaybackRate() == 0.0f;
[email protected]d43ed912009-02-03 04:52:53582}
583
[email protected]4e6be3f2009-05-07 02:24:44584bool WebMediaPlayerImpl::seeking() const {
acolwellb4034942014-08-28 15:42:43585 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]d43ed912009-02-03 04:52:53586
[email protected]ef405f66b2012-04-18 02:39:55587 if (ready_state_ == WebMediaPlayer::ReadyStateHaveNothing)
[email protected]0acebfa2009-08-21 22:45:40588 return false;
[email protected]67cd5052009-09-10 21:53:22589
[email protected]b3766a22010-12-22 17:34:13590 return seeking_;
[email protected]ec9212f2008-12-18 21:40:36591}
592
[email protected]39bdde32013-04-17 17:44:20593double WebMediaPlayerImpl::duration() const {
acolwellb4034942014-08-28 15:42:43594 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]39bdde32013-04-17 17:44:20595
596 if (ready_state_ == WebMediaPlayer::ReadyStateHaveNothing)
597 return std::numeric_limits<double>::quiet_NaN();
598
[email protected]39bdde32013-04-17 17:44:20599 return GetPipelineDuration();
[email protected]d43ed912009-02-03 04:52:53600}
601
[email protected]db66d0092014-04-16 07:15:12602double WebMediaPlayerImpl::timelineOffset() const {
acolwellb4034942014-08-28 15:42:43603 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]db66d0092014-04-16 07:15:12604
605 if (pipeline_metadata_.timeline_offset.is_null())
606 return std::numeric_limits<double>::quiet_NaN();
607
608 return pipeline_metadata_.timeline_offset.ToJsTime();
609}
610
[email protected]39bdde32013-04-17 17:44:20611double WebMediaPlayerImpl::currentTime() const {
acolwellb4034942014-08-28 15:42:43612 DCHECK(main_task_runner_->BelongsToCurrentThread());
scherkusd2c745b2014-09-04 05:03:40613 DCHECK_NE(ready_state_, WebMediaPlayer::ReadyStateHaveNothing);
614
615 // TODO(scherkus): Replace with an explicit ended signal to HTMLMediaElement,
616 // see http://crbug.com/409280
617 if (ended_)
618 return duration();
619
sandersd1c0bba02016-03-04 23:14:08620 if (seeking())
621 return seek_time_.InSecondsF();
wolenetz1b2ae7d2015-06-10 00:44:21622
hubbed5f36882016-01-15 22:40:37623#if defined(OS_ANDROID) // WMPI_CAST
sandersd1c0bba02016-03-04 23:14:08624 if (isRemote())
hubbed5f36882016-01-15 22:40:37625 return cast_impl_.currentTime();
hubbed5f36882016-01-15 22:40:37626#endif
627
sandersd1c0bba02016-03-04 23:14:08628 if (paused_)
hubbed5f36882016-01-15 22:40:37629 return paused_time_.InSecondsF();
hubbed5f36882016-01-15 22:40:37630
631 return pipeline_.GetMediaTime().InSecondsF();
[email protected]d43ed912009-02-03 04:52:53632}
633
danakj13afe0362016-02-27 01:22:50634WebMediaPlayer::NetworkState WebMediaPlayerImpl::getNetworkState() const {
acolwellb4034942014-08-28 15:42:43635 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]ddb1e5a2010-12-13 20:10:45636 return network_state_;
637}
638
danakj13afe0362016-02-27 01:22:50639WebMediaPlayer::ReadyState WebMediaPlayerImpl::getReadyState() const {
acolwellb4034942014-08-28 15:42:43640 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]ddb1e5a2010-12-13 20:10:45641 return ready_state_;
642}
643
[email protected]02022fc2014-05-16 00:05:31644blink::WebTimeRanges WebMediaPlayerImpl::buffered() const {
acolwellb4034942014-08-28 15:42:43645 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]779a8322014-08-22 21:28:37646
acolwell9e0840d2014-09-06 19:01:32647 Ranges<base::TimeDelta> buffered_time_ranges =
[email protected]02022fc2014-05-16 00:05:31648 pipeline_.GetBufferedTimeRanges();
[email protected]779a8322014-08-22 21:28:37649
650 const base::TimeDelta duration = pipeline_.GetMediaDuration();
acolwell9e0840d2014-09-06 19:01:32651 if (duration != kInfiniteDuration()) {
[email protected]779a8322014-08-22 21:28:37652 buffered_data_source_host_.AddBufferedTimeRanges(
653 &buffered_time_ranges, duration);
654 }
[email protected]02022fc2014-05-16 00:05:31655 return ConvertToWebTimeRanges(buffered_time_ranges);
656}
657
philipjb0e6f3f2014-09-30 09:51:53658blink::WebTimeRanges WebMediaPlayerImpl::seekable() const {
acolwellb4034942014-08-28 15:42:43659 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]39bdde32013-04-17 17:44:20660
dalecurtis56359cb2014-10-28 00:06:29661 if (ready_state_ < WebMediaPlayer::ReadyStateHaveMetadata)
philipjb0e6f3f2014-09-30 09:51:53662 return blink::WebTimeRanges();
663
dalecurtis56359cb2014-10-28 00:06:29664 const double seekable_end = duration();
665
666 // Allow a special exception for seeks to zero for streaming sources with a
667 // finite duration; this allows looping to work.
668 const bool allow_seek_to_zero = data_source_ && data_source_->IsStreaming() &&
mateuszs3371ab02015-04-24 13:20:23669 std::isfinite(seekable_end);
dalecurtis56359cb2014-10-28 00:06:29670
671 // TODO(dalecurtis): Technically this allows seeking on media which return an
672 // infinite duration so long as DataSource::IsStreaming() is false. While not
673 // expected, disabling this breaks semi-live players, http://crbug.com/427412.
674 const blink::WebTimeRange seekable_range(
675 0.0, allow_seek_to_zero ? 0.0 : seekable_end);
philipjb0e6f3f2014-09-30 09:51:53676 return blink::WebTimeRanges(&seekable_range, 1);
[email protected]ec9212f2008-12-18 21:40:36677}
678
[email protected]5d2b3e4c2014-05-12 23:27:30679bool WebMediaPlayerImpl::didLoadingProgress() {
acolwellb4034942014-08-28 15:42:43680 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]6683e1b2014-04-10 01:45:38681 bool pipeline_progress = pipeline_.DidLoadingProgress();
682 bool data_progress = buffered_data_source_host_.DidLoadingProgress();
683 return pipeline_progress || data_progress;
[email protected]d43ed912009-02-03 04:52:53684}
685
[email protected]dd5c7972014-08-21 15:00:37686void WebMediaPlayerImpl::paint(blink::WebCanvas* canvas,
687 const blink::WebRect& rect,
[email protected]dd5c7972014-08-21 15:00:37688 unsigned char alpha,
689 SkXfermode::Mode mode) {
acolwellb4034942014-08-28 15:42:43690 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]dd061e12014-05-06 19:21:22691 TRACE_EVENT0("media", "WebMediaPlayerImpl:paint");
[email protected]4e6be3f2009-05-07 02:24:44692
xhwang80739452016-01-13 00:48:00693 if (is_cdm_attached_)
694 return;
695
mcasasf1236fc22015-05-29 22:38:56696 scoped_refptr<VideoFrame> video_frame = GetCurrentFrameFromCompositor();
[email protected]0fe5d43b2014-01-24 23:32:45697
[email protected]b49beeb2013-03-01 20:04:00698 gfx::Rect gfx_rect(rect);
dongseong.hwang0c4e9d82015-01-08 20:11:13699 Context3D context_3d;
mcasas265bdbf82015-06-12 18:44:07700 if (video_frame.get() && video_frame->HasTextures()) {
mcasasf1236fc22015-05-29 22:38:56701 if (!context_3d_cb_.is_null())
dongseong.hwang0c4e9d82015-01-08 20:11:13702 context_3d = context_3d_cb_.Run();
dongseong.hwang0c4e9d82015-01-08 20:11:13703 // GPU Process crashed.
704 if (!context_3d.gl)
705 return;
706 }
danakj795f1732015-08-31 23:40:22707 skcanvas_video_renderer_.Paint(video_frame, canvas, gfx::RectF(gfx_rect),
708 alpha, mode, pipeline_metadata_.video_rotation,
709 context_3d);
[email protected]ec9212f2008-12-18 21:40:36710}
[email protected]5df51652009-01-17 00:03:00711
[email protected]38259a7a82009-07-29 21:49:49712bool WebMediaPlayerImpl::hasSingleSecurityOrigin() const {
[email protected]b49beeb2013-03-01 20:04:00713 if (data_source_)
714 return data_source_->HasSingleOrigin();
[email protected]fcdb7462009-10-21 21:05:11715 return true;
[email protected]38259a7a82009-07-29 21:49:49716}
717
[email protected]3fe27112012-06-07 04:00:01718bool WebMediaPlayerImpl::didPassCORSAccessCheck() const {
[email protected]b49beeb2013-03-01 20:04:00719 if (data_source_)
720 return data_source_->DidPassCORSAccessCheck();
721 return false;
[email protected]3fe27112012-06-07 04:00:01722}
723
[email protected]39bdde32013-04-17 17:44:20724double WebMediaPlayerImpl::mediaTimeForTimeValue(double timeValue) const {
qinminb4c39782015-08-10 18:43:24725 return base::TimeDelta::FromSecondsD(timeValue).InSecondsF();
[email protected]e06e16d82011-05-26 22:13:33726}
727
[email protected]d82b18ae2011-03-23 21:28:59728unsigned WebMediaPlayerImpl::decodedFrameCount() const {
acolwellb4034942014-08-28 15:42:43729 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]4c51bc662011-02-16 02:03:16730
acolwell9e0840d2014-09-06 19:01:32731 PipelineStatistics stats = pipeline_.GetStatistics();
[email protected]4c51bc662011-02-16 02:03:16732 return stats.video_frames_decoded;
733}
734
[email protected]d82b18ae2011-03-23 21:28:59735unsigned WebMediaPlayerImpl::droppedFrameCount() const {
acolwellb4034942014-08-28 15:42:43736 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]4c51bc662011-02-16 02:03:16737
acolwell9e0840d2014-09-06 19:01:32738 PipelineStatistics stats = pipeline_.GetStatistics();
[email protected]dd061e12014-05-06 19:21:22739 return stats.video_frames_dropped;
[email protected]4c51bc662011-02-16 02:03:16740}
741
chakshu.a94326b72016-03-08 05:11:44742size_t WebMediaPlayerImpl::audioDecodedByteCount() const {
acolwellb4034942014-08-28 15:42:43743 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]4c51bc662011-02-16 02:03:16744
acolwell9e0840d2014-09-06 19:01:32745 PipelineStatistics stats = pipeline_.GetStatistics();
[email protected]4c51bc662011-02-16 02:03:16746 return stats.audio_bytes_decoded;
747}
748
chakshu.a94326b72016-03-08 05:11:44749size_t WebMediaPlayerImpl::videoDecodedByteCount() const {
acolwellb4034942014-08-28 15:42:43750 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]4c51bc662011-02-16 02:03:16751
acolwell9e0840d2014-09-06 19:01:32752 PipelineStatistics stats = pipeline_.GetStatistics();
[email protected]4c51bc662011-02-16 02:03:16753 return stats.video_bytes_decoded;
754}
755
[email protected]6523b242013-03-13 11:10:07756bool WebMediaPlayerImpl::copyVideoTextureToPlatformTexture(
danakj46070b02016-03-28 21:54:11757 gpu::gles2::GLES2Interface* gl,
zmo57d577a2015-10-30 18:28:59758 unsigned int texture,
759 unsigned int internal_format,
760 unsigned int type,
761 bool premultiply_alpha,
762 bool flip_y) {
[email protected]bfc05f22013-10-19 17:55:16763 TRACE_EVENT0("media", "WebMediaPlayerImpl:copyVideoTextureToPlatformTexture");
764
mcasasf1236fc22015-05-29 22:38:56765 scoped_refptr<VideoFrame> video_frame = GetCurrentFrameFromCompositor();
[email protected]dd061e12014-05-06 19:21:22766
mcasas265bdbf82015-06-12 18:44:07767 if (!video_frame.get() || !video_frame->HasTextures() ||
dcastagna31a65d432015-06-11 19:01:00768 media::VideoFrame::NumPlanes(video_frame->format()) != 1) {
[email protected]e56f88c72013-06-25 22:31:29769 return false;
dongseong.hwang0c4e9d82015-01-08 20:11:13770 }
[email protected]df41e252014-02-03 23:39:50771
dcastagna31a65d432015-06-11 19:01:00772 SkCanvasVideoRenderer::CopyVideoFrameSingleTextureToGLTexture(
zmo57d577a2015-10-30 18:28:59773 gl, video_frame.get(), texture, internal_format, type, premultiply_alpha,
774 flip_y);
[email protected]e56f88c72013-06-25 22:31:29775 return true;
[email protected]6523b242013-03-13 11:10:07776}
777
[email protected]7bce1832014-01-09 00:01:22778void WebMediaPlayerImpl::setContentDecryptionModule(
[email protected]9ebc3b03f2014-08-13 04:01:23779 blink::WebContentDecryptionModule* cdm,
780 blink::WebContentDecryptionModuleResult result) {
acolwellb4034942014-08-28 15:42:43781 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]9ebc3b03f2014-08-13 04:01:23782
jrummell06f27072015-06-08 18:12:38783 // Once the CDM is set it can't be cleared as there may be frames being
784 // decrypted on other threads. So fail this request.
785 // http://crbug.com/462365#c7.
xhwang97de4202014-11-25 08:44:01786 if (!cdm) {
787 result.completeWithError(
jrummell06f27072015-06-08 18:12:38788 blink::WebContentDecryptionModuleExceptionInvalidStateError, 0,
789 "The existing MediaKeys object cannot be removed at this time.");
xhwang97de4202014-11-25 08:44:01790 return;
791 }
792
jrummell89e61d82015-07-23 20:03:34793 // Create a local copy of |result| to avoid problems with the callback
794 // getting passed to the media thread and causing |result| to be destructed
jrummell4acbec912016-02-27 02:45:03795 // on the wrong thread in some failure conditions. Blink should prevent
796 // multiple simultaneous calls.
797 DCHECK(!set_cdm_result_);
jrummell89e61d82015-07-23 20:03:34798 set_cdm_result_.reset(new blink::WebContentDecryptionModuleResult(result));
799
800 SetCdm(BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnCdmAttached),
xhwang9bd8c732015-04-13 23:27:53801 ToWebContentDecryptionModuleImpl(cdm)->GetCdmContext());
xhwang97de4202014-11-25 08:44:01802}
803
xhwange8c4181a2014-12-06 08:10:01804void WebMediaPlayerImpl::OnEncryptedMediaInitData(
jrummellcf78967c2015-04-03 05:03:58805 EmeInitDataType init_data_type,
Avi Drissman97785ea2015-12-19 01:11:31806 const std::vector<uint8_t>& init_data) {
jrummellcf78967c2015-04-03 05:03:58807 DCHECK(init_data_type != EmeInitDataType::UNKNOWN);
xhwangbab66f52014-12-02 23:49:50808
ddorwin301ccdb2016-02-25 02:39:17809 // TODO(xhwang): Update this UMA name. https://crbug.com/589251
xhwangbab66f52014-12-02 23:49:50810 UMA_HISTOGRAM_COUNTS("Media.EME.NeedKey", 1);
811
srirama.m26f864d02015-07-14 05:21:46812 encrypted_client_->encrypted(
davidbenb50f00c2015-12-01 00:01:50813 ConvertToWebInitDataType(init_data_type), init_data.data(),
srirama.m26f864d02015-07-14 05:21:46814 base::saturated_cast<unsigned int>(init_data.size()));
xhwangbab66f52014-12-02 23:49:50815}
816
servolk81e01e02016-03-05 03:29:15817void WebMediaPlayerImpl::OnFFmpegMediaTracksUpdated(
818 scoped_ptr<MediaTracks> tracks) {
819 // For MSE/chunk_demuxer case the media track updates are handled by
820 // WebSourceBufferImpl.
821 DCHECK(demuxer_.get());
822 DCHECK(!chunk_demuxer_);
servolkef1e5ef2016-03-25 04:55:26823
824 // Report the media track information to blink.
825 for (const auto& track : tracks->tracks()) {
826 if (track->type() == MediaTrack::Audio) {
827 auto track_id = client_->addAudioTrack(
828 blink::WebString::fromUTF8(track->id()),
829 blink::WebMediaPlayerClient::AudioTrackKindMain,
830 blink::WebString::fromUTF8(track->label()),
831 blink::WebString::fromUTF8(track->language()),
832 /*enabled*/ true);
833 (void)track_id;
834 } else if (track->type() == MediaTrack::Video) {
835 auto track_id = client_->addVideoTrack(
836 blink::WebString::fromUTF8(track->id()),
837 blink::WebMediaPlayerClient::VideoTrackKindMain,
838 blink::WebString::fromUTF8(track->label()),
839 blink::WebString::fromUTF8(track->language()),
840 /*selected*/ true);
841 (void)track_id;
842 } else {
843 // Text tracks are not supported through this code path yet.
844 NOTREACHED();
845 }
846 }
servolk81e01e02016-03-05 03:29:15847}
848
jrummell74fc4f942015-03-02 22:48:27849void WebMediaPlayerImpl::OnWaitingForDecryptionKey() {
srirama.m26f864d02015-07-14 05:21:46850 encrypted_client_->didBlockPlaybackWaitingForKey();
jrummell74fc4f942015-03-02 22:48:27851
852 // TODO(jrummell): didResumePlaybackBlockedForKey() should only be called
853 // when a key has been successfully added (e.g. OnSessionKeysChange() with
854 // |has_additional_usable_key| = true). http://crbug.com/461903
srirama.m26f864d02015-07-14 05:21:46855 encrypted_client_->didResumePlaybackBlockedForKey();
jrummell74fc4f942015-03-02 22:48:27856}
857
xhwang9bd8c732015-04-13 23:27:53858void WebMediaPlayerImpl::SetCdm(const CdmAttachedCB& cdm_attached_cb,
859 CdmContext* cdm_context) {
xhwang80739452016-01-13 00:48:00860 if (!cdm_context) {
861 cdm_attached_cb.Run(false);
862 return;
863 }
864
jrummell87a2db52015-05-05 22:27:18865 // If CDM initialization succeeded, tell the pipeline about it.
xhwang80739452016-01-13 00:48:00866 pipeline_.SetCdm(cdm_context, cdm_attached_cb);
xhwang97de4202014-11-25 08:44:01867}
868
jrummell89e61d82015-07-23 20:03:34869void WebMediaPlayerImpl::OnCdmAttached(bool success) {
xhwang97de4202014-11-25 08:44:01870 if (success) {
jrummell89e61d82015-07-23 20:03:34871 set_cdm_result_->complete();
872 set_cdm_result_.reset();
xhwang80739452016-01-13 00:48:00873 is_cdm_attached_ = true;
xhwang97de4202014-11-25 08:44:01874 return;
875 }
876
jrummell89e61d82015-07-23 20:03:34877 set_cdm_result_->completeWithError(
xhwang97de4202014-11-25 08:44:01878 blink::WebContentDecryptionModuleExceptionNotSupportedError, 0,
879 "Unable to set MediaKeys object");
jrummell89e61d82015-07-23 20:03:34880 set_cdm_result_.reset();
[email protected]9ebc3b03f2014-08-13 04:01:23881}
882
sandersd1c0bba02016-03-04 23:14:08883void WebMediaPlayerImpl::OnPipelineSeeked(bool time_updated) {
[email protected]5d11eff2011-09-15 00:06:06884 seeking_ = false;
wolenetz1b2ae7d2015-06-10 00:44:21885 seek_time_ = base::TimeDelta();
hubbe5a2dec022016-03-17 01:14:23886 if (paused_) {
887#if defined(OS_ANDROID) // WMPI_CAST
888 if (isRemote()) {
889 paused_time_ = base::TimeDelta::FromSecondsD(cast_impl_.currentTime());
890 } else {
891 paused_time_ = pipeline_.GetMediaTime();
892 }
893#else
sandersd1c0bba02016-03-04 23:14:08894 paused_time_ = pipeline_.GetMediaTime();
hubbe5a2dec022016-03-17 01:14:23895#endif
896 }
sandersd1c0bba02016-03-04 23:14:08897 if (time_updated)
898 should_notify_time_changed_ = true;
[email protected]8931c41a2009-07-07 17:31:49899}
900
sandersd1c0bba02016-03-04 23:14:08901void WebMediaPlayerImpl::OnPipelineSuspended() {
hubbed5f36882016-01-15 22:40:37902#if defined(OS_ANDROID)
903 if (isRemote()) {
dalecurtis6b916612016-03-22 20:42:36904 if (delegate_)
905 delegate_->PlayerGone(delegate_id_);
hubbed5f36882016-01-15 22:40:37906 scoped_refptr<VideoFrame> frame = cast_impl_.GetCastingBanner();
907 if (frame) {
908 compositor_->PaintFrameUsingOldRenderingPath(frame);
909 }
910 }
911#endif
912
dalecurtis3a7d38f42016-03-07 21:17:13913 memory_usage_reporting_timer_.Stop();
914 ReportMemoryUsage();
sandersd1c0bba02016-03-04 23:14:08915
dalecurtis37fe5862016-03-15 19:29:09916 // If we're not in an aggressive buffering state, tell the data source we have
917 // enough data so that it may release the connection.
918 if (buffering_strategy_ !=
919 BufferedDataSource::BUFFERING_STRATEGY_AGGRESSIVE) {
liberato3f9f32b2016-03-16 16:54:51920 if (data_source_)
921 data_source_->OnBufferingHaveEnough(true);
dalecurtis37fe5862016-03-15 19:29:09922 }
923
sandersd1c0bba02016-03-04 23:14:08924 if (pending_suspend_resume_cycle_) {
watkdee516f2016-02-18 02:22:19925 pending_suspend_resume_cycle_ = false;
sandersd1c0bba02016-03-04 23:14:08926 pipeline_controller_.Resume();
sandersd1e49fb62015-12-12 01:18:06927 return;
928 }
929}
930
sandersd1c0bba02016-03-04 23:14:08931void WebMediaPlayerImpl::OnPipelineResumed() {
dalecurtis0431cbf2016-03-12 01:19:43932 if (playback_rate_ > 0 && !paused_) {
sandersd1c0bba02016-03-04 23:14:08933 NotifyPlaybackStarted();
dalecurtis0431cbf2016-03-12 01:19:43934 } else if (!playback_rate_ || paused_ || ended_) {
935 // Resend our paused notification so the pipeline is considered for idle
936 // resource reclamation; duplicate pause notifications are ignored.
937 NotifyPlaybackPaused();
938 }
sandersd1c0bba02016-03-04 23:14:08939}
940
[email protected]6954fe12013-01-03 03:22:32941void WebMediaPlayerImpl::OnPipelineEnded() {
[email protected]2a06ca62014-06-04 13:59:52942 DVLOG(1) << __FUNCTION__;
acolwellb4034942014-08-28 15:42:43943 DCHECK(main_task_runner_->BelongsToCurrentThread());
scherkusd2c745b2014-09-04 05:03:40944
sandersd1c0bba02016-03-04 23:14:08945 // Ignore state changes until we've completed all outstanding operations.
946 if (!pipeline_controller_.IsStable())
scherkusd2c745b2014-09-04 05:03:40947 return;
948
949 ended_ = true;
[email protected]ce70c982013-12-20 17:04:32950 client_->timeChanged();
[email protected]576537842009-08-12 23:52:05951}
952
[email protected]a9590c22011-03-16 16:57:02953void WebMediaPlayerImpl::OnPipelineError(PipelineStatus error) {
hubbed82bed52015-12-15 23:07:16954 DVLOG(1) << __FUNCTION__;
acolwellb4034942014-08-28 15:42:43955 DCHECK(main_task_runner_->BelongsToCurrentThread());
acolwell9e0840d2014-09-06 19:01:32956 DCHECK_NE(error, PIPELINE_OK);
[email protected]a8e2cb82012-08-17 00:02:39957
dalecurtis2ff781da2016-03-03 01:52:13958 if (suppress_destruction_errors_)
959 return;
960
dalecurtis600306632016-03-19 00:28:34961 // Release the delegate for player errors; this drops the media session and
962 // avoids idle suspension from ticking.
963 if (delegate_)
964 delegate_->PlayerGone(delegate_id_);
965
dalecurtis6e3901e2016-03-16 20:51:08966#if defined(OS_ANDROID)
967 // For 10% of pipeline decode failures log the playback URL. The URL is set
968 // as the crash-key 'subresource_url' during DoLoad().
969 //
970 // TODO(dalecurtis): This is temporary to track down higher than average
971 // decode failure rates for video-only content. See http://crbug.com/595076.
972 if (base::RandDouble() <= 0.1 && error == PIPELINE_ERROR_DECODE)
973 base::debug::DumpWithoutCrashing();
974#endif
975
dalecurtis2ff781da2016-03-03 01:52:13976 media_log_->AddEvent(media_log_->CreatePipelineErrorEvent(error));
977
[email protected]a8e2cb82012-08-17 00:02:39978 if (ready_state_ == WebMediaPlayer::ReadyStateHaveNothing) {
979 // Any error that occurs before reaching ReadyStateHaveMetadata should
980 // be considered a format error.
981 SetNetworkState(WebMediaPlayer::NetworkStateFormatError);
[email protected]a8e2cb82012-08-17 00:02:39982 return;
983 }
984
[email protected]be57ee52013-05-28 22:27:27985 SetNetworkState(PipelineErrorToNetworkState(error));
[email protected]db190487d2009-07-30 18:51:52986}
987
[email protected]b8877772014-03-26 20:17:15988void WebMediaPlayerImpl::OnPipelineMetadata(
acolwell9e0840d2014-09-06 19:01:32989 PipelineMetadata metadata) {
[email protected]2a06ca62014-06-04 13:59:52990 DVLOG(1) << __FUNCTION__;
[email protected]a8e2cb82012-08-17 00:02:39991
[email protected]b8877772014-03-26 20:17:15992 pipeline_metadata_ = metadata;
[email protected]739847c02014-01-16 00:12:25993
dalecurtis849cf4b22015-03-27 18:35:45994 UMA_HISTOGRAM_ENUMERATION("Media.VideoRotation", metadata.video_rotation,
acolwell9e0840d2014-09-06 19:01:32995 VIDEO_ROTATION_MAX + 1);
[email protected]b8877772014-03-26 20:17:15996 SetReadyState(WebMediaPlayer::ReadyStateHaveMetadata);
[email protected]21c3f7502013-03-23 03:29:51997
[email protected]b8877772014-03-26 20:17:15998 if (hasVideo()) {
999 DCHECK(!video_weblayer_);
loyso0940d412016-03-14 01:30:311000 scoped_refptr<cc::VideoLayer> layer =
1001 cc::VideoLayer::Create(compositor_, pipeline_metadata_.video_rotation);
[email protected]f78c3e82014-08-08 01:24:471002
acolwell9e0840d2014-09-06 19:01:321003 if (pipeline_metadata_.video_rotation == VIDEO_ROTATION_90 ||
1004 pipeline_metadata_.video_rotation == VIDEO_ROTATION_270) {
[email protected]f78c3e82014-08-08 01:24:471005 gfx::Size size = pipeline_metadata_.natural_size;
1006 pipeline_metadata_.natural_size = gfx::Size(size.height(), size.width());
1007 }
1008
[email protected]38564622014-08-19 02:47:181009 video_weblayer_.reset(new cc_blink::WebLayerImpl(layer));
jbauman952274d2015-09-10 23:23:361010 video_weblayer_->layer()->SetContentsOpaque(opaque_);
1011 video_weblayer_->SetContentsOpaqueIsFixed(true);
[email protected]a7c4f582014-04-16 18:44:491012 client_->setWebLayer(video_weblayer_.get());
[email protected]a8e2cb82012-08-17 00:02:391013 }
dalecurtis8e4dc682016-03-15 02:30:301014
1015 // Tell the delegate we can now be safely suspended due to inactivity if a
1016 // subsequent play event does not occur.
1017 if (paused_)
1018 NotifyPlaybackPaused();
sandersd520b46bd2016-03-21 21:18:441019
1020 // If the frame is hidden, it may be time to suspend playback.
1021 if (delegate_ && delegate_->IsHidden())
1022 OnHidden();
[email protected]a8e2cb82012-08-17 00:02:391023}
1024
[email protected]ba7d5f92014-06-24 05:37:401025void WebMediaPlayerImpl::OnPipelineBufferingStateChanged(
acolwell9e0840d2014-09-06 19:01:321026 BufferingState buffering_state) {
[email protected]ba7d5f92014-06-24 05:37:401027 DVLOG(1) << __FUNCTION__ << "(" << buffering_state << ")";
[email protected]b8877772014-03-26 20:17:151028
sandersd1c0bba02016-03-04 23:14:081029 // Ignore buffering state changes until we've completed all outstanding
1030 // operations.
1031 if (!pipeline_controller_.IsStable())
[email protected]ba7d5f92014-06-24 05:37:401032 return;
[email protected]b8877772014-03-26 20:17:151033
[email protected]ba7d5f92014-06-24 05:37:401034 // TODO(scherkus): Handle other buffering states when Pipeline starts using
1035 // them and translate them ready state changes http://crbug.com/144683
acolwell9e0840d2014-09-06 19:01:321036 DCHECK_EQ(buffering_state, BUFFERING_HAVE_ENOUGH);
[email protected]ba7d5f92014-06-24 05:37:401037 SetReadyState(WebMediaPlayer::ReadyStateHaveEnoughData);
1038
dalecurtis849cf4b22015-03-27 18:35:451039 // Let the DataSource know we have enough data. It may use this information to
1040 // release unused network connections.
1041 if (data_source_)
dalecurtis37fe5862016-03-15 19:29:091042 data_source_->OnBufferingHaveEnough(false);
dalecurtis849cf4b22015-03-27 18:35:451043
[email protected]ba7d5f92014-06-24 05:37:401044 // Blink expects a timeChanged() in response to a seek().
1045 if (should_notify_time_changed_)
1046 client_->timeChanged();
dalecurtis0f0097a2015-12-01 17:40:471047
1048 // Once we have enough, start reporting the total memory usage. We'll also
1049 // report once playback starts.
1050 ReportMemoryUsage();
[email protected]b8877772014-03-26 20:17:151051}
1052
[email protected]ef8394c2013-08-21 20:26:301053void WebMediaPlayerImpl::OnDemuxerOpened() {
acolwellb4034942014-08-28 15:42:431054 DCHECK(main_task_runner_->BelongsToCurrentThread());
wolenetz1fb319d2015-07-14 17:49:041055 client_->mediaSourceOpened(
1056 new WebMediaSourceImpl(chunk_demuxer_, media_log_));
[email protected]81bb3322011-07-21 15:55:501057}
1058
[email protected]8a561062013-11-22 01:19:311059void WebMediaPlayerImpl::OnAddTextTrack(
acolwell9e0840d2014-09-06 19:01:321060 const TextTrackConfig& config,
1061 const AddTextTrackDoneCB& done_cb) {
acolwellb4034942014-08-28 15:42:431062 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]71537722013-05-23 06:47:531063
[email protected]8a561062013-11-22 01:19:311064 const WebInbandTextTrackImpl::Kind web_kind =
1065 static_cast<WebInbandTextTrackImpl::Kind>(config.kind());
1066 const blink::WebString web_label =
1067 blink::WebString::fromUTF8(config.label());
1068 const blink::WebString web_language =
1069 blink::WebString::fromUTF8(config.language());
[email protected]427ff102013-11-26 23:45:401070 const blink::WebString web_id =
1071 blink::WebString::fromUTF8(config.id());
[email protected]71537722013-05-23 06:47:531072
[email protected]8a561062013-11-22 01:19:311073 scoped_ptr<WebInbandTextTrackImpl> web_inband_text_track(
henriks9cce5fa2014-12-12 09:35:301074 new WebInbandTextTrackImpl(web_kind, web_label, web_language, web_id));
[email protected]8a561062013-11-22 01:19:311075
servolk92333c0e2016-03-30 17:13:461076 scoped_ptr<media::TextTrack> text_track(new TextTrackImpl(
dcheng652f5ff2015-12-27 08:54:001077 main_task_runner_, client_, std::move(web_inband_text_track)));
[email protected]8a561062013-11-22 01:19:311078
dcheng652f5ff2015-12-27 08:54:001079 done_cb.Run(std::move(text_track));
[email protected]71537722013-05-23 06:47:531080}
1081
dalecurtis0431cbf2016-03-12 01:19:431082void WebMediaPlayerImpl::OnHidden() {
sandersd1e49fb62015-12-12 01:18:061083 DCHECK(main_task_runner_->BelongsToCurrentThread());
dalecurtis0431cbf2016-03-12 01:19:431084 if (!IsSuspendUponHiddenEnabled())
sandersd1e49fb62015-12-12 01:18:061085 return;
sandersd1e49fb62015-12-12 01:18:061086
dalecurtis0431cbf2016-03-12 01:19:431087#if defined(OS_ANDROID) // WMPI_CAST
hubbed5f36882016-01-15 22:40:371088 // If we're remote, the pipeline should already be suspended.
1089 if (isRemote())
1090 return;
1091#endif
1092
sandersd520b46bd2016-03-21 21:18:441093 // Don't suspend before metadata is available, as we don't know if there is a
1094 // video track yet.
1095 if (ready_state_ < WebMediaPlayer::ReadyStateHaveMetadata)
1096 return;
1097
dalecurtis0431cbf2016-03-12 01:19:431098 // Don't suspend players which only have audio and have not completed
1099 // playback. The user can still control these players via the MediaSession UI.
1100 // If the player has never started playback, OnSuspendRequested() will handle
1101 // release of any idle resources.
1102 if (!hasVideo() && !paused_ && !ended_)
1103 return;
1104
dalecurtis37fe5862016-03-15 19:29:091105 // Always reset the buffering strategy to normal when suspending for hidden to
1106 // prevent an idle network connection from lingering.
1107 setBufferingStrategy(WebMediaPlayer::BufferingStrategy::Normal);
dalecurtis0431cbf2016-03-12 01:19:431108 pipeline_controller_.Suspend();
watk01dc0132016-03-23 23:10:401109 // If we're in the middle of a suspend/resume cycle we no longer want to
1110 // resume when the suspend completes.
1111 pending_suspend_resume_cycle_ = false;
dalecurtis0431cbf2016-03-12 01:19:431112 if (delegate_)
1113 delegate_->PlayerGone(delegate_id_);
sandersd1e49fb62015-12-12 01:18:061114}
1115
1116void WebMediaPlayerImpl::OnShown() {
1117 DCHECK(main_task_runner_->BelongsToCurrentThread());
dalecurtis0431cbf2016-03-12 01:19:431118 if (!IsSuspendUponHiddenEnabled())
sandersd1e49fb62015-12-12 01:18:061119 return;
sandersd1e49fb62015-12-12 01:18:061120
dalecurtis0431cbf2016-03-12 01:19:431121#if defined(OS_ANDROID) // WMPI_CAST
hubbed5f36882016-01-15 22:40:371122 // If we're remote, the pipeline should stay suspended.
1123 if (isRemote())
1124 return;
1125#endif
1126
sandersd520b46bd2016-03-21 21:18:441127 // If we do not yet have metadata, the only way we could have been suspended
1128 // is by a OnSuspendRequested() with |must_suspend| set. In that case we need
1129 // to resume, otherwise playback will be broken.
1130 //
1131 // Otherwise, resume if we should be playing.
1132 if (ready_state_ < WebMediaPlayer::ReadyStateHaveMetadata ||
1133 (!ended_ && !paused_)) {
sandersd1c0bba02016-03-04 23:14:081134 pipeline_controller_.Resume();
sandersd520b46bd2016-03-21 21:18:441135 }
sandersd1e49fb62015-12-12 01:18:061136}
1137
dalecurtis0431cbf2016-03-12 01:19:431138void WebMediaPlayerImpl::OnSuspendRequested(bool must_suspend) {
1139 DCHECK(main_task_runner_->BelongsToCurrentThread());
1140
1141#if defined(OS_ANDROID) // WMPI_CAST
1142 // If we're remote, the pipeline should already be suspended.
1143 if (isRemote())
1144 return;
1145#endif
1146
dalecurtis8413f9ef2016-03-17 19:23:331147#if defined(OS_MACOSX)
1148 // TODO(sandersd): Idle suspend is disabled on OSX since hardware decoded
1149 // frames are owned by the video decoder in the GPU process. A mechanism for
1150 // detaching ownership from the decoder is needed. http://crbug.com/595716.
1151 return;
1152#else
dalecurtis0431cbf2016-03-12 01:19:431153 // Suspend should never be requested unless required or we're already in an
1154 // idle state (paused or ended).
1155 DCHECK(must_suspend || paused_ || ended_);
1156
1157 // Always suspend, but only notify the delegate if we must; this allows any
1158 // exposed UI for player controls to continue to function even though the
1159 // player has now been suspended.
1160 pipeline_controller_.Suspend();
1161 if (must_suspend && delegate_)
1162 delegate_->PlayerGone(delegate_id_);
dalecurtis8413f9ef2016-03-17 19:23:331163#endif
dalecurtis0431cbf2016-03-12 01:19:431164}
1165
dalecurtisbb3eaac2016-01-27 21:10:251166void WebMediaPlayerImpl::OnPlay() {
1167 play();
1168 client_->playbackStateChanged();
1169}
1170
1171void WebMediaPlayerImpl::OnPause() {
1172 pause();
1173 client_->playbackStateChanged();
1174}
1175
1176void WebMediaPlayerImpl::OnVolumeMultiplierUpdate(double multiplier) {
1177 volume_multiplier_ = multiplier;
1178 setVolume(volume_);
1179}
1180
watkdee516f2016-02-18 02:22:191181void WebMediaPlayerImpl::ScheduleRestart() {
sandersd1c0bba02016-03-04 23:14:081182 if (!pipeline_controller_.IsSuspended()) {
watkdee516f2016-02-18 02:22:191183 pending_suspend_resume_cycle_ = true;
sandersd1c0bba02016-03-04 23:14:081184 pipeline_controller_.Suspend();
watkdee516f2016-02-18 02:22:191185 }
1186}
1187
hubbed5f36882016-01-15 22:40:371188#if defined(OS_ANDROID) // WMPI_CAST
hubbed5f36882016-01-15 22:40:371189bool WebMediaPlayerImpl::isRemote() const {
1190 return cast_impl_.isRemote();
1191}
1192
1193void WebMediaPlayerImpl::SetMediaPlayerManager(
1194 RendererMediaPlayerManagerInterface* media_player_manager) {
1195 cast_impl_.SetMediaPlayerManager(media_player_manager);
1196}
1197
1198void WebMediaPlayerImpl::requestRemotePlayback() {
1199 cast_impl_.requestRemotePlayback();
1200}
1201
1202void WebMediaPlayerImpl::requestRemotePlaybackControl() {
1203 cast_impl_.requestRemotePlaybackControl();
1204}
1205
1206void WebMediaPlayerImpl::OnRemotePlaybackEnded() {
1207 DVLOG(1) << __FUNCTION__;
1208 DCHECK(main_task_runner_->BelongsToCurrentThread());
1209
1210 ended_ = true;
1211 client_->timeChanged();
1212}
1213
1214void WebMediaPlayerImpl::OnDisconnectedFromRemoteDevice(double t) {
sandersd1c0bba02016-03-04 23:14:081215 DoSeek(base::TimeDelta::FromSecondsD(t), false);
1216 if (delegate_ && !delegate_->IsHidden())
1217 pipeline_controller_.Resume();
hubbed5f36882016-01-15 22:40:371218
hubbed5f36882016-01-15 22:40:371219 // We already told the delegate we're paused when remoting started.
1220 client_->playbackStateChanged();
1221 client_->disconnectedFromRemoteDevice();
1222}
1223
1224void WebMediaPlayerImpl::SuspendForRemote() {
sandersd1c0bba02016-03-04 23:14:081225 if (!pipeline_controller_.IsSuspended()) {
1226 pipeline_controller_.Suspend();
1227 } else {
1228 // TODO(sandersd): If PipelineController::Suspend() called |suspended_cb|
1229 // when already suspended, we wouldn't need this case.
hubbed5f36882016-01-15 22:40:371230 scoped_refptr<VideoFrame> frame = cast_impl_.GetCastingBanner();
1231 if (frame) {
1232 compositor_->PaintFrameUsingOldRenderingPath(frame);
1233 }
1234 }
hubbed5f36882016-01-15 22:40:371235}
1236
1237gfx::Size WebMediaPlayerImpl::GetCanvasSize() const {
1238 if (!video_weblayer_)
1239 return pipeline_metadata_.natural_size;
1240
1241 return video_weblayer_->bounds();
1242}
1243
1244void WebMediaPlayerImpl::SetDeviceScaleFactor(float scale_factor) {
1245 cast_impl_.SetDeviceScaleFactor(scale_factor);
1246}
1247#endif // defined(OS_ANDROID) // WMPI_CAST
1248
[email protected]fee8a902014-06-03 13:43:361249void WebMediaPlayerImpl::DataSourceInitialized(bool success) {
hubbed82bed52015-12-15 23:07:161250 DVLOG(1) << __FUNCTION__;
acolwellb4034942014-08-28 15:42:431251 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]a9415292012-01-19 19:55:201252
[email protected]d250190da3b2012-07-23 22:57:301253 if (!success) {
[email protected]ef405f66b2012-04-18 02:39:551254 SetNetworkState(WebMediaPlayer::NetworkStateFormatError);
[email protected]a9415292012-01-19 19:55:201255 return;
1256 }
1257
[email protected]ef8394c2013-08-21 20:26:301258 StartPipeline();
[email protected]a9415292012-01-19 19:55:201259}
1260
[email protected]122f40252012-06-12 05:01:561261void WebMediaPlayerImpl::NotifyDownloading(bool is_downloading) {
hubbed82bed52015-12-15 23:07:161262 DVLOG(1) << __FUNCTION__;
[email protected]122f40252012-06-12 05:01:561263 if (!is_downloading && network_state_ == WebMediaPlayer::NetworkStateLoading)
1264 SetNetworkState(WebMediaPlayer::NetworkStateIdle);
1265 else if (is_downloading && network_state_ == WebMediaPlayer::NetworkStateIdle)
1266 SetNetworkState(WebMediaPlayer::NetworkStateLoading);
1267 media_log_->AddEvent(
1268 media_log_->CreateBooleanEvent(
acolwell9e0840d2014-09-06 19:01:321269 MediaLogEvent::NETWORK_ACTIVITY_SET,
[email protected]122f40252012-06-12 05:01:561270 "is_downloading_data", is_downloading));
1271}
1272
watkdee516f2016-02-18 02:22:191273// TODO(watk): Move this state management out of WMPI.
1274void WebMediaPlayerImpl::OnSurfaceRequested(
1275 const SurfaceCreatedCB& surface_created_cb) {
1276 DCHECK(main_task_runner_->BelongsToCurrentThread());
1277 DCHECK(surface_manager_);
1278
1279 // A null callback indicates that the decoder is going away.
1280 if (surface_created_cb.is_null()) {
1281 decoder_requires_restart_for_fullscreen_ = false;
1282 return;
1283 }
1284
1285 // If we're getting a surface request it means GVD is initializing, so until
1286 // we get a null surface request, GVD is the active decoder. While that's the
1287 // case we should restart the pipeline on fullscreen transitions so that when
1288 // we create a new GVD it will request a surface again and get the right kind
1289 // of surface for the fullscreen state.
1290 // TODO(watk): Don't require a pipeline restart to switch surfaces for
1291 // cases where it isn't necessary.
1292 decoder_requires_restart_for_fullscreen_ = true;
1293 if (fullscreen_) {
1294 surface_manager_->CreateFullscreenSurface(pipeline_metadata_.natural_size,
1295 surface_created_cb);
1296 } else {
1297 // Tell the decoder to create its own surface.
1298 surface_created_cb.Run(SurfaceManager::kNoSurfaceID);
1299 }
1300}
1301
sandersd1e49fb62015-12-12 01:18:061302scoped_ptr<Renderer> WebMediaPlayerImpl::CreateRenderer() {
watkdee516f2016-02-18 02:22:191303 RequestSurfaceCB request_surface_cb;
1304#if defined(OS_ANDROID)
1305 request_surface_cb =
1306 BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnSurfaceRequested);
1307#endif
sandersd1e49fb62015-12-12 01:18:061308 return renderer_factory_->CreateRenderer(
1309 media_task_runner_, worker_task_runner_, audio_source_provider_.get(),
watkdee516f2016-02-18 02:22:191310 compositor_, request_surface_cb);
sandersd1e49fb62015-12-12 01:18:061311}
1312
[email protected]ef8394c2013-08-21 20:26:301313void WebMediaPlayerImpl::StartPipeline() {
acolwellb4034942014-08-28 15:42:431314 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]ddbc6ff2013-04-19 15:28:331315
xhwange8c4181a2014-12-06 08:10:011316 Demuxer::EncryptedMediaInitDataCB encrypted_media_init_data_cb =
1317 BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnEncryptedMediaInitData);
[email protected]2b57e2e2014-05-09 11:07:251318
[email protected]ddbc6ff2013-04-19 15:28:331319 // Figure out which demuxer to use.
[email protected]ef8394c2013-08-21 20:26:301320 if (load_type_ != LoadTypeMediaSource) {
[email protected]ddbc6ff2013-04-19 15:28:331321 DCHECK(!chunk_demuxer_);
[email protected]f5443ef72013-04-22 04:03:381322 DCHECK(data_source_);
1323
j.isorcef6778e652015-11-16 17:14:251324#if !defined(MEDIA_DISABLE_FFMPEG)
servolk81e01e02016-03-05 03:29:151325 Demuxer::MediaTracksUpdatedCB media_tracks_updated_cb =
servolkef1e5ef2016-03-25 04:55:261326 BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnFFmpegMediaTracksUpdated);
servolk81e01e02016-03-05 03:29:151327
xhwange8c4181a2014-12-06 08:10:011328 demuxer_.reset(new FFmpegDemuxer(media_task_runner_, data_source_.get(),
servolk81e01e02016-03-05 03:29:151329 encrypted_media_init_data_cb,
1330 media_tracks_updated_cb, media_log_));
j.isorcef6778e652015-11-16 17:14:251331#else
1332 OnPipelineError(PipelineStatus::DEMUXER_ERROR_COULD_NOT_OPEN);
1333 return;
1334#endif
[email protected]ddbc6ff2013-04-19 15:28:331335 } else {
[email protected]f5443ef72013-04-22 04:03:381336 DCHECK(!chunk_demuxer_);
1337 DCHECK(!data_source_);
1338
acolwell9e0840d2014-09-06 19:01:321339 chunk_demuxer_ = new ChunkDemuxer(
[email protected]ef8394c2013-08-21 20:26:301340 BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnDemuxerOpened),
wolenetz1fb319d2015-07-14 17:49:041341 encrypted_media_init_data_cb, media_log_, true);
[email protected]f5443ef72013-04-22 04:03:381342 demuxer_.reset(chunk_demuxer_);
[email protected]ddbc6ff2013-04-19 15:28:331343 }
1344
sandersdb5e21462016-03-09 01:49:071345 // TODO(sandersd): FileSystem objects may also be non-static, but due to our
1346 // caching layer such situations are broken already. http://crbug.com/593159
1347 bool is_static = !chunk_demuxer_;
1348
[email protected]f5443ef72013-04-22 04:03:381349 // ... and we're ready to go!
[email protected]d228aeec2014-06-20 19:16:491350 seeking_ = true;
xhwangf94a634d2014-10-22 22:07:271351
sandersd1e49fb62015-12-12 01:18:061352 // TODO(sandersd): On Android, defer Start() if the tab is not visible.
sandersd1c0bba02016-03-04 23:14:081353 bool is_streaming = (data_source_ && data_source_->IsStreaming());
1354 pipeline_controller_.Start(
sandersdb5e21462016-03-09 01:49:071355 demuxer_.get(), is_streaming, is_static,
[email protected]f5443ef72013-04-22 04:03:381356 BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnPipelineEnded),
[email protected]b8877772014-03-26 20:17:151357 BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnPipelineMetadata),
[email protected]ba7d5f92014-06-24 05:37:401358 BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnPipelineBufferingStateChanged),
xhwang59805902014-08-29 01:44:151359 BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnDurationChanged),
jrummell74fc4f942015-03-02 22:48:271360 BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnAddTextTrack),
1361 BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnWaitingForDecryptionKey));
[email protected]f5443ef72013-04-22 04:03:381362}
1363
1364void WebMediaPlayerImpl::SetNetworkState(WebMediaPlayer::NetworkState state) {
[email protected]2a06ca62014-06-04 13:59:521365 DVLOG(1) << __FUNCTION__ << "(" << state << ")";
acolwellb4034942014-08-28 15:42:431366 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]f5443ef72013-04-22 04:03:381367 network_state_ = state;
1368 // Always notify to ensure client has the latest value.
[email protected]ce70c982013-12-20 17:04:321369 client_->networkStateChanged();
[email protected]f5443ef72013-04-22 04:03:381370}
1371
1372void WebMediaPlayerImpl::SetReadyState(WebMediaPlayer::ReadyState state) {
[email protected]2a06ca62014-06-04 13:59:521373 DVLOG(1) << __FUNCTION__ << "(" << state << ")";
acolwellb4034942014-08-28 15:42:431374 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]f5443ef72013-04-22 04:03:381375
[email protected]fee8a902014-06-03 13:43:361376 if (state == WebMediaPlayer::ReadyStateHaveEnoughData && data_source_ &&
1377 data_source_->assume_fully_buffered() &&
[email protected]f5443ef72013-04-22 04:03:381378 network_state_ == WebMediaPlayer::NetworkStateLoading)
1379 SetNetworkState(WebMediaPlayer::NetworkStateLoaded);
1380
1381 ready_state_ = state;
1382 // Always notify to ensure client has the latest value.
[email protected]ce70c982013-12-20 17:04:321383 client_->readyStateChanged();
[email protected]f5443ef72013-04-22 04:03:381384}
1385
Dana Jansens71331252016-03-09 20:57:221386blink::WebAudioSourceProvider* WebMediaPlayerImpl::getAudioSourceProvider() {
[email protected]ff875be52013-06-02 23:47:381387 return audio_source_provider_.get();
[email protected]f5443ef72013-04-22 04:03:381388}
1389
[email protected]f5443ef72013-04-22 04:03:381390double WebMediaPlayerImpl::GetPipelineDuration() const {
[email protected]f6af7592014-02-28 10:09:111391 base::TimeDelta duration = pipeline_.GetMediaDuration();
[email protected]f5443ef72013-04-22 04:03:381392
1393 // Return positive infinity if the resource is unbounded.
1394 // http://www.whatwg.org/specs/web-apps/current-work/multipage/video.html#dom-media-duration
acolwell9e0840d2014-09-06 19:01:321395 if (duration == kInfiniteDuration())
[email protected]f5443ef72013-04-22 04:03:381396 return std::numeric_limits<double>::infinity();
1397
1398 return duration.InSecondsF();
1399}
1400
[email protected]75e145a2014-04-15 17:44:321401void WebMediaPlayerImpl::OnDurationChanged() {
[email protected]f5443ef72013-04-22 04:03:381402 if (ready_state_ == WebMediaPlayer::ReadyStateHaveNothing)
1403 return;
1404
[email protected]ce70c982013-12-20 17:04:321405 client_->durationChanged();
[email protected]f5443ef72013-04-22 04:03:381406}
1407
[email protected]75e145a2014-04-15 17:44:321408void WebMediaPlayerImpl::OnNaturalSizeChanged(gfx::Size size) {
acolwellb4034942014-08-28 15:42:431409 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]739847c02014-01-16 00:12:251410 DCHECK_NE(ready_state_, WebMediaPlayer::ReadyStateHaveNothing);
1411 TRACE_EVENT0("media", "WebMediaPlayerImpl::OnNaturalSizeChanged");
1412
1413 media_log_->AddEvent(
1414 media_log_->CreateVideoSizeSetEvent(size.width(), size.height()));
[email protected]739847c02014-01-16 00:12:251415
watkdee516f2016-02-18 02:22:191416 if (fullscreen_ && surface_manager_ &&
1417 pipeline_metadata_.natural_size != size) {
1418 surface_manager_->NaturalSizeChanged(size);
1419 }
1420
1421 pipeline_metadata_.natural_size = size;
[email protected]739847c02014-01-16 00:12:251422 client_->sizeChanged();
1423}
1424
[email protected]75e145a2014-04-15 17:44:321425void WebMediaPlayerImpl::OnOpacityChanged(bool opaque) {
acolwellb4034942014-08-28 15:42:431426 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]75e145a2014-04-15 17:44:321427 DCHECK_NE(ready_state_, WebMediaPlayer::ReadyStateHaveNothing);
1428
1429 opaque_ = opaque;
jbauman952274d2015-09-10 23:23:361430 // Modify content opaqueness of cc::Layer directly so that
1431 // SetContentsOpaqueIsFixed is ignored.
[email protected]75e145a2014-04-15 17:44:321432 if (video_weblayer_)
jbauman952274d2015-09-10 23:23:361433 video_weblayer_->layer()->SetContentsOpaque(opaque_);
[email protected]75e145a2014-04-15 17:44:321434}
1435
[email protected]dd061e12014-05-06 19:21:221436static void GetCurrentFrameAndSignal(
1437 VideoFrameCompositor* compositor,
acolwell9e0840d2014-09-06 19:01:321438 scoped_refptr<VideoFrame>* video_frame_out,
[email protected]dd061e12014-05-06 19:21:221439 base::WaitableEvent* event) {
1440 TRACE_EVENT0("media", "GetCurrentFrameAndSignal");
dalecurtis44ce4de2015-05-11 18:42:071441 *video_frame_out = compositor->GetCurrentFrameAndUpdateIfStale();
[email protected]dd061e12014-05-06 19:21:221442 event->Signal();
1443}
1444
acolwell9e0840d2014-09-06 19:01:321445scoped_refptr<VideoFrame>
[email protected]dd061e12014-05-06 19:21:221446WebMediaPlayerImpl::GetCurrentFrameFromCompositor() {
1447 TRACE_EVENT0("media", "WebMediaPlayerImpl::GetCurrentFrameFromCompositor");
1448 if (compositor_task_runner_->BelongsToCurrentThread())
dalecurtis44ce4de2015-05-11 18:42:071449 return compositor_->GetCurrentFrameAndUpdateIfStale();
[email protected]dd061e12014-05-06 19:21:221450
1451 // Use a posted task and waitable event instead of a lock otherwise
1452 // WebGL/Canvas can see different content than what the compositor is seeing.
acolwell9e0840d2014-09-06 19:01:321453 scoped_refptr<VideoFrame> video_frame;
[email protected]dd061e12014-05-06 19:21:221454 base::WaitableEvent event(false, false);
1455 compositor_task_runner_->PostTask(FROM_HERE,
1456 base::Bind(&GetCurrentFrameAndSignal,
1457 base::Unretained(compositor_),
1458 &video_frame,
1459 &event));
1460 event.Wait();
1461 return video_frame;
1462}
1463
dalecurtis0f0097a2015-12-01 17:40:471464void WebMediaPlayerImpl::NotifyPlaybackStarted() {
hubbed5f36882016-01-15 22:40:371465#if defined(OS_ANDROID) // WMPI_CAST
dalecurtis5bbc487e2016-02-27 04:15:051466 // We do not tell our delegates about remote playback, because that would
hubbed5f36882016-01-15 22:40:371467 // keep the device awake, which is not what we want.
1468 if (isRemote())
1469 return;
1470#endif
dalecurtis5bbc487e2016-02-27 04:15:051471
sandersd1c0bba02016-03-04 23:14:081472 // NotifyPlaybackStarted() may be called by interactions while suspended,
1473 // (play/pause in particular). Those actions won't have any effect until the
1474 // pipeline is resumed.
1475 // TODO(dalecurtis): Should these be dropped at the call sites instead?
1476 // Alternatively, rename this method to include Maybe or Changed, and handle
1477 // multiple calls safely.
1478 if (pipeline_controller_.IsSuspended())
dalecurtis5bbc487e2016-02-27 04:15:051479 return;
1480
dalecurtisbb3eaac2016-01-27 21:10:251481 if (delegate_) {
1482 delegate_->DidPlay(delegate_id_, hasVideo(), hasAudio(), false,
1483 pipeline_.GetMediaDuration());
1484 }
dalecurtis0f0097a2015-12-01 17:40:471485 if (!memory_usage_reporting_timer_.IsRunning()) {
1486 memory_usage_reporting_timer_.Start(FROM_HERE,
1487 base::TimeDelta::FromSeconds(2), this,
1488 &WebMediaPlayerImpl::ReportMemoryUsage);
1489 }
1490}
1491
1492void WebMediaPlayerImpl::NotifyPlaybackPaused() {
hubbed5f36882016-01-15 22:40:371493#if defined(OS_ANDROID) // WMPI_CAST
1494 if (isRemote())
1495 return;
1496#endif
sandersd1c0bba02016-03-04 23:14:081497
1498 // Same as above, NotifyPlaybackPaused() may be called by interactions while
1499 // suspended, but those actions won't have any effect until the pipeline is
1500 // resumed.
1501 if (pipeline_controller_.IsSuspended())
1502 return;
1503
1504 if (delegate_)
dalecurtisbb3eaac2016-01-27 21:10:251505 delegate_->DidPause(delegate_id_, ended_);
dalecurtis0f0097a2015-12-01 17:40:471506 memory_usage_reporting_timer_.Stop();
1507 ReportMemoryUsage();
1508}
1509
dalecurtis83266c72015-10-29 18:43:201510void WebMediaPlayerImpl::ReportMemoryUsage() {
1511 DCHECK(main_task_runner_->BelongsToCurrentThread());
1512
wdzierzanowskifd4cd91c52015-12-02 23:50:201513 // About base::Unretained() usage below: We destroy |demuxer_| on the main
1514 // thread. Before that, however, ~WebMediaPlayerImpl() posts a task to the
1515 // media thread and waits for it to finish. Hence, the GetMemoryUsage() task
1516 // posted here must finish earlier.
1517
1518 if (demuxer_) {
1519 base::PostTaskAndReplyWithResult(
1520 media_task_runner_.get(), FROM_HERE,
1521 base::Bind(&Demuxer::GetMemoryUsage, base::Unretained(demuxer_.get())),
1522 base::Bind(&WebMediaPlayerImpl::FinishMemoryUsageReport, AsWeakPtr()));
1523 } else {
1524 FinishMemoryUsageReport(0);
1525 }
1526}
1527
1528void WebMediaPlayerImpl::FinishMemoryUsageReport(int64_t demuxer_memory_usage) {
1529 DCHECK(main_task_runner_->BelongsToCurrentThread());
1530
dalecurtis83266c72015-10-29 18:43:201531 const PipelineStatistics stats = pipeline_.GetStatistics();
1532 const int64_t current_memory_usage =
1533 stats.audio_memory_usage + stats.video_memory_usage +
1534 (data_source_ ? data_source_->GetMemoryUsage() : 0) +
wdzierzanowskifd4cd91c52015-12-02 23:50:201535 demuxer_memory_usage;
dalecurtis83266c72015-10-29 18:43:201536
dalecurtis3a7d38f42016-03-07 21:17:131537 // Note, this isn't entirely accurate, there may be VideoFrames held by the
1538 // compositor or other resources that we're unaware of.
1539
dalecurtis83266c72015-10-29 18:43:201540 DVLOG(2) << "Memory Usage -- Audio: " << stats.audio_memory_usage
1541 << ", Video: " << stats.video_memory_usage << ", DataSource: "
1542 << (data_source_ ? data_source_->GetMemoryUsage() : 0)
wdzierzanowskifd4cd91c52015-12-02 23:50:201543 << ", Demuxer: " << demuxer_memory_usage;
dalecurtis83266c72015-10-29 18:43:201544
1545 const int64_t delta = current_memory_usage - last_reported_memory_usage_;
1546 last_reported_memory_usage_ = current_memory_usage;
1547 adjust_allocated_memory_cb_.Run(delta);
1548}
1549
dalecurtis0431cbf2016-03-12 01:19:431550bool WebMediaPlayerImpl::IsAutomaticResumeAllowed() {
1551#if defined(OS_ANDROID)
1552 return !hasVideo() || (delegate_ && !delegate_->IsHidden());
1553#else
1554 // On non-Android platforms Resume() is always allowed.
1555 return true;
1556#endif
1557}
1558
acolwell9e0840d2014-09-06 19:01:321559} // namespace media