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

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

Issue 2490783002: Refactor WebMediaPlayerDelegate interface. (Closed)
Patch Set: Unit tests found a real bug! 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
« no previous file with comments | « media/blink/webmediaplayer_impl.h ('k') | media/blink/webmediaplayer_impl_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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,
(...skipping 10 matching lines...) Expand all
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), 184 delegate_state_(DelegateState::GONE),
185 is_idle_(false), 185 delegate_has_audio_(false),
186 must_suspend_(false),
187 network_state_(WebMediaPlayer::NetworkStateEmpty), 186 network_state_(WebMediaPlayer::NetworkStateEmpty),
188 ready_state_(WebMediaPlayer::ReadyStateHaveNothing), 187 ready_state_(WebMediaPlayer::ReadyStateHaveNothing),
189 highest_ready_state_(WebMediaPlayer::ReadyStateHaveNothing), 188 highest_ready_state_(WebMediaPlayer::ReadyStateHaveNothing),
190 preload_(MultibufferDataSource::AUTO), 189 preload_(MultibufferDataSource::AUTO),
191 buffering_strategy_(MultibufferDataSource::BUFFERING_STRATEGY_NORMAL), 190 buffering_strategy_(MultibufferDataSource::BUFFERING_STRATEGY_NORMAL),
192 main_task_runner_(frame->loadingTaskRunner()), 191 main_task_runner_(frame->loadingTaskRunner()),
193 media_task_runner_(params.media_task_runner()), 192 media_task_runner_(params.media_task_runner()),
194 worker_task_runner_(params.worker_task_runner()), 193 worker_task_runner_(params.worker_task_runner()),
195 media_log_(params.media_log()), 194 media_log_(params.media_log()),
196 pipeline_(media_task_runner_, media_log_.get()), 195 pipeline_(media_task_runner_, media_log_.get()),
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
236 volume_(1.0), 235 volume_(1.0),
237 volume_multiplier_(1.0), 236 volume_multiplier_(1.0),
238 renderer_factory_(std::move(renderer_factory)), 237 renderer_factory_(std::move(renderer_factory)),
239 surface_manager_(params.surface_manager()), 238 surface_manager_(params.surface_manager()),
240 overlay_surface_id_(SurfaceManager::kNoSurfaceID), 239 overlay_surface_id_(SurfaceManager::kNoSurfaceID),
241 suppress_destruction_errors_(false), 240 suppress_destruction_errors_(false),
242 can_suspend_state_(CanSuspendState::UNKNOWN), 241 can_suspend_state_(CanSuspendState::UNKNOWN),
243 use_fallback_path_(false), 242 use_fallback_path_(false),
244 is_encrypted_(false), 243 is_encrypted_(false),
245 underflow_count_(0), 244 underflow_count_(0),
245 preroll_attempt_pending_(false),
246 observer_(params.media_observer()) { 246 observer_(params.media_observer()) {
247 DCHECK(!adjust_allocated_memory_cb_.is_null()); 247 DCHECK(!adjust_allocated_memory_cb_.is_null());
248 DCHECK(renderer_factory_); 248 DCHECK(renderer_factory_);
249 DCHECK(client_); 249 DCHECK(client_);
250 250
251 tick_clock_.reset(new base::DefaultTickClock()); 251 tick_clock_.reset(new base::DefaultTickClock());
252 252
253 force_video_overlays_ = base::CommandLine::ForCurrentProcess()->HasSwitch( 253 force_video_overlays_ = base::CommandLine::ForCurrentProcess()->HasSwitch(
254 switches::kForceVideoOverlays); 254 switches::kForceVideoOverlays);
255 255
256 if (delegate_) 256 if (delegate_) {
257 delegate_id_ = delegate_->AddObserver(this); 257 delegate_id_ = delegate_->AddObserver(this);
258 delegate_->SetIdle(delegate_id_, true);
259 }
258 260
259 media_log_->AddEvent( 261 media_log_->AddEvent(
260 media_log_->CreateEvent(MediaLogEvent::WEBMEDIAPLAYER_CREATED)); 262 media_log_->CreateEvent(MediaLogEvent::WEBMEDIAPLAYER_CREATED));
261 263
262 if (params.initial_cdm()) 264 if (params.initial_cdm())
263 SetCdm(params.initial_cdm()); 265 SetCdm(params.initial_cdm());
264 266
265 // TODO(xhwang): When we use an external Renderer, many methods won't work, 267 // TODO(xhwang): When we use an external Renderer, many methods won't work,
266 // e.g. GetCurrentFrameFromCompositor(). See http://crbug.com/434861 268 // e.g. GetCurrentFrameFromCompositor(). See http://crbug.com/434861
267 audio_source_provider_ = 269 audio_source_provider_ =
(...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after
418 void WebMediaPlayerImpl::play() { 420 void WebMediaPlayerImpl::play() {
419 DVLOG(1) << __func__; 421 DVLOG(1) << __func__;
420 DCHECK(main_task_runner_->BelongsToCurrentThread()); 422 DCHECK(main_task_runner_->BelongsToCurrentThread());
421 423
422 #if defined(OS_ANDROID) // WMPI_CAST 424 #if defined(OS_ANDROID) // WMPI_CAST
423 if (isRemote()) { 425 if (isRemote()) {
424 cast_impl_.play(); 426 cast_impl_.play();
425 return; 427 return;
426 } 428 }
427 #endif 429 #endif
430 // TODO(sandersd): Do we want to reset the idle timer here?
431 if (delegate_)
432 delegate_->SetIdle(delegate_id_, false);
428 paused_ = false; 433 paused_ = false;
429 is_idle_ = false;
430 pipeline_.SetPlaybackRate(playback_rate_); 434 pipeline_.SetPlaybackRate(playback_rate_);
431 background_pause_timer_.Stop(); 435 background_pause_timer_.Stop();
432 436
433 if (data_source_) 437 if (data_source_)
434 data_source_->MediaIsPlaying(); 438 data_source_->MediaIsPlaying();
435 439
436 if (observer_) 440 if (observer_)
437 observer_->OnPlaying(); 441 observer_->OnPlaying();
438 442
439 DCHECK(watch_time_reporter_); 443 DCHECK(watch_time_reporter_);
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after
524 AsWeakPtr(), BUFFERING_HAVE_ENOUGH)); 528 AsWeakPtr(), BUFFERING_HAVE_ENOUGH));
525 } 529 }
526 return; 530 return;
527 } 531 }
528 532
529 // Call this before setting |seeking_| so that the current media time can be 533 // Call this before setting |seeking_| so that the current media time can be
530 // recorded by the reporter. 534 // recorded by the reporter.
531 if (watch_time_reporter_) 535 if (watch_time_reporter_)
532 watch_time_reporter_->OnSeeking(); 536 watch_time_reporter_->OnSeeking();
533 537
534 // TODO(sandersd): Ideally we would not clear the idle state if 538 // TODO(sandersd): Move |seeking_| to PipelineController.
535 // |pipeline_controller_| can elide the seek. 539 // TODO(sandersd): Do we want to reset the idle timer here?
536 is_idle_ = false; 540 if (delegate_)
541 delegate_->SetIdle(delegate_id_, false);
537 ended_ = false; 542 ended_ = false;
538
539 seeking_ = true; 543 seeking_ = true;
540 seek_time_ = time; 544 seek_time_ = time;
541 if (paused_) 545 if (paused_)
542 paused_time_ = time; 546 paused_time_ = time;
543 pipeline_controller_.Seek(time, time_updated); 547 pipeline_controller_.Seek(time, time_updated);
544 548
545 // This needs to be called after Seek() so that if a resume is triggered, it 549 // This needs to be called after Seek() so that if a resume is triggered, it
546 // is to the correct time. 550 // is to the correct time.
547 UpdatePlayState(); 551 UpdatePlayState();
548 } 552 }
(...skipping 259 matching lines...) Expand 10 before | Expand all | Expand 10 after
808 const bool force_seeks_to_zero = !use_fallback_path_ && is_finite_stream; 812 const bool force_seeks_to_zero = !use_fallback_path_ && is_finite_stream;
809 813
810 // TODO(dalecurtis): Technically this allows seeking on media which return an 814 // TODO(dalecurtis): Technically this allows seeking on media which return an
811 // infinite duration so long as DataSource::IsStreaming() is false. While not 815 // infinite duration so long as DataSource::IsStreaming() is false. While not
812 // expected, disabling this breaks semi-live players, http://crbug.com/427412. 816 // expected, disabling this breaks semi-live players, http://crbug.com/427412.
813 const blink::WebTimeRange seekable_range( 817 const blink::WebTimeRange seekable_range(
814 0.0, force_seeks_to_zero ? 0.0 : seekable_end); 818 0.0, force_seeks_to_zero ? 0.0 : seekable_end);
815 return blink::WebTimeRanges(&seekable_range, 1); 819 return blink::WebTimeRanges(&seekable_range, 1);
816 } 820 }
817 821
822 bool WebMediaPlayerImpl::IsPrerollAttemptNeeded() {
823 // TODO(sandersd): Replace with |highest_ready_state_since_seek_| if we need
824 // to ensure that preroll always gets a chance to complete.
825 // See http://crbug.com/671525.
826 if (highest_ready_state_ >= ReadyState::ReadyStateHaveFutureData)
827 return false;
828
829 if (preroll_attempt_pending_)
830 return true;
831
832 // Freshly initialized; there has never been any loading progress. (Otherwise
833 // |preroll_attempt_pending_| would be true when the start time is null.)
834 if (preroll_attempt_start_time_.is_null())
835 return false;
836
837 base::TimeDelta preroll_attempt_duration =
838 tick_clock_->NowTicks() - preroll_attempt_start_time_;
839 return preroll_attempt_duration < kPrerollAttemptTimeout;
840 }
841
818 bool WebMediaPlayerImpl::didLoadingProgress() { 842 bool WebMediaPlayerImpl::didLoadingProgress() {
819 DCHECK(main_task_runner_->BelongsToCurrentThread()); 843 DCHECK(main_task_runner_->BelongsToCurrentThread());
820 844
821 // Note: Separate variables used to ensure both methods are called every time. 845 // Note: Separate variables used to ensure both methods are called every time.
822 const bool pipeline_progress = pipeline_.DidLoadingProgress(); 846 const bool pipeline_progress = pipeline_.DidLoadingProgress();
823 const bool data_progress = buffered_data_source_host_.DidLoadingProgress(); 847 const bool data_progress = buffered_data_source_host_.DidLoadingProgress();
824 const bool did_loading_progress = pipeline_progress || data_progress; 848 const bool did_loading_progress = pipeline_progress || data_progress;
825 849
826 // If we've idle suspended before reaching kHaveFutureData and loading has 850 if (did_loading_progress &&
827 // progressed we need to spin up the renderer and figure out if we have enough 851 highest_ready_state_ < ReadyState::ReadyStateHaveFutureData) {
828 // data yet; |client_| may be waiting on this signal to trigger playback. The 852 // Reset the preroll attempt clock.
829 // idle timeout is long enough that this is a low-cost operation. 853 preroll_attempt_pending_ = true;
830 if (highest_ready_state_ < ReadyState::ReadyStateHaveFutureData && 854 preroll_attempt_start_time_ = base::TimeTicks();
831 pipeline_controller_.IsSuspended() && did_loading_progress && is_idle_) { 855
832 is_idle_ = false; 856 // Clear any 'stale' flag and give the pipeline a chance to resume. If we
857 // are already resumed, this will cause |preroll_attempt_start_time_| to be
858 // set.
859 // TODO(sandersd): Should this be on the same stack? It might be surprising
860 // that didLoadingProgress() can synchronously change state.
861 if (delegate_)
862 delegate_->ClearStaleFlag(delegate_id_);
833 UpdatePlayState(); 863 UpdatePlayState();
834 } 864 }
835 865
836 if (did_loading_progress)
837 last_time_loading_progressed_ = tick_clock_->NowTicks();
838
839 return did_loading_progress; 866 return did_loading_progress;
840 } 867 }
841 868
842 void WebMediaPlayerImpl::paint(blink::WebCanvas* canvas, 869 void WebMediaPlayerImpl::paint(blink::WebCanvas* canvas,
843 const blink::WebRect& rect, 870 const blink::WebRect& rect,
844 SkPaint& paint) { 871 SkPaint& paint) {
845 DCHECK(main_task_runner_->BelongsToCurrentThread()); 872 DCHECK(main_task_runner_->BelongsToCurrentThread());
846 TRACE_EVENT0("media", "WebMediaPlayerImpl:paint"); 873 TRACE_EVENT0("media", "WebMediaPlayerImpl:paint");
847 874
848 // TODO(sandersd): Move this check into GetCurrentFrameFromCompositor() when 875 // TODO(sandersd): Move this check into GetCurrentFrameFromCompositor() when
(...skipping 397 matching lines...) Expand 10 before | Expand all | Expand 10 after
1246 // TODO(chcunningham): Monitor playback position vs buffered. Potentially 1273 // TODO(chcunningham): Monitor playback position vs buffered. Potentially
1247 // transition to HAVE_FUTURE_DATA here if not enough is buffered. 1274 // transition to HAVE_FUTURE_DATA here if not enough is buffered.
1248 SetReadyState(WebMediaPlayer::ReadyStateHaveEnoughData); 1275 SetReadyState(WebMediaPlayer::ReadyStateHaveEnoughData);
1249 1276
1250 // Let the DataSource know we have enough data. It may use this information 1277 // Let the DataSource know we have enough data. It may use this information
1251 // to release unused network connections. 1278 // to release unused network connections.
1252 if (data_source_) 1279 if (data_source_)
1253 data_source_->OnBufferingHaveEnough(false); 1280 data_source_->OnBufferingHaveEnough(false);
1254 1281
1255 // Blink expects a timeChanged() in response to a seek(). 1282 // Blink expects a timeChanged() in response to a seek().
1256 if (should_notify_time_changed_) 1283 if (should_notify_time_changed_) {
1284 should_notify_time_changed_ = false;
1257 client_->timeChanged(); 1285 client_->timeChanged();
1286 }
1258 1287
1259 // Once we have enough, start reporting the total memory usage. We'll also 1288 // Once we have enough, start reporting the total memory usage. We'll also
1260 // report once playback starts. 1289 // report once playback starts.
1261 ReportMemoryUsage(); 1290 ReportMemoryUsage();
1262 1291
1263 // Report the amount of time it took to leave the underflow state. Don't 1292 // Report the amount of time it took to leave the underflow state. Don't
1264 // bother to report this for MSE playbacks since it's out of our control. 1293 // bother to report this for MSE playbacks since it's out of our control.
1265 if (underflow_timer_ && data_source_) { 1294 if (underflow_timer_ && data_source_) {
1266 UMA_HISTOGRAM_TIMES("Media.UnderflowDuration", 1295 UMA_HISTOGRAM_TIMES("Media.UnderflowDuration",
1267 underflow_timer_->Elapsed()); 1296 underflow_timer_->Elapsed());
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after
1368 DCHECK(main_task_runner_->BelongsToCurrentThread()); 1397 DCHECK(main_task_runner_->BelongsToCurrentThread());
1369 DCHECK_NE(ready_state_, WebMediaPlayer::ReadyStateHaveNothing); 1398 DCHECK_NE(ready_state_, WebMediaPlayer::ReadyStateHaveNothing);
1370 1399
1371 opaque_ = opaque; 1400 opaque_ = opaque;
1372 // Modify content opaqueness of cc::Layer directly so that 1401 // Modify content opaqueness of cc::Layer directly so that
1373 // SetContentsOpaqueIsFixed is ignored. 1402 // SetContentsOpaqueIsFixed is ignored.
1374 if (video_weblayer_) 1403 if (video_weblayer_)
1375 video_weblayer_->layer()->SetContentsOpaque(opaque_); 1404 video_weblayer_->layer()->SetContentsOpaque(opaque_);
1376 } 1405 }
1377 1406
1378 void WebMediaPlayerImpl::OnHidden() { 1407 void WebMediaPlayerImpl::OnFrameHidden() {
1379 DCHECK(main_task_runner_->BelongsToCurrentThread()); 1408 DCHECK(main_task_runner_->BelongsToCurrentThread());
1380 1409
1381 if (watch_time_reporter_) 1410 if (watch_time_reporter_)
1382 watch_time_reporter_->OnHidden(); 1411 watch_time_reporter_->OnHidden();
1383 1412
1384 if (ShouldPauseWhenHidden()) { 1413 if (ShouldPauseWhenHidden()) {
1385 if (!paused_when_hidden_) { 1414 if (!paused_when_hidden_) {
1386 // OnPause() will set |paused_when_hidden_| to false and call 1415 // OnPause() will set |paused_when_hidden_| to false and call
1387 // UpdatePlayState(), so set the flag to true after and then return. 1416 // UpdatePlayState(), so set the flag to true after and then return.
1388 OnPause(); 1417 OnPause();
1389 paused_when_hidden_ = true; 1418 paused_when_hidden_ = true;
1390 return; 1419 return;
1391 } 1420 }
1392 } else { 1421 } else {
1393 DisableVideoTrackIfNeeded(); 1422 DisableVideoTrackIfNeeded();
1394 } 1423 }
1395 1424
1396 UpdatePlayState(); 1425 UpdatePlayState();
1397 1426
1398 // Schedule suspended playing media to be paused if the user doesn't come back 1427 // Schedule suspended playing media to be paused if the user doesn't come back
1399 // to it within some timeout period to avoid any autoplay surprises. 1428 // to it within some timeout period to avoid any autoplay surprises.
1400 ScheduleIdlePauseTimer(); 1429 ScheduleIdlePauseTimer();
1401 } 1430 }
1402 1431
1403 void WebMediaPlayerImpl::OnShown() { 1432 void WebMediaPlayerImpl::OnFrameClosed() {
1404 DCHECK(main_task_runner_->BelongsToCurrentThread()); 1433 DCHECK(main_task_runner_->BelongsToCurrentThread());
1434 UpdatePlayState();
1435 }
1436
1437 void WebMediaPlayerImpl::OnFrameShown() {
1438 DCHECK(main_task_runner_->BelongsToCurrentThread());
1439 background_pause_timer_.Stop();
1440
1405 if (watch_time_reporter_) 1441 if (watch_time_reporter_)
1406 watch_time_reporter_->OnShown(); 1442 watch_time_reporter_->OnShown();
1407 1443
1408 compositor_task_runner_->PostTask( 1444 compositor_task_runner_->PostTask(
1409 FROM_HERE, 1445 FROM_HERE,
1410 base::Bind(&VideoFrameCompositor::SetForegroundTime, 1446 base::Bind(&VideoFrameCompositor::SetForegroundTime,
1411 base::Unretained(compositor_), base::TimeTicks::Now())); 1447 base::Unretained(compositor_), base::TimeTicks::Now()));
1412 1448
1413 must_suspend_ = false;
1414 background_pause_timer_.Stop();
1415
1416 if (paused_when_hidden_) { 1449 if (paused_when_hidden_) {
1417 paused_when_hidden_ = false; 1450 paused_when_hidden_ = false;
1418 OnPlay(); // Calls UpdatePlayState() so return afterwards. 1451 OnPlay(); // Calls UpdatePlayState() so return afterwards.
1419 return; 1452 return;
1420 } 1453 }
1421 1454
1422 EnableVideoTrackIfNeeded(); 1455 EnableVideoTrackIfNeeded();
1423 1456
1424 UpdatePlayState(); 1457 UpdatePlayState();
1425 } 1458 }
1426 1459
1427 bool WebMediaPlayerImpl::OnSuspendRequested(bool must_suspend) { 1460 void WebMediaPlayerImpl::OnIdleTimeout() {
1428 DCHECK(main_task_runner_->BelongsToCurrentThread()); 1461 DCHECK(main_task_runner_->BelongsToCurrentThread());
1429 1462
1430 if (must_suspend) { 1463 // If we are attempting preroll, clear the stale flag.
1431 must_suspend_ = true; 1464 if (IsPrerollAttemptNeeded()) {
1432 UpdatePlayState(); 1465 if (delegate_)
1433 return true; 1466 delegate_->ClearStaleFlag(delegate_id_);
1467 return;
1434 } 1468 }
1435 1469
1436 // If we're beyond HaveFutureData, we can safely suspend at any time. 1470 UpdatePlayState();
1437 if (highest_ready_state_ >= WebMediaPlayer::ReadyStateHaveFutureData) {
1438 is_idle_ = true;
1439 UpdatePlayState();
1440 return true;
1441 }
1442
1443 // Before HaveFutureData blink will not call play(), so we must be careful to
1444 // only suspend if we'll eventually receive an event that will trigger a
1445 // resume. If the last time loading progressed was a while ago, and we still
1446 // haven't reached HaveFutureData, we assume that we're waiting on more data
1447 // to continue pre-rolling. When that data is loaded the pipeline will be
1448 // resumed by didLoadingProgress().
1449 if (last_time_loading_progressed_.is_null() ||
1450 (tick_clock_->NowTicks() - last_time_loading_progressed_) >
1451 kLoadingToIdleTimeout) {
1452 is_idle_ = true;
1453 UpdatePlayState();
1454 return true;
1455 }
1456
1457 return false;
1458 } 1471 }
1459 1472
1460 void WebMediaPlayerImpl::OnPlay() { 1473 void WebMediaPlayerImpl::OnPlay() {
1461 play(); 1474 play();
1462 client_->playbackStateChanged(); 1475 client_->playbackStateChanged();
1463 } 1476 }
1464 1477
1465 void WebMediaPlayerImpl::OnPause() { 1478 void WebMediaPlayerImpl::OnPause() {
1466 pause(); 1479 pause();
1467 client_->playbackStateChanged(); 1480 client_->playbackStateChanged();
(...skipping 316 matching lines...) Expand 10 before | Expand all | Expand 10 after
1784 bool is_streaming = false; 1797 bool is_streaming = false;
1785 #else 1798 #else
1786 bool is_remote = false; 1799 bool is_remote = false;
1787 bool is_streaming = IsStreaming(); 1800 bool is_streaming = IsStreaming();
1788 #endif 1801 #endif
1789 1802
1790 bool is_suspended = pipeline_controller_.IsSuspended(); 1803 bool is_suspended = pipeline_controller_.IsSuspended();
1791 bool is_backgrounded = IsBackgroundedSuspendEnabled() && IsHidden(); 1804 bool is_backgrounded = IsBackgroundedSuspendEnabled() && IsHidden();
1792 PlayState state = UpdatePlayState_ComputePlayState( 1805 PlayState state = UpdatePlayState_ComputePlayState(
1793 is_remote, is_streaming, is_suspended, is_backgrounded); 1806 is_remote, is_streaming, is_suspended, is_backgrounded);
1794 SetDelegateState(state.delegate_state); 1807 SetDelegateState(state.delegate_state, state.is_idle);
1795 SetMemoryReportingState(state.is_memory_reporting_enabled); 1808 SetMemoryReportingState(state.is_memory_reporting_enabled);
1796 SetSuspendState(state.is_suspended || pending_suspend_resume_cycle_); 1809 SetSuspendState(state.is_suspended || pending_suspend_resume_cycle_);
1797 } 1810 }
1798 1811
1799 void WebMediaPlayerImpl::SetDelegateState(DelegateState new_state) { 1812 void WebMediaPlayerImpl::SetDelegateState(DelegateState new_state,
1813 bool is_idle) {
1800 if (!delegate_) 1814 if (!delegate_)
1801 return; 1815 return;
1802 1816
1803 if (delegate_state_ == new_state) { 1817 // Prevent duplicate delegate calls.
1804 if (delegate_state_ != DelegateState::PLAYING || 1818 // TODO(sandersd): Move this deduplication into the delegate itself.
1805 autoplay_muted_ == client_->isAutoplayingMuted()) { 1819 // TODO(sandersd): WebContentsObserverSanityChecker does not allow sending the
1806 return; 1820 // 'playing' IPC more than once in a row, even if the metadata has changed.
1807 } 1821 // Figure out whether it should.
1822 bool has_audio = hasAudio() && !client_->isAutoplayingMuted();
1823 if (delegate_state_ == new_state &&
1824 (delegate_state_ != DelegateState::PLAYING ||
1825 delegate_has_audio_ == has_audio)) {
1826 return;
1808 } 1827 }
1828 delegate_state_ = new_state;
1829 delegate_has_audio_ = has_audio;
1809 1830
1810 delegate_state_ = new_state; 1831 switch (new_state) {
1811
1812 switch (delegate_state_) {
1813 case DelegateState::GONE: 1832 case DelegateState::GONE:
1814 delegate_->PlayerGone(delegate_id_); 1833 delegate_->PlayerGone(delegate_id_);
1815 break; 1834 break;
1816 case DelegateState::PLAYING: { 1835 case DelegateState::PLAYING: {
1817 autoplay_muted_ = client_->isAutoplayingMuted();
1818 bool has_audio = autoplay_muted_ ? false : hasAudio();
1819 delegate_->DidPlay( 1836 delegate_->DidPlay(
1820 delegate_id_, hasVideo(), has_audio, false, 1837 delegate_id_, hasVideo(), has_audio,
1821 media::DurationToMediaContentType(pipeline_.GetMediaDuration())); 1838 media::DurationToMediaContentType(pipeline_.GetMediaDuration()));
1822 break; 1839 break;
1823 } 1840 }
1824 case DelegateState::PAUSED: 1841 case DelegateState::PAUSED:
1825 delegate_->DidPause(delegate_id_, false); 1842 delegate_->DidPause(delegate_id_);
1826 break;
1827 case DelegateState::ENDED:
1828 delegate_->DidPause(delegate_id_, true);
1829 break; 1843 break;
1830 } 1844 }
1845
1846 delegate_->SetIdle(delegate_id_, is_idle);
1831 } 1847 }
1832 1848
1833 void WebMediaPlayerImpl::SetMemoryReportingState( 1849 void WebMediaPlayerImpl::SetMemoryReportingState(
1834 bool is_memory_reporting_enabled) { 1850 bool is_memory_reporting_enabled) {
1835 if (memory_usage_reporting_timer_.IsRunning() == 1851 if (memory_usage_reporting_timer_.IsRunning() ==
1836 is_memory_reporting_enabled) { 1852 is_memory_reporting_enabled) {
1837 return; 1853 return;
1838 } 1854 }
1839 1855
1840 if (is_memory_reporting_enabled) { 1856 if (is_memory_reporting_enabled) {
(...skipping 25 matching lines...) Expand all
1866 can_suspend_state_ = 1882 can_suspend_state_ =
1867 frame->metadata()->IsTrue(VideoFrameMetadata::DECODER_OWNS_FRAME) 1883 frame->metadata()->IsTrue(VideoFrameMetadata::DECODER_OWNS_FRAME)
1868 ? CanSuspendState::NO 1884 ? CanSuspendState::NO
1869 : CanSuspendState::YES; 1885 : CanSuspendState::YES;
1870 } 1886 }
1871 } 1887 }
1872 #else 1888 #else
1873 can_suspend_state_ = CanSuspendState::YES; 1889 can_suspend_state_ = CanSuspendState::YES;
1874 #endif 1890 #endif
1875 1891
1876 if (can_suspend_state_ == CanSuspendState::NO) 1892 if (is_suspended && can_suspend_state_ != CanSuspendState::NO) {
1877 return; 1893 // If we were not resumed for long enough to satisfy the preroll attempt,
1878 1894 // reset the clock.
1879 if (is_suspended) { 1895 if (!preroll_attempt_pending_ && IsPrerollAttemptNeeded()) {
1896 preroll_attempt_pending_ = true;
1897 preroll_attempt_start_time_ = base::TimeTicks();
1898 }
1880 pipeline_controller_.Suspend(); 1899 pipeline_controller_.Suspend();
1881 } else { 1900 } else {
1901 // When resuming, start the preroll attempt clock.
1902 if (preroll_attempt_pending_) {
1903 preroll_attempt_pending_ = false;
1904 preroll_attempt_start_time_ = tick_clock_->NowTicks();
1905 }
1882 pipeline_controller_.Resume(); 1906 pipeline_controller_.Resume();
1883 } 1907 }
1884 } 1908 }
1885 1909
1886 WebMediaPlayerImpl::PlayState 1910 WebMediaPlayerImpl::PlayState
1887 WebMediaPlayerImpl::UpdatePlayState_ComputePlayState(bool is_remote, 1911 WebMediaPlayerImpl::UpdatePlayState_ComputePlayState(bool is_remote,
1888 bool is_streaming, 1912 bool is_streaming,
1889 bool is_suspended, 1913 bool is_suspended,
1890 bool is_backgrounded) { 1914 bool is_backgrounded) {
1891 PlayState result; 1915 PlayState result;
1892 1916
1917 bool must_suspend = delegate_ && delegate_->IsFrameClosed();
1918 bool is_stale = delegate_ && delegate_->IsStale(delegate_id_);
1919
1893 // This includes both data source (before pipeline startup) and pipeline 1920 // This includes both data source (before pipeline startup) and pipeline
1894 // errors. 1921 // errors.
1895 bool has_error = IsNetworkStateError(network_state_); 1922 bool has_error = IsNetworkStateError(network_state_);
1896 1923
1897 // After HaveMetadata, we know which tracks are present and the duration. 1924 // After HaveMetadata, we know which tracks are present and the duration.
1898 bool have_metadata = ready_state_ >= WebMediaPlayer::ReadyStateHaveMetadata; 1925 bool have_metadata = ready_state_ >= WebMediaPlayer::ReadyStateHaveMetadata;
1899 1926
1900 // After HaveFutureData, Blink will call play() if the state is not paused; 1927 // After HaveFutureData, Blink will call play() if the state is not paused;
1901 // prior to this point |paused_| is not accurate. 1928 // prior to this point |paused_| is not accurate.
1902 bool have_future_data = 1929 bool have_future_data =
1903 highest_ready_state_ >= WebMediaPlayer::ReadyStateHaveFutureData; 1930 highest_ready_state_ >= WebMediaPlayer::ReadyStateHaveFutureData;
1904 1931
1905 // Background suspend is not enabled for audio-only players unless paused, 1932 // Background suspend is not enabled for audio-only players unless paused,
1906 // though in the case of audio-only the session should be kept. 1933 // though in the case of audio-only the session should be kept.
1907 // Videos are not suspended if the user resumed the playback via the remote 1934 // Videos are not suspended if the user resumed the playback via the remote
1908 // controls earlier and it's still playing. 1935 // controls earlier and it's still playing.
1909 bool is_backgrounded_video = is_backgrounded && have_metadata && hasVideo(); 1936 bool is_backgrounded_video = is_backgrounded && have_metadata && hasVideo();
1910 bool can_play_backgrounded = is_backgrounded_video && !is_remote && 1937 bool can_play_backgrounded = is_backgrounded_video && !is_remote &&
1911 hasAudio() && IsResumeBackgroundVideosEnabled(); 1938 hasAudio() && IsResumeBackgroundVideosEnabled();
1912 bool is_background_playing = 1939 bool is_background_playing =
1913 delegate_ && delegate_->IsPlayingBackgroundVideo(); 1940 delegate_ && delegate_->IsBackgroundVideoPlaybackUnlocked();
1914 bool background_suspended = !is_streaming && is_backgrounded_video && 1941 bool background_suspended = !is_streaming && is_backgrounded_video &&
1915 !(can_play_backgrounded && is_background_playing); 1942 !(can_play_backgrounded && is_background_playing);
1916 bool background_pause_suspended = 1943 bool background_pause_suspended =
1917 !is_streaming && is_backgrounded && paused_ && have_future_data; 1944 !is_streaming && is_backgrounded && paused_ && have_future_data;
1918 1945
1919 // Idle suspension is allowed prior to have future data since there exist 1946 // Idle suspension is allowed prior to have future data since there exist
1920 // mechanisms to exit the idle state when the player is capable of reaching 1947 // mechanisms to exit the idle state when the player is capable of reaching
1921 // the have future data state; see didLoadingProgress(). 1948 // the have future data state; see didLoadingProgress().
1922 // 1949 //
1923 // TODO(sandersd): Make the delegate suspend idle players immediately when 1950 // TODO(sandersd): Make the delegate suspend idle players immediately when
1924 // hidden. 1951 // hidden.
1925 bool idle_suspended = 1952 bool idle_suspended =
1926 !is_streaming && is_idle_ && paused_ && !seeking_ && !overlay_enabled_; 1953 !is_streaming && is_stale && paused_ && !seeking_ && !overlay_enabled_;
1927 1954
1928 // If we're already suspended, see if we can wait for user interaction. Prior 1955 // If we're already suspended, see if we can wait for user interaction. Prior
1929 // to HaveFutureData, we require |is_idle_| to remain suspended. |is_idle_| 1956 // to HaveFutureData, we require |is_stale| to remain suspended. |is_stale|
1930 // will be cleared when we receive data which may take us to HaveFutureData. 1957 // will be cleared when we receive data which may take us to HaveFutureData.
1931 bool can_stay_suspended = 1958 bool can_stay_suspended =
1932 (is_idle_ || have_future_data) && is_suspended && paused_ && !seeking_; 1959 (is_stale || have_future_data) && is_suspended && paused_ && !seeking_;
1933 1960
1934 // Combined suspend state. 1961 // Combined suspend state.
1935 result.is_suspended = is_remote || must_suspend_ || idle_suspended || 1962 result.is_suspended = is_remote || must_suspend || idle_suspended ||
1936 background_suspended || background_pause_suspended || 1963 background_suspended || background_pause_suspended ||
1937 can_stay_suspended; 1964 can_stay_suspended;
1938 1965
1939 // We do not treat |playback_rate_| == 0 as paused. For the media session, 1966 // We do not treat |playback_rate_| == 0 as paused. For the media session,
1940 // being paused implies displaying a play button, which is incorrect in this 1967 // being paused implies displaying a play button, which is incorrect in this
1941 // case. For memory usage reporting, we just use the same definition (but we 1968 // case. For memory usage reporting, we just use the same definition (but we
1942 // don't have to). 1969 // don't have to).
1943 // 1970 //
1944 // Similarly, we don't consider |ended_| to be paused. Blink will immediately 1971 // Similarly, we don't consider |ended_| to be paused. Blink will immediately
1945 // call pause() or seek(), so |ended_| should not affect the computation. 1972 // call pause() or seek(), so |ended_| should not affect the computation.
1946 // Despite that, |ended_| does result in a separate paused state, to simplfy 1973 // Despite that, |ended_| does result in a separate paused state, to simplfy
1947 // the contract for SetDelegateState(). 1974 // the contract for SetDelegateState().
1948 // 1975 //
1949 // |has_session| is used to decide when to create a media session. Idle 1976 // |has_session| is used to decide when to create a media session. Idle
1950 // suspension does not destroy the media session, because we expect that the 1977 // suspension does not destroy the media session, because we expect that the
1951 // notification controls (and audio focus) remain. We also require: 1978 // notification controls (and audio focus) remain. We also require:
1952 // - |have_metadata|, since the tracks and duration are passed to DidPlay(). 1979 // - |have_metadata|, since the tracks and duration are passed to DidPlay().
1953 // - |have_future_data|, since we need to know whether we are paused to 1980 // - |have_future_data|, since we need to know whether we are paused to
1954 // correctly configure the session. 1981 // correctly configure the session.
1955 // 1982 //
1956 // TODO(sandersd): If Blink told us the paused state sooner, we could create 1983 // TODO(sandersd): If Blink told us the paused state sooner, we could create
1957 // the media session sooner. 1984 // the media session sooner.
1958 bool can_play = !has_error && !is_remote && have_future_data; 1985 bool can_play = !has_error && !is_remote && have_future_data;
1959 bool has_session_playing = 1986 bool has_session_playing = can_play && !must_suspend && !background_suspended;
1960 can_play && !must_suspend_ && !background_suspended;
1961 1987
1962 // |has_session_suspended| means the player is suspended from the media 1988 // |has_session_suspended| means the player is suspended from the media
1963 // element point of view but paused and can be resumed from the delegate point 1989 // element point of view but paused and can be resumed from the delegate point
1964 // of view. Therefore it behaves like |paused_| for the delegate. 1990 // of view. Therefore it behaves like |paused_| for the delegate.
1965 bool has_session_suspended = can_play && !must_suspend_ && 1991 bool has_session_suspended = can_play && !must_suspend &&
1966 background_suspended && can_play_backgrounded; 1992 background_suspended && can_play_backgrounded;
1967 1993
1968 bool has_session = has_session_playing || has_session_suspended; 1994 bool has_session = has_session_playing || has_session_suspended;
1969 1995
1970 if (!has_session) { 1996 if (!has_session) {
1971 result.delegate_state = DelegateState::GONE; 1997 result.delegate_state = DelegateState::GONE;
1998 result.is_idle = delegate_ && delegate_->IsIdle(delegate_id_);
1972 } else if (paused_ || has_session_suspended) { 1999 } else if (paused_ || has_session_suspended) {
2000 // TODO(sandersd): Is it possible to have a suspended session, be ended,
2001 // and not be paused? If so we should be in a PLAYING state.
1973 result.delegate_state = 2002 result.delegate_state =
1974 ended_ ? DelegateState::ENDED : DelegateState::PAUSED; 2003 ended_ ? DelegateState::GONE : DelegateState::PAUSED;
2004 result.is_idle = !seeking_;
1975 } else { 2005 } else {
1976 result.delegate_state = DelegateState::PLAYING; 2006 result.delegate_state = DelegateState::PLAYING;
2007 result.is_idle = false;
1977 } 2008 }
1978 2009
1979 // It's not critical if some cases where memory usage can change are missed, 2010 // It's not critical if some cases where memory usage can change are missed,
1980 // since media memory changes are usually gradual. 2011 // since media memory changes are usually gradual.
1981 result.is_memory_reporting_enabled = 2012 result.is_memory_reporting_enabled =
1982 can_play && !result.is_suspended && !paused_; 2013 can_play && !result.is_suspended && (!paused_ || seeking_);
1983 2014
1984 return result; 2015 return result;
1985 } 2016 }
1986 2017
1987 void WebMediaPlayerImpl::ReportMemoryUsage() { 2018 void WebMediaPlayerImpl::ReportMemoryUsage() {
1988 DCHECK(main_task_runner_->BelongsToCurrentThread()); 2019 DCHECK(main_task_runner_->BelongsToCurrentThread());
1989 2020
1990 // About base::Unretained() usage below: We destroy |demuxer_| on the main 2021 // About base::Unretained() usage below: We destroy |demuxer_| on the main
1991 // thread. Before that, however, ~WebMediaPlayerImpl() posts a task to the 2022 // thread. Before that, however, ~WebMediaPlayerImpl() posts a task to the
1992 // media thread and waits for it to finish. Hence, the GetMemoryUsage() task 2023 // media thread and waits for it to finish. Hence, the GetMemoryUsage() task
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
2058 this, &WebMediaPlayerImpl::OnPause); 2089 this, &WebMediaPlayerImpl::OnPause);
2059 } 2090 }
2060 2091
2061 void WebMediaPlayerImpl::CreateWatchTimeReporter() { 2092 void WebMediaPlayerImpl::CreateWatchTimeReporter() {
2062 // Create the watch time reporter and synchronize its initial state. 2093 // Create the watch time reporter and synchronize its initial state.
2063 watch_time_reporter_.reset(new WatchTimeReporter( 2094 watch_time_reporter_.reset(new WatchTimeReporter(
2064 hasAudio(), hasVideo(), !!chunk_demuxer_, is_encrypted_, media_log_, 2095 hasAudio(), hasVideo(), !!chunk_demuxer_, is_encrypted_, media_log_,
2065 pipeline_metadata_.natural_size, 2096 pipeline_metadata_.natural_size,
2066 base::Bind(&GetCurrentTimeInternal, this))); 2097 base::Bind(&GetCurrentTimeInternal, this)));
2067 watch_time_reporter_->OnVolumeChange(volume_); 2098 watch_time_reporter_->OnVolumeChange(volume_);
2068 if (IsHidden()) 2099 if (delegate_ && delegate_->IsFrameHidden())
2069 watch_time_reporter_->OnHidden(); 2100 watch_time_reporter_->OnHidden();
2070 else 2101 else
2071 watch_time_reporter_->OnShown(); 2102 watch_time_reporter_->OnShown();
2072 } 2103 }
2073 2104
2074 bool WebMediaPlayerImpl::IsHidden() const { 2105 bool WebMediaPlayerImpl::IsHidden() const {
2075 DCHECK(main_task_runner_->BelongsToCurrentThread()); 2106 DCHECK(main_task_runner_->BelongsToCurrentThread());
2076 2107
2077 return delegate_ && delegate_->IsHidden(); 2108 return delegate_ && delegate_->IsFrameHidden() && !delegate_->IsFrameClosed();
2078 } 2109 }
2079 2110
2080 bool WebMediaPlayerImpl::IsStreaming() const { 2111 bool WebMediaPlayerImpl::IsStreaming() const {
2081 return data_source_ && data_source_->IsStreaming(); 2112 return data_source_ && data_source_->IsStreaming();
2082 } 2113 }
2083 2114
2084 bool WebMediaPlayerImpl::DoesOverlaySupportMetadata() const { 2115 bool WebMediaPlayerImpl::DoesOverlaySupportMetadata() const {
2085 return pipeline_metadata_.video_rotation == VIDEO_ROTATION_0; 2116 return pipeline_metadata_.video_rotation == VIDEO_ROTATION_0;
2086 } 2117 }
2087 2118
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
2154 pipeline_statistics_for_test_ = base::make_optional(stats); 2185 pipeline_statistics_for_test_ = base::make_optional(stats);
2155 } 2186 }
2156 2187
2157 PipelineStatistics WebMediaPlayerImpl::GetPipelineStatistics() const { 2188 PipelineStatistics WebMediaPlayerImpl::GetPipelineStatistics() const {
2158 DCHECK(main_task_runner_->BelongsToCurrentThread()); 2189 DCHECK(main_task_runner_->BelongsToCurrentThread());
2159 2190
2160 return pipeline_statistics_for_test_.value_or(pipeline_.GetStatistics()); 2191 return pipeline_statistics_for_test_.value_or(pipeline_.GetStatistics());
2161 } 2192 }
2162 2193
2163 } // namespace media 2194 } // namespace media
OLDNEW
« no previous file with comments | « media/blink/webmediaplayer_impl.h ('k') | media/blink/webmediaplayer_impl_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698