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

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

Issue 2490783002: Refactor WebMediaPlayerDelegate interface. (Closed)
Patch Set: Unit tests. Created 4 years 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 163 matching lines...) Expand 10 before | Expand all | Expand 10 after
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_(base::ThreadTaskRunnerHandle::Get()), 189 main_task_runner_(base::ThreadTaskRunnerHandle::Get()),
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 disable_fullscreen_video_overlays_ = 251 disable_fullscreen_video_overlays_ =
254 !base::FeatureList::IsEnabled(media::kOverlayFullscreenVideo); 252 !base::FeatureList::IsEnabled(media::kOverlayFullscreenVideo);
255 253
256 if (delegate_) 254 if (delegate_) {
257 delegate_id_ = delegate_->AddObserver(this); 255 delegate_id_ = delegate_->AddObserver(this);
256 delegate_->SetIdle(delegate_id_, true);
257 }
258 258
259 media_log_->AddEvent( 259 media_log_->AddEvent(
260 media_log_->CreateEvent(MediaLogEvent::WEBMEDIAPLAYER_CREATED)); 260 media_log_->CreateEvent(MediaLogEvent::WEBMEDIAPLAYER_CREATED));
261 261
262 if (params.initial_cdm()) 262 if (params.initial_cdm())
263 SetCdm(params.initial_cdm()); 263 SetCdm(params.initial_cdm());
264 264
265 // TODO(xhwang): When we use an external Renderer, many methods won't work, 265 // TODO(xhwang): When we use an external Renderer, many methods won't work,
266 // e.g. GetCurrentFrameFromCompositor(). See http://crbug.com/434861 266 // e.g. GetCurrentFrameFromCompositor(). See http://crbug.com/434861
267 267
(...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after
414 void WebMediaPlayerImpl::play() { 414 void WebMediaPlayerImpl::play() {
415 DVLOG(1) << __func__; 415 DVLOG(1) << __func__;
416 DCHECK(main_task_runner_->BelongsToCurrentThread()); 416 DCHECK(main_task_runner_->BelongsToCurrentThread());
417 417
418 #if defined(OS_ANDROID) // WMPI_CAST 418 #if defined(OS_ANDROID) // WMPI_CAST
419 if (isRemote()) { 419 if (isRemote()) {
420 cast_impl_.play(); 420 cast_impl_.play();
421 return; 421 return;
422 } 422 }
423 #endif 423 #endif
424 // TODO(sandersd): Do we want to reset the idle timer here?
425 if (delegate_)
426 delegate_->SetIdle(delegate_id_, false);
424 paused_ = false; 427 paused_ = false;
425 is_idle_ = false;
426 pipeline_.SetPlaybackRate(playback_rate_); 428 pipeline_.SetPlaybackRate(playback_rate_);
427 background_pause_timer_.Stop(); 429 background_pause_timer_.Stop();
428 430
429 if (data_source_) 431 if (data_source_)
430 data_source_->MediaIsPlaying(); 432 data_source_->MediaIsPlaying();
431 433
432 DCHECK(watch_time_reporter_); 434 DCHECK(watch_time_reporter_);
433 watch_time_reporter_->OnPlaying(); 435 watch_time_reporter_->OnPlaying();
434 media_log_->AddEvent(media_log_->CreateEvent(MediaLogEvent::PLAY)); 436 media_log_->AddEvent(media_log_->CreateEvent(MediaLogEvent::PLAY));
435 UpdatePlayState(); 437 UpdatePlayState();
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after
510 AsWeakPtr(), BUFFERING_HAVE_ENOUGH)); 512 AsWeakPtr(), BUFFERING_HAVE_ENOUGH));
511 } 513 }
512 return; 514 return;
513 } 515 }
514 516
515 // Call this before setting |seeking_| so that the current media time can be 517 // Call this before setting |seeking_| so that the current media time can be
516 // recorded by the reporter. 518 // recorded by the reporter.
517 if (watch_time_reporter_) 519 if (watch_time_reporter_)
518 watch_time_reporter_->OnSeeking(); 520 watch_time_reporter_->OnSeeking();
519 521
520 // TODO(sandersd): Ideally we would not clear the idle state if 522 // TODO(sandersd): Move |seeking_| to PipelineController.
521 // |pipeline_controller_| can elide the seek. 523 // TODO(sandersd): Do we want to reset the idle timer here?
522 is_idle_ = false; 524 if (delegate_)
525 delegate_->SetIdle(delegate_id_, false);
523 ended_ = false; 526 ended_ = false;
524
525 seeking_ = true; 527 seeking_ = true;
526 seek_time_ = time; 528 seek_time_ = time;
527 if (paused_) 529 if (paused_)
528 paused_time_ = time; 530 paused_time_ = time;
529 pipeline_controller_.Seek(time, time_updated); 531 pipeline_controller_.Seek(time, time_updated);
530 532
531 // This needs to be called after Seek() so that if a resume is triggered, it 533 // This needs to be called after Seek() so that if a resume is triggered, it
532 // is to the correct time. 534 // is to the correct time.
533 UpdatePlayState(); 535 UpdatePlayState();
534 } 536 }
(...skipping 246 matching lines...) Expand 10 before | Expand all | Expand 10 after
781 std::isfinite(seekable_end); 783 std::isfinite(seekable_end);
782 784
783 // TODO(dalecurtis): Technically this allows seeking on media which return an 785 // TODO(dalecurtis): Technically this allows seeking on media which return an
784 // infinite duration so long as DataSource::IsStreaming() is false. While not 786 // infinite duration so long as DataSource::IsStreaming() is false. While not
785 // expected, disabling this breaks semi-live players, http://crbug.com/427412. 787 // expected, disabling this breaks semi-live players, http://crbug.com/427412.
786 const blink::WebTimeRange seekable_range( 788 const blink::WebTimeRange seekable_range(
787 0.0, allow_seek_to_zero ? 0.0 : seekable_end); 789 0.0, allow_seek_to_zero ? 0.0 : seekable_end);
788 return blink::WebTimeRanges(&seekable_range, 1); 790 return blink::WebTimeRanges(&seekable_range, 1);
789 } 791 }
790 792
793 bool WebMediaPlayerImpl::IsPrerollAttemptNeeded() {
794 // TODO(sandersd): Replace with |highest_ready_state_since_seek_| if we need
795 // to ensure that preroll always gets a chance to complete.
796 if (highest_ready_state_ >= ReadyState::ReadyStateHaveFutureData)
797 return false;
798
799 if (preroll_attempt_pending_)
800 return true;
801
802 // Freshly initialized; there has never been any loading progress. (Otherwise
803 // |preroll_attempt_pending_| would be true when the start time is null.)
804 if (preroll_attempt_start_time_.is_null())
805 return false;
806
807 base::TimeDelta preroll_attempt_duration =
808 tick_clock_->NowTicks() - preroll_attempt_start_time_;
809 return preroll_attempt_duration < kLoadingToIdleTimeout;
watk 2016/12/10 00:01:31 maybe this should be kPrerollAttemptTimeout now?
sandersd (OOO until July 31) 2017/01/05 23:12:20 Done.
810 }
811
791 bool WebMediaPlayerImpl::didLoadingProgress() { 812 bool WebMediaPlayerImpl::didLoadingProgress() {
792 DCHECK(main_task_runner_->BelongsToCurrentThread()); 813 DCHECK(main_task_runner_->BelongsToCurrentThread());
793 814
794 // Note: Separate variables used to ensure both methods are called every time. 815 // Note: Separate variables used to ensure both methods are called every time.
795 const bool pipeline_progress = pipeline_.DidLoadingProgress(); 816 const bool pipeline_progress = pipeline_.DidLoadingProgress();
796 const bool data_progress = buffered_data_source_host_.DidLoadingProgress(); 817 const bool data_progress = buffered_data_source_host_.DidLoadingProgress();
797 const bool did_loading_progress = pipeline_progress || data_progress; 818 const bool did_loading_progress = pipeline_progress || data_progress;
798 819
799 // If we've idle suspended before reaching kHaveFutureData and loading has 820 if (did_loading_progress &&
800 // progressed we need to spin up the renderer and figure out if we have enough 821 highest_ready_state_ < ReadyState::ReadyStateHaveFutureData) {
801 // data yet; |client_| may be waiting on this signal to trigger playback. The 822 // Reset the preroll attempt clock.
802 // idle timeout is long enough that this is a low-cost operation. 823 preroll_attempt_pending_ = true;
803 if (highest_ready_state_ < ReadyState::ReadyStateHaveFutureData && 824 preroll_attempt_start_time_ = base::TimeTicks();
804 pipeline_controller_.IsSuspended() && did_loading_progress && is_idle_) { 825
805 is_idle_ = false; 826 // Clear any 'stale' flag and give the pipeline a chance to resume. If we
827 // are already resumed, this will cause |preroll_attempt_start_time_| to be
828 // set.
829 // TODO(sandersd): Should this be on the same stack? It might be surprsing
watk 2016/12/10 00:01:31 surprising
sandersd (OOO until July 31) 2017/01/05 23:12:20 Done.
830 // that didLoadingProgress() can synchronously change state.
831 if (delegate_)
832 delegate_->ClearStaleFlag(delegate_id_);
806 UpdatePlayState(); 833 UpdatePlayState();
807 } 834 }
808 835
809 if (did_loading_progress)
810 last_time_loading_progressed_ = tick_clock_->NowTicks();
811
812 return did_loading_progress; 836 return did_loading_progress;
813 } 837 }
814 838
815 void WebMediaPlayerImpl::paint(blink::WebCanvas* canvas, 839 void WebMediaPlayerImpl::paint(blink::WebCanvas* canvas,
816 const blink::WebRect& rect, 840 const blink::WebRect& rect,
817 SkPaint& paint) { 841 SkPaint& paint) {
818 DCHECK(main_task_runner_->BelongsToCurrentThread()); 842 DCHECK(main_task_runner_->BelongsToCurrentThread());
819 TRACE_EVENT0("media", "WebMediaPlayerImpl:paint"); 843 TRACE_EVENT0("media", "WebMediaPlayerImpl:paint");
820 844
821 // TODO(sandersd): Move this check into GetCurrentFrameFromCompositor() when 845 // TODO(sandersd): Move this check into GetCurrentFrameFromCompositor() when
(...skipping 372 matching lines...) Expand 10 before | Expand all | Expand 10 after
1194 // TODO(chcunningham): Monitor playback position vs buffered. Potentially 1218 // TODO(chcunningham): Monitor playback position vs buffered. Potentially
1195 // transition to HAVE_FUTURE_DATA here if not enough is buffered. 1219 // transition to HAVE_FUTURE_DATA here if not enough is buffered.
1196 SetReadyState(WebMediaPlayer::ReadyStateHaveEnoughData); 1220 SetReadyState(WebMediaPlayer::ReadyStateHaveEnoughData);
1197 1221
1198 // Let the DataSource know we have enough data. It may use this information 1222 // Let the DataSource know we have enough data. It may use this information
1199 // to release unused network connections. 1223 // to release unused network connections.
1200 if (data_source_) 1224 if (data_source_)
1201 data_source_->OnBufferingHaveEnough(false); 1225 data_source_->OnBufferingHaveEnough(false);
1202 1226
1203 // Blink expects a timeChanged() in response to a seek(). 1227 // Blink expects a timeChanged() in response to a seek().
1204 if (should_notify_time_changed_) 1228 if (should_notify_time_changed_) {
1229 should_notify_time_changed_ = false;
1205 client_->timeChanged(); 1230 client_->timeChanged();
1231 }
1206 1232
1207 // Once we have enough, start reporting the total memory usage. We'll also 1233 // Once we have enough, start reporting the total memory usage. We'll also
1208 // report once playback starts. 1234 // report once playback starts.
1209 ReportMemoryUsage(); 1235 ReportMemoryUsage();
1210 1236
1211 // Report the amount of time it took to leave the underflow state. Don't 1237 // Report the amount of time it took to leave the underflow state. Don't
1212 // bother to report this for MSE playbacks since it's out of our control. 1238 // bother to report this for MSE playbacks since it's out of our control.
1213 if (underflow_timer_ && data_source_) { 1239 if (underflow_timer_ && data_source_) {
1214 UMA_HISTOGRAM_TIMES("Media.UnderflowDuration", 1240 UMA_HISTOGRAM_TIMES("Media.UnderflowDuration",
1215 underflow_timer_->Elapsed()); 1241 underflow_timer_->Elapsed());
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after
1311 DCHECK(main_task_runner_->BelongsToCurrentThread()); 1337 DCHECK(main_task_runner_->BelongsToCurrentThread());
1312 DCHECK_NE(ready_state_, WebMediaPlayer::ReadyStateHaveNothing); 1338 DCHECK_NE(ready_state_, WebMediaPlayer::ReadyStateHaveNothing);
1313 1339
1314 opaque_ = opaque; 1340 opaque_ = opaque;
1315 // Modify content opaqueness of cc::Layer directly so that 1341 // Modify content opaqueness of cc::Layer directly so that
1316 // SetContentsOpaqueIsFixed is ignored. 1342 // SetContentsOpaqueIsFixed is ignored.
1317 if (video_weblayer_) 1343 if (video_weblayer_)
1318 video_weblayer_->layer()->SetContentsOpaque(opaque_); 1344 video_weblayer_->layer()->SetContentsOpaque(opaque_);
1319 } 1345 }
1320 1346
1321 void WebMediaPlayerImpl::OnHidden() { 1347 void WebMediaPlayerImpl::OnFrameHidden() {
1322 DCHECK(main_task_runner_->BelongsToCurrentThread()); 1348 DCHECK(main_task_runner_->BelongsToCurrentThread());
1323 1349
1324 if (IsBackgroundVideoTrackOptimizationEnabled()) 1350 if (IsBackgroundVideoTrackOptimizationEnabled())
1325 selectedVideoTrackChanged(nullptr); 1351 selectedVideoTrackChanged(nullptr);
1326 1352
1327 if (watch_time_reporter_) 1353 if (watch_time_reporter_)
1328 watch_time_reporter_->OnHidden(); 1354 watch_time_reporter_->OnHidden();
1329 1355
1330 UpdatePlayState(); 1356 UpdatePlayState();
1331 1357
1332 // Schedule suspended playing media to be paused if the user doesn't come back 1358 // Schedule suspended playing media to be paused if the user doesn't come back
1333 // to it within some timeout period to avoid any autoplay surprises. 1359 // to it within some timeout period to avoid any autoplay surprises.
1334 ScheduleIdlePauseTimer(); 1360 ScheduleIdlePauseTimer();
1335 } 1361 }
1336 1362
1337 void WebMediaPlayerImpl::OnShown() { 1363 void WebMediaPlayerImpl::OnFrameClosed() {
1338 DCHECK(main_task_runner_->BelongsToCurrentThread()); 1364 DCHECK(main_task_runner_->BelongsToCurrentThread());
1365 UpdatePlayState();
1366 }
1367
1368 void WebMediaPlayerImpl::OnFrameShown() {
1369 DCHECK(main_task_runner_->BelongsToCurrentThread());
1370 background_pause_timer_.Stop();
1371
1339 if (watch_time_reporter_) 1372 if (watch_time_reporter_)
1340 watch_time_reporter_->OnShown(); 1373 watch_time_reporter_->OnShown();
1341 1374
1342 if (IsBackgroundVideoTrackOptimizationEnabled() && 1375 if (IsBackgroundVideoTrackOptimizationEnabled() &&
1343 client_->hasSelectedVideoTrack()) { 1376 client_->hasSelectedVideoTrack()) {
1344 WebMediaPlayer::TrackId trackId = client_->getSelectedVideoTrackId(); 1377 WebMediaPlayer::TrackId trackId = client_->getSelectedVideoTrackId();
1345 selectedVideoTrackChanged(&trackId); 1378 selectedVideoTrackChanged(&trackId);
1346 } 1379 }
1347 1380
1348 must_suspend_ = false;
1349 background_pause_timer_.Stop();
1350
1351 UpdatePlayState(); 1381 UpdatePlayState();
1352 } 1382 }
1353 1383
1354 bool WebMediaPlayerImpl::OnSuspendRequested(bool must_suspend) { 1384 bool WebMediaPlayerImpl::OnIdleTimeout() {
1355 DCHECK(main_task_runner_->BelongsToCurrentThread()); 1385 DCHECK(main_task_runner_->BelongsToCurrentThread());
1386 if (IsPrerollAttemptNeeded())
1387 return false;
1356 1388
1357 if (must_suspend) { 1389 // Post the update as a task so that:
1358 must_suspend_ = true; 1390 // 1) IsStale() returns true in UpdatePlayState().
1359 UpdatePlayState(); 1391 // 2) We don't have to worry if we call SetIdle(false).
1360 return true; 1392 main_task_runner_->PostTask(
1361 } 1393 FROM_HERE, base::Bind(&WebMediaPlayerImpl::UpdatePlayState, AsWeakPtr()));
1362 1394
1363 // If we're beyond HaveFutureData, we can safely suspend at any time. 1395 return true;
1364 if (highest_ready_state_ >= WebMediaPlayer::ReadyStateHaveFutureData) {
1365 is_idle_ = true;
1366 UpdatePlayState();
1367 return true;
1368 }
1369
1370 // Before HaveFutureData blink will not call play(), so we must be careful to
1371 // only suspend if we'll eventually receive an event that will trigger a
1372 // resume. If the last time loading progressed was a while ago, and we still
1373 // haven't reached HaveFutureData, we assume that we're waiting on more data
1374 // to continue pre-rolling. When that data is loaded the pipeline will be
1375 // resumed by didLoadingProgress().
1376 if (last_time_loading_progressed_.is_null() ||
1377 (tick_clock_->NowTicks() - last_time_loading_progressed_) >
1378 kLoadingToIdleTimeout) {
1379 is_idle_ = true;
1380 UpdatePlayState();
1381 return true;
1382 }
1383
1384 return false;
1385 } 1396 }
1386 1397
1387 void WebMediaPlayerImpl::OnPlay() { 1398 void WebMediaPlayerImpl::OnPlay() {
1388 play(); 1399 play();
1389 client_->playbackStateChanged(); 1400 client_->playbackStateChanged();
1390 } 1401 }
1391 1402
1392 void WebMediaPlayerImpl::OnPause() { 1403 void WebMediaPlayerImpl::OnPause() {
1393 pause(); 1404 pause();
1394 client_->playbackStateChanged(); 1405 client_->playbackStateChanged();
(...skipping 322 matching lines...) Expand 10 before | Expand all | Expand 10 after
1717 bool is_streaming = false; 1728 bool is_streaming = false;
1718 #else 1729 #else
1719 bool is_remote = false; 1730 bool is_remote = false;
1720 bool is_streaming = data_source_ && data_source_->IsStreaming(); 1731 bool is_streaming = data_source_ && data_source_->IsStreaming();
1721 #endif 1732 #endif
1722 1733
1723 bool is_suspended = pipeline_controller_.IsSuspended(); 1734 bool is_suspended = pipeline_controller_.IsSuspended();
1724 bool is_backgrounded = IsBackgroundedSuspendEnabled() && IsHidden(); 1735 bool is_backgrounded = IsBackgroundedSuspendEnabled() && IsHidden();
1725 PlayState state = UpdatePlayState_ComputePlayState( 1736 PlayState state = UpdatePlayState_ComputePlayState(
1726 is_remote, is_streaming, is_suspended, is_backgrounded); 1737 is_remote, is_streaming, is_suspended, is_backgrounded);
1727 SetDelegateState(state.delegate_state); 1738 SetDelegateState(state.delegate_state, state.is_idle);
1728 SetMemoryReportingState(state.is_memory_reporting_enabled); 1739 SetMemoryReportingState(state.is_memory_reporting_enabled);
1729 SetSuspendState(state.is_suspended || pending_suspend_resume_cycle_); 1740 SetSuspendState(state.is_suspended || pending_suspend_resume_cycle_);
1730 } 1741 }
1731 1742
1732 void WebMediaPlayerImpl::SetDelegateState(DelegateState new_state) { 1743 void WebMediaPlayerImpl::SetDelegateState(DelegateState new_state,
1744 bool is_idle) {
1733 if (!delegate_) 1745 if (!delegate_)
1734 return; 1746 return;
1735 1747
1736 if (delegate_state_ == new_state) { 1748 switch (new_state) {
1737 if (delegate_state_ != DelegateState::PLAYING ||
1738 autoplay_muted_ == client_->isAutoplayingMuted()) {
1739 return;
1740 }
1741 }
1742
1743 delegate_state_ = new_state;
1744
1745 switch (delegate_state_) {
1746 case DelegateState::GONE: 1749 case DelegateState::GONE:
1747 delegate_->PlayerGone(delegate_id_); 1750 delegate_->PlayerGone(delegate_id_);
1748 break; 1751 break;
1749 case DelegateState::PLAYING: { 1752 case DelegateState::PLAYING: {
1750 autoplay_muted_ = client_->isAutoplayingMuted(); 1753 bool has_audio = hasAudio() && !client_->isAutoplayingMuted();
1751 bool has_audio = autoplay_muted_ ? false : hasAudio();
1752 delegate_->DidPlay( 1754 delegate_->DidPlay(
1753 delegate_id_, hasVideo(), has_audio, false, 1755 delegate_id_, has_audio, hasVideo(),
1754 media::DurationToMediaContentType(pipeline_.GetMediaDuration())); 1756 media::DurationToMediaContentType(pipeline_.GetMediaDuration()));
1755 break; 1757 break;
1756 } 1758 }
1757 case DelegateState::PAUSED: 1759 case DelegateState::PAUSED:
1758 delegate_->DidPause(delegate_id_, false); 1760 delegate_->DidPause(delegate_id_);
1759 break;
1760 case DelegateState::ENDED:
1761 delegate_->DidPause(delegate_id_, true);
1762 break; 1761 break;
1763 } 1762 }
1763
1764 delegate_->SetIdle(delegate_id_, is_idle);
1764 } 1765 }
1765 1766
1766 void WebMediaPlayerImpl::SetMemoryReportingState( 1767 void WebMediaPlayerImpl::SetMemoryReportingState(
1767 bool is_memory_reporting_enabled) { 1768 bool is_memory_reporting_enabled) {
1768 if (memory_usage_reporting_timer_.IsRunning() == 1769 if (memory_usage_reporting_timer_.IsRunning() ==
1769 is_memory_reporting_enabled) { 1770 is_memory_reporting_enabled) {
1770 return; 1771 return;
1771 } 1772 }
1772 1773
1773 if (is_memory_reporting_enabled) { 1774 if (is_memory_reporting_enabled) {
(...skipping 25 matching lines...) Expand all
1799 can_suspend_state_ = 1800 can_suspend_state_ =
1800 frame->metadata()->IsTrue(VideoFrameMetadata::DECODER_OWNS_FRAME) 1801 frame->metadata()->IsTrue(VideoFrameMetadata::DECODER_OWNS_FRAME)
1801 ? CanSuspendState::NO 1802 ? CanSuspendState::NO
1802 : CanSuspendState::YES; 1803 : CanSuspendState::YES;
1803 } 1804 }
1804 } 1805 }
1805 #else 1806 #else
1806 can_suspend_state_ = CanSuspendState::YES; 1807 can_suspend_state_ = CanSuspendState::YES;
1807 #endif 1808 #endif
1808 1809
1809 if (can_suspend_state_ == CanSuspendState::NO) 1810 if (is_suspended && can_suspend_state_ != CanSuspendState::NO) {
1810 return; 1811 // If we were not resumed for long enough to satisfy the preroll attempt,
1811 1812 // reset the clock.
1812 if (is_suspended) { 1813 if (!preroll_attempt_pending_ && IsPrerollAttemptNeeded()) {
1814 preroll_attempt_pending_ = true;
1815 preroll_attempt_start_time_ = base::TimeTicks();
1816 }
1813 pipeline_controller_.Suspend(); 1817 pipeline_controller_.Suspend();
1814 } else { 1818 } else {
1819 // When resuming, start the preroll attempt clock.
1820 if (preroll_attempt_pending_) {
1821 preroll_attempt_pending_ = false;
1822 preroll_attempt_start_time_ = tick_clock_->NowTicks();
1823 }
1815 pipeline_controller_.Resume(); 1824 pipeline_controller_.Resume();
1816 } 1825 }
1817 } 1826 }
1818 1827
1819 WebMediaPlayerImpl::PlayState 1828 WebMediaPlayerImpl::PlayState
1820 WebMediaPlayerImpl::UpdatePlayState_ComputePlayState(bool is_remote, 1829 WebMediaPlayerImpl::UpdatePlayState_ComputePlayState(bool is_remote,
1821 bool is_streaming, 1830 bool is_streaming,
1822 bool is_suspended, 1831 bool is_suspended,
1823 bool is_backgrounded) { 1832 bool is_backgrounded) {
1824 PlayState result; 1833 PlayState result;
1825 1834
1835 bool must_suspend = delegate_->IsFrameClosed();
1836 bool is_stale = delegate_->IsStale(delegate_id_);
1837
1826 // This includes both data source (before pipeline startup) and pipeline 1838 // This includes both data source (before pipeline startup) and pipeline
1827 // errors. 1839 // errors.
1828 bool has_error = IsNetworkStateError(network_state_); 1840 bool has_error = IsNetworkStateError(network_state_);
1829 1841
1830 // After HaveMetadata, we know which tracks are present and the duration. 1842 // After HaveMetadata, we know which tracks are present and the duration.
1831 bool have_metadata = ready_state_ >= WebMediaPlayer::ReadyStateHaveMetadata; 1843 bool have_metadata = ready_state_ >= WebMediaPlayer::ReadyStateHaveMetadata;
1832 1844
1833 // After HaveFutureData, Blink will call play() if the state is not paused; 1845 // After HaveFutureData, Blink will call play() if the state is not paused;
1834 // prior to this point |paused_| is not accurate. 1846 // prior to this point |paused_| is not accurate.
1835 bool have_future_data = 1847 bool have_future_data =
1836 highest_ready_state_ >= WebMediaPlayer::ReadyStateHaveFutureData; 1848 highest_ready_state_ >= WebMediaPlayer::ReadyStateHaveFutureData;
1837 1849
1838 // Background suspend is not enabled for audio-only players unless paused, 1850 // Background suspend is not enabled for audio-only players unless paused,
1839 // though in the case of audio-only the session should be kept. 1851 // though in the case of audio-only the session should be kept.
1840 // Videos are not suspended if the user resumed the playback via the remote 1852 // Videos are not suspended if the user resumed the playback via the remote
1841 // controls earlier and it's still playing. 1853 // controls earlier and it's still playing.
1842 bool is_backgrounded_video = is_backgrounded && have_metadata && hasVideo(); 1854 bool is_backgrounded_video = is_backgrounded && have_metadata && hasVideo();
1843 bool can_play_backgrounded = is_backgrounded_video && !is_remote && 1855 bool can_play_backgrounded = is_backgrounded_video && !is_remote &&
1844 hasAudio() && IsResumeBackgroundVideosEnabled(); 1856 hasAudio() &&
1845 bool is_background_playing = 1857 IsResumeBackgroundVideosEnabled() && delegate_ &&
1846 delegate_ && delegate_->IsPlayingBackgroundVideo(); 1858 delegate_->IsBackgroundVideoPlaybackAllowed();
1847 bool background_suspended = !is_streaming && is_backgrounded_video && 1859 bool background_suspended =
1848 !(can_play_backgrounded && is_background_playing); 1860 !is_streaming && is_backgrounded_video && !can_play_backgrounded;
1849 bool background_pause_suspended = 1861 bool background_pause_suspended =
1850 !is_streaming && is_backgrounded && paused_ && have_future_data; 1862 !is_streaming && is_backgrounded && paused_ && have_future_data;
1851 1863
1852 // Idle suspension is allowed prior to have future data since there exist 1864 // Idle suspension is allowed prior to have future data since there exist
1853 // mechanisms to exit the idle state when the player is capable of reaching 1865 // mechanisms to exit the idle state when the player is capable of reaching
1854 // the have future data state; see didLoadingProgress(). 1866 // the have future data state; see didLoadingProgress().
1855 // 1867 //
1856 // TODO(sandersd): Make the delegate suspend idle players immediately when 1868 // TODO(sandersd): Make the delegate suspend idle players immediately when
1857 // hidden. 1869 // hidden.
1858 bool idle_suspended = 1870 bool idle_suspended =
1859 !is_streaming && is_idle_ && paused_ && !seeking_ && !overlay_enabled_; 1871 !is_streaming && is_stale && paused_ && !seeking_ && !overlay_enabled_;
1860 1872
1861 // If we're already suspended, see if we can wait for user interaction. Prior 1873 // If we're already suspended, see if we can wait for user interaction. Prior
1862 // to HaveFutureData, we require |is_idle_| to remain suspended. |is_idle_| 1874 // to HaveFutureData, we require |is_stale| to remain suspended. |is_stale|
1863 // will be cleared when we receive data which may take us to HaveFutureData. 1875 // will be cleared when we receive data which may take us to HaveFutureData.
1864 bool can_stay_suspended = 1876 bool can_stay_suspended =
1865 (is_idle_ || have_future_data) && is_suspended && paused_ && !seeking_; 1877 (is_stale || have_future_data) && is_suspended && paused_ && !seeking_;
1866 1878
1867 // Combined suspend state. 1879 // Combined suspend state.
1868 result.is_suspended = is_remote || must_suspend_ || idle_suspended || 1880 result.is_suspended = is_remote || must_suspend || idle_suspended ||
1869 background_suspended || background_pause_suspended || 1881 background_suspended || background_pause_suspended ||
1870 can_stay_suspended; 1882 can_stay_suspended;
1871 1883
1872 // We do not treat |playback_rate_| == 0 as paused. For the media session, 1884 // We do not treat |playback_rate_| == 0 as paused. For the media session,
1873 // being paused implies displaying a play button, which is incorrect in this 1885 // being paused implies displaying a play button, which is incorrect in this
1874 // case. For memory usage reporting, we just use the same definition (but we 1886 // case. For memory usage reporting, we just use the same definition (but we
1875 // don't have to). 1887 // don't have to).
1876 // 1888 //
1877 // Similarly, we don't consider |ended_| to be paused. Blink will immediately 1889 // Similarly, we don't consider |ended_| to be paused. Blink will immediately
1878 // call pause() or seek(), so |ended_| should not affect the computation. 1890 // call pause() or seek(), so |ended_| should not affect the computation.
1879 // Despite that, |ended_| does result in a separate paused state, to simplfy 1891 // Despite that, |ended_| does result in a separate paused state, to simplfy
1880 // the contract for SetDelegateState(). 1892 // the contract for SetDelegateState().
1881 // 1893 //
1882 // |has_session| is used to decide when to create a media session. Idle 1894 // |has_session| is used to decide when to create a media session. Idle
1883 // suspension does not destroy the media session, because we expect that the 1895 // suspension does not destroy the media session, because we expect that the
1884 // notification controls (and audio focus) remain. We also require: 1896 // notification controls (and audio focus) remain. We also require:
1885 // - |have_metadata|, since the tracks and duration are passed to DidPlay(). 1897 // - |have_metadata|, since the tracks and duration are passed to DidPlay().
1886 // - |have_future_data|, since we need to know whether we are paused to 1898 // - |have_future_data|, since we need to know whether we are paused to
1887 // correctly configure the session. 1899 // correctly configure the session.
1888 // 1900 //
1889 // TODO(sandersd): If Blink told us the paused state sooner, we could create 1901 // TODO(sandersd): If Blink told us the paused state sooner, we could create
1890 // the media session sooner. 1902 // the media session sooner.
1891 bool can_play = !has_error && !is_remote && have_future_data; 1903 bool can_play = !has_error && !is_remote && have_future_data;
1892 bool has_session_playing = 1904 bool has_session_playing = can_play && !must_suspend && !background_suspended;
1893 can_play && !must_suspend_ && !background_suspended;
1894 1905
1895 // |has_session_suspended| means the player is suspended from the media 1906 // |has_session_suspended| means the player is suspended from the media
1896 // element point of view but paused and can be resumed from the delegate point 1907 // element point of view but paused and can be resumed from the delegate point
1897 // of view. Therefore it behaves like |paused_| for the delegate. 1908 // of view. Therefore it behaves like |paused_| for the delegate.
1898 bool has_session_suspended = can_play && !must_suspend_ && 1909 bool has_session_suspended = can_play && !must_suspend &&
1899 background_suspended && can_play_backgrounded; 1910 background_suspended && can_play_backgrounded;
1900 1911
1901 bool has_session = has_session_playing || has_session_suspended; 1912 bool has_session = has_session_playing || has_session_suspended;
1902 1913
1903 if (!has_session) { 1914 if (!has_session) {
1904 result.delegate_state = DelegateState::GONE; 1915 result.delegate_state = DelegateState::GONE;
1916 result.is_idle = delegate_ && delegate_->IsIdle(delegate_id_);
1905 } else if (paused_ || has_session_suspended) { 1917 } else if (paused_ || has_session_suspended) {
1918 // TODO(sandersd): Is it possible to have a suspended session, be ended,
1919 // and not be paused? If so we should be in a PLAYING state.
1906 result.delegate_state = 1920 result.delegate_state =
1907 ended_ ? DelegateState::ENDED : DelegateState::PAUSED; 1921 ended_ ? DelegateState::GONE : DelegateState::PAUSED;
1922 result.is_idle = !seeking_;
1908 } else { 1923 } else {
1909 result.delegate_state = DelegateState::PLAYING; 1924 result.delegate_state = DelegateState::PLAYING;
1925 result.is_idle = false;
1910 } 1926 }
1911 1927
1912 // It's not critical if some cases where memory usage can change are missed, 1928 // It's not critical if some cases where memory usage can change are missed,
1913 // since media memory changes are usually gradual. 1929 // since media memory changes are usually gradual.
1914 result.is_memory_reporting_enabled = 1930 result.is_memory_reporting_enabled =
1915 can_play && !result.is_suspended && !paused_; 1931 can_play && !result.is_suspended && (!paused_ || seeking_);
1916 1932
1917 return result; 1933 return result;
1918 } 1934 }
1919 1935
1920 void WebMediaPlayerImpl::ReportMemoryUsage() { 1936 void WebMediaPlayerImpl::ReportMemoryUsage() {
1921 DCHECK(main_task_runner_->BelongsToCurrentThread()); 1937 DCHECK(main_task_runner_->BelongsToCurrentThread());
1922 1938
1923 // About base::Unretained() usage below: We destroy |demuxer_| on the main 1939 // About base::Unretained() usage below: We destroy |demuxer_| on the main
1924 // thread. Before that, however, ~WebMediaPlayerImpl() posts a task to the 1940 // thread. Before that, however, ~WebMediaPlayerImpl() posts a task to the
1925 // media thread and waits for it to finish. Hence, the GetMemoryUsage() task 1941 // media thread and waits for it to finish. Hence, the GetMemoryUsage() task
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
1973 this, &WebMediaPlayerImpl::OnPause); 1989 this, &WebMediaPlayerImpl::OnPause);
1974 } 1990 }
1975 1991
1976 void WebMediaPlayerImpl::CreateWatchTimeReporter() { 1992 void WebMediaPlayerImpl::CreateWatchTimeReporter() {
1977 // Create the watch time reporter and synchronize its initial state. 1993 // Create the watch time reporter and synchronize its initial state.
1978 watch_time_reporter_.reset(new WatchTimeReporter( 1994 watch_time_reporter_.reset(new WatchTimeReporter(
1979 hasAudio(), hasVideo(), !!chunk_demuxer_, is_encrypted_, media_log_, 1995 hasAudio(), hasVideo(), !!chunk_demuxer_, is_encrypted_, media_log_,
1980 pipeline_metadata_.natural_size, 1996 pipeline_metadata_.natural_size,
1981 base::Bind(&GetCurrentTimeInternal, this))); 1997 base::Bind(&GetCurrentTimeInternal, this)));
1982 watch_time_reporter_->OnVolumeChange(volume_); 1998 watch_time_reporter_->OnVolumeChange(volume_);
1983 if (IsHidden()) 1999 if (delegate_ && delegate_->IsFrameHidden())
watk 2016/12/10 00:01:31 Seems like this should still call IsHidden?
sandersd (OOO until July 31) 2017/01/05 23:12:20 I'm not sure. I think that means that we could rep
1984 watch_time_reporter_->OnHidden(); 2000 watch_time_reporter_->OnHidden();
1985 else 2001 else
1986 watch_time_reporter_->OnShown(); 2002 watch_time_reporter_->OnShown();
1987 } 2003 }
1988 2004
1989 bool WebMediaPlayerImpl::IsHidden() const { 2005 bool WebMediaPlayerImpl::IsHidden() const {
1990 DCHECK(main_task_runner_->BelongsToCurrentThread()); 2006 DCHECK(main_task_runner_->BelongsToCurrentThread());
1991 2007
1992 return delegate_ && delegate_->IsHidden(); 2008 return delegate_ && delegate_->IsFrameHidden() && !delegate_->IsFrameClosed();
1993 } 2009 }
1994 2010
1995 } // namespace media 2011 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698