blob: 2185d93168bb689680dd72f5400e1fd51798e76d [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"
xhwangbab66f52014-12-02 23:49:5060#include "third_party/WebKit/public/web/WebRuntimeFeatures.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
[email protected]8931c41a2009-07-07 17:31:49109} // namespace
110
[email protected]6683e1b2014-04-10 01:45:38111class BufferedDataSourceHostImpl;
112
danakj365175c2016-02-06 00:37:37113STATIC_ASSERT_ENUM(WebMediaPlayer::CORSModeUnspecified,
114 UrlData::CORS_UNSPECIFIED);
115STATIC_ASSERT_ENUM(WebMediaPlayer::CORSModeAnonymous, UrlData::CORS_ANONYMOUS);
116STATIC_ASSERT_ENUM(WebMediaPlayer::CORSModeUseCredentials,
117 UrlData::CORS_USE_CREDENTIALS);
[email protected]a5a01102012-06-06 17:01:24118
[email protected]2c539b82012-08-18 04:10:19119#define BIND_TO_RENDER_LOOP(function) \
acolwellb4034942014-08-28 15:42:43120 (DCHECK(main_task_runner_->BelongsToCurrentThread()), \
acolwell9e0840d2014-09-06 19:01:32121 BindToCurrentLoop(base::Bind(function, AsWeakPtr())))
[email protected]5983adb2012-10-24 00:12:00122
[email protected]4e982192014-06-21 13:35:45123#define BIND_TO_RENDER_LOOP1(function, arg1) \
acolwellb4034942014-08-28 15:42:43124 (DCHECK(main_task_runner_->BelongsToCurrentThread()), \
acolwell9e0840d2014-09-06 19:01:32125 BindToCurrentLoop(base::Bind(function, AsWeakPtr(), arg1)))
[email protected]4e982192014-06-21 13:35:45126
[email protected]5b5bb9d2010-10-22 19:57:36127WebMediaPlayerImpl::WebMediaPlayerImpl(
[email protected]35b2a972014-04-04 15:50:22128 blink::WebLocalFrame* frame,
[email protected]180ef242013-11-07 06:50:46129 blink::WebMediaPlayerClient* client,
srirama.m26f864d02015-07-14 05:21:46130 blink::WebMediaPlayerEncryptedMediaClient* encrypted_client,
[email protected]b8976652011-10-26 23:46:55131 base::WeakPtr<WebMediaPlayerDelegate> delegate,
xhwang6fa356202014-12-11 00:44:12132 scoped_ptr<RendererFactory> renderer_factory,
hubbe5f0ad43b2015-12-14 20:57:26133 linked_ptr<UrlIndex> url_index,
[email protected]e82b2bd2013-01-02 17:47:57134 const WebMediaPlayerParams& params)
[email protected]f6af7592014-02-28 10:09:11135 : frame_(frame),
[email protected]ef405f66b2012-04-18 02:39:55136 network_state_(WebMediaPlayer::NetworkStateEmpty),
137 ready_state_(WebMediaPlayer::ReadyStateHaveNothing),
acolwella5081a42014-08-28 23:42:52138 preload_(BufferedDataSource::AUTO),
sandersdc6ab163a2015-12-12 03:56:13139 buffering_strategy_(
140 BufferedDataSourceInterface::BUFFERING_STRATEGY_NORMAL),
anujk.sharma2fa37a02015-04-30 05:51:32141 main_task_runner_(base::ThreadTaskRunnerHandle::Get()),
acolwell755d12d2014-08-30 01:09:19142 media_task_runner_(params.media_task_runner()),
dcastagna617d086b2015-08-20 01:39:30143 worker_task_runner_(params.worker_task_runner()),
acolwell755d12d2014-08-30 01:09:19144 media_log_(params.media_log()),
acolwellb4034942014-08-28 15:42:43145 pipeline_(media_task_runner_, media_log_.get()),
sandersd1c0bba02016-03-04 23:14:08146 pipeline_controller_(
147 &pipeline_,
148 base::Bind(&WebMediaPlayerImpl::CreateRenderer,
149 base::Unretained(this)),
150 base::Bind(&WebMediaPlayerImpl::OnPipelineSeeked, AsWeakPtr()),
151 base::Bind(&WebMediaPlayerImpl::OnPipelineSuspended, AsWeakPtr()),
152 base::Bind(&WebMediaPlayerImpl::OnPipelineResumed, AsWeakPtr()),
153 base::Bind(&WebMediaPlayerImpl::OnPipelineError, AsWeakPtr())),
[email protected]f988d9b2014-07-25 00:35:43154 load_type_(LoadTypeURL),
[email protected]75e145a2014-04-15 17:44:32155 opaque_(false),
wolenetz1b2ae7d2015-06-10 00:44:21156 playback_rate_(0.0),
[email protected]49480902009-07-14 20:23:43157 paused_(true),
[email protected]b3766a22010-12-22 17:34:13158 seeking_(false),
watkdee516f2016-02-18 02:22:19159 pending_suspend_resume_cycle_(false),
scherkusd2c745b2014-09-04 05:03:40160 ended_(false),
yoichio863bebf2016-03-04 07:56:58161 should_notify_time_changed_(false),
watkdee516f2016-02-18 02:22:19162 fullscreen_(false),
163 decoder_requires_restart_for_fullscreen_(false),
[email protected]5badb082010-06-11 17:40:15164 client_(client),
srirama.m26f864d02015-07-14 05:21:46165 encrypted_client_(encrypted_client),
[email protected]baff4512011-10-19 18:21:07166 delegate_(delegate),
dalecurtisbb3eaac2016-01-27 21:10:25167 delegate_id_(0),
[email protected]d726eddc2013-07-02 22:25:55168 defer_load_cb_(params.defer_load_cb()),
dongseong.hwang0c4e9d82015-01-08 20:11:13169 context_3d_cb_(params.context_3d_cb()),
dalecurtis83266c72015-10-29 18:43:20170 adjust_allocated_memory_cb_(params.adjust_allocated_memory_cb()),
171 last_reported_memory_usage_(0),
[email protected]132dd57c2012-08-10 23:24:34172 supports_save_(true),
[email protected]f5443ef72013-04-22 04:03:38173 chunk_demuxer_(NULL),
hubbe5f0ad43b2015-12-14 20:57:26174 url_index_(url_index),
Bartosz Fabianowski85a823812015-04-16 10:27:51175 // Threaded compositing isn't enabled universally yet.
176 compositor_task_runner_(
177 params.compositor_task_runner()
178 ? params.compositor_task_runner()
179 : base::MessageLoop::current()->task_runner()),
[email protected]dd061e12014-05-06 19:21:22180 compositor_(new VideoFrameCompositor(
Bartosz Fabianowski85a823812015-04-16 10:27:51181 compositor_task_runner_,
[email protected]75e145a2014-04-15 17:44:32182 BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnNaturalSizeChanged),
[email protected]dd061e12014-05-06 19:21:22183 BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnOpacityChanged))),
xhwang80739452016-01-13 00:48:00184 is_cdm_attached_(false),
hubbed5f36882016-01-15 22:40:37185#if defined(OS_ANDROID) // WMPI_CAST
dalecurtisbb3eaac2016-01-27 21:10:25186 cast_impl_(this, client_, params.context_3d_cb()),
hubbed5f36882016-01-15 22:40:37187#endif
dalecurtisbb3eaac2016-01-27 21:10:25188 volume_(1.0),
189 volume_multiplier_(1.0),
watkdee516f2016-02-18 02:22:19190 renderer_factory_(std::move(renderer_factory)),
dalecurtis2ff781da2016-03-03 01:52:13191 surface_manager_(params.surface_manager()),
192 suppress_destruction_errors_(false) {
dalecurtis83266c72015-10-29 18:43:20193 DCHECK(!adjust_allocated_memory_cb_.is_null());
xhwang59d4175a2016-01-14 03:19:30194 DCHECK(renderer_factory_);
dalecurtis83266c72015-10-29 18:43:20195
dalecurtisbb3eaac2016-01-27 21:10:25196 if (delegate_)
197 delegate_id_ = delegate_->AddObserver(this);
sandersd1e49fb62015-12-12 01:18:06198
[email protected]c93eb0a62011-08-09 22:47:24199 media_log_->AddEvent(
acolwell9e0840d2014-09-06 19:01:32200 media_log_->CreateEvent(MediaLogEvent::WEBMEDIAPLAYER_CREATED));
[email protected]4e6be3f2009-05-07 02:24:44201
xhwang0ad11e512014-11-25 23:43:09202 if (params.initial_cdm()) {
xhwang9bd8c732015-04-13 23:27:53203 SetCdm(base::Bind(&IgnoreCdmAttached),
204 ToWebContentDecryptionModuleImpl(params.initial_cdm())
205 ->GetCdmContext());
xhwang0ad11e512014-11-25 23:43:09206 }
207
xhwangf94a634d2014-10-22 22:07:27208 // TODO(xhwang): When we use an external Renderer, many methods won't work,
xhwang6fa356202014-12-11 00:44:12209 // e.g. GetCurrentFrameFromCompositor(). See http://crbug.com/434861
[email protected]c50edb962013-10-19 18:05:07210
[email protected]ddbc6ff2013-04-19 15:28:33211 // Use the null sink if no sink was provided.
[email protected]4a914882013-01-10 00:43:48212 audio_source_provider_ = new WebAudioSourceProviderImpl(
[email protected]ff875be52013-06-02 23:47:38213 params.audio_renderer_sink().get()
214 ? params.audio_renderer_sink()
acolwell9e0840d2014-09-06 19:01:32215 : new NullAudioSink(media_task_runner_));
[email protected]ec9212f2008-12-18 21:40:36216}
217
[email protected]4e6be3f2009-05-07 02:24:44218WebMediaPlayerImpl::~WebMediaPlayerImpl() {
[email protected]ce70c982013-12-20 17:04:32219 client_->setWebLayer(NULL);
[email protected]21c3f7502013-03-23 03:29:51220
acolwellb4034942014-08-28 15:42:43221 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]d43ed912009-02-03 04:52:53222
sandersd1e49fb62015-12-12 01:18:06223 if (delegate_) {
dalecurtisbb3eaac2016-01-27 21:10:25224 delegate_->PlayerGone(delegate_id_);
225 delegate_->RemoveObserver(delegate_id_);
sandersd1e49fb62015-12-12 01:18:06226 }
[email protected]baff4512011-10-19 18:21:07227
[email protected]f6af7592014-02-28 10:09:11228 // Abort any pending IO so stopping the pipeline doesn't get blocked.
dalecurtis2ff781da2016-03-03 01:52:13229 suppress_destruction_errors_ = true;
[email protected]f6af7592014-02-28 10:09:11230 if (data_source_)
231 data_source_->Abort();
232 if (chunk_demuxer_) {
233 chunk_demuxer_->Shutdown();
sandersd1c0bba02016-03-04 23:14:08234 chunk_demuxer_ = nullptr;
[email protected]f6af7592014-02-28 10:09:11235 }
236
xhwang6fa356202014-12-11 00:44:12237 renderer_factory_.reset();
[email protected]f6af7592014-02-28 10:09:11238
239 // Make sure to kill the pipeline so there's no more media threads running.
240 // Note: stopping the pipeline might block for a long time.
241 base::WaitableEvent waiter(false, false);
242 pipeline_.Stop(
243 base::Bind(&base::WaitableEvent::Signal, base::Unretained(&waiter)));
244 waiter.Wait();
245
dalecurtis83266c72015-10-29 18:43:20246 if (last_reported_memory_usage_)
247 adjust_allocated_memory_cb_.Run(-last_reported_memory_usage_);
248
[email protected]dd061e12014-05-06 19:21:22249 compositor_task_runner_->DeleteSoon(FROM_HERE, compositor_);
xhwangea8bb3562015-06-08 21:18:37250
251 media_log_->AddEvent(
252 media_log_->CreateEvent(MediaLogEvent::WEBMEDIAPLAYER_DESTROYED));
[email protected]ec9212f2008-12-18 21:40:36253}
254
[email protected]180ef242013-11-07 06:50:46255void WebMediaPlayerImpl::load(LoadType load_type, const blink::WebURL& url,
[email protected]62e5e682013-03-07 23:53:24256 CORSMode cors_mode) {
[email protected]2a06ca62014-06-04 13:59:52257 DVLOG(1) << __FUNCTION__ << "(" << load_type << ", " << url << ", "
258 << cors_mode << ")";
[email protected]d726eddc2013-07-02 22:25:55259 if (!defer_load_cb_.is_null()) {
260 defer_load_cb_.Run(base::Bind(
[email protected]ef8394c2013-08-21 20:26:30261 &WebMediaPlayerImpl::DoLoad, AsWeakPtr(), load_type, url, cors_mode));
[email protected]d726eddc2013-07-02 22:25:55262 return;
263 }
[email protected]ef8394c2013-08-21 20:26:30264 DoLoad(load_type, url, cors_mode);
[email protected]62e5e682013-03-07 23:53:24265}
266
watkdee516f2016-02-18 02:22:19267void WebMediaPlayerImpl::enteredFullscreen() {
268 fullscreen_ = true;
269 if (decoder_requires_restart_for_fullscreen_)
270 ScheduleRestart();
271}
272
273void WebMediaPlayerImpl::exitedFullscreen() {
274 fullscreen_ = false;
275 if (decoder_requires_restart_for_fullscreen_)
276 ScheduleRestart();
277}
278
[email protected]ef8394c2013-08-21 20:26:30279void WebMediaPlayerImpl::DoLoad(LoadType load_type,
[email protected]180ef242013-11-07 06:50:46280 const blink::WebURL& url,
[email protected]d726eddc2013-07-02 22:25:55281 CORSMode cors_mode) {
hubbed82bed52015-12-15 23:07:16282 DVLOG(1) << __FUNCTION__;
acolwellb4034942014-08-28 15:42:43283 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]d726eddc2013-07-02 22:25:55284
[email protected]62e5e682013-03-07 23:53:24285 GURL gurl(url);
wolenetz0c6e7d92016-03-05 00:25:15286 ReportMetrics(load_type, gurl, frame_->document().securityOrigin());
[email protected]62e5e682013-03-07 23:53:24287
[email protected]926f8fd2013-04-12 20:27:53288 // Set subresource URL for crash reporting.
289 base::debug::SetCrashKeyValue("subresource_url", gurl.spec());
290
[email protected]ef8394c2013-08-21 20:26:30291 load_type_ = load_type;
292
[email protected]62e5e682013-03-07 23:53:24293 SetNetworkState(WebMediaPlayer::NetworkStateLoading);
294 SetReadyState(WebMediaPlayer::ReadyStateHaveNothing);
kinukof19cde72015-12-18 23:15:25295 media_log_->AddEvent(media_log_->CreateLoadEvent(url.string().utf8()));
[email protected]d726eddc2013-07-02 22:25:55296
297 // Media source pipelines can start immediately.
[email protected]ef8394c2013-08-21 20:26:30298 if (load_type == LoadTypeMediaSource) {
[email protected]d726eddc2013-07-02 22:25:55299 supports_save_ = false;
[email protected]ef8394c2013-08-21 20:26:30300 StartPipeline();
[email protected]d726eddc2013-07-02 22:25:55301 return;
302 }
303
hubbe2703d09e2016-02-10 23:17:18304 // TODO(hubbe): This experiment is temporary and should be removed once
305 // we have enough data to support the primacy of the new media cache.
306 // See http://crbug.com/514719 for details.
[email protected]d726eddc2013-07-02 22:25:55307 // Otherwise it's a regular request which requires resolving the URL first.
hubbe2703d09e2016-02-10 23:17:18308 if (base::FeatureList::IsEnabled(kUseNewMediaCache)) {
hubbe5f0ad43b2015-12-14 20:57:26309 // Remove this when MultiBufferDataSource becomes default.
310 LOG(WARNING) << "Using MultibufferDataSource";
311 data_source_.reset(new MultibufferDataSource(
312 url, static_cast<UrlData::CORSMode>(cors_mode), main_task_runner_,
313 url_index_, frame_, media_log_.get(), &buffered_data_source_host_,
314 base::Bind(&WebMediaPlayerImpl::NotifyDownloading, AsWeakPtr())));
315 } else {
316 data_source_.reset(new BufferedDataSource(
317 url, static_cast<BufferedResourceLoader::CORSMode>(cors_mode),
318 main_task_runner_, frame_, media_log_.get(),
319 &buffered_data_source_host_,
320 base::Bind(&WebMediaPlayerImpl::NotifyDownloading, AsWeakPtr())));
321 }
dalecurtis9157fc9e2015-01-16 01:09:11322 data_source_->SetPreload(preload_);
sandersdc6ab163a2015-12-12 03:56:13323 data_source_->SetBufferingStrategy(buffering_strategy_);
[email protected]d726eddc2013-07-02 22:25:55324 data_source_->Initialize(
[email protected]fee8a902014-06-03 13:43:36325 base::Bind(&WebMediaPlayerImpl::DataSourceInitialized, AsWeakPtr()));
hubbed5f36882016-01-15 22:40:37326
327#if defined(OS_ANDROID) // WMPI_CAST
dalecurtisbb3eaac2016-01-27 21:10:25328 cast_impl_.Initialize(url, frame_, delegate_id_);
hubbed5f36882016-01-15 22:40:37329#endif
[email protected]62e5e682013-03-07 23:53:24330}
331
[email protected]4e6be3f2009-05-07 02:24:44332void WebMediaPlayerImpl::play() {
[email protected]2a06ca62014-06-04 13:59:52333 DVLOG(1) << __FUNCTION__;
acolwellb4034942014-08-28 15:42:43334 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]d43ed912009-02-03 04:52:53335
hubbed5f36882016-01-15 22:40:37336#if defined(OS_ANDROID) // WMPI_CAST
337 if (isRemote()) {
dalecurtis6e2716d2016-01-21 04:49:15338 cast_impl_.play();
hubbed5f36882016-01-15 22:40:37339 return;
340 }
341#endif
342
[email protected]49480902009-07-14 20:23:43343 paused_ = false;
yoichio863bebf2016-03-04 07:56:58344 pipeline_.SetPlaybackRate(playback_rate_);
sandersd1c0bba02016-03-04 23:14:08345
[email protected]039b7542013-10-17 22:06:25346 if (data_source_)
347 data_source_->MediaIsPlaying();
[email protected]090f7312011-08-05 23:26:40348
acolwell9e0840d2014-09-06 19:01:32349 media_log_->AddEvent(media_log_->CreateEvent(MediaLogEvent::PLAY));
[email protected]baff4512011-10-19 18:21:07350
dalecurtis5bbc487e2016-02-27 04:15:05351 if (playback_rate_ > 0) {
yoichio863bebf2016-03-04 07:56:58352 NotifyPlaybackStarted();
sandersd1c0bba02016-03-04 23:14:08353
354 // Resume the player if playback was initiated in the foreground. Resume()
355 // will do nothing if the pipeline is not suspended state, but will clear
356 // some internal pending state, so it should always be called.
357 if (delegate_ && !delegate_->IsHidden())
358 pipeline_controller_.Resume();
dalecurtis5bbc487e2016-02-27 04:15:05359 }
[email protected]ec9212f2008-12-18 21:40:36360}
361
[email protected]4e6be3f2009-05-07 02:24:44362void WebMediaPlayerImpl::pause() {
[email protected]2a06ca62014-06-04 13:59:52363 DVLOG(1) << __FUNCTION__;
acolwellb4034942014-08-28 15:42:43364 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]d43ed912009-02-03 04:52:53365
dalecurtis6d269ed2014-09-11 21:18:13366 const bool was_already_paused = paused_ || playback_rate_ == 0;
[email protected]49480902009-07-14 20:23:43367 paused_ = true;
hubbed5f36882016-01-15 22:40:37368
369#if defined(OS_ANDROID) // WMPI_CAST
370 if (isRemote()) {
dalecurtis6e2716d2016-01-21 04:49:15371 cast_impl_.pause();
hubbed5f36882016-01-15 22:40:37372 return;
373 }
374#endif
375
a.berwal338bf002015-04-22 11:14:50376 pipeline_.SetPlaybackRate(0.0);
sandersd1c0bba02016-03-04 23:14:08377
378 // pause() may be called after playback has ended and the HTMLMediaElement
379 // requires that currentTime() == duration() after ending. We want to ensure
380 // |paused_time_| matches currentTime() in this case or a future seek() may
381 // incorrectly discard what it thinks is a seek to the existing time.
382 paused_time_ =
383 ended_ ? pipeline_.GetMediaDuration() : pipeline_.GetMediaTime();
[email protected]090f7312011-08-05 23:26:40384
acolwell9e0840d2014-09-06 19:01:32385 media_log_->AddEvent(media_log_->CreateEvent(MediaLogEvent::PAUSE));
[email protected]baff4512011-10-19 18:21:07386
dalecurtisbb3eaac2016-01-27 21:10:25387 if (!was_already_paused)
dalecurtis0f0097a2015-12-01 17:40:47388 NotifyPlaybackPaused();
[email protected]ec9212f2008-12-18 21:40:36389}
390
[email protected]574a1d62009-07-17 03:23:46391bool WebMediaPlayerImpl::supportsSave() const {
acolwellb4034942014-08-28 15:42:43392 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]132dd57c2012-08-10 23:24:34393 return supports_save_;
[email protected]574a1d62009-07-17 03:23:46394}
395
[email protected]39bdde32013-04-17 17:44:20396void WebMediaPlayerImpl::seek(double seconds) {
xhwang12d8d042014-12-01 21:48:57397 DVLOG(1) << __FUNCTION__ << "(" << seconds << "s)";
acolwellb4034942014-08-28 15:42:43398 DCHECK(main_task_runner_->BelongsToCurrentThread());
sandersd1c0bba02016-03-04 23:14:08399 DoSeek(base::TimeDelta::FromSecondsD(seconds), true);
400}
401
402void WebMediaPlayerImpl::DoSeek(base::TimeDelta time, bool time_updated) {
403 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]d43ed912009-02-03 04:52:53404
scherkusd2c745b2014-09-04 05:03:40405 ended_ = false;
406
hubbed5f36882016-01-15 22:40:37407#if defined(OS_ANDROID) // WMPI_CAST
408 if (isRemote()) {
sandersd1c0bba02016-03-04 23:14:08409 cast_impl_.seek(time);
hubbed5f36882016-01-15 22:40:37410 return;
411 }
412#endif
413
srirama.mccf671812015-01-08 11:59:13414 ReadyState old_state = ready_state_;
[email protected]1bb666802013-11-28 06:12:08415 if (ready_state_ > WebMediaPlayer::ReadyStateHaveMetadata)
416 SetReadyState(WebMediaPlayer::ReadyStateHaveMetadata);
417
sandersd1c0bba02016-03-04 23:14:08418 // When paused, we know exactly what the current time is and can elide seeks
419 // to it. However, there are two cases that are not elided:
420 // 1) When the pipeline state is not stable.
421 // In this case we just let |pipeline_controller_| decide what to do, as
422 // it has complete information.
423 // 2) For MSE.
424 // Because the buffers may have changed between seeks, MSE seeks are
425 // never elided.
426 if (paused_ && pipeline_controller_.IsStable() && paused_time_ == time &&
427 !chunk_demuxer_) {
428 // If the ready state was high enough before, we can indicate that the seek
429 // completed just by restoring it. Otherwise we will just wait for the real
430 // ready state change to eventually happen.
431 if (old_state == ReadyStateHaveEnoughData) {
srirama.m8f4a37562014-12-13 08:16:18432 main_task_runner_->PostTask(
srirama.m36ab2682014-12-11 04:20:01433 FROM_HERE,
434 base::Bind(&WebMediaPlayerImpl::OnPipelineBufferingStateChanged,
srirama.m8f4a37562014-12-13 08:16:18435 AsWeakPtr(), BUFFERING_HAVE_ENOUGH));
srirama.m36ab2682014-12-11 04:20:01436 }
sandersd1c0bba02016-03-04 23:14:08437 return;
srirama.m36ab2682014-12-11 04:20:01438 }
[email protected]44ff37c02009-10-24 01:03:03439
[email protected]b3766a22010-12-22 17:34:13440 seeking_ = true;
sandersd1c0bba02016-03-04 23:14:08441 seek_time_ = time;
442 if (paused_)
443 paused_time_ = time;
444 pipeline_controller_.Seek(time, time_updated);
[email protected]b3766a22010-12-22 17:34:13445
sandersd1c0bba02016-03-04 23:14:08446 // Resume the pipeline if the seek is initiated in the foreground so that
447 // the correct frame is displayed. If the pipeline is not suspended, Resume()
448 // will do nothing but clear some pending state.
449 if (delegate_ && !delegate_->IsHidden())
450 pipeline_controller_.Resume();
[email protected]ec9212f2008-12-18 21:40:36451}
452
[email protected]39bdde32013-04-17 17:44:20453void WebMediaPlayerImpl::setRate(double rate) {
[email protected]2a06ca62014-06-04 13:59:52454 DVLOG(1) << __FUNCTION__ << "(" << rate << ")";
acolwellb4034942014-08-28 15:42:43455 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]d43ed912009-02-03 04:52:53456
[email protected]378f0b72009-08-11 17:11:42457 // TODO(kylep): Remove when support for negatives is added. Also, modify the
458 // following checks so rewind uses reasonable values also.
[email protected]39bdde32013-04-17 17:44:20459 if (rate < 0.0)
[email protected]378f0b72009-08-11 17:11:42460 return;
461
462 // Limit rates to reasonable values by clamping.
[email protected]39bdde32013-04-17 17:44:20463 if (rate != 0.0) {
[email protected]378f0b72009-08-11 17:11:42464 if (rate < kMinRate)
465 rate = kMinRate;
466 else if (rate > kMaxRate)
467 rate = kMaxRate;
dalecurtisbb3eaac2016-01-27 21:10:25468 if (playback_rate_ == 0 && !paused_)
dalecurtis0f0097a2015-12-01 17:40:47469 NotifyPlaybackStarted();
dalecurtisbb3eaac2016-01-27 21:10:25470 } else if (playback_rate_ != 0 && !paused_) {
dalecurtis0f0097a2015-12-01 17:40:47471 NotifyPlaybackPaused();
[email protected]378f0b72009-08-11 17:11:42472 }
473
[email protected]49480902009-07-14 20:23:43474 playback_rate_ = rate;
475 if (!paused_) {
[email protected]f6af7592014-02-28 10:09:11476 pipeline_.SetPlaybackRate(rate);
[email protected]039b7542013-10-17 22:06:25477 if (data_source_)
478 data_source_->MediaPlaybackRateChanged(rate);
[email protected]49480902009-07-14 20:23:43479 }
[email protected]ec9212f2008-12-18 21:40:36480}
481
[email protected]39bdde32013-04-17 17:44:20482void WebMediaPlayerImpl::setVolume(double volume) {
[email protected]2a06ca62014-06-04 13:59:52483 DVLOG(1) << __FUNCTION__ << "(" << volume << ")";
acolwellb4034942014-08-28 15:42:43484 DCHECK(main_task_runner_->BelongsToCurrentThread());
dalecurtisbb3eaac2016-01-27 21:10:25485 volume_ = volume;
486 pipeline_.SetVolume(volume_ * volume_multiplier_);
[email protected]ec9212f2008-12-18 21:40:36487}
[email protected]f0a51fb52009-03-05 12:46:38488
guidouc7babef2015-10-22 00:42:35489void WebMediaPlayerImpl::setSinkId(
490 const blink::WebString& sink_id,
491 const blink::WebSecurityOrigin& security_origin,
492 blink::WebSetSinkIdCallbacks* web_callback) {
guidou69223ce2015-06-16 10:36:19493 DCHECK(main_task_runner_->BelongsToCurrentThread());
guidou5754e612015-07-31 08:09:41494 DVLOG(1) << __FUNCTION__;
guidouc7babef2015-10-22 00:42:35495
guidou5754e612015-07-31 08:09:41496 media::SwitchOutputDeviceCB callback =
497 media::ConvertToSwitchOutputDeviceCB(web_callback);
guidouc7babef2015-10-22 00:42:35498 media_task_runner_->PostTask(
499 FROM_HERE,
500 base::Bind(&SetSinkIdOnMediaThread, audio_source_provider_,
501 sink_id.utf8(), static_cast<url::Origin>(security_origin),
502 callback));
guidou69223ce2015-06-16 10:36:19503}
504
danakj365175c2016-02-06 00:37:37505STATIC_ASSERT_ENUM(WebMediaPlayer::PreloadNone, BufferedDataSource::NONE);
506STATIC_ASSERT_ENUM(WebMediaPlayer::PreloadMetaData,
507 BufferedDataSource::METADATA);
508STATIC_ASSERT_ENUM(WebMediaPlayer::PreloadAuto, BufferedDataSource::AUTO);
[email protected]23a8b1d82011-04-05 16:28:20509
[email protected]ef405f66b2012-04-18 02:39:55510void WebMediaPlayerImpl::setPreload(WebMediaPlayer::Preload preload) {
[email protected]2a06ca62014-06-04 13:59:52511 DVLOG(1) << __FUNCTION__ << "(" << preload << ")";
acolwellb4034942014-08-28 15:42:43512 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]4e6be3f2009-05-07 02:24:44513
acolwella5081a42014-08-28 23:42:52514 preload_ = static_cast<BufferedDataSource::Preload>(preload);
[email protected]b49beeb2013-03-01 20:04:00515 if (data_source_)
[email protected]09c60222014-08-07 16:42:31516 data_source_->SetPreload(preload_);
[email protected]4e6be3f2009-05-07 02:24:44517}
518
danakj365175c2016-02-06 00:37:37519STATIC_ASSERT_ENUM(WebMediaPlayer::BufferingStrategy::Normal,
520 BufferedDataSource::BUFFERING_STRATEGY_NORMAL);
521STATIC_ASSERT_ENUM(WebMediaPlayer::BufferingStrategy::Aggressive,
522 BufferedDataSource::BUFFERING_STRATEGY_AGGRESSIVE);
sandersdc6ab163a2015-12-12 03:56:13523
524void WebMediaPlayerImpl::setBufferingStrategy(
525 WebMediaPlayer::BufferingStrategy buffering_strategy) {
526 DVLOG(1) << __FUNCTION__;
527 DCHECK(main_task_runner_->BelongsToCurrentThread());
528
529 buffering_strategy_ =
530 static_cast<BufferedDataSource::BufferingStrategy>(buffering_strategy);
531 if (data_source_)
532 data_source_->SetBufferingStrategy(buffering_strategy_);
533}
534
[email protected]4e6be3f2009-05-07 02:24:44535bool WebMediaPlayerImpl::hasVideo() const {
acolwellb4034942014-08-28 15:42:43536 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]d43ed912009-02-03 04:52:53537
[email protected]b8877772014-03-26 20:17:15538 return pipeline_metadata_.has_video;
[email protected]d43ed912009-02-03 04:52:53539}
540
[email protected]fc367af2009-08-14 23:06:35541bool WebMediaPlayerImpl::hasAudio() const {
acolwellb4034942014-08-28 15:42:43542 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]fc367af2009-08-14 23:06:35543
[email protected]b8877772014-03-26 20:17:15544 return pipeline_metadata_.has_audio;
[email protected]fc367af2009-08-14 23:06:35545}
546
[email protected]180ef242013-11-07 06:50:46547blink::WebSize WebMediaPlayerImpl::naturalSize() const {
acolwellb4034942014-08-28 15:42:43548 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]d43ed912009-02-03 04:52:53549
[email protected]b8877772014-03-26 20:17:15550 return blink::WebSize(pipeline_metadata_.natural_size);
[email protected]d43ed912009-02-03 04:52:53551}
552
[email protected]4e6be3f2009-05-07 02:24:44553bool WebMediaPlayerImpl::paused() const {
acolwellb4034942014-08-28 15:42:43554 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]d43ed912009-02-03 04:52:53555
hubbed5f36882016-01-15 22:40:37556#if defined(OS_ANDROID) // WMPI_CAST
557 if (isRemote())
558 return cast_impl_.paused();
559#endif
[email protected]f6af7592014-02-28 10:09:11560 return pipeline_.GetPlaybackRate() == 0.0f;
[email protected]d43ed912009-02-03 04:52:53561}
562
[email protected]4e6be3f2009-05-07 02:24:44563bool WebMediaPlayerImpl::seeking() const {
acolwellb4034942014-08-28 15:42:43564 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]d43ed912009-02-03 04:52:53565
[email protected]ef405f66b2012-04-18 02:39:55566 if (ready_state_ == WebMediaPlayer::ReadyStateHaveNothing)
[email protected]0acebfa2009-08-21 22:45:40567 return false;
[email protected]67cd5052009-09-10 21:53:22568
[email protected]b3766a22010-12-22 17:34:13569 return seeking_;
[email protected]ec9212f2008-12-18 21:40:36570}
571
[email protected]39bdde32013-04-17 17:44:20572double WebMediaPlayerImpl::duration() const {
acolwellb4034942014-08-28 15:42:43573 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]39bdde32013-04-17 17:44:20574
575 if (ready_state_ == WebMediaPlayer::ReadyStateHaveNothing)
576 return std::numeric_limits<double>::quiet_NaN();
577
[email protected]39bdde32013-04-17 17:44:20578 return GetPipelineDuration();
[email protected]d43ed912009-02-03 04:52:53579}
580
[email protected]db66d0092014-04-16 07:15:12581double WebMediaPlayerImpl::timelineOffset() const {
acolwellb4034942014-08-28 15:42:43582 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]db66d0092014-04-16 07:15:12583
584 if (pipeline_metadata_.timeline_offset.is_null())
585 return std::numeric_limits<double>::quiet_NaN();
586
587 return pipeline_metadata_.timeline_offset.ToJsTime();
588}
589
[email protected]39bdde32013-04-17 17:44:20590double WebMediaPlayerImpl::currentTime() const {
acolwellb4034942014-08-28 15:42:43591 DCHECK(main_task_runner_->BelongsToCurrentThread());
scherkusd2c745b2014-09-04 05:03:40592 DCHECK_NE(ready_state_, WebMediaPlayer::ReadyStateHaveNothing);
593
594 // TODO(scherkus): Replace with an explicit ended signal to HTMLMediaElement,
595 // see http://crbug.com/409280
596 if (ended_)
597 return duration();
598
sandersd1c0bba02016-03-04 23:14:08599 if (seeking())
600 return seek_time_.InSecondsF();
wolenetz1b2ae7d2015-06-10 00:44:21601
hubbed5f36882016-01-15 22:40:37602#if defined(OS_ANDROID) // WMPI_CAST
sandersd1c0bba02016-03-04 23:14:08603 if (isRemote())
hubbed5f36882016-01-15 22:40:37604 return cast_impl_.currentTime();
hubbed5f36882016-01-15 22:40:37605#endif
606
sandersd1c0bba02016-03-04 23:14:08607 if (paused_)
hubbed5f36882016-01-15 22:40:37608 return paused_time_.InSecondsF();
hubbed5f36882016-01-15 22:40:37609
610 return pipeline_.GetMediaTime().InSecondsF();
[email protected]d43ed912009-02-03 04:52:53611}
612
danakj13afe0362016-02-27 01:22:50613WebMediaPlayer::NetworkState WebMediaPlayerImpl::getNetworkState() const {
acolwellb4034942014-08-28 15:42:43614 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]ddb1e5a2010-12-13 20:10:45615 return network_state_;
616}
617
danakj13afe0362016-02-27 01:22:50618WebMediaPlayer::ReadyState WebMediaPlayerImpl::getReadyState() const {
acolwellb4034942014-08-28 15:42:43619 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]ddb1e5a2010-12-13 20:10:45620 return ready_state_;
621}
622
[email protected]02022fc2014-05-16 00:05:31623blink::WebTimeRanges WebMediaPlayerImpl::buffered() const {
acolwellb4034942014-08-28 15:42:43624 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]779a8322014-08-22 21:28:37625
acolwell9e0840d2014-09-06 19:01:32626 Ranges<base::TimeDelta> buffered_time_ranges =
[email protected]02022fc2014-05-16 00:05:31627 pipeline_.GetBufferedTimeRanges();
[email protected]779a8322014-08-22 21:28:37628
629 const base::TimeDelta duration = pipeline_.GetMediaDuration();
acolwell9e0840d2014-09-06 19:01:32630 if (duration != kInfiniteDuration()) {
[email protected]779a8322014-08-22 21:28:37631 buffered_data_source_host_.AddBufferedTimeRanges(
632 &buffered_time_ranges, duration);
633 }
[email protected]02022fc2014-05-16 00:05:31634 return ConvertToWebTimeRanges(buffered_time_ranges);
635}
636
philipjb0e6f3f2014-09-30 09:51:53637blink::WebTimeRanges WebMediaPlayerImpl::seekable() const {
acolwellb4034942014-08-28 15:42:43638 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]39bdde32013-04-17 17:44:20639
dalecurtis56359cb2014-10-28 00:06:29640 if (ready_state_ < WebMediaPlayer::ReadyStateHaveMetadata)
philipjb0e6f3f2014-09-30 09:51:53641 return blink::WebTimeRanges();
642
dalecurtis56359cb2014-10-28 00:06:29643 const double seekable_end = duration();
644
645 // Allow a special exception for seeks to zero for streaming sources with a
646 // finite duration; this allows looping to work.
647 const bool allow_seek_to_zero = data_source_ && data_source_->IsStreaming() &&
mateuszs3371ab02015-04-24 13:20:23648 std::isfinite(seekable_end);
dalecurtis56359cb2014-10-28 00:06:29649
650 // TODO(dalecurtis): Technically this allows seeking on media which return an
651 // infinite duration so long as DataSource::IsStreaming() is false. While not
652 // expected, disabling this breaks semi-live players, http://crbug.com/427412.
653 const blink::WebTimeRange seekable_range(
654 0.0, allow_seek_to_zero ? 0.0 : seekable_end);
philipjb0e6f3f2014-09-30 09:51:53655 return blink::WebTimeRanges(&seekable_range, 1);
[email protected]ec9212f2008-12-18 21:40:36656}
657
[email protected]5d2b3e4c2014-05-12 23:27:30658bool WebMediaPlayerImpl::didLoadingProgress() {
acolwellb4034942014-08-28 15:42:43659 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]6683e1b2014-04-10 01:45:38660 bool pipeline_progress = pipeline_.DidLoadingProgress();
661 bool data_progress = buffered_data_source_host_.DidLoadingProgress();
662 return pipeline_progress || data_progress;
[email protected]d43ed912009-02-03 04:52:53663}
664
[email protected]dd5c7972014-08-21 15:00:37665void WebMediaPlayerImpl::paint(blink::WebCanvas* canvas,
666 const blink::WebRect& rect,
[email protected]dd5c7972014-08-21 15:00:37667 unsigned char alpha,
668 SkXfermode::Mode mode) {
acolwellb4034942014-08-28 15:42:43669 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]dd061e12014-05-06 19:21:22670 TRACE_EVENT0("media", "WebMediaPlayerImpl:paint");
[email protected]4e6be3f2009-05-07 02:24:44671
xhwang80739452016-01-13 00:48:00672 if (is_cdm_attached_)
673 return;
674
mcasasf1236fc22015-05-29 22:38:56675 scoped_refptr<VideoFrame> video_frame = GetCurrentFrameFromCompositor();
[email protected]0fe5d43b2014-01-24 23:32:45676
[email protected]b49beeb2013-03-01 20:04:00677 gfx::Rect gfx_rect(rect);
dongseong.hwang0c4e9d82015-01-08 20:11:13678 Context3D context_3d;
mcasas265bdbf82015-06-12 18:44:07679 if (video_frame.get() && video_frame->HasTextures()) {
mcasasf1236fc22015-05-29 22:38:56680 if (!context_3d_cb_.is_null())
dongseong.hwang0c4e9d82015-01-08 20:11:13681 context_3d = context_3d_cb_.Run();
dongseong.hwang0c4e9d82015-01-08 20:11:13682 // GPU Process crashed.
683 if (!context_3d.gl)
684 return;
685 }
danakj795f1732015-08-31 23:40:22686 skcanvas_video_renderer_.Paint(video_frame, canvas, gfx::RectF(gfx_rect),
687 alpha, mode, pipeline_metadata_.video_rotation,
688 context_3d);
[email protected]ec9212f2008-12-18 21:40:36689}
[email protected]5df51652009-01-17 00:03:00690
[email protected]38259a7a82009-07-29 21:49:49691bool WebMediaPlayerImpl::hasSingleSecurityOrigin() const {
[email protected]b49beeb2013-03-01 20:04:00692 if (data_source_)
693 return data_source_->HasSingleOrigin();
[email protected]fcdb7462009-10-21 21:05:11694 return true;
[email protected]38259a7a82009-07-29 21:49:49695}
696
[email protected]3fe27112012-06-07 04:00:01697bool WebMediaPlayerImpl::didPassCORSAccessCheck() const {
[email protected]b49beeb2013-03-01 20:04:00698 if (data_source_)
699 return data_source_->DidPassCORSAccessCheck();
700 return false;
[email protected]3fe27112012-06-07 04:00:01701}
702
[email protected]39bdde32013-04-17 17:44:20703double WebMediaPlayerImpl::mediaTimeForTimeValue(double timeValue) const {
qinminb4c39782015-08-10 18:43:24704 return base::TimeDelta::FromSecondsD(timeValue).InSecondsF();
[email protected]e06e16d82011-05-26 22:13:33705}
706
[email protected]d82b18ae2011-03-23 21:28:59707unsigned WebMediaPlayerImpl::decodedFrameCount() const {
acolwellb4034942014-08-28 15:42:43708 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]4c51bc662011-02-16 02:03:16709
acolwell9e0840d2014-09-06 19:01:32710 PipelineStatistics stats = pipeline_.GetStatistics();
[email protected]4c51bc662011-02-16 02:03:16711 return stats.video_frames_decoded;
712}
713
[email protected]d82b18ae2011-03-23 21:28:59714unsigned WebMediaPlayerImpl::droppedFrameCount() const {
acolwellb4034942014-08-28 15:42:43715 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]4c51bc662011-02-16 02:03:16716
acolwell9e0840d2014-09-06 19:01:32717 PipelineStatistics stats = pipeline_.GetStatistics();
[email protected]dd061e12014-05-06 19:21:22718 return stats.video_frames_dropped;
[email protected]4c51bc662011-02-16 02:03:16719}
720
[email protected]d82b18ae2011-03-23 21:28:59721unsigned WebMediaPlayerImpl::audioDecodedByteCount() const {
acolwellb4034942014-08-28 15:42:43722 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]4c51bc662011-02-16 02:03:16723
acolwell9e0840d2014-09-06 19:01:32724 PipelineStatistics stats = pipeline_.GetStatistics();
[email protected]4c51bc662011-02-16 02:03:16725 return stats.audio_bytes_decoded;
726}
727
[email protected]d82b18ae2011-03-23 21:28:59728unsigned WebMediaPlayerImpl::videoDecodedByteCount() 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_bytes_decoded;
733}
734
[email protected]6523b242013-03-13 11:10:07735bool WebMediaPlayerImpl::copyVideoTextureToPlatformTexture(
[email protected]180ef242013-11-07 06:50:46736 blink::WebGraphicsContext3D* web_graphics_context,
zmo57d577a2015-10-30 18:28:59737 unsigned int texture,
738 unsigned int internal_format,
739 unsigned int type,
740 bool premultiply_alpha,
741 bool flip_y) {
[email protected]bfc05f22013-10-19 17:55:16742 TRACE_EVENT0("media", "WebMediaPlayerImpl:copyVideoTextureToPlatformTexture");
743
mcasasf1236fc22015-05-29 22:38:56744 scoped_refptr<VideoFrame> video_frame = GetCurrentFrameFromCompositor();
[email protected]dd061e12014-05-06 19:21:22745
mcasas265bdbf82015-06-12 18:44:07746 if (!video_frame.get() || !video_frame->HasTextures() ||
dcastagna31a65d432015-06-11 19:01:00747 media::VideoFrame::NumPlanes(video_frame->format()) != 1) {
[email protected]e56f88c72013-06-25 22:31:29748 return false;
dongseong.hwang0c4e9d82015-01-08 20:11:13749 }
[email protected]df41e252014-02-03 23:39:50750
dongseong.hwang0c4e9d82015-01-08 20:11:13751 // TODO(dshwang): need more elegant way to convert WebGraphicsContext3D to
752 // GLES2Interface.
753 gpu::gles2::GLES2Interface* gl =
754 static_cast<gpu_blink::WebGraphicsContext3DImpl*>(web_graphics_context)
755 ->GetGLInterface();
dcastagna31a65d432015-06-11 19:01:00756 SkCanvasVideoRenderer::CopyVideoFrameSingleTextureToGLTexture(
zmo57d577a2015-10-30 18:28:59757 gl, video_frame.get(), texture, internal_format, type, premultiply_alpha,
758 flip_y);
[email protected]e56f88c72013-06-25 22:31:29759 return true;
[email protected]6523b242013-03-13 11:10:07760}
761
[email protected]7bce1832014-01-09 00:01:22762void WebMediaPlayerImpl::setContentDecryptionModule(
[email protected]9ebc3b03f2014-08-13 04:01:23763 blink::WebContentDecryptionModule* cdm,
764 blink::WebContentDecryptionModuleResult result) {
acolwellb4034942014-08-28 15:42:43765 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]9ebc3b03f2014-08-13 04:01:23766
jrummell06f27072015-06-08 18:12:38767 // Once the CDM is set it can't be cleared as there may be frames being
768 // decrypted on other threads. So fail this request.
769 // http://crbug.com/462365#c7.
xhwang97de4202014-11-25 08:44:01770 if (!cdm) {
771 result.completeWithError(
jrummell06f27072015-06-08 18:12:38772 blink::WebContentDecryptionModuleExceptionInvalidStateError, 0,
773 "The existing MediaKeys object cannot be removed at this time.");
xhwang97de4202014-11-25 08:44:01774 return;
775 }
776
jrummell89e61d82015-07-23 20:03:34777 // Create a local copy of |result| to avoid problems with the callback
778 // getting passed to the media thread and causing |result| to be destructed
jrummell4acbec912016-02-27 02:45:03779 // on the wrong thread in some failure conditions. Blink should prevent
780 // multiple simultaneous calls.
781 DCHECK(!set_cdm_result_);
jrummell89e61d82015-07-23 20:03:34782 set_cdm_result_.reset(new blink::WebContentDecryptionModuleResult(result));
783
784 SetCdm(BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnCdmAttached),
xhwang9bd8c732015-04-13 23:27:53785 ToWebContentDecryptionModuleImpl(cdm)->GetCdmContext());
xhwang97de4202014-11-25 08:44:01786}
787
xhwange8c4181a2014-12-06 08:10:01788void WebMediaPlayerImpl::OnEncryptedMediaInitData(
jrummellcf78967c2015-04-03 05:03:58789 EmeInitDataType init_data_type,
Avi Drissman97785ea2015-12-19 01:11:31790 const std::vector<uint8_t>& init_data) {
jrummellcf78967c2015-04-03 05:03:58791 DCHECK(init_data_type != EmeInitDataType::UNKNOWN);
xhwangbab66f52014-12-02 23:49:50792
ddorwinfdb9a2b2016-02-22 22:25:10793 // Do not fire the "encrypted" event if Encrypted Media is not enabled.
794 // EME may not be enabled on Android Jelly Bean.
795 if (!blink::WebRuntimeFeatures::isEncryptedMediaEnabled()) {
xhwangbab66f52014-12-02 23:49:50796 return;
797 }
798
ddorwin301ccdb2016-02-25 02:39:17799 // TODO(xhwang): Update this UMA name. https://crbug.com/589251
xhwangbab66f52014-12-02 23:49:50800 UMA_HISTOGRAM_COUNTS("Media.EME.NeedKey", 1);
801
srirama.m26f864d02015-07-14 05:21:46802 encrypted_client_->encrypted(
davidbenb50f00c2015-12-01 00:01:50803 ConvertToWebInitDataType(init_data_type), init_data.data(),
srirama.m26f864d02015-07-14 05:21:46804 base::saturated_cast<unsigned int>(init_data.size()));
xhwangbab66f52014-12-02 23:49:50805}
806
servolk81e01e02016-03-05 03:29:15807void WebMediaPlayerImpl::OnFFmpegMediaTracksUpdated(
808 scoped_ptr<MediaTracks> tracks) {
809 // For MSE/chunk_demuxer case the media track updates are handled by
810 // WebSourceBufferImpl.
811 DCHECK(demuxer_.get());
812 DCHECK(!chunk_demuxer_);
813}
814
jrummell74fc4f942015-03-02 22:48:27815void WebMediaPlayerImpl::OnWaitingForDecryptionKey() {
srirama.m26f864d02015-07-14 05:21:46816 encrypted_client_->didBlockPlaybackWaitingForKey();
jrummell74fc4f942015-03-02 22:48:27817
818 // TODO(jrummell): didResumePlaybackBlockedForKey() should only be called
819 // when a key has been successfully added (e.g. OnSessionKeysChange() with
820 // |has_additional_usable_key| = true). http://crbug.com/461903
srirama.m26f864d02015-07-14 05:21:46821 encrypted_client_->didResumePlaybackBlockedForKey();
jrummell74fc4f942015-03-02 22:48:27822}
823
xhwang9bd8c732015-04-13 23:27:53824void WebMediaPlayerImpl::SetCdm(const CdmAttachedCB& cdm_attached_cb,
825 CdmContext* cdm_context) {
xhwang80739452016-01-13 00:48:00826 if (!cdm_context) {
827 cdm_attached_cb.Run(false);
828 return;
829 }
830
jrummell87a2db52015-05-05 22:27:18831 // If CDM initialization succeeded, tell the pipeline about it.
xhwang80739452016-01-13 00:48:00832 pipeline_.SetCdm(cdm_context, cdm_attached_cb);
xhwang97de4202014-11-25 08:44:01833}
834
jrummell89e61d82015-07-23 20:03:34835void WebMediaPlayerImpl::OnCdmAttached(bool success) {
xhwang97de4202014-11-25 08:44:01836 if (success) {
jrummell89e61d82015-07-23 20:03:34837 set_cdm_result_->complete();
838 set_cdm_result_.reset();
xhwang80739452016-01-13 00:48:00839 is_cdm_attached_ = true;
xhwang97de4202014-11-25 08:44:01840 return;
841 }
842
jrummell89e61d82015-07-23 20:03:34843 set_cdm_result_->completeWithError(
xhwang97de4202014-11-25 08:44:01844 blink::WebContentDecryptionModuleExceptionNotSupportedError, 0,
845 "Unable to set MediaKeys object");
jrummell89e61d82015-07-23 20:03:34846 set_cdm_result_.reset();
[email protected]9ebc3b03f2014-08-13 04:01:23847}
848
sandersd1c0bba02016-03-04 23:14:08849void WebMediaPlayerImpl::OnPipelineSeeked(bool time_updated) {
[email protected]5d11eff2011-09-15 00:06:06850 seeking_ = false;
wolenetz1b2ae7d2015-06-10 00:44:21851 seek_time_ = base::TimeDelta();
[email protected]10a64d92012-04-10 21:08:02852 if (paused_)
sandersd1c0bba02016-03-04 23:14:08853 paused_time_ = pipeline_.GetMediaTime();
854 if (time_updated)
855 should_notify_time_changed_ = true;
[email protected]8931c41a2009-07-07 17:31:49856}
857
sandersd1c0bba02016-03-04 23:14:08858void WebMediaPlayerImpl::OnPipelineSuspended() {
hubbed5f36882016-01-15 22:40:37859#if defined(OS_ANDROID)
860 if (isRemote()) {
861 scoped_refptr<VideoFrame> frame = cast_impl_.GetCastingBanner();
862 if (frame) {
863 compositor_->PaintFrameUsingOldRenderingPath(frame);
864 }
865 }
866#endif
867
sandersd1c0bba02016-03-04 23:14:08868 if (delegate_)
869 delegate_->PlayerGone(delegate_id_);
870
871 if (pending_suspend_resume_cycle_) {
watkdee516f2016-02-18 02:22:19872 pending_suspend_resume_cycle_ = false;
sandersd1c0bba02016-03-04 23:14:08873 pipeline_controller_.Resume();
sandersd1e49fb62015-12-12 01:18:06874 return;
875 }
876}
877
sandersd1c0bba02016-03-04 23:14:08878void WebMediaPlayerImpl::OnPipelineResumed() {
879 if (playback_rate_ > 0 && !paused_)
880 NotifyPlaybackStarted();
881}
882
[email protected]6954fe12013-01-03 03:22:32883void WebMediaPlayerImpl::OnPipelineEnded() {
[email protected]2a06ca62014-06-04 13:59:52884 DVLOG(1) << __FUNCTION__;
acolwellb4034942014-08-28 15:42:43885 DCHECK(main_task_runner_->BelongsToCurrentThread());
scherkusd2c745b2014-09-04 05:03:40886
sandersd1c0bba02016-03-04 23:14:08887 // Ignore state changes until we've completed all outstanding operations.
888 if (!pipeline_controller_.IsStable())
scherkusd2c745b2014-09-04 05:03:40889 return;
890
891 ended_ = true;
[email protected]ce70c982013-12-20 17:04:32892 client_->timeChanged();
[email protected]576537842009-08-12 23:52:05893}
894
[email protected]a9590c22011-03-16 16:57:02895void WebMediaPlayerImpl::OnPipelineError(PipelineStatus error) {
hubbed82bed52015-12-15 23:07:16896 DVLOG(1) << __FUNCTION__;
acolwellb4034942014-08-28 15:42:43897 DCHECK(main_task_runner_->BelongsToCurrentThread());
acolwell9e0840d2014-09-06 19:01:32898 DCHECK_NE(error, PIPELINE_OK);
[email protected]a8e2cb82012-08-17 00:02:39899
dalecurtis2ff781da2016-03-03 01:52:13900 if (suppress_destruction_errors_)
901 return;
902
903 media_log_->AddEvent(media_log_->CreatePipelineErrorEvent(error));
904
[email protected]a8e2cb82012-08-17 00:02:39905 if (ready_state_ == WebMediaPlayer::ReadyStateHaveNothing) {
906 // Any error that occurs before reaching ReadyStateHaveMetadata should
907 // be considered a format error.
908 SetNetworkState(WebMediaPlayer::NetworkStateFormatError);
[email protected]a8e2cb82012-08-17 00:02:39909 return;
910 }
911
[email protected]be57ee52013-05-28 22:27:27912 SetNetworkState(PipelineErrorToNetworkState(error));
[email protected]db190487d2009-07-30 18:51:52913}
914
[email protected]b8877772014-03-26 20:17:15915void WebMediaPlayerImpl::OnPipelineMetadata(
acolwell9e0840d2014-09-06 19:01:32916 PipelineMetadata metadata) {
[email protected]2a06ca62014-06-04 13:59:52917 DVLOG(1) << __FUNCTION__;
[email protected]a8e2cb82012-08-17 00:02:39918
[email protected]b8877772014-03-26 20:17:15919 pipeline_metadata_ = metadata;
[email protected]739847c02014-01-16 00:12:25920
dalecurtis849cf4b22015-03-27 18:35:45921 UMA_HISTOGRAM_ENUMERATION("Media.VideoRotation", metadata.video_rotation,
acolwell9e0840d2014-09-06 19:01:32922 VIDEO_ROTATION_MAX + 1);
[email protected]b8877772014-03-26 20:17:15923 SetReadyState(WebMediaPlayer::ReadyStateHaveMetadata);
[email protected]21c3f7502013-03-23 03:29:51924
[email protected]b8877772014-03-26 20:17:15925 if (hasVideo()) {
926 DCHECK(!video_weblayer_);
loyso510a9b62016-03-02 00:42:56927 scoped_refptr<cc::VideoLayer> layer = cc::VideoLayer::Create(
928 cc::LayerSettings(), compositor_, pipeline_metadata_.video_rotation);
[email protected]f78c3e82014-08-08 01:24:47929
acolwell9e0840d2014-09-06 19:01:32930 if (pipeline_metadata_.video_rotation == VIDEO_ROTATION_90 ||
931 pipeline_metadata_.video_rotation == VIDEO_ROTATION_270) {
[email protected]f78c3e82014-08-08 01:24:47932 gfx::Size size = pipeline_metadata_.natural_size;
933 pipeline_metadata_.natural_size = gfx::Size(size.height(), size.width());
934 }
935
[email protected]38564622014-08-19 02:47:18936 video_weblayer_.reset(new cc_blink::WebLayerImpl(layer));
jbauman952274d2015-09-10 23:23:36937 video_weblayer_->layer()->SetContentsOpaque(opaque_);
938 video_weblayer_->SetContentsOpaqueIsFixed(true);
[email protected]a7c4f582014-04-16 18:44:49939 client_->setWebLayer(video_weblayer_.get());
sandersdb96662f2016-01-09 00:46:06940
941 // If there is video and the frame is hidden, then it may be time to suspend
942 // playback.
943 if (delegate_ && delegate_->IsHidden())
dalecurtise43b57d2016-02-13 00:59:10944 OnHidden(false);
[email protected]a8e2cb82012-08-17 00:02:39945 }
[email protected]a8e2cb82012-08-17 00:02:39946}
947
[email protected]ba7d5f92014-06-24 05:37:40948void WebMediaPlayerImpl::OnPipelineBufferingStateChanged(
acolwell9e0840d2014-09-06 19:01:32949 BufferingState buffering_state) {
[email protected]ba7d5f92014-06-24 05:37:40950 DVLOG(1) << __FUNCTION__ << "(" << buffering_state << ")";
[email protected]b8877772014-03-26 20:17:15951
sandersd1c0bba02016-03-04 23:14:08952 // Ignore buffering state changes until we've completed all outstanding
953 // operations.
954 if (!pipeline_controller_.IsStable())
[email protected]ba7d5f92014-06-24 05:37:40955 return;
[email protected]b8877772014-03-26 20:17:15956
[email protected]ba7d5f92014-06-24 05:37:40957 // TODO(scherkus): Handle other buffering states when Pipeline starts using
958 // them and translate them ready state changes http://crbug.com/144683
acolwell9e0840d2014-09-06 19:01:32959 DCHECK_EQ(buffering_state, BUFFERING_HAVE_ENOUGH);
[email protected]ba7d5f92014-06-24 05:37:40960 SetReadyState(WebMediaPlayer::ReadyStateHaveEnoughData);
961
dalecurtis849cf4b22015-03-27 18:35:45962 // Let the DataSource know we have enough data. It may use this information to
963 // release unused network connections.
964 if (data_source_)
965 data_source_->OnBufferingHaveEnough();
966
[email protected]ba7d5f92014-06-24 05:37:40967 // Blink expects a timeChanged() in response to a seek().
968 if (should_notify_time_changed_)
969 client_->timeChanged();
dalecurtis0f0097a2015-12-01 17:40:47970
971 // Once we have enough, start reporting the total memory usage. We'll also
972 // report once playback starts.
973 ReportMemoryUsage();
[email protected]b8877772014-03-26 20:17:15974}
975
[email protected]ef8394c2013-08-21 20:26:30976void WebMediaPlayerImpl::OnDemuxerOpened() {
acolwellb4034942014-08-28 15:42:43977 DCHECK(main_task_runner_->BelongsToCurrentThread());
wolenetz1fb319d2015-07-14 17:49:04978 client_->mediaSourceOpened(
979 new WebMediaSourceImpl(chunk_demuxer_, media_log_));
[email protected]81bb3322011-07-21 15:55:50980}
981
[email protected]8a561062013-11-22 01:19:31982void WebMediaPlayerImpl::OnAddTextTrack(
acolwell9e0840d2014-09-06 19:01:32983 const TextTrackConfig& config,
984 const AddTextTrackDoneCB& done_cb) {
acolwellb4034942014-08-28 15:42:43985 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]71537722013-05-23 06:47:53986
[email protected]8a561062013-11-22 01:19:31987 const WebInbandTextTrackImpl::Kind web_kind =
988 static_cast<WebInbandTextTrackImpl::Kind>(config.kind());
989 const blink::WebString web_label =
990 blink::WebString::fromUTF8(config.label());
991 const blink::WebString web_language =
992 blink::WebString::fromUTF8(config.language());
[email protected]427ff102013-11-26 23:45:40993 const blink::WebString web_id =
994 blink::WebString::fromUTF8(config.id());
[email protected]71537722013-05-23 06:47:53995
[email protected]8a561062013-11-22 01:19:31996 scoped_ptr<WebInbandTextTrackImpl> web_inband_text_track(
henriks9cce5fa2014-12-12 09:35:30997 new WebInbandTextTrackImpl(web_kind, web_label, web_language, web_id));
[email protected]8a561062013-11-22 01:19:31998
acolwell9e0840d2014-09-06 19:01:32999 scoped_ptr<TextTrack> text_track(new TextTrackImpl(
dcheng652f5ff2015-12-27 08:54:001000 main_task_runner_, client_, std::move(web_inband_text_track)));
[email protected]8a561062013-11-22 01:19:311001
dcheng652f5ff2015-12-27 08:54:001002 done_cb.Run(std::move(text_track));
[email protected]71537722013-05-23 06:47:531003}
1004
dalecurtise43b57d2016-02-13 00:59:101005void WebMediaPlayerImpl::OnHidden(bool must_suspend) {
sandersd1e49fb62015-12-12 01:18:061006 DCHECK(main_task_runner_->BelongsToCurrentThread());
1007
1008#if !defined(OS_ANDROID)
1009 // Suspend/Resume is enabled by default on Android.
1010 if (!base::CommandLine::ForCurrentProcess()->HasSwitch(
1011 switches::kEnableMediaSuspend)) {
1012 return;
1013 }
1014#endif // !defined(OS_ANDROID)
1015
1016 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
1017 switches::kDisableMediaSuspend)) {
1018 return;
1019 }
1020
hubbed5f36882016-01-15 22:40:371021#if defined(OS_ANDROID)
1022 // If we're remote, the pipeline should already be suspended.
1023 if (isRemote())
1024 return;
1025#endif
1026
dalecurtis78f75962016-02-29 23:08:201027 if (must_suspend || (paused_ && ended_) || hasVideo())
sandersd1c0bba02016-03-04 23:14:081028 pipeline_controller_.Suspend();
sandersd1e49fb62015-12-12 01:18:061029}
1030
1031void WebMediaPlayerImpl::OnShown() {
1032 DCHECK(main_task_runner_->BelongsToCurrentThread());
1033
1034#if !defined(OS_ANDROID)
1035 // Suspend/Resume is enabled by default on Android.
1036 if (!base::CommandLine::ForCurrentProcess()->HasSwitch(
1037 switches::kEnableMediaSuspend)) {
1038 return;
1039 }
1040#endif // !defined(OS_ANDROID)
1041
1042 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
1043 switches::kDisableMediaSuspend)) {
1044 return;
1045 }
1046
hubbed5f36882016-01-15 22:40:371047#if defined(OS_ANDROID)
1048 // If we're remote, the pipeline should stay suspended.
1049 if (isRemote())
1050 return;
1051#endif
1052
dalecurtis5bbc487e2016-02-27 04:15:051053 if (!ended_ && !paused_)
sandersd1c0bba02016-03-04 23:14:081054 pipeline_controller_.Resume();
sandersd1e49fb62015-12-12 01:18:061055}
1056
dalecurtisbb3eaac2016-01-27 21:10:251057void WebMediaPlayerImpl::OnPlay() {
1058 play();
1059 client_->playbackStateChanged();
1060}
1061
1062void WebMediaPlayerImpl::OnPause() {
1063 pause();
1064 client_->playbackStateChanged();
1065}
1066
1067void WebMediaPlayerImpl::OnVolumeMultiplierUpdate(double multiplier) {
1068 volume_multiplier_ = multiplier;
1069 setVolume(volume_);
1070}
1071
watkdee516f2016-02-18 02:22:191072void WebMediaPlayerImpl::ScheduleRestart() {
sandersd1c0bba02016-03-04 23:14:081073 if (!pipeline_controller_.IsSuspended()) {
watkdee516f2016-02-18 02:22:191074 pending_suspend_resume_cycle_ = true;
sandersd1c0bba02016-03-04 23:14:081075 pipeline_controller_.Suspend();
watkdee516f2016-02-18 02:22:191076 }
1077}
1078
hubbed5f36882016-01-15 22:40:371079#if defined(OS_ANDROID) // WMPI_CAST
hubbed5f36882016-01-15 22:40:371080bool WebMediaPlayerImpl::isRemote() const {
1081 return cast_impl_.isRemote();
1082}
1083
1084void WebMediaPlayerImpl::SetMediaPlayerManager(
1085 RendererMediaPlayerManagerInterface* media_player_manager) {
1086 cast_impl_.SetMediaPlayerManager(media_player_manager);
1087}
1088
1089void WebMediaPlayerImpl::requestRemotePlayback() {
1090 cast_impl_.requestRemotePlayback();
1091}
1092
1093void WebMediaPlayerImpl::requestRemotePlaybackControl() {
1094 cast_impl_.requestRemotePlaybackControl();
1095}
1096
1097void WebMediaPlayerImpl::OnRemotePlaybackEnded() {
1098 DVLOG(1) << __FUNCTION__;
1099 DCHECK(main_task_runner_->BelongsToCurrentThread());
1100
1101 ended_ = true;
1102 client_->timeChanged();
1103}
1104
1105void WebMediaPlayerImpl::OnDisconnectedFromRemoteDevice(double t) {
sandersd1c0bba02016-03-04 23:14:081106 DoSeek(base::TimeDelta::FromSecondsD(t), false);
1107 if (delegate_ && !delegate_->IsHidden())
1108 pipeline_controller_.Resume();
hubbed5f36882016-01-15 22:40:371109
hubbed5f36882016-01-15 22:40:371110 // We already told the delegate we're paused when remoting started.
1111 client_->playbackStateChanged();
1112 client_->disconnectedFromRemoteDevice();
1113}
1114
1115void WebMediaPlayerImpl::SuspendForRemote() {
sandersd1c0bba02016-03-04 23:14:081116 if (!pipeline_controller_.IsSuspended()) {
1117 pipeline_controller_.Suspend();
1118 } else {
1119 // TODO(sandersd): If PipelineController::Suspend() called |suspended_cb|
1120 // when already suspended, we wouldn't need this case.
hubbed5f36882016-01-15 22:40:371121 scoped_refptr<VideoFrame> frame = cast_impl_.GetCastingBanner();
1122 if (frame) {
1123 compositor_->PaintFrameUsingOldRenderingPath(frame);
1124 }
1125 }
hubbed5f36882016-01-15 22:40:371126}
1127
1128gfx::Size WebMediaPlayerImpl::GetCanvasSize() const {
1129 if (!video_weblayer_)
1130 return pipeline_metadata_.natural_size;
1131
1132 return video_weblayer_->bounds();
1133}
1134
1135void WebMediaPlayerImpl::SetDeviceScaleFactor(float scale_factor) {
1136 cast_impl_.SetDeviceScaleFactor(scale_factor);
1137}
1138#endif // defined(OS_ANDROID) // WMPI_CAST
1139
[email protected]fee8a902014-06-03 13:43:361140void WebMediaPlayerImpl::DataSourceInitialized(bool success) {
hubbed82bed52015-12-15 23:07:161141 DVLOG(1) << __FUNCTION__;
acolwellb4034942014-08-28 15:42:431142 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]a9415292012-01-19 19:55:201143
[email protected]d250190da3b2012-07-23 22:57:301144 if (!success) {
[email protected]ef405f66b2012-04-18 02:39:551145 SetNetworkState(WebMediaPlayer::NetworkStateFormatError);
[email protected]a9415292012-01-19 19:55:201146 return;
1147 }
1148
[email protected]ef8394c2013-08-21 20:26:301149 StartPipeline();
[email protected]a9415292012-01-19 19:55:201150}
1151
[email protected]122f40252012-06-12 05:01:561152void WebMediaPlayerImpl::NotifyDownloading(bool is_downloading) {
hubbed82bed52015-12-15 23:07:161153 DVLOG(1) << __FUNCTION__;
[email protected]122f40252012-06-12 05:01:561154 if (!is_downloading && network_state_ == WebMediaPlayer::NetworkStateLoading)
1155 SetNetworkState(WebMediaPlayer::NetworkStateIdle);
1156 else if (is_downloading && network_state_ == WebMediaPlayer::NetworkStateIdle)
1157 SetNetworkState(WebMediaPlayer::NetworkStateLoading);
1158 media_log_->AddEvent(
1159 media_log_->CreateBooleanEvent(
acolwell9e0840d2014-09-06 19:01:321160 MediaLogEvent::NETWORK_ACTIVITY_SET,
[email protected]122f40252012-06-12 05:01:561161 "is_downloading_data", is_downloading));
1162}
1163
watkdee516f2016-02-18 02:22:191164// TODO(watk): Move this state management out of WMPI.
1165void WebMediaPlayerImpl::OnSurfaceRequested(
1166 const SurfaceCreatedCB& surface_created_cb) {
1167 DCHECK(main_task_runner_->BelongsToCurrentThread());
1168 DCHECK(surface_manager_);
1169
1170 // A null callback indicates that the decoder is going away.
1171 if (surface_created_cb.is_null()) {
1172 decoder_requires_restart_for_fullscreen_ = false;
1173 return;
1174 }
1175
1176 // If we're getting a surface request it means GVD is initializing, so until
1177 // we get a null surface request, GVD is the active decoder. While that's the
1178 // case we should restart the pipeline on fullscreen transitions so that when
1179 // we create a new GVD it will request a surface again and get the right kind
1180 // of surface for the fullscreen state.
1181 // TODO(watk): Don't require a pipeline restart to switch surfaces for
1182 // cases where it isn't necessary.
1183 decoder_requires_restart_for_fullscreen_ = true;
1184 if (fullscreen_) {
1185 surface_manager_->CreateFullscreenSurface(pipeline_metadata_.natural_size,
1186 surface_created_cb);
1187 } else {
1188 // Tell the decoder to create its own surface.
1189 surface_created_cb.Run(SurfaceManager::kNoSurfaceID);
1190 }
1191}
1192
sandersd1e49fb62015-12-12 01:18:061193scoped_ptr<Renderer> WebMediaPlayerImpl::CreateRenderer() {
watkdee516f2016-02-18 02:22:191194 RequestSurfaceCB request_surface_cb;
1195#if defined(OS_ANDROID)
1196 request_surface_cb =
1197 BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnSurfaceRequested);
1198#endif
sandersd1e49fb62015-12-12 01:18:061199 return renderer_factory_->CreateRenderer(
1200 media_task_runner_, worker_task_runner_, audio_source_provider_.get(),
watkdee516f2016-02-18 02:22:191201 compositor_, request_surface_cb);
sandersd1e49fb62015-12-12 01:18:061202}
1203
[email protected]ef8394c2013-08-21 20:26:301204void WebMediaPlayerImpl::StartPipeline() {
acolwellb4034942014-08-28 15:42:431205 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]ddbc6ff2013-04-19 15:28:331206
xhwange8c4181a2014-12-06 08:10:011207 Demuxer::EncryptedMediaInitDataCB encrypted_media_init_data_cb =
1208 BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnEncryptedMediaInitData);
[email protected]2b57e2e2014-05-09 11:07:251209
[email protected]ddbc6ff2013-04-19 15:28:331210 // Figure out which demuxer to use.
[email protected]ef8394c2013-08-21 20:26:301211 if (load_type_ != LoadTypeMediaSource) {
[email protected]ddbc6ff2013-04-19 15:28:331212 DCHECK(!chunk_demuxer_);
[email protected]f5443ef72013-04-22 04:03:381213 DCHECK(data_source_);
1214
j.isorcef6778e652015-11-16 17:14:251215#if !defined(MEDIA_DISABLE_FFMPEG)
servolk81e01e02016-03-05 03:29:151216 Demuxer::MediaTracksUpdatedCB media_tracks_updated_cb =
1217 base::Bind(&WebMediaPlayerImpl::OnFFmpegMediaTracksUpdated,
1218 base::Unretained(this));
1219
xhwange8c4181a2014-12-06 08:10:011220 demuxer_.reset(new FFmpegDemuxer(media_task_runner_, data_source_.get(),
servolk81e01e02016-03-05 03:29:151221 encrypted_media_init_data_cb,
1222 media_tracks_updated_cb, media_log_));
j.isorcef6778e652015-11-16 17:14:251223#else
1224 OnPipelineError(PipelineStatus::DEMUXER_ERROR_COULD_NOT_OPEN);
1225 return;
1226#endif
[email protected]ddbc6ff2013-04-19 15:28:331227 } else {
[email protected]f5443ef72013-04-22 04:03:381228 DCHECK(!chunk_demuxer_);
1229 DCHECK(!data_source_);
1230
acolwell9e0840d2014-09-06 19:01:321231 chunk_demuxer_ = new ChunkDemuxer(
[email protected]ef8394c2013-08-21 20:26:301232 BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnDemuxerOpened),
wolenetz1fb319d2015-07-14 17:49:041233 encrypted_media_init_data_cb, media_log_, true);
[email protected]f5443ef72013-04-22 04:03:381234 demuxer_.reset(chunk_demuxer_);
[email protected]ddbc6ff2013-04-19 15:28:331235 }
1236
[email protected]f5443ef72013-04-22 04:03:381237 // ... and we're ready to go!
[email protected]d228aeec2014-06-20 19:16:491238 seeking_ = true;
xhwangf94a634d2014-10-22 22:07:271239
sandersd1e49fb62015-12-12 01:18:061240 // TODO(sandersd): On Android, defer Start() if the tab is not visible.
sandersd1c0bba02016-03-04 23:14:081241 bool is_streaming = (data_source_ && data_source_->IsStreaming());
1242 pipeline_controller_.Start(
1243 chunk_demuxer_, demuxer_.get(), is_streaming,
[email protected]f5443ef72013-04-22 04:03:381244 BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnPipelineEnded),
[email protected]b8877772014-03-26 20:17:151245 BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnPipelineMetadata),
[email protected]ba7d5f92014-06-24 05:37:401246 BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnPipelineBufferingStateChanged),
xhwang59805902014-08-29 01:44:151247 BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnDurationChanged),
jrummell74fc4f942015-03-02 22:48:271248 BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnAddTextTrack),
1249 BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnWaitingForDecryptionKey));
[email protected]f5443ef72013-04-22 04:03:381250}
1251
1252void WebMediaPlayerImpl::SetNetworkState(WebMediaPlayer::NetworkState state) {
[email protected]2a06ca62014-06-04 13:59:521253 DVLOG(1) << __FUNCTION__ << "(" << state << ")";
acolwellb4034942014-08-28 15:42:431254 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]f5443ef72013-04-22 04:03:381255 network_state_ = state;
1256 // Always notify to ensure client has the latest value.
[email protected]ce70c982013-12-20 17:04:321257 client_->networkStateChanged();
[email protected]f5443ef72013-04-22 04:03:381258}
1259
1260void WebMediaPlayerImpl::SetReadyState(WebMediaPlayer::ReadyState state) {
[email protected]2a06ca62014-06-04 13:59:521261 DVLOG(1) << __FUNCTION__ << "(" << state << ")";
acolwellb4034942014-08-28 15:42:431262 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]f5443ef72013-04-22 04:03:381263
[email protected]fee8a902014-06-03 13:43:361264 if (state == WebMediaPlayer::ReadyStateHaveEnoughData && data_source_ &&
1265 data_source_->assume_fully_buffered() &&
[email protected]f5443ef72013-04-22 04:03:381266 network_state_ == WebMediaPlayer::NetworkStateLoading)
1267 SetNetworkState(WebMediaPlayer::NetworkStateLoaded);
1268
1269 ready_state_ = state;
1270 // Always notify to ensure client has the latest value.
[email protected]ce70c982013-12-20 17:04:321271 client_->readyStateChanged();
[email protected]f5443ef72013-04-22 04:03:381272}
1273
[email protected]180ef242013-11-07 06:50:461274blink::WebAudioSourceProvider* WebMediaPlayerImpl::audioSourceProvider() {
[email protected]ff875be52013-06-02 23:47:381275 return audio_source_provider_.get();
[email protected]f5443ef72013-04-22 04:03:381276}
1277
[email protected]f5443ef72013-04-22 04:03:381278double WebMediaPlayerImpl::GetPipelineDuration() const {
[email protected]f6af7592014-02-28 10:09:111279 base::TimeDelta duration = pipeline_.GetMediaDuration();
[email protected]f5443ef72013-04-22 04:03:381280
1281 // Return positive infinity if the resource is unbounded.
1282 // http://www.whatwg.org/specs/web-apps/current-work/multipage/video.html#dom-media-duration
acolwell9e0840d2014-09-06 19:01:321283 if (duration == kInfiniteDuration())
[email protected]f5443ef72013-04-22 04:03:381284 return std::numeric_limits<double>::infinity();
1285
1286 return duration.InSecondsF();
1287}
1288
[email protected]75e145a2014-04-15 17:44:321289void WebMediaPlayerImpl::OnDurationChanged() {
[email protected]f5443ef72013-04-22 04:03:381290 if (ready_state_ == WebMediaPlayer::ReadyStateHaveNothing)
1291 return;
1292
[email protected]ce70c982013-12-20 17:04:321293 client_->durationChanged();
[email protected]f5443ef72013-04-22 04:03:381294}
1295
[email protected]75e145a2014-04-15 17:44:321296void WebMediaPlayerImpl::OnNaturalSizeChanged(gfx::Size size) {
acolwellb4034942014-08-28 15:42:431297 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]739847c02014-01-16 00:12:251298 DCHECK_NE(ready_state_, WebMediaPlayer::ReadyStateHaveNothing);
1299 TRACE_EVENT0("media", "WebMediaPlayerImpl::OnNaturalSizeChanged");
1300
1301 media_log_->AddEvent(
1302 media_log_->CreateVideoSizeSetEvent(size.width(), size.height()));
[email protected]739847c02014-01-16 00:12:251303
watkdee516f2016-02-18 02:22:191304 if (fullscreen_ && surface_manager_ &&
1305 pipeline_metadata_.natural_size != size) {
1306 surface_manager_->NaturalSizeChanged(size);
1307 }
1308
1309 pipeline_metadata_.natural_size = size;
[email protected]739847c02014-01-16 00:12:251310 client_->sizeChanged();
1311}
1312
[email protected]75e145a2014-04-15 17:44:321313void WebMediaPlayerImpl::OnOpacityChanged(bool opaque) {
acolwellb4034942014-08-28 15:42:431314 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]75e145a2014-04-15 17:44:321315 DCHECK_NE(ready_state_, WebMediaPlayer::ReadyStateHaveNothing);
1316
1317 opaque_ = opaque;
jbauman952274d2015-09-10 23:23:361318 // Modify content opaqueness of cc::Layer directly so that
1319 // SetContentsOpaqueIsFixed is ignored.
[email protected]75e145a2014-04-15 17:44:321320 if (video_weblayer_)
jbauman952274d2015-09-10 23:23:361321 video_weblayer_->layer()->SetContentsOpaque(opaque_);
[email protected]75e145a2014-04-15 17:44:321322}
1323
[email protected]dd061e12014-05-06 19:21:221324static void GetCurrentFrameAndSignal(
1325 VideoFrameCompositor* compositor,
acolwell9e0840d2014-09-06 19:01:321326 scoped_refptr<VideoFrame>* video_frame_out,
[email protected]dd061e12014-05-06 19:21:221327 base::WaitableEvent* event) {
1328 TRACE_EVENT0("media", "GetCurrentFrameAndSignal");
dalecurtis44ce4de2015-05-11 18:42:071329 *video_frame_out = compositor->GetCurrentFrameAndUpdateIfStale();
[email protected]dd061e12014-05-06 19:21:221330 event->Signal();
1331}
1332
acolwell9e0840d2014-09-06 19:01:321333scoped_refptr<VideoFrame>
[email protected]dd061e12014-05-06 19:21:221334WebMediaPlayerImpl::GetCurrentFrameFromCompositor() {
1335 TRACE_EVENT0("media", "WebMediaPlayerImpl::GetCurrentFrameFromCompositor");
1336 if (compositor_task_runner_->BelongsToCurrentThread())
dalecurtis44ce4de2015-05-11 18:42:071337 return compositor_->GetCurrentFrameAndUpdateIfStale();
[email protected]dd061e12014-05-06 19:21:221338
1339 // Use a posted task and waitable event instead of a lock otherwise
1340 // WebGL/Canvas can see different content than what the compositor is seeing.
acolwell9e0840d2014-09-06 19:01:321341 scoped_refptr<VideoFrame> video_frame;
[email protected]dd061e12014-05-06 19:21:221342 base::WaitableEvent event(false, false);
1343 compositor_task_runner_->PostTask(FROM_HERE,
1344 base::Bind(&GetCurrentFrameAndSignal,
1345 base::Unretained(compositor_),
1346 &video_frame,
1347 &event));
1348 event.Wait();
1349 return video_frame;
1350}
1351
dalecurtis0f0097a2015-12-01 17:40:471352void WebMediaPlayerImpl::NotifyPlaybackStarted() {
hubbed5f36882016-01-15 22:40:371353#if defined(OS_ANDROID) // WMPI_CAST
dalecurtis5bbc487e2016-02-27 04:15:051354 // We do not tell our delegates about remote playback, because that would
hubbed5f36882016-01-15 22:40:371355 // keep the device awake, which is not what we want.
1356 if (isRemote())
1357 return;
1358#endif
dalecurtis5bbc487e2016-02-27 04:15:051359
sandersd1c0bba02016-03-04 23:14:081360 // NotifyPlaybackStarted() may be called by interactions while suspended,
1361 // (play/pause in particular). Those actions won't have any effect until the
1362 // pipeline is resumed.
1363 // TODO(dalecurtis): Should these be dropped at the call sites instead?
1364 // Alternatively, rename this method to include Maybe or Changed, and handle
1365 // multiple calls safely.
1366 if (pipeline_controller_.IsSuspended())
dalecurtis5bbc487e2016-02-27 04:15:051367 return;
1368
dalecurtisbb3eaac2016-01-27 21:10:251369 if (delegate_) {
1370 delegate_->DidPlay(delegate_id_, hasVideo(), hasAudio(), false,
1371 pipeline_.GetMediaDuration());
1372 }
dalecurtis0f0097a2015-12-01 17:40:471373 if (!memory_usage_reporting_timer_.IsRunning()) {
1374 memory_usage_reporting_timer_.Start(FROM_HERE,
1375 base::TimeDelta::FromSeconds(2), this,
1376 &WebMediaPlayerImpl::ReportMemoryUsage);
1377 }
1378}
1379
1380void WebMediaPlayerImpl::NotifyPlaybackPaused() {
hubbed5f36882016-01-15 22:40:371381#if defined(OS_ANDROID) // WMPI_CAST
1382 if (isRemote())
1383 return;
1384#endif
sandersd1c0bba02016-03-04 23:14:081385
1386 // Same as above, NotifyPlaybackPaused() may be called by interactions while
1387 // suspended, but those actions won't have any effect until the pipeline is
1388 // resumed.
1389 if (pipeline_controller_.IsSuspended())
1390 return;
1391
1392 if (delegate_)
dalecurtisbb3eaac2016-01-27 21:10:251393 delegate_->DidPause(delegate_id_, ended_);
dalecurtis0f0097a2015-12-01 17:40:471394 memory_usage_reporting_timer_.Stop();
1395 ReportMemoryUsage();
1396}
1397
dalecurtis83266c72015-10-29 18:43:201398void WebMediaPlayerImpl::ReportMemoryUsage() {
1399 DCHECK(main_task_runner_->BelongsToCurrentThread());
1400
wdzierzanowskifd4cd91c52015-12-02 23:50:201401 // About base::Unretained() usage below: We destroy |demuxer_| on the main
1402 // thread. Before that, however, ~WebMediaPlayerImpl() posts a task to the
1403 // media thread and waits for it to finish. Hence, the GetMemoryUsage() task
1404 // posted here must finish earlier.
1405
1406 if (demuxer_) {
1407 base::PostTaskAndReplyWithResult(
1408 media_task_runner_.get(), FROM_HERE,
1409 base::Bind(&Demuxer::GetMemoryUsage, base::Unretained(demuxer_.get())),
1410 base::Bind(&WebMediaPlayerImpl::FinishMemoryUsageReport, AsWeakPtr()));
1411 } else {
1412 FinishMemoryUsageReport(0);
1413 }
1414}
1415
1416void WebMediaPlayerImpl::FinishMemoryUsageReport(int64_t demuxer_memory_usage) {
1417 DCHECK(main_task_runner_->BelongsToCurrentThread());
1418
dalecurtis83266c72015-10-29 18:43:201419 const PipelineStatistics stats = pipeline_.GetStatistics();
1420 const int64_t current_memory_usage =
1421 stats.audio_memory_usage + stats.video_memory_usage +
1422 (data_source_ ? data_source_->GetMemoryUsage() : 0) +
wdzierzanowskifd4cd91c52015-12-02 23:50:201423 demuxer_memory_usage;
dalecurtis83266c72015-10-29 18:43:201424
1425 DVLOG(2) << "Memory Usage -- Audio: " << stats.audio_memory_usage
1426 << ", Video: " << stats.video_memory_usage << ", DataSource: "
1427 << (data_source_ ? data_source_->GetMemoryUsage() : 0)
wdzierzanowskifd4cd91c52015-12-02 23:50:201428 << ", Demuxer: " << demuxer_memory_usage;
dalecurtis83266c72015-10-29 18:43:201429
1430 const int64_t delta = current_memory_usage - last_reported_memory_usage_;
1431 last_reported_memory_usage_ = current_memory_usage;
1432 adjust_allocated_memory_cb_.Run(delta);
1433}
1434
acolwell9e0840d2014-09-06 19:01:321435} // namespace media