Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(256)

Side by Side Diff: media/blink/webmediaplayer_impl.cc

Issue 2490783002: Refactor WebMediaPlayerDelegate interface. (Closed)
Patch Set: Fix did_play_ to only be set once per play. Created 3 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2013 The Chromium Authors. All rights reserved. 1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "media/blink/webmediaplayer_impl.h" 5 #include "media/blink/webmediaplayer_impl.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 #include <cmath> 8 #include <cmath>
9 #include <limits> 9 #include <limits>
10 #include <string> 10 #include <string>
(...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after
142 return natural_size; 142 return natural_size;
143 } 143 }
144 144
145 base::TimeDelta GetCurrentTimeInternal(WebMediaPlayerImpl* p_this) { 145 base::TimeDelta GetCurrentTimeInternal(WebMediaPlayerImpl* p_this) {
146 // We wrap currentTime() instead of using pipeline_.GetMediaTime() since there 146 // We wrap currentTime() instead of using pipeline_.GetMediaTime() since there
147 // are a variety of cases in which that time is not accurate; e.g., while 147 // are a variety of cases in which that time is not accurate; e.g., while
148 // remoting and during a pause or seek. 148 // remoting and during a pause or seek.
149 return base::TimeDelta::FromSecondsD(p_this->currentTime()); 149 return base::TimeDelta::FromSecondsD(p_this->currentTime());
150 } 150 }
151 151
152 // How much time must have elapsed since loading last progressed before the 152 // How much time must have elapsed since loading last progressed before we
153 // player is eligible for idle suspension. 153 // assume that the decoder will have had time to complete preroll.
154 constexpr base::TimeDelta kLoadingToIdleTimeout = 154 constexpr base::TimeDelta kPrerollAttemptTimeout =
155 base::TimeDelta::FromSeconds(3); 155 base::TimeDelta::FromSeconds(3);
156 156
157 } // namespace 157 } // namespace
158 158
159 class BufferedDataSourceHostImpl; 159 class BufferedDataSourceHostImpl;
160 160
161 STATIC_ASSERT_ENUM(WebMediaPlayer::CORSModeUnspecified, 161 STATIC_ASSERT_ENUM(WebMediaPlayer::CORSModeUnspecified,
162 UrlData::CORS_UNSPECIFIED); 162 UrlData::CORS_UNSPECIFIED);
163 STATIC_ASSERT_ENUM(WebMediaPlayer::CORSModeAnonymous, UrlData::CORS_ANONYMOUS); 163 STATIC_ASSERT_ENUM(WebMediaPlayer::CORSModeAnonymous, UrlData::CORS_ANONYMOUS);
164 STATIC_ASSERT_ENUM(WebMediaPlayer::CORSModeUseCredentials, 164 STATIC_ASSERT_ENUM(WebMediaPlayer::CORSModeUseCredentials,
165 UrlData::CORS_USE_CREDENTIALS); 165 UrlData::CORS_USE_CREDENTIALS);
166 166
167 #define BIND_TO_RENDER_LOOP(function) \ 167 #define BIND_TO_RENDER_LOOP(function) \
168 (DCHECK(main_task_runner_->BelongsToCurrentThread()), \ 168 (DCHECK(main_task_runner_->BelongsToCurrentThread()), \
169 BindToCurrentLoop(base::Bind(function, AsWeakPtr()))) 169 BindToCurrentLoop(base::Bind(function, AsWeakPtr())))
170 170
171 #define BIND_TO_RENDER_LOOP1(function, arg1) \ 171 #define BIND_TO_RENDER_LOOP1(function, arg1) \
172 (DCHECK(main_task_runner_->BelongsToCurrentThread()), \ 172 (DCHECK(main_task_runner_->BelongsToCurrentThread()), \
173 BindToCurrentLoop(base::Bind(function, AsWeakPtr(), arg1))) 173 BindToCurrentLoop(base::Bind(function, AsWeakPtr(), arg1)))
174 174
175 WebMediaPlayerImpl::WebMediaPlayerImpl( 175 WebMediaPlayerImpl::WebMediaPlayerImpl(
176 blink::WebLocalFrame* frame, 176 blink::WebLocalFrame* frame,
177 blink::WebMediaPlayerClient* client, 177 blink::WebMediaPlayerClient* client,
178 blink::WebMediaPlayerEncryptedMediaClient* encrypted_client, 178 blink::WebMediaPlayerEncryptedMediaClient* encrypted_client,
179 base::WeakPtr<WebMediaPlayerDelegate> delegate, 179 base::WeakPtr<WebMediaPlayerDelegate> delegate,
180 std::unique_ptr<RendererFactory> renderer_factory, 180 std::unique_ptr<RendererFactory> renderer_factory,
181 linked_ptr<UrlIndex> url_index, 181 linked_ptr<UrlIndex> url_index,
182 const WebMediaPlayerParams& params) 182 const WebMediaPlayerParams& params)
183 : frame_(frame), 183 : frame_(frame),
184 delegate_state_(DelegateState::GONE),
185 is_idle_(false),
186 must_suspend_(false),
187 network_state_(WebMediaPlayer::NetworkStateEmpty), 184 network_state_(WebMediaPlayer::NetworkStateEmpty),
188 ready_state_(WebMediaPlayer::ReadyStateHaveNothing), 185 ready_state_(WebMediaPlayer::ReadyStateHaveNothing),
189 highest_ready_state_(WebMediaPlayer::ReadyStateHaveNothing), 186 highest_ready_state_(WebMediaPlayer::ReadyStateHaveNothing),
190 preload_(MultibufferDataSource::AUTO), 187 preload_(MultibufferDataSource::AUTO),
191 buffering_strategy_(MultibufferDataSource::BUFFERING_STRATEGY_NORMAL), 188 buffering_strategy_(MultibufferDataSource::BUFFERING_STRATEGY_NORMAL),
192 main_task_runner_(frame->loadingTaskRunner()), 189 main_task_runner_(frame->loadingTaskRunner()),
193 media_task_runner_(params.media_task_runner()), 190 media_task_runner_(params.media_task_runner()),
194 worker_task_runner_(params.worker_task_runner()), 191 worker_task_runner_(params.worker_task_runner()),
195 media_log_(params.media_log()), 192 media_log_(params.media_log()),
196 pipeline_(media_task_runner_, media_log_.get()), 193 pipeline_(media_task_runner_, media_log_.get()),
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
233 volume_(1.0), 230 volume_(1.0),
234 volume_multiplier_(1.0), 231 volume_multiplier_(1.0),
235 renderer_factory_(std::move(renderer_factory)), 232 renderer_factory_(std::move(renderer_factory)),
236 surface_manager_(params.surface_manager()), 233 surface_manager_(params.surface_manager()),
237 overlay_surface_id_(SurfaceManager::kNoSurfaceID), 234 overlay_surface_id_(SurfaceManager::kNoSurfaceID),
238 suppress_destruction_errors_(false), 235 suppress_destruction_errors_(false),
239 can_suspend_state_(CanSuspendState::UNKNOWN), 236 can_suspend_state_(CanSuspendState::UNKNOWN),
240 use_fallback_path_(false), 237 use_fallback_path_(false),
241 is_encrypted_(false), 238 is_encrypted_(false),
242 underflow_count_(0), 239 underflow_count_(0),
240 preroll_attempt_pending_(false),
243 observer_(params.media_observer()) { 241 observer_(params.media_observer()) {
244 DCHECK(!adjust_allocated_memory_cb_.is_null()); 242 DCHECK(!adjust_allocated_memory_cb_.is_null());
245 DCHECK(renderer_factory_); 243 DCHECK(renderer_factory_);
246 DCHECK(client_); 244 DCHECK(client_);
247 245
248 tick_clock_.reset(new base::DefaultTickClock()); 246 tick_clock_.reset(new base::DefaultTickClock());
249 247
250 force_video_overlays_ = base::CommandLine::ForCurrentProcess()->HasSwitch( 248 force_video_overlays_ = base::CommandLine::ForCurrentProcess()->HasSwitch(
251 switches::kForceVideoOverlays); 249 switches::kForceVideoOverlays);
252 250
253 if (delegate_) 251 if (delegate_) {
254 delegate_id_ = delegate_->AddObserver(this); 252 delegate_id_ = delegate_->AddObserver(this);
253 delegate_->SetIdle(delegate_id_, true);
254 }
255 255
256 media_log_->AddEvent( 256 media_log_->AddEvent(
257 media_log_->CreateEvent(MediaLogEvent::WEBMEDIAPLAYER_CREATED)); 257 media_log_->CreateEvent(MediaLogEvent::WEBMEDIAPLAYER_CREATED));
258 258
259 if (params.initial_cdm()) 259 if (params.initial_cdm())
260 SetCdm(params.initial_cdm()); 260 SetCdm(params.initial_cdm());
261 261
262 // TODO(xhwang): When we use an external Renderer, many methods won't work, 262 // TODO(xhwang): When we use an external Renderer, many methods won't work,
263 // e.g. GetCurrentFrameFromCompositor(). See http://crbug.com/434861 263 // e.g. GetCurrentFrameFromCompositor(). See http://crbug.com/434861
264 audio_source_provider_ = 264 audio_source_provider_ =
(...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after
415 void WebMediaPlayerImpl::play() { 415 void WebMediaPlayerImpl::play() {
416 DVLOG(1) << __func__; 416 DVLOG(1) << __func__;
417 DCHECK(main_task_runner_->BelongsToCurrentThread()); 417 DCHECK(main_task_runner_->BelongsToCurrentThread());
418 418
419 #if defined(OS_ANDROID) // WMPI_CAST 419 #if defined(OS_ANDROID) // WMPI_CAST
420 if (isRemote()) { 420 if (isRemote()) {
421 cast_impl_.play(); 421 cast_impl_.play();
422 return; 422 return;
423 } 423 }
424 #endif 424 #endif
425 // TODO(sandersd): Do we want to reset the idle timer here?
426 if (delegate_)
427 delegate_->SetIdle(delegate_id_, false);
425 paused_ = false; 428 paused_ = false;
426 is_idle_ = false;
427 pipeline_.SetPlaybackRate(playback_rate_); 429 pipeline_.SetPlaybackRate(playback_rate_);
428 background_pause_timer_.Stop(); 430 background_pause_timer_.Stop();
429 431
430 if (data_source_) 432 if (data_source_)
431 data_source_->MediaIsPlaying(); 433 data_source_->MediaIsPlaying();
432 434
433 if (observer_) 435 if (observer_)
434 observer_->OnPlaying(); 436 observer_->OnPlaying();
435 437
436 DCHECK(watch_time_reporter_); 438 DCHECK(watch_time_reporter_);
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after
517 AsWeakPtr(), BUFFERING_HAVE_ENOUGH)); 519 AsWeakPtr(), BUFFERING_HAVE_ENOUGH));
518 } 520 }
519 return; 521 return;
520 } 522 }
521 523
522 // Call this before setting |seeking_| so that the current media time can be 524 // Call this before setting |seeking_| so that the current media time can be
523 // recorded by the reporter. 525 // recorded by the reporter.
524 if (watch_time_reporter_) 526 if (watch_time_reporter_)
525 watch_time_reporter_->OnSeeking(); 527 watch_time_reporter_->OnSeeking();
526 528
527 // TODO(sandersd): Ideally we would not clear the idle state if 529 // TODO(sandersd): Move |seeking_| to PipelineController.
528 // |pipeline_controller_| can elide the seek. 530 // TODO(sandersd): Do we want to reset the idle timer here?
529 is_idle_ = false; 531 if (delegate_)
532 delegate_->SetIdle(delegate_id_, false);
530 ended_ = false; 533 ended_ = false;
531
532 seeking_ = true; 534 seeking_ = true;
533 seek_time_ = time; 535 seek_time_ = time;
534 if (paused_) 536 if (paused_)
535 paused_time_ = time; 537 paused_time_ = time;
536 pipeline_controller_.Seek(time, time_updated); 538 pipeline_controller_.Seek(time, time_updated);
537 539
538 // This needs to be called after Seek() so that if a resume is triggered, it 540 // This needs to be called after Seek() so that if a resume is triggered, it
539 // is to the correct time. 541 // is to the correct time.
540 UpdatePlayState(); 542 UpdatePlayState();
541 } 543 }
(...skipping 246 matching lines...) Expand 10 before | Expand all | Expand 10 after
788 std::isfinite(seekable_end); 790 std::isfinite(seekable_end);
789 791
790 // TODO(dalecurtis): Technically this allows seeking on media which return an 792 // TODO(dalecurtis): Technically this allows seeking on media which return an
791 // infinite duration so long as DataSource::IsStreaming() is false. While not 793 // infinite duration so long as DataSource::IsStreaming() is false. While not
792 // expected, disabling this breaks semi-live players, http://crbug.com/427412. 794 // expected, disabling this breaks semi-live players, http://crbug.com/427412.
793 const blink::WebTimeRange seekable_range( 795 const blink::WebTimeRange seekable_range(
794 0.0, allow_seek_to_zero ? 0.0 : seekable_end); 796 0.0, allow_seek_to_zero ? 0.0 : seekable_end);
795 return blink::WebTimeRanges(&seekable_range, 1); 797 return blink::WebTimeRanges(&seekable_range, 1);
796 } 798 }
797 799
800 bool WebMediaPlayerImpl::IsPrerollAttemptNeeded() {
801 // TODO(sandersd): Replace with |highest_ready_state_since_seek_| if we need
802 // to ensure that preroll always gets a chance to complete.
803 // See http://crbug.com/671525.
804 if (highest_ready_state_ >= ReadyState::ReadyStateHaveFutureData)
805 return false;
806
807 if (preroll_attempt_pending_)
808 return true;
809
810 // Freshly initialized; there has never been any loading progress. (Otherwise
811 // |preroll_attempt_pending_| would be true when the start time is null.)
812 if (preroll_attempt_start_time_.is_null())
813 return false;
814
815 base::TimeDelta preroll_attempt_duration =
816 tick_clock_->NowTicks() - preroll_attempt_start_time_;
817 return preroll_attempt_duration < kPrerollAttemptTimeout;
818 }
819
798 bool WebMediaPlayerImpl::didLoadingProgress() { 820 bool WebMediaPlayerImpl::didLoadingProgress() {
799 DCHECK(main_task_runner_->BelongsToCurrentThread()); 821 DCHECK(main_task_runner_->BelongsToCurrentThread());
800 822
801 // Note: Separate variables used to ensure both methods are called every time. 823 // Note: Separate variables used to ensure both methods are called every time.
802 const bool pipeline_progress = pipeline_.DidLoadingProgress(); 824 const bool pipeline_progress = pipeline_.DidLoadingProgress();
803 const bool data_progress = buffered_data_source_host_.DidLoadingProgress(); 825 const bool data_progress = buffered_data_source_host_.DidLoadingProgress();
804 const bool did_loading_progress = pipeline_progress || data_progress; 826 const bool did_loading_progress = pipeline_progress || data_progress;
805 827
806 // If we've idle suspended before reaching kHaveFutureData and loading has 828 if (did_loading_progress &&
807 // progressed we need to spin up the renderer and figure out if we have enough 829 highest_ready_state_ < ReadyState::ReadyStateHaveFutureData) {
808 // data yet; |client_| may be waiting on this signal to trigger playback. The 830 // Reset the preroll attempt clock.
809 // idle timeout is long enough that this is a low-cost operation. 831 preroll_attempt_pending_ = true;
810 if (highest_ready_state_ < ReadyState::ReadyStateHaveFutureData && 832 preroll_attempt_start_time_ = base::TimeTicks();
811 pipeline_controller_.IsSuspended() && did_loading_progress && is_idle_) { 833
812 is_idle_ = false; 834 // Clear any 'stale' flag and give the pipeline a chance to resume. If we
835 // are already resumed, this will cause |preroll_attempt_start_time_| to be
836 // set.
837 // TODO(sandersd): Should this be on the same stack? It might be surprising
838 // that didLoadingProgress() can synchronously change state.
839 if (delegate_)
840 delegate_->ClearStaleFlag(delegate_id_);
813 UpdatePlayState(); 841 UpdatePlayState();
814 } 842 }
815 843
816 if (did_loading_progress)
817 last_time_loading_progressed_ = tick_clock_->NowTicks();
818
819 return did_loading_progress; 844 return did_loading_progress;
820 } 845 }
821 846
822 void WebMediaPlayerImpl::paint(blink::WebCanvas* canvas, 847 void WebMediaPlayerImpl::paint(blink::WebCanvas* canvas,
823 const blink::WebRect& rect, 848 const blink::WebRect& rect,
824 SkPaint& paint) { 849 SkPaint& paint) {
825 DCHECK(main_task_runner_->BelongsToCurrentThread()); 850 DCHECK(main_task_runner_->BelongsToCurrentThread());
826 TRACE_EVENT0("media", "WebMediaPlayerImpl:paint"); 851 TRACE_EVENT0("media", "WebMediaPlayerImpl:paint");
827 852
828 // TODO(sandersd): Move this check into GetCurrentFrameFromCompositor() when 853 // TODO(sandersd): Move this check into GetCurrentFrameFromCompositor() when
(...skipping 380 matching lines...) Expand 10 before | Expand all | Expand 10 after
1209 // TODO(chcunningham): Monitor playback position vs buffered. Potentially 1234 // TODO(chcunningham): Monitor playback position vs buffered. Potentially
1210 // transition to HAVE_FUTURE_DATA here if not enough is buffered. 1235 // transition to HAVE_FUTURE_DATA here if not enough is buffered.
1211 SetReadyState(WebMediaPlayer::ReadyStateHaveEnoughData); 1236 SetReadyState(WebMediaPlayer::ReadyStateHaveEnoughData);
1212 1237
1213 // Let the DataSource know we have enough data. It may use this information 1238 // Let the DataSource know we have enough data. It may use this information
1214 // to release unused network connections. 1239 // to release unused network connections.
1215 if (data_source_) 1240 if (data_source_)
1216 data_source_->OnBufferingHaveEnough(false); 1241 data_source_->OnBufferingHaveEnough(false);
1217 1242
1218 // Blink expects a timeChanged() in response to a seek(). 1243 // Blink expects a timeChanged() in response to a seek().
1219 if (should_notify_time_changed_) 1244 if (should_notify_time_changed_) {
1245 should_notify_time_changed_ = false;
1220 client_->timeChanged(); 1246 client_->timeChanged();
1247 }
1221 1248
1222 // Once we have enough, start reporting the total memory usage. We'll also 1249 // Once we have enough, start reporting the total memory usage. We'll also
1223 // report once playback starts. 1250 // report once playback starts.
1224 ReportMemoryUsage(); 1251 ReportMemoryUsage();
1225 1252
1226 // Report the amount of time it took to leave the underflow state. Don't 1253 // Report the amount of time it took to leave the underflow state. Don't
1227 // bother to report this for MSE playbacks since it's out of our control. 1254 // bother to report this for MSE playbacks since it's out of our control.
1228 if (underflow_timer_ && data_source_) { 1255 if (underflow_timer_ && data_source_) {
1229 UMA_HISTOGRAM_TIMES("Media.UnderflowDuration", 1256 UMA_HISTOGRAM_TIMES("Media.UnderflowDuration",
1230 underflow_timer_->Elapsed()); 1257 underflow_timer_->Elapsed());
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after
1326 DCHECK(main_task_runner_->BelongsToCurrentThread()); 1353 DCHECK(main_task_runner_->BelongsToCurrentThread());
1327 DCHECK_NE(ready_state_, WebMediaPlayer::ReadyStateHaveNothing); 1354 DCHECK_NE(ready_state_, WebMediaPlayer::ReadyStateHaveNothing);
1328 1355
1329 opaque_ = opaque; 1356 opaque_ = opaque;
1330 // Modify content opaqueness of cc::Layer directly so that 1357 // Modify content opaqueness of cc::Layer directly so that
1331 // SetContentsOpaqueIsFixed is ignored. 1358 // SetContentsOpaqueIsFixed is ignored.
1332 if (video_weblayer_) 1359 if (video_weblayer_)
1333 video_weblayer_->layer()->SetContentsOpaque(opaque_); 1360 video_weblayer_->layer()->SetContentsOpaque(opaque_);
1334 } 1361 }
1335 1362
1336 void WebMediaPlayerImpl::OnHidden() { 1363 void WebMediaPlayerImpl::OnFrameHidden() {
whywhat 2017/01/06 17:18:52 nit: Following discussion with Dale around naming
sandersd (OOO until July 31) 2017/01/06 23:08:35 I think I prefer to keep these names, since they a
DaleCurtis 2017/01/07 00:31:03 Saving the rename for later sgtm.
1337 DCHECK(main_task_runner_->BelongsToCurrentThread()); 1364 DCHECK(main_task_runner_->BelongsToCurrentThread());
1338 1365
1339 if (IsBackgroundVideoTrackOptimizationEnabled()) 1366 if (IsBackgroundVideoTrackOptimizationEnabled())
1340 selectedVideoTrackChanged(nullptr); 1367 selectedVideoTrackChanged(nullptr);
1341 1368
1342 if (watch_time_reporter_) 1369 if (watch_time_reporter_)
1343 watch_time_reporter_->OnHidden(); 1370 watch_time_reporter_->OnHidden();
1344 1371
1345 UpdatePlayState(); 1372 UpdatePlayState();
1346 1373
1347 // Schedule suspended playing media to be paused if the user doesn't come back 1374 // Schedule suspended playing media to be paused if the user doesn't come back
1348 // to it within some timeout period to avoid any autoplay surprises. 1375 // to it within some timeout period to avoid any autoplay surprises.
1349 ScheduleIdlePauseTimer(); 1376 ScheduleIdlePauseTimer();
1350 } 1377 }
1351 1378
1352 void WebMediaPlayerImpl::OnShown() { 1379 void WebMediaPlayerImpl::OnFrameClosed() {
1353 DCHECK(main_task_runner_->BelongsToCurrentThread()); 1380 DCHECK(main_task_runner_->BelongsToCurrentThread());
1381 UpdatePlayState();
1382 }
1383
1384 void WebMediaPlayerImpl::OnFrameShown() {
1385 DCHECK(main_task_runner_->BelongsToCurrentThread());
1386 background_pause_timer_.Stop();
1387
1354 if (watch_time_reporter_) 1388 if (watch_time_reporter_)
1355 watch_time_reporter_->OnShown(); 1389 watch_time_reporter_->OnShown();
1356 1390
1357 if (IsBackgroundVideoTrackOptimizationEnabled() && 1391 if (IsBackgroundVideoTrackOptimizationEnabled() &&
1358 client_->hasSelectedVideoTrack()) { 1392 client_->hasSelectedVideoTrack()) {
1359 WebMediaPlayer::TrackId trackId = client_->getSelectedVideoTrackId(); 1393 WebMediaPlayer::TrackId trackId = client_->getSelectedVideoTrackId();
1360 selectedVideoTrackChanged(&trackId); 1394 selectedVideoTrackChanged(&trackId);
1361 } 1395 }
1362 1396
1363 must_suspend_ = false;
1364 background_pause_timer_.Stop();
1365
1366 UpdatePlayState(); 1397 UpdatePlayState();
1367 } 1398 }
1368 1399
1369 bool WebMediaPlayerImpl::OnSuspendRequested(bool must_suspend) { 1400 void WebMediaPlayerImpl::OnIdleTimeout() {
1370 DCHECK(main_task_runner_->BelongsToCurrentThread()); 1401 DCHECK(main_task_runner_->BelongsToCurrentThread());
1371 1402
1372 if (must_suspend) { 1403 // If we are attempting preroll, clear the stale flag.
1373 must_suspend_ = true; 1404 if (IsPrerollAttemptNeeded()) {
1374 UpdatePlayState(); 1405 if (delegate_)
1375 return true; 1406 delegate_->ClearStaleFlag(delegate_id_);
1407 return;
1376 } 1408 }
1377 1409
1378 // If we're beyond HaveFutureData, we can safely suspend at any time. 1410 UpdatePlayState();
1379 if (highest_ready_state_ >= WebMediaPlayer::ReadyStateHaveFutureData) {
1380 is_idle_ = true;
1381 UpdatePlayState();
1382 return true;
1383 }
1384
1385 // Before HaveFutureData blink will not call play(), so we must be careful to
1386 // only suspend if we'll eventually receive an event that will trigger a
1387 // resume. If the last time loading progressed was a while ago, and we still
1388 // haven't reached HaveFutureData, we assume that we're waiting on more data
1389 // to continue pre-rolling. When that data is loaded the pipeline will be
1390 // resumed by didLoadingProgress().
1391 if (last_time_loading_progressed_.is_null() ||
1392 (tick_clock_->NowTicks() - last_time_loading_progressed_) >
1393 kLoadingToIdleTimeout) {
1394 is_idle_ = true;
1395 UpdatePlayState();
1396 return true;
1397 }
1398
1399 return false;
1400 } 1411 }
1401 1412
1402 void WebMediaPlayerImpl::OnPlay() { 1413 void WebMediaPlayerImpl::OnPlay() {
1403 play(); 1414 play();
1404 client_->playbackStateChanged(); 1415 client_->playbackStateChanged();
1405 } 1416 }
1406 1417
1407 void WebMediaPlayerImpl::OnPause() { 1418 void WebMediaPlayerImpl::OnPause() {
1408 pause(); 1419 pause();
1409 client_->playbackStateChanged(); 1420 client_->playbackStateChanged();
(...skipping 327 matching lines...) Expand 10 before | Expand all | Expand 10 after
1737 bool is_streaming = false; 1748 bool is_streaming = false;
1738 #else 1749 #else
1739 bool is_remote = false; 1750 bool is_remote = false;
1740 bool is_streaming = data_source_ && data_source_->IsStreaming(); 1751 bool is_streaming = data_source_ && data_source_->IsStreaming();
1741 #endif 1752 #endif
1742 1753
1743 bool is_suspended = pipeline_controller_.IsSuspended(); 1754 bool is_suspended = pipeline_controller_.IsSuspended();
1744 bool is_backgrounded = IsBackgroundedSuspendEnabled() && IsHidden(); 1755 bool is_backgrounded = IsBackgroundedSuspendEnabled() && IsHidden();
1745 PlayState state = UpdatePlayState_ComputePlayState( 1756 PlayState state = UpdatePlayState_ComputePlayState(
1746 is_remote, is_streaming, is_suspended, is_backgrounded); 1757 is_remote, is_streaming, is_suspended, is_backgrounded);
1747 SetDelegateState(state.delegate_state); 1758 SetDelegateState(state.delegate_state, state.is_idle);
1748 SetMemoryReportingState(state.is_memory_reporting_enabled); 1759 SetMemoryReportingState(state.is_memory_reporting_enabled);
1749 SetSuspendState(state.is_suspended || pending_suspend_resume_cycle_); 1760 SetSuspendState(state.is_suspended || pending_suspend_resume_cycle_);
1750 } 1761 }
1751 1762
1752 void WebMediaPlayerImpl::SetDelegateState(DelegateState new_state) { 1763 void WebMediaPlayerImpl::SetDelegateState(DelegateState new_state,
1764 bool is_idle) {
1753 if (!delegate_) 1765 if (!delegate_)
1754 return; 1766 return;
1755 1767
1756 if (delegate_state_ == new_state) { 1768 switch (new_state) {
1757 if (delegate_state_ != DelegateState::PLAYING ||
1758 autoplay_muted_ == client_->isAutoplayingMuted()) {
1759 return;
1760 }
1761 }
1762
1763 delegate_state_ = new_state;
1764
1765 switch (delegate_state_) {
1766 case DelegateState::GONE: 1769 case DelegateState::GONE:
1767 delegate_->PlayerGone(delegate_id_); 1770 delegate_->PlayerGone(delegate_id_);
1768 break; 1771 break;
1769 case DelegateState::PLAYING: { 1772 case DelegateState::PLAYING: {
1770 autoplay_muted_ = client_->isAutoplayingMuted(); 1773 bool has_audio = hasAudio() && !client_->isAutoplayingMuted();
1771 bool has_audio = autoplay_muted_ ? false : hasAudio();
1772 delegate_->DidPlay( 1774 delegate_->DidPlay(
1773 delegate_id_, hasVideo(), has_audio, false, 1775 delegate_id_, has_audio, hasVideo(),
1774 media::DurationToMediaContentType(pipeline_.GetMediaDuration())); 1776 media::DurationToMediaContentType(pipeline_.GetMediaDuration()));
1775 break; 1777 break;
1776 } 1778 }
1777 case DelegateState::PAUSED: 1779 case DelegateState::PAUSED:
1778 delegate_->DidPause(delegate_id_, false); 1780 delegate_->DidPause(delegate_id_);
1779 break;
1780 case DelegateState::ENDED:
1781 delegate_->DidPause(delegate_id_, true);
1782 break; 1781 break;
1783 } 1782 }
1783
1784 delegate_->SetIdle(delegate_id_, is_idle);
1784 } 1785 }
1785 1786
1786 void WebMediaPlayerImpl::SetMemoryReportingState( 1787 void WebMediaPlayerImpl::SetMemoryReportingState(
1787 bool is_memory_reporting_enabled) { 1788 bool is_memory_reporting_enabled) {
1788 if (memory_usage_reporting_timer_.IsRunning() == 1789 if (memory_usage_reporting_timer_.IsRunning() ==
1789 is_memory_reporting_enabled) { 1790 is_memory_reporting_enabled) {
1790 return; 1791 return;
1791 } 1792 }
1792 1793
1793 if (is_memory_reporting_enabled) { 1794 if (is_memory_reporting_enabled) {
(...skipping 25 matching lines...) Expand all
1819 can_suspend_state_ = 1820 can_suspend_state_ =
1820 frame->metadata()->IsTrue(VideoFrameMetadata::DECODER_OWNS_FRAME) 1821 frame->metadata()->IsTrue(VideoFrameMetadata::DECODER_OWNS_FRAME)
1821 ? CanSuspendState::NO 1822 ? CanSuspendState::NO
1822 : CanSuspendState::YES; 1823 : CanSuspendState::YES;
1823 } 1824 }
1824 } 1825 }
1825 #else 1826 #else
1826 can_suspend_state_ = CanSuspendState::YES; 1827 can_suspend_state_ = CanSuspendState::YES;
1827 #endif 1828 #endif
1828 1829
1829 if (can_suspend_state_ == CanSuspendState::NO) 1830 if (is_suspended && can_suspend_state_ != CanSuspendState::NO) {
1830 return; 1831 // If we were not resumed for long enough to satisfy the preroll attempt,
1831 1832 // reset the clock.
1832 if (is_suspended) { 1833 if (!preroll_attempt_pending_ && IsPrerollAttemptNeeded()) {
1834 preroll_attempt_pending_ = true;
1835 preroll_attempt_start_time_ = base::TimeTicks();
1836 }
1833 pipeline_controller_.Suspend(); 1837 pipeline_controller_.Suspend();
1834 } else { 1838 } else {
1839 // When resuming, start the preroll attempt clock.
1840 if (preroll_attempt_pending_) {
1841 preroll_attempt_pending_ = false;
1842 preroll_attempt_start_time_ = tick_clock_->NowTicks();
1843 }
1835 pipeline_controller_.Resume(); 1844 pipeline_controller_.Resume();
1836 } 1845 }
1837 } 1846 }
1838 1847
1839 WebMediaPlayerImpl::PlayState 1848 WebMediaPlayerImpl::PlayState
1840 WebMediaPlayerImpl::UpdatePlayState_ComputePlayState(bool is_remote, 1849 WebMediaPlayerImpl::UpdatePlayState_ComputePlayState(bool is_remote,
1841 bool is_streaming, 1850 bool is_streaming,
1842 bool is_suspended, 1851 bool is_suspended,
1843 bool is_backgrounded) { 1852 bool is_backgrounded) {
1844 PlayState result; 1853 PlayState result;
1845 1854
1855 bool must_suspend = delegate_ && delegate_->IsFrameClosed();
1856 bool is_stale = delegate_ && delegate_->IsStale(delegate_id_);
1857
1846 // This includes both data source (before pipeline startup) and pipeline 1858 // This includes both data source (before pipeline startup) and pipeline
1847 // errors. 1859 // errors.
1848 bool has_error = IsNetworkStateError(network_state_); 1860 bool has_error = IsNetworkStateError(network_state_);
1849 1861
1850 // After HaveMetadata, we know which tracks are present and the duration. 1862 // After HaveMetadata, we know which tracks are present and the duration.
1851 bool have_metadata = ready_state_ >= WebMediaPlayer::ReadyStateHaveMetadata; 1863 bool have_metadata = ready_state_ >= WebMediaPlayer::ReadyStateHaveMetadata;
1852 1864
1853 // After HaveFutureData, Blink will call play() if the state is not paused; 1865 // After HaveFutureData, Blink will call play() if the state is not paused;
1854 // prior to this point |paused_| is not accurate. 1866 // prior to this point |paused_| is not accurate.
1855 bool have_future_data = 1867 bool have_future_data =
1856 highest_ready_state_ >= WebMediaPlayer::ReadyStateHaveFutureData; 1868 highest_ready_state_ >= WebMediaPlayer::ReadyStateHaveFutureData;
1857 1869
1858 // Background suspend is not enabled for audio-only players unless paused, 1870 // Background suspend is not enabled for audio-only players unless paused,
1859 // though in the case of audio-only the session should be kept. 1871 // though in the case of audio-only the session should be kept.
1860 // Videos are not suspended if the user resumed the playback via the remote 1872 // Videos are not suspended if the user resumed the playback via the remote
1861 // controls earlier and it's still playing. 1873 // controls earlier and it's still playing.
1862 bool is_backgrounded_video = is_backgrounded && have_metadata && hasVideo(); 1874 bool is_backgrounded_video = is_backgrounded && have_metadata && hasVideo();
1863 bool can_play_backgrounded = is_backgrounded_video && !is_remote && 1875 bool can_play_backgrounded = is_backgrounded_video && !is_remote &&
1864 hasAudio() && IsResumeBackgroundVideosEnabled(); 1876 hasAudio() && IsResumeBackgroundVideosEnabled();
1865 bool is_background_playing = 1877 bool is_background_playing =
1866 delegate_ && delegate_->IsPlayingBackgroundVideo(); 1878 delegate_ && delegate_->IsBackgroundVideoPlaybackAllowed();
whywhat 2017/01/06 17:18:51 nit: I'm a bit concerned that IsBgVideoPlaybackAll
sandersd (OOO until July 31) 2017/01/06 23:08:35 Done.
1867 bool background_suspended = !is_streaming && is_backgrounded_video && 1879 bool background_suspended = !is_streaming && is_backgrounded_video &&
1868 !(can_play_backgrounded && is_background_playing); 1880 !(can_play_backgrounded && is_background_playing);
1869 bool background_pause_suspended = 1881 bool background_pause_suspended =
1870 !is_streaming && is_backgrounded && paused_ && have_future_data; 1882 !is_streaming && is_backgrounded && paused_ && have_future_data;
1871 1883
1872 // Idle suspension is allowed prior to have future data since there exist 1884 // Idle suspension is allowed prior to have future data since there exist
1873 // mechanisms to exit the idle state when the player is capable of reaching 1885 // mechanisms to exit the idle state when the player is capable of reaching
1874 // the have future data state; see didLoadingProgress(). 1886 // the have future data state; see didLoadingProgress().
1875 // 1887 //
1876 // TODO(sandersd): Make the delegate suspend idle players immediately when 1888 // TODO(sandersd): Make the delegate suspend idle players immediately when
1877 // hidden. 1889 // hidden.
1878 bool idle_suspended = 1890 bool idle_suspended =
1879 !is_streaming && is_idle_ && paused_ && !seeking_ && !overlay_enabled_; 1891 !is_streaming && is_stale && paused_ && !seeking_ && !overlay_enabled_;
1880 1892
1881 // If we're already suspended, see if we can wait for user interaction. Prior 1893 // If we're already suspended, see if we can wait for user interaction. Prior
1882 // to HaveFutureData, we require |is_idle_| to remain suspended. |is_idle_| 1894 // to HaveFutureData, we require |is_stale| to remain suspended. |is_stale|
1883 // will be cleared when we receive data which may take us to HaveFutureData. 1895 // will be cleared when we receive data which may take us to HaveFutureData.
1884 bool can_stay_suspended = 1896 bool can_stay_suspended =
1885 (is_idle_ || have_future_data) && is_suspended && paused_ && !seeking_; 1897 (is_stale || have_future_data) && is_suspended && paused_ && !seeking_;
1886 1898
1887 // Combined suspend state. 1899 // Combined suspend state.
1888 result.is_suspended = is_remote || must_suspend_ || idle_suspended || 1900 result.is_suspended = is_remote || must_suspend || idle_suspended ||
1889 background_suspended || background_pause_suspended || 1901 background_suspended || background_pause_suspended ||
1890 can_stay_suspended; 1902 can_stay_suspended;
1891 1903
1892 // We do not treat |playback_rate_| == 0 as paused. For the media session, 1904 // We do not treat |playback_rate_| == 0 as paused. For the media session,
1893 // being paused implies displaying a play button, which is incorrect in this 1905 // being paused implies displaying a play button, which is incorrect in this
1894 // case. For memory usage reporting, we just use the same definition (but we 1906 // case. For memory usage reporting, we just use the same definition (but we
1895 // don't have to). 1907 // don't have to).
1896 // 1908 //
1897 // Similarly, we don't consider |ended_| to be paused. Blink will immediately 1909 // Similarly, we don't consider |ended_| to be paused. Blink will immediately
1898 // call pause() or seek(), so |ended_| should not affect the computation. 1910 // call pause() or seek(), so |ended_| should not affect the computation.
1899 // Despite that, |ended_| does result in a separate paused state, to simplfy 1911 // Despite that, |ended_| does result in a separate paused state, to simplfy
1900 // the contract for SetDelegateState(). 1912 // the contract for SetDelegateState().
1901 // 1913 //
1902 // |has_session| is used to decide when to create a media session. Idle 1914 // |has_session| is used to decide when to create a media session. Idle
1903 // suspension does not destroy the media session, because we expect that the 1915 // suspension does not destroy the media session, because we expect that the
1904 // notification controls (and audio focus) remain. We also require: 1916 // notification controls (and audio focus) remain. We also require:
1905 // - |have_metadata|, since the tracks and duration are passed to DidPlay(). 1917 // - |have_metadata|, since the tracks and duration are passed to DidPlay().
1906 // - |have_future_data|, since we need to know whether we are paused to 1918 // - |have_future_data|, since we need to know whether we are paused to
1907 // correctly configure the session. 1919 // correctly configure the session.
1908 // 1920 //
1909 // TODO(sandersd): If Blink told us the paused state sooner, we could create 1921 // TODO(sandersd): If Blink told us the paused state sooner, we could create
1910 // the media session sooner. 1922 // the media session sooner.
1911 bool can_play = !has_error && !is_remote && have_future_data; 1923 bool can_play = !has_error && !is_remote && have_future_data;
1912 bool has_session_playing = 1924 bool has_session_playing = can_play && !must_suspend && !background_suspended;
1913 can_play && !must_suspend_ && !background_suspended;
1914 1925
1915 // |has_session_suspended| means the player is suspended from the media 1926 // |has_session_suspended| means the player is suspended from the media
1916 // element point of view but paused and can be resumed from the delegate point 1927 // element point of view but paused and can be resumed from the delegate point
1917 // of view. Therefore it behaves like |paused_| for the delegate. 1928 // of view. Therefore it behaves like |paused_| for the delegate.
1918 bool has_session_suspended = can_play && !must_suspend_ && 1929 bool has_session_suspended = can_play && !must_suspend &&
1919 background_suspended && can_play_backgrounded; 1930 background_suspended && can_play_backgrounded;
1920 1931
1921 bool has_session = has_session_playing || has_session_suspended; 1932 bool has_session = has_session_playing || has_session_suspended;
1922 1933
1923 if (!has_session) { 1934 if (!has_session) {
1924 result.delegate_state = DelegateState::GONE; 1935 result.delegate_state = DelegateState::GONE;
1936 result.is_idle = delegate_ && delegate_->IsIdle(delegate_id_);
1925 } else if (paused_ || has_session_suspended) { 1937 } else if (paused_ || has_session_suspended) {
1938 // TODO(sandersd): Is it possible to have a suspended session, be ended,
1939 // and not be paused? If so we should be in a PLAYING state.
1926 result.delegate_state = 1940 result.delegate_state =
1927 ended_ ? DelegateState::ENDED : DelegateState::PAUSED; 1941 ended_ ? DelegateState::GONE : DelegateState::PAUSED;
1942 result.is_idle = !seeking_;
1928 } else { 1943 } else {
1929 result.delegate_state = DelegateState::PLAYING; 1944 result.delegate_state = DelegateState::PLAYING;
1945 result.is_idle = false;
1930 } 1946 }
1931 1947
1932 // It's not critical if some cases where memory usage can change are missed, 1948 // It's not critical if some cases where memory usage can change are missed,
1933 // since media memory changes are usually gradual. 1949 // since media memory changes are usually gradual.
1934 result.is_memory_reporting_enabled = 1950 result.is_memory_reporting_enabled =
1935 can_play && !result.is_suspended && !paused_; 1951 can_play && !result.is_suspended && (!paused_ || seeking_);
1936 1952
1937 return result; 1953 return result;
1938 } 1954 }
1939 1955
1940 void WebMediaPlayerImpl::ReportMemoryUsage() { 1956 void WebMediaPlayerImpl::ReportMemoryUsage() {
1941 DCHECK(main_task_runner_->BelongsToCurrentThread()); 1957 DCHECK(main_task_runner_->BelongsToCurrentThread());
1942 1958
1943 // About base::Unretained() usage below: We destroy |demuxer_| on the main 1959 // About base::Unretained() usage below: We destroy |demuxer_| on the main
1944 // thread. Before that, however, ~WebMediaPlayerImpl() posts a task to the 1960 // thread. Before that, however, ~WebMediaPlayerImpl() posts a task to the
1945 // media thread and waits for it to finish. Hence, the GetMemoryUsage() task 1961 // media thread and waits for it to finish. Hence, the GetMemoryUsage() task
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
2011 this, &WebMediaPlayerImpl::OnPause); 2027 this, &WebMediaPlayerImpl::OnPause);
2012 } 2028 }
2013 2029
2014 void WebMediaPlayerImpl::CreateWatchTimeReporter() { 2030 void WebMediaPlayerImpl::CreateWatchTimeReporter() {
2015 // Create the watch time reporter and synchronize its initial state. 2031 // Create the watch time reporter and synchronize its initial state.
2016 watch_time_reporter_.reset(new WatchTimeReporter( 2032 watch_time_reporter_.reset(new WatchTimeReporter(
2017 hasAudio(), hasVideo(), !!chunk_demuxer_, is_encrypted_, media_log_, 2033 hasAudio(), hasVideo(), !!chunk_demuxer_, is_encrypted_, media_log_,
2018 pipeline_metadata_.natural_size, 2034 pipeline_metadata_.natural_size,
2019 base::Bind(&GetCurrentTimeInternal, this))); 2035 base::Bind(&GetCurrentTimeInternal, this)));
2020 watch_time_reporter_->OnVolumeChange(volume_); 2036 watch_time_reporter_->OnVolumeChange(volume_);
2021 if (IsHidden()) 2037 if (delegate_ && delegate_->IsFrameHidden())
2022 watch_time_reporter_->OnHidden(); 2038 watch_time_reporter_->OnHidden();
2023 else 2039 else
2024 watch_time_reporter_->OnShown(); 2040 watch_time_reporter_->OnShown();
2025 } 2041 }
2026 2042
2027 bool WebMediaPlayerImpl::IsHidden() const { 2043 bool WebMediaPlayerImpl::IsHidden() const {
2028 DCHECK(main_task_runner_->BelongsToCurrentThread()); 2044 DCHECK(main_task_runner_->BelongsToCurrentThread());
2029 2045
2030 return delegate_ && delegate_->IsHidden(); 2046 return delegate_ && delegate_->IsFrameHidden() && !delegate_->IsFrameClosed();
2031 } 2047 }
2032 2048
2033 bool WebMediaPlayerImpl::DoesOverlaySupportMetadata() const { 2049 bool WebMediaPlayerImpl::DoesOverlaySupportMetadata() const {
2034 return pipeline_metadata_.video_rotation == VIDEO_ROTATION_0; 2050 return pipeline_metadata_.video_rotation == VIDEO_ROTATION_0;
2035 } 2051 }
2036 2052
2037 void WebMediaPlayerImpl::ActivateViewportIntersectionMonitoring(bool activate) { 2053 void WebMediaPlayerImpl::ActivateViewportIntersectionMonitoring(bool activate) {
2038 DCHECK(main_task_runner_->BelongsToCurrentThread()); 2054 DCHECK(main_task_runner_->BelongsToCurrentThread());
2039 2055
2040 client_->activateViewportIntersectionMonitoring(activate); 2056 client_->activateViewportIntersectionMonitoring(activate);
2041 } 2057 }
2042 2058
2043 } // namespace media 2059 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698