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

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

Issue 1641423002: Re-land extract state management from WebMediaPlayerImpl. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: WMPI fixes. Created 4 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2013 The Chromium Authors. All rights reserved. 1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "media/blink/webmediaplayer_impl.h" 5 #include "media/blink/webmediaplayer_impl.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 #include <cmath> 8 #include <cmath>
9 #include <limits> 9 #include <limits>
10 #include <string> 10 #include <string>
11 #include <utility> 11 #include <utility>
12 12
13 #include "base/bind.h" 13 #include "base/bind.h"
14 #include "base/bind_helpers.h"
14 #include "base/callback.h" 15 #include "base/callback.h"
15 #include "base/callback_helpers.h" 16 #include "base/callback_helpers.h"
16 #include "base/command_line.h" 17 #include "base/command_line.h"
17 #include "base/debug/alias.h" 18 #include "base/debug/alias.h"
18 #include "base/debug/crash_logging.h" 19 #include "base/debug/crash_logging.h"
19 #include "base/metrics/histogram.h" 20 #include "base/metrics/histogram.h"
20 #include "base/single_thread_task_runner.h" 21 #include "base/single_thread_task_runner.h"
21 #include "base/synchronization/waitable_event.h" 22 #include "base/synchronization/waitable_event.h"
22 #include "base/task_runner_util.h" 23 #include "base/task_runner_util.h"
23 #include "base/thread_task_runner_handle.h" 24 #include "base/thread_task_runner_handle.h"
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after
136 network_state_(WebMediaPlayer::NetworkStateEmpty), 137 network_state_(WebMediaPlayer::NetworkStateEmpty),
137 ready_state_(WebMediaPlayer::ReadyStateHaveNothing), 138 ready_state_(WebMediaPlayer::ReadyStateHaveNothing),
138 preload_(BufferedDataSource::AUTO), 139 preload_(BufferedDataSource::AUTO),
139 buffering_strategy_( 140 buffering_strategy_(
140 BufferedDataSourceInterface::BUFFERING_STRATEGY_NORMAL), 141 BufferedDataSourceInterface::BUFFERING_STRATEGY_NORMAL),
141 main_task_runner_(base::ThreadTaskRunnerHandle::Get()), 142 main_task_runner_(base::ThreadTaskRunnerHandle::Get()),
142 media_task_runner_(params.media_task_runner()), 143 media_task_runner_(params.media_task_runner()),
143 worker_task_runner_(params.worker_task_runner()), 144 worker_task_runner_(params.worker_task_runner()),
144 media_log_(params.media_log()), 145 media_log_(params.media_log()),
145 pipeline_(media_task_runner_, media_log_.get()), 146 pipeline_(media_task_runner_, media_log_.get()),
147 pipeline_state_(&pipeline_,
148 base::Bind(&WebMediaPlayerImpl::CreateRenderer,
149 base::Unretained(this)),
150 base::Bind(&WebMediaPlayerImpl::OnPipelineSeeked,
151 base::Unretained(this)),
152 base::Bind(&WebMediaPlayerImpl::OnPipelineSuspended,
153 base::Unretained(this)),
154 base::Bind(&WebMediaPlayerImpl::OnPipelineError,
155 base::Unretained(this))),
146 load_type_(LoadTypeURL), 156 load_type_(LoadTypeURL),
147 opaque_(false), 157 opaque_(false),
148 playback_rate_(0.0), 158 playback_rate_(0.0),
149 paused_(true), 159 paused_(true),
150 seeking_(false), 160 seeking_(false),
151 pending_suspend_(false),
152 pending_time_change_(false),
153 pending_resume_(false),
154 suspending_(false),
155 suspended_(false),
156 resuming_(false),
157 ended_(false), 161 ended_(false),
158 pending_seek_(false),
159 should_notify_time_changed_(false),
160 client_(client), 162 client_(client),
161 encrypted_client_(encrypted_client), 163 encrypted_client_(encrypted_client),
162 delegate_(delegate), 164 delegate_(delegate),
163 defer_load_cb_(params.defer_load_cb()), 165 defer_load_cb_(params.defer_load_cb()),
164 context_3d_cb_(params.context_3d_cb()), 166 context_3d_cb_(params.context_3d_cb()),
165 adjust_allocated_memory_cb_(params.adjust_allocated_memory_cb()), 167 adjust_allocated_memory_cb_(params.adjust_allocated_memory_cb()),
166 last_reported_memory_usage_(0), 168 last_reported_memory_usage_(0),
167 supports_save_(true), 169 supports_save_(true),
168 chunk_demuxer_(NULL), 170 chunk_demuxer_(NULL),
169 url_index_(url_index), 171 url_index_(url_index),
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
220 if (delegate_) { 222 if (delegate_) {
221 delegate_->RemoveObserver(this); 223 delegate_->RemoveObserver(this);
222 delegate_->PlayerGone(this); 224 delegate_->PlayerGone(this);
223 } 225 }
224 226
225 // Abort any pending IO so stopping the pipeline doesn't get blocked. 227 // Abort any pending IO so stopping the pipeline doesn't get blocked.
226 if (data_source_) 228 if (data_source_)
227 data_source_->Abort(); 229 data_source_->Abort();
228 if (chunk_demuxer_) { 230 if (chunk_demuxer_) {
229 chunk_demuxer_->Shutdown(); 231 chunk_demuxer_->Shutdown();
230 chunk_demuxer_ = NULL; 232 chunk_demuxer_ = nullptr;
231 } 233 }
232 234
233 renderer_factory_.reset(); 235 renderer_factory_.reset();
234 236
235 // Make sure to kill the pipeline so there's no more media threads running. 237 // Make sure to kill the pipeline so there's no more media threads running.
236 // Note: stopping the pipeline might block for a long time. 238 // Note: stopping the pipeline might block for a long time.
237 base::WaitableEvent waiter(false, false); 239 base::WaitableEvent waiter(false, false);
238 pipeline_.Stop( 240 pipeline_.Stop(
239 base::Bind(&base::WaitableEvent::Signal, base::Unretained(&waiter))); 241 base::Bind(&base::WaitableEvent::Signal, base::Unretained(&waiter)));
240 waiter.Wait(); 242 waiter.Wait();
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
318 DCHECK(main_task_runner_->BelongsToCurrentThread()); 320 DCHECK(main_task_runner_->BelongsToCurrentThread());
319 321
320 #if defined(OS_ANDROID) // WMPI_CAST 322 #if defined(OS_ANDROID) // WMPI_CAST
321 if (isRemote()) { 323 if (isRemote()) {
322 cast_impl_.play(); 324 cast_impl_.play();
323 return; 325 return;
324 } 326 }
325 #endif 327 #endif
326 328
327 paused_ = false; 329 paused_ = false;
330 pipeline_.SetPlaybackRate(playback_rate_);
328 331
329 pipeline_.SetPlaybackRate(playback_rate_);
330 if (data_source_) 332 if (data_source_)
331 data_source_->MediaIsPlaying(); 333 data_source_->MediaIsPlaying();
332 334
333 media_log_->AddEvent(media_log_->CreateEvent(MediaLogEvent::PLAY)); 335 media_log_->AddEvent(media_log_->CreateEvent(MediaLogEvent::PLAY));
334 336
335 if (delegate_ && playback_rate_ > 0) 337 if (delegate_ && playback_rate_ > 0)
336 NotifyPlaybackStarted(); 338 NotifyPlaybackStarted();
337 } 339 }
338 340
339 void WebMediaPlayerImpl::pause() { 341 void WebMediaPlayerImpl::pause() {
340 DVLOG(1) << __FUNCTION__; 342 DVLOG(1) << __FUNCTION__;
341 DCHECK(main_task_runner_->BelongsToCurrentThread()); 343 DCHECK(main_task_runner_->BelongsToCurrentThread());
342 344
343 const bool was_already_paused = paused_ || playback_rate_ == 0; 345 const bool was_already_paused = paused_ || playback_rate_ == 0;
344 paused_ = true; 346 paused_ = true;
345 347
346 #if defined(OS_ANDROID) // WMPI_CAST 348 #if defined(OS_ANDROID) // WMPI_CAST
347 if (isRemote()) { 349 if (isRemote()) {
348 cast_impl_.pause(); 350 cast_impl_.pause();
349 return; 351 return;
350 } 352 }
351 #endif 353 #endif
352 354
353 pipeline_.SetPlaybackRate(0.0); 355 pipeline_.SetPlaybackRate(0.0);
354 UpdatePausedTime(); 356
357 // pause() may be called after playback has ended and the HTMLMediaElement
358 // requires that currentTime() == duration() after ending. We want to ensure
359 // |paused_time_| matches currentTime() in this case or a future seek() may
360 // incorrectly discard what it thinks is a seek to the existing time.
361 paused_time_ =
362 ended_ ? pipeline_.GetMediaDuration() : pipeline_.GetMediaTime();
355 363
356 media_log_->AddEvent(media_log_->CreateEvent(MediaLogEvent::PAUSE)); 364 media_log_->AddEvent(media_log_->CreateEvent(MediaLogEvent::PAUSE));
357 365
358 if (!was_already_paused && delegate_) 366 if (!was_already_paused && delegate_)
359 NotifyPlaybackPaused(); 367 NotifyPlaybackPaused();
360 } 368 }
361 369
362 bool WebMediaPlayerImpl::supportsSave() const { 370 bool WebMediaPlayerImpl::supportsSave() const {
363 DCHECK(main_task_runner_->BelongsToCurrentThread()); 371 DCHECK(main_task_runner_->BelongsToCurrentThread());
364 return supports_save_; 372 return supports_save_;
365 } 373 }
366 374
367 void WebMediaPlayerImpl::seek(double seconds) { 375 void WebMediaPlayerImpl::seek(double seconds) {
368 DVLOG(1) << __FUNCTION__ << "(" << seconds << "s)"; 376 DVLOG(1) << __FUNCTION__ << "(" << seconds << "s)";
369 DCHECK(main_task_runner_->BelongsToCurrentThread()); 377 DCHECK(main_task_runner_->BelongsToCurrentThread());
378 DoSeek(base::TimeDelta::FromSecondsD(seconds), true);
379 }
380
381 void WebMediaPlayerImpl::DoSeek(base::TimeDelta time, bool time_updated) {
382 DCHECK(main_task_runner_->BelongsToCurrentThread());
370 383
371 ended_ = false; 384 ended_ = false;
372 385
373 base::TimeDelta new_seek_time = base::TimeDelta::FromSecondsD(seconds);
374
375 #if defined(OS_ANDROID) // WMPI_CAST 386 #if defined(OS_ANDROID) // WMPI_CAST
376 if (isRemote()) { 387 if (isRemote()) {
377 cast_impl_.seek(new_seek_time); 388 cast_impl_.seek(time);
378 return; 389 return;
379 } 390 }
380 #endif 391 #endif
381 392
382 ReadyState old_state = ready_state_; 393 ReadyState old_state = ready_state_;
383 if (ready_state_ > WebMediaPlayer::ReadyStateHaveMetadata) 394 if (ready_state_ > WebMediaPlayer::ReadyStateHaveMetadata)
384 SetReadyState(WebMediaPlayer::ReadyStateHaveMetadata); 395 SetReadyState(WebMediaPlayer::ReadyStateHaveMetadata);
385 396
386 if (seeking_ || suspended_) { 397 // When paused, we know exactly what the current time is and can elide seeks
387 // Once resuming, it's too late to change the resume time and so the 398 // to it. However, there are two cases that are not elided:
388 // implementation is a little different. 399 // 1) When the pipeline state is not stable.
389 bool is_suspended = suspended_ && !resuming_; 400 // In this case we just let |pipeline_state_| decide what to do, as it
390 401 // has complete information.
391 // If we are currently seeking or resuming to |new_seek_time|, skip the 402 // 2) For MSE.
392 // seek (except for MSE, which always seeks). 403 // Because the buffers may have changed between seeks, MSE seeks are
393 if (!is_suspended && new_seek_time == seek_time_) { 404 // never elided.
394 if (chunk_demuxer_) { 405 if (paused_ && pipeline_state_.IsPlaying() && paused_time_ == time &&
395 // Don't suppress any redundant in-progress MSE seek. There could have 406 !chunk_demuxer_) {
396 // been changes to the underlying buffers after seeking the demuxer and 407 // If the ready state was high enough before, we can indicate that the seek
397 // before receiving OnPipelineSeeked() for the currently in-progress 408 // completed just by restoring it. Otherwise we will just wait for the real
398 // seek. 409 // ready state change to eventually happen.
399 MEDIA_LOG(DEBUG, media_log_) 410 if (old_state == ReadyStateHaveEnoughData) {
400 << "Detected MediaSource seek to same time as in-progress seek to "
401 << seek_time_ << ".";
402 } else {
403 // Suppress all redundant seeks if unrestricted by media source demuxer
404 // API.
405 pending_seek_ = false;
406 pending_seek_time_ = base::TimeDelta();
407 return;
408 }
409 }
410
411 // If |chunk_demuxer_| is already seeking, cancel that seek and schedule the
412 // new one.
413 if (!is_suspended && chunk_demuxer_)
414 chunk_demuxer_->CancelPendingSeek(new_seek_time);
415
416 // Schedule a seek once the current suspend or seek finishes.
417 pending_seek_ = true;
418 pending_seek_time_ = new_seek_time;
419
420 // In the case of seeking while suspended, the seek is considered to have
421 // started immediately (but won't complete until the pipeline is resumed).
422 if (is_suspended) {
423 seeking_ = true;
424 seek_time_ = new_seek_time;
425 }
426
427 return;
428 }
429
430 media_log_->AddEvent(media_log_->CreateSeekEvent(seconds));
431
432 // Update our paused time.
433 // For non-MSE playbacks, in paused state ignore the seek operations to
434 // current time if the loading is completed and generate
435 // OnPipelineBufferingStateChanged event to eventually fire seeking and seeked
436 // events. We don't short-circuit MSE seeks in this logic because the
437 // underlying buffers around the seek time might have changed (or even been
438 // removed) since previous seek/preroll/pause action, and the pipeline might
439 // need to flush so the new buffers are decoded and rendered instead of the
440 // old ones.
441 if (paused_) {
442 if (paused_time_ != new_seek_time || chunk_demuxer_) {
443 paused_time_ = new_seek_time;
444 } else if (old_state == ReadyStateHaveEnoughData) {
445 main_task_runner_->PostTask( 411 main_task_runner_->PostTask(
446 FROM_HERE, 412 FROM_HERE,
447 base::Bind(&WebMediaPlayerImpl::OnPipelineBufferingStateChanged, 413 base::Bind(&WebMediaPlayerImpl::OnPipelineBufferingStateChanged,
448 AsWeakPtr(), BUFFERING_HAVE_ENOUGH)); 414 AsWeakPtr(), BUFFERING_HAVE_ENOUGH));
449 return;
450 } 415 }
416 return;
451 } 417 }
452 418
453 seeking_ = true; 419 seeking_ = true;
454 seek_time_ = new_seek_time; 420 seek_time_ = time;
455 421 if (paused_)
456 if (chunk_demuxer_) 422 paused_time_ = time;
457 chunk_demuxer_->StartWaitingForSeek(seek_time_); 423 pipeline_state_.Seek(time, time_updated);
458
459 pipeline_.Seek(seek_time_, BIND_TO_RENDER_LOOP1(
460 &WebMediaPlayerImpl::OnPipelineSeeked, true));
461 } 424 }
462 425
463 void WebMediaPlayerImpl::setRate(double rate) { 426 void WebMediaPlayerImpl::setRate(double rate) {
464 DVLOG(1) << __FUNCTION__ << "(" << rate << ")"; 427 DVLOG(1) << __FUNCTION__ << "(" << rate << ")";
465 DCHECK(main_task_runner_->BelongsToCurrentThread()); 428 DCHECK(main_task_runner_->BelongsToCurrentThread());
466 429
467 // TODO(kylep): Remove when support for negatives is added. Also, modify the 430 // TODO(kylep): Remove when support for negatives is added. Also, modify the
468 // following checks so rewind uses reasonable values also. 431 // following checks so rewind uses reasonable values also.
469 if (rate < 0.0) 432 if (rate < 0.0)
470 return; 433 return;
(...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after
608 571
609 double WebMediaPlayerImpl::currentTime() const { 572 double WebMediaPlayerImpl::currentTime() const {
610 DCHECK(main_task_runner_->BelongsToCurrentThread()); 573 DCHECK(main_task_runner_->BelongsToCurrentThread());
611 DCHECK_NE(ready_state_, WebMediaPlayer::ReadyStateHaveNothing); 574 DCHECK_NE(ready_state_, WebMediaPlayer::ReadyStateHaveNothing);
612 575
613 // TODO(scherkus): Replace with an explicit ended signal to HTMLMediaElement, 576 // TODO(scherkus): Replace with an explicit ended signal to HTMLMediaElement,
614 // see http://crbug.com/409280 577 // see http://crbug.com/409280
615 if (ended_) 578 if (ended_)
616 return duration(); 579 return duration();
617 580
618 // We know the current seek time better than pipeline: pipeline may processing 581 if (seeking())
619 // an earlier seek before a pending seek has been started, or it might not yet 582 return seek_time_.InSecondsF();
620 // have the current seek time returnable via GetMediaTime().
621 if (seeking()) {
622 return pending_seek_ ? pending_seek_time_.InSecondsF()
623 : seek_time_.InSecondsF();
624 }
625 583
626 #if defined(OS_ANDROID) // WMPI_CAST 584 #if defined(OS_ANDROID) // WMPI_CAST
627 if (isRemote()) { 585 if (isRemote())
628 return cast_impl_.currentTime(); 586 return cast_impl_.currentTime();
629 }
630 #endif 587 #endif
631 588
632 if (paused_) { 589 if (paused_)
633 return paused_time_.InSecondsF(); 590 return paused_time_.InSecondsF();
634 }
635 591
636 return pipeline_.GetMediaTime().InSecondsF(); 592 return pipeline_.GetMediaTime().InSecondsF();
637 } 593 }
638 594
639 WebMediaPlayer::NetworkState WebMediaPlayerImpl::networkState() const { 595 WebMediaPlayer::NetworkState WebMediaPlayerImpl::networkState() const {
640 DCHECK(main_task_runner_->BelongsToCurrentThread()); 596 DCHECK(main_task_runner_->BelongsToCurrentThread());
641 return network_state_; 597 return network_state_;
642 } 598 }
643 599
644 WebMediaPlayer::ReadyState WebMediaPlayerImpl::readyState() const { 600 WebMediaPlayer::ReadyState WebMediaPlayerImpl::readyState() const {
(...skipping 253 matching lines...) Expand 10 before | Expand all | Expand 10 after
898 is_cdm_attached_ = true; 854 is_cdm_attached_ = true;
899 return; 855 return;
900 } 856 }
901 857
902 set_cdm_result_->completeWithError( 858 set_cdm_result_->completeWithError(
903 blink::WebContentDecryptionModuleExceptionNotSupportedError, 0, 859 blink::WebContentDecryptionModuleExceptionNotSupportedError, 0,
904 "Unable to set MediaKeys object"); 860 "Unable to set MediaKeys object");
905 set_cdm_result_.reset(); 861 set_cdm_result_.reset();
906 } 862 }
907 863
908 void WebMediaPlayerImpl::OnPipelineSeeked(bool time_changed, 864 void WebMediaPlayerImpl::OnPipelineSeeked(bool time_updated) {
909 PipelineStatus status) {
910 DVLOG(1) << __FUNCTION__ << "(" << time_changed << ", " << status << ")";
911 DCHECK(main_task_runner_->BelongsToCurrentThread());
912
913 if (status != PIPELINE_OK) {
914 OnPipelineError(status);
915 return;
916 }
917
918 // Whether or not the seek was caused by a resume, we're not suspended now.
919 resuming_ = false;
920 suspended_ = false;
921
922 // If there is a pending suspend, the seek does not complete until after the
923 // next resume.
924 if (pending_suspend_) {
925 pending_suspend_ = false;
926 pending_time_change_ = time_changed;
927 Suspend();
928 return;
929 }
930
931 // Clear seek state. Note that if the seek was caused by a resume, then
932 // |seek_time_| is always set but |seeking_| is only set if there was a
933 // pending seek at the time.
934 seeking_ = false; 865 seeking_ = false;
935 seek_time_ = base::TimeDelta(); 866 seek_time_ = base::TimeDelta();
936
937 if (pending_seek_) {
938 double pending_seek_seconds = pending_seek_time_.InSecondsF();
939 pending_seek_ = false;
940 pending_seek_time_ = base::TimeDelta();
941 seek(pending_seek_seconds);
942 return;
943 }
944
945 // Update our paused time.
946 if (paused_) 867 if (paused_)
947 UpdatePausedTime(); 868 paused_time_ = pipeline_.GetMediaTime();
948 869 if (time_updated)
949 should_notify_time_changed_ = time_changed; 870 should_notify_time_changed_ = true;
950 } 871 }
951 872
952 void WebMediaPlayerImpl::OnPipelineSuspended(PipelineStatus status) { 873 void WebMediaPlayerImpl::OnPipelineSuspended() {
953 DVLOG(1) << __FUNCTION__ << "(" << status << ")";
954 DCHECK(main_task_runner_->BelongsToCurrentThread());
955
956 if (status != PIPELINE_OK) {
957 OnPipelineError(status);
958 return;
959 }
960
961 suspending_ = false;
962
963 #if defined(OS_ANDROID) 874 #if defined(OS_ANDROID)
964 if (isRemote()) { 875 if (isRemote()) {
965 scoped_refptr<VideoFrame> frame = cast_impl_.GetCastingBanner(); 876 scoped_refptr<VideoFrame> frame = cast_impl_.GetCastingBanner();
966 if (frame) { 877 if (frame) {
967 compositor_->PaintFrameUsingOldRenderingPath(frame); 878 compositor_->PaintFrameUsingOldRenderingPath(frame);
968 } 879 }
969 } 880 }
970 #endif 881 #endif
971
972 if (pending_resume_) {
973 pending_resume_ = false;
974 Resume();
975 return;
976 }
977 } 882 }
978 883
979 void WebMediaPlayerImpl::OnPipelineEnded() { 884 void WebMediaPlayerImpl::OnPipelineEnded() {
980 DVLOG(1) << __FUNCTION__; 885 DVLOG(1) << __FUNCTION__;
981 DCHECK(main_task_runner_->BelongsToCurrentThread()); 886 DCHECK(main_task_runner_->BelongsToCurrentThread());
982 887
983 // Ignore state changes until we've completed all outstanding seeks. 888 // Ignore state changes until we've completed all outstanding operations.
984 if (seeking_ || pending_seek_) 889 if (!pipeline_state_.IsPlaying())
985 return; 890 return;
986 891
987 ended_ = true; 892 ended_ = true;
988 client_->timeChanged(); 893 client_->timeChanged();
989 } 894 }
990 895
991 void WebMediaPlayerImpl::OnPipelineError(PipelineStatus error) { 896 void WebMediaPlayerImpl::OnPipelineError(PipelineStatus error) {
992 DVLOG(1) << __FUNCTION__; 897 DVLOG(1) << __FUNCTION__;
993 DCHECK(main_task_runner_->BelongsToCurrentThread()); 898 DCHECK(main_task_runner_->BelongsToCurrentThread());
994 DCHECK_NE(error, PIPELINE_OK); 899 DCHECK_NE(error, PIPELINE_OK);
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
1034 // playback. 939 // playback.
1035 if (delegate_ && delegate_->IsHidden()) 940 if (delegate_ && delegate_->IsHidden())
1036 OnHidden(); 941 OnHidden();
1037 } 942 }
1038 } 943 }
1039 944
1040 void WebMediaPlayerImpl::OnPipelineBufferingStateChanged( 945 void WebMediaPlayerImpl::OnPipelineBufferingStateChanged(
1041 BufferingState buffering_state) { 946 BufferingState buffering_state) {
1042 DVLOG(1) << __FUNCTION__ << "(" << buffering_state << ")"; 947 DVLOG(1) << __FUNCTION__ << "(" << buffering_state << ")";
1043 948
1044 // Ignore buffering state changes until we've completed all outstanding seeks. 949 // Ignore buffering state changes until we've completed all outstanding
1045 if (seeking_ || pending_seek_) 950 // operations.
951 if (!pipeline_state_.IsPlaying())
1046 return; 952 return;
1047 953
1048 // TODO(scherkus): Handle other buffering states when Pipeline starts using 954 // TODO(scherkus): Handle other buffering states when Pipeline starts using
1049 // them and translate them ready state changes http://crbug.com/144683 955 // them and translate them ready state changes http://crbug.com/144683
1050 DCHECK_EQ(buffering_state, BUFFERING_HAVE_ENOUGH); 956 DCHECK_EQ(buffering_state, BUFFERING_HAVE_ENOUGH);
1051 SetReadyState(WebMediaPlayer::ReadyStateHaveEnoughData); 957 SetReadyState(WebMediaPlayer::ReadyStateHaveEnoughData);
1052 958
1053 // Let the DataSource know we have enough data. It may use this information to 959 // Let the DataSource know we have enough data. It may use this information to
1054 // release unused network connections. 960 // release unused network connections.
1055 if (data_source_) 961 if (data_source_)
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
1108 switches::kDisableMediaSuspend)) { 1014 switches::kDisableMediaSuspend)) {
1109 return; 1015 return;
1110 } 1016 }
1111 1017
1112 #if defined(OS_ANDROID) 1018 #if defined(OS_ANDROID)
1113 // If we're remote, the pipeline should already be suspended. 1019 // If we're remote, the pipeline should already be suspended.
1114 if (isRemote()) 1020 if (isRemote())
1115 return; 1021 return;
1116 #endif 1022 #endif
1117 1023
1118 ScheduleSuspend(); 1024 if (pipeline_.IsRunning() && hasVideo())
1119 } 1025 pipeline_state_.Suspend();
1120
1121 void WebMediaPlayerImpl::ScheduleSuspend() {
1122 if (!pipeline_.IsRunning() || !hasVideo())
1123 return;
1124
1125 if (resuming_ || seeking_) {
1126 pending_suspend_ = true;
1127 return;
1128 }
1129
1130 if (pending_resume_) {
1131 pending_resume_ = false;
1132 return;
1133 }
1134
1135 Suspend();
1136 }
1137
1138 void WebMediaPlayerImpl::Suspend() {
1139 DCHECK(main_task_runner_->BelongsToCurrentThread());
1140 CHECK(!suspended_);
1141 suspended_ = true;
1142 suspending_ = true;
1143 pipeline_.Suspend(
1144 BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnPipelineSuspended));
1145 } 1026 }
1146 1027
1147 void WebMediaPlayerImpl::OnShown() { 1028 void WebMediaPlayerImpl::OnShown() {
1148 DCHECK(main_task_runner_->BelongsToCurrentThread()); 1029 DCHECK(main_task_runner_->BelongsToCurrentThread());
1149 1030
1150 #if !defined(OS_ANDROID) 1031 #if !defined(OS_ANDROID)
1151 // Suspend/Resume is enabled by default on Android. 1032 // Suspend/Resume is enabled by default on Android.
1152 if (!base::CommandLine::ForCurrentProcess()->HasSwitch( 1033 if (!base::CommandLine::ForCurrentProcess()->HasSwitch(
1153 switches::kEnableMediaSuspend)) { 1034 switches::kEnableMediaSuspend)) {
1154 return; 1035 return;
1155 } 1036 }
1156 #endif // !defined(OS_ANDROID) 1037 #endif // !defined(OS_ANDROID)
1157 1038
1158 if (base::CommandLine::ForCurrentProcess()->HasSwitch( 1039 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
1159 switches::kDisableMediaSuspend)) { 1040 switches::kDisableMediaSuspend)) {
1160 return; 1041 return;
1161 } 1042 }
1162 1043
1163 #if defined(OS_ANDROID) 1044 #if defined(OS_ANDROID)
1164 // If we're remote, the pipeline should stay suspended. 1045 // If we're remote, the pipeline should stay suspended.
1165 if (isRemote()) 1046 if (isRemote())
1166 return; 1047 return;
1167 #endif 1048 #endif
1168 1049
1169 ScheduleResume(); 1050 if (pipeline_.IsRunning())
1170 } 1051 pipeline_state_.Resume();
1171
1172 void WebMediaPlayerImpl::ScheduleResume() {
1173 if (!pipeline_.IsRunning())
1174 return;
1175
1176 if (suspending_) {
1177 pending_resume_ = true;
1178 return;
1179 }
1180
1181 if (pending_suspend_) {
1182 pending_suspend_ = false;
1183 return;
1184 }
1185
1186 // Might already be resuming iff we came back from remote playback recently.
1187 if (suspended_ && !resuming_)
1188 Resume();
1189 }
1190
1191 void WebMediaPlayerImpl::Resume() {
1192 DCHECK(main_task_runner_->BelongsToCurrentThread());
1193 CHECK(suspended_);
1194 CHECK(!resuming_);
1195
1196 // If there was a time change pending when we suspended (which can happen when
1197 // we suspend immediately after a seek), surface it after resuming.
1198 bool time_changed = pending_time_change_;
1199 pending_time_change_ = false;
1200
1201 if (seeking_ || pending_seek_) {
1202 if (pending_seek_) {
1203 seek_time_ = pending_seek_time_;
1204 pending_seek_ = false;
1205 pending_seek_time_ = base::TimeDelta();
1206 }
1207 time_changed = true;
1208 } else {
1209 // It is safe to call GetCurrentFrameTimestamp() because VFC is stopped
1210 // during Suspend(). It won't be started again until after Resume() is
1211 // called.
1212 seek_time_ = compositor_->GetCurrentFrameTimestamp();
1213 }
1214
1215 if (chunk_demuxer_)
1216 chunk_demuxer_->StartWaitingForSeek(seek_time_);
1217
1218 resuming_ = true;
1219 pipeline_.Resume(CreateRenderer(), seek_time_,
1220 BIND_TO_RENDER_LOOP1(&WebMediaPlayerImpl::OnPipelineSeeked,
1221 time_changed));
1222 } 1052 }
1223 1053
1224 #if defined(OS_ANDROID) // WMPI_CAST 1054 #if defined(OS_ANDROID) // WMPI_CAST
1225 1055
1226 bool WebMediaPlayerImpl::isRemote() const { 1056 bool WebMediaPlayerImpl::isRemote() const {
1227 return cast_impl_.isRemote(); 1057 return cast_impl_.isRemote();
1228 } 1058 }
1229 1059
1230 void WebMediaPlayerImpl::SetMediaPlayerManager( 1060 void WebMediaPlayerImpl::SetMediaPlayerManager(
1231 RendererMediaPlayerManagerInterface* media_player_manager) { 1061 RendererMediaPlayerManagerInterface* media_player_manager) {
(...skipping 10 matching lines...) Expand all
1242 1072
1243 void WebMediaPlayerImpl::OnRemotePlaybackEnded() { 1073 void WebMediaPlayerImpl::OnRemotePlaybackEnded() {
1244 DVLOG(1) << __FUNCTION__; 1074 DVLOG(1) << __FUNCTION__;
1245 DCHECK(main_task_runner_->BelongsToCurrentThread()); 1075 DCHECK(main_task_runner_->BelongsToCurrentThread());
1246 1076
1247 ended_ = true; 1077 ended_ = true;
1248 client_->timeChanged(); 1078 client_->timeChanged();
1249 } 1079 }
1250 1080
1251 void WebMediaPlayerImpl::OnDisconnectedFromRemoteDevice(double t) { 1081 void WebMediaPlayerImpl::OnDisconnectedFromRemoteDevice(double t) {
1252 paused_time_ = base::TimeDelta::FromSecondsD(t); 1082 DoSeek(base::TimeDelta::FromSecondsD(t), false);
wolenetz 2016/01/29 21:42:30 Do we need to do anything with paused_time_/seek_t
sandersd (OOO until July 31) 2016/02/01 23:19:26 We do; it should be done correctly by DoSeek(). I
wolenetz 2016/02/26 02:30:11 Acknowledged.
1253 pending_seek_ = true; 1083 if (delegate_ && !delegate_->IsHidden())
wolenetz 2016/01/29 21:42:30 I confess I don't understand what's going on here
sandersd (OOO until July 31) 2016/02/01 23:19:26 This just says that we want to resume playback whe
wolenetz 2016/02/26 02:30:11 Acknowledged.
1254 pending_seek_time_ = paused_time_; 1084 pipeline_state_.Resume();
1255 1085
1256 ScheduleResume();
1257
1258 if (paused_time_ == pipeline_.GetMediaDuration()) {
1259 ended_ = true;
1260 }
1261 // We already told the delegate we're paused when remoting started. 1086 // We already told the delegate we're paused when remoting started.
1262 client_->playbackStateChanged(); 1087 client_->playbackStateChanged();
1263 client_->disconnectedFromRemoteDevice(); 1088 client_->disconnectedFromRemoteDevice();
1264 } 1089 }
1265 1090
1266 void WebMediaPlayerImpl::SuspendForRemote() { 1091 void WebMediaPlayerImpl::SuspendForRemote() {
1267 if (suspended_ && !suspending_) { 1092 if (pipeline_state_.IsSuspended()) {
1268 scoped_refptr<VideoFrame> frame = cast_impl_.GetCastingBanner(); 1093 scoped_refptr<VideoFrame> frame = cast_impl_.GetCastingBanner();
1269 if (frame) { 1094 if (frame) {
1270 compositor_->PaintFrameUsingOldRenderingPath(frame); 1095 compositor_->PaintFrameUsingOldRenderingPath(frame);
1271 } 1096 }
1272 } 1097 }
1273 ScheduleSuspend(); 1098 pipeline_state_.Suspend();
1274 } 1099 }
1275 1100
1276 gfx::Size WebMediaPlayerImpl::GetCanvasSize() const { 1101 gfx::Size WebMediaPlayerImpl::GetCanvasSize() const {
1277 if (!video_weblayer_) 1102 if (!video_weblayer_)
1278 return pipeline_metadata_.natural_size; 1103 return pipeline_metadata_.natural_size;
1279 1104
1280 return video_weblayer_->bounds(); 1105 return video_weblayer_->bounds();
1281 } 1106 }
1282 1107
1283 void WebMediaPlayerImpl::SetDeviceScaleFactor(float scale_factor) { 1108 void WebMediaPlayerImpl::SetDeviceScaleFactor(float scale_factor) {
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
1338 DCHECK(!data_source_); 1163 DCHECK(!data_source_);
1339 1164
1340 chunk_demuxer_ = new ChunkDemuxer( 1165 chunk_demuxer_ = new ChunkDemuxer(
1341 BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnDemuxerOpened), 1166 BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnDemuxerOpened),
1342 encrypted_media_init_data_cb, media_log_, true); 1167 encrypted_media_init_data_cb, media_log_, true);
1343 demuxer_.reset(chunk_demuxer_); 1168 demuxer_.reset(chunk_demuxer_);
1344 } 1169 }
1345 1170
1346 // ... and we're ready to go! 1171 // ... and we're ready to go!
1347 seeking_ = true; 1172 seeking_ = true;
1348 1173 pipeline_state_.Start(
1349 // TODO(sandersd): On Android, defer Start() if the tab is not visible. 1174 chunk_demuxer_, demuxer_.get(),
1350 pipeline_.Start(
1351 demuxer_.get(), CreateRenderer(),
1352 BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnPipelineEnded), 1175 BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnPipelineEnded),
1353 BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnPipelineError),
1354 BIND_TO_RENDER_LOOP1(&WebMediaPlayerImpl::OnPipelineSeeked, false),
1355 BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnPipelineMetadata), 1176 BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnPipelineMetadata),
1356 BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnPipelineBufferingStateChanged), 1177 BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnPipelineBufferingStateChanged),
1357 BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnDurationChanged), 1178 BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnDurationChanged),
1358 BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnAddTextTrack), 1179 BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnAddTextTrack),
1359 BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnWaitingForDecryptionKey)); 1180 BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnWaitingForDecryptionKey));
1360 } 1181 }
1361 1182
1362 void WebMediaPlayerImpl::SetNetworkState(WebMediaPlayer::NetworkState state) { 1183 void WebMediaPlayerImpl::SetNetworkState(WebMediaPlayer::NetworkState state) {
1363 DVLOG(1) << __FUNCTION__ << "(" << state << ")"; 1184 DVLOG(1) << __FUNCTION__ << "(" << state << ")";
1364 DCHECK(main_task_runner_->BelongsToCurrentThread()); 1185 DCHECK(main_task_runner_->BelongsToCurrentThread());
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after
1447 base::WaitableEvent event(false, false); 1268 base::WaitableEvent event(false, false);
1448 compositor_task_runner_->PostTask(FROM_HERE, 1269 compositor_task_runner_->PostTask(FROM_HERE,
1449 base::Bind(&GetCurrentFrameAndSignal, 1270 base::Bind(&GetCurrentFrameAndSignal,
1450 base::Unretained(compositor_), 1271 base::Unretained(compositor_),
1451 &video_frame, 1272 &video_frame,
1452 &event)); 1273 &event));
1453 event.Wait(); 1274 event.Wait();
1454 return video_frame; 1275 return video_frame;
1455 } 1276 }
1456 1277
1457 void WebMediaPlayerImpl::UpdatePausedTime() {
1458 DCHECK(main_task_runner_->BelongsToCurrentThread());
1459
1460 // pause() may be called after playback has ended and the HTMLMediaElement
1461 // requires that currentTime() == duration() after ending. We want to ensure
1462 // |paused_time_| matches currentTime() in this case or a future seek() may
1463 // incorrectly discard what it thinks is a seek to the existing time.
1464 paused_time_ =
1465 ended_ ? pipeline_.GetMediaDuration() : pipeline_.GetMediaTime();
1466 }
1467
1468 void WebMediaPlayerImpl::NotifyPlaybackStarted() { 1278 void WebMediaPlayerImpl::NotifyPlaybackStarted() {
1469 #if defined(OS_ANDROID) // WMPI_CAST 1279 #if defined(OS_ANDROID) // WMPI_CAST
1470 // We do not tell our delegates about remote playback, becuase that would 1280 // We do not tell our delegates about remote playback, becuase that would
1471 // keep the device awake, which is not what we want. 1281 // keep the device awake, which is not what we want.
1472 if (isRemote()) 1282 if (isRemote())
1473 return; 1283 return;
1474 #endif 1284 #endif
1475 if (delegate_) 1285 if (delegate_)
1476 delegate_->DidPlay(this); 1286 delegate_->DidPlay(this);
1477 if (!memory_usage_reporting_timer_.IsRunning()) { 1287 if (!memory_usage_reporting_timer_.IsRunning()) {
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
1523 << ", Video: " << stats.video_memory_usage << ", DataSource: " 1333 << ", Video: " << stats.video_memory_usage << ", DataSource: "
1524 << (data_source_ ? data_source_->GetMemoryUsage() : 0) 1334 << (data_source_ ? data_source_->GetMemoryUsage() : 0)
1525 << ", Demuxer: " << demuxer_memory_usage; 1335 << ", Demuxer: " << demuxer_memory_usage;
1526 1336
1527 const int64_t delta = current_memory_usage - last_reported_memory_usage_; 1337 const int64_t delta = current_memory_usage - last_reported_memory_usage_;
1528 last_reported_memory_usage_ = current_memory_usage; 1338 last_reported_memory_usage_ = current_memory_usage;
1529 adjust_allocated_memory_cb_.Run(delta); 1339 adjust_allocated_memory_cb_.Run(delta);
1530 } 1340 }
1531 1341
1532 } // namespace media 1342 } // namespace media
OLDNEW
« media/blink/pipeline_state.cc ('K') | « media/blink/webmediaplayer_impl.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698