blob: 366ada9eddc7407a641a1b1dc0c809181f4426dc [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
sandersd50a635e2016-04-04 22:50:09133bool IsNetworkStateError(blink::WebMediaPlayer::NetworkState state) {
Blink Reformat1c4d759e2017-04-09 16:34:54134 bool result = state == blink::WebMediaPlayer::kNetworkStateFormatError ||
135 state == blink::WebMediaPlayer::kNetworkStateNetworkError ||
136 state == blink::WebMediaPlayer::kNetworkStateDecodeError;
137 DCHECK_EQ(state > blink::WebMediaPlayer::kNetworkStateLoaded, result);
sandersd50a635e2016-04-04 22:50:09138 return result;
139}
140
sandersd2c478422016-08-02 01:19:25141gfx::Size GetRotatedVideoSize(VideoRotation rotation, gfx::Size natural_size) {
142 if (rotation == VIDEO_ROTATION_90 || rotation == VIDEO_ROTATION_270)
143 return gfx::Size(natural_size.height(), natural_size.width());
144 return natural_size;
145}
146
dalecurtis04bdb582016-08-17 22:15:23147base::TimeDelta GetCurrentTimeInternal(WebMediaPlayerImpl* p_this) {
tguilbert350936ff2017-02-24 05:39:27148 // We wrap currentTime() instead of using pipeline_controller_.GetMediaTime()
149 // since there are a variety of cases in which that time is not accurate;
150 // e.g., while remoting and during a pause or seek.
Blink Reformat1c4d759e2017-04-09 16:34:54151 return base::TimeDelta::FromSecondsD(p_this->CurrentTime());
dalecurtis04bdb582016-08-17 22:15:23152}
153
sandersd35d2c3f2017-01-14 02:04:42154// How much time must have elapsed since loading last progressed before we
155// assume that the decoder will have had time to complete preroll.
156constexpr base::TimeDelta kPrerollAttemptTimeout =
watkd026f792016-11-05 00:28:51157 base::TimeDelta::FromSeconds(3);
158
[email protected]8931c41a2009-07-07 17:31:49159} // namespace
160
[email protected]6683e1b2014-04-10 01:45:38161class BufferedDataSourceHostImpl;
162
Blink Reformat1c4d759e2017-04-09 16:34:54163STATIC_ASSERT_ENUM(WebMediaPlayer::kCORSModeUnspecified,
danakj365175c2016-02-06 00:37:37164 UrlData::CORS_UNSPECIFIED);
Blink Reformat1c4d759e2017-04-09 16:34:54165STATIC_ASSERT_ENUM(WebMediaPlayer::kCORSModeAnonymous, UrlData::CORS_ANONYMOUS);
166STATIC_ASSERT_ENUM(WebMediaPlayer::kCORSModeUseCredentials,
danakj365175c2016-02-06 00:37:37167 UrlData::CORS_USE_CREDENTIALS);
[email protected]a5a01102012-06-06 17:01:24168
[email protected]5b5bb9d2010-10-22 19:57:36169WebMediaPlayerImpl::WebMediaPlayerImpl(
[email protected]35b2a972014-04-04 15:50:22170 blink::WebLocalFrame* frame,
[email protected]180ef242013-11-07 06:50:46171 blink::WebMediaPlayerClient* client,
srirama.m26f864d02015-07-14 05:21:46172 blink::WebMediaPlayerEncryptedMediaClient* encrypted_client,
tguilbert1bb1c782017-01-23 21:15:11173 WebMediaPlayerDelegate* delegate,
dcheng3076abbf2016-04-22 20:42:39174 std::unique_ptr<RendererFactory> renderer_factory,
hubbe5f0ad43b2015-12-14 20:57:26175 linked_ptr<UrlIndex> url_index,
[email protected]e82b2bd2013-01-02 17:47:57176 const WebMediaPlayerParams& params)
[email protected]f6af7592014-02-28 10:09:11177 : frame_(frame),
sandersd50a635e2016-04-04 22:50:09178 delegate_state_(DelegateState::GONE),
sandersd35d2c3f2017-01-14 02:04:42179 delegate_has_audio_(false),
Blink Reformat1c4d759e2017-04-09 16:34:54180 network_state_(WebMediaPlayer::kNetworkStateEmpty),
181 ready_state_(WebMediaPlayer::kReadyStateHaveNothing),
182 highest_ready_state_(WebMediaPlayer::kReadyStateHaveNothing),
dalecurtisb6e052f52016-08-25 00:35:55183 preload_(MultibufferDataSource::AUTO),
Blink Reformat1c4d759e2017-04-09 16:34:54184 main_task_runner_(frame->LoadingTaskRunner()),
acolwell755d12d2014-08-30 01:09:19185 media_task_runner_(params.media_task_runner()),
dcastagna617d086b2015-08-20 01:39:30186 worker_task_runner_(params.worker_task_runner()),
acolwell755d12d2014-08-30 01:09:19187 media_log_(params.media_log()),
sandersd1c0bba02016-03-04 23:14:08188 pipeline_controller_(
tguilbert350936ff2017-02-24 05:39:27189 base::MakeUnique<PipelineImpl>(media_task_runner_, media_log_.get()),
sandersd1c0bba02016-03-04 23:14:08190 base::Bind(&WebMediaPlayerImpl::CreateRenderer,
191 base::Unretained(this)),
192 base::Bind(&WebMediaPlayerImpl::OnPipelineSeeked, AsWeakPtr()),
193 base::Bind(&WebMediaPlayerImpl::OnPipelineSuspended, AsWeakPtr()),
avayvod2135a642017-01-13 00:17:14194 base::Bind(&WebMediaPlayerImpl::OnBeforePipelineResume, AsWeakPtr()),
195 base::Bind(&WebMediaPlayerImpl::OnPipelineResumed, AsWeakPtr()),
alokp967c902452016-05-06 05:21:37196 base::Bind(&WebMediaPlayerImpl::OnError, AsWeakPtr())),
Blink Reformat1c4d759e2017-04-09 16:34:54197 load_type_(kLoadTypeURL),
[email protected]75e145a2014-04-15 17:44:32198 opaque_(false),
wolenetz1b2ae7d2015-06-10 00:44:21199 playback_rate_(0.0),
[email protected]49480902009-07-14 20:23:43200 paused_(true),
avayvodeb9098d2017-01-07 00:33:03201 paused_when_hidden_(false),
[email protected]b3766a22010-12-22 17:34:13202 seeking_(false),
watkdee516f2016-02-18 02:22:19203 pending_suspend_resume_cycle_(false),
scherkusd2c745b2014-09-04 05:03:40204 ended_(false),
yoichio863bebf2016-03-04 07:56:58205 should_notify_time_changed_(false),
tsunghungee562e92016-07-20 18:03:31206 overlay_enabled_(false),
207 decoder_requires_restart_for_overlay_(false),
[email protected]5badb082010-06-11 17:40:15208 client_(client),
srirama.m26f864d02015-07-14 05:21:46209 encrypted_client_(encrypted_client),
[email protected]baff4512011-10-19 18:21:07210 delegate_(delegate),
dalecurtisbb3eaac2016-01-27 21:10:25211 delegate_id_(0),
[email protected]d726eddc2013-07-02 22:25:55212 defer_load_cb_(params.defer_load_cb()),
dongseong.hwang0c4e9d82015-01-08 20:11:13213 context_3d_cb_(params.context_3d_cb()),
dalecurtis83266c72015-10-29 18:43:20214 adjust_allocated_memory_cb_(params.adjust_allocated_memory_cb()),
215 last_reported_memory_usage_(0),
[email protected]132dd57c2012-08-10 23:24:34216 supports_save_(true),
[email protected]f5443ef72013-04-22 04:03:38217 chunk_demuxer_(NULL),
hubbe5f0ad43b2015-12-14 20:57:26218 url_index_(url_index),
Bartosz Fabianowski85a823812015-04-16 10:27:51219 // Threaded compositing isn't enabled universally yet.
fdoraydb3ef7d2016-06-09 15:42:38220 compositor_task_runner_(params.compositor_task_runner()
221 ? params.compositor_task_runner()
222 : base::ThreadTaskRunnerHandle::Get()),
alokp5d86e9b2016-05-17 20:20:41223 compositor_(new VideoFrameCompositor(compositor_task_runner_)),
hubbed5f36882016-01-15 22:40:37224#if defined(OS_ANDROID) // WMPI_CAST
dalecurtisbb3eaac2016-01-27 21:10:25225 cast_impl_(this, client_, params.context_3d_cb()),
hubbed5f36882016-01-15 22:40:37226#endif
dalecurtisbb3eaac2016-01-27 21:10:25227 volume_(1.0),
228 volume_multiplier_(1.0),
watkdee516f2016-02-18 02:22:19229 renderer_factory_(std::move(renderer_factory)),
dalecurtis2ff781da2016-03-03 01:52:13230 surface_manager_(params.surface_manager()),
tsunghungee562e92016-07-20 18:03:31231 overlay_surface_id_(SurfaceManager::kNoSurfaceID),
dalecurtis7f366b2242016-04-13 01:16:17232 suppress_destruction_errors_(false),
jameswest451a5bb2017-01-27 03:59:39233 suspend_enabled_(params.allow_suspend()),
tguilbert25a4d112016-10-13 21:56:51234 use_fallback_path_(false),
dalecurtis9d638a12016-08-30 06:20:55235 is_encrypted_(false),
sandersd35d2c3f2017-01-14 02:04:42236 preroll_attempt_pending_(false),
avayvod590011e32017-01-20 02:01:00237 observer_(params.media_observer()),
238 max_keyframe_distance_to_disable_background_video_(
servolkf94b4602017-01-31 16:44:27239 params.max_keyframe_distance_to_disable_background_video()),
240 enable_instant_source_buffer_gc_(
shaktisahu24189c12017-03-11 17:42:55241 params.enable_instant_source_buffer_gc()),
242 embedded_media_experience_enabled_(
243 params.embedded_media_experience_enabled()) {
xhwang51139732017-02-24 19:36:08244 DVLOG(1) << __func__;
dalecurtis83266c72015-10-29 18:43:20245 DCHECK(!adjust_allocated_memory_cb_.is_null());
xhwang59d4175a2016-01-14 03:19:30246 DCHECK(renderer_factory_);
servolkef1e5ef2016-03-25 04:55:26247 DCHECK(client_);
tguilbert1bb1c782017-01-23 21:15:11248 DCHECK(delegate_);
dalecurtis83266c72015-10-29 18:43:20249
watkd026f792016-11-05 00:28:51250 tick_clock_.reset(new base::DefaultTickClock());
251
tsunghungee562e92016-07-20 18:03:31252 force_video_overlays_ = base::CommandLine::ForCurrentProcess()->HasSwitch(
253 switches::kForceVideoOverlays);
254
ampea73f792017-01-19 04:05:39255 enable_fullscreen_video_overlays_ =
256 base::FeatureList::IsEnabled(media::kOverlayFullscreenVideo);
257
tguilbert1bb1c782017-01-23 21:15:11258 delegate_id_ = delegate_->AddObserver(this);
259 delegate_->SetIdle(delegate_id_, true);
sandersd1e49fb62015-12-12 01:18:06260
[email protected]c93eb0a62011-08-09 22:47:24261 media_log_->AddEvent(
acolwell9e0840d2014-09-06 19:01:32262 media_log_->CreateEvent(MediaLogEvent::WEBMEDIAPLAYER_CREATED));
[email protected]4e6be3f2009-05-07 02:24:44263
jrummelle616ee92016-10-08 02:15:44264 if (params.initial_cdm())
265 SetCdm(params.initial_cdm());
xhwang0ad11e512014-11-25 23:43:09266
xhwangf94a634d2014-10-22 22:07:27267 // TODO(xhwang): When we use an external Renderer, many methods won't work,
xhwang6fa356202014-12-11 00:44:12268 // e.g. GetCurrentFrameFromCompositor(). See http://crbug.com/434861
olkae4ba2ed82016-12-06 16:34:51269 audio_source_provider_ =
270 new WebAudioSourceProviderImpl(params.audio_renderer_sink(), media_log_);
xjz4e5d4bf32017-02-15 21:26:35271
272 if (observer_)
273 observer_->SetClient(this);
[email protected]ec9212f2008-12-18 21:40:36274}
275
[email protected]4e6be3f2009-05-07 02:24:44276WebMediaPlayerImpl::~WebMediaPlayerImpl() {
xhwang51139732017-02-24 19:36:08277 DVLOG(1) << __func__;
acolwellb4034942014-08-28 15:42:43278 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]d43ed912009-02-03 04:52:53279
xhwang51139732017-02-24 19:36:08280 if (set_cdm_result_) {
281 DVLOG(2) << "Resolve pending SetCdm() when media player is destroyed.";
Blink Reformat1c4d759e2017-04-09 16:34:54282 set_cdm_result_->Complete();
xhwang51139732017-02-24 19:36:08283 set_cdm_result_.reset();
284 }
285
alokp1116967f2016-06-11 17:30:56286 suppress_destruction_errors_ = true;
tguilbert1bb1c782017-01-23 21:15:11287
288 delegate_->PlayerGone(delegate_id_);
289 delegate_->RemoveObserver(delegate_id_);
[email protected]baff4512011-10-19 18:21:07290
dalecurtis04bdb582016-08-17 22:15:23291 // Finalize any watch time metrics before destroying the pipeline.
292 watch_time_reporter_.reset();
293
tguilbert350936ff2017-02-24 05:39:27294 // The underlying Pipeline must be stopped before it is destroyed.
295 pipeline_controller_.Stop();
[email protected]f6af7592014-02-28 10:09:11296
dalecurtis83266c72015-10-29 18:43:20297 if (last_reported_memory_usage_)
298 adjust_allocated_memory_cb_.Run(-last_reported_memory_usage_);
299
dalecurtise1edb312016-06-22 02:33:21300 // Destruct compositor resources in the proper order.
Blink Reformat1c4d759e2017-04-09 16:34:54301 client_->SetWebLayer(nullptr);
dalecurtise1edb312016-06-22 02:33:21302 if (video_weblayer_)
303 static_cast<cc::VideoLayer*>(video_weblayer_->layer())->StopUsingProvider();
[email protected]dd061e12014-05-06 19:21:22304 compositor_task_runner_->DeleteSoon(FROM_HERE, compositor_);
xhwangea8bb3562015-06-08 21:18:37305
306 media_log_->AddEvent(
307 media_log_->CreateEvent(MediaLogEvent::WEBMEDIAPLAYER_DESTROYED));
[email protected]ec9212f2008-12-18 21:40:36308}
309
Blink Reformat1c4d759e2017-04-09 16:34:54310void WebMediaPlayerImpl::Load(LoadType load_type,
guidou9bfe4e2f2016-04-09 08:31:19311 const blink::WebMediaPlayerSource& source,
[email protected]62e5e682013-03-07 23:53:24312 CORSMode cors_mode) {
xhwang51139732017-02-24 19:36:08313 DVLOG(1) << __func__;
guidou9bfe4e2f2016-04-09 08:31:19314 // Only URL or MSE blob URL is supported.
Blink Reformat1c4d759e2017-04-09 16:34:54315 DCHECK(source.IsURL());
316 blink::WebURL url = source.GetAsURL();
pkastingf5279482016-07-27 02:18:20317 DVLOG(1) << __func__ << "(" << load_type << ", " << url << ", " << cors_mode
318 << ")";
[email protected]d726eddc2013-07-02 22:25:55319 if (!defer_load_cb_.is_null()) {
tguilbert350936ff2017-02-24 05:39:27320 defer_load_cb_.Run(base::Bind(&WebMediaPlayerImpl::DoLoad, AsWeakPtr(),
321 load_type, url, cors_mode));
[email protected]d726eddc2013-07-02 22:25:55322 return;
323 }
[email protected]ef8394c2013-08-21 20:26:30324 DoLoad(load_type, url, cors_mode);
[email protected]62e5e682013-03-07 23:53:24325}
326
Blink Reformat1c4d759e2017-04-09 16:34:54327bool WebMediaPlayerImpl::SupportsOverlayFullscreenVideo() {
watk9c87c6fa2016-05-06 20:36:51328#if defined(OS_ANDROID)
watkf835a792016-06-24 23:24:40329 return true;
watk9c87c6fa2016-05-06 20:36:51330#else
331 return false;
332#endif
333}
334
tsunghungee562e92016-07-20 18:03:31335void WebMediaPlayerImpl::EnableOverlay() {
336 overlay_enabled_ = true;
watkf835a792016-06-24 23:24:40337 if (surface_manager_) {
338 surface_created_cb_.Reset(
339 base::Bind(&WebMediaPlayerImpl::OnSurfaceCreated, AsWeakPtr()));
340 surface_manager_->CreateFullscreenSurface(pipeline_metadata_.natural_size,
341 surface_created_cb_.callback());
342 }
tsunghungee562e92016-07-20 18:03:31343
344 if (decoder_requires_restart_for_overlay_)
watkdee516f2016-02-18 02:22:19345 ScheduleRestart();
346}
347
tsunghungee562e92016-07-20 18:03:31348void WebMediaPlayerImpl::DisableOverlay() {
349 overlay_enabled_ = false;
watkf835a792016-06-24 23:24:40350 surface_created_cb_.Cancel();
tsunghungee562e92016-07-20 18:03:31351 overlay_surface_id_ = SurfaceManager::kNoSurfaceID;
352
353 if (decoder_requires_restart_for_overlay_)
watkdee516f2016-02-18 02:22:19354 ScheduleRestart();
dalecurtis4b632fce22016-11-10 00:52:17355 else if (!set_surface_cb_.is_null())
356 set_surface_cb_.Run(overlay_surface_id_);
watkdee516f2016-02-18 02:22:19357}
358
Blink Reformat1c4d759e2017-04-09 16:34:54359void WebMediaPlayerImpl::EnteredFullscreen() {
liberato2fd111be2017-01-04 00:25:06360 // |force_video_overlays_| implies that we're already in overlay mode, so take
361 // no action here. Otherwise, switch to an overlay if it's allowed and if
362 // it will display properly.
363 if (!force_video_overlays_ && enable_fullscreen_video_overlays_ &&
364 DoesOverlaySupportMetadata()) {
tsunghungee562e92016-07-20 18:03:31365 EnableOverlay();
liberato2fd111be2017-01-04 00:25:06366 }
xjzd3fe45a2016-10-12 18:26:37367 if (observer_)
368 observer_->OnEnteredFullscreen();
tsunghungee562e92016-07-20 18:03:31369}
370
Blink Reformat1c4d759e2017-04-09 16:34:54371void WebMediaPlayerImpl::ExitedFullscreen() {
liberato2fd111be2017-01-04 00:25:06372 // If we're in overlay mode, then exit it unless we're supposed to be in
373 // overlay mode all the time.
374 if (!force_video_overlays_ && overlay_enabled_)
tsunghungee562e92016-07-20 18:03:31375 DisableOverlay();
xjzd3fe45a2016-10-12 18:26:37376 if (observer_)
377 observer_->OnExitedFullscreen();
tsunghungee562e92016-07-20 18:03:31378}
379
Blink Reformat1c4d759e2017-04-09 16:34:54380void WebMediaPlayerImpl::BecameDominantVisibleContent(bool isDominant) {
xjzcdbbe732016-12-03 20:47:42381 if (observer_)
382 observer_->OnBecameDominantVisibleContent(isDominant);
383}
384
Blink Reformat1c4d759e2017-04-09 16:34:54385void WebMediaPlayerImpl::SetIsEffectivelyFullscreen(
zqzhangabc08242017-03-02 16:07:14386 bool isEffectivelyFullscreen) {
387 delegate_->SetIsEffectivelyFullscreen(delegate_id_, isEffectivelyFullscreen);
388}
389
[email protected]ef8394c2013-08-21 20:26:30390void WebMediaPlayerImpl::DoLoad(LoadType load_type,
[email protected]180ef242013-11-07 06:50:46391 const blink::WebURL& url,
[email protected]d726eddc2013-07-02 22:25:55392 CORSMode cors_mode) {
pkastingf5279482016-07-27 02:18:20393 DVLOG(1) << __func__;
acolwellb4034942014-08-28 15:42:43394 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]d726eddc2013-07-02 22:25:55395
[email protected]62e5e682013-03-07 23:53:24396 GURL gurl(url);
Blink Reformat1c4d759e2017-04-09 16:34:54397 ReportMetrics(load_type, gurl, frame_->GetSecurityOrigin(), media_log_);
[email protected]62e5e682013-03-07 23:53:24398
[email protected]926f8fd2013-04-12 20:27:53399 // Set subresource URL for crash reporting.
400 base::debug::SetCrashKeyValue("subresource_url", gurl.spec());
401
tguilbert25a4d112016-10-13 21:56:51402 if (use_fallback_path_)
403 fallback_url_ = gurl;
404
[email protected]ef8394c2013-08-21 20:26:30405 load_type_ = load_type;
406
Blink Reformat1c4d759e2017-04-09 16:34:54407 SetNetworkState(WebMediaPlayer::kNetworkStateLoading);
408 SetReadyState(WebMediaPlayer::kReadyStateHaveNothing);
409 media_log_->AddEvent(media_log_->CreateLoadEvent(url.GetString().Utf8()));
[email protected]d726eddc2013-07-02 22:25:55410
411 // Media source pipelines can start immediately.
Blink Reformat1c4d759e2017-04-09 16:34:54412 if (load_type == kLoadTypeMediaSource) {
[email protected]d726eddc2013-07-02 22:25:55413 supports_save_ = false;
[email protected]ef8394c2013-08-21 20:26:30414 StartPipeline();
hubbe5f0ad43b2015-12-14 20:57:26415 } else {
dalecurtisb6e052f52016-08-25 00:35:55416 data_source_.reset(new MultibufferDataSource(
417 url, static_cast<UrlData::CORSMode>(cors_mode), main_task_runner_,
418 url_index_, frame_, media_log_.get(), &buffered_data_source_host_,
419 base::Bind(&WebMediaPlayerImpl::NotifyDownloading, AsWeakPtr())));
avayvode46d7bef2016-03-30 23:18:26420 data_source_->SetPreload(preload_);
avayvode46d7bef2016-03-30 23:18:26421 data_source_->Initialize(
422 base::Bind(&WebMediaPlayerImpl::DataSourceInitialized, AsWeakPtr()));
hubbe5f0ad43b2015-12-14 20:57:26423 }
hubbed5f36882016-01-15 22:40:37424
425#if defined(OS_ANDROID) // WMPI_CAST
dalecurtisbb3eaac2016-01-27 21:10:25426 cast_impl_.Initialize(url, frame_, delegate_id_);
hubbed5f36882016-01-15 22:40:37427#endif
[email protected]62e5e682013-03-07 23:53:24428}
429
Blink Reformat1c4d759e2017-04-09 16:34:54430void WebMediaPlayerImpl::Play() {
pkastingf5279482016-07-27 02:18:20431 DVLOG(1) << __func__;
acolwellb4034942014-08-28 15:42:43432 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]d43ed912009-02-03 04:52:53433
avayvod65fad272017-02-24 01:00:48434 // User initiated play unlocks background video playback.
Blink Reformat1c4d759e2017-04-09 16:34:54435 if (blink::WebUserGestureIndicator::IsProcessingUserGesture())
avayvod65fad272017-02-24 01:00:48436 video_locked_when_paused_when_hidden_ = false;
437
hubbed5f36882016-01-15 22:40:37438#if defined(OS_ANDROID) // WMPI_CAST
Blink Reformat1c4d759e2017-04-09 16:34:54439 if (IsRemote()) {
dalecurtis6e2716d2016-01-21 04:49:15440 cast_impl_.play();
hubbed5f36882016-01-15 22:40:37441 return;
442 }
443#endif
sandersd35d2c3f2017-01-14 02:04:42444 // TODO(sandersd): Do we want to reset the idle timer here?
tguilbert1bb1c782017-01-23 21:15:11445 delegate_->SetIdle(delegate_id_, false);
[email protected]49480902009-07-14 20:23:43446 paused_ = false;
tguilbert350936ff2017-02-24 05:39:27447 pipeline_controller_.SetPlaybackRate(playback_rate_);
dalecurtis4619cd02016-09-22 21:39:10448 background_pause_timer_.Stop();
sandersd1c0bba02016-03-04 23:14:08449
[email protected]039b7542013-10-17 22:06:25450 if (data_source_)
451 data_source_->MediaIsPlaying();
[email protected]090f7312011-08-05 23:26:40452
xjz48a9cb72016-12-20 04:02:49453 if (observer_)
454 observer_->OnPlaying();
455
dalecurtis04bdb582016-08-17 22:15:23456 DCHECK(watch_time_reporter_);
457 watch_time_reporter_->OnPlaying();
acolwell9e0840d2014-09-06 19:01:32458 media_log_->AddEvent(media_log_->CreateEvent(MediaLogEvent::PLAY));
sandersd50a635e2016-04-04 22:50:09459 UpdatePlayState();
[email protected]ec9212f2008-12-18 21:40:36460}
461
Blink Reformat1c4d759e2017-04-09 16:34:54462void WebMediaPlayerImpl::Pause() {
pkastingf5279482016-07-27 02:18:20463 DVLOG(1) << __func__;
acolwellb4034942014-08-28 15:42:43464 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]d43ed912009-02-03 04:52:53465
sandersd50a635e2016-04-04 22:50:09466 // We update the paused state even when casting, since we expect pause() to be
467 // called when casting begins, and when we exit casting we should end up in a
468 // paused state.
[email protected]49480902009-07-14 20:23:43469 paused_ = true;
hubbed5f36882016-01-15 22:40:37470
avayvodeb9098d2017-01-07 00:33:03471 // No longer paused because it was hidden.
472 paused_when_hidden_ = false;
473
avayvod65fad272017-02-24 01:00:48474 // User initiated pause locks background videos.
Blink Reformat1c4d759e2017-04-09 16:34:54475 if (blink::WebUserGestureIndicator::IsProcessingUserGesture())
avayvod65fad272017-02-24 01:00:48476 video_locked_when_paused_when_hidden_ = true;
477
hubbed5f36882016-01-15 22:40:37478#if defined(OS_ANDROID) // WMPI_CAST
Blink Reformat1c4d759e2017-04-09 16:34:54479 if (IsRemote()) {
dalecurtis6e2716d2016-01-21 04:49:15480 cast_impl_.pause();
hubbed5f36882016-01-15 22:40:37481 return;
482 }
483#endif
484
tguilbert350936ff2017-02-24 05:39:27485 pipeline_controller_.SetPlaybackRate(0.0);
sandersd1c0bba02016-03-04 23:14:08486
487 // pause() may be called after playback has ended and the HTMLMediaElement
488 // requires that currentTime() == duration() after ending. We want to ensure
489 // |paused_time_| matches currentTime() in this case or a future seek() may
490 // incorrectly discard what it thinks is a seek to the existing time.
tguilbert350936ff2017-02-24 05:39:27491 paused_time_ =
492 ended_ ? GetPipelineMediaDuration() : pipeline_controller_.GetMediaTime();
[email protected]090f7312011-08-05 23:26:40493
xjz48a9cb72016-12-20 04:02:49494 if (observer_)
495 observer_->OnPaused();
496
dalecurtis04bdb582016-08-17 22:15:23497 DCHECK(watch_time_reporter_);
498 watch_time_reporter_->OnPaused();
acolwell9e0840d2014-09-06 19:01:32499 media_log_->AddEvent(media_log_->CreateEvent(MediaLogEvent::PAUSE));
avayvod2135a642017-01-13 00:17:14500
sandersd50a635e2016-04-04 22:50:09501 UpdatePlayState();
[email protected]ec9212f2008-12-18 21:40:36502}
503
Blink Reformat1c4d759e2017-04-09 16:34:54504bool WebMediaPlayerImpl::SupportsSave() const {
acolwellb4034942014-08-28 15:42:43505 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]132dd57c2012-08-10 23:24:34506 return supports_save_;
[email protected]574a1d62009-07-17 03:23:46507}
508
Blink Reformat1c4d759e2017-04-09 16:34:54509void WebMediaPlayerImpl::Seek(double seconds) {
pkastingf5279482016-07-27 02:18:20510 DVLOG(1) << __func__ << "(" << seconds << "s)";
acolwellb4034942014-08-28 15:42:43511 DCHECK(main_task_runner_->BelongsToCurrentThread());
servolk86b3d88fb2017-03-18 02:50:28512 media_log_->AddEvent(media_log_->CreateSeekEvent(seconds));
sandersd1c0bba02016-03-04 23:14:08513 DoSeek(base::TimeDelta::FromSecondsD(seconds), true);
514}
515
516void WebMediaPlayerImpl::DoSeek(base::TimeDelta time, bool time_updated) {
517 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]d43ed912009-02-03 04:52:53518
hubbed5f36882016-01-15 22:40:37519#if defined(OS_ANDROID) // WMPI_CAST
Blink Reformat1c4d759e2017-04-09 16:34:54520 if (IsRemote()) {
sandersd1c0bba02016-03-04 23:14:08521 cast_impl_.seek(time);
hubbed5f36882016-01-15 22:40:37522 return;
523 }
524#endif
525
srirama.mccf671812015-01-08 11:59:13526 ReadyState old_state = ready_state_;
Blink Reformat1c4d759e2017-04-09 16:34:54527 if (ready_state_ > WebMediaPlayer::kReadyStateHaveMetadata)
528 SetReadyState(WebMediaPlayer::kReadyStateHaveMetadata);
[email protected]1bb666802013-11-28 06:12:08529
sandersd1c0bba02016-03-04 23:14:08530 // When paused, we know exactly what the current time is and can elide seeks
531 // to it. However, there are two cases that are not elided:
532 // 1) When the pipeline state is not stable.
533 // In this case we just let |pipeline_controller_| decide what to do, as
534 // it has complete information.
535 // 2) For MSE.
536 // Because the buffers may have changed between seeks, MSE seeks are
537 // never elided.
538 if (paused_ && pipeline_controller_.IsStable() && paused_time_ == time &&
539 !chunk_demuxer_) {
540 // If the ready state was high enough before, we can indicate that the seek
541 // completed just by restoring it. Otherwise we will just wait for the real
542 // ready state change to eventually happen.
Blink Reformat1c4d759e2017-04-09 16:34:54543 if (old_state == kReadyStateHaveEnoughData) {
srirama.m8f4a37562014-12-13 08:16:18544 main_task_runner_->PostTask(
alokp967c902452016-05-06 05:21:37545 FROM_HERE, base::Bind(&WebMediaPlayerImpl::OnBufferingStateChange,
546 AsWeakPtr(), BUFFERING_HAVE_ENOUGH));
srirama.m36ab2682014-12-11 04:20:01547 }
sandersd1c0bba02016-03-04 23:14:08548 return;
srirama.m36ab2682014-12-11 04:20:01549 }
[email protected]44ff37c02009-10-24 01:03:03550
dalecurtis04bdb582016-08-17 22:15:23551 // Call this before setting |seeking_| so that the current media time can be
552 // recorded by the reporter.
553 if (watch_time_reporter_)
554 watch_time_reporter_->OnSeeking();
555
dalecurtis1af3c1a2017-04-11 00:53:49556 // Clear any new frame processed callbacks on seek; otherwise we'll end up
557 // logging a time long after the seek completes.
558 frame_time_report_cb_.Cancel();
559
sandersd35d2c3f2017-01-14 02:04:42560 // TODO(sandersd): Move |seeking_| to PipelineController.
561 // TODO(sandersd): Do we want to reset the idle timer here?
tguilbert1bb1c782017-01-23 21:15:11562 delegate_->SetIdle(delegate_id_, false);
sandersd50a635e2016-04-04 22:50:09563 ended_ = false;
[email protected]b3766a22010-12-22 17:34:13564 seeking_ = true;
sandersd1c0bba02016-03-04 23:14:08565 seek_time_ = time;
566 if (paused_)
567 paused_time_ = time;
568 pipeline_controller_.Seek(time, time_updated);
[email protected]b3766a22010-12-22 17:34:13569
sandersd50a635e2016-04-04 22:50:09570 // This needs to be called after Seek() so that if a resume is triggered, it
571 // is to the correct time.
572 UpdatePlayState();
[email protected]ec9212f2008-12-18 21:40:36573}
574
Blink Reformat1c4d759e2017-04-09 16:34:54575void WebMediaPlayerImpl::SetRate(double rate) {
pkastingf5279482016-07-27 02:18:20576 DVLOG(1) << __func__ << "(" << rate << ")";
acolwellb4034942014-08-28 15:42:43577 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]d43ed912009-02-03 04:52:53578
[email protected]378f0b72009-08-11 17:11:42579 // TODO(kylep): Remove when support for negatives is added. Also, modify the
580 // following checks so rewind uses reasonable values also.
[email protected]39bdde32013-04-17 17:44:20581 if (rate < 0.0)
[email protected]378f0b72009-08-11 17:11:42582 return;
583
584 // Limit rates to reasonable values by clamping.
[email protected]39bdde32013-04-17 17:44:20585 if (rate != 0.0) {
[email protected]378f0b72009-08-11 17:11:42586 if (rate < kMinRate)
587 rate = kMinRate;
588 else if (rate > kMaxRate)
589 rate = kMaxRate;
590 }
591
[email protected]49480902009-07-14 20:23:43592 playback_rate_ = rate;
593 if (!paused_) {
tguilbert350936ff2017-02-24 05:39:27594 pipeline_controller_.SetPlaybackRate(rate);
[email protected]039b7542013-10-17 22:06:25595 if (data_source_)
596 data_source_->MediaPlaybackRateChanged(rate);
[email protected]49480902009-07-14 20:23:43597 }
[email protected]ec9212f2008-12-18 21:40:36598}
599
Blink Reformat1c4d759e2017-04-09 16:34:54600void WebMediaPlayerImpl::SetVolume(double volume) {
pkastingf5279482016-07-27 02:18:20601 DVLOG(1) << __func__ << "(" << volume << ")";
acolwellb4034942014-08-28 15:42:43602 DCHECK(main_task_runner_->BelongsToCurrentThread());
dalecurtisbb3eaac2016-01-27 21:10:25603 volume_ = volume;
tguilbert350936ff2017-02-24 05:39:27604 pipeline_controller_.SetVolume(volume_ * volume_multiplier_);
dalecurtis04bdb582016-08-17 22:15:23605 if (watch_time_reporter_)
606 watch_time_reporter_->OnVolumeChange(volume);
mlamouri910111362016-11-04 11:28:24607
608 // The play state is updated because the player might have left the autoplay
609 // muted state.
610 UpdatePlayState();
[email protected]ec9212f2008-12-18 21:40:36611}
[email protected]f0a51fb52009-03-05 12:46:38612
Blink Reformat1c4d759e2017-04-09 16:34:54613void WebMediaPlayerImpl::SetSinkId(
guidouc7babef2015-10-22 00:42:35614 const blink::WebString& sink_id,
615 const blink::WebSecurityOrigin& security_origin,
616 blink::WebSetSinkIdCallbacks* web_callback) {
guidou69223ce2015-06-16 10:36:19617 DCHECK(main_task_runner_->BelongsToCurrentThread());
pkastingf5279482016-07-27 02:18:20618 DVLOG(1) << __func__;
guidouc7babef2015-10-22 00:42:35619
olka68b69392016-04-01 11:42:12620 media::OutputDeviceStatusCB callback =
621 media::ConvertToOutputDeviceStatusCB(web_callback);
guidouc7babef2015-10-22 00:42:35622 media_task_runner_->PostTask(
623 FROM_HERE,
624 base::Bind(&SetSinkIdOnMediaThread, audio_source_provider_,
Blink Reformat1c4d759e2017-04-09 16:34:54625 sink_id.Utf8(), static_cast<url::Origin>(security_origin),
guidouc7babef2015-10-22 00:42:35626 callback));
guidou69223ce2015-06-16 10:36:19627}
628
Blink Reformat1c4d759e2017-04-09 16:34:54629STATIC_ASSERT_ENUM(WebMediaPlayer::kPreloadNone, MultibufferDataSource::NONE);
630STATIC_ASSERT_ENUM(WebMediaPlayer::kPreloadMetaData,
dalecurtisb6e052f52016-08-25 00:35:55631 MultibufferDataSource::METADATA);
Blink Reformat1c4d759e2017-04-09 16:34:54632STATIC_ASSERT_ENUM(WebMediaPlayer::kPreloadAuto, MultibufferDataSource::AUTO);
[email protected]23a8b1d82011-04-05 16:28:20633
Blink Reformat1c4d759e2017-04-09 16:34:54634void WebMediaPlayerImpl::SetPreload(WebMediaPlayer::Preload preload) {
pkastingf5279482016-07-27 02:18:20635 DVLOG(1) << __func__ << "(" << preload << ")";
acolwellb4034942014-08-28 15:42:43636 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]4e6be3f2009-05-07 02:24:44637
dalecurtisb6e052f52016-08-25 00:35:55638 preload_ = static_cast<MultibufferDataSource::Preload>(preload);
[email protected]b49beeb2013-03-01 20:04:00639 if (data_source_)
[email protected]09c60222014-08-07 16:42:31640 data_source_->SetPreload(preload_);
[email protected]4e6be3f2009-05-07 02:24:44641}
642
Blink Reformat1c4d759e2017-04-09 16:34:54643bool WebMediaPlayerImpl::HasVideo() const {
acolwellb4034942014-08-28 15:42:43644 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]d43ed912009-02-03 04:52:53645
[email protected]b8877772014-03-26 20:17:15646 return pipeline_metadata_.has_video;
[email protected]d43ed912009-02-03 04:52:53647}
648
Blink Reformat1c4d759e2017-04-09 16:34:54649bool WebMediaPlayerImpl::HasAudio() const {
acolwellb4034942014-08-28 15:42:43650 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]fc367af2009-08-14 23:06:35651
[email protected]b8877772014-03-26 20:17:15652 return pipeline_metadata_.has_audio;
[email protected]fc367af2009-08-14 23:06:35653}
654
Blink Reformat1c4d759e2017-04-09 16:34:54655void WebMediaPlayerImpl::EnabledAudioTracksChanged(
servolkf25ceed2016-07-01 03:44:38656 const blink::WebVector<blink::WebMediaPlayer::TrackId>& enabledTrackIds) {
657 DCHECK(main_task_runner_->BelongsToCurrentThread());
658
659 std::ostringstream logstr;
660 std::vector<MediaTrack::Id> enabledMediaTrackIds;
661 for (const auto& blinkTrackId : enabledTrackIds) {
Blink Reformat1c4d759e2017-04-09 16:34:54662 MediaTrack::Id track_id = blinkTrackId.Utf8().data();
servolkf25ceed2016-07-01 03:44:38663 logstr << track_id << " ";
664 enabledMediaTrackIds.push_back(track_id);
665 }
666 MEDIA_LOG(INFO, media_log_) << "Enabled audio tracks: [" << logstr.str()
667 << "]";
tguilbert350936ff2017-02-24 05:39:27668 pipeline_controller_.OnEnabledAudioTracksChanged(enabledMediaTrackIds);
servolkf25ceed2016-07-01 03:44:38669}
670
Blink Reformat1c4d759e2017-04-09 16:34:54671void WebMediaPlayerImpl::SelectedVideoTrackChanged(
servolkf25ceed2016-07-01 03:44:38672 blink::WebMediaPlayer::TrackId* selectedTrackId) {
673 DCHECK(main_task_runner_->BelongsToCurrentThread());
674
servolk9bed6602017-02-24 01:20:11675 base::Optional<MediaTrack::Id> selected_video_track_id;
676 if (selectedTrackId && !video_track_disabled_)
Blink Reformat1c4d759e2017-04-09 16:34:54677 selected_video_track_id = MediaTrack::Id(selectedTrackId->Utf8().data());
servolk9bed6602017-02-24 01:20:11678 MEDIA_LOG(INFO, media_log_) << "Selected video track: ["
679 << selected_video_track_id.value_or("") << "]";
tguilbert350936ff2017-02-24 05:39:27680 pipeline_controller_.OnSelectedVideoTrackChanged(selected_video_track_id);
servolkf25ceed2016-07-01 03:44:38681}
682
Blink Reformat1c4d759e2017-04-09 16:34:54683bool WebMediaPlayerImpl::GetLastUploadedFrameInfo(unsigned* width,
kainino36eeff82017-03-30 00:55:30684 unsigned* height,
685 double* timestamp) {
686 *width = last_uploaded_frame_size_.width();
687 *height = last_uploaded_frame_size_.height();
688 *timestamp = last_uploaded_frame_timestamp_.InSecondsF();
689 return true;
690}
691
Blink Reformat1c4d759e2017-04-09 16:34:54692blink::WebSize WebMediaPlayerImpl::NaturalSize() const {
acolwellb4034942014-08-28 15:42:43693 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]d43ed912009-02-03 04:52:53694
[email protected]b8877772014-03-26 20:17:15695 return blink::WebSize(pipeline_metadata_.natural_size);
[email protected]d43ed912009-02-03 04:52:53696}
697
Blink Reformat1c4d759e2017-04-09 16:34:54698bool WebMediaPlayerImpl::Paused() const {
acolwellb4034942014-08-28 15:42:43699 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]d43ed912009-02-03 04:52:53700
hubbed5f36882016-01-15 22:40:37701#if defined(OS_ANDROID) // WMPI_CAST
Blink Reformat1c4d759e2017-04-09 16:34:54702 if (IsRemote())
danakj4f1fd6a2017-01-06 21:15:17703 return cast_impl_.IsPaused();
hubbed5f36882016-01-15 22:40:37704#endif
sandersd50a635e2016-04-04 22:50:09705
tguilbert350936ff2017-02-24 05:39:27706 return pipeline_controller_.GetPlaybackRate() == 0.0f;
[email protected]d43ed912009-02-03 04:52:53707}
708
Blink Reformat1c4d759e2017-04-09 16:34:54709bool WebMediaPlayerImpl::Seeking() const {
acolwellb4034942014-08-28 15:42:43710 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]d43ed912009-02-03 04:52:53711
Blink Reformat1c4d759e2017-04-09 16:34:54712 if (ready_state_ == WebMediaPlayer::kReadyStateHaveNothing)
[email protected]0acebfa2009-08-21 22:45:40713 return false;
[email protected]67cd5052009-09-10 21:53:22714
[email protected]b3766a22010-12-22 17:34:13715 return seeking_;
[email protected]ec9212f2008-12-18 21:40:36716}
717
Blink Reformat1c4d759e2017-04-09 16:34:54718double WebMediaPlayerImpl::Duration() const {
acolwellb4034942014-08-28 15:42:43719 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]39bdde32013-04-17 17:44:20720
Blink Reformat1c4d759e2017-04-09 16:34:54721 if (ready_state_ == WebMediaPlayer::kReadyStateHaveNothing)
[email protected]39bdde32013-04-17 17:44:20722 return std::numeric_limits<double>::quiet_NaN();
723
chcunninghamb92d5062017-01-10 21:50:22724 // Use duration from ChunkDemuxer when present. MSE allows users to specify
725 // duration as a double. This propagates to the rest of the pipeline as a
726 // TimeDelta with potentially reduced precision (limited to Microseconds).
727 // ChunkDemuxer returns the full-precision user-specified double. This ensures
728 // users can "get" the exact duration they "set".
729 if (chunk_demuxer_)
730 return chunk_demuxer_->GetDuration();
731
avayvodcc273dd2017-01-19 19:35:12732 base::TimeDelta pipeline_duration = GetPipelineMediaDuration();
chcunninghamb92d5062017-01-10 21:50:22733 return pipeline_duration == kInfiniteDuration
734 ? std::numeric_limits<double>::infinity()
735 : pipeline_duration.InSecondsF();
[email protected]d43ed912009-02-03 04:52:53736}
737
[email protected]db66d0092014-04-16 07:15:12738double WebMediaPlayerImpl::timelineOffset() const {
acolwellb4034942014-08-28 15:42:43739 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]db66d0092014-04-16 07:15:12740
741 if (pipeline_metadata_.timeline_offset.is_null())
742 return std::numeric_limits<double>::quiet_NaN();
743
744 return pipeline_metadata_.timeline_offset.ToJsTime();
745}
746
Blink Reformat1c4d759e2017-04-09 16:34:54747double WebMediaPlayerImpl::CurrentTime() const {
acolwellb4034942014-08-28 15:42:43748 DCHECK(main_task_runner_->BelongsToCurrentThread());
Blink Reformat1c4d759e2017-04-09 16:34:54749 DCHECK_NE(ready_state_, WebMediaPlayer::kReadyStateHaveNothing);
scherkusd2c745b2014-09-04 05:03:40750
751 // TODO(scherkus): Replace with an explicit ended signal to HTMLMediaElement,
752 // see http://crbug.com/409280
753 if (ended_)
Blink Reformat1c4d759e2017-04-09 16:34:54754 return Duration();
scherkusd2c745b2014-09-04 05:03:40755
Blink Reformat1c4d759e2017-04-09 16:34:54756 if (Seeking())
sandersd1c0bba02016-03-04 23:14:08757 return seek_time_.InSecondsF();
wolenetz1b2ae7d2015-06-10 00:44:21758
hubbed5f36882016-01-15 22:40:37759#if defined(OS_ANDROID) // WMPI_CAST
Blink Reformat1c4d759e2017-04-09 16:34:54760 if (IsRemote())
hubbed5f36882016-01-15 22:40:37761 return cast_impl_.currentTime();
hubbed5f36882016-01-15 22:40:37762#endif
763
sandersd1c0bba02016-03-04 23:14:08764 if (paused_)
hubbed5f36882016-01-15 22:40:37765 return paused_time_.InSecondsF();
hubbed5f36882016-01-15 22:40:37766
tguilbert350936ff2017-02-24 05:39:27767 return pipeline_controller_.GetMediaTime().InSecondsF();
[email protected]d43ed912009-02-03 04:52:53768}
769
Blink Reformat1c4d759e2017-04-09 16:34:54770WebMediaPlayer::NetworkState WebMediaPlayerImpl::GetNetworkState() const {
acolwellb4034942014-08-28 15:42:43771 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]ddb1e5a2010-12-13 20:10:45772 return network_state_;
773}
774
Blink Reformat1c4d759e2017-04-09 16:34:54775WebMediaPlayer::ReadyState WebMediaPlayerImpl::GetReadyState() const {
acolwellb4034942014-08-28 15:42:43776 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]ddb1e5a2010-12-13 20:10:45777 return ready_state_;
778}
779
Blink Reformat1c4d759e2017-04-09 16:34:54780blink::WebString WebMediaPlayerImpl::GetErrorMessage() {
wolenetz4d39cc02016-04-05 19:54:41781 DCHECK(main_task_runner_->BelongsToCurrentThread());
Blink Reformat1c4d759e2017-04-09 16:34:54782 return blink::WebString::FromUTF8(media_log_->GetLastErrorMessage());
wolenetz4d39cc02016-04-05 19:54:41783}
784
Blink Reformat1c4d759e2017-04-09 16:34:54785blink::WebTimeRanges WebMediaPlayerImpl::Buffered() const {
acolwellb4034942014-08-28 15:42:43786 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]779a8322014-08-22 21:28:37787
acolwell9e0840d2014-09-06 19:01:32788 Ranges<base::TimeDelta> buffered_time_ranges =
tguilbert350936ff2017-02-24 05:39:27789 pipeline_controller_.GetBufferedTimeRanges();
[email protected]779a8322014-08-22 21:28:37790
avayvodcc273dd2017-01-19 19:35:12791 const base::TimeDelta duration = GetPipelineMediaDuration();
dalecurtis39a7f932016-07-19 18:34:59792 if (duration != kInfiniteDuration) {
tguilbert350936ff2017-02-24 05:39:27793 buffered_data_source_host_.AddBufferedTimeRanges(&buffered_time_ranges,
794 duration);
[email protected]779a8322014-08-22 21:28:37795 }
[email protected]02022fc2014-05-16 00:05:31796 return ConvertToWebTimeRanges(buffered_time_ranges);
797}
798
Blink Reformat1c4d759e2017-04-09 16:34:54799blink::WebTimeRanges WebMediaPlayerImpl::Seekable() const {
acolwellb4034942014-08-28 15:42:43800 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]39bdde32013-04-17 17:44:20801
Blink Reformat1c4d759e2017-04-09 16:34:54802 if (ready_state_ < WebMediaPlayer::kReadyStateHaveMetadata)
philipjb0e6f3f2014-09-30 09:51:53803 return blink::WebTimeRanges();
804
Blink Reformat1c4d759e2017-04-09 16:34:54805 const double seekable_end = Duration();
dalecurtis56359cb2014-10-28 00:06:29806
807 // Allow a special exception for seeks to zero for streaming sources with a
808 // finite duration; this allows looping to work.
tguilbertade2bcb2017-01-07 02:57:45809 const bool is_finite_stream = data_source_ && data_source_->IsStreaming() &&
810 std::isfinite(seekable_end);
811
812 // Do not change the seekable range when using the fallback path.
813 // The MediaPlayerRenderer will take care of dropping invalid seeks.
814 const bool force_seeks_to_zero = !use_fallback_path_ && is_finite_stream;
dalecurtis56359cb2014-10-28 00:06:29815
816 // TODO(dalecurtis): Technically this allows seeking on media which return an
tguilbertade2bcb2017-01-07 02:57:45817 // infinite duration so long as DataSource::IsStreaming() is false. While not
dalecurtis56359cb2014-10-28 00:06:29818 // expected, disabling this breaks semi-live players, http://crbug.com/427412.
819 const blink::WebTimeRange seekable_range(
tguilbertade2bcb2017-01-07 02:57:45820 0.0, force_seeks_to_zero ? 0.0 : seekable_end);
philipjb0e6f3f2014-09-30 09:51:53821 return blink::WebTimeRanges(&seekable_range, 1);
[email protected]ec9212f2008-12-18 21:40:36822}
823
sandersd35d2c3f2017-01-14 02:04:42824bool WebMediaPlayerImpl::IsPrerollAttemptNeeded() {
825 // TODO(sandersd): Replace with |highest_ready_state_since_seek_| if we need
826 // to ensure that preroll always gets a chance to complete.
827 // See http://crbug.com/671525.
Blink Reformat1c4d759e2017-04-09 16:34:54828 if (highest_ready_state_ >= ReadyState::kReadyStateHaveFutureData)
sandersd35d2c3f2017-01-14 02:04:42829 return false;
830
831 if (preroll_attempt_pending_)
832 return true;
833
834 // Freshly initialized; there has never been any loading progress. (Otherwise
835 // |preroll_attempt_pending_| would be true when the start time is null.)
836 if (preroll_attempt_start_time_.is_null())
837 return false;
838
839 base::TimeDelta preroll_attempt_duration =
840 tick_clock_->NowTicks() - preroll_attempt_start_time_;
841 return preroll_attempt_duration < kPrerollAttemptTimeout;
842}
843
Blink Reformat1c4d759e2017-04-09 16:34:54844bool WebMediaPlayerImpl::DidLoadingProgress() {
acolwellb4034942014-08-28 15:42:43845 DCHECK(main_task_runner_->BelongsToCurrentThread());
dalecurtise7120dc2016-09-03 02:54:35846
847 // Note: Separate variables used to ensure both methods are called every time.
tguilbert350936ff2017-02-24 05:39:27848 const bool pipeline_progress = pipeline_controller_.DidLoadingProgress();
dalecurtise7120dc2016-09-03 02:54:35849 const bool data_progress = buffered_data_source_host_.DidLoadingProgress();
850 const bool did_loading_progress = pipeline_progress || data_progress;
851
sandersd35d2c3f2017-01-14 02:04:42852 if (did_loading_progress &&
Blink Reformat1c4d759e2017-04-09 16:34:54853 highest_ready_state_ < ReadyState::kReadyStateHaveFutureData) {
sandersd35d2c3f2017-01-14 02:04:42854 // Reset the preroll attempt clock.
855 preroll_attempt_pending_ = true;
856 preroll_attempt_start_time_ = base::TimeTicks();
857
858 // Clear any 'stale' flag and give the pipeline a chance to resume. If we
859 // are already resumed, this will cause |preroll_attempt_start_time_| to be
860 // set.
861 // TODO(sandersd): Should this be on the same stack? It might be surprising
862 // that didLoadingProgress() can synchronously change state.
tguilbert1bb1c782017-01-23 21:15:11863 delegate_->ClearStaleFlag(delegate_id_);
dalecurtise7120dc2016-09-03 02:54:35864 UpdatePlayState();
865 }
866
867 return did_loading_progress;
[email protected]d43ed912009-02-03 04:52:53868}
869
Blink Reformat1c4d759e2017-04-09 16:34:54870void WebMediaPlayerImpl::Paint(blink::WebCanvas* canvas,
[email protected]dd5c7972014-08-21 15:00:37871 const blink::WebRect& rect,
enne11266b82017-03-02 01:43:47872 cc::PaintFlags& flags) {
acolwellb4034942014-08-28 15:42:43873 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]dd061e12014-05-06 19:21:22874 TRACE_EVENT0("media", "WebMediaPlayerImpl:paint");
[email protected]4e6be3f2009-05-07 02:24:44875
xhwang213e50c2016-10-10 23:56:31876 // TODO(sandersd): Move this check into GetCurrentFrameFromCompositor() when
877 // we have other ways to check if decoder owns video frame.
878 // See http://crbug.com/595716 and http://crbug.com/602708
jrummelle616ee92016-10-08 02:15:44879 if (cdm_)
xhwang80739452016-01-13 00:48:00880 return;
881
mcasasf1236fc22015-05-29 22:38:56882 scoped_refptr<VideoFrame> video_frame = GetCurrentFrameFromCompositor();
[email protected]0fe5d43b2014-01-24 23:32:45883
[email protected]b49beeb2013-03-01 20:04:00884 gfx::Rect gfx_rect(rect);
dongseong.hwang0c4e9d82015-01-08 20:11:13885 Context3D context_3d;
mcasas265bdbf82015-06-12 18:44:07886 if (video_frame.get() && video_frame->HasTextures()) {
mcasasf1236fc22015-05-29 22:38:56887 if (!context_3d_cb_.is_null())
dongseong.hwang0c4e9d82015-01-08 20:11:13888 context_3d = context_3d_cb_.Run();
dongseong.hwang0c4e9d82015-01-08 20:11:13889 if (!context_3d.gl)
danakj53f7ec902016-05-21 01:30:10890 return; // Unable to get/create a shared main thread context.
891 if (!context_3d.gr_context)
892 return; // The context has been lost since and can't setup a GrContext.
dongseong.hwang0c4e9d82015-01-08 20:11:13893 }
danakj795f1732015-08-31 23:40:22894 skcanvas_video_renderer_.Paint(video_frame, canvas, gfx::RectF(gfx_rect),
enne11266b82017-03-02 01:43:47895 flags, pipeline_metadata_.video_rotation,
danakj795f1732015-08-31 23:40:22896 context_3d);
[email protected]ec9212f2008-12-18 21:40:36897}
[email protected]5df51652009-01-17 00:03:00898
Blink Reformat1c4d759e2017-04-09 16:34:54899bool WebMediaPlayerImpl::HasSingleSecurityOrigin() const {
[email protected]b49beeb2013-03-01 20:04:00900 if (data_source_)
901 return data_source_->HasSingleOrigin();
[email protected]fcdb7462009-10-21 21:05:11902 return true;
[email protected]38259a7a82009-07-29 21:49:49903}
904
Blink Reformat1c4d759e2017-04-09 16:34:54905bool WebMediaPlayerImpl::DidPassCORSAccessCheck() const {
[email protected]b49beeb2013-03-01 20:04:00906 if (data_source_)
907 return data_source_->DidPassCORSAccessCheck();
908 return false;
[email protected]3fe27112012-06-07 04:00:01909}
910
Blink Reformat1c4d759e2017-04-09 16:34:54911double WebMediaPlayerImpl::MediaTimeForTimeValue(double timeValue) const {
qinminb4c39782015-08-10 18:43:24912 return base::TimeDelta::FromSecondsD(timeValue).InSecondsF();
[email protected]e06e16d82011-05-26 22:13:33913}
914
Blink Reformat1c4d759e2017-04-09 16:34:54915unsigned WebMediaPlayerImpl::DecodedFrameCount() const {
acolwellb4034942014-08-28 15:42:43916 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]4c51bc662011-02-16 02:03:16917
avayvodc4bfb0e62017-01-13 01:07:01918 PipelineStatistics stats = GetPipelineStatistics();
[email protected]4c51bc662011-02-16 02:03:16919 return stats.video_frames_decoded;
920}
921
Blink Reformat1c4d759e2017-04-09 16:34:54922unsigned WebMediaPlayerImpl::DroppedFrameCount() const {
acolwellb4034942014-08-28 15:42:43923 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]4c51bc662011-02-16 02:03:16924
avayvodc4bfb0e62017-01-13 01:07:01925 PipelineStatistics stats = GetPipelineStatistics();
[email protected]dd061e12014-05-06 19:21:22926 return stats.video_frames_dropped;
[email protected]4c51bc662011-02-16 02:03:16927}
928
Blink Reformat1c4d759e2017-04-09 16:34:54929size_t WebMediaPlayerImpl::AudioDecodedByteCount() const {
acolwellb4034942014-08-28 15:42:43930 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]4c51bc662011-02-16 02:03:16931
avayvodc4bfb0e62017-01-13 01:07:01932 PipelineStatistics stats = GetPipelineStatistics();
[email protected]4c51bc662011-02-16 02:03:16933 return stats.audio_bytes_decoded;
934}
935
Blink Reformat1c4d759e2017-04-09 16:34:54936size_t WebMediaPlayerImpl::VideoDecodedByteCount() const {
acolwellb4034942014-08-28 15:42:43937 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]4c51bc662011-02-16 02:03:16938
avayvodc4bfb0e62017-01-13 01:07:01939 PipelineStatistics stats = GetPipelineStatistics();
[email protected]4c51bc662011-02-16 02:03:16940 return stats.video_bytes_decoded;
941}
942
Blink Reformat1c4d759e2017-04-09 16:34:54943bool WebMediaPlayerImpl::CopyVideoTextureToPlatformTexture(
danakj46070b02016-03-28 21:54:11944 gpu::gles2::GLES2Interface* gl,
zmo57d577a2015-10-30 18:28:59945 unsigned int texture,
zmo57d577a2015-10-30 18:28:59946 bool premultiply_alpha,
947 bool flip_y) {
xhwang213e50c2016-10-10 23:56:31948 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]bfc05f22013-10-19 17:55:16949 TRACE_EVENT0("media", "WebMediaPlayerImpl:copyVideoTextureToPlatformTexture");
950
xhwang213e50c2016-10-10 23:56:31951 // TODO(sandersd): Move this check into GetCurrentFrameFromCompositor() when
952 // we have other ways to check if decoder owns video frame.
953 // See http://crbug.com/595716 and http://crbug.com/602708
954 if (cdm_)
955 return false;
[email protected]dd061e12014-05-06 19:21:22956
xhwang213e50c2016-10-10 23:56:31957 scoped_refptr<VideoFrame> video_frame = GetCurrentFrameFromCompositor();
jbauman581d041c2016-07-21 01:01:03958 if (!video_frame.get() || !video_frame->HasTextures()) {
[email protected]e56f88c72013-06-25 22:31:29959 return false;
dongseong.hwang0c4e9d82015-01-08 20:11:13960 }
[email protected]df41e252014-02-03 23:39:50961
jbauman581d041c2016-07-21 01:01:03962 Context3D context_3d;
963 if (!context_3d_cb_.is_null())
964 context_3d = context_3d_cb_.Run();
965 return skcanvas_video_renderer_.CopyVideoFrameTexturesToGLTexture(
kbr4910ae52017-01-11 00:52:28966 context_3d, gl, video_frame.get(), texture, premultiply_alpha, flip_y);
[email protected]6523b242013-03-13 11:10:07967}
968
Blink Reformat1c4d759e2017-04-09 16:34:54969void WebMediaPlayerImpl::SetContentDecryptionModule(
[email protected]9ebc3b03f2014-08-13 04:01:23970 blink::WebContentDecryptionModule* cdm,
971 blink::WebContentDecryptionModuleResult result) {
xhwang51139732017-02-24 19:36:08972 DVLOG(1) << __func__ << ": cdm = " << cdm;
acolwellb4034942014-08-28 15:42:43973 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]9ebc3b03f2014-08-13 04:01:23974
jrummell06f27072015-06-08 18:12:38975 // Once the CDM is set it can't be cleared as there may be frames being
976 // decrypted on other threads. So fail this request.
977 // http://crbug.com/462365#c7.
xhwang97de4202014-11-25 08:44:01978 if (!cdm) {
Blink Reformat1c4d759e2017-04-09 16:34:54979 result.CompleteWithError(
980 blink::kWebContentDecryptionModuleExceptionInvalidStateError, 0,
xhwang79b193042016-12-13 18:52:43981 "The existing ContentDecryptionModule object cannot be removed at this "
982 "time.");
xhwang97de4202014-11-25 08:44:01983 return;
984 }
985
jrummell89e61d82015-07-23 20:03:34986 // Create a local copy of |result| to avoid problems with the callback
987 // getting passed to the media thread and causing |result| to be destructed
jrummell4acbec912016-02-27 02:45:03988 // on the wrong thread in some failure conditions. Blink should prevent
989 // multiple simultaneous calls.
990 DCHECK(!set_cdm_result_);
jrummell89e61d82015-07-23 20:03:34991 set_cdm_result_.reset(new blink::WebContentDecryptionModuleResult(result));
992
dalecurtis04bdb582016-08-17 22:15:23993 // Recreate the watch time reporter if necessary.
994 const bool was_encrypted = is_encrypted_;
995 is_encrypted_ = true;
996 if (!was_encrypted && watch_time_reporter_)
997 CreateWatchTimeReporter();
998
jrummelle616ee92016-10-08 02:15:44999 SetCdm(cdm);
xhwang97de4202014-11-25 08:44:011000}
1001
xhwange8c4181a2014-12-06 08:10:011002void WebMediaPlayerImpl::OnEncryptedMediaInitData(
jrummellcf78967c2015-04-03 05:03:581003 EmeInitDataType init_data_type,
Avi Drissman97785ea2015-12-19 01:11:311004 const std::vector<uint8_t>& init_data) {
jrummellcf78967c2015-04-03 05:03:581005 DCHECK(init_data_type != EmeInitDataType::UNKNOWN);
xhwangbab66f52014-12-02 23:49:501006
ddorwin301ccdb2016-02-25 02:39:171007 // TODO(xhwang): Update this UMA name. https://crbug.com/589251
xhwangbab66f52014-12-02 23:49:501008 UMA_HISTOGRAM_COUNTS("Media.EME.NeedKey", 1);
1009
dalecurtis04bdb582016-08-17 22:15:231010 // Recreate the watch time reporter if necessary.
1011 const bool was_encrypted = is_encrypted_;
1012 is_encrypted_ = true;
1013 if (!was_encrypted && watch_time_reporter_)
1014 CreateWatchTimeReporter();
1015
Blink Reformat1c4d759e2017-04-09 16:34:541016 encrypted_client_->Encrypted(
davidbenb50f00c2015-12-01 00:01:501017 ConvertToWebInitDataType(init_data_type), init_data.data(),
srirama.m26f864d02015-07-14 05:21:461018 base::saturated_cast<unsigned int>(init_data.size()));
xhwangbab66f52014-12-02 23:49:501019}
1020
servolk81e01e02016-03-05 03:29:151021void WebMediaPlayerImpl::OnFFmpegMediaTracksUpdated(
dcheng3076abbf2016-04-22 20:42:391022 std::unique_ptr<MediaTracks> tracks) {
servolk81e01e02016-03-05 03:29:151023 // For MSE/chunk_demuxer case the media track updates are handled by
1024 // WebSourceBufferImpl.
1025 DCHECK(demuxer_.get());
1026 DCHECK(!chunk_demuxer_);
servolkef1e5ef2016-03-25 04:55:261027
servolk16e8bdf82017-04-11 17:00:391028 // Report the media track information to blink. Only the first audio track and
1029 // the first video track are enabled by default to match blink logic.
1030 bool is_first_audio_track = true;
1031 bool is_first_video_track = true;
servolkef1e5ef2016-03-25 04:55:261032 for (const auto& track : tracks->tracks()) {
1033 if (track->type() == MediaTrack::Audio) {
Blink Reformat1c4d759e2017-04-09 16:34:541034 client_->AddAudioTrack(blink::WebString::FromUTF8(track->id()),
1035 blink::WebMediaPlayerClient::kAudioTrackKindMain,
1036 blink::WebString::FromUTF8(track->label()),
1037 blink::WebString::FromUTF8(track->language()),
servolk16e8bdf82017-04-11 17:00:391038 is_first_audio_track);
1039 is_first_audio_track = false;
servolkef1e5ef2016-03-25 04:55:261040 } else if (track->type() == MediaTrack::Video) {
Blink Reformat1c4d759e2017-04-09 16:34:541041 client_->AddVideoTrack(blink::WebString::FromUTF8(track->id()),
1042 blink::WebMediaPlayerClient::kVideoTrackKindMain,
1043 blink::WebString::FromUTF8(track->label()),
1044 blink::WebString::FromUTF8(track->language()),
servolk16e8bdf82017-04-11 17:00:391045 is_first_video_track);
1046 is_first_video_track = false;
servolkef1e5ef2016-03-25 04:55:261047 } else {
1048 // Text tracks are not supported through this code path yet.
1049 NOTREACHED();
1050 }
1051 }
servolk81e01e02016-03-05 03:29:151052}
1053
jrummelle616ee92016-10-08 02:15:441054void WebMediaPlayerImpl::SetCdm(blink::WebContentDecryptionModule* cdm) {
1055 DCHECK(main_task_runner_->BelongsToCurrentThread());
1056 DCHECK(cdm);
xhwang79b193042016-12-13 18:52:431057 scoped_refptr<ContentDecryptionModule> cdm_reference =
jrummelle616ee92016-10-08 02:15:441058 ToWebContentDecryptionModuleImpl(cdm)->GetCdm();
1059 if (!cdm_reference) {
1060 NOTREACHED();
1061 OnCdmAttached(false);
xhwang80739452016-01-13 00:48:001062 return;
1063 }
1064
jrummelle616ee92016-10-08 02:15:441065 CdmContext* cdm_context = cdm_reference->GetCdmContext();
1066 if (!cdm_context) {
1067 OnCdmAttached(false);
1068 return;
1069 }
1070
xjzd3fe45a2016-10-12 18:26:371071 if (observer_)
1072 observer_->OnSetCdm(cdm_context);
1073
jrummelle616ee92016-10-08 02:15:441074 // Keep the reference to the CDM, as it shouldn't be destroyed until
1075 // after the pipeline is done with the |cdm_context|.
1076 pending_cdm_ = std::move(cdm_reference);
tguilbert350936ff2017-02-24 05:39:271077 pipeline_controller_.SetCdm(
1078 cdm_context, base::Bind(&WebMediaPlayerImpl::OnCdmAttached, AsWeakPtr()));
xhwang97de4202014-11-25 08:44:011079}
1080
jrummell89e61d82015-07-23 20:03:341081void WebMediaPlayerImpl::OnCdmAttached(bool success) {
xhwang51139732017-02-24 19:36:081082 DVLOG(1) << __func__ << ": success = " << success;
jrummelle616ee92016-10-08 02:15:441083 DCHECK(main_task_runner_->BelongsToCurrentThread());
1084 DCHECK(pending_cdm_);
1085
1086 // If the CDM is set from the constructor there is no promise
1087 // (|set_cdm_result_|) to fulfill.
xhwang97de4202014-11-25 08:44:011088 if (success) {
jrummelle616ee92016-10-08 02:15:441089 // This will release the previously attached CDM (if any).
1090 cdm_ = std::move(pending_cdm_);
1091 if (set_cdm_result_) {
Blink Reformat1c4d759e2017-04-09 16:34:541092 set_cdm_result_->Complete();
jrummelle616ee92016-10-08 02:15:441093 set_cdm_result_.reset();
1094 }
1095
xhwang97de4202014-11-25 08:44:011096 return;
1097 }
1098
jrummelle616ee92016-10-08 02:15:441099 pending_cdm_ = nullptr;
1100 if (set_cdm_result_) {
Blink Reformat1c4d759e2017-04-09 16:34:541101 set_cdm_result_->CompleteWithError(
1102 blink::kWebContentDecryptionModuleExceptionNotSupportedError, 0,
xhwang79b193042016-12-13 18:52:431103 "Unable to set ContentDecryptionModule object");
jrummelle616ee92016-10-08 02:15:441104 set_cdm_result_.reset();
1105 }
[email protected]9ebc3b03f2014-08-13 04:01:231106}
1107
sandersd1c0bba02016-03-04 23:14:081108void WebMediaPlayerImpl::OnPipelineSeeked(bool time_updated) {
[email protected]5d11eff2011-09-15 00:06:061109 seeking_ = false;
wolenetz1b2ae7d2015-06-10 00:44:211110 seek_time_ = base::TimeDelta();
avayvod2135a642017-01-13 00:17:141111
hubbe5a2dec022016-03-17 01:14:231112 if (paused_) {
1113#if defined(OS_ANDROID) // WMPI_CAST
Blink Reformat1c4d759e2017-04-09 16:34:541114 if (IsRemote()) {
hubbe5a2dec022016-03-17 01:14:231115 paused_time_ = base::TimeDelta::FromSecondsD(cast_impl_.currentTime());
1116 } else {
tguilbert350936ff2017-02-24 05:39:271117 paused_time_ = pipeline_controller_.GetMediaTime();
hubbe5a2dec022016-03-17 01:14:231118 }
1119#else
tguilbert350936ff2017-02-24 05:39:271120 paused_time_ = pipeline_controller_.GetMediaTime();
hubbe5a2dec022016-03-17 01:14:231121#endif
dalecurtis04bdb582016-08-17 22:15:231122 } else {
1123 DCHECK(watch_time_reporter_);
1124 watch_time_reporter_->OnPlaying();
hubbe5a2dec022016-03-17 01:14:231125 }
sandersd1c0bba02016-03-04 23:14:081126 if (time_updated)
1127 should_notify_time_changed_ = true;
dalecurtisaf34d8712016-09-20 04:32:261128
dalecurtis4f6d14d2017-02-22 17:42:221129 // Reset underflow duration upon seek; this prevents looping videos and user
1130 // actions from artificially inflating the duration.
1131 underflow_timer_.reset();
avayvod56e1f3942017-01-21 02:06:311132
1133 // Background video optimizations are delayed when shown/hidden if pipeline
1134 // is seeking.
1135 UpdateBackgroundVideoOptimizationState();
[email protected]8931c41a2009-07-07 17:31:491136}
1137
sandersd1c0bba02016-03-04 23:14:081138void WebMediaPlayerImpl::OnPipelineSuspended() {
hubbed5f36882016-01-15 22:40:371139#if defined(OS_ANDROID)
Blink Reformat1c4d759e2017-04-09 16:34:541140 if (IsRemote()) {
hubbed5f36882016-01-15 22:40:371141 scoped_refptr<VideoFrame> frame = cast_impl_.GetCastingBanner();
sandersd50a635e2016-04-04 22:50:091142 if (frame)
dalecurtise9c89e92016-05-20 19:38:001143 compositor_->PaintSingleFrame(frame);
hubbed5f36882016-01-15 22:40:371144 }
1145#endif
1146
sandersd2f5bb6152017-03-29 22:57:531147 // Tell the data source we have enough data so that it may release the
1148 // connection.
1149 if (data_source_)
1150 data_source_->OnBufferingHaveEnough(true);
dalecurtis37fe5862016-03-15 19:29:091151
sandersd50a635e2016-04-04 22:50:091152 ReportMemoryUsage();
1153
sandersd1c0bba02016-03-04 23:14:081154 if (pending_suspend_resume_cycle_) {
watkdee516f2016-02-18 02:22:191155 pending_suspend_resume_cycle_ = false;
sandersd50a635e2016-04-04 22:50:091156 UpdatePlayState();
dalecurtis0431cbf2016-03-12 01:19:431157 }
sandersd1c0bba02016-03-04 23:14:081158}
1159
avayvod2135a642017-01-13 00:17:141160void WebMediaPlayerImpl::OnBeforePipelineResume() {
1161 // Enable video track if we disabled it in the background - this way the new
1162 // renderer will attach its callbacks to the video stream properly.
1163 // TODO(avayvod): Remove this when disabling and enabling video tracks in
1164 // non-playing state works correctly. See https://crbug.com/678374.
1165 EnableVideoTrackIfNeeded();
1166 is_pipeline_resuming_ = true;
1167}
1168
1169void WebMediaPlayerImpl::OnPipelineResumed() {
1170 is_pipeline_resuming_ = false;
1171
avayvod56e1f3942017-01-21 02:06:311172 UpdateBackgroundVideoOptimizationState();
avayvod2135a642017-01-13 00:17:141173}
1174
alokp967c902452016-05-06 05:21:371175void WebMediaPlayerImpl::OnDemuxerOpened() {
1176 DCHECK(main_task_runner_->BelongsToCurrentThread());
Blink Reformat1c4d759e2017-04-09 16:34:541177 client_->MediaSourceOpened(
alokp967c902452016-05-06 05:21:371178 new WebMediaSourceImpl(chunk_demuxer_, media_log_));
1179}
1180
servolkf94b4602017-01-31 16:44:271181void WebMediaPlayerImpl::OnMemoryPressure(
1182 base::MemoryPressureListener::MemoryPressureLevel memory_pressure_level) {
1183 DVLOG(2) << __func__ << " memory_pressure_level=" << memory_pressure_level;
1184 DCHECK(main_task_runner_->BelongsToCurrentThread());
1185 DCHECK(base::FeatureList::IsEnabled(kMemoryPressureBasedSourceBufferGC));
1186 DCHECK(chunk_demuxer_);
1187
1188 // The new value of |memory_pressure_level| will take effect on the next
1189 // garbage collection. Typically this means the next SourceBuffer append()
1190 // operation, since per MSE spec, the garbage collection must only occur
1191 // during SourceBuffer append(). But if memory pressure is critical it might
1192 // be better to perform GC immediately rather than wait for the next append
1193 // and potentially get killed due to out-of-memory.
1194 // So if this experiment is enabled and pressure level is critical, we'll pass
1195 // down force_instant_gc==true, which will force immediate GC on
1196 // SourceBufferStreams.
1197 bool force_instant_gc =
1198 (enable_instant_source_buffer_gc_ &&
1199 memory_pressure_level ==
1200 base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL);
1201
1202 // base::Unretained is safe, since chunk_demuxer_ is actually owned by
1203 // |this| via this->demuxer_.
1204 media_task_runner_->PostTask(
1205 FROM_HERE, base::Bind(&ChunkDemuxer::OnMemoryPressure,
1206 base::Unretained(chunk_demuxer_),
Blink Reformat1c4d759e2017-04-09 16:34:541207 base::TimeDelta::FromSecondsD(CurrentTime()),
servolkf94b4602017-01-31 16:44:271208 memory_pressure_level, force_instant_gc));
1209}
1210
alokp967c902452016-05-06 05:21:371211void WebMediaPlayerImpl::OnError(PipelineStatus status) {
pkastingf5279482016-07-27 02:18:201212 DVLOG(1) << __func__;
alokp967c902452016-05-06 05:21:371213 DCHECK(main_task_runner_->BelongsToCurrentThread());
1214 DCHECK_NE(status, PIPELINE_OK);
1215
1216 if (suppress_destruction_errors_)
1217 return;
1218
chcunningham8aeee0b52017-04-07 22:41:401219 ReportPipelineError(load_type_, status, media_log_);
alokp967c902452016-05-06 05:21:371220 media_log_->AddEvent(media_log_->CreatePipelineErrorEvent(status));
1221
Blink Reformat1c4d759e2017-04-09 16:34:541222 if (ready_state_ == WebMediaPlayer::kReadyStateHaveNothing) {
alokp967c902452016-05-06 05:21:371223 // Any error that occurs before reaching ReadyStateHaveMetadata should
1224 // be considered a format error.
Blink Reformat1c4d759e2017-04-09 16:34:541225 SetNetworkState(WebMediaPlayer::kNetworkStateFormatError);
alokp967c902452016-05-06 05:21:371226 } else {
1227 SetNetworkState(PipelineErrorToNetworkState(status));
1228 }
1229
1230 UpdatePlayState();
1231}
1232
1233void WebMediaPlayerImpl::OnEnded() {
pkastingf5279482016-07-27 02:18:201234 DVLOG(1) << __func__;
acolwellb4034942014-08-28 15:42:431235 DCHECK(main_task_runner_->BelongsToCurrentThread());
scherkusd2c745b2014-09-04 05:03:401236
sandersd1c0bba02016-03-04 23:14:081237 // Ignore state changes until we've completed all outstanding operations.
1238 if (!pipeline_controller_.IsStable())
scherkusd2c745b2014-09-04 05:03:401239 return;
1240
1241 ended_ = true;
Blink Reformat1c4d759e2017-04-09 16:34:541242 client_->TimeChanged();
sandersd50a635e2016-04-04 22:50:091243
dalecurtis1af3c1a2017-04-11 00:53:491244 // Clear any new frame processed callbacks on end; otherwise we'll end up
1245 // logging a time long after playback ends.
1246 frame_time_report_cb_.Cancel();
1247
sandersd50a635e2016-04-04 22:50:091248 // We don't actually want this to run until |client_| calls seek() or pause(),
1249 // but that should have already happened in timeChanged() and so this is
1250 // expected to be a no-op.
1251 UpdatePlayState();
[email protected]576537842009-08-12 23:52:051252}
1253
alokp967c902452016-05-06 05:21:371254void WebMediaPlayerImpl::OnMetadata(PipelineMetadata metadata) {
pkastingf5279482016-07-27 02:18:201255 DVLOG(1) << __func__;
acolwellb4034942014-08-28 15:42:431256 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]a8e2cb82012-08-17 00:02:391257
[email protected]b8877772014-03-26 20:17:151258 pipeline_metadata_ = metadata;
[email protected]739847c02014-01-16 00:12:251259
Blink Reformat1c4d759e2017-04-09 16:34:541260 SetReadyState(WebMediaPlayer::kReadyStateHaveMetadata);
dalecurtis849cf4b22015-03-27 18:35:451261 UMA_HISTOGRAM_ENUMERATION("Media.VideoRotation", metadata.video_rotation,
acolwell9e0840d2014-09-06 19:01:321262 VIDEO_ROTATION_MAX + 1);
[email protected]21c3f7502013-03-23 03:29:511263
Blink Reformat1c4d759e2017-04-09 16:34:541264 if (HasVideo()) {
liberato2fd111be2017-01-04 00:25:061265 if (overlay_enabled_) {
1266 // SurfaceView doesn't support rotated video, so transition back if
1267 // the video is now rotated. If |force_video_overlays_|, we keep the
1268 // overlay anyway so that the state machine keeps working.
1269 if (!force_video_overlays_ && !DoesOverlaySupportMetadata())
1270 DisableOverlay();
1271 else if (surface_manager_)
1272 surface_manager_->NaturalSizeChanged(pipeline_metadata_.natural_size);
1273 }
watkf835a792016-06-24 23:24:401274
1275 DCHECK(!video_weblayer_);
dalecurtise1edb312016-06-22 02:33:211276 video_weblayer_.reset(new cc_blink::WebLayerImpl(cc::VideoLayer::Create(
1277 compositor_, pipeline_metadata_.video_rotation)));
jbauman952274d2015-09-10 23:23:361278 video_weblayer_->layer()->SetContentsOpaque(opaque_);
1279 video_weblayer_->SetContentsOpaqueIsFixed(true);
Blink Reformat1c4d759e2017-04-09 16:34:541280 client_->SetWebLayer(video_weblayer_.get());
[email protected]a8e2cb82012-08-17 00:02:391281 }
dalecurtis8e4dc682016-03-15 02:30:301282
xjzd3fe45a2016-10-12 18:26:371283 if (observer_)
xjz15b483f2017-01-12 00:21:361284 observer_->OnMetadataChanged(pipeline_metadata_);
xjzd3fe45a2016-10-12 18:26:371285
dalecurtis04bdb582016-08-17 22:15:231286 CreateWatchTimeReporter();
sandersd50a635e2016-04-04 22:50:091287 UpdatePlayState();
[email protected]a8e2cb82012-08-17 00:02:391288}
1289
alokp967c902452016-05-06 05:21:371290void WebMediaPlayerImpl::OnBufferingStateChange(BufferingState state) {
pkastingf5279482016-07-27 02:18:201291 DVLOG(1) << __func__ << "(" << state << ")";
alokp967c902452016-05-06 05:21:371292 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]b8877772014-03-26 20:17:151293
sandersd1c0bba02016-03-04 23:14:081294 // Ignore buffering state changes until we've completed all outstanding
1295 // operations.
1296 if (!pipeline_controller_.IsStable())
[email protected]ba7d5f92014-06-24 05:37:401297 return;
[email protected]b8877772014-03-26 20:17:151298
dalecurtis869bf2f2017-01-10 18:01:101299 media_log_->AddEvent(media_log_->CreateBufferingStateChangedEvent(
1300 "pipeline_buffering_state", state));
1301
chcunninghameb270c92016-07-15 01:00:451302 if (state == BUFFERING_HAVE_ENOUGH) {
Blink Reformat1c4d759e2017-04-09 16:34:541303 if (highest_ready_state_ < WebMediaPlayer::kReadyStateHaveEnoughData) {
dalecurtis4f6d14d2017-02-22 17:42:221304 // Record a zero value for underflow histogram so that the histogram
dalecurtis821e803f2016-09-01 18:44:151305 // includes playbacks which never encounter an underflow event.
dalecurtis4f6d14d2017-02-22 17:42:221306 RecordUnderflowDuration(base::TimeDelta());
dalecurtis821e803f2016-09-01 18:44:151307 }
1308
chcunninghameb270c92016-07-15 01:00:451309 // TODO(chcunningham): Monitor playback position vs buffered. Potentially
1310 // transition to HAVE_FUTURE_DATA here if not enough is buffered.
Blink Reformat1c4d759e2017-04-09 16:34:541311 SetReadyState(WebMediaPlayer::kReadyStateHaveEnoughData);
[email protected]ba7d5f92014-06-24 05:37:401312
chcunninghameb270c92016-07-15 01:00:451313 // Let the DataSource know we have enough data. It may use this information
1314 // to release unused network connections.
1315 if (data_source_)
1316 data_source_->OnBufferingHaveEnough(false);
dalecurtis849cf4b22015-03-27 18:35:451317
chcunninghameb270c92016-07-15 01:00:451318 // Blink expects a timeChanged() in response to a seek().
sandersd35d2c3f2017-01-14 02:04:421319 if (should_notify_time_changed_) {
1320 should_notify_time_changed_ = false;
Blink Reformat1c4d759e2017-04-09 16:34:541321 client_->TimeChanged();
sandersd35d2c3f2017-01-14 02:04:421322 }
dalecurtis0f0097a2015-12-01 17:40:471323
chcunninghameb270c92016-07-15 01:00:451324 // Once we have enough, start reporting the total memory usage. We'll also
1325 // report once playback starts.
1326 ReportMemoryUsage();
dalecurtis9d638a12016-08-30 06:20:551327
dalecurtis4f6d14d2017-02-22 17:42:221328 // Report the amount of time it took to leave the underflow state.
1329 if (underflow_timer_) {
1330 RecordUnderflowDuration(underflow_timer_->Elapsed());
dalecurtis9d638a12016-08-30 06:20:551331 underflow_timer_.reset();
1332 }
chcunninghameb270c92016-07-15 01:00:451333 } else {
1334 // Buffering has underflowed.
1335 DCHECK_EQ(state, BUFFERING_HAVE_NOTHING);
dalecurtisacd77d62016-09-09 23:23:141336
dalecurtisd06eabc2017-02-24 23:43:291337 // Report the number of times we've entered the underflow state. Ensure we
1338 // only report the value when transitioning from HAVE_ENOUGH to
1339 // HAVE_NOTHING.
Blink Reformat1c4d759e2017-04-09 16:34:541340 if (ready_state_ == WebMediaPlayer::kReadyStateHaveEnoughData)
dalecurtisacd77d62016-09-09 23:23:141341 underflow_timer_.reset(new base::ElapsedTimer());
dalecurtisacd77d62016-09-09 23:23:141342
chcunninghameb270c92016-07-15 01:00:451343 // It shouldn't be possible to underflow if we've not advanced past
1344 // HAVE_CURRENT_DATA.
Blink Reformat1c4d759e2017-04-09 16:34:541345 DCHECK_GT(highest_ready_state_, WebMediaPlayer::kReadyStateHaveCurrentData);
1346 SetReadyState(WebMediaPlayer::kReadyStateHaveCurrentData);
chcunninghameb270c92016-07-15 01:00:451347 }
sandersd50a635e2016-04-04 22:50:091348
1349 UpdatePlayState();
[email protected]b8877772014-03-26 20:17:151350}
1351
alokp967c902452016-05-06 05:21:371352void WebMediaPlayerImpl::OnDurationChange() {
acolwellb4034942014-08-28 15:42:431353 DCHECK(main_task_runner_->BelongsToCurrentThread());
alokp967c902452016-05-06 05:21:371354
1355 // TODO(sandersd): We should call delegate_->DidPlay() with the new duration,
1356 // especially if it changed from <5s to >5s.
Blink Reformat1c4d759e2017-04-09 16:34:541357 if (ready_state_ == WebMediaPlayer::kReadyStateHaveNothing)
alokp967c902452016-05-06 05:21:371358 return;
1359
Blink Reformat1c4d759e2017-04-09 16:34:541360 client_->DurationChanged();
[email protected]81bb3322011-07-21 15:55:501361}
1362
alokp967c902452016-05-06 05:21:371363void WebMediaPlayerImpl::OnAddTextTrack(const TextTrackConfig& config,
1364 const AddTextTrackDoneCB& done_cb) {
acolwellb4034942014-08-28 15:42:431365 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]71537722013-05-23 06:47:531366
[email protected]8a561062013-11-22 01:19:311367 const WebInbandTextTrackImpl::Kind web_kind =
1368 static_cast<WebInbandTextTrackImpl::Kind>(config.kind());
Blink Reformat1c4d759e2017-04-09 16:34:541369 const blink::WebString web_label = blink::WebString::FromUTF8(config.label());
[email protected]8a561062013-11-22 01:19:311370 const blink::WebString web_language =
Blink Reformat1c4d759e2017-04-09 16:34:541371 blink::WebString::FromUTF8(config.language());
1372 const blink::WebString web_id = blink::WebString::FromUTF8(config.id());
[email protected]71537722013-05-23 06:47:531373
dcheng3076abbf2016-04-22 20:42:391374 std::unique_ptr<WebInbandTextTrackImpl> web_inband_text_track(
henriks9cce5fa2014-12-12 09:35:301375 new WebInbandTextTrackImpl(web_kind, web_label, web_language, web_id));
[email protected]8a561062013-11-22 01:19:311376
dcheng3076abbf2016-04-22 20:42:391377 std::unique_ptr<media::TextTrack> text_track(new TextTrackImpl(
dcheng652f5ff2015-12-27 08:54:001378 main_task_runner_, client_, std::move(web_inband_text_track)));
[email protected]8a561062013-11-22 01:19:311379
dcheng652f5ff2015-12-27 08:54:001380 done_cb.Run(std::move(text_track));
[email protected]71537722013-05-23 06:47:531381}
1382
alokp967c902452016-05-06 05:21:371383void WebMediaPlayerImpl::OnWaitingForDecryptionKey() {
1384 DCHECK(main_task_runner_->BelongsToCurrentThread());
1385
Blink Reformat1c4d759e2017-04-09 16:34:541386 encrypted_client_->DidBlockPlaybackWaitingForKey();
alokp967c902452016-05-06 05:21:371387 // TODO(jrummell): didResumePlaybackBlockedForKey() should only be called
1388 // when a key has been successfully added (e.g. OnSessionKeysChange() with
1389 // |has_additional_usable_key| = true). http://crbug.com/461903
Blink Reformat1c4d759e2017-04-09 16:34:541390 encrypted_client_->DidResumePlaybackBlockedForKey();
alokp967c902452016-05-06 05:21:371391}
1392
alokp5d86e9b2016-05-17 20:20:411393void WebMediaPlayerImpl::OnVideoNaturalSizeChange(const gfx::Size& size) {
1394 DCHECK(main_task_runner_->BelongsToCurrentThread());
Blink Reformat1c4d759e2017-04-09 16:34:541395 DCHECK_NE(ready_state_, WebMediaPlayer::kReadyStateHaveNothing);
alokp5d86e9b2016-05-17 20:20:411396
xjz15b483f2017-01-12 00:21:361397 // The input |size| is from the decoded video frame, which is the original
1398 // natural size and need to be rotated accordingly.
sandersd2c478422016-08-02 01:19:251399 gfx::Size rotated_size =
1400 GetRotatedVideoSize(pipeline_metadata_.video_rotation, size);
1401
1402 if (rotated_size == pipeline_metadata_.natural_size)
alokp5d86e9b2016-05-17 20:20:411403 return;
1404
1405 TRACE_EVENT0("media", "WebMediaPlayerImpl::OnNaturalSizeChanged");
sandersd2c478422016-08-02 01:19:251406 media_log_->AddEvent(media_log_->CreateVideoSizeSetEvent(
1407 rotated_size.width(), rotated_size.height()));
alokp5d86e9b2016-05-17 20:20:411408
tsunghungee562e92016-07-20 18:03:311409 if (overlay_enabled_ && surface_manager_)
sandersd2c478422016-08-02 01:19:251410 surface_manager_->NaturalSizeChanged(rotated_size);
alokp5d86e9b2016-05-17 20:20:411411
xjz516ef6d2017-01-07 00:23:061412 gfx::Size old_size = pipeline_metadata_.natural_size;
1413 pipeline_metadata_.natural_size = rotated_size;
1414 if (old_size.IsEmpty()) {
tguilbert796a40e2016-11-09 01:11:421415 // WatchTimeReporter doesn't report metrics for empty videos. Re-create
1416 // |watch_time_reporter_| if we didn't originally know the video size.
1417 CreateWatchTimeReporter();
1418 }
Blink Reformat1c4d759e2017-04-09 16:34:541419 client_->SizeChanged();
xjz516ef6d2017-01-07 00:23:061420
xjz15b483f2017-01-12 00:21:361421 if (observer_)
1422 observer_->OnMetadataChanged(pipeline_metadata_);
alokp5d86e9b2016-05-17 20:20:411423}
1424
1425void WebMediaPlayerImpl::OnVideoOpacityChange(bool opaque) {
1426 DCHECK(main_task_runner_->BelongsToCurrentThread());
Blink Reformat1c4d759e2017-04-09 16:34:541427 DCHECK_NE(ready_state_, WebMediaPlayer::kReadyStateHaveNothing);
alokp5d86e9b2016-05-17 20:20:411428
1429 opaque_ = opaque;
1430 // Modify content opaqueness of cc::Layer directly so that
1431 // SetContentsOpaqueIsFixed is ignored.
1432 if (video_weblayer_)
1433 video_weblayer_->layer()->SetContentsOpaque(opaque_);
1434}
1435
avayvodeecec52c2017-02-14 01:25:091436void WebMediaPlayerImpl::OnVideoAverageKeyframeDistanceUpdate() {
1437 UpdateBackgroundVideoOptimizationState();
1438}
1439
sandersd35d2c3f2017-01-14 02:04:421440void WebMediaPlayerImpl::OnFrameHidden() {
sandersd1e49fb62015-12-12 01:18:061441 DCHECK(main_task_runner_->BelongsToCurrentThread());
avayvod39c102402016-11-23 21:43:131442
avayvod65fad272017-02-24 01:00:481443 // Backgrounding a video requires a user gesture to resume playback.
1444 if (IsHidden())
1445 video_locked_when_paused_when_hidden_ = true;
1446
dalecurtis04bdb582016-08-17 22:15:231447 if (watch_time_reporter_)
1448 watch_time_reporter_->OnHidden();
avayvod48a8be52016-08-04 19:52:501449
avayvod65fad272017-02-24 01:00:481450 UpdateBackgroundVideoOptimizationState();
sandersd50a635e2016-04-04 22:50:091451 UpdatePlayState();
dalecurtis8b8505e72016-06-10 21:59:171452
1453 // Schedule suspended playing media to be paused if the user doesn't come back
1454 // to it within some timeout period to avoid any autoplay surprises.
1455 ScheduleIdlePauseTimer();
sandersd1e49fb62015-12-12 01:18:061456}
1457
sandersd35d2c3f2017-01-14 02:04:421458void WebMediaPlayerImpl::OnFrameClosed() {
sandersd1e49fb62015-12-12 01:18:061459 DCHECK(main_task_runner_->BelongsToCurrentThread());
sandersd35d2c3f2017-01-14 02:04:421460 UpdatePlayState();
1461}
1462
1463void WebMediaPlayerImpl::OnFrameShown() {
1464 DCHECK(main_task_runner_->BelongsToCurrentThread());
1465 background_pause_timer_.Stop();
1466
avayvod65fad272017-02-24 01:00:481467 // Foreground videos don't require user gesture to continue playback.
1468 video_locked_when_paused_when_hidden_ = false;
1469
dalecurtis04bdb582016-08-17 22:15:231470 if (watch_time_reporter_)
1471 watch_time_reporter_->OnShown();
1472
avayvodcc273dd2017-01-19 19:35:121473 // Only track the time to the first frame if playing or about to play because
1474 // of being shown and only for videos we would optimize background playback
1475 // for.
1476 if ((!paused_ && IsBackgroundOptimizationCandidate()) ||
1477 paused_when_hidden_) {
dalecurtis1af3c1a2017-04-11 00:53:491478 frame_time_report_cb_.Reset(
1479 base::Bind(&WebMediaPlayerImpl::ReportTimeFromForegroundToFirstFrame,
1480 AsWeakPtr(), base::TimeTicks::Now()));
avayvodcc273dd2017-01-19 19:35:121481 compositor_task_runner_->PostTask(
1482 FROM_HERE,
1483 base::Bind(&VideoFrameCompositor::SetOnNewProcessedFrameCallback,
dalecurtis1af3c1a2017-04-11 00:53:491484 base::Unretained(compositor_),
1485 BindToCurrentLoop(frame_time_report_cb_.callback())));
avayvodcc273dd2017-01-19 19:35:121486 }
avayvodac607d652017-01-06 03:16:431487
avayvod65fad272017-02-24 01:00:481488 EnableVideoTrackIfNeeded();
1489
avayvod2135a642017-01-13 00:17:141490 if (paused_when_hidden_) {
1491 paused_when_hidden_ = false;
1492 OnPlay(); // Calls UpdatePlayState() so return afterwards.
1493 return;
1494 }
1495
sandersd50a635e2016-04-04 22:50:091496 UpdatePlayState();
sandersd1e49fb62015-12-12 01:18:061497}
1498
sandersd35d2c3f2017-01-14 02:04:421499void WebMediaPlayerImpl::OnIdleTimeout() {
dalecurtis0431cbf2016-03-12 01:19:431500 DCHECK(main_task_runner_->BelongsToCurrentThread());
1501
sandersd35d2c3f2017-01-14 02:04:421502 // If we are attempting preroll, clear the stale flag.
1503 if (IsPrerollAttemptNeeded()) {
tguilbert1bb1c782017-01-23 21:15:111504 delegate_->ClearStaleFlag(delegate_id_);
sandersd35d2c3f2017-01-14 02:04:421505 return;
watkd026f792016-11-05 00:28:511506 }
sandersd50a635e2016-04-04 22:50:091507
sandersd35d2c3f2017-01-14 02:04:421508 UpdatePlayState();
dalecurtis0431cbf2016-03-12 01:19:431509}
1510
dalecurtisbb3eaac2016-01-27 21:10:251511void WebMediaPlayerImpl::OnPlay() {
Blink Reformat1c4d759e2017-04-09 16:34:541512 Play();
1513 client_->PlaybackStateChanged();
dalecurtisbb3eaac2016-01-27 21:10:251514}
1515
1516void WebMediaPlayerImpl::OnPause() {
Blink Reformat1c4d759e2017-04-09 16:34:541517 Pause();
1518 client_->PlaybackStateChanged();
dalecurtisbb3eaac2016-01-27 21:10:251519}
1520
1521void WebMediaPlayerImpl::OnVolumeMultiplierUpdate(double multiplier) {
1522 volume_multiplier_ = multiplier;
Blink Reformat1c4d759e2017-04-09 16:34:541523 SetVolume(volume_);
dalecurtisbb3eaac2016-01-27 21:10:251524}
1525
zqzhang8ac49002017-03-16 21:51:351526void WebMediaPlayerImpl::OnBecamePersistentVideo(bool value) {
Blink Reformat1c4d759e2017-04-09 16:34:541527 client_->OnBecamePersistentVideo(value);
zqzhang8ac49002017-03-16 21:51:351528}
1529
watkdee516f2016-02-18 02:22:191530void WebMediaPlayerImpl::ScheduleRestart() {
sandersd50a635e2016-04-04 22:50:091531 // TODO(watk): All restart logic should be moved into PipelineController.
tguilbert350936ff2017-02-24 05:39:271532 if (pipeline_controller_.IsPipelineRunning() &&
1533 !pipeline_controller_.IsPipelineSuspended()) {
watkdee516f2016-02-18 02:22:191534 pending_suspend_resume_cycle_ = true;
sandersd50a635e2016-04-04 22:50:091535 UpdatePlayState();
watkdee516f2016-02-18 02:22:191536 }
1537}
1538
Blink Reformat1c4d759e2017-04-09 16:34:541539void WebMediaPlayerImpl::RequestRemotePlaybackDisabled(bool disabled) {
miu77f914c2016-11-19 23:56:181540 if (observer_)
1541 observer_->OnRemotePlaybackDisabled(disabled);
1542}
1543
hubbed5f36882016-01-15 22:40:371544#if defined(OS_ANDROID) // WMPI_CAST
Blink Reformat1c4d759e2017-04-09 16:34:541545bool WebMediaPlayerImpl::IsRemote() const {
hubbed5f36882016-01-15 22:40:371546 return cast_impl_.isRemote();
1547}
1548
1549void WebMediaPlayerImpl::SetMediaPlayerManager(
1550 RendererMediaPlayerManagerInterface* media_player_manager) {
1551 cast_impl_.SetMediaPlayerManager(media_player_manager);
1552}
1553
Blink Reformat1c4d759e2017-04-09 16:34:541554void WebMediaPlayerImpl::RequestRemotePlayback() {
hubbed5f36882016-01-15 22:40:371555 cast_impl_.requestRemotePlayback();
1556}
1557
Blink Reformat1c4d759e2017-04-09 16:34:541558void WebMediaPlayerImpl::RequestRemotePlaybackControl() {
hubbed5f36882016-01-15 22:40:371559 cast_impl_.requestRemotePlaybackControl();
1560}
1561
Blink Reformat1c4d759e2017-04-09 16:34:541562void WebMediaPlayerImpl::RequestRemotePlaybackStop() {
avayvod8d8c53b2016-11-04 16:10:301563 cast_impl_.requestRemotePlaybackStop();
1564}
1565
hubbed5f36882016-01-15 22:40:371566void WebMediaPlayerImpl::OnRemotePlaybackEnded() {
pkastingf5279482016-07-27 02:18:201567 DVLOG(1) << __func__;
hubbed5f36882016-01-15 22:40:371568 DCHECK(main_task_runner_->BelongsToCurrentThread());
1569
1570 ended_ = true;
Blink Reformat1c4d759e2017-04-09 16:34:541571 client_->TimeChanged();
hubbed5f36882016-01-15 22:40:371572}
1573
1574void WebMediaPlayerImpl::OnDisconnectedFromRemoteDevice(double t) {
sandersd1c0bba02016-03-04 23:14:081575 DoSeek(base::TimeDelta::FromSecondsD(t), false);
hubbed5f36882016-01-15 22:40:371576
hubbed5f36882016-01-15 22:40:371577 // We already told the delegate we're paused when remoting started.
Blink Reformat1c4d759e2017-04-09 16:34:541578 client_->PlaybackStateChanged();
1579 client_->DisconnectedFromRemoteDevice();
sandersd50a635e2016-04-04 22:50:091580
1581 UpdatePlayState();
hubbed5f36882016-01-15 22:40:371582}
1583
1584void WebMediaPlayerImpl::SuspendForRemote() {
sandersd50a635e2016-04-04 22:50:091585 if (pipeline_controller_.IsPipelineSuspended()) {
hubbed5f36882016-01-15 22:40:371586 scoped_refptr<VideoFrame> frame = cast_impl_.GetCastingBanner();
sandersd50a635e2016-04-04 22:50:091587 if (frame)
dalecurtise9c89e92016-05-20 19:38:001588 compositor_->PaintSingleFrame(frame);
hubbed5f36882016-01-15 22:40:371589 }
sandersd50a635e2016-04-04 22:50:091590
1591 UpdatePlayState();
hubbed5f36882016-01-15 22:40:371592}
1593
1594gfx::Size WebMediaPlayerImpl::GetCanvasSize() const {
1595 if (!video_weblayer_)
1596 return pipeline_metadata_.natural_size;
1597
Blink Reformat1c4d759e2017-04-09 16:34:541598 return video_weblayer_->Bounds();
hubbed5f36882016-01-15 22:40:371599}
1600
1601void WebMediaPlayerImpl::SetDeviceScaleFactor(float scale_factor) {
1602 cast_impl_.SetDeviceScaleFactor(scale_factor);
1603}
hubbee4027f92016-05-19 05:18:131604
tguilbert25a4d112016-10-13 21:56:511605void WebMediaPlayerImpl::SetUseFallbackPath(bool use_fallback_path) {
1606 use_fallback_path_ = use_fallback_path;
1607}
hubbed5f36882016-01-15 22:40:371608#endif // defined(OS_ANDROID) // WMPI_CAST
1609
Blink Reformat1c4d759e2017-04-09 16:34:541610void WebMediaPlayerImpl::SetPoster(const blink::WebURL& poster) {
xjzc102fd82017-01-04 20:13:531611#if defined(OS_ANDROID)
1612 cast_impl_.setPoster(poster);
1613#endif
1614
1615 if (observer_)
1616 observer_->OnSetPoster(poster);
1617}
1618
[email protected]fee8a902014-06-03 13:43:361619void WebMediaPlayerImpl::DataSourceInitialized(bool success) {
pkastingf5279482016-07-27 02:18:201620 DVLOG(1) << __func__;
acolwellb4034942014-08-28 15:42:431621 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]a9415292012-01-19 19:55:201622
dalecurtisea27a3ed2016-06-24 01:41:301623#if defined(OS_ANDROID)
1624 // We can't play HLS URLs with WebMediaPlayerImpl, so in cases where they are
1625 // encountered, instruct the HTML media element to create a new WebMediaPlayer
tguilbertd7e079c2017-02-07 01:16:241626 // instance with the correct URL to trigger the creation of WMPI with a
1627 // MediaPlayerRendererFactory instead.
dalecurtisea27a3ed2016-06-24 01:41:301628 //
tguilbertd7e079c2017-02-07 01:16:241629 // TODO(tguilbert): Allow 'hotswapping' renderer factories to prevent reloads
1630 // and/or rely on demuxer extracted MediaContainerNames. See crbug.com/663503.
tguilbert25a4d112016-10-13 21:56:511631 if (data_source_ && !use_fallback_path_) {
dalecurtisea27a3ed2016-06-24 01:41:301632 const GURL url_after_redirects = data_source_->GetUrlAfterRedirects();
qinmin0d9521272016-10-10 20:43:191633 if (MediaCodecUtil::IsHLSURL(url_after_redirects)) {
Blink Reformat1c4d759e2017-04-09 16:34:541634 client_->RequestReload(url_after_redirects);
dalecurtisea27a3ed2016-06-24 01:41:301635 // |this| may be destructed, do nothing after this.
1636 return;
1637 }
1638 }
1639#endif
1640
[email protected]d250190da3b2012-07-23 22:57:301641 if (!success) {
Blink Reformat1c4d759e2017-04-09 16:34:541642 SetNetworkState(WebMediaPlayer::kNetworkStateFormatError);
sandersd50a635e2016-04-04 22:50:091643
1644 // Not really necessary, since the pipeline was never started, but it at
1645 // least this makes sure that the error handling code is in sync.
1646 UpdatePlayState();
1647
[email protected]a9415292012-01-19 19:55:201648 return;
1649 }
1650
[email protected]ef8394c2013-08-21 20:26:301651 StartPipeline();
[email protected]a9415292012-01-19 19:55:201652}
1653
[email protected]122f40252012-06-12 05:01:561654void WebMediaPlayerImpl::NotifyDownloading(bool is_downloading) {
pkastingf5279482016-07-27 02:18:201655 DVLOG(1) << __func__;
Blink Reformat1c4d759e2017-04-09 16:34:541656 if (!is_downloading && network_state_ == WebMediaPlayer::kNetworkStateLoading)
1657 SetNetworkState(WebMediaPlayer::kNetworkStateIdle);
1658 else if (is_downloading &&
1659 network_state_ == WebMediaPlayer::kNetworkStateIdle)
1660 SetNetworkState(WebMediaPlayer::kNetworkStateLoading);
[email protected]122f40252012-06-12 05:01:561661 media_log_->AddEvent(
tguilbert350936ff2017-02-24 05:39:271662 media_log_->CreateBooleanEvent(MediaLogEvent::NETWORK_ACTIVITY_SET,
1663 "is_downloading_data", is_downloading));
[email protected]122f40252012-06-12 05:01:561664}
1665
watkf835a792016-06-24 23:24:401666void WebMediaPlayerImpl::OnSurfaceCreated(int surface_id) {
tsunghungee562e92016-07-20 18:03:311667 overlay_surface_id_ = surface_id;
dalecurtis4b632fce22016-11-10 00:52:171668 if (!set_surface_cb_.is_null()) {
1669 // If restart is required, the callback is one-shot only.
1670 if (decoder_requires_restart_for_overlay_)
1671 base::ResetAndReturn(&set_surface_cb_).Run(surface_id);
1672 else
1673 set_surface_cb_.Run(surface_id);
1674 }
watkf835a792016-06-24 23:24:401675}
1676
watkdee516f2016-02-18 02:22:191677void WebMediaPlayerImpl::OnSurfaceRequested(
dalecurtis4b632fce22016-11-10 00:52:171678 bool decoder_requires_restart_for_overlay,
1679 const SurfaceCreatedCB& set_surface_cb) {
watkdee516f2016-02-18 02:22:191680 DCHECK(main_task_runner_->BelongsToCurrentThread());
1681 DCHECK(surface_manager_);
tguilbert25a4d112016-10-13 21:56:511682 DCHECK(!use_fallback_path_);
watkdee516f2016-02-18 02:22:191683
1684 // A null callback indicates that the decoder is going away.
dalecurtis4b632fce22016-11-10 00:52:171685 if (set_surface_cb.is_null()) {
tsunghungee562e92016-07-20 18:03:311686 decoder_requires_restart_for_overlay_ = false;
dalecurtis4b632fce22016-11-10 00:52:171687 set_surface_cb_.Reset();
watkdee516f2016-02-18 02:22:191688 return;
1689 }
1690
dalecurtis4b632fce22016-11-10 00:52:171691 // If we get a surface request it means GpuVideoDecoder is initializing, so
1692 // until we get a null surface request, GVD is the active decoder.
1693 //
1694 // If |decoder_requires_restart_for_overlay| is true, we must restart the
1695 // pipeline for fullscreen transitions. The decoder is unable to switch
1696 // surfaces otherwise. If false, we simply need to tell the decoder about the
1697 // new surface and it will handle things seamlessly.
1698 decoder_requires_restart_for_overlay_ = decoder_requires_restart_for_overlay;
1699 set_surface_cb_ = set_surface_cb;
1700
1701 // If we're waiting for the surface to arrive, OnSurfaceCreated() will be
1702 // called later when it arrives; so do nothing for now.
1703 if (overlay_enabled_ && overlay_surface_id_ == SurfaceManager::kNoSurfaceID)
1704 return;
1705
1706 OnSurfaceCreated(overlay_surface_id_);
watkdee516f2016-02-18 02:22:191707}
1708
dcheng3076abbf2016-04-22 20:42:391709std::unique_ptr<Renderer> WebMediaPlayerImpl::CreateRenderer() {
dcheng37b415b92017-01-27 20:17:431710 DCHECK(main_task_runner_->BelongsToCurrentThread());
1711
tsunghungee562e92016-07-20 18:03:311712 if (force_video_overlays_)
1713 EnableOverlay();
1714
watkdee516f2016-02-18 02:22:191715 RequestSurfaceCB request_surface_cb;
1716#if defined(OS_ANDROID)
dcheng37b415b92017-01-27 20:17:431717 request_surface_cb = BindToCurrentLoop(
1718 base::Bind(&WebMediaPlayerImpl::OnSurfaceRequested, AsWeakPtr()));
watkdee516f2016-02-18 02:22:191719#endif
sandersd1e49fb62015-12-12 01:18:061720 return renderer_factory_->CreateRenderer(
1721 media_task_runner_, worker_task_runner_, audio_source_provider_.get(),
watkdee516f2016-02-18 02:22:191722 compositor_, request_surface_cb);
sandersd1e49fb62015-12-12 01:18:061723}
1724
[email protected]ef8394c2013-08-21 20:26:301725void WebMediaPlayerImpl::StartPipeline() {
acolwellb4034942014-08-28 15:42:431726 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]ddbc6ff2013-04-19 15:28:331727
xhwange8c4181a2014-12-06 08:10:011728 Demuxer::EncryptedMediaInitDataCB encrypted_media_init_data_cb =
dcheng37b415b92017-01-27 20:17:431729 BindToCurrentLoop(base::Bind(
1730 &WebMediaPlayerImpl::OnEncryptedMediaInitData, AsWeakPtr()));
[email protected]2b57e2e2014-05-09 11:07:251731
tguilbert25a4d112016-10-13 21:56:511732 if (use_fallback_path_) {
tguilbert9881bc22016-10-27 03:13:411733 demuxer_.reset(
1734 new MediaUrlDemuxer(media_task_runner_, fallback_url_,
Blink Reformat1c4d759e2017-04-09 16:34:541735 frame_->GetDocument().FirstPartyForCookies()));
tguilbert25a4d112016-10-13 21:56:511736 pipeline_controller_.Start(demuxer_.get(), this, false, false);
1737 return;
1738 }
1739
[email protected]ddbc6ff2013-04-19 15:28:331740 // Figure out which demuxer to use.
Blink Reformat1c4d759e2017-04-09 16:34:541741 if (load_type_ != kLoadTypeMediaSource) {
[email protected]ddbc6ff2013-04-19 15:28:331742 DCHECK(!chunk_demuxer_);
[email protected]f5443ef72013-04-22 04:03:381743 DCHECK(data_source_);
1744
j.isorcef6778e652015-11-16 17:14:251745#if !defined(MEDIA_DISABLE_FFMPEG)
servolk81e01e02016-03-05 03:29:151746 Demuxer::MediaTracksUpdatedCB media_tracks_updated_cb =
dcheng37b415b92017-01-27 20:17:431747 BindToCurrentLoop(base::Bind(
1748 &WebMediaPlayerImpl::OnFFmpegMediaTracksUpdated, AsWeakPtr()));
servolk81e01e02016-03-05 03:29:151749
xhwange8c4181a2014-12-06 08:10:011750 demuxer_.reset(new FFmpegDemuxer(media_task_runner_, data_source_.get(),
servolk81e01e02016-03-05 03:29:151751 encrypted_media_init_data_cb,
1752 media_tracks_updated_cb, media_log_));
j.isorcef6778e652015-11-16 17:14:251753#else
alokp967c902452016-05-06 05:21:371754 OnError(PipelineStatus::DEMUXER_ERROR_COULD_NOT_OPEN);
j.isorcef6778e652015-11-16 17:14:251755 return;
1756#endif
[email protected]ddbc6ff2013-04-19 15:28:331757 } else {
[email protected]f5443ef72013-04-22 04:03:381758 DCHECK(!chunk_demuxer_);
1759 DCHECK(!data_source_);
1760
acolwell9e0840d2014-09-06 19:01:321761 chunk_demuxer_ = new ChunkDemuxer(
dcheng37b415b92017-01-27 20:17:431762 BindToCurrentLoop(
1763 base::Bind(&WebMediaPlayerImpl::OnDemuxerOpened, AsWeakPtr())),
chcunningham967db2f2016-11-02 20:47:171764 encrypted_media_init_data_cb, media_log_);
[email protected]f5443ef72013-04-22 04:03:381765 demuxer_.reset(chunk_demuxer_);
servolkf94b4602017-01-31 16:44:271766
1767 if (base::FeatureList::IsEnabled(kMemoryPressureBasedSourceBufferGC)) {
1768 // base::Unretained is safe because |this| owns memory_pressure_listener_.
1769 memory_pressure_listener_ =
1770 base::MakeUnique<base::MemoryPressureListener>(base::Bind(
1771 &WebMediaPlayerImpl::OnMemoryPressure, base::Unretained(this)));
1772 }
[email protected]ddbc6ff2013-04-19 15:28:331773 }
1774
sandersdb5e21462016-03-09 01:49:071775 // TODO(sandersd): FileSystem objects may also be non-static, but due to our
1776 // caching layer such situations are broken already. http://crbug.com/593159
1777 bool is_static = !chunk_demuxer_;
avayvod102cdb62017-01-07 03:11:091778 bool is_streaming = IsStreaming();
sandersdb8eb5f1d2016-11-19 04:04:021779 UMA_HISTOGRAM_BOOLEAN("Media.IsStreaming", is_streaming);
sandersdb5e21462016-03-09 01:49:071780
[email protected]f5443ef72013-04-22 04:03:381781 // ... and we're ready to go!
sandersd1e49fb62015-12-12 01:18:061782 // TODO(sandersd): On Android, defer Start() if the tab is not visible.
sandersdb8eb5f1d2016-11-19 04:04:021783 seeking_ = true;
alokp967c902452016-05-06 05:21:371784 pipeline_controller_.Start(demuxer_.get(), this, is_streaming, is_static);
[email protected]f5443ef72013-04-22 04:03:381785}
1786
1787void WebMediaPlayerImpl::SetNetworkState(WebMediaPlayer::NetworkState state) {
pkastingf5279482016-07-27 02:18:201788 DVLOG(1) << __func__ << "(" << state << ")";
acolwellb4034942014-08-28 15:42:431789 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]f5443ef72013-04-22 04:03:381790 network_state_ = state;
1791 // Always notify to ensure client has the latest value.
Blink Reformat1c4d759e2017-04-09 16:34:541792 client_->NetworkStateChanged();
[email protected]f5443ef72013-04-22 04:03:381793}
1794
1795void WebMediaPlayerImpl::SetReadyState(WebMediaPlayer::ReadyState state) {
pkastingf5279482016-07-27 02:18:201796 DVLOG(1) << __func__ << "(" << state << ")";
acolwellb4034942014-08-28 15:42:431797 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]f5443ef72013-04-22 04:03:381798
Blink Reformat1c4d759e2017-04-09 16:34:541799 if (state == WebMediaPlayer::kReadyStateHaveEnoughData && data_source_ &&
[email protected]fee8a902014-06-03 13:43:361800 data_source_->assume_fully_buffered() &&
Blink Reformat1c4d759e2017-04-09 16:34:541801 network_state_ == WebMediaPlayer::kNetworkStateLoading)
1802 SetNetworkState(WebMediaPlayer::kNetworkStateLoaded);
[email protected]f5443ef72013-04-22 04:03:381803
1804 ready_state_ = state;
sandersd50a635e2016-04-04 22:50:091805 highest_ready_state_ = std::max(highest_ready_state_, ready_state_);
1806
[email protected]f5443ef72013-04-22 04:03:381807 // Always notify to ensure client has the latest value.
Blink Reformat1c4d759e2017-04-09 16:34:541808 client_->ReadyStateChanged();
[email protected]f5443ef72013-04-22 04:03:381809}
1810
Blink Reformat1c4d759e2017-04-09 16:34:541811blink::WebAudioSourceProvider* WebMediaPlayerImpl::GetAudioSourceProvider() {
[email protected]ff875be52013-06-02 23:47:381812 return audio_source_provider_.get();
[email protected]f5443ef72013-04-22 04:03:381813}
1814
tguilbert350936ff2017-02-24 05:39:271815static void GetCurrentFrameAndSignal(VideoFrameCompositor* compositor,
1816 scoped_refptr<VideoFrame>* video_frame_out,
1817 base::WaitableEvent* event) {
[email protected]dd061e12014-05-06 19:21:221818 TRACE_EVENT0("media", "GetCurrentFrameAndSignal");
dalecurtis44ce4de2015-05-11 18:42:071819 *video_frame_out = compositor->GetCurrentFrameAndUpdateIfStale();
[email protected]dd061e12014-05-06 19:21:221820 event->Signal();
1821}
1822
tguilbert350936ff2017-02-24 05:39:271823scoped_refptr<VideoFrame> WebMediaPlayerImpl::GetCurrentFrameFromCompositor() {
xhwang213e50c2016-10-10 23:56:311824 DCHECK(main_task_runner_->BelongsToCurrentThread());
[email protected]dd061e12014-05-06 19:21:221825 TRACE_EVENT0("media", "WebMediaPlayerImpl::GetCurrentFrameFromCompositor");
xhwang213e50c2016-10-10 23:56:311826
1827 // Needed when the |main_task_runner_| and |compositor_task_runner_| are the
1828 // same to avoid deadlock in the Wait() below.
kainino36eeff82017-03-30 00:55:301829 if (compositor_task_runner_->BelongsToCurrentThread()) {
1830 scoped_refptr<VideoFrame> video_frame =
1831 compositor_->GetCurrentFrameAndUpdateIfStale();
1832 if (!video_frame) {
1833 return nullptr;
1834 }
1835 last_uploaded_frame_size_ = video_frame->natural_size();
1836 last_uploaded_frame_timestamp_ = video_frame->timestamp();
1837 return video_frame;
1838 }
[email protected]dd061e12014-05-06 19:21:221839
1840 // Use a posted task and waitable event instead of a lock otherwise
1841 // WebGL/Canvas can see different content than what the compositor is seeing.
acolwell9e0840d2014-09-06 19:01:321842 scoped_refptr<VideoFrame> video_frame;
gab0d77c7cb2016-06-02 00:00:231843 base::WaitableEvent event(base::WaitableEvent::ResetPolicy::AUTOMATIC,
1844 base::WaitableEvent::InitialState::NOT_SIGNALED);
tguilbert350936ff2017-02-24 05:39:271845 compositor_task_runner_->PostTask(
1846 FROM_HERE,
1847 base::Bind(&GetCurrentFrameAndSignal, base::Unretained(compositor_),
1848 &video_frame, &event));
[email protected]dd061e12014-05-06 19:21:221849 event.Wait();
kainino36eeff82017-03-30 00:55:301850
1851 if (!video_frame) {
1852 return nullptr;
1853 }
1854 last_uploaded_frame_size_ = video_frame->natural_size();
1855 last_uploaded_frame_timestamp_ = video_frame->timestamp();
[email protected]dd061e12014-05-06 19:21:221856 return video_frame;
1857}
1858
sandersd50a635e2016-04-04 22:50:091859void WebMediaPlayerImpl::UpdatePlayState() {
xhwang213e50c2016-10-10 23:56:311860 DCHECK(main_task_runner_->BelongsToCurrentThread());
1861
hubbed5f36882016-01-15 22:40:371862#if defined(OS_ANDROID) // WMPI_CAST
Blink Reformat1c4d759e2017-04-09 16:34:541863 bool is_remote = IsRemote();
xjz4e5d4bf32017-02-15 21:26:351864 bool can_auto_suspend = true;
sandersd50a635e2016-04-04 22:50:091865#else
1866 bool is_remote = false;
xjz4e5d4bf32017-02-15 21:26:351867 bool can_auto_suspend = !disable_pipeline_auto_suspend_ && !IsStreaming();
hubbed5f36882016-01-15 22:40:371868#endif
xhwang213e50c2016-10-10 23:56:311869
dalecurtis8b8505e72016-06-10 21:59:171870 bool is_suspended = pipeline_controller_.IsSuspended();
avayvod39c102402016-11-23 21:43:131871 bool is_backgrounded = IsBackgroundedSuspendEnabled() && IsHidden();
sandersdaaff1a652016-11-17 01:47:251872 PlayState state = UpdatePlayState_ComputePlayState(
xjz4e5d4bf32017-02-15 21:26:351873 is_remote, can_auto_suspend, is_suspended, is_backgrounded);
sandersd35d2c3f2017-01-14 02:04:421874 SetDelegateState(state.delegate_state, state.is_idle);
sandersd50a635e2016-04-04 22:50:091875 SetMemoryReportingState(state.is_memory_reporting_enabled);
1876 SetSuspendState(state.is_suspended || pending_suspend_resume_cycle_);
1877}
dalecurtis5bbc487e2016-02-27 04:15:051878
sandersd35d2c3f2017-01-14 02:04:421879void WebMediaPlayerImpl::SetDelegateState(DelegateState new_state,
1880 bool is_idle) {
tguilbert1bb1c782017-01-23 21:15:111881 DCHECK(delegate_);
dalecurtis5bbc487e2016-02-27 04:15:051882
sandersd35d2c3f2017-01-14 02:04:421883 // Prevent duplicate delegate calls.
1884 // TODO(sandersd): Move this deduplication into the delegate itself.
1885 // TODO(sandersd): WebContentsObserverSanityChecker does not allow sending the
1886 // 'playing' IPC more than once in a row, even if the metadata has changed.
1887 // Figure out whether it should.
Blink Reformat1c4d759e2017-04-09 16:34:541888 bool has_audio = HasAudio() && !client_->IsAutoplayingMuted();
sandersd35d2c3f2017-01-14 02:04:421889 if (delegate_state_ == new_state &&
1890 (delegate_state_ != DelegateState::PLAYING ||
1891 delegate_has_audio_ == has_audio)) {
1892 return;
mlamouri910111362016-11-04 11:28:241893 }
sandersd50a635e2016-04-04 22:50:091894 delegate_state_ = new_state;
sandersd35d2c3f2017-01-14 02:04:421895 delegate_has_audio_ = has_audio;
sandersd50a635e2016-04-04 22:50:091896
sandersd35d2c3f2017-01-14 02:04:421897 switch (new_state) {
sandersd50a635e2016-04-04 22:50:091898 case DelegateState::GONE:
1899 delegate_->PlayerGone(delegate_id_);
1900 break;
mlamouri910111362016-11-04 11:28:241901 case DelegateState::PLAYING: {
zqzhang5d8eab72016-08-26 20:34:301902 delegate_->DidPlay(
Blink Reformat1c4d759e2017-04-09 16:34:541903 delegate_id_, HasVideo(), has_audio,
avayvodcc273dd2017-01-19 19:35:121904 media::DurationToMediaContentType(GetPipelineMediaDuration()));
sandersd50a635e2016-04-04 22:50:091905 break;
mlamouri910111362016-11-04 11:28:241906 }
sandersd50a635e2016-04-04 22:50:091907 case DelegateState::PAUSED:
sandersd35d2c3f2017-01-14 02:04:421908 delegate_->DidPause(delegate_id_);
sandersd50a635e2016-04-04 22:50:091909 break;
dalecurtis0f0097a2015-12-01 17:40:471910 }
sandersd35d2c3f2017-01-14 02:04:421911
1912 delegate_->SetIdle(delegate_id_, is_idle);
dalecurtis0f0097a2015-12-01 17:40:471913}
1914
sandersd50a635e2016-04-04 22:50:091915void WebMediaPlayerImpl::SetMemoryReportingState(
1916 bool is_memory_reporting_enabled) {
1917 if (memory_usage_reporting_timer_.IsRunning() ==
1918 is_memory_reporting_enabled) {
hubbed5f36882016-01-15 22:40:371919 return;
sandersd50a635e2016-04-04 22:50:091920 }
sandersd1c0bba02016-03-04 23:14:081921
sandersd50a635e2016-04-04 22:50:091922 if (is_memory_reporting_enabled) {
1923 memory_usage_reporting_timer_.Start(FROM_HERE,
1924 base::TimeDelta::FromSeconds(2), this,
1925 &WebMediaPlayerImpl::ReportMemoryUsage);
1926 } else {
1927 memory_usage_reporting_timer_.Stop();
1928 ReportMemoryUsage();
1929 }
1930}
1931
1932void WebMediaPlayerImpl::SetSuspendState(bool is_suspended) {
xhwang213e50c2016-10-10 23:56:311933 DCHECK(main_task_runner_->BelongsToCurrentThread());
jameswest451a5bb2017-01-27 03:59:391934 if (!suspend_enabled_) {
1935 DCHECK(!pipeline_controller_.IsSuspended());
1936 return;
1937 }
xhwang213e50c2016-10-10 23:56:311938
sandersd50a635e2016-04-04 22:50:091939 // Do not change the state after an error has occurred.
1940 // TODO(sandersd): Update PipelineController to remove the need for this.
1941 if (IsNetworkStateError(network_state_))
sandersd1c0bba02016-03-04 23:14:081942 return;
1943
jameswest451a5bb2017-01-27 03:59:391944 if (is_suspended) {
sandersd35d2c3f2017-01-14 02:04:421945 // If we were not resumed for long enough to satisfy the preroll attempt,
1946 // reset the clock.
1947 if (!preroll_attempt_pending_ && IsPrerollAttemptNeeded()) {
1948 preroll_attempt_pending_ = true;
1949 preroll_attempt_start_time_ = base::TimeTicks();
1950 }
sandersd50a635e2016-04-04 22:50:091951 pipeline_controller_.Suspend();
1952 } else {
sandersd35d2c3f2017-01-14 02:04:421953 // When resuming, start the preroll attempt clock.
1954 if (preroll_attempt_pending_) {
1955 preroll_attempt_pending_ = false;
1956 preroll_attempt_start_time_ = tick_clock_->NowTicks();
1957 }
sandersd50a635e2016-04-04 22:50:091958 pipeline_controller_.Resume();
1959 }
1960}
1961
1962WebMediaPlayerImpl::PlayState
1963WebMediaPlayerImpl::UpdatePlayState_ComputePlayState(bool is_remote,
xjz4e5d4bf32017-02-15 21:26:351964 bool can_auto_suspend,
dalecurtis8b8505e72016-06-10 21:59:171965 bool is_suspended,
sandersd50a635e2016-04-04 22:50:091966 bool is_backgrounded) {
1967 PlayState result;
1968
tguilbert1bb1c782017-01-23 21:15:111969 bool must_suspend = delegate_->IsFrameClosed();
1970 bool is_stale = delegate_->IsStale(delegate_id_);
sandersd35d2c3f2017-01-14 02:04:421971
sandersd50a635e2016-04-04 22:50:091972 // This includes both data source (before pipeline startup) and pipeline
1973 // errors.
1974 bool has_error = IsNetworkStateError(network_state_);
1975
dalecurtiscc8baf72016-10-27 01:49:441976 // After HaveFutureData, Blink will call play() if the state is not paused;
1977 // prior to this point |paused_| is not accurate.
sandersd50a635e2016-04-04 22:50:091978 bool have_future_data =
Blink Reformat1c4d759e2017-04-09 16:34:541979 highest_ready_state_ >= WebMediaPlayer::kReadyStateHaveFutureData;
sandersd50a635e2016-04-04 22:50:091980
avayvod65fad272017-02-24 01:00:481981 // Background suspend is only enabled for paused players.
1982 // In the case of players with audio the session should be kept.
1983 bool background_suspended =
xjz4e5d4bf32017-02-15 21:26:351984 can_auto_suspend && is_backgrounded && paused_ && have_future_data;
sandersd50a635e2016-04-04 22:50:091985
dalecurtiscc8baf72016-10-27 01:49:441986 // Idle suspension is allowed prior to have future data since there exist
1987 // mechanisms to exit the idle state when the player is capable of reaching
1988 // the have future data state; see didLoadingProgress().
1989 //
sandersd50a635e2016-04-04 22:50:091990 // TODO(sandersd): Make the delegate suspend idle players immediately when
1991 // hidden.
sandersdaaff1a652016-11-17 01:47:251992 bool idle_suspended =
xjz4e5d4bf32017-02-15 21:26:351993 can_auto_suspend && is_stale && paused_ && !seeking_ && !overlay_enabled_;
dalecurtise7120dc2016-09-03 02:54:351994
1995 // If we're already suspended, see if we can wait for user interaction. Prior
sandersd35d2c3f2017-01-14 02:04:421996 // to HaveFutureData, we require |is_stale| to remain suspended. |is_stale|
dalecurtise7120dc2016-09-03 02:54:351997 // will be cleared when we receive data which may take us to HaveFutureData.
1998 bool can_stay_suspended =
sandersd35d2c3f2017-01-14 02:04:421999 (is_stale || have_future_data) && is_suspended && paused_ && !seeking_;
sandersd50a635e2016-04-04 22:50:092000
2001 // Combined suspend state.
sandersd35d2c3f2017-01-14 02:04:422002 result.is_suspended = is_remote || must_suspend || idle_suspended ||
avayvod65fad272017-02-24 01:00:482003 background_suspended || can_stay_suspended;
sandersd50a635e2016-04-04 22:50:092004
2005 // We do not treat |playback_rate_| == 0 as paused. For the media session,
2006 // being paused implies displaying a play button, which is incorrect in this
2007 // case. For memory usage reporting, we just use the same definition (but we
2008 // don't have to).
2009 //
2010 // Similarly, we don't consider |ended_| to be paused. Blink will immediately
2011 // call pause() or seek(), so |ended_| should not affect the computation.
2012 // Despite that, |ended_| does result in a separate paused state, to simplfy
2013 // the contract for SetDelegateState().
2014 //
avayvod65fad272017-02-24 01:00:482015 // |has_remote_controls| indicates if the player can be controlled outside the
2016 // page (e.g. via the notification controls or by audio focus events). Idle
sandersd50a635e2016-04-04 22:50:092017 // suspension does not destroy the media session, because we expect that the
avayvod5f34b642017-03-23 03:14:042018 // notification controls (and audio focus) remain. With some exceptions for
2019 // background videos, the player only needs to have audio to have controls
2020 // (requires |have_future_data|).
2021 //
2022 // |alive| indicates if the player should be present (not |GONE|) to the
2023 // delegate, either paused or playing. The following must be true for the
2024 // player:
sandersd50a635e2016-04-04 22:50:092025 // - |have_future_data|, since we need to know whether we are paused to
avayvod65fad272017-02-24 01:00:482026 // correctly configure the session and also because the tracks and
avayvod5f34b642017-03-23 03:14:042027 // duration are passed to DidPlay(),
2028 // - |is_remote| is false as remote playback is not handled by the delegate,
2029 // - |has_error| is false as player should have no errors,
2030 // - |background_suspended| is false, otherwise |has_remote_controls| must
2031 // be true.
sandersd50a635e2016-04-04 22:50:092032 //
avayvod65fad272017-02-24 01:00:482033 // TODO(sandersd): If Blink told us the paused state sooner, we could detect
2034 // if the remote controls are available sooner.
2035
2036 // Background videos with audio don't have remote controls if background
2037 // suspend is enabled and resuming background videos is not (original Android
2038 // behavior).
2039 bool backgrounded_video_has_no_remote_controls =
2040 IsBackgroundedSuspendEnabled() && !IsResumeBackgroundVideosEnabled() &&
Blink Reformat1c4d759e2017-04-09 16:34:542041 is_backgrounded && HasVideo();
sandersd50a635e2016-04-04 22:50:092042 bool can_play = !has_error && !is_remote && have_future_data;
avayvod5f34b642017-03-23 03:14:042043 bool has_remote_controls =
Blink Reformat1c4d759e2017-04-09 16:34:542044 HasAudio() && !backgrounded_video_has_no_remote_controls;
avayvod5f34b642017-03-23 03:14:042045 bool alive = can_play && !must_suspend &&
2046 (!background_suspended || has_remote_controls);
2047 if (!alive) {
sandersd50a635e2016-04-04 22:50:092048 result.delegate_state = DelegateState::GONE;
tguilbert1bb1c782017-01-23 21:15:112049 result.is_idle = delegate_->IsIdle(delegate_id_);
avayvod65fad272017-02-24 01:00:482050 } else if (paused_) {
sandersd35d2c3f2017-01-14 02:04:422051 // TODO(sandersd): Is it possible to have a suspended session, be ended,
2052 // and not be paused? If so we should be in a PLAYING state.
dalecurtise7120dc2016-09-03 02:54:352053 result.delegate_state =
sandersd35d2c3f2017-01-14 02:04:422054 ended_ ? DelegateState::GONE : DelegateState::PAUSED;
2055 result.is_idle = !seeking_;
sandersd50a635e2016-04-04 22:50:092056 } else {
2057 result.delegate_state = DelegateState::PLAYING;
sandersd35d2c3f2017-01-14 02:04:422058 result.is_idle = false;
sandersd50a635e2016-04-04 22:50:092059 }
2060
dalecurtis8b8505e72016-06-10 21:59:172061 // It's not critical if some cases where memory usage can change are missed,
sandersd50a635e2016-04-04 22:50:092062 // since media memory changes are usually gradual.
2063 result.is_memory_reporting_enabled =
sandersd35d2c3f2017-01-14 02:04:422064 can_play && !result.is_suspended && (!paused_ || seeking_);
sandersd50a635e2016-04-04 22:50:092065
2066 return result;
dalecurtis0f0097a2015-12-01 17:40:472067}
2068
dalecurtis83266c72015-10-29 18:43:202069void WebMediaPlayerImpl::ReportMemoryUsage() {
2070 DCHECK(main_task_runner_->BelongsToCurrentThread());
2071
wdzierzanowskifd4cd91c52015-12-02 23:50:202072 // About base::Unretained() usage below: We destroy |demuxer_| on the main
2073 // thread. Before that, however, ~WebMediaPlayerImpl() posts a task to the
2074 // media thread and waits for it to finish. Hence, the GetMemoryUsage() task
2075 // posted here must finish earlier.
2076
2077 if (demuxer_) {
2078 base::PostTaskAndReplyWithResult(
2079 media_task_runner_.get(), FROM_HERE,
2080 base::Bind(&Demuxer::GetMemoryUsage, base::Unretained(demuxer_.get())),
2081 base::Bind(&WebMediaPlayerImpl::FinishMemoryUsageReport, AsWeakPtr()));
2082 } else {
2083 FinishMemoryUsageReport(0);
2084 }
2085}
2086
2087void WebMediaPlayerImpl::FinishMemoryUsageReport(int64_t demuxer_memory_usage) {
2088 DCHECK(main_task_runner_->BelongsToCurrentThread());
2089
avayvodc4bfb0e62017-01-13 01:07:012090 const PipelineStatistics stats = GetPipelineStatistics();
servolk639473e492016-12-15 04:14:202091 const int64_t data_source_memory_usage =
2092 data_source_ ? data_source_->GetMemoryUsage() : 0;
dalecurtis83266c72015-10-29 18:43:202093 const int64_t current_memory_usage =
2094 stats.audio_memory_usage + stats.video_memory_usage +
servolk639473e492016-12-15 04:14:202095 data_source_memory_usage + demuxer_memory_usage;
dalecurtis83266c72015-10-29 18:43:202096
dalecurtis3a7d38f42016-03-07 21:17:132097 // Note, this isn't entirely accurate, there may be VideoFrames held by the
2098 // compositor or other resources that we're unaware of.
2099
dalecurtis83266c72015-10-29 18:43:202100 DVLOG(2) << "Memory Usage -- Audio: " << stats.audio_memory_usage
servolk639473e492016-12-15 04:14:202101 << ", Video: " << stats.video_memory_usage
2102 << ", DataSource: " << data_source_memory_usage
wdzierzanowskifd4cd91c52015-12-02 23:50:202103 << ", Demuxer: " << demuxer_memory_usage;
dalecurtis83266c72015-10-29 18:43:202104
2105 const int64_t delta = current_memory_usage - last_reported_memory_usage_;
2106 last_reported_memory_usage_ = current_memory_usage;
2107 adjust_allocated_memory_cb_.Run(delta);
servolk639473e492016-12-15 04:14:202108
Blink Reformat1c4d759e2017-04-09 16:34:542109 if (HasAudio()) {
servolk639473e492016-12-15 04:14:202110 UMA_HISTOGRAM_MEMORY_KB("Media.WebMediaPlayerImpl.Memory.Audio",
2111 stats.audio_memory_usage / 1024);
2112 }
Blink Reformat1c4d759e2017-04-09 16:34:542113 if (HasVideo()) {
servolk639473e492016-12-15 04:14:202114 UMA_HISTOGRAM_MEMORY_KB("Media.WebMediaPlayerImpl.Memory.Video",
2115 stats.video_memory_usage / 1024);
2116 }
2117 if (data_source_) {
2118 UMA_HISTOGRAM_MEMORY_KB("Media.WebMediaPlayerImpl.Memory.DataSource",
2119 data_source_memory_usage / 1024);
2120 }
2121 if (demuxer_) {
2122 UMA_HISTOGRAM_MEMORY_KB("Media.WebMediaPlayerImpl.Memory.Demuxer",
2123 demuxer_memory_usage / 1024);
2124 }
dalecurtis83266c72015-10-29 18:43:202125}
2126
dalecurtis8b8505e72016-06-10 21:59:172127void WebMediaPlayerImpl::ScheduleIdlePauseTimer() {
avayvod65fad272017-02-24 01:00:482128 // Only schedule the pause timer if we're not paused or paused but going to
avayvod52efd282017-03-07 21:13:042129 // resume when foregrounded, and are suspended and have audio.
2130 if ((paused_ && !paused_when_hidden_) ||
Blink Reformat1c4d759e2017-04-09 16:34:542131 !pipeline_controller_.IsSuspended() || !HasAudio()) {
dalecurtis8b8505e72016-06-10 21:59:172132 return;
avayvod52efd282017-03-07 21:13:042133 }
dalecurtis8b8505e72016-06-10 21:59:172134
2135#if defined(OS_ANDROID)
2136 // Remote players will be suspended and locally paused.
Blink Reformat1c4d759e2017-04-09 16:34:542137 if (IsRemote())
dalecurtis8b8505e72016-06-10 21:59:172138 return;
2139#endif
2140
2141 // Idle timeout chosen arbitrarily.
2142 background_pause_timer_.Start(FROM_HERE, base::TimeDelta::FromSeconds(5),
2143 this, &WebMediaPlayerImpl::OnPause);
2144}
2145
dalecurtis04bdb582016-08-17 22:15:232146void WebMediaPlayerImpl::CreateWatchTimeReporter() {
2147 // Create the watch time reporter and synchronize its initial state.
shaktisahu24189c12017-03-11 17:42:552148 watch_time_reporter_.reset(
Blink Reformat1c4d759e2017-04-09 16:34:542149 new WatchTimeReporter(HasAudio(), HasVideo(), !!chunk_demuxer_,
shaktisahu24189c12017-03-11 17:42:552150 is_encrypted_, embedded_media_experience_enabled_,
2151 media_log_, pipeline_metadata_.natural_size,
2152 base::Bind(&GetCurrentTimeInternal, this)));
dalecurtis04bdb582016-08-17 22:15:232153 watch_time_reporter_->OnVolumeChange(volume_);
tguilbert1bb1c782017-01-23 21:15:112154 if (delegate_->IsFrameHidden())
dalecurtis04bdb582016-08-17 22:15:232155 watch_time_reporter_->OnHidden();
2156 else
2157 watch_time_reporter_->OnShown();
2158}
2159
avayvod39c102402016-11-23 21:43:132160bool WebMediaPlayerImpl::IsHidden() const {
2161 DCHECK(main_task_runner_->BelongsToCurrentThread());
2162
tguilbert1bb1c782017-01-23 21:15:112163 return delegate_->IsFrameHidden() && !delegate_->IsFrameClosed();
avayvod39c102402016-11-23 21:43:132164}
2165
avayvod102cdb62017-01-07 03:11:092166bool WebMediaPlayerImpl::IsStreaming() const {
2167 return data_source_ && data_source_->IsStreaming();
2168}
2169
liberato2fd111be2017-01-04 00:25:062170bool WebMediaPlayerImpl::DoesOverlaySupportMetadata() const {
2171 return pipeline_metadata_.video_rotation == VIDEO_ROTATION_0;
2172}
2173
xjzaf29d4182016-12-16 01:52:322174void WebMediaPlayerImpl::ActivateViewportIntersectionMonitoring(bool activate) {
2175 DCHECK(main_task_runner_->BelongsToCurrentThread());
2176
Blink Reformat1c4d759e2017-04-09 16:34:542177 client_->ActivateViewportIntersectionMonitoring(activate);
xjzaf29d4182016-12-16 01:52:322178}
2179
avayvodcc273dd2017-01-19 19:35:122180bool WebMediaPlayerImpl::ShouldPauseVideoWhenHidden() const {
avayvod65fad272017-02-24 01:00:482181 // If suspending background video, pause any video that's not remoted or
2182 // not unlocked to play in the background.
2183 if (IsBackgroundedSuspendEnabled()) {
Blink Reformat1c4d759e2017-04-09 16:34:542184 if (!HasVideo())
avayvod65fad272017-02-24 01:00:482185 return false;
2186
2187#if defined(OS_ANDROID)
Blink Reformat1c4d759e2017-04-09 16:34:542188 if (IsRemote())
avayvod65fad272017-02-24 01:00:482189 return false;
avayvodcc273dd2017-01-19 19:35:122190#endif
avayvodeb9098d2017-01-07 00:33:032191
Blink Reformat1c4d759e2017-04-09 16:34:542192 return !HasAudio() || (IsResumeBackgroundVideosEnabled() &&
2193 video_locked_when_paused_when_hidden_);
avayvod65fad272017-02-24 01:00:482194 }
2195
2196 // Otherwise only pause if the optimization is on and it's a video-only
2197 // optimization candidate.
Blink Reformat1c4d759e2017-04-09 16:34:542198 return IsBackgroundVideoTrackOptimizationEnabled() && !HasAudio() &&
avayvod65fad272017-02-24 01:00:482199 IsBackgroundOptimizationCandidate();
avayvodeb9098d2017-01-07 00:33:032200}
2201
avayvod2135a642017-01-13 00:17:142202bool WebMediaPlayerImpl::ShouldDisableVideoWhenHidden() const {
avayvodcc273dd2017-01-19 19:35:122203 // This optimization is behind the flag on all platforms.
2204 if (!IsBackgroundVideoTrackOptimizationEnabled())
avayvodc4bfb0e62017-01-13 01:07:012205 return false;
avayvodc4bfb0e62017-01-13 01:07:012206
avayvodcc273dd2017-01-19 19:35:122207 // Disable video track only for players with audio that match the criteria for
2208 // being optimized.
Blink Reformat1c4d759e2017-04-09 16:34:542209 return HasAudio() && IsBackgroundOptimizationCandidate();
avayvodcc273dd2017-01-19 19:35:122210}
2211
2212bool WebMediaPlayerImpl::IsBackgroundOptimizationCandidate() const {
2213 DCHECK(main_task_runner_->BelongsToCurrentThread());
2214
avayvodcc273dd2017-01-19 19:35:122215#if defined(OS_ANDROID) // WMPI_CAST
avayvodac1a8522017-01-20 19:02:502216 // Don't optimize players being Cast.
Blink Reformat1c4d759e2017-04-09 16:34:542217 if (IsRemote())
avayvodcc273dd2017-01-19 19:35:122218 return false;
avayvodac1a8522017-01-20 19:02:502219
2220 // Video-only players are always optimized (paused) on Android.
2221 // Don't check the keyframe distance and duration.
Blink Reformat1c4d759e2017-04-09 16:34:542222 if (!HasAudio() && HasVideo())
avayvodac1a8522017-01-20 19:02:502223 return true;
avayvodcc273dd2017-01-19 19:35:122224#endif // defined(OS_ANDROID)
2225
2226 // Don't optimize audio-only or streaming players.
Blink Reformat1c4d759e2017-04-09 16:34:542227 if (!HasVideo() || IsStreaming())
avayvodcc273dd2017-01-19 19:35:122228 return false;
2229
2230 // Videos shorter than the maximum allowed keyframe distance can be optimized.
2231 base::TimeDelta duration = GetPipelineMediaDuration();
2232 if (duration < max_keyframe_distance_to_disable_background_video_)
2233 return true;
2234
2235 // Otherwise, only optimize videos with shorter average keyframe distance.
avayvodc4bfb0e62017-01-13 01:07:012236 PipelineStatistics stats = GetPipelineStatistics();
2237 return stats.video_keyframe_distance_average <
2238 max_keyframe_distance_to_disable_background_video_;
avayvod2135a642017-01-13 00:17:142239}
2240
avayvod56e1f3942017-01-21 02:06:312241void WebMediaPlayerImpl::UpdateBackgroundVideoOptimizationState() {
2242 if (IsHidden()) {
2243 if (ShouldPauseVideoWhenHidden())
2244 PauseVideoIfNeeded();
2245 else
2246 DisableVideoTrackIfNeeded();
2247 } else {
2248 EnableVideoTrackIfNeeded();
2249 }
2250}
2251
2252void WebMediaPlayerImpl::PauseVideoIfNeeded() {
2253 DCHECK(IsHidden());
2254
2255 // Don't pause video while the pipeline is stopped, resuming or seeking.
2256 // Also if the video is paused already.
tguilbert350936ff2017-02-24 05:39:272257 if (!pipeline_controller_.IsPipelineRunning() || is_pipeline_resuming_ ||
2258 seeking_ || paused_)
avayvod56e1f3942017-01-21 02:06:312259 return;
2260
2261 // OnPause() will set |paused_when_hidden_| to false and call
2262 // UpdatePlayState(), so set the flag to true after and then return.
2263 OnPause();
2264 paused_when_hidden_ = true;
2265}
2266
avayvod2135a642017-01-13 00:17:142267void WebMediaPlayerImpl::EnableVideoTrackIfNeeded() {
avayvod56e1f3942017-01-21 02:06:312268 // Don't change video track while the pipeline is stopped, resuming or
2269 // seeking.
tguilbert350936ff2017-02-24 05:39:272270 if (!pipeline_controller_.IsPipelineRunning() || is_pipeline_resuming_ ||
2271 seeking_)
avayvod2135a642017-01-13 00:17:142272 return;
2273
2274 if (video_track_disabled_) {
2275 video_track_disabled_ = false;
Blink Reformat1c4d759e2017-04-09 16:34:542276 if (client_->HasSelectedVideoTrack()) {
2277 WebMediaPlayer::TrackId trackId = client_->GetSelectedVideoTrackId();
2278 SelectedVideoTrackChanged(&trackId);
avayvod2135a642017-01-13 00:17:142279 }
2280 }
2281}
2282
2283void WebMediaPlayerImpl::DisableVideoTrackIfNeeded() {
2284 DCHECK(IsHidden());
2285
2286 // Don't change video track while the pipeline is resuming or seeking.
2287 if (is_pipeline_resuming_ || seeking_)
2288 return;
2289
2290 if (!video_track_disabled_ && ShouldDisableVideoWhenHidden()) {
2291 video_track_disabled_ = true;
Blink Reformat1c4d759e2017-04-09 16:34:542292 SelectedVideoTrackChanged(nullptr);
avayvod2135a642017-01-13 00:17:142293 }
2294}
2295
avayvodc4bfb0e62017-01-13 01:07:012296void WebMediaPlayerImpl::SetPipelineStatisticsForTest(
2297 const PipelineStatistics& stats) {
2298 pipeline_statistics_for_test_ = base::make_optional(stats);
2299}
2300
2301PipelineStatistics WebMediaPlayerImpl::GetPipelineStatistics() const {
2302 DCHECK(main_task_runner_->BelongsToCurrentThread());
2303
tguilbert350936ff2017-02-24 05:39:272304 return pipeline_statistics_for_test_.value_or(
2305 pipeline_controller_.GetStatistics());
avayvodc4bfb0e62017-01-13 01:07:012306}
2307
avayvodcc273dd2017-01-19 19:35:122308void WebMediaPlayerImpl::SetPipelineMediaDurationForTest(
2309 base::TimeDelta duration) {
2310 pipeline_media_duration_for_test_ = base::make_optional(duration);
2311}
2312
2313base::TimeDelta WebMediaPlayerImpl::GetPipelineMediaDuration() const {
2314 DCHECK(main_task_runner_->BelongsToCurrentThread());
2315
2316 return pipeline_media_duration_for_test_.value_or(
tguilbert350936ff2017-02-24 05:39:272317 pipeline_controller_.GetMediaDuration());
avayvodcc273dd2017-01-19 19:35:122318}
2319
2320void WebMediaPlayerImpl::ReportTimeFromForegroundToFirstFrame(
2321 base::TimeTicks foreground_time,
2322 base::TimeTicks new_frame_time) {
2323 base::TimeDelta time_to_first_frame = new_frame_time - foreground_time;
Blink Reformat1c4d759e2017-04-09 16:34:542324 if (HasAudio()) {
avayvodcc273dd2017-01-19 19:35:122325 UMA_HISTOGRAM_TIMES(
2326 "Media.Video.TimeFromForegroundToFirstFrame.DisableTrack",
2327 time_to_first_frame);
2328 } else {
2329 UMA_HISTOGRAM_TIMES("Media.Video.TimeFromForegroundToFirstFrame.Paused",
2330 time_to_first_frame);
2331 }
2332}
xjz4e5d4bf32017-02-15 21:26:352333void WebMediaPlayerImpl::SwitchRenderer(bool disable_pipeline_auto_suspend) {
2334 DCHECK(main_task_runner_->BelongsToCurrentThread());
2335 disable_pipeline_auto_suspend_ = disable_pipeline_auto_suspend;
2336 ScheduleRestart();
2337}
2338
dalecurtis4f6d14d2017-02-22 17:42:222339void WebMediaPlayerImpl::RecordUnderflowDuration(base::TimeDelta duration) {
2340 DCHECK(data_source_ || chunk_demuxer_);
2341 if (data_source_)
2342 UMA_HISTOGRAM_TIMES("Media.UnderflowDuration", duration);
2343 else
2344 UMA_HISTOGRAM_TIMES("Media.UnderflowDuration.MSE", duration);
2345}
2346
acolwell9e0840d2014-09-06 19:01:322347} // namespace media