blob: 39c299ce1bee3560052536eaf9daab38a2c0ffb7 [file] [log] [blame]
[email protected]d3933992012-01-06 18:59:271// Copyright (c) 2012 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
[email protected]a9288f52011-11-17 05:18:165#include "webkit/media/webmediaplayer_impl.h"
[email protected]8931c41a2009-07-07 17:31:496
[email protected]47b06ceb2010-08-04 22:41:117#include <limits>
[email protected]d82b18ae2011-03-23 21:28:598#include <string>
[email protected]cbdc8c2b2012-06-16 01:27:369#include <vector>
[email protected]47b06ceb2010-08-04 22:41:1110
[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]963ab912010-01-22 19:56:1413#include "base/command_line.h"
[email protected]ed2c9c3d12012-02-06 20:51:2414#include "base/message_loop_proxy.h"
[email protected]b0b258f2011-11-08 00:34:2315#include "base/metrics/histogram.h"
[email protected]f7a6b992012-04-19 09:45:5616#include "base/string_number_conversions.h"
[email protected]cf02541b2012-04-11 08:02:1717#include "base/synchronization/waitable_event.h"
[email protected]e4fc09e2012-04-06 03:17:4418#include "media/audio/null_audio_sink.h"
[email protected]2c539b82012-08-18 04:10:1919#include "media/base/bind_to_loop.h"
[email protected]f8db8132010-12-03 00:27:4920#include "media/base/filter_collection.h"
[email protected]32da1002010-03-03 21:57:3521#include "media/base/limits.h"
[email protected]090f7312011-08-05 23:26:4022#include "media/base/media_log.h"
[email protected]963ab912010-01-22 19:56:1423#include "media/base/media_switches.h"
[email protected]d399866c2012-01-18 09:30:3224#include "media/base/pipeline.h"
[email protected]e81283bb2010-08-31 18:01:2125#include "media/base/video_frame.h"
[email protected]37136d162012-04-09 23:39:1926#include "media/filters/audio_renderer_impl.h"
[email protected]efe7cd22012-09-12 23:55:0127#include "media/filters/chunk_demuxer.h"
[email protected]d4833b72012-01-13 22:16:1728#include "media/filters/video_renderer_base.h"
[email protected]c1d9cdc2011-01-17 06:50:0129#include "third_party/WebKit/Source/WebKit/chromium/public/WebVideoFrame.h"
[email protected]b0b258f2011-11-08 00:34:2330#include "third_party/WebKit/Source/WebKit/chromium/public/WebView.h"
[email protected]3034b6812011-12-03 00:00:1431#include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebRect.h"
32#include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebSize.h"
[email protected]f7a6b992012-04-19 09:45:5633#include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebString.h"
[email protected]3034b6812011-12-03 00:00:1434#include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebURL.h"
[email protected]38aefc312011-09-20 05:06:3735#include "v8/include/v8.h"
[email protected]a9288f52011-11-17 05:18:1636#include "webkit/media/buffered_data_source.h"
[email protected]a9415292012-01-19 19:55:2037#include "webkit/media/filter_helpers.h"
[email protected]a9288f52011-11-17 05:18:1638#include "webkit/media/webmediaplayer_delegate.h"
39#include "webkit/media/webmediaplayer_proxy.h"
[email protected]e45912e2012-04-25 20:33:1540#include "webkit/media/webmediaplayer_util.h"
[email protected]a9288f52011-11-17 05:18:1641#include "webkit/media/webvideoframe_impl.h"
[email protected]9f5b0fd2012-07-23 23:35:2542#include "webkit/plugins/ppapi/ppapi_webplugin_impl.h"
[email protected]b3f2b912009-04-09 16:18:5243
[email protected]df143bdc2009-06-16 17:34:1944using WebKit::WebCanvas;
[email protected]ef405f66b2012-04-18 02:39:5545using WebKit::WebMediaPlayer;
[email protected]b3f2b912009-04-09 16:18:5246using WebKit::WebRect;
47using WebKit::WebSize;
[email protected]f7a6b992012-04-19 09:45:5648using WebKit::WebString;
[email protected]a9590c22011-03-16 16:57:0249using media::PipelineStatus;
[email protected]ec9212f2008-12-18 21:40:3650
[email protected]8931c41a2009-07-07 17:31:4951namespace {
52
[email protected]38aefc312011-09-20 05:06:3753// Amount of extra memory used by each player instance reported to V8.
54// It is not exact number -- first, it differs on different platforms,
55// and second, it is very hard to calculate. Instead, use some arbitrary
56// value that will cause garbage collection from time to time. We don't want
57// it to happen on every allocation, but don't want 5k players to sit in memory
58// either. Looks that chosen constant achieves both goals, at least for audio
59// objects. (Do not worry about video objects yet, JS programs do not create
60// thousands of them...)
61const int kPlayerExtraMemory = 1024 * 1024;
62
[email protected]378f0b72009-08-11 17:11:4263// Limits the range of playback rate.
64//
65// TODO(kylep): Revisit these.
66//
67// Vista has substantially lower performance than XP or Windows7. If you speed
68// up a video too much, it can't keep up, and rendering stops updating except on
69// the time bar. For really high speeds, audio becomes a bottleneck and we just
70// use up the data we have, which may not achieve the speed requested, but will
71// not crash the tab.
72//
73// A very slow speed, ie 0.00000001x, causes the machine to lock up. (It seems
74// like a busy loop). It gets unresponsive, although its not completely dead.
75//
76// Also our timers are not very accurate (especially for ogg), which becomes
77// evident at low speeds and on Vista. Since other speeds are risky and outside
78// the norms, we think 1/16x to 16x is a safe and useful range for now.
79const float kMinRate = 0.0625f;
80const float kMaxRate = 16.0f;
81
[email protected]8931c41a2009-07-07 17:31:4982} // namespace
83
[email protected]a9288f52011-11-17 05:18:1684namespace webkit_media {
[email protected]add51772009-06-11 18:25:1785
[email protected]a8884632012-06-29 03:05:3486#define COMPILE_ASSERT_MATCHING_ENUM(name) \
[email protected]a5a01102012-06-06 17:01:2487 COMPILE_ASSERT(static_cast<int>(WebKit::WebMediaPlayer::CORSMode ## name) == \
[email protected]a8884632012-06-29 03:05:3488 static_cast<int>(BufferedResourceLoader::k ## name), \
[email protected]a5a01102012-06-06 17:01:2489 mismatching_enums)
90COMPILE_ASSERT_MATCHING_ENUM(Unspecified);
91COMPILE_ASSERT_MATCHING_ENUM(Anonymous);
92COMPILE_ASSERT_MATCHING_ENUM(UseCredentials);
93#undef COMPILE_ASSERT_MATCHING_ENUM
94
[email protected]2c539b82012-08-18 04:10:1995#define BIND_TO_RENDER_LOOP(function) \
96 media::BindToLoop(main_loop_->message_loop_proxy(), base::Bind( \
97 function, AsWeakPtr()))
98
[email protected]c566cb792012-06-20 00:51:5299static WebKit::WebTimeRanges ConvertToWebTimeRanges(
100 const media::Ranges<base::TimeDelta>& ranges) {
101 WebKit::WebTimeRanges result(ranges.size());
102 for (size_t i = 0; i < ranges.size(); i++) {
103 result[i].start = ranges.start(i).InSecondsF();
104 result[i].end = ranges.end(i).InSecondsF();
105 }
106 return result;
107}
108
[email protected]efe7cd22012-09-12 23:55:01109// TODO(acolwell): Investigate whether the key_system & session_id parameters
110// are really necessary.
111typedef base::Callback<void(const std::string&,
112 const std::string&,
113 scoped_array<uint8>,
114 int)> OnNeedKeyCB;
115
116static void OnDemuxerNeedKeyTrampoline(
117 const scoped_refptr<base::MessageLoopProxy>& message_loop,
118 const OnNeedKeyCB& need_key_cb,
119 scoped_array<uint8> init_data,
120 int init_data_size) {
121 message_loop->PostTask(FROM_HERE, base::Bind(
122 need_key_cb, "", "", base::Passed(&init_data), init_data_size));
123}
124
[email protected]5b5bb9d2010-10-22 19:57:36125WebMediaPlayerImpl::WebMediaPlayerImpl(
[email protected]da952fd2012-01-13 03:49:25126 WebKit::WebFrame* frame,
[email protected]5b5bb9d2010-10-22 19:57:36127 WebKit::WebMediaPlayerClient* client,
[email protected]b8976652011-10-26 23:46:55128 base::WeakPtr<WebMediaPlayerDelegate> delegate,
[email protected]f78d1dfc2011-01-15 07:09:27129 media::FilterCollection* collection,
[email protected]9e2269d2012-01-07 00:06:21130 WebKit::WebAudioSourceProvider* audio_source_provider,
[email protected]1113bfdf2012-07-16 21:46:10131 media::AudioRendererSink* audio_renderer_sink,
[email protected]ab2c4732011-07-20 19:57:40132 media::MessageLoopFactory* message_loop_factory,
[email protected]090f7312011-08-05 23:26:40133 MediaStreamClient* media_stream_client,
134 media::MediaLog* media_log)
[email protected]a9415292012-01-19 19:55:20135 : frame_(frame),
[email protected]ef405f66b2012-04-18 02:39:55136 network_state_(WebMediaPlayer::NetworkStateEmpty),
137 ready_state_(WebMediaPlayer::ReadyStateHaveNothing),
[email protected]da952fd2012-01-13 03:49:25138 main_loop_(MessageLoop::current()),
[email protected]457d8342010-10-23 01:20:37139 filter_collection_(collection),
[email protected]f78d1dfc2011-01-15 07:09:27140 message_loop_factory_(message_loop_factory),
[email protected]49480902009-07-14 20:23:43141 paused_(true),
[email protected]b3766a22010-12-22 17:34:13142 seeking_(false),
[email protected]49480902009-07-14 20:23:43143 playback_rate_(0.0f),
[email protected]5d11eff2011-09-15 00:06:06144 pending_seek_(false),
[email protected]b1a975e2011-12-21 00:12:39145 pending_seek_seconds_(0.0f),
[email protected]5badb082010-06-11 17:40:15146 client_(client),
[email protected]ed2c9c3d12012-02-06 20:51:24147 proxy_(new WebMediaPlayerProxy(main_loop_->message_loop_proxy(), this)),
[email protected]baff4512011-10-19 18:21:07148 delegate_(delegate),
[email protected]090f7312011-08-05 23:26:40149 media_stream_client_(media_stream_client),
[email protected]c25a33382011-09-23 17:37:57150 media_log_(media_log),
[email protected]c5b1b642012-03-26 19:40:51151 accelerated_compositing_reported_(false),
[email protected]9e2269d2012-01-07 00:06:21152 incremented_externally_allocated_memory_(false),
[email protected]580a2372012-05-12 16:50:29153 audio_source_provider_(audio_source_provider),
[email protected]1113bfdf2012-07-16 21:46:10154 audio_renderer_sink_(audio_renderer_sink),
[email protected]a8884632012-06-29 03:05:34155 is_local_source_(false),
[email protected]132dd57c2012-08-10 23:24:34156 supports_save_(true),
[email protected]a8e2cb82012-08-17 00:02:39157 decryptor_(proxy_.get(), client, frame),
158 starting_(false) {
[email protected]c93eb0a62011-08-09 22:47:24159 media_log_->AddEvent(
160 media_log_->CreateEvent(media::MediaLogEvent::WEBMEDIAPLAYER_CREATED));
[email protected]4e6be3f2009-05-07 02:24:44161
[email protected]084c8552012-08-12 22:51:20162 scoped_refptr<base::MessageLoopProxy> pipeline_message_loop =
163 message_loop_factory_->GetMessageLoop(
164 media::MessageLoopFactory::kPipeline);
[email protected]d399866c2012-01-18 09:30:32165 pipeline_ = new media::Pipeline(pipeline_message_loop, media_log_);
[email protected]db190487d2009-07-30 18:51:52166
[email protected]da952fd2012-01-13 03:49:25167 // Let V8 know we started new thread if we did not did it yet.
168 // Made separate task to avoid deletion of player currently being created.
169 // Also, delaying GC until after player starts gets rid of starting lag --
170 // collection happens in parallel with playing.
171 //
172 // TODO(enal): remove when we get rid of per-audio-stream thread.
173 MessageLoop::current()->PostTask(
174 FROM_HERE,
175 base::Bind(&WebMediaPlayerImpl::IncrementExternallyAllocatedMemory,
176 AsWeakPtr()));
177
[email protected]da952fd2012-01-13 03:49:25178 // Also we want to be notified of |main_loop_| destruction.
179 main_loop_->AddDestructionObserver(this);
180
181 // Create default video renderer.
[email protected]d4833b72012-01-13 22:16:17182 scoped_refptr<media::VideoRendererBase> video_renderer =
183 new media::VideoRendererBase(
184 base::Bind(&WebMediaPlayerProxy::Repaint, proxy_),
[email protected]2c539b82012-08-18 04:10:19185 BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::SetOpaque),
[email protected]b3c471792012-03-17 01:34:26186 true);
[email protected]da952fd2012-01-13 03:49:25187 filter_collection_->AddVideoRenderer(video_renderer);
[email protected]d4833b72012-01-13 22:16:17188 proxy_->set_frame_provider(video_renderer);
[email protected]da952fd2012-01-13 03:49:25189
[email protected]a9415292012-01-19 19:55:20190 // Create default audio renderer.
[email protected]e4fc09e2012-04-06 03:17:44191 filter_collection_->AddAudioRenderer(
[email protected]37136d162012-04-09 23:39:19192 new media::AudioRendererImpl(new media::NullAudioSink()));
[email protected]ec9212f2008-12-18 21:40:36193}
194
[email protected]4e6be3f2009-05-07 02:24:44195WebMediaPlayerImpl::~WebMediaPlayerImpl() {
[email protected]c25a33382011-09-23 17:37:57196 DCHECK_EQ(main_loop_, MessageLoop::current());
[email protected]8931c41a2009-07-07 17:31:49197 Destroy();
[email protected]c93eb0a62011-08-09 22:47:24198 media_log_->AddEvent(
199 media_log_->CreateEvent(media::MediaLogEvent::WEBMEDIAPLAYER_DESTROYED));
[email protected]d43ed912009-02-03 04:52:53200
[email protected]baff4512011-10-19 18:21:07201 if (delegate_)
202 delegate_->PlayerGone(this);
203
[email protected]4e6be3f2009-05-07 02:24:44204 // Finally tell the |main_loop_| we don't want to be notified of destruction
[email protected]d43ed912009-02-03 04:52:53205 // event.
206 if (main_loop_) {
207 main_loop_->RemoveDestructionObserver(this);
208 }
[email protected]ec9212f2008-12-18 21:40:36209}
210
[email protected]daeae722011-11-15 23:00:58211namespace {
212
213// Helper enum for reporting scheme histograms.
214enum URLSchemeForHistogram {
215 kUnknownURLScheme,
216 kMissingURLScheme,
217 kHttpURLScheme,
218 kHttpsURLScheme,
219 kFtpURLScheme,
220 kChromeExtensionURLScheme,
221 kJavascriptURLScheme,
222 kFileURLScheme,
223 kBlobURLScheme,
224 kDataURLScheme,
[email protected]aacd4a42012-04-11 02:34:48225 kFileSystemScheme,
226 kMaxURLScheme = kFileSystemScheme // Must be equal to highest enum value.
[email protected]daeae722011-11-15 23:00:58227};
228
229URLSchemeForHistogram URLScheme(const GURL& url) {
230 if (!url.has_scheme()) return kMissingURLScheme;
231 if (url.SchemeIs("http")) return kHttpURLScheme;
232 if (url.SchemeIs("https")) return kHttpsURLScheme;
233 if (url.SchemeIs("ftp")) return kFtpURLScheme;
234 if (url.SchemeIs("chrome-extension")) return kChromeExtensionURLScheme;
235 if (url.SchemeIs("javascript")) return kJavascriptURLScheme;
236 if (url.SchemeIs("file")) return kFileURLScheme;
237 if (url.SchemeIs("blob")) return kBlobURLScheme;
238 if (url.SchemeIs("data")) return kDataURLScheme;
[email protected]aacd4a42012-04-11 02:34:48239 if (url.SchemeIs("filesystem")) return kFileSystemScheme;
[email protected]daeae722011-11-15 23:00:58240 return kUnknownURLScheme;
241}
242
243} // anonymous namespace
244
[email protected]a5a01102012-06-06 17:01:24245void WebMediaPlayerImpl::load(const WebKit::WebURL& url, CORSMode cors_mode) {
[email protected]c25a33382011-09-23 17:37:57246 DCHECK_EQ(main_loop_, MessageLoop::current());
[email protected]d43ed912009-02-03 04:52:53247
[email protected]a9415292012-01-19 19:55:20248 GURL gurl(url);
249 UMA_HISTOGRAM_ENUMERATION("Media.URLScheme", URLScheme(gurl), kMaxURLScheme);
[email protected]daeae722011-11-15 23:00:58250
[email protected]a9415292012-01-19 19:55:20251 // Handle any volume/preload changes that occured before load().
[email protected]835070f2010-05-18 23:48:29252 setVolume(GetClient()->volume());
[email protected]23a8b1d82011-04-05 16:28:20253 setPreload(GetClient()->preload());
[email protected]835070f2010-05-18 23:48:29254
[email protected]ef405f66b2012-04-18 02:39:55255 SetNetworkState(WebMediaPlayer::NetworkStateLoading);
256 SetReadyState(WebMediaPlayer::ReadyStateHaveNothing);
[email protected]24d75c72011-08-09 17:53:45257 media_log_->AddEvent(media_log_->CreateLoadEvent(url.spec()));
[email protected]a9415292012-01-19 19:55:20258
259 // Media streams pipelines can start immediately.
260 if (BuildMediaStreamCollection(url, media_stream_client_,
261 message_loop_factory_.get(),
262 filter_collection_.get())) {
[email protected]132dd57c2012-08-10 23:24:34263 supports_save_ = false;
[email protected]9bfe9b82012-04-02 17:56:27264 StartPipeline();
[email protected]a9415292012-01-19 19:55:20265 return;
266 }
267
268 // Media source pipelines can start immediately.
[email protected]efe7cd22012-09-12 23:55:01269 if (!url.isEmpty() && url == GetClient()->sourceURL()) {
270 chunk_demuxer_ = new media::ChunkDemuxer(
271 BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnDemuxerOpened),
272 base::Bind(&OnDemuxerNeedKeyTrampoline,
273 main_loop_->message_loop_proxy(),
274 base::Bind(&WebMediaPlayerImpl::OnNeedKey, AsWeakPtr())));
275
276 BuildMediaSourceCollection(chunk_demuxer_,
277 message_loop_factory_.get(),
278 filter_collection_.get(),
279 &decryptor_);
[email protected]132dd57c2012-08-10 23:24:34280 supports_save_ = false;
[email protected]9bfe9b82012-04-02 17:56:27281 StartPipeline();
[email protected]a9415292012-01-19 19:55:20282 return;
283 }
284
285 // Otherwise it's a regular request which requires resolving the URL first.
[email protected]6fa507fa2012-03-17 00:18:35286 proxy_->set_data_source(
[email protected]122f40252012-06-12 05:01:56287 new BufferedDataSource(main_loop_, frame_, media_log_,
288 base::Bind(&WebMediaPlayerImpl::NotifyDownloading,
[email protected]2c539b82012-08-18 04:10:19289 AsWeakPtr())));
[email protected]a5a01102012-06-06 17:01:24290 proxy_->data_source()->Initialize(
291 url, static_cast<BufferedResourceLoader::CORSMode>(cors_mode),
292 base::Bind(
293 &WebMediaPlayerImpl::DataSourceInitialized,
[email protected]2c539b82012-08-18 04:10:19294 AsWeakPtr(), gurl));
[email protected]29f184542012-04-27 19:20:42295
[email protected]580a2372012-05-12 16:50:29296 is_local_source_ = !gurl.SchemeIs("http") && !gurl.SchemeIs("https");
[email protected]29f184542012-04-27 19:20:42297
298 BuildDefaultCollection(proxy_->data_source(),
[email protected]29f184542012-04-27 19:20:42299 message_loop_factory_.get(),
300 filter_collection_.get(),
[email protected]d46aea52012-08-07 16:44:53301 &decryptor_);
[email protected]ec9212f2008-12-18 21:40:36302}
303
[email protected]4e6be3f2009-05-07 02:24:44304void WebMediaPlayerImpl::cancelLoad() {
[email protected]c25a33382011-09-23 17:37:57305 DCHECK_EQ(main_loop_, MessageLoop::current());
[email protected]ec9212f2008-12-18 21:40:36306}
307
[email protected]4e6be3f2009-05-07 02:24:44308void WebMediaPlayerImpl::play() {
[email protected]c25a33382011-09-23 17:37:57309 DCHECK_EQ(main_loop_, MessageLoop::current());
[email protected]d43ed912009-02-03 04:52:53310
[email protected]49480902009-07-14 20:23:43311 paused_ = false;
312 pipeline_->SetPlaybackRate(playback_rate_);
[email protected]090f7312011-08-05 23:26:40313
[email protected]24d75c72011-08-09 17:53:45314 media_log_->AddEvent(media_log_->CreateEvent(media::MediaLogEvent::PLAY));
[email protected]baff4512011-10-19 18:21:07315
316 if (delegate_)
317 delegate_->DidPlay(this);
[email protected]ec9212f2008-12-18 21:40:36318}
319
[email protected]4e6be3f2009-05-07 02:24:44320void WebMediaPlayerImpl::pause() {
[email protected]c25a33382011-09-23 17:37:57321 DCHECK_EQ(main_loop_, MessageLoop::current());
[email protected]d43ed912009-02-03 04:52:53322
[email protected]49480902009-07-14 20:23:43323 paused_ = true;
[email protected]3b4cbbf2009-07-11 00:16:19324 pipeline_->SetPlaybackRate(0.0f);
[email protected]f7c0ada02012-07-23 08:42:50325 paused_time_ = pipeline_->GetMediaTime();
[email protected]090f7312011-08-05 23:26:40326
[email protected]24d75c72011-08-09 17:53:45327 media_log_->AddEvent(media_log_->CreateEvent(media::MediaLogEvent::PAUSE));
[email protected]baff4512011-10-19 18:21:07328
329 if (delegate_)
330 delegate_->DidPause(this);
[email protected]ec9212f2008-12-18 21:40:36331}
332
[email protected]574a1d62009-07-17 03:23:46333bool WebMediaPlayerImpl::supportsFullscreen() const {
[email protected]c25a33382011-09-23 17:37:57334 DCHECK_EQ(main_loop_, MessageLoop::current());
[email protected]574a1d62009-07-17 03:23:46335 return true;
336}
337
338bool WebMediaPlayerImpl::supportsSave() const {
[email protected]c25a33382011-09-23 17:37:57339 DCHECK_EQ(main_loop_, MessageLoop::current());
[email protected]132dd57c2012-08-10 23:24:34340 return supports_save_;
[email protected]574a1d62009-07-17 03:23:46341}
342
[email protected]4e6be3f2009-05-07 02:24:44343void WebMediaPlayerImpl::seek(float seconds) {
[email protected]c25a33382011-09-23 17:37:57344 DCHECK_EQ(main_loop_, MessageLoop::current());
[email protected]d43ed912009-02-03 04:52:53345
[email protected]a8e2cb82012-08-17 00:02:39346 if (starting_ || seeking_) {
[email protected]5d11eff2011-09-15 00:06:06347 pending_seek_ = true;
348 pending_seek_seconds_ = seconds;
[email protected]efe7cd22012-09-12 23:55:01349 if (chunk_demuxer_)
350 chunk_demuxer_->CancelPendingSeek();
[email protected]5d11eff2011-09-15 00:06:06351 return;
352 }
353
[email protected]c93eb0a62011-08-09 22:47:24354 media_log_->AddEvent(media_log_->CreateSeekEvent(seconds));
355
[email protected]b781e772011-02-04 20:27:51356 base::TimeDelta seek_time = ConvertSecondsToTimestamp(seconds);
[email protected]44ff37c02009-10-24 01:03:03357
358 // Update our paused time.
[email protected]7b268b7a2011-11-18 19:52:08359 if (paused_)
[email protected]44ff37c02009-10-24 01:03:03360 paused_time_ = seek_time;
[email protected]44ff37c02009-10-24 01:03:03361
[email protected]b3766a22010-12-22 17:34:13362 seeking_ = true;
363
[email protected]efe7cd22012-09-12 23:55:01364 if (chunk_demuxer_)
365 chunk_demuxer_->StartWaitingForSeek();
[email protected]020fba32011-06-29 16:37:46366
[email protected]44ff37c02009-10-24 01:03:03367 // Kick off the asynchronous seek!
[email protected]3b4cbbf2009-07-11 00:16:19368 pipeline_->Seek(
[email protected]44ff37c02009-10-24 01:03:03369 seek_time,
[email protected]2c539b82012-08-18 04:10:19370 BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnPipelineSeek));
[email protected]ec9212f2008-12-18 21:40:36371}
372
[email protected]4e6be3f2009-05-07 02:24:44373void WebMediaPlayerImpl::setEndTime(float seconds) {
[email protected]c25a33382011-09-23 17:37:57374 DCHECK_EQ(main_loop_, MessageLoop::current());
[email protected]d43ed912009-02-03 04:52:53375
376 // TODO(hclam): add method call when it has been implemented.
377 return;
[email protected]ec9212f2008-12-18 21:40:36378}
[email protected]d43ed912009-02-03 04:52:53379
[email protected]4e6be3f2009-05-07 02:24:44380void WebMediaPlayerImpl::setRate(float rate) {
[email protected]c25a33382011-09-23 17:37:57381 DCHECK_EQ(main_loop_, MessageLoop::current());
[email protected]d43ed912009-02-03 04:52:53382
[email protected]378f0b72009-08-11 17:11:42383 // TODO(kylep): Remove when support for negatives is added. Also, modify the
384 // following checks so rewind uses reasonable values also.
385 if (rate < 0.0f)
386 return;
387
388 // Limit rates to reasonable values by clamping.
389 if (rate != 0.0f) {
390 if (rate < kMinRate)
391 rate = kMinRate;
392 else if (rate > kMaxRate)
393 rate = kMaxRate;
394 }
395
[email protected]49480902009-07-14 20:23:43396 playback_rate_ = rate;
397 if (!paused_) {
398 pipeline_->SetPlaybackRate(rate);
399 }
[email protected]ec9212f2008-12-18 21:40:36400}
401
[email protected]4e6be3f2009-05-07 02:24:44402void WebMediaPlayerImpl::setVolume(float volume) {
[email protected]c25a33382011-09-23 17:37:57403 DCHECK_EQ(main_loop_, MessageLoop::current());
[email protected]d43ed912009-02-03 04:52:53404
[email protected]3b4cbbf2009-07-11 00:16:19405 pipeline_->SetVolume(volume);
[email protected]ec9212f2008-12-18 21:40:36406}
[email protected]f0a51fb52009-03-05 12:46:38407
[email protected]4e6be3f2009-05-07 02:24:44408void WebMediaPlayerImpl::setVisible(bool visible) {
[email protected]c25a33382011-09-23 17:37:57409 DCHECK_EQ(main_loop_, MessageLoop::current());
[email protected]d43ed912009-02-03 04:52:53410
411 // TODO(hclam): add appropriate method call when pipeline has it implemented.
412 return;
[email protected]ec9212f2008-12-18 21:40:36413}
[email protected]d43ed912009-02-03 04:52:53414
[email protected]23a8b1d82011-04-05 16:28:20415#define COMPILE_ASSERT_MATCHING_ENUM(webkit_name, chromium_name) \
[email protected]ef405f66b2012-04-18 02:39:55416 COMPILE_ASSERT(static_cast<int>(WebMediaPlayer::webkit_name) == \
[email protected]6c430202012-03-31 00:06:44417 static_cast<int>(webkit_media::chromium_name), \
[email protected]474c37a2011-08-23 20:24:52418 mismatching_enums)
[email protected]ef405f66b2012-04-18 02:39:55419COMPILE_ASSERT_MATCHING_ENUM(PreloadNone, NONE);
420COMPILE_ASSERT_MATCHING_ENUM(PreloadMetaData, METADATA);
421COMPILE_ASSERT_MATCHING_ENUM(PreloadAuto, AUTO);
[email protected]a5a01102012-06-06 17:01:24422#undef COMPILE_ASSERT_MATCHING_ENUM
[email protected]23a8b1d82011-04-05 16:28:20423
[email protected]ef405f66b2012-04-18 02:39:55424void WebMediaPlayerImpl::setPreload(WebMediaPlayer::Preload preload) {
[email protected]c25a33382011-09-23 17:37:57425 DCHECK_EQ(main_loop_, MessageLoop::current());
[email protected]4e6be3f2009-05-07 02:24:44426
[email protected]6c430202012-03-31 00:06:44427 if (proxy_ && proxy_->data_source()) {
428 // XXX: Why do I need to use webkit_media:: prefix? clang complains!
429 proxy_->data_source()->SetPreload(
430 static_cast<webkit_media::Preload>(preload));
431 }
[email protected]4e6be3f2009-05-07 02:24:44432}
433
434bool WebMediaPlayerImpl::totalBytesKnown() {
[email protected]c25a33382011-09-23 17:37:57435 DCHECK_EQ(main_loop_, MessageLoop::current());
[email protected]d43ed912009-02-03 04:52:53436
[email protected]3b4cbbf2009-07-11 00:16:19437 return pipeline_->GetTotalBytes() != 0;
[email protected]d43ed912009-02-03 04:52:53438}
439
[email protected]4e6be3f2009-05-07 02:24:44440bool WebMediaPlayerImpl::hasVideo() const {
[email protected]c25a33382011-09-23 17:37:57441 DCHECK_EQ(main_loop_, MessageLoop::current());
[email protected]d43ed912009-02-03 04:52:53442
[email protected]cee32342011-03-09 15:58:16443 return pipeline_->HasVideo();
[email protected]d43ed912009-02-03 04:52:53444}
445
[email protected]fc367af2009-08-14 23:06:35446bool WebMediaPlayerImpl::hasAudio() const {
[email protected]c25a33382011-09-23 17:37:57447 DCHECK_EQ(main_loop_, MessageLoop::current());
[email protected]fc367af2009-08-14 23:06:35448
[email protected]cee32342011-03-09 15:58:16449 return pipeline_->HasAudio();
[email protected]fc367af2009-08-14 23:06:35450}
451
[email protected]4e6be3f2009-05-07 02:24:44452WebKit::WebSize WebMediaPlayerImpl::naturalSize() const {
[email protected]c25a33382011-09-23 17:37:57453 DCHECK_EQ(main_loop_, MessageLoop::current());
[email protected]d43ed912009-02-03 04:52:53454
[email protected]2975fa532011-09-19 20:18:33455 gfx::Size size;
456 pipeline_->GetNaturalVideoSize(&size);
457 return WebKit::WebSize(size);
[email protected]d43ed912009-02-03 04:52:53458}
459
[email protected]4e6be3f2009-05-07 02:24:44460bool WebMediaPlayerImpl::paused() const {
[email protected]c25a33382011-09-23 17:37:57461 DCHECK_EQ(main_loop_, MessageLoop::current());
[email protected]d43ed912009-02-03 04:52:53462
[email protected]3b4cbbf2009-07-11 00:16:19463 return pipeline_->GetPlaybackRate() == 0.0f;
[email protected]d43ed912009-02-03 04:52:53464}
465
[email protected]4e6be3f2009-05-07 02:24:44466bool WebMediaPlayerImpl::seeking() const {
[email protected]c25a33382011-09-23 17:37:57467 DCHECK_EQ(main_loop_, MessageLoop::current());
[email protected]d43ed912009-02-03 04:52:53468
[email protected]ef405f66b2012-04-18 02:39:55469 if (ready_state_ == WebMediaPlayer::ReadyStateHaveNothing)
[email protected]0acebfa2009-08-21 22:45:40470 return false;
[email protected]67cd5052009-09-10 21:53:22471
[email protected]b3766a22010-12-22 17:34:13472 return seeking_;
[email protected]ec9212f2008-12-18 21:40:36473}
474
[email protected]4e6be3f2009-05-07 02:24:44475float WebMediaPlayerImpl::duration() const {
[email protected]c25a33382011-09-23 17:37:57476 DCHECK_EQ(main_loop_, MessageLoop::current());
[email protected]d43ed912009-02-03 04:52:53477
[email protected]47b06ceb2010-08-04 22:41:11478 base::TimeDelta duration = pipeline_->GetMediaDuration();
[email protected]b3e1bc02011-12-07 18:54:17479
480 // Return positive infinity if the resource is unbounded.
481 // http://www.whatwg.org/specs/web-apps/current-work/multipage/video.html#dom-media-duration
[email protected]eb5d6082012-01-18 03:29:37482 if (duration == media::kInfiniteDuration())
[email protected]47b06ceb2010-08-04 22:41:11483 return std::numeric_limits<float>::infinity();
[email protected]b3e1bc02011-12-07 18:54:17484
[email protected]47b06ceb2010-08-04 22:41:11485 return static_cast<float>(duration.InSecondsF());
[email protected]d43ed912009-02-03 04:52:53486}
487
[email protected]4e6be3f2009-05-07 02:24:44488float WebMediaPlayerImpl::currentTime() const {
[email protected]c25a33382011-09-23 17:37:57489 DCHECK_EQ(main_loop_, MessageLoop::current());
[email protected]7b268b7a2011-11-18 19:52:08490 if (paused_)
[email protected]f467d032009-10-23 00:56:24491 return static_cast<float>(paused_time_.InSecondsF());
[email protected]f7c0ada02012-07-23 08:42:50492 return static_cast<float>(pipeline_->GetMediaTime().InSecondsF());
[email protected]d43ed912009-02-03 04:52:53493}
494
[email protected]4e6be3f2009-05-07 02:24:44495int WebMediaPlayerImpl::dataRate() const {
[email protected]c25a33382011-09-23 17:37:57496 DCHECK_EQ(main_loop_, MessageLoop::current());
[email protected]d43ed912009-02-03 04:52:53497
498 // TODO(hclam): Add this method call if pipeline has it in the interface.
499 return 0;
500}
501
[email protected]ef405f66b2012-04-18 02:39:55502WebMediaPlayer::NetworkState WebMediaPlayerImpl::networkState() const {
[email protected]122f40252012-06-12 05:01:56503 DCHECK_EQ(main_loop_, MessageLoop::current());
[email protected]ddb1e5a2010-12-13 20:10:45504 return network_state_;
505}
506
[email protected]ef405f66b2012-04-18 02:39:55507WebMediaPlayer::ReadyState WebMediaPlayerImpl::readyState() const {
[email protected]122f40252012-06-12 05:01:56508 DCHECK_EQ(main_loop_, MessageLoop::current());
[email protected]ddb1e5a2010-12-13 20:10:45509 return ready_state_;
510}
511
[email protected]f70f8e12010-05-25 21:30:39512const WebKit::WebTimeRanges& WebMediaPlayerImpl::buffered() {
[email protected]c25a33382011-09-23 17:37:57513 DCHECK_EQ(main_loop_, MessageLoop::current());
[email protected]c566cb792012-06-20 00:51:52514 WebKit::WebTimeRanges web_ranges(
515 ConvertToWebTimeRanges(pipeline_->GetBufferedTimeRanges()));
[email protected]49f7b772012-05-10 00:45:35516 buffered_.swap(web_ranges);
[email protected]f70f8e12010-05-25 21:30:39517 return buffered_;
518}
519
[email protected]4e6be3f2009-05-07 02:24:44520float WebMediaPlayerImpl::maxTimeSeekable() const {
[email protected]c25a33382011-09-23 17:37:57521 DCHECK_EQ(main_loop_, MessageLoop::current());
[email protected]d43ed912009-02-03 04:52:53522
[email protected]580a2372012-05-12 16:50:29523 // We don't support seeking in streaming media.
524 if (proxy_ && proxy_->data_source() && proxy_->data_source()->IsStreaming())
[email protected]73293602009-04-29 00:30:22525 return 0.0f;
[email protected]fd286f22010-04-20 23:45:15526 return static_cast<float>(pipeline_->GetMediaDuration().InSecondsF());
[email protected]ec9212f2008-12-18 21:40:36527}
528
[email protected]7ed21be2012-05-30 08:09:15529bool WebMediaPlayerImpl::didLoadingProgress() const {
530 DCHECK_EQ(main_loop_, MessageLoop::current());
531 return pipeline_->DidLoadingProgress();
[email protected]d43ed912009-02-03 04:52:53532}
533
[email protected]4e6be3f2009-05-07 02:24:44534unsigned long long WebMediaPlayerImpl::totalBytes() const {
[email protected]c25a33382011-09-23 17:37:57535 DCHECK_EQ(main_loop_, MessageLoop::current());
[email protected]d43ed912009-02-03 04:52:53536
[email protected]3b4cbbf2009-07-11 00:16:19537 return pipeline_->GetTotalBytes();
[email protected]d43ed912009-02-03 04:52:53538}
539
[email protected]4e6be3f2009-05-07 02:24:44540void WebMediaPlayerImpl::setSize(const WebSize& size) {
[email protected]c25a33382011-09-23 17:37:57541 DCHECK_EQ(main_loop_, MessageLoop::current());
[email protected]d43ed912009-02-03 04:52:53542
[email protected]86b3f4b2011-11-18 23:52:46543 // Don't need to do anything as we use the dimensions passed in via paint().
[email protected]ec9212f2008-12-18 21:40:36544}
545
[email protected]df143bdc2009-06-16 17:34:19546void WebMediaPlayerImpl::paint(WebCanvas* canvas,
[email protected]4dc43be2012-03-27 14:05:07547 const WebRect& rect,
548 uint8_t alpha) {
[email protected]c25a33382011-09-23 17:37:57549 DCHECK_EQ(main_loop_, MessageLoop::current());
[email protected]8931c41a2009-07-07 17:31:49550 DCHECK(proxy_);
[email protected]4e6be3f2009-05-07 02:24:44551
[email protected]eaf7d9a2012-05-19 06:14:33552 if (!accelerated_compositing_reported_) {
553 accelerated_compositing_reported_ = true;
[email protected]3dc8f1b2012-05-21 22:54:32554 // Normally paint() is only called in non-accelerated rendering, but there
555 // are exceptions such as webgl where compositing is used in the WebView but
556 // video frames are still rendered to a canvas.
557 UMA_HISTOGRAM_BOOLEAN(
558 "Media.AcceleratedCompositingActive",
559 frame_->view()->isAcceleratedCompositingActive());
[email protected]eaf7d9a2012-05-19 06:14:33560 }
561
[email protected]4dc43be2012-03-27 14:05:07562 proxy_->Paint(canvas, rect, alpha);
[email protected]ec9212f2008-12-18 21:40:36563}
[email protected]5df51652009-01-17 00:03:00564
[email protected]38259a7a82009-07-29 21:49:49565bool WebMediaPlayerImpl::hasSingleSecurityOrigin() const {
[email protected]cf31d6f2010-10-26 02:23:47566 if (proxy_)
567 return proxy_->HasSingleOrigin();
[email protected]fcdb7462009-10-21 21:05:11568 return true;
[email protected]38259a7a82009-07-29 21:49:49569}
570
[email protected]3fe27112012-06-07 04:00:01571bool WebMediaPlayerImpl::didPassCORSAccessCheck() const {
572 return proxy_ && proxy_->DidPassCORSAccessCheck();
573}
574
[email protected]ef405f66b2012-04-18 02:39:55575WebMediaPlayer::MovieLoadType WebMediaPlayerImpl::movieLoadType() const {
[email protected]c25a33382011-09-23 17:37:57576 DCHECK_EQ(main_loop_, MessageLoop::current());
[email protected]38259a7a82009-07-29 21:49:49577
[email protected]580a2372012-05-12 16:50:29578 // Disable seeking while streaming.
579 if (proxy_ && proxy_->data_source() && proxy_->data_source()->IsStreaming())
[email protected]ef405f66b2012-04-18 02:39:55580 return WebMediaPlayer::MovieLoadTypeLiveStream;
581 return WebMediaPlayer::MovieLoadTypeUnknown;
[email protected]38259a7a82009-07-29 21:49:49582}
583
[email protected]e06e16d82011-05-26 22:13:33584float WebMediaPlayerImpl::mediaTimeForTimeValue(float timeValue) const {
585 return ConvertSecondsToTimestamp(timeValue).InSecondsF();
586}
587
[email protected]d82b18ae2011-03-23 21:28:59588unsigned WebMediaPlayerImpl::decodedFrameCount() const {
[email protected]c25a33382011-09-23 17:37:57589 DCHECK_EQ(main_loop_, MessageLoop::current());
[email protected]4c51bc662011-02-16 02:03:16590
591 media::PipelineStatistics stats = pipeline_->GetStatistics();
592 return stats.video_frames_decoded;
593}
594
[email protected]d82b18ae2011-03-23 21:28:59595unsigned WebMediaPlayerImpl::droppedFrameCount() const {
[email protected]c25a33382011-09-23 17:37:57596 DCHECK_EQ(main_loop_, MessageLoop::current());
[email protected]4c51bc662011-02-16 02:03:16597
598 media::PipelineStatistics stats = pipeline_->GetStatistics();
599 return stats.video_frames_dropped;
600}
601
[email protected]d82b18ae2011-03-23 21:28:59602unsigned WebMediaPlayerImpl::audioDecodedByteCount() const {
[email protected]c25a33382011-09-23 17:37:57603 DCHECK_EQ(main_loop_, MessageLoop::current());
[email protected]4c51bc662011-02-16 02:03:16604
605 media::PipelineStatistics stats = pipeline_->GetStatistics();
606 return stats.audio_bytes_decoded;
607}
608
[email protected]d82b18ae2011-03-23 21:28:59609unsigned WebMediaPlayerImpl::videoDecodedByteCount() const {
[email protected]c25a33382011-09-23 17:37:57610 DCHECK_EQ(main_loop_, MessageLoop::current());
[email protected]4c51bc662011-02-16 02:03:16611
612 media::PipelineStatistics stats = pipeline_->GetStatistics();
613 return stats.video_bytes_decoded;
614}
615
[email protected]e81283bb2010-08-31 18:01:21616WebKit::WebVideoFrame* WebMediaPlayerImpl::getCurrentFrame() {
617 scoped_refptr<media::VideoFrame> video_frame;
618 proxy_->GetCurrentFrame(&video_frame);
619 if (video_frame.get())
620 return new WebVideoFrameImpl(video_frame);
621 return NULL;
622}
623
624void WebMediaPlayerImpl::putCurrentFrame(
625 WebKit::WebVideoFrame* web_video_frame) {
[email protected]c5b1b642012-03-26 19:40:51626 if (!accelerated_compositing_reported_) {
627 accelerated_compositing_reported_ = true;
[email protected]3dc8f1b2012-05-21 22:54:32628 DCHECK(frame_->view()->isAcceleratedCompositingActive());
[email protected]eaf7d9a2012-05-19 06:14:33629 UMA_HISTOGRAM_BOOLEAN("Media.AcceleratedCompositingActive", true);
[email protected]c5b1b642012-03-26 19:40:51630 }
[email protected]e81283bb2010-08-31 18:01:21631 if (web_video_frame) {
[email protected]ad8e04a2010-11-01 04:16:27632 scoped_refptr<media::VideoFrame> video_frame(
633 WebVideoFrameImpl::toVideoFrame(web_video_frame));
[email protected]e81283bb2010-08-31 18:01:21634 proxy_->PutCurrentFrame(video_frame);
635 delete web_video_frame;
[email protected]e1d69d762011-12-13 05:12:18636 } else {
637 proxy_->PutCurrentFrame(NULL);
[email protected]e81283bb2010-08-31 18:01:21638 }
639}
640
[email protected]35c83a02012-04-23 23:46:36641#define COMPILE_ASSERT_MATCHING_STATUS_ENUM(webkit_name, chromium_name) \
642 COMPILE_ASSERT(static_cast<int>(WebKit::WebMediaPlayer::webkit_name) == \
643 static_cast<int>(media::ChunkDemuxer::chromium_name), \
644 mismatching_status_enums)
645COMPILE_ASSERT_MATCHING_STATUS_ENUM(AddIdStatusOk, kOk);
646COMPILE_ASSERT_MATCHING_STATUS_ENUM(AddIdStatusNotSupported, kNotSupported);
647COMPILE_ASSERT_MATCHING_STATUS_ENUM(AddIdStatusReachedIdLimit, kReachedIdLimit);
648
649WebKit::WebMediaPlayer::AddIdStatus WebMediaPlayerImpl::sourceAddId(
650 const WebKit::WebString& id,
[email protected]cedfc1652012-05-09 22:30:54651 const WebKit::WebString& type,
652 const WebKit::WebVector<WebKit::WebString>& codecs) {
653 DCHECK_EQ(main_loop_, MessageLoop::current());
654 std::vector<std::string> new_codecs(codecs.size());
655 for (size_t i = 0; i < codecs.size(); ++i)
656 new_codecs[i] = codecs[i].utf8().data();
657
658 return static_cast<WebKit::WebMediaPlayer::AddIdStatus>(
[email protected]efe7cd22012-09-12 23:55:01659 chunk_demuxer_->AddId(id.utf8().data(), type.utf8().data(), new_codecs));
[email protected]35c83a02012-04-23 23:46:36660}
661
662bool WebMediaPlayerImpl::sourceRemoveId(const WebKit::WebString& id) {
663 DCHECK(!id.isEmpty());
[email protected]efe7cd22012-09-12 23:55:01664 chunk_demuxer_->RemoveId(id.utf8().data());
[email protected]35c83a02012-04-23 23:46:36665 return true;
666}
667
[email protected]10faa9d2012-05-03 05:39:10668WebKit::WebTimeRanges WebMediaPlayerImpl::sourceBuffered(
669 const WebKit::WebString& id) {
[email protected]efe7cd22012-09-12 23:55:01670 return ConvertToWebTimeRanges(
671 chunk_demuxer_->GetBufferedRanges(id.utf8().data()));
[email protected]10faa9d2012-05-03 05:39:10672}
673
[email protected]35c83a02012-04-23 23:46:36674bool WebMediaPlayerImpl::sourceAppend(const WebKit::WebString& id,
675 const unsigned char* data,
676 unsigned length) {
[email protected]c25a33382011-09-23 17:37:57677 DCHECK_EQ(main_loop_, MessageLoop::current());
[email protected]1a554c02012-08-02 17:39:58678
679 float old_duration = duration();
[email protected]efe7cd22012-09-12 23:55:01680 if (!chunk_demuxer_->AppendData(id.utf8().data(), data, length))
[email protected]1a554c02012-08-02 17:39:58681 return false;
682
683 if (old_duration != duration())
684 GetClient()->durationChanged();
685
686 return true;
[email protected]81bb3322011-07-21 15:55:50687}
688
[email protected]10faa9d2012-05-03 05:39:10689bool WebMediaPlayerImpl::sourceAbort(const WebKit::WebString& id) {
[email protected]efe7cd22012-09-12 23:55:01690 chunk_demuxer_->Abort(id.utf8().data());
[email protected]10faa9d2012-05-03 05:39:10691 return true;
692}
693
[email protected]f75fb47c2012-08-28 03:07:33694void WebMediaPlayerImpl::sourceSetDuration(double new_duration) {
695 if (static_cast<double>(duration()) == new_duration)
696 return;
697
[email protected]efe7cd22012-09-12 23:55:01698 chunk_demuxer_->SetDuration(
[email protected]f75fb47c2012-08-28 03:07:33699 base::TimeDelta::FromMicroseconds(
700 new_duration * base::Time::kMicrosecondsPerSecond));
701 GetClient()->durationChanged();
702}
703
[email protected]81bb3322011-07-21 15:55:50704void WebMediaPlayerImpl::sourceEndOfStream(
[email protected]ef405f66b2012-04-18 02:39:55705 WebMediaPlayer::EndOfStreamStatus status) {
[email protected]c25a33382011-09-23 17:37:57706 DCHECK_EQ(main_loop_, MessageLoop::current());
[email protected]81bb3322011-07-21 15:55:50707 media::PipelineStatus pipeline_status = media::PIPELINE_OK;
708
[email protected]cbdc8c2b2012-06-16 01:27:36709 switch (status) {
[email protected]ef405f66b2012-04-18 02:39:55710 case WebMediaPlayer::EndOfStreamStatusNoError:
[email protected]e4064fd2011-08-04 16:15:51711 break;
[email protected]ef405f66b2012-04-18 02:39:55712 case WebMediaPlayer::EndOfStreamStatusNetworkError:
[email protected]81bb3322011-07-21 15:55:50713 pipeline_status = media::PIPELINE_ERROR_NETWORK;
714 break;
[email protected]ef405f66b2012-04-18 02:39:55715 case WebMediaPlayer::EndOfStreamStatusDecodeError:
[email protected]81bb3322011-07-21 15:55:50716 pipeline_status = media::PIPELINE_ERROR_DECODE;
717 break;
718 default:
719 NOTIMPLEMENTED();
720 }
721
[email protected]1a554c02012-08-02 17:39:58722 float old_duration = duration();
[email protected]efe7cd22012-09-12 23:55:01723 chunk_demuxer_->EndOfStream(pipeline_status);
[email protected]1a554c02012-08-02 17:39:58724
725 if (old_duration != duration())
726 GetClient()->durationChanged();
[email protected]81bb3322011-07-21 15:55:50727}
[email protected]81bb3322011-07-21 15:55:50728
[email protected]7bdad1a42012-08-09 20:46:01729bool WebMediaPlayerImpl::sourceSetTimestampOffset(const WebKit::WebString& id,
730 double offset) {
[email protected]50bba442012-08-14 23:30:57731 base::TimeDelta time_offset = base::TimeDelta::FromMicroseconds(
732 offset * base::Time::kMicrosecondsPerSecond);
[email protected]efe7cd22012-09-12 23:55:01733 return chunk_demuxer_->SetTimestampOffset(id.utf8().data(), time_offset);
[email protected]7bdad1a42012-08-09 20:46:01734}
735
[email protected]f7a6b992012-04-19 09:45:56736WebKit::WebMediaPlayer::MediaKeyException
737WebMediaPlayerImpl::generateKeyRequest(const WebString& key_system,
738 const unsigned char* init_data,
739 unsigned init_data_length) {
740 if (!IsSupportedKeySystem(key_system))
741 return WebKit::WebMediaPlayer::MediaKeyExceptionKeySystemNotSupported;
742
[email protected]a8884632012-06-29 03:05:34743 // We do not support run-time switching between key systems for now.
744 if (current_key_system_.isEmpty())
745 current_key_system_ = key_system;
746 else if (key_system != current_key_system_)
747 return WebKit::WebMediaPlayer::MediaKeyExceptionInvalidPlayerState;
748
[email protected]f7a6b992012-04-19 09:45:56749 DVLOG(1) << "generateKeyRequest: " << key_system.utf8().data() << ": "
750 << std::string(reinterpret_cast<const char*>(init_data),
[email protected]cbdc8c2b2012-06-16 01:27:36751 static_cast<size_t>(init_data_length));
[email protected]f7a6b992012-04-19 09:45:56752
[email protected]6a206732012-08-29 01:14:40753 if (!decryptor_.GenerateKeyRequest(key_system.utf8(),
754 init_data, init_data_length)) {
755 current_key_system_.reset();
756 return WebKit::WebMediaPlayer::MediaKeyExceptionKeySystemNotSupported;
757 }
758
[email protected]f7a6b992012-04-19 09:45:56759 return WebKit::WebMediaPlayer::MediaKeyExceptionNoError;
760}
761
762WebKit::WebMediaPlayer::MediaKeyException WebMediaPlayerImpl::addKey(
763 const WebString& key_system,
764 const unsigned char* key,
765 unsigned key_length,
766 const unsigned char* init_data,
767 unsigned init_data_length,
768 const WebString& session_id) {
[email protected]a0149082012-04-19 17:33:41769 DCHECK(key);
770 DCHECK_GT(key_length, 0u);
771
[email protected]f7a6b992012-04-19 09:45:56772 if (!IsSupportedKeySystem(key_system))
773 return WebKit::WebMediaPlayer::MediaKeyExceptionKeySystemNotSupported;
774
[email protected]a8884632012-06-29 03:05:34775 if (current_key_system_.isEmpty() || key_system != current_key_system_)
776 return WebKit::WebMediaPlayer::MediaKeyExceptionInvalidPlayerState;
777
[email protected]f7a6b992012-04-19 09:45:56778 DVLOG(1) << "addKey: " << key_system.utf8().data() << ": "
779 << std::string(reinterpret_cast<const char*>(key),
780 static_cast<size_t>(key_length)) << ", "
781 << std::string(reinterpret_cast<const char*>(init_data),
782 static_cast<size_t>(init_data_length))
783 << " [" << session_id.utf8().data() << "]";
784
[email protected]a8884632012-06-29 03:05:34785 decryptor_.AddKey(key_system.utf8(), key, key_length,
786 init_data, init_data_length, session_id.utf8());
[email protected]f7a6b992012-04-19 09:45:56787 return WebKit::WebMediaPlayer::MediaKeyExceptionNoError;
788}
789
790WebKit::WebMediaPlayer::MediaKeyException WebMediaPlayerImpl::cancelKeyRequest(
791 const WebString& key_system,
792 const WebString& session_id) {
793 if (!IsSupportedKeySystem(key_system))
794 return WebKit::WebMediaPlayer::MediaKeyExceptionKeySystemNotSupported;
795
[email protected]a8884632012-06-29 03:05:34796 if (current_key_system_.isEmpty() || key_system != current_key_system_)
797 return WebKit::WebMediaPlayer::MediaKeyExceptionInvalidPlayerState;
798
799 decryptor_.CancelKeyRequest(key_system.utf8(), session_id.utf8());
[email protected]f7a6b992012-04-19 09:45:56800 return WebKit::WebMediaPlayer::MediaKeyExceptionNoError;
801}
802
[email protected]4e6be3f2009-05-07 02:24:44803void WebMediaPlayerImpl::WillDestroyCurrentMessageLoop() {
[email protected]8931c41a2009-07-07 17:31:49804 Destroy();
805 main_loop_ = NULL;
806}
807
808void WebMediaPlayerImpl::Repaint() {
[email protected]c25a33382011-09-23 17:37:57809 DCHECK_EQ(main_loop_, MessageLoop::current());
[email protected]8931c41a2009-07-07 17:31:49810 GetClient()->repaint();
811}
812
[email protected]a9590c22011-03-16 16:57:02813void WebMediaPlayerImpl::OnPipelineSeek(PipelineStatus status) {
[email protected]c25a33382011-09-23 17:37:57814 DCHECK_EQ(main_loop_, MessageLoop::current());
[email protected]a8e2cb82012-08-17 00:02:39815 starting_ = false;
[email protected]5d11eff2011-09-15 00:06:06816 seeking_ = false;
817 if (pending_seek_) {
818 pending_seek_ = false;
819 seek(pending_seek_seconds_);
820 return;
821 }
822
[email protected]10a64d92012-04-10 21:08:02823 if (status != media::PIPELINE_OK) {
824 OnPipelineError(status);
825 return;
[email protected]96706912009-07-15 17:18:05826 }
[email protected]10a64d92012-04-10 21:08:02827
828 // Update our paused time.
829 if (paused_)
[email protected]f7c0ada02012-07-23 08:42:50830 paused_time_ = pipeline_->GetMediaTime();
[email protected]10a64d92012-04-10 21:08:02831
832 GetClient()->timeChanged();
[email protected]8931c41a2009-07-07 17:31:49833}
834
[email protected]a9590c22011-03-16 16:57:02835void WebMediaPlayerImpl::OnPipelineEnded(PipelineStatus status) {
[email protected]c25a33382011-09-23 17:37:57836 DCHECK_EQ(main_loop_, MessageLoop::current());
[email protected]10a64d92012-04-10 21:08:02837 if (status != media::PIPELINE_OK) {
838 OnPipelineError(status);
839 return;
840 }
841 GetClient()->timeChanged();
[email protected]576537842009-08-12 23:52:05842}
843
[email protected]a9590c22011-03-16 16:57:02844void WebMediaPlayerImpl::OnPipelineError(PipelineStatus error) {
[email protected]c25a33382011-09-23 17:37:57845 DCHECK_EQ(main_loop_, MessageLoop::current());
[email protected]a8e2cb82012-08-17 00:02:39846
847 if (ready_state_ == WebMediaPlayer::ReadyStateHaveNothing) {
848 // Any error that occurs before reaching ReadyStateHaveMetadata should
849 // be considered a format error.
850 SetNetworkState(WebMediaPlayer::NetworkStateFormatError);
851 Repaint();
852 return;
853 }
854
[email protected]a9590c22011-03-16 16:57:02855 switch (error) {
[email protected]db190487d2009-07-30 18:51:52856 case media::PIPELINE_OK:
[email protected]cb4ef9672012-06-20 00:46:58857 NOTREACHED() << "PIPELINE_OK isn't an error!";
[email protected]a9590c22011-03-16 16:57:02858 break;
859
[email protected]e4064fd2011-08-04 16:15:51860 case media::PIPELINE_ERROR_NETWORK:
[email protected]34ec75782012-05-04 05:27:36861 case media::PIPELINE_ERROR_READ:
[email protected]ef405f66b2012-04-18 02:39:55862 SetNetworkState(WebMediaPlayer::NetworkStateNetworkError);
[email protected]e4064fd2011-08-04 16:15:51863 break;
864
[email protected]2cc4fd22012-07-14 00:01:04865 // TODO(vrk): Because OnPipelineInitialize() directly reports the
866 // NetworkStateFormatError instead of calling OnPipelineError(), I believe
867 // this block can be deleted. Should look into it! (crbug.com/126070)
[email protected]db190487d2009-07-30 18:51:52868 case media::PIPELINE_ERROR_INITIALIZATION_FAILED:
[email protected]db190487d2009-07-30 18:51:52869 case media::PIPELINE_ERROR_COULD_NOT_RENDER:
[email protected]db190487d2009-07-30 18:51:52870 case media::PIPELINE_ERROR_URL_NOT_FOUND:
[email protected]db190487d2009-07-30 18:51:52871 case media::DEMUXER_ERROR_COULD_NOT_OPEN:
872 case media::DEMUXER_ERROR_COULD_NOT_PARSE:
873 case media::DEMUXER_ERROR_NO_SUPPORTED_STREAMS:
[email protected]1ab1c24b2011-09-21 22:44:04874 case media::DECODER_ERROR_NOT_SUPPORTED:
[email protected]ef405f66b2012-04-18 02:39:55875 SetNetworkState(WebMediaPlayer::NetworkStateFormatError);
[email protected]9c4e77ab2009-07-31 00:17:08876 break;
877
878 case media::PIPELINE_ERROR_DECODE:
879 case media::PIPELINE_ERROR_ABORT:
[email protected]641c9abc2011-01-05 18:44:10880 case media::PIPELINE_ERROR_OPERATION_PENDING:
881 case media::PIPELINE_ERROR_INVALID_STATE:
[email protected]ef405f66b2012-04-18 02:39:55882 SetNetworkState(WebMediaPlayer::NetworkStateDecodeError);
[email protected]db190487d2009-07-30 18:51:52883 break;
[email protected]2b61b682012-04-23 02:20:56884
885 case media::PIPELINE_ERROR_DECRYPT:
886 // Decrypt error.
887 // TODO(xhwang): Change to use NetworkStateDecryptError once it's added in
888 // Webkit (see http://crbug.com/124486).
889 SetNetworkState(WebMediaPlayer::NetworkStateDecodeError);
890 break;
[email protected]cb4ef9672012-06-20 00:46:58891
892 case media::PIPELINE_STATUS_MAX:
893 NOTREACHED() << "PIPELINE_STATUS_MAX isn't a real error!";
894 break;
[email protected]db190487d2009-07-30 18:51:52895 }
[email protected]bb2c1f32009-08-14 04:14:50896
897 // Repaint to trigger UI update.
898 Repaint();
[email protected]db190487d2009-07-30 18:51:52899}
900
[email protected]a8e2cb82012-08-17 00:02:39901void WebMediaPlayerImpl::OnPipelineBufferingState(
902 media::Pipeline::BufferingState buffering_state) {
903 DVLOG(1) << "OnPipelineBufferingState(" << buffering_state << ")";
904
905 switch (buffering_state) {
906 case media::Pipeline::kHaveMetadata:
907 SetReadyState(WebMediaPlayer::ReadyStateHaveMetadata);
908 break;
909 case media::Pipeline::kPrerollCompleted:
910 SetReadyState(WebMediaPlayer::ReadyStateHaveEnoughData);
911 break;
912 }
913
914 // Repaint to trigger UI update.
915 Repaint();
916}
917
[email protected]81bb3322011-07-21 15:55:50918void WebMediaPlayerImpl::OnDemuxerOpened() {
[email protected]c25a33382011-09-23 17:37:57919 DCHECK_EQ(main_loop_, MessageLoop::current());
[email protected]6aa03b32011-10-27 21:44:44920 GetClient()->sourceOpened();
[email protected]81bb3322011-07-21 15:55:50921}
922
[email protected]cbdc8c2b2012-06-16 01:27:36923void WebMediaPlayerImpl::OnKeyAdded(const std::string& key_system,
924 const std::string& session_id) {
[email protected]4205f0aab2012-04-26 04:33:06925 DCHECK_EQ(main_loop_, MessageLoop::current());
926
[email protected]cbdc8c2b2012-06-16 01:27:36927 GetClient()->keyAdded(WebString::fromUTF8(key_system),
928 WebString::fromUTF8(session_id));
929}
930
931void WebMediaPlayerImpl::OnNeedKey(const std::string& key_system,
932 const std::string& session_id,
933 scoped_array<uint8> init_data,
934 int init_data_size) {
935 DCHECK_EQ(main_loop_, MessageLoop::current());
936
937 GetClient()->keyNeeded(WebString::fromUTF8(key_system),
938 WebString::fromUTF8(session_id),
939 init_data.get(),
940 init_data_size);
941}
942
[email protected]a8884632012-06-29 03:05:34943#define COMPILE_ASSERT_MATCHING_ENUM(name) \
944 COMPILE_ASSERT(static_cast<int>(WebKit::WebMediaPlayerClient::name) == \
945 static_cast<int>(media::Decryptor::k ## name), \
946 mismatching_enums)
947COMPILE_ASSERT_MATCHING_ENUM(UnknownError);
948COMPILE_ASSERT_MATCHING_ENUM(ClientError);
949COMPILE_ASSERT_MATCHING_ENUM(ServiceError);
950COMPILE_ASSERT_MATCHING_ENUM(OutputError);
951COMPILE_ASSERT_MATCHING_ENUM(HardwareChangeError);
952COMPILE_ASSERT_MATCHING_ENUM(DomainError);
953#undef COMPILE_ASSERT_MATCHING_ENUM
954
[email protected]cbdc8c2b2012-06-16 01:27:36955void WebMediaPlayerImpl::OnKeyError(const std::string& key_system,
956 const std::string& session_id,
[email protected]3942cc79572012-06-19 20:06:18957 media::Decryptor::KeyError error_code,
[email protected]cbdc8c2b2012-06-16 01:27:36958 int system_code) {
959 DCHECK_EQ(main_loop_, MessageLoop::current());
960
961 GetClient()->keyError(
962 WebString::fromUTF8(key_system),
963 WebString::fromUTF8(session_id),
964 static_cast<WebKit::WebMediaPlayerClient::MediaKeyErrorCode>(error_code),
965 system_code);
966}
967
968void WebMediaPlayerImpl::OnKeyMessage(const std::string& key_system,
969 const std::string& session_id,
970 scoped_array<uint8> message,
971 int message_length,
972 const std::string& /* default_url */) {
973 DCHECK_EQ(main_loop_, MessageLoop::current());
974
975 GetClient()->keyMessage(WebString::fromUTF8(key_system),
976 WebString::fromUTF8(session_id),
977 message.get(),
978 message_length);
[email protected]4205f0aab2012-04-26 04:33:06979}
980
[email protected]5bb69ef2011-12-23 16:29:09981void WebMediaPlayerImpl::SetOpaque(bool opaque) {
982 DCHECK_EQ(main_loop_, MessageLoop::current());
983
984 GetClient()->setOpaque(opaque);
985}
986
[email protected]d250190da3b2012-07-23 22:57:30987void WebMediaPlayerImpl::DataSourceInitialized(const GURL& gurl, bool success) {
[email protected]a9415292012-01-19 19:55:20988 DCHECK_EQ(main_loop_, MessageLoop::current());
989
[email protected]d250190da3b2012-07-23 22:57:30990 if (!success) {
[email protected]ef405f66b2012-04-18 02:39:55991 SetNetworkState(WebMediaPlayer::NetworkStateFormatError);
[email protected]a9415292012-01-19 19:55:20992 Repaint();
993 return;
994 }
995
[email protected]9bfe9b82012-04-02 17:56:27996 StartPipeline();
[email protected]a9415292012-01-19 19:55:20997}
998
[email protected]122f40252012-06-12 05:01:56999void WebMediaPlayerImpl::NotifyDownloading(bool is_downloading) {
1000 if (!is_downloading && network_state_ == WebMediaPlayer::NetworkStateLoading)
1001 SetNetworkState(WebMediaPlayer::NetworkStateIdle);
1002 else if (is_downloading && network_state_ == WebMediaPlayer::NetworkStateIdle)
1003 SetNetworkState(WebMediaPlayer::NetworkStateLoading);
1004 media_log_->AddEvent(
1005 media_log_->CreateBooleanEvent(
1006 media::MediaLogEvent::NETWORK_ACTIVITY_SET,
1007 "is_downloading_data", is_downloading));
1008}
1009
[email protected]9bfe9b82012-04-02 17:56:271010void WebMediaPlayerImpl::StartPipeline() {
[email protected]a8e2cb82012-08-17 00:02:391011 starting_ = true;
[email protected]a9415292012-01-19 19:55:201012 pipeline_->Start(
1013 filter_collection_.Pass(),
[email protected]2c539b82012-08-18 04:10:191014 BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnPipelineEnded),
1015 BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnPipelineError),
1016 BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnPipelineSeek),
1017 BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnPipelineBufferingState));
[email protected]a9415292012-01-19 19:55:201018}
1019
[email protected]ef405f66b2012-04-18 02:39:551020void WebMediaPlayerImpl::SetNetworkState(WebMediaPlayer::NetworkState state) {
[email protected]c25a33382011-09-23 17:37:571021 DCHECK_EQ(main_loop_, MessageLoop::current());
[email protected]287ae442012-04-03 08:08:471022 DVLOG(1) << "SetNetworkState: " << state;
[email protected]867e59272009-08-25 18:08:161023 network_state_ = state;
[email protected]287ae442012-04-03 08:08:471024 // Always notify to ensure client has the latest value.
[email protected]867e59272009-08-25 18:08:161025 GetClient()->networkStateChanged();
[email protected]8931c41a2009-07-07 17:31:491026}
1027
[email protected]ef405f66b2012-04-18 02:39:551028void WebMediaPlayerImpl::SetReadyState(WebMediaPlayer::ReadyState state) {
[email protected]c25a33382011-09-23 17:37:571029 DCHECK_EQ(main_loop_, MessageLoop::current());
[email protected]287ae442012-04-03 08:08:471030 DVLOG(1) << "SetReadyState: " << state;
[email protected]a8e2cb82012-08-17 00:02:391031
1032 if (ready_state_ == WebMediaPlayer::ReadyStateHaveNothing &&
1033 state >= WebMediaPlayer::ReadyStateHaveMetadata) {
1034 if (!hasVideo())
1035 GetClient()->disableAcceleratedCompositing();
1036 } else if (state == WebMediaPlayer::ReadyStateHaveEnoughData) {
1037 if (is_local_source_ &&
1038 network_state_ == WebMediaPlayer::NetworkStateLoading) {
1039 SetNetworkState(WebMediaPlayer::NetworkStateLoaded);
1040 }
1041 }
1042
[email protected]867e59272009-08-25 18:08:161043 ready_state_ = state;
[email protected]287ae442012-04-03 08:08:471044 // Always notify to ensure client has the latest value.
[email protected]867e59272009-08-25 18:08:161045 GetClient()->readyStateChanged();
[email protected]8931c41a2009-07-07 17:31:491046}
1047
1048void WebMediaPlayerImpl::Destroy() {
[email protected]c25a33382011-09-23 17:37:571049 DCHECK_EQ(main_loop_, MessageLoop::current());
[email protected]8931c41a2009-07-07 17:31:491050
[email protected]5b5bb9d2010-10-22 19:57:361051 // Tell the data source to abort any pending reads so that the pipeline is
1052 // not blocked when issuing stop commands to the other filters.
[email protected]81bb3322011-07-21 15:55:501053 if (proxy_) {
[email protected]a9415292012-01-19 19:55:201054 proxy_->AbortDataSource();
[email protected]efe7cd22012-09-12 23:55:011055 if (chunk_demuxer_) {
1056 chunk_demuxer_->Shutdown();
1057 chunk_demuxer_ = NULL;
1058 }
[email protected]81bb3322011-07-21 15:55:501059 }
[email protected]020fba32011-06-29 16:37:461060
[email protected]8931c41a2009-07-07 17:31:491061 // Make sure to kill the pipeline so there's no more media threads running.
[email protected]5badb082010-06-11 17:40:151062 // Note: stopping the pipeline might block for a long time.
[email protected]8dbf4d0b2012-08-09 22:51:591063 base::WaitableEvent waiter(false, false);
1064 pipeline_->Stop(base::Bind(
1065 &base::WaitableEvent::Signal, base::Unretained(&waiter)));
1066 waiter.Wait();
[email protected]38aefc312011-09-20 05:06:371067
[email protected]a9415292012-01-19 19:55:201068 // Let V8 know we are not using extra resources anymore.
1069 if (incremented_externally_allocated_memory_) {
1070 v8::V8::AdjustAmountOfExternalAllocatedMemory(-kPlayerExtraMemory);
1071 incremented_externally_allocated_memory_ = false;
[email protected]a8e24d522010-12-01 07:13:581072 }
[email protected]5df51652009-01-17 00:03:001073
[email protected]f78d1dfc2011-01-15 07:09:271074 message_loop_factory_.reset();
1075
[email protected]8931c41a2009-07-07 17:31:491076 // And then detach the proxy, it may live on the render thread for a little
1077 // longer until all the tasks are finished.
1078 if (proxy_) {
1079 proxy_->Detach();
1080 proxy_ = NULL;
[email protected]a7281022009-06-17 17:58:041081 }
[email protected]5df51652009-01-17 00:03:001082}
1083
[email protected]8931c41a2009-07-07 17:31:491084WebKit::WebMediaPlayerClient* WebMediaPlayerImpl::GetClient() {
[email protected]c25a33382011-09-23 17:37:571085 DCHECK_EQ(main_loop_, MessageLoop::current());
[email protected]8931c41a2009-07-07 17:31:491086 DCHECK(client_);
1087 return client_;
[email protected]5df51652009-01-17 00:03:001088}
[email protected]add51772009-06-11 18:25:171089
[email protected]9e2269d2012-01-07 00:06:211090WebKit::WebAudioSourceProvider* WebMediaPlayerImpl::audioSourceProvider() {
1091 return audio_source_provider_;
1092}
1093
[email protected]c25a33382011-09-23 17:37:571094void WebMediaPlayerImpl::IncrementExternallyAllocatedMemory() {
1095 DCHECK_EQ(main_loop_, MessageLoop::current());
1096 incremented_externally_allocated_memory_ = true;
1097 v8::V8::AdjustAmountOfExternalAllocatedMemory(kPlayerExtraMemory);
[email protected]38aefc312011-09-20 05:06:371098}
1099
[email protected]a9288f52011-11-17 05:18:161100} // namespace webkit_media