blob: 3d1179977c21454855a045bcb5389453b320a8ea [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>
mateuszs3371ab02015-04-24 13:20:238#include <cmath>
[email protected]47b06ceb2010-08-04 22:41:119#include <limits>
guidouc7babef2015-10-22 00:42:3510#include <string>
dcheng652f5ff2015-12-27 08:54:0011#include <utility>
[email protected]47b06ceb2010-08-04 22:41:1112
[email protected]08273c7b2011-09-17 00:33:5113#include "base/bind.h"
sandersd1c0bba02016-03-04 23:14:0814#include "base/bind_helpers.h"
[email protected]2041cf342010-02-19 03:15:5915#include "base/callback.h"
[email protected]7502ef12014-01-25 01:19:2716#include "base/callback_helpers.h"
sandersd1e49fb62015-12-12 01:18:0617#include "base/command_line.h"
[email protected]ca04095f2014-02-07 10:23:5618#include "base/debug/alias.h"
[email protected]926f8fd2013-04-12 20:27:5319#include "base/debug/crash_logging.h"
fdoraydb3ef7d2016-06-09 15:42:3820#include "base/location.h"
servolkf94b4602017-01-31 16:44:2721#include "base/memory/ptr_util.h"
asvitkine30330812016-08-30 04:01:0822#include "base/metrics/histogram_macros.h"
acolwellb4034942014-08-28 15:42:4323#include "base/single_thread_task_runner.h"
servolka233f832016-06-10 20:39:0424#include "base/strings/string_number_conversions.h"
wdzierzanowskifd4cd91c52015-12-02 23:50:2025#include "base/task_runner_util.h"
gabba14a442016-05-11 20:10:2026#include "base/threading/thread_task_runner_handle.h"
ssid9525f4672015-01-28 12:13:1527#include "base/trace_event/trace_event.h"
sandersd1e49fb62015-12-12 01:18:0628#include "build/build_config.h"
[email protected]38564622014-08-19 02:47:1829#include "cc/blink/web_layer_impl.h"
[email protected]21c3f7502013-03-23 03:29:5130#include "cc/layers/video_layer.h"
[email protected]e4fc09e2012-04-06 03:17:4431#include "media/audio/null_audio_sink.h"
[email protected]2eccbed2014-01-10 05:15:5332#include "media/base/bind_to_current_loop.h"
xhwang0ad11e512014-11-25 23:43:0933#include "media/base/cdm_context.h"
xhwang79b193042016-12-13 18:52:4334#include "media/base/content_decryption_module.h"
[email protected]32da1002010-03-03 21:57:3535#include "media/base/limits.h"
zqzhang5d8eab72016-08-26 20:34:3036#include "media/base/media_content_type.h"
[email protected]090f7312011-08-05 23:26:4037#include "media/base/media_log.h"
sandersd1e49fb62015-12-12 01:18:0638#include "media/base/media_switches.h"
tguilbert25a4d112016-10-13 21:56:5139#include "media/base/media_url_demuxer.h"
[email protected]8a561062013-11-22 01:19:3140#include "media/base/text_renderer.h"
watk9f9dfdc92015-09-04 21:33:2941#include "media/base/timestamp_constants.h"
[email protected]e81283bb2010-08-31 18:01:2142#include "media/base/video_frame.h"
acolwell9e0840d2014-09-06 19:01:3243#include "media/blink/texttrack_impl.h"
dalecurtis04bdb582016-08-17 22:15:2344#include "media/blink/watch_time_reporter.h"
acolwell9e0840d2014-09-06 19:01:3245#include "media/blink/webaudiosourceprovider_impl.h"
xhwang97de4202014-11-25 08:44:0146#include "media/blink/webcontentdecryptionmodule_impl.h"
acolwell9e0840d2014-09-06 19:01:3247#include "media/blink/webinbandtexttrack_impl.h"
48#include "media/blink/webmediaplayer_delegate.h"
acolwell9e0840d2014-09-06 19:01:3249#include "media/blink/webmediaplayer_util.h"
50#include "media/blink/webmediasource_impl.h"
[email protected]efe7cd22012-09-12 23:55:0151#include "media/filters/chunk_demuxer.h"
[email protected]ddbc6ff2013-04-19 15:28:3352#include "media/filters/ffmpeg_demuxer.h"
jrummellc9d8e532015-02-26 18:38:1953#include "third_party/WebKit/public/platform/WebEncryptedMediaTypes.h"
srirama.m26f864d02015-07-14 05:21:4654#include "third_party/WebKit/public/platform/WebMediaPlayerClient.h"
55#include "third_party/WebKit/public/platform/WebMediaPlayerEncryptedMediaClient.h"
guidou9bfe4e2f2016-04-09 08:31:1956#include "third_party/WebKit/public/platform/WebMediaPlayerSource.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"
mek966863c2016-02-04 23:39:0559#include "third_party/WebKit/public/platform/WebSecurityOrigin.h"
[email protected]c10884462013-05-30 00:22:0960#include "third_party/WebKit/public/platform/WebSize.h"
61#include "third_party/WebKit/public/platform/WebString.h"
62#include "third_party/WebKit/public/platform/WebURL.h"
tguilbert9881bc22016-10-27 03:13:4163#include "third_party/WebKit/public/web/WebDocument.h"
xhwang0acca44b2015-06-18 00:43:3164#include "third_party/WebKit/public/web/WebFrame.h"
[email protected]80504652014-04-18 04:41:5065#include "third_party/WebKit/public/web/WebLocalFrame.h"
avayvod65fad272017-02-24 01:00:4866#include "third_party/WebKit/public/web/WebUserGestureIndicator.h"
[email protected]2255a9332013-06-17 05:12:3167#include "third_party/WebKit/public/web/WebView.h"
[email protected]b3f2b912009-04-09 16:18:5268
dalecurtisea27a3ed2016-06-24 01:41:3069#if defined(OS_ANDROID)
70#include "media/base/android/media_codec_util.h"
71#endif
72
[email protected]180ef242013-11-07 06:50:4673using blink::WebCanvas;
74using blink::WebMediaPlayer;
75using blink::WebRect;
76using blink::WebSize;
77using blink::WebString;
hubbed5f36882016-01-15 22:40:3778using gpu::gles2::GLES2Interface;
79
danakj365175c2016-02-06 00:37:3780#define STATIC_ASSERT_ENUM(a, b) \
81 static_assert(static_cast<int>(a) == static_cast<int>(b), \
82 "mismatching enums: " #a)
83
hubbed5f36882016-01-15 22:40:3784namespace media {
[email protected]ec9212f2008-12-18 21:40:3685
[email protected]8931c41a2009-07-07 17:31:4986namespace {
87
[email protected]378f0b72009-08-11 17:11:4288// Limits the range of playback rate.
89//
90// TODO(kylep): Revisit these.
91//
92// Vista has substantially lower performance than XP or Windows7. If you speed
93// up a video too much, it can't keep up, and rendering stops updating except on
94// the time bar. For really high speeds, audio becomes a bottleneck and we just
95// use up the data we have, which may not achieve the speed requested, but will
96// not crash the tab.
97//
98// A very slow speed, ie 0.00000001x, causes the machine to lock up. (It seems
99// like a busy loop). It gets unresponsive, although its not completely dead.
100//
101// Also our timers are not very accurate (especially for ogg), which becomes
102// evident at low speeds and on Vista. Since other speeds are risky and outside
103// the norms, we think 1/16x to 16x is a safe and useful range for now.
[email protected]39bdde32013-04-17 17:44:20104const double kMinRate = 0.0625;
105const double kMaxRate = 16.0;
[email protected]378f0b72009-08-11 17:11:42106
hubbed5f36882016-01-15 22:40:37107void SetSinkIdOnMediaThread(scoped_refptr<WebAudioSourceProviderImpl> sink,
108 const std::string& device_id,
109 const url::Origin& security_origin,
olka68b69392016-04-01 11:42:12110 const OutputDeviceStatusCB& callback) {
111 sink->SwitchOutputDevice(device_id, security_origin, callback);
guidouc7babef2015-10-22 00:42:35112}
113
sandersd50a635e2016-04-04 22:50:09114bool IsBackgroundedSuspendEnabled() {
dalecurtis0431cbf2016-03-12 01:19:43115#if !defined(OS_ANDROID)
116 // Suspend/Resume is only enabled by default on Android.
117 return base::CommandLine::ForCurrentProcess()->HasSwitch(
118 switches::kEnableMediaSuspend);
119#else
120 return !base::CommandLine::ForCurrentProcess()->HasSwitch(
121 switches::kDisableMediaSuspend);
122#endif
123}
124
avayvod48a8be52016-08-04 19:52:50125bool IsResumeBackgroundVideosEnabled() {
126 return base::FeatureList::IsEnabled(kResumeBackgroundVideo);
127}
128
avayvod39c102402016-11-23 21:43:13129bool IsBackgroundVideoTrackOptimizationEnabled() {
130 return base::FeatureList::IsEnabled(kBackgroundVideoTrackOptimization);
131}
132
avayvod01201332017-04-14 00:27:15133bool IsBackgroundVideoPauseOptimizationEnabled() {
134 return base::FeatureList::IsEnabled(kBackgroundVideoPauseOptimization);
135}
136
sandersd50a635e2016-04-04 22:50:09137bool IsNetworkStateError(blink::WebMediaPlayer::NetworkState state) {
Blink Reformat1c4d759e2017-04-09 16:34:54138 bool result = state == blink::WebMediaPlayer::kNetworkStateFormatError ||
139 state == blink::WebMediaPlayer::kNetworkStateNetworkError ||
140 state == blink::WebMediaPlayer::kNetworkStateDecodeError;
141 DCHECK_EQ(state > blink::WebMediaPlayer::kNetworkStateLoaded, result);
sandersd50a635e2016-04-04 22:50:09142 return result;
143}
144
sandersd2c478422016-08-02 01:19:25145gfx::Size GetRotatedVideoSize(VideoRotation rotation, gfx::Size natural_size) {
146 if (rotation == VIDEO_ROTATION_90 || rotation == VIDEO_ROTATION_270)
147 return gfx::Size(natural_size.height(), natural_size.width());
148 return natural_size;
149}
150
dalecurtis04bdb582016-08-17 22:15:23151base::TimeDelta GetCurrentTimeInternal(WebMediaPlayerImpl* p_this) {
tguilbert350936ff2017-02-24 05:39:27152 // We wrap currentTime() instead of using pipeline_controller_.GetMediaTime()
153 // since there are a variety of cases in which that time is not accurate;
154 // e.g., while remoting and during a pause or seek.
Blink Reformat1c4d759e2017-04-09 16:34:54155 return base::TimeDelta::FromSecondsD(p_this->CurrentTime());
dalecurtis04bdb582016-08-17 22:15:23156}
157
sandersd35d2c3f2017-01-14 02:04:42158// How much time must have elapsed since loading last progressed before we
159// assume that the decoder will have had time to complete preroll.
160constexpr base::TimeDelta kPrerollAttemptTimeout =
watkd026f792016-11-05 00:28:51161 base::TimeDelta::FromSeconds(3);
162
[email protected]8931c41a2009-07-07 17:31:49163} // namespace
164
[email protected]6683e1b2014-04-10 01:45:38165class BufferedDataSourceHostImpl;
166
Blink Reformat1c4d759e2017-04-09 16:34:54167STATIC_ASSERT_ENUM(WebMediaPlayer::kCORSModeUnspecified,
danakj365175c2016-02-06 00:37:37168 UrlData::CORS_UNSPECIFIED);
Blink Reformat1c4d759e2017-04-09 16:34:54169STATIC_ASSERT_ENUM(WebMediaPlayer::kCORSModeAnonymous, UrlData::CORS_ANONYMOUS);
170STATIC_ASSERT_ENUM(WebMediaPlayer::kCORSModeUseCredentials,
danakj365175c2016-02-06 00:37:37171 UrlData::CORS_USE_CREDENTIALS);
[email protected]a5a01102012-06-06 17:01:24172
[email protected]5b5bb9d2010-10-22 19:57:36173WebMediaPlayerImpl::WebMediaPlayerImpl(
[email protected]35b2a972014-04-04 15:50:22174 blink::WebLocalFrame* frame,
[email protected]180ef242013-11-07 06:50:46175 blink::WebMediaPlayerClient* client,
srirama.m26f864d02015-07-14 05:21:46176 blink::WebMediaPlayerEncryptedMediaClient* encrypted_client,
tguilbert1bb1c782017-01-23 21:15:11177 WebMediaPlayerDelegate* delegate,
tguilbert70d2a00a2017-04-25 00:30:44178 std::unique_ptr<RendererFactorySelector> renderer_factory_selector,
hubbe5f0ad43b2015-12-14 20:57:26179 linked_ptr<UrlIndex> url_index,
dalecurtis9cddc0b2017-04-19 21:23:38180 std::unique_ptr<WebMediaPlayerParams> params)
[email protected]f6af7592014-02-28 10:09:11181 : frame_(frame),
sandersd50a635e2016-04-04 22:50:09182 delegate_state_(DelegateState::GONE),
sandersd35d2c3f2017-01-14 02:04:42183 delegate_has_audio_(false),
Blink Reformat1c4d759e2017-04-09 16:34:54184 network_state_(WebMediaPlayer::kNetworkStateEmpty),
185 ready_state_(WebMediaPlayer::kReadyStateHaveNothing),
186 highest_ready_state_(WebMediaPlayer::kReadyStateHaveNothing),
dalecurtisb6e052f52016-08-25 00:35:55187 preload_(MultibufferDataSource::AUTO),
Blink Reformat1c4d759e2017-04-09 16:34:54188 main_task_runner_(frame->LoadingTaskRunner()),
dalecurtis9cddc0b2017-04-19 21:23:38189 media_task_runner_(params->media_task_runner()),
190 worker_task_runner_(params->worker_task_runner()),
191 media_log_(params->take_media_log()),
sandersd1c0bba02016-03-04 23:14:08192 pipeline_controller_(
tguilbert350936ff2017-02-24 05:39:27193 base::MakeUnique<PipelineImpl>(media_task_runner_, media_log_.get()),
sandersd1c0bba02016-03-04 23:14:08194 base::Bind(&WebMediaPlayerImpl::CreateRenderer,
195 base::Unretained(this)),
196 base::Bind(&WebMediaPlayerImpl::OnPipelineSeeked, AsWeakPtr()),
197 base::Bind(&WebMediaPlayerImpl::OnPipelineSuspended, AsWeakPtr()),
avayvod2135a642017-01-13 00:17:14198 base::Bind(&WebMediaPlayerImpl::OnBeforePipelineResume, AsWeakPtr()),
199 base::Bind(&WebMediaPlayerImpl::OnPipelineResumed, AsWeakPtr()),
alokp967c902452016-05-06 05:21:37200 base::Bind(&WebMediaPlayerImpl::OnError, AsWeakPtr())),
Blink Reformat1c4d759e2017-04-09 16:34:54201 load_type_(kLoadTypeURL),
[email protected]75e145a2014-04-15 17:44:32202 opaque_(false),
wolenetz1b2ae7d2015-06-10 00:44:21203 playback_rate_(0.0),
[email protected]49480902009-07-14 20:23:43204 paused_(true),
avayvodeb9098d2017-01-07 00:33:03205 paused_when_hidden_(false),
[email protected]b3766a22010-12-22 17:34:13206 seeking_(false),
watkdee516f2016-02-18 02:22:19207 pending_suspend_resume_cycle_(false),
scherkusd2c745b2014-09-04 05:03:40208 ended_(false),
yoichio863bebf2016-03-04 07:56:58209 should_notify_time_changed_(false),
tsunghungee562e92016-07-20 18:03:31210 overlay_enabled_(false),
211 decoder_requires_restart_for_overlay_(false),
[email protected]5badb082010-06-11 17:40:15212 client_(client),
srirama.m26f864d02015-07-14 05:21:46213 encrypted_client_(encrypted_client),
[email protected]baff4512011-10-19 18:21:07214 delegate_(delegate),
dalecurtisbb3eaac2016-01-27 21:10:25215 delegate_id_(0),
dalecurtis9cddc0b2017-04-19 21:23:38216 defer_load_cb_(params->defer_load_cb()),
217 context_3d_cb_(params->context_3d_cb()),
218 adjust_allocated_memory_cb_(params->adjust_allocated_memory_cb()),
dalecurtis83266c72015-10-29 18:43:20219 last_reported_memory_usage_(0),
[email protected]132dd57c2012-08-10 23:24:34220 supports_save_(true),
[email protected]f5443ef72013-04-22 04:03:38221 chunk_demuxer_(NULL),
hubbeb2d3efd2017-05-05 23:26:38222 tick_clock_(new base::DefaultTickClock()),
223 buffered_data_source_host_(
224 base::Bind(&WebMediaPlayerImpl::OnProgress, AsWeakPtr()),
225 tick_clock_.get()),
hubbe5f0ad43b2015-12-14 20:57:26226 url_index_(url_index),
Bartosz Fabianowski85a823812015-04-16 10:27:51227 // Threaded compositing isn't enabled universally yet.
dalecurtis9cddc0b2017-04-19 21:23:38228 compositor_task_runner_(params->compositor_task_runner()
229 ? params->compositor_task_runner()
fdoraydb3ef7d2016-06-09 15:42:38230 : base::ThreadTaskRunnerHandle::Get()),
alokp5d86e9b2016-05-17 20:20:41231 compositor_(new VideoFrameCompositor(compositor_task_runner_)),
hubbed5f36882016-01-15 22:40:37232#if defined(OS_ANDROID) // WMPI_CAST
dalecurtis9cddc0b2017-04-19 21:23:38233 cast_impl_(this, client_, params->context_3d_cb()),
hubbed5f36882016-01-15 22:40:37234#endif
dalecurtisbb3eaac2016-01-27 21:10:25235 volume_(1.0),
236 volume_multiplier_(1.0),
tguilbert70d2a00a2017-04-25 00:30:44237 renderer_factory_selector_(std::move(renderer_factory_selector)),
dalecurtis9cddc0b2017-04-19 21:23:38238 surface_manager_(params->surface_manager()),
tsunghungee562e92016-07-20 18:03:31239 overlay_surface_id_(SurfaceManager::kNoSurfaceID),
dalecurtis7f366b2242016-04-13 01:16:17240 suppress_destruction_errors_(false),
dalecurtis9cddc0b2017-04-19 21:23:38241 suspend_enabled_(params->allow_suspend()),
dalecurtis9d638a12016-08-30 06:20:55242 is_encrypted_(false),
sandersd35d2c3f2017-01-14 02:04:42243 preroll_attempt_pending_(false),
dalecurtis9cddc0b2017-04-19 21:23:38244 observer_(params->media_observer()),
avayvod590011e32017-01-20 02:01:00245 max_keyframe_distance_to_disable_background_video_(
dalecurtis9cddc0b2017-04-19 21:23:38246 params->max_keyframe_distance_to_disable_background_video()),
avayvode85ec422017-04-14 00:11:33247 max_keyframe_distance_to_disable_background_video_mse_(
dalecurtis9cddc0b2017-04-19 21:23:38248 params->max_keyframe_distance_to_disable_background_video_mse()),
servolkf94b4602017-01-31 16:44:27249 enable_instant_source_buffer_gc_(
dalecurtis9cddc0b2017-04-19 21:23:38250 params->enable_instant_source_buffer_gc()),
shaktisahu24189c12017-03-11 17:42:55251 embedded_media_experience_enabled_(
dalecurtis9cddc0b2017-04-19 21:23:38252 params->embedded_media_experience_enabled()) {
xhwang51139732017-02-24 19:36:08253 DVLOG(1) << __func__;
dalecurtis83266c72015-10-29 18:43:20254 DCHECK(!adjust_allocated_memory_cb_.is_null());
tguilbert70d2a00a2017-04-25 00:30:44255 DCHECK(renderer_factory_selector_);
servolkef1e5ef2016-03-25 04:55:26256 DCHECK(client_);
tguilbert1bb1c782017-01-23 21:15:11257 DCHECK(delegate_);
dalecurtis83266c72015-10-29 18:43:20258
tsunghungee562e92016-07-20 18:03:31259 force_video_overlays_ = base::CommandLine::ForCurrentProcess()->HasSwitch(
260 switches::kForceVideoOverlays);
261
ampea73f792017-01-19 04:05:39262 enable_fullscreen_video_overlays_ =
263 base::FeatureList::IsEnabled(media::kOverlayFullscreenVideo);
264
tguilbert1bb1c782017-01-23 21:15:11265 delegate_id_ = delegate_->AddObserver(this);
266 delegate_->SetIdle(delegate_id_, true);
sandersd1e49fb62015-12-12 01:18:06267
[email protected]c93eb0a62011-08-09 22:47:24268 media_log_->AddEvent(
acolwell9e0840d2014-09-06 19:01:32269 media_log_->CreateEvent(MediaLogEvent::WEBMEDIAPLAYER_CREATED));
[email protected]4e6be3f2009-05-07 02:24:44270
dalecurtis9cddc0b2017-04-19 21:23:38271 if (params->initial_cdm())
272 SetCdm(params->initial_cdm());
xhwang0ad11e512014-11-25 23:43:09273
xhwangf94a634d2014-10-22 22:07:27274 // TODO(xhwang): When we use an external Renderer, many methods won't work,
xhwang6fa356202014-12-11 00:44:12275 // e.g. GetCurrentFrameFromCompositor(). See http://crbug.com/434861
dalecurtis9cddc0b2017-04-19 21:23:38276 audio_source_provider_ = new WebAudioSourceProviderImpl(
277 params->audio_renderer_sink(), media_log_.get());
xjz4e5d4bf32017-02-15 21:26:35278
279 if (observer_)
280 observer_->SetClient(this);
[email protected]ec9212f2008-12-18 21:40:36281}
282
[email protected]4e6be3f2009-05-07 02:24:44283WebMediaPlayerImpl::~WebMediaPlayerImpl() {
xhwang51139732017-02-24 19:36:08284 DVLOG(1) << __func__;
acolwellb4034942014-08-28 15:42:43285 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]d43ed912009-02-03 04:52:53286
xhwang51139732017-02-24 19:36:08287 if (set_cdm_result_) {
288 DVLOG(2) << "Resolve pending SetCdm() when media player is destroyed.";
Blink Reformat1c4d759e2017-04-09 16:34:54289 set_cdm_result_->Complete();
xhwang51139732017-02-24 19:36:08290 set_cdm_result_.reset();
291 }
292
alokp1116967f2016-06-11 17:30:56293 suppress_destruction_errors_ = true;
tguilbert1bb1c782017-01-23 21:15:11294
295 delegate_->PlayerGone(delegate_id_);
296 delegate_->RemoveObserver(delegate_id_);
[email protected]baff4512011-10-19 18:21:07297
dalecurtis04bdb582016-08-17 22:15:23298 // Finalize any watch time metrics before destroying the pipeline.
299 watch_time_reporter_.reset();
300
tguilbert350936ff2017-02-24 05:39:27301 // The underlying Pipeline must be stopped before it is destroyed.
302 pipeline_controller_.Stop();
[email protected]f6af7592014-02-28 10:09:11303
dalecurtis83266c72015-10-29 18:43:20304 if (last_reported_memory_usage_)
305 adjust_allocated_memory_cb_.Run(-last_reported_memory_usage_);
306
dalecurtise1edb312016-06-22 02:33:21307 // Destruct compositor resources in the proper order.
Blink Reformat1c4d759e2017-04-09 16:34:54308 client_->SetWebLayer(nullptr);
dalecurtise1edb312016-06-22 02:33:21309 if (video_weblayer_)
310 static_cast<cc::VideoLayer*>(video_weblayer_->layer())->StopUsingProvider();
[email protected]dd061e12014-05-06 19:21:22311 compositor_task_runner_->DeleteSoon(FROM_HERE, compositor_);
xhwangea8bb3562015-06-08 21:18:37312
313 media_log_->AddEvent(
314 media_log_->CreateEvent(MediaLogEvent::WEBMEDIAPLAYER_DESTROYED));
[email protected]ec9212f2008-12-18 21:40:36315}
316
Blink Reformat1c4d759e2017-04-09 16:34:54317void WebMediaPlayerImpl::Load(LoadType load_type,
guidou9bfe4e2f2016-04-09 08:31:19318 const blink::WebMediaPlayerSource& source,
[email protected]62e5e682013-03-07 23:53:24319 CORSMode cors_mode) {
xhwang51139732017-02-24 19:36:08320 DVLOG(1) << __func__;
guidou9bfe4e2f2016-04-09 08:31:19321 // Only URL or MSE blob URL is supported.
Blink Reformat1c4d759e2017-04-09 16:34:54322 DCHECK(source.IsURL());
323 blink::WebURL url = source.GetAsURL();
pkastingf5279482016-07-27 02:18:20324 DVLOG(1) << __func__ << "(" << load_type << ", " << url << ", " << cors_mode
325 << ")";
[email protected]d726eddc2013-07-02 22:25:55326 if (!defer_load_cb_.is_null()) {
tguilbert350936ff2017-02-24 05:39:27327 defer_load_cb_.Run(base::Bind(&WebMediaPlayerImpl::DoLoad, AsWeakPtr(),
328 load_type, url, cors_mode));
[email protected]d726eddc2013-07-02 22:25:55329 return;
330 }
[email protected]ef8394c2013-08-21 20:26:30331 DoLoad(load_type, url, cors_mode);
[email protected]62e5e682013-03-07 23:53:24332}
333
Blink Reformat1c4d759e2017-04-09 16:34:54334bool WebMediaPlayerImpl::SupportsOverlayFullscreenVideo() {
watk9c87c6fa2016-05-06 20:36:51335#if defined(OS_ANDROID)
tguilbert1423a662017-04-28 01:54:43336 return !using_media_player_renderer_;
watk9c87c6fa2016-05-06 20:36:51337#else
338 return false;
339#endif
340}
341
tsunghungee562e92016-07-20 18:03:31342void WebMediaPlayerImpl::EnableOverlay() {
343 overlay_enabled_ = true;
watkf835a792016-06-24 23:24:40344 if (surface_manager_) {
liberatoe8e3f43d2017-05-01 22:23:11345 overlay_surface_id_.reset();
watkf835a792016-06-24 23:24:40346 surface_created_cb_.Reset(
347 base::Bind(&WebMediaPlayerImpl::OnSurfaceCreated, AsWeakPtr()));
348 surface_manager_->CreateFullscreenSurface(pipeline_metadata_.natural_size,
349 surface_created_cb_.callback());
350 }
tsunghungee562e92016-07-20 18:03:31351
352 if (decoder_requires_restart_for_overlay_)
watkdee516f2016-02-18 02:22:19353 ScheduleRestart();
354}
355
tsunghungee562e92016-07-20 18:03:31356void WebMediaPlayerImpl::DisableOverlay() {
357 overlay_enabled_ = false;
watkf835a792016-06-24 23:24:40358 surface_created_cb_.Cancel();
tsunghungee562e92016-07-20 18:03:31359 overlay_surface_id_ = SurfaceManager::kNoSurfaceID;
360
361 if (decoder_requires_restart_for_overlay_)
watkdee516f2016-02-18 02:22:19362 ScheduleRestart();
dalecurtis4b632fce22016-11-10 00:52:17363 else if (!set_surface_cb_.is_null())
liberatoe8e3f43d2017-05-01 22:23:11364 set_surface_cb_.Run(*overlay_surface_id_);
watkdee516f2016-02-18 02:22:19365}
366
Blink Reformat1c4d759e2017-04-09 16:34:54367void WebMediaPlayerImpl::EnteredFullscreen() {
liberato2fd111be2017-01-04 00:25:06368 // |force_video_overlays_| implies that we're already in overlay mode, so take
369 // no action here. Otherwise, switch to an overlay if it's allowed and if
370 // it will display properly.
371 if (!force_video_overlays_ && enable_fullscreen_video_overlays_ &&
372 DoesOverlaySupportMetadata()) {
tsunghungee562e92016-07-20 18:03:31373 EnableOverlay();
liberato2fd111be2017-01-04 00:25:06374 }
xjzd3fe45a2016-10-12 18:26:37375 if (observer_)
376 observer_->OnEnteredFullscreen();
tsunghungee562e92016-07-20 18:03:31377}
378
Blink Reformat1c4d759e2017-04-09 16:34:54379void WebMediaPlayerImpl::ExitedFullscreen() {
liberato2fd111be2017-01-04 00:25:06380 // If we're in overlay mode, then exit it unless we're supposed to be in
381 // overlay mode all the time.
382 if (!force_video_overlays_ && overlay_enabled_)
tsunghungee562e92016-07-20 18:03:31383 DisableOverlay();
xjzd3fe45a2016-10-12 18:26:37384 if (observer_)
385 observer_->OnExitedFullscreen();
tsunghungee562e92016-07-20 18:03:31386}
387
Blink Reformat1c4d759e2017-04-09 16:34:54388void WebMediaPlayerImpl::BecameDominantVisibleContent(bool isDominant) {
xjzcdbbe732016-12-03 20:47:42389 if (observer_)
390 observer_->OnBecameDominantVisibleContent(isDominant);
391}
392
Blink Reformat1c4d759e2017-04-09 16:34:54393void WebMediaPlayerImpl::SetIsEffectivelyFullscreen(
zqzhangabc08242017-03-02 16:07:14394 bool isEffectivelyFullscreen) {
395 delegate_->SetIsEffectivelyFullscreen(delegate_id_, isEffectivelyFullscreen);
396}
397
[email protected]ef8394c2013-08-21 20:26:30398void WebMediaPlayerImpl::DoLoad(LoadType load_type,
[email protected]180ef242013-11-07 06:50:46399 const blink::WebURL& url,
[email protected]d726eddc2013-07-02 22:25:55400 CORSMode cors_mode) {
pkastingf5279482016-07-27 02:18:20401 DVLOG(1) << __func__;
acolwellb4034942014-08-28 15:42:43402 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]d726eddc2013-07-02 22:25:55403
[email protected]62e5e682013-03-07 23:53:24404 GURL gurl(url);
dalecurtis9cddc0b2017-04-19 21:23:38405 ReportMetrics(load_type, gurl, frame_->GetSecurityOrigin(), media_log_.get());
[email protected]62e5e682013-03-07 23:53:24406
[email protected]926f8fd2013-04-12 20:27:53407 // Set subresource URL for crash reporting.
408 base::debug::SetCrashKeyValue("subresource_url", gurl.spec());
409
tguilbert75e2bf62017-04-26 20:13:12410 // Used for HLS playback.
411 loaded_url_ = gurl;
tguilbert25a4d112016-10-13 21:56:51412
[email protected]ef8394c2013-08-21 20:26:30413 load_type_ = load_type;
414
Blink Reformat1c4d759e2017-04-09 16:34:54415 SetNetworkState(WebMediaPlayer::kNetworkStateLoading);
416 SetReadyState(WebMediaPlayer::kReadyStateHaveNothing);
417 media_log_->AddEvent(media_log_->CreateLoadEvent(url.GetString().Utf8()));
[email protected]d726eddc2013-07-02 22:25:55418
419 // Media source pipelines can start immediately.
Blink Reformat1c4d759e2017-04-09 16:34:54420 if (load_type == kLoadTypeMediaSource) {
[email protected]d726eddc2013-07-02 22:25:55421 supports_save_ = false;
[email protected]ef8394c2013-08-21 20:26:30422 StartPipeline();
hubbe5f0ad43b2015-12-14 20:57:26423 } else {
dalecurtisb6e052f52016-08-25 00:35:55424 data_source_.reset(new MultibufferDataSource(
425 url, static_cast<UrlData::CORSMode>(cors_mode), main_task_runner_,
426 url_index_, frame_, media_log_.get(), &buffered_data_source_host_,
427 base::Bind(&WebMediaPlayerImpl::NotifyDownloading, AsWeakPtr())));
avayvode46d7bef2016-03-30 23:18:26428 data_source_->SetPreload(preload_);
avayvode46d7bef2016-03-30 23:18:26429 data_source_->Initialize(
430 base::Bind(&WebMediaPlayerImpl::DataSourceInitialized, AsWeakPtr()));
hubbe5f0ad43b2015-12-14 20:57:26431 }
hubbed5f36882016-01-15 22:40:37432
433#if defined(OS_ANDROID) // WMPI_CAST
dalecurtisbb3eaac2016-01-27 21:10:25434 cast_impl_.Initialize(url, frame_, delegate_id_);
hubbed5f36882016-01-15 22:40:37435#endif
[email protected]62e5e682013-03-07 23:53:24436}
437
Blink Reformat1c4d759e2017-04-09 16:34:54438void WebMediaPlayerImpl::Play() {
pkastingf5279482016-07-27 02:18:20439 DVLOG(1) << __func__;
acolwellb4034942014-08-28 15:42:43440 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]d43ed912009-02-03 04:52:53441
avayvod65fad272017-02-24 01:00:48442 // User initiated play unlocks background video playback.
Blink Reformat1c4d759e2017-04-09 16:34:54443 if (blink::WebUserGestureIndicator::IsProcessingUserGesture())
avayvod65fad272017-02-24 01:00:48444 video_locked_when_paused_when_hidden_ = false;
445
hubbed5f36882016-01-15 22:40:37446#if defined(OS_ANDROID) // WMPI_CAST
Blink Reformat1c4d759e2017-04-09 16:34:54447 if (IsRemote()) {
dalecurtis6e2716d2016-01-21 04:49:15448 cast_impl_.play();
hubbed5f36882016-01-15 22:40:37449 return;
450 }
451#endif
sandersd35d2c3f2017-01-14 02:04:42452 // TODO(sandersd): Do we want to reset the idle timer here?
tguilbert1bb1c782017-01-23 21:15:11453 delegate_->SetIdle(delegate_id_, false);
[email protected]49480902009-07-14 20:23:43454 paused_ = false;
tguilbert350936ff2017-02-24 05:39:27455 pipeline_controller_.SetPlaybackRate(playback_rate_);
dalecurtis4619cd02016-09-22 21:39:10456 background_pause_timer_.Stop();
sandersd1c0bba02016-03-04 23:14:08457
[email protected]039b7542013-10-17 22:06:25458 if (data_source_)
459 data_source_->MediaIsPlaying();
[email protected]090f7312011-08-05 23:26:40460
xjz48a9cb72016-12-20 04:02:49461 if (observer_)
462 observer_->OnPlaying();
463
dalecurtis04bdb582016-08-17 22:15:23464 DCHECK(watch_time_reporter_);
465 watch_time_reporter_->OnPlaying();
acolwell9e0840d2014-09-06 19:01:32466 media_log_->AddEvent(media_log_->CreateEvent(MediaLogEvent::PLAY));
sandersd50a635e2016-04-04 22:50:09467 UpdatePlayState();
[email protected]ec9212f2008-12-18 21:40:36468}
469
Blink Reformat1c4d759e2017-04-09 16:34:54470void WebMediaPlayerImpl::Pause() {
pkastingf5279482016-07-27 02:18:20471 DVLOG(1) << __func__;
acolwellb4034942014-08-28 15:42:43472 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]d43ed912009-02-03 04:52:53473
sandersd50a635e2016-04-04 22:50:09474 // We update the paused state even when casting, since we expect pause() to be
475 // called when casting begins, and when we exit casting we should end up in a
476 // paused state.
[email protected]49480902009-07-14 20:23:43477 paused_ = true;
hubbed5f36882016-01-15 22:40:37478
avayvodeb9098d2017-01-07 00:33:03479 // No longer paused because it was hidden.
480 paused_when_hidden_ = false;
481
avayvod65fad272017-02-24 01:00:48482 // User initiated pause locks background videos.
Blink Reformat1c4d759e2017-04-09 16:34:54483 if (blink::WebUserGestureIndicator::IsProcessingUserGesture())
avayvod65fad272017-02-24 01:00:48484 video_locked_when_paused_when_hidden_ = true;
485
hubbed5f36882016-01-15 22:40:37486#if defined(OS_ANDROID) // WMPI_CAST
Blink Reformat1c4d759e2017-04-09 16:34:54487 if (IsRemote()) {
dalecurtis6e2716d2016-01-21 04:49:15488 cast_impl_.pause();
hubbed5f36882016-01-15 22:40:37489 return;
490 }
491#endif
492
tguilbert350936ff2017-02-24 05:39:27493 pipeline_controller_.SetPlaybackRate(0.0);
sandersd1c0bba02016-03-04 23:14:08494
495 // pause() may be called after playback has ended and the HTMLMediaElement
496 // requires that currentTime() == duration() after ending. We want to ensure
497 // |paused_time_| matches currentTime() in this case or a future seek() may
498 // incorrectly discard what it thinks is a seek to the existing time.
tguilbert350936ff2017-02-24 05:39:27499 paused_time_ =
500 ended_ ? GetPipelineMediaDuration() : pipeline_controller_.GetMediaTime();
[email protected]090f7312011-08-05 23:26:40501
xjz48a9cb72016-12-20 04:02:49502 if (observer_)
503 observer_->OnPaused();
504
dalecurtis04bdb582016-08-17 22:15:23505 DCHECK(watch_time_reporter_);
506 watch_time_reporter_->OnPaused();
acolwell9e0840d2014-09-06 19:01:32507 media_log_->AddEvent(media_log_->CreateEvent(MediaLogEvent::PAUSE));
avayvod2135a642017-01-13 00:17:14508
sandersd50a635e2016-04-04 22:50:09509 UpdatePlayState();
[email protected]ec9212f2008-12-18 21:40:36510}
511
Blink Reformat1c4d759e2017-04-09 16:34:54512bool WebMediaPlayerImpl::SupportsSave() const {
acolwellb4034942014-08-28 15:42:43513 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]132dd57c2012-08-10 23:24:34514 return supports_save_;
[email protected]574a1d62009-07-17 03:23:46515}
516
Blink Reformat1c4d759e2017-04-09 16:34:54517void WebMediaPlayerImpl::Seek(double seconds) {
pkastingf5279482016-07-27 02:18:20518 DVLOG(1) << __func__ << "(" << seconds << "s)";
acolwellb4034942014-08-28 15:42:43519 DCHECK(main_task_runner_->BelongsToCurrentThread());
servolk86b3d88fb2017-03-18 02:50:28520 media_log_->AddEvent(media_log_->CreateSeekEvent(seconds));
sandersd1c0bba02016-03-04 23:14:08521 DoSeek(base::TimeDelta::FromSecondsD(seconds), true);
522}
523
524void WebMediaPlayerImpl::DoSeek(base::TimeDelta time, bool time_updated) {
525 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]d43ed912009-02-03 04:52:53526
hubbed5f36882016-01-15 22:40:37527#if defined(OS_ANDROID) // WMPI_CAST
Blink Reformat1c4d759e2017-04-09 16:34:54528 if (IsRemote()) {
sandersd1c0bba02016-03-04 23:14:08529 cast_impl_.seek(time);
hubbed5f36882016-01-15 22:40:37530 return;
531 }
532#endif
533
srirama.mccf671812015-01-08 11:59:13534 ReadyState old_state = ready_state_;
Blink Reformat1c4d759e2017-04-09 16:34:54535 if (ready_state_ > WebMediaPlayer::kReadyStateHaveMetadata)
536 SetReadyState(WebMediaPlayer::kReadyStateHaveMetadata);
[email protected]1bb666802013-11-28 06:12:08537
sandersd1c0bba02016-03-04 23:14:08538 // When paused, we know exactly what the current time is and can elide seeks
539 // to it. However, there are two cases that are not elided:
540 // 1) When the pipeline state is not stable.
541 // In this case we just let |pipeline_controller_| decide what to do, as
542 // it has complete information.
543 // 2) For MSE.
544 // Because the buffers may have changed between seeks, MSE seeks are
545 // never elided.
546 if (paused_ && pipeline_controller_.IsStable() && paused_time_ == time &&
547 !chunk_demuxer_) {
548 // If the ready state was high enough before, we can indicate that the seek
549 // completed just by restoring it. Otherwise we will just wait for the real
550 // ready state change to eventually happen.
Blink Reformat1c4d759e2017-04-09 16:34:54551 if (old_state == kReadyStateHaveEnoughData) {
srirama.m8f4a37562014-12-13 08:16:18552 main_task_runner_->PostTask(
alokp967c902452016-05-06 05:21:37553 FROM_HERE, base::Bind(&WebMediaPlayerImpl::OnBufferingStateChange,
554 AsWeakPtr(), BUFFERING_HAVE_ENOUGH));
srirama.m36ab2682014-12-11 04:20:01555 }
sandersd1c0bba02016-03-04 23:14:08556 return;
srirama.m36ab2682014-12-11 04:20:01557 }
[email protected]44ff37c02009-10-24 01:03:03558
dalecurtis04bdb582016-08-17 22:15:23559 // Call this before setting |seeking_| so that the current media time can be
560 // recorded by the reporter.
561 if (watch_time_reporter_)
562 watch_time_reporter_->OnSeeking();
563
dalecurtis1af3c1a2017-04-11 00:53:49564 // Clear any new frame processed callbacks on seek; otherwise we'll end up
565 // logging a time long after the seek completes.
566 frame_time_report_cb_.Cancel();
567
sandersd35d2c3f2017-01-14 02:04:42568 // TODO(sandersd): Move |seeking_| to PipelineController.
569 // TODO(sandersd): Do we want to reset the idle timer here?
tguilbert1bb1c782017-01-23 21:15:11570 delegate_->SetIdle(delegate_id_, false);
sandersd50a635e2016-04-04 22:50:09571 ended_ = false;
[email protected]b3766a22010-12-22 17:34:13572 seeking_ = true;
sandersd1c0bba02016-03-04 23:14:08573 seek_time_ = time;
574 if (paused_)
575 paused_time_ = time;
576 pipeline_controller_.Seek(time, time_updated);
[email protected]b3766a22010-12-22 17:34:13577
sandersd50a635e2016-04-04 22:50:09578 // This needs to be called after Seek() so that if a resume is triggered, it
579 // is to the correct time.
580 UpdatePlayState();
[email protected]ec9212f2008-12-18 21:40:36581}
582
Blink Reformat1c4d759e2017-04-09 16:34:54583void WebMediaPlayerImpl::SetRate(double rate) {
pkastingf5279482016-07-27 02:18:20584 DVLOG(1) << __func__ << "(" << rate << ")";
acolwellb4034942014-08-28 15:42:43585 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]d43ed912009-02-03 04:52:53586
[email protected]378f0b72009-08-11 17:11:42587 // TODO(kylep): Remove when support for negatives is added. Also, modify the
588 // following checks so rewind uses reasonable values also.
[email protected]39bdde32013-04-17 17:44:20589 if (rate < 0.0)
[email protected]378f0b72009-08-11 17:11:42590 return;
591
592 // Limit rates to reasonable values by clamping.
[email protected]39bdde32013-04-17 17:44:20593 if (rate != 0.0) {
[email protected]378f0b72009-08-11 17:11:42594 if (rate < kMinRate)
595 rate = kMinRate;
596 else if (rate > kMaxRate)
597 rate = kMaxRate;
598 }
599
[email protected]49480902009-07-14 20:23:43600 playback_rate_ = rate;
601 if (!paused_) {
tguilbert350936ff2017-02-24 05:39:27602 pipeline_controller_.SetPlaybackRate(rate);
[email protected]039b7542013-10-17 22:06:25603 if (data_source_)
604 data_source_->MediaPlaybackRateChanged(rate);
[email protected]49480902009-07-14 20:23:43605 }
[email protected]ec9212f2008-12-18 21:40:36606}
607
Blink Reformat1c4d759e2017-04-09 16:34:54608void WebMediaPlayerImpl::SetVolume(double volume) {
pkastingf5279482016-07-27 02:18:20609 DVLOG(1) << __func__ << "(" << volume << ")";
acolwellb4034942014-08-28 15:42:43610 DCHECK(main_task_runner_->BelongsToCurrentThread());
dalecurtisbb3eaac2016-01-27 21:10:25611 volume_ = volume;
tguilbert350936ff2017-02-24 05:39:27612 pipeline_controller_.SetVolume(volume_ * volume_multiplier_);
dalecurtis04bdb582016-08-17 22:15:23613 if (watch_time_reporter_)
614 watch_time_reporter_->OnVolumeChange(volume);
mlamouri910111362016-11-04 11:28:24615
616 // The play state is updated because the player might have left the autoplay
617 // muted state.
618 UpdatePlayState();
[email protected]ec9212f2008-12-18 21:40:36619}
[email protected]f0a51fb52009-03-05 12:46:38620
Blink Reformat1c4d759e2017-04-09 16:34:54621void WebMediaPlayerImpl::SetSinkId(
guidouc7babef2015-10-22 00:42:35622 const blink::WebString& sink_id,
623 const blink::WebSecurityOrigin& security_origin,
624 blink::WebSetSinkIdCallbacks* web_callback) {
guidou69223ce2015-06-16 10:36:19625 DCHECK(main_task_runner_->BelongsToCurrentThread());
pkastingf5279482016-07-27 02:18:20626 DVLOG(1) << __func__;
guidouc7babef2015-10-22 00:42:35627
olka68b69392016-04-01 11:42:12628 media::OutputDeviceStatusCB callback =
629 media::ConvertToOutputDeviceStatusCB(web_callback);
guidouc7babef2015-10-22 00:42:35630 media_task_runner_->PostTask(
631 FROM_HERE,
632 base::Bind(&SetSinkIdOnMediaThread, audio_source_provider_,
Blink Reformat1c4d759e2017-04-09 16:34:54633 sink_id.Utf8(), static_cast<url::Origin>(security_origin),
guidouc7babef2015-10-22 00:42:35634 callback));
guidou69223ce2015-06-16 10:36:19635}
636
Blink Reformat1c4d759e2017-04-09 16:34:54637STATIC_ASSERT_ENUM(WebMediaPlayer::kPreloadNone, MultibufferDataSource::NONE);
638STATIC_ASSERT_ENUM(WebMediaPlayer::kPreloadMetaData,
dalecurtisb6e052f52016-08-25 00:35:55639 MultibufferDataSource::METADATA);
Blink Reformat1c4d759e2017-04-09 16:34:54640STATIC_ASSERT_ENUM(WebMediaPlayer::kPreloadAuto, MultibufferDataSource::AUTO);
[email protected]23a8b1d82011-04-05 16:28:20641
Blink Reformat1c4d759e2017-04-09 16:34:54642void WebMediaPlayerImpl::SetPreload(WebMediaPlayer::Preload preload) {
pkastingf5279482016-07-27 02:18:20643 DVLOG(1) << __func__ << "(" << preload << ")";
acolwellb4034942014-08-28 15:42:43644 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]4e6be3f2009-05-07 02:24:44645
dalecurtisb6e052f52016-08-25 00:35:55646 preload_ = static_cast<MultibufferDataSource::Preload>(preload);
[email protected]b49beeb2013-03-01 20:04:00647 if (data_source_)
[email protected]09c60222014-08-07 16:42:31648 data_source_->SetPreload(preload_);
[email protected]4e6be3f2009-05-07 02:24:44649}
650
Blink Reformat1c4d759e2017-04-09 16:34:54651bool WebMediaPlayerImpl::HasVideo() const {
acolwellb4034942014-08-28 15:42:43652 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]d43ed912009-02-03 04:52:53653
[email protected]b8877772014-03-26 20:17:15654 return pipeline_metadata_.has_video;
[email protected]d43ed912009-02-03 04:52:53655}
656
Blink Reformat1c4d759e2017-04-09 16:34:54657bool WebMediaPlayerImpl::HasAudio() const {
acolwellb4034942014-08-28 15:42:43658 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]fc367af2009-08-14 23:06:35659
[email protected]b8877772014-03-26 20:17:15660 return pipeline_metadata_.has_audio;
[email protected]fc367af2009-08-14 23:06:35661}
662
Blink Reformat1c4d759e2017-04-09 16:34:54663void WebMediaPlayerImpl::EnabledAudioTracksChanged(
servolkf25ceed2016-07-01 03:44:38664 const blink::WebVector<blink::WebMediaPlayer::TrackId>& enabledTrackIds) {
665 DCHECK(main_task_runner_->BelongsToCurrentThread());
666
667 std::ostringstream logstr;
668 std::vector<MediaTrack::Id> enabledMediaTrackIds;
669 for (const auto& blinkTrackId : enabledTrackIds) {
Blink Reformat1c4d759e2017-04-09 16:34:54670 MediaTrack::Id track_id = blinkTrackId.Utf8().data();
servolkf25ceed2016-07-01 03:44:38671 logstr << track_id << " ";
672 enabledMediaTrackIds.push_back(track_id);
673 }
dalecurtis9cddc0b2017-04-19 21:23:38674 MEDIA_LOG(INFO, media_log_.get())
675 << "Enabled audio tracks: [" << logstr.str() << "]";
tguilbert350936ff2017-02-24 05:39:27676 pipeline_controller_.OnEnabledAudioTracksChanged(enabledMediaTrackIds);
servolkf25ceed2016-07-01 03:44:38677}
678
Blink Reformat1c4d759e2017-04-09 16:34:54679void WebMediaPlayerImpl::SelectedVideoTrackChanged(
servolkf25ceed2016-07-01 03:44:38680 blink::WebMediaPlayer::TrackId* selectedTrackId) {
681 DCHECK(main_task_runner_->BelongsToCurrentThread());
682
servolk9bed6602017-02-24 01:20:11683 base::Optional<MediaTrack::Id> selected_video_track_id;
684 if (selectedTrackId && !video_track_disabled_)
Blink Reformat1c4d759e2017-04-09 16:34:54685 selected_video_track_id = MediaTrack::Id(selectedTrackId->Utf8().data());
dalecurtis9cddc0b2017-04-19 21:23:38686 MEDIA_LOG(INFO, media_log_.get())
687 << "Selected video track: [" << selected_video_track_id.value_or("")
688 << "]";
tguilbert350936ff2017-02-24 05:39:27689 pipeline_controller_.OnSelectedVideoTrackChanged(selected_video_track_id);
servolkf25ceed2016-07-01 03:44:38690}
691
Blink Reformat1c4d759e2017-04-09 16:34:54692bool WebMediaPlayerImpl::GetLastUploadedFrameInfo(unsigned* width,
kainino36eeff82017-03-30 00:55:30693 unsigned* height,
694 double* timestamp) {
695 *width = last_uploaded_frame_size_.width();
696 *height = last_uploaded_frame_size_.height();
697 *timestamp = last_uploaded_frame_timestamp_.InSecondsF();
698 return true;
699}
700
Blink Reformat1c4d759e2017-04-09 16:34:54701blink::WebSize WebMediaPlayerImpl::NaturalSize() const {
acolwellb4034942014-08-28 15:42:43702 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]d43ed912009-02-03 04:52:53703
[email protected]b8877772014-03-26 20:17:15704 return blink::WebSize(pipeline_metadata_.natural_size);
[email protected]d43ed912009-02-03 04:52:53705}
706
Blink Reformat1c4d759e2017-04-09 16:34:54707bool WebMediaPlayerImpl::Paused() const {
acolwellb4034942014-08-28 15:42:43708 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]d43ed912009-02-03 04:52:53709
hubbed5f36882016-01-15 22:40:37710#if defined(OS_ANDROID) // WMPI_CAST
Blink Reformat1c4d759e2017-04-09 16:34:54711 if (IsRemote())
danakj4f1fd6a2017-01-06 21:15:17712 return cast_impl_.IsPaused();
hubbed5f36882016-01-15 22:40:37713#endif
sandersd50a635e2016-04-04 22:50:09714
tguilbert350936ff2017-02-24 05:39:27715 return pipeline_controller_.GetPlaybackRate() == 0.0f;
[email protected]d43ed912009-02-03 04:52:53716}
717
Blink Reformat1c4d759e2017-04-09 16:34:54718bool WebMediaPlayerImpl::Seeking() const {
acolwellb4034942014-08-28 15:42:43719 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]d43ed912009-02-03 04:52:53720
Blink Reformat1c4d759e2017-04-09 16:34:54721 if (ready_state_ == WebMediaPlayer::kReadyStateHaveNothing)
[email protected]0acebfa2009-08-21 22:45:40722 return false;
[email protected]67cd5052009-09-10 21:53:22723
[email protected]b3766a22010-12-22 17:34:13724 return seeking_;
[email protected]ec9212f2008-12-18 21:40:36725}
726
Blink Reformat1c4d759e2017-04-09 16:34:54727double WebMediaPlayerImpl::Duration() const {
acolwellb4034942014-08-28 15:42:43728 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]39bdde32013-04-17 17:44:20729
Blink Reformat1c4d759e2017-04-09 16:34:54730 if (ready_state_ == WebMediaPlayer::kReadyStateHaveNothing)
[email protected]39bdde32013-04-17 17:44:20731 return std::numeric_limits<double>::quiet_NaN();
732
chcunninghamb92d5062017-01-10 21:50:22733 // Use duration from ChunkDemuxer when present. MSE allows users to specify
734 // duration as a double. This propagates to the rest of the pipeline as a
735 // TimeDelta with potentially reduced precision (limited to Microseconds).
736 // ChunkDemuxer returns the full-precision user-specified double. This ensures
737 // users can "get" the exact duration they "set".
738 if (chunk_demuxer_)
739 return chunk_demuxer_->GetDuration();
740
avayvodcc273dd2017-01-19 19:35:12741 base::TimeDelta pipeline_duration = GetPipelineMediaDuration();
chcunninghamb92d5062017-01-10 21:50:22742 return pipeline_duration == kInfiniteDuration
743 ? std::numeric_limits<double>::infinity()
744 : pipeline_duration.InSecondsF();
[email protected]d43ed912009-02-03 04:52:53745}
746
[email protected]db66d0092014-04-16 07:15:12747double WebMediaPlayerImpl::timelineOffset() const {
acolwellb4034942014-08-28 15:42:43748 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]db66d0092014-04-16 07:15:12749
750 if (pipeline_metadata_.timeline_offset.is_null())
751 return std::numeric_limits<double>::quiet_NaN();
752
753 return pipeline_metadata_.timeline_offset.ToJsTime();
754}
755
Blink Reformat1c4d759e2017-04-09 16:34:54756double WebMediaPlayerImpl::CurrentTime() const {
acolwellb4034942014-08-28 15:42:43757 DCHECK(main_task_runner_->BelongsToCurrentThread());
Blink Reformat1c4d759e2017-04-09 16:34:54758 DCHECK_NE(ready_state_, WebMediaPlayer::kReadyStateHaveNothing);
scherkusd2c745b2014-09-04 05:03:40759
760 // TODO(scherkus): Replace with an explicit ended signal to HTMLMediaElement,
761 // see http://crbug.com/409280
762 if (ended_)
Blink Reformat1c4d759e2017-04-09 16:34:54763 return Duration();
scherkusd2c745b2014-09-04 05:03:40764
Blink Reformat1c4d759e2017-04-09 16:34:54765 if (Seeking())
sandersd1c0bba02016-03-04 23:14:08766 return seek_time_.InSecondsF();
wolenetz1b2ae7d2015-06-10 00:44:21767
hubbed5f36882016-01-15 22:40:37768#if defined(OS_ANDROID) // WMPI_CAST
Blink Reformat1c4d759e2017-04-09 16:34:54769 if (IsRemote())
hubbed5f36882016-01-15 22:40:37770 return cast_impl_.currentTime();
hubbed5f36882016-01-15 22:40:37771#endif
772
sandersd1c0bba02016-03-04 23:14:08773 if (paused_)
hubbed5f36882016-01-15 22:40:37774 return paused_time_.InSecondsF();
hubbed5f36882016-01-15 22:40:37775
tguilbert350936ff2017-02-24 05:39:27776 return pipeline_controller_.GetMediaTime().InSecondsF();
[email protected]d43ed912009-02-03 04:52:53777}
778
Blink Reformat1c4d759e2017-04-09 16:34:54779WebMediaPlayer::NetworkState WebMediaPlayerImpl::GetNetworkState() const {
acolwellb4034942014-08-28 15:42:43780 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]ddb1e5a2010-12-13 20:10:45781 return network_state_;
782}
783
Blink Reformat1c4d759e2017-04-09 16:34:54784WebMediaPlayer::ReadyState WebMediaPlayerImpl::GetReadyState() const {
acolwellb4034942014-08-28 15:42:43785 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]ddb1e5a2010-12-13 20:10:45786 return ready_state_;
787}
788
wolenetzed8e7092017-04-21 16:28:59789blink::WebString WebMediaPlayerImpl::GetErrorMessage() const {
wolenetz4d39cc02016-04-05 19:54:41790 DCHECK(main_task_runner_->BelongsToCurrentThread());
wolenetzed8e7092017-04-21 16:28:59791 return blink::WebString::FromUTF8(media_log_->GetErrorMessage());
wolenetz4d39cc02016-04-05 19:54:41792}
793
Blink Reformat1c4d759e2017-04-09 16:34:54794blink::WebTimeRanges WebMediaPlayerImpl::Buffered() const {
acolwellb4034942014-08-28 15:42:43795 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]779a8322014-08-22 21:28:37796
acolwell9e0840d2014-09-06 19:01:32797 Ranges<base::TimeDelta> buffered_time_ranges =
tguilbert350936ff2017-02-24 05:39:27798 pipeline_controller_.GetBufferedTimeRanges();
[email protected]779a8322014-08-22 21:28:37799
avayvodcc273dd2017-01-19 19:35:12800 const base::TimeDelta duration = GetPipelineMediaDuration();
dalecurtis39a7f932016-07-19 18:34:59801 if (duration != kInfiniteDuration) {
tguilbert350936ff2017-02-24 05:39:27802 buffered_data_source_host_.AddBufferedTimeRanges(&buffered_time_ranges,
803 duration);
[email protected]779a8322014-08-22 21:28:37804 }
[email protected]02022fc2014-05-16 00:05:31805 return ConvertToWebTimeRanges(buffered_time_ranges);
806}
807
Blink Reformat1c4d759e2017-04-09 16:34:54808blink::WebTimeRanges WebMediaPlayerImpl::Seekable() const {
acolwellb4034942014-08-28 15:42:43809 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]39bdde32013-04-17 17:44:20810
Blink Reformat1c4d759e2017-04-09 16:34:54811 if (ready_state_ < WebMediaPlayer::kReadyStateHaveMetadata)
philipjb0e6f3f2014-09-30 09:51:53812 return blink::WebTimeRanges();
813
Blink Reformat1c4d759e2017-04-09 16:34:54814 const double seekable_end = Duration();
dalecurtis56359cb2014-10-28 00:06:29815
816 // Allow a special exception for seeks to zero for streaming sources with a
817 // finite duration; this allows looping to work.
tguilbertade2bcb2017-01-07 02:57:45818 const bool is_finite_stream = data_source_ && data_source_->IsStreaming() &&
819 std::isfinite(seekable_end);
820
tguilbert75e2bf62017-04-26 20:13:12821 // Do not change the seekable range when using the MediaPlayerRenderer. It
822 // will take care of dropping invalid seeks.
823 const bool force_seeks_to_zero =
824 !using_media_player_renderer_ && is_finite_stream;
dalecurtis56359cb2014-10-28 00:06:29825
826 // TODO(dalecurtis): Technically this allows seeking on media which return an
tguilbertade2bcb2017-01-07 02:57:45827 // infinite duration so long as DataSource::IsStreaming() is false. While not
dalecurtis56359cb2014-10-28 00:06:29828 // expected, disabling this breaks semi-live players, http://crbug.com/427412.
829 const blink::WebTimeRange seekable_range(
tguilbertade2bcb2017-01-07 02:57:45830 0.0, force_seeks_to_zero ? 0.0 : seekable_end);
philipjb0e6f3f2014-09-30 09:51:53831 return blink::WebTimeRanges(&seekable_range, 1);
[email protected]ec9212f2008-12-18 21:40:36832}
833
sandersd35d2c3f2017-01-14 02:04:42834bool WebMediaPlayerImpl::IsPrerollAttemptNeeded() {
835 // TODO(sandersd): Replace with |highest_ready_state_since_seek_| if we need
836 // to ensure that preroll always gets a chance to complete.
837 // See http://crbug.com/671525.
Blink Reformat1c4d759e2017-04-09 16:34:54838 if (highest_ready_state_ >= ReadyState::kReadyStateHaveFutureData)
sandersd35d2c3f2017-01-14 02:04:42839 return false;
840
841 if (preroll_attempt_pending_)
842 return true;
843
844 // Freshly initialized; there has never been any loading progress. (Otherwise
845 // |preroll_attempt_pending_| would be true when the start time is null.)
846 if (preroll_attempt_start_time_.is_null())
847 return false;
848
849 base::TimeDelta preroll_attempt_duration =
850 tick_clock_->NowTicks() - preroll_attempt_start_time_;
851 return preroll_attempt_duration < kPrerollAttemptTimeout;
852}
853
Blink Reformat1c4d759e2017-04-09 16:34:54854bool WebMediaPlayerImpl::DidLoadingProgress() {
acolwellb4034942014-08-28 15:42:43855 DCHECK(main_task_runner_->BelongsToCurrentThread());
dalecurtise7120dc2016-09-03 02:54:35856
857 // Note: Separate variables used to ensure both methods are called every time.
tguilbert350936ff2017-02-24 05:39:27858 const bool pipeline_progress = pipeline_controller_.DidLoadingProgress();
dalecurtise7120dc2016-09-03 02:54:35859 const bool data_progress = buffered_data_source_host_.DidLoadingProgress();
hubbeb2d3efd2017-05-05 23:26:38860 return pipeline_progress || data_progress;
[email protected]d43ed912009-02-03 04:52:53861}
862
Blink Reformat1c4d759e2017-04-09 16:34:54863void WebMediaPlayerImpl::Paint(blink::WebCanvas* canvas,
[email protected]dd5c7972014-08-21 15:00:37864 const blink::WebRect& rect,
enne11266b82017-03-02 01:43:47865 cc::PaintFlags& flags) {
acolwellb4034942014-08-28 15:42:43866 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]dd061e12014-05-06 19:21:22867 TRACE_EVENT0("media", "WebMediaPlayerImpl:paint");
[email protected]4e6be3f2009-05-07 02:24:44868
watkd16bb3e2017-04-25 01:18:31869 // We can't copy from protected frames.
jrummelle616ee92016-10-08 02:15:44870 if (cdm_)
xhwang80739452016-01-13 00:48:00871 return;
872
mcasasf1236fc22015-05-29 22:38:56873 scoped_refptr<VideoFrame> video_frame = GetCurrentFrameFromCompositor();
[email protected]0fe5d43b2014-01-24 23:32:45874
[email protected]b49beeb2013-03-01 20:04:00875 gfx::Rect gfx_rect(rect);
dongseong.hwang0c4e9d82015-01-08 20:11:13876 Context3D context_3d;
mcasas265bdbf82015-06-12 18:44:07877 if (video_frame.get() && video_frame->HasTextures()) {
mcasasf1236fc22015-05-29 22:38:56878 if (!context_3d_cb_.is_null())
dongseong.hwang0c4e9d82015-01-08 20:11:13879 context_3d = context_3d_cb_.Run();
dongseong.hwang0c4e9d82015-01-08 20:11:13880 if (!context_3d.gl)
danakj53f7ec902016-05-21 01:30:10881 return; // Unable to get/create a shared main thread context.
882 if (!context_3d.gr_context)
883 return; // The context has been lost since and can't setup a GrContext.
dongseong.hwang0c4e9d82015-01-08 20:11:13884 }
danakj795f1732015-08-31 23:40:22885 skcanvas_video_renderer_.Paint(video_frame, canvas, gfx::RectF(gfx_rect),
enne11266b82017-03-02 01:43:47886 flags, pipeline_metadata_.video_rotation,
danakj795f1732015-08-31 23:40:22887 context_3d);
[email protected]ec9212f2008-12-18 21:40:36888}
[email protected]5df51652009-01-17 00:03:00889
Blink Reformat1c4d759e2017-04-09 16:34:54890bool WebMediaPlayerImpl::HasSingleSecurityOrigin() const {
[email protected]b49beeb2013-03-01 20:04:00891 if (data_source_)
892 return data_source_->HasSingleOrigin();
[email protected]fcdb7462009-10-21 21:05:11893 return true;
[email protected]38259a7a82009-07-29 21:49:49894}
895
Blink Reformat1c4d759e2017-04-09 16:34:54896bool WebMediaPlayerImpl::DidPassCORSAccessCheck() const {
[email protected]b49beeb2013-03-01 20:04:00897 if (data_source_)
898 return data_source_->DidPassCORSAccessCheck();
899 return false;
[email protected]3fe27112012-06-07 04:00:01900}
901
Blink Reformat1c4d759e2017-04-09 16:34:54902double WebMediaPlayerImpl::MediaTimeForTimeValue(double timeValue) const {
qinminb4c39782015-08-10 18:43:24903 return base::TimeDelta::FromSecondsD(timeValue).InSecondsF();
[email protected]e06e16d82011-05-26 22:13:33904}
905
Blink Reformat1c4d759e2017-04-09 16:34:54906unsigned WebMediaPlayerImpl::DecodedFrameCount() const {
acolwellb4034942014-08-28 15:42:43907 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]4c51bc662011-02-16 02:03:16908
avayvodc4bfb0e62017-01-13 01:07:01909 PipelineStatistics stats = GetPipelineStatistics();
[email protected]4c51bc662011-02-16 02:03:16910 return stats.video_frames_decoded;
911}
912
Blink Reformat1c4d759e2017-04-09 16:34:54913unsigned WebMediaPlayerImpl::DroppedFrameCount() const {
acolwellb4034942014-08-28 15:42:43914 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]4c51bc662011-02-16 02:03:16915
avayvodc4bfb0e62017-01-13 01:07:01916 PipelineStatistics stats = GetPipelineStatistics();
[email protected]dd061e12014-05-06 19:21:22917 return stats.video_frames_dropped;
[email protected]4c51bc662011-02-16 02:03:16918}
919
Blink Reformat1c4d759e2017-04-09 16:34:54920size_t WebMediaPlayerImpl::AudioDecodedByteCount() const {
acolwellb4034942014-08-28 15:42:43921 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]4c51bc662011-02-16 02:03:16922
avayvodc4bfb0e62017-01-13 01:07:01923 PipelineStatistics stats = GetPipelineStatistics();
[email protected]4c51bc662011-02-16 02:03:16924 return stats.audio_bytes_decoded;
925}
926
Blink Reformat1c4d759e2017-04-09 16:34:54927size_t WebMediaPlayerImpl::VideoDecodedByteCount() const {
acolwellb4034942014-08-28 15:42:43928 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]4c51bc662011-02-16 02:03:16929
avayvodc4bfb0e62017-01-13 01:07:01930 PipelineStatistics stats = GetPipelineStatistics();
[email protected]4c51bc662011-02-16 02:03:16931 return stats.video_bytes_decoded;
932}
933
Blink Reformat1c4d759e2017-04-09 16:34:54934bool WebMediaPlayerImpl::CopyVideoTextureToPlatformTexture(
danakj46070b02016-03-28 21:54:11935 gpu::gles2::GLES2Interface* gl,
jiajia.qinc2943162017-05-12 01:34:39936 unsigned int target,
zmo57d577a2015-10-30 18:28:59937 unsigned int texture,
kbr0986e622017-04-13 02:34:58938 unsigned internal_format,
939 unsigned format,
940 unsigned type,
jiajia.qinc2943162017-05-12 01:34:39941 int level,
zmo57d577a2015-10-30 18:28:59942 bool premultiply_alpha,
943 bool flip_y) {
xhwang213e50c2016-10-10 23:56:31944 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]bfc05f22013-10-19 17:55:16945 TRACE_EVENT0("media", "WebMediaPlayerImpl:copyVideoTextureToPlatformTexture");
946
watkd16bb3e2017-04-25 01:18:31947 // We can't copy from protected frames.
xhwang213e50c2016-10-10 23:56:31948 if (cdm_)
949 return false;
[email protected]dd061e12014-05-06 19:21:22950
xhwang213e50c2016-10-10 23:56:31951 scoped_refptr<VideoFrame> video_frame = GetCurrentFrameFromCompositor();
jbauman581d041c2016-07-21 01:01:03952 if (!video_frame.get() || !video_frame->HasTextures()) {
[email protected]e56f88c72013-06-25 22:31:29953 return false;
dongseong.hwang0c4e9d82015-01-08 20:11:13954 }
[email protected]df41e252014-02-03 23:39:50955
jbauman581d041c2016-07-21 01:01:03956 Context3D context_3d;
957 if (!context_3d_cb_.is_null())
958 context_3d = context_3d_cb_.Run();
959 return skcanvas_video_renderer_.CopyVideoFrameTexturesToGLTexture(
jiajia.qinc2943162017-05-12 01:34:39960 context_3d, gl, video_frame.get(), target, texture, internal_format,
961 format, type, level, premultiply_alpha, flip_y);
[email protected]6523b242013-03-13 11:10:07962}
963
Blink Reformat1c4d759e2017-04-09 16:34:54964void WebMediaPlayerImpl::SetContentDecryptionModule(
[email protected]9ebc3b03f2014-08-13 04:01:23965 blink::WebContentDecryptionModule* cdm,
966 blink::WebContentDecryptionModuleResult result) {
xhwang51139732017-02-24 19:36:08967 DVLOG(1) << __func__ << ": cdm = " << cdm;
acolwellb4034942014-08-28 15:42:43968 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]9ebc3b03f2014-08-13 04:01:23969
jrummell06f27072015-06-08 18:12:38970 // Once the CDM is set it can't be cleared as there may be frames being
971 // decrypted on other threads. So fail this request.
972 // http://crbug.com/462365#c7.
xhwang97de4202014-11-25 08:44:01973 if (!cdm) {
Blink Reformat1c4d759e2017-04-09 16:34:54974 result.CompleteWithError(
975 blink::kWebContentDecryptionModuleExceptionInvalidStateError, 0,
xhwang79b193042016-12-13 18:52:43976 "The existing ContentDecryptionModule object cannot be removed at this "
977 "time.");
xhwang97de4202014-11-25 08:44:01978 return;
979 }
980
jrummell89e61d82015-07-23 20:03:34981 // Create a local copy of |result| to avoid problems with the callback
982 // getting passed to the media thread and causing |result| to be destructed
jrummell4acbec912016-02-27 02:45:03983 // on the wrong thread in some failure conditions. Blink should prevent
984 // multiple simultaneous calls.
985 DCHECK(!set_cdm_result_);
jrummell89e61d82015-07-23 20:03:34986 set_cdm_result_.reset(new blink::WebContentDecryptionModuleResult(result));
987
dalecurtis04bdb582016-08-17 22:15:23988 // Recreate the watch time reporter if necessary.
989 const bool was_encrypted = is_encrypted_;
990 is_encrypted_ = true;
991 if (!was_encrypted && watch_time_reporter_)
992 CreateWatchTimeReporter();
993
jrummelle616ee92016-10-08 02:15:44994 SetCdm(cdm);
xhwang97de4202014-11-25 08:44:01995}
996
xhwange8c4181a2014-12-06 08:10:01997void WebMediaPlayerImpl::OnEncryptedMediaInitData(
jrummellcf78967c2015-04-03 05:03:58998 EmeInitDataType init_data_type,
Avi Drissman97785ea2015-12-19 01:11:31999 const std::vector<uint8_t>& init_data) {
jrummellcf78967c2015-04-03 05:03:581000 DCHECK(init_data_type != EmeInitDataType::UNKNOWN);
xhwangbab66f52014-12-02 23:49:501001
ddorwin301ccdb2016-02-25 02:39:171002 // TODO(xhwang): Update this UMA name. https://crbug.com/589251
xhwangbab66f52014-12-02 23:49:501003 UMA_HISTOGRAM_COUNTS("Media.EME.NeedKey", 1);
1004
dalecurtis04bdb582016-08-17 22:15:231005 // Recreate the watch time reporter if necessary.
1006 const bool was_encrypted = is_encrypted_;
1007 is_encrypted_ = true;
1008 if (!was_encrypted && watch_time_reporter_)
1009 CreateWatchTimeReporter();
1010
Blink Reformat1c4d759e2017-04-09 16:34:541011 encrypted_client_->Encrypted(
davidbenb50f00c2015-12-01 00:01:501012 ConvertToWebInitDataType(init_data_type), init_data.data(),
srirama.m26f864d02015-07-14 05:21:461013 base::saturated_cast<unsigned int>(init_data.size()));
xhwangbab66f52014-12-02 23:49:501014}
1015
servolk81e01e02016-03-05 03:29:151016void WebMediaPlayerImpl::OnFFmpegMediaTracksUpdated(
dcheng3076abbf2016-04-22 20:42:391017 std::unique_ptr<MediaTracks> tracks) {
servolk81e01e02016-03-05 03:29:151018 // For MSE/chunk_demuxer case the media track updates are handled by
1019 // WebSourceBufferImpl.
1020 DCHECK(demuxer_.get());
1021 DCHECK(!chunk_demuxer_);
servolkef1e5ef2016-03-25 04:55:261022
servolk16e8bdf82017-04-11 17:00:391023 // Report the media track information to blink. Only the first audio track and
1024 // the first video track are enabled by default to match blink logic.
1025 bool is_first_audio_track = true;
1026 bool is_first_video_track = true;
servolkef1e5ef2016-03-25 04:55:261027 for (const auto& track : tracks->tracks()) {
1028 if (track->type() == MediaTrack::Audio) {
Blink Reformat1c4d759e2017-04-09 16:34:541029 client_->AddAudioTrack(blink::WebString::FromUTF8(track->id()),
1030 blink::WebMediaPlayerClient::kAudioTrackKindMain,
1031 blink::WebString::FromUTF8(track->label()),
1032 blink::WebString::FromUTF8(track->language()),
servolk16e8bdf82017-04-11 17:00:391033 is_first_audio_track);
1034 is_first_audio_track = false;
servolkef1e5ef2016-03-25 04:55:261035 } else if (track->type() == MediaTrack::Video) {
Blink Reformat1c4d759e2017-04-09 16:34:541036 client_->AddVideoTrack(blink::WebString::FromUTF8(track->id()),
1037 blink::WebMediaPlayerClient::kVideoTrackKindMain,
1038 blink::WebString::FromUTF8(track->label()),
1039 blink::WebString::FromUTF8(track->language()),
servolk16e8bdf82017-04-11 17:00:391040 is_first_video_track);
1041 is_first_video_track = false;
servolkef1e5ef2016-03-25 04:55:261042 } else {
1043 // Text tracks are not supported through this code path yet.
1044 NOTREACHED();
1045 }
1046 }
servolk81e01e02016-03-05 03:29:151047}
1048
jrummelle616ee92016-10-08 02:15:441049void WebMediaPlayerImpl::SetCdm(blink::WebContentDecryptionModule* cdm) {
1050 DCHECK(main_task_runner_->BelongsToCurrentThread());
1051 DCHECK(cdm);
xhwang79b193042016-12-13 18:52:431052 scoped_refptr<ContentDecryptionModule> cdm_reference =
jrummelle616ee92016-10-08 02:15:441053 ToWebContentDecryptionModuleImpl(cdm)->GetCdm();
1054 if (!cdm_reference) {
1055 NOTREACHED();
1056 OnCdmAttached(false);
xhwang80739452016-01-13 00:48:001057 return;
1058 }
1059
jrummelle616ee92016-10-08 02:15:441060 CdmContext* cdm_context = cdm_reference->GetCdmContext();
1061 if (!cdm_context) {
1062 OnCdmAttached(false);
1063 return;
1064 }
1065
xjzd3fe45a2016-10-12 18:26:371066 if (observer_)
1067 observer_->OnSetCdm(cdm_context);
1068
jrummelle616ee92016-10-08 02:15:441069 // Keep the reference to the CDM, as it shouldn't be destroyed until
1070 // after the pipeline is done with the |cdm_context|.
1071 pending_cdm_ = std::move(cdm_reference);
tguilbert350936ff2017-02-24 05:39:271072 pipeline_controller_.SetCdm(
1073 cdm_context, base::Bind(&WebMediaPlayerImpl::OnCdmAttached, AsWeakPtr()));
xhwang97de4202014-11-25 08:44:011074}
1075
jrummell89e61d82015-07-23 20:03:341076void WebMediaPlayerImpl::OnCdmAttached(bool success) {
xhwang51139732017-02-24 19:36:081077 DVLOG(1) << __func__ << ": success = " << success;
jrummelle616ee92016-10-08 02:15:441078 DCHECK(main_task_runner_->BelongsToCurrentThread());
1079 DCHECK(pending_cdm_);
1080
1081 // If the CDM is set from the constructor there is no promise
1082 // (|set_cdm_result_|) to fulfill.
xhwang97de4202014-11-25 08:44:011083 if (success) {
xhwang29c5ad202017-04-14 07:02:191084 media_log_->SetBooleanProperty("has_cdm", true);
1085
jrummelle616ee92016-10-08 02:15:441086 // This will release the previously attached CDM (if any).
1087 cdm_ = std::move(pending_cdm_);
1088 if (set_cdm_result_) {
Blink Reformat1c4d759e2017-04-09 16:34:541089 set_cdm_result_->Complete();
jrummelle616ee92016-10-08 02:15:441090 set_cdm_result_.reset();
1091 }
1092
xhwang97de4202014-11-25 08:44:011093 return;
1094 }
1095
jrummelle616ee92016-10-08 02:15:441096 pending_cdm_ = nullptr;
1097 if (set_cdm_result_) {
Blink Reformat1c4d759e2017-04-09 16:34:541098 set_cdm_result_->CompleteWithError(
1099 blink::kWebContentDecryptionModuleExceptionNotSupportedError, 0,
xhwang79b193042016-12-13 18:52:431100 "Unable to set ContentDecryptionModule object");
jrummelle616ee92016-10-08 02:15:441101 set_cdm_result_.reset();
1102 }
[email protected]9ebc3b03f2014-08-13 04:01:231103}
1104
sandersd1c0bba02016-03-04 23:14:081105void WebMediaPlayerImpl::OnPipelineSeeked(bool time_updated) {
[email protected]5d11eff2011-09-15 00:06:061106 seeking_ = false;
wolenetz1b2ae7d2015-06-10 00:44:211107 seek_time_ = base::TimeDelta();
avayvod2135a642017-01-13 00:17:141108
hubbe5a2dec022016-03-17 01:14:231109 if (paused_) {
1110#if defined(OS_ANDROID) // WMPI_CAST
Blink Reformat1c4d759e2017-04-09 16:34:541111 if (IsRemote()) {
hubbe5a2dec022016-03-17 01:14:231112 paused_time_ = base::TimeDelta::FromSecondsD(cast_impl_.currentTime());
1113 } else {
tguilbert350936ff2017-02-24 05:39:271114 paused_time_ = pipeline_controller_.GetMediaTime();
hubbe5a2dec022016-03-17 01:14:231115 }
1116#else
tguilbert350936ff2017-02-24 05:39:271117 paused_time_ = pipeline_controller_.GetMediaTime();
hubbe5a2dec022016-03-17 01:14:231118#endif
dalecurtis04bdb582016-08-17 22:15:231119 } else {
1120 DCHECK(watch_time_reporter_);
1121 watch_time_reporter_->OnPlaying();
hubbe5a2dec022016-03-17 01:14:231122 }
sandersd1c0bba02016-03-04 23:14:081123 if (time_updated)
1124 should_notify_time_changed_ = true;
dalecurtisaf34d8712016-09-20 04:32:261125
dalecurtis4f6d14d2017-02-22 17:42:221126 // Reset underflow duration upon seek; this prevents looping videos and user
1127 // actions from artificially inflating the duration.
1128 underflow_timer_.reset();
avayvod56e1f3942017-01-21 02:06:311129
1130 // Background video optimizations are delayed when shown/hidden if pipeline
1131 // is seeking.
1132 UpdateBackgroundVideoOptimizationState();
[email protected]8931c41a2009-07-07 17:31:491133}
1134
sandersd1c0bba02016-03-04 23:14:081135void WebMediaPlayerImpl::OnPipelineSuspended() {
hubbed5f36882016-01-15 22:40:371136#if defined(OS_ANDROID)
Blink Reformat1c4d759e2017-04-09 16:34:541137 if (IsRemote()) {
hubbed5f36882016-01-15 22:40:371138 scoped_refptr<VideoFrame> frame = cast_impl_.GetCastingBanner();
sandersd50a635e2016-04-04 22:50:091139 if (frame)
dalecurtise9c89e92016-05-20 19:38:001140 compositor_->PaintSingleFrame(frame);
hubbed5f36882016-01-15 22:40:371141 }
1142#endif
1143
sandersd2f5bb6152017-03-29 22:57:531144 // Tell the data source we have enough data so that it may release the
1145 // connection.
1146 if (data_source_)
1147 data_source_->OnBufferingHaveEnough(true);
dalecurtis37fe5862016-03-15 19:29:091148
sandersd50a635e2016-04-04 22:50:091149 ReportMemoryUsage();
1150
sandersd1c0bba02016-03-04 23:14:081151 if (pending_suspend_resume_cycle_) {
watkdee516f2016-02-18 02:22:191152 pending_suspend_resume_cycle_ = false;
sandersd50a635e2016-04-04 22:50:091153 UpdatePlayState();
dalecurtis0431cbf2016-03-12 01:19:431154 }
sandersd1c0bba02016-03-04 23:14:081155}
1156
avayvod2135a642017-01-13 00:17:141157void WebMediaPlayerImpl::OnBeforePipelineResume() {
1158 // Enable video track if we disabled it in the background - this way the new
1159 // renderer will attach its callbacks to the video stream properly.
1160 // TODO(avayvod): Remove this when disabling and enabling video tracks in
1161 // non-playing state works correctly. See https://crbug.com/678374.
1162 EnableVideoTrackIfNeeded();
1163 is_pipeline_resuming_ = true;
1164}
1165
1166void WebMediaPlayerImpl::OnPipelineResumed() {
1167 is_pipeline_resuming_ = false;
1168
avayvod56e1f3942017-01-21 02:06:311169 UpdateBackgroundVideoOptimizationState();
avayvod2135a642017-01-13 00:17:141170}
1171
alokp967c902452016-05-06 05:21:371172void WebMediaPlayerImpl::OnDemuxerOpened() {
1173 DCHECK(main_task_runner_->BelongsToCurrentThread());
dalecurtis9cddc0b2017-04-19 21:23:381174 client_->MediaSourceOpened(new WebMediaSourceImpl(chunk_demuxer_));
alokp967c902452016-05-06 05:21:371175}
1176
servolkf94b4602017-01-31 16:44:271177void WebMediaPlayerImpl::OnMemoryPressure(
1178 base::MemoryPressureListener::MemoryPressureLevel memory_pressure_level) {
1179 DVLOG(2) << __func__ << " memory_pressure_level=" << memory_pressure_level;
1180 DCHECK(main_task_runner_->BelongsToCurrentThread());
1181 DCHECK(base::FeatureList::IsEnabled(kMemoryPressureBasedSourceBufferGC));
1182 DCHECK(chunk_demuxer_);
1183
1184 // The new value of |memory_pressure_level| will take effect on the next
1185 // garbage collection. Typically this means the next SourceBuffer append()
1186 // operation, since per MSE spec, the garbage collection must only occur
1187 // during SourceBuffer append(). But if memory pressure is critical it might
1188 // be better to perform GC immediately rather than wait for the next append
1189 // and potentially get killed due to out-of-memory.
1190 // So if this experiment is enabled and pressure level is critical, we'll pass
1191 // down force_instant_gc==true, which will force immediate GC on
1192 // SourceBufferStreams.
1193 bool force_instant_gc =
1194 (enable_instant_source_buffer_gc_ &&
1195 memory_pressure_level ==
1196 base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL);
1197
1198 // base::Unretained is safe, since chunk_demuxer_ is actually owned by
1199 // |this| via this->demuxer_.
1200 media_task_runner_->PostTask(
1201 FROM_HERE, base::Bind(&ChunkDemuxer::OnMemoryPressure,
1202 base::Unretained(chunk_demuxer_),
Blink Reformat1c4d759e2017-04-09 16:34:541203 base::TimeDelta::FromSecondsD(CurrentTime()),
servolkf94b4602017-01-31 16:44:271204 memory_pressure_level, force_instant_gc));
1205}
1206
alokp967c902452016-05-06 05:21:371207void WebMediaPlayerImpl::OnError(PipelineStatus status) {
pkastingf5279482016-07-27 02:18:201208 DVLOG(1) << __func__;
alokp967c902452016-05-06 05:21:371209 DCHECK(main_task_runner_->BelongsToCurrentThread());
1210 DCHECK_NE(status, PIPELINE_OK);
1211
1212 if (suppress_destruction_errors_)
1213 return;
1214
dalecurtis9cddc0b2017-04-19 21:23:381215 ReportPipelineError(load_type_, status, media_log_.get());
alokp967c902452016-05-06 05:21:371216 media_log_->AddEvent(media_log_->CreatePipelineErrorEvent(status));
1217
Blink Reformat1c4d759e2017-04-09 16:34:541218 if (ready_state_ == WebMediaPlayer::kReadyStateHaveNothing) {
alokp967c902452016-05-06 05:21:371219 // Any error that occurs before reaching ReadyStateHaveMetadata should
1220 // be considered a format error.
Blink Reformat1c4d759e2017-04-09 16:34:541221 SetNetworkState(WebMediaPlayer::kNetworkStateFormatError);
alokp967c902452016-05-06 05:21:371222 } else {
1223 SetNetworkState(PipelineErrorToNetworkState(status));
1224 }
1225
1226 UpdatePlayState();
1227}
1228
1229void WebMediaPlayerImpl::OnEnded() {
pkastingf5279482016-07-27 02:18:201230 DVLOG(1) << __func__;
acolwellb4034942014-08-28 15:42:431231 DCHECK(main_task_runner_->BelongsToCurrentThread());
scherkusd2c745b2014-09-04 05:03:401232
sandersd1c0bba02016-03-04 23:14:081233 // Ignore state changes until we've completed all outstanding operations.
1234 if (!pipeline_controller_.IsStable())
scherkusd2c745b2014-09-04 05:03:401235 return;
1236
1237 ended_ = true;
Blink Reformat1c4d759e2017-04-09 16:34:541238 client_->TimeChanged();
sandersd50a635e2016-04-04 22:50:091239
dalecurtis1af3c1a2017-04-11 00:53:491240 // Clear any new frame processed callbacks on end; otherwise we'll end up
1241 // logging a time long after playback ends.
1242 frame_time_report_cb_.Cancel();
1243
sandersd50a635e2016-04-04 22:50:091244 // We don't actually want this to run until |client_| calls seek() or pause(),
1245 // but that should have already happened in timeChanged() and so this is
1246 // expected to be a no-op.
1247 UpdatePlayState();
[email protected]576537842009-08-12 23:52:051248}
1249
alokp967c902452016-05-06 05:21:371250void WebMediaPlayerImpl::OnMetadata(PipelineMetadata metadata) {
pkastingf5279482016-07-27 02:18:201251 DVLOG(1) << __func__;
acolwellb4034942014-08-28 15:42:431252 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]a8e2cb82012-08-17 00:02:391253
[email protected]b8877772014-03-26 20:17:151254 pipeline_metadata_ = metadata;
[email protected]739847c02014-01-16 00:12:251255
Blink Reformat1c4d759e2017-04-09 16:34:541256 SetReadyState(WebMediaPlayer::kReadyStateHaveMetadata);
dalecurtis849cf4b22015-03-27 18:35:451257 UMA_HISTOGRAM_ENUMERATION("Media.VideoRotation", metadata.video_rotation,
acolwell9e0840d2014-09-06 19:01:321258 VIDEO_ROTATION_MAX + 1);
[email protected]21c3f7502013-03-23 03:29:511259
Blink Reformat1c4d759e2017-04-09 16:34:541260 if (HasVideo()) {
liberato2fd111be2017-01-04 00:25:061261 if (overlay_enabled_) {
1262 // SurfaceView doesn't support rotated video, so transition back if
1263 // the video is now rotated. If |force_video_overlays_|, we keep the
1264 // overlay anyway so that the state machine keeps working.
1265 if (!force_video_overlays_ && !DoesOverlaySupportMetadata())
1266 DisableOverlay();
1267 else if (surface_manager_)
1268 surface_manager_->NaturalSizeChanged(pipeline_metadata_.natural_size);
1269 }
watkf835a792016-06-24 23:24:401270
1271 DCHECK(!video_weblayer_);
dalecurtise1edb312016-06-22 02:33:211272 video_weblayer_.reset(new cc_blink::WebLayerImpl(cc::VideoLayer::Create(
1273 compositor_, pipeline_metadata_.video_rotation)));
jbauman952274d2015-09-10 23:23:361274 video_weblayer_->layer()->SetContentsOpaque(opaque_);
1275 video_weblayer_->SetContentsOpaqueIsFixed(true);
Blink Reformat1c4d759e2017-04-09 16:34:541276 client_->SetWebLayer(video_weblayer_.get());
[email protected]a8e2cb82012-08-17 00:02:391277 }
dalecurtis8e4dc682016-03-15 02:30:301278
xjzd3fe45a2016-10-12 18:26:371279 if (observer_)
xjz15b483f2017-01-12 00:21:361280 observer_->OnMetadataChanged(pipeline_metadata_);
xjzd3fe45a2016-10-12 18:26:371281
dalecurtis04bdb582016-08-17 22:15:231282 CreateWatchTimeReporter();
sandersd50a635e2016-04-04 22:50:091283 UpdatePlayState();
[email protected]a8e2cb82012-08-17 00:02:391284}
1285
hubbeb2d3efd2017-05-05 23:26:381286void WebMediaPlayerImpl::OnProgress() {
1287 DVLOG(1) << __func__;
1288 if (highest_ready_state_ < ReadyState::kReadyStateHaveFutureData) {
1289 // Reset the preroll attempt clock.
1290 preroll_attempt_pending_ = true;
1291 preroll_attempt_start_time_ = base::TimeTicks();
1292
1293 // Clear any 'stale' flag and give the pipeline a chance to resume. If we
1294 // are already resumed, this will cause |preroll_attempt_start_time_| to
1295 // be set.
1296 delegate_->ClearStaleFlag(delegate_id_);
1297 UpdatePlayState();
1298 } else if (ready_state_ == ReadyState::kReadyStateHaveFutureData &&
1299 CanPlayThrough()) {
1300 SetReadyState(WebMediaPlayer::kReadyStateHaveEnoughData);
1301 }
1302}
1303
1304bool WebMediaPlayerImpl::CanPlayThrough() {
1305 if (!base::FeatureList::IsEnabled(kSpecCompliantCanPlayThrough))
1306 return true;
1307 if (chunk_demuxer_)
1308 return true;
1309 if (data_source_ && data_source_->assume_fully_buffered())
1310 return true;
1311 // If we're not currently downloading, we have as much buffer as
1312 // we're ever going to get, which means we say we can play through.
1313 if (network_state_ == WebMediaPlayer::kNetworkStateIdle)
1314 return true;
1315 return buffered_data_source_host_.CanPlayThrough(
1316 base::TimeDelta::FromSecondsD(CurrentTime()),
1317 base::TimeDelta::FromSecondsD(Duration()),
1318 playback_rate_ == 0.0 ? 1.0 : playback_rate_);
1319}
1320
alokp967c902452016-05-06 05:21:371321void WebMediaPlayerImpl::OnBufferingStateChange(BufferingState state) {
pkastingf5279482016-07-27 02:18:201322 DVLOG(1) << __func__ << "(" << state << ")";
alokp967c902452016-05-06 05:21:371323 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]b8877772014-03-26 20:17:151324
sandersd1c0bba02016-03-04 23:14:081325 // Ignore buffering state changes until we've completed all outstanding
1326 // operations.
1327 if (!pipeline_controller_.IsStable())
[email protected]ba7d5f92014-06-24 05:37:401328 return;
[email protected]b8877772014-03-26 20:17:151329
dalecurtis869bf2f2017-01-10 18:01:101330 media_log_->AddEvent(media_log_->CreateBufferingStateChangedEvent(
1331 "pipeline_buffering_state", state));
1332
chcunninghameb270c92016-07-15 01:00:451333 if (state == BUFFERING_HAVE_ENOUGH) {
Blink Reformat1c4d759e2017-04-09 16:34:541334 if (highest_ready_state_ < WebMediaPlayer::kReadyStateHaveEnoughData) {
dalecurtis4f6d14d2017-02-22 17:42:221335 // Record a zero value for underflow histogram so that the histogram
dalecurtis821e803f2016-09-01 18:44:151336 // includes playbacks which never encounter an underflow event.
dalecurtis4f6d14d2017-02-22 17:42:221337 RecordUnderflowDuration(base::TimeDelta());
dalecurtis821e803f2016-09-01 18:44:151338 }
1339
hubbeb2d3efd2017-05-05 23:26:381340 SetReadyState(CanPlayThrough() ? WebMediaPlayer::kReadyStateHaveEnoughData
1341 : WebMediaPlayer::kReadyStateHaveFutureData);
[email protected]ba7d5f92014-06-24 05:37:401342
chcunninghameb270c92016-07-15 01:00:451343 // Let the DataSource know we have enough data. It may use this information
1344 // to release unused network connections.
1345 if (data_source_)
1346 data_source_->OnBufferingHaveEnough(false);
dalecurtis849cf4b22015-03-27 18:35:451347
chcunninghameb270c92016-07-15 01:00:451348 // Blink expects a timeChanged() in response to a seek().
sandersd35d2c3f2017-01-14 02:04:421349 if (should_notify_time_changed_) {
1350 should_notify_time_changed_ = false;
Blink Reformat1c4d759e2017-04-09 16:34:541351 client_->TimeChanged();
sandersd35d2c3f2017-01-14 02:04:421352 }
dalecurtis0f0097a2015-12-01 17:40:471353
chcunninghameb270c92016-07-15 01:00:451354 // Once we have enough, start reporting the total memory usage. We'll also
1355 // report once playback starts.
1356 ReportMemoryUsage();
dalecurtis9d638a12016-08-30 06:20:551357
dalecurtis4f6d14d2017-02-22 17:42:221358 // Report the amount of time it took to leave the underflow state.
1359 if (underflow_timer_) {
1360 RecordUnderflowDuration(underflow_timer_->Elapsed());
dalecurtis9d638a12016-08-30 06:20:551361 underflow_timer_.reset();
1362 }
chcunninghameb270c92016-07-15 01:00:451363 } else {
1364 // Buffering has underflowed.
1365 DCHECK_EQ(state, BUFFERING_HAVE_NOTHING);
dalecurtisacd77d62016-09-09 23:23:141366
dalecurtisd06eabc2017-02-24 23:43:291367 // Report the number of times we've entered the underflow state. Ensure we
1368 // only report the value when transitioning from HAVE_ENOUGH to
1369 // HAVE_NOTHING.
Blink Reformat1c4d759e2017-04-09 16:34:541370 if (ready_state_ == WebMediaPlayer::kReadyStateHaveEnoughData)
dalecurtisacd77d62016-09-09 23:23:141371 underflow_timer_.reset(new base::ElapsedTimer());
dalecurtisacd77d62016-09-09 23:23:141372
chcunninghameb270c92016-07-15 01:00:451373 // It shouldn't be possible to underflow if we've not advanced past
1374 // HAVE_CURRENT_DATA.
Blink Reformat1c4d759e2017-04-09 16:34:541375 DCHECK_GT(highest_ready_state_, WebMediaPlayer::kReadyStateHaveCurrentData);
1376 SetReadyState(WebMediaPlayer::kReadyStateHaveCurrentData);
chcunninghameb270c92016-07-15 01:00:451377 }
sandersd50a635e2016-04-04 22:50:091378
1379 UpdatePlayState();
[email protected]b8877772014-03-26 20:17:151380}
1381
alokp967c902452016-05-06 05:21:371382void WebMediaPlayerImpl::OnDurationChange() {
acolwellb4034942014-08-28 15:42:431383 DCHECK(main_task_runner_->BelongsToCurrentThread());
alokp967c902452016-05-06 05:21:371384
1385 // TODO(sandersd): We should call delegate_->DidPlay() with the new duration,
1386 // especially if it changed from <5s to >5s.
Blink Reformat1c4d759e2017-04-09 16:34:541387 if (ready_state_ == WebMediaPlayer::kReadyStateHaveNothing)
alokp967c902452016-05-06 05:21:371388 return;
1389
Blink Reformat1c4d759e2017-04-09 16:34:541390 client_->DurationChanged();
[email protected]81bb3322011-07-21 15:55:501391}
1392
alokp967c902452016-05-06 05:21:371393void WebMediaPlayerImpl::OnAddTextTrack(const TextTrackConfig& config,
1394 const AddTextTrackDoneCB& done_cb) {
acolwellb4034942014-08-28 15:42:431395 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]71537722013-05-23 06:47:531396
[email protected]8a561062013-11-22 01:19:311397 const WebInbandTextTrackImpl::Kind web_kind =
1398 static_cast<WebInbandTextTrackImpl::Kind>(config.kind());
Blink Reformat1c4d759e2017-04-09 16:34:541399 const blink::WebString web_label = blink::WebString::FromUTF8(config.label());
[email protected]8a561062013-11-22 01:19:311400 const blink::WebString web_language =
Blink Reformat1c4d759e2017-04-09 16:34:541401 blink::WebString::FromUTF8(config.language());
1402 const blink::WebString web_id = blink::WebString::FromUTF8(config.id());
[email protected]71537722013-05-23 06:47:531403
dcheng3076abbf2016-04-22 20:42:391404 std::unique_ptr<WebInbandTextTrackImpl> web_inband_text_track(
henriks9cce5fa2014-12-12 09:35:301405 new WebInbandTextTrackImpl(web_kind, web_label, web_language, web_id));
[email protected]8a561062013-11-22 01:19:311406
dcheng3076abbf2016-04-22 20:42:391407 std::unique_ptr<media::TextTrack> text_track(new TextTrackImpl(
dcheng652f5ff2015-12-27 08:54:001408 main_task_runner_, client_, std::move(web_inband_text_track)));
[email protected]8a561062013-11-22 01:19:311409
dcheng652f5ff2015-12-27 08:54:001410 done_cb.Run(std::move(text_track));
[email protected]71537722013-05-23 06:47:531411}
1412
alokp967c902452016-05-06 05:21:371413void WebMediaPlayerImpl::OnWaitingForDecryptionKey() {
1414 DCHECK(main_task_runner_->BelongsToCurrentThread());
1415
Blink Reformat1c4d759e2017-04-09 16:34:541416 encrypted_client_->DidBlockPlaybackWaitingForKey();
alokp967c902452016-05-06 05:21:371417 // TODO(jrummell): didResumePlaybackBlockedForKey() should only be called
1418 // when a key has been successfully added (e.g. OnSessionKeysChange() with
1419 // |has_additional_usable_key| = true). http://crbug.com/461903
Blink Reformat1c4d759e2017-04-09 16:34:541420 encrypted_client_->DidResumePlaybackBlockedForKey();
alokp967c902452016-05-06 05:21:371421}
1422
alokp5d86e9b2016-05-17 20:20:411423void WebMediaPlayerImpl::OnVideoNaturalSizeChange(const gfx::Size& size) {
1424 DCHECK(main_task_runner_->BelongsToCurrentThread());
Blink Reformat1c4d759e2017-04-09 16:34:541425 DCHECK_NE(ready_state_, WebMediaPlayer::kReadyStateHaveNothing);
alokp5d86e9b2016-05-17 20:20:411426
xhwang60802652017-04-19 07:29:581427 TRACE_EVENT0("media", "WebMediaPlayerImpl::OnNaturalSizeChanged");
1428
xjz15b483f2017-01-12 00:21:361429 // The input |size| is from the decoded video frame, which is the original
1430 // natural size and need to be rotated accordingly.
sandersd2c478422016-08-02 01:19:251431 gfx::Size rotated_size =
1432 GetRotatedVideoSize(pipeline_metadata_.video_rotation, size);
1433
xhwang60802652017-04-19 07:29:581434 RecordVideoNaturalSize(rotated_size);
1435
1436 gfx::Size old_size = pipeline_metadata_.natural_size;
1437 if (rotated_size == old_size)
alokp5d86e9b2016-05-17 20:20:411438 return;
1439
xjz516ef6d2017-01-07 00:23:061440 pipeline_metadata_.natural_size = rotated_size;
dalecurtis25405562017-04-14 23:35:111441
1442 // Re-create |watch_time_reporter_| if we didn't originally know the video
1443 // size or the previous size was too small for reporting.
1444 if (!watch_time_reporter_->IsSizeLargeEnoughToReportWatchTime())
tguilbert796a40e2016-11-09 01:11:421445 CreateWatchTimeReporter();
dalecurtis25405562017-04-14 23:35:111446
xhwang60802652017-04-19 07:29:581447 if (overlay_enabled_ && surface_manager_)
1448 surface_manager_->NaturalSizeChanged(rotated_size);
1449
Blink Reformat1c4d759e2017-04-09 16:34:541450 client_->SizeChanged();
xjz516ef6d2017-01-07 00:23:061451
xjz15b483f2017-01-12 00:21:361452 if (observer_)
1453 observer_->OnMetadataChanged(pipeline_metadata_);
alokp5d86e9b2016-05-17 20:20:411454}
1455
1456void WebMediaPlayerImpl::OnVideoOpacityChange(bool opaque) {
1457 DCHECK(main_task_runner_->BelongsToCurrentThread());
Blink Reformat1c4d759e2017-04-09 16:34:541458 DCHECK_NE(ready_state_, WebMediaPlayer::kReadyStateHaveNothing);
alokp5d86e9b2016-05-17 20:20:411459
1460 opaque_ = opaque;
1461 // Modify content opaqueness of cc::Layer directly so that
1462 // SetContentsOpaqueIsFixed is ignored.
1463 if (video_weblayer_)
1464 video_weblayer_->layer()->SetContentsOpaque(opaque_);
1465}
1466
avayvodeecec52c2017-02-14 01:25:091467void WebMediaPlayerImpl::OnVideoAverageKeyframeDistanceUpdate() {
1468 UpdateBackgroundVideoOptimizationState();
1469}
1470
sandersd35d2c3f2017-01-14 02:04:421471void WebMediaPlayerImpl::OnFrameHidden() {
sandersd1e49fb62015-12-12 01:18:061472 DCHECK(main_task_runner_->BelongsToCurrentThread());
avayvod39c102402016-11-23 21:43:131473
avayvod65fad272017-02-24 01:00:481474 // Backgrounding a video requires a user gesture to resume playback.
1475 if (IsHidden())
1476 video_locked_when_paused_when_hidden_ = true;
1477
dalecurtis04bdb582016-08-17 22:15:231478 if (watch_time_reporter_)
1479 watch_time_reporter_->OnHidden();
avayvod48a8be52016-08-04 19:52:501480
avayvod65fad272017-02-24 01:00:481481 UpdateBackgroundVideoOptimizationState();
sandersd50a635e2016-04-04 22:50:091482 UpdatePlayState();
dalecurtis8b8505e72016-06-10 21:59:171483
1484 // Schedule suspended playing media to be paused if the user doesn't come back
1485 // to it within some timeout period to avoid any autoplay surprises.
1486 ScheduleIdlePauseTimer();
sandersd1e49fb62015-12-12 01:18:061487}
1488
sandersd35d2c3f2017-01-14 02:04:421489void WebMediaPlayerImpl::OnFrameClosed() {
sandersd1e49fb62015-12-12 01:18:061490 DCHECK(main_task_runner_->BelongsToCurrentThread());
sandersd35d2c3f2017-01-14 02:04:421491 UpdatePlayState();
1492}
1493
1494void WebMediaPlayerImpl::OnFrameShown() {
1495 DCHECK(main_task_runner_->BelongsToCurrentThread());
1496 background_pause_timer_.Stop();
1497
avayvod65fad272017-02-24 01:00:481498 // Foreground videos don't require user gesture to continue playback.
1499 video_locked_when_paused_when_hidden_ = false;
1500
dalecurtis04bdb582016-08-17 22:15:231501 if (watch_time_reporter_)
1502 watch_time_reporter_->OnShown();
1503
avayvodcc273dd2017-01-19 19:35:121504 // Only track the time to the first frame if playing or about to play because
1505 // of being shown and only for videos we would optimize background playback
1506 // for.
1507 if ((!paused_ && IsBackgroundOptimizationCandidate()) ||
1508 paused_when_hidden_) {
dalecurtis1af3c1a2017-04-11 00:53:491509 frame_time_report_cb_.Reset(
1510 base::Bind(&WebMediaPlayerImpl::ReportTimeFromForegroundToFirstFrame,
1511 AsWeakPtr(), base::TimeTicks::Now()));
avayvodcc273dd2017-01-19 19:35:121512 compositor_task_runner_->PostTask(
1513 FROM_HERE,
1514 base::Bind(&VideoFrameCompositor::SetOnNewProcessedFrameCallback,
dalecurtis1af3c1a2017-04-11 00:53:491515 base::Unretained(compositor_),
1516 BindToCurrentLoop(frame_time_report_cb_.callback())));
avayvodcc273dd2017-01-19 19:35:121517 }
avayvodac607d652017-01-06 03:16:431518
avayvod65fad272017-02-24 01:00:481519 EnableVideoTrackIfNeeded();
1520
avayvod2135a642017-01-13 00:17:141521 if (paused_when_hidden_) {
1522 paused_when_hidden_ = false;
1523 OnPlay(); // Calls UpdatePlayState() so return afterwards.
1524 return;
1525 }
1526
sandersd50a635e2016-04-04 22:50:091527 UpdatePlayState();
sandersd1e49fb62015-12-12 01:18:061528}
1529
sandersd35d2c3f2017-01-14 02:04:421530void WebMediaPlayerImpl::OnIdleTimeout() {
dalecurtis0431cbf2016-03-12 01:19:431531 DCHECK(main_task_runner_->BelongsToCurrentThread());
1532
sandersd35d2c3f2017-01-14 02:04:421533 // If we are attempting preroll, clear the stale flag.
1534 if (IsPrerollAttemptNeeded()) {
tguilbert1bb1c782017-01-23 21:15:111535 delegate_->ClearStaleFlag(delegate_id_);
sandersd35d2c3f2017-01-14 02:04:421536 return;
watkd026f792016-11-05 00:28:511537 }
sandersd50a635e2016-04-04 22:50:091538
sandersd35d2c3f2017-01-14 02:04:421539 UpdatePlayState();
dalecurtis0431cbf2016-03-12 01:19:431540}
1541
dalecurtisbb3eaac2016-01-27 21:10:251542void WebMediaPlayerImpl::OnPlay() {
Blink Reformat1c4d759e2017-04-09 16:34:541543 Play();
1544 client_->PlaybackStateChanged();
dalecurtisbb3eaac2016-01-27 21:10:251545}
1546
1547void WebMediaPlayerImpl::OnPause() {
Blink Reformat1c4d759e2017-04-09 16:34:541548 Pause();
1549 client_->PlaybackStateChanged();
dalecurtisbb3eaac2016-01-27 21:10:251550}
1551
1552void WebMediaPlayerImpl::OnVolumeMultiplierUpdate(double multiplier) {
1553 volume_multiplier_ = multiplier;
Blink Reformat1c4d759e2017-04-09 16:34:541554 SetVolume(volume_);
dalecurtisbb3eaac2016-01-27 21:10:251555}
1556
zqzhang8ac49002017-03-16 21:51:351557void WebMediaPlayerImpl::OnBecamePersistentVideo(bool value) {
Blink Reformat1c4d759e2017-04-09 16:34:541558 client_->OnBecamePersistentVideo(value);
zqzhang8ac49002017-03-16 21:51:351559}
1560
watkdee516f2016-02-18 02:22:191561void WebMediaPlayerImpl::ScheduleRestart() {
sandersd50a635e2016-04-04 22:50:091562 // TODO(watk): All restart logic should be moved into PipelineController.
tguilbert350936ff2017-02-24 05:39:271563 if (pipeline_controller_.IsPipelineRunning() &&
1564 !pipeline_controller_.IsPipelineSuspended()) {
watkdee516f2016-02-18 02:22:191565 pending_suspend_resume_cycle_ = true;
sandersd50a635e2016-04-04 22:50:091566 UpdatePlayState();
watkdee516f2016-02-18 02:22:191567 }
1568}
1569
Blink Reformat1c4d759e2017-04-09 16:34:541570void WebMediaPlayerImpl::RequestRemotePlaybackDisabled(bool disabled) {
miu77f914c2016-11-19 23:56:181571 if (observer_)
1572 observer_->OnRemotePlaybackDisabled(disabled);
1573}
1574
hubbed5f36882016-01-15 22:40:371575#if defined(OS_ANDROID) // WMPI_CAST
Blink Reformat1c4d759e2017-04-09 16:34:541576bool WebMediaPlayerImpl::IsRemote() const {
hubbed5f36882016-01-15 22:40:371577 return cast_impl_.isRemote();
1578}
1579
1580void WebMediaPlayerImpl::SetMediaPlayerManager(
1581 RendererMediaPlayerManagerInterface* media_player_manager) {
1582 cast_impl_.SetMediaPlayerManager(media_player_manager);
1583}
1584
Blink Reformat1c4d759e2017-04-09 16:34:541585void WebMediaPlayerImpl::RequestRemotePlayback() {
hubbed5f36882016-01-15 22:40:371586 cast_impl_.requestRemotePlayback();
1587}
1588
Blink Reformat1c4d759e2017-04-09 16:34:541589void WebMediaPlayerImpl::RequestRemotePlaybackControl() {
hubbed5f36882016-01-15 22:40:371590 cast_impl_.requestRemotePlaybackControl();
1591}
1592
Blink Reformat1c4d759e2017-04-09 16:34:541593void WebMediaPlayerImpl::RequestRemotePlaybackStop() {
avayvod8d8c53b2016-11-04 16:10:301594 cast_impl_.requestRemotePlaybackStop();
1595}
1596
hubbed5f36882016-01-15 22:40:371597void WebMediaPlayerImpl::OnRemotePlaybackEnded() {
pkastingf5279482016-07-27 02:18:201598 DVLOG(1) << __func__;
hubbed5f36882016-01-15 22:40:371599 DCHECK(main_task_runner_->BelongsToCurrentThread());
1600
1601 ended_ = true;
Blink Reformat1c4d759e2017-04-09 16:34:541602 client_->TimeChanged();
hubbed5f36882016-01-15 22:40:371603}
1604
1605void WebMediaPlayerImpl::OnDisconnectedFromRemoteDevice(double t) {
sandersd1c0bba02016-03-04 23:14:081606 DoSeek(base::TimeDelta::FromSecondsD(t), false);
hubbed5f36882016-01-15 22:40:371607
hubbed5f36882016-01-15 22:40:371608 // We already told the delegate we're paused when remoting started.
Blink Reformat1c4d759e2017-04-09 16:34:541609 client_->PlaybackStateChanged();
1610 client_->DisconnectedFromRemoteDevice();
sandersd50a635e2016-04-04 22:50:091611
1612 UpdatePlayState();
hubbed5f36882016-01-15 22:40:371613}
1614
1615void WebMediaPlayerImpl::SuspendForRemote() {
sandersd50a635e2016-04-04 22:50:091616 if (pipeline_controller_.IsPipelineSuspended()) {
hubbed5f36882016-01-15 22:40:371617 scoped_refptr<VideoFrame> frame = cast_impl_.GetCastingBanner();
sandersd50a635e2016-04-04 22:50:091618 if (frame)
dalecurtise9c89e92016-05-20 19:38:001619 compositor_->PaintSingleFrame(frame);
hubbed5f36882016-01-15 22:40:371620 }
sandersd50a635e2016-04-04 22:50:091621
1622 UpdatePlayState();
hubbed5f36882016-01-15 22:40:371623}
1624
1625gfx::Size WebMediaPlayerImpl::GetCanvasSize() const {
1626 if (!video_weblayer_)
1627 return pipeline_metadata_.natural_size;
1628
Blink Reformat1c4d759e2017-04-09 16:34:541629 return video_weblayer_->Bounds();
hubbed5f36882016-01-15 22:40:371630}
1631
1632void WebMediaPlayerImpl::SetDeviceScaleFactor(float scale_factor) {
1633 cast_impl_.SetDeviceScaleFactor(scale_factor);
1634}
hubbee4027f92016-05-19 05:18:131635
Blink Reformat1c4d759e2017-04-09 16:34:541636void WebMediaPlayerImpl::SetPoster(const blink::WebURL& poster) {
xjzc102fd82017-01-04 20:13:531637 cast_impl_.setPoster(poster);
xjzc102fd82017-01-04 20:13:531638}
xjz2504c4da2017-04-18 18:50:141639#endif // defined(OS_ANDROID) // WMPI_CAST
xjzc102fd82017-01-04 20:13:531640
[email protected]fee8a902014-06-03 13:43:361641void WebMediaPlayerImpl::DataSourceInitialized(bool success) {
pkastingf5279482016-07-27 02:18:201642 DVLOG(1) << __func__;
acolwellb4034942014-08-28 15:42:431643 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]a9415292012-01-19 19:55:201644
dalecurtisea27a3ed2016-06-24 01:41:301645#if defined(OS_ANDROID)
1646 // We can't play HLS URLs with WebMediaPlayerImpl, so in cases where they are
tguilbert75e2bf62017-04-26 20:13:121647 // encountered, instruct the HTML media element to use the MediaPlayerRenderer
1648 // instead.
dalecurtisea27a3ed2016-06-24 01:41:301649 //
tguilbert75e2bf62017-04-26 20:13:121650 // TODO(tguilbert): Detect the presence of HLS based on demuxing results,
1651 // rather than the URL string. See crbug.com/663503.
1652 if (data_source_) {
dalecurtisea27a3ed2016-06-24 01:41:301653 const GURL url_after_redirects = data_source_->GetUrlAfterRedirects();
qinmin0d9521272016-10-10 20:43:191654 if (MediaCodecUtil::IsHLSURL(url_after_redirects)) {
tguilbert75e2bf62017-04-26 20:13:121655 renderer_factory_selector_->SetUseMediaPlayer(true);
dalecurtisea27a3ed2016-06-24 01:41:301656 }
1657 }
1658#endif
1659
[email protected]d250190da3b2012-07-23 22:57:301660 if (!success) {
Blink Reformat1c4d759e2017-04-09 16:34:541661 SetNetworkState(WebMediaPlayer::kNetworkStateFormatError);
sandersd50a635e2016-04-04 22:50:091662
1663 // Not really necessary, since the pipeline was never started, but it at
1664 // least this makes sure that the error handling code is in sync.
1665 UpdatePlayState();
1666
[email protected]a9415292012-01-19 19:55:201667 return;
1668 }
1669
[email protected]ef8394c2013-08-21 20:26:301670 StartPipeline();
[email protected]a9415292012-01-19 19:55:201671}
1672
[email protected]122f40252012-06-12 05:01:561673void WebMediaPlayerImpl::NotifyDownloading(bool is_downloading) {
hubbeb2d3efd2017-05-05 23:26:381674 DVLOG(1) << __func__ << "(" << is_downloading << ")";
Blink Reformat1c4d759e2017-04-09 16:34:541675 if (!is_downloading && network_state_ == WebMediaPlayer::kNetworkStateLoading)
1676 SetNetworkState(WebMediaPlayer::kNetworkStateIdle);
1677 else if (is_downloading &&
1678 network_state_ == WebMediaPlayer::kNetworkStateIdle)
1679 SetNetworkState(WebMediaPlayer::kNetworkStateLoading);
hubbeb2d3efd2017-05-05 23:26:381680 if (ready_state_ == ReadyState::kReadyStateHaveFutureData && !is_downloading)
1681 SetReadyState(WebMediaPlayer::kReadyStateHaveEnoughData);
[email protected]122f40252012-06-12 05:01:561682 media_log_->AddEvent(
tguilbert350936ff2017-02-24 05:39:271683 media_log_->CreateBooleanEvent(MediaLogEvent::NETWORK_ACTIVITY_SET,
1684 "is_downloading_data", is_downloading));
[email protected]122f40252012-06-12 05:01:561685}
1686
watkf835a792016-06-24 23:24:401687void WebMediaPlayerImpl::OnSurfaceCreated(int surface_id) {
tsunghungee562e92016-07-20 18:03:311688 overlay_surface_id_ = surface_id;
dalecurtis4b632fce22016-11-10 00:52:171689 if (!set_surface_cb_.is_null()) {
1690 // If restart is required, the callback is one-shot only.
1691 if (decoder_requires_restart_for_overlay_)
1692 base::ResetAndReturn(&set_surface_cb_).Run(surface_id);
1693 else
1694 set_surface_cb_.Run(surface_id);
1695 }
watkf835a792016-06-24 23:24:401696}
1697
watkdee516f2016-02-18 02:22:191698void WebMediaPlayerImpl::OnSurfaceRequested(
dalecurtis4b632fce22016-11-10 00:52:171699 bool decoder_requires_restart_for_overlay,
1700 const SurfaceCreatedCB& set_surface_cb) {
watkdee516f2016-02-18 02:22:191701 DCHECK(main_task_runner_->BelongsToCurrentThread());
1702 DCHECK(surface_manager_);
1703
1704 // A null callback indicates that the decoder is going away.
dalecurtis4b632fce22016-11-10 00:52:171705 if (set_surface_cb.is_null()) {
tsunghungee562e92016-07-20 18:03:311706 decoder_requires_restart_for_overlay_ = false;
dalecurtis4b632fce22016-11-10 00:52:171707 set_surface_cb_.Reset();
watkdee516f2016-02-18 02:22:191708 return;
1709 }
1710
dalecurtis4b632fce22016-11-10 00:52:171711 // If we get a surface request it means GpuVideoDecoder is initializing, so
1712 // until we get a null surface request, GVD is the active decoder.
1713 //
1714 // If |decoder_requires_restart_for_overlay| is true, we must restart the
1715 // pipeline for fullscreen transitions. The decoder is unable to switch
1716 // surfaces otherwise. If false, we simply need to tell the decoder about the
1717 // new surface and it will handle things seamlessly.
1718 decoder_requires_restart_for_overlay_ = decoder_requires_restart_for_overlay;
1719 set_surface_cb_ = set_surface_cb;
1720
1721 // If we're waiting for the surface to arrive, OnSurfaceCreated() will be
1722 // called later when it arrives; so do nothing for now.
liberatoe8e3f43d2017-05-01 22:23:111723 if (!overlay_surface_id_)
dalecurtis4b632fce22016-11-10 00:52:171724 return;
1725
liberatoe8e3f43d2017-05-01 22:23:111726 OnSurfaceCreated(*overlay_surface_id_);
watkdee516f2016-02-18 02:22:191727}
1728
dcheng3076abbf2016-04-22 20:42:391729std::unique_ptr<Renderer> WebMediaPlayerImpl::CreateRenderer() {
dcheng37b415b92017-01-27 20:17:431730 DCHECK(main_task_runner_->BelongsToCurrentThread());
1731
tsunghungee562e92016-07-20 18:03:311732 if (force_video_overlays_)
1733 EnableOverlay();
1734
watkdee516f2016-02-18 02:22:191735 RequestSurfaceCB request_surface_cb;
1736#if defined(OS_ANDROID)
dcheng37b415b92017-01-27 20:17:431737 request_surface_cb = BindToCurrentLoop(
1738 base::Bind(&WebMediaPlayerImpl::OnSurfaceRequested, AsWeakPtr()));
watkdee516f2016-02-18 02:22:191739#endif
tguilbert70d2a00a2017-04-25 00:30:441740 return renderer_factory_selector_->GetCurrentFactory()->CreateRenderer(
sandersd1e49fb62015-12-12 01:18:061741 media_task_runner_, worker_task_runner_, audio_source_provider_.get(),
watkdee516f2016-02-18 02:22:191742 compositor_, request_surface_cb);
sandersd1e49fb62015-12-12 01:18:061743}
1744
[email protected]ef8394c2013-08-21 20:26:301745void WebMediaPlayerImpl::StartPipeline() {
acolwellb4034942014-08-28 15:42:431746 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]ddbc6ff2013-04-19 15:28:331747
xhwange8c4181a2014-12-06 08:10:011748 Demuxer::EncryptedMediaInitDataCB encrypted_media_init_data_cb =
dcheng37b415b92017-01-27 20:17:431749 BindToCurrentLoop(base::Bind(
1750 &WebMediaPlayerImpl::OnEncryptedMediaInitData, AsWeakPtr()));
[email protected]2b57e2e2014-05-09 11:07:251751
tguilbert75e2bf62017-04-26 20:13:121752 if (renderer_factory_selector_->GetCurrentFactory()
1753 ->GetRequiredMediaResourceType() == MediaResource::Type::URL) {
1754 if (data_source_)
1755 loaded_url_ = data_source_->GetUrlAfterRedirects();
1756
1757 // MediaPlayerRendererClient factory is the only factory that a
1758 // MediaResource::Type::URL for the moment. This might no longer be true
1759 // when we remove WebMediaPlayerCast.
1760 //
1761 // TODO(tguilbert/avayvod): Update this flag when removing |cast_impl_|.
1762 using_media_player_renderer_ = true;
1763
tguilbert9881bc22016-10-27 03:13:411764 demuxer_.reset(
tguilbert75e2bf62017-04-26 20:13:121765 new MediaUrlDemuxer(media_task_runner_, loaded_url_,
Blink Reformat1c4d759e2017-04-09 16:34:541766 frame_->GetDocument().FirstPartyForCookies()));
tguilbert25a4d112016-10-13 21:56:511767 pipeline_controller_.Start(demuxer_.get(), this, false, false);
1768 return;
1769 }
1770
[email protected]ddbc6ff2013-04-19 15:28:331771 // Figure out which demuxer to use.
Blink Reformat1c4d759e2017-04-09 16:34:541772 if (load_type_ != kLoadTypeMediaSource) {
[email protected]ddbc6ff2013-04-19 15:28:331773 DCHECK(!chunk_demuxer_);
[email protected]f5443ef72013-04-22 04:03:381774 DCHECK(data_source_);
1775
j.isorcef6778e652015-11-16 17:14:251776#if !defined(MEDIA_DISABLE_FFMPEG)
servolk81e01e02016-03-05 03:29:151777 Demuxer::MediaTracksUpdatedCB media_tracks_updated_cb =
dcheng37b415b92017-01-27 20:17:431778 BindToCurrentLoop(base::Bind(
1779 &WebMediaPlayerImpl::OnFFmpegMediaTracksUpdated, AsWeakPtr()));
servolk81e01e02016-03-05 03:29:151780
dalecurtis9cddc0b2017-04-19 21:23:381781 demuxer_.reset(new FFmpegDemuxer(
1782 media_task_runner_, data_source_.get(), encrypted_media_init_data_cb,
1783 media_tracks_updated_cb, media_log_.get()));
j.isorcef6778e652015-11-16 17:14:251784#else
alokp967c902452016-05-06 05:21:371785 OnError(PipelineStatus::DEMUXER_ERROR_COULD_NOT_OPEN);
j.isorcef6778e652015-11-16 17:14:251786 return;
1787#endif
[email protected]ddbc6ff2013-04-19 15:28:331788 } else {
[email protected]f5443ef72013-04-22 04:03:381789 DCHECK(!chunk_demuxer_);
1790 DCHECK(!data_source_);
1791
acolwell9e0840d2014-09-06 19:01:321792 chunk_demuxer_ = new ChunkDemuxer(
dcheng37b415b92017-01-27 20:17:431793 BindToCurrentLoop(
1794 base::Bind(&WebMediaPlayerImpl::OnDemuxerOpened, AsWeakPtr())),
dalecurtis9cddc0b2017-04-19 21:23:381795 encrypted_media_init_data_cb, media_log_.get());
[email protected]f5443ef72013-04-22 04:03:381796 demuxer_.reset(chunk_demuxer_);
servolkf94b4602017-01-31 16:44:271797
1798 if (base::FeatureList::IsEnabled(kMemoryPressureBasedSourceBufferGC)) {
1799 // base::Unretained is safe because |this| owns memory_pressure_listener_.
1800 memory_pressure_listener_ =
1801 base::MakeUnique<base::MemoryPressureListener>(base::Bind(
1802 &WebMediaPlayerImpl::OnMemoryPressure, base::Unretained(this)));
1803 }
[email protected]ddbc6ff2013-04-19 15:28:331804 }
1805
sandersdb5e21462016-03-09 01:49:071806 // TODO(sandersd): FileSystem objects may also be non-static, but due to our
1807 // caching layer such situations are broken already. http://crbug.com/593159
1808 bool is_static = !chunk_demuxer_;
avayvod102cdb62017-01-07 03:11:091809 bool is_streaming = IsStreaming();
sandersdb8eb5f1d2016-11-19 04:04:021810 UMA_HISTOGRAM_BOOLEAN("Media.IsStreaming", is_streaming);
sandersdb5e21462016-03-09 01:49:071811
[email protected]f5443ef72013-04-22 04:03:381812 // ... and we're ready to go!
sandersd1e49fb62015-12-12 01:18:061813 // TODO(sandersd): On Android, defer Start() if the tab is not visible.
sandersdb8eb5f1d2016-11-19 04:04:021814 seeking_ = true;
alokp967c902452016-05-06 05:21:371815 pipeline_controller_.Start(demuxer_.get(), this, is_streaming, is_static);
[email protected]f5443ef72013-04-22 04:03:381816}
1817
1818void WebMediaPlayerImpl::SetNetworkState(WebMediaPlayer::NetworkState state) {
pkastingf5279482016-07-27 02:18:201819 DVLOG(1) << __func__ << "(" << state << ")";
acolwellb4034942014-08-28 15:42:431820 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]f5443ef72013-04-22 04:03:381821 network_state_ = state;
1822 // Always notify to ensure client has the latest value.
Blink Reformat1c4d759e2017-04-09 16:34:541823 client_->NetworkStateChanged();
[email protected]f5443ef72013-04-22 04:03:381824}
1825
1826void WebMediaPlayerImpl::SetReadyState(WebMediaPlayer::ReadyState state) {
pkastingf5279482016-07-27 02:18:201827 DVLOG(1) << __func__ << "(" << state << ")";
acolwellb4034942014-08-28 15:42:431828 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]f5443ef72013-04-22 04:03:381829
Blink Reformat1c4d759e2017-04-09 16:34:541830 if (state == WebMediaPlayer::kReadyStateHaveEnoughData && data_source_ &&
[email protected]fee8a902014-06-03 13:43:361831 data_source_->assume_fully_buffered() &&
Blink Reformat1c4d759e2017-04-09 16:34:541832 network_state_ == WebMediaPlayer::kNetworkStateLoading)
1833 SetNetworkState(WebMediaPlayer::kNetworkStateLoaded);
[email protected]f5443ef72013-04-22 04:03:381834
1835 ready_state_ = state;
sandersd50a635e2016-04-04 22:50:091836 highest_ready_state_ = std::max(highest_ready_state_, ready_state_);
1837
[email protected]f5443ef72013-04-22 04:03:381838 // Always notify to ensure client has the latest value.
Blink Reformat1c4d759e2017-04-09 16:34:541839 client_->ReadyStateChanged();
[email protected]f5443ef72013-04-22 04:03:381840}
1841
Blink Reformat1c4d759e2017-04-09 16:34:541842blink::WebAudioSourceProvider* WebMediaPlayerImpl::GetAudioSourceProvider() {
[email protected]ff875be52013-06-02 23:47:381843 return audio_source_provider_.get();
[email protected]f5443ef72013-04-22 04:03:381844}
1845
tguilbert350936ff2017-02-24 05:39:271846static void GetCurrentFrameAndSignal(VideoFrameCompositor* compositor,
1847 scoped_refptr<VideoFrame>* video_frame_out,
1848 base::WaitableEvent* event) {
[email protected]dd061e12014-05-06 19:21:221849 TRACE_EVENT0("media", "GetCurrentFrameAndSignal");
dalecurtis44ce4de2015-05-11 18:42:071850 *video_frame_out = compositor->GetCurrentFrameAndUpdateIfStale();
[email protected]dd061e12014-05-06 19:21:221851 event->Signal();
1852}
1853
tguilbert350936ff2017-02-24 05:39:271854scoped_refptr<VideoFrame> WebMediaPlayerImpl::GetCurrentFrameFromCompositor() {
xhwang213e50c2016-10-10 23:56:311855 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]dd061e12014-05-06 19:21:221856 TRACE_EVENT0("media", "WebMediaPlayerImpl::GetCurrentFrameFromCompositor");
xhwang213e50c2016-10-10 23:56:311857
1858 // Needed when the |main_task_runner_| and |compositor_task_runner_| are the
1859 // same to avoid deadlock in the Wait() below.
kainino36eeff82017-03-30 00:55:301860 if (compositor_task_runner_->BelongsToCurrentThread()) {
1861 scoped_refptr<VideoFrame> video_frame =
1862 compositor_->GetCurrentFrameAndUpdateIfStale();
1863 if (!video_frame) {
1864 return nullptr;
1865 }
1866 last_uploaded_frame_size_ = video_frame->natural_size();
1867 last_uploaded_frame_timestamp_ = video_frame->timestamp();
1868 return video_frame;
1869 }
[email protected]dd061e12014-05-06 19:21:221870
1871 // Use a posted task and waitable event instead of a lock otherwise
1872 // WebGL/Canvas can see different content than what the compositor is seeing.
acolwell9e0840d2014-09-06 19:01:321873 scoped_refptr<VideoFrame> video_frame;
gab0d77c7cb2016-06-02 00:00:231874 base::WaitableEvent event(base::WaitableEvent::ResetPolicy::AUTOMATIC,
1875 base::WaitableEvent::InitialState::NOT_SIGNALED);
tguilbert350936ff2017-02-24 05:39:271876 compositor_task_runner_->PostTask(
1877 FROM_HERE,
1878 base::Bind(&GetCurrentFrameAndSignal, base::Unretained(compositor_),
1879 &video_frame, &event));
[email protected]dd061e12014-05-06 19:21:221880 event.Wait();
kainino36eeff82017-03-30 00:55:301881
1882 if (!video_frame) {
1883 return nullptr;
1884 }
1885 last_uploaded_frame_size_ = video_frame->natural_size();
1886 last_uploaded_frame_timestamp_ = video_frame->timestamp();
[email protected]dd061e12014-05-06 19:21:221887 return video_frame;
1888}
1889
sandersd50a635e2016-04-04 22:50:091890void WebMediaPlayerImpl::UpdatePlayState() {
xhwang213e50c2016-10-10 23:56:311891 DCHECK(main_task_runner_->BelongsToCurrentThread());
1892
hubbed5f36882016-01-15 22:40:371893#if defined(OS_ANDROID) // WMPI_CAST
Blink Reformat1c4d759e2017-04-09 16:34:541894 bool is_remote = IsRemote();
xjz4e5d4bf32017-02-15 21:26:351895 bool can_auto_suspend = true;
sandersd50a635e2016-04-04 22:50:091896#else
1897 bool is_remote = false;
xjz4e5d4bf32017-02-15 21:26:351898 bool can_auto_suspend = !disable_pipeline_auto_suspend_ && !IsStreaming();
hubbed5f36882016-01-15 22:40:371899#endif
xhwang213e50c2016-10-10 23:56:311900
dalecurtis8b8505e72016-06-10 21:59:171901 bool is_suspended = pipeline_controller_.IsSuspended();
avayvod39c102402016-11-23 21:43:131902 bool is_backgrounded = IsBackgroundedSuspendEnabled() && IsHidden();
sandersdaaff1a652016-11-17 01:47:251903 PlayState state = UpdatePlayState_ComputePlayState(
xjz4e5d4bf32017-02-15 21:26:351904 is_remote, can_auto_suspend, is_suspended, is_backgrounded);
sandersd35d2c3f2017-01-14 02:04:421905 SetDelegateState(state.delegate_state, state.is_idle);
sandersd50a635e2016-04-04 22:50:091906 SetMemoryReportingState(state.is_memory_reporting_enabled);
1907 SetSuspendState(state.is_suspended || pending_suspend_resume_cycle_);
1908}
dalecurtis5bbc487e2016-02-27 04:15:051909
sandersd35d2c3f2017-01-14 02:04:421910void WebMediaPlayerImpl::SetDelegateState(DelegateState new_state,
1911 bool is_idle) {
tguilbert1bb1c782017-01-23 21:15:111912 DCHECK(delegate_);
dalecurtis5bbc487e2016-02-27 04:15:051913
sandersd35d2c3f2017-01-14 02:04:421914 // Prevent duplicate delegate calls.
1915 // TODO(sandersd): Move this deduplication into the delegate itself.
1916 // TODO(sandersd): WebContentsObserverSanityChecker does not allow sending the
1917 // 'playing' IPC more than once in a row, even if the metadata has changed.
1918 // Figure out whether it should.
Blink Reformat1c4d759e2017-04-09 16:34:541919 bool has_audio = HasAudio() && !client_->IsAutoplayingMuted();
sandersd35d2c3f2017-01-14 02:04:421920 if (delegate_state_ == new_state &&
1921 (delegate_state_ != DelegateState::PLAYING ||
1922 delegate_has_audio_ == has_audio)) {
1923 return;
mlamouri910111362016-11-04 11:28:241924 }
sandersd50a635e2016-04-04 22:50:091925 delegate_state_ = new_state;
sandersd35d2c3f2017-01-14 02:04:421926 delegate_has_audio_ = has_audio;
sandersd50a635e2016-04-04 22:50:091927
sandersd35d2c3f2017-01-14 02:04:421928 switch (new_state) {
sandersd50a635e2016-04-04 22:50:091929 case DelegateState::GONE:
1930 delegate_->PlayerGone(delegate_id_);
1931 break;
mlamouri910111362016-11-04 11:28:241932 case DelegateState::PLAYING: {
zqzhang5d8eab72016-08-26 20:34:301933 delegate_->DidPlay(
Blink Reformat1c4d759e2017-04-09 16:34:541934 delegate_id_, HasVideo(), has_audio,
avayvodcc273dd2017-01-19 19:35:121935 media::DurationToMediaContentType(GetPipelineMediaDuration()));
sandersd50a635e2016-04-04 22:50:091936 break;
mlamouri910111362016-11-04 11:28:241937 }
sandersd50a635e2016-04-04 22:50:091938 case DelegateState::PAUSED:
sandersd35d2c3f2017-01-14 02:04:421939 delegate_->DidPause(delegate_id_);
sandersd50a635e2016-04-04 22:50:091940 break;
dalecurtis0f0097a2015-12-01 17:40:471941 }
sandersd35d2c3f2017-01-14 02:04:421942
1943 delegate_->SetIdle(delegate_id_, is_idle);
dalecurtis0f0097a2015-12-01 17:40:471944}
1945
sandersd50a635e2016-04-04 22:50:091946void WebMediaPlayerImpl::SetMemoryReportingState(
1947 bool is_memory_reporting_enabled) {
1948 if (memory_usage_reporting_timer_.IsRunning() ==
1949 is_memory_reporting_enabled) {
hubbed5f36882016-01-15 22:40:371950 return;
sandersd50a635e2016-04-04 22:50:091951 }
sandersd1c0bba02016-03-04 23:14:081952
sandersd50a635e2016-04-04 22:50:091953 if (is_memory_reporting_enabled) {
1954 memory_usage_reporting_timer_.Start(FROM_HERE,
1955 base::TimeDelta::FromSeconds(2), this,
1956 &WebMediaPlayerImpl::ReportMemoryUsage);
1957 } else {
1958 memory_usage_reporting_timer_.Stop();
1959 ReportMemoryUsage();
1960 }
1961}
1962
1963void WebMediaPlayerImpl::SetSuspendState(bool is_suspended) {
xhwang213e50c2016-10-10 23:56:311964 DCHECK(main_task_runner_->BelongsToCurrentThread());
jameswest451a5bb2017-01-27 03:59:391965 if (!suspend_enabled_) {
1966 DCHECK(!pipeline_controller_.IsSuspended());
1967 return;
1968 }
xhwang213e50c2016-10-10 23:56:311969
sandersd50a635e2016-04-04 22:50:091970 // Do not change the state after an error has occurred.
1971 // TODO(sandersd): Update PipelineController to remove the need for this.
1972 if (IsNetworkStateError(network_state_))
sandersd1c0bba02016-03-04 23:14:081973 return;
1974
jameswest451a5bb2017-01-27 03:59:391975 if (is_suspended) {
sandersd35d2c3f2017-01-14 02:04:421976 // If we were not resumed for long enough to satisfy the preroll attempt,
1977 // reset the clock.
1978 if (!preroll_attempt_pending_ && IsPrerollAttemptNeeded()) {
1979 preroll_attempt_pending_ = true;
1980 preroll_attempt_start_time_ = base::TimeTicks();
1981 }
sandersd50a635e2016-04-04 22:50:091982 pipeline_controller_.Suspend();
1983 } else {
sandersd35d2c3f2017-01-14 02:04:421984 // When resuming, start the preroll attempt clock.
1985 if (preroll_attempt_pending_) {
1986 preroll_attempt_pending_ = false;
1987 preroll_attempt_start_time_ = tick_clock_->NowTicks();
1988 }
sandersd50a635e2016-04-04 22:50:091989 pipeline_controller_.Resume();
1990 }
1991}
1992
1993WebMediaPlayerImpl::PlayState
1994WebMediaPlayerImpl::UpdatePlayState_ComputePlayState(bool is_remote,
xjz4e5d4bf32017-02-15 21:26:351995 bool can_auto_suspend,
dalecurtis8b8505e72016-06-10 21:59:171996 bool is_suspended,
sandersd50a635e2016-04-04 22:50:091997 bool is_backgrounded) {
1998 PlayState result;
1999
tguilbert1bb1c782017-01-23 21:15:112000 bool must_suspend = delegate_->IsFrameClosed();
2001 bool is_stale = delegate_->IsStale(delegate_id_);
sandersd35d2c3f2017-01-14 02:04:422002
sandersd50a635e2016-04-04 22:50:092003 // This includes both data source (before pipeline startup) and pipeline
2004 // errors.
2005 bool has_error = IsNetworkStateError(network_state_);
2006
dalecurtiscc8baf72016-10-27 01:49:442007 // After HaveFutureData, Blink will call play() if the state is not paused;
2008 // prior to this point |paused_| is not accurate.
sandersd50a635e2016-04-04 22:50:092009 bool have_future_data =
Blink Reformat1c4d759e2017-04-09 16:34:542010 highest_ready_state_ >= WebMediaPlayer::kReadyStateHaveFutureData;
sandersd50a635e2016-04-04 22:50:092011
avayvod65fad272017-02-24 01:00:482012 // Background suspend is only enabled for paused players.
2013 // In the case of players with audio the session should be kept.
2014 bool background_suspended =
xjz4e5d4bf32017-02-15 21:26:352015 can_auto_suspend && is_backgrounded && paused_ && have_future_data;
sandersd50a635e2016-04-04 22:50:092016
dalecurtiscc8baf72016-10-27 01:49:442017 // Idle suspension is allowed prior to have future data since there exist
2018 // mechanisms to exit the idle state when the player is capable of reaching
2019 // the have future data state; see didLoadingProgress().
2020 //
sandersd50a635e2016-04-04 22:50:092021 // TODO(sandersd): Make the delegate suspend idle players immediately when
2022 // hidden.
sandersdaaff1a652016-11-17 01:47:252023 bool idle_suspended =
xjz4e5d4bf32017-02-15 21:26:352024 can_auto_suspend && is_stale && paused_ && !seeking_ && !overlay_enabled_;
dalecurtise7120dc2016-09-03 02:54:352025
2026 // If we're already suspended, see if we can wait for user interaction. Prior
sandersd35d2c3f2017-01-14 02:04:422027 // to HaveFutureData, we require |is_stale| to remain suspended. |is_stale|
dalecurtise7120dc2016-09-03 02:54:352028 // will be cleared when we receive data which may take us to HaveFutureData.
2029 bool can_stay_suspended =
sandersd35d2c3f2017-01-14 02:04:422030 (is_stale || have_future_data) && is_suspended && paused_ && !seeking_;
sandersd50a635e2016-04-04 22:50:092031
2032 // Combined suspend state.
sandersd35d2c3f2017-01-14 02:04:422033 result.is_suspended = is_remote || must_suspend || idle_suspended ||
avayvod65fad272017-02-24 01:00:482034 background_suspended || can_stay_suspended;
sandersd50a635e2016-04-04 22:50:092035
2036 // We do not treat |playback_rate_| == 0 as paused. For the media session,
2037 // being paused implies displaying a play button, which is incorrect in this
2038 // case. For memory usage reporting, we just use the same definition (but we
2039 // don't have to).
2040 //
2041 // Similarly, we don't consider |ended_| to be paused. Blink will immediately
2042 // call pause() or seek(), so |ended_| should not affect the computation.
2043 // Despite that, |ended_| does result in a separate paused state, to simplfy
2044 // the contract for SetDelegateState().
2045 //
avayvod65fad272017-02-24 01:00:482046 // |has_remote_controls| indicates if the player can be controlled outside the
2047 // page (e.g. via the notification controls or by audio focus events). Idle
sandersd50a635e2016-04-04 22:50:092048 // suspension does not destroy the media session, because we expect that the
avayvod5f34b642017-03-23 03:14:042049 // notification controls (and audio focus) remain. With some exceptions for
2050 // background videos, the player only needs to have audio to have controls
2051 // (requires |have_future_data|).
2052 //
2053 // |alive| indicates if the player should be present (not |GONE|) to the
2054 // delegate, either paused or playing. The following must be true for the
2055 // player:
sandersd50a635e2016-04-04 22:50:092056 // - |have_future_data|, since we need to know whether we are paused to
avayvod65fad272017-02-24 01:00:482057 // correctly configure the session and also because the tracks and
avayvod5f34b642017-03-23 03:14:042058 // duration are passed to DidPlay(),
2059 // - |is_remote| is false as remote playback is not handled by the delegate,
2060 // - |has_error| is false as player should have no errors,
2061 // - |background_suspended| is false, otherwise |has_remote_controls| must
2062 // be true.
sandersd50a635e2016-04-04 22:50:092063 //
avayvod65fad272017-02-24 01:00:482064 // TODO(sandersd): If Blink told us the paused state sooner, we could detect
2065 // if the remote controls are available sooner.
2066
2067 // Background videos with audio don't have remote controls if background
2068 // suspend is enabled and resuming background videos is not (original Android
2069 // behavior).
2070 bool backgrounded_video_has_no_remote_controls =
2071 IsBackgroundedSuspendEnabled() && !IsResumeBackgroundVideosEnabled() &&
Blink Reformat1c4d759e2017-04-09 16:34:542072 is_backgrounded && HasVideo();
sandersd50a635e2016-04-04 22:50:092073 bool can_play = !has_error && !is_remote && have_future_data;
avayvod5f34b642017-03-23 03:14:042074 bool has_remote_controls =
Blink Reformat1c4d759e2017-04-09 16:34:542075 HasAudio() && !backgrounded_video_has_no_remote_controls;
avayvod5f34b642017-03-23 03:14:042076 bool alive = can_play && !must_suspend &&
2077 (!background_suspended || has_remote_controls);
2078 if (!alive) {
sandersd50a635e2016-04-04 22:50:092079 result.delegate_state = DelegateState::GONE;
tguilbert1bb1c782017-01-23 21:15:112080 result.is_idle = delegate_->IsIdle(delegate_id_);
avayvod65fad272017-02-24 01:00:482081 } else if (paused_) {
sandersd35d2c3f2017-01-14 02:04:422082 // TODO(sandersd): Is it possible to have a suspended session, be ended,
2083 // and not be paused? If so we should be in a PLAYING state.
dalecurtise7120dc2016-09-03 02:54:352084 result.delegate_state =
sandersd35d2c3f2017-01-14 02:04:422085 ended_ ? DelegateState::GONE : DelegateState::PAUSED;
2086 result.is_idle = !seeking_;
sandersd50a635e2016-04-04 22:50:092087 } else {
2088 result.delegate_state = DelegateState::PLAYING;
sandersd35d2c3f2017-01-14 02:04:422089 result.is_idle = false;
sandersd50a635e2016-04-04 22:50:092090 }
2091
dalecurtis8b8505e72016-06-10 21:59:172092 // It's not critical if some cases where memory usage can change are missed,
sandersd50a635e2016-04-04 22:50:092093 // since media memory changes are usually gradual.
2094 result.is_memory_reporting_enabled =
sandersd35d2c3f2017-01-14 02:04:422095 can_play && !result.is_suspended && (!paused_ || seeking_);
sandersd50a635e2016-04-04 22:50:092096
2097 return result;
dalecurtis0f0097a2015-12-01 17:40:472098}
2099
dalecurtis83266c72015-10-29 18:43:202100void WebMediaPlayerImpl::ReportMemoryUsage() {
2101 DCHECK(main_task_runner_->BelongsToCurrentThread());
2102
wdzierzanowskifd4cd91c52015-12-02 23:50:202103 // About base::Unretained() usage below: We destroy |demuxer_| on the main
2104 // thread. Before that, however, ~WebMediaPlayerImpl() posts a task to the
2105 // media thread and waits for it to finish. Hence, the GetMemoryUsage() task
2106 // posted here must finish earlier.
2107
2108 if (demuxer_) {
2109 base::PostTaskAndReplyWithResult(
2110 media_task_runner_.get(), FROM_HERE,
2111 base::Bind(&Demuxer::GetMemoryUsage, base::Unretained(demuxer_.get())),
2112 base::Bind(&WebMediaPlayerImpl::FinishMemoryUsageReport, AsWeakPtr()));
2113 } else {
2114 FinishMemoryUsageReport(0);
2115 }
2116}
2117
2118void WebMediaPlayerImpl::FinishMemoryUsageReport(int64_t demuxer_memory_usage) {
2119 DCHECK(main_task_runner_->BelongsToCurrentThread());
2120
avayvodc4bfb0e62017-01-13 01:07:012121 const PipelineStatistics stats = GetPipelineStatistics();
servolk639473e492016-12-15 04:14:202122 const int64_t data_source_memory_usage =
2123 data_source_ ? data_source_->GetMemoryUsage() : 0;
dalecurtisecc76612017-04-19 00:31:202124
2125 // If we have video and no video memory usage, assume the VideoFrameCompositor
2126 // is holding onto the last frame after we've suspended the pipeline; which
2127 // thus reports zero memory usage from the video renderer.
2128 //
2129 // Technically this should use the coded size, but that requires us to hop to
2130 // the compositor to get and byte-perfect accuracy isn't important here.
2131 const int64_t video_memory_usage =
2132 stats.video_memory_usage +
2133 (pipeline_metadata_.has_video && !stats.video_memory_usage
2134 ? VideoFrame::AllocationSize(PIXEL_FORMAT_YV12,
2135 pipeline_metadata_.natural_size)
2136 : 0);
2137
dalecurtis83266c72015-10-29 18:43:202138 const int64_t current_memory_usage =
dalecurtisecc76612017-04-19 00:31:202139 stats.audio_memory_usage + video_memory_usage + data_source_memory_usage +
2140 demuxer_memory_usage;
dalecurtis83266c72015-10-29 18:43:202141
dalecurtisecc76612017-04-19 00:31:202142 DVLOG(2) << "Memory Usage -- Total: " << current_memory_usage
2143 << " Audio: " << stats.audio_memory_usage
2144 << ", Video: " << video_memory_usage
servolk639473e492016-12-15 04:14:202145 << ", DataSource: " << data_source_memory_usage
wdzierzanowskifd4cd91c52015-12-02 23:50:202146 << ", Demuxer: " << demuxer_memory_usage;
dalecurtis83266c72015-10-29 18:43:202147
2148 const int64_t delta = current_memory_usage - last_reported_memory_usage_;
2149 last_reported_memory_usage_ = current_memory_usage;
2150 adjust_allocated_memory_cb_.Run(delta);
servolk639473e492016-12-15 04:14:202151
Blink Reformat1c4d759e2017-04-09 16:34:542152 if (HasAudio()) {
servolk639473e492016-12-15 04:14:202153 UMA_HISTOGRAM_MEMORY_KB("Media.WebMediaPlayerImpl.Memory.Audio",
2154 stats.audio_memory_usage / 1024);
2155 }
Blink Reformat1c4d759e2017-04-09 16:34:542156 if (HasVideo()) {
servolk639473e492016-12-15 04:14:202157 UMA_HISTOGRAM_MEMORY_KB("Media.WebMediaPlayerImpl.Memory.Video",
dalecurtisecc76612017-04-19 00:31:202158 video_memory_usage / 1024);
servolk639473e492016-12-15 04:14:202159 }
2160 if (data_source_) {
2161 UMA_HISTOGRAM_MEMORY_KB("Media.WebMediaPlayerImpl.Memory.DataSource",
2162 data_source_memory_usage / 1024);
2163 }
2164 if (demuxer_) {
2165 UMA_HISTOGRAM_MEMORY_KB("Media.WebMediaPlayerImpl.Memory.Demuxer",
2166 demuxer_memory_usage / 1024);
2167 }
dalecurtis83266c72015-10-29 18:43:202168}
2169
dalecurtis8b8505e72016-06-10 21:59:172170void WebMediaPlayerImpl::ScheduleIdlePauseTimer() {
avayvod65fad272017-02-24 01:00:482171 // Only schedule the pause timer if we're not paused or paused but going to
avayvod52efd282017-03-07 21:13:042172 // resume when foregrounded, and are suspended and have audio.
2173 if ((paused_ && !paused_when_hidden_) ||
Blink Reformat1c4d759e2017-04-09 16:34:542174 !pipeline_controller_.IsSuspended() || !HasAudio()) {
dalecurtis8b8505e72016-06-10 21:59:172175 return;
avayvod52efd282017-03-07 21:13:042176 }
dalecurtis8b8505e72016-06-10 21:59:172177
2178#if defined(OS_ANDROID)
2179 // Remote players will be suspended and locally paused.
Blink Reformat1c4d759e2017-04-09 16:34:542180 if (IsRemote())
dalecurtis8b8505e72016-06-10 21:59:172181 return;
2182#endif
2183
2184 // Idle timeout chosen arbitrarily.
2185 background_pause_timer_.Start(FROM_HERE, base::TimeDelta::FromSeconds(5),
2186 this, &WebMediaPlayerImpl::OnPause);
2187}
2188
dalecurtis04bdb582016-08-17 22:15:232189void WebMediaPlayerImpl::CreateWatchTimeReporter() {
2190 // Create the watch time reporter and synchronize its initial state.
shaktisahu24189c12017-03-11 17:42:552191 watch_time_reporter_.reset(
Blink Reformat1c4d759e2017-04-09 16:34:542192 new WatchTimeReporter(HasAudio(), HasVideo(), !!chunk_demuxer_,
shaktisahu24189c12017-03-11 17:42:552193 is_encrypted_, embedded_media_experience_enabled_,
dalecurtis9cddc0b2017-04-19 21:23:382194 media_log_.get(), pipeline_metadata_.natural_size,
shaktisahu24189c12017-03-11 17:42:552195 base::Bind(&GetCurrentTimeInternal, this)));
dalecurtis04bdb582016-08-17 22:15:232196 watch_time_reporter_->OnVolumeChange(volume_);
tguilbert1bb1c782017-01-23 21:15:112197 if (delegate_->IsFrameHidden())
dalecurtis04bdb582016-08-17 22:15:232198 watch_time_reporter_->OnHidden();
2199 else
2200 watch_time_reporter_->OnShown();
2201}
2202
avayvod39c102402016-11-23 21:43:132203bool WebMediaPlayerImpl::IsHidden() const {
2204 DCHECK(main_task_runner_->BelongsToCurrentThread());
2205
tguilbert1bb1c782017-01-23 21:15:112206 return delegate_->IsFrameHidden() && !delegate_->IsFrameClosed();
avayvod39c102402016-11-23 21:43:132207}
2208
avayvod102cdb62017-01-07 03:11:092209bool WebMediaPlayerImpl::IsStreaming() const {
2210 return data_source_ && data_source_->IsStreaming();
2211}
2212
liberato2fd111be2017-01-04 00:25:062213bool WebMediaPlayerImpl::DoesOverlaySupportMetadata() const {
2214 return pipeline_metadata_.video_rotation == VIDEO_ROTATION_0;
2215}
2216
xjzaf29d4182016-12-16 01:52:322217void WebMediaPlayerImpl::ActivateViewportIntersectionMonitoring(bool activate) {
2218 DCHECK(main_task_runner_->BelongsToCurrentThread());
2219
Blink Reformat1c4d759e2017-04-09 16:34:542220 client_->ActivateViewportIntersectionMonitoring(activate);
xjzaf29d4182016-12-16 01:52:322221}
2222
avayvodcc273dd2017-01-19 19:35:122223bool WebMediaPlayerImpl::ShouldPauseVideoWhenHidden() const {
avayvod65fad272017-02-24 01:00:482224 // If suspending background video, pause any video that's not remoted or
2225 // not unlocked to play in the background.
2226 if (IsBackgroundedSuspendEnabled()) {
Blink Reformat1c4d759e2017-04-09 16:34:542227 if (!HasVideo())
avayvod65fad272017-02-24 01:00:482228 return false;
2229
2230#if defined(OS_ANDROID)
Blink Reformat1c4d759e2017-04-09 16:34:542231 if (IsRemote())
avayvod65fad272017-02-24 01:00:482232 return false;
avayvodcc273dd2017-01-19 19:35:122233#endif
avayvodeb9098d2017-01-07 00:33:032234
Blink Reformat1c4d759e2017-04-09 16:34:542235 return !HasAudio() || (IsResumeBackgroundVideosEnabled() &&
2236 video_locked_when_paused_when_hidden_);
avayvod65fad272017-02-24 01:00:482237 }
2238
2239 // Otherwise only pause if the optimization is on and it's a video-only
2240 // optimization candidate.
avayvod01201332017-04-14 00:27:152241 return IsBackgroundVideoPauseOptimizationEnabled() && !HasAudio() &&
avayvod65fad272017-02-24 01:00:482242 IsBackgroundOptimizationCandidate();
avayvodeb9098d2017-01-07 00:33:032243}
2244
avayvod2135a642017-01-13 00:17:142245bool WebMediaPlayerImpl::ShouldDisableVideoWhenHidden() const {
avayvodcc273dd2017-01-19 19:35:122246 // This optimization is behind the flag on all platforms.
2247 if (!IsBackgroundVideoTrackOptimizationEnabled())
avayvodc4bfb0e62017-01-13 01:07:012248 return false;
avayvodc4bfb0e62017-01-13 01:07:012249
avayvodcc273dd2017-01-19 19:35:122250 // Disable video track only for players with audio that match the criteria for
2251 // being optimized.
Blink Reformat1c4d759e2017-04-09 16:34:542252 return HasAudio() && IsBackgroundOptimizationCandidate();
avayvodcc273dd2017-01-19 19:35:122253}
2254
2255bool WebMediaPlayerImpl::IsBackgroundOptimizationCandidate() const {
2256 DCHECK(main_task_runner_->BelongsToCurrentThread());
2257
avayvodcc273dd2017-01-19 19:35:122258#if defined(OS_ANDROID) // WMPI_CAST
avayvodac1a8522017-01-20 19:02:502259 // Don't optimize players being Cast.
Blink Reformat1c4d759e2017-04-09 16:34:542260 if (IsRemote())
avayvodcc273dd2017-01-19 19:35:122261 return false;
avayvodac1a8522017-01-20 19:02:502262
2263 // Video-only players are always optimized (paused) on Android.
2264 // Don't check the keyframe distance and duration.
Blink Reformat1c4d759e2017-04-09 16:34:542265 if (!HasAudio() && HasVideo())
avayvodac1a8522017-01-20 19:02:502266 return true;
avayvodcc273dd2017-01-19 19:35:122267#endif // defined(OS_ANDROID)
2268
2269 // Don't optimize audio-only or streaming players.
Blink Reformat1c4d759e2017-04-09 16:34:542270 if (!HasVideo() || IsStreaming())
avayvodcc273dd2017-01-19 19:35:122271 return false;
2272
2273 // Videos shorter than the maximum allowed keyframe distance can be optimized.
2274 base::TimeDelta duration = GetPipelineMediaDuration();
avayvode85ec422017-04-14 00:11:332275 base::TimeDelta max_keyframe_distance =
2276 (load_type_ == kLoadTypeMediaSource)
2277 ? max_keyframe_distance_to_disable_background_video_mse_
2278 : max_keyframe_distance_to_disable_background_video_;
2279 if (duration < max_keyframe_distance)
avayvodcc273dd2017-01-19 19:35:122280 return true;
2281
2282 // Otherwise, only optimize videos with shorter average keyframe distance.
avayvodc4bfb0e62017-01-13 01:07:012283 PipelineStatistics stats = GetPipelineStatistics();
avayvode85ec422017-04-14 00:11:332284 return stats.video_keyframe_distance_average < max_keyframe_distance;
avayvod2135a642017-01-13 00:17:142285}
2286
avayvod56e1f3942017-01-21 02:06:312287void WebMediaPlayerImpl::UpdateBackgroundVideoOptimizationState() {
2288 if (IsHidden()) {
2289 if (ShouldPauseVideoWhenHidden())
2290 PauseVideoIfNeeded();
2291 else
2292 DisableVideoTrackIfNeeded();
2293 } else {
2294 EnableVideoTrackIfNeeded();
2295 }
2296}
2297
2298void WebMediaPlayerImpl::PauseVideoIfNeeded() {
2299 DCHECK(IsHidden());
2300
2301 // Don't pause video while the pipeline is stopped, resuming or seeking.
2302 // Also if the video is paused already.
tguilbert350936ff2017-02-24 05:39:272303 if (!pipeline_controller_.IsPipelineRunning() || is_pipeline_resuming_ ||
2304 seeking_ || paused_)
avayvod56e1f3942017-01-21 02:06:312305 return;
2306
2307 // OnPause() will set |paused_when_hidden_| to false and call
2308 // UpdatePlayState(), so set the flag to true after and then return.
2309 OnPause();
2310 paused_when_hidden_ = true;
2311}
2312
avayvod2135a642017-01-13 00:17:142313void WebMediaPlayerImpl::EnableVideoTrackIfNeeded() {
avayvod56e1f3942017-01-21 02:06:312314 // Don't change video track while the pipeline is stopped, resuming or
2315 // seeking.
tguilbert350936ff2017-02-24 05:39:272316 if (!pipeline_controller_.IsPipelineRunning() || is_pipeline_resuming_ ||
2317 seeking_)
avayvod2135a642017-01-13 00:17:142318 return;
2319
2320 if (video_track_disabled_) {
2321 video_track_disabled_ = false;
Blink Reformat1c4d759e2017-04-09 16:34:542322 if (client_->HasSelectedVideoTrack()) {
2323 WebMediaPlayer::TrackId trackId = client_->GetSelectedVideoTrackId();
2324 SelectedVideoTrackChanged(&trackId);
avayvod2135a642017-01-13 00:17:142325 }
2326 }
2327}
2328
2329void WebMediaPlayerImpl::DisableVideoTrackIfNeeded() {
2330 DCHECK(IsHidden());
2331
2332 // Don't change video track while the pipeline is resuming or seeking.
2333 if (is_pipeline_resuming_ || seeking_)
2334 return;
2335
2336 if (!video_track_disabled_ && ShouldDisableVideoWhenHidden()) {
2337 video_track_disabled_ = true;
Blink Reformat1c4d759e2017-04-09 16:34:542338 SelectedVideoTrackChanged(nullptr);
avayvod2135a642017-01-13 00:17:142339 }
2340}
2341
avayvodc4bfb0e62017-01-13 01:07:012342void WebMediaPlayerImpl::SetPipelineStatisticsForTest(
2343 const PipelineStatistics& stats) {
2344 pipeline_statistics_for_test_ = base::make_optional(stats);
2345}
2346
2347PipelineStatistics WebMediaPlayerImpl::GetPipelineStatistics() const {
2348 DCHECK(main_task_runner_->BelongsToCurrentThread());
2349
tguilbert350936ff2017-02-24 05:39:272350 return pipeline_statistics_for_test_.value_or(
2351 pipeline_controller_.GetStatistics());
avayvodc4bfb0e62017-01-13 01:07:012352}
2353
avayvodcc273dd2017-01-19 19:35:122354void WebMediaPlayerImpl::SetPipelineMediaDurationForTest(
2355 base::TimeDelta duration) {
2356 pipeline_media_duration_for_test_ = base::make_optional(duration);
2357}
2358
2359base::TimeDelta WebMediaPlayerImpl::GetPipelineMediaDuration() const {
2360 DCHECK(main_task_runner_->BelongsToCurrentThread());
2361
2362 return pipeline_media_duration_for_test_.value_or(
tguilbert350936ff2017-02-24 05:39:272363 pipeline_controller_.GetMediaDuration());
avayvodcc273dd2017-01-19 19:35:122364}
2365
2366void WebMediaPlayerImpl::ReportTimeFromForegroundToFirstFrame(
2367 base::TimeTicks foreground_time,
2368 base::TimeTicks new_frame_time) {
2369 base::TimeDelta time_to_first_frame = new_frame_time - foreground_time;
Blink Reformat1c4d759e2017-04-09 16:34:542370 if (HasAudio()) {
avayvodcc273dd2017-01-19 19:35:122371 UMA_HISTOGRAM_TIMES(
2372 "Media.Video.TimeFromForegroundToFirstFrame.DisableTrack",
2373 time_to_first_frame);
2374 } else {
2375 UMA_HISTOGRAM_TIMES("Media.Video.TimeFromForegroundToFirstFrame.Paused",
2376 time_to_first_frame);
2377 }
2378}
xjzdf9b67e2017-04-13 23:28:252379void WebMediaPlayerImpl::SwitchRenderer(bool is_rendered_remotely) {
xjz4e5d4bf32017-02-15 21:26:352380 DCHECK(main_task_runner_->BelongsToCurrentThread());
xjzdf9b67e2017-04-13 23:28:252381 disable_pipeline_auto_suspend_ = is_rendered_remotely;
xjz4e5d4bf32017-02-15 21:26:352382 ScheduleRestart();
xjzdf9b67e2017-04-13 23:28:252383 if (client_) {
2384 if (is_rendered_remotely)
2385 client_->MediaRemotingStarted();
2386 else
2387 client_->MediaRemotingStopped();
2388 }
xjz4e5d4bf32017-02-15 21:26:352389}
2390
dalecurtis4f6d14d2017-02-22 17:42:222391void WebMediaPlayerImpl::RecordUnderflowDuration(base::TimeDelta duration) {
2392 DCHECK(data_source_ || chunk_demuxer_);
2393 if (data_source_)
2394 UMA_HISTOGRAM_TIMES("Media.UnderflowDuration", duration);
2395 else
2396 UMA_HISTOGRAM_TIMES("Media.UnderflowDuration.MSE", duration);
2397}
2398
xhwang60802652017-04-19 07:29:582399#define UMA_HISTOGRAM_VIDEO_HEIGHT(name, sample) \
2400 UMA_HISTOGRAM_CUSTOM_COUNTS(name, sample, 100, 10000, 50)
2401
2402void WebMediaPlayerImpl::RecordVideoNaturalSize(const gfx::Size& natural_size) {
2403 // Always report video natural size to MediaLog.
2404 media_log_->AddEvent(media_log_->CreateVideoSizeSetEvent(
2405 natural_size.width(), natural_size.height()));
2406
2407 if (initial_video_height_recorded_)
2408 return;
2409
2410 initial_video_height_recorded_ = true;
2411
2412 int height = natural_size.height();
2413
2414 if (load_type_ == kLoadTypeURL)
2415 UMA_HISTOGRAM_VIDEO_HEIGHT("Media.VideoHeight.Initial.SRC", height);
2416 else if (load_type_ == kLoadTypeMediaSource)
2417 UMA_HISTOGRAM_VIDEO_HEIGHT("Media.VideoHeight.Initial.MSE", height);
2418
2419 if (is_encrypted_)
2420 UMA_HISTOGRAM_VIDEO_HEIGHT("Media.VideoHeight.Initial.EME", height);
2421
2422 UMA_HISTOGRAM_VIDEO_HEIGHT("Media.VideoHeight.Initial.All", height);
2423}
2424
2425#undef UMA_HISTOGRAM_VIDEO_HEIGHT
2426
hubbeb2d3efd2017-05-05 23:26:382427void WebMediaPlayerImpl::SetTickClockForTest(base::TickClock* tick_clock) {
2428 tick_clock_.reset(tick_clock);
2429 buffered_data_source_host_.SetTickClockForTest(tick_clock);
2430}
2431
acolwell9e0840d2014-09-06 19:01:322432} // namespace media