blob: adea37549ceb4a6ac0be372f62e7428f18d82db7 [file] [log] [blame]
[email protected]85a37afd2013-05-30 22:51:151// Copyright 2013 The Chromium Authors. All rights reserved.
[email protected]891acc92009-04-27 19:56:412// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
[email protected]ec9212f2008-12-18 21:40:364
[email protected]5e35a8d2013-07-10 19:37:215#include "content/renderer/media/webmediaplayer_impl.h"
[email protected]8931c41a2009-07-07 17:31:496
[email protected]c2a45e242013-02-15 20:24:587#include <algorithm>
[email protected]47b06ceb2010-08-04 22:41:118#include <limits>
[email protected]d82b18ae2011-03-23 21:28:599#include <string>
[email protected]cbdc8c2b2012-06-16 01:27:3610#include <vector>
[email protected]47b06ceb2010-08-04 22:41:1111
[email protected]08273c7b2011-09-17 00:33:5112#include "base/bind.h"
[email protected]2041cf342010-02-19 03:15:5913#include "base/callback.h"
[email protected]ddbc6ff2013-04-19 15:28:3314#include "base/command_line.h"
[email protected]926f8fd2013-04-12 20:27:5315#include "base/debug/crash_logging.h"
[email protected]7ccb7072013-06-10 20:56:2816#include "base/message_loop/message_loop_proxy.h"
[email protected]b0b258f2011-11-08 00:34:2317#include "base/metrics/histogram.h"
[email protected]4ce532f2013-03-27 22:03:4018#include "base/strings/string_number_conversions.h"
[email protected]cf02541b2012-04-11 08:02:1719#include "base/synchronization/waitable_event.h"
[email protected]21c3f7502013-03-23 03:29:5120#include "cc/layers/video_layer.h"
[email protected]ca73adc72013-07-11 11:37:0221#include "content/public/common/content_switches.h"
[email protected]5e35a8d2013-07-10 19:37:2122#include "content/renderer/media/buffered_data_source.h"
[email protected]61582e8c2013-07-14 00:38:3323#include "content/renderer/media/crypto/key_systems.h"
[email protected]5e35a8d2013-07-10 19:37:2124#include "content/renderer/media/texttrack_impl.h"
25#include "content/renderer/media/webaudiosourceprovider_impl.h"
26#include "content/renderer/media/webinbandtexttrack_impl.h"
27#include "content/renderer/media/webmediaplayer_delegate.h"
28#include "content/renderer/media/webmediaplayer_params.h"
29#include "content/renderer/media/webmediaplayer_util.h"
[email protected]ef8394c2013-08-21 20:26:3030#include "content/renderer/media/webmediasource_impl.h"
[email protected]adab2332013-07-25 18:04:3231#include "content/renderer/pepper/pepper_webplugin_impl.h"
[email protected]6523b242013-03-13 11:10:0732#include "gpu/GLES2/gl2extchromium.h"
[email protected]e4fc09e2012-04-06 03:17:4433#include "media/audio/null_audio_sink.h"
[email protected]2c539b82012-08-18 04:10:1934#include "media/base/bind_to_loop.h"
[email protected]f8db8132010-12-03 00:27:4935#include "media/base/filter_collection.h"
[email protected]32da1002010-03-03 21:57:3536#include "media/base/limits.h"
[email protected]090f7312011-08-05 23:26:4037#include "media/base/media_log.h"
[email protected]ddbc6ff2013-04-19 15:28:3338#include "media/base/media_switches.h"
[email protected]d399866c2012-01-18 09:30:3239#include "media/base/pipeline.h"
[email protected]e81283bb2010-08-31 18:01:2140#include "media/base/video_frame.h"
[email protected]37136d162012-04-09 23:39:1941#include "media/filters/audio_renderer_impl.h"
[email protected]efe7cd22012-09-12 23:55:0142#include "media/filters/chunk_demuxer.h"
[email protected]ddbc6ff2013-04-19 15:28:3343#include "media/filters/ffmpeg_audio_decoder.h"
44#include "media/filters/ffmpeg_demuxer.h"
45#include "media/filters/ffmpeg_video_decoder.h"
[email protected]1cad8802013-08-13 16:54:3246#include "media/filters/gpu_video_accelerator_factories.h"
[email protected]b9a407e2013-07-24 07:30:0247#include "media/filters/gpu_video_decoder.h"
[email protected]ddbc6ff2013-04-19 15:28:3348#include "media/filters/opus_audio_decoder.h"
[email protected]d4833b72012-01-13 22:16:1749#include "media/filters/video_renderer_base.h"
[email protected]ddbc6ff2013-04-19 15:28:3350#include "media/filters/vpx_video_decoder.h"
[email protected]c10884462013-05-30 00:22:0951#include "third_party/WebKit/public/platform/WebRect.h"
52#include "third_party/WebKit/public/platform/WebSize.h"
53#include "third_party/WebKit/public/platform/WebString.h"
54#include "third_party/WebKit/public/platform/WebURL.h"
[email protected]2255a9332013-06-17 05:12:3155#include "third_party/WebKit/public/web/WebMediaSource.h"
56#include "third_party/WebKit/public/web/WebRuntimeFeatures.h"
57#include "third_party/WebKit/public/web/WebView.h"
[email protected]38aefc312011-09-20 05:06:3758#include "v8/include/v8.h"
[email protected]799fd732013-05-15 21:18:5259#include "webkit/renderer/compositor_bindings/web_layer_impl.h"
[email protected]b3f2b912009-04-09 16:18:5260
[email protected]df143bdc2009-06-16 17:34:1961using WebKit::WebCanvas;
[email protected]ef405f66b2012-04-18 02:39:5562using WebKit::WebMediaPlayer;
[email protected]b3f2b912009-04-09 16:18:5263using WebKit::WebRect;
64using WebKit::WebSize;
[email protected]f7a6b992012-04-19 09:45:5665using WebKit::WebString;
[email protected]a9590c22011-03-16 16:57:0266using media::PipelineStatus;
[email protected]ec9212f2008-12-18 21:40:3667
[email protected]8931c41a2009-07-07 17:31:4968namespace {
69
[email protected]38aefc312011-09-20 05:06:3770// Amount of extra memory used by each player instance reported to V8.
71// It is not exact number -- first, it differs on different platforms,
72// and second, it is very hard to calculate. Instead, use some arbitrary
73// value that will cause garbage collection from time to time. We don't want
74// it to happen on every allocation, but don't want 5k players to sit in memory
75// either. Looks that chosen constant achieves both goals, at least for audio
76// objects. (Do not worry about video objects yet, JS programs do not create
77// thousands of them...)
78const int kPlayerExtraMemory = 1024 * 1024;
79
[email protected]378f0b72009-08-11 17:11:4280// Limits the range of playback rate.
81//
82// TODO(kylep): Revisit these.
83//
84// Vista has substantially lower performance than XP or Windows7. If you speed
85// up a video too much, it can't keep up, and rendering stops updating except on
86// the time bar. For really high speeds, audio becomes a bottleneck and we just
87// use up the data we have, which may not achieve the speed requested, but will
88// not crash the tab.
89//
90// A very slow speed, ie 0.00000001x, causes the machine to lock up. (It seems
91// like a busy loop). It gets unresponsive, although its not completely dead.
92//
93// Also our timers are not very accurate (especially for ogg), which becomes
94// evident at low speeds and on Vista. Since other speeds are risky and outside
95// the norms, we think 1/16x to 16x is a safe and useful range for now.
[email protected]39bdde32013-04-17 17:44:2096const double kMinRate = 0.0625;
97const double kMaxRate = 16.0;
[email protected]378f0b72009-08-11 17:11:4298
[email protected]2ca7d5c2012-10-23 07:30:5499// Prefix for histograms related to Encrypted Media Extensions.
100const char* kMediaEme = "Media.EME.";
[email protected]61582e8c2013-07-14 00:38:33101
[email protected]8931c41a2009-07-07 17:31:49102} // namespace
103
[email protected]5e35a8d2013-07-10 19:37:21104namespace content {
[email protected]add51772009-06-11 18:25:17105
[email protected]a8884632012-06-29 03:05:34106#define COMPILE_ASSERT_MATCHING_ENUM(name) \
[email protected]2ca7d5c2012-10-23 07:30:54107 COMPILE_ASSERT(static_cast<int>(WebMediaPlayer::CORSMode ## name) == \
[email protected]a8884632012-06-29 03:05:34108 static_cast<int>(BufferedResourceLoader::k ## name), \
[email protected]a5a01102012-06-06 17:01:24109 mismatching_enums)
110COMPILE_ASSERT_MATCHING_ENUM(Unspecified);
111COMPILE_ASSERT_MATCHING_ENUM(Anonymous);
112COMPILE_ASSERT_MATCHING_ENUM(UseCredentials);
113#undef COMPILE_ASSERT_MATCHING_ENUM
114
[email protected]2c539b82012-08-18 04:10:19115#define BIND_TO_RENDER_LOOP(function) \
[email protected]e82c0e352013-03-01 01:53:46116 media::BindToLoop(main_loop_, base::Bind(function, AsWeakPtr()))
[email protected]2c539b82012-08-18 04:10:19117
[email protected]62e5e682013-03-07 23:53:24118#define BIND_TO_RENDER_LOOP_1(function, arg1) \
119 media::BindToLoop(main_loop_, base::Bind(function, AsWeakPtr(), arg1))
120
[email protected]5983adb2012-10-24 00:12:00121#define BIND_TO_RENDER_LOOP_2(function, arg1, arg2) \
[email protected]e82c0e352013-03-01 01:53:46122 media::BindToLoop(main_loop_, base::Bind(function, AsWeakPtr(), arg1, arg2))
[email protected]5983adb2012-10-24 00:12:00123
[email protected]2ef99602012-12-08 04:22:21124static void LogMediaSourceError(const scoped_refptr<media::MediaLog>& media_log,
125 const std::string& error) {
126 media_log->AddEvent(media_log->CreateMediaSourceErrorEvent(error));
127}
128
[email protected]5b5bb9d2010-10-22 19:57:36129WebMediaPlayerImpl::WebMediaPlayerImpl(
[email protected]da952fd2012-01-13 03:49:25130 WebKit::WebFrame* frame,
[email protected]5b5bb9d2010-10-22 19:57:36131 WebKit::WebMediaPlayerClient* client,
[email protected]b8976652011-10-26 23:46:55132 base::WeakPtr<WebMediaPlayerDelegate> delegate,
[email protected]e82b2bd2013-01-02 17:47:57133 const WebMediaPlayerParams& params)
[email protected]a9415292012-01-19 19:55:20134 : frame_(frame),
[email protected]ef405f66b2012-04-18 02:39:55135 network_state_(WebMediaPlayer::NetworkStateEmpty),
136 ready_state_(WebMediaPlayer::ReadyStateHaveNothing),
[email protected]e82c0e352013-03-01 01:53:46137 main_loop_(base::MessageLoopProxy::current()),
[email protected]c1330c82013-06-06 02:23:25138 media_loop_(params.message_loop_proxy()),
[email protected]49480902009-07-14 20:23:43139 paused_(true),
[email protected]b3766a22010-12-22 17:34:13140 seeking_(false),
[email protected]49480902009-07-14 20:23:43141 playback_rate_(0.0f),
[email protected]5d11eff2011-09-15 00:06:06142 pending_seek_(false),
[email protected]b1a975e2011-12-21 00:12:39143 pending_seek_seconds_(0.0f),
[email protected]5badb082010-06-11 17:40:15144 client_(client),
[email protected]baff4512011-10-19 18:21:07145 delegate_(delegate),
[email protected]d726eddc2013-07-02 22:25:55146 defer_load_cb_(params.defer_load_cb()),
[email protected]e82b2bd2013-01-02 17:47:57147 media_log_(params.media_log()),
[email protected]c5b1b642012-03-26 19:40:51148 accelerated_compositing_reported_(false),
[email protected]9e2269d2012-01-07 00:06:21149 incremented_externally_allocated_memory_(false),
[email protected]ddbc6ff2013-04-19 15:28:33150 gpu_factories_(params.gpu_factories()),
[email protected]a8884632012-06-29 03:05:34151 is_local_source_(false),
[email protected]132dd57c2012-08-10 23:24:34152 supports_save_(true),
[email protected]b49beeb2013-03-01 20:04:00153 starting_(false),
[email protected]f5443ef72013-04-22 04:03:38154 chunk_demuxer_(NULL),
[email protected]21c3f7502013-03-23 03:29:51155 pending_repaint_(false),
[email protected]29037ce52013-05-06 22:44:16156 pending_size_change_(false),
[email protected]71537722013-05-23 06:47:53157 video_frame_provider_client_(NULL),
158 text_track_index_(0) {
[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]cadac622013-06-11 16:46:36162 pipeline_.reset(new media::Pipeline(media_loop_, media_log_.get()));
[email protected]db190487d2009-07-30 18:51:52163
[email protected]e82b2bd2013-01-02 17:47:57164 // Let V8 know we started new thread if we did not do it yet.
[email protected]da952fd2012-01-13 03:49:25165 // Made separate task to avoid deletion of player currently being created.
166 // Also, delaying GC until after player starts gets rid of starting lag --
167 // collection happens in parallel with playing.
168 //
169 // TODO(enal): remove when we get rid of per-audio-stream thread.
[email protected]e82c0e352013-03-01 01:53:46170 main_loop_->PostTask(
[email protected]da952fd2012-01-13 03:49:25171 FROM_HERE,
172 base::Bind(&WebMediaPlayerImpl::IncrementExternallyAllocatedMemory,
173 AsWeakPtr()));
174
[email protected]da952fd2012-01-13 03:49:25175 // Also we want to be notified of |main_loop_| destruction.
[email protected]fb5af232013-04-22 22:40:03176 base::MessageLoop::current()->AddDestructionObserver(this);
[email protected]da952fd2012-01-13 03:49:25177
[email protected]16c242d2013-05-31 23:56:47178 if (WebKit::WebRuntimeFeatures::isLegacyEncryptedMediaEnabled()) {
[email protected]abd36b3af2012-12-22 03:42:02179 decryptor_.reset(new ProxyDecryptor(
[email protected]04af49912013-06-21 22:09:01180#if defined(ENABLE_PEPPER_CDMS)
[email protected]abd36b3af2012-12-22 03:42:02181 client,
182 frame,
[email protected]04af49912013-06-21 22:09:01183#endif
[email protected]abd36b3af2012-12-22 03:42:02184 BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnKeyAdded),
185 BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnKeyError),
[email protected]7e06e6ac2013-06-20 21:34:15186 BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnKeyMessage)));
[email protected]47ebb0e2012-11-30 08:28:29187 }
[email protected]893f28282012-12-14 22:51:35188
[email protected]ddbc6ff2013-04-19 15:28:33189 // Use the null sink if no sink was provided.
[email protected]4a914882013-01-10 00:43:48190 audio_source_provider_ = new WebAudioSourceProviderImpl(
[email protected]ff875be52013-06-02 23:47:38191 params.audio_renderer_sink().get()
192 ? params.audio_renderer_sink()
[email protected]c1330c82013-06-06 02:23:25193 : new media::NullAudioSink(media_loop_));
[email protected]ec9212f2008-12-18 21:40:36194}
195
[email protected]4e6be3f2009-05-07 02:24:44196WebMediaPlayerImpl::~WebMediaPlayerImpl() {
[email protected]21c3f7502013-03-23 03:29:51197 SetVideoFrameProviderClient(NULL);
198 GetClient()->setWebLayer(NULL);
[email protected]21c3f7502013-03-23 03:29:51199
[email protected]e82c0e352013-03-01 01:53:46200 DCHECK(main_loop_->BelongsToCurrentThread());
[email protected]c93eb0a62011-08-09 22:47:24201 media_log_->AddEvent(
202 media_log_->CreateEvent(media::MediaLogEvent::WEBMEDIAPLAYER_DESTROYED));
[email protected]d43ed912009-02-03 04:52:53203
[email protected]9b55d802013-06-04 02:39:46204 if (delegate_.get())
[email protected]baff4512011-10-19 18:21:07205 delegate_->PlayerGone(this);
206
[email protected]a3702c52013-05-09 05:40:30207 Destroy();
208
[email protected]e82c0e352013-03-01 01:53:46209 // Remove destruction observer if we're being destroyed but the main thread is
210 // still running.
[email protected]fb5af232013-04-22 22:40:03211 if (base::MessageLoop::current())
212 base::MessageLoop::current()->RemoveDestructionObserver(this);
[email protected]ec9212f2008-12-18 21:40:36213}
214
[email protected]daeae722011-11-15 23:00:58215namespace {
216
217// Helper enum for reporting scheme histograms.
218enum URLSchemeForHistogram {
219 kUnknownURLScheme,
220 kMissingURLScheme,
221 kHttpURLScheme,
222 kHttpsURLScheme,
223 kFtpURLScheme,
224 kChromeExtensionURLScheme,
225 kJavascriptURLScheme,
226 kFileURLScheme,
227 kBlobURLScheme,
228 kDataURLScheme,
[email protected]aacd4a42012-04-11 02:34:48229 kFileSystemScheme,
230 kMaxURLScheme = kFileSystemScheme // Must be equal to highest enum value.
[email protected]daeae722011-11-15 23:00:58231};
232
233URLSchemeForHistogram URLScheme(const GURL& url) {
234 if (!url.has_scheme()) return kMissingURLScheme;
235 if (url.SchemeIs("http")) return kHttpURLScheme;
236 if (url.SchemeIs("https")) return kHttpsURLScheme;
237 if (url.SchemeIs("ftp")) return kFtpURLScheme;
238 if (url.SchemeIs("chrome-extension")) return kChromeExtensionURLScheme;
239 if (url.SchemeIs("javascript")) return kJavascriptURLScheme;
240 if (url.SchemeIs("file")) return kFileURLScheme;
241 if (url.SchemeIs("blob")) return kBlobURLScheme;
242 if (url.SchemeIs("data")) return kDataURLScheme;
[email protected]aacd4a42012-04-11 02:34:48243 if (url.SchemeIs("filesystem")) return kFileSystemScheme;
[email protected]daeae722011-11-15 23:00:58244 return kUnknownURLScheme;
245}
246
247} // anonymous namespace
248
[email protected]ef8394c2013-08-21 20:26:30249void WebMediaPlayerImpl::load(LoadType load_type, const WebKit::WebURL& url,
[email protected]62e5e682013-03-07 23:53:24250 CORSMode cors_mode) {
[email protected]d726eddc2013-07-02 22:25:55251 if (!defer_load_cb_.is_null()) {
252 defer_load_cb_.Run(base::Bind(
[email protected]ef8394c2013-08-21 20:26:30253 &WebMediaPlayerImpl::DoLoad, AsWeakPtr(), load_type, url, cors_mode));
[email protected]d726eddc2013-07-02 22:25:55254 return;
255 }
[email protected]ef8394c2013-08-21 20:26:30256 DoLoad(load_type, url, cors_mode);
[email protected]62e5e682013-03-07 23:53:24257}
258
[email protected]ef8394c2013-08-21 20:26:30259void WebMediaPlayerImpl::DoLoad(LoadType load_type,
260 const WebKit::WebURL& url,
[email protected]d726eddc2013-07-02 22:25:55261 CORSMode cors_mode) {
262 DCHECK(main_loop_->BelongsToCurrentThread());
263
[email protected]62e5e682013-03-07 23:53:24264 GURL gurl(url);
265 UMA_HISTOGRAM_ENUMERATION("Media.URLScheme", URLScheme(gurl), kMaxURLScheme);
266
[email protected]926f8fd2013-04-12 20:27:53267 // Set subresource URL for crash reporting.
268 base::debug::SetCrashKeyValue("subresource_url", gurl.spec());
269
[email protected]ef8394c2013-08-21 20:26:30270 load_type_ = load_type;
271
[email protected]62e5e682013-03-07 23:53:24272 // Handle any volume/preload changes that occurred before load().
273 setVolume(GetClient()->volume());
274 setPreload(GetClient()->preload());
275
276 SetNetworkState(WebMediaPlayer::NetworkStateLoading);
277 SetReadyState(WebMediaPlayer::ReadyStateHaveNothing);
278 media_log_->AddEvent(media_log_->CreateLoadEvent(url.spec()));
[email protected]d726eddc2013-07-02 22:25:55279
280 // Media source pipelines can start immediately.
[email protected]ef8394c2013-08-21 20:26:30281 if (load_type == LoadTypeMediaSource) {
[email protected]d726eddc2013-07-02 22:25:55282 supports_save_ = false;
[email protected]ef8394c2013-08-21 20:26:30283 StartPipeline();
[email protected]d726eddc2013-07-02 22:25:55284 return;
285 }
286
287 // Otherwise it's a regular request which requires resolving the URL first.
288 data_source_.reset(new BufferedDataSource(
289 main_loop_,
290 frame_,
291 media_log_.get(),
292 base::Bind(&WebMediaPlayerImpl::NotifyDownloading, AsWeakPtr())));
293 data_source_->Initialize(
294 url, static_cast<BufferedResourceLoader::CORSMode>(cors_mode),
295 base::Bind(
296 &WebMediaPlayerImpl::DataSourceInitialized,
297 AsWeakPtr(), gurl));
298
299 is_local_source_ = !gurl.SchemeIs("http") && !gurl.SchemeIs("https");
[email protected]62e5e682013-03-07 23:53:24300}
301
[email protected]4e6be3f2009-05-07 02:24:44302void WebMediaPlayerImpl::play() {
[email protected]e82c0e352013-03-01 01:53:46303 DCHECK(main_loop_->BelongsToCurrentThread());
[email protected]d43ed912009-02-03 04:52:53304
[email protected]49480902009-07-14 20:23:43305 paused_ = false;
306 pipeline_->SetPlaybackRate(playback_rate_);
[email protected]090f7312011-08-05 23:26:40307
[email protected]24d75c72011-08-09 17:53:45308 media_log_->AddEvent(media_log_->CreateEvent(media::MediaLogEvent::PLAY));
[email protected]baff4512011-10-19 18:21:07309
[email protected]9b55d802013-06-04 02:39:46310 if (delegate_.get())
[email protected]baff4512011-10-19 18:21:07311 delegate_->DidPlay(this);
[email protected]ec9212f2008-12-18 21:40:36312}
313
[email protected]4e6be3f2009-05-07 02:24:44314void WebMediaPlayerImpl::pause() {
[email protected]e82c0e352013-03-01 01:53:46315 DCHECK(main_loop_->BelongsToCurrentThread());
[email protected]d43ed912009-02-03 04:52:53316
[email protected]49480902009-07-14 20:23:43317 paused_ = true;
[email protected]3b4cbbf2009-07-11 00:16:19318 pipeline_->SetPlaybackRate(0.0f);
[email protected]f7c0ada02012-07-23 08:42:50319 paused_time_ = pipeline_->GetMediaTime();
[email protected]090f7312011-08-05 23:26:40320
[email protected]24d75c72011-08-09 17:53:45321 media_log_->AddEvent(media_log_->CreateEvent(media::MediaLogEvent::PAUSE));
[email protected]baff4512011-10-19 18:21:07322
[email protected]9b55d802013-06-04 02:39:46323 if (delegate_.get())
[email protected]baff4512011-10-19 18:21:07324 delegate_->DidPause(this);
[email protected]ec9212f2008-12-18 21:40:36325}
326
[email protected]574a1d62009-07-17 03:23:46327bool WebMediaPlayerImpl::supportsFullscreen() const {
[email protected]e82c0e352013-03-01 01:53:46328 DCHECK(main_loop_->BelongsToCurrentThread());
[email protected]574a1d62009-07-17 03:23:46329 return true;
330}
331
332bool WebMediaPlayerImpl::supportsSave() const {
[email protected]e82c0e352013-03-01 01:53:46333 DCHECK(main_loop_->BelongsToCurrentThread());
[email protected]132dd57c2012-08-10 23:24:34334 return supports_save_;
[email protected]574a1d62009-07-17 03:23:46335}
336
[email protected]39bdde32013-04-17 17:44:20337void WebMediaPlayerImpl::seek(double seconds) {
[email protected]e82c0e352013-03-01 01:53:46338 DCHECK(main_loop_->BelongsToCurrentThread());
[email protected]d43ed912009-02-03 04:52:53339
[email protected]bb8a70b2013-06-26 06:23:35340 base::TimeDelta seek_time = ConvertSecondsToTimestamp(seconds);
341
[email protected]a8e2cb82012-08-17 00:02:39342 if (starting_ || seeking_) {
[email protected]5d11eff2011-09-15 00:06:06343 pending_seek_ = true;
344 pending_seek_seconds_ = seconds;
[email protected]efe7cd22012-09-12 23:55:01345 if (chunk_demuxer_)
[email protected]bb8a70b2013-06-26 06:23:35346 chunk_demuxer_->CancelPendingSeek(seek_time);
[email protected]5d11eff2011-09-15 00:06:06347 return;
348 }
349
[email protected]c93eb0a62011-08-09 22:47:24350 media_log_->AddEvent(media_log_->CreateSeekEvent(seconds));
351
[email protected]44ff37c02009-10-24 01:03:03352 // Update our paused time.
[email protected]7b268b7a2011-11-18 19:52:08353 if (paused_)
[email protected]44ff37c02009-10-24 01:03:03354 paused_time_ = seek_time;
[email protected]44ff37c02009-10-24 01:03:03355
[email protected]b3766a22010-12-22 17:34:13356 seeking_ = true;
357
[email protected]efe7cd22012-09-12 23:55:01358 if (chunk_demuxer_)
[email protected]bb8a70b2013-06-26 06:23:35359 chunk_demuxer_->StartWaitingForSeek(seek_time);
[email protected]020fba32011-06-29 16:37:46360
[email protected]44ff37c02009-10-24 01:03:03361 // Kick off the asynchronous seek!
[email protected]3b4cbbf2009-07-11 00:16:19362 pipeline_->Seek(
[email protected]44ff37c02009-10-24 01:03:03363 seek_time,
[email protected]2c539b82012-08-18 04:10:19364 BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnPipelineSeek));
[email protected]ec9212f2008-12-18 21:40:36365}
366
[email protected]39bdde32013-04-17 17:44:20367void WebMediaPlayerImpl::setRate(double rate) {
[email protected]e82c0e352013-03-01 01:53:46368 DCHECK(main_loop_->BelongsToCurrentThread());
[email protected]d43ed912009-02-03 04:52:53369
[email protected]378f0b72009-08-11 17:11:42370 // TODO(kylep): Remove when support for negatives is added. Also, modify the
371 // following checks so rewind uses reasonable values also.
[email protected]39bdde32013-04-17 17:44:20372 if (rate < 0.0)
[email protected]378f0b72009-08-11 17:11:42373 return;
374
375 // Limit rates to reasonable values by clamping.
[email protected]39bdde32013-04-17 17:44:20376 if (rate != 0.0) {
[email protected]378f0b72009-08-11 17:11:42377 if (rate < kMinRate)
378 rate = kMinRate;
379 else if (rate > kMaxRate)
380 rate = kMaxRate;
381 }
382
[email protected]49480902009-07-14 20:23:43383 playback_rate_ = rate;
384 if (!paused_) {
385 pipeline_->SetPlaybackRate(rate);
386 }
[email protected]ec9212f2008-12-18 21:40:36387}
388
[email protected]39bdde32013-04-17 17:44:20389void WebMediaPlayerImpl::setVolume(double volume) {
[email protected]e82c0e352013-03-01 01:53:46390 DCHECK(main_loop_->BelongsToCurrentThread());
[email protected]d43ed912009-02-03 04:52:53391
[email protected]3b4cbbf2009-07-11 00:16:19392 pipeline_->SetVolume(volume);
[email protected]ec9212f2008-12-18 21:40:36393}
[email protected]f0a51fb52009-03-05 12:46:38394
[email protected]23a8b1d82011-04-05 16:28:20395#define COMPILE_ASSERT_MATCHING_ENUM(webkit_name, chromium_name) \
[email protected]ef405f66b2012-04-18 02:39:55396 COMPILE_ASSERT(static_cast<int>(WebMediaPlayer::webkit_name) == \
[email protected]5e35a8d2013-07-10 19:37:21397 static_cast<int>(content::chromium_name), \
[email protected]474c37a2011-08-23 20:24:52398 mismatching_enums)
[email protected]ef405f66b2012-04-18 02:39:55399COMPILE_ASSERT_MATCHING_ENUM(PreloadNone, NONE);
400COMPILE_ASSERT_MATCHING_ENUM(PreloadMetaData, METADATA);
401COMPILE_ASSERT_MATCHING_ENUM(PreloadAuto, AUTO);
[email protected]a5a01102012-06-06 17:01:24402#undef COMPILE_ASSERT_MATCHING_ENUM
[email protected]23a8b1d82011-04-05 16:28:20403
[email protected]ef405f66b2012-04-18 02:39:55404void WebMediaPlayerImpl::setPreload(WebMediaPlayer::Preload preload) {
[email protected]e82c0e352013-03-01 01:53:46405 DCHECK(main_loop_->BelongsToCurrentThread());
[email protected]4e6be3f2009-05-07 02:24:44406
[email protected]b49beeb2013-03-01 20:04:00407 if (data_source_)
[email protected]5e35a8d2013-07-10 19:37:21408 data_source_->SetPreload(static_cast<content::Preload>(preload));
[email protected]4e6be3f2009-05-07 02:24:44409}
410
[email protected]4e6be3f2009-05-07 02:24:44411bool WebMediaPlayerImpl::hasVideo() const {
[email protected]e82c0e352013-03-01 01:53:46412 DCHECK(main_loop_->BelongsToCurrentThread());
[email protected]d43ed912009-02-03 04:52:53413
[email protected]cee32342011-03-09 15:58:16414 return pipeline_->HasVideo();
[email protected]d43ed912009-02-03 04:52:53415}
416
[email protected]fc367af2009-08-14 23:06:35417bool WebMediaPlayerImpl::hasAudio() const {
[email protected]e82c0e352013-03-01 01:53:46418 DCHECK(main_loop_->BelongsToCurrentThread());
[email protected]fc367af2009-08-14 23:06:35419
[email protected]cee32342011-03-09 15:58:16420 return pipeline_->HasAudio();
[email protected]fc367af2009-08-14 23:06:35421}
422
[email protected]4e6be3f2009-05-07 02:24:44423WebKit::WebSize WebMediaPlayerImpl::naturalSize() const {
[email protected]e82c0e352013-03-01 01:53:46424 DCHECK(main_loop_->BelongsToCurrentThread());
[email protected]d43ed912009-02-03 04:52:53425
[email protected]2975fa532011-09-19 20:18:33426 gfx::Size size;
427 pipeline_->GetNaturalVideoSize(&size);
428 return WebKit::WebSize(size);
[email protected]d43ed912009-02-03 04:52:53429}
430
[email protected]4e6be3f2009-05-07 02:24:44431bool WebMediaPlayerImpl::paused() const {
[email protected]e82c0e352013-03-01 01:53:46432 DCHECK(main_loop_->BelongsToCurrentThread());
[email protected]d43ed912009-02-03 04:52:53433
[email protected]3b4cbbf2009-07-11 00:16:19434 return pipeline_->GetPlaybackRate() == 0.0f;
[email protected]d43ed912009-02-03 04:52:53435}
436
[email protected]4e6be3f2009-05-07 02:24:44437bool WebMediaPlayerImpl::seeking() const {
[email protected]e82c0e352013-03-01 01:53:46438 DCHECK(main_loop_->BelongsToCurrentThread());
[email protected]d43ed912009-02-03 04:52:53439
[email protected]ef405f66b2012-04-18 02:39:55440 if (ready_state_ == WebMediaPlayer::ReadyStateHaveNothing)
[email protected]0acebfa2009-08-21 22:45:40441 return false;
[email protected]67cd5052009-09-10 21:53:22442
[email protected]b3766a22010-12-22 17:34:13443 return seeking_;
[email protected]ec9212f2008-12-18 21:40:36444}
445
[email protected]39bdde32013-04-17 17:44:20446double WebMediaPlayerImpl::duration() const {
447 DCHECK(main_loop_->BelongsToCurrentThread());
448
449 if (ready_state_ == WebMediaPlayer::ReadyStateHaveNothing)
450 return std::numeric_limits<double>::quiet_NaN();
451
[email protected]39bdde32013-04-17 17:44:20452 return GetPipelineDuration();
[email protected]d43ed912009-02-03 04:52:53453}
454
[email protected]39bdde32013-04-17 17:44:20455double WebMediaPlayerImpl::currentTime() const {
[email protected]e82c0e352013-03-01 01:53:46456 DCHECK(main_loop_->BelongsToCurrentThread());
[email protected]39bdde32013-04-17 17:44:20457 return (paused_ ? paused_time_ : pipeline_->GetMediaTime()).InSecondsF();
[email protected]d43ed912009-02-03 04:52:53458}
459
[email protected]ef405f66b2012-04-18 02:39:55460WebMediaPlayer::NetworkState WebMediaPlayerImpl::networkState() const {
[email protected]e82c0e352013-03-01 01:53:46461 DCHECK(main_loop_->BelongsToCurrentThread());
[email protected]ddb1e5a2010-12-13 20:10:45462 return network_state_;
463}
464
[email protected]ef405f66b2012-04-18 02:39:55465WebMediaPlayer::ReadyState WebMediaPlayerImpl::readyState() const {
[email protected]e82c0e352013-03-01 01:53:46466 DCHECK(main_loop_->BelongsToCurrentThread());
[email protected]ddb1e5a2010-12-13 20:10:45467 return ready_state_;
468}
469
[email protected]f70f8e12010-05-25 21:30:39470const WebKit::WebTimeRanges& WebMediaPlayerImpl::buffered() {
[email protected]e82c0e352013-03-01 01:53:46471 DCHECK(main_loop_->BelongsToCurrentThread());
[email protected]c566cb792012-06-20 00:51:52472 WebKit::WebTimeRanges web_ranges(
473 ConvertToWebTimeRanges(pipeline_->GetBufferedTimeRanges()));
[email protected]49f7b772012-05-10 00:45:35474 buffered_.swap(web_ranges);
[email protected]f70f8e12010-05-25 21:30:39475 return buffered_;
476}
477
[email protected]39bdde32013-04-17 17:44:20478double WebMediaPlayerImpl::maxTimeSeekable() const {
479 DCHECK(main_loop_->BelongsToCurrentThread());
480
481 // If we haven't even gotten to ReadyStateHaveMetadata yet then just
482 // return 0 so that the seekable range is empty.
483 if (ready_state_ < WebMediaPlayer::ReadyStateHaveMetadata)
484 return 0.0;
485
486 // We don't support seeking in streaming media.
487 if (data_source_ && data_source_->IsStreaming())
488 return 0.0;
[email protected]62b5897c2013-01-30 22:53:35489 return duration();
[email protected]ec9212f2008-12-18 21:40:36490}
491
[email protected]7ed21be2012-05-30 08:09:15492bool WebMediaPlayerImpl::didLoadingProgress() const {
[email protected]e82c0e352013-03-01 01:53:46493 DCHECK(main_loop_->BelongsToCurrentThread());
[email protected]7ed21be2012-05-30 08:09:15494 return pipeline_->DidLoadingProgress();
[email protected]d43ed912009-02-03 04:52:53495}
496
[email protected]df143bdc2009-06-16 17:34:19497void WebMediaPlayerImpl::paint(WebCanvas* canvas,
[email protected]4dc43be2012-03-27 14:05:07498 const WebRect& rect,
[email protected]98f60ed2013-05-24 23:20:54499 unsigned char alpha) {
[email protected]e82c0e352013-03-01 01:53:46500 DCHECK(main_loop_->BelongsToCurrentThread());
[email protected]4e6be3f2009-05-07 02:24:44501
[email protected]eaf7d9a2012-05-19 06:14:33502 if (!accelerated_compositing_reported_) {
503 accelerated_compositing_reported_ = true;
[email protected]3dc8f1b2012-05-21 22:54:32504 // Normally paint() is only called in non-accelerated rendering, but there
505 // are exceptions such as webgl where compositing is used in the WebView but
506 // video frames are still rendered to a canvas.
507 UMA_HISTOGRAM_BOOLEAN(
508 "Media.AcceleratedCompositingActive",
509 frame_->view()->isAcceleratedCompositingActive());
[email protected]eaf7d9a2012-05-19 06:14:33510 }
511
[email protected]b49beeb2013-03-01 20:04:00512 // Avoid locking and potentially blocking the video rendering thread while
513 // painting in software.
514 scoped_refptr<media::VideoFrame> video_frame;
515 {
516 base::AutoLock auto_lock(lock_);
517 video_frame = current_frame_;
518 }
519 gfx::Rect gfx_rect(rect);
[email protected]ff875be52013-06-02 23:47:38520 skcanvas_video_renderer_.Paint(video_frame.get(), canvas, gfx_rect, alpha);
[email protected]ec9212f2008-12-18 21:40:36521}
[email protected]5df51652009-01-17 00:03:00522
[email protected]38259a7a82009-07-29 21:49:49523bool WebMediaPlayerImpl::hasSingleSecurityOrigin() const {
[email protected]b49beeb2013-03-01 20:04:00524 if (data_source_)
525 return data_source_->HasSingleOrigin();
[email protected]fcdb7462009-10-21 21:05:11526 return true;
[email protected]38259a7a82009-07-29 21:49:49527}
528
[email protected]3fe27112012-06-07 04:00:01529bool WebMediaPlayerImpl::didPassCORSAccessCheck() const {
[email protected]b49beeb2013-03-01 20:04:00530 if (data_source_)
531 return data_source_->DidPassCORSAccessCheck();
532 return false;
[email protected]3fe27112012-06-07 04:00:01533}
534
[email protected]39bdde32013-04-17 17:44:20535double WebMediaPlayerImpl::mediaTimeForTimeValue(double timeValue) const {
[email protected]e06e16d82011-05-26 22:13:33536 return ConvertSecondsToTimestamp(timeValue).InSecondsF();
537}
538
[email protected]d82b18ae2011-03-23 21:28:59539unsigned WebMediaPlayerImpl::decodedFrameCount() const {
[email protected]e82c0e352013-03-01 01:53:46540 DCHECK(main_loop_->BelongsToCurrentThread());
[email protected]4c51bc662011-02-16 02:03:16541
542 media::PipelineStatistics stats = pipeline_->GetStatistics();
543 return stats.video_frames_decoded;
544}
545
[email protected]d82b18ae2011-03-23 21:28:59546unsigned WebMediaPlayerImpl::droppedFrameCount() const {
[email protected]e82c0e352013-03-01 01:53:46547 DCHECK(main_loop_->BelongsToCurrentThread());
[email protected]4c51bc662011-02-16 02:03:16548
549 media::PipelineStatistics stats = pipeline_->GetStatistics();
550 return stats.video_frames_dropped;
551}
552
[email protected]d82b18ae2011-03-23 21:28:59553unsigned WebMediaPlayerImpl::audioDecodedByteCount() const {
[email protected]e82c0e352013-03-01 01:53:46554 DCHECK(main_loop_->BelongsToCurrentThread());
[email protected]4c51bc662011-02-16 02:03:16555
556 media::PipelineStatistics stats = pipeline_->GetStatistics();
557 return stats.audio_bytes_decoded;
558}
559
[email protected]d82b18ae2011-03-23 21:28:59560unsigned WebMediaPlayerImpl::videoDecodedByteCount() const {
[email protected]e82c0e352013-03-01 01:53:46561 DCHECK(main_loop_->BelongsToCurrentThread());
[email protected]4c51bc662011-02-16 02:03:16562
563 media::PipelineStatistics stats = pipeline_->GetStatistics();
564 return stats.video_bytes_decoded;
565}
566
[email protected]21c3f7502013-03-23 03:29:51567void WebMediaPlayerImpl::SetVideoFrameProviderClient(
568 cc::VideoFrameProvider::Client* client) {
569 // This is called from both the main renderer thread and the compositor
570 // thread (when the main thread is blocked).
571 if (video_frame_provider_client_)
572 video_frame_provider_client_->StopUsingProvider();
573 video_frame_provider_client_ = client;
574}
575
576scoped_refptr<media::VideoFrame> WebMediaPlayerImpl::GetCurrentFrame() {
577 base::AutoLock auto_lock(lock_);
578 return current_frame_;
579}
580
581void WebMediaPlayerImpl::PutCurrentFrame(
582 const scoped_refptr<media::VideoFrame>& frame) {
583 if (!accelerated_compositing_reported_) {
584 accelerated_compositing_reported_ = true;
585 DCHECK(frame_->view()->isAcceleratedCompositingActive());
586 UMA_HISTOGRAM_BOOLEAN("Media.AcceleratedCompositingActive", true);
587 }
588}
[email protected]e81283bb2010-08-31 18:01:21589
[email protected]6523b242013-03-13 11:10:07590bool WebMediaPlayerImpl::copyVideoTextureToPlatformTexture(
591 WebKit::WebGraphicsContext3D* web_graphics_context,
592 unsigned int texture,
593 unsigned int level,
594 unsigned int internal_format,
[email protected]9aa2b2782013-05-14 00:13:31595 unsigned int type,
[email protected]6523b242013-03-13 11:10:07596 bool premultiply_alpha,
597 bool flip_y) {
598 scoped_refptr<media::VideoFrame> video_frame;
599 {
600 base::AutoLock auto_lock(lock_);
601 video_frame = current_frame_;
602 }
[email protected]e56f88c72013-06-25 22:31:29603
604 if (!video_frame.get())
605 return false;
606 if (video_frame->format() != media::VideoFrame::NATIVE_TEXTURE)
607 return false;
608 if (video_frame->texture_target() != GL_TEXTURE_2D)
609 return false;
610
611 scoped_refptr<media::VideoFrame::MailboxHolder> mailbox_holder =
612 video_frame->texture_mailbox();
613
614 uint32 source_texture = web_graphics_context->createTexture();
615
616 web_graphics_context->waitSyncPoint(mailbox_holder->sync_point());
617 web_graphics_context->bindTexture(GL_TEXTURE_2D, source_texture);
618 web_graphics_context->consumeTextureCHROMIUM(GL_TEXTURE_2D,
619 mailbox_holder->mailbox().name);
620
621 // The video is stored in a unmultiplied format, so premultiply
622 // if necessary.
623 web_graphics_context->pixelStorei(GL_UNPACK_PREMULTIPLY_ALPHA_CHROMIUM,
624 premultiply_alpha);
625 // Application itself needs to take care of setting the right flip_y
626 // value down to get the expected result.
627 // flip_y==true means to reverse the video orientation while
628 // flip_y==false means to keep the intrinsic orientation.
629 web_graphics_context->pixelStorei(GL_UNPACK_FLIP_Y_CHROMIUM, flip_y);
630 web_graphics_context->copyTextureCHROMIUM(GL_TEXTURE_2D,
631 source_texture,
632 texture,
633 level,
634 internal_format,
635 type);
636 web_graphics_context->pixelStorei(GL_UNPACK_FLIP_Y_CHROMIUM, false);
637 web_graphics_context->pixelStorei(GL_UNPACK_PREMULTIPLY_ALPHA_CHROMIUM,
638 false);
639
640 web_graphics_context->deleteTexture(source_texture);
641
642 // The flush() operation is not necessary here. It is kept since the
643 // performance will be better when it is added than not.
644 web_graphics_context->flush();
645 return true;
[email protected]6523b242013-03-13 11:10:07646}
647
[email protected]49a097e2013-04-02 19:31:51648// Helper functions to report media EME related stats to UMA. They follow the
649// convention of more commonly used macros UMA_HISTOGRAM_ENUMERATION and
650// UMA_HISTOGRAM_COUNTS. The reason that we cannot use those macros directly is
651// that UMA_* macros require the names to be constant throughout the process'
652// lifetime.
[email protected]f3a1d40d2013-06-25 22:12:50653static void EmeUMAHistogramEnumeration(const WebKit::WebString& key_system,
[email protected]49a097e2013-04-02 19:31:51654 const std::string& method,
655 int sample,
656 int boundary_value) {
657 base::LinearHistogram::FactoryGet(
658 kMediaEme + KeySystemNameForUMA(key_system) + "." + method,
659 1, boundary_value, boundary_value + 1,
660 base::Histogram::kUmaTargetedHistogramFlag)->Add(sample);
661}
662
[email protected]f3a1d40d2013-06-25 22:12:50663static void EmeUMAHistogramCounts(const WebKit::WebString& key_system,
[email protected]49a097e2013-04-02 19:31:51664 const std::string& method,
665 int sample) {
666 // Use the same parameters as UMA_HISTOGRAM_COUNTS.
667 base::Histogram::FactoryGet(
668 kMediaEme + KeySystemNameForUMA(key_system) + "." + method,
669 1, 1000000, 50, base::Histogram::kUmaTargetedHistogramFlag)->Add(sample);
670}
671
[email protected]2ca7d5c2012-10-23 07:30:54672// Helper enum for reporting generateKeyRequest/addKey histograms.
673enum MediaKeyException {
674 kUnknownResultId,
675 kSuccess,
676 kKeySystemNotSupported,
677 kInvalidPlayerState,
678 kMaxMediaKeyException
679};
680
681static MediaKeyException MediaKeyExceptionForUMA(
682 WebMediaPlayer::MediaKeyException e) {
683 switch (e) {
684 case WebMediaPlayer::MediaKeyExceptionKeySystemNotSupported:
685 return kKeySystemNotSupported;
686 case WebMediaPlayer::MediaKeyExceptionInvalidPlayerState:
687 return kInvalidPlayerState;
688 case WebMediaPlayer::MediaKeyExceptionNoError:
689 return kSuccess;
690 default:
691 return kUnknownResultId;
692 }
693}
694
695// Helper for converting |key_system| name and exception |e| to a pair of enum
696// values from above, for reporting to UMA.
697static void ReportMediaKeyExceptionToUMA(
698 const std::string& method,
699 const WebString& key_system,
700 WebMediaPlayer::MediaKeyException e) {
701 MediaKeyException result_id = MediaKeyExceptionForUMA(e);
702 DCHECK_NE(result_id, kUnknownResultId) << e;
[email protected]49a097e2013-04-02 19:31:51703 EmeUMAHistogramEnumeration(
[email protected]f3a1d40d2013-06-25 22:12:50704 key_system, method, result_id, kMaxMediaKeyException);
[email protected]2ca7d5c2012-10-23 07:30:54705}
706
707WebMediaPlayer::MediaKeyException
[email protected]f7a6b992012-04-19 09:45:56708WebMediaPlayerImpl::generateKeyRequest(const WebString& key_system,
709 const unsigned char* init_data,
710 unsigned init_data_length) {
[email protected]2ca7d5c2012-10-23 07:30:54711 WebMediaPlayer::MediaKeyException e =
712 GenerateKeyRequestInternal(key_system, init_data, init_data_length);
713 ReportMediaKeyExceptionToUMA("generateKeyRequest", key_system, e);
714 return e;
715}
716
717WebMediaPlayer::MediaKeyException
718WebMediaPlayerImpl::GenerateKeyRequestInternal(
719 const WebString& key_system,
720 const unsigned char* init_data,
721 unsigned init_data_length) {
[email protected]f7a6b992012-04-19 09:45:56722 DVLOG(1) << "generateKeyRequest: " << key_system.utf8().data() << ": "
723 << std::string(reinterpret_cast<const char*>(init_data),
[email protected]cbdc8c2b2012-06-16 01:27:36724 static_cast<size_t>(init_data_length));
[email protected]f7a6b992012-04-19 09:45:56725
[email protected]fecb5fe2013-06-19 00:52:13726 if (!IsSupportedKeySystem(key_system))
727 return WebMediaPlayer::MediaKeyExceptionKeySystemNotSupported;
728
729 // We do not support run-time switching between key systems for now.
730 if (current_key_system_.isEmpty()) {
731 if (!decryptor_->InitializeCDM(key_system.utf8()))
732 return WebMediaPlayer::MediaKeyExceptionKeySystemNotSupported;
733 current_key_system_ = key_system;
734 }
735 else if (key_system != current_key_system_) {
736 return WebMediaPlayer::MediaKeyExceptionInvalidPlayerState;
737 }
738
[email protected]c8d40282012-10-27 07:23:13739 // TODO(xhwang): We assume all streams are from the same container (thus have
740 // the same "type") for now. In the future, the "type" should be passed down
741 // from the application.
[email protected]fecb5fe2013-06-19 00:52:13742 if (!decryptor_->GenerateKeyRequest(init_data_type_,
[email protected]83fdd992012-12-21 19:57:49743 init_data, init_data_length)) {
[email protected]6a206732012-08-29 01:14:40744 current_key_system_.reset();
[email protected]2ca7d5c2012-10-23 07:30:54745 return WebMediaPlayer::MediaKeyExceptionKeySystemNotSupported;
[email protected]6a206732012-08-29 01:14:40746 }
747
[email protected]2ca7d5c2012-10-23 07:30:54748 return WebMediaPlayer::MediaKeyExceptionNoError;
[email protected]f7a6b992012-04-19 09:45:56749}
750
[email protected]2ca7d5c2012-10-23 07:30:54751WebMediaPlayer::MediaKeyException WebMediaPlayerImpl::addKey(
752 const WebString& key_system,
753 const unsigned char* key,
754 unsigned key_length,
755 const unsigned char* init_data,
756 unsigned init_data_length,
757 const WebString& session_id) {
758 WebMediaPlayer::MediaKeyException e = AddKeyInternal(
759 key_system, key, key_length, init_data, init_data_length, session_id);
760 ReportMediaKeyExceptionToUMA("addKey", key_system, e);
761 return e;
762}
763
[email protected]2ca7d5c2012-10-23 07:30:54764WebMediaPlayer::MediaKeyException WebMediaPlayerImpl::AddKeyInternal(
[email protected]f7a6b992012-04-19 09:45:56765 const WebString& key_system,
766 const unsigned char* key,
767 unsigned key_length,
768 const unsigned char* init_data,
769 unsigned init_data_length,
770 const WebString& session_id) {
[email protected]a0149082012-04-19 17:33:41771 DCHECK(key);
772 DCHECK_GT(key_length, 0u);
[email protected]f7a6b992012-04-19 09:45:56773 DVLOG(1) << "addKey: " << key_system.utf8().data() << ": "
774 << std::string(reinterpret_cast<const char*>(key),
775 static_cast<size_t>(key_length)) << ", "
776 << std::string(reinterpret_cast<const char*>(init_data),
777 static_cast<size_t>(init_data_length))
778 << " [" << session_id.utf8().data() << "]";
779
[email protected]fecb5fe2013-06-19 00:52:13780
781 if (!IsSupportedKeySystem(key_system))
782 return WebMediaPlayer::MediaKeyExceptionKeySystemNotSupported;
783
784 if (current_key_system_.isEmpty() || key_system != current_key_system_)
785 return WebMediaPlayer::MediaKeyExceptionInvalidPlayerState;
786
787 decryptor_->AddKey(key, key_length,
[email protected]83fdd992012-12-21 19:57:49788 init_data, init_data_length, session_id.utf8());
[email protected]2ca7d5c2012-10-23 07:30:54789 return WebMediaPlayer::MediaKeyExceptionNoError;
[email protected]f7a6b992012-04-19 09:45:56790}
791
[email protected]2ca7d5c2012-10-23 07:30:54792WebMediaPlayer::MediaKeyException WebMediaPlayerImpl::cancelKeyRequest(
793 const WebString& key_system,
794 const WebString& session_id) {
795 WebMediaPlayer::MediaKeyException e =
796 CancelKeyRequestInternal(key_system, session_id);
797 ReportMediaKeyExceptionToUMA("cancelKeyRequest", key_system, e);
798 return e;
799}
800
801WebMediaPlayer::MediaKeyException
802WebMediaPlayerImpl::CancelKeyRequestInternal(
[email protected]f7a6b992012-04-19 09:45:56803 const WebString& key_system,
804 const WebString& session_id) {
805 if (!IsSupportedKeySystem(key_system))
[email protected]2ca7d5c2012-10-23 07:30:54806 return WebMediaPlayer::MediaKeyExceptionKeySystemNotSupported;
[email protected]f7a6b992012-04-19 09:45:56807
[email protected]a8884632012-06-29 03:05:34808 if (current_key_system_.isEmpty() || key_system != current_key_system_)
[email protected]2ca7d5c2012-10-23 07:30:54809 return WebMediaPlayer::MediaKeyExceptionInvalidPlayerState;
[email protected]a8884632012-06-29 03:05:34810
[email protected]fecb5fe2013-06-19 00:52:13811 decryptor_->CancelKeyRequest(session_id.utf8());
[email protected]2ca7d5c2012-10-23 07:30:54812 return WebMediaPlayer::MediaKeyExceptionNoError;
[email protected]f7a6b992012-04-19 09:45:56813}
814
[email protected]4e6be3f2009-05-07 02:24:44815void WebMediaPlayerImpl::WillDestroyCurrentMessageLoop() {
[email protected]8931c41a2009-07-07 17:31:49816 Destroy();
[email protected]8931c41a2009-07-07 17:31:49817}
818
819void WebMediaPlayerImpl::Repaint() {
[email protected]e82c0e352013-03-01 01:53:46820 DCHECK(main_loop_->BelongsToCurrentThread());
[email protected]b49beeb2013-03-01 20:04:00821
[email protected]29037ce52013-05-06 22:44:16822 bool size_changed = false;
823 {
824 base::AutoLock auto_lock(lock_);
825 std::swap(pending_size_change_, size_changed);
826 pending_repaint_ = false;
827 }
828
829 if (size_changed)
830 GetClient()->sizeChanged();
831
832 GetClient()->repaint();
[email protected]8931c41a2009-07-07 17:31:49833}
834
[email protected]a9590c22011-03-16 16:57:02835void WebMediaPlayerImpl::OnPipelineSeek(PipelineStatus status) {
[email protected]e82c0e352013-03-01 01:53:46836 DCHECK(main_loop_->BelongsToCurrentThread());
[email protected]a8e2cb82012-08-17 00:02:39837 starting_ = false;
[email protected]5d11eff2011-09-15 00:06:06838 seeking_ = false;
839 if (pending_seek_) {
840 pending_seek_ = false;
841 seek(pending_seek_seconds_);
842 return;
843 }
844
[email protected]10a64d92012-04-10 21:08:02845 if (status != media::PIPELINE_OK) {
846 OnPipelineError(status);
847 return;
[email protected]96706912009-07-15 17:18:05848 }
[email protected]10a64d92012-04-10 21:08:02849
850 // Update our paused time.
851 if (paused_)
[email protected]f7c0ada02012-07-23 08:42:50852 paused_time_ = pipeline_->GetMediaTime();
[email protected]10a64d92012-04-10 21:08:02853
854 GetClient()->timeChanged();
[email protected]8931c41a2009-07-07 17:31:49855}
856
[email protected]6954fe12013-01-03 03:22:32857void WebMediaPlayerImpl::OnPipelineEnded() {
[email protected]e82c0e352013-03-01 01:53:46858 DCHECK(main_loop_->BelongsToCurrentThread());
[email protected]10a64d92012-04-10 21:08:02859 GetClient()->timeChanged();
[email protected]576537842009-08-12 23:52:05860}
861
[email protected]a9590c22011-03-16 16:57:02862void WebMediaPlayerImpl::OnPipelineError(PipelineStatus error) {
[email protected]e82c0e352013-03-01 01:53:46863 DCHECK(main_loop_->BelongsToCurrentThread());
[email protected]be57ee52013-05-28 22:27:27864 DCHECK_NE(error, media::PIPELINE_OK);
[email protected]a8e2cb82012-08-17 00:02:39865
866 if (ready_state_ == WebMediaPlayer::ReadyStateHaveNothing) {
867 // Any error that occurs before reaching ReadyStateHaveMetadata should
868 // be considered a format error.
869 SetNetworkState(WebMediaPlayer::NetworkStateFormatError);
870 Repaint();
871 return;
872 }
873
[email protected]be57ee52013-05-28 22:27:27874 SetNetworkState(PipelineErrorToNetworkState(error));
[email protected]a9590c22011-03-16 16:57:02875
[email protected]be57ee52013-05-28 22:27:27876 if (error == media::PIPELINE_ERROR_DECRYPT)
[email protected]f3a1d40d2013-06-25 22:12:50877 EmeUMAHistogramCounts(current_key_system_, "DecryptError", 1);
[email protected]bb2c1f32009-08-14 04:14:50878
879 // Repaint to trigger UI update.
880 Repaint();
[email protected]db190487d2009-07-30 18:51:52881}
882
[email protected]a8e2cb82012-08-17 00:02:39883void WebMediaPlayerImpl::OnPipelineBufferingState(
884 media::Pipeline::BufferingState buffering_state) {
885 DVLOG(1) << "OnPipelineBufferingState(" << buffering_state << ")";
886
887 switch (buffering_state) {
888 case media::Pipeline::kHaveMetadata:
889 SetReadyState(WebMediaPlayer::ReadyStateHaveMetadata);
[email protected]21c3f7502013-03-23 03:29:51890
[email protected]21c3f7502013-03-23 03:29:51891 if (hasVideo() && GetClient()->needsWebLayerForVideo()) {
892 DCHECK(!video_weblayer_);
893 video_weblayer_.reset(
894 new webkit::WebLayerImpl(cc::VideoLayer::Create(this)));
895 GetClient()->setWebLayer(video_weblayer_.get());
896 }
[email protected]a8e2cb82012-08-17 00:02:39897 break;
898 case media::Pipeline::kPrerollCompleted:
[email protected]a06d9e972013-06-20 08:43:47899 // Only transition to ReadyStateHaveEnoughData if we don't have
900 // any pending seeks because the transition can cause Blink to
901 // report that the most recent seek has completed.
902 if (!pending_seek_)
903 SetReadyState(WebMediaPlayer::ReadyStateHaveEnoughData);
[email protected]a8e2cb82012-08-17 00:02:39904 break;
905 }
906
907 // Repaint to trigger UI update.
908 Repaint();
909}
910
[email protected]ef8394c2013-08-21 20:26:30911void WebMediaPlayerImpl::OnDemuxerOpened() {
[email protected]e82c0e352013-03-01 01:53:46912 DCHECK(main_loop_->BelongsToCurrentThread());
[email protected]ef8394c2013-08-21 20:26:30913 GetClient()->mediaSourceOpened(new WebMediaSourceImpl(
[email protected]5f811a2d2013-03-15 23:54:51914 chunk_demuxer_, base::Bind(&LogMediaSourceError, media_log_)));
[email protected]81bb3322011-07-21 15:55:50915}
916
[email protected]fecb5fe2013-06-19 00:52:13917void WebMediaPlayerImpl::OnKeyAdded(const std::string& session_id) {
[email protected]e82c0e352013-03-01 01:53:46918 DCHECK(main_loop_->BelongsToCurrentThread());
[email protected]f3a1d40d2013-06-25 22:12:50919 EmeUMAHistogramCounts(current_key_system_, "KeyAdded", 1);
[email protected]fecb5fe2013-06-19 00:52:13920 GetClient()->keyAdded(current_key_system_,
[email protected]cbdc8c2b2012-06-16 01:27:36921 WebString::fromUTF8(session_id));
922}
923
[email protected]fecb5fe2013-06-19 00:52:13924void WebMediaPlayerImpl::OnNeedKey(const std::string& session_id,
[email protected]c8d40282012-10-27 07:23:13925 const std::string& type,
[email protected]9ec0f9c2013-04-07 16:10:47926 scoped_ptr<uint8[]> init_data,
[email protected]cbdc8c2b2012-06-16 01:27:36927 int init_data_size) {
[email protected]e82c0e352013-03-01 01:53:46928 DCHECK(main_loop_->BelongsToCurrentThread());
[email protected]cbdc8c2b2012-06-16 01:27:36929
[email protected]47ebb0e2012-11-30 08:28:29930 // Do not fire NeedKey event if encrypted media is not enabled.
931 if (!decryptor_)
932 return;
933
[email protected]2ca7d5c2012-10-23 07:30:54934 UMA_HISTOGRAM_COUNTS(kMediaEme + std::string("NeedKey"), 1);
935
[email protected]c8d40282012-10-27 07:23:13936 DCHECK(init_data_type_.empty() || type.empty() || type == init_data_type_);
937 if (init_data_type_.empty())
938 init_data_type_ = type;
939
[email protected]fecb5fe2013-06-19 00:52:13940 GetClient()->keyNeeded(WebString(),
[email protected]cbdc8c2b2012-06-16 01:27:36941 WebString::fromUTF8(session_id),
942 init_data.get(),
943 init_data_size);
944}
945
[email protected]71537722013-05-23 06:47:53946scoped_ptr<media::TextTrack>
947WebMediaPlayerImpl::OnTextTrack(media::TextKind kind,
948 const std::string& label,
949 const std::string& language) {
950 typedef WebInbandTextTrackImpl::Kind webkind_t;
951 const webkind_t webkind = static_cast<webkind_t>(kind);
952 const WebKit::WebString weblabel = WebKit::WebString::fromUTF8(label);
953 const WebKit::WebString weblanguage = WebKit::WebString::fromUTF8(language);
954
955 WebInbandTextTrackImpl* const text_track =
956 new WebInbandTextTrackImpl(webkind, weblabel, weblanguage,
957 text_track_index_++);
[email protected]71537722013-05-23 06:47:53958
[email protected]2fb8aa2dd2013-07-08 21:23:35959 return scoped_ptr<media::TextTrack>(new TextTrackImpl(GetClient(),
960 text_track));
[email protected]71537722013-05-23 06:47:53961}
962
[email protected]fecb5fe2013-06-19 00:52:13963void WebMediaPlayerImpl::OnKeyError(const std::string& session_id,
[email protected]15b05a72013-05-30 00:40:57964 media::MediaKeys::KeyError error_code,
[email protected]cbdc8c2b2012-06-16 01:27:36965 int system_code) {
[email protected]e82c0e352013-03-01 01:53:46966 DCHECK(main_loop_->BelongsToCurrentThread());
[email protected]cbdc8c2b2012-06-16 01:27:36967
[email protected]f3a1d40d2013-06-25 22:12:50968 EmeUMAHistogramEnumeration(current_key_system_, "KeyError",
[email protected]fecb5fe2013-06-19 00:52:13969 error_code, media::MediaKeys::kMaxKeyError);
[email protected]2ca7d5c2012-10-23 07:30:54970
[email protected]cbdc8c2b2012-06-16 01:27:36971 GetClient()->keyError(
[email protected]fecb5fe2013-06-19 00:52:13972 current_key_system_,
[email protected]cbdc8c2b2012-06-16 01:27:36973 WebString::fromUTF8(session_id),
974 static_cast<WebKit::WebMediaPlayerClient::MediaKeyErrorCode>(error_code),
975 system_code);
976}
977
[email protected]fecb5fe2013-06-19 00:52:13978void WebMediaPlayerImpl::OnKeyMessage(const std::string& session_id,
[email protected]0a81bdb2013-06-29 23:18:06979 const std::vector<uint8>& message,
[email protected]abd36b3af2012-12-22 03:42:02980 const std::string& default_url) {
[email protected]e82c0e352013-03-01 01:53:46981 DCHECK(main_loop_->BelongsToCurrentThread());
[email protected]cbdc8c2b2012-06-16 01:27:36982
[email protected]abd36b3af2012-12-22 03:42:02983 const GURL default_url_gurl(default_url);
984 DLOG_IF(WARNING, !default_url.empty() && !default_url_gurl.is_valid())
985 << "Invalid URL in default_url: " << default_url;
986
[email protected]fecb5fe2013-06-19 00:52:13987 GetClient()->keyMessage(current_key_system_,
[email protected]cbdc8c2b2012-06-16 01:27:36988 WebString::fromUTF8(session_id),
[email protected]33325ff2013-07-01 07:49:36989 message.empty() ? NULL : &message[0],
[email protected]65a8c102012-12-15 00:56:57990 message.size(),
[email protected]abd36b3af2012-12-22 03:42:02991 default_url_gurl);
[email protected]4205f0aab2012-04-26 04:33:06992}
993
[email protected]5bb69ef2011-12-23 16:29:09994void WebMediaPlayerImpl::SetOpaque(bool opaque) {
[email protected]e82c0e352013-03-01 01:53:46995 DCHECK(main_loop_->BelongsToCurrentThread());
[email protected]5bb69ef2011-12-23 16:29:09996
997 GetClient()->setOpaque(opaque);
998}
999
[email protected]d250190da3b2012-07-23 22:57:301000void WebMediaPlayerImpl::DataSourceInitialized(const GURL& gurl, bool success) {
[email protected]e82c0e352013-03-01 01:53:461001 DCHECK(main_loop_->BelongsToCurrentThread());
[email protected]a9415292012-01-19 19:55:201002
[email protected]d250190da3b2012-07-23 22:57:301003 if (!success) {
[email protected]ef405f66b2012-04-18 02:39:551004 SetNetworkState(WebMediaPlayer::NetworkStateFormatError);
[email protected]a9415292012-01-19 19:55:201005 Repaint();
1006 return;
1007 }
1008
[email protected]ef8394c2013-08-21 20:26:301009 StartPipeline();
[email protected]a9415292012-01-19 19:55:201010}
1011
[email protected]122f40252012-06-12 05:01:561012void WebMediaPlayerImpl::NotifyDownloading(bool is_downloading) {
1013 if (!is_downloading && network_state_ == WebMediaPlayer::NetworkStateLoading)
1014 SetNetworkState(WebMediaPlayer::NetworkStateIdle);
1015 else if (is_downloading && network_state_ == WebMediaPlayer::NetworkStateIdle)
1016 SetNetworkState(WebMediaPlayer::NetworkStateLoading);
1017 media_log_->AddEvent(
1018 media_log_->CreateBooleanEvent(
1019 media::MediaLogEvent::NETWORK_ACTIVITY_SET,
1020 "is_downloading_data", is_downloading));
1021}
1022
[email protected]ef8394c2013-08-21 20:26:301023void WebMediaPlayerImpl::StartPipeline() {
[email protected]ddbc6ff2013-04-19 15:28:331024 const CommandLine* cmd_line = CommandLine::ForCurrentProcess();
[email protected]b573f952013-06-04 10:50:091025 bool increase_preroll_on_underflow = true;
[email protected]ddbc6ff2013-04-19 15:28:331026
[email protected]0814ac62013-06-07 21:01:291027 // Keep track if this is a MSE or non-MSE playback.
[email protected]ef8394c2013-08-21 20:26:301028 UMA_HISTOGRAM_BOOLEAN("Media.MSE.Playback",
1029 (load_type_ == LoadTypeMediaSource));
[email protected]0814ac62013-06-07 21:01:291030
[email protected]ddbc6ff2013-04-19 15:28:331031 // Figure out which demuxer to use.
[email protected]ef8394c2013-08-21 20:26:301032 if (load_type_ != LoadTypeMediaSource) {
[email protected]ddbc6ff2013-04-19 15:28:331033 DCHECK(!chunk_demuxer_);
[email protected]f5443ef72013-04-22 04:03:381034 DCHECK(data_source_);
1035
1036 demuxer_.reset(new media::FFmpegDemuxer(
[email protected]c1330c82013-06-06 02:23:251037 media_loop_, data_source_.get(),
[email protected]1e931f62013-07-31 23:25:521038 BIND_TO_RENDER_LOOP_1(&WebMediaPlayerImpl::OnNeedKey, ""),
1039 media_log_));
[email protected]ddbc6ff2013-04-19 15:28:331040 } else {
[email protected]f5443ef72013-04-22 04:03:381041 DCHECK(!chunk_demuxer_);
1042 DCHECK(!data_source_);
1043
[email protected]7afb1bb32013-06-29 14:27:101044 media::AddTextTrackCB add_text_track_cb;
1045
1046 if (cmd_line->HasSwitch(switches::kEnableInbandTextTracks)) {
1047 add_text_track_cb =
1048 base::Bind(&WebMediaPlayerImpl::OnTextTrack, base::Unretained(this));
1049 }
1050
[email protected]f5443ef72013-04-22 04:03:381051 chunk_demuxer_ = new media::ChunkDemuxer(
[email protected]ef8394c2013-08-21 20:26:301052 BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnDemuxerOpened),
[email protected]fecb5fe2013-06-19 00:52:131053 BIND_TO_RENDER_LOOP_1(&WebMediaPlayerImpl::OnNeedKey, ""),
[email protected]7afb1bb32013-06-29 14:27:101054 add_text_track_cb,
[email protected]f5443ef72013-04-22 04:03:381055 base::Bind(&LogMediaSourceError, media_log_));
1056 demuxer_.reset(chunk_demuxer_);
[email protected]ddbc6ff2013-04-19 15:28:331057
[email protected]6314f1b2013-08-12 11:14:011058#if !defined(OS_CHROMEOS)
1059 // Disable GpuVideoDecoder creation on platforms other than CrOS until
[email protected]67908292013-08-03 12:17:151060 // they support codec config changes.
[email protected]ddbc6ff2013-04-19 15:28:331061 // TODO(acolwell): Remove this once http://crbug.com/151045 is fixed.
1062 gpu_factories_ = NULL;
[email protected]67908292013-08-03 12:17:151063#endif
[email protected]b573f952013-06-04 10:50:091064
1065 // Disable preroll increases on underflow since the web application has no
1066 // way to detect that this is happening and runs the risk of triggering
1067 // unwanted garbage collection if it is to aggressive about appending data.
1068 // TODO(acolwell): Remove this once http://crbug.com/144683 is fixed.
1069 increase_preroll_on_underflow = false;
[email protected]ddbc6ff2013-04-19 15:28:331070 }
1071
[email protected]f5443ef72013-04-22 04:03:381072 scoped_ptr<media::FilterCollection> filter_collection(
1073 new media::FilterCollection());
1074 filter_collection->SetDemuxer(demuxer_.get());
1075
[email protected]ddbc6ff2013-04-19 15:28:331076 // Figure out if EME is enabled.
1077 media::SetDecryptorReadyCB set_decryptor_ready_cb;
1078 if (decryptor_) {
1079 set_decryptor_ready_cb = base::Bind(&ProxyDecryptor::SetDecryptorReadyCB,
1080 base::Unretained(decryptor_.get()));
1081 }
1082
1083 // Create our audio decoders and renderer.
1084 ScopedVector<media::AudioDecoder> audio_decoders;
[email protected]c1330c82013-06-06 02:23:251085 audio_decoders.push_back(new media::FFmpegAudioDecoder(media_loop_));
[email protected]ddbc6ff2013-04-19 15:28:331086 if (cmd_line->HasSwitch(switches::kEnableOpusPlayback)) {
[email protected]c1330c82013-06-06 02:23:251087 audio_decoders.push_back(new media::OpusAudioDecoder(media_loop_));
[email protected]ddbc6ff2013-04-19 15:28:331088 }
1089
1090 scoped_ptr<media::AudioRenderer> audio_renderer(
[email protected]c1330c82013-06-06 02:23:251091 new media::AudioRendererImpl(media_loop_,
[email protected]ff875be52013-06-02 23:47:381092 audio_source_provider_.get(),
[email protected]ddbc6ff2013-04-19 15:28:331093 audio_decoders.Pass(),
[email protected]b573f952013-06-04 10:50:091094 set_decryptor_ready_cb,
1095 increase_preroll_on_underflow));
[email protected]ddbc6ff2013-04-19 15:28:331096 filter_collection->SetAudioRenderer(audio_renderer.Pass());
1097
1098 // Create our video decoders and renderer.
1099 ScopedVector<media::VideoDecoder> video_decoders;
1100
[email protected]96cb47d02013-08-16 07:34:521101 if (gpu_factories_.get()) {
1102 video_decoders.push_back(
1103 new media::GpuVideoDecoder(gpu_factories_, media_log_));
1104 }
[email protected]ddbc6ff2013-04-19 15:28:331105
[email protected]ddbc6ff2013-04-19 15:28:331106 // TODO(phajdan.jr): Remove ifdefs when libvpx with vp9 support is released
1107 // (http://crbug.com/174287) .
1108#if !defined(MEDIA_DISABLE_LIBVPX)
[email protected]b150b5532013-06-15 00:50:541109 video_decoders.push_back(new media::VpxVideoDecoder(media_loop_));
[email protected]ddbc6ff2013-04-19 15:28:331110#endif // !defined(MEDIA_DISABLE_LIBVPX)
1111
[email protected]c1330c82013-06-06 02:23:251112 video_decoders.push_back(new media::FFmpegVideoDecoder(media_loop_));
[email protected]6ac955b2013-04-19 23:43:321113
[email protected]ddbc6ff2013-04-19 15:28:331114 scoped_ptr<media::VideoRenderer> video_renderer(
1115 new media::VideoRendererBase(
[email protected]c1330c82013-06-06 02:23:251116 media_loop_,
[email protected]ddbc6ff2013-04-19 15:28:331117 video_decoders.Pass(),
1118 set_decryptor_ready_cb,
1119 base::Bind(&WebMediaPlayerImpl::FrameReady, base::Unretained(this)),
1120 BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::SetOpaque),
1121 true));
1122 filter_collection->SetVideoRenderer(video_renderer.Pass());
1123
[email protected]f5443ef72013-04-22 04:03:381124 // ... and we're ready to go!
1125 starting_ = true;
1126 pipeline_->Start(
1127 filter_collection.Pass(),
1128 BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnPipelineEnded),
1129 BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnPipelineError),
1130 BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnPipelineSeek),
1131 BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnPipelineBufferingState),
1132 BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnDurationChange));
1133}
1134
1135void WebMediaPlayerImpl::SetNetworkState(WebMediaPlayer::NetworkState state) {
1136 DCHECK(main_loop_->BelongsToCurrentThread());
1137 DVLOG(1) << "SetNetworkState: " << state;
1138 network_state_ = state;
1139 // Always notify to ensure client has the latest value.
1140 GetClient()->networkStateChanged();
1141}
1142
1143void WebMediaPlayerImpl::SetReadyState(WebMediaPlayer::ReadyState state) {
1144 DCHECK(main_loop_->BelongsToCurrentThread());
1145 DVLOG(1) << "SetReadyState: " << state;
1146
1147 if (state == WebMediaPlayer::ReadyStateHaveEnoughData &&
1148 is_local_source_ &&
1149 network_state_ == WebMediaPlayer::NetworkStateLoading)
1150 SetNetworkState(WebMediaPlayer::NetworkStateLoaded);
1151
1152 ready_state_ = state;
1153 // Always notify to ensure client has the latest value.
1154 GetClient()->readyStateChanged();
1155}
1156
1157void WebMediaPlayerImpl::Destroy() {
1158 DCHECK(main_loop_->BelongsToCurrentThread());
1159
1160 // Abort any pending IO so stopping the pipeline doesn't get blocked.
1161 if (data_source_)
1162 data_source_->Abort();
1163 if (chunk_demuxer_) {
1164 chunk_demuxer_->Shutdown();
1165 chunk_demuxer_ = NULL;
1166 }
1167
[email protected]ff875be52013-06-02 23:47:381168 if (gpu_factories_.get()) {
[email protected]f5443ef72013-04-22 04:03:381169 gpu_factories_->Abort();
1170 gpu_factories_ = NULL;
1171 }
1172
1173 // Make sure to kill the pipeline so there's no more media threads running.
1174 // Note: stopping the pipeline might block for a long time.
1175 base::WaitableEvent waiter(false, false);
1176 pipeline_->Stop(base::Bind(
1177 &base::WaitableEvent::Signal, base::Unretained(&waiter)));
1178 waiter.Wait();
1179
1180 // Let V8 know we are not using extra resources anymore.
1181 if (incremented_externally_allocated_memory_) {
1182 v8::V8::AdjustAmountOfExternalAllocatedMemory(-kPlayerExtraMemory);
1183 incremented_externally_allocated_memory_ = false;
1184 }
1185
[email protected]f5443ef72013-04-22 04:03:381186 // Release any final references now that everything has stopped.
[email protected]a3702c52013-05-09 05:40:301187 pipeline_.reset();
[email protected]f5443ef72013-04-22 04:03:381188 demuxer_.reset();
[email protected]cccbd0f62013-04-26 18:39:591189 data_source_.reset();
[email protected]f5443ef72013-04-22 04:03:381190}
1191
1192WebKit::WebMediaPlayerClient* WebMediaPlayerImpl::GetClient() {
1193 DCHECK(main_loop_->BelongsToCurrentThread());
1194 DCHECK(client_);
1195 return client_;
1196}
1197
1198WebKit::WebAudioSourceProvider* WebMediaPlayerImpl::audioSourceProvider() {
[email protected]ff875be52013-06-02 23:47:381199 return audio_source_provider_.get();
[email protected]f5443ef72013-04-22 04:03:381200}
1201
1202void WebMediaPlayerImpl::IncrementExternallyAllocatedMemory() {
1203 DCHECK(main_loop_->BelongsToCurrentThread());
1204 incremented_externally_allocated_memory_ = true;
1205 v8::V8::AdjustAmountOfExternalAllocatedMemory(kPlayerExtraMemory);
1206}
1207
1208double WebMediaPlayerImpl::GetPipelineDuration() const {
1209 base::TimeDelta duration = pipeline_->GetMediaDuration();
1210
1211 // Return positive infinity if the resource is unbounded.
1212 // http://www.whatwg.org/specs/web-apps/current-work/multipage/video.html#dom-media-duration
1213 if (duration == media::kInfiniteDuration())
1214 return std::numeric_limits<double>::infinity();
1215
1216 return duration.InSecondsF();
1217}
1218
1219void WebMediaPlayerImpl::OnDurationChange() {
1220 if (ready_state_ == WebMediaPlayer::ReadyStateHaveNothing)
1221 return;
1222
1223 GetClient()->durationChanged();
1224}
1225
1226void WebMediaPlayerImpl::FrameReady(
1227 const scoped_refptr<media::VideoFrame>& frame) {
1228 base::AutoLock auto_lock(lock_);
[email protected]29037ce52013-05-06 22:44:161229
[email protected]ff875be52013-06-02 23:47:381230 if (current_frame_.get() &&
[email protected]29037ce52013-05-06 22:44:161231 current_frame_->natural_size() != frame->natural_size() &&
1232 !pending_size_change_) {
1233 pending_size_change_ = true;
1234 }
1235
[email protected]f5443ef72013-04-22 04:03:381236 current_frame_ = frame;
1237
1238 if (pending_repaint_)
1239 return;
1240
1241 pending_repaint_ = true;
1242 main_loop_->PostTask(FROM_HERE, base::Bind(
1243 &WebMediaPlayerImpl::Repaint, AsWeakPtr()));
[email protected]ddbc6ff2013-04-19 15:28:331244}
1245
[email protected]5e35a8d2013-07-10 19:37:211246} // namespace content