OLD | NEW |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 |
OLD | NEW |