blob: 0aaf1f0b14c66b6bae883b5d8908faaef8d8acb7 [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"
39#include "media/blink/webinbandtexttrack_impl.h"
40#include "media/blink/webmediaplayer_delegate.h"
41#include "media/blink/webmediaplayer_params.h"
42#include "media/blink/webmediaplayer_util.h"
43#include "media/blink/webmediasource_impl.h"
[email protected]37136d162012-04-09 23:39:1944#include "media/filters/audio_renderer_impl.h"
[email protected]efe7cd22012-09-12 23:55:0145#include "media/filters/chunk_demuxer.h"
[email protected]ddbc6ff2013-04-19 15:28:3346#include "media/filters/ffmpeg_audio_decoder.h"
47#include "media/filters/ffmpeg_demuxer.h"
48#include "media/filters/ffmpeg_video_decoder.h"
[email protected]1cad8802013-08-13 16:54:3249#include "media/filters/gpu_video_accelerator_factories.h"
[email protected]b9a407e2013-07-24 07:30:0250#include "media/filters/gpu_video_decoder.h"
[email protected]ddbc6ff2013-04-19 15:28:3351#include "media/filters/opus_audio_decoder.h"
xhwangbe9da702014-08-23 21:44:5552#include "media/filters/renderer_impl.h"
[email protected]cc3933d2013-11-26 03:41:0253#include "media/filters/video_renderer_impl.h"
[email protected]ddbc6ff2013-04-19 15:28:3354#include "media/filters/vpx_video_decoder.h"
[email protected]745746d2013-08-23 02:09:1655#include "third_party/WebKit/public/platform/WebMediaSource.h"
[email protected]c10884462013-05-30 00:22:0956#include "third_party/WebKit/public/platform/WebRect.h"
57#include "third_party/WebKit/public/platform/WebSize.h"
58#include "third_party/WebKit/public/platform/WebString.h"
59#include "third_party/WebKit/public/platform/WebURL.h"
[email protected]80504652014-04-18 04:41:5060#include "third_party/WebKit/public/web/WebLocalFrame.h"
[email protected]65b85282014-03-31 23:32:3161#include "third_party/WebKit/public/web/WebSecurityOrigin.h"
[email protected]2255a9332013-06-17 05:12:3162#include "third_party/WebKit/public/web/WebView.h"
[email protected]b3f2b912009-04-09 16:18:5263
[email protected]180ef242013-11-07 06:50:4664using blink::WebCanvas;
65using blink::WebMediaPlayer;
66using blink::WebRect;
67using blink::WebSize;
68using blink::WebString;
[email protected]ec9212f2008-12-18 21:40:3669
[email protected]8931c41a2009-07-07 17:31:4970namespace {
71
[email protected]378f0b72009-08-11 17:11:4272// Limits the range of playback rate.
73//
74// TODO(kylep): Revisit these.
75//
76// Vista has substantially lower performance than XP or Windows7. If you speed
77// up a video too much, it can't keep up, and rendering stops updating except on
78// the time bar. For really high speeds, audio becomes a bottleneck and we just
79// use up the data we have, which may not achieve the speed requested, but will
80// not crash the tab.
81//
82// A very slow speed, ie 0.00000001x, causes the machine to lock up. (It seems
83// like a busy loop). It gets unresponsive, although its not completely dead.
84//
85// Also our timers are not very accurate (especially for ogg), which becomes
86// evident at low speeds and on Vista. Since other speeds are risky and outside
87// the norms, we think 1/16x to 16x is a safe and useful range for now.
[email protected]39bdde32013-04-17 17:44:2088const double kMinRate = 0.0625;
89const double kMaxRate = 16.0;
[email protected]378f0b72009-08-11 17:11:4290
[email protected]47c345b2014-07-22 10:31:5791class SyncPointClientImpl : public media::VideoFrame::SyncPointClient {
92 public:
93 explicit SyncPointClientImpl(
94 blink::WebGraphicsContext3D* web_graphics_context)
95 : web_graphics_context_(web_graphics_context) {}
dchengc24565478f2014-10-21 12:23:2796 ~SyncPointClientImpl() override {}
97 uint32 InsertSyncPoint() override {
[email protected]47c345b2014-07-22 10:31:5798 return web_graphics_context_->insertSyncPoint();
99 }
dchengc24565478f2014-10-21 12:23:27100 void WaitSyncPoint(uint32 sync_point) override {
[email protected]47c345b2014-07-22 10:31:57101 web_graphics_context_->waitSyncPoint(sync_point);
102 }
103
104 private:
105 blink::WebGraphicsContext3D* web_graphics_context_;
106};
107
[email protected]8931c41a2009-07-07 17:31:49108} // namespace
109
acolwell9e0840d2014-09-06 19:01:32110namespace media {
[email protected]add51772009-06-11 18:25:17111
[email protected]6683e1b2014-04-10 01:45:38112class BufferedDataSourceHostImpl;
113
[email protected]a8884632012-06-29 03:05:34114#define COMPILE_ASSERT_MATCHING_ENUM(name) \
[email protected]2ca7d5c2012-10-23 07:30:54115 COMPILE_ASSERT(static_cast<int>(WebMediaPlayer::CORSMode ## name) == \
[email protected]a8884632012-06-29 03:05:34116 static_cast<int>(BufferedResourceLoader::k ## name), \
[email protected]a5a01102012-06-06 17:01:24117 mismatching_enums)
118COMPILE_ASSERT_MATCHING_ENUM(Unspecified);
119COMPILE_ASSERT_MATCHING_ENUM(Anonymous);
120COMPILE_ASSERT_MATCHING_ENUM(UseCredentials);
121#undef COMPILE_ASSERT_MATCHING_ENUM
122
[email protected]2c539b82012-08-18 04:10:19123#define BIND_TO_RENDER_LOOP(function) \
acolwellb4034942014-08-28 15:42:43124 (DCHECK(main_task_runner_->BelongsToCurrentThread()), \
acolwell9e0840d2014-09-06 19:01:32125 BindToCurrentLoop(base::Bind(function, AsWeakPtr())))
[email protected]5983adb2012-10-24 00:12:00126
[email protected]4e982192014-06-21 13:35:45127#define BIND_TO_RENDER_LOOP1(function, arg1) \
acolwellb4034942014-08-28 15:42:43128 (DCHECK(main_task_runner_->BelongsToCurrentThread()), \
acolwell9e0840d2014-09-06 19:01:32129 BindToCurrentLoop(base::Bind(function, AsWeakPtr(), arg1)))
[email protected]4e982192014-06-21 13:35:45130
acolwell9e0840d2014-09-06 19:01:32131static void LogMediaSourceError(const scoped_refptr<MediaLog>& media_log,
[email protected]2ef99602012-12-08 04:22:21132 const std::string& error) {
133 media_log->AddEvent(media_log->CreateMediaSourceErrorEvent(error));
134}
135
[email protected]5b5bb9d2010-10-22 19:57:36136WebMediaPlayerImpl::WebMediaPlayerImpl(
[email protected]35b2a972014-04-04 15:50:22137 blink::WebLocalFrame* frame,
[email protected]180ef242013-11-07 06:50:46138 blink::WebMediaPlayerClient* client,
[email protected]b8976652011-10-26 23:46:55139 base::WeakPtr<WebMediaPlayerDelegate> delegate,
xhwangf94a634d2014-10-22 22:07:27140 scoped_ptr<Renderer> renderer,
[email protected]e82b2bd2013-01-02 17:47:57141 const WebMediaPlayerParams& params)
[email protected]f6af7592014-02-28 10:09:11142 : frame_(frame),
[email protected]ef405f66b2012-04-18 02:39:55143 network_state_(WebMediaPlayer::NetworkStateEmpty),
144 ready_state_(WebMediaPlayer::ReadyStateHaveNothing),
acolwella5081a42014-08-28 23:42:52145 preload_(BufferedDataSource::AUTO),
acolwellb4034942014-08-28 15:42:43146 main_task_runner_(base::MessageLoopProxy::current()),
acolwell755d12d2014-08-30 01:09:19147 media_task_runner_(params.media_task_runner()),
148 media_log_(params.media_log()),
acolwellb4034942014-08-28 15:42:43149 pipeline_(media_task_runner_, media_log_.get()),
[email protected]f988d9b2014-07-25 00:35:43150 load_type_(LoadTypeURL),
[email protected]75e145a2014-04-15 17:44:32151 opaque_(false),
[email protected]49480902009-07-14 20:23:43152 paused_(true),
[email protected]b3766a22010-12-22 17:34:13153 seeking_(false),
[email protected]49480902009-07-14 20:23:43154 playback_rate_(0.0f),
scherkusd2c745b2014-09-04 05:03:40155 ended_(false),
[email protected]5d11eff2011-09-15 00:06:06156 pending_seek_(false),
[email protected]b1a975e2011-12-21 00:12:39157 pending_seek_seconds_(0.0f),
[email protected]ba7d5f92014-06-24 05:37:40158 should_notify_time_changed_(false),
[email protected]5badb082010-06-11 17:40:15159 client_(client),
[email protected]baff4512011-10-19 18:21:07160 delegate_(delegate),
[email protected]d726eddc2013-07-02 22:25:55161 defer_load_cb_(params.defer_load_cb()),
acolwell755d12d2014-08-30 01:09:19162 gpu_factories_(params.gpu_factories()),
[email protected]132dd57c2012-08-10 23:24:34163 supports_save_(true),
[email protected]f5443ef72013-04-22 04:03:38164 chunk_demuxer_(NULL),
acolwell755d12d2014-08-30 01:09:19165 compositor_task_runner_(params.compositor_task_runner()),
[email protected]dd061e12014-05-06 19:21:22166 compositor_(new VideoFrameCompositor(
[email protected]75e145a2014-04-15 17:44:32167 BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnNaturalSizeChanged),
[email protected]dd061e12014-05-06 19:21:22168 BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnOpacityChanged))),
[email protected]7bce1832014-01-09 00:01:22169 text_track_index_(0),
acolwell755d12d2014-08-30 01:09:19170 encrypted_media_support_(
171 params.CreateEncryptedMediaPlayerSupport(client)),
xhwangf94a634d2014-10-22 22:07:27172 audio_hardware_config_(params.audio_hardware_config()),
173 renderer_(renderer.Pass()) {
acolwelle2ea5182014-08-25 23:01:07174 DCHECK(encrypted_media_support_);
175
acolwell755d12d2014-08-30 01:09:19176 // Threaded compositing isn't enabled universally yet.
dchengd3c60602014-09-03 17:14:37177 if (!compositor_task_runner_.get())
acolwell755d12d2014-08-30 01:09:19178 compositor_task_runner_ = base::MessageLoopProxy::current();
179
[email protected]c93eb0a62011-08-09 22:47:24180 media_log_->AddEvent(
acolwell9e0840d2014-09-06 19:01:32181 media_log_->CreateEvent(MediaLogEvent::WEBMEDIAPLAYER_CREATED));
[email protected]4e6be3f2009-05-07 02:24:44182
xhwangf94a634d2014-10-22 22:07:27183 // TODO(xhwang): When we use an external Renderer, many methods won't work,
184 // e.g. GetCurrentFrameFromCompositor(). Fix this in a future CL.
185 if (renderer_)
186 return;
187
[email protected]c50edb962013-10-19 18:05:07188 // |gpu_factories_| requires that its entry points be called on its
[email protected]b639a832013-12-20 21:12:39189 // |GetTaskRunner()|. Since |pipeline_| will own decoders created from the
[email protected]c50edb962013-10-19 18:05:07190 // factories, require that their message loops are identical.
dchengf70d95e2014-08-27 02:06:28191 DCHECK(!gpu_factories_.get() ||
acolwellb4034942014-08-28 15:42:43192 (gpu_factories_->GetTaskRunner() == media_task_runner_.get()));
[email protected]c50edb962013-10-19 18:05:07193
[email protected]ddbc6ff2013-04-19 15:28:33194 // Use the null sink if no sink was provided.
[email protected]4a914882013-01-10 00:43:48195 audio_source_provider_ = new WebAudioSourceProviderImpl(
[email protected]ff875be52013-06-02 23:47:38196 params.audio_renderer_sink().get()
197 ? params.audio_renderer_sink()
acolwell9e0840d2014-09-06 19:01:32198 : new NullAudioSink(media_task_runner_));
[email protected]ec9212f2008-12-18 21:40:36199}
200
[email protected]4e6be3f2009-05-07 02:24:44201WebMediaPlayerImpl::~WebMediaPlayerImpl() {
[email protected]ce70c982013-12-20 17:04:32202 client_->setWebLayer(NULL);
[email protected]21c3f7502013-03-23 03:29:51203
acolwellb4034942014-08-28 15:42:43204 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]c93eb0a62011-08-09 22:47:24205 media_log_->AddEvent(
acolwell9e0840d2014-09-06 19:01:32206 media_log_->CreateEvent(MediaLogEvent::WEBMEDIAPLAYER_DESTROYED));
[email protected]d43ed912009-02-03 04:52:53207
dalecurtis6d269ed2014-09-11 21:18:13208 if (delegate_)
[email protected]baff4512011-10-19 18:21:07209 delegate_->PlayerGone(this);
210
[email protected]f6af7592014-02-28 10:09:11211 // Abort any pending IO so stopping the pipeline doesn't get blocked.
212 if (data_source_)
213 data_source_->Abort();
214 if (chunk_demuxer_) {
215 chunk_demuxer_->Shutdown();
216 chunk_demuxer_ = NULL;
217 }
218
219 gpu_factories_ = NULL;
220
221 // Make sure to kill the pipeline so there's no more media threads running.
222 // Note: stopping the pipeline might block for a long time.
223 base::WaitableEvent waiter(false, false);
224 pipeline_.Stop(
225 base::Bind(&base::WaitableEvent::Signal, base::Unretained(&waiter)));
226 waiter.Wait();
227
[email protected]dd061e12014-05-06 19:21:22228 compositor_task_runner_->DeleteSoon(FROM_HERE, compositor_);
[email protected]ec9212f2008-12-18 21:40:36229}
230
[email protected]180ef242013-11-07 06:50:46231void WebMediaPlayerImpl::load(LoadType load_type, const blink::WebURL& url,
[email protected]62e5e682013-03-07 23:53:24232 CORSMode cors_mode) {
[email protected]2a06ca62014-06-04 13:59:52233 DVLOG(1) << __FUNCTION__ << "(" << load_type << ", " << url << ", "
234 << cors_mode << ")";
[email protected]d726eddc2013-07-02 22:25:55235 if (!defer_load_cb_.is_null()) {
236 defer_load_cb_.Run(base::Bind(
[email protected]ef8394c2013-08-21 20:26:30237 &WebMediaPlayerImpl::DoLoad, AsWeakPtr(), load_type, url, cors_mode));
[email protected]d726eddc2013-07-02 22:25:55238 return;
239 }
[email protected]ef8394c2013-08-21 20:26:30240 DoLoad(load_type, url, cors_mode);
[email protected]62e5e682013-03-07 23:53:24241}
242
[email protected]ef8394c2013-08-21 20:26:30243void WebMediaPlayerImpl::DoLoad(LoadType load_type,
[email protected]180ef242013-11-07 06:50:46244 const blink::WebURL& url,
[email protected]d726eddc2013-07-02 22:25:55245 CORSMode cors_mode) {
acolwellb4034942014-08-28 15:42:43246 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]d726eddc2013-07-02 22:25:55247
[email protected]62e5e682013-03-07 23:53:24248 GURL gurl(url);
[email protected]e2f6bba2014-06-09 20:08:07249 ReportMediaSchemeUma(gurl);
[email protected]62e5e682013-03-07 23:53:24250
[email protected]926f8fd2013-04-12 20:27:53251 // Set subresource URL for crash reporting.
252 base::debug::SetCrashKeyValue("subresource_url", gurl.spec());
253
[email protected]ef8394c2013-08-21 20:26:30254 load_type_ = load_type;
255
[email protected]62e5e682013-03-07 23:53:24256 SetNetworkState(WebMediaPlayer::NetworkStateLoading);
257 SetReadyState(WebMediaPlayer::ReadyStateHaveNothing);
258 media_log_->AddEvent(media_log_->CreateLoadEvent(url.spec()));
[email protected]d726eddc2013-07-02 22:25:55259
260 // Media source pipelines can start immediately.
[email protected]ef8394c2013-08-21 20:26:30261 if (load_type == LoadTypeMediaSource) {
[email protected]d726eddc2013-07-02 22:25:55262 supports_save_ = false;
[email protected]ef8394c2013-08-21 20:26:30263 StartPipeline();
[email protected]d726eddc2013-07-02 22:25:55264 return;
265 }
266
267 // Otherwise it's a regular request which requires resolving the URL first.
268 data_source_.reset(new BufferedDataSource(
[email protected]fee8a902014-06-03 13:43:36269 url,
270 static_cast<BufferedResourceLoader::CORSMode>(cors_mode),
acolwellb4034942014-08-28 15:42:43271 main_task_runner_,
[email protected]d726eddc2013-07-02 22:25:55272 frame_,
273 media_log_.get(),
[email protected]6683e1b2014-04-10 01:45:38274 &buffered_data_source_host_,
[email protected]d726eddc2013-07-02 22:25:55275 base::Bind(&WebMediaPlayerImpl::NotifyDownloading, AsWeakPtr())));
276 data_source_->Initialize(
[email protected]fee8a902014-06-03 13:43:36277 base::Bind(&WebMediaPlayerImpl::DataSourceInitialized, AsWeakPtr()));
[email protected]09c60222014-08-07 16:42:31278 data_source_->SetPreload(preload_);
[email protected]62e5e682013-03-07 23:53:24279}
280
[email protected]4e6be3f2009-05-07 02:24:44281void WebMediaPlayerImpl::play() {
[email protected]2a06ca62014-06-04 13:59:52282 DVLOG(1) << __FUNCTION__;
acolwellb4034942014-08-28 15:42:43283 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]d43ed912009-02-03 04:52:53284
[email protected]49480902009-07-14 20:23:43285 paused_ = false;
[email protected]f6af7592014-02-28 10:09:11286 pipeline_.SetPlaybackRate(playback_rate_);
[email protected]039b7542013-10-17 22:06:25287 if (data_source_)
288 data_source_->MediaIsPlaying();
[email protected]090f7312011-08-05 23:26:40289
acolwell9e0840d2014-09-06 19:01:32290 media_log_->AddEvent(media_log_->CreateEvent(MediaLogEvent::PLAY));
[email protected]baff4512011-10-19 18:21:07291
dalecurtis6d269ed2014-09-11 21:18:13292 if (delegate_ && playback_rate_ > 0)
[email protected]baff4512011-10-19 18:21:07293 delegate_->DidPlay(this);
[email protected]ec9212f2008-12-18 21:40:36294}
295
[email protected]4e6be3f2009-05-07 02:24:44296void WebMediaPlayerImpl::pause() {
[email protected]2a06ca62014-06-04 13:59:52297 DVLOG(1) << __FUNCTION__;
acolwellb4034942014-08-28 15:42:43298 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]d43ed912009-02-03 04:52:53299
dalecurtis6d269ed2014-09-11 21:18:13300 const bool was_already_paused = paused_ || playback_rate_ == 0;
[email protected]49480902009-07-14 20:23:43301 paused_ = true;
[email protected]f6af7592014-02-28 10:09:11302 pipeline_.SetPlaybackRate(0.0f);
[email protected]039b7542013-10-17 22:06:25303 if (data_source_)
304 data_source_->MediaIsPaused();
[email protected]f6af7592014-02-28 10:09:11305 paused_time_ = pipeline_.GetMediaTime();
[email protected]090f7312011-08-05 23:26:40306
acolwell9e0840d2014-09-06 19:01:32307 media_log_->AddEvent(media_log_->CreateEvent(MediaLogEvent::PAUSE));
[email protected]baff4512011-10-19 18:21:07308
dalecurtis6d269ed2014-09-11 21:18:13309 if (!was_already_paused && delegate_)
[email protected]baff4512011-10-19 18:21:07310 delegate_->DidPause(this);
[email protected]ec9212f2008-12-18 21:40:36311}
312
[email protected]574a1d62009-07-17 03:23:46313bool WebMediaPlayerImpl::supportsSave() const {
acolwellb4034942014-08-28 15:42:43314 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]132dd57c2012-08-10 23:24:34315 return supports_save_;
[email protected]574a1d62009-07-17 03:23:46316}
317
[email protected]39bdde32013-04-17 17:44:20318void WebMediaPlayerImpl::seek(double seconds) {
[email protected]2a06ca62014-06-04 13:59:52319 DVLOG(1) << __FUNCTION__ << "(" << seconds << ")";
acolwellb4034942014-08-28 15:42:43320 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]d43ed912009-02-03 04:52:53321
scherkusd2c745b2014-09-04 05:03:40322 ended_ = false;
323
[email protected]1bb666802013-11-28 06:12:08324 if (ready_state_ > WebMediaPlayer::ReadyStateHaveMetadata)
325 SetReadyState(WebMediaPlayer::ReadyStateHaveMetadata);
326
[email protected]bb8a70b2013-06-26 06:23:35327 base::TimeDelta seek_time = ConvertSecondsToTimestamp(seconds);
328
[email protected]d228aeec2014-06-20 19:16:49329 if (seeking_) {
[email protected]5d11eff2011-09-15 00:06:06330 pending_seek_ = true;
331 pending_seek_seconds_ = seconds;
[email protected]efe7cd22012-09-12 23:55:01332 if (chunk_demuxer_)
[email protected]bb8a70b2013-06-26 06:23:35333 chunk_demuxer_->CancelPendingSeek(seek_time);
[email protected]5d11eff2011-09-15 00:06:06334 return;
335 }
336
[email protected]c93eb0a62011-08-09 22:47:24337 media_log_->AddEvent(media_log_->CreateSeekEvent(seconds));
338
[email protected]44ff37c02009-10-24 01:03:03339 // Update our paused time.
Bartosz Fabianowski36c68322014-11-13 13:48:37340 if (paused_)
341 paused_time_ = seek_time;
[email protected]44ff37c02009-10-24 01:03:03342
[email protected]b3766a22010-12-22 17:34:13343 seeking_ = true;
344
[email protected]efe7cd22012-09-12 23:55:01345 if (chunk_demuxer_)
[email protected]bb8a70b2013-06-26 06:23:35346 chunk_demuxer_->StartWaitingForSeek(seek_time);
[email protected]020fba32011-06-29 16:37:46347
[email protected]44ff37c02009-10-24 01:03:03348 // Kick off the asynchronous seek!
[email protected]f6af7592014-02-28 10:09:11349 pipeline_.Seek(
[email protected]44ff37c02009-10-24 01:03:03350 seek_time,
[email protected]4e982192014-06-21 13:35:45351 BIND_TO_RENDER_LOOP1(&WebMediaPlayerImpl::OnPipelineSeeked, true));
[email protected]ec9212f2008-12-18 21:40:36352}
353
[email protected]39bdde32013-04-17 17:44:20354void WebMediaPlayerImpl::setRate(double rate) {
[email protected]2a06ca62014-06-04 13:59:52355 DVLOG(1) << __FUNCTION__ << "(" << rate << ")";
acolwellb4034942014-08-28 15:42:43356 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]d43ed912009-02-03 04:52:53357
[email protected]378f0b72009-08-11 17:11:42358 // TODO(kylep): Remove when support for negatives is added. Also, modify the
359 // following checks so rewind uses reasonable values also.
[email protected]39bdde32013-04-17 17:44:20360 if (rate < 0.0)
[email protected]378f0b72009-08-11 17:11:42361 return;
362
363 // Limit rates to reasonable values by clamping.
[email protected]39bdde32013-04-17 17:44:20364 if (rate != 0.0) {
[email protected]378f0b72009-08-11 17:11:42365 if (rate < kMinRate)
366 rate = kMinRate;
367 else if (rate > kMaxRate)
368 rate = kMaxRate;
dalecurtisbb761e12014-09-12 01:16:35369 if (playback_rate_ == 0 && !paused_ && delegate_)
dalecurtis6d269ed2014-09-11 21:18:13370 delegate_->DidPlay(this);
dalecurtisbb761e12014-09-12 01:16:35371 } else if (playback_rate_ != 0 && !paused_ && delegate_) {
dalecurtis6d269ed2014-09-11 21:18:13372 delegate_->DidPause(this);
[email protected]378f0b72009-08-11 17:11:42373 }
374
[email protected]49480902009-07-14 20:23:43375 playback_rate_ = rate;
376 if (!paused_) {
[email protected]f6af7592014-02-28 10:09:11377 pipeline_.SetPlaybackRate(rate);
[email protected]039b7542013-10-17 22:06:25378 if (data_source_)
379 data_source_->MediaPlaybackRateChanged(rate);
[email protected]49480902009-07-14 20:23:43380 }
[email protected]ec9212f2008-12-18 21:40:36381}
382
[email protected]39bdde32013-04-17 17:44:20383void WebMediaPlayerImpl::setVolume(double volume) {
[email protected]2a06ca62014-06-04 13:59:52384 DVLOG(1) << __FUNCTION__ << "(" << volume << ")";
acolwellb4034942014-08-28 15:42:43385 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]d43ed912009-02-03 04:52:53386
[email protected]f6af7592014-02-28 10:09:11387 pipeline_.SetVolume(volume);
[email protected]ec9212f2008-12-18 21:40:36388}
[email protected]f0a51fb52009-03-05 12:46:38389
[email protected]23a8b1d82011-04-05 16:28:20390#define COMPILE_ASSERT_MATCHING_ENUM(webkit_name, chromium_name) \
[email protected]ef405f66b2012-04-18 02:39:55391 COMPILE_ASSERT(static_cast<int>(WebMediaPlayer::webkit_name) == \
acolwella5081a42014-08-28 23:42:52392 static_cast<int>(BufferedDataSource::chromium_name), \
[email protected]474c37a2011-08-23 20:24:52393 mismatching_enums)
[email protected]ef405f66b2012-04-18 02:39:55394COMPILE_ASSERT_MATCHING_ENUM(PreloadNone, NONE);
395COMPILE_ASSERT_MATCHING_ENUM(PreloadMetaData, METADATA);
396COMPILE_ASSERT_MATCHING_ENUM(PreloadAuto, AUTO);
[email protected]a5a01102012-06-06 17:01:24397#undef COMPILE_ASSERT_MATCHING_ENUM
[email protected]23a8b1d82011-04-05 16:28:20398
[email protected]ef405f66b2012-04-18 02:39:55399void WebMediaPlayerImpl::setPreload(WebMediaPlayer::Preload preload) {
[email protected]2a06ca62014-06-04 13:59:52400 DVLOG(1) << __FUNCTION__ << "(" << preload << ")";
acolwellb4034942014-08-28 15:42:43401 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]4e6be3f2009-05-07 02:24:44402
acolwella5081a42014-08-28 23:42:52403 preload_ = static_cast<BufferedDataSource::Preload>(preload);
[email protected]b49beeb2013-03-01 20:04:00404 if (data_source_)
[email protected]09c60222014-08-07 16:42:31405 data_source_->SetPreload(preload_);
[email protected]4e6be3f2009-05-07 02:24:44406}
407
[email protected]4e6be3f2009-05-07 02:24:44408bool WebMediaPlayerImpl::hasVideo() const {
acolwellb4034942014-08-28 15:42:43409 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]d43ed912009-02-03 04:52:53410
[email protected]b8877772014-03-26 20:17:15411 return pipeline_metadata_.has_video;
[email protected]d43ed912009-02-03 04:52:53412}
413
[email protected]fc367af2009-08-14 23:06:35414bool WebMediaPlayerImpl::hasAudio() const {
acolwellb4034942014-08-28 15:42:43415 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]fc367af2009-08-14 23:06:35416
[email protected]b8877772014-03-26 20:17:15417 return pipeline_metadata_.has_audio;
[email protected]fc367af2009-08-14 23:06:35418}
419
[email protected]180ef242013-11-07 06:50:46420blink::WebSize WebMediaPlayerImpl::naturalSize() const {
acolwellb4034942014-08-28 15:42:43421 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]d43ed912009-02-03 04:52:53422
[email protected]b8877772014-03-26 20:17:15423 return blink::WebSize(pipeline_metadata_.natural_size);
[email protected]d43ed912009-02-03 04:52:53424}
425
[email protected]4e6be3f2009-05-07 02:24:44426bool WebMediaPlayerImpl::paused() const {
acolwellb4034942014-08-28 15:42:43427 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]d43ed912009-02-03 04:52:53428
[email protected]f6af7592014-02-28 10:09:11429 return pipeline_.GetPlaybackRate() == 0.0f;
[email protected]d43ed912009-02-03 04:52:53430}
431
[email protected]4e6be3f2009-05-07 02:24:44432bool WebMediaPlayerImpl::seeking() const {
acolwellb4034942014-08-28 15:42:43433 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]d43ed912009-02-03 04:52:53434
[email protected]ef405f66b2012-04-18 02:39:55435 if (ready_state_ == WebMediaPlayer::ReadyStateHaveNothing)
[email protected]0acebfa2009-08-21 22:45:40436 return false;
[email protected]67cd5052009-09-10 21:53:22437
[email protected]b3766a22010-12-22 17:34:13438 return seeking_;
[email protected]ec9212f2008-12-18 21:40:36439}
440
[email protected]39bdde32013-04-17 17:44:20441double WebMediaPlayerImpl::duration() const {
acolwellb4034942014-08-28 15:42:43442 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]39bdde32013-04-17 17:44:20443
444 if (ready_state_ == WebMediaPlayer::ReadyStateHaveNothing)
445 return std::numeric_limits<double>::quiet_NaN();
446
[email protected]39bdde32013-04-17 17:44:20447 return GetPipelineDuration();
[email protected]d43ed912009-02-03 04:52:53448}
449
[email protected]db66d0092014-04-16 07:15:12450double WebMediaPlayerImpl::timelineOffset() const {
acolwellb4034942014-08-28 15:42:43451 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]db66d0092014-04-16 07:15:12452
453 if (pipeline_metadata_.timeline_offset.is_null())
454 return std::numeric_limits<double>::quiet_NaN();
455
456 return pipeline_metadata_.timeline_offset.ToJsTime();
457}
458
[email protected]39bdde32013-04-17 17:44:20459double WebMediaPlayerImpl::currentTime() const {
acolwellb4034942014-08-28 15:42:43460 DCHECK(main_task_runner_->BelongsToCurrentThread());
scherkusd2c745b2014-09-04 05:03:40461 DCHECK_NE(ready_state_, WebMediaPlayer::ReadyStateHaveNothing);
462
463 // TODO(scherkus): Replace with an explicit ended signal to HTMLMediaElement,
464 // see http://crbug.com/409280
465 if (ended_)
466 return duration();
467
[email protected]f6af7592014-02-28 10:09:11468 return (paused_ ? paused_time_ : pipeline_.GetMediaTime()).InSecondsF();
[email protected]d43ed912009-02-03 04:52:53469}
470
[email protected]ef405f66b2012-04-18 02:39:55471WebMediaPlayer::NetworkState WebMediaPlayerImpl::networkState() const {
acolwellb4034942014-08-28 15:42:43472 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]ddb1e5a2010-12-13 20:10:45473 return network_state_;
474}
475
[email protected]ef405f66b2012-04-18 02:39:55476WebMediaPlayer::ReadyState WebMediaPlayerImpl::readyState() const {
acolwellb4034942014-08-28 15:42:43477 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]ddb1e5a2010-12-13 20:10:45478 return ready_state_;
479}
480
[email protected]02022fc2014-05-16 00:05:31481blink::WebTimeRanges WebMediaPlayerImpl::buffered() const {
acolwellb4034942014-08-28 15:42:43482 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]779a8322014-08-22 21:28:37483
acolwell9e0840d2014-09-06 19:01:32484 Ranges<base::TimeDelta> buffered_time_ranges =
[email protected]02022fc2014-05-16 00:05:31485 pipeline_.GetBufferedTimeRanges();
[email protected]779a8322014-08-22 21:28:37486
487 const base::TimeDelta duration = pipeline_.GetMediaDuration();
acolwell9e0840d2014-09-06 19:01:32488 if (duration != kInfiniteDuration()) {
[email protected]779a8322014-08-22 21:28:37489 buffered_data_source_host_.AddBufferedTimeRanges(
490 &buffered_time_ranges, duration);
491 }
[email protected]02022fc2014-05-16 00:05:31492 return ConvertToWebTimeRanges(buffered_time_ranges);
493}
494
philipjb0e6f3f2014-09-30 09:51:53495blink::WebTimeRanges WebMediaPlayerImpl::seekable() const {
acolwellb4034942014-08-28 15:42:43496 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]39bdde32013-04-17 17:44:20497
dalecurtis56359cb2014-10-28 00:06:29498 if (ready_state_ < WebMediaPlayer::ReadyStateHaveMetadata)
philipjb0e6f3f2014-09-30 09:51:53499 return blink::WebTimeRanges();
500
dalecurtis56359cb2014-10-28 00:06:29501 const double seekable_end = duration();
502
503 // Allow a special exception for seeks to zero for streaming sources with a
504 // finite duration; this allows looping to work.
505 const bool allow_seek_to_zero = data_source_ && data_source_->IsStreaming() &&
506 base::IsFinite(seekable_end);
507
508 // TODO(dalecurtis): Technically this allows seeking on media which return an
509 // infinite duration so long as DataSource::IsStreaming() is false. While not
510 // expected, disabling this breaks semi-live players, http://crbug.com/427412.
511 const blink::WebTimeRange seekable_range(
512 0.0, allow_seek_to_zero ? 0.0 : seekable_end);
philipjb0e6f3f2014-09-30 09:51:53513 return blink::WebTimeRanges(&seekable_range, 1);
[email protected]ec9212f2008-12-18 21:40:36514}
515
[email protected]5d2b3e4c2014-05-12 23:27:30516bool WebMediaPlayerImpl::didLoadingProgress() {
acolwellb4034942014-08-28 15:42:43517 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]6683e1b2014-04-10 01:45:38518 bool pipeline_progress = pipeline_.DidLoadingProgress();
519 bool data_progress = buffered_data_source_host_.DidLoadingProgress();
520 return pipeline_progress || data_progress;
[email protected]d43ed912009-02-03 04:52:53521}
522
[email protected]dd5c7972014-08-21 15:00:37523void WebMediaPlayerImpl::paint(blink::WebCanvas* canvas,
524 const blink::WebRect& rect,
[email protected]dd5c7972014-08-21 15:00:37525 unsigned char alpha,
526 SkXfermode::Mode mode) {
acolwellb4034942014-08-28 15:42:43527 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]dd061e12014-05-06 19:21:22528 TRACE_EVENT0("media", "WebMediaPlayerImpl:paint");
[email protected]4e6be3f2009-05-07 02:24:44529
[email protected]5e1502e2014-03-24 22:48:44530 // TODO(scherkus): Clarify paint() API contract to better understand when and
531 // why it's being called. For example, today paint() is called when:
532 // - We haven't reached HAVE_CURRENT_DATA and need to paint black
533 // - We're painting to a canvas
534 // See http://crbug.com/341225 http://crbug.com/342621 for details.
acolwell9e0840d2014-09-06 19:01:32535 scoped_refptr<VideoFrame> video_frame =
[email protected]dd061e12014-05-06 19:21:22536 GetCurrentFrameFromCompositor();
[email protected]0fe5d43b2014-01-24 23:32:45537
[email protected]b49beeb2013-03-01 20:04:00538 gfx::Rect gfx_rect(rect);
[email protected]f78c3e82014-08-08 01:24:47539
rileya54b8c1742014-09-16 02:20:42540 skcanvas_video_renderer_.Paint(video_frame,
[email protected]8bad1822014-08-09 05:52:38541 canvas,
542 gfx_rect,
543 alpha,
[email protected]dd5c7972014-08-21 15:00:37544 mode,
[email protected]8bad1822014-08-09 05:52:38545 pipeline_metadata_.video_rotation);
[email protected]ec9212f2008-12-18 21:40:36546}
[email protected]5df51652009-01-17 00:03:00547
[email protected]38259a7a82009-07-29 21:49:49548bool WebMediaPlayerImpl::hasSingleSecurityOrigin() const {
[email protected]b49beeb2013-03-01 20:04:00549 if (data_source_)
550 return data_source_->HasSingleOrigin();
[email protected]fcdb7462009-10-21 21:05:11551 return true;
[email protected]38259a7a82009-07-29 21:49:49552}
553
[email protected]3fe27112012-06-07 04:00:01554bool WebMediaPlayerImpl::didPassCORSAccessCheck() const {
[email protected]b49beeb2013-03-01 20:04:00555 if (data_source_)
556 return data_source_->DidPassCORSAccessCheck();
557 return false;
[email protected]3fe27112012-06-07 04:00:01558}
559
[email protected]39bdde32013-04-17 17:44:20560double WebMediaPlayerImpl::mediaTimeForTimeValue(double timeValue) const {
[email protected]e06e16d82011-05-26 22:13:33561 return ConvertSecondsToTimestamp(timeValue).InSecondsF();
562}
563
[email protected]d82b18ae2011-03-23 21:28:59564unsigned WebMediaPlayerImpl::decodedFrameCount() const {
acolwellb4034942014-08-28 15:42:43565 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]4c51bc662011-02-16 02:03:16566
acolwell9e0840d2014-09-06 19:01:32567 PipelineStatistics stats = pipeline_.GetStatistics();
[email protected]4c51bc662011-02-16 02:03:16568 return stats.video_frames_decoded;
569}
570
[email protected]d82b18ae2011-03-23 21:28:59571unsigned WebMediaPlayerImpl::droppedFrameCount() const {
acolwellb4034942014-08-28 15:42:43572 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]4c51bc662011-02-16 02:03:16573
acolwell9e0840d2014-09-06 19:01:32574 PipelineStatistics stats = pipeline_.GetStatistics();
[email protected]dd061e12014-05-06 19:21:22575 return stats.video_frames_dropped;
[email protected]4c51bc662011-02-16 02:03:16576}
577
[email protected]d82b18ae2011-03-23 21:28:59578unsigned WebMediaPlayerImpl::audioDecodedByteCount() const {
acolwellb4034942014-08-28 15:42:43579 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]4c51bc662011-02-16 02:03:16580
acolwell9e0840d2014-09-06 19:01:32581 PipelineStatistics stats = pipeline_.GetStatistics();
[email protected]4c51bc662011-02-16 02:03:16582 return stats.audio_bytes_decoded;
583}
584
[email protected]d82b18ae2011-03-23 21:28:59585unsigned WebMediaPlayerImpl::videoDecodedByteCount() const {
acolwellb4034942014-08-28 15:42:43586 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]4c51bc662011-02-16 02:03:16587
acolwell9e0840d2014-09-06 19:01:32588 PipelineStatistics stats = pipeline_.GetStatistics();
[email protected]4c51bc662011-02-16 02:03:16589 return stats.video_bytes_decoded;
590}
591
[email protected]6523b242013-03-13 11:10:07592bool WebMediaPlayerImpl::copyVideoTextureToPlatformTexture(
[email protected]180ef242013-11-07 06:50:46593 blink::WebGraphicsContext3D* web_graphics_context,
[email protected]6523b242013-03-13 11:10:07594 unsigned int texture,
595 unsigned int level,
596 unsigned int internal_format,
[email protected]9aa2b2782013-05-14 00:13:31597 unsigned int type,
[email protected]6523b242013-03-13 11:10:07598 bool premultiply_alpha,
599 bool flip_y) {
[email protected]bfc05f22013-10-19 17:55:16600 TRACE_EVENT0("media", "WebMediaPlayerImpl:copyVideoTextureToPlatformTexture");
601
acolwell9e0840d2014-09-06 19:01:32602 scoped_refptr<VideoFrame> video_frame =
[email protected]dd061e12014-05-06 19:21:22603 GetCurrentFrameFromCompositor();
604
dchengf70d95e2014-08-27 02:06:28605 if (!video_frame.get())
[email protected]e56f88c72013-06-25 22:31:29606 return false;
acolwell9e0840d2014-09-06 19:01:32607 if (video_frame->format() != VideoFrame::NATIVE_TEXTURE)
[email protected]e56f88c72013-06-25 22:31:29608 return false;
[email protected]df41e252014-02-03 23:39:50609
[email protected]c37a4cc2014-04-30 19:15:28610 const gpu::MailboxHolder* mailbox_holder = video_frame->mailbox_holder();
[email protected]df41e252014-02-03 23:39:50611 if (mailbox_holder->texture_target != GL_TEXTURE_2D)
[email protected]e56f88c72013-06-25 22:31:29612 return false;
613
[email protected]df41e252014-02-03 23:39:50614 web_graphics_context->waitSyncPoint(mailbox_holder->sync_point);
[email protected]c77f2722014-07-22 09:04:32615 uint32 source_texture = web_graphics_context->createAndConsumeTextureCHROMIUM(
616 GL_TEXTURE_2D, mailbox_holder->mailbox.name);
[email protected]e56f88c72013-06-25 22:31:29617
618 // The video is stored in a unmultiplied format, so premultiply
619 // if necessary.
620 web_graphics_context->pixelStorei(GL_UNPACK_PREMULTIPLY_ALPHA_CHROMIUM,
621 premultiply_alpha);
622 // Application itself needs to take care of setting the right flip_y
623 // value down to get the expected result.
624 // flip_y==true means to reverse the video orientation while
625 // flip_y==false means to keep the intrinsic orientation.
626 web_graphics_context->pixelStorei(GL_UNPACK_FLIP_Y_CHROMIUM, flip_y);
627 web_graphics_context->copyTextureCHROMIUM(GL_TEXTURE_2D,
628 source_texture,
629 texture,
630 level,
631 internal_format,
632 type);
633 web_graphics_context->pixelStorei(GL_UNPACK_FLIP_Y_CHROMIUM, false);
634 web_graphics_context->pixelStorei(GL_UNPACK_PREMULTIPLY_ALPHA_CHROMIUM,
635 false);
636
637 web_graphics_context->deleteTexture(source_texture);
[email protected]e56f88c72013-06-25 22:31:29638 web_graphics_context->flush();
[email protected]47c345b2014-07-22 10:31:57639
640 SyncPointClientImpl client(web_graphics_context);
641 video_frame->UpdateReleaseSyncPoint(&client);
[email protected]e56f88c72013-06-25 22:31:29642 return true;
[email protected]6523b242013-03-13 11:10:07643}
644
[email protected]2ca7d5c2012-10-23 07:30:54645WebMediaPlayer::MediaKeyException
[email protected]f7a6b992012-04-19 09:45:56646WebMediaPlayerImpl::generateKeyRequest(const WebString& key_system,
647 const unsigned char* init_data,
648 unsigned init_data_length) {
acolwellb4034942014-08-28 15:42:43649 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]7502ef12014-01-25 01:19:27650
acolwelle2ea5182014-08-25 23:01:07651 return encrypted_media_support_->GenerateKeyRequest(
652 frame_, key_system, init_data, init_data_length);
[email protected]f7a6b992012-04-19 09:45:56653}
654
[email protected]2ca7d5c2012-10-23 07:30:54655WebMediaPlayer::MediaKeyException WebMediaPlayerImpl::addKey(
656 const WebString& key_system,
657 const unsigned char* key,
658 unsigned key_length,
659 const unsigned char* init_data,
660 unsigned init_data_length,
661 const WebString& session_id) {
acolwellb4034942014-08-28 15:42:43662 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]f7a6b992012-04-19 09:45:56663
acolwelle2ea5182014-08-25 23:01:07664 return encrypted_media_support_->AddKey(
665 key_system, key, key_length, init_data, init_data_length, session_id);
[email protected]f7a6b992012-04-19 09:45:56666}
667
[email protected]2ca7d5c2012-10-23 07:30:54668WebMediaPlayer::MediaKeyException WebMediaPlayerImpl::cancelKeyRequest(
669 const WebString& key_system,
670 const WebString& session_id) {
acolwellb4034942014-08-28 15:42:43671 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]0b9999d2014-02-20 02:16:11672
acolwelle2ea5182014-08-25 23:01:07673 return encrypted_media_support_->CancelKeyRequest(key_system, session_id);
[email protected]f7a6b992012-04-19 09:45:56674}
675
[email protected]7bce1832014-01-09 00:01:22676void WebMediaPlayerImpl::setContentDecryptionModule(
677 blink::WebContentDecryptionModule* cdm) {
acolwellb4034942014-08-28 15:42:43678 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]7502ef12014-01-25 01:19:27679
acolwelle2ea5182014-08-25 23:01:07680 encrypted_media_support_->SetContentDecryptionModule(cdm);
[email protected]9ebc3b03f2014-08-13 04:01:23681}
682
683void WebMediaPlayerImpl::setContentDecryptionModule(
684 blink::WebContentDecryptionModule* cdm,
685 blink::WebContentDecryptionModuleResult result) {
acolwellb4034942014-08-28 15:42:43686 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]9ebc3b03f2014-08-13 04:01:23687
acolwelle2ea5182014-08-25 23:01:07688 encrypted_media_support_->SetContentDecryptionModule(cdm, result);
[email protected]9ebc3b03f2014-08-13 04:01:23689}
690
[email protected]4e982192014-06-21 13:35:45691void WebMediaPlayerImpl::OnPipelineSeeked(bool time_changed,
692 PipelineStatus status) {
693 DVLOG(1) << __FUNCTION__ << "(" << time_changed << ", " << status << ")";
acolwellb4034942014-08-28 15:42:43694 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]5d11eff2011-09-15 00:06:06695 seeking_ = false;
696 if (pending_seek_) {
697 pending_seek_ = false;
698 seek(pending_seek_seconds_);
699 return;
700 }
701
acolwell9e0840d2014-09-06 19:01:32702 if (status != PIPELINE_OK) {
[email protected]10a64d92012-04-10 21:08:02703 OnPipelineError(status);
704 return;
[email protected]96706912009-07-15 17:18:05705 }
[email protected]10a64d92012-04-10 21:08:02706
707 // Update our paused time.
708 if (paused_)
[email protected]f6af7592014-02-28 10:09:11709 paused_time_ = pipeline_.GetMediaTime();
[email protected]10a64d92012-04-10 21:08:02710
[email protected]ba7d5f92014-06-24 05:37:40711 should_notify_time_changed_ = time_changed;
[email protected]8931c41a2009-07-07 17:31:49712}
713
[email protected]6954fe12013-01-03 03:22:32714void WebMediaPlayerImpl::OnPipelineEnded() {
[email protected]2a06ca62014-06-04 13:59:52715 DVLOG(1) << __FUNCTION__;
acolwellb4034942014-08-28 15:42:43716 DCHECK(main_task_runner_->BelongsToCurrentThread());
scherkusd2c745b2014-09-04 05:03:40717
718 // Ignore state changes until we've completed all outstanding seeks.
719 if (seeking_ || pending_seek_)
720 return;
721
722 ended_ = true;
[email protected]ce70c982013-12-20 17:04:32723 client_->timeChanged();
[email protected]576537842009-08-12 23:52:05724}
725
[email protected]a9590c22011-03-16 16:57:02726void WebMediaPlayerImpl::OnPipelineError(PipelineStatus error) {
acolwellb4034942014-08-28 15:42:43727 DCHECK(main_task_runner_->BelongsToCurrentThread());
acolwell9e0840d2014-09-06 19:01:32728 DCHECK_NE(error, PIPELINE_OK);
[email protected]a8e2cb82012-08-17 00:02:39729
730 if (ready_state_ == WebMediaPlayer::ReadyStateHaveNothing) {
731 // Any error that occurs before reaching ReadyStateHaveMetadata should
732 // be considered a format error.
733 SetNetworkState(WebMediaPlayer::NetworkStateFormatError);
[email protected]a8e2cb82012-08-17 00:02:39734 return;
735 }
736
[email protected]be57ee52013-05-28 22:27:27737 SetNetworkState(PipelineErrorToNetworkState(error));
[email protected]a9590c22011-03-16 16:57:02738
acolwell9e0840d2014-09-06 19:01:32739 if (error == PIPELINE_ERROR_DECRYPT)
acolwelle2ea5182014-08-25 23:01:07740 encrypted_media_support_->OnPipelineDecryptError();
[email protected]db190487d2009-07-30 18:51:52741}
742
[email protected]b8877772014-03-26 20:17:15743void WebMediaPlayerImpl::OnPipelineMetadata(
acolwell9e0840d2014-09-06 19:01:32744 PipelineMetadata metadata) {
[email protected]2a06ca62014-06-04 13:59:52745 DVLOG(1) << __FUNCTION__;
[email protected]a8e2cb82012-08-17 00:02:39746
[email protected]b8877772014-03-26 20:17:15747 pipeline_metadata_ = metadata;
[email protected]739847c02014-01-16 00:12:25748
[email protected]eddfef92014-07-18 01:26:47749 UMA_HISTOGRAM_ENUMERATION("Media.VideoRotation",
750 metadata.video_rotation,
acolwell9e0840d2014-09-06 19:01:32751 VIDEO_ROTATION_MAX + 1);
[email protected]b8877772014-03-26 20:17:15752 SetReadyState(WebMediaPlayer::ReadyStateHaveMetadata);
[email protected]21c3f7502013-03-23 03:29:51753
[email protected]b8877772014-03-26 20:17:15754 if (hasVideo()) {
755 DCHECK(!video_weblayer_);
[email protected]f78c3e82014-08-08 01:24:47756 scoped_refptr<cc::VideoLayer> layer =
757 cc::VideoLayer::Create(compositor_, pipeline_metadata_.video_rotation);
758
acolwell9e0840d2014-09-06 19:01:32759 if (pipeline_metadata_.video_rotation == VIDEO_ROTATION_90 ||
760 pipeline_metadata_.video_rotation == VIDEO_ROTATION_270) {
[email protected]f78c3e82014-08-08 01:24:47761 gfx::Size size = pipeline_metadata_.natural_size;
762 pipeline_metadata_.natural_size = gfx::Size(size.height(), size.width());
763 }
764
[email protected]38564622014-08-19 02:47:18765 video_weblayer_.reset(new cc_blink::WebLayerImpl(layer));
[email protected]75e145a2014-04-15 17:44:32766 video_weblayer_->setOpaque(opaque_);
[email protected]a7c4f582014-04-16 18:44:49767 client_->setWebLayer(video_weblayer_.get());
[email protected]a8e2cb82012-08-17 00:02:39768 }
[email protected]a8e2cb82012-08-17 00:02:39769}
770
[email protected]ba7d5f92014-06-24 05:37:40771void WebMediaPlayerImpl::OnPipelineBufferingStateChanged(
acolwell9e0840d2014-09-06 19:01:32772 BufferingState buffering_state) {
[email protected]ba7d5f92014-06-24 05:37:40773 DVLOG(1) << __FUNCTION__ << "(" << buffering_state << ")";
[email protected]b8877772014-03-26 20:17:15774
[email protected]ba7d5f92014-06-24 05:37:40775 // Ignore buffering state changes until we've completed all outstanding seeks.
776 if (seeking_ || pending_seek_)
777 return;
[email protected]b8877772014-03-26 20:17:15778
[email protected]ba7d5f92014-06-24 05:37:40779 // TODO(scherkus): Handle other buffering states when Pipeline starts using
780 // them and translate them ready state changes http://crbug.com/144683
acolwell9e0840d2014-09-06 19:01:32781 DCHECK_EQ(buffering_state, BUFFERING_HAVE_ENOUGH);
[email protected]ba7d5f92014-06-24 05:37:40782 SetReadyState(WebMediaPlayer::ReadyStateHaveEnoughData);
783
784 // Blink expects a timeChanged() in response to a seek().
785 if (should_notify_time_changed_)
786 client_->timeChanged();
[email protected]b8877772014-03-26 20:17:15787}
788
[email protected]ef8394c2013-08-21 20:26:30789void WebMediaPlayerImpl::OnDemuxerOpened() {
acolwellb4034942014-08-28 15:42:43790 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]ce70c982013-12-20 17:04:32791 client_->mediaSourceOpened(new WebMediaSourceImpl(
[email protected]5f811a2d2013-03-15 23:54:51792 chunk_demuxer_, base::Bind(&LogMediaSourceError, media_log_)));
[email protected]81bb3322011-07-21 15:55:50793}
794
[email protected]8a561062013-11-22 01:19:31795void WebMediaPlayerImpl::OnAddTextTrack(
acolwell9e0840d2014-09-06 19:01:32796 const TextTrackConfig& config,
797 const AddTextTrackDoneCB& done_cb) {
acolwellb4034942014-08-28 15:42:43798 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]71537722013-05-23 06:47:53799
[email protected]8a561062013-11-22 01:19:31800 const WebInbandTextTrackImpl::Kind web_kind =
801 static_cast<WebInbandTextTrackImpl::Kind>(config.kind());
802 const blink::WebString web_label =
803 blink::WebString::fromUTF8(config.label());
804 const blink::WebString web_language =
805 blink::WebString::fromUTF8(config.language());
[email protected]427ff102013-11-26 23:45:40806 const blink::WebString web_id =
807 blink::WebString::fromUTF8(config.id());
[email protected]71537722013-05-23 06:47:53808
[email protected]8a561062013-11-22 01:19:31809 scoped_ptr<WebInbandTextTrackImpl> web_inband_text_track(
[email protected]427ff102013-11-26 23:45:40810 new WebInbandTextTrackImpl(web_kind, web_label, web_language, web_id,
[email protected]8a561062013-11-22 01:19:31811 text_track_index_++));
812
acolwell9e0840d2014-09-06 19:01:32813 scoped_ptr<TextTrack> text_track(new TextTrackImpl(
acolwellb4034942014-08-28 15:42:43814 main_task_runner_, client_, web_inband_text_track.Pass()));
[email protected]8a561062013-11-22 01:19:31815
816 done_cb.Run(text_track.Pass());
[email protected]71537722013-05-23 06:47:53817}
818
[email protected]fee8a902014-06-03 13:43:36819void WebMediaPlayerImpl::DataSourceInitialized(bool success) {
acolwellb4034942014-08-28 15:42:43820 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]a9415292012-01-19 19:55:20821
[email protected]d250190da3b2012-07-23 22:57:30822 if (!success) {
[email protected]ef405f66b2012-04-18 02:39:55823 SetNetworkState(WebMediaPlayer::NetworkStateFormatError);
[email protected]a9415292012-01-19 19:55:20824 return;
825 }
826
[email protected]ef8394c2013-08-21 20:26:30827 StartPipeline();
[email protected]a9415292012-01-19 19:55:20828}
829
[email protected]122f40252012-06-12 05:01:56830void WebMediaPlayerImpl::NotifyDownloading(bool is_downloading) {
831 if (!is_downloading && network_state_ == WebMediaPlayer::NetworkStateLoading)
832 SetNetworkState(WebMediaPlayer::NetworkStateIdle);
833 else if (is_downloading && network_state_ == WebMediaPlayer::NetworkStateIdle)
834 SetNetworkState(WebMediaPlayer::NetworkStateLoading);
835 media_log_->AddEvent(
836 media_log_->CreateBooleanEvent(
acolwell9e0840d2014-09-06 19:01:32837 MediaLogEvent::NETWORK_ACTIVITY_SET,
[email protected]122f40252012-06-12 05:01:56838 "is_downloading_data", is_downloading));
839}
840
xhwangbe9da702014-08-23 21:44:55841// TODO(xhwang): Move this to a factory class so that we can create different
842// renderers.
acolwell9e0840d2014-09-06 19:01:32843scoped_ptr<Renderer> WebMediaPlayerImpl::CreateRenderer() {
844 SetDecryptorReadyCB set_decryptor_ready_cb =
acolwelle2ea5182014-08-25 23:01:07845 encrypted_media_support_->CreateSetDecryptorReadyCB();
xhwangbe9da702014-08-23 21:44:55846
847 // Create our audio decoders and renderer.
acolwell9e0840d2014-09-06 19:01:32848 ScopedVector<AudioDecoder> audio_decoders;
xhwangbe9da702014-08-23 21:44:55849
xhwangff459d4e2014-09-09 04:55:47850 audio_decoders.push_back(new media::FFmpegAudioDecoder(
851 media_task_runner_, base::Bind(&LogMediaSourceError, media_log_)));
852 audio_decoders.push_back(new media::OpusAudioDecoder(media_task_runner_));
xhwangbe9da702014-08-23 21:44:55853
xhwangff459d4e2014-09-09 04:55:47854 scoped_ptr<AudioRenderer> audio_renderer(
855 new AudioRendererImpl(media_task_runner_,
856 audio_source_provider_.get(),
857 audio_decoders.Pass(),
858 set_decryptor_ready_cb,
859 audio_hardware_config_,
860 media_log_));
xhwangbe9da702014-08-23 21:44:55861
862 // Create our video decoders and renderer.
acolwell9e0840d2014-09-06 19:01:32863 ScopedVector<VideoDecoder> video_decoders;
xhwangbe9da702014-08-23 21:44:55864
xhwangff459d4e2014-09-09 04:55:47865 if (gpu_factories_.get())
866 video_decoders.push_back(new GpuVideoDecoder(gpu_factories_));
xhwangbe9da702014-08-23 21:44:55867
868#if !defined(MEDIA_DISABLE_LIBVPX)
acolwell9e0840d2014-09-06 19:01:32869 video_decoders.push_back(new VpxVideoDecoder(media_task_runner_));
xhwangbe9da702014-08-23 21:44:55870#endif // !defined(MEDIA_DISABLE_LIBVPX)
871
acolwell9e0840d2014-09-06 19:01:32872 video_decoders.push_back(new FFmpegVideoDecoder(media_task_runner_));
xhwangbe9da702014-08-23 21:44:55873
xhwangff459d4e2014-09-09 04:55:47874 scoped_ptr<VideoRenderer> video_renderer(new VideoRendererImpl(
875 media_task_runner_,
876 video_decoders.Pass(),
877 set_decryptor_ready_cb,
xhwangff459d4e2014-09-09 04:55:47878 true,
879 media_log_));
xhwangbe9da702014-08-23 21:44:55880
881 // Create renderer.
acolwell9e0840d2014-09-06 19:01:32882 return scoped_ptr<Renderer>(new RendererImpl(
xhwangabd95fd2014-10-03 07:10:01883 media_task_runner_, audio_renderer.Pass(), video_renderer.Pass()));
xhwangbe9da702014-08-23 21:44:55884}
885
[email protected]ef8394c2013-08-21 20:26:30886void WebMediaPlayerImpl::StartPipeline() {
acolwellb4034942014-08-28 15:42:43887 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]ddbc6ff2013-04-19 15:28:33888
[email protected]0814ac62013-06-07 21:01:29889 // Keep track if this is a MSE or non-MSE playback.
[email protected]ef8394c2013-08-21 20:26:30890 UMA_HISTOGRAM_BOOLEAN("Media.MSE.Playback",
891 (load_type_ == LoadTypeMediaSource));
[email protected]0814ac62013-06-07 21:01:29892
acolwell9e0840d2014-09-06 19:01:32893 LogCB mse_log_cb;
894 Demuxer::NeedKeyCB need_key_cb =
acolwelle2ea5182014-08-25 23:01:07895 encrypted_media_support_->CreateNeedKeyCB();
[email protected]2b57e2e2014-05-09 11:07:25896
[email protected]ddbc6ff2013-04-19 15:28:33897 // Figure out which demuxer to use.
[email protected]ef8394c2013-08-21 20:26:30898 if (load_type_ != LoadTypeMediaSource) {
[email protected]ddbc6ff2013-04-19 15:28:33899 DCHECK(!chunk_demuxer_);
[email protected]f5443ef72013-04-22 04:03:38900 DCHECK(data_source_);
901
acolwell9e0840d2014-09-06 19:01:32902 demuxer_.reset(new FFmpegDemuxer(
acolwellb4034942014-08-28 15:42:43903 media_task_runner_, data_source_.get(),
acolwelle2ea5182014-08-25 23:01:07904 need_key_cb,
[email protected]1e931f62013-07-31 23:25:52905 media_log_));
[email protected]ddbc6ff2013-04-19 15:28:33906 } else {
[email protected]f5443ef72013-04-22 04:03:38907 DCHECK(!chunk_demuxer_);
908 DCHECK(!data_source_);
909
[email protected]2b57e2e2014-05-09 11:07:25910 mse_log_cb = base::Bind(&LogMediaSourceError, media_log_);
911
acolwell9e0840d2014-09-06 19:01:32912 chunk_demuxer_ = new ChunkDemuxer(
[email protected]ef8394c2013-08-21 20:26:30913 BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnDemuxerOpened),
acolwelle2ea5182014-08-25 23:01:07914 need_key_cb,
[email protected]2b57e2e2014-05-09 11:07:25915 mse_log_cb,
[email protected]ae3c42e2014-04-30 05:48:05916 true);
[email protected]f5443ef72013-04-22 04:03:38917 demuxer_.reset(chunk_demuxer_);
[email protected]ddbc6ff2013-04-19 15:28:33918 }
919
[email protected]f5443ef72013-04-22 04:03:38920 // ... and we're ready to go!
[email protected]d228aeec2014-06-20 19:16:49921 seeking_ = true;
xhwangf94a634d2014-10-22 22:07:27922
923 if (!renderer_)
924 renderer_ = CreateRenderer();
925
[email protected]f6af7592014-02-28 10:09:11926 pipeline_.Start(
xhwang59805902014-08-29 01:44:15927 demuxer_.get(),
xhwangf94a634d2014-10-22 22:07:27928 renderer_.Pass(),
[email protected]f5443ef72013-04-22 04:03:38929 BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnPipelineEnded),
930 BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnPipelineError),
[email protected]4e982192014-06-21 13:35:45931 BIND_TO_RENDER_LOOP1(&WebMediaPlayerImpl::OnPipelineSeeked, false),
[email protected]b8877772014-03-26 20:17:15932 BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnPipelineMetadata),
[email protected]ba7d5f92014-06-24 05:37:40933 BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnPipelineBufferingStateChanged),
xhwang94c0bd32014-11-13 20:49:31934 base::Bind(&WebMediaPlayerImpl::FrameReady, base::Unretained(this)),
xhwang59805902014-08-29 01:44:15935 BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnDurationChanged),
936 BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnAddTextTrack));
[email protected]f5443ef72013-04-22 04:03:38937}
938
939void WebMediaPlayerImpl::SetNetworkState(WebMediaPlayer::NetworkState state) {
[email protected]2a06ca62014-06-04 13:59:52940 DVLOG(1) << __FUNCTION__ << "(" << state << ")";
acolwellb4034942014-08-28 15:42:43941 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]f5443ef72013-04-22 04:03:38942 network_state_ = state;
943 // Always notify to ensure client has the latest value.
[email protected]ce70c982013-12-20 17:04:32944 client_->networkStateChanged();
[email protected]f5443ef72013-04-22 04:03:38945}
946
947void WebMediaPlayerImpl::SetReadyState(WebMediaPlayer::ReadyState state) {
[email protected]2a06ca62014-06-04 13:59:52948 DVLOG(1) << __FUNCTION__ << "(" << state << ")";
acolwellb4034942014-08-28 15:42:43949 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]f5443ef72013-04-22 04:03:38950
[email protected]fee8a902014-06-03 13:43:36951 if (state == WebMediaPlayer::ReadyStateHaveEnoughData && data_source_ &&
952 data_source_->assume_fully_buffered() &&
[email protected]f5443ef72013-04-22 04:03:38953 network_state_ == WebMediaPlayer::NetworkStateLoading)
954 SetNetworkState(WebMediaPlayer::NetworkStateLoaded);
955
956 ready_state_ = state;
957 // Always notify to ensure client has the latest value.
[email protected]ce70c982013-12-20 17:04:32958 client_->readyStateChanged();
[email protected]f5443ef72013-04-22 04:03:38959}
960
[email protected]180ef242013-11-07 06:50:46961blink::WebAudioSourceProvider* WebMediaPlayerImpl::audioSourceProvider() {
[email protected]ff875be52013-06-02 23:47:38962 return audio_source_provider_.get();
[email protected]f5443ef72013-04-22 04:03:38963}
964
[email protected]f5443ef72013-04-22 04:03:38965double WebMediaPlayerImpl::GetPipelineDuration() const {
[email protected]f6af7592014-02-28 10:09:11966 base::TimeDelta duration = pipeline_.GetMediaDuration();
[email protected]f5443ef72013-04-22 04:03:38967
968 // Return positive infinity if the resource is unbounded.
969 // http://www.whatwg.org/specs/web-apps/current-work/multipage/video.html#dom-media-duration
acolwell9e0840d2014-09-06 19:01:32970 if (duration == kInfiniteDuration())
[email protected]f5443ef72013-04-22 04:03:38971 return std::numeric_limits<double>::infinity();
972
973 return duration.InSecondsF();
974}
975
[email protected]75e145a2014-04-15 17:44:32976void WebMediaPlayerImpl::OnDurationChanged() {
[email protected]f5443ef72013-04-22 04:03:38977 if (ready_state_ == WebMediaPlayer::ReadyStateHaveNothing)
978 return;
979
[email protected]ce70c982013-12-20 17:04:32980 client_->durationChanged();
[email protected]f5443ef72013-04-22 04:03:38981}
982
[email protected]75e145a2014-04-15 17:44:32983void WebMediaPlayerImpl::OnNaturalSizeChanged(gfx::Size size) {
acolwellb4034942014-08-28 15:42:43984 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]739847c02014-01-16 00:12:25985 DCHECK_NE(ready_state_, WebMediaPlayer::ReadyStateHaveNothing);
986 TRACE_EVENT0("media", "WebMediaPlayerImpl::OnNaturalSizeChanged");
987
988 media_log_->AddEvent(
989 media_log_->CreateVideoSizeSetEvent(size.width(), size.height()));
[email protected]b8877772014-03-26 20:17:15990 pipeline_metadata_.natural_size = size;
[email protected]739847c02014-01-16 00:12:25991
992 client_->sizeChanged();
993}
994
[email protected]75e145a2014-04-15 17:44:32995void WebMediaPlayerImpl::OnOpacityChanged(bool opaque) {
acolwellb4034942014-08-28 15:42:43996 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]75e145a2014-04-15 17:44:32997 DCHECK_NE(ready_state_, WebMediaPlayer::ReadyStateHaveNothing);
998
999 opaque_ = opaque;
[email protected]75e145a2014-04-15 17:44:321000 if (video_weblayer_)
1001 video_weblayer_->setOpaque(opaque_);
1002}
1003
[email protected]f5443ef72013-04-22 04:03:381004void WebMediaPlayerImpl::FrameReady(
acolwell9e0840d2014-09-06 19:01:321005 const scoped_refptr<VideoFrame>& frame) {
[email protected]dd061e12014-05-06 19:21:221006 compositor_task_runner_->PostTask(
1007 FROM_HERE,
1008 base::Bind(&VideoFrameCompositor::UpdateCurrentFrame,
1009 base::Unretained(compositor_),
1010 frame));
[email protected]bfc05f22013-10-19 17:55:161011}
1012
[email protected]dd061e12014-05-06 19:21:221013static void GetCurrentFrameAndSignal(
1014 VideoFrameCompositor* compositor,
acolwell9e0840d2014-09-06 19:01:321015 scoped_refptr<VideoFrame>* video_frame_out,
[email protected]dd061e12014-05-06 19:21:221016 base::WaitableEvent* event) {
1017 TRACE_EVENT0("media", "GetCurrentFrameAndSignal");
1018 *video_frame_out = compositor->GetCurrentFrame();
1019 event->Signal();
1020}
1021
acolwell9e0840d2014-09-06 19:01:321022scoped_refptr<VideoFrame>
[email protected]dd061e12014-05-06 19:21:221023WebMediaPlayerImpl::GetCurrentFrameFromCompositor() {
1024 TRACE_EVENT0("media", "WebMediaPlayerImpl::GetCurrentFrameFromCompositor");
1025 if (compositor_task_runner_->BelongsToCurrentThread())
1026 return compositor_->GetCurrentFrame();
1027
1028 // Use a posted task and waitable event instead of a lock otherwise
1029 // WebGL/Canvas can see different content than what the compositor is seeing.
acolwell9e0840d2014-09-06 19:01:321030 scoped_refptr<VideoFrame> video_frame;
[email protected]dd061e12014-05-06 19:21:221031 base::WaitableEvent event(false, false);
1032 compositor_task_runner_->PostTask(FROM_HERE,
1033 base::Bind(&GetCurrentFrameAndSignal,
1034 base::Unretained(compositor_),
1035 &video_frame,
1036 &event));
1037 event.Wait();
1038 return video_frame;
1039}
1040
acolwell9e0840d2014-09-06 19:01:321041} // namespace media