blob: 56c467dd8a71b5864fdab6879dadd22aa228e9b0 [file] [log] [blame]
[email protected]85a37afd2013-05-30 22:51:151// Copyright 2013 The Chromium Authors. All rights reserved.
[email protected]891acc92009-04-27 19:56:412// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
[email protected]ec9212f2008-12-18 21:40:364
acolwell9e0840d2014-09-06 19:01:325#include "media/blink/webmediaplayer_impl.h"
[email protected]8931c41a2009-07-07 17:31:496
[email protected]c2a45e242013-02-15 20:24:587#include <algorithm>
[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]7502ef12014-01-25 01:19:2714#include "base/callback_helpers.h"
[email protected]ca04095f2014-02-07 10:23:5615#include "base/debug/alias.h"
[email protected]926f8fd2013-04-12 20:27:5316#include "base/debug/crash_logging.h"
[email protected]bfc05f22013-10-19 17:55:1617#include "base/debug/trace_event.h"
dalecurtisdfe0527f22014-10-07 20:52:0118#include "base/float_util.h"
[email protected]7ccb7072013-06-10 20:56:2819#include "base/message_loop/message_loop_proxy.h"
[email protected]b0b258f2011-11-08 00:34:2320#include "base/metrics/histogram.h"
acolwellb4034942014-08-28 15:42:4321#include "base/single_thread_task_runner.h"
[email protected]cf02541b2012-04-11 08:02:1722#include "base/synchronization/waitable_event.h"
[email protected]38564622014-08-19 02:47:1823#include "cc/blink/web_layer_impl.h"
[email protected]21c3f7502013-03-23 03:29:5124#include "cc/layers/video_layer.h"
[email protected]6523b242013-03-13 11:10:0725#include "gpu/GLES2/gl2extchromium.h"
[email protected]df41e252014-02-03 23:39:5026#include "gpu/command_buffer/common/mailbox_holder.h"
[email protected]e4fc09e2012-04-06 03:17:4427#include "media/audio/null_audio_sink.h"
[email protected]f9a428742014-03-28 04:20:2628#include "media/base/audio_hardware_config.h"
[email protected]2eccbed2014-01-10 05:15:5329#include "media/base/bind_to_current_loop.h"
[email protected]32da1002010-03-03 21:57:3530#include "media/base/limits.h"
[email protected]090f7312011-08-05 23:26:4031#include "media/base/media_log.h"
[email protected]d399866c2012-01-18 09:30:3232#include "media/base/pipeline.h"
[email protected]8a561062013-11-22 01:19:3133#include "media/base/text_renderer.h"
[email protected]e81283bb2010-08-31 18:01:2134#include "media/base/video_frame.h"
acolwell9e0840d2014-09-06 19:01:3235#include "media/blink/buffered_data_source.h"
36#include "media/blink/encrypted_media_player_support.h"
37#include "media/blink/texttrack_impl.h"
38#include "media/blink/webaudiosourceprovider_impl.h"
xhwang97de4202014-11-25 08:44:0139#include "media/blink/webcontentdecryptionmodule_impl.h"
acolwell9e0840d2014-09-06 19:01:3240#include "media/blink/webinbandtexttrack_impl.h"
41#include "media/blink/webmediaplayer_delegate.h"
42#include "media/blink/webmediaplayer_params.h"
43#include "media/blink/webmediaplayer_util.h"
44#include "media/blink/webmediasource_impl.h"
[email protected]37136d162012-04-09 23:39:1945#include "media/filters/audio_renderer_impl.h"
[email protected]efe7cd22012-09-12 23:55:0146#include "media/filters/chunk_demuxer.h"
[email protected]ddbc6ff2013-04-19 15:28:3347#include "media/filters/ffmpeg_audio_decoder.h"
48#include "media/filters/ffmpeg_demuxer.h"
49#include "media/filters/ffmpeg_video_decoder.h"
[email protected]1cad8802013-08-13 16:54:3250#include "media/filters/gpu_video_accelerator_factories.h"
[email protected]b9a407e2013-07-24 07:30:0251#include "media/filters/gpu_video_decoder.h"
[email protected]ddbc6ff2013-04-19 15:28:3352#include "media/filters/opus_audio_decoder.h"
xhwangbe9da702014-08-23 21:44:5553#include "media/filters/renderer_impl.h"
[email protected]cc3933d2013-11-26 03:41:0254#include "media/filters/video_renderer_impl.h"
[email protected]ddbc6ff2013-04-19 15:28:3355#include "media/filters/vpx_video_decoder.h"
[email protected]745746d2013-08-23 02:09:1656#include "third_party/WebKit/public/platform/WebMediaSource.h"
[email protected]c10884462013-05-30 00:22:0957#include "third_party/WebKit/public/platform/WebRect.h"
58#include "third_party/WebKit/public/platform/WebSize.h"
59#include "third_party/WebKit/public/platform/WebString.h"
60#include "third_party/WebKit/public/platform/WebURL.h"
[email protected]80504652014-04-18 04:41:5061#include "third_party/WebKit/public/web/WebLocalFrame.h"
[email protected]65b85282014-03-31 23:32:3162#include "third_party/WebKit/public/web/WebSecurityOrigin.h"
[email protected]2255a9332013-06-17 05:12:3163#include "third_party/WebKit/public/web/WebView.h"
[email protected]b3f2b912009-04-09 16:18:5264
[email protected]180ef242013-11-07 06:50:4665using blink::WebCanvas;
66using blink::WebMediaPlayer;
67using blink::WebRect;
68using blink::WebSize;
69using blink::WebString;
[email protected]ec9212f2008-12-18 21:40:3670
[email protected]8931c41a2009-07-07 17:31:4971namespace {
72
[email protected]378f0b72009-08-11 17:11:4273// Limits the range of playback rate.
74//
75// TODO(kylep): Revisit these.
76//
77// Vista has substantially lower performance than XP or Windows7. If you speed
78// up a video too much, it can't keep up, and rendering stops updating except on
79// the time bar. For really high speeds, audio becomes a bottleneck and we just
80// use up the data we have, which may not achieve the speed requested, but will
81// not crash the tab.
82//
83// A very slow speed, ie 0.00000001x, causes the machine to lock up. (It seems
84// like a busy loop). It gets unresponsive, although its not completely dead.
85//
86// Also our timers are not very accurate (especially for ogg), which becomes
87// evident at low speeds and on Vista. Since other speeds are risky and outside
88// the norms, we think 1/16x to 16x is a safe and useful range for now.
[email protected]39bdde32013-04-17 17:44:2089const double kMinRate = 0.0625;
90const double kMaxRate = 16.0;
[email protected]378f0b72009-08-11 17:11:4291
[email protected]47c345b2014-07-22 10:31:5792class SyncPointClientImpl : public media::VideoFrame::SyncPointClient {
93 public:
94 explicit SyncPointClientImpl(
95 blink::WebGraphicsContext3D* web_graphics_context)
96 : web_graphics_context_(web_graphics_context) {}
dchengc24565478f2014-10-21 12:23:2797 ~SyncPointClientImpl() override {}
98 uint32 InsertSyncPoint() override {
[email protected]47c345b2014-07-22 10:31:5799 return web_graphics_context_->insertSyncPoint();
100 }
dchengc24565478f2014-10-21 12:23:27101 void WaitSyncPoint(uint32 sync_point) override {
[email protected]47c345b2014-07-22 10:31:57102 web_graphics_context_->waitSyncPoint(sync_point);
103 }
104
105 private:
106 blink::WebGraphicsContext3D* web_graphics_context_;
107};
108
[email protected]8931c41a2009-07-07 17:31:49109} // namespace
110
acolwell9e0840d2014-09-06 19:01:32111namespace media {
[email protected]add51772009-06-11 18:25:17112
[email protected]6683e1b2014-04-10 01:45:38113class BufferedDataSourceHostImpl;
114
[email protected]a8884632012-06-29 03:05:34115#define COMPILE_ASSERT_MATCHING_ENUM(name) \
[email protected]2ca7d5c2012-10-23 07:30:54116 COMPILE_ASSERT(static_cast<int>(WebMediaPlayer::CORSMode ## name) == \
[email protected]a8884632012-06-29 03:05:34117 static_cast<int>(BufferedResourceLoader::k ## name), \
[email protected]a5a01102012-06-06 17:01:24118 mismatching_enums)
119COMPILE_ASSERT_MATCHING_ENUM(Unspecified);
120COMPILE_ASSERT_MATCHING_ENUM(Anonymous);
121COMPILE_ASSERT_MATCHING_ENUM(UseCredentials);
122#undef COMPILE_ASSERT_MATCHING_ENUM
123
[email protected]2c539b82012-08-18 04:10:19124#define BIND_TO_RENDER_LOOP(function) \
acolwellb4034942014-08-28 15:42:43125 (DCHECK(main_task_runner_->BelongsToCurrentThread()), \
acolwell9e0840d2014-09-06 19:01:32126 BindToCurrentLoop(base::Bind(function, AsWeakPtr())))
[email protected]5983adb2012-10-24 00:12:00127
[email protected]4e982192014-06-21 13:35:45128#define BIND_TO_RENDER_LOOP1(function, arg1) \
acolwellb4034942014-08-28 15:42:43129 (DCHECK(main_task_runner_->BelongsToCurrentThread()), \
acolwell9e0840d2014-09-06 19:01:32130 BindToCurrentLoop(base::Bind(function, AsWeakPtr(), arg1)))
[email protected]4e982192014-06-21 13:35:45131
acolwell9e0840d2014-09-06 19:01:32132static void LogMediaSourceError(const scoped_refptr<MediaLog>& media_log,
[email protected]2ef99602012-12-08 04:22:21133 const std::string& error) {
134 media_log->AddEvent(media_log->CreateMediaSourceErrorEvent(error));
135}
136
[email protected]5b5bb9d2010-10-22 19:57:36137WebMediaPlayerImpl::WebMediaPlayerImpl(
[email protected]35b2a972014-04-04 15:50:22138 blink::WebLocalFrame* frame,
[email protected]180ef242013-11-07 06:50:46139 blink::WebMediaPlayerClient* client,
[email protected]b8976652011-10-26 23:46:55140 base::WeakPtr<WebMediaPlayerDelegate> delegate,
xhwangf94a634d2014-10-22 22:07:27141 scoped_ptr<Renderer> renderer,
xhwang16ff1362014-11-19 00:16:34142 scoped_ptr<CdmFactory> cdm_factory,
[email protected]e82b2bd2013-01-02 17:47:57143 const WebMediaPlayerParams& params)
[email protected]f6af7592014-02-28 10:09:11144 : frame_(frame),
[email protected]ef405f66b2012-04-18 02:39:55145 network_state_(WebMediaPlayer::NetworkStateEmpty),
146 ready_state_(WebMediaPlayer::ReadyStateHaveNothing),
acolwella5081a42014-08-28 23:42:52147 preload_(BufferedDataSource::AUTO),
acolwellb4034942014-08-28 15:42:43148 main_task_runner_(base::MessageLoopProxy::current()),
acolwell755d12d2014-08-30 01:09:19149 media_task_runner_(params.media_task_runner()),
150 media_log_(params.media_log()),
acolwellb4034942014-08-28 15:42:43151 pipeline_(media_task_runner_, media_log_.get()),
[email protected]f988d9b2014-07-25 00:35:43152 load_type_(LoadTypeURL),
[email protected]75e145a2014-04-15 17:44:32153 opaque_(false),
[email protected]49480902009-07-14 20:23:43154 paused_(true),
[email protected]b3766a22010-12-22 17:34:13155 seeking_(false),
[email protected]49480902009-07-14 20:23:43156 playback_rate_(0.0f),
scherkusd2c745b2014-09-04 05:03:40157 ended_(false),
[email protected]5d11eff2011-09-15 00:06:06158 pending_seek_(false),
[email protected]b1a975e2011-12-21 00:12:39159 pending_seek_seconds_(0.0f),
[email protected]ba7d5f92014-06-24 05:37:40160 should_notify_time_changed_(false),
[email protected]5badb082010-06-11 17:40:15161 client_(client),
[email protected]baff4512011-10-19 18:21:07162 delegate_(delegate),
[email protected]d726eddc2013-07-02 22:25:55163 defer_load_cb_(params.defer_load_cb()),
acolwell755d12d2014-08-30 01:09:19164 gpu_factories_(params.gpu_factories()),
[email protected]132dd57c2012-08-10 23:24:34165 supports_save_(true),
[email protected]f5443ef72013-04-22 04:03:38166 chunk_demuxer_(NULL),
acolwell755d12d2014-08-30 01:09:19167 compositor_task_runner_(params.compositor_task_runner()),
[email protected]dd061e12014-05-06 19:21:22168 compositor_(new VideoFrameCompositor(
[email protected]75e145a2014-04-15 17:44:32169 BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnNaturalSizeChanged),
[email protected]dd061e12014-05-06 19:21:22170 BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnOpacityChanged))),
[email protected]7bce1832014-01-09 00:01:22171 text_track_index_(0),
xhwang97de4202014-11-25 08:44:01172 encrypted_media_support_(
173 cdm_factory.Pass(),
174 client,
175 base::Bind(&WebMediaPlayerImpl::SetCdm, AsWeakPtr())),
xhwangf94a634d2014-10-22 22:07:27176 audio_hardware_config_(params.audio_hardware_config()),
177 renderer_(renderer.Pass()) {
acolwell755d12d2014-08-30 01:09:19178 // Threaded compositing isn't enabled universally yet.
dchengd3c60602014-09-03 17:14:37179 if (!compositor_task_runner_.get())
acolwell755d12d2014-08-30 01:09:19180 compositor_task_runner_ = base::MessageLoopProxy::current();
181
[email protected]c93eb0a62011-08-09 22:47:24182 media_log_->AddEvent(
acolwell9e0840d2014-09-06 19:01:32183 media_log_->CreateEvent(MediaLogEvent::WEBMEDIAPLAYER_CREATED));
[email protected]4e6be3f2009-05-07 02:24:44184
xhwangf94a634d2014-10-22 22:07:27185 // TODO(xhwang): When we use an external Renderer, many methods won't work,
186 // e.g. GetCurrentFrameFromCompositor(). Fix this in a future CL.
187 if (renderer_)
188 return;
189
[email protected]c50edb962013-10-19 18:05:07190 // |gpu_factories_| requires that its entry points be called on its
[email protected]b639a832013-12-20 21:12:39191 // |GetTaskRunner()|. Since |pipeline_| will own decoders created from the
[email protected]c50edb962013-10-19 18:05:07192 // factories, require that their message loops are identical.
dchengf70d95e2014-08-27 02:06:28193 DCHECK(!gpu_factories_.get() ||
acolwellb4034942014-08-28 15:42:43194 (gpu_factories_->GetTaskRunner() == media_task_runner_.get()));
[email protected]c50edb962013-10-19 18:05:07195
[email protected]ddbc6ff2013-04-19 15:28:33196 // Use the null sink if no sink was provided.
[email protected]4a914882013-01-10 00:43:48197 audio_source_provider_ = new WebAudioSourceProviderImpl(
[email protected]ff875be52013-06-02 23:47:38198 params.audio_renderer_sink().get()
199 ? params.audio_renderer_sink()
acolwell9e0840d2014-09-06 19:01:32200 : new NullAudioSink(media_task_runner_));
[email protected]ec9212f2008-12-18 21:40:36201}
202
[email protected]4e6be3f2009-05-07 02:24:44203WebMediaPlayerImpl::~WebMediaPlayerImpl() {
[email protected]ce70c982013-12-20 17:04:32204 client_->setWebLayer(NULL);
[email protected]21c3f7502013-03-23 03:29:51205
acolwellb4034942014-08-28 15:42:43206 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]c93eb0a62011-08-09 22:47:24207 media_log_->AddEvent(
acolwell9e0840d2014-09-06 19:01:32208 media_log_->CreateEvent(MediaLogEvent::WEBMEDIAPLAYER_DESTROYED));
[email protected]d43ed912009-02-03 04:52:53209
dalecurtis6d269ed2014-09-11 21:18:13210 if (delegate_)
[email protected]baff4512011-10-19 18:21:07211 delegate_->PlayerGone(this);
212
[email protected]f6af7592014-02-28 10:09:11213 // Abort any pending IO so stopping the pipeline doesn't get blocked.
214 if (data_source_)
215 data_source_->Abort();
216 if (chunk_demuxer_) {
217 chunk_demuxer_->Shutdown();
218 chunk_demuxer_ = NULL;
219 }
220
221 gpu_factories_ = NULL;
222
223 // Make sure to kill the pipeline so there's no more media threads running.
224 // Note: stopping the pipeline might block for a long time.
225 base::WaitableEvent waiter(false, false);
226 pipeline_.Stop(
227 base::Bind(&base::WaitableEvent::Signal, base::Unretained(&waiter)));
228 waiter.Wait();
229
[email protected]dd061e12014-05-06 19:21:22230 compositor_task_runner_->DeleteSoon(FROM_HERE, compositor_);
[email protected]ec9212f2008-12-18 21:40:36231}
232
[email protected]180ef242013-11-07 06:50:46233void WebMediaPlayerImpl::load(LoadType load_type, const blink::WebURL& url,
[email protected]62e5e682013-03-07 23:53:24234 CORSMode cors_mode) {
[email protected]2a06ca62014-06-04 13:59:52235 DVLOG(1) << __FUNCTION__ << "(" << load_type << ", " << url << ", "
236 << cors_mode << ")";
[email protected]d726eddc2013-07-02 22:25:55237 if (!defer_load_cb_.is_null()) {
238 defer_load_cb_.Run(base::Bind(
[email protected]ef8394c2013-08-21 20:26:30239 &WebMediaPlayerImpl::DoLoad, AsWeakPtr(), load_type, url, cors_mode));
[email protected]d726eddc2013-07-02 22:25:55240 return;
241 }
[email protected]ef8394c2013-08-21 20:26:30242 DoLoad(load_type, url, cors_mode);
[email protected]62e5e682013-03-07 23:53:24243}
244
[email protected]ef8394c2013-08-21 20:26:30245void WebMediaPlayerImpl::DoLoad(LoadType load_type,
[email protected]180ef242013-11-07 06:50:46246 const blink::WebURL& url,
[email protected]d726eddc2013-07-02 22:25:55247 CORSMode cors_mode) {
acolwellb4034942014-08-28 15:42:43248 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]d726eddc2013-07-02 22:25:55249
[email protected]62e5e682013-03-07 23:53:24250 GURL gurl(url);
[email protected]e2f6bba2014-06-09 20:08:07251 ReportMediaSchemeUma(gurl);
[email protected]62e5e682013-03-07 23:53:24252
[email protected]926f8fd2013-04-12 20:27:53253 // Set subresource URL for crash reporting.
254 base::debug::SetCrashKeyValue("subresource_url", gurl.spec());
255
[email protected]ef8394c2013-08-21 20:26:30256 load_type_ = load_type;
257
[email protected]62e5e682013-03-07 23:53:24258 SetNetworkState(WebMediaPlayer::NetworkStateLoading);
259 SetReadyState(WebMediaPlayer::ReadyStateHaveNothing);
260 media_log_->AddEvent(media_log_->CreateLoadEvent(url.spec()));
[email protected]d726eddc2013-07-02 22:25:55261
262 // Media source pipelines can start immediately.
[email protected]ef8394c2013-08-21 20:26:30263 if (load_type == LoadTypeMediaSource) {
[email protected]d726eddc2013-07-02 22:25:55264 supports_save_ = false;
[email protected]ef8394c2013-08-21 20:26:30265 StartPipeline();
[email protected]d726eddc2013-07-02 22:25:55266 return;
267 }
268
269 // Otherwise it's a regular request which requires resolving the URL first.
270 data_source_.reset(new BufferedDataSource(
[email protected]fee8a902014-06-03 13:43:36271 url,
272 static_cast<BufferedResourceLoader::CORSMode>(cors_mode),
acolwellb4034942014-08-28 15:42:43273 main_task_runner_,
[email protected]d726eddc2013-07-02 22:25:55274 frame_,
275 media_log_.get(),
[email protected]6683e1b2014-04-10 01:45:38276 &buffered_data_source_host_,
[email protected]d726eddc2013-07-02 22:25:55277 base::Bind(&WebMediaPlayerImpl::NotifyDownloading, AsWeakPtr())));
278 data_source_->Initialize(
[email protected]fee8a902014-06-03 13:43:36279 base::Bind(&WebMediaPlayerImpl::DataSourceInitialized, AsWeakPtr()));
[email protected]09c60222014-08-07 16:42:31280 data_source_->SetPreload(preload_);
[email protected]62e5e682013-03-07 23:53:24281}
282
[email protected]4e6be3f2009-05-07 02:24:44283void WebMediaPlayerImpl::play() {
[email protected]2a06ca62014-06-04 13:59:52284 DVLOG(1) << __FUNCTION__;
acolwellb4034942014-08-28 15:42:43285 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]d43ed912009-02-03 04:52:53286
[email protected]49480902009-07-14 20:23:43287 paused_ = false;
[email protected]f6af7592014-02-28 10:09:11288 pipeline_.SetPlaybackRate(playback_rate_);
[email protected]039b7542013-10-17 22:06:25289 if (data_source_)
290 data_source_->MediaIsPlaying();
[email protected]090f7312011-08-05 23:26:40291
acolwell9e0840d2014-09-06 19:01:32292 media_log_->AddEvent(media_log_->CreateEvent(MediaLogEvent::PLAY));
[email protected]baff4512011-10-19 18:21:07293
dalecurtis6d269ed2014-09-11 21:18:13294 if (delegate_ && playback_rate_ > 0)
[email protected]baff4512011-10-19 18:21:07295 delegate_->DidPlay(this);
[email protected]ec9212f2008-12-18 21:40:36296}
297
[email protected]4e6be3f2009-05-07 02:24:44298void WebMediaPlayerImpl::pause() {
[email protected]2a06ca62014-06-04 13:59:52299 DVLOG(1) << __FUNCTION__;
acolwellb4034942014-08-28 15:42:43300 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]d43ed912009-02-03 04:52:53301
dalecurtis6d269ed2014-09-11 21:18:13302 const bool was_already_paused = paused_ || playback_rate_ == 0;
[email protected]49480902009-07-14 20:23:43303 paused_ = true;
[email protected]f6af7592014-02-28 10:09:11304 pipeline_.SetPlaybackRate(0.0f);
[email protected]039b7542013-10-17 22:06:25305 if (data_source_)
306 data_source_->MediaIsPaused();
[email protected]f6af7592014-02-28 10:09:11307 paused_time_ = pipeline_.GetMediaTime();
[email protected]090f7312011-08-05 23:26:40308
acolwell9e0840d2014-09-06 19:01:32309 media_log_->AddEvent(media_log_->CreateEvent(MediaLogEvent::PAUSE));
[email protected]baff4512011-10-19 18:21:07310
dalecurtis6d269ed2014-09-11 21:18:13311 if (!was_already_paused && delegate_)
[email protected]baff4512011-10-19 18:21:07312 delegate_->DidPause(this);
[email protected]ec9212f2008-12-18 21:40:36313}
314
[email protected]574a1d62009-07-17 03:23:46315bool WebMediaPlayerImpl::supportsSave() const {
acolwellb4034942014-08-28 15:42:43316 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]132dd57c2012-08-10 23:24:34317 return supports_save_;
[email protected]574a1d62009-07-17 03:23:46318}
319
[email protected]39bdde32013-04-17 17:44:20320void WebMediaPlayerImpl::seek(double seconds) {
[email protected]2a06ca62014-06-04 13:59:52321 DVLOG(1) << __FUNCTION__ << "(" << seconds << ")";
acolwellb4034942014-08-28 15:42:43322 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]d43ed912009-02-03 04:52:53323
scherkusd2c745b2014-09-04 05:03:40324 ended_ = false;
325
[email protected]1bb666802013-11-28 06:12:08326 if (ready_state_ > WebMediaPlayer::ReadyStateHaveMetadata)
327 SetReadyState(WebMediaPlayer::ReadyStateHaveMetadata);
328
[email protected]bb8a70b2013-06-26 06:23:35329 base::TimeDelta seek_time = ConvertSecondsToTimestamp(seconds);
330
[email protected]d228aeec2014-06-20 19:16:49331 if (seeking_) {
[email protected]5d11eff2011-09-15 00:06:06332 pending_seek_ = true;
333 pending_seek_seconds_ = seconds;
[email protected]efe7cd22012-09-12 23:55:01334 if (chunk_demuxer_)
[email protected]bb8a70b2013-06-26 06:23:35335 chunk_demuxer_->CancelPendingSeek(seek_time);
[email protected]5d11eff2011-09-15 00:06:06336 return;
337 }
338
[email protected]c93eb0a62011-08-09 22:47:24339 media_log_->AddEvent(media_log_->CreateSeekEvent(seconds));
340
[email protected]44ff37c02009-10-24 01:03:03341 // Update our paused time.
Bartosz Fabianowski36c68322014-11-13 13:48:37342 if (paused_)
343 paused_time_ = seek_time;
[email protected]44ff37c02009-10-24 01:03:03344
[email protected]b3766a22010-12-22 17:34:13345 seeking_ = true;
346
[email protected]efe7cd22012-09-12 23:55:01347 if (chunk_demuxer_)
[email protected]bb8a70b2013-06-26 06:23:35348 chunk_demuxer_->StartWaitingForSeek(seek_time);
[email protected]020fba32011-06-29 16:37:46349
[email protected]44ff37c02009-10-24 01:03:03350 // Kick off the asynchronous seek!
[email protected]f6af7592014-02-28 10:09:11351 pipeline_.Seek(
[email protected]44ff37c02009-10-24 01:03:03352 seek_time,
[email protected]4e982192014-06-21 13:35:45353 BIND_TO_RENDER_LOOP1(&WebMediaPlayerImpl::OnPipelineSeeked, true));
[email protected]ec9212f2008-12-18 21:40:36354}
355
[email protected]39bdde32013-04-17 17:44:20356void WebMediaPlayerImpl::setRate(double rate) {
[email protected]2a06ca62014-06-04 13:59:52357 DVLOG(1) << __FUNCTION__ << "(" << rate << ")";
acolwellb4034942014-08-28 15:42:43358 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]d43ed912009-02-03 04:52:53359
[email protected]378f0b72009-08-11 17:11:42360 // TODO(kylep): Remove when support for negatives is added. Also, modify the
361 // following checks so rewind uses reasonable values also.
[email protected]39bdde32013-04-17 17:44:20362 if (rate < 0.0)
[email protected]378f0b72009-08-11 17:11:42363 return;
364
365 // Limit rates to reasonable values by clamping.
[email protected]39bdde32013-04-17 17:44:20366 if (rate != 0.0) {
[email protected]378f0b72009-08-11 17:11:42367 if (rate < kMinRate)
368 rate = kMinRate;
369 else if (rate > kMaxRate)
370 rate = kMaxRate;
dalecurtisbb761e12014-09-12 01:16:35371 if (playback_rate_ == 0 && !paused_ && delegate_)
dalecurtis6d269ed2014-09-11 21:18:13372 delegate_->DidPlay(this);
dalecurtisbb761e12014-09-12 01:16:35373 } else if (playback_rate_ != 0 && !paused_ && delegate_) {
dalecurtis6d269ed2014-09-11 21:18:13374 delegate_->DidPause(this);
[email protected]378f0b72009-08-11 17:11:42375 }
376
[email protected]49480902009-07-14 20:23:43377 playback_rate_ = rate;
378 if (!paused_) {
[email protected]f6af7592014-02-28 10:09:11379 pipeline_.SetPlaybackRate(rate);
[email protected]039b7542013-10-17 22:06:25380 if (data_source_)
381 data_source_->MediaPlaybackRateChanged(rate);
[email protected]49480902009-07-14 20:23:43382 }
[email protected]ec9212f2008-12-18 21:40:36383}
384
[email protected]39bdde32013-04-17 17:44:20385void WebMediaPlayerImpl::setVolume(double volume) {
[email protected]2a06ca62014-06-04 13:59:52386 DVLOG(1) << __FUNCTION__ << "(" << volume << ")";
acolwellb4034942014-08-28 15:42:43387 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]d43ed912009-02-03 04:52:53388
[email protected]f6af7592014-02-28 10:09:11389 pipeline_.SetVolume(volume);
[email protected]ec9212f2008-12-18 21:40:36390}
[email protected]f0a51fb52009-03-05 12:46:38391
[email protected]23a8b1d82011-04-05 16:28:20392#define COMPILE_ASSERT_MATCHING_ENUM(webkit_name, chromium_name) \
[email protected]ef405f66b2012-04-18 02:39:55393 COMPILE_ASSERT(static_cast<int>(WebMediaPlayer::webkit_name) == \
acolwella5081a42014-08-28 23:42:52394 static_cast<int>(BufferedDataSource::chromium_name), \
[email protected]474c37a2011-08-23 20:24:52395 mismatching_enums)
[email protected]ef405f66b2012-04-18 02:39:55396COMPILE_ASSERT_MATCHING_ENUM(PreloadNone, NONE);
397COMPILE_ASSERT_MATCHING_ENUM(PreloadMetaData, METADATA);
398COMPILE_ASSERT_MATCHING_ENUM(PreloadAuto, AUTO);
[email protected]a5a01102012-06-06 17:01:24399#undef COMPILE_ASSERT_MATCHING_ENUM
[email protected]23a8b1d82011-04-05 16:28:20400
[email protected]ef405f66b2012-04-18 02:39:55401void WebMediaPlayerImpl::setPreload(WebMediaPlayer::Preload preload) {
[email protected]2a06ca62014-06-04 13:59:52402 DVLOG(1) << __FUNCTION__ << "(" << preload << ")";
acolwellb4034942014-08-28 15:42:43403 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]4e6be3f2009-05-07 02:24:44404
acolwella5081a42014-08-28 23:42:52405 preload_ = static_cast<BufferedDataSource::Preload>(preload);
[email protected]b49beeb2013-03-01 20:04:00406 if (data_source_)
[email protected]09c60222014-08-07 16:42:31407 data_source_->SetPreload(preload_);
[email protected]4e6be3f2009-05-07 02:24:44408}
409
[email protected]4e6be3f2009-05-07 02:24:44410bool WebMediaPlayerImpl::hasVideo() const {
acolwellb4034942014-08-28 15:42:43411 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]d43ed912009-02-03 04:52:53412
[email protected]b8877772014-03-26 20:17:15413 return pipeline_metadata_.has_video;
[email protected]d43ed912009-02-03 04:52:53414}
415
[email protected]fc367af2009-08-14 23:06:35416bool WebMediaPlayerImpl::hasAudio() const {
acolwellb4034942014-08-28 15:42:43417 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]fc367af2009-08-14 23:06:35418
[email protected]b8877772014-03-26 20:17:15419 return pipeline_metadata_.has_audio;
[email protected]fc367af2009-08-14 23:06:35420}
421
[email protected]180ef242013-11-07 06:50:46422blink::WebSize WebMediaPlayerImpl::naturalSize() const {
acolwellb4034942014-08-28 15:42:43423 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]d43ed912009-02-03 04:52:53424
[email protected]b8877772014-03-26 20:17:15425 return blink::WebSize(pipeline_metadata_.natural_size);
[email protected]d43ed912009-02-03 04:52:53426}
427
[email protected]4e6be3f2009-05-07 02:24:44428bool WebMediaPlayerImpl::paused() const {
acolwellb4034942014-08-28 15:42:43429 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]d43ed912009-02-03 04:52:53430
[email protected]f6af7592014-02-28 10:09:11431 return pipeline_.GetPlaybackRate() == 0.0f;
[email protected]d43ed912009-02-03 04:52:53432}
433
[email protected]4e6be3f2009-05-07 02:24:44434bool WebMediaPlayerImpl::seeking() const {
acolwellb4034942014-08-28 15:42:43435 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]d43ed912009-02-03 04:52:53436
[email protected]ef405f66b2012-04-18 02:39:55437 if (ready_state_ == WebMediaPlayer::ReadyStateHaveNothing)
[email protected]0acebfa2009-08-21 22:45:40438 return false;
[email protected]67cd5052009-09-10 21:53:22439
[email protected]b3766a22010-12-22 17:34:13440 return seeking_;
[email protected]ec9212f2008-12-18 21:40:36441}
442
[email protected]39bdde32013-04-17 17:44:20443double WebMediaPlayerImpl::duration() const {
acolwellb4034942014-08-28 15:42:43444 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]39bdde32013-04-17 17:44:20445
446 if (ready_state_ == WebMediaPlayer::ReadyStateHaveNothing)
447 return std::numeric_limits<double>::quiet_NaN();
448
[email protected]39bdde32013-04-17 17:44:20449 return GetPipelineDuration();
[email protected]d43ed912009-02-03 04:52:53450}
451
[email protected]db66d0092014-04-16 07:15:12452double WebMediaPlayerImpl::timelineOffset() const {
acolwellb4034942014-08-28 15:42:43453 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]db66d0092014-04-16 07:15:12454
455 if (pipeline_metadata_.timeline_offset.is_null())
456 return std::numeric_limits<double>::quiet_NaN();
457
458 return pipeline_metadata_.timeline_offset.ToJsTime();
459}
460
[email protected]39bdde32013-04-17 17:44:20461double WebMediaPlayerImpl::currentTime() const {
acolwellb4034942014-08-28 15:42:43462 DCHECK(main_task_runner_->BelongsToCurrentThread());
scherkusd2c745b2014-09-04 05:03:40463 DCHECK_NE(ready_state_, WebMediaPlayer::ReadyStateHaveNothing);
464
465 // TODO(scherkus): Replace with an explicit ended signal to HTMLMediaElement,
466 // see http://crbug.com/409280
467 if (ended_)
468 return duration();
469
[email protected]f6af7592014-02-28 10:09:11470 return (paused_ ? paused_time_ : pipeline_.GetMediaTime()).InSecondsF();
[email protected]d43ed912009-02-03 04:52:53471}
472
[email protected]ef405f66b2012-04-18 02:39:55473WebMediaPlayer::NetworkState WebMediaPlayerImpl::networkState() const {
acolwellb4034942014-08-28 15:42:43474 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]ddb1e5a2010-12-13 20:10:45475 return network_state_;
476}
477
[email protected]ef405f66b2012-04-18 02:39:55478WebMediaPlayer::ReadyState WebMediaPlayerImpl::readyState() const {
acolwellb4034942014-08-28 15:42:43479 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]ddb1e5a2010-12-13 20:10:45480 return ready_state_;
481}
482
[email protected]02022fc2014-05-16 00:05:31483blink::WebTimeRanges WebMediaPlayerImpl::buffered() const {
acolwellb4034942014-08-28 15:42:43484 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]779a8322014-08-22 21:28:37485
acolwell9e0840d2014-09-06 19:01:32486 Ranges<base::TimeDelta> buffered_time_ranges =
[email protected]02022fc2014-05-16 00:05:31487 pipeline_.GetBufferedTimeRanges();
[email protected]779a8322014-08-22 21:28:37488
489 const base::TimeDelta duration = pipeline_.GetMediaDuration();
acolwell9e0840d2014-09-06 19:01:32490 if (duration != kInfiniteDuration()) {
[email protected]779a8322014-08-22 21:28:37491 buffered_data_source_host_.AddBufferedTimeRanges(
492 &buffered_time_ranges, duration);
493 }
[email protected]02022fc2014-05-16 00:05:31494 return ConvertToWebTimeRanges(buffered_time_ranges);
495}
496
philipjb0e6f3f2014-09-30 09:51:53497blink::WebTimeRanges WebMediaPlayerImpl::seekable() const {
acolwellb4034942014-08-28 15:42:43498 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]39bdde32013-04-17 17:44:20499
dalecurtis56359cb2014-10-28 00:06:29500 if (ready_state_ < WebMediaPlayer::ReadyStateHaveMetadata)
philipjb0e6f3f2014-09-30 09:51:53501 return blink::WebTimeRanges();
502
dalecurtis56359cb2014-10-28 00:06:29503 const double seekable_end = duration();
504
505 // Allow a special exception for seeks to zero for streaming sources with a
506 // finite duration; this allows looping to work.
507 const bool allow_seek_to_zero = data_source_ && data_source_->IsStreaming() &&
508 base::IsFinite(seekable_end);
509
510 // TODO(dalecurtis): Technically this allows seeking on media which return an
511 // infinite duration so long as DataSource::IsStreaming() is false. While not
512 // expected, disabling this breaks semi-live players, http://crbug.com/427412.
513 const blink::WebTimeRange seekable_range(
514 0.0, allow_seek_to_zero ? 0.0 : seekable_end);
philipjb0e6f3f2014-09-30 09:51:53515 return blink::WebTimeRanges(&seekable_range, 1);
[email protected]ec9212f2008-12-18 21:40:36516}
517
[email protected]5d2b3e4c2014-05-12 23:27:30518bool WebMediaPlayerImpl::didLoadingProgress() {
acolwellb4034942014-08-28 15:42:43519 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]6683e1b2014-04-10 01:45:38520 bool pipeline_progress = pipeline_.DidLoadingProgress();
521 bool data_progress = buffered_data_source_host_.DidLoadingProgress();
522 return pipeline_progress || data_progress;
[email protected]d43ed912009-02-03 04:52:53523}
524
[email protected]dd5c7972014-08-21 15:00:37525void WebMediaPlayerImpl::paint(blink::WebCanvas* canvas,
526 const blink::WebRect& rect,
[email protected]dd5c7972014-08-21 15:00:37527 unsigned char alpha,
528 SkXfermode::Mode mode) {
acolwellb4034942014-08-28 15:42:43529 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]dd061e12014-05-06 19:21:22530 TRACE_EVENT0("media", "WebMediaPlayerImpl:paint");
[email protected]4e6be3f2009-05-07 02:24:44531
[email protected]5e1502e2014-03-24 22:48:44532 // TODO(scherkus): Clarify paint() API contract to better understand when and
533 // why it's being called. For example, today paint() is called when:
534 // - We haven't reached HAVE_CURRENT_DATA and need to paint black
535 // - We're painting to a canvas
536 // See http://crbug.com/341225 http://crbug.com/342621 for details.
acolwell9e0840d2014-09-06 19:01:32537 scoped_refptr<VideoFrame> video_frame =
[email protected]dd061e12014-05-06 19:21:22538 GetCurrentFrameFromCompositor();
[email protected]0fe5d43b2014-01-24 23:32:45539
[email protected]b49beeb2013-03-01 20:04:00540 gfx::Rect gfx_rect(rect);
[email protected]f78c3e82014-08-08 01:24:47541
rileya54b8c1742014-09-16 02:20:42542 skcanvas_video_renderer_.Paint(video_frame,
[email protected]8bad1822014-08-09 05:52:38543 canvas,
544 gfx_rect,
545 alpha,
[email protected]dd5c7972014-08-21 15:00:37546 mode,
[email protected]8bad1822014-08-09 05:52:38547 pipeline_metadata_.video_rotation);
[email protected]ec9212f2008-12-18 21:40:36548}
[email protected]5df51652009-01-17 00:03:00549
[email protected]38259a7a82009-07-29 21:49:49550bool WebMediaPlayerImpl::hasSingleSecurityOrigin() const {
[email protected]b49beeb2013-03-01 20:04:00551 if (data_source_)
552 return data_source_->HasSingleOrigin();
[email protected]fcdb7462009-10-21 21:05:11553 return true;
[email protected]38259a7a82009-07-29 21:49:49554}
555
[email protected]3fe27112012-06-07 04:00:01556bool WebMediaPlayerImpl::didPassCORSAccessCheck() const {
[email protected]b49beeb2013-03-01 20:04:00557 if (data_source_)
558 return data_source_->DidPassCORSAccessCheck();
559 return false;
[email protected]3fe27112012-06-07 04:00:01560}
561
[email protected]39bdde32013-04-17 17:44:20562double WebMediaPlayerImpl::mediaTimeForTimeValue(double timeValue) const {
[email protected]e06e16d82011-05-26 22:13:33563 return ConvertSecondsToTimestamp(timeValue).InSecondsF();
564}
565
[email protected]d82b18ae2011-03-23 21:28:59566unsigned WebMediaPlayerImpl::decodedFrameCount() const {
acolwellb4034942014-08-28 15:42:43567 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]4c51bc662011-02-16 02:03:16568
acolwell9e0840d2014-09-06 19:01:32569 PipelineStatistics stats = pipeline_.GetStatistics();
[email protected]4c51bc662011-02-16 02:03:16570 return stats.video_frames_decoded;
571}
572
[email protected]d82b18ae2011-03-23 21:28:59573unsigned WebMediaPlayerImpl::droppedFrameCount() const {
acolwellb4034942014-08-28 15:42:43574 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]4c51bc662011-02-16 02:03:16575
acolwell9e0840d2014-09-06 19:01:32576 PipelineStatistics stats = pipeline_.GetStatistics();
[email protected]dd061e12014-05-06 19:21:22577 return stats.video_frames_dropped;
[email protected]4c51bc662011-02-16 02:03:16578}
579
[email protected]d82b18ae2011-03-23 21:28:59580unsigned WebMediaPlayerImpl::audioDecodedByteCount() const {
acolwellb4034942014-08-28 15:42:43581 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]4c51bc662011-02-16 02:03:16582
acolwell9e0840d2014-09-06 19:01:32583 PipelineStatistics stats = pipeline_.GetStatistics();
[email protected]4c51bc662011-02-16 02:03:16584 return stats.audio_bytes_decoded;
585}
586
[email protected]d82b18ae2011-03-23 21:28:59587unsigned WebMediaPlayerImpl::videoDecodedByteCount() const {
acolwellb4034942014-08-28 15:42:43588 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]4c51bc662011-02-16 02:03:16589
acolwell9e0840d2014-09-06 19:01:32590 PipelineStatistics stats = pipeline_.GetStatistics();
[email protected]4c51bc662011-02-16 02:03:16591 return stats.video_bytes_decoded;
592}
593
[email protected]6523b242013-03-13 11:10:07594bool WebMediaPlayerImpl::copyVideoTextureToPlatformTexture(
[email protected]180ef242013-11-07 06:50:46595 blink::WebGraphicsContext3D* web_graphics_context,
[email protected]6523b242013-03-13 11:10:07596 unsigned int texture,
597 unsigned int level,
598 unsigned int internal_format,
[email protected]9aa2b2782013-05-14 00:13:31599 unsigned int type,
[email protected]6523b242013-03-13 11:10:07600 bool premultiply_alpha,
601 bool flip_y) {
[email protected]bfc05f22013-10-19 17:55:16602 TRACE_EVENT0("media", "WebMediaPlayerImpl:copyVideoTextureToPlatformTexture");
603
acolwell9e0840d2014-09-06 19:01:32604 scoped_refptr<VideoFrame> video_frame =
[email protected]dd061e12014-05-06 19:21:22605 GetCurrentFrameFromCompositor();
606
dchengf70d95e2014-08-27 02:06:28607 if (!video_frame.get())
[email protected]e56f88c72013-06-25 22:31:29608 return false;
acolwell9e0840d2014-09-06 19:01:32609 if (video_frame->format() != VideoFrame::NATIVE_TEXTURE)
[email protected]e56f88c72013-06-25 22:31:29610 return false;
[email protected]df41e252014-02-03 23:39:50611
[email protected]c37a4cc2014-04-30 19:15:28612 const gpu::MailboxHolder* mailbox_holder = video_frame->mailbox_holder();
[email protected]df41e252014-02-03 23:39:50613 if (mailbox_holder->texture_target != GL_TEXTURE_2D)
[email protected]e56f88c72013-06-25 22:31:29614 return false;
615
[email protected]df41e252014-02-03 23:39:50616 web_graphics_context->waitSyncPoint(mailbox_holder->sync_point);
[email protected]c77f2722014-07-22 09:04:32617 uint32 source_texture = web_graphics_context->createAndConsumeTextureCHROMIUM(
618 GL_TEXTURE_2D, mailbox_holder->mailbox.name);
[email protected]e56f88c72013-06-25 22:31:29619
620 // The video is stored in a unmultiplied format, so premultiply
621 // if necessary.
622 web_graphics_context->pixelStorei(GL_UNPACK_PREMULTIPLY_ALPHA_CHROMIUM,
623 premultiply_alpha);
624 // Application itself needs to take care of setting the right flip_y
625 // value down to get the expected result.
626 // flip_y==true means to reverse the video orientation while
627 // flip_y==false means to keep the intrinsic orientation.
628 web_graphics_context->pixelStorei(GL_UNPACK_FLIP_Y_CHROMIUM, flip_y);
629 web_graphics_context->copyTextureCHROMIUM(GL_TEXTURE_2D,
630 source_texture,
631 texture,
632 level,
633 internal_format,
634 type);
635 web_graphics_context->pixelStorei(GL_UNPACK_FLIP_Y_CHROMIUM, false);
636 web_graphics_context->pixelStorei(GL_UNPACK_PREMULTIPLY_ALPHA_CHROMIUM,
637 false);
638
639 web_graphics_context->deleteTexture(source_texture);
[email protected]e56f88c72013-06-25 22:31:29640 web_graphics_context->flush();
[email protected]47c345b2014-07-22 10:31:57641
642 SyncPointClientImpl client(web_graphics_context);
643 video_frame->UpdateReleaseSyncPoint(&client);
[email protected]e56f88c72013-06-25 22:31:29644 return true;
[email protected]6523b242013-03-13 11:10:07645}
646
[email protected]2ca7d5c2012-10-23 07:30:54647WebMediaPlayer::MediaKeyException
[email protected]f7a6b992012-04-19 09:45:56648WebMediaPlayerImpl::generateKeyRequest(const WebString& key_system,
649 const unsigned char* init_data,
650 unsigned init_data_length) {
acolwellb4034942014-08-28 15:42:43651 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]7502ef12014-01-25 01:19:27652
xhwang16ff1362014-11-19 00:16:34653 return encrypted_media_support_.GenerateKeyRequest(
acolwelle2ea5182014-08-25 23:01:07654 frame_, key_system, init_data, init_data_length);
[email protected]f7a6b992012-04-19 09:45:56655}
656
[email protected]2ca7d5c2012-10-23 07:30:54657WebMediaPlayer::MediaKeyException WebMediaPlayerImpl::addKey(
658 const WebString& key_system,
659 const unsigned char* key,
660 unsigned key_length,
661 const unsigned char* init_data,
662 unsigned init_data_length,
663 const WebString& session_id) {
acolwellb4034942014-08-28 15:42:43664 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]f7a6b992012-04-19 09:45:56665
xhwang16ff1362014-11-19 00:16:34666 return encrypted_media_support_.AddKey(
acolwelle2ea5182014-08-25 23:01:07667 key_system, key, key_length, init_data, init_data_length, session_id);
[email protected]f7a6b992012-04-19 09:45:56668}
669
[email protected]2ca7d5c2012-10-23 07:30:54670WebMediaPlayer::MediaKeyException WebMediaPlayerImpl::cancelKeyRequest(
671 const WebString& key_system,
672 const WebString& session_id) {
acolwellb4034942014-08-28 15:42:43673 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]0b9999d2014-02-20 02:16:11674
xhwang16ff1362014-11-19 00:16:34675 return encrypted_media_support_.CancelKeyRequest(key_system, session_id);
[email protected]f7a6b992012-04-19 09:45:56676}
677
[email protected]7bce1832014-01-09 00:01:22678void WebMediaPlayerImpl::setContentDecryptionModule(
[email protected]9ebc3b03f2014-08-13 04:01:23679 blink::WebContentDecryptionModule* cdm,
680 blink::WebContentDecryptionModuleResult result) {
acolwellb4034942014-08-28 15:42:43681 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]9ebc3b03f2014-08-13 04:01:23682
xhwang97de4202014-11-25 08:44:01683 // TODO(xhwang): Support setMediaKeys(0) if necessary: http://crbug.com/330324
684 if (!cdm) {
685 result.completeWithError(
686 blink::WebContentDecryptionModuleExceptionNotSupportedError, 0,
687 "Null MediaKeys object is not supported.");
688 return;
689 }
690
691 SetCdm(ToWebContentDecryptionModuleImpl(cdm)->GetCdmContext(),
692 BIND_TO_RENDER_LOOP1(&WebMediaPlayerImpl::OnCdmAttached, result));
693}
694
695void WebMediaPlayerImpl::SetCdm(CdmContext* cdm_context,
696 const CdmAttachedCB& cdm_attached_cb) {
697 pipeline_.SetCdm(cdm_context, cdm_attached_cb);
698}
699
700void WebMediaPlayerImpl::OnCdmAttached(
701 blink::WebContentDecryptionModuleResult result,
702 bool success) {
703 if (success) {
704 result.complete();
705 return;
706 }
707
708 result.completeWithError(
709 blink::WebContentDecryptionModuleExceptionNotSupportedError, 0,
710 "Unable to set MediaKeys object");
[email protected]9ebc3b03f2014-08-13 04:01:23711}
712
[email protected]4e982192014-06-21 13:35:45713void WebMediaPlayerImpl::OnPipelineSeeked(bool time_changed,
714 PipelineStatus status) {
715 DVLOG(1) << __FUNCTION__ << "(" << time_changed << ", " << status << ")";
acolwellb4034942014-08-28 15:42:43716 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]5d11eff2011-09-15 00:06:06717 seeking_ = false;
718 if (pending_seek_) {
719 pending_seek_ = false;
720 seek(pending_seek_seconds_);
721 return;
722 }
723
acolwell9e0840d2014-09-06 19:01:32724 if (status != PIPELINE_OK) {
[email protected]10a64d92012-04-10 21:08:02725 OnPipelineError(status);
726 return;
[email protected]96706912009-07-15 17:18:05727 }
[email protected]10a64d92012-04-10 21:08:02728
729 // Update our paused time.
730 if (paused_)
[email protected]f6af7592014-02-28 10:09:11731 paused_time_ = pipeline_.GetMediaTime();
[email protected]10a64d92012-04-10 21:08:02732
[email protected]ba7d5f92014-06-24 05:37:40733 should_notify_time_changed_ = time_changed;
[email protected]8931c41a2009-07-07 17:31:49734}
735
[email protected]6954fe12013-01-03 03:22:32736void WebMediaPlayerImpl::OnPipelineEnded() {
[email protected]2a06ca62014-06-04 13:59:52737 DVLOG(1) << __FUNCTION__;
acolwellb4034942014-08-28 15:42:43738 DCHECK(main_task_runner_->BelongsToCurrentThread());
scherkusd2c745b2014-09-04 05:03:40739
740 // Ignore state changes until we've completed all outstanding seeks.
741 if (seeking_ || pending_seek_)
742 return;
743
744 ended_ = true;
[email protected]ce70c982013-12-20 17:04:32745 client_->timeChanged();
[email protected]576537842009-08-12 23:52:05746}
747
[email protected]a9590c22011-03-16 16:57:02748void WebMediaPlayerImpl::OnPipelineError(PipelineStatus error) {
acolwellb4034942014-08-28 15:42:43749 DCHECK(main_task_runner_->BelongsToCurrentThread());
acolwell9e0840d2014-09-06 19:01:32750 DCHECK_NE(error, PIPELINE_OK);
[email protected]a8e2cb82012-08-17 00:02:39751
752 if (ready_state_ == WebMediaPlayer::ReadyStateHaveNothing) {
753 // Any error that occurs before reaching ReadyStateHaveMetadata should
754 // be considered a format error.
755 SetNetworkState(WebMediaPlayer::NetworkStateFormatError);
[email protected]a8e2cb82012-08-17 00:02:39756 return;
757 }
758
[email protected]be57ee52013-05-28 22:27:27759 SetNetworkState(PipelineErrorToNetworkState(error));
[email protected]a9590c22011-03-16 16:57:02760
acolwell9e0840d2014-09-06 19:01:32761 if (error == PIPELINE_ERROR_DECRYPT)
xhwang16ff1362014-11-19 00:16:34762 encrypted_media_support_.OnPipelineDecryptError();
[email protected]db190487d2009-07-30 18:51:52763}
764
[email protected]b8877772014-03-26 20:17:15765void WebMediaPlayerImpl::OnPipelineMetadata(
acolwell9e0840d2014-09-06 19:01:32766 PipelineMetadata metadata) {
[email protected]2a06ca62014-06-04 13:59:52767 DVLOG(1) << __FUNCTION__;
[email protected]a8e2cb82012-08-17 00:02:39768
[email protected]b8877772014-03-26 20:17:15769 pipeline_metadata_ = metadata;
[email protected]739847c02014-01-16 00:12:25770
[email protected]eddfef92014-07-18 01:26:47771 UMA_HISTOGRAM_ENUMERATION("Media.VideoRotation",
772 metadata.video_rotation,
acolwell9e0840d2014-09-06 19:01:32773 VIDEO_ROTATION_MAX + 1);
[email protected]b8877772014-03-26 20:17:15774 SetReadyState(WebMediaPlayer::ReadyStateHaveMetadata);
[email protected]21c3f7502013-03-23 03:29:51775
[email protected]b8877772014-03-26 20:17:15776 if (hasVideo()) {
777 DCHECK(!video_weblayer_);
[email protected]f78c3e82014-08-08 01:24:47778 scoped_refptr<cc::VideoLayer> layer =
779 cc::VideoLayer::Create(compositor_, pipeline_metadata_.video_rotation);
780
acolwell9e0840d2014-09-06 19:01:32781 if (pipeline_metadata_.video_rotation == VIDEO_ROTATION_90 ||
782 pipeline_metadata_.video_rotation == VIDEO_ROTATION_270) {
[email protected]f78c3e82014-08-08 01:24:47783 gfx::Size size = pipeline_metadata_.natural_size;
784 pipeline_metadata_.natural_size = gfx::Size(size.height(), size.width());
785 }
786
[email protected]38564622014-08-19 02:47:18787 video_weblayer_.reset(new cc_blink::WebLayerImpl(layer));
[email protected]75e145a2014-04-15 17:44:32788 video_weblayer_->setOpaque(opaque_);
[email protected]a7c4f582014-04-16 18:44:49789 client_->setWebLayer(video_weblayer_.get());
[email protected]a8e2cb82012-08-17 00:02:39790 }
[email protected]a8e2cb82012-08-17 00:02:39791}
792
[email protected]ba7d5f92014-06-24 05:37:40793void WebMediaPlayerImpl::OnPipelineBufferingStateChanged(
acolwell9e0840d2014-09-06 19:01:32794 BufferingState buffering_state) {
[email protected]ba7d5f92014-06-24 05:37:40795 DVLOG(1) << __FUNCTION__ << "(" << buffering_state << ")";
[email protected]b8877772014-03-26 20:17:15796
[email protected]ba7d5f92014-06-24 05:37:40797 // Ignore buffering state changes until we've completed all outstanding seeks.
798 if (seeking_ || pending_seek_)
799 return;
[email protected]b8877772014-03-26 20:17:15800
[email protected]ba7d5f92014-06-24 05:37:40801 // TODO(scherkus): Handle other buffering states when Pipeline starts using
802 // them and translate them ready state changes http://crbug.com/144683
acolwell9e0840d2014-09-06 19:01:32803 DCHECK_EQ(buffering_state, BUFFERING_HAVE_ENOUGH);
[email protected]ba7d5f92014-06-24 05:37:40804 SetReadyState(WebMediaPlayer::ReadyStateHaveEnoughData);
805
806 // Blink expects a timeChanged() in response to a seek().
807 if (should_notify_time_changed_)
808 client_->timeChanged();
[email protected]b8877772014-03-26 20:17:15809}
810
[email protected]ef8394c2013-08-21 20:26:30811void WebMediaPlayerImpl::OnDemuxerOpened() {
acolwellb4034942014-08-28 15:42:43812 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]ce70c982013-12-20 17:04:32813 client_->mediaSourceOpened(new WebMediaSourceImpl(
[email protected]5f811a2d2013-03-15 23:54:51814 chunk_demuxer_, base::Bind(&LogMediaSourceError, media_log_)));
[email protected]81bb3322011-07-21 15:55:50815}
816
[email protected]8a561062013-11-22 01:19:31817void WebMediaPlayerImpl::OnAddTextTrack(
acolwell9e0840d2014-09-06 19:01:32818 const TextTrackConfig& config,
819 const AddTextTrackDoneCB& done_cb) {
acolwellb4034942014-08-28 15:42:43820 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]71537722013-05-23 06:47:53821
[email protected]8a561062013-11-22 01:19:31822 const WebInbandTextTrackImpl::Kind web_kind =
823 static_cast<WebInbandTextTrackImpl::Kind>(config.kind());
824 const blink::WebString web_label =
825 blink::WebString::fromUTF8(config.label());
826 const blink::WebString web_language =
827 blink::WebString::fromUTF8(config.language());
[email protected]427ff102013-11-26 23:45:40828 const blink::WebString web_id =
829 blink::WebString::fromUTF8(config.id());
[email protected]71537722013-05-23 06:47:53830
[email protected]8a561062013-11-22 01:19:31831 scoped_ptr<WebInbandTextTrackImpl> web_inband_text_track(
[email protected]427ff102013-11-26 23:45:40832 new WebInbandTextTrackImpl(web_kind, web_label, web_language, web_id,
[email protected]8a561062013-11-22 01:19:31833 text_track_index_++));
834
acolwell9e0840d2014-09-06 19:01:32835 scoped_ptr<TextTrack> text_track(new TextTrackImpl(
acolwellb4034942014-08-28 15:42:43836 main_task_runner_, client_, web_inband_text_track.Pass()));
[email protected]8a561062013-11-22 01:19:31837
838 done_cb.Run(text_track.Pass());
[email protected]71537722013-05-23 06:47:53839}
840
[email protected]fee8a902014-06-03 13:43:36841void WebMediaPlayerImpl::DataSourceInitialized(bool success) {
acolwellb4034942014-08-28 15:42:43842 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]a9415292012-01-19 19:55:20843
[email protected]d250190da3b2012-07-23 22:57:30844 if (!success) {
[email protected]ef405f66b2012-04-18 02:39:55845 SetNetworkState(WebMediaPlayer::NetworkStateFormatError);
[email protected]a9415292012-01-19 19:55:20846 return;
847 }
848
[email protected]ef8394c2013-08-21 20:26:30849 StartPipeline();
[email protected]a9415292012-01-19 19:55:20850}
851
[email protected]122f40252012-06-12 05:01:56852void WebMediaPlayerImpl::NotifyDownloading(bool is_downloading) {
853 if (!is_downloading && network_state_ == WebMediaPlayer::NetworkStateLoading)
854 SetNetworkState(WebMediaPlayer::NetworkStateIdle);
855 else if (is_downloading && network_state_ == WebMediaPlayer::NetworkStateIdle)
856 SetNetworkState(WebMediaPlayer::NetworkStateLoading);
857 media_log_->AddEvent(
858 media_log_->CreateBooleanEvent(
acolwell9e0840d2014-09-06 19:01:32859 MediaLogEvent::NETWORK_ACTIVITY_SET,
[email protected]122f40252012-06-12 05:01:56860 "is_downloading_data", is_downloading));
861}
862
xhwangbe9da702014-08-23 21:44:55863// TODO(xhwang): Move this to a factory class so that we can create different
864// renderers.
acolwell9e0840d2014-09-06 19:01:32865scoped_ptr<Renderer> WebMediaPlayerImpl::CreateRenderer() {
xhwangbe9da702014-08-23 21:44:55866 // Create our audio decoders and renderer.
acolwell9e0840d2014-09-06 19:01:32867 ScopedVector<AudioDecoder> audio_decoders;
xhwangbe9da702014-08-23 21:44:55868
xhwang16ff1362014-11-19 00:16:34869 audio_decoders.push_back(new FFmpegAudioDecoder(
xhwangff459d4e2014-09-09 04:55:47870 media_task_runner_, base::Bind(&LogMediaSourceError, media_log_)));
xhwang16ff1362014-11-19 00:16:34871 audio_decoders.push_back(new OpusAudioDecoder(media_task_runner_));
xhwangbe9da702014-08-23 21:44:55872
xhwang97de4202014-11-25 08:44:01873 scoped_ptr<AudioRenderer> audio_renderer(new AudioRendererImpl(
874 media_task_runner_, audio_source_provider_.get(), audio_decoders.Pass(),
875 audio_hardware_config_, media_log_));
xhwangbe9da702014-08-23 21:44:55876
877 // Create our video decoders and renderer.
acolwell9e0840d2014-09-06 19:01:32878 ScopedVector<VideoDecoder> video_decoders;
xhwangbe9da702014-08-23 21:44:55879
xhwangff459d4e2014-09-09 04:55:47880 if (gpu_factories_.get())
881 video_decoders.push_back(new GpuVideoDecoder(gpu_factories_));
xhwangbe9da702014-08-23 21:44:55882
883#if !defined(MEDIA_DISABLE_LIBVPX)
acolwell9e0840d2014-09-06 19:01:32884 video_decoders.push_back(new VpxVideoDecoder(media_task_runner_));
xhwangbe9da702014-08-23 21:44:55885#endif // !defined(MEDIA_DISABLE_LIBVPX)
886
acolwell9e0840d2014-09-06 19:01:32887 video_decoders.push_back(new FFmpegVideoDecoder(media_task_runner_));
xhwangbe9da702014-08-23 21:44:55888
xhwangff459d4e2014-09-09 04:55:47889 scoped_ptr<VideoRenderer> video_renderer(new VideoRendererImpl(
xhwang97de4202014-11-25 08:44:01890 media_task_runner_, video_decoders.Pass(), true, media_log_));
xhwangbe9da702014-08-23 21:44:55891
892 // Create renderer.
acolwell9e0840d2014-09-06 19:01:32893 return scoped_ptr<Renderer>(new RendererImpl(
xhwangabd95fd2014-10-03 07:10:01894 media_task_runner_, audio_renderer.Pass(), video_renderer.Pass()));
xhwangbe9da702014-08-23 21:44:55895}
896
[email protected]ef8394c2013-08-21 20:26:30897void WebMediaPlayerImpl::StartPipeline() {
acolwellb4034942014-08-28 15:42:43898 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]ddbc6ff2013-04-19 15:28:33899
[email protected]0814ac62013-06-07 21:01:29900 // Keep track if this is a MSE or non-MSE playback.
[email protected]ef8394c2013-08-21 20:26:30901 UMA_HISTOGRAM_BOOLEAN("Media.MSE.Playback",
902 (load_type_ == LoadTypeMediaSource));
[email protected]0814ac62013-06-07 21:01:29903
acolwell9e0840d2014-09-06 19:01:32904 LogCB mse_log_cb;
905 Demuxer::NeedKeyCB need_key_cb =
xhwang16ff1362014-11-19 00:16:34906 encrypted_media_support_.CreateNeedKeyCB();
[email protected]2b57e2e2014-05-09 11:07:25907
[email protected]ddbc6ff2013-04-19 15:28:33908 // Figure out which demuxer to use.
[email protected]ef8394c2013-08-21 20:26:30909 if (load_type_ != LoadTypeMediaSource) {
[email protected]ddbc6ff2013-04-19 15:28:33910 DCHECK(!chunk_demuxer_);
[email protected]f5443ef72013-04-22 04:03:38911 DCHECK(data_source_);
912
acolwell9e0840d2014-09-06 19:01:32913 demuxer_.reset(new FFmpegDemuxer(
acolwellb4034942014-08-28 15:42:43914 media_task_runner_, data_source_.get(),
acolwelle2ea5182014-08-25 23:01:07915 need_key_cb,
[email protected]1e931f62013-07-31 23:25:52916 media_log_));
[email protected]ddbc6ff2013-04-19 15:28:33917 } else {
[email protected]f5443ef72013-04-22 04:03:38918 DCHECK(!chunk_demuxer_);
919 DCHECK(!data_source_);
920
[email protected]2b57e2e2014-05-09 11:07:25921 mse_log_cb = base::Bind(&LogMediaSourceError, media_log_);
922
acolwell9e0840d2014-09-06 19:01:32923 chunk_demuxer_ = new ChunkDemuxer(
[email protected]ef8394c2013-08-21 20:26:30924 BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnDemuxerOpened),
acolwelle2ea5182014-08-25 23:01:07925 need_key_cb,
[email protected]2b57e2e2014-05-09 11:07:25926 mse_log_cb,
watk14bcfc52014-11-20 00:29:09927 media_log_,
[email protected]ae3c42e2014-04-30 05:48:05928 true);
[email protected]f5443ef72013-04-22 04:03:38929 demuxer_.reset(chunk_demuxer_);
[email protected]ddbc6ff2013-04-19 15:28:33930 }
931
[email protected]f5443ef72013-04-22 04:03:38932 // ... and we're ready to go!
[email protected]d228aeec2014-06-20 19:16:49933 seeking_ = true;
xhwangf94a634d2014-10-22 22:07:27934
935 if (!renderer_)
936 renderer_ = CreateRenderer();
937
[email protected]f6af7592014-02-28 10:09:11938 pipeline_.Start(
xhwang59805902014-08-29 01:44:15939 demuxer_.get(),
xhwangf94a634d2014-10-22 22:07:27940 renderer_.Pass(),
[email protected]f5443ef72013-04-22 04:03:38941 BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnPipelineEnded),
942 BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnPipelineError),
[email protected]4e982192014-06-21 13:35:45943 BIND_TO_RENDER_LOOP1(&WebMediaPlayerImpl::OnPipelineSeeked, false),
[email protected]b8877772014-03-26 20:17:15944 BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnPipelineMetadata),
[email protected]ba7d5f92014-06-24 05:37:40945 BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnPipelineBufferingStateChanged),
xhwang94c0bd32014-11-13 20:49:31946 base::Bind(&WebMediaPlayerImpl::FrameReady, base::Unretained(this)),
xhwang59805902014-08-29 01:44:15947 BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnDurationChanged),
948 BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnAddTextTrack));
[email protected]f5443ef72013-04-22 04:03:38949}
950
951void WebMediaPlayerImpl::SetNetworkState(WebMediaPlayer::NetworkState state) {
[email protected]2a06ca62014-06-04 13:59:52952 DVLOG(1) << __FUNCTION__ << "(" << state << ")";
acolwellb4034942014-08-28 15:42:43953 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]f5443ef72013-04-22 04:03:38954 network_state_ = state;
955 // Always notify to ensure client has the latest value.
[email protected]ce70c982013-12-20 17:04:32956 client_->networkStateChanged();
[email protected]f5443ef72013-04-22 04:03:38957}
958
959void WebMediaPlayerImpl::SetReadyState(WebMediaPlayer::ReadyState state) {
[email protected]2a06ca62014-06-04 13:59:52960 DVLOG(1) << __FUNCTION__ << "(" << state << ")";
acolwellb4034942014-08-28 15:42:43961 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]f5443ef72013-04-22 04:03:38962
[email protected]fee8a902014-06-03 13:43:36963 if (state == WebMediaPlayer::ReadyStateHaveEnoughData && data_source_ &&
964 data_source_->assume_fully_buffered() &&
[email protected]f5443ef72013-04-22 04:03:38965 network_state_ == WebMediaPlayer::NetworkStateLoading)
966 SetNetworkState(WebMediaPlayer::NetworkStateLoaded);
967
968 ready_state_ = state;
969 // Always notify to ensure client has the latest value.
[email protected]ce70c982013-12-20 17:04:32970 client_->readyStateChanged();
[email protected]f5443ef72013-04-22 04:03:38971}
972
[email protected]180ef242013-11-07 06:50:46973blink::WebAudioSourceProvider* WebMediaPlayerImpl::audioSourceProvider() {
[email protected]ff875be52013-06-02 23:47:38974 return audio_source_provider_.get();
[email protected]f5443ef72013-04-22 04:03:38975}
976
[email protected]f5443ef72013-04-22 04:03:38977double WebMediaPlayerImpl::GetPipelineDuration() const {
[email protected]f6af7592014-02-28 10:09:11978 base::TimeDelta duration = pipeline_.GetMediaDuration();
[email protected]f5443ef72013-04-22 04:03:38979
980 // Return positive infinity if the resource is unbounded.
981 // http://www.whatwg.org/specs/web-apps/current-work/multipage/video.html#dom-media-duration
acolwell9e0840d2014-09-06 19:01:32982 if (duration == kInfiniteDuration())
[email protected]f5443ef72013-04-22 04:03:38983 return std::numeric_limits<double>::infinity();
984
985 return duration.InSecondsF();
986}
987
[email protected]75e145a2014-04-15 17:44:32988void WebMediaPlayerImpl::OnDurationChanged() {
[email protected]f5443ef72013-04-22 04:03:38989 if (ready_state_ == WebMediaPlayer::ReadyStateHaveNothing)
990 return;
991
[email protected]ce70c982013-12-20 17:04:32992 client_->durationChanged();
[email protected]f5443ef72013-04-22 04:03:38993}
994
[email protected]75e145a2014-04-15 17:44:32995void WebMediaPlayerImpl::OnNaturalSizeChanged(gfx::Size size) {
acolwellb4034942014-08-28 15:42:43996 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]739847c02014-01-16 00:12:25997 DCHECK_NE(ready_state_, WebMediaPlayer::ReadyStateHaveNothing);
998 TRACE_EVENT0("media", "WebMediaPlayerImpl::OnNaturalSizeChanged");
999
1000 media_log_->AddEvent(
1001 media_log_->CreateVideoSizeSetEvent(size.width(), size.height()));
[email protected]b8877772014-03-26 20:17:151002 pipeline_metadata_.natural_size = size;
[email protected]739847c02014-01-16 00:12:251003
1004 client_->sizeChanged();
1005}
1006
[email protected]75e145a2014-04-15 17:44:321007void WebMediaPlayerImpl::OnOpacityChanged(bool opaque) {
acolwellb4034942014-08-28 15:42:431008 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]75e145a2014-04-15 17:44:321009 DCHECK_NE(ready_state_, WebMediaPlayer::ReadyStateHaveNothing);
1010
1011 opaque_ = opaque;
[email protected]75e145a2014-04-15 17:44:321012 if (video_weblayer_)
1013 video_weblayer_->setOpaque(opaque_);
1014}
1015
[email protected]f5443ef72013-04-22 04:03:381016void WebMediaPlayerImpl::FrameReady(
acolwell9e0840d2014-09-06 19:01:321017 const scoped_refptr<VideoFrame>& frame) {
[email protected]dd061e12014-05-06 19:21:221018 compositor_task_runner_->PostTask(
1019 FROM_HERE,
1020 base::Bind(&VideoFrameCompositor::UpdateCurrentFrame,
1021 base::Unretained(compositor_),
1022 frame));
[email protected]bfc05f22013-10-19 17:55:161023}
1024
[email protected]dd061e12014-05-06 19:21:221025static void GetCurrentFrameAndSignal(
1026 VideoFrameCompositor* compositor,
acolwell9e0840d2014-09-06 19:01:321027 scoped_refptr<VideoFrame>* video_frame_out,
[email protected]dd061e12014-05-06 19:21:221028 base::WaitableEvent* event) {
1029 TRACE_EVENT0("media", "GetCurrentFrameAndSignal");
1030 *video_frame_out = compositor->GetCurrentFrame();
1031 event->Signal();
1032}
1033
acolwell9e0840d2014-09-06 19:01:321034scoped_refptr<VideoFrame>
[email protected]dd061e12014-05-06 19:21:221035WebMediaPlayerImpl::GetCurrentFrameFromCompositor() {
1036 TRACE_EVENT0("media", "WebMediaPlayerImpl::GetCurrentFrameFromCompositor");
1037 if (compositor_task_runner_->BelongsToCurrentThread())
1038 return compositor_->GetCurrentFrame();
1039
1040 // Use a posted task and waitable event instead of a lock otherwise
1041 // WebGL/Canvas can see different content than what the compositor is seeing.
acolwell9e0840d2014-09-06 19:01:321042 scoped_refptr<VideoFrame> video_frame;
[email protected]dd061e12014-05-06 19:21:221043 base::WaitableEvent event(false, false);
1044 compositor_task_runner_->PostTask(FROM_HERE,
1045 base::Bind(&GetCurrentFrameAndSignal,
1046 base::Unretained(compositor_),
1047 &video_frame,
1048 &event));
1049 event.Wait();
1050 return video_frame;
1051}
1052
acolwell9e0840d2014-09-06 19:01:321053} // namespace media