blob: da8feecc54b873831a94d4e3535efb102ff13c33 [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>
10
[email protected]08273c7b2011-09-17 00:33:5111#include "base/bind.h"
[email protected]2041cf342010-02-19 03:15:5912#include "base/callback.h"
[email protected]7502ef12014-01-25 01:19:2713#include "base/callback_helpers.h"
[email protected]ca04095f2014-02-07 10:23:5614#include "base/debug/alias.h"
[email protected]926f8fd2013-04-12 20:27:5315#include "base/debug/crash_logging.h"
[email protected]b0b258f2011-11-08 00:34:2316#include "base/metrics/histogram.h"
acolwellb4034942014-08-28 15:42:4317#include "base/single_thread_task_runner.h"
[email protected]cf02541b2012-04-11 08:02:1718#include "base/synchronization/waitable_event.h"
anujk.sharma2fa37a02015-04-30 05:51:3219#include "base/thread_task_runner_handle.h"
ssid9525f4672015-01-28 12:13:1520#include "base/trace_event/trace_event.h"
[email protected]38564622014-08-19 02:47:1821#include "cc/blink/web_layer_impl.h"
[email protected]21c3f7502013-03-23 03:29:5122#include "cc/layers/video_layer.h"
dongseong.hwang0c4e9d82015-01-08 20:11:1323#include "gpu/blink/webgraphicscontext3d_impl.h"
[email protected]e4fc09e2012-04-06 03:17:4424#include "media/audio/null_audio_sink.h"
[email protected]2eccbed2014-01-10 05:15:5325#include "media/base/bind_to_current_loop.h"
xhwang0ad11e512014-11-25 23:43:0926#include "media/base/cdm_context.h"
[email protected]32da1002010-03-03 21:57:3527#include "media/base/limits.h"
[email protected]090f7312011-08-05 23:26:4028#include "media/base/media_log.h"
[email protected]8a561062013-11-22 01:19:3129#include "media/base/text_renderer.h"
[email protected]e81283bb2010-08-31 18:01:2130#include "media/base/video_frame.h"
acolwell9e0840d2014-09-06 19:01:3231#include "media/blink/texttrack_impl.h"
32#include "media/blink/webaudiosourceprovider_impl.h"
xhwang97de4202014-11-25 08:44:0133#include "media/blink/webcontentdecryptionmodule_impl.h"
acolwell9e0840d2014-09-06 19:01:3234#include "media/blink/webinbandtexttrack_impl.h"
35#include "media/blink/webmediaplayer_delegate.h"
acolwell9e0840d2014-09-06 19:01:3236#include "media/blink/webmediaplayer_util.h"
37#include "media/blink/webmediasource_impl.h"
[email protected]efe7cd22012-09-12 23:55:0138#include "media/filters/chunk_demuxer.h"
[email protected]ddbc6ff2013-04-19 15:28:3339#include "media/filters/ffmpeg_demuxer.h"
jrummellc9d8e532015-02-26 18:38:1940#include "third_party/WebKit/public/platform/WebEncryptedMediaTypes.h"
[email protected]745746d2013-08-23 02:09:1641#include "third_party/WebKit/public/platform/WebMediaSource.h"
[email protected]c10884462013-05-30 00:22:0942#include "third_party/WebKit/public/platform/WebRect.h"
43#include "third_party/WebKit/public/platform/WebSize.h"
44#include "third_party/WebKit/public/platform/WebString.h"
45#include "third_party/WebKit/public/platform/WebURL.h"
[email protected]80504652014-04-18 04:41:5046#include "third_party/WebKit/public/web/WebLocalFrame.h"
xhwangbab66f52014-12-02 23:49:5047#include "third_party/WebKit/public/web/WebRuntimeFeatures.h"
[email protected]65b85282014-03-31 23:32:3148#include "third_party/WebKit/public/web/WebSecurityOrigin.h"
[email protected]2255a9332013-06-17 05:12:3149#include "third_party/WebKit/public/web/WebView.h"
[email protected]b3f2b912009-04-09 16:18:5250
[email protected]180ef242013-11-07 06:50:4651using blink::WebCanvas;
52using blink::WebMediaPlayer;
53using blink::WebRect;
54using blink::WebSize;
55using blink::WebString;
[email protected]ec9212f2008-12-18 21:40:3656
[email protected]8931c41a2009-07-07 17:31:4957namespace {
58
[email protected]378f0b72009-08-11 17:11:4259// Limits the range of playback rate.
60//
61// TODO(kylep): Revisit these.
62//
63// Vista has substantially lower performance than XP or Windows7. If you speed
64// up a video too much, it can't keep up, and rendering stops updating except on
65// the time bar. For really high speeds, audio becomes a bottleneck and we just
66// use up the data we have, which may not achieve the speed requested, but will
67// not crash the tab.
68//
69// A very slow speed, ie 0.00000001x, causes the machine to lock up. (It seems
70// like a busy loop). It gets unresponsive, although its not completely dead.
71//
72// Also our timers are not very accurate (especially for ogg), which becomes
73// evident at low speeds and on Vista. Since other speeds are risky and outside
74// the norms, we think 1/16x to 16x is a safe and useful range for now.
[email protected]39bdde32013-04-17 17:44:2075const double kMinRate = 0.0625;
76const double kMaxRate = 16.0;
[email protected]378f0b72009-08-11 17:11:4277
[email protected]8931c41a2009-07-07 17:31:4978} // namespace
79
acolwell9e0840d2014-09-06 19:01:3280namespace media {
[email protected]add51772009-06-11 18:25:1781
[email protected]6683e1b2014-04-10 01:45:3882class BufferedDataSourceHostImpl;
83
mostynb502b00b2015-01-05 23:43:4084#define STATIC_ASSERT_MATCHING_ENUM(name) \
85 static_assert(static_cast<int>(WebMediaPlayer::CORSMode ## name) == \
86 static_cast<int>(BufferedResourceLoader::k ## name), \
87 "mismatching enum values: " #name)
88STATIC_ASSERT_MATCHING_ENUM(Unspecified);
89STATIC_ASSERT_MATCHING_ENUM(Anonymous);
90STATIC_ASSERT_MATCHING_ENUM(UseCredentials);
91#undef STATIC_ASSERT_MATCHING_ENUM
[email protected]a5a01102012-06-06 17:01:2492
[email protected]2c539b82012-08-18 04:10:1993#define BIND_TO_RENDER_LOOP(function) \
acolwellb4034942014-08-28 15:42:4394 (DCHECK(main_task_runner_->BelongsToCurrentThread()), \
acolwell9e0840d2014-09-06 19:01:3295 BindToCurrentLoop(base::Bind(function, AsWeakPtr())))
[email protected]5983adb2012-10-24 00:12:0096
[email protected]4e982192014-06-21 13:35:4597#define BIND_TO_RENDER_LOOP1(function, arg1) \
acolwellb4034942014-08-28 15:42:4398 (DCHECK(main_task_runner_->BelongsToCurrentThread()), \
acolwell9e0840d2014-09-06 19:01:3299 BindToCurrentLoop(base::Bind(function, AsWeakPtr(), arg1)))
[email protected]4e982192014-06-21 13:35:45100
[email protected]5b5bb9d2010-10-22 19:57:36101WebMediaPlayerImpl::WebMediaPlayerImpl(
[email protected]35b2a972014-04-04 15:50:22102 blink::WebLocalFrame* frame,
[email protected]180ef242013-11-07 06:50:46103 blink::WebMediaPlayerClient* client,
[email protected]b8976652011-10-26 23:46:55104 base::WeakPtr<WebMediaPlayerDelegate> delegate,
xhwang6fa356202014-12-11 00:44:12105 scoped_ptr<RendererFactory> renderer_factory,
xhwangd7180832015-04-03 05:38:15106 CdmFactory* cdm_factory,
[email protected]e82b2bd2013-01-02 17:47:57107 const WebMediaPlayerParams& params)
[email protected]f6af7592014-02-28 10:09:11108 : frame_(frame),
[email protected]ef405f66b2012-04-18 02:39:55109 network_state_(WebMediaPlayer::NetworkStateEmpty),
110 ready_state_(WebMediaPlayer::ReadyStateHaveNothing),
acolwella5081a42014-08-28 23:42:52111 preload_(BufferedDataSource::AUTO),
anujk.sharma2fa37a02015-04-30 05:51:32112 main_task_runner_(base::ThreadTaskRunnerHandle::Get()),
acolwell755d12d2014-08-30 01:09:19113 media_task_runner_(params.media_task_runner()),
114 media_log_(params.media_log()),
acolwellb4034942014-08-28 15:42:43115 pipeline_(media_task_runner_, media_log_.get()),
[email protected]f988d9b2014-07-25 00:35:43116 load_type_(LoadTypeURL),
[email protected]75e145a2014-04-15 17:44:32117 opaque_(false),
[email protected]49480902009-07-14 20:23:43118 paused_(true),
[email protected]b3766a22010-12-22 17:34:13119 seeking_(false),
a.berwal338bf002015-04-22 11:14:50120 playback_rate_(0.0),
scherkusd2c745b2014-09-04 05:03:40121 ended_(false),
[email protected]5d11eff2011-09-15 00:06:06122 pending_seek_(false),
[email protected]b1a975e2011-12-21 00:12:39123 pending_seek_seconds_(0.0f),
[email protected]ba7d5f92014-06-24 05:37:40124 should_notify_time_changed_(false),
[email protected]5badb082010-06-11 17:40:15125 client_(client),
[email protected]baff4512011-10-19 18:21:07126 delegate_(delegate),
[email protected]d726eddc2013-07-02 22:25:55127 defer_load_cb_(params.defer_load_cb()),
dongseong.hwang0c4e9d82015-01-08 20:11:13128 context_3d_cb_(params.context_3d_cb()),
[email protected]132dd57c2012-08-10 23:24:34129 supports_save_(true),
[email protected]f5443ef72013-04-22 04:03:38130 chunk_demuxer_(NULL),
Bartosz Fabianowski85a823812015-04-16 10:27:51131 // Threaded compositing isn't enabled universally yet.
132 compositor_task_runner_(
133 params.compositor_task_runner()
134 ? params.compositor_task_runner()
135 : base::MessageLoop::current()->task_runner()),
[email protected]dd061e12014-05-06 19:21:22136 compositor_(new VideoFrameCompositor(
Bartosz Fabianowski85a823812015-04-16 10:27:51137 compositor_task_runner_,
[email protected]75e145a2014-04-15 17:44:32138 BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnNaturalSizeChanged),
[email protected]dd061e12014-05-06 19:21:22139 BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnOpacityChanged))),
xhwang9bd8c732015-04-13 23:27:53140 encrypted_media_support_(cdm_factory,
141 client,
142 params.media_permission(),
143 base::Bind(&WebMediaPlayerImpl::SetCdm,
144 AsWeakPtr(),
145 base::Bind(&IgnoreCdmAttached))),
xhwang6fa356202014-12-11 00:44:12146 renderer_factory_(renderer_factory.Pass()) {
[email protected]c93eb0a62011-08-09 22:47:24147 media_log_->AddEvent(
acolwell9e0840d2014-09-06 19:01:32148 media_log_->CreateEvent(MediaLogEvent::WEBMEDIAPLAYER_CREATED));
[email protected]4e6be3f2009-05-07 02:24:44149
xhwang0ad11e512014-11-25 23:43:09150 if (params.initial_cdm()) {
xhwang9bd8c732015-04-13 23:27:53151 SetCdm(base::Bind(&IgnoreCdmAttached),
152 ToWebContentDecryptionModuleImpl(params.initial_cdm())
153 ->GetCdmContext());
xhwang0ad11e512014-11-25 23:43:09154 }
155
xhwangf94a634d2014-10-22 22:07:27156 // TODO(xhwang): When we use an external Renderer, many methods won't work,
xhwang6fa356202014-12-11 00:44:12157 // e.g. GetCurrentFrameFromCompositor(). See http://crbug.com/434861
[email protected]c50edb962013-10-19 18:05:07158
[email protected]ddbc6ff2013-04-19 15:28:33159 // Use the null sink if no sink was provided.
[email protected]4a914882013-01-10 00:43:48160 audio_source_provider_ = new WebAudioSourceProviderImpl(
[email protected]ff875be52013-06-02 23:47:38161 params.audio_renderer_sink().get()
162 ? params.audio_renderer_sink()
acolwell9e0840d2014-09-06 19:01:32163 : new NullAudioSink(media_task_runner_));
[email protected]ec9212f2008-12-18 21:40:36164}
165
[email protected]4e6be3f2009-05-07 02:24:44166WebMediaPlayerImpl::~WebMediaPlayerImpl() {
[email protected]ce70c982013-12-20 17:04:32167 client_->setWebLayer(NULL);
[email protected]21c3f7502013-03-23 03:29:51168
acolwellb4034942014-08-28 15:42:43169 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]c93eb0a62011-08-09 22:47:24170 media_log_->AddEvent(
acolwell9e0840d2014-09-06 19:01:32171 media_log_->CreateEvent(MediaLogEvent::WEBMEDIAPLAYER_DESTROYED));
[email protected]d43ed912009-02-03 04:52:53172
dalecurtis6d269ed2014-09-11 21:18:13173 if (delegate_)
[email protected]baff4512011-10-19 18:21:07174 delegate_->PlayerGone(this);
175
[email protected]f6af7592014-02-28 10:09:11176 // Abort any pending IO so stopping the pipeline doesn't get blocked.
177 if (data_source_)
178 data_source_->Abort();
179 if (chunk_demuxer_) {
180 chunk_demuxer_->Shutdown();
181 chunk_demuxer_ = NULL;
182 }
183
xhwang6fa356202014-12-11 00:44:12184 renderer_factory_.reset();
[email protected]f6af7592014-02-28 10:09:11185
186 // Make sure to kill the pipeline so there's no more media threads running.
187 // Note: stopping the pipeline might block for a long time.
188 base::WaitableEvent waiter(false, false);
189 pipeline_.Stop(
190 base::Bind(&base::WaitableEvent::Signal, base::Unretained(&waiter)));
191 waiter.Wait();
192
[email protected]dd061e12014-05-06 19:21:22193 compositor_task_runner_->DeleteSoon(FROM_HERE, compositor_);
[email protected]ec9212f2008-12-18 21:40:36194}
195
[email protected]180ef242013-11-07 06:50:46196void WebMediaPlayerImpl::load(LoadType load_type, const blink::WebURL& url,
[email protected]62e5e682013-03-07 23:53:24197 CORSMode cors_mode) {
[email protected]2a06ca62014-06-04 13:59:52198 DVLOG(1) << __FUNCTION__ << "(" << load_type << ", " << url << ", "
199 << cors_mode << ")";
[email protected]d726eddc2013-07-02 22:25:55200 if (!defer_load_cb_.is_null()) {
201 defer_load_cb_.Run(base::Bind(
[email protected]ef8394c2013-08-21 20:26:30202 &WebMediaPlayerImpl::DoLoad, AsWeakPtr(), load_type, url, cors_mode));
[email protected]d726eddc2013-07-02 22:25:55203 return;
204 }
[email protected]ef8394c2013-08-21 20:26:30205 DoLoad(load_type, url, cors_mode);
[email protected]62e5e682013-03-07 23:53:24206}
207
[email protected]ef8394c2013-08-21 20:26:30208void WebMediaPlayerImpl::DoLoad(LoadType load_type,
[email protected]180ef242013-11-07 06:50:46209 const blink::WebURL& url,
[email protected]d726eddc2013-07-02 22:25:55210 CORSMode cors_mode) {
acolwellb4034942014-08-28 15:42:43211 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]d726eddc2013-07-02 22:25:55212
[email protected]62e5e682013-03-07 23:53:24213 GURL gurl(url);
[email protected]e2f6bba2014-06-09 20:08:07214 ReportMediaSchemeUma(gurl);
[email protected]62e5e682013-03-07 23:53:24215
[email protected]926f8fd2013-04-12 20:27:53216 // Set subresource URL for crash reporting.
217 base::debug::SetCrashKeyValue("subresource_url", gurl.spec());
218
[email protected]ef8394c2013-08-21 20:26:30219 load_type_ = load_type;
220
[email protected]62e5e682013-03-07 23:53:24221 SetNetworkState(WebMediaPlayer::NetworkStateLoading);
222 SetReadyState(WebMediaPlayer::ReadyStateHaveNothing);
223 media_log_->AddEvent(media_log_->CreateLoadEvent(url.spec()));
[email protected]d726eddc2013-07-02 22:25:55224
225 // Media source pipelines can start immediately.
[email protected]ef8394c2013-08-21 20:26:30226 if (load_type == LoadTypeMediaSource) {
[email protected]d726eddc2013-07-02 22:25:55227 supports_save_ = false;
[email protected]ef8394c2013-08-21 20:26:30228 StartPipeline();
[email protected]d726eddc2013-07-02 22:25:55229 return;
230 }
231
232 // Otherwise it's a regular request which requires resolving the URL first.
233 data_source_.reset(new BufferedDataSource(
[email protected]fee8a902014-06-03 13:43:36234 url,
235 static_cast<BufferedResourceLoader::CORSMode>(cors_mode),
acolwellb4034942014-08-28 15:42:43236 main_task_runner_,
[email protected]d726eddc2013-07-02 22:25:55237 frame_,
238 media_log_.get(),
[email protected]6683e1b2014-04-10 01:45:38239 &buffered_data_source_host_,
[email protected]d726eddc2013-07-02 22:25:55240 base::Bind(&WebMediaPlayerImpl::NotifyDownloading, AsWeakPtr())));
dalecurtis9157fc9e2015-01-16 01:09:11241 data_source_->SetPreload(preload_);
[email protected]d726eddc2013-07-02 22:25:55242 data_source_->Initialize(
[email protected]fee8a902014-06-03 13:43:36243 base::Bind(&WebMediaPlayerImpl::DataSourceInitialized, AsWeakPtr()));
[email protected]62e5e682013-03-07 23:53:24244}
245
[email protected]4e6be3f2009-05-07 02:24:44246void WebMediaPlayerImpl::play() {
[email protected]2a06ca62014-06-04 13:59:52247 DVLOG(1) << __FUNCTION__;
acolwellb4034942014-08-28 15:42:43248 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]d43ed912009-02-03 04:52:53249
[email protected]49480902009-07-14 20:23:43250 paused_ = false;
[email protected]f6af7592014-02-28 10:09:11251 pipeline_.SetPlaybackRate(playback_rate_);
[email protected]039b7542013-10-17 22:06:25252 if (data_source_)
253 data_source_->MediaIsPlaying();
[email protected]090f7312011-08-05 23:26:40254
acolwell9e0840d2014-09-06 19:01:32255 media_log_->AddEvent(media_log_->CreateEvent(MediaLogEvent::PLAY));
[email protected]baff4512011-10-19 18:21:07256
dalecurtis6d269ed2014-09-11 21:18:13257 if (delegate_ && playback_rate_ > 0)
[email protected]baff4512011-10-19 18:21:07258 delegate_->DidPlay(this);
[email protected]ec9212f2008-12-18 21:40:36259}
260
[email protected]4e6be3f2009-05-07 02:24:44261void WebMediaPlayerImpl::pause() {
[email protected]2a06ca62014-06-04 13:59:52262 DVLOG(1) << __FUNCTION__;
acolwellb4034942014-08-28 15:42:43263 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]d43ed912009-02-03 04:52:53264
dalecurtis6d269ed2014-09-11 21:18:13265 const bool was_already_paused = paused_ || playback_rate_ == 0;
[email protected]49480902009-07-14 20:23:43266 paused_ = true;
a.berwal338bf002015-04-22 11:14:50267 pipeline_.SetPlaybackRate(0.0);
[email protected]039b7542013-10-17 22:06:25268 if (data_source_)
269 data_source_->MediaIsPaused();
dalecurtis2e50e6f62015-01-09 02:42:52270 UpdatePausedTime();
[email protected]090f7312011-08-05 23:26:40271
acolwell9e0840d2014-09-06 19:01:32272 media_log_->AddEvent(media_log_->CreateEvent(MediaLogEvent::PAUSE));
[email protected]baff4512011-10-19 18:21:07273
dalecurtis6d269ed2014-09-11 21:18:13274 if (!was_already_paused && delegate_)
[email protected]baff4512011-10-19 18:21:07275 delegate_->DidPause(this);
[email protected]ec9212f2008-12-18 21:40:36276}
277
[email protected]574a1d62009-07-17 03:23:46278bool WebMediaPlayerImpl::supportsSave() const {
acolwellb4034942014-08-28 15:42:43279 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]132dd57c2012-08-10 23:24:34280 return supports_save_;
[email protected]574a1d62009-07-17 03:23:46281}
282
[email protected]39bdde32013-04-17 17:44:20283void WebMediaPlayerImpl::seek(double seconds) {
xhwang12d8d042014-12-01 21:48:57284 DVLOG(1) << __FUNCTION__ << "(" << seconds << "s)";
acolwellb4034942014-08-28 15:42:43285 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]d43ed912009-02-03 04:52:53286
scherkusd2c745b2014-09-04 05:03:40287 ended_ = false;
288
srirama.mccf671812015-01-08 11:59:13289 ReadyState old_state = ready_state_;
[email protected]1bb666802013-11-28 06:12:08290 if (ready_state_ > WebMediaPlayer::ReadyStateHaveMetadata)
291 SetReadyState(WebMediaPlayer::ReadyStateHaveMetadata);
292
[email protected]bb8a70b2013-06-26 06:23:35293 base::TimeDelta seek_time = ConvertSecondsToTimestamp(seconds);
294
[email protected]d228aeec2014-06-20 19:16:49295 if (seeking_) {
[email protected]5d11eff2011-09-15 00:06:06296 pending_seek_ = true;
297 pending_seek_seconds_ = seconds;
[email protected]efe7cd22012-09-12 23:55:01298 if (chunk_demuxer_)
[email protected]bb8a70b2013-06-26 06:23:35299 chunk_demuxer_->CancelPendingSeek(seek_time);
[email protected]5d11eff2011-09-15 00:06:06300 return;
301 }
302
[email protected]c93eb0a62011-08-09 22:47:24303 media_log_->AddEvent(media_log_->CreateSeekEvent(seconds));
304
[email protected]44ff37c02009-10-24 01:03:03305 // Update our paused time.
srirama.mccf671812015-01-08 11:59:13306 // In paused state ignore the seek operations to current time if the loading
307 // is completed and generate OnPipelineBufferingStateChanged event to
308 // eventually fire seeking and seeked events
srirama.m36ab2682014-12-11 04:20:01309 if (paused_) {
310 if (paused_time_ != seek_time) {
311 paused_time_ = seek_time;
srirama.mccf671812015-01-08 11:59:13312 } else if (old_state == ReadyStateHaveEnoughData) {
srirama.m8f4a37562014-12-13 08:16:18313 main_task_runner_->PostTask(
srirama.m36ab2682014-12-11 04:20:01314 FROM_HERE,
315 base::Bind(&WebMediaPlayerImpl::OnPipelineBufferingStateChanged,
srirama.m8f4a37562014-12-13 08:16:18316 AsWeakPtr(), BUFFERING_HAVE_ENOUGH));
srirama.m36ab2682014-12-11 04:20:01317 return;
318 }
319 }
[email protected]44ff37c02009-10-24 01:03:03320
[email protected]b3766a22010-12-22 17:34:13321 seeking_ = true;
322
[email protected]efe7cd22012-09-12 23:55:01323 if (chunk_demuxer_)
[email protected]bb8a70b2013-06-26 06:23:35324 chunk_demuxer_->StartWaitingForSeek(seek_time);
[email protected]020fba32011-06-29 16:37:46325
[email protected]44ff37c02009-10-24 01:03:03326 // Kick off the asynchronous seek!
[email protected]f6af7592014-02-28 10:09:11327 pipeline_.Seek(
[email protected]44ff37c02009-10-24 01:03:03328 seek_time,
[email protected]4e982192014-06-21 13:35:45329 BIND_TO_RENDER_LOOP1(&WebMediaPlayerImpl::OnPipelineSeeked, true));
[email protected]ec9212f2008-12-18 21:40:36330}
331
[email protected]39bdde32013-04-17 17:44:20332void WebMediaPlayerImpl::setRate(double rate) {
[email protected]2a06ca62014-06-04 13:59:52333 DVLOG(1) << __FUNCTION__ << "(" << rate << ")";
acolwellb4034942014-08-28 15:42:43334 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]d43ed912009-02-03 04:52:53335
[email protected]378f0b72009-08-11 17:11:42336 // TODO(kylep): Remove when support for negatives is added. Also, modify the
337 // following checks so rewind uses reasonable values also.
[email protected]39bdde32013-04-17 17:44:20338 if (rate < 0.0)
[email protected]378f0b72009-08-11 17:11:42339 return;
340
341 // Limit rates to reasonable values by clamping.
[email protected]39bdde32013-04-17 17:44:20342 if (rate != 0.0) {
[email protected]378f0b72009-08-11 17:11:42343 if (rate < kMinRate)
344 rate = kMinRate;
345 else if (rate > kMaxRate)
346 rate = kMaxRate;
dalecurtisbb761e12014-09-12 01:16:35347 if (playback_rate_ == 0 && !paused_ && delegate_)
dalecurtis6d269ed2014-09-11 21:18:13348 delegate_->DidPlay(this);
dalecurtisbb761e12014-09-12 01:16:35349 } else if (playback_rate_ != 0 && !paused_ && delegate_) {
dalecurtis6d269ed2014-09-11 21:18:13350 delegate_->DidPause(this);
[email protected]378f0b72009-08-11 17:11:42351 }
352
[email protected]49480902009-07-14 20:23:43353 playback_rate_ = rate;
354 if (!paused_) {
[email protected]f6af7592014-02-28 10:09:11355 pipeline_.SetPlaybackRate(rate);
[email protected]039b7542013-10-17 22:06:25356 if (data_source_)
357 data_source_->MediaPlaybackRateChanged(rate);
[email protected]49480902009-07-14 20:23:43358 }
[email protected]ec9212f2008-12-18 21:40:36359}
360
[email protected]39bdde32013-04-17 17:44:20361void WebMediaPlayerImpl::setVolume(double volume) {
[email protected]2a06ca62014-06-04 13:59:52362 DVLOG(1) << __FUNCTION__ << "(" << volume << ")";
acolwellb4034942014-08-28 15:42:43363 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]d43ed912009-02-03 04:52:53364
[email protected]f6af7592014-02-28 10:09:11365 pipeline_.SetVolume(volume);
[email protected]ec9212f2008-12-18 21:40:36366}
[email protected]f0a51fb52009-03-05 12:46:38367
mostynb502b00b2015-01-05 23:43:40368#define STATIC_ASSERT_MATCHING_ENUM(webkit_name, chromium_name) \
369 static_assert(static_cast<int>(WebMediaPlayer::webkit_name) == \
370 static_cast<int>(BufferedDataSource::chromium_name), \
371 "mismatching enum values: " #webkit_name)
372STATIC_ASSERT_MATCHING_ENUM(PreloadNone, NONE);
373STATIC_ASSERT_MATCHING_ENUM(PreloadMetaData, METADATA);
374STATIC_ASSERT_MATCHING_ENUM(PreloadAuto, AUTO);
375#undef STATIC_ASSERT_MATCHING_ENUM
[email protected]23a8b1d82011-04-05 16:28:20376
[email protected]ef405f66b2012-04-18 02:39:55377void WebMediaPlayerImpl::setPreload(WebMediaPlayer::Preload preload) {
[email protected]2a06ca62014-06-04 13:59:52378 DVLOG(1) << __FUNCTION__ << "(" << preload << ")";
acolwellb4034942014-08-28 15:42:43379 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]4e6be3f2009-05-07 02:24:44380
acolwella5081a42014-08-28 23:42:52381 preload_ = static_cast<BufferedDataSource::Preload>(preload);
[email protected]b49beeb2013-03-01 20:04:00382 if (data_source_)
[email protected]09c60222014-08-07 16:42:31383 data_source_->SetPreload(preload_);
[email protected]4e6be3f2009-05-07 02:24:44384}
385
[email protected]4e6be3f2009-05-07 02:24:44386bool WebMediaPlayerImpl::hasVideo() const {
acolwellb4034942014-08-28 15:42:43387 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]d43ed912009-02-03 04:52:53388
[email protected]b8877772014-03-26 20:17:15389 return pipeline_metadata_.has_video;
[email protected]d43ed912009-02-03 04:52:53390}
391
[email protected]fc367af2009-08-14 23:06:35392bool WebMediaPlayerImpl::hasAudio() const {
acolwellb4034942014-08-28 15:42:43393 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]fc367af2009-08-14 23:06:35394
[email protected]b8877772014-03-26 20:17:15395 return pipeline_metadata_.has_audio;
[email protected]fc367af2009-08-14 23:06:35396}
397
[email protected]180ef242013-11-07 06:50:46398blink::WebSize WebMediaPlayerImpl::naturalSize() const {
acolwellb4034942014-08-28 15:42:43399 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]d43ed912009-02-03 04:52:53400
[email protected]b8877772014-03-26 20:17:15401 return blink::WebSize(pipeline_metadata_.natural_size);
[email protected]d43ed912009-02-03 04:52:53402}
403
[email protected]4e6be3f2009-05-07 02:24:44404bool WebMediaPlayerImpl::paused() const {
acolwellb4034942014-08-28 15:42:43405 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]d43ed912009-02-03 04:52:53406
[email protected]f6af7592014-02-28 10:09:11407 return pipeline_.GetPlaybackRate() == 0.0f;
[email protected]d43ed912009-02-03 04:52:53408}
409
[email protected]4e6be3f2009-05-07 02:24:44410bool WebMediaPlayerImpl::seeking() const {
acolwellb4034942014-08-28 15:42:43411 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]d43ed912009-02-03 04:52:53412
[email protected]ef405f66b2012-04-18 02:39:55413 if (ready_state_ == WebMediaPlayer::ReadyStateHaveNothing)
[email protected]0acebfa2009-08-21 22:45:40414 return false;
[email protected]67cd5052009-09-10 21:53:22415
[email protected]b3766a22010-12-22 17:34:13416 return seeking_;
[email protected]ec9212f2008-12-18 21:40:36417}
418
[email protected]39bdde32013-04-17 17:44:20419double WebMediaPlayerImpl::duration() const {
acolwellb4034942014-08-28 15:42:43420 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]39bdde32013-04-17 17:44:20421
422 if (ready_state_ == WebMediaPlayer::ReadyStateHaveNothing)
423 return std::numeric_limits<double>::quiet_NaN();
424
[email protected]39bdde32013-04-17 17:44:20425 return GetPipelineDuration();
[email protected]d43ed912009-02-03 04:52:53426}
427
[email protected]db66d0092014-04-16 07:15:12428double WebMediaPlayerImpl::timelineOffset() const {
acolwellb4034942014-08-28 15:42:43429 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]db66d0092014-04-16 07:15:12430
431 if (pipeline_metadata_.timeline_offset.is_null())
432 return std::numeric_limits<double>::quiet_NaN();
433
434 return pipeline_metadata_.timeline_offset.ToJsTime();
435}
436
[email protected]39bdde32013-04-17 17:44:20437double WebMediaPlayerImpl::currentTime() const {
acolwellb4034942014-08-28 15:42:43438 DCHECK(main_task_runner_->BelongsToCurrentThread());
scherkusd2c745b2014-09-04 05:03:40439 DCHECK_NE(ready_state_, WebMediaPlayer::ReadyStateHaveNothing);
440
441 // TODO(scherkus): Replace with an explicit ended signal to HTMLMediaElement,
442 // see http://crbug.com/409280
443 if (ended_)
444 return duration();
445
[email protected]f6af7592014-02-28 10:09:11446 return (paused_ ? paused_time_ : pipeline_.GetMediaTime()).InSecondsF();
[email protected]d43ed912009-02-03 04:52:53447}
448
[email protected]ef405f66b2012-04-18 02:39:55449WebMediaPlayer::NetworkState WebMediaPlayerImpl::networkState() const {
acolwellb4034942014-08-28 15:42:43450 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]ddb1e5a2010-12-13 20:10:45451 return network_state_;
452}
453
[email protected]ef405f66b2012-04-18 02:39:55454WebMediaPlayer::ReadyState WebMediaPlayerImpl::readyState() const {
acolwellb4034942014-08-28 15:42:43455 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]ddb1e5a2010-12-13 20:10:45456 return ready_state_;
457}
458
[email protected]02022fc2014-05-16 00:05:31459blink::WebTimeRanges WebMediaPlayerImpl::buffered() const {
acolwellb4034942014-08-28 15:42:43460 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]779a8322014-08-22 21:28:37461
acolwell9e0840d2014-09-06 19:01:32462 Ranges<base::TimeDelta> buffered_time_ranges =
[email protected]02022fc2014-05-16 00:05:31463 pipeline_.GetBufferedTimeRanges();
[email protected]779a8322014-08-22 21:28:37464
465 const base::TimeDelta duration = pipeline_.GetMediaDuration();
acolwell9e0840d2014-09-06 19:01:32466 if (duration != kInfiniteDuration()) {
[email protected]779a8322014-08-22 21:28:37467 buffered_data_source_host_.AddBufferedTimeRanges(
468 &buffered_time_ranges, duration);
469 }
[email protected]02022fc2014-05-16 00:05:31470 return ConvertToWebTimeRanges(buffered_time_ranges);
471}
472
philipjb0e6f3f2014-09-30 09:51:53473blink::WebTimeRanges WebMediaPlayerImpl::seekable() const {
acolwellb4034942014-08-28 15:42:43474 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]39bdde32013-04-17 17:44:20475
dalecurtis56359cb2014-10-28 00:06:29476 if (ready_state_ < WebMediaPlayer::ReadyStateHaveMetadata)
philipjb0e6f3f2014-09-30 09:51:53477 return blink::WebTimeRanges();
478
dalecurtis56359cb2014-10-28 00:06:29479 const double seekable_end = duration();
480
481 // Allow a special exception for seeks to zero for streaming sources with a
482 // finite duration; this allows looping to work.
483 const bool allow_seek_to_zero = data_source_ && data_source_->IsStreaming() &&
mateuszs3371ab02015-04-24 13:20:23484 std::isfinite(seekable_end);
dalecurtis56359cb2014-10-28 00:06:29485
486 // TODO(dalecurtis): Technically this allows seeking on media which return an
487 // infinite duration so long as DataSource::IsStreaming() is false. While not
488 // expected, disabling this breaks semi-live players, http://crbug.com/427412.
489 const blink::WebTimeRange seekable_range(
490 0.0, allow_seek_to_zero ? 0.0 : seekable_end);
philipjb0e6f3f2014-09-30 09:51:53491 return blink::WebTimeRanges(&seekable_range, 1);
[email protected]ec9212f2008-12-18 21:40:36492}
493
[email protected]5d2b3e4c2014-05-12 23:27:30494bool WebMediaPlayerImpl::didLoadingProgress() {
acolwellb4034942014-08-28 15:42:43495 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]6683e1b2014-04-10 01:45:38496 bool pipeline_progress = pipeline_.DidLoadingProgress();
497 bool data_progress = buffered_data_source_host_.DidLoadingProgress();
498 return pipeline_progress || data_progress;
[email protected]d43ed912009-02-03 04:52:53499}
500
[email protected]dd5c7972014-08-21 15:00:37501void WebMediaPlayerImpl::paint(blink::WebCanvas* canvas,
502 const blink::WebRect& rect,
[email protected]dd5c7972014-08-21 15:00:37503 unsigned char alpha,
504 SkXfermode::Mode mode) {
acolwellb4034942014-08-28 15:42:43505 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]dd061e12014-05-06 19:21:22506 TRACE_EVENT0("media", "WebMediaPlayerImpl:paint");
[email protected]4e6be3f2009-05-07 02:24:44507
[email protected]5e1502e2014-03-24 22:48:44508 // TODO(scherkus): Clarify paint() API contract to better understand when and
509 // why it's being called. For example, today paint() is called when:
510 // - We haven't reached HAVE_CURRENT_DATA and need to paint black
511 // - We're painting to a canvas
512 // See http://crbug.com/341225 http://crbug.com/342621 for details.
mcasasf1236fc22015-05-29 22:38:56513 scoped_refptr<VideoFrame> video_frame = GetCurrentFrameFromCompositor();
[email protected]0fe5d43b2014-01-24 23:32:45514
[email protected]b49beeb2013-03-01 20:04:00515 gfx::Rect gfx_rect(rect);
dongseong.hwang0c4e9d82015-01-08 20:11:13516 Context3D context_3d;
517 if (video_frame.get() &&
mcasasf1236fc22015-05-29 22:38:56518 video_frame->storage_type() == VideoFrame::STORAGE_TEXTURE) {
519 if (!context_3d_cb_.is_null())
dongseong.hwang0c4e9d82015-01-08 20:11:13520 context_3d = context_3d_cb_.Run();
dongseong.hwang0c4e9d82015-01-08 20:11:13521 // GPU Process crashed.
522 if (!context_3d.gl)
523 return;
524 }
525 skcanvas_video_renderer_.Paint(video_frame, canvas, gfx_rect, alpha, mode,
526 pipeline_metadata_.video_rotation, context_3d);
[email protected]ec9212f2008-12-18 21:40:36527}
[email protected]5df51652009-01-17 00:03:00528
[email protected]38259a7a82009-07-29 21:49:49529bool WebMediaPlayerImpl::hasSingleSecurityOrigin() const {
[email protected]b49beeb2013-03-01 20:04:00530 if (data_source_)
531 return data_source_->HasSingleOrigin();
[email protected]fcdb7462009-10-21 21:05:11532 return true;
[email protected]38259a7a82009-07-29 21:49:49533}
534
[email protected]3fe27112012-06-07 04:00:01535bool WebMediaPlayerImpl::didPassCORSAccessCheck() const {
[email protected]b49beeb2013-03-01 20:04:00536 if (data_source_)
537 return data_source_->DidPassCORSAccessCheck();
538 return false;
[email protected]3fe27112012-06-07 04:00:01539}
540
[email protected]39bdde32013-04-17 17:44:20541double WebMediaPlayerImpl::mediaTimeForTimeValue(double timeValue) const {
[email protected]e06e16d82011-05-26 22:13:33542 return ConvertSecondsToTimestamp(timeValue).InSecondsF();
543}
544
[email protected]d82b18ae2011-03-23 21:28:59545unsigned WebMediaPlayerImpl::decodedFrameCount() const {
acolwellb4034942014-08-28 15:42:43546 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]4c51bc662011-02-16 02:03:16547
acolwell9e0840d2014-09-06 19:01:32548 PipelineStatistics stats = pipeline_.GetStatistics();
[email protected]4c51bc662011-02-16 02:03:16549 return stats.video_frames_decoded;
550}
551
[email protected]d82b18ae2011-03-23 21:28:59552unsigned WebMediaPlayerImpl::droppedFrameCount() const {
acolwellb4034942014-08-28 15:42:43553 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]4c51bc662011-02-16 02:03:16554
acolwell9e0840d2014-09-06 19:01:32555 PipelineStatistics stats = pipeline_.GetStatistics();
[email protected]dd061e12014-05-06 19:21:22556 return stats.video_frames_dropped;
[email protected]4c51bc662011-02-16 02:03:16557}
558
[email protected]d82b18ae2011-03-23 21:28:59559unsigned WebMediaPlayerImpl::audioDecodedByteCount() const {
acolwellb4034942014-08-28 15:42:43560 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]4c51bc662011-02-16 02:03:16561
acolwell9e0840d2014-09-06 19:01:32562 PipelineStatistics stats = pipeline_.GetStatistics();
[email protected]4c51bc662011-02-16 02:03:16563 return stats.audio_bytes_decoded;
564}
565
[email protected]d82b18ae2011-03-23 21:28:59566unsigned WebMediaPlayerImpl::videoDecodedByteCount() const {
acolwellb4034942014-08-28 15:42:43567 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]4c51bc662011-02-16 02:03:16568
acolwell9e0840d2014-09-06 19:01:32569 PipelineStatistics stats = pipeline_.GetStatistics();
[email protected]4c51bc662011-02-16 02:03:16570 return stats.video_bytes_decoded;
571}
572
[email protected]6523b242013-03-13 11:10:07573bool WebMediaPlayerImpl::copyVideoTextureToPlatformTexture(
[email protected]180ef242013-11-07 06:50:46574 blink::WebGraphicsContext3D* web_graphics_context,
[email protected]6523b242013-03-13 11:10:07575 unsigned int texture,
576 unsigned int level,
577 unsigned int internal_format,
[email protected]9aa2b2782013-05-14 00:13:31578 unsigned int type,
[email protected]6523b242013-03-13 11:10:07579 bool premultiply_alpha,
580 bool flip_y) {
dongseong.hwang46305b12015-03-05 18:28:04581 return copyVideoTextureToPlatformTexture(web_graphics_context, texture,
582 internal_format, type,
583 premultiply_alpha, flip_y);
584}
585
586bool WebMediaPlayerImpl::copyVideoTextureToPlatformTexture(
587 blink::WebGraphicsContext3D* web_graphics_context,
588 unsigned int texture,
589 unsigned int internal_format,
590 unsigned int type,
591 bool premultiply_alpha,
592 bool flip_y) {
[email protected]bfc05f22013-10-19 17:55:16593 TRACE_EVENT0("media", "WebMediaPlayerImpl:copyVideoTextureToPlatformTexture");
594
mcasasf1236fc22015-05-29 22:38:56595 scoped_refptr<VideoFrame> video_frame = GetCurrentFrameFromCompositor();
[email protected]dd061e12014-05-06 19:21:22596
dongseong.hwang0c4e9d82015-01-08 20:11:13597 if (!video_frame.get() ||
mcasasf1236fc22015-05-29 22:38:56598 video_frame->storage_type() != VideoFrame::STORAGE_TEXTURE) {
[email protected]e56f88c72013-06-25 22:31:29599 return false;
dongseong.hwang0c4e9d82015-01-08 20:11:13600 }
[email protected]df41e252014-02-03 23:39:50601
dongseong.hwang0c4e9d82015-01-08 20:11:13602 // TODO(dshwang): need more elegant way to convert WebGraphicsContext3D to
603 // GLES2Interface.
604 gpu::gles2::GLES2Interface* gl =
605 static_cast<gpu_blink::WebGraphicsContext3DImpl*>(web_graphics_context)
606 ->GetGLInterface();
607 SkCanvasVideoRenderer::CopyVideoFrameTextureToGLTexture(
dongseong.hwang46305b12015-03-05 18:28:04608 gl, video_frame.get(), texture, internal_format, type, premultiply_alpha,
609 flip_y);
[email protected]e56f88c72013-06-25 22:31:29610 return true;
[email protected]6523b242013-03-13 11:10:07611}
612
[email protected]2ca7d5c2012-10-23 07:30:54613WebMediaPlayer::MediaKeyException
[email protected]f7a6b992012-04-19 09:45:56614WebMediaPlayerImpl::generateKeyRequest(const WebString& key_system,
615 const unsigned char* init_data,
616 unsigned init_data_length) {
acolwellb4034942014-08-28 15:42:43617 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]7502ef12014-01-25 01:19:27618
xhwang16ff1362014-11-19 00:16:34619 return encrypted_media_support_.GenerateKeyRequest(
acolwelle2ea5182014-08-25 23:01:07620 frame_, key_system, init_data, init_data_length);
[email protected]f7a6b992012-04-19 09:45:56621}
622
[email protected]2ca7d5c2012-10-23 07:30:54623WebMediaPlayer::MediaKeyException WebMediaPlayerImpl::addKey(
624 const WebString& key_system,
625 const unsigned char* key,
626 unsigned key_length,
627 const unsigned char* init_data,
628 unsigned init_data_length,
629 const WebString& session_id) {
acolwellb4034942014-08-28 15:42:43630 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]f7a6b992012-04-19 09:45:56631
xhwang16ff1362014-11-19 00:16:34632 return encrypted_media_support_.AddKey(
acolwelle2ea5182014-08-25 23:01:07633 key_system, key, key_length, init_data, init_data_length, session_id);
[email protected]f7a6b992012-04-19 09:45:56634}
635
[email protected]2ca7d5c2012-10-23 07:30:54636WebMediaPlayer::MediaKeyException WebMediaPlayerImpl::cancelKeyRequest(
637 const WebString& key_system,
638 const WebString& session_id) {
acolwellb4034942014-08-28 15:42:43639 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]0b9999d2014-02-20 02:16:11640
xhwang16ff1362014-11-19 00:16:34641 return encrypted_media_support_.CancelKeyRequest(key_system, session_id);
[email protected]f7a6b992012-04-19 09:45:56642}
643
[email protected]7bce1832014-01-09 00:01:22644void WebMediaPlayerImpl::setContentDecryptionModule(
[email protected]9ebc3b03f2014-08-13 04:01:23645 blink::WebContentDecryptionModule* cdm,
646 blink::WebContentDecryptionModuleResult result) {
acolwellb4034942014-08-28 15:42:43647 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]9ebc3b03f2014-08-13 04:01:23648
xhwang97de4202014-11-25 08:44:01649 // TODO(xhwang): Support setMediaKeys(0) if necessary: http://crbug.com/330324
650 if (!cdm) {
651 result.completeWithError(
652 blink::WebContentDecryptionModuleExceptionNotSupportedError, 0,
653 "Null MediaKeys object is not supported.");
654 return;
655 }
656
xhwang9bd8c732015-04-13 23:27:53657 SetCdm(BIND_TO_RENDER_LOOP1(&WebMediaPlayerImpl::OnCdmAttached, result),
658 ToWebContentDecryptionModuleImpl(cdm)->GetCdmContext());
xhwang97de4202014-11-25 08:44:01659}
660
xhwange8c4181a2014-12-06 08:10:01661void WebMediaPlayerImpl::OnEncryptedMediaInitData(
jrummellcf78967c2015-04-03 05:03:58662 EmeInitDataType init_data_type,
xhwange8c4181a2014-12-06 08:10:01663 const std::vector<uint8>& init_data) {
jrummellcf78967c2015-04-03 05:03:58664 DCHECK(init_data_type != EmeInitDataType::UNKNOWN);
xhwangbab66f52014-12-02 23:49:50665
xhwange8c4181a2014-12-06 08:10:01666 // Do not fire "encrypted" event if encrypted media is not enabled.
xhwangbab66f52014-12-02 23:49:50667 // TODO(xhwang): Handle this in |client_|.
668 if (!blink::WebRuntimeFeatures::isPrefixedEncryptedMediaEnabled() &&
669 !blink::WebRuntimeFeatures::isEncryptedMediaEnabled()) {
670 return;
671 }
672
xhwange8c4181a2014-12-06 08:10:01673 // TODO(xhwang): Update this UMA name.
xhwangbab66f52014-12-02 23:49:50674 UMA_HISTOGRAM_COUNTS("Media.EME.NeedKey", 1);
675
676 encrypted_media_support_.SetInitDataType(init_data_type);
677
jrummellcf78967c2015-04-03 05:03:58678 client_->encrypted(ConvertToWebInitDataType(init_data_type),
679 vector_as_array(&init_data),
680 base::saturated_cast<unsigned int>(init_data.size()));
xhwangbab66f52014-12-02 23:49:50681}
682
jrummell74fc4f942015-03-02 22:48:27683void WebMediaPlayerImpl::OnWaitingForDecryptionKey() {
684 client_->didBlockPlaybackWaitingForKey();
685
686 // TODO(jrummell): didResumePlaybackBlockedForKey() should only be called
687 // when a key has been successfully added (e.g. OnSessionKeysChange() with
688 // |has_additional_usable_key| = true). http://crbug.com/461903
689 client_->didResumePlaybackBlockedForKey();
690}
691
xhwang9bd8c732015-04-13 23:27:53692void WebMediaPlayerImpl::SetCdm(const CdmAttachedCB& cdm_attached_cb,
693 CdmContext* cdm_context) {
jrummell87a2db52015-05-05 22:27:18694 // If CDM initialization succeeded, tell the pipeline about it.
695 if (cdm_context)
696 pipeline_.SetCdm(cdm_context, cdm_attached_cb);
xhwang97de4202014-11-25 08:44:01697}
698
699void WebMediaPlayerImpl::OnCdmAttached(
700 blink::WebContentDecryptionModuleResult result,
701 bool success) {
702 if (success) {
703 result.complete();
704 return;
705 }
706
707 result.completeWithError(
708 blink::WebContentDecryptionModuleExceptionNotSupportedError, 0,
709 "Unable to set MediaKeys object");
[email protected]9ebc3b03f2014-08-13 04:01:23710}
711
[email protected]4e982192014-06-21 13:35:45712void WebMediaPlayerImpl::OnPipelineSeeked(bool time_changed,
713 PipelineStatus status) {
714 DVLOG(1) << __FUNCTION__ << "(" << time_changed << ", " << status << ")";
acolwellb4034942014-08-28 15:42:43715 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]5d11eff2011-09-15 00:06:06716 seeking_ = false;
717 if (pending_seek_) {
718 pending_seek_ = false;
719 seek(pending_seek_seconds_);
720 return;
721 }
722
acolwell9e0840d2014-09-06 19:01:32723 if (status != PIPELINE_OK) {
[email protected]10a64d92012-04-10 21:08:02724 OnPipelineError(status);
725 return;
[email protected]96706912009-07-15 17:18:05726 }
[email protected]10a64d92012-04-10 21:08:02727
728 // Update our paused time.
729 if (paused_)
dalecurtis2e50e6f62015-01-09 02:42:52730 UpdatePausedTime();
[email protected]10a64d92012-04-10 21:08:02731
[email protected]ba7d5f92014-06-24 05:37:40732 should_notify_time_changed_ = time_changed;
[email protected]8931c41a2009-07-07 17:31:49733}
734
[email protected]6954fe12013-01-03 03:22:32735void WebMediaPlayerImpl::OnPipelineEnded() {
[email protected]2a06ca62014-06-04 13:59:52736 DVLOG(1) << __FUNCTION__;
acolwellb4034942014-08-28 15:42:43737 DCHECK(main_task_runner_->BelongsToCurrentThread());
scherkusd2c745b2014-09-04 05:03:40738
739 // Ignore state changes until we've completed all outstanding seeks.
740 if (seeking_ || pending_seek_)
741 return;
742
743 ended_ = true;
[email protected]ce70c982013-12-20 17:04:32744 client_->timeChanged();
[email protected]576537842009-08-12 23:52:05745}
746
[email protected]a9590c22011-03-16 16:57:02747void WebMediaPlayerImpl::OnPipelineError(PipelineStatus error) {
acolwellb4034942014-08-28 15:42:43748 DCHECK(main_task_runner_->BelongsToCurrentThread());
acolwell9e0840d2014-09-06 19:01:32749 DCHECK_NE(error, PIPELINE_OK);
[email protected]a8e2cb82012-08-17 00:02:39750
751 if (ready_state_ == WebMediaPlayer::ReadyStateHaveNothing) {
752 // Any error that occurs before reaching ReadyStateHaveMetadata should
753 // be considered a format error.
754 SetNetworkState(WebMediaPlayer::NetworkStateFormatError);
[email protected]a8e2cb82012-08-17 00:02:39755 return;
756 }
757
[email protected]be57ee52013-05-28 22:27:27758 SetNetworkState(PipelineErrorToNetworkState(error));
[email protected]a9590c22011-03-16 16:57:02759
acolwell9e0840d2014-09-06 19:01:32760 if (error == PIPELINE_ERROR_DECRYPT)
xhwang16ff1362014-11-19 00:16:34761 encrypted_media_support_.OnPipelineDecryptError();
[email protected]db190487d2009-07-30 18:51:52762}
763
[email protected]b8877772014-03-26 20:17:15764void WebMediaPlayerImpl::OnPipelineMetadata(
acolwell9e0840d2014-09-06 19:01:32765 PipelineMetadata metadata) {
[email protected]2a06ca62014-06-04 13:59:52766 DVLOG(1) << __FUNCTION__;
[email protected]a8e2cb82012-08-17 00:02:39767
[email protected]b8877772014-03-26 20:17:15768 pipeline_metadata_ = metadata;
[email protected]739847c02014-01-16 00:12:25769
dalecurtis849cf4b22015-03-27 18:35:45770 UMA_HISTOGRAM_ENUMERATION("Media.VideoRotation", metadata.video_rotation,
acolwell9e0840d2014-09-06 19:01:32771 VIDEO_ROTATION_MAX + 1);
[email protected]b8877772014-03-26 20:17:15772 SetReadyState(WebMediaPlayer::ReadyStateHaveMetadata);
[email protected]21c3f7502013-03-23 03:29:51773
[email protected]b8877772014-03-26 20:17:15774 if (hasVideo()) {
775 DCHECK(!video_weblayer_);
[email protected]f78c3e82014-08-08 01:24:47776 scoped_refptr<cc::VideoLayer> layer =
loysoa6edaaff2015-05-25 03:26:44777 cc::VideoLayer::Create(cc_blink::WebLayerImpl::LayerSettings(),
778 compositor_, pipeline_metadata_.video_rotation);
[email protected]f78c3e82014-08-08 01:24:47779
acolwell9e0840d2014-09-06 19:01:32780 if (pipeline_metadata_.video_rotation == VIDEO_ROTATION_90 ||
781 pipeline_metadata_.video_rotation == VIDEO_ROTATION_270) {
[email protected]f78c3e82014-08-08 01:24:47782 gfx::Size size = pipeline_metadata_.natural_size;
783 pipeline_metadata_.natural_size = gfx::Size(size.height(), size.width());
784 }
785
[email protected]38564622014-08-19 02:47:18786 video_weblayer_.reset(new cc_blink::WebLayerImpl(layer));
[email protected]75e145a2014-04-15 17:44:32787 video_weblayer_->setOpaque(opaque_);
[email protected]a7c4f582014-04-16 18:44:49788 client_->setWebLayer(video_weblayer_.get());
[email protected]a8e2cb82012-08-17 00:02:39789 }
[email protected]a8e2cb82012-08-17 00:02:39790}
791
[email protected]ba7d5f92014-06-24 05:37:40792void WebMediaPlayerImpl::OnPipelineBufferingStateChanged(
acolwell9e0840d2014-09-06 19:01:32793 BufferingState buffering_state) {
[email protected]ba7d5f92014-06-24 05:37:40794 DVLOG(1) << __FUNCTION__ << "(" << buffering_state << ")";
[email protected]b8877772014-03-26 20:17:15795
[email protected]ba7d5f92014-06-24 05:37:40796 // Ignore buffering state changes until we've completed all outstanding seeks.
797 if (seeking_ || pending_seek_)
798 return;
[email protected]b8877772014-03-26 20:17:15799
[email protected]ba7d5f92014-06-24 05:37:40800 // TODO(scherkus): Handle other buffering states when Pipeline starts using
801 // them and translate them ready state changes http://crbug.com/144683
acolwell9e0840d2014-09-06 19:01:32802 DCHECK_EQ(buffering_state, BUFFERING_HAVE_ENOUGH);
[email protected]ba7d5f92014-06-24 05:37:40803 SetReadyState(WebMediaPlayer::ReadyStateHaveEnoughData);
804
dalecurtis849cf4b22015-03-27 18:35:45805 // Let the DataSource know we have enough data. It may use this information to
806 // release unused network connections.
807 if (data_source_)
808 data_source_->OnBufferingHaveEnough();
809
[email protected]ba7d5f92014-06-24 05:37:40810 // Blink expects a timeChanged() in response to a seek().
811 if (should_notify_time_changed_)
812 client_->timeChanged();
[email protected]b8877772014-03-26 20:17:15813}
814
[email protected]ef8394c2013-08-21 20:26:30815void WebMediaPlayerImpl::OnDemuxerOpened() {
acolwellb4034942014-08-28 15:42:43816 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]ce70c982013-12-20 17:04:32817 client_->mediaSourceOpened(new WebMediaSourceImpl(
wolenetz7ffc4de2015-04-01 17:14:43818 chunk_demuxer_, base::Bind(&MediaLog::AddLogEvent, media_log_)));
[email protected]81bb3322011-07-21 15:55:50819}
820
[email protected]8a561062013-11-22 01:19:31821void WebMediaPlayerImpl::OnAddTextTrack(
acolwell9e0840d2014-09-06 19:01:32822 const TextTrackConfig& config,
823 const AddTextTrackDoneCB& done_cb) {
acolwellb4034942014-08-28 15:42:43824 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]71537722013-05-23 06:47:53825
[email protected]8a561062013-11-22 01:19:31826 const WebInbandTextTrackImpl::Kind web_kind =
827 static_cast<WebInbandTextTrackImpl::Kind>(config.kind());
828 const blink::WebString web_label =
829 blink::WebString::fromUTF8(config.label());
830 const blink::WebString web_language =
831 blink::WebString::fromUTF8(config.language());
[email protected]427ff102013-11-26 23:45:40832 const blink::WebString web_id =
833 blink::WebString::fromUTF8(config.id());
[email protected]71537722013-05-23 06:47:53834
[email protected]8a561062013-11-22 01:19:31835 scoped_ptr<WebInbandTextTrackImpl> web_inband_text_track(
henriks9cce5fa2014-12-12 09:35:30836 new WebInbandTextTrackImpl(web_kind, web_label, web_language, web_id));
[email protected]8a561062013-11-22 01:19:31837
acolwell9e0840d2014-09-06 19:01:32838 scoped_ptr<TextTrack> text_track(new TextTrackImpl(
acolwellb4034942014-08-28 15:42:43839 main_task_runner_, client_, web_inband_text_track.Pass()));
[email protected]8a561062013-11-22 01:19:31840
841 done_cb.Run(text_track.Pass());
[email protected]71537722013-05-23 06:47:53842}
843
[email protected]fee8a902014-06-03 13:43:36844void WebMediaPlayerImpl::DataSourceInitialized(bool success) {
acolwellb4034942014-08-28 15:42:43845 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]a9415292012-01-19 19:55:20846
[email protected]d250190da3b2012-07-23 22:57:30847 if (!success) {
[email protected]ef405f66b2012-04-18 02:39:55848 SetNetworkState(WebMediaPlayer::NetworkStateFormatError);
[email protected]a9415292012-01-19 19:55:20849 return;
850 }
851
[email protected]ef8394c2013-08-21 20:26:30852 StartPipeline();
[email protected]a9415292012-01-19 19:55:20853}
854
[email protected]122f40252012-06-12 05:01:56855void WebMediaPlayerImpl::NotifyDownloading(bool is_downloading) {
856 if (!is_downloading && network_state_ == WebMediaPlayer::NetworkStateLoading)
857 SetNetworkState(WebMediaPlayer::NetworkStateIdle);
858 else if (is_downloading && network_state_ == WebMediaPlayer::NetworkStateIdle)
859 SetNetworkState(WebMediaPlayer::NetworkStateLoading);
860 media_log_->AddEvent(
861 media_log_->CreateBooleanEvent(
acolwell9e0840d2014-09-06 19:01:32862 MediaLogEvent::NETWORK_ACTIVITY_SET,
[email protected]122f40252012-06-12 05:01:56863 "is_downloading_data", is_downloading));
864}
865
[email protected]ef8394c2013-08-21 20:26:30866void WebMediaPlayerImpl::StartPipeline() {
acolwellb4034942014-08-28 15:42:43867 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]ddbc6ff2013-04-19 15:28:33868
[email protected]0814ac62013-06-07 21:01:29869 // Keep track if this is a MSE or non-MSE playback.
[email protected]ef8394c2013-08-21 20:26:30870 UMA_HISTOGRAM_BOOLEAN("Media.MSE.Playback",
871 (load_type_ == LoadTypeMediaSource));
[email protected]0814ac62013-06-07 21:01:29872
acolwell9e0840d2014-09-06 19:01:32873 LogCB mse_log_cb;
xhwange8c4181a2014-12-06 08:10:01874 Demuxer::EncryptedMediaInitDataCB encrypted_media_init_data_cb =
875 BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnEncryptedMediaInitData);
[email protected]2b57e2e2014-05-09 11:07:25876
[email protected]ddbc6ff2013-04-19 15:28:33877 // Figure out which demuxer to use.
[email protected]ef8394c2013-08-21 20:26:30878 if (load_type_ != LoadTypeMediaSource) {
[email protected]ddbc6ff2013-04-19 15:28:33879 DCHECK(!chunk_demuxer_);
[email protected]f5443ef72013-04-22 04:03:38880 DCHECK(data_source_);
881
xhwange8c4181a2014-12-06 08:10:01882 demuxer_.reset(new FFmpegDemuxer(media_task_runner_, data_source_.get(),
883 encrypted_media_init_data_cb, media_log_));
[email protected]ddbc6ff2013-04-19 15:28:33884 } else {
[email protected]f5443ef72013-04-22 04:03:38885 DCHECK(!chunk_demuxer_);
886 DCHECK(!data_source_);
887
wolenetz7ffc4de2015-04-01 17:14:43888 mse_log_cb = base::Bind(&MediaLog::AddLogEvent, media_log_);
[email protected]2b57e2e2014-05-09 11:07:25889
acolwell9e0840d2014-09-06 19:01:32890 chunk_demuxer_ = new ChunkDemuxer(
[email protected]ef8394c2013-08-21 20:26:30891 BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnDemuxerOpened),
xhwange8c4181a2014-12-06 08:10:01892 encrypted_media_init_data_cb, mse_log_cb, media_log_, true);
[email protected]f5443ef72013-04-22 04:03:38893 demuxer_.reset(chunk_demuxer_);
[email protected]ddbc6ff2013-04-19 15:28:33894 }
895
[email protected]f5443ef72013-04-22 04:03:38896 // ... and we're ready to go!
[email protected]d228aeec2014-06-20 19:16:49897 seeking_ = true;
xhwangf94a634d2014-10-22 22:07:27898
[email protected]f6af7592014-02-28 10:09:11899 pipeline_.Start(
xhwang59805902014-08-29 01:44:15900 demuxer_.get(),
Bartosz Fabianowski85a823812015-04-16 10:27:51901 renderer_factory_->CreateRenderer(
902 media_task_runner_, audio_source_provider_.get(), compositor_),
[email protected]f5443ef72013-04-22 04:03:38903 BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnPipelineEnded),
904 BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnPipelineError),
[email protected]4e982192014-06-21 13:35:45905 BIND_TO_RENDER_LOOP1(&WebMediaPlayerImpl::OnPipelineSeeked, false),
[email protected]b8877772014-03-26 20:17:15906 BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnPipelineMetadata),
[email protected]ba7d5f92014-06-24 05:37:40907 BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnPipelineBufferingStateChanged),
xhwang59805902014-08-29 01:44:15908 BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnDurationChanged),
jrummell74fc4f942015-03-02 22:48:27909 BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnAddTextTrack),
910 BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnWaitingForDecryptionKey));
[email protected]f5443ef72013-04-22 04:03:38911}
912
913void WebMediaPlayerImpl::SetNetworkState(WebMediaPlayer::NetworkState state) {
[email protected]2a06ca62014-06-04 13:59:52914 DVLOG(1) << __FUNCTION__ << "(" << state << ")";
acolwellb4034942014-08-28 15:42:43915 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]f5443ef72013-04-22 04:03:38916 network_state_ = state;
917 // Always notify to ensure client has the latest value.
[email protected]ce70c982013-12-20 17:04:32918 client_->networkStateChanged();
[email protected]f5443ef72013-04-22 04:03:38919}
920
921void WebMediaPlayerImpl::SetReadyState(WebMediaPlayer::ReadyState state) {
[email protected]2a06ca62014-06-04 13:59:52922 DVLOG(1) << __FUNCTION__ << "(" << state << ")";
acolwellb4034942014-08-28 15:42:43923 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]f5443ef72013-04-22 04:03:38924
[email protected]fee8a902014-06-03 13:43:36925 if (state == WebMediaPlayer::ReadyStateHaveEnoughData && data_source_ &&
926 data_source_->assume_fully_buffered() &&
[email protected]f5443ef72013-04-22 04:03:38927 network_state_ == WebMediaPlayer::NetworkStateLoading)
928 SetNetworkState(WebMediaPlayer::NetworkStateLoaded);
929
930 ready_state_ = state;
931 // Always notify to ensure client has the latest value.
[email protected]ce70c982013-12-20 17:04:32932 client_->readyStateChanged();
[email protected]f5443ef72013-04-22 04:03:38933}
934
[email protected]180ef242013-11-07 06:50:46935blink::WebAudioSourceProvider* WebMediaPlayerImpl::audioSourceProvider() {
[email protected]ff875be52013-06-02 23:47:38936 return audio_source_provider_.get();
[email protected]f5443ef72013-04-22 04:03:38937}
938
[email protected]f5443ef72013-04-22 04:03:38939double WebMediaPlayerImpl::GetPipelineDuration() const {
[email protected]f6af7592014-02-28 10:09:11940 base::TimeDelta duration = pipeline_.GetMediaDuration();
[email protected]f5443ef72013-04-22 04:03:38941
942 // Return positive infinity if the resource is unbounded.
943 // http://www.whatwg.org/specs/web-apps/current-work/multipage/video.html#dom-media-duration
acolwell9e0840d2014-09-06 19:01:32944 if (duration == kInfiniteDuration())
[email protected]f5443ef72013-04-22 04:03:38945 return std::numeric_limits<double>::infinity();
946
947 return duration.InSecondsF();
948}
949
[email protected]75e145a2014-04-15 17:44:32950void WebMediaPlayerImpl::OnDurationChanged() {
[email protected]f5443ef72013-04-22 04:03:38951 if (ready_state_ == WebMediaPlayer::ReadyStateHaveNothing)
952 return;
953
[email protected]ce70c982013-12-20 17:04:32954 client_->durationChanged();
[email protected]f5443ef72013-04-22 04:03:38955}
956
[email protected]75e145a2014-04-15 17:44:32957void WebMediaPlayerImpl::OnNaturalSizeChanged(gfx::Size size) {
acolwellb4034942014-08-28 15:42:43958 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]739847c02014-01-16 00:12:25959 DCHECK_NE(ready_state_, WebMediaPlayer::ReadyStateHaveNothing);
960 TRACE_EVENT0("media", "WebMediaPlayerImpl::OnNaturalSizeChanged");
961
962 media_log_->AddEvent(
963 media_log_->CreateVideoSizeSetEvent(size.width(), size.height()));
[email protected]b8877772014-03-26 20:17:15964 pipeline_metadata_.natural_size = size;
[email protected]739847c02014-01-16 00:12:25965
966 client_->sizeChanged();
967}
968
[email protected]75e145a2014-04-15 17:44:32969void WebMediaPlayerImpl::OnOpacityChanged(bool opaque) {
acolwellb4034942014-08-28 15:42:43970 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]75e145a2014-04-15 17:44:32971 DCHECK_NE(ready_state_, WebMediaPlayer::ReadyStateHaveNothing);
972
973 opaque_ = opaque;
[email protected]75e145a2014-04-15 17:44:32974 if (video_weblayer_)
975 video_weblayer_->setOpaque(opaque_);
976}
977
[email protected]dd061e12014-05-06 19:21:22978static void GetCurrentFrameAndSignal(
979 VideoFrameCompositor* compositor,
acolwell9e0840d2014-09-06 19:01:32980 scoped_refptr<VideoFrame>* video_frame_out,
[email protected]dd061e12014-05-06 19:21:22981 base::WaitableEvent* event) {
982 TRACE_EVENT0("media", "GetCurrentFrameAndSignal");
dalecurtis44ce4de2015-05-11 18:42:07983 *video_frame_out = compositor->GetCurrentFrameAndUpdateIfStale();
[email protected]dd061e12014-05-06 19:21:22984 event->Signal();
985}
986
acolwell9e0840d2014-09-06 19:01:32987scoped_refptr<VideoFrame>
[email protected]dd061e12014-05-06 19:21:22988WebMediaPlayerImpl::GetCurrentFrameFromCompositor() {
989 TRACE_EVENT0("media", "WebMediaPlayerImpl::GetCurrentFrameFromCompositor");
990 if (compositor_task_runner_->BelongsToCurrentThread())
dalecurtis44ce4de2015-05-11 18:42:07991 return compositor_->GetCurrentFrameAndUpdateIfStale();
[email protected]dd061e12014-05-06 19:21:22992
993 // Use a posted task and waitable event instead of a lock otherwise
994 // WebGL/Canvas can see different content than what the compositor is seeing.
acolwell9e0840d2014-09-06 19:01:32995 scoped_refptr<VideoFrame> video_frame;
[email protected]dd061e12014-05-06 19:21:22996 base::WaitableEvent event(false, false);
997 compositor_task_runner_->PostTask(FROM_HERE,
998 base::Bind(&GetCurrentFrameAndSignal,
999 base::Unretained(compositor_),
1000 &video_frame,
1001 &event));
1002 event.Wait();
1003 return video_frame;
1004}
1005
dalecurtis2e50e6f62015-01-09 02:42:521006void WebMediaPlayerImpl::UpdatePausedTime() {
1007 DCHECK(main_task_runner_->BelongsToCurrentThread());
1008
1009 // pause() may be called after playback has ended and the HTMLMediaElement
1010 // requires that currentTime() == duration() after ending. We want to ensure
1011 // |paused_time_| matches currentTime() in this case or a future seek() may
1012 // incorrectly discard what it thinks is a seek to the existing time.
1013 paused_time_ =
1014 ended_ ? pipeline_.GetMediaDuration() : pipeline_.GetMediaTime();
1015}
1016
acolwell9e0840d2014-09-06 19:01:321017} // namespace media