blob: 94642d4b7f807769eae729a77d13cd813b3f1370 [file] [log] [blame]
[email protected]b781e772011-02-04 20:27:511// Copyright (c) 2011 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]8931c41a2009-07-07 17:31:495#include "webkit/glue/webmediaplayer_impl.h"
6
[email protected]47b06ceb2010-08-04 22:41:117#include <limits>
[email protected]d82b18ae2011-03-23 21:28:598#include <string>
[email protected]47b06ceb2010-08-04 22:41:119
[email protected]08273c7b2011-09-17 00:33:5110#include "base/bind.h"
[email protected]2041cf342010-02-19 03:15:5911#include "base/callback.h"
[email protected]963ab912010-01-22 19:56:1412#include "base/command_line.h"
[email protected]b0b258f2011-11-08 00:34:2313#include "base/metrics/histogram.h"
[email protected]b6c29552011-03-14 15:56:2914#include "media/base/composite_data_source_factory.h"
[email protected]f8db8132010-12-03 00:27:4915#include "media/base/filter_collection.h"
[email protected]32da1002010-03-03 21:57:3516#include "media/base/limits.h"
[email protected]090f7312011-08-05 23:26:4017#include "media/base/media_log.h"
[email protected]963ab912010-01-22 19:56:1418#include "media/base/media_switches.h"
[email protected]583634b2010-11-11 17:47:1519#include "media/base/pipeline_impl.h"
[email protected]e81283bb2010-08-31 18:01:2120#include "media/base/video_frame.h"
[email protected]81bb3322011-07-21 15:55:5021#include "media/filters/chunk_demuxer_factory.h"
[email protected]08107faa2011-08-24 16:49:0122#include "media/filters/dummy_demuxer_factory.h"
[email protected]4c616fa52009-03-30 20:10:0723#include "media/filters/ffmpeg_audio_decoder.h"
[email protected]c88c7c22011-03-14 19:44:2224#include "media/filters/ffmpeg_demuxer_factory.h"
[email protected]720ac732009-04-02 23:55:4425#include "media/filters/ffmpeg_video_decoder.h"
[email protected]891acc92009-04-27 19:56:4126#include "media/filters/null_audio_renderer.h"
[email protected]c1d9cdc2011-01-17 06:50:0127#include "third_party/WebKit/Source/WebKit/chromium/public/WebRect.h"
28#include "third_party/WebKit/Source/WebKit/chromium/public/WebSize.h"
29#include "third_party/WebKit/Source/WebKit/chromium/public/WebURL.h"
30#include "third_party/WebKit/Source/WebKit/chromium/public/WebVideoFrame.h"
[email protected]b0b258f2011-11-08 00:34:2331#include "third_party/WebKit/Source/WebKit/chromium/public/WebView.h"
[email protected]38aefc312011-09-20 05:06:3732#include "v8/include/v8.h"
[email protected]5b5bb9d2010-10-22 19:57:3633#include "webkit/glue/media/buffered_data_source.h"
[email protected]5b5bb9d2010-10-22 19:57:3634#include "webkit/glue/media/simple_data_source.h"
[email protected]ab2c4732011-07-20 19:57:4035#include "webkit/glue/media/media_stream_client.h"
[email protected]add51772009-06-11 18:25:1736#include "webkit/glue/media/video_renderer_impl.h"
[email protected]8400e032010-02-26 18:50:1137#include "webkit/glue/media/web_video_renderer.h"
[email protected]baff4512011-10-19 18:21:0738#include "webkit/glue/webmediaplayer_delegate.h"
[email protected]a23306102011-08-09 22:50:2639#include "webkit/glue/webmediaplayer_proxy.h"
[email protected]e81283bb2010-08-31 18:01:2140#include "webkit/glue/webvideoframe_impl.h"
[email protected]b3f2b912009-04-09 16:18:5241
[email protected]df143bdc2009-06-16 17:34:1942using WebKit::WebCanvas;
[email protected]b3f2b912009-04-09 16:18:5243using WebKit::WebRect;
44using WebKit::WebSize;
[email protected]a9590c22011-03-16 16:57:0245using media::PipelineStatus;
[email protected]ec9212f2008-12-18 21:40:3646
[email protected]8931c41a2009-07-07 17:31:4947namespace {
48
[email protected]38aefc312011-09-20 05:06:3749// Amount of extra memory used by each player instance reported to V8.
50// It is not exact number -- first, it differs on different platforms,
51// and second, it is very hard to calculate. Instead, use some arbitrary
52// value that will cause garbage collection from time to time. We don't want
53// it to happen on every allocation, but don't want 5k players to sit in memory
54// either. Looks that chosen constant achieves both goals, at least for audio
55// objects. (Do not worry about video objects yet, JS programs do not create
56// thousands of them...)
57const int kPlayerExtraMemory = 1024 * 1024;
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.
75const float kMinRate = 0.0625f;
76const float kMaxRate = 16.0f;
77
[email protected]b781e772011-02-04 20:27:5178// Platform independent method for converting and rounding floating point
79// seconds to an int64 timestamp.
80//
81// Refer to https://bugs.webkit.org/show_bug.cgi?id=52697 for details.
82base::TimeDelta ConvertSecondsToTimestamp(float seconds) {
83 float microseconds = seconds * base::Time::kMicrosecondsPerSecond;
84 float integer = ceilf(microseconds);
85 float difference = integer - microseconds;
86
87 // Round down if difference is large enough.
88 if ((microseconds > 0 && difference > 0.5f) ||
89 (microseconds <= 0 && difference >= 0.5f)) {
90 integer -= 1.0f;
91 }
92
93 // Now we can safely cast to int64 microseconds.
94 return base::TimeDelta::FromMicroseconds(static_cast<int64>(integer));
95}
96
[email protected]8931c41a2009-07-07 17:31:4997} // namespace
98
[email protected]add51772009-06-11 18:25:1799namespace webkit_glue {
100
[email protected]5b5bb9d2010-10-22 19:57:36101WebMediaPlayerImpl::WebMediaPlayerImpl(
102 WebKit::WebMediaPlayerClient* client,
[email protected]b8976652011-10-26 23:46:55103 base::WeakPtr<WebMediaPlayerDelegate> delegate,
[email protected]f78d1dfc2011-01-15 07:09:27104 media::FilterCollection* collection,
[email protected]ab2c4732011-07-20 19:57:40105 media::MessageLoopFactory* message_loop_factory,
[email protected]090f7312011-08-05 23:26:40106 MediaStreamClient* media_stream_client,
107 media::MediaLog* media_log)
[email protected]4e6be3f2009-05-07 02:24:44108 : network_state_(WebKit::WebMediaPlayer::Empty),
109 ready_state_(WebKit::WebMediaPlayer::HaveNothing),
[email protected]d43ed912009-02-03 04:52:53110 main_loop_(NULL),
[email protected]457d8342010-10-23 01:20:37111 filter_collection_(collection),
[email protected]a8e24d522010-12-01 07:13:58112 pipeline_(NULL),
[email protected]f78d1dfc2011-01-15 07:09:27113 message_loop_factory_(message_loop_factory),
[email protected]49480902009-07-14 20:23:43114 paused_(true),
[email protected]b3766a22010-12-22 17:34:13115 seeking_(false),
[email protected]49480902009-07-14 20:23:43116 playback_rate_(0.0f),
[email protected]5d11eff2011-09-15 00:06:06117 pending_seek_(false),
[email protected]5badb082010-06-11 17:40:15118 client_(client),
[email protected]ab2c4732011-07-20 19:57:40119 proxy_(NULL),
[email protected]baff4512011-10-19 18:21:07120 delegate_(delegate),
[email protected]090f7312011-08-05 23:26:40121 media_stream_client_(media_stream_client),
[email protected]c25a33382011-09-23 17:37:57122 media_log_(media_log),
[email protected]daeae722011-11-15 23:00:58123 is_accelerated_compositing_active_(false),
[email protected]c25a33382011-09-23 17:37:57124 incremented_externally_allocated_memory_(false) {
[email protected]4e6be3f2009-05-07 02:24:44125 // Saves the current message loop.
126 DCHECK(!main_loop_);
127 main_loop_ = MessageLoop::current();
[email protected]c93eb0a62011-08-09 22:47:24128 media_log_->AddEvent(
129 media_log_->CreateEvent(media::MediaLogEvent::WEBMEDIAPLAYER_CREATED));
[email protected]a8e24d522010-12-01 07:13:58130}
[email protected]4e6be3f2009-05-07 02:24:44131
[email protected]a8e24d522010-12-01 07:13:58132bool WebMediaPlayerImpl::Initialize(
[email protected]79684282010-12-06 21:15:46133 WebKit::WebFrame* frame,
[email protected]a8e24d522010-12-01 07:13:58134 bool use_simple_data_source,
135 scoped_refptr<WebVideoRenderer> web_video_renderer) {
[email protected]c25a33382011-09-23 17:37:57136 DCHECK_EQ(main_loop_, MessageLoop::current());
[email protected]f78d1dfc2011-01-15 07:09:27137 MessageLoop* pipeline_message_loop =
138 message_loop_factory_->GetMessageLoop("PipelineThread");
139 if (!pipeline_message_loop) {
[email protected]3b4cbbf2009-07-11 00:16:19140 NOTREACHED() << "Could not start PipelineThread";
[email protected]a8e24d522010-12-01 07:13:58141 return false;
[email protected]3b4cbbf2009-07-11 00:16:19142 }
143
[email protected]38aefc312011-09-20 05:06:37144 // Let V8 know we started new thread if we did not did it yet.
145 // Made separate task to avoid deletion of player currently being created.
146 // Also, delaying GC until after player starts gets rid of starting lag --
147 // collection happens in parallel with playing.
148 // TODO(enal): remove when we get rid of per-audio-stream thread.
[email protected]c25a33382011-09-23 17:37:57149 if (!incremented_externally_allocated_memory_) {
150 MessageLoop::current()->PostTask(
[email protected]38aefc312011-09-20 05:06:37151 FROM_HERE,
[email protected]c25a33382011-09-23 17:37:57152 base::Bind(&WebMediaPlayerImpl::IncrementExternallyAllocatedMemory,
153 AsWeakPtr()));
[email protected]38aefc312011-09-20 05:06:37154 }
155
[email protected]daeae722011-11-15 23:00:58156 is_accelerated_compositing_active_ =
157 frame->view()->isAcceleratedCompositingActive();
[email protected]b0b258f2011-11-08 00:34:23158
[email protected]c93eb0a62011-08-09 22:47:24159 pipeline_ = new media::PipelineImpl(pipeline_message_loop, media_log_);
[email protected]db190487d2009-07-30 18:51:52160
[email protected]4e6be3f2009-05-07 02:24:44161 // Also we want to be notified of |main_loop_| destruction.
162 main_loop_->AddDestructionObserver(this);
[email protected]8931c41a2009-07-07 17:31:49163
164 // Creates the proxy.
[email protected]a23306102011-08-09 22:50:26165 proxy_ = new WebMediaPlayerProxy(main_loop_, this);
166 web_video_renderer->SetWebMediaPlayerProxy(proxy_);
[email protected]457d8342010-10-23 01:20:37167 proxy_->SetVideoRenderer(web_video_renderer);
[email protected]8931c41a2009-07-07 17:31:49168
[email protected]576537842009-08-12 23:52:05169 // Set our pipeline callbacks.
[email protected]583634b2010-11-11 17:47:15170 pipeline_->Init(
[email protected]460e5712011-08-09 23:25:53171 base::Bind(&WebMediaPlayerProxy::PipelineEndedCallback,
172 proxy_.get()),
173 base::Bind(&WebMediaPlayerProxy::PipelineErrorCallback,
174 proxy_.get()),
175 base::Bind(&WebMediaPlayerProxy::NetworkEventCallback,
176 proxy_.get()));
[email protected]db190487d2009-07-30 18:51:52177
[email protected]5b5bb9d2010-10-22 19:57:36178 // A simple data source that keeps all data in memory.
[email protected]b6c29552011-03-14 15:56:29179 scoped_ptr<media::DataSourceFactory> simple_data_source_factory(
180 SimpleDataSource::CreateFactory(MessageLoop::current(), frame,
[email protected]24d75c72011-08-09 17:53:45181 media_log_,
[email protected]b6c29552011-03-14 15:56:29182 proxy_->GetBuildObserver()));
[email protected]457d8342010-10-23 01:20:37183
[email protected]5b5bb9d2010-10-22 19:57:36184 // A sophisticated data source that does memory caching.
[email protected]b6c29552011-03-14 15:56:29185 scoped_ptr<media::DataSourceFactory> buffered_data_source_factory(
186 BufferedDataSource::CreateFactory(MessageLoop::current(), frame,
[email protected]24d75c72011-08-09 17:53:45187 media_log_,
[email protected]b6c29552011-03-14 15:56:29188 proxy_->GetBuildObserver()));
189
190 scoped_ptr<media::CompositeDataSourceFactory> data_source_factory(
191 new media::CompositeDataSourceFactory());
[email protected]457d8342010-10-23 01:20:37192
[email protected]5b5bb9d2010-10-22 19:57:36193 if (use_simple_data_source) {
[email protected]b6c29552011-03-14 15:56:29194 data_source_factory->AddFactory(simple_data_source_factory.release());
195 data_source_factory->AddFactory(buffered_data_source_factory.release());
[email protected]5b5bb9d2010-10-22 19:57:36196 } else {
[email protected]b6c29552011-03-14 15:56:29197 data_source_factory->AddFactory(buffered_data_source_factory.release());
198 data_source_factory->AddFactory(simple_data_source_factory.release());
[email protected]5b5bb9d2010-10-22 19:57:36199 }
200
[email protected]6aa03b32011-10-27 21:44:44201 scoped_ptr<media::DemuxerFactory> demuxer_factory(
202 new media::FFmpegDemuxerFactory(data_source_factory.release(),
203 pipeline_message_loop));
204
205 std::string source_url = GetClient()->sourceURL().spec();
206
207 if (!source_url.empty()) {
208 demuxer_factory.reset(
209 new media::ChunkDemuxerFactory(source_url,
210 demuxer_factory.release(),
211 proxy_));
212 }
213 filter_collection_->SetDemuxerFactory(demuxer_factory.release());
[email protected]b6c29552011-03-14 15:56:29214
[email protected]8931c41a2009-07-07 17:31:49215 // Add in the default filter factories.
[email protected]f78d1dfc2011-01-15 07:09:27216 filter_collection_->AddAudioDecoder(new media::FFmpegAudioDecoder(
217 message_loop_factory_->GetMessageLoop("AudioDecoderThread")));
218 filter_collection_->AddVideoDecoder(new media::FFmpegVideoDecoder(
[email protected]08382352011-10-28 21:21:22219 message_loop_factory_->GetMessageLoop("VideoDecoderThread")));
[email protected]b7ba5b52010-11-15 22:04:49220 filter_collection_->AddAudioRenderer(new media::NullAudioRenderer());
[email protected]a8e24d522010-12-01 07:13:58221
222 return true;
[email protected]ec9212f2008-12-18 21:40:36223}
224
[email protected]4e6be3f2009-05-07 02:24:44225WebMediaPlayerImpl::~WebMediaPlayerImpl() {
[email protected]c25a33382011-09-23 17:37:57226 DCHECK_EQ(main_loop_, MessageLoop::current());
[email protected]8931c41a2009-07-07 17:31:49227 Destroy();
[email protected]c93eb0a62011-08-09 22:47:24228 media_log_->AddEvent(
229 media_log_->CreateEvent(media::MediaLogEvent::WEBMEDIAPLAYER_DESTROYED));
[email protected]d43ed912009-02-03 04:52:53230
[email protected]baff4512011-10-19 18:21:07231 if (delegate_)
232 delegate_->PlayerGone(this);
233
[email protected]4e6be3f2009-05-07 02:24:44234 // Finally tell the |main_loop_| we don't want to be notified of destruction
[email protected]d43ed912009-02-03 04:52:53235 // event.
236 if (main_loop_) {
237 main_loop_->RemoveDestructionObserver(this);
238 }
[email protected]ec9212f2008-12-18 21:40:36239}
240
[email protected]daeae722011-11-15 23:00:58241namespace {
242
243// Helper enum for reporting scheme histograms.
244enum URLSchemeForHistogram {
245 kUnknownURLScheme,
246 kMissingURLScheme,
247 kHttpURLScheme,
248 kHttpsURLScheme,
249 kFtpURLScheme,
250 kChromeExtensionURLScheme,
251 kJavascriptURLScheme,
252 kFileURLScheme,
253 kBlobURLScheme,
254 kDataURLScheme,
255 kMaxURLScheme = kDataURLScheme // Must be equal to highest enum value.
256};
257
258URLSchemeForHistogram URLScheme(const GURL& url) {
259 if (!url.has_scheme()) return kMissingURLScheme;
260 if (url.SchemeIs("http")) return kHttpURLScheme;
261 if (url.SchemeIs("https")) return kHttpsURLScheme;
262 if (url.SchemeIs("ftp")) return kFtpURLScheme;
263 if (url.SchemeIs("chrome-extension")) return kChromeExtensionURLScheme;
264 if (url.SchemeIs("javascript")) return kJavascriptURLScheme;
265 if (url.SchemeIs("file")) return kFileURLScheme;
266 if (url.SchemeIs("blob")) return kBlobURLScheme;
267 if (url.SchemeIs("data")) return kDataURLScheme;
268 return kUnknownURLScheme;
269}
270
271} // anonymous namespace
272
[email protected]4e6be3f2009-05-07 02:24:44273void WebMediaPlayerImpl::load(const WebKit::WebURL& url) {
[email protected]c25a33382011-09-23 17:37:57274 DCHECK_EQ(main_loop_, MessageLoop::current());
[email protected]8931c41a2009-07-07 17:31:49275 DCHECK(proxy_);
[email protected]d43ed912009-02-03 04:52:53276
[email protected]daeae722011-11-15 23:00:58277 UMA_HISTOGRAM_ENUMERATION("Media.URLScheme", URLScheme(url), kMaxURLScheme);
278
[email protected]ab2c4732011-07-20 19:57:40279 if (media_stream_client_) {
[email protected]08107faa2011-08-24 16:49:01280 bool has_video = false;
281 bool has_audio = false;
[email protected]ab2c4732011-07-20 19:57:40282 scoped_refptr<media::VideoDecoder> new_decoder =
283 media_stream_client_->GetVideoDecoder(url, message_loop_factory_.get());
284 if (new_decoder.get()) {
285 // Remove the default decoder.
286 scoped_refptr<media::VideoDecoder> old_videodecoder;
287 filter_collection_->SelectVideoDecoder(&old_videodecoder);
288 filter_collection_->AddVideoDecoder(new_decoder.get());
[email protected]08107faa2011-08-24 16:49:01289 has_video = true;
[email protected]ab2c4732011-07-20 19:57:40290 }
[email protected]08107faa2011-08-24 16:49:01291
292 // TODO(wjia): add audio decoder handling when it's available.
293 if (has_video || has_audio)
294 filter_collection_->SetDemuxerFactory(
295 new media::DummyDemuxerFactory(has_video, has_audio));
[email protected]ab2c4732011-07-20 19:57:40296 }
297
[email protected]835070f2010-05-18 23:48:29298 // Handle any volume changes that occured before load().
299 setVolume(GetClient()->volume());
[email protected]23a8b1d82011-04-05 16:28:20300 // Get the preload value.
301 setPreload(GetClient()->preload());
[email protected]835070f2010-05-18 23:48:29302
[email protected]a7281022009-06-17 17:58:04303 // Initialize the pipeline.
[email protected]8931c41a2009-07-07 17:31:49304 SetNetworkState(WebKit::WebMediaPlayer::Loading);
305 SetReadyState(WebKit::WebMediaPlayer::HaveNothing);
[email protected]3b4cbbf2009-07-11 00:16:19306 pipeline_->Start(
[email protected]9e166972010-11-03 05:40:13307 filter_collection_.release(),
[email protected]8931c41a2009-07-07 17:31:49308 url.spec(),
[email protected]460e5712011-08-09 23:25:53309 base::Bind(&WebMediaPlayerProxy::PipelineInitializationCallback,
310 proxy_.get()));
311
[email protected]24d75c72011-08-09 17:53:45312 media_log_->AddEvent(media_log_->CreateLoadEvent(url.spec()));
[email protected]ec9212f2008-12-18 21:40:36313}
314
[email protected]4e6be3f2009-05-07 02:24:44315void WebMediaPlayerImpl::cancelLoad() {
[email protected]c25a33382011-09-23 17:37:57316 DCHECK_EQ(main_loop_, MessageLoop::current());
[email protected]ec9212f2008-12-18 21:40:36317}
318
[email protected]4e6be3f2009-05-07 02:24:44319void WebMediaPlayerImpl::play() {
[email protected]c25a33382011-09-23 17:37:57320 DCHECK_EQ(main_loop_, MessageLoop::current());
[email protected]d43ed912009-02-03 04:52:53321
[email protected]49480902009-07-14 20:23:43322 paused_ = false;
323 pipeline_->SetPlaybackRate(playback_rate_);
[email protected]090f7312011-08-05 23:26:40324
[email protected]24d75c72011-08-09 17:53:45325 media_log_->AddEvent(media_log_->CreateEvent(media::MediaLogEvent::PLAY));
[email protected]baff4512011-10-19 18:21:07326
327 if (delegate_)
328 delegate_->DidPlay(this);
[email protected]ec9212f2008-12-18 21:40:36329}
330
[email protected]4e6be3f2009-05-07 02:24:44331void WebMediaPlayerImpl::pause() {
[email protected]c25a33382011-09-23 17:37:57332 DCHECK_EQ(main_loop_, MessageLoop::current());
[email protected]d43ed912009-02-03 04:52:53333
[email protected]49480902009-07-14 20:23:43334 paused_ = true;
[email protected]3b4cbbf2009-07-11 00:16:19335 pipeline_->SetPlaybackRate(0.0f);
[email protected]f467d032009-10-23 00:56:24336 paused_time_ = pipeline_->GetCurrentTime();
[email protected]090f7312011-08-05 23:26:40337
[email protected]24d75c72011-08-09 17:53:45338 media_log_->AddEvent(media_log_->CreateEvent(media::MediaLogEvent::PAUSE));
[email protected]baff4512011-10-19 18:21:07339
340 if (delegate_)
341 delegate_->DidPause(this);
[email protected]ec9212f2008-12-18 21:40:36342}
343
[email protected]574a1d62009-07-17 03:23:46344bool WebMediaPlayerImpl::supportsFullscreen() const {
[email protected]c25a33382011-09-23 17:37:57345 DCHECK_EQ(main_loop_, MessageLoop::current());
[email protected]574a1d62009-07-17 03:23:46346 return true;
347}
348
349bool WebMediaPlayerImpl::supportsSave() const {
[email protected]c25a33382011-09-23 17:37:57350 DCHECK_EQ(main_loop_, MessageLoop::current());
[email protected]574a1d62009-07-17 03:23:46351 return true;
352}
353
[email protected]4e6be3f2009-05-07 02:24:44354void WebMediaPlayerImpl::seek(float seconds) {
[email protected]c25a33382011-09-23 17:37:57355 DCHECK_EQ(main_loop_, MessageLoop::current());
[email protected]d43ed912009-02-03 04:52:53356
[email protected]2a6c25692009-08-18 00:25:55357 // WebKit fires a seek(0) at the very start, however pipeline already does a
358 // seek(0) internally. Avoid doing seek(0) the second time because this will
359 // cause extra pre-rolling and will break servers without range request
360 // support.
[email protected]d8840af42009-08-25 21:27:56361 //
362 // We still have to notify WebKit that time has changed otherwise
363 // HTMLMediaElement gets into an inconsistent state.
[email protected]2a6c25692009-08-18 00:25:55364 if (pipeline_->GetCurrentTime().ToInternalValue() == 0 && seconds == 0) {
[email protected]d8840af42009-08-25 21:27:56365 GetClient()->timeChanged();
[email protected]2a6c25692009-08-18 00:25:55366 return;
367 }
[email protected]576537842009-08-12 23:52:05368
[email protected]5d11eff2011-09-15 00:06:06369 if (seeking_) {
370 pending_seek_ = true;
371 pending_seek_seconds_ = seconds;
372 return;
373 }
374
[email protected]c93eb0a62011-08-09 22:47:24375 media_log_->AddEvent(media_log_->CreateSeekEvent(seconds));
376
[email protected]b781e772011-02-04 20:27:51377 base::TimeDelta seek_time = ConvertSecondsToTimestamp(seconds);
[email protected]44ff37c02009-10-24 01:03:03378
379 // Update our paused time.
380 if (paused_) {
381 paused_time_ = seek_time;
382 }
383
[email protected]b3766a22010-12-22 17:34:13384 seeking_ = true;
385
[email protected]81bb3322011-07-21 15:55:50386 proxy_->DemuxerFlush();
[email protected]020fba32011-06-29 16:37:46387
[email protected]44ff37c02009-10-24 01:03:03388 // Kick off the asynchronous seek!
[email protected]3b4cbbf2009-07-11 00:16:19389 pipeline_->Seek(
[email protected]44ff37c02009-10-24 01:03:03390 seek_time,
[email protected]460e5712011-08-09 23:25:53391 base::Bind(&WebMediaPlayerProxy::PipelineSeekCallback,
392 proxy_.get()));
[email protected]ec9212f2008-12-18 21:40:36393}
394
[email protected]4e6be3f2009-05-07 02:24:44395void WebMediaPlayerImpl::setEndTime(float seconds) {
[email protected]c25a33382011-09-23 17:37:57396 DCHECK_EQ(main_loop_, MessageLoop::current());
[email protected]d43ed912009-02-03 04:52:53397
398 // TODO(hclam): add method call when it has been implemented.
399 return;
[email protected]ec9212f2008-12-18 21:40:36400}
[email protected]d43ed912009-02-03 04:52:53401
[email protected]4e6be3f2009-05-07 02:24:44402void WebMediaPlayerImpl::setRate(float rate) {
[email protected]c25a33382011-09-23 17:37:57403 DCHECK_EQ(main_loop_, MessageLoop::current());
[email protected]d43ed912009-02-03 04:52:53404
[email protected]378f0b72009-08-11 17:11:42405 // TODO(kylep): Remove when support for negatives is added. Also, modify the
406 // following checks so rewind uses reasonable values also.
407 if (rate < 0.0f)
408 return;
409
410 // Limit rates to reasonable values by clamping.
411 if (rate != 0.0f) {
412 if (rate < kMinRate)
413 rate = kMinRate;
414 else if (rate > kMaxRate)
415 rate = kMaxRate;
416 }
417
[email protected]49480902009-07-14 20:23:43418 playback_rate_ = rate;
419 if (!paused_) {
420 pipeline_->SetPlaybackRate(rate);
421 }
[email protected]ec9212f2008-12-18 21:40:36422}
423
[email protected]4e6be3f2009-05-07 02:24:44424void WebMediaPlayerImpl::setVolume(float volume) {
[email protected]c25a33382011-09-23 17:37:57425 DCHECK_EQ(main_loop_, MessageLoop::current());
[email protected]d43ed912009-02-03 04:52:53426
[email protected]3b4cbbf2009-07-11 00:16:19427 pipeline_->SetVolume(volume);
[email protected]ec9212f2008-12-18 21:40:36428}
[email protected]f0a51fb52009-03-05 12:46:38429
[email protected]4e6be3f2009-05-07 02:24:44430void WebMediaPlayerImpl::setVisible(bool visible) {
[email protected]c25a33382011-09-23 17:37:57431 DCHECK_EQ(main_loop_, MessageLoop::current());
[email protected]d43ed912009-02-03 04:52:53432
433 // TODO(hclam): add appropriate method call when pipeline has it implemented.
434 return;
[email protected]ec9212f2008-12-18 21:40:36435}
[email protected]d43ed912009-02-03 04:52:53436
[email protected]23a8b1d82011-04-05 16:28:20437#define COMPILE_ASSERT_MATCHING_ENUM(webkit_name, chromium_name) \
[email protected]474c37a2011-08-23 20:24:52438 COMPILE_ASSERT(static_cast<int>(WebKit::WebMediaPlayer::webkit_name) == \
439 static_cast<int>(media::chromium_name), \
440 mismatching_enums)
[email protected]23a8b1d82011-04-05 16:28:20441COMPILE_ASSERT_MATCHING_ENUM(None, NONE);
442COMPILE_ASSERT_MATCHING_ENUM(MetaData, METADATA);
443COMPILE_ASSERT_MATCHING_ENUM(Auto, AUTO);
444
445void WebMediaPlayerImpl::setPreload(WebKit::WebMediaPlayer::Preload preload) {
[email protected]c25a33382011-09-23 17:37:57446 DCHECK_EQ(main_loop_, MessageLoop::current());
[email protected]4e6be3f2009-05-07 02:24:44447
[email protected]23a8b1d82011-04-05 16:28:20448 pipeline_->SetPreload(static_cast<media::Preload>(preload));
[email protected]4e6be3f2009-05-07 02:24:44449}
450
451bool WebMediaPlayerImpl::totalBytesKnown() {
[email protected]c25a33382011-09-23 17:37:57452 DCHECK_EQ(main_loop_, MessageLoop::current());
[email protected]d43ed912009-02-03 04:52:53453
[email protected]3b4cbbf2009-07-11 00:16:19454 return pipeline_->GetTotalBytes() != 0;
[email protected]d43ed912009-02-03 04:52:53455}
456
[email protected]4e6be3f2009-05-07 02:24:44457bool WebMediaPlayerImpl::hasVideo() const {
[email protected]c25a33382011-09-23 17:37:57458 DCHECK_EQ(main_loop_, MessageLoop::current());
[email protected]d43ed912009-02-03 04:52:53459
[email protected]cee32342011-03-09 15:58:16460 return pipeline_->HasVideo();
[email protected]d43ed912009-02-03 04:52:53461}
462
[email protected]fc367af2009-08-14 23:06:35463bool WebMediaPlayerImpl::hasAudio() const {
[email protected]c25a33382011-09-23 17:37:57464 DCHECK_EQ(main_loop_, MessageLoop::current());
[email protected]fc367af2009-08-14 23:06:35465
[email protected]cee32342011-03-09 15:58:16466 return pipeline_->HasAudio();
[email protected]fc367af2009-08-14 23:06:35467}
468
[email protected]4e6be3f2009-05-07 02:24:44469WebKit::WebSize WebMediaPlayerImpl::naturalSize() const {
[email protected]c25a33382011-09-23 17:37:57470 DCHECK_EQ(main_loop_, MessageLoop::current());
[email protected]d43ed912009-02-03 04:52:53471
[email protected]2975fa532011-09-19 20:18:33472 gfx::Size size;
473 pipeline_->GetNaturalVideoSize(&size);
474 return WebKit::WebSize(size);
[email protected]d43ed912009-02-03 04:52:53475}
476
[email protected]4e6be3f2009-05-07 02:24:44477bool WebMediaPlayerImpl::paused() const {
[email protected]c25a33382011-09-23 17:37:57478 DCHECK_EQ(main_loop_, MessageLoop::current());
[email protected]d43ed912009-02-03 04:52:53479
[email protected]3b4cbbf2009-07-11 00:16:19480 return pipeline_->GetPlaybackRate() == 0.0f;
[email protected]d43ed912009-02-03 04:52:53481}
482
[email protected]4e6be3f2009-05-07 02:24:44483bool WebMediaPlayerImpl::seeking() const {
[email protected]c25a33382011-09-23 17:37:57484 DCHECK_EQ(main_loop_, MessageLoop::current());
[email protected]d43ed912009-02-03 04:52:53485
[email protected]0acebfa2009-08-21 22:45:40486 if (ready_state_ == WebKit::WebMediaPlayer::HaveNothing)
487 return false;
[email protected]67cd5052009-09-10 21:53:22488
[email protected]b3766a22010-12-22 17:34:13489 return seeking_;
[email protected]ec9212f2008-12-18 21:40:36490}
491
[email protected]4e6be3f2009-05-07 02:24:44492float WebMediaPlayerImpl::duration() const {
[email protected]c25a33382011-09-23 17:37:57493 DCHECK_EQ(main_loop_, MessageLoop::current());
[email protected]d43ed912009-02-03 04:52:53494
[email protected]47b06ceb2010-08-04 22:41:11495 base::TimeDelta duration = pipeline_->GetMediaDuration();
496 if (duration.InMicroseconds() == media::Limits::kMaxTimeInMicroseconds)
497 return std::numeric_limits<float>::infinity();
498 return static_cast<float>(duration.InSecondsF());
[email protected]d43ed912009-02-03 04:52:53499}
500
[email protected]4e6be3f2009-05-07 02:24:44501float WebMediaPlayerImpl::currentTime() const {
[email protected]c25a33382011-09-23 17:37:57502 DCHECK_EQ(main_loop_, MessageLoop::current());
[email protected]f467d032009-10-23 00:56:24503 if (paused_) {
504 return static_cast<float>(paused_time_.InSecondsF());
505 }
[email protected]128740b2009-07-17 22:09:28506 return static_cast<float>(pipeline_->GetCurrentTime().InSecondsF());
[email protected]d43ed912009-02-03 04:52:53507}
508
[email protected]4e6be3f2009-05-07 02:24:44509int WebMediaPlayerImpl::dataRate() const {
[email protected]c25a33382011-09-23 17:37:57510 DCHECK_EQ(main_loop_, MessageLoop::current());
[email protected]d43ed912009-02-03 04:52:53511
512 // TODO(hclam): Add this method call if pipeline has it in the interface.
513 return 0;
514}
515
[email protected]ddb1e5a2010-12-13 20:10:45516WebKit::WebMediaPlayer::NetworkState WebMediaPlayerImpl::networkState() const {
517 return network_state_;
518}
519
520WebKit::WebMediaPlayer::ReadyState WebMediaPlayerImpl::readyState() const {
521 return ready_state_;
522}
523
[email protected]f70f8e12010-05-25 21:30:39524const WebKit::WebTimeRanges& WebMediaPlayerImpl::buffered() {
[email protected]c25a33382011-09-23 17:37:57525 DCHECK_EQ(main_loop_, MessageLoop::current());
[email protected]f70f8e12010-05-25 21:30:39526
527 // Update buffered_ with the most recent buffered time.
[email protected]69a83852010-06-12 01:12:13528 if (buffered_.size() > 0) {
529 float buffered_time = static_cast<float>(
530 pipeline_->GetBufferedTime().InSecondsF());
531 if (buffered_time >= buffered_[0].start)
532 buffered_[0].end = buffered_time;
533 }
[email protected]f70f8e12010-05-25 21:30:39534
535 return buffered_;
536}
537
[email protected]4e6be3f2009-05-07 02:24:44538float WebMediaPlayerImpl::maxTimeSeekable() const {
[email protected]c25a33382011-09-23 17:37:57539 DCHECK_EQ(main_loop_, MessageLoop::current());
[email protected]d43ed912009-02-03 04:52:53540
[email protected]38259a7a82009-07-29 21:49:49541 // If we are performing streaming, we report that we cannot seek at all.
542 // We are using this flag to indicate if the data source supports seeking
543 // or not. We should be able to seek even if we are performing streaming.
544 // TODO(hclam): We need to update this when we have better caching.
545 if (pipeline_->IsStreaming())
[email protected]73293602009-04-29 00:30:22546 return 0.0f;
[email protected]fd286f22010-04-20 23:45:15547 return static_cast<float>(pipeline_->GetMediaDuration().InSecondsF());
[email protected]ec9212f2008-12-18 21:40:36548}
549
[email protected]4e6be3f2009-05-07 02:24:44550unsigned long long WebMediaPlayerImpl::bytesLoaded() const {
[email protected]c25a33382011-09-23 17:37:57551 DCHECK_EQ(main_loop_, MessageLoop::current());
[email protected]d43ed912009-02-03 04:52:53552
[email protected]3b4cbbf2009-07-11 00:16:19553 return pipeline_->GetBufferedBytes();
[email protected]d43ed912009-02-03 04:52:53554}
555
[email protected]4e6be3f2009-05-07 02:24:44556unsigned long long WebMediaPlayerImpl::totalBytes() const {
[email protected]c25a33382011-09-23 17:37:57557 DCHECK_EQ(main_loop_, MessageLoop::current());
[email protected]d43ed912009-02-03 04:52:53558
[email protected]3b4cbbf2009-07-11 00:16:19559 return pipeline_->GetTotalBytes();
[email protected]d43ed912009-02-03 04:52:53560}
561
[email protected]4e6be3f2009-05-07 02:24:44562void WebMediaPlayerImpl::setSize(const WebSize& size) {
[email protected]c25a33382011-09-23 17:37:57563 DCHECK_EQ(main_loop_, MessageLoop::current());
[email protected]8931c41a2009-07-07 17:31:49564 DCHECK(proxy_);
[email protected]d43ed912009-02-03 04:52:53565
[email protected]8931c41a2009-07-07 17:31:49566 proxy_->SetSize(gfx::Rect(0, 0, size.width, size.height));
[email protected]ec9212f2008-12-18 21:40:36567}
568
[email protected]df143bdc2009-06-16 17:34:19569void WebMediaPlayerImpl::paint(WebCanvas* canvas,
[email protected]4e6be3f2009-05-07 02:24:44570 const WebRect& rect) {
[email protected]c25a33382011-09-23 17:37:57571 DCHECK_EQ(main_loop_, MessageLoop::current());
[email protected]8931c41a2009-07-07 17:31:49572 DCHECK(proxy_);
[email protected]4e6be3f2009-05-07 02:24:44573
[email protected]8c89e7792009-08-19 21:18:34574#if WEBKIT_USING_SKIA
[email protected]8931c41a2009-07-07 17:31:49575 proxy_->Paint(canvas, rect);
[email protected]776775e2009-09-21 15:21:29576#elif WEBKIT_USING_CG
[email protected]32da1002010-03-03 21:57:35577 // Get the current scaling in X and Y.
578 CGAffineTransform mat = CGContextGetCTM(canvas);
579 float scale_x = sqrt(mat.a * mat.a + mat.b * mat.b);
580 float scale_y = sqrt(mat.c * mat.c + mat.d * mat.d);
581 float inverse_scale_x = SkScalarNearlyZero(scale_x) ? 0.0f : 1.0f / scale_x;
582 float inverse_scale_y = SkScalarNearlyZero(scale_y) ? 0.0f : 1.0f / scale_y;
583 int scaled_width = static_cast<int>(rect.width * fabs(scale_x));
584 int scaled_height = static_cast<int>(rect.height * fabs(scale_y));
585
586 // Make sure we don't create a huge canvas.
587 // TODO(hclam): Respect the aspect ratio.
588 if (scaled_width > static_cast<int>(media::Limits::kMaxCanvas))
589 scaled_width = media::Limits::kMaxCanvas;
590 if (scaled_height > static_cast<int>(media::Limits::kMaxCanvas))
591 scaled_height = media::Limits::kMaxCanvas;
592
[email protected]776775e2009-09-21 15:21:29593 // If there is no preexisting platform canvas, or if the size has
594 // changed, recreate the canvas. This is to avoid recreating the bitmap
595 // buffer over and over for each frame of video.
596 if (!skia_canvas_.get() ||
[email protected]32da1002010-03-03 21:57:35597 skia_canvas_->getDevice()->width() != scaled_width ||
598 skia_canvas_->getDevice()->height() != scaled_height) {
599 skia_canvas_.reset(
600 new skia::PlatformCanvas(scaled_width, scaled_height, true));
[email protected]776775e2009-09-21 15:21:29601 }
602
603 // Draw to our temporary skia canvas.
[email protected]32da1002010-03-03 21:57:35604 gfx::Rect normalized_rect(scaled_width, scaled_height);
[email protected]776775e2009-09-21 15:21:29605 proxy_->Paint(skia_canvas_.get(), normalized_rect);
606
607 // The mac coordinate system is flipped vertical from the normal skia
608 // coordinates. During painting of the frame, flip the coordinates
609 // system and, for simplicity, also translate the clip rectangle to
610 // start at 0,0.
611 CGContextSaveGState(canvas);
612 CGContextTranslateCTM(canvas, rect.x, rect.height + rect.y);
[email protected]32da1002010-03-03 21:57:35613 CGContextScaleCTM(canvas, inverse_scale_x, -inverse_scale_y);
[email protected]776775e2009-09-21 15:21:29614
615 // We need a local variable CGRect version for DrawToContext.
616 CGRect normalized_cgrect =
617 CGRectMake(normalized_rect.x(), normalized_rect.y(),
618 normalized_rect.width(), normalized_rect.height());
619
620 // Copy the frame rendered to our temporary skia canvas onto the passed in
621 // canvas.
[email protected]62f2e802011-05-26 14:28:35622 skia::DrawToNativeContext(skia_canvas_.get(), canvas, 0, 0,
623 &normalized_cgrect);
[email protected]776775e2009-09-21 15:21:29624
625 CGContextRestoreGState(canvas);
[email protected]8c89e7792009-08-19 21:18:34626#else
[email protected]776775e2009-09-21 15:21:29627 NOTIMPLEMENTED() << "We only support rendering to skia or CG";
[email protected]8c89e7792009-08-19 21:18:34628#endif
[email protected]ec9212f2008-12-18 21:40:36629}
[email protected]5df51652009-01-17 00:03:00630
[email protected]38259a7a82009-07-29 21:49:49631bool WebMediaPlayerImpl::hasSingleSecurityOrigin() const {
[email protected]cf31d6f2010-10-26 02:23:47632 if (proxy_)
633 return proxy_->HasSingleOrigin();
[email protected]fcdb7462009-10-21 21:05:11634 return true;
[email protected]38259a7a82009-07-29 21:49:49635}
636
637WebKit::WebMediaPlayer::MovieLoadType
638 WebMediaPlayerImpl::movieLoadType() const {
[email protected]c25a33382011-09-23 17:37:57639 DCHECK_EQ(main_loop_, MessageLoop::current());
[email protected]38259a7a82009-07-29 21:49:49640
641 // TODO(hclam): If the pipeline is performing streaming, we say that this is
642 // a live stream. But instead it should be a StoredStream if we have proper
643 // caching.
644 if (pipeline_->IsStreaming())
645 return WebKit::WebMediaPlayer::LiveStream;
646 return WebKit::WebMediaPlayer::Unknown;
647}
648
[email protected]e06e16d82011-05-26 22:13:33649float WebMediaPlayerImpl::mediaTimeForTimeValue(float timeValue) const {
650 return ConvertSecondsToTimestamp(timeValue).InSecondsF();
651}
652
[email protected]d82b18ae2011-03-23 21:28:59653unsigned WebMediaPlayerImpl::decodedFrameCount() const {
[email protected]c25a33382011-09-23 17:37:57654 DCHECK_EQ(main_loop_, MessageLoop::current());
[email protected]4c51bc662011-02-16 02:03:16655
656 media::PipelineStatistics stats = pipeline_->GetStatistics();
657 return stats.video_frames_decoded;
658}
659
[email protected]d82b18ae2011-03-23 21:28:59660unsigned WebMediaPlayerImpl::droppedFrameCount() const {
[email protected]c25a33382011-09-23 17:37:57661 DCHECK_EQ(main_loop_, MessageLoop::current());
[email protected]4c51bc662011-02-16 02:03:16662
663 media::PipelineStatistics stats = pipeline_->GetStatistics();
664 return stats.video_frames_dropped;
665}
666
[email protected]d82b18ae2011-03-23 21:28:59667unsigned WebMediaPlayerImpl::audioDecodedByteCount() const {
[email protected]c25a33382011-09-23 17:37:57668 DCHECK_EQ(main_loop_, MessageLoop::current());
[email protected]4c51bc662011-02-16 02:03:16669
670 media::PipelineStatistics stats = pipeline_->GetStatistics();
671 return stats.audio_bytes_decoded;
672}
673
[email protected]d82b18ae2011-03-23 21:28:59674unsigned WebMediaPlayerImpl::videoDecodedByteCount() const {
[email protected]c25a33382011-09-23 17:37:57675 DCHECK_EQ(main_loop_, MessageLoop::current());
[email protected]4c51bc662011-02-16 02:03:16676
677 media::PipelineStatistics stats = pipeline_->GetStatistics();
678 return stats.video_bytes_decoded;
679}
680
[email protected]e81283bb2010-08-31 18:01:21681WebKit::WebVideoFrame* WebMediaPlayerImpl::getCurrentFrame() {
682 scoped_refptr<media::VideoFrame> video_frame;
683 proxy_->GetCurrentFrame(&video_frame);
684 if (video_frame.get())
685 return new WebVideoFrameImpl(video_frame);
686 return NULL;
687}
688
689void WebMediaPlayerImpl::putCurrentFrame(
690 WebKit::WebVideoFrame* web_video_frame) {
691 if (web_video_frame) {
[email protected]ad8e04a2010-11-01 04:16:27692 scoped_refptr<media::VideoFrame> video_frame(
693 WebVideoFrameImpl::toVideoFrame(web_video_frame));
[email protected]e81283bb2010-08-31 18:01:21694 proxy_->PutCurrentFrame(video_frame);
695 delete web_video_frame;
696 }
697}
698
[email protected]81bb3322011-07-21 15:55:50699bool WebMediaPlayerImpl::sourceAppend(const unsigned char* data,
700 unsigned length) {
[email protected]c25a33382011-09-23 17:37:57701 DCHECK_EQ(main_loop_, MessageLoop::current());
[email protected]81bb3322011-07-21 15:55:50702 return proxy_->DemuxerAppend(data, length);
703}
704
705void WebMediaPlayerImpl::sourceEndOfStream(
706 WebKit::WebMediaPlayer::EndOfStreamStatus status) {
[email protected]c25a33382011-09-23 17:37:57707 DCHECK_EQ(main_loop_, MessageLoop::current());
[email protected]81bb3322011-07-21 15:55:50708 media::PipelineStatus pipeline_status = media::PIPELINE_OK;
709
710 switch(status) {
[email protected]e4064fd2011-08-04 16:15:51711 case WebKit::WebMediaPlayer::EosNoError:
712 break;
[email protected]81bb3322011-07-21 15:55:50713 case WebKit::WebMediaPlayer::EosNetworkError:
714 pipeline_status = media::PIPELINE_ERROR_NETWORK;
715 break;
716 case WebKit::WebMediaPlayer::EosDecodeError:
717 pipeline_status = media::PIPELINE_ERROR_DECODE;
718 break;
719 default:
720 NOTIMPLEMENTED();
721 }
722
723 proxy_->DemuxerEndOfStream(pipeline_status);
724}
[email protected]81bb3322011-07-21 15:55:50725
[email protected]4e6be3f2009-05-07 02:24:44726void WebMediaPlayerImpl::WillDestroyCurrentMessageLoop() {
[email protected]8931c41a2009-07-07 17:31:49727 Destroy();
728 main_loop_ = NULL;
729}
730
731void WebMediaPlayerImpl::Repaint() {
[email protected]c25a33382011-09-23 17:37:57732 DCHECK_EQ(main_loop_, MessageLoop::current());
[email protected]8931c41a2009-07-07 17:31:49733 GetClient()->repaint();
734}
735
[email protected]a9590c22011-03-16 16:57:02736void WebMediaPlayerImpl::OnPipelineInitialize(PipelineStatus status) {
[email protected]c25a33382011-09-23 17:37:57737 DCHECK_EQ(main_loop_, MessageLoop::current());
[email protected]a9590c22011-03-16 16:57:02738 if (status == media::PIPELINE_OK) {
[email protected]67cd5052009-09-10 21:53:22739 // Only keep one time range starting from 0.
[email protected]c8ca48ea2009-10-16 01:59:17740 WebKit::WebTimeRanges new_buffered(static_cast<size_t>(1));
[email protected]747ca432009-10-09 22:44:48741 new_buffered[0].start = 0.0f;
742 new_buffered[0].end =
[email protected]fd286f22010-04-20 23:45:15743 static_cast<float>(pipeline_->GetMediaDuration().InSecondsF());
[email protected]747ca432009-10-09 22:44:48744 buffered_.swap(new_buffered);
[email protected]67cd5052009-09-10 21:53:22745
[email protected]daeae722011-11-15 23:00:58746 if (hasVideo()) {
747 UMA_HISTOGRAM_BOOLEAN("Media.AcceleratedCompositingActive",
748 is_accelerated_compositing_active_);
749 }
750
[email protected]65bdef09c2011-05-20 05:41:27751 if (pipeline_->IsLoaded()) {
752 SetNetworkState(WebKit::WebMediaPlayer::Loaded);
753 }
754
[email protected]64d3d792010-04-02 03:03:07755 // Since we have initialized the pipeline, say we have everything otherwise
756 // we'll remain either loading/idle.
[email protected]96706912009-07-15 17:18:05757 // TODO(hclam): change this to report the correct status.
758 SetReadyState(WebKit::WebMediaPlayer::HaveMetadata);
759 SetReadyState(WebKit::WebMediaPlayer::HaveEnoughData);
[email protected]96706912009-07-15 17:18:05760 } else {
[email protected]a9590c22011-03-16 16:57:02761 // TODO(hclam): should use |status| to determine the state
[email protected]96706912009-07-15 17:18:05762 // properly and reports error using MediaError.
763 // WebKit uses FormatError to indicate an error for bogus URL or bad file.
764 // Since we are at the initialization stage we can safely treat every error
765 // as format error. Should post a task to call to |webmediaplayer_|.
766 SetNetworkState(WebKit::WebMediaPlayer::FormatError);
767 }
[email protected]83f2a8a2009-08-18 22:42:15768
769 // Repaint to trigger UI update.
770 Repaint();
[email protected]96706912009-07-15 17:18:05771}
772
[email protected]a9590c22011-03-16 16:57:02773void WebMediaPlayerImpl::OnPipelineSeek(PipelineStatus status) {
[email protected]c25a33382011-09-23 17:37:57774 DCHECK_EQ(main_loop_, MessageLoop::current());
[email protected]5d11eff2011-09-15 00:06:06775 seeking_ = false;
776 if (pending_seek_) {
777 pending_seek_ = false;
778 seek(pending_seek_seconds_);
779 return;
780 }
781
[email protected]a9590c22011-03-16 16:57:02782 if (status == media::PIPELINE_OK) {
[email protected]44ff37c02009-10-24 01:03:03783 // Update our paused time.
784 if (paused_) {
785 paused_time_ = pipeline_->GetCurrentTime();
786 }
787
[email protected]0acebfa2009-08-21 22:45:40788 SetReadyState(WebKit::WebMediaPlayer::HaveEnoughData);
[email protected]96706912009-07-15 17:18:05789 GetClient()->timeChanged();
790 }
[email protected]8931c41a2009-07-07 17:31:49791}
792
[email protected]a9590c22011-03-16 16:57:02793void WebMediaPlayerImpl::OnPipelineEnded(PipelineStatus status) {
[email protected]c25a33382011-09-23 17:37:57794 DCHECK_EQ(main_loop_, MessageLoop::current());
[email protected]a9590c22011-03-16 16:57:02795 if (status == media::PIPELINE_OK) {
[email protected]576537842009-08-12 23:52:05796 GetClient()->timeChanged();
797 }
798}
799
[email protected]a9590c22011-03-16 16:57:02800void WebMediaPlayerImpl::OnPipelineError(PipelineStatus error) {
[email protected]c25a33382011-09-23 17:37:57801 DCHECK_EQ(main_loop_, MessageLoop::current());
[email protected]a9590c22011-03-16 16:57:02802 switch (error) {
[email protected]db190487d2009-07-30 18:51:52803 case media::PIPELINE_OK:
[email protected]a9590c22011-03-16 16:57:02804 LOG(DFATAL) << "PIPELINE_OK isn't an error!";
805 break;
806
[email protected]e4064fd2011-08-04 16:15:51807 case media::PIPELINE_ERROR_NETWORK:
808 SetNetworkState(WebMediaPlayer::NetworkError);
809 break;
810
[email protected]db190487d2009-07-30 18:51:52811 case media::PIPELINE_ERROR_INITIALIZATION_FAILED:
812 case media::PIPELINE_ERROR_REQUIRED_FILTER_MISSING:
813 case media::PIPELINE_ERROR_COULD_NOT_RENDER:
[email protected]db190487d2009-07-30 18:51:52814 case media::PIPELINE_ERROR_URL_NOT_FOUND:
[email protected]db190487d2009-07-30 18:51:52815 case media::PIPELINE_ERROR_READ:
[email protected]db190487d2009-07-30 18:51:52816 case media::DEMUXER_ERROR_COULD_NOT_OPEN:
817 case media::DEMUXER_ERROR_COULD_NOT_PARSE:
818 case media::DEMUXER_ERROR_NO_SUPPORTED_STREAMS:
819 case media::DEMUXER_ERROR_COULD_NOT_CREATE_THREAD:
[email protected]1ab1c24b2011-09-21 22:44:04820 case media::DECODER_ERROR_NOT_SUPPORTED:
[email protected]b6c29552011-03-14 15:56:29821 case media::DATASOURCE_ERROR_URL_NOT_SUPPORTED:
[email protected]9c4e77ab2009-07-31 00:17:08822 // Format error.
823 SetNetworkState(WebMediaPlayer::FormatError);
824 break;
825
826 case media::PIPELINE_ERROR_DECODE:
827 case media::PIPELINE_ERROR_ABORT:
828 case media::PIPELINE_ERROR_OUT_OF_MEMORY:
829 case media::PIPELINE_ERROR_AUDIO_HARDWARE:
[email protected]641c9abc2011-01-05 18:44:10830 case media::PIPELINE_ERROR_OPERATION_PENDING:
831 case media::PIPELINE_ERROR_INVALID_STATE:
[email protected]db190487d2009-07-30 18:51:52832 // Decode error.
833 SetNetworkState(WebMediaPlayer::DecodeError);
834 break;
835 }
[email protected]bb2c1f32009-08-14 04:14:50836
837 // Repaint to trigger UI update.
838 Repaint();
[email protected]db190487d2009-07-30 18:51:52839}
840
[email protected]b55a06a2011-10-19 20:21:12841void WebMediaPlayerImpl::OnNetworkEvent(bool is_downloading_data) {
[email protected]c25a33382011-09-23 17:37:57842 DCHECK_EQ(main_loop_, MessageLoop::current());
[email protected]b55a06a2011-10-19 20:21:12843 if (is_downloading_data)
844 SetNetworkState(WebKit::WebMediaPlayer::Loading);
845 else
846 SetNetworkState(WebKit::WebMediaPlayer::Idle);
[email protected]4f92fbc2009-10-16 01:29:50847}
848
[email protected]81bb3322011-07-21 15:55:50849void WebMediaPlayerImpl::OnDemuxerOpened() {
[email protected]c25a33382011-09-23 17:37:57850 DCHECK_EQ(main_loop_, MessageLoop::current());
[email protected]81bb3322011-07-21 15:55:50851
[email protected]6aa03b32011-10-27 21:44:44852 GetClient()->sourceOpened();
[email protected]81bb3322011-07-21 15:55:50853}
854
[email protected]8931c41a2009-07-07 17:31:49855void WebMediaPlayerImpl::SetNetworkState(
856 WebKit::WebMediaPlayer::NetworkState state) {
[email protected]c25a33382011-09-23 17:37:57857 DCHECK_EQ(main_loop_, MessageLoop::current());
[email protected]867e59272009-08-25 18:08:16858 // Always notify to ensure client has the latest value.
859 network_state_ = state;
860 GetClient()->networkStateChanged();
[email protected]8931c41a2009-07-07 17:31:49861}
862
863void WebMediaPlayerImpl::SetReadyState(
864 WebKit::WebMediaPlayer::ReadyState state) {
[email protected]c25a33382011-09-23 17:37:57865 DCHECK_EQ(main_loop_, MessageLoop::current());
[email protected]867e59272009-08-25 18:08:16866 // Always notify to ensure client has the latest value.
867 ready_state_ = state;
868 GetClient()->readyStateChanged();
[email protected]8931c41a2009-07-07 17:31:49869}
870
871void WebMediaPlayerImpl::Destroy() {
[email protected]c25a33382011-09-23 17:37:57872 DCHECK_EQ(main_loop_, MessageLoop::current());
[email protected]8931c41a2009-07-07 17:31:49873
[email protected]5b5bb9d2010-10-22 19:57:36874 // Tell the data source to abort any pending reads so that the pipeline is
875 // not blocked when issuing stop commands to the other filters.
[email protected]81bb3322011-07-21 15:55:50876 if (proxy_) {
[email protected]f63760a2011-02-16 04:59:10877 proxy_->AbortDataSources();
[email protected]81bb3322011-07-21 15:55:50878 proxy_->DemuxerShutdown();
879 }
[email protected]020fba32011-06-29 16:37:46880
[email protected]8931c41a2009-07-07 17:31:49881 // Make sure to kill the pipeline so there's no more media threads running.
[email protected]5badb082010-06-11 17:40:15882 // Note: stopping the pipeline might block for a long time.
[email protected]a8e24d522010-12-01 07:13:58883 if (pipeline_) {
[email protected]ea431e52011-03-17 22:03:12884 media::PipelineStatusNotification note;
885 pipeline_->Stop(note.Callback());
886 note.Wait();
[email protected]38aefc312011-09-20 05:06:37887
888 // Let V8 know we are not using extra resources anymore.
[email protected]c25a33382011-09-23 17:37:57889 if (incremented_externally_allocated_memory_) {
890 v8::V8::AdjustAmountOfExternalAllocatedMemory(-kPlayerExtraMemory);
891 incremented_externally_allocated_memory_ = false;
[email protected]38aefc312011-09-20 05:06:37892 }
[email protected]a8e24d522010-12-01 07:13:58893 }
[email protected]5df51652009-01-17 00:03:00894
[email protected]f78d1dfc2011-01-15 07:09:27895 message_loop_factory_.reset();
896
[email protected]8931c41a2009-07-07 17:31:49897 // And then detach the proxy, it may live on the render thread for a little
898 // longer until all the tasks are finished.
899 if (proxy_) {
900 proxy_->Detach();
901 proxy_ = NULL;
[email protected]a7281022009-06-17 17:58:04902 }
[email protected]5df51652009-01-17 00:03:00903}
904
[email protected]8931c41a2009-07-07 17:31:49905WebKit::WebMediaPlayerClient* WebMediaPlayerImpl::GetClient() {
[email protected]c25a33382011-09-23 17:37:57906 DCHECK_EQ(main_loop_, MessageLoop::current());
[email protected]8931c41a2009-07-07 17:31:49907 DCHECK(client_);
908 return client_;
[email protected]5df51652009-01-17 00:03:00909}
[email protected]add51772009-06-11 18:25:17910
[email protected]c25a33382011-09-23 17:37:57911void WebMediaPlayerImpl::IncrementExternallyAllocatedMemory() {
912 DCHECK_EQ(main_loop_, MessageLoop::current());
913 incremented_externally_allocated_memory_ = true;
914 v8::V8::AdjustAmountOfExternalAllocatedMemory(kPlayerExtraMemory);
[email protected]38aefc312011-09-20 05:06:37915}
916
[email protected]add51772009-06-11 18:25:17917} // namespace webkit_glue