blob: e5ac3c98ecf7692c3e10c91d88b8e9bb97886158 [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"
xhwang0ad11e512014-11-25 23:43:0930#include "media/base/cdm_context.h"
[email protected]32da1002010-03-03 21:57:3531#include "media/base/limits.h"
[email protected]090f7312011-08-05 23:26:4032#include "media/base/media_log.h"
[email protected]d399866c2012-01-18 09:30:3233#include "media/base/pipeline.h"
[email protected]8a561062013-11-22 01:19:3134#include "media/base/text_renderer.h"
[email protected]e81283bb2010-08-31 18:01:2135#include "media/base/video_frame.h"
acolwell9e0840d2014-09-06 19:01:3236#include "media/blink/buffered_data_source.h"
37#include "media/blink/encrypted_media_player_support.h"
38#include "media/blink/texttrack_impl.h"
39#include "media/blink/webaudiosourceprovider_impl.h"
xhwang97de4202014-11-25 08:44:0140#include "media/blink/webcontentdecryptionmodule_impl.h"
acolwell9e0840d2014-09-06 19:01:3241#include "media/blink/webinbandtexttrack_impl.h"
42#include "media/blink/webmediaplayer_delegate.h"
43#include "media/blink/webmediaplayer_params.h"
44#include "media/blink/webmediaplayer_util.h"
45#include "media/blink/webmediasource_impl.h"
[email protected]37136d162012-04-09 23:39:1946#include "media/filters/audio_renderer_impl.h"
[email protected]efe7cd22012-09-12 23:55:0147#include "media/filters/chunk_demuxer.h"
[email protected]ddbc6ff2013-04-19 15:28:3348#include "media/filters/ffmpeg_audio_decoder.h"
49#include "media/filters/ffmpeg_demuxer.h"
50#include "media/filters/ffmpeg_video_decoder.h"
[email protected]1cad8802013-08-13 16:54:3251#include "media/filters/gpu_video_accelerator_factories.h"
[email protected]b9a407e2013-07-24 07:30:0252#include "media/filters/gpu_video_decoder.h"
[email protected]ddbc6ff2013-04-19 15:28:3353#include "media/filters/opus_audio_decoder.h"
xhwangbe9da702014-08-23 21:44:5554#include "media/filters/renderer_impl.h"
[email protected]cc3933d2013-11-26 03:41:0255#include "media/filters/video_renderer_impl.h"
[email protected]ddbc6ff2013-04-19 15:28:3356#include "media/filters/vpx_video_decoder.h"
[email protected]745746d2013-08-23 02:09:1657#include "third_party/WebKit/public/platform/WebMediaSource.h"
[email protected]c10884462013-05-30 00:22:0958#include "third_party/WebKit/public/platform/WebRect.h"
59#include "third_party/WebKit/public/platform/WebSize.h"
60#include "third_party/WebKit/public/platform/WebString.h"
61#include "third_party/WebKit/public/platform/WebURL.h"
[email protected]80504652014-04-18 04:41:5062#include "third_party/WebKit/public/web/WebLocalFrame.h"
xhwangbab66f52014-12-02 23:49:5063#include "third_party/WebKit/public/web/WebRuntimeFeatures.h"
[email protected]65b85282014-03-31 23:32:3164#include "third_party/WebKit/public/web/WebSecurityOrigin.h"
[email protected]2255a9332013-06-17 05:12:3165#include "third_party/WebKit/public/web/WebView.h"
[email protected]b3f2b912009-04-09 16:18:5266
[email protected]180ef242013-11-07 06:50:4667using blink::WebCanvas;
68using blink::WebMediaPlayer;
69using blink::WebRect;
70using blink::WebSize;
71using blink::WebString;
[email protected]ec9212f2008-12-18 21:40:3672
[email protected]8931c41a2009-07-07 17:31:4973namespace {
74
[email protected]378f0b72009-08-11 17:11:4275// Limits the range of playback rate.
76//
77// TODO(kylep): Revisit these.
78//
79// Vista has substantially lower performance than XP or Windows7. If you speed
80// up a video too much, it can't keep up, and rendering stops updating except on
81// the time bar. For really high speeds, audio becomes a bottleneck and we just
82// use up the data we have, which may not achieve the speed requested, but will
83// not crash the tab.
84//
85// A very slow speed, ie 0.00000001x, causes the machine to lock up. (It seems
86// like a busy loop). It gets unresponsive, although its not completely dead.
87//
88// Also our timers are not very accurate (especially for ogg), which becomes
89// evident at low speeds and on Vista. Since other speeds are risky and outside
90// the norms, we think 1/16x to 16x is a safe and useful range for now.
[email protected]39bdde32013-04-17 17:44:2091const double kMinRate = 0.0625;
92const double kMaxRate = 16.0;
[email protected]378f0b72009-08-11 17:11:4293
[email protected]47c345b2014-07-22 10:31:5794class SyncPointClientImpl : public media::VideoFrame::SyncPointClient {
95 public:
96 explicit SyncPointClientImpl(
97 blink::WebGraphicsContext3D* web_graphics_context)
98 : web_graphics_context_(web_graphics_context) {}
dchengc24565478f2014-10-21 12:23:2799 ~SyncPointClientImpl() override {}
100 uint32 InsertSyncPoint() override {
[email protected]47c345b2014-07-22 10:31:57101 return web_graphics_context_->insertSyncPoint();
102 }
dchengc24565478f2014-10-21 12:23:27103 void WaitSyncPoint(uint32 sync_point) override {
[email protected]47c345b2014-07-22 10:31:57104 web_graphics_context_->waitSyncPoint(sync_point);
105 }
106
107 private:
108 blink::WebGraphicsContext3D* web_graphics_context_;
109};
110
[email protected]8931c41a2009-07-07 17:31:49111} // namespace
112
acolwell9e0840d2014-09-06 19:01:32113namespace media {
[email protected]add51772009-06-11 18:25:17114
[email protected]6683e1b2014-04-10 01:45:38115class BufferedDataSourceHostImpl;
116
[email protected]a8884632012-06-29 03:05:34117#define COMPILE_ASSERT_MATCHING_ENUM(name) \
[email protected]2ca7d5c2012-10-23 07:30:54118 COMPILE_ASSERT(static_cast<int>(WebMediaPlayer::CORSMode ## name) == \
[email protected]a8884632012-06-29 03:05:34119 static_cast<int>(BufferedResourceLoader::k ## name), \
[email protected]a5a01102012-06-06 17:01:24120 mismatching_enums)
121COMPILE_ASSERT_MATCHING_ENUM(Unspecified);
122COMPILE_ASSERT_MATCHING_ENUM(Anonymous);
123COMPILE_ASSERT_MATCHING_ENUM(UseCredentials);
124#undef COMPILE_ASSERT_MATCHING_ENUM
125
[email protected]2c539b82012-08-18 04:10:19126#define BIND_TO_RENDER_LOOP(function) \
acolwellb4034942014-08-28 15:42:43127 (DCHECK(main_task_runner_->BelongsToCurrentThread()), \
acolwell9e0840d2014-09-06 19:01:32128 BindToCurrentLoop(base::Bind(function, AsWeakPtr())))
[email protected]5983adb2012-10-24 00:12:00129
[email protected]4e982192014-06-21 13:35:45130#define BIND_TO_RENDER_LOOP1(function, arg1) \
acolwellb4034942014-08-28 15:42:43131 (DCHECK(main_task_runner_->BelongsToCurrentThread()), \
acolwell9e0840d2014-09-06 19:01:32132 BindToCurrentLoop(base::Bind(function, AsWeakPtr(), arg1)))
[email protected]4e982192014-06-21 13:35:45133
acolwell9e0840d2014-09-06 19:01:32134static void LogMediaSourceError(const scoped_refptr<MediaLog>& media_log,
[email protected]2ef99602012-12-08 04:22:21135 const std::string& error) {
136 media_log->AddEvent(media_log->CreateMediaSourceErrorEvent(error));
137}
138
[email protected]5b5bb9d2010-10-22 19:57:36139WebMediaPlayerImpl::WebMediaPlayerImpl(
[email protected]35b2a972014-04-04 15:50:22140 blink::WebLocalFrame* frame,
[email protected]180ef242013-11-07 06:50:46141 blink::WebMediaPlayerClient* client,
[email protected]b8976652011-10-26 23:46:55142 base::WeakPtr<WebMediaPlayerDelegate> delegate,
xhwangf94a634d2014-10-22 22:07:27143 scoped_ptr<Renderer> renderer,
xhwang16ff1362014-11-19 00:16:34144 scoped_ptr<CdmFactory> cdm_factory,
[email protected]e82b2bd2013-01-02 17:47:57145 const WebMediaPlayerParams& params)
[email protected]f6af7592014-02-28 10:09:11146 : frame_(frame),
[email protected]ef405f66b2012-04-18 02:39:55147 network_state_(WebMediaPlayer::NetworkStateEmpty),
148 ready_state_(WebMediaPlayer::ReadyStateHaveNothing),
acolwella5081a42014-08-28 23:42:52149 preload_(BufferedDataSource::AUTO),
acolwellb4034942014-08-28 15:42:43150 main_task_runner_(base::MessageLoopProxy::current()),
acolwell755d12d2014-08-30 01:09:19151 media_task_runner_(params.media_task_runner()),
152 media_log_(params.media_log()),
acolwellb4034942014-08-28 15:42:43153 pipeline_(media_task_runner_, media_log_.get()),
[email protected]f988d9b2014-07-25 00:35:43154 load_type_(LoadTypeURL),
[email protected]75e145a2014-04-15 17:44:32155 opaque_(false),
[email protected]49480902009-07-14 20:23:43156 paused_(true),
[email protected]b3766a22010-12-22 17:34:13157 seeking_(false),
[email protected]49480902009-07-14 20:23:43158 playback_rate_(0.0f),
scherkusd2c745b2014-09-04 05:03:40159 ended_(false),
[email protected]5d11eff2011-09-15 00:06:06160 pending_seek_(false),
[email protected]b1a975e2011-12-21 00:12:39161 pending_seek_seconds_(0.0f),
[email protected]ba7d5f92014-06-24 05:37:40162 should_notify_time_changed_(false),
[email protected]5badb082010-06-11 17:40:15163 client_(client),
[email protected]baff4512011-10-19 18:21:07164 delegate_(delegate),
[email protected]d726eddc2013-07-02 22:25:55165 defer_load_cb_(params.defer_load_cb()),
acolwell755d12d2014-08-30 01:09:19166 gpu_factories_(params.gpu_factories()),
[email protected]132dd57c2012-08-10 23:24:34167 supports_save_(true),
[email protected]f5443ef72013-04-22 04:03:38168 chunk_demuxer_(NULL),
acolwell755d12d2014-08-30 01:09:19169 compositor_task_runner_(params.compositor_task_runner()),
[email protected]dd061e12014-05-06 19:21:22170 compositor_(new VideoFrameCompositor(
[email protected]75e145a2014-04-15 17:44:32171 BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnNaturalSizeChanged),
[email protected]dd061e12014-05-06 19:21:22172 BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnOpacityChanged))),
[email protected]7bce1832014-01-09 00:01:22173 text_track_index_(0),
xhwang97de4202014-11-25 08:44:01174 encrypted_media_support_(
175 cdm_factory.Pass(),
176 client,
177 base::Bind(&WebMediaPlayerImpl::SetCdm, AsWeakPtr())),
xhwangf94a634d2014-10-22 22:07:27178 audio_hardware_config_(params.audio_hardware_config()),
179 renderer_(renderer.Pass()) {
acolwell755d12d2014-08-30 01:09:19180 // Threaded compositing isn't enabled universally yet.
dchengd3c60602014-09-03 17:14:37181 if (!compositor_task_runner_.get())
acolwell755d12d2014-08-30 01:09:19182 compositor_task_runner_ = base::MessageLoopProxy::current();
183
[email protected]c93eb0a62011-08-09 22:47:24184 media_log_->AddEvent(
acolwell9e0840d2014-09-06 19:01:32185 media_log_->CreateEvent(MediaLogEvent::WEBMEDIAPLAYER_CREATED));
[email protected]4e6be3f2009-05-07 02:24:44186
xhwang0ad11e512014-11-25 23:43:09187 if (params.initial_cdm()) {
188 SetCdm(
189 ToWebContentDecryptionModuleImpl(params.initial_cdm())->GetCdmContext(),
190 base::Bind(&IgnoreCdmAttached));
191 }
192
xhwangf94a634d2014-10-22 22:07:27193 // TODO(xhwang): When we use an external Renderer, many methods won't work,
194 // e.g. GetCurrentFrameFromCompositor(). Fix this in a future CL.
195 if (renderer_)
196 return;
197
[email protected]c50edb962013-10-19 18:05:07198 // |gpu_factories_| requires that its entry points be called on its
[email protected]b639a832013-12-20 21:12:39199 // |GetTaskRunner()|. Since |pipeline_| will own decoders created from the
[email protected]c50edb962013-10-19 18:05:07200 // factories, require that their message loops are identical.
dchengf70d95e2014-08-27 02:06:28201 DCHECK(!gpu_factories_.get() ||
acolwellb4034942014-08-28 15:42:43202 (gpu_factories_->GetTaskRunner() == media_task_runner_.get()));
[email protected]c50edb962013-10-19 18:05:07203
[email protected]ddbc6ff2013-04-19 15:28:33204 // Use the null sink if no sink was provided.
[email protected]4a914882013-01-10 00:43:48205 audio_source_provider_ = new WebAudioSourceProviderImpl(
[email protected]ff875be52013-06-02 23:47:38206 params.audio_renderer_sink().get()
207 ? params.audio_renderer_sink()
acolwell9e0840d2014-09-06 19:01:32208 : new NullAudioSink(media_task_runner_));
[email protected]ec9212f2008-12-18 21:40:36209}
210
[email protected]4e6be3f2009-05-07 02:24:44211WebMediaPlayerImpl::~WebMediaPlayerImpl() {
[email protected]ce70c982013-12-20 17:04:32212 client_->setWebLayer(NULL);
[email protected]21c3f7502013-03-23 03:29:51213
acolwellb4034942014-08-28 15:42:43214 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]c93eb0a62011-08-09 22:47:24215 media_log_->AddEvent(
acolwell9e0840d2014-09-06 19:01:32216 media_log_->CreateEvent(MediaLogEvent::WEBMEDIAPLAYER_DESTROYED));
[email protected]d43ed912009-02-03 04:52:53217
dalecurtis6d269ed2014-09-11 21:18:13218 if (delegate_)
[email protected]baff4512011-10-19 18:21:07219 delegate_->PlayerGone(this);
220
[email protected]f6af7592014-02-28 10:09:11221 // Abort any pending IO so stopping the pipeline doesn't get blocked.
222 if (data_source_)
223 data_source_->Abort();
224 if (chunk_demuxer_) {
225 chunk_demuxer_->Shutdown();
226 chunk_demuxer_ = NULL;
227 }
228
229 gpu_factories_ = NULL;
230
231 // Make sure to kill the pipeline so there's no more media threads running.
232 // Note: stopping the pipeline might block for a long time.
233 base::WaitableEvent waiter(false, false);
234 pipeline_.Stop(
235 base::Bind(&base::WaitableEvent::Signal, base::Unretained(&waiter)));
236 waiter.Wait();
237
[email protected]dd061e12014-05-06 19:21:22238 compositor_task_runner_->DeleteSoon(FROM_HERE, compositor_);
[email protected]ec9212f2008-12-18 21:40:36239}
240
[email protected]180ef242013-11-07 06:50:46241void WebMediaPlayerImpl::load(LoadType load_type, const blink::WebURL& url,
[email protected]62e5e682013-03-07 23:53:24242 CORSMode cors_mode) {
[email protected]2a06ca62014-06-04 13:59:52243 DVLOG(1) << __FUNCTION__ << "(" << load_type << ", " << url << ", "
244 << cors_mode << ")";
[email protected]d726eddc2013-07-02 22:25:55245 if (!defer_load_cb_.is_null()) {
246 defer_load_cb_.Run(base::Bind(
[email protected]ef8394c2013-08-21 20:26:30247 &WebMediaPlayerImpl::DoLoad, AsWeakPtr(), load_type, url, cors_mode));
[email protected]d726eddc2013-07-02 22:25:55248 return;
249 }
[email protected]ef8394c2013-08-21 20:26:30250 DoLoad(load_type, url, cors_mode);
[email protected]62e5e682013-03-07 23:53:24251}
252
[email protected]ef8394c2013-08-21 20:26:30253void WebMediaPlayerImpl::DoLoad(LoadType load_type,
[email protected]180ef242013-11-07 06:50:46254 const blink::WebURL& url,
[email protected]d726eddc2013-07-02 22:25:55255 CORSMode cors_mode) {
acolwellb4034942014-08-28 15:42:43256 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]d726eddc2013-07-02 22:25:55257
[email protected]62e5e682013-03-07 23:53:24258 GURL gurl(url);
[email protected]e2f6bba2014-06-09 20:08:07259 ReportMediaSchemeUma(gurl);
[email protected]62e5e682013-03-07 23:53:24260
[email protected]926f8fd2013-04-12 20:27:53261 // Set subresource URL for crash reporting.
262 base::debug::SetCrashKeyValue("subresource_url", gurl.spec());
263
[email protected]ef8394c2013-08-21 20:26:30264 load_type_ = load_type;
265
[email protected]62e5e682013-03-07 23:53:24266 SetNetworkState(WebMediaPlayer::NetworkStateLoading);
267 SetReadyState(WebMediaPlayer::ReadyStateHaveNothing);
268 media_log_->AddEvent(media_log_->CreateLoadEvent(url.spec()));
[email protected]d726eddc2013-07-02 22:25:55269
270 // Media source pipelines can start immediately.
[email protected]ef8394c2013-08-21 20:26:30271 if (load_type == LoadTypeMediaSource) {
[email protected]d726eddc2013-07-02 22:25:55272 supports_save_ = false;
[email protected]ef8394c2013-08-21 20:26:30273 StartPipeline();
[email protected]d726eddc2013-07-02 22:25:55274 return;
275 }
276
277 // Otherwise it's a regular request which requires resolving the URL first.
278 data_source_.reset(new BufferedDataSource(
[email protected]fee8a902014-06-03 13:43:36279 url,
280 static_cast<BufferedResourceLoader::CORSMode>(cors_mode),
acolwellb4034942014-08-28 15:42:43281 main_task_runner_,
[email protected]d726eddc2013-07-02 22:25:55282 frame_,
283 media_log_.get(),
[email protected]6683e1b2014-04-10 01:45:38284 &buffered_data_source_host_,
[email protected]d726eddc2013-07-02 22:25:55285 base::Bind(&WebMediaPlayerImpl::NotifyDownloading, AsWeakPtr())));
286 data_source_->Initialize(
[email protected]fee8a902014-06-03 13:43:36287 base::Bind(&WebMediaPlayerImpl::DataSourceInitialized, AsWeakPtr()));
[email protected]09c60222014-08-07 16:42:31288 data_source_->SetPreload(preload_);
[email protected]62e5e682013-03-07 23:53:24289}
290
[email protected]4e6be3f2009-05-07 02:24:44291void WebMediaPlayerImpl::play() {
[email protected]2a06ca62014-06-04 13:59:52292 DVLOG(1) << __FUNCTION__;
acolwellb4034942014-08-28 15:42:43293 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]d43ed912009-02-03 04:52:53294
[email protected]49480902009-07-14 20:23:43295 paused_ = false;
[email protected]f6af7592014-02-28 10:09:11296 pipeline_.SetPlaybackRate(playback_rate_);
[email protected]039b7542013-10-17 22:06:25297 if (data_source_)
298 data_source_->MediaIsPlaying();
[email protected]090f7312011-08-05 23:26:40299
acolwell9e0840d2014-09-06 19:01:32300 media_log_->AddEvent(media_log_->CreateEvent(MediaLogEvent::PLAY));
[email protected]baff4512011-10-19 18:21:07301
dalecurtis6d269ed2014-09-11 21:18:13302 if (delegate_ && playback_rate_ > 0)
[email protected]baff4512011-10-19 18:21:07303 delegate_->DidPlay(this);
[email protected]ec9212f2008-12-18 21:40:36304}
305
[email protected]4e6be3f2009-05-07 02:24:44306void WebMediaPlayerImpl::pause() {
[email protected]2a06ca62014-06-04 13:59:52307 DVLOG(1) << __FUNCTION__;
acolwellb4034942014-08-28 15:42:43308 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]d43ed912009-02-03 04:52:53309
dalecurtis6d269ed2014-09-11 21:18:13310 const bool was_already_paused = paused_ || playback_rate_ == 0;
[email protected]49480902009-07-14 20:23:43311 paused_ = true;
[email protected]f6af7592014-02-28 10:09:11312 pipeline_.SetPlaybackRate(0.0f);
[email protected]039b7542013-10-17 22:06:25313 if (data_source_)
314 data_source_->MediaIsPaused();
[email protected]f6af7592014-02-28 10:09:11315 paused_time_ = pipeline_.GetMediaTime();
[email protected]090f7312011-08-05 23:26:40316
acolwell9e0840d2014-09-06 19:01:32317 media_log_->AddEvent(media_log_->CreateEvent(MediaLogEvent::PAUSE));
[email protected]baff4512011-10-19 18:21:07318
dalecurtis6d269ed2014-09-11 21:18:13319 if (!was_already_paused && delegate_)
[email protected]baff4512011-10-19 18:21:07320 delegate_->DidPause(this);
[email protected]ec9212f2008-12-18 21:40:36321}
322
[email protected]574a1d62009-07-17 03:23:46323bool WebMediaPlayerImpl::supportsSave() const {
acolwellb4034942014-08-28 15:42:43324 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]132dd57c2012-08-10 23:24:34325 return supports_save_;
[email protected]574a1d62009-07-17 03:23:46326}
327
[email protected]39bdde32013-04-17 17:44:20328void WebMediaPlayerImpl::seek(double seconds) {
xhwang12d8d042014-12-01 21:48:57329 DVLOG(1) << __FUNCTION__ << "(" << seconds << "s)";
acolwellb4034942014-08-28 15:42:43330 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]d43ed912009-02-03 04:52:53331
scherkusd2c745b2014-09-04 05:03:40332 ended_ = false;
333
[email protected]1bb666802013-11-28 06:12:08334 if (ready_state_ > WebMediaPlayer::ReadyStateHaveMetadata)
335 SetReadyState(WebMediaPlayer::ReadyStateHaveMetadata);
336
[email protected]bb8a70b2013-06-26 06:23:35337 base::TimeDelta seek_time = ConvertSecondsToTimestamp(seconds);
338
[email protected]d228aeec2014-06-20 19:16:49339 if (seeking_) {
[email protected]5d11eff2011-09-15 00:06:06340 pending_seek_ = true;
341 pending_seek_seconds_ = seconds;
[email protected]efe7cd22012-09-12 23:55:01342 if (chunk_demuxer_)
[email protected]bb8a70b2013-06-26 06:23:35343 chunk_demuxer_->CancelPendingSeek(seek_time);
[email protected]5d11eff2011-09-15 00:06:06344 return;
345 }
346
[email protected]c93eb0a62011-08-09 22:47:24347 media_log_->AddEvent(media_log_->CreateSeekEvent(seconds));
348
[email protected]44ff37c02009-10-24 01:03:03349 // Update our paused time.
Bartosz Fabianowski36c68322014-11-13 13:48:37350 if (paused_)
351 paused_time_ = seek_time;
[email protected]44ff37c02009-10-24 01:03:03352
[email protected]b3766a22010-12-22 17:34:13353 seeking_ = true;
354
[email protected]efe7cd22012-09-12 23:55:01355 if (chunk_demuxer_)
[email protected]bb8a70b2013-06-26 06:23:35356 chunk_demuxer_->StartWaitingForSeek(seek_time);
[email protected]020fba32011-06-29 16:37:46357
[email protected]44ff37c02009-10-24 01:03:03358 // Kick off the asynchronous seek!
[email protected]f6af7592014-02-28 10:09:11359 pipeline_.Seek(
[email protected]44ff37c02009-10-24 01:03:03360 seek_time,
[email protected]4e982192014-06-21 13:35:45361 BIND_TO_RENDER_LOOP1(&WebMediaPlayerImpl::OnPipelineSeeked, true));
[email protected]ec9212f2008-12-18 21:40:36362}
363
[email protected]39bdde32013-04-17 17:44:20364void WebMediaPlayerImpl::setRate(double rate) {
[email protected]2a06ca62014-06-04 13:59:52365 DVLOG(1) << __FUNCTION__ << "(" << rate << ")";
acolwellb4034942014-08-28 15:42:43366 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]d43ed912009-02-03 04:52:53367
[email protected]378f0b72009-08-11 17:11:42368 // TODO(kylep): Remove when support for negatives is added. Also, modify the
369 // following checks so rewind uses reasonable values also.
[email protected]39bdde32013-04-17 17:44:20370 if (rate < 0.0)
[email protected]378f0b72009-08-11 17:11:42371 return;
372
373 // Limit rates to reasonable values by clamping.
[email protected]39bdde32013-04-17 17:44:20374 if (rate != 0.0) {
[email protected]378f0b72009-08-11 17:11:42375 if (rate < kMinRate)
376 rate = kMinRate;
377 else if (rate > kMaxRate)
378 rate = kMaxRate;
dalecurtisbb761e12014-09-12 01:16:35379 if (playback_rate_ == 0 && !paused_ && delegate_)
dalecurtis6d269ed2014-09-11 21:18:13380 delegate_->DidPlay(this);
dalecurtisbb761e12014-09-12 01:16:35381 } else if (playback_rate_ != 0 && !paused_ && delegate_) {
dalecurtis6d269ed2014-09-11 21:18:13382 delegate_->DidPause(this);
[email protected]378f0b72009-08-11 17:11:42383 }
384
[email protected]49480902009-07-14 20:23:43385 playback_rate_ = rate;
386 if (!paused_) {
[email protected]f6af7592014-02-28 10:09:11387 pipeline_.SetPlaybackRate(rate);
[email protected]039b7542013-10-17 22:06:25388 if (data_source_)
389 data_source_->MediaPlaybackRateChanged(rate);
[email protected]49480902009-07-14 20:23:43390 }
[email protected]ec9212f2008-12-18 21:40:36391}
392
[email protected]39bdde32013-04-17 17:44:20393void WebMediaPlayerImpl::setVolume(double volume) {
[email protected]2a06ca62014-06-04 13:59:52394 DVLOG(1) << __FUNCTION__ << "(" << volume << ")";
acolwellb4034942014-08-28 15:42:43395 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]d43ed912009-02-03 04:52:53396
[email protected]f6af7592014-02-28 10:09:11397 pipeline_.SetVolume(volume);
[email protected]ec9212f2008-12-18 21:40:36398}
[email protected]f0a51fb52009-03-05 12:46:38399
[email protected]23a8b1d82011-04-05 16:28:20400#define COMPILE_ASSERT_MATCHING_ENUM(webkit_name, chromium_name) \
[email protected]ef405f66b2012-04-18 02:39:55401 COMPILE_ASSERT(static_cast<int>(WebMediaPlayer::webkit_name) == \
acolwella5081a42014-08-28 23:42:52402 static_cast<int>(BufferedDataSource::chromium_name), \
[email protected]474c37a2011-08-23 20:24:52403 mismatching_enums)
[email protected]ef405f66b2012-04-18 02:39:55404COMPILE_ASSERT_MATCHING_ENUM(PreloadNone, NONE);
405COMPILE_ASSERT_MATCHING_ENUM(PreloadMetaData, METADATA);
406COMPILE_ASSERT_MATCHING_ENUM(PreloadAuto, AUTO);
[email protected]a5a01102012-06-06 17:01:24407#undef COMPILE_ASSERT_MATCHING_ENUM
[email protected]23a8b1d82011-04-05 16:28:20408
[email protected]ef405f66b2012-04-18 02:39:55409void WebMediaPlayerImpl::setPreload(WebMediaPlayer::Preload preload) {
[email protected]2a06ca62014-06-04 13:59:52410 DVLOG(1) << __FUNCTION__ << "(" << preload << ")";
acolwellb4034942014-08-28 15:42:43411 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]4e6be3f2009-05-07 02:24:44412
acolwella5081a42014-08-28 23:42:52413 preload_ = static_cast<BufferedDataSource::Preload>(preload);
[email protected]b49beeb2013-03-01 20:04:00414 if (data_source_)
[email protected]09c60222014-08-07 16:42:31415 data_source_->SetPreload(preload_);
[email protected]4e6be3f2009-05-07 02:24:44416}
417
[email protected]4e6be3f2009-05-07 02:24:44418bool WebMediaPlayerImpl::hasVideo() const {
acolwellb4034942014-08-28 15:42:43419 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]d43ed912009-02-03 04:52:53420
[email protected]b8877772014-03-26 20:17:15421 return pipeline_metadata_.has_video;
[email protected]d43ed912009-02-03 04:52:53422}
423
[email protected]fc367af2009-08-14 23:06:35424bool WebMediaPlayerImpl::hasAudio() const {
acolwellb4034942014-08-28 15:42:43425 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]fc367af2009-08-14 23:06:35426
[email protected]b8877772014-03-26 20:17:15427 return pipeline_metadata_.has_audio;
[email protected]fc367af2009-08-14 23:06:35428}
429
[email protected]180ef242013-11-07 06:50:46430blink::WebSize WebMediaPlayerImpl::naturalSize() const {
acolwellb4034942014-08-28 15:42:43431 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]d43ed912009-02-03 04:52:53432
[email protected]b8877772014-03-26 20:17:15433 return blink::WebSize(pipeline_metadata_.natural_size);
[email protected]d43ed912009-02-03 04:52:53434}
435
[email protected]4e6be3f2009-05-07 02:24:44436bool WebMediaPlayerImpl::paused() const {
acolwellb4034942014-08-28 15:42:43437 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]d43ed912009-02-03 04:52:53438
[email protected]f6af7592014-02-28 10:09:11439 return pipeline_.GetPlaybackRate() == 0.0f;
[email protected]d43ed912009-02-03 04:52:53440}
441
[email protected]4e6be3f2009-05-07 02:24:44442bool WebMediaPlayerImpl::seeking() const {
acolwellb4034942014-08-28 15:42:43443 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]d43ed912009-02-03 04:52:53444
[email protected]ef405f66b2012-04-18 02:39:55445 if (ready_state_ == WebMediaPlayer::ReadyStateHaveNothing)
[email protected]0acebfa2009-08-21 22:45:40446 return false;
[email protected]67cd5052009-09-10 21:53:22447
[email protected]b3766a22010-12-22 17:34:13448 return seeking_;
[email protected]ec9212f2008-12-18 21:40:36449}
450
[email protected]39bdde32013-04-17 17:44:20451double WebMediaPlayerImpl::duration() const {
acolwellb4034942014-08-28 15:42:43452 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]39bdde32013-04-17 17:44:20453
454 if (ready_state_ == WebMediaPlayer::ReadyStateHaveNothing)
455 return std::numeric_limits<double>::quiet_NaN();
456
[email protected]39bdde32013-04-17 17:44:20457 return GetPipelineDuration();
[email protected]d43ed912009-02-03 04:52:53458}
459
[email protected]db66d0092014-04-16 07:15:12460double WebMediaPlayerImpl::timelineOffset() const {
acolwellb4034942014-08-28 15:42:43461 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]db66d0092014-04-16 07:15:12462
463 if (pipeline_metadata_.timeline_offset.is_null())
464 return std::numeric_limits<double>::quiet_NaN();
465
466 return pipeline_metadata_.timeline_offset.ToJsTime();
467}
468
[email protected]39bdde32013-04-17 17:44:20469double WebMediaPlayerImpl::currentTime() const {
acolwellb4034942014-08-28 15:42:43470 DCHECK(main_task_runner_->BelongsToCurrentThread());
scherkusd2c745b2014-09-04 05:03:40471 DCHECK_NE(ready_state_, WebMediaPlayer::ReadyStateHaveNothing);
472
473 // TODO(scherkus): Replace with an explicit ended signal to HTMLMediaElement,
474 // see http://crbug.com/409280
475 if (ended_)
476 return duration();
477
[email protected]f6af7592014-02-28 10:09:11478 return (paused_ ? paused_time_ : pipeline_.GetMediaTime()).InSecondsF();
[email protected]d43ed912009-02-03 04:52:53479}
480
[email protected]ef405f66b2012-04-18 02:39:55481WebMediaPlayer::NetworkState WebMediaPlayerImpl::networkState() const {
acolwellb4034942014-08-28 15:42:43482 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]ddb1e5a2010-12-13 20:10:45483 return network_state_;
484}
485
[email protected]ef405f66b2012-04-18 02:39:55486WebMediaPlayer::ReadyState WebMediaPlayerImpl::readyState() const {
acolwellb4034942014-08-28 15:42:43487 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]ddb1e5a2010-12-13 20:10:45488 return ready_state_;
489}
490
[email protected]02022fc2014-05-16 00:05:31491blink::WebTimeRanges WebMediaPlayerImpl::buffered() const {
acolwellb4034942014-08-28 15:42:43492 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]779a8322014-08-22 21:28:37493
acolwell9e0840d2014-09-06 19:01:32494 Ranges<base::TimeDelta> buffered_time_ranges =
[email protected]02022fc2014-05-16 00:05:31495 pipeline_.GetBufferedTimeRanges();
[email protected]779a8322014-08-22 21:28:37496
497 const base::TimeDelta duration = pipeline_.GetMediaDuration();
acolwell9e0840d2014-09-06 19:01:32498 if (duration != kInfiniteDuration()) {
[email protected]779a8322014-08-22 21:28:37499 buffered_data_source_host_.AddBufferedTimeRanges(
500 &buffered_time_ranges, duration);
501 }
[email protected]02022fc2014-05-16 00:05:31502 return ConvertToWebTimeRanges(buffered_time_ranges);
503}
504
philipjb0e6f3f2014-09-30 09:51:53505blink::WebTimeRanges WebMediaPlayerImpl::seekable() const {
acolwellb4034942014-08-28 15:42:43506 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]39bdde32013-04-17 17:44:20507
dalecurtis56359cb2014-10-28 00:06:29508 if (ready_state_ < WebMediaPlayer::ReadyStateHaveMetadata)
philipjb0e6f3f2014-09-30 09:51:53509 return blink::WebTimeRanges();
510
dalecurtis56359cb2014-10-28 00:06:29511 const double seekable_end = duration();
512
513 // Allow a special exception for seeks to zero for streaming sources with a
514 // finite duration; this allows looping to work.
515 const bool allow_seek_to_zero = data_source_ && data_source_->IsStreaming() &&
516 base::IsFinite(seekable_end);
517
518 // TODO(dalecurtis): Technically this allows seeking on media which return an
519 // infinite duration so long as DataSource::IsStreaming() is false. While not
520 // expected, disabling this breaks semi-live players, http://crbug.com/427412.
521 const blink::WebTimeRange seekable_range(
522 0.0, allow_seek_to_zero ? 0.0 : seekable_end);
philipjb0e6f3f2014-09-30 09:51:53523 return blink::WebTimeRanges(&seekable_range, 1);
[email protected]ec9212f2008-12-18 21:40:36524}
525
[email protected]5d2b3e4c2014-05-12 23:27:30526bool WebMediaPlayerImpl::didLoadingProgress() {
acolwellb4034942014-08-28 15:42:43527 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]6683e1b2014-04-10 01:45:38528 bool pipeline_progress = pipeline_.DidLoadingProgress();
529 bool data_progress = buffered_data_source_host_.DidLoadingProgress();
530 return pipeline_progress || data_progress;
[email protected]d43ed912009-02-03 04:52:53531}
532
[email protected]dd5c7972014-08-21 15:00:37533void WebMediaPlayerImpl::paint(blink::WebCanvas* canvas,
534 const blink::WebRect& rect,
[email protected]dd5c7972014-08-21 15:00:37535 unsigned char alpha,
536 SkXfermode::Mode mode) {
acolwellb4034942014-08-28 15:42:43537 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]dd061e12014-05-06 19:21:22538 TRACE_EVENT0("media", "WebMediaPlayerImpl:paint");
[email protected]4e6be3f2009-05-07 02:24:44539
[email protected]5e1502e2014-03-24 22:48:44540 // TODO(scherkus): Clarify paint() API contract to better understand when and
541 // why it's being called. For example, today paint() is called when:
542 // - We haven't reached HAVE_CURRENT_DATA and need to paint black
543 // - We're painting to a canvas
544 // See http://crbug.com/341225 http://crbug.com/342621 for details.
acolwell9e0840d2014-09-06 19:01:32545 scoped_refptr<VideoFrame> video_frame =
[email protected]dd061e12014-05-06 19:21:22546 GetCurrentFrameFromCompositor();
[email protected]0fe5d43b2014-01-24 23:32:45547
[email protected]b49beeb2013-03-01 20:04:00548 gfx::Rect gfx_rect(rect);
[email protected]f78c3e82014-08-08 01:24:47549
rileya54b8c1742014-09-16 02:20:42550 skcanvas_video_renderer_.Paint(video_frame,
[email protected]8bad1822014-08-09 05:52:38551 canvas,
552 gfx_rect,
553 alpha,
[email protected]dd5c7972014-08-21 15:00:37554 mode,
[email protected]8bad1822014-08-09 05:52:38555 pipeline_metadata_.video_rotation);
[email protected]ec9212f2008-12-18 21:40:36556}
[email protected]5df51652009-01-17 00:03:00557
[email protected]38259a7a82009-07-29 21:49:49558bool WebMediaPlayerImpl::hasSingleSecurityOrigin() const {
[email protected]b49beeb2013-03-01 20:04:00559 if (data_source_)
560 return data_source_->HasSingleOrigin();
[email protected]fcdb7462009-10-21 21:05:11561 return true;
[email protected]38259a7a82009-07-29 21:49:49562}
563
[email protected]3fe27112012-06-07 04:00:01564bool WebMediaPlayerImpl::didPassCORSAccessCheck() const {
[email protected]b49beeb2013-03-01 20:04:00565 if (data_source_)
566 return data_source_->DidPassCORSAccessCheck();
567 return false;
[email protected]3fe27112012-06-07 04:00:01568}
569
[email protected]39bdde32013-04-17 17:44:20570double WebMediaPlayerImpl::mediaTimeForTimeValue(double timeValue) const {
[email protected]e06e16d82011-05-26 22:13:33571 return ConvertSecondsToTimestamp(timeValue).InSecondsF();
572}
573
[email protected]d82b18ae2011-03-23 21:28:59574unsigned WebMediaPlayerImpl::decodedFrameCount() const {
acolwellb4034942014-08-28 15:42:43575 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]4c51bc662011-02-16 02:03:16576
acolwell9e0840d2014-09-06 19:01:32577 PipelineStatistics stats = pipeline_.GetStatistics();
[email protected]4c51bc662011-02-16 02:03:16578 return stats.video_frames_decoded;
579}
580
[email protected]d82b18ae2011-03-23 21:28:59581unsigned WebMediaPlayerImpl::droppedFrameCount() const {
acolwellb4034942014-08-28 15:42:43582 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]4c51bc662011-02-16 02:03:16583
acolwell9e0840d2014-09-06 19:01:32584 PipelineStatistics stats = pipeline_.GetStatistics();
[email protected]dd061e12014-05-06 19:21:22585 return stats.video_frames_dropped;
[email protected]4c51bc662011-02-16 02:03:16586}
587
[email protected]d82b18ae2011-03-23 21:28:59588unsigned WebMediaPlayerImpl::audioDecodedByteCount() const {
acolwellb4034942014-08-28 15:42:43589 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]4c51bc662011-02-16 02:03:16590
acolwell9e0840d2014-09-06 19:01:32591 PipelineStatistics stats = pipeline_.GetStatistics();
[email protected]4c51bc662011-02-16 02:03:16592 return stats.audio_bytes_decoded;
593}
594
[email protected]d82b18ae2011-03-23 21:28:59595unsigned WebMediaPlayerImpl::videoDecodedByteCount() const {
acolwellb4034942014-08-28 15:42:43596 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]4c51bc662011-02-16 02:03:16597
acolwell9e0840d2014-09-06 19:01:32598 PipelineStatistics stats = pipeline_.GetStatistics();
[email protected]4c51bc662011-02-16 02:03:16599 return stats.video_bytes_decoded;
600}
601
[email protected]6523b242013-03-13 11:10:07602bool WebMediaPlayerImpl::copyVideoTextureToPlatformTexture(
[email protected]180ef242013-11-07 06:50:46603 blink::WebGraphicsContext3D* web_graphics_context,
[email protected]6523b242013-03-13 11:10:07604 unsigned int texture,
605 unsigned int level,
606 unsigned int internal_format,
[email protected]9aa2b2782013-05-14 00:13:31607 unsigned int type,
[email protected]6523b242013-03-13 11:10:07608 bool premultiply_alpha,
609 bool flip_y) {
[email protected]bfc05f22013-10-19 17:55:16610 TRACE_EVENT0("media", "WebMediaPlayerImpl:copyVideoTextureToPlatformTexture");
611
acolwell9e0840d2014-09-06 19:01:32612 scoped_refptr<VideoFrame> video_frame =
[email protected]dd061e12014-05-06 19:21:22613 GetCurrentFrameFromCompositor();
614
dchengf70d95e2014-08-27 02:06:28615 if (!video_frame.get())
[email protected]e56f88c72013-06-25 22:31:29616 return false;
acolwell9e0840d2014-09-06 19:01:32617 if (video_frame->format() != VideoFrame::NATIVE_TEXTURE)
[email protected]e56f88c72013-06-25 22:31:29618 return false;
[email protected]df41e252014-02-03 23:39:50619
[email protected]c37a4cc2014-04-30 19:15:28620 const gpu::MailboxHolder* mailbox_holder = video_frame->mailbox_holder();
[email protected]df41e252014-02-03 23:39:50621 if (mailbox_holder->texture_target != GL_TEXTURE_2D)
[email protected]e56f88c72013-06-25 22:31:29622 return false;
623
[email protected]df41e252014-02-03 23:39:50624 web_graphics_context->waitSyncPoint(mailbox_holder->sync_point);
[email protected]c77f2722014-07-22 09:04:32625 uint32 source_texture = web_graphics_context->createAndConsumeTextureCHROMIUM(
626 GL_TEXTURE_2D, mailbox_holder->mailbox.name);
[email protected]e56f88c72013-06-25 22:31:29627
628 // The video is stored in a unmultiplied format, so premultiply
629 // if necessary.
630 web_graphics_context->pixelStorei(GL_UNPACK_PREMULTIPLY_ALPHA_CHROMIUM,
631 premultiply_alpha);
632 // Application itself needs to take care of setting the right flip_y
633 // value down to get the expected result.
634 // flip_y==true means to reverse the video orientation while
635 // flip_y==false means to keep the intrinsic orientation.
636 web_graphics_context->pixelStorei(GL_UNPACK_FLIP_Y_CHROMIUM, flip_y);
637 web_graphics_context->copyTextureCHROMIUM(GL_TEXTURE_2D,
638 source_texture,
639 texture,
640 level,
641 internal_format,
642 type);
643 web_graphics_context->pixelStorei(GL_UNPACK_FLIP_Y_CHROMIUM, false);
644 web_graphics_context->pixelStorei(GL_UNPACK_PREMULTIPLY_ALPHA_CHROMIUM,
645 false);
646
647 web_graphics_context->deleteTexture(source_texture);
[email protected]e56f88c72013-06-25 22:31:29648 web_graphics_context->flush();
[email protected]47c345b2014-07-22 10:31:57649
650 SyncPointClientImpl client(web_graphics_context);
651 video_frame->UpdateReleaseSyncPoint(&client);
[email protected]e56f88c72013-06-25 22:31:29652 return true;
[email protected]6523b242013-03-13 11:10:07653}
654
[email protected]2ca7d5c2012-10-23 07:30:54655WebMediaPlayer::MediaKeyException
[email protected]f7a6b992012-04-19 09:45:56656WebMediaPlayerImpl::generateKeyRequest(const WebString& key_system,
657 const unsigned char* init_data,
658 unsigned init_data_length) {
acolwellb4034942014-08-28 15:42:43659 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]7502ef12014-01-25 01:19:27660
xhwang16ff1362014-11-19 00:16:34661 return encrypted_media_support_.GenerateKeyRequest(
acolwelle2ea5182014-08-25 23:01:07662 frame_, key_system, init_data, init_data_length);
[email protected]f7a6b992012-04-19 09:45:56663}
664
[email protected]2ca7d5c2012-10-23 07:30:54665WebMediaPlayer::MediaKeyException WebMediaPlayerImpl::addKey(
666 const WebString& key_system,
667 const unsigned char* key,
668 unsigned key_length,
669 const unsigned char* init_data,
670 unsigned init_data_length,
671 const WebString& session_id) {
acolwellb4034942014-08-28 15:42:43672 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]f7a6b992012-04-19 09:45:56673
xhwang16ff1362014-11-19 00:16:34674 return encrypted_media_support_.AddKey(
acolwelle2ea5182014-08-25 23:01:07675 key_system, key, key_length, init_data, init_data_length, session_id);
[email protected]f7a6b992012-04-19 09:45:56676}
677
[email protected]2ca7d5c2012-10-23 07:30:54678WebMediaPlayer::MediaKeyException WebMediaPlayerImpl::cancelKeyRequest(
679 const WebString& key_system,
680 const WebString& session_id) {
acolwellb4034942014-08-28 15:42:43681 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]0b9999d2014-02-20 02:16:11682
xhwang16ff1362014-11-19 00:16:34683 return encrypted_media_support_.CancelKeyRequest(key_system, session_id);
[email protected]f7a6b992012-04-19 09:45:56684}
685
[email protected]7bce1832014-01-09 00:01:22686void WebMediaPlayerImpl::setContentDecryptionModule(
[email protected]9ebc3b03f2014-08-13 04:01:23687 blink::WebContentDecryptionModule* cdm,
688 blink::WebContentDecryptionModuleResult result) {
acolwellb4034942014-08-28 15:42:43689 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]9ebc3b03f2014-08-13 04:01:23690
xhwang97de4202014-11-25 08:44:01691 // TODO(xhwang): Support setMediaKeys(0) if necessary: http://crbug.com/330324
692 if (!cdm) {
693 result.completeWithError(
694 blink::WebContentDecryptionModuleExceptionNotSupportedError, 0,
695 "Null MediaKeys object is not supported.");
696 return;
697 }
698
699 SetCdm(ToWebContentDecryptionModuleImpl(cdm)->GetCdmContext(),
700 BIND_TO_RENDER_LOOP1(&WebMediaPlayerImpl::OnCdmAttached, result));
701}
702
xhwange8c4181a2014-12-06 08:10:01703void WebMediaPlayerImpl::OnEncryptedMediaInitData(
704 const std::string& init_data_type,
705 const std::vector<uint8>& init_data) {
xhwangbab66f52014-12-02 23:49:50706 DCHECK(!init_data_type.empty());
707
xhwange8c4181a2014-12-06 08:10:01708 // Do not fire "encrypted" event if encrypted media is not enabled.
xhwangbab66f52014-12-02 23:49:50709 // TODO(xhwang): Handle this in |client_|.
710 if (!blink::WebRuntimeFeatures::isPrefixedEncryptedMediaEnabled() &&
711 !blink::WebRuntimeFeatures::isEncryptedMediaEnabled()) {
712 return;
713 }
714
xhwange8c4181a2014-12-06 08:10:01715 // TODO(xhwang): Update this UMA name.
xhwangbab66f52014-12-02 23:49:50716 UMA_HISTOGRAM_COUNTS("Media.EME.NeedKey", 1);
717
718 encrypted_media_support_.SetInitDataType(init_data_type);
719
720 const uint8* init_data_ptr = init_data.empty() ? nullptr : &init_data[0];
721 client_->encrypted(WebString::fromUTF8(init_data_type), init_data_ptr,
722 base::saturated_cast<unsigned int>(init_data.size()));
723}
724
xhwang97de4202014-11-25 08:44:01725void WebMediaPlayerImpl::SetCdm(CdmContext* cdm_context,
726 const CdmAttachedCB& cdm_attached_cb) {
727 pipeline_.SetCdm(cdm_context, cdm_attached_cb);
728}
729
730void WebMediaPlayerImpl::OnCdmAttached(
731 blink::WebContentDecryptionModuleResult result,
732 bool success) {
733 if (success) {
734 result.complete();
735 return;
736 }
737
738 result.completeWithError(
739 blink::WebContentDecryptionModuleExceptionNotSupportedError, 0,
740 "Unable to set MediaKeys object");
[email protected]9ebc3b03f2014-08-13 04:01:23741}
742
[email protected]4e982192014-06-21 13:35:45743void WebMediaPlayerImpl::OnPipelineSeeked(bool time_changed,
744 PipelineStatus status) {
745 DVLOG(1) << __FUNCTION__ << "(" << time_changed << ", " << status << ")";
acolwellb4034942014-08-28 15:42:43746 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]5d11eff2011-09-15 00:06:06747 seeking_ = false;
748 if (pending_seek_) {
749 pending_seek_ = false;
750 seek(pending_seek_seconds_);
751 return;
752 }
753
acolwell9e0840d2014-09-06 19:01:32754 if (status != PIPELINE_OK) {
[email protected]10a64d92012-04-10 21:08:02755 OnPipelineError(status);
756 return;
[email protected]96706912009-07-15 17:18:05757 }
[email protected]10a64d92012-04-10 21:08:02758
759 // Update our paused time.
760 if (paused_)
[email protected]f6af7592014-02-28 10:09:11761 paused_time_ = pipeline_.GetMediaTime();
[email protected]10a64d92012-04-10 21:08:02762
[email protected]ba7d5f92014-06-24 05:37:40763 should_notify_time_changed_ = time_changed;
[email protected]8931c41a2009-07-07 17:31:49764}
765
[email protected]6954fe12013-01-03 03:22:32766void WebMediaPlayerImpl::OnPipelineEnded() {
[email protected]2a06ca62014-06-04 13:59:52767 DVLOG(1) << __FUNCTION__;
acolwellb4034942014-08-28 15:42:43768 DCHECK(main_task_runner_->BelongsToCurrentThread());
scherkusd2c745b2014-09-04 05:03:40769
770 // Ignore state changes until we've completed all outstanding seeks.
771 if (seeking_ || pending_seek_)
772 return;
773
774 ended_ = true;
[email protected]ce70c982013-12-20 17:04:32775 client_->timeChanged();
[email protected]576537842009-08-12 23:52:05776}
777
[email protected]a9590c22011-03-16 16:57:02778void WebMediaPlayerImpl::OnPipelineError(PipelineStatus error) {
acolwellb4034942014-08-28 15:42:43779 DCHECK(main_task_runner_->BelongsToCurrentThread());
acolwell9e0840d2014-09-06 19:01:32780 DCHECK_NE(error, PIPELINE_OK);
[email protected]a8e2cb82012-08-17 00:02:39781
782 if (ready_state_ == WebMediaPlayer::ReadyStateHaveNothing) {
783 // Any error that occurs before reaching ReadyStateHaveMetadata should
784 // be considered a format error.
785 SetNetworkState(WebMediaPlayer::NetworkStateFormatError);
[email protected]a8e2cb82012-08-17 00:02:39786 return;
787 }
788
[email protected]be57ee52013-05-28 22:27:27789 SetNetworkState(PipelineErrorToNetworkState(error));
[email protected]a9590c22011-03-16 16:57:02790
acolwell9e0840d2014-09-06 19:01:32791 if (error == PIPELINE_ERROR_DECRYPT)
xhwang16ff1362014-11-19 00:16:34792 encrypted_media_support_.OnPipelineDecryptError();
[email protected]db190487d2009-07-30 18:51:52793}
794
[email protected]b8877772014-03-26 20:17:15795void WebMediaPlayerImpl::OnPipelineMetadata(
acolwell9e0840d2014-09-06 19:01:32796 PipelineMetadata metadata) {
[email protected]2a06ca62014-06-04 13:59:52797 DVLOG(1) << __FUNCTION__;
[email protected]a8e2cb82012-08-17 00:02:39798
[email protected]b8877772014-03-26 20:17:15799 pipeline_metadata_ = metadata;
[email protected]739847c02014-01-16 00:12:25800
[email protected]eddfef92014-07-18 01:26:47801 UMA_HISTOGRAM_ENUMERATION("Media.VideoRotation",
802 metadata.video_rotation,
acolwell9e0840d2014-09-06 19:01:32803 VIDEO_ROTATION_MAX + 1);
[email protected]b8877772014-03-26 20:17:15804 SetReadyState(WebMediaPlayer::ReadyStateHaveMetadata);
[email protected]21c3f7502013-03-23 03:29:51805
[email protected]b8877772014-03-26 20:17:15806 if (hasVideo()) {
807 DCHECK(!video_weblayer_);
[email protected]f78c3e82014-08-08 01:24:47808 scoped_refptr<cc::VideoLayer> layer =
809 cc::VideoLayer::Create(compositor_, pipeline_metadata_.video_rotation);
810
acolwell9e0840d2014-09-06 19:01:32811 if (pipeline_metadata_.video_rotation == VIDEO_ROTATION_90 ||
812 pipeline_metadata_.video_rotation == VIDEO_ROTATION_270) {
[email protected]f78c3e82014-08-08 01:24:47813 gfx::Size size = pipeline_metadata_.natural_size;
814 pipeline_metadata_.natural_size = gfx::Size(size.height(), size.width());
815 }
816
[email protected]38564622014-08-19 02:47:18817 video_weblayer_.reset(new cc_blink::WebLayerImpl(layer));
[email protected]75e145a2014-04-15 17:44:32818 video_weblayer_->setOpaque(opaque_);
[email protected]a7c4f582014-04-16 18:44:49819 client_->setWebLayer(video_weblayer_.get());
[email protected]a8e2cb82012-08-17 00:02:39820 }
[email protected]a8e2cb82012-08-17 00:02:39821}
822
[email protected]ba7d5f92014-06-24 05:37:40823void WebMediaPlayerImpl::OnPipelineBufferingStateChanged(
acolwell9e0840d2014-09-06 19:01:32824 BufferingState buffering_state) {
[email protected]ba7d5f92014-06-24 05:37:40825 DVLOG(1) << __FUNCTION__ << "(" << buffering_state << ")";
[email protected]b8877772014-03-26 20:17:15826
[email protected]ba7d5f92014-06-24 05:37:40827 // Ignore buffering state changes until we've completed all outstanding seeks.
828 if (seeking_ || pending_seek_)
829 return;
[email protected]b8877772014-03-26 20:17:15830
[email protected]ba7d5f92014-06-24 05:37:40831 // TODO(scherkus): Handle other buffering states when Pipeline starts using
832 // them and translate them ready state changes http://crbug.com/144683
acolwell9e0840d2014-09-06 19:01:32833 DCHECK_EQ(buffering_state, BUFFERING_HAVE_ENOUGH);
[email protected]ba7d5f92014-06-24 05:37:40834 SetReadyState(WebMediaPlayer::ReadyStateHaveEnoughData);
835
836 // Blink expects a timeChanged() in response to a seek().
837 if (should_notify_time_changed_)
838 client_->timeChanged();
[email protected]b8877772014-03-26 20:17:15839}
840
[email protected]ef8394c2013-08-21 20:26:30841void WebMediaPlayerImpl::OnDemuxerOpened() {
acolwellb4034942014-08-28 15:42:43842 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]ce70c982013-12-20 17:04:32843 client_->mediaSourceOpened(new WebMediaSourceImpl(
[email protected]5f811a2d2013-03-15 23:54:51844 chunk_demuxer_, base::Bind(&LogMediaSourceError, media_log_)));
[email protected]81bb3322011-07-21 15:55:50845}
846
[email protected]8a561062013-11-22 01:19:31847void WebMediaPlayerImpl::OnAddTextTrack(
acolwell9e0840d2014-09-06 19:01:32848 const TextTrackConfig& config,
849 const AddTextTrackDoneCB& done_cb) {
acolwellb4034942014-08-28 15:42:43850 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]71537722013-05-23 06:47:53851
[email protected]8a561062013-11-22 01:19:31852 const WebInbandTextTrackImpl::Kind web_kind =
853 static_cast<WebInbandTextTrackImpl::Kind>(config.kind());
854 const blink::WebString web_label =
855 blink::WebString::fromUTF8(config.label());
856 const blink::WebString web_language =
857 blink::WebString::fromUTF8(config.language());
[email protected]427ff102013-11-26 23:45:40858 const blink::WebString web_id =
859 blink::WebString::fromUTF8(config.id());
[email protected]71537722013-05-23 06:47:53860
[email protected]8a561062013-11-22 01:19:31861 scoped_ptr<WebInbandTextTrackImpl> web_inband_text_track(
[email protected]427ff102013-11-26 23:45:40862 new WebInbandTextTrackImpl(web_kind, web_label, web_language, web_id,
[email protected]8a561062013-11-22 01:19:31863 text_track_index_++));
864
acolwell9e0840d2014-09-06 19:01:32865 scoped_ptr<TextTrack> text_track(new TextTrackImpl(
acolwellb4034942014-08-28 15:42:43866 main_task_runner_, client_, web_inband_text_track.Pass()));
[email protected]8a561062013-11-22 01:19:31867
868 done_cb.Run(text_track.Pass());
[email protected]71537722013-05-23 06:47:53869}
870
[email protected]fee8a902014-06-03 13:43:36871void WebMediaPlayerImpl::DataSourceInitialized(bool success) {
acolwellb4034942014-08-28 15:42:43872 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]a9415292012-01-19 19:55:20873
[email protected]d250190da3b2012-07-23 22:57:30874 if (!success) {
[email protected]ef405f66b2012-04-18 02:39:55875 SetNetworkState(WebMediaPlayer::NetworkStateFormatError);
[email protected]a9415292012-01-19 19:55:20876 return;
877 }
878
[email protected]ef8394c2013-08-21 20:26:30879 StartPipeline();
[email protected]a9415292012-01-19 19:55:20880}
881
[email protected]122f40252012-06-12 05:01:56882void WebMediaPlayerImpl::NotifyDownloading(bool is_downloading) {
883 if (!is_downloading && network_state_ == WebMediaPlayer::NetworkStateLoading)
884 SetNetworkState(WebMediaPlayer::NetworkStateIdle);
885 else if (is_downloading && network_state_ == WebMediaPlayer::NetworkStateIdle)
886 SetNetworkState(WebMediaPlayer::NetworkStateLoading);
887 media_log_->AddEvent(
888 media_log_->CreateBooleanEvent(
acolwell9e0840d2014-09-06 19:01:32889 MediaLogEvent::NETWORK_ACTIVITY_SET,
[email protected]122f40252012-06-12 05:01:56890 "is_downloading_data", is_downloading));
891}
892
xhwangbe9da702014-08-23 21:44:55893// TODO(xhwang): Move this to a factory class so that we can create different
894// renderers.
acolwell9e0840d2014-09-06 19:01:32895scoped_ptr<Renderer> WebMediaPlayerImpl::CreateRenderer() {
xhwangbe9da702014-08-23 21:44:55896 // Create our audio decoders and renderer.
acolwell9e0840d2014-09-06 19:01:32897 ScopedVector<AudioDecoder> audio_decoders;
xhwangbe9da702014-08-23 21:44:55898
xhwang16ff1362014-11-19 00:16:34899 audio_decoders.push_back(new FFmpegAudioDecoder(
xhwangff459d4e2014-09-09 04:55:47900 media_task_runner_, base::Bind(&LogMediaSourceError, media_log_)));
xhwang16ff1362014-11-19 00:16:34901 audio_decoders.push_back(new OpusAudioDecoder(media_task_runner_));
xhwangbe9da702014-08-23 21:44:55902
xhwang97de4202014-11-25 08:44:01903 scoped_ptr<AudioRenderer> audio_renderer(new AudioRendererImpl(
904 media_task_runner_, audio_source_provider_.get(), audio_decoders.Pass(),
905 audio_hardware_config_, media_log_));
xhwangbe9da702014-08-23 21:44:55906
907 // Create our video decoders and renderer.
acolwell9e0840d2014-09-06 19:01:32908 ScopedVector<VideoDecoder> video_decoders;
xhwangbe9da702014-08-23 21:44:55909
xhwangff459d4e2014-09-09 04:55:47910 if (gpu_factories_.get())
911 video_decoders.push_back(new GpuVideoDecoder(gpu_factories_));
xhwangbe9da702014-08-23 21:44:55912
913#if !defined(MEDIA_DISABLE_LIBVPX)
acolwell9e0840d2014-09-06 19:01:32914 video_decoders.push_back(new VpxVideoDecoder(media_task_runner_));
xhwangbe9da702014-08-23 21:44:55915#endif // !defined(MEDIA_DISABLE_LIBVPX)
916
acolwell9e0840d2014-09-06 19:01:32917 video_decoders.push_back(new FFmpegVideoDecoder(media_task_runner_));
xhwangbe9da702014-08-23 21:44:55918
xhwangff459d4e2014-09-09 04:55:47919 scoped_ptr<VideoRenderer> video_renderer(new VideoRendererImpl(
xhwang97de4202014-11-25 08:44:01920 media_task_runner_, video_decoders.Pass(), true, media_log_));
xhwangbe9da702014-08-23 21:44:55921
922 // Create renderer.
acolwell9e0840d2014-09-06 19:01:32923 return scoped_ptr<Renderer>(new RendererImpl(
xhwangabd95fd2014-10-03 07:10:01924 media_task_runner_, audio_renderer.Pass(), video_renderer.Pass()));
xhwangbe9da702014-08-23 21:44:55925}
926
[email protected]ef8394c2013-08-21 20:26:30927void WebMediaPlayerImpl::StartPipeline() {
acolwellb4034942014-08-28 15:42:43928 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]ddbc6ff2013-04-19 15:28:33929
[email protected]0814ac62013-06-07 21:01:29930 // Keep track if this is a MSE or non-MSE playback.
[email protected]ef8394c2013-08-21 20:26:30931 UMA_HISTOGRAM_BOOLEAN("Media.MSE.Playback",
932 (load_type_ == LoadTypeMediaSource));
[email protected]0814ac62013-06-07 21:01:29933
acolwell9e0840d2014-09-06 19:01:32934 LogCB mse_log_cb;
xhwange8c4181a2014-12-06 08:10:01935 Demuxer::EncryptedMediaInitDataCB encrypted_media_init_data_cb =
936 BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnEncryptedMediaInitData);
[email protected]2b57e2e2014-05-09 11:07:25937
[email protected]ddbc6ff2013-04-19 15:28:33938 // Figure out which demuxer to use.
[email protected]ef8394c2013-08-21 20:26:30939 if (load_type_ != LoadTypeMediaSource) {
[email protected]ddbc6ff2013-04-19 15:28:33940 DCHECK(!chunk_demuxer_);
[email protected]f5443ef72013-04-22 04:03:38941 DCHECK(data_source_);
942
xhwange8c4181a2014-12-06 08:10:01943 demuxer_.reset(new FFmpegDemuxer(media_task_runner_, data_source_.get(),
944 encrypted_media_init_data_cb, media_log_));
[email protected]ddbc6ff2013-04-19 15:28:33945 } else {
[email protected]f5443ef72013-04-22 04:03:38946 DCHECK(!chunk_demuxer_);
947 DCHECK(!data_source_);
948
[email protected]2b57e2e2014-05-09 11:07:25949 mse_log_cb = base::Bind(&LogMediaSourceError, media_log_);
950
acolwell9e0840d2014-09-06 19:01:32951 chunk_demuxer_ = new ChunkDemuxer(
[email protected]ef8394c2013-08-21 20:26:30952 BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnDemuxerOpened),
xhwange8c4181a2014-12-06 08:10:01953 encrypted_media_init_data_cb, mse_log_cb, media_log_, true);
[email protected]f5443ef72013-04-22 04:03:38954 demuxer_.reset(chunk_demuxer_);
[email protected]ddbc6ff2013-04-19 15:28:33955 }
956
[email protected]f5443ef72013-04-22 04:03:38957 // ... and we're ready to go!
[email protected]d228aeec2014-06-20 19:16:49958 seeking_ = true;
xhwangf94a634d2014-10-22 22:07:27959
960 if (!renderer_)
961 renderer_ = CreateRenderer();
962
[email protected]f6af7592014-02-28 10:09:11963 pipeline_.Start(
xhwang59805902014-08-29 01:44:15964 demuxer_.get(),
xhwangf94a634d2014-10-22 22:07:27965 renderer_.Pass(),
[email protected]f5443ef72013-04-22 04:03:38966 BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnPipelineEnded),
967 BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnPipelineError),
[email protected]4e982192014-06-21 13:35:45968 BIND_TO_RENDER_LOOP1(&WebMediaPlayerImpl::OnPipelineSeeked, false),
[email protected]b8877772014-03-26 20:17:15969 BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnPipelineMetadata),
[email protected]ba7d5f92014-06-24 05:37:40970 BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnPipelineBufferingStateChanged),
xhwang94c0bd32014-11-13 20:49:31971 base::Bind(&WebMediaPlayerImpl::FrameReady, base::Unretained(this)),
xhwang59805902014-08-29 01:44:15972 BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnDurationChanged),
973 BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnAddTextTrack));
[email protected]f5443ef72013-04-22 04:03:38974}
975
976void WebMediaPlayerImpl::SetNetworkState(WebMediaPlayer::NetworkState state) {
[email protected]2a06ca62014-06-04 13:59:52977 DVLOG(1) << __FUNCTION__ << "(" << state << ")";
acolwellb4034942014-08-28 15:42:43978 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]f5443ef72013-04-22 04:03:38979 network_state_ = state;
980 // Always notify to ensure client has the latest value.
[email protected]ce70c982013-12-20 17:04:32981 client_->networkStateChanged();
[email protected]f5443ef72013-04-22 04:03:38982}
983
984void WebMediaPlayerImpl::SetReadyState(WebMediaPlayer::ReadyState state) {
[email protected]2a06ca62014-06-04 13:59:52985 DVLOG(1) << __FUNCTION__ << "(" << state << ")";
acolwellb4034942014-08-28 15:42:43986 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]f5443ef72013-04-22 04:03:38987
[email protected]fee8a902014-06-03 13:43:36988 if (state == WebMediaPlayer::ReadyStateHaveEnoughData && data_source_ &&
989 data_source_->assume_fully_buffered() &&
[email protected]f5443ef72013-04-22 04:03:38990 network_state_ == WebMediaPlayer::NetworkStateLoading)
991 SetNetworkState(WebMediaPlayer::NetworkStateLoaded);
992
993 ready_state_ = state;
994 // Always notify to ensure client has the latest value.
[email protected]ce70c982013-12-20 17:04:32995 client_->readyStateChanged();
[email protected]f5443ef72013-04-22 04:03:38996}
997
[email protected]180ef242013-11-07 06:50:46998blink::WebAudioSourceProvider* WebMediaPlayerImpl::audioSourceProvider() {
[email protected]ff875be52013-06-02 23:47:38999 return audio_source_provider_.get();
[email protected]f5443ef72013-04-22 04:03:381000}
1001
[email protected]f5443ef72013-04-22 04:03:381002double WebMediaPlayerImpl::GetPipelineDuration() const {
[email protected]f6af7592014-02-28 10:09:111003 base::TimeDelta duration = pipeline_.GetMediaDuration();
[email protected]f5443ef72013-04-22 04:03:381004
1005 // Return positive infinity if the resource is unbounded.
1006 // http://www.whatwg.org/specs/web-apps/current-work/multipage/video.html#dom-media-duration
acolwell9e0840d2014-09-06 19:01:321007 if (duration == kInfiniteDuration())
[email protected]f5443ef72013-04-22 04:03:381008 return std::numeric_limits<double>::infinity();
1009
1010 return duration.InSecondsF();
1011}
1012
[email protected]75e145a2014-04-15 17:44:321013void WebMediaPlayerImpl::OnDurationChanged() {
[email protected]f5443ef72013-04-22 04:03:381014 if (ready_state_ == WebMediaPlayer::ReadyStateHaveNothing)
1015 return;
1016
[email protected]ce70c982013-12-20 17:04:321017 client_->durationChanged();
[email protected]f5443ef72013-04-22 04:03:381018}
1019
[email protected]75e145a2014-04-15 17:44:321020void WebMediaPlayerImpl::OnNaturalSizeChanged(gfx::Size size) {
acolwellb4034942014-08-28 15:42:431021 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]739847c02014-01-16 00:12:251022 DCHECK_NE(ready_state_, WebMediaPlayer::ReadyStateHaveNothing);
1023 TRACE_EVENT0("media", "WebMediaPlayerImpl::OnNaturalSizeChanged");
1024
1025 media_log_->AddEvent(
1026 media_log_->CreateVideoSizeSetEvent(size.width(), size.height()));
[email protected]b8877772014-03-26 20:17:151027 pipeline_metadata_.natural_size = size;
[email protected]739847c02014-01-16 00:12:251028
1029 client_->sizeChanged();
1030}
1031
[email protected]75e145a2014-04-15 17:44:321032void WebMediaPlayerImpl::OnOpacityChanged(bool opaque) {
acolwellb4034942014-08-28 15:42:431033 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]75e145a2014-04-15 17:44:321034 DCHECK_NE(ready_state_, WebMediaPlayer::ReadyStateHaveNothing);
1035
1036 opaque_ = opaque;
[email protected]75e145a2014-04-15 17:44:321037 if (video_weblayer_)
1038 video_weblayer_->setOpaque(opaque_);
1039}
1040
[email protected]f5443ef72013-04-22 04:03:381041void WebMediaPlayerImpl::FrameReady(
acolwell9e0840d2014-09-06 19:01:321042 const scoped_refptr<VideoFrame>& frame) {
[email protected]dd061e12014-05-06 19:21:221043 compositor_task_runner_->PostTask(
1044 FROM_HERE,
1045 base::Bind(&VideoFrameCompositor::UpdateCurrentFrame,
1046 base::Unretained(compositor_),
1047 frame));
[email protected]bfc05f22013-10-19 17:55:161048}
1049
[email protected]dd061e12014-05-06 19:21:221050static void GetCurrentFrameAndSignal(
1051 VideoFrameCompositor* compositor,
acolwell9e0840d2014-09-06 19:01:321052 scoped_refptr<VideoFrame>* video_frame_out,
[email protected]dd061e12014-05-06 19:21:221053 base::WaitableEvent* event) {
1054 TRACE_EVENT0("media", "GetCurrentFrameAndSignal");
1055 *video_frame_out = compositor->GetCurrentFrame();
1056 event->Signal();
1057}
1058
acolwell9e0840d2014-09-06 19:01:321059scoped_refptr<VideoFrame>
[email protected]dd061e12014-05-06 19:21:221060WebMediaPlayerImpl::GetCurrentFrameFromCompositor() {
1061 TRACE_EVENT0("media", "WebMediaPlayerImpl::GetCurrentFrameFromCompositor");
1062 if (compositor_task_runner_->BelongsToCurrentThread())
1063 return compositor_->GetCurrentFrame();
1064
1065 // Use a posted task and waitable event instead of a lock otherwise
1066 // WebGL/Canvas can see different content than what the compositor is seeing.
acolwell9e0840d2014-09-06 19:01:321067 scoped_refptr<VideoFrame> video_frame;
[email protected]dd061e12014-05-06 19:21:221068 base::WaitableEvent event(false, false);
1069 compositor_task_runner_->PostTask(FROM_HERE,
1070 base::Bind(&GetCurrentFrameAndSignal,
1071 base::Unretained(compositor_),
1072 &video_frame,
1073 &event));
1074 event.Wait();
1075 return video_frame;
1076}
1077
acolwell9e0840d2014-09-06 19:01:321078} // namespace media