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

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: Initialize |should_notify_time_changed_|. Created 4 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « media/blink/webmediaplayer_impl.h ('k') | media/filters/pipeline_controller.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2013 The Chromium Authors. All rights reserved. 1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "media/blink/webmediaplayer_impl.h" 5 #include "media/blink/webmediaplayer_impl.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 #include <cmath> 8 #include <cmath>
9 #include <limits> 9 #include <limits>
10 #include <string> 10 #include <string>
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_controller_(
148 &pipeline_,
149 base::Bind(&WebMediaPlayerImpl::CreateRenderer,
150 base::Unretained(this)),
151 base::Bind(&WebMediaPlayerImpl::OnPipelineSeeked, AsWeakPtr()),
152 base::Bind(&WebMediaPlayerImpl::OnPipelineSuspended, AsWeakPtr()),
153 base::Bind(&WebMediaPlayerImpl::OnPipelineResumed, AsWeakPtr()),
154 base::Bind(&WebMediaPlayerImpl::OnPipelineError, AsWeakPtr())),
146 load_type_(LoadTypeURL), 155 load_type_(LoadTypeURL),
147 opaque_(false), 156 opaque_(false),
148 playback_rate_(0.0), 157 playback_rate_(0.0),
149 paused_(true), 158 paused_(true),
150 seeking_(false), 159 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 pending_suspend_resume_cycle_(false), 160 pending_suspend_resume_cycle_(false),
158 ended_(false), 161 ended_(false),
159 pending_seek_(false),
160 should_notify_time_changed_(false), 162 should_notify_time_changed_(false),
161 fullscreen_(false), 163 fullscreen_(false),
162 decoder_requires_restart_for_fullscreen_(false), 164 decoder_requires_restart_for_fullscreen_(false),
163 client_(client), 165 client_(client),
164 encrypted_client_(encrypted_client), 166 encrypted_client_(encrypted_client),
165 delegate_(delegate), 167 delegate_(delegate),
166 delegate_id_(0), 168 delegate_id_(0),
167 defer_load_cb_(params.defer_load_cb()), 169 defer_load_cb_(params.defer_load_cb()),
168 context_3d_cb_(params.context_3d_cb()), 170 context_3d_cb_(params.context_3d_cb()),
169 adjust_allocated_memory_cb_(params.adjust_allocated_memory_cb()), 171 adjust_allocated_memory_cb_(params.adjust_allocated_memory_cb()),
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
223 delegate_->PlayerGone(delegate_id_); 225 delegate_->PlayerGone(delegate_id_);
224 delegate_->RemoveObserver(delegate_id_); 226 delegate_->RemoveObserver(delegate_id_);
225 } 227 }
226 228
227 // Abort any pending IO so stopping the pipeline doesn't get blocked. 229 // Abort any pending IO so stopping the pipeline doesn't get blocked.
228 suppress_destruction_errors_ = true; 230 suppress_destruction_errors_ = true;
229 if (data_source_) 231 if (data_source_)
230 data_source_->Abort(); 232 data_source_->Abort();
231 if (chunk_demuxer_) { 233 if (chunk_demuxer_) {
232 chunk_demuxer_->Shutdown(); 234 chunk_demuxer_->Shutdown();
233 chunk_demuxer_ = NULL; 235 chunk_demuxer_ = nullptr;
234 } 236 }
235 237
236 renderer_factory_.reset(); 238 renderer_factory_.reset();
237 239
238 // Make sure to kill the pipeline so there's no more media threads running. 240 // Make sure to kill the pipeline so there's no more media threads running.
239 // Note: stopping the pipeline might block for a long time. 241 // Note: stopping the pipeline might block for a long time.
240 base::WaitableEvent waiter(false, false); 242 base::WaitableEvent waiter(false, false);
241 pipeline_.Stop( 243 pipeline_.Stop(
242 base::Bind(&base::WaitableEvent::Signal, base::Unretained(&waiter))); 244 base::Bind(&base::WaitableEvent::Signal, base::Unretained(&waiter)));
243 waiter.Wait(); 245 waiter.Wait();
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after
335 DCHECK(main_task_runner_->BelongsToCurrentThread()); 337 DCHECK(main_task_runner_->BelongsToCurrentThread());
336 338
337 #if defined(OS_ANDROID) // WMPI_CAST 339 #if defined(OS_ANDROID) // WMPI_CAST
338 if (isRemote()) { 340 if (isRemote()) {
339 cast_impl_.play(); 341 cast_impl_.play();
340 return; 342 return;
341 } 343 }
342 #endif 344 #endif
343 345
344 paused_ = false; 346 paused_ = false;
347 pipeline_.SetPlaybackRate(playback_rate_);
345 348
346 pipeline_.SetPlaybackRate(playback_rate_);
347 if (data_source_) 349 if (data_source_)
348 data_source_->MediaIsPlaying(); 350 data_source_->MediaIsPlaying();
349 351
350 media_log_->AddEvent(media_log_->CreateEvent(MediaLogEvent::PLAY)); 352 media_log_->AddEvent(media_log_->CreateEvent(MediaLogEvent::PLAY));
351 353
352 if (playback_rate_ > 0) { 354 if (playback_rate_ > 0) {
353 // Resume the player if playback was initiated in the foreground. 355 NotifyPlaybackStarted();
354 if (suspended_ && !resuming_ && delegate_ && !delegate_->IsHidden()) {
355 ScheduleResume();
356 return;
357 }
358 356
359 NotifyPlaybackStarted(); 357 // Resume the player if playback was initiated in the foreground. Resume()
358 // will do nothing if the pipeline is not suspended state, but will clear
359 // some internal pending state, so it should always be called.
360 if (delegate_ && !delegate_->IsHidden())
361 pipeline_controller_.Resume();
360 } 362 }
361 } 363 }
362 364
363 void WebMediaPlayerImpl::pause() { 365 void WebMediaPlayerImpl::pause() {
364 DVLOG(1) << __FUNCTION__; 366 DVLOG(1) << __FUNCTION__;
365 DCHECK(main_task_runner_->BelongsToCurrentThread()); 367 DCHECK(main_task_runner_->BelongsToCurrentThread());
366 368
367 const bool was_already_paused = paused_ || playback_rate_ == 0; 369 const bool was_already_paused = paused_ || playback_rate_ == 0;
368 paused_ = true; 370 paused_ = true;
369 371
370 #if defined(OS_ANDROID) // WMPI_CAST 372 #if defined(OS_ANDROID) // WMPI_CAST
371 if (isRemote()) { 373 if (isRemote()) {
372 cast_impl_.pause(); 374 cast_impl_.pause();
373 return; 375 return;
374 } 376 }
375 #endif 377 #endif
376 378
377 pipeline_.SetPlaybackRate(0.0); 379 pipeline_.SetPlaybackRate(0.0);
378 UpdatePausedTime(); 380
381 // pause() may be called after playback has ended and the HTMLMediaElement
382 // requires that currentTime() == duration() after ending. We want to ensure
383 // |paused_time_| matches currentTime() in this case or a future seek() may
384 // incorrectly discard what it thinks is a seek to the existing time.
385 paused_time_ =
386 ended_ ? pipeline_.GetMediaDuration() : pipeline_.GetMediaTime();
379 387
380 media_log_->AddEvent(media_log_->CreateEvent(MediaLogEvent::PAUSE)); 388 media_log_->AddEvent(media_log_->CreateEvent(MediaLogEvent::PAUSE));
381 389
382 if (!was_already_paused) 390 if (!was_already_paused)
383 NotifyPlaybackPaused(); 391 NotifyPlaybackPaused();
384 } 392 }
385 393
386 bool WebMediaPlayerImpl::supportsSave() const { 394 bool WebMediaPlayerImpl::supportsSave() const {
387 DCHECK(main_task_runner_->BelongsToCurrentThread()); 395 DCHECK(main_task_runner_->BelongsToCurrentThread());
388 return supports_save_; 396 return supports_save_;
389 } 397 }
390 398
391 void WebMediaPlayerImpl::seek(double seconds) { 399 void WebMediaPlayerImpl::seek(double seconds) {
392 DVLOG(1) << __FUNCTION__ << "(" << seconds << "s)"; 400 DVLOG(1) << __FUNCTION__ << "(" << seconds << "s)";
393 DCHECK(main_task_runner_->BelongsToCurrentThread()); 401 DCHECK(main_task_runner_->BelongsToCurrentThread());
402 DoSeek(base::TimeDelta::FromSecondsD(seconds), true);
403 }
404
405 void WebMediaPlayerImpl::DoSeek(base::TimeDelta time, bool time_updated) {
406 DCHECK(main_task_runner_->BelongsToCurrentThread());
394 407
395 ended_ = false; 408 ended_ = false;
396 409
397 base::TimeDelta new_seek_time = base::TimeDelta::FromSecondsD(seconds);
398
399 #if defined(OS_ANDROID) // WMPI_CAST 410 #if defined(OS_ANDROID) // WMPI_CAST
400 if (isRemote()) { 411 if (isRemote()) {
401 cast_impl_.seek(new_seek_time); 412 cast_impl_.seek(time);
402 return; 413 return;
403 } 414 }
404 #endif 415 #endif
405 416
406 ReadyState old_state = ready_state_; 417 ReadyState old_state = ready_state_;
407 if (ready_state_ > WebMediaPlayer::ReadyStateHaveMetadata) 418 if (ready_state_ > WebMediaPlayer::ReadyStateHaveMetadata)
408 SetReadyState(WebMediaPlayer::ReadyStateHaveMetadata); 419 SetReadyState(WebMediaPlayer::ReadyStateHaveMetadata);
409 420
410 if (seeking_ || suspended_) { 421 // When paused, we know exactly what the current time is and can elide seeks
411 // Once resuming, it's too late to change the resume time and so the 422 // to it. However, there are two cases that are not elided:
412 // implementation is a little different. 423 // 1) When the pipeline state is not stable.
413 bool is_suspended = suspended_ && !resuming_; 424 // In this case we just let |pipeline_controller_| decide what to do, as
414 425 // it has complete information.
415 // If we are currently seeking or resuming to |new_seek_time|, skip the 426 // 2) For MSE.
416 // seek (except for MSE, which always seeks). 427 // Because the buffers may have changed between seeks, MSE seeks are
417 if (!is_suspended && new_seek_time == seek_time_) { 428 // never elided.
418 if (chunk_demuxer_) { 429 if (paused_ && pipeline_controller_.IsStable() && paused_time_ == time &&
419 // Don't suppress any redundant in-progress MSE seek. There could have 430 !chunk_demuxer_) {
420 // been changes to the underlying buffers after seeking the demuxer and 431 // If the ready state was high enough before, we can indicate that the seek
421 // before receiving OnPipelineSeeked() for the currently in-progress 432 // completed just by restoring it. Otherwise we will just wait for the real
422 // seek. 433 // ready state change to eventually happen.
423 MEDIA_LOG(DEBUG, media_log_) 434 if (old_state == ReadyStateHaveEnoughData) {
424 << "Detected MediaSource seek to same time as in-progress seek to "
425 << seek_time_ << ".";
426 } else {
427 // Suppress all redundant seeks if unrestricted by media source demuxer
428 // API.
429 pending_seek_ = false;
430 pending_seek_time_ = base::TimeDelta();
431 return;
432 }
433 }
434
435 // If |chunk_demuxer_| is already seeking, cancel that seek and schedule the
436 // new one.
437 if (!is_suspended && chunk_demuxer_)
438 chunk_demuxer_->CancelPendingSeek(new_seek_time);
439
440 // Schedule a seek once the current suspend or seek finishes.
441 pending_seek_ = true;
442 pending_seek_time_ = new_seek_time;
443
444 // In the case of seeking while suspended, the seek is considered to have
445 // started immediately (but won't complete until the pipeline is resumed).
446 if (is_suspended) {
447 seeking_ = true;
448 seek_time_ = new_seek_time;
449
450 // Resume the pipeline if the seek is initiated in the foreground so that
451 // the correct frame is displayed.
452 if (delegate_ && !delegate_->IsHidden())
453 ScheduleResume();
454 }
455
456 return;
457 }
458
459 media_log_->AddEvent(media_log_->CreateSeekEvent(seconds));
460
461 // Update our paused time.
462 // For non-MSE playbacks, in paused state ignore the seek operations to
463 // current time if the loading is completed and generate
464 // OnPipelineBufferingStateChanged event to eventually fire seeking and seeked
465 // events. We don't short-circuit MSE seeks in this logic because the
466 // underlying buffers around the seek time might have changed (or even been
467 // removed) since previous seek/preroll/pause action, and the pipeline might
468 // need to flush so the new buffers are decoded and rendered instead of the
469 // old ones.
470 if (paused_) {
471 if (paused_time_ != new_seek_time || chunk_demuxer_) {
472 paused_time_ = new_seek_time;
473 } else if (old_state == ReadyStateHaveEnoughData) {
474 main_task_runner_->PostTask( 435 main_task_runner_->PostTask(
475 FROM_HERE, 436 FROM_HERE,
476 base::Bind(&WebMediaPlayerImpl::OnPipelineBufferingStateChanged, 437 base::Bind(&WebMediaPlayerImpl::OnPipelineBufferingStateChanged,
477 AsWeakPtr(), BUFFERING_HAVE_ENOUGH)); 438 AsWeakPtr(), BUFFERING_HAVE_ENOUGH));
478 return;
479 } 439 }
440 return;
480 } 441 }
481 442
482 seeking_ = true; 443 seeking_ = true;
483 seek_time_ = new_seek_time; 444 seek_time_ = time;
445 if (paused_)
446 paused_time_ = time;
447 pipeline_controller_.Seek(time, time_updated);
484 448
485 if (chunk_demuxer_) 449 // Resume the pipeline if the seek is initiated in the foreground so that
486 chunk_demuxer_->StartWaitingForSeek(seek_time_); 450 // the correct frame is displayed. If the pipeline is not suspended, Resume()
487 451 // will do nothing but clear some pending state.
488 pipeline_.Seek(seek_time_, BIND_TO_RENDER_LOOP1( 452 if (delegate_ && !delegate_->IsHidden())
489 &WebMediaPlayerImpl::OnPipelineSeeked, true)); 453 pipeline_controller_.Resume();
490 } 454 }
491 455
492 void WebMediaPlayerImpl::setRate(double rate) { 456 void WebMediaPlayerImpl::setRate(double rate) {
493 DVLOG(1) << __FUNCTION__ << "(" << rate << ")"; 457 DVLOG(1) << __FUNCTION__ << "(" << rate << ")";
494 DCHECK(main_task_runner_->BelongsToCurrentThread()); 458 DCHECK(main_task_runner_->BelongsToCurrentThread());
495 459
496 // TODO(kylep): Remove when support for negatives is added. Also, modify the 460 // TODO(kylep): Remove when support for negatives is added. Also, modify the
497 // following checks so rewind uses reasonable values also. 461 // following checks so rewind uses reasonable values also.
498 if (rate < 0.0) 462 if (rate < 0.0)
499 return; 463 return;
(...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after
628 592
629 double WebMediaPlayerImpl::currentTime() const { 593 double WebMediaPlayerImpl::currentTime() const {
630 DCHECK(main_task_runner_->BelongsToCurrentThread()); 594 DCHECK(main_task_runner_->BelongsToCurrentThread());
631 DCHECK_NE(ready_state_, WebMediaPlayer::ReadyStateHaveNothing); 595 DCHECK_NE(ready_state_, WebMediaPlayer::ReadyStateHaveNothing);
632 596
633 // TODO(scherkus): Replace with an explicit ended signal to HTMLMediaElement, 597 // TODO(scherkus): Replace with an explicit ended signal to HTMLMediaElement,
634 // see http://crbug.com/409280 598 // see http://crbug.com/409280
635 if (ended_) 599 if (ended_)
636 return duration(); 600 return duration();
637 601
638 // We know the current seek time better than pipeline: pipeline may processing 602 if (seeking())
639 // an earlier seek before a pending seek has been started, or it might not yet 603 return seek_time_.InSecondsF();
640 // have the current seek time returnable via GetMediaTime().
641 if (seeking()) {
642 return pending_seek_ ? pending_seek_time_.InSecondsF()
643 : seek_time_.InSecondsF();
644 }
645 604
646 #if defined(OS_ANDROID) // WMPI_CAST 605 #if defined(OS_ANDROID) // WMPI_CAST
647 if (isRemote()) { 606 if (isRemote())
648 return cast_impl_.currentTime(); 607 return cast_impl_.currentTime();
649 }
650 #endif 608 #endif
651 609
652 if (paused_) { 610 if (paused_)
653 return paused_time_.InSecondsF(); 611 return paused_time_.InSecondsF();
654 }
655 612
656 return pipeline_.GetMediaTime().InSecondsF(); 613 return pipeline_.GetMediaTime().InSecondsF();
657 } 614 }
658 615
659 WebMediaPlayer::NetworkState WebMediaPlayerImpl::getNetworkState() const { 616 WebMediaPlayer::NetworkState WebMediaPlayerImpl::getNetworkState() const {
660 DCHECK(main_task_runner_->BelongsToCurrentThread()); 617 DCHECK(main_task_runner_->BelongsToCurrentThread());
661 return network_state_; 618 return network_state_;
662 } 619 }
663 620
664 WebMediaPlayer::ReadyState WebMediaPlayerImpl::getReadyState() const { 621 WebMediaPlayer::ReadyState WebMediaPlayerImpl::getReadyState() const {
(...skipping 212 matching lines...) Expand 10 before | Expand all | Expand 10 after
877 is_cdm_attached_ = true; 834 is_cdm_attached_ = true;
878 return; 835 return;
879 } 836 }
880 837
881 set_cdm_result_->completeWithError( 838 set_cdm_result_->completeWithError(
882 blink::WebContentDecryptionModuleExceptionNotSupportedError, 0, 839 blink::WebContentDecryptionModuleExceptionNotSupportedError, 0,
883 "Unable to set MediaKeys object"); 840 "Unable to set MediaKeys object");
884 set_cdm_result_.reset(); 841 set_cdm_result_.reset();
885 } 842 }
886 843
887 void WebMediaPlayerImpl::OnPipelineSeeked(bool time_changed, 844 void WebMediaPlayerImpl::OnPipelineSeeked(bool time_updated) {
888 PipelineStatus status) {
889 DVLOG(1) << __FUNCTION__ << "(" << time_changed << ", " << status << ")";
890 DCHECK(main_task_runner_->BelongsToCurrentThread());
891
892 if (status != PIPELINE_OK) {
893 OnPipelineError(status);
894 return;
895 }
896
897 // Whether or not the seek was caused by a resume, we're not suspended now.
898 const bool was_resuming = resuming_;
899 resuming_ = false;
900 suspended_ = false;
901
902 // If we we're resuming into the playing state, notify the delegate.
903 if (was_resuming && playback_rate_ > 0 && !paused_)
904 NotifyPlaybackStarted();
905
906 // If there is a pending suspend, the seek does not complete until after the
907 // next resume.
908 if (pending_suspend_) {
909 pending_suspend_ = false;
910 pending_time_change_ = time_changed;
911 Suspend();
912 return;
913 }
914
915 // Clear seek state. Note that if the seek was caused by a resume, then
916 // |seek_time_| is always set but |seeking_| is only set if there was a
917 // pending seek at the time.
918 seeking_ = false; 845 seeking_ = false;
919 seek_time_ = base::TimeDelta(); 846 seek_time_ = base::TimeDelta();
920
921 if (pending_seek_) {
922 double pending_seek_seconds = pending_seek_time_.InSecondsF();
923 pending_seek_ = false;
924 pending_seek_time_ = base::TimeDelta();
925 seek(pending_seek_seconds);
926 return;
927 }
928
929 // Update our paused time.
930 if (paused_) 847 if (paused_)
931 UpdatePausedTime(); 848 paused_time_ = pipeline_.GetMediaTime();
932 849 if (time_updated)
933 should_notify_time_changed_ = time_changed; 850 should_notify_time_changed_ = true;
934 } 851 }
935 852
936 void WebMediaPlayerImpl::OnPipelineSuspended(PipelineStatus status) { 853 void WebMediaPlayerImpl::OnPipelineSuspended() {
937 DVLOG(1) << __FUNCTION__ << "(" << status << ")";
938 DCHECK(main_task_runner_->BelongsToCurrentThread());
939
940 if (status != PIPELINE_OK) {
941 OnPipelineError(status);
942 return;
943 }
944
945 suspending_ = false;
946 if (delegate_)
947 delegate_->PlayerGone(delegate_id_);
948
949 #if defined(OS_ANDROID) 854 #if defined(OS_ANDROID)
950 if (isRemote()) { 855 if (isRemote()) {
951 scoped_refptr<VideoFrame> frame = cast_impl_.GetCastingBanner(); 856 scoped_refptr<VideoFrame> frame = cast_impl_.GetCastingBanner();
952 if (frame) { 857 if (frame) {
953 compositor_->PaintFrameUsingOldRenderingPath(frame); 858 compositor_->PaintFrameUsingOldRenderingPath(frame);
954 } 859 }
955 } 860 }
956 #endif 861 #endif
957 862
958 if (pending_resume_ || pending_suspend_resume_cycle_) { 863 if (delegate_)
959 pending_resume_ = false; 864 delegate_->PlayerGone(delegate_id_);
865
866 if (pending_suspend_resume_cycle_) {
960 pending_suspend_resume_cycle_ = false; 867 pending_suspend_resume_cycle_ = false;
961 Resume(); 868 pipeline_controller_.Resume();
962 return; 869 return;
963 } 870 }
964 } 871 }
965 872
873 void WebMediaPlayerImpl::OnPipelineResumed() {
874 if (playback_rate_ > 0 && !paused_)
875 NotifyPlaybackStarted();
876 }
877
966 void WebMediaPlayerImpl::OnPipelineEnded() { 878 void WebMediaPlayerImpl::OnPipelineEnded() {
967 DVLOG(1) << __FUNCTION__; 879 DVLOG(1) << __FUNCTION__;
968 DCHECK(main_task_runner_->BelongsToCurrentThread()); 880 DCHECK(main_task_runner_->BelongsToCurrentThread());
969 881
970 // Ignore state changes until we've completed all outstanding seeks. 882 // Ignore state changes until we've completed all outstanding operations.
971 if (seeking_ || pending_seek_) 883 if (!pipeline_controller_.IsStable())
972 return; 884 return;
973 885
974 ended_ = true; 886 ended_ = true;
975 client_->timeChanged(); 887 client_->timeChanged();
976 } 888 }
977 889
978 void WebMediaPlayerImpl::OnPipelineError(PipelineStatus error) { 890 void WebMediaPlayerImpl::OnPipelineError(PipelineStatus error) {
979 DVLOG(1) << __FUNCTION__; 891 DVLOG(1) << __FUNCTION__;
980 DCHECK(main_task_runner_->BelongsToCurrentThread()); 892 DCHECK(main_task_runner_->BelongsToCurrentThread());
981 DCHECK_NE(error, PIPELINE_OK); 893 DCHECK_NE(error, PIPELINE_OK);
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
1025 // playback. 937 // playback.
1026 if (delegate_ && delegate_->IsHidden()) 938 if (delegate_ && delegate_->IsHidden())
1027 OnHidden(false); 939 OnHidden(false);
1028 } 940 }
1029 } 941 }
1030 942
1031 void WebMediaPlayerImpl::OnPipelineBufferingStateChanged( 943 void WebMediaPlayerImpl::OnPipelineBufferingStateChanged(
1032 BufferingState buffering_state) { 944 BufferingState buffering_state) {
1033 DVLOG(1) << __FUNCTION__ << "(" << buffering_state << ")"; 945 DVLOG(1) << __FUNCTION__ << "(" << buffering_state << ")";
1034 946
1035 // Ignore buffering state changes until we've completed all outstanding seeks. 947 // Ignore buffering state changes until we've completed all outstanding
1036 if (seeking_ || pending_seek_) 948 // operations.
949 if (!pipeline_controller_.IsStable())
1037 return; 950 return;
1038 951
1039 // TODO(scherkus): Handle other buffering states when Pipeline starts using 952 // TODO(scherkus): Handle other buffering states when Pipeline starts using
1040 // them and translate them ready state changes http://crbug.com/144683 953 // them and translate them ready state changes http://crbug.com/144683
1041 DCHECK_EQ(buffering_state, BUFFERING_HAVE_ENOUGH); 954 DCHECK_EQ(buffering_state, BUFFERING_HAVE_ENOUGH);
1042 SetReadyState(WebMediaPlayer::ReadyStateHaveEnoughData); 955 SetReadyState(WebMediaPlayer::ReadyStateHaveEnoughData);
1043 956
1044 // Let the DataSource know we have enough data. It may use this information to 957 // Let the DataSource know we have enough data. It may use this information to
1045 // release unused network connections. 958 // release unused network connections.
1046 if (data_source_) 959 if (data_source_)
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
1100 return; 1013 return;
1101 } 1014 }
1102 1015
1103 #if defined(OS_ANDROID) 1016 #if defined(OS_ANDROID)
1104 // If we're remote, the pipeline should already be suspended. 1017 // If we're remote, the pipeline should already be suspended.
1105 if (isRemote()) 1018 if (isRemote())
1106 return; 1019 return;
1107 #endif 1020 #endif
1108 1021
1109 if (must_suspend || (paused_ && ended_) || hasVideo()) 1022 if (must_suspend || (paused_ && ended_) || hasVideo())
1110 ScheduleSuspend(); 1023 pipeline_controller_.Suspend();
1111 }
1112
1113 void WebMediaPlayerImpl::ScheduleSuspend() {
1114 if (!pipeline_.IsRunning())
1115 return;
1116
1117 if (resuming_ || seeking_) {
1118 pending_suspend_ = true;
1119 return;
1120 }
1121
1122 if (pending_resume_) {
1123 pending_resume_ = false;
1124 return;
1125 }
1126
1127 Suspend();
1128 }
1129
1130 void WebMediaPlayerImpl::Suspend() {
1131 DCHECK(main_task_runner_->BelongsToCurrentThread());
1132
1133 // Since Pipeline::IsRunning() may be set on the media thread there are cases
1134 // where two suspends might be issued concurrently.
1135 if (suspended_)
1136 return;
1137
1138 suspended_ = true;
1139 suspending_ = true;
1140 pipeline_.Suspend(
1141 BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnPipelineSuspended));
1142 } 1024 }
1143 1025
1144 void WebMediaPlayerImpl::OnShown() { 1026 void WebMediaPlayerImpl::OnShown() {
1145 DCHECK(main_task_runner_->BelongsToCurrentThread()); 1027 DCHECK(main_task_runner_->BelongsToCurrentThread());
1146 1028
1147 #if !defined(OS_ANDROID) 1029 #if !defined(OS_ANDROID)
1148 // Suspend/Resume is enabled by default on Android. 1030 // Suspend/Resume is enabled by default on Android.
1149 if (!base::CommandLine::ForCurrentProcess()->HasSwitch( 1031 if (!base::CommandLine::ForCurrentProcess()->HasSwitch(
1150 switches::kEnableMediaSuspend)) { 1032 switches::kEnableMediaSuspend)) {
1151 return; 1033 return;
1152 } 1034 }
1153 #endif // !defined(OS_ANDROID) 1035 #endif // !defined(OS_ANDROID)
1154 1036
1155 if (base::CommandLine::ForCurrentProcess()->HasSwitch( 1037 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
1156 switches::kDisableMediaSuspend)) { 1038 switches::kDisableMediaSuspend)) {
1157 return; 1039 return;
1158 } 1040 }
1159 1041
1160 #if defined(OS_ANDROID) 1042 #if defined(OS_ANDROID)
1161 // If we're remote, the pipeline should stay suspended. 1043 // If we're remote, the pipeline should stay suspended.
1162 if (isRemote()) 1044 if (isRemote())
1163 return; 1045 return;
1164 #endif 1046 #endif
1165 1047
1166 if (!ended_ && !paused_) 1048 if (!ended_ && !paused_)
1167 ScheduleResume(); 1049 pipeline_controller_.Resume();
1168 }
1169
1170 void WebMediaPlayerImpl::ScheduleResume() {
1171 if (!pipeline_.IsRunning())
1172 return;
1173
1174 if (suspending_) {
1175 pending_resume_ = true;
1176 return;
1177 }
1178
1179 if (pending_suspend_) {
1180 pending_suspend_ = false;
1181 return;
1182 }
1183
1184 // Might already be resuming iff we came back from remote playback recently.
1185 if (suspended_ && !resuming_)
1186 Resume();
1187 } 1050 }
1188 1051
1189 void WebMediaPlayerImpl::OnPlay() { 1052 void WebMediaPlayerImpl::OnPlay() {
1190 play(); 1053 play();
1191 client_->playbackStateChanged(); 1054 client_->playbackStateChanged();
1192 } 1055 }
1193 1056
1194 void WebMediaPlayerImpl::OnPause() { 1057 void WebMediaPlayerImpl::OnPause() {
1195 pause(); 1058 pause();
1196 client_->playbackStateChanged(); 1059 client_->playbackStateChanged();
1197 } 1060 }
1198 1061
1199 void WebMediaPlayerImpl::OnVolumeMultiplierUpdate(double multiplier) { 1062 void WebMediaPlayerImpl::OnVolumeMultiplierUpdate(double multiplier) {
1200 volume_multiplier_ = multiplier; 1063 volume_multiplier_ = multiplier;
1201 setVolume(volume_); 1064 setVolume(volume_);
1202 } 1065 }
1203 1066
1204 void WebMediaPlayerImpl::Resume() {
1205 DCHECK(main_task_runner_->BelongsToCurrentThread());
1206 CHECK(suspended_);
1207 CHECK(!resuming_);
1208
1209 // If there was a time change pending when we suspended (which can happen when
1210 // we suspend immediately after a seek), surface it after resuming.
1211 bool time_changed = pending_time_change_;
1212 pending_time_change_ = false;
1213
1214 if (seeking_ || pending_seek_) {
1215 if (pending_seek_) {
1216 seek_time_ = pending_seek_time_;
1217 pending_seek_ = false;
1218 pending_seek_time_ = base::TimeDelta();
1219 }
1220 time_changed = true;
1221 } else {
1222 // It is safe to call GetCurrentFrameTimestamp() because VFC is stopped
1223 // during Suspend(). It won't be started again until after Resume() is
1224 // called. Use the pipeline time if there's no video.
1225 if (!data_source_ || !data_source_->IsStreaming()) {
1226 seek_time_ = hasVideo() ? compositor_->GetCurrentFrameTimestamp()
1227 : pipeline_.GetMediaTime();
1228 } else {
1229 // Resume from zero if a resource does not support range requests; this
1230 // avoids a painful "read-the-whole-file" seek penalty.
1231 seek_time_ = base::TimeDelta();
1232 }
1233 }
1234
1235 if (chunk_demuxer_)
1236 chunk_demuxer_->StartWaitingForSeek(seek_time_);
1237
1238 resuming_ = true;
1239 pipeline_.Resume(CreateRenderer(), seek_time_,
1240 BIND_TO_RENDER_LOOP1(&WebMediaPlayerImpl::OnPipelineSeeked,
1241 time_changed));
1242 }
1243
1244 void WebMediaPlayerImpl::ScheduleRestart() { 1067 void WebMediaPlayerImpl::ScheduleRestart() {
1245 // If we're suspended but not resuming there is no need to restart because 1068 if (!pipeline_controller_.IsSuspended()) {
1246 // there is no renderer to kill.
1247 if (!suspended_ || resuming_) {
1248 pending_suspend_resume_cycle_ = true; 1069 pending_suspend_resume_cycle_ = true;
1249 ScheduleSuspend(); 1070 pipeline_controller_.Suspend();
1250 } 1071 }
1251 } 1072 }
1252 1073
1253 #if defined(OS_ANDROID) // WMPI_CAST 1074 #if defined(OS_ANDROID) // WMPI_CAST
1254
1255 bool WebMediaPlayerImpl::isRemote() const { 1075 bool WebMediaPlayerImpl::isRemote() const {
1256 return cast_impl_.isRemote(); 1076 return cast_impl_.isRemote();
1257 } 1077 }
1258 1078
1259 void WebMediaPlayerImpl::SetMediaPlayerManager( 1079 void WebMediaPlayerImpl::SetMediaPlayerManager(
1260 RendererMediaPlayerManagerInterface* media_player_manager) { 1080 RendererMediaPlayerManagerInterface* media_player_manager) {
1261 cast_impl_.SetMediaPlayerManager(media_player_manager); 1081 cast_impl_.SetMediaPlayerManager(media_player_manager);
1262 } 1082 }
1263 1083
1264 void WebMediaPlayerImpl::requestRemotePlayback() { 1084 void WebMediaPlayerImpl::requestRemotePlayback() {
1265 cast_impl_.requestRemotePlayback(); 1085 cast_impl_.requestRemotePlayback();
1266 } 1086 }
1267 1087
1268 void WebMediaPlayerImpl::requestRemotePlaybackControl() { 1088 void WebMediaPlayerImpl::requestRemotePlaybackControl() {
1269 cast_impl_.requestRemotePlaybackControl(); 1089 cast_impl_.requestRemotePlaybackControl();
1270 } 1090 }
1271 1091
1272 void WebMediaPlayerImpl::OnRemotePlaybackEnded() { 1092 void WebMediaPlayerImpl::OnRemotePlaybackEnded() {
1273 DVLOG(1) << __FUNCTION__; 1093 DVLOG(1) << __FUNCTION__;
1274 DCHECK(main_task_runner_->BelongsToCurrentThread()); 1094 DCHECK(main_task_runner_->BelongsToCurrentThread());
1275 1095
1276 ended_ = true; 1096 ended_ = true;
1277 client_->timeChanged(); 1097 client_->timeChanged();
1278 } 1098 }
1279 1099
1280 void WebMediaPlayerImpl::OnDisconnectedFromRemoteDevice(double t) { 1100 void WebMediaPlayerImpl::OnDisconnectedFromRemoteDevice(double t) {
1281 paused_time_ = base::TimeDelta::FromSecondsD(t); 1101 DoSeek(base::TimeDelta::FromSecondsD(t), false);
1282 pending_seek_ = true; 1102 if (delegate_ && !delegate_->IsHidden())
1283 pending_seek_time_ = paused_time_; 1103 pipeline_controller_.Resume();
1284 1104
1285 ScheduleResume();
1286
1287 if (paused_time_ == pipeline_.GetMediaDuration()) {
1288 ended_ = true;
1289 }
1290 // We already told the delegate we're paused when remoting started. 1105 // We already told the delegate we're paused when remoting started.
1291 client_->playbackStateChanged(); 1106 client_->playbackStateChanged();
1292 client_->disconnectedFromRemoteDevice(); 1107 client_->disconnectedFromRemoteDevice();
1293 } 1108 }
1294 1109
1295 void WebMediaPlayerImpl::SuspendForRemote() { 1110 void WebMediaPlayerImpl::SuspendForRemote() {
1296 if (suspended_ && !suspending_) { 1111 if (!pipeline_controller_.IsSuspended()) {
1112 pipeline_controller_.Suspend();
1113 } else {
1114 // TODO(sandersd): If PipelineController::Suspend() called |suspended_cb|
1115 // when already suspended, we wouldn't need this case.
1297 scoped_refptr<VideoFrame> frame = cast_impl_.GetCastingBanner(); 1116 scoped_refptr<VideoFrame> frame = cast_impl_.GetCastingBanner();
1298 if (frame) { 1117 if (frame) {
1299 compositor_->PaintFrameUsingOldRenderingPath(frame); 1118 compositor_->PaintFrameUsingOldRenderingPath(frame);
1300 } 1119 }
1301 } 1120 }
1302 ScheduleSuspend();
1303 } 1121 }
1304 1122
1305 gfx::Size WebMediaPlayerImpl::GetCanvasSize() const { 1123 gfx::Size WebMediaPlayerImpl::GetCanvasSize() const {
1306 if (!video_weblayer_) 1124 if (!video_weblayer_)
1307 return pipeline_metadata_.natural_size; 1125 return pipeline_metadata_.natural_size;
1308 1126
1309 return video_weblayer_->bounds(); 1127 return video_weblayer_->bounds();
1310 } 1128 }
1311 1129
1312 void WebMediaPlayerImpl::SetDeviceScaleFactor(float scale_factor) { 1130 void WebMediaPlayerImpl::SetDeviceScaleFactor(float scale_factor) {
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after
1403 chunk_demuxer_ = new ChunkDemuxer( 1221 chunk_demuxer_ = new ChunkDemuxer(
1404 BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnDemuxerOpened), 1222 BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnDemuxerOpened),
1405 encrypted_media_init_data_cb, media_log_, true); 1223 encrypted_media_init_data_cb, media_log_, true);
1406 demuxer_.reset(chunk_demuxer_); 1224 demuxer_.reset(chunk_demuxer_);
1407 } 1225 }
1408 1226
1409 // ... and we're ready to go! 1227 // ... and we're ready to go!
1410 seeking_ = true; 1228 seeking_ = true;
1411 1229
1412 // TODO(sandersd): On Android, defer Start() if the tab is not visible. 1230 // TODO(sandersd): On Android, defer Start() if the tab is not visible.
1413 pipeline_.Start( 1231 bool is_streaming = (data_source_ && data_source_->IsStreaming());
1414 demuxer_.get(), CreateRenderer(), 1232 pipeline_controller_.Start(
1233 chunk_demuxer_, demuxer_.get(), is_streaming,
1415 BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnPipelineEnded), 1234 BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnPipelineEnded),
1416 BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnPipelineError),
1417 BIND_TO_RENDER_LOOP1(&WebMediaPlayerImpl::OnPipelineSeeked, false),
1418 BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnPipelineMetadata), 1235 BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnPipelineMetadata),
1419 BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnPipelineBufferingStateChanged), 1236 BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnPipelineBufferingStateChanged),
1420 BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnDurationChanged), 1237 BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnDurationChanged),
1421 BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnAddTextTrack), 1238 BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnAddTextTrack),
1422 BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnWaitingForDecryptionKey)); 1239 BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnWaitingForDecryptionKey));
1423 } 1240 }
1424 1241
1425 void WebMediaPlayerImpl::SetNetworkState(WebMediaPlayer::NetworkState state) { 1242 void WebMediaPlayerImpl::SetNetworkState(WebMediaPlayer::NetworkState state) {
1426 DVLOG(1) << __FUNCTION__ << "(" << state << ")"; 1243 DVLOG(1) << __FUNCTION__ << "(" << state << ")";
1427 DCHECK(main_task_runner_->BelongsToCurrentThread()); 1244 DCHECK(main_task_runner_->BelongsToCurrentThread());
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after
1515 base::WaitableEvent event(false, false); 1332 base::WaitableEvent event(false, false);
1516 compositor_task_runner_->PostTask(FROM_HERE, 1333 compositor_task_runner_->PostTask(FROM_HERE,
1517 base::Bind(&GetCurrentFrameAndSignal, 1334 base::Bind(&GetCurrentFrameAndSignal,
1518 base::Unretained(compositor_), 1335 base::Unretained(compositor_),
1519 &video_frame, 1336 &video_frame,
1520 &event)); 1337 &event));
1521 event.Wait(); 1338 event.Wait();
1522 return video_frame; 1339 return video_frame;
1523 } 1340 }
1524 1341
1525 void WebMediaPlayerImpl::UpdatePausedTime() {
1526 DCHECK(main_task_runner_->BelongsToCurrentThread());
1527
1528 // pause() may be called after playback has ended and the HTMLMediaElement
1529 // requires that currentTime() == duration() after ending. We want to ensure
1530 // |paused_time_| matches currentTime() in this case or a future seek() may
1531 // incorrectly discard what it thinks is a seek to the existing time.
1532 paused_time_ =
1533 ended_ ? pipeline_.GetMediaDuration() : pipeline_.GetMediaTime();
1534 }
1535
1536 void WebMediaPlayerImpl::NotifyPlaybackStarted() { 1342 void WebMediaPlayerImpl::NotifyPlaybackStarted() {
1537 #if defined(OS_ANDROID) // WMPI_CAST 1343 #if defined(OS_ANDROID) // WMPI_CAST
1538 // We do not tell our delegates about remote playback, because that would 1344 // We do not tell our delegates about remote playback, because that would
1539 // keep the device awake, which is not what we want. 1345 // keep the device awake, which is not what we want.
1540 if (isRemote()) 1346 if (isRemote())
1541 return; 1347 return;
1542 #endif 1348 #endif
1543 1349
1544 // Don't send delegate notifications when suspended; upon suspend we send 1350 // NotifyPlaybackStarted() may be called by interactions while suspended,
1545 // PlayerGone() to the delegate -- no more notifications should be sent until 1351 // (play/pause in particular). Those actions won't have any effect until the
1546 // after resume. 1352 // pipeline is resumed.
1547 if (suspended_) 1353 // TODO(dalecurtis): Should these be dropped at the call sites instead?
1354 // Alternatively, rename this method to include Maybe or Changed, and handle
1355 // multiple calls safely.
1356 if (pipeline_controller_.IsSuspended())
1548 return; 1357 return;
1549 1358
1550 if (delegate_) { 1359 if (delegate_) {
1551 delegate_->DidPlay(delegate_id_, hasVideo(), hasAudio(), false, 1360 delegate_->DidPlay(delegate_id_, hasVideo(), hasAudio(), false,
1552 pipeline_.GetMediaDuration()); 1361 pipeline_.GetMediaDuration());
1553 } 1362 }
1554 if (!memory_usage_reporting_timer_.IsRunning()) { 1363 if (!memory_usage_reporting_timer_.IsRunning()) {
1555 memory_usage_reporting_timer_.Start(FROM_HERE, 1364 memory_usage_reporting_timer_.Start(FROM_HERE,
1556 base::TimeDelta::FromSeconds(2), this, 1365 base::TimeDelta::FromSeconds(2), this,
1557 &WebMediaPlayerImpl::ReportMemoryUsage); 1366 &WebMediaPlayerImpl::ReportMemoryUsage);
1558 } 1367 }
1559 } 1368 }
1560 1369
1561 void WebMediaPlayerImpl::NotifyPlaybackPaused() { 1370 void WebMediaPlayerImpl::NotifyPlaybackPaused() {
1562 #if defined(OS_ANDROID) // WMPI_CAST 1371 #if defined(OS_ANDROID) // WMPI_CAST
1563 if (isRemote()) 1372 if (isRemote())
1564 return; 1373 return;
1565 #endif 1374 #endif
1566 // Don't send delegate notifications when suspended; upon suspend we send 1375
1567 // PlayerGone() to the delegate -- no more notifications should be sent until 1376 // Same as above, NotifyPlaybackPaused() may be called by interactions while
1568 // after resume. 1377 // suspended, but those actions won't have any effect until the pipeline is
1569 if (!suspended_ && delegate_) 1378 // resumed.
1379 if (pipeline_controller_.IsSuspended())
1380 return;
1381
1382 if (delegate_)
1570 delegate_->DidPause(delegate_id_, ended_); 1383 delegate_->DidPause(delegate_id_, ended_);
1571 memory_usage_reporting_timer_.Stop(); 1384 memory_usage_reporting_timer_.Stop();
1572 ReportMemoryUsage(); 1385 ReportMemoryUsage();
1573 } 1386 }
1574 1387
1575 void WebMediaPlayerImpl::ReportMemoryUsage() { 1388 void WebMediaPlayerImpl::ReportMemoryUsage() {
1576 DCHECK(main_task_runner_->BelongsToCurrentThread()); 1389 DCHECK(main_task_runner_->BelongsToCurrentThread());
1577 1390
1578 // About base::Unretained() usage below: We destroy |demuxer_| on the main 1391 // About base::Unretained() usage below: We destroy |demuxer_| on the main
1579 // thread. Before that, however, ~WebMediaPlayerImpl() posts a task to the 1392 // thread. Before that, however, ~WebMediaPlayerImpl() posts a task to the
(...skipping 23 matching lines...) Expand all
1603 << ", Video: " << stats.video_memory_usage << ", DataSource: " 1416 << ", Video: " << stats.video_memory_usage << ", DataSource: "
1604 << (data_source_ ? data_source_->GetMemoryUsage() : 0) 1417 << (data_source_ ? data_source_->GetMemoryUsage() : 0)
1605 << ", Demuxer: " << demuxer_memory_usage; 1418 << ", Demuxer: " << demuxer_memory_usage;
1606 1419
1607 const int64_t delta = current_memory_usage - last_reported_memory_usage_; 1420 const int64_t delta = current_memory_usage - last_reported_memory_usage_;
1608 last_reported_memory_usage_ = current_memory_usage; 1421 last_reported_memory_usage_ = current_memory_usage;
1609 adjust_allocated_memory_cb_.Run(delta); 1422 adjust_allocated_memory_cb_.Run(delta);
1610 } 1423 }
1611 1424
1612 } // namespace media 1425 } // namespace media
OLDNEW
« no previous file with comments | « media/blink/webmediaplayer_impl.h ('k') | media/filters/pipeline_controller.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698