blob: 15c6b0071ae8253fe0b73a53354f2f52f3ec66f3 [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]bfc05f22013-10-19 17:55:1616#include "base/debug/trace_event.h"
[email protected]7ccb7072013-06-10 20:56:2817#include "base/message_loop/message_loop_proxy.h"
[email protected]b0b258f2011-11-08 00:34:2318#include "base/metrics/histogram.h"
[email protected]4ce532f2013-03-27 22:03:4019#include "base/strings/string_number_conversions.h"
[email protected]cf02541b2012-04-11 08:02:1720#include "base/synchronization/waitable_event.h"
[email protected]21c3f7502013-03-23 03:29:5121#include "cc/layers/video_layer.h"
[email protected]ca73adc72013-07-11 11:37:0222#include "content/public/common/content_switches.h"
[email protected]5e35a8d2013-07-10 19:37:2123#include "content/renderer/media/buffered_data_source.h"
[email protected]61582e8c2013-07-14 00:38:3324#include "content/renderer/media/crypto/key_systems.h"
[email protected]5e35a8d2013-07-10 19:37:2125#include "content/renderer/media/texttrack_impl.h"
26#include "content/renderer/media/webaudiosourceprovider_impl.h"
27#include "content/renderer/media/webinbandtexttrack_impl.h"
28#include "content/renderer/media/webmediaplayer_delegate.h"
29#include "content/renderer/media/webmediaplayer_params.h"
30#include "content/renderer/media/webmediaplayer_util.h"
[email protected]ef8394c2013-08-21 20:26:3031#include "content/renderer/media/webmediasource_impl.h"
[email protected]adab2332013-07-25 18:04:3232#include "content/renderer/pepper/pepper_webplugin_impl.h"
[email protected]6523b242013-03-13 11:10:0733#include "gpu/GLES2/gl2extchromium.h"
[email protected]e4fc09e2012-04-06 03:17:4434#include "media/audio/null_audio_sink.h"
[email protected]2c539b82012-08-18 04:10:1935#include "media/base/bind_to_loop.h"
[email protected]f8db8132010-12-03 00:27:4936#include "media/base/filter_collection.h"
[email protected]32da1002010-03-03 21:57:3537#include "media/base/limits.h"
[email protected]090f7312011-08-05 23:26:4038#include "media/base/media_log.h"
[email protected]ddbc6ff2013-04-19 15:28:3339#include "media/base/media_switches.h"
[email protected]d399866c2012-01-18 09:30:3240#include "media/base/pipeline.h"
[email protected]e81283bb2010-08-31 18:01:2141#include "media/base/video_frame.h"
[email protected]37136d162012-04-09 23:39:1942#include "media/filters/audio_renderer_impl.h"
[email protected]efe7cd22012-09-12 23:55:0143#include "media/filters/chunk_demuxer.h"
[email protected]ddbc6ff2013-04-19 15:28:3344#include "media/filters/ffmpeg_audio_decoder.h"
45#include "media/filters/ffmpeg_demuxer.h"
46#include "media/filters/ffmpeg_video_decoder.h"
[email protected]1cad8802013-08-13 16:54:3247#include "media/filters/gpu_video_accelerator_factories.h"
[email protected]b9a407e2013-07-24 07:30:0248#include "media/filters/gpu_video_decoder.h"
[email protected]ddbc6ff2013-04-19 15:28:3349#include "media/filters/opus_audio_decoder.h"
[email protected]d4833b72012-01-13 22:16:1750#include "media/filters/video_renderer_base.h"
[email protected]ddbc6ff2013-04-19 15:28:3351#include "media/filters/vpx_video_decoder.h"
[email protected]745746d2013-08-23 02:09:1652#include "third_party/WebKit/public/platform/WebMediaSource.h"
[email protected]c10884462013-05-30 00:22:0953#include "third_party/WebKit/public/platform/WebRect.h"
54#include "third_party/WebKit/public/platform/WebSize.h"
55#include "third_party/WebKit/public/platform/WebString.h"
56#include "third_party/WebKit/public/platform/WebURL.h"
[email protected]f961a0f2013-09-23 04:15:4557#include "third_party/WebKit/public/web/WebDocument.h"
[email protected]2255a9332013-06-17 05:12:3158#include "third_party/WebKit/public/web/WebRuntimeFeatures.h"
59#include "third_party/WebKit/public/web/WebView.h"
[email protected]38aefc312011-09-20 05:06:3760#include "v8/include/v8.h"
[email protected]799fd732013-05-15 21:18:5261#include "webkit/renderer/compositor_bindings/web_layer_impl.h"
[email protected]b3f2b912009-04-09 16:18:5262
[email protected]df143bdc2009-06-16 17:34:1963using WebKit::WebCanvas;
[email protected]ef405f66b2012-04-18 02:39:5564using WebKit::WebMediaPlayer;
[email protected]b3f2b912009-04-09 16:18:5265using WebKit::WebRect;
66using WebKit::WebSize;
[email protected]f7a6b992012-04-19 09:45:5667using WebKit::WebString;
[email protected]a9590c22011-03-16 16:57:0268using media::PipelineStatus;
[email protected]ec9212f2008-12-18 21:40:3669
[email protected]8931c41a2009-07-07 17:31:4970namespace {
71
[email protected]38aefc312011-09-20 05:06:3772// Amount of extra memory used by each player instance reported to V8.
73// It is not exact number -- first, it differs on different platforms,
74// and second, it is very hard to calculate. Instead, use some arbitrary
75// value that will cause garbage collection from time to time. We don't want
76// it to happen on every allocation, but don't want 5k players to sit in memory
77// either. Looks that chosen constant achieves both goals, at least for audio
78// objects. (Do not worry about video objects yet, JS programs do not create
79// thousands of them...)
80const int kPlayerExtraMemory = 1024 * 1024;
81
[email protected]378f0b72009-08-11 17:11:4282// Limits the range of playback rate.
83//
84// TODO(kylep): Revisit these.
85//
86// Vista has substantially lower performance than XP or Windows7. If you speed
87// up a video too much, it can't keep up, and rendering stops updating except on
88// the time bar. For really high speeds, audio becomes a bottleneck and we just
89// use up the data we have, which may not achieve the speed requested, but will
90// not crash the tab.
91//
92// A very slow speed, ie 0.00000001x, causes the machine to lock up. (It seems
93// like a busy loop). It gets unresponsive, although its not completely dead.
94//
95// Also our timers are not very accurate (especially for ogg), which becomes
96// evident at low speeds and on Vista. Since other speeds are risky and outside
97// the norms, we think 1/16x to 16x is a safe and useful range for now.
[email protected]39bdde32013-04-17 17:44:2098const double kMinRate = 0.0625;
99const double kMaxRate = 16.0;
[email protected]378f0b72009-08-11 17:11:42100
[email protected]2ca7d5c2012-10-23 07:30:54101// Prefix for histograms related to Encrypted Media Extensions.
102const char* kMediaEme = "Media.EME.";
[email protected]61582e8c2013-07-14 00:38:33103
[email protected]8931c41a2009-07-07 17:31:49104} // namespace
105
[email protected]5e35a8d2013-07-10 19:37:21106namespace content {
[email protected]add51772009-06-11 18:25:17107
[email protected]a8884632012-06-29 03:05:34108#define COMPILE_ASSERT_MATCHING_ENUM(name) \
[email protected]2ca7d5c2012-10-23 07:30:54109 COMPILE_ASSERT(static_cast<int>(WebMediaPlayer::CORSMode ## name) == \
[email protected]a8884632012-06-29 03:05:34110 static_cast<int>(BufferedResourceLoader::k ## name), \
[email protected]a5a01102012-06-06 17:01:24111 mismatching_enums)
112COMPILE_ASSERT_MATCHING_ENUM(Unspecified);
113COMPILE_ASSERT_MATCHING_ENUM(Anonymous);
114COMPILE_ASSERT_MATCHING_ENUM(UseCredentials);
115#undef COMPILE_ASSERT_MATCHING_ENUM
116
[email protected]2c539b82012-08-18 04:10:19117#define BIND_TO_RENDER_LOOP(function) \
[email protected]e82c0e352013-03-01 01:53:46118 media::BindToLoop(main_loop_, base::Bind(function, AsWeakPtr()))
[email protected]2c539b82012-08-18 04:10:19119
[email protected]62e5e682013-03-07 23:53:24120#define BIND_TO_RENDER_LOOP_1(function, arg1) \
121 media::BindToLoop(main_loop_, base::Bind(function, AsWeakPtr(), arg1))
122
[email protected]5983adb2012-10-24 00:12:00123#define BIND_TO_RENDER_LOOP_2(function, arg1, arg2) \
[email protected]e82c0e352013-03-01 01:53:46124 media::BindToLoop(main_loop_, base::Bind(function, AsWeakPtr(), arg1, arg2))
[email protected]5983adb2012-10-24 00:12:00125
[email protected]2ef99602012-12-08 04:22:21126static void LogMediaSourceError(const scoped_refptr<media::MediaLog>& media_log,
127 const std::string& error) {
128 media_log->AddEvent(media_log->CreateMediaSourceErrorEvent(error));
129}
130
[email protected]5b5bb9d2010-10-22 19:57:36131WebMediaPlayerImpl::WebMediaPlayerImpl(
[email protected]da952fd2012-01-13 03:49:25132 WebKit::WebFrame* frame,
[email protected]5b5bb9d2010-10-22 19:57:36133 WebKit::WebMediaPlayerClient* client,
[email protected]b8976652011-10-26 23:46:55134 base::WeakPtr<WebMediaPlayerDelegate> delegate,
[email protected]e82b2bd2013-01-02 17:47:57135 const WebMediaPlayerParams& params)
[email protected]a9415292012-01-19 19:55:20136 : frame_(frame),
[email protected]ef405f66b2012-04-18 02:39:55137 network_state_(WebMediaPlayer::NetworkStateEmpty),
138 ready_state_(WebMediaPlayer::ReadyStateHaveNothing),
[email protected]e82c0e352013-03-01 01:53:46139 main_loop_(base::MessageLoopProxy::current()),
[email protected]c1330c82013-06-06 02:23:25140 media_loop_(params.message_loop_proxy()),
[email protected]49480902009-07-14 20:23:43141 paused_(true),
[email protected]b3766a22010-12-22 17:34:13142 seeking_(false),
[email protected]49480902009-07-14 20:23:43143 playback_rate_(0.0f),
[email protected]5d11eff2011-09-15 00:06:06144 pending_seek_(false),
[email protected]b1a975e2011-12-21 00:12:39145 pending_seek_seconds_(0.0f),
[email protected]5badb082010-06-11 17:40:15146 client_(client),
[email protected]baff4512011-10-19 18:21:07147 delegate_(delegate),
[email protected]d726eddc2013-07-02 22:25:55148 defer_load_cb_(params.defer_load_cb()),
[email protected]e82b2bd2013-01-02 17:47:57149 media_log_(params.media_log()),
[email protected]c5b1b642012-03-26 19:40:51150 accelerated_compositing_reported_(false),
[email protected]9e2269d2012-01-07 00:06:21151 incremented_externally_allocated_memory_(false),
[email protected]ddbc6ff2013-04-19 15:28:33152 gpu_factories_(params.gpu_factories()),
[email protected]a8884632012-06-29 03:05:34153 is_local_source_(false),
[email protected]132dd57c2012-08-10 23:24:34154 supports_save_(true),
[email protected]b49beeb2013-03-01 20:04:00155 starting_(false),
[email protected]f5443ef72013-04-22 04:03:38156 chunk_demuxer_(NULL),
[email protected]c46a9f42013-10-16 03:28:18157 current_frame_painted_(false),
158 frames_dropped_before_paint_(0),
[email protected]21c3f7502013-03-23 03:29:51159 pending_repaint_(false),
[email protected]29037ce52013-05-06 22:44:16160 pending_size_change_(false),
[email protected]71537722013-05-23 06:47:53161 video_frame_provider_client_(NULL),
162 text_track_index_(0) {
[email protected]c93eb0a62011-08-09 22:47:24163 media_log_->AddEvent(
164 media_log_->CreateEvent(media::MediaLogEvent::WEBMEDIAPLAYER_CREATED));
[email protected]4e6be3f2009-05-07 02:24:44165
[email protected]cadac622013-06-11 16:46:36166 pipeline_.reset(new media::Pipeline(media_loop_, media_log_.get()));
[email protected]db190487d2009-07-30 18:51:52167
[email protected]e82b2bd2013-01-02 17:47:57168 // Let V8 know we started new thread if we did not do it yet.
[email protected]da952fd2012-01-13 03:49:25169 // Made separate task to avoid deletion of player currently being created.
170 // Also, delaying GC until after player starts gets rid of starting lag --
171 // collection happens in parallel with playing.
172 //
173 // TODO(enal): remove when we get rid of per-audio-stream thread.
[email protected]e82c0e352013-03-01 01:53:46174 main_loop_->PostTask(
[email protected]da952fd2012-01-13 03:49:25175 FROM_HERE,
176 base::Bind(&WebMediaPlayerImpl::IncrementExternallyAllocatedMemory,
177 AsWeakPtr()));
178
[email protected]da952fd2012-01-13 03:49:25179 // Also we want to be notified of |main_loop_| destruction.
[email protected]fb5af232013-04-22 22:40:03180 base::MessageLoop::current()->AddDestructionObserver(this);
[email protected]da952fd2012-01-13 03:49:25181
[email protected]e76d92f2013-09-26 20:03:35182 if (WebKit::WebRuntimeFeatures::isPrefixedEncryptedMediaEnabled()) {
[email protected]abd36b3af2012-12-22 03:42:02183 decryptor_.reset(new ProxyDecryptor(
[email protected]04af49912013-06-21 22:09:01184#if defined(ENABLE_PEPPER_CDMS)
[email protected]abd36b3af2012-12-22 03:42:02185 client,
186 frame,
[email protected]04af49912013-06-21 22:09:01187#endif
[email protected]abd36b3af2012-12-22 03:42:02188 BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnKeyAdded),
189 BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnKeyError),
[email protected]7e06e6ac2013-06-20 21:34:15190 BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnKeyMessage)));
[email protected]47ebb0e2012-11-30 08:28:29191 }
[email protected]893f28282012-12-14 22:51:35192
[email protected]ddbc6ff2013-04-19 15:28:33193 // Use the null sink if no sink was provided.
[email protected]4a914882013-01-10 00:43:48194 audio_source_provider_ = new WebAudioSourceProviderImpl(
[email protected]ff875be52013-06-02 23:47:38195 params.audio_renderer_sink().get()
196 ? params.audio_renderer_sink()
[email protected]c1330c82013-06-06 02:23:25197 : new media::NullAudioSink(media_loop_));
[email protected]ec9212f2008-12-18 21:40:36198}
199
[email protected]4e6be3f2009-05-07 02:24:44200WebMediaPlayerImpl::~WebMediaPlayerImpl() {
[email protected]21c3f7502013-03-23 03:29:51201 SetVideoFrameProviderClient(NULL);
202 GetClient()->setWebLayer(NULL);
[email protected]21c3f7502013-03-23 03:29:51203
[email protected]e82c0e352013-03-01 01:53:46204 DCHECK(main_loop_->BelongsToCurrentThread());
[email protected]c93eb0a62011-08-09 22:47:24205 media_log_->AddEvent(
206 media_log_->CreateEvent(media::MediaLogEvent::WEBMEDIAPLAYER_DESTROYED));
[email protected]d43ed912009-02-03 04:52:53207
[email protected]9b55d802013-06-04 02:39:46208 if (delegate_.get())
[email protected]baff4512011-10-19 18:21:07209 delegate_->PlayerGone(this);
210
[email protected]a3702c52013-05-09 05:40:30211 Destroy();
212
[email protected]e82c0e352013-03-01 01:53:46213 // Remove destruction observer if we're being destroyed but the main thread is
214 // still running.
[email protected]fb5af232013-04-22 22:40:03215 if (base::MessageLoop::current())
216 base::MessageLoop::current()->RemoveDestructionObserver(this);
[email protected]ec9212f2008-12-18 21:40:36217}
218
[email protected]daeae722011-11-15 23:00:58219namespace {
220
221// Helper enum for reporting scheme histograms.
222enum URLSchemeForHistogram {
223 kUnknownURLScheme,
224 kMissingURLScheme,
225 kHttpURLScheme,
226 kHttpsURLScheme,
227 kFtpURLScheme,
228 kChromeExtensionURLScheme,
229 kJavascriptURLScheme,
230 kFileURLScheme,
231 kBlobURLScheme,
232 kDataURLScheme,
[email protected]aacd4a42012-04-11 02:34:48233 kFileSystemScheme,
234 kMaxURLScheme = kFileSystemScheme // Must be equal to highest enum value.
[email protected]daeae722011-11-15 23:00:58235};
236
237URLSchemeForHistogram URLScheme(const GURL& url) {
238 if (!url.has_scheme()) return kMissingURLScheme;
239 if (url.SchemeIs("http")) return kHttpURLScheme;
240 if (url.SchemeIs("https")) return kHttpsURLScheme;
241 if (url.SchemeIs("ftp")) return kFtpURLScheme;
242 if (url.SchemeIs("chrome-extension")) return kChromeExtensionURLScheme;
243 if (url.SchemeIs("javascript")) return kJavascriptURLScheme;
244 if (url.SchemeIs("file")) return kFileURLScheme;
245 if (url.SchemeIs("blob")) return kBlobURLScheme;
246 if (url.SchemeIs("data")) return kDataURLScheme;
[email protected]aacd4a42012-04-11 02:34:48247 if (url.SchemeIs("filesystem")) return kFileSystemScheme;
[email protected]daeae722011-11-15 23:00:58248 return kUnknownURLScheme;
249}
250
251} // anonymous namespace
252
[email protected]ef8394c2013-08-21 20:26:30253void WebMediaPlayerImpl::load(LoadType load_type, const WebKit::WebURL& url,
[email protected]62e5e682013-03-07 23:53:24254 CORSMode cors_mode) {
[email protected]d726eddc2013-07-02 22:25:55255 if (!defer_load_cb_.is_null()) {
256 defer_load_cb_.Run(base::Bind(
[email protected]ef8394c2013-08-21 20:26:30257 &WebMediaPlayerImpl::DoLoad, AsWeakPtr(), load_type, url, cors_mode));
[email protected]d726eddc2013-07-02 22:25:55258 return;
259 }
[email protected]ef8394c2013-08-21 20:26:30260 DoLoad(load_type, url, cors_mode);
[email protected]62e5e682013-03-07 23:53:24261}
262
[email protected]ef8394c2013-08-21 20:26:30263void WebMediaPlayerImpl::DoLoad(LoadType load_type,
264 const WebKit::WebURL& url,
[email protected]d726eddc2013-07-02 22:25:55265 CORSMode cors_mode) {
266 DCHECK(main_loop_->BelongsToCurrentThread());
267
[email protected]62e5e682013-03-07 23:53:24268 GURL gurl(url);
269 UMA_HISTOGRAM_ENUMERATION("Media.URLScheme", URLScheme(gurl), kMaxURLScheme);
270
[email protected]926f8fd2013-04-12 20:27:53271 // Set subresource URL for crash reporting.
272 base::debug::SetCrashKeyValue("subresource_url", gurl.spec());
273
[email protected]ef8394c2013-08-21 20:26:30274 load_type_ = load_type;
275
[email protected]62e5e682013-03-07 23:53:24276 // Handle any volume/preload changes that occurred before load().
277 setVolume(GetClient()->volume());
278 setPreload(GetClient()->preload());
279
280 SetNetworkState(WebMediaPlayer::NetworkStateLoading);
281 SetReadyState(WebMediaPlayer::ReadyStateHaveNothing);
282 media_log_->AddEvent(media_log_->CreateLoadEvent(url.spec()));
[email protected]d726eddc2013-07-02 22:25:55283
284 // Media source pipelines can start immediately.
[email protected]ef8394c2013-08-21 20:26:30285 if (load_type == LoadTypeMediaSource) {
[email protected]d726eddc2013-07-02 22:25:55286 supports_save_ = false;
[email protected]ef8394c2013-08-21 20:26:30287 StartPipeline();
[email protected]d726eddc2013-07-02 22:25:55288 return;
289 }
290
291 // Otherwise it's a regular request which requires resolving the URL first.
292 data_source_.reset(new BufferedDataSource(
293 main_loop_,
294 frame_,
295 media_log_.get(),
296 base::Bind(&WebMediaPlayerImpl::NotifyDownloading, AsWeakPtr())));
297 data_source_->Initialize(
298 url, static_cast<BufferedResourceLoader::CORSMode>(cors_mode),
299 base::Bind(
300 &WebMediaPlayerImpl::DataSourceInitialized,
301 AsWeakPtr(), gurl));
302
[email protected]91f5689032013-08-22 01:43:33303 is_local_source_ = !gurl.SchemeIsHTTPOrHTTPS();
[email protected]62e5e682013-03-07 23:53:24304}
305
[email protected]4e6be3f2009-05-07 02:24:44306void WebMediaPlayerImpl::play() {
[email protected]e82c0e352013-03-01 01:53:46307 DCHECK(main_loop_->BelongsToCurrentThread());
[email protected]d43ed912009-02-03 04:52:53308
[email protected]49480902009-07-14 20:23:43309 paused_ = false;
[email protected]039b7542013-10-17 22:06:25310 pipeline_->SetPlaybackRate(playback_rate_);
311 if (data_source_)
312 data_source_->MediaIsPlaying();
[email protected]090f7312011-08-05 23:26:40313
[email protected]24d75c72011-08-09 17:53:45314 media_log_->AddEvent(media_log_->CreateEvent(media::MediaLogEvent::PLAY));
[email protected]baff4512011-10-19 18:21:07315
[email protected]9b55d802013-06-04 02:39:46316 if (delegate_.get())
[email protected]baff4512011-10-19 18:21:07317 delegate_->DidPlay(this);
[email protected]ec9212f2008-12-18 21:40:36318}
319
[email protected]4e6be3f2009-05-07 02:24:44320void WebMediaPlayerImpl::pause() {
[email protected]e82c0e352013-03-01 01:53:46321 DCHECK(main_loop_->BelongsToCurrentThread());
[email protected]d43ed912009-02-03 04:52:53322
[email protected]49480902009-07-14 20:23:43323 paused_ = true;
[email protected]039b7542013-10-17 22:06:25324 pipeline_->SetPlaybackRate(0.0f);
325 if (data_source_)
326 data_source_->MediaIsPaused();
[email protected]f7c0ada02012-07-23 08:42:50327 paused_time_ = pipeline_->GetMediaTime();
[email protected]090f7312011-08-05 23:26:40328
[email protected]24d75c72011-08-09 17:53:45329 media_log_->AddEvent(media_log_->CreateEvent(media::MediaLogEvent::PAUSE));
[email protected]baff4512011-10-19 18:21:07330
[email protected]9b55d802013-06-04 02:39:46331 if (delegate_.get())
[email protected]baff4512011-10-19 18:21:07332 delegate_->DidPause(this);
[email protected]ec9212f2008-12-18 21:40:36333}
334
[email protected]574a1d62009-07-17 03:23:46335bool WebMediaPlayerImpl::supportsFullscreen() const {
[email protected]e82c0e352013-03-01 01:53:46336 DCHECK(main_loop_->BelongsToCurrentThread());
[email protected]574a1d62009-07-17 03:23:46337 return true;
338}
339
340bool WebMediaPlayerImpl::supportsSave() const {
[email protected]e82c0e352013-03-01 01:53:46341 DCHECK(main_loop_->BelongsToCurrentThread());
[email protected]132dd57c2012-08-10 23:24:34342 return supports_save_;
[email protected]574a1d62009-07-17 03:23:46343}
344
[email protected]39bdde32013-04-17 17:44:20345void WebMediaPlayerImpl::seek(double seconds) {
[email protected]e82c0e352013-03-01 01:53:46346 DCHECK(main_loop_->BelongsToCurrentThread());
[email protected]d43ed912009-02-03 04:52:53347
[email protected]bb8a70b2013-06-26 06:23:35348 base::TimeDelta seek_time = ConvertSecondsToTimestamp(seconds);
349
[email protected]a8e2cb82012-08-17 00:02:39350 if (starting_ || seeking_) {
[email protected]5d11eff2011-09-15 00:06:06351 pending_seek_ = true;
352 pending_seek_seconds_ = seconds;
[email protected]efe7cd22012-09-12 23:55:01353 if (chunk_demuxer_)
[email protected]bb8a70b2013-06-26 06:23:35354 chunk_demuxer_->CancelPendingSeek(seek_time);
[email protected]5d11eff2011-09-15 00:06:06355 return;
356 }
357
[email protected]c93eb0a62011-08-09 22:47:24358 media_log_->AddEvent(media_log_->CreateSeekEvent(seconds));
359
[email protected]44ff37c02009-10-24 01:03:03360 // Update our paused time.
[email protected]7b268b7a2011-11-18 19:52:08361 if (paused_)
[email protected]44ff37c02009-10-24 01:03:03362 paused_time_ = seek_time;
[email protected]44ff37c02009-10-24 01:03:03363
[email protected]b3766a22010-12-22 17:34:13364 seeking_ = true;
365
[email protected]efe7cd22012-09-12 23:55:01366 if (chunk_demuxer_)
[email protected]bb8a70b2013-06-26 06:23:35367 chunk_demuxer_->StartWaitingForSeek(seek_time);
[email protected]020fba32011-06-29 16:37:46368
[email protected]44ff37c02009-10-24 01:03:03369 // Kick off the asynchronous seek!
[email protected]3b4cbbf2009-07-11 00:16:19370 pipeline_->Seek(
[email protected]44ff37c02009-10-24 01:03:03371 seek_time,
[email protected]2c539b82012-08-18 04:10:19372 BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnPipelineSeek));
[email protected]ec9212f2008-12-18 21:40:36373}
374
[email protected]39bdde32013-04-17 17:44:20375void WebMediaPlayerImpl::setRate(double rate) {
[email protected]e82c0e352013-03-01 01:53:46376 DCHECK(main_loop_->BelongsToCurrentThread());
[email protected]d43ed912009-02-03 04:52:53377
[email protected]378f0b72009-08-11 17:11:42378 // TODO(kylep): Remove when support for negatives is added. Also, modify the
379 // following checks so rewind uses reasonable values also.
[email protected]39bdde32013-04-17 17:44:20380 if (rate < 0.0)
[email protected]378f0b72009-08-11 17:11:42381 return;
382
383 // Limit rates to reasonable values by clamping.
[email protected]39bdde32013-04-17 17:44:20384 if (rate != 0.0) {
[email protected]378f0b72009-08-11 17:11:42385 if (rate < kMinRate)
386 rate = kMinRate;
387 else if (rate > kMaxRate)
388 rate = kMaxRate;
389 }
390
[email protected]49480902009-07-14 20:23:43391 playback_rate_ = rate;
392 if (!paused_) {
[email protected]039b7542013-10-17 22:06:25393 pipeline_->SetPlaybackRate(rate);
394 if (data_source_)
395 data_source_->MediaPlaybackRateChanged(rate);
[email protected]49480902009-07-14 20:23:43396 }
[email protected]ec9212f2008-12-18 21:40:36397}
398
[email protected]39bdde32013-04-17 17:44:20399void WebMediaPlayerImpl::setVolume(double volume) {
[email protected]e82c0e352013-03-01 01:53:46400 DCHECK(main_loop_->BelongsToCurrentThread());
[email protected]d43ed912009-02-03 04:52:53401
[email protected]3b4cbbf2009-07-11 00:16:19402 pipeline_->SetVolume(volume);
[email protected]ec9212f2008-12-18 21:40:36403}
[email protected]f0a51fb52009-03-05 12:46:38404
[email protected]23a8b1d82011-04-05 16:28:20405#define COMPILE_ASSERT_MATCHING_ENUM(webkit_name, chromium_name) \
[email protected]ef405f66b2012-04-18 02:39:55406 COMPILE_ASSERT(static_cast<int>(WebMediaPlayer::webkit_name) == \
[email protected]5e35a8d2013-07-10 19:37:21407 static_cast<int>(content::chromium_name), \
[email protected]474c37a2011-08-23 20:24:52408 mismatching_enums)
[email protected]ef405f66b2012-04-18 02:39:55409COMPILE_ASSERT_MATCHING_ENUM(PreloadNone, NONE);
410COMPILE_ASSERT_MATCHING_ENUM(PreloadMetaData, METADATA);
411COMPILE_ASSERT_MATCHING_ENUM(PreloadAuto, AUTO);
[email protected]a5a01102012-06-06 17:01:24412#undef COMPILE_ASSERT_MATCHING_ENUM
[email protected]23a8b1d82011-04-05 16:28:20413
[email protected]ef405f66b2012-04-18 02:39:55414void WebMediaPlayerImpl::setPreload(WebMediaPlayer::Preload preload) {
[email protected]e82c0e352013-03-01 01:53:46415 DCHECK(main_loop_->BelongsToCurrentThread());
[email protected]4e6be3f2009-05-07 02:24:44416
[email protected]b49beeb2013-03-01 20:04:00417 if (data_source_)
[email protected]5e35a8d2013-07-10 19:37:21418 data_source_->SetPreload(static_cast<content::Preload>(preload));
[email protected]4e6be3f2009-05-07 02:24:44419}
420
[email protected]4e6be3f2009-05-07 02:24:44421bool WebMediaPlayerImpl::hasVideo() const {
[email protected]e82c0e352013-03-01 01:53:46422 DCHECK(main_loop_->BelongsToCurrentThread());
[email protected]d43ed912009-02-03 04:52:53423
[email protected]cee32342011-03-09 15:58:16424 return pipeline_->HasVideo();
[email protected]d43ed912009-02-03 04:52:53425}
426
[email protected]fc367af2009-08-14 23:06:35427bool WebMediaPlayerImpl::hasAudio() const {
[email protected]e82c0e352013-03-01 01:53:46428 DCHECK(main_loop_->BelongsToCurrentThread());
[email protected]fc367af2009-08-14 23:06:35429
[email protected]cee32342011-03-09 15:58:16430 return pipeline_->HasAudio();
[email protected]fc367af2009-08-14 23:06:35431}
432
[email protected]4e6be3f2009-05-07 02:24:44433WebKit::WebSize WebMediaPlayerImpl::naturalSize() const {
[email protected]e82c0e352013-03-01 01:53:46434 DCHECK(main_loop_->BelongsToCurrentThread());
[email protected]d43ed912009-02-03 04:52:53435
[email protected]2975fa532011-09-19 20:18:33436 gfx::Size size;
437 pipeline_->GetNaturalVideoSize(&size);
438 return WebKit::WebSize(size);
[email protected]d43ed912009-02-03 04:52:53439}
440
[email protected]4e6be3f2009-05-07 02:24:44441bool WebMediaPlayerImpl::paused() const {
[email protected]e82c0e352013-03-01 01:53:46442 DCHECK(main_loop_->BelongsToCurrentThread());
[email protected]d43ed912009-02-03 04:52:53443
[email protected]3b4cbbf2009-07-11 00:16:19444 return pipeline_->GetPlaybackRate() == 0.0f;
[email protected]d43ed912009-02-03 04:52:53445}
446
[email protected]4e6be3f2009-05-07 02:24:44447bool WebMediaPlayerImpl::seeking() const {
[email protected]e82c0e352013-03-01 01:53:46448 DCHECK(main_loop_->BelongsToCurrentThread());
[email protected]d43ed912009-02-03 04:52:53449
[email protected]ef405f66b2012-04-18 02:39:55450 if (ready_state_ == WebMediaPlayer::ReadyStateHaveNothing)
[email protected]0acebfa2009-08-21 22:45:40451 return false;
[email protected]67cd5052009-09-10 21:53:22452
[email protected]b3766a22010-12-22 17:34:13453 return seeking_;
[email protected]ec9212f2008-12-18 21:40:36454}
455
[email protected]39bdde32013-04-17 17:44:20456double WebMediaPlayerImpl::duration() const {
457 DCHECK(main_loop_->BelongsToCurrentThread());
458
459 if (ready_state_ == WebMediaPlayer::ReadyStateHaveNothing)
460 return std::numeric_limits<double>::quiet_NaN();
461
[email protected]39bdde32013-04-17 17:44:20462 return GetPipelineDuration();
[email protected]d43ed912009-02-03 04:52:53463}
464
[email protected]39bdde32013-04-17 17:44:20465double WebMediaPlayerImpl::currentTime() const {
[email protected]e82c0e352013-03-01 01:53:46466 DCHECK(main_loop_->BelongsToCurrentThread());
[email protected]39bdde32013-04-17 17:44:20467 return (paused_ ? paused_time_ : pipeline_->GetMediaTime()).InSecondsF();
[email protected]d43ed912009-02-03 04:52:53468}
469
[email protected]ef405f66b2012-04-18 02:39:55470WebMediaPlayer::NetworkState WebMediaPlayerImpl::networkState() const {
[email protected]e82c0e352013-03-01 01:53:46471 DCHECK(main_loop_->BelongsToCurrentThread());
[email protected]ddb1e5a2010-12-13 20:10:45472 return network_state_;
473}
474
[email protected]ef405f66b2012-04-18 02:39:55475WebMediaPlayer::ReadyState WebMediaPlayerImpl::readyState() const {
[email protected]e82c0e352013-03-01 01:53:46476 DCHECK(main_loop_->BelongsToCurrentThread());
[email protected]ddb1e5a2010-12-13 20:10:45477 return ready_state_;
478}
479
[email protected]f70f8e12010-05-25 21:30:39480const WebKit::WebTimeRanges& WebMediaPlayerImpl::buffered() {
[email protected]e82c0e352013-03-01 01:53:46481 DCHECK(main_loop_->BelongsToCurrentThread());
[email protected]c566cb792012-06-20 00:51:52482 WebKit::WebTimeRanges web_ranges(
483 ConvertToWebTimeRanges(pipeline_->GetBufferedTimeRanges()));
[email protected]49f7b772012-05-10 00:45:35484 buffered_.swap(web_ranges);
[email protected]f70f8e12010-05-25 21:30:39485 return buffered_;
486}
487
[email protected]39bdde32013-04-17 17:44:20488double WebMediaPlayerImpl::maxTimeSeekable() const {
489 DCHECK(main_loop_->BelongsToCurrentThread());
490
491 // If we haven't even gotten to ReadyStateHaveMetadata yet then just
492 // return 0 so that the seekable range is empty.
493 if (ready_state_ < WebMediaPlayer::ReadyStateHaveMetadata)
494 return 0.0;
495
496 // We don't support seeking in streaming media.
497 if (data_source_ && data_source_->IsStreaming())
498 return 0.0;
[email protected]62b5897c2013-01-30 22:53:35499 return duration();
[email protected]ec9212f2008-12-18 21:40:36500}
501
[email protected]7ed21be2012-05-30 08:09:15502bool WebMediaPlayerImpl::didLoadingProgress() const {
[email protected]e82c0e352013-03-01 01:53:46503 DCHECK(main_loop_->BelongsToCurrentThread());
[email protected]7ed21be2012-05-30 08:09:15504 return pipeline_->DidLoadingProgress();
[email protected]d43ed912009-02-03 04:52:53505}
506
[email protected]df143bdc2009-06-16 17:34:19507void WebMediaPlayerImpl::paint(WebCanvas* canvas,
[email protected]4dc43be2012-03-27 14:05:07508 const WebRect& rect,
[email protected]98f60ed2013-05-24 23:20:54509 unsigned char alpha) {
[email protected]e82c0e352013-03-01 01:53:46510 DCHECK(main_loop_->BelongsToCurrentThread());
[email protected]4e6be3f2009-05-07 02:24:44511
[email protected]eaf7d9a2012-05-19 06:14:33512 if (!accelerated_compositing_reported_) {
513 accelerated_compositing_reported_ = true;
[email protected]3dc8f1b2012-05-21 22:54:32514 // Normally paint() is only called in non-accelerated rendering, but there
515 // are exceptions such as webgl where compositing is used in the WebView but
516 // video frames are still rendered to a canvas.
517 UMA_HISTOGRAM_BOOLEAN(
518 "Media.AcceleratedCompositingActive",
519 frame_->view()->isAcceleratedCompositingActive());
[email protected]eaf7d9a2012-05-19 06:14:33520 }
521
[email protected]b49beeb2013-03-01 20:04:00522 // Avoid locking and potentially blocking the video rendering thread while
523 // painting in software.
524 scoped_refptr<media::VideoFrame> video_frame;
525 {
526 base::AutoLock auto_lock(lock_);
[email protected]bfc05f22013-10-19 17:55:16527 DoneWaitingForPaint(true);
[email protected]b49beeb2013-03-01 20:04:00528 video_frame = current_frame_;
529 }
[email protected]bfc05f22013-10-19 17:55:16530 TRACE_EVENT0("media", "WebMediaPlayerImpl:paint");
[email protected]b49beeb2013-03-01 20:04:00531 gfx::Rect gfx_rect(rect);
[email protected]ff875be52013-06-02 23:47:38532 skcanvas_video_renderer_.Paint(video_frame.get(), canvas, gfx_rect, alpha);
[email protected]ec9212f2008-12-18 21:40:36533}
[email protected]5df51652009-01-17 00:03:00534
[email protected]38259a7a82009-07-29 21:49:49535bool WebMediaPlayerImpl::hasSingleSecurityOrigin() const {
[email protected]b49beeb2013-03-01 20:04:00536 if (data_source_)
537 return data_source_->HasSingleOrigin();
[email protected]fcdb7462009-10-21 21:05:11538 return true;
[email protected]38259a7a82009-07-29 21:49:49539}
540
[email protected]3fe27112012-06-07 04:00:01541bool WebMediaPlayerImpl::didPassCORSAccessCheck() const {
[email protected]b49beeb2013-03-01 20:04:00542 if (data_source_)
543 return data_source_->DidPassCORSAccessCheck();
544 return false;
[email protected]3fe27112012-06-07 04:00:01545}
546
[email protected]39bdde32013-04-17 17:44:20547double WebMediaPlayerImpl::mediaTimeForTimeValue(double timeValue) const {
[email protected]e06e16d82011-05-26 22:13:33548 return ConvertSecondsToTimestamp(timeValue).InSecondsF();
549}
550
[email protected]d82b18ae2011-03-23 21:28:59551unsigned WebMediaPlayerImpl::decodedFrameCount() const {
[email protected]e82c0e352013-03-01 01:53:46552 DCHECK(main_loop_->BelongsToCurrentThread());
[email protected]4c51bc662011-02-16 02:03:16553
554 media::PipelineStatistics stats = pipeline_->GetStatistics();
555 return stats.video_frames_decoded;
556}
557
[email protected]d82b18ae2011-03-23 21:28:59558unsigned WebMediaPlayerImpl::droppedFrameCount() const {
[email protected]e82c0e352013-03-01 01:53:46559 DCHECK(main_loop_->BelongsToCurrentThread());
[email protected]4c51bc662011-02-16 02:03:16560
561 media::PipelineStatistics stats = pipeline_->GetStatistics();
[email protected]c46a9f42013-10-16 03:28:18562
563 base::AutoLock auto_lock(lock_);
564 unsigned frames_dropped =
565 stats.video_frames_dropped + frames_dropped_before_paint_;
566 DCHECK_LE(frames_dropped, stats.video_frames_decoded);
567 return frames_dropped;
[email protected]4c51bc662011-02-16 02:03:16568}
569
[email protected]d82b18ae2011-03-23 21:28:59570unsigned WebMediaPlayerImpl::audioDecodedByteCount() const {
[email protected]e82c0e352013-03-01 01:53:46571 DCHECK(main_loop_->BelongsToCurrentThread());
[email protected]4c51bc662011-02-16 02:03:16572
573 media::PipelineStatistics stats = pipeline_->GetStatistics();
574 return stats.audio_bytes_decoded;
575}
576
[email protected]d82b18ae2011-03-23 21:28:59577unsigned WebMediaPlayerImpl::videoDecodedByteCount() const {
[email protected]e82c0e352013-03-01 01:53:46578 DCHECK(main_loop_->BelongsToCurrentThread());
[email protected]4c51bc662011-02-16 02:03:16579
580 media::PipelineStatistics stats = pipeline_->GetStatistics();
581 return stats.video_bytes_decoded;
582}
583
[email protected]21c3f7502013-03-23 03:29:51584void WebMediaPlayerImpl::SetVideoFrameProviderClient(
585 cc::VideoFrameProvider::Client* client) {
586 // This is called from both the main renderer thread and the compositor
587 // thread (when the main thread is blocked).
588 if (video_frame_provider_client_)
589 video_frame_provider_client_->StopUsingProvider();
590 video_frame_provider_client_ = client;
591}
592
593scoped_refptr<media::VideoFrame> WebMediaPlayerImpl::GetCurrentFrame() {
594 base::AutoLock auto_lock(lock_);
[email protected]bfc05f22013-10-19 17:55:16595 DoneWaitingForPaint(true);
596 TRACE_EVENT_ASYNC_BEGIN0(
597 "media", "WebMediaPlayerImpl:compositing", this);
[email protected]21c3f7502013-03-23 03:29:51598 return current_frame_;
599}
600
601void WebMediaPlayerImpl::PutCurrentFrame(
602 const scoped_refptr<media::VideoFrame>& frame) {
603 if (!accelerated_compositing_reported_) {
604 accelerated_compositing_reported_ = true;
605 DCHECK(frame_->view()->isAcceleratedCompositingActive());
606 UMA_HISTOGRAM_BOOLEAN("Media.AcceleratedCompositingActive", true);
607 }
[email protected]bfc05f22013-10-19 17:55:16608 TRACE_EVENT_ASYNC_END0("media", "WebMediaPlayerImpl:compositing", this);
[email protected]21c3f7502013-03-23 03:29:51609}
[email protected]e81283bb2010-08-31 18:01:21610
[email protected]6523b242013-03-13 11:10:07611bool WebMediaPlayerImpl::copyVideoTextureToPlatformTexture(
612 WebKit::WebGraphicsContext3D* web_graphics_context,
613 unsigned int texture,
614 unsigned int level,
615 unsigned int internal_format,
[email protected]9aa2b2782013-05-14 00:13:31616 unsigned int type,
[email protected]6523b242013-03-13 11:10:07617 bool premultiply_alpha,
618 bool flip_y) {
619 scoped_refptr<media::VideoFrame> video_frame;
620 {
621 base::AutoLock auto_lock(lock_);
622 video_frame = current_frame_;
623 }
[email protected]e56f88c72013-06-25 22:31:29624
[email protected]bfc05f22013-10-19 17:55:16625 TRACE_EVENT0("media", "WebMediaPlayerImpl:copyVideoTextureToPlatformTexture");
626
627 if (!video_frame)
[email protected]e56f88c72013-06-25 22:31:29628 return false;
629 if (video_frame->format() != media::VideoFrame::NATIVE_TEXTURE)
630 return false;
631 if (video_frame->texture_target() != GL_TEXTURE_2D)
632 return false;
633
634 scoped_refptr<media::VideoFrame::MailboxHolder> mailbox_holder =
635 video_frame->texture_mailbox();
636
637 uint32 source_texture = web_graphics_context->createTexture();
638
639 web_graphics_context->waitSyncPoint(mailbox_holder->sync_point());
640 web_graphics_context->bindTexture(GL_TEXTURE_2D, source_texture);
641 web_graphics_context->consumeTextureCHROMIUM(GL_TEXTURE_2D,
642 mailbox_holder->mailbox().name);
643
644 // The video is stored in a unmultiplied format, so premultiply
645 // if necessary.
646 web_graphics_context->pixelStorei(GL_UNPACK_PREMULTIPLY_ALPHA_CHROMIUM,
647 premultiply_alpha);
648 // Application itself needs to take care of setting the right flip_y
649 // value down to get the expected result.
650 // flip_y==true means to reverse the video orientation while
651 // flip_y==false means to keep the intrinsic orientation.
652 web_graphics_context->pixelStorei(GL_UNPACK_FLIP_Y_CHROMIUM, flip_y);
653 web_graphics_context->copyTextureCHROMIUM(GL_TEXTURE_2D,
654 source_texture,
655 texture,
656 level,
657 internal_format,
658 type);
659 web_graphics_context->pixelStorei(GL_UNPACK_FLIP_Y_CHROMIUM, false);
660 web_graphics_context->pixelStorei(GL_UNPACK_PREMULTIPLY_ALPHA_CHROMIUM,
661 false);
662
663 web_graphics_context->deleteTexture(source_texture);
664
665 // The flush() operation is not necessary here. It is kept since the
666 // performance will be better when it is added than not.
667 web_graphics_context->flush();
668 return true;
[email protected]6523b242013-03-13 11:10:07669}
670
[email protected]49a097e2013-04-02 19:31:51671// Helper functions to report media EME related stats to UMA. They follow the
672// convention of more commonly used macros UMA_HISTOGRAM_ENUMERATION and
673// UMA_HISTOGRAM_COUNTS. The reason that we cannot use those macros directly is
674// that UMA_* macros require the names to be constant throughout the process'
675// lifetime.
[email protected]f3a1d40d2013-06-25 22:12:50676static void EmeUMAHistogramEnumeration(const WebKit::WebString& key_system,
[email protected]49a097e2013-04-02 19:31:51677 const std::string& method,
678 int sample,
679 int boundary_value) {
680 base::LinearHistogram::FactoryGet(
681 kMediaEme + KeySystemNameForUMA(key_system) + "." + method,
682 1, boundary_value, boundary_value + 1,
683 base::Histogram::kUmaTargetedHistogramFlag)->Add(sample);
684}
685
[email protected]f3a1d40d2013-06-25 22:12:50686static void EmeUMAHistogramCounts(const WebKit::WebString& key_system,
[email protected]49a097e2013-04-02 19:31:51687 const std::string& method,
688 int sample) {
689 // Use the same parameters as UMA_HISTOGRAM_COUNTS.
690 base::Histogram::FactoryGet(
691 kMediaEme + KeySystemNameForUMA(key_system) + "." + method,
692 1, 1000000, 50, base::Histogram::kUmaTargetedHistogramFlag)->Add(sample);
693}
694
[email protected]2ca7d5c2012-10-23 07:30:54695// Helper enum for reporting generateKeyRequest/addKey histograms.
696enum MediaKeyException {
697 kUnknownResultId,
698 kSuccess,
699 kKeySystemNotSupported,
700 kInvalidPlayerState,
701 kMaxMediaKeyException
702};
703
704static MediaKeyException MediaKeyExceptionForUMA(
705 WebMediaPlayer::MediaKeyException e) {
706 switch (e) {
707 case WebMediaPlayer::MediaKeyExceptionKeySystemNotSupported:
708 return kKeySystemNotSupported;
709 case WebMediaPlayer::MediaKeyExceptionInvalidPlayerState:
710 return kInvalidPlayerState;
711 case WebMediaPlayer::MediaKeyExceptionNoError:
712 return kSuccess;
713 default:
714 return kUnknownResultId;
715 }
716}
717
718// Helper for converting |key_system| name and exception |e| to a pair of enum
719// values from above, for reporting to UMA.
720static void ReportMediaKeyExceptionToUMA(
721 const std::string& method,
722 const WebString& key_system,
723 WebMediaPlayer::MediaKeyException e) {
724 MediaKeyException result_id = MediaKeyExceptionForUMA(e);
725 DCHECK_NE(result_id, kUnknownResultId) << e;
[email protected]49a097e2013-04-02 19:31:51726 EmeUMAHistogramEnumeration(
[email protected]f3a1d40d2013-06-25 22:12:50727 key_system, method, result_id, kMaxMediaKeyException);
[email protected]2ca7d5c2012-10-23 07:30:54728}
729
730WebMediaPlayer::MediaKeyException
[email protected]f7a6b992012-04-19 09:45:56731WebMediaPlayerImpl::generateKeyRequest(const WebString& key_system,
732 const unsigned char* init_data,
733 unsigned init_data_length) {
[email protected]2ca7d5c2012-10-23 07:30:54734 WebMediaPlayer::MediaKeyException e =
735 GenerateKeyRequestInternal(key_system, init_data, init_data_length);
736 ReportMediaKeyExceptionToUMA("generateKeyRequest", key_system, e);
737 return e;
738}
739
740WebMediaPlayer::MediaKeyException
741WebMediaPlayerImpl::GenerateKeyRequestInternal(
742 const WebString& key_system,
743 const unsigned char* init_data,
744 unsigned init_data_length) {
[email protected]f7a6b992012-04-19 09:45:56745 DVLOG(1) << "generateKeyRequest: " << key_system.utf8().data() << ": "
746 << std::string(reinterpret_cast<const char*>(init_data),
[email protected]cbdc8c2b2012-06-16 01:27:36747 static_cast<size_t>(init_data_length));
[email protected]f7a6b992012-04-19 09:45:56748
[email protected]2a3d19b62013-08-28 05:34:04749 if (!IsConcreteSupportedKeySystem(key_system))
[email protected]fecb5fe2013-06-19 00:52:13750 return WebMediaPlayer::MediaKeyExceptionKeySystemNotSupported;
751
752 // We do not support run-time switching between key systems for now.
753 if (current_key_system_.isEmpty()) {
[email protected]f961a0f2013-09-23 04:15:45754 if (!decryptor_->InitializeCDM(key_system.utf8(), frame_->document().url()))
[email protected]fecb5fe2013-06-19 00:52:13755 return WebMediaPlayer::MediaKeyExceptionKeySystemNotSupported;
756 current_key_system_ = key_system;
757 }
758 else if (key_system != current_key_system_) {
759 return WebMediaPlayer::MediaKeyExceptionInvalidPlayerState;
760 }
761
[email protected]c8d40282012-10-27 07:23:13762 // TODO(xhwang): We assume all streams are from the same container (thus have
763 // the same "type") for now. In the future, the "type" should be passed down
764 // from the application.
[email protected]fecb5fe2013-06-19 00:52:13765 if (!decryptor_->GenerateKeyRequest(init_data_type_,
[email protected]83fdd992012-12-21 19:57:49766 init_data, init_data_length)) {
[email protected]6a206732012-08-29 01:14:40767 current_key_system_.reset();
[email protected]2ca7d5c2012-10-23 07:30:54768 return WebMediaPlayer::MediaKeyExceptionKeySystemNotSupported;
[email protected]6a206732012-08-29 01:14:40769 }
770
[email protected]2ca7d5c2012-10-23 07:30:54771 return WebMediaPlayer::MediaKeyExceptionNoError;
[email protected]f7a6b992012-04-19 09:45:56772}
773
[email protected]2ca7d5c2012-10-23 07:30:54774WebMediaPlayer::MediaKeyException WebMediaPlayerImpl::addKey(
775 const WebString& key_system,
776 const unsigned char* key,
777 unsigned key_length,
778 const unsigned char* init_data,
779 unsigned init_data_length,
780 const WebString& session_id) {
781 WebMediaPlayer::MediaKeyException e = AddKeyInternal(
782 key_system, key, key_length, init_data, init_data_length, session_id);
783 ReportMediaKeyExceptionToUMA("addKey", key_system, e);
784 return e;
785}
786
[email protected]2ca7d5c2012-10-23 07:30:54787WebMediaPlayer::MediaKeyException WebMediaPlayerImpl::AddKeyInternal(
[email protected]f7a6b992012-04-19 09:45:56788 const WebString& key_system,
789 const unsigned char* key,
790 unsigned key_length,
791 const unsigned char* init_data,
792 unsigned init_data_length,
793 const WebString& session_id) {
[email protected]a0149082012-04-19 17:33:41794 DCHECK(key);
795 DCHECK_GT(key_length, 0u);
[email protected]f7a6b992012-04-19 09:45:56796 DVLOG(1) << "addKey: " << key_system.utf8().data() << ": "
797 << std::string(reinterpret_cast<const char*>(key),
798 static_cast<size_t>(key_length)) << ", "
799 << std::string(reinterpret_cast<const char*>(init_data),
800 static_cast<size_t>(init_data_length))
801 << " [" << session_id.utf8().data() << "]";
802
[email protected]fecb5fe2013-06-19 00:52:13803
[email protected]2a3d19b62013-08-28 05:34:04804 if (!IsConcreteSupportedKeySystem(key_system))
[email protected]fecb5fe2013-06-19 00:52:13805 return WebMediaPlayer::MediaKeyExceptionKeySystemNotSupported;
806
807 if (current_key_system_.isEmpty() || key_system != current_key_system_)
808 return WebMediaPlayer::MediaKeyExceptionInvalidPlayerState;
809
810 decryptor_->AddKey(key, key_length,
[email protected]83fdd992012-12-21 19:57:49811 init_data, init_data_length, 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]2ca7d5c2012-10-23 07:30:54815WebMediaPlayer::MediaKeyException WebMediaPlayerImpl::cancelKeyRequest(
816 const WebString& key_system,
817 const WebString& session_id) {
818 WebMediaPlayer::MediaKeyException e =
819 CancelKeyRequestInternal(key_system, session_id);
820 ReportMediaKeyExceptionToUMA("cancelKeyRequest", key_system, e);
821 return e;
822}
823
824WebMediaPlayer::MediaKeyException
825WebMediaPlayerImpl::CancelKeyRequestInternal(
[email protected]f7a6b992012-04-19 09:45:56826 const WebString& key_system,
827 const WebString& session_id) {
[email protected]2a3d19b62013-08-28 05:34:04828 if (!IsConcreteSupportedKeySystem(key_system))
[email protected]2ca7d5c2012-10-23 07:30:54829 return WebMediaPlayer::MediaKeyExceptionKeySystemNotSupported;
[email protected]f7a6b992012-04-19 09:45:56830
[email protected]a8884632012-06-29 03:05:34831 if (current_key_system_.isEmpty() || key_system != current_key_system_)
[email protected]2ca7d5c2012-10-23 07:30:54832 return WebMediaPlayer::MediaKeyExceptionInvalidPlayerState;
[email protected]a8884632012-06-29 03:05:34833
[email protected]fecb5fe2013-06-19 00:52:13834 decryptor_->CancelKeyRequest(session_id.utf8());
[email protected]2ca7d5c2012-10-23 07:30:54835 return WebMediaPlayer::MediaKeyExceptionNoError;
[email protected]f7a6b992012-04-19 09:45:56836}
837
[email protected]4e6be3f2009-05-07 02:24:44838void WebMediaPlayerImpl::WillDestroyCurrentMessageLoop() {
[email protected]8931c41a2009-07-07 17:31:49839 Destroy();
[email protected]8931c41a2009-07-07 17:31:49840}
841
842void WebMediaPlayerImpl::Repaint() {
[email protected]e82c0e352013-03-01 01:53:46843 DCHECK(main_loop_->BelongsToCurrentThread());
[email protected]bfc05f22013-10-19 17:55:16844 TRACE_EVENT0("media", "WebMediaPlayerImpl:repaint");
[email protected]b49beeb2013-03-01 20:04:00845
[email protected]29037ce52013-05-06 22:44:16846 bool size_changed = false;
847 {
848 base::AutoLock auto_lock(lock_);
849 std::swap(pending_size_change_, size_changed);
[email protected]bfc05f22013-10-19 17:55:16850 if (pending_repaint_) {
851 TRACE_EVENT_ASYNC_END0(
852 "media", "WebMediaPlayerImpl:repaintPending", this);
853 pending_repaint_ = false;
854 }
[email protected]29037ce52013-05-06 22:44:16855 }
856
[email protected]bfc05f22013-10-19 17:55:16857 if (size_changed) {
858 TRACE_EVENT0("media", "WebMediaPlayerImpl:clientSizeChanged");
[email protected]29037ce52013-05-06 22:44:16859 GetClient()->sizeChanged();
[email protected]bfc05f22013-10-19 17:55:16860 }
[email protected]29037ce52013-05-06 22:44:16861
[email protected]bfc05f22013-10-19 17:55:16862 TRACE_EVENT0("media", "WebMediaPlayerImpl:clientRepaint");
[email protected]29037ce52013-05-06 22:44:16863 GetClient()->repaint();
[email protected]8931c41a2009-07-07 17:31:49864}
865
[email protected]a9590c22011-03-16 16:57:02866void WebMediaPlayerImpl::OnPipelineSeek(PipelineStatus status) {
[email protected]e82c0e352013-03-01 01:53:46867 DCHECK(main_loop_->BelongsToCurrentThread());
[email protected]a8e2cb82012-08-17 00:02:39868 starting_ = false;
[email protected]5d11eff2011-09-15 00:06:06869 seeking_ = false;
870 if (pending_seek_) {
871 pending_seek_ = false;
872 seek(pending_seek_seconds_);
873 return;
874 }
875
[email protected]10a64d92012-04-10 21:08:02876 if (status != media::PIPELINE_OK) {
877 OnPipelineError(status);
878 return;
[email protected]96706912009-07-15 17:18:05879 }
[email protected]10a64d92012-04-10 21:08:02880
881 // Update our paused time.
882 if (paused_)
[email protected]f7c0ada02012-07-23 08:42:50883 paused_time_ = pipeline_->GetMediaTime();
[email protected]10a64d92012-04-10 21:08:02884
885 GetClient()->timeChanged();
[email protected]8931c41a2009-07-07 17:31:49886}
887
[email protected]6954fe12013-01-03 03:22:32888void WebMediaPlayerImpl::OnPipelineEnded() {
[email protected]e82c0e352013-03-01 01:53:46889 DCHECK(main_loop_->BelongsToCurrentThread());
[email protected]10a64d92012-04-10 21:08:02890 GetClient()->timeChanged();
[email protected]576537842009-08-12 23:52:05891}
892
[email protected]a9590c22011-03-16 16:57:02893void WebMediaPlayerImpl::OnPipelineError(PipelineStatus error) {
[email protected]e82c0e352013-03-01 01:53:46894 DCHECK(main_loop_->BelongsToCurrentThread());
[email protected]be57ee52013-05-28 22:27:27895 DCHECK_NE(error, media::PIPELINE_OK);
[email protected]a8e2cb82012-08-17 00:02:39896
897 if (ready_state_ == WebMediaPlayer::ReadyStateHaveNothing) {
898 // Any error that occurs before reaching ReadyStateHaveMetadata should
899 // be considered a format error.
900 SetNetworkState(WebMediaPlayer::NetworkStateFormatError);
901 Repaint();
902 return;
903 }
904
[email protected]be57ee52013-05-28 22:27:27905 SetNetworkState(PipelineErrorToNetworkState(error));
[email protected]a9590c22011-03-16 16:57:02906
[email protected]be57ee52013-05-28 22:27:27907 if (error == media::PIPELINE_ERROR_DECRYPT)
[email protected]f3a1d40d2013-06-25 22:12:50908 EmeUMAHistogramCounts(current_key_system_, "DecryptError", 1);
[email protected]bb2c1f32009-08-14 04:14:50909
910 // Repaint to trigger UI update.
911 Repaint();
[email protected]db190487d2009-07-30 18:51:52912}
913
[email protected]a8e2cb82012-08-17 00:02:39914void WebMediaPlayerImpl::OnPipelineBufferingState(
915 media::Pipeline::BufferingState buffering_state) {
916 DVLOG(1) << "OnPipelineBufferingState(" << buffering_state << ")";
917
918 switch (buffering_state) {
919 case media::Pipeline::kHaveMetadata:
920 SetReadyState(WebMediaPlayer::ReadyStateHaveMetadata);
[email protected]21c3f7502013-03-23 03:29:51921
[email protected]21c3f7502013-03-23 03:29:51922 if (hasVideo() && GetClient()->needsWebLayerForVideo()) {
923 DCHECK(!video_weblayer_);
924 video_weblayer_.reset(
925 new webkit::WebLayerImpl(cc::VideoLayer::Create(this)));
926 GetClient()->setWebLayer(video_weblayer_.get());
927 }
[email protected]a8e2cb82012-08-17 00:02:39928 break;
929 case media::Pipeline::kPrerollCompleted:
[email protected]a06d9e972013-06-20 08:43:47930 // Only transition to ReadyStateHaveEnoughData if we don't have
931 // any pending seeks because the transition can cause Blink to
932 // report that the most recent seek has completed.
933 if (!pending_seek_)
934 SetReadyState(WebMediaPlayer::ReadyStateHaveEnoughData);
[email protected]a8e2cb82012-08-17 00:02:39935 break;
936 }
937
938 // Repaint to trigger UI update.
939 Repaint();
940}
941
[email protected]ef8394c2013-08-21 20:26:30942void WebMediaPlayerImpl::OnDemuxerOpened() {
[email protected]e82c0e352013-03-01 01:53:46943 DCHECK(main_loop_->BelongsToCurrentThread());
[email protected]ef8394c2013-08-21 20:26:30944 GetClient()->mediaSourceOpened(new WebMediaSourceImpl(
[email protected]5f811a2d2013-03-15 23:54:51945 chunk_demuxer_, base::Bind(&LogMediaSourceError, media_log_)));
[email protected]81bb3322011-07-21 15:55:50946}
947
[email protected]fecb5fe2013-06-19 00:52:13948void WebMediaPlayerImpl::OnKeyAdded(const std::string& session_id) {
[email protected]e82c0e352013-03-01 01:53:46949 DCHECK(main_loop_->BelongsToCurrentThread());
[email protected]f3a1d40d2013-06-25 22:12:50950 EmeUMAHistogramCounts(current_key_system_, "KeyAdded", 1);
[email protected]fecb5fe2013-06-19 00:52:13951 GetClient()->keyAdded(current_key_system_,
[email protected]cbdc8c2b2012-06-16 01:27:36952 WebString::fromUTF8(session_id));
953}
954
[email protected]3a41ebb2013-10-08 00:25:03955void WebMediaPlayerImpl::OnNeedKey(const std::string& type,
[email protected]322d22c2013-08-26 18:50:41956 const std::vector<uint8>& init_data) {
[email protected]e82c0e352013-03-01 01:53:46957 DCHECK(main_loop_->BelongsToCurrentThread());
[email protected]cbdc8c2b2012-06-16 01:27:36958
[email protected]47ebb0e2012-11-30 08:28:29959 // Do not fire NeedKey event if encrypted media is not enabled.
960 if (!decryptor_)
961 return;
962
[email protected]2ca7d5c2012-10-23 07:30:54963 UMA_HISTOGRAM_COUNTS(kMediaEme + std::string("NeedKey"), 1);
964
[email protected]c8d40282012-10-27 07:23:13965 DCHECK(init_data_type_.empty() || type.empty() || type == init_data_type_);
966 if (init_data_type_.empty())
967 init_data_type_ = type;
968
[email protected]322d22c2013-08-26 18:50:41969 const uint8* init_data_ptr = init_data.empty() ? NULL : &init_data[0];
[email protected]fecb5fe2013-06-19 00:52:13970 GetClient()->keyNeeded(WebString(),
[email protected]3a41ebb2013-10-08 00:25:03971 WebString(),
[email protected]322d22c2013-08-26 18:50:41972 init_data_ptr,
973 init_data.size());
[email protected]cbdc8c2b2012-06-16 01:27:36974}
975
[email protected]71537722013-05-23 06:47:53976scoped_ptr<media::TextTrack>
977WebMediaPlayerImpl::OnTextTrack(media::TextKind kind,
978 const std::string& label,
979 const std::string& language) {
980 typedef WebInbandTextTrackImpl::Kind webkind_t;
981 const webkind_t webkind = static_cast<webkind_t>(kind);
982 const WebKit::WebString weblabel = WebKit::WebString::fromUTF8(label);
983 const WebKit::WebString weblanguage = WebKit::WebString::fromUTF8(language);
984
985 WebInbandTextTrackImpl* const text_track =
986 new WebInbandTextTrackImpl(webkind, weblabel, weblanguage,
987 text_track_index_++);
[email protected]71537722013-05-23 06:47:53988
[email protected]2fb8aa2dd2013-07-08 21:23:35989 return scoped_ptr<media::TextTrack>(new TextTrackImpl(GetClient(),
990 text_track));
[email protected]71537722013-05-23 06:47:53991}
992
[email protected]fecb5fe2013-06-19 00:52:13993void WebMediaPlayerImpl::OnKeyError(const std::string& session_id,
[email protected]15b05a72013-05-30 00:40:57994 media::MediaKeys::KeyError error_code,
[email protected]cbdc8c2b2012-06-16 01:27:36995 int system_code) {
[email protected]e82c0e352013-03-01 01:53:46996 DCHECK(main_loop_->BelongsToCurrentThread());
[email protected]cbdc8c2b2012-06-16 01:27:36997
[email protected]f3a1d40d2013-06-25 22:12:50998 EmeUMAHistogramEnumeration(current_key_system_, "KeyError",
[email protected]fecb5fe2013-06-19 00:52:13999 error_code, media::MediaKeys::kMaxKeyError);
[email protected]2ca7d5c2012-10-23 07:30:541000
[email protected]cbdc8c2b2012-06-16 01:27:361001 GetClient()->keyError(
[email protected]fecb5fe2013-06-19 00:52:131002 current_key_system_,
[email protected]cbdc8c2b2012-06-16 01:27:361003 WebString::fromUTF8(session_id),
1004 static_cast<WebKit::WebMediaPlayerClient::MediaKeyErrorCode>(error_code),
1005 system_code);
1006}
1007
[email protected]fecb5fe2013-06-19 00:52:131008void WebMediaPlayerImpl::OnKeyMessage(const std::string& session_id,
[email protected]0a81bdb2013-06-29 23:18:061009 const std::vector<uint8>& message,
[email protected]abd36b3af2012-12-22 03:42:021010 const std::string& default_url) {
[email protected]e82c0e352013-03-01 01:53:461011 DCHECK(main_loop_->BelongsToCurrentThread());
[email protected]cbdc8c2b2012-06-16 01:27:361012
[email protected]abd36b3af2012-12-22 03:42:021013 const GURL default_url_gurl(default_url);
1014 DLOG_IF(WARNING, !default_url.empty() && !default_url_gurl.is_valid())
1015 << "Invalid URL in default_url: " << default_url;
1016
[email protected]fecb5fe2013-06-19 00:52:131017 GetClient()->keyMessage(current_key_system_,
[email protected]cbdc8c2b2012-06-16 01:27:361018 WebString::fromUTF8(session_id),
[email protected]33325ff2013-07-01 07:49:361019 message.empty() ? NULL : &message[0],
[email protected]65a8c102012-12-15 00:56:571020 message.size(),
[email protected]abd36b3af2012-12-22 03:42:021021 default_url_gurl);
[email protected]4205f0aab2012-04-26 04:33:061022}
1023
[email protected]5bb69ef2011-12-23 16:29:091024void WebMediaPlayerImpl::SetOpaque(bool opaque) {
[email protected]e82c0e352013-03-01 01:53:461025 DCHECK(main_loop_->BelongsToCurrentThread());
[email protected]5bb69ef2011-12-23 16:29:091026
1027 GetClient()->setOpaque(opaque);
1028}
1029
[email protected]d250190da3b2012-07-23 22:57:301030void WebMediaPlayerImpl::DataSourceInitialized(const GURL& gurl, bool success) {
[email protected]e82c0e352013-03-01 01:53:461031 DCHECK(main_loop_->BelongsToCurrentThread());
[email protected]a9415292012-01-19 19:55:201032
[email protected]d250190da3b2012-07-23 22:57:301033 if (!success) {
[email protected]ef405f66b2012-04-18 02:39:551034 SetNetworkState(WebMediaPlayer::NetworkStateFormatError);
[email protected]a9415292012-01-19 19:55:201035 Repaint();
1036 return;
1037 }
1038
[email protected]ef8394c2013-08-21 20:26:301039 StartPipeline();
[email protected]a9415292012-01-19 19:55:201040}
1041
[email protected]122f40252012-06-12 05:01:561042void WebMediaPlayerImpl::NotifyDownloading(bool is_downloading) {
1043 if (!is_downloading && network_state_ == WebMediaPlayer::NetworkStateLoading)
1044 SetNetworkState(WebMediaPlayer::NetworkStateIdle);
1045 else if (is_downloading && network_state_ == WebMediaPlayer::NetworkStateIdle)
1046 SetNetworkState(WebMediaPlayer::NetworkStateLoading);
1047 media_log_->AddEvent(
1048 media_log_->CreateBooleanEvent(
1049 media::MediaLogEvent::NETWORK_ACTIVITY_SET,
1050 "is_downloading_data", is_downloading));
1051}
1052
[email protected]ef8394c2013-08-21 20:26:301053void WebMediaPlayerImpl::StartPipeline() {
[email protected]ddbc6ff2013-04-19 15:28:331054 const CommandLine* cmd_line = CommandLine::ForCurrentProcess();
[email protected]b573f952013-06-04 10:50:091055 bool increase_preroll_on_underflow = true;
[email protected]ddbc6ff2013-04-19 15:28:331056
[email protected]0814ac62013-06-07 21:01:291057 // Keep track if this is a MSE or non-MSE playback.
[email protected]ef8394c2013-08-21 20:26:301058 UMA_HISTOGRAM_BOOLEAN("Media.MSE.Playback",
1059 (load_type_ == LoadTypeMediaSource));
[email protected]0814ac62013-06-07 21:01:291060
[email protected]ddbc6ff2013-04-19 15:28:331061 // Figure out which demuxer to use.
[email protected]ef8394c2013-08-21 20:26:301062 if (load_type_ != LoadTypeMediaSource) {
[email protected]ddbc6ff2013-04-19 15:28:331063 DCHECK(!chunk_demuxer_);
[email protected]f5443ef72013-04-22 04:03:381064 DCHECK(data_source_);
1065
1066 demuxer_.reset(new media::FFmpegDemuxer(
[email protected]c1330c82013-06-06 02:23:251067 media_loop_, data_source_.get(),
[email protected]3a41ebb2013-10-08 00:25:031068 BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnNeedKey),
[email protected]1e931f62013-07-31 23:25:521069 media_log_));
[email protected]ddbc6ff2013-04-19 15:28:331070 } else {
[email protected]f5443ef72013-04-22 04:03:381071 DCHECK(!chunk_demuxer_);
1072 DCHECK(!data_source_);
1073
[email protected]7afb1bb32013-06-29 14:27:101074 media::AddTextTrackCB add_text_track_cb;
1075
1076 if (cmd_line->HasSwitch(switches::kEnableInbandTextTracks)) {
1077 add_text_track_cb =
1078 base::Bind(&WebMediaPlayerImpl::OnTextTrack, base::Unretained(this));
1079 }
1080
[email protected]f5443ef72013-04-22 04:03:381081 chunk_demuxer_ = new media::ChunkDemuxer(
[email protected]ef8394c2013-08-21 20:26:301082 BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnDemuxerOpened),
[email protected]3a41ebb2013-10-08 00:25:031083 BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnNeedKey),
[email protected]7afb1bb32013-06-29 14:27:101084 add_text_track_cb,
[email protected]f5443ef72013-04-22 04:03:381085 base::Bind(&LogMediaSourceError, media_log_));
1086 demuxer_.reset(chunk_demuxer_);
[email protected]ddbc6ff2013-04-19 15:28:331087
[email protected]6314f1b2013-08-12 11:14:011088#if !defined(OS_CHROMEOS)
1089 // Disable GpuVideoDecoder creation on platforms other than CrOS until
[email protected]67908292013-08-03 12:17:151090 // they support codec config changes.
[email protected]ddbc6ff2013-04-19 15:28:331091 // TODO(acolwell): Remove this once http://crbug.com/151045 is fixed.
1092 gpu_factories_ = NULL;
[email protected]67908292013-08-03 12:17:151093#endif
[email protected]b573f952013-06-04 10:50:091094
1095 // Disable preroll increases on underflow since the web application has no
1096 // way to detect that this is happening and runs the risk of triggering
1097 // unwanted garbage collection if it is to aggressive about appending data.
1098 // TODO(acolwell): Remove this once http://crbug.com/144683 is fixed.
1099 increase_preroll_on_underflow = false;
[email protected]ddbc6ff2013-04-19 15:28:331100 }
1101
[email protected]f5443ef72013-04-22 04:03:381102 scoped_ptr<media::FilterCollection> filter_collection(
1103 new media::FilterCollection());
1104 filter_collection->SetDemuxer(demuxer_.get());
1105
[email protected]ddbc6ff2013-04-19 15:28:331106 // Figure out if EME is enabled.
1107 media::SetDecryptorReadyCB set_decryptor_ready_cb;
1108 if (decryptor_) {
1109 set_decryptor_ready_cb = base::Bind(&ProxyDecryptor::SetDecryptorReadyCB,
1110 base::Unretained(decryptor_.get()));
1111 }
1112
1113 // Create our audio decoders and renderer.
1114 ScopedVector<media::AudioDecoder> audio_decoders;
[email protected]c1330c82013-06-06 02:23:251115 audio_decoders.push_back(new media::FFmpegAudioDecoder(media_loop_));
[email protected]ddbc6ff2013-04-19 15:28:331116 if (cmd_line->HasSwitch(switches::kEnableOpusPlayback)) {
[email protected]c1330c82013-06-06 02:23:251117 audio_decoders.push_back(new media::OpusAudioDecoder(media_loop_));
[email protected]ddbc6ff2013-04-19 15:28:331118 }
1119
1120 scoped_ptr<media::AudioRenderer> audio_renderer(
[email protected]c1330c82013-06-06 02:23:251121 new media::AudioRendererImpl(media_loop_,
[email protected]ff875be52013-06-02 23:47:381122 audio_source_provider_.get(),
[email protected]ddbc6ff2013-04-19 15:28:331123 audio_decoders.Pass(),
[email protected]b573f952013-06-04 10:50:091124 set_decryptor_ready_cb,
1125 increase_preroll_on_underflow));
[email protected]ddbc6ff2013-04-19 15:28:331126 filter_collection->SetAudioRenderer(audio_renderer.Pass());
1127
1128 // Create our video decoders and renderer.
1129 ScopedVector<media::VideoDecoder> video_decoders;
1130
[email protected]96cb47d02013-08-16 07:34:521131 if (gpu_factories_.get()) {
1132 video_decoders.push_back(
1133 new media::GpuVideoDecoder(gpu_factories_, media_log_));
1134 }
[email protected]ddbc6ff2013-04-19 15:28:331135
[email protected]ddbc6ff2013-04-19 15:28:331136 // TODO(phajdan.jr): Remove ifdefs when libvpx with vp9 support is released
1137 // (http://crbug.com/174287) .
1138#if !defined(MEDIA_DISABLE_LIBVPX)
[email protected]b150b5532013-06-15 00:50:541139 video_decoders.push_back(new media::VpxVideoDecoder(media_loop_));
[email protected]ddbc6ff2013-04-19 15:28:331140#endif // !defined(MEDIA_DISABLE_LIBVPX)
1141
[email protected]c1330c82013-06-06 02:23:251142 video_decoders.push_back(new media::FFmpegVideoDecoder(media_loop_));
[email protected]6ac955b2013-04-19 23:43:321143
[email protected]ddbc6ff2013-04-19 15:28:331144 scoped_ptr<media::VideoRenderer> video_renderer(
1145 new media::VideoRendererBase(
[email protected]c1330c82013-06-06 02:23:251146 media_loop_,
[email protected]ddbc6ff2013-04-19 15:28:331147 video_decoders.Pass(),
1148 set_decryptor_ready_cb,
1149 base::Bind(&WebMediaPlayerImpl::FrameReady, base::Unretained(this)),
1150 BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::SetOpaque),
1151 true));
1152 filter_collection->SetVideoRenderer(video_renderer.Pass());
1153
[email protected]f5443ef72013-04-22 04:03:381154 // ... and we're ready to go!
1155 starting_ = true;
1156 pipeline_->Start(
1157 filter_collection.Pass(),
1158 BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnPipelineEnded),
1159 BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnPipelineError),
1160 BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnPipelineSeek),
1161 BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnPipelineBufferingState),
1162 BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnDurationChange));
1163}
1164
1165void WebMediaPlayerImpl::SetNetworkState(WebMediaPlayer::NetworkState state) {
1166 DCHECK(main_loop_->BelongsToCurrentThread());
1167 DVLOG(1) << "SetNetworkState: " << state;
1168 network_state_ = state;
1169 // Always notify to ensure client has the latest value.
1170 GetClient()->networkStateChanged();
1171}
1172
1173void WebMediaPlayerImpl::SetReadyState(WebMediaPlayer::ReadyState state) {
1174 DCHECK(main_loop_->BelongsToCurrentThread());
1175 DVLOG(1) << "SetReadyState: " << state;
1176
1177 if (state == WebMediaPlayer::ReadyStateHaveEnoughData &&
1178 is_local_source_ &&
1179 network_state_ == WebMediaPlayer::NetworkStateLoading)
1180 SetNetworkState(WebMediaPlayer::NetworkStateLoaded);
1181
1182 ready_state_ = state;
1183 // Always notify to ensure client has the latest value.
1184 GetClient()->readyStateChanged();
1185}
1186
1187void WebMediaPlayerImpl::Destroy() {
1188 DCHECK(main_loop_->BelongsToCurrentThread());
1189
1190 // Abort any pending IO so stopping the pipeline doesn't get blocked.
1191 if (data_source_)
1192 data_source_->Abort();
1193 if (chunk_demuxer_) {
1194 chunk_demuxer_->Shutdown();
1195 chunk_demuxer_ = NULL;
1196 }
1197
[email protected]ff875be52013-06-02 23:47:381198 if (gpu_factories_.get()) {
[email protected]f5443ef72013-04-22 04:03:381199 gpu_factories_->Abort();
1200 gpu_factories_ = NULL;
1201 }
1202
1203 // Make sure to kill the pipeline so there's no more media threads running.
1204 // Note: stopping the pipeline might block for a long time.
1205 base::WaitableEvent waiter(false, false);
1206 pipeline_->Stop(base::Bind(
1207 &base::WaitableEvent::Signal, base::Unretained(&waiter)));
1208 waiter.Wait();
1209
1210 // Let V8 know we are not using extra resources anymore.
1211 if (incremented_externally_allocated_memory_) {
1212 v8::V8::AdjustAmountOfExternalAllocatedMemory(-kPlayerExtraMemory);
1213 incremented_externally_allocated_memory_ = false;
1214 }
1215
[email protected]f5443ef72013-04-22 04:03:381216 // Release any final references now that everything has stopped.
[email protected]a3702c52013-05-09 05:40:301217 pipeline_.reset();
[email protected]f5443ef72013-04-22 04:03:381218 demuxer_.reset();
[email protected]cccbd0f62013-04-26 18:39:591219 data_source_.reset();
[email protected]f5443ef72013-04-22 04:03:381220}
1221
1222WebKit::WebMediaPlayerClient* WebMediaPlayerImpl::GetClient() {
1223 DCHECK(main_loop_->BelongsToCurrentThread());
1224 DCHECK(client_);
1225 return client_;
1226}
1227
1228WebKit::WebAudioSourceProvider* WebMediaPlayerImpl::audioSourceProvider() {
[email protected]ff875be52013-06-02 23:47:381229 return audio_source_provider_.get();
[email protected]f5443ef72013-04-22 04:03:381230}
1231
1232void WebMediaPlayerImpl::IncrementExternallyAllocatedMemory() {
1233 DCHECK(main_loop_->BelongsToCurrentThread());
1234 incremented_externally_allocated_memory_ = true;
1235 v8::V8::AdjustAmountOfExternalAllocatedMemory(kPlayerExtraMemory);
1236}
1237
1238double WebMediaPlayerImpl::GetPipelineDuration() const {
1239 base::TimeDelta duration = pipeline_->GetMediaDuration();
1240
1241 // Return positive infinity if the resource is unbounded.
1242 // http://www.whatwg.org/specs/web-apps/current-work/multipage/video.html#dom-media-duration
1243 if (duration == media::kInfiniteDuration())
1244 return std::numeric_limits<double>::infinity();
1245
1246 return duration.InSecondsF();
1247}
1248
1249void WebMediaPlayerImpl::OnDurationChange() {
1250 if (ready_state_ == WebMediaPlayer::ReadyStateHaveNothing)
1251 return;
1252
1253 GetClient()->durationChanged();
1254}
1255
1256void WebMediaPlayerImpl::FrameReady(
1257 const scoped_refptr<media::VideoFrame>& frame) {
1258 base::AutoLock auto_lock(lock_);
[email protected]29037ce52013-05-06 22:44:161259
[email protected]bfc05f22013-10-19 17:55:161260 if (current_frame_ &&
[email protected]29037ce52013-05-06 22:44:161261 current_frame_->natural_size() != frame->natural_size() &&
1262 !pending_size_change_) {
1263 pending_size_change_ = true;
1264 }
1265
[email protected]bfc05f22013-10-19 17:55:161266 DoneWaitingForPaint(false);
[email protected]c46a9f42013-10-16 03:28:181267
[email protected]f5443ef72013-04-22 04:03:381268 current_frame_ = frame;
[email protected]c46a9f42013-10-16 03:28:181269 current_frame_painted_ = false;
[email protected]bfc05f22013-10-19 17:55:161270 TRACE_EVENT_FLOW_BEGIN0("media", "WebMediaPlayerImpl:waitingForPaint", this);
[email protected]f5443ef72013-04-22 04:03:381271
1272 if (pending_repaint_)
1273 return;
1274
[email protected]bfc05f22013-10-19 17:55:161275 TRACE_EVENT_ASYNC_BEGIN0("media", "WebMediaPlayerImpl:repaintPending", this);
[email protected]f5443ef72013-04-22 04:03:381276 pending_repaint_ = true;
1277 main_loop_->PostTask(FROM_HERE, base::Bind(
1278 &WebMediaPlayerImpl::Repaint, AsWeakPtr()));
[email protected]ddbc6ff2013-04-19 15:28:331279}
1280
[email protected]bfc05f22013-10-19 17:55:161281void WebMediaPlayerImpl::DoneWaitingForPaint(bool painting_frame) {
1282 lock_.AssertAcquired();
1283 if (!current_frame_ || current_frame_painted_)
1284 return;
1285
1286 TRACE_EVENT_FLOW_END0("media", "WebMediaPlayerImpl:waitingForPaint", this);
1287
1288 if (painting_frame) {
1289 current_frame_painted_ = true;
1290 return;
1291 }
1292
1293 // The frame wasn't painted, but we aren't waiting for a Repaint() call so
1294 // assume that the frame wasn't painted because the video wasn't visible.
1295 if (!pending_repaint_)
1296 return;
1297
1298 // The |current_frame_| wasn't painted, it is being replaced, and we haven't
1299 // even gotten the chance to request a repaint for it yet. Mark it as dropped.
1300 TRACE_EVENT0("media", "WebMediaPlayerImpl:frameDropped");
1301 DVLOG(1) << "Frame dropped before being painted: "
1302 << current_frame_->GetTimestamp().InSecondsF();
1303 if (frames_dropped_before_paint_ < kuint32max)
1304 frames_dropped_before_paint_++;
1305}
1306
[email protected]5e35a8d2013-07-10 19:37:211307} // namespace content