 Chromium Code Reviews
 Chromium Code Reviews Issue 2796193002:
  fix canplaythrough  (Closed)
    
  
    Issue 2796193002:
  fix canplaythrough  (Closed) 
  | 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 197 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 208 client_(client), | 208 client_(client), | 
| 209 encrypted_client_(encrypted_client), | 209 encrypted_client_(encrypted_client), | 
| 210 delegate_(delegate), | 210 delegate_(delegate), | 
| 211 delegate_id_(0), | 211 delegate_id_(0), | 
| 212 defer_load_cb_(params.defer_load_cb()), | 212 defer_load_cb_(params.defer_load_cb()), | 
| 213 context_3d_cb_(params.context_3d_cb()), | 213 context_3d_cb_(params.context_3d_cb()), | 
| 214 adjust_allocated_memory_cb_(params.adjust_allocated_memory_cb()), | 214 adjust_allocated_memory_cb_(params.adjust_allocated_memory_cb()), | 
| 215 last_reported_memory_usage_(0), | 215 last_reported_memory_usage_(0), | 
| 216 supports_save_(true), | 216 supports_save_(true), | 
| 217 chunk_demuxer_(NULL), | 217 chunk_demuxer_(NULL), | 
| 218 buffered_data_source_host_( | |
| 219 base::Bind(&WebMediaPlayerImpl::OnProgress, AsWeakPtr())), | |
| 218 url_index_(url_index), | 220 url_index_(url_index), | 
| 219 // Threaded compositing isn't enabled universally yet. | 221 // Threaded compositing isn't enabled universally yet. | 
| 220 compositor_task_runner_(params.compositor_task_runner() | 222 compositor_task_runner_(params.compositor_task_runner() | 
| 221 ? params.compositor_task_runner() | 223 ? params.compositor_task_runner() | 
| 222 : base::ThreadTaskRunnerHandle::Get()), | 224 : base::ThreadTaskRunnerHandle::Get()), | 
| 223 compositor_(new VideoFrameCompositor(compositor_task_runner_)), | 225 compositor_(new VideoFrameCompositor(compositor_task_runner_)), | 
| 224 #if defined(OS_ANDROID) // WMPI_CAST | 226 #if defined(OS_ANDROID) // WMPI_CAST | 
| 225 cast_impl_(this, client_, params.context_3d_cb()), | 227 cast_impl_(this, client_, params.context_3d_cb()), | 
| 226 #endif | 228 #endif | 
| 227 volume_(1.0), | 229 volume_(1.0), | 
| (...skipping 610 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 838 } | 840 } | 
| 839 | 841 | 
| 840 bool WebMediaPlayerImpl::didLoadingProgress() { | 842 bool WebMediaPlayerImpl::didLoadingProgress() { | 
| 841 DCHECK(main_task_runner_->BelongsToCurrentThread()); | 843 DCHECK(main_task_runner_->BelongsToCurrentThread()); | 
| 842 | 844 | 
| 843 // 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. | 
| 844 const bool pipeline_progress = pipeline_controller_.DidLoadingProgress(); | 846 const bool pipeline_progress = pipeline_controller_.DidLoadingProgress(); | 
| 845 const bool data_progress = buffered_data_source_host_.DidLoadingProgress(); | 847 const bool data_progress = buffered_data_source_host_.DidLoadingProgress(); | 
| 846 const bool did_loading_progress = pipeline_progress || data_progress; | 848 const bool did_loading_progress = pipeline_progress || data_progress; | 
| 847 | 849 | 
| 848 if (did_loading_progress && | 850 if (did_loading_progress) { | 
| 849 highest_ready_state_ < ReadyState::ReadyStateHaveFutureData) { | 851 if (highest_ready_state_ < ReadyState::ReadyStateHaveFutureData) { | 
| 850 // Reset the preroll attempt clock. | 852 // Reset the preroll attempt clock. | 
| 851 preroll_attempt_pending_ = true; | 853 preroll_attempt_pending_ = true; | 
| 852 preroll_attempt_start_time_ = base::TimeTicks(); | 854 preroll_attempt_start_time_ = base::TimeTicks(); | 
| 853 | 855 | 
| 854 // Clear any 'stale' flag and give the pipeline a chance to resume. If we | 856 // Clear any 'stale' flag and give the pipeline a chance to resume. If we | 
| 855 // are already resumed, this will cause |preroll_attempt_start_time_| to be | 857 // are already resumed, this will cause |preroll_attempt_start_time_| to | 
| 856 // set. | 858 // be set. | 
| 857 // TODO(sandersd): Should this be on the same stack? It might be surprising | 859 // TODO(sandersd): Should this be on the same stack? It might be | 
| 858 // that didLoadingProgress() can synchronously change state. | 860 // surprising that didLoadingProgress() can synchronously change state. | 
| 859 delegate_->ClearStaleFlag(delegate_id_); | 861 delegate_->ClearStaleFlag(delegate_id_); | 
| 860 UpdatePlayState(); | 862 UpdatePlayState(); | 
| 863 } | |
| 864 if (ready_state_ == ReadyState::ReadyStateHaveFutureData && | |
| 865 CanPlayThrough()) { | |
| 866 SetReadyState(WebMediaPlayer::ReadyStateHaveEnoughData); | |
| 867 } | |
| 861 } | 868 } | 
| 862 | 869 | 
| 863 return did_loading_progress; | 870 return did_loading_progress; | 
| 864 } | 871 } | 
| 865 | 872 | 
| 866 void WebMediaPlayerImpl::paint(blink::WebCanvas* canvas, | 873 void WebMediaPlayerImpl::paint(blink::WebCanvas* canvas, | 
| 867 const blink::WebRect& rect, | 874 const blink::WebRect& rect, | 
| 868 cc::PaintFlags& flags) { | 875 cc::PaintFlags& flags) { | 
| 869 DCHECK(main_task_runner_->BelongsToCurrentThread()); | 876 DCHECK(main_task_runner_->BelongsToCurrentThread()); | 
| 870 TRACE_EVENT0("media", "WebMediaPlayerImpl:paint"); | 877 TRACE_EVENT0("media", "WebMediaPlayerImpl:paint"); | 
| (...skipping 396 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1267 client_->setWebLayer(video_weblayer_.get()); | 1274 client_->setWebLayer(video_weblayer_.get()); | 
| 1268 } | 1275 } | 
| 1269 | 1276 | 
| 1270 if (observer_) | 1277 if (observer_) | 
| 1271 observer_->OnMetadataChanged(pipeline_metadata_); | 1278 observer_->OnMetadataChanged(pipeline_metadata_); | 
| 1272 | 1279 | 
| 1273 CreateWatchTimeReporter(); | 1280 CreateWatchTimeReporter(); | 
| 1274 UpdatePlayState(); | 1281 UpdatePlayState(); | 
| 1275 } | 1282 } | 
| 1276 | 1283 | 
| 1284 void WebMediaPlayerImpl::OnProgress() { | |
| 1285 if (ready_state_ == ReadyState::ReadyStateHaveFutureData && | |
| 1286 CanPlayThrough()) { | |
| 1287 SetReadyState(WebMediaPlayer::ReadyStateHaveEnoughData); | |
| 
chcunningham
2017/04/06 16:55:41
Do we need this logic both here and in didLoadingP
 
hubbe
2017/04/06 21:25:38
I can remove it from didLoadingProgress()
 | |
| 1288 } | |
| 1289 } | |
| 1290 | |
| 1291 bool WebMediaPlayerImpl::CanPlayThrough() { | |
| 1292 return buffered_data_source_host_.CanPlayThrough( | |
| 
chcunningham
2017/04/06 16:55:41
What about MSE (no buffered_data_source_host_)?
 
hubbe
2017/04/06 21:25:38
There is always a buffered_data_source_host_, but
 | |
| 1293 base::TimeDelta::FromSecondsD(currentTime()), | |
| 1294 base::TimeDelta::FromSecondsD(duration()), | |
| 1295 playback_rate_ == 0.0 ? 1.0 : playback_rate_); | |
| 1296 } | |
| 1297 | |
| 1277 void WebMediaPlayerImpl::OnBufferingStateChange(BufferingState state) { | 1298 void WebMediaPlayerImpl::OnBufferingStateChange(BufferingState state) { | 
| 1278 DVLOG(1) << __func__ << "(" << state << ")"; | 1299 DVLOG(1) << __func__ << "(" << state << ")"; | 
| 1279 DCHECK(main_task_runner_->BelongsToCurrentThread()); | 1300 DCHECK(main_task_runner_->BelongsToCurrentThread()); | 
| 1280 | 1301 | 
| 1281 // Ignore buffering state changes until we've completed all outstanding | 1302 // Ignore buffering state changes until we've completed all outstanding | 
| 1282 // operations. | 1303 // operations. | 
| 1283 if (!pipeline_controller_.IsStable()) | 1304 if (!pipeline_controller_.IsStable()) | 
| 1284 return; | 1305 return; | 
| 1285 | 1306 | 
| 1286 media_log_->AddEvent(media_log_->CreateBufferingStateChangedEvent( | 1307 media_log_->AddEvent(media_log_->CreateBufferingStateChangedEvent( | 
| 1287 "pipeline_buffering_state", state)); | 1308 "pipeline_buffering_state", state)); | 
| 1288 | 1309 | 
| 1289 if (state == BUFFERING_HAVE_ENOUGH) { | 1310 if (state == BUFFERING_HAVE_ENOUGH) { | 
| 1290 if (highest_ready_state_ < WebMediaPlayer::ReadyStateHaveEnoughData) { | 1311 if (highest_ready_state_ < WebMediaPlayer::ReadyStateHaveEnoughData) { | 
| 1291 // Record a zero value for underflow histogram so that the histogram | 1312 // Record a zero value for underflow histogram so that the histogram | 
| 1292 // includes playbacks which never encounter an underflow event. | 1313 // includes playbacks which never encounter an underflow event. | 
| 1293 RecordUnderflowDuration(base::TimeDelta()); | 1314 RecordUnderflowDuration(base::TimeDelta()); | 
| 1294 } | 1315 } | 
| 1295 | 1316 | 
| 1296 // TODO(chcunningham): Monitor playback position vs buffered. Potentially | 1317 if (CanPlayThrough()) { | 
| 1297 // transition to HAVE_FUTURE_DATA here if not enough is buffered. | 1318 SetReadyState(WebMediaPlayer::ReadyStateHaveEnoughData); | 
| 1298 SetReadyState(WebMediaPlayer::ReadyStateHaveEnoughData); | 1319 } else { | 
| 1320 SetReadyState(WebMediaPlayer::ReadyStateHaveFutureData); | |
| 1321 } | |
| 1299 | 1322 | 
| 1300 // Let the DataSource know we have enough data. It may use this information | 1323 // Let the DataSource know we have enough data. It may use this information | 
| 1301 // to release unused network connections. | 1324 // to release unused network connections. | 
| 1302 if (data_source_) | 1325 if (data_source_) | 
| 1303 data_source_->OnBufferingHaveEnough(false); | 1326 data_source_->OnBufferingHaveEnough(false); | 
| 1304 | 1327 | 
| 1305 // Blink expects a timeChanged() in response to a seek(). | 1328 // Blink expects a timeChanged() in response to a seek(). | 
| 1306 if (should_notify_time_changed_) { | 1329 if (should_notify_time_changed_) { | 
| 1307 should_notify_time_changed_ = false; | 1330 should_notify_time_changed_ = false; | 
| 1308 client_->timeChanged(); | 1331 client_->timeChanged(); | 
| (...skipping 328 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1637 | 1660 | 
| 1638 StartPipeline(); | 1661 StartPipeline(); | 
| 1639 } | 1662 } | 
| 1640 | 1663 | 
| 1641 void WebMediaPlayerImpl::NotifyDownloading(bool is_downloading) { | 1664 void WebMediaPlayerImpl::NotifyDownloading(bool is_downloading) { | 
| 1642 DVLOG(1) << __func__; | 1665 DVLOG(1) << __func__; | 
| 1643 if (!is_downloading && network_state_ == WebMediaPlayer::NetworkStateLoading) | 1666 if (!is_downloading && network_state_ == WebMediaPlayer::NetworkStateLoading) | 
| 1644 SetNetworkState(WebMediaPlayer::NetworkStateIdle); | 1667 SetNetworkState(WebMediaPlayer::NetworkStateIdle); | 
| 1645 else if (is_downloading && network_state_ == WebMediaPlayer::NetworkStateIdle) | 1668 else if (is_downloading && network_state_ == WebMediaPlayer::NetworkStateIdle) | 
| 1646 SetNetworkState(WebMediaPlayer::NetworkStateLoading); | 1669 SetNetworkState(WebMediaPlayer::NetworkStateLoading); | 
| 1670 if (ready_state_ == ReadyState::ReadyStateHaveFutureData && !is_downloading) | |
| 1671 SetReadyState(WebMediaPlayer::ReadyStateHaveEnoughData); | |
| 
mlamouri (slow - plz ping)
2017/04/06 11:32:56
If I understand correctly, that means that we will
 
hubbe
2017/04/06 21:25:38
That's what the standard says to do when the buffe
 
mlamouri (slow - plz ping)
2017/04/07 11:23:44
FWIW, what I understood by reading the code is tha
 | |
| 1647 media_log_->AddEvent( | 1672 media_log_->AddEvent( | 
| 1648 media_log_->CreateBooleanEvent(MediaLogEvent::NETWORK_ACTIVITY_SET, | 1673 media_log_->CreateBooleanEvent(MediaLogEvent::NETWORK_ACTIVITY_SET, | 
| 1649 "is_downloading_data", is_downloading)); | 1674 "is_downloading_data", is_downloading)); | 
| 1650 } | 1675 } | 
| 1651 | 1676 | 
| 1652 void WebMediaPlayerImpl::OnSurfaceCreated(int surface_id) { | 1677 void WebMediaPlayerImpl::OnSurfaceCreated(int surface_id) { | 
| 1653 overlay_surface_id_ = surface_id; | 1678 overlay_surface_id_ = surface_id; | 
| 1654 if (!set_surface_cb_.is_null()) { | 1679 if (!set_surface_cb_.is_null()) { | 
| 1655 // If restart is required, the callback is one-shot only. | 1680 // If restart is required, the callback is one-shot only. | 
| 1656 if (decoder_requires_restart_for_overlay_) | 1681 if (decoder_requires_restart_for_overlay_) | 
| (...skipping 668 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2325 | 2350 | 
| 2326 void WebMediaPlayerImpl::RecordUnderflowDuration(base::TimeDelta duration) { | 2351 void WebMediaPlayerImpl::RecordUnderflowDuration(base::TimeDelta duration) { | 
| 2327 DCHECK(data_source_ || chunk_demuxer_); | 2352 DCHECK(data_source_ || chunk_demuxer_); | 
| 2328 if (data_source_) | 2353 if (data_source_) | 
| 2329 UMA_HISTOGRAM_TIMES("Media.UnderflowDuration", duration); | 2354 UMA_HISTOGRAM_TIMES("Media.UnderflowDuration", duration); | 
| 2330 else | 2355 else | 
| 2331 UMA_HISTOGRAM_TIMES("Media.UnderflowDuration.MSE", duration); | 2356 UMA_HISTOGRAM_TIMES("Media.UnderflowDuration.MSE", duration); | 
| 2332 } | 2357 } | 
| 2333 | 2358 | 
| 2334 } // namespace media | 2359 } // namespace media | 
| OLD | NEW |