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

Side by Side Diff: media/base/pipeline.cc

Issue 291093013: Revert of Update AudioRenderer API to fire changes in BufferingState. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 6 years, 7 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 | Annotate | Revision Log
« no previous file with comments | « media/base/pipeline.h ('k') | media/base/pipeline_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 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/base/pipeline.h" 5 #include "media/base/pipeline.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 8
9 #include "base/bind.h" 9 #include "base/bind.h"
10 #include "base/callback.h" 10 #include "base/callback.h"
(...skipping 396 matching lines...) Expand 10 before | Expand all | Expand 10 after
407 metadata.natural_size = stream->video_decoder_config().natural_size(); 407 metadata.natural_size = stream->video_decoder_config().natural_size();
408 metadata_cb_.Run(metadata); 408 metadata_cb_.Run(metadata);
409 } 409 }
410 410
411 return DoInitialPreroll(done_cb); 411 return DoInitialPreroll(done_cb);
412 412
413 case kPlaying: 413 case kPlaying:
414 PlaybackRateChangedTask(GetPlaybackRate()); 414 PlaybackRateChangedTask(GetPlaybackRate());
415 VolumeChangedTask(GetVolume()); 415 VolumeChangedTask(GetVolume());
416 416
417 // Handle renderers that immediately signal they have enough data.
418 if (!WaitingForEnoughData())
419 StartPlayback();
420
421 // We enter this state from either kInitPrerolling or kSeeking. As of now 417 // We enter this state from either kInitPrerolling or kSeeking. As of now
422 // both those states call Preroll(), which means by time we enter this 418 // both those states call Preroll(), which means by time we enter this
423 // state we've already buffered enough data. Forcefully update the 419 // state we've already buffered enough data. Forcefully update the
424 // buffering state, which start the clock and renderers and transition 420 // buffering state, which start the clock and renderers and transition
425 // into kPlaying state. 421 // into kPlaying state.
426 // 422 //
427 // TODO(scherkus): Remove after renderers are taught to fire buffering 423 // TODO(scherkus): Remove after renderers are taught to fire buffering
428 // state callbacks http://crbug.com/144683 424 // state callbacks http://crbug.com/144683
429 if (video_renderer_) { 425 DCHECK(WaitingForEnoughData());
430 DCHECK(WaitingForEnoughData()); 426 if (audio_renderer_)
427 BufferingStateChanged(&audio_buffering_state_, BUFFERING_HAVE_ENOUGH);
428 if (video_renderer_)
431 BufferingStateChanged(&video_buffering_state_, BUFFERING_HAVE_ENOUGH); 429 BufferingStateChanged(&video_buffering_state_, BUFFERING_HAVE_ENOUGH);
432 }
433 return; 430 return;
434 431
435 case kStopping: 432 case kStopping:
436 case kStopped: 433 case kStopped:
437 case kCreated: 434 case kCreated:
438 case kSeeking: 435 case kSeeking:
439 NOTREACHED() << "State has no transition: " << state_; 436 NOTREACHED() << "State has no transition: " << state_;
440 return; 437 return;
441 } 438 }
442 } 439 }
443 440
444 // Note that the usage of base::Unretained() with the audio/video renderers 441 // Note that the usage of base::Unretained() with the audio/video renderers
445 // in the following DoXXX() functions is considered safe as they are owned by 442 // in the following DoXXX() functions is considered safe as they are owned by
446 // |pending_callbacks_| and share the same lifetime. 443 // |pending_callbacks_| and share the same lifetime.
447 // 444 //
448 // That being said, deleting the renderers while keeping |pending_callbacks_| 445 // That being said, deleting the renderers while keeping |pending_callbacks_|
449 // running on the media thread would result in crashes. 446 // running on the media thread would result in crashes.
450 void Pipeline::DoInitialPreroll(const PipelineStatusCB& done_cb) { 447 void Pipeline::DoInitialPreroll(const PipelineStatusCB& done_cb) {
451 DCHECK(task_runner_->BelongsToCurrentThread()); 448 DCHECK(task_runner_->BelongsToCurrentThread());
452 DCHECK(!pending_callbacks_.get()); 449 DCHECK(!pending_callbacks_.get());
453 SerialRunner::Queue bound_fns; 450 SerialRunner::Queue bound_fns;
454 451
455 base::TimeDelta seek_timestamp = demuxer_->GetStartTime(); 452 base::TimeDelta seek_timestamp = demuxer_->GetStartTime();
456 453
457 // Preroll renderers. 454 // Preroll renderers.
458 if (audio_renderer_) { 455 if (audio_renderer_) {
459 bound_fns.Push(base::Bind(&AudioRenderer::StartPlayingFrom, 456 bound_fns.Push(base::Bind(
460 base::Unretained(audio_renderer_.get()), 457 &AudioRenderer::Preroll, base::Unretained(audio_renderer_.get()),
461 seek_timestamp)); 458 seek_timestamp));
462 } 459 }
463 460
464 if (video_renderer_) { 461 if (video_renderer_) {
465 bound_fns.Push(base::Bind( 462 bound_fns.Push(base::Bind(
466 &VideoRenderer::Preroll, base::Unretained(video_renderer_.get()), 463 &VideoRenderer::Preroll, base::Unretained(video_renderer_.get()),
467 seek_timestamp)); 464 seek_timestamp));
468 465
469 // TODO(scherkus): Remove after VideoRenderer is taught to fire buffering 466 // TODO(scherkus): Remove after VideoRenderer is taught to fire buffering
470 // state callbacks http://crbug.com/144683 467 // state callbacks http://crbug.com/144683
471 bound_fns.Push(base::Bind(&VideoRenderer::Play, 468 bound_fns.Push(base::Bind(&VideoRenderer::Play,
472 base::Unretained(video_renderer_.get()))); 469 base::Unretained(video_renderer_.get())));
473 } 470 }
474 471
475 if (text_renderer_) { 472 if (text_renderer_) {
476 bound_fns.Push(base::Bind( 473 bound_fns.Push(base::Bind(
477 &TextRenderer::Play, base::Unretained(text_renderer_.get()))); 474 &TextRenderer::Play, base::Unretained(text_renderer_.get())));
478 } 475 }
479 476
480 pending_callbacks_ = SerialRunner::Run(bound_fns, done_cb); 477 pending_callbacks_ = SerialRunner::Run(bound_fns, done_cb);
481 } 478 }
482 479
483 #if DCHECK_IS_ON
484 static void VerifyBufferingStates(BufferingState* audio_buffering_state,
485 BufferingState* video_buffering_state) {
486 DCHECK_EQ(*audio_buffering_state, BUFFERING_HAVE_NOTHING);
487 DCHECK_EQ(*video_buffering_state, BUFFERING_HAVE_NOTHING);
488 }
489 #endif
490
491 void Pipeline::DoSeek( 480 void Pipeline::DoSeek(
492 base::TimeDelta seek_timestamp, 481 base::TimeDelta seek_timestamp,
493 const PipelineStatusCB& done_cb) { 482 const PipelineStatusCB& done_cb) {
494 DCHECK(task_runner_->BelongsToCurrentThread()); 483 DCHECK(task_runner_->BelongsToCurrentThread());
495 DCHECK(!pending_callbacks_.get()); 484 DCHECK(!pending_callbacks_.get());
496 SerialRunner::Queue bound_fns; 485 SerialRunner::Queue bound_fns;
497 486
498 // Pause. 487 // Pause.
499 if (text_renderer_) { 488 if (text_renderer_) {
500 bound_fns.Push(base::Bind( 489 bound_fns.Push(base::Bind(
501 &TextRenderer::Pause, base::Unretained(text_renderer_.get()))); 490 &TextRenderer::Pause, base::Unretained(text_renderer_.get())));
502 } 491 }
503 492
504 // Flush. 493 // Flush.
505 if (audio_renderer_) { 494 if (audio_renderer_) {
506 bound_fns.Push(base::Bind( 495 bound_fns.Push(base::Bind(
507 &AudioRenderer::Flush, base::Unretained(audio_renderer_.get()))); 496 &AudioRenderer::Flush, base::Unretained(audio_renderer_.get())));
497
498 // TODO(scherkus): Remove after AudioRenderer is taught to fire buffering
499 // state callbacks http://crbug.com/144683
500 bound_fns.Push(base::Bind(&Pipeline::BufferingStateChanged,
501 base::Unretained(this),
502 &audio_buffering_state_,
503 BUFFERING_HAVE_NOTHING));
508 } 504 }
509
510 if (video_renderer_) { 505 if (video_renderer_) {
511 bound_fns.Push(base::Bind( 506 bound_fns.Push(base::Bind(
512 &VideoRenderer::Flush, base::Unretained(video_renderer_.get()))); 507 &VideoRenderer::Flush, base::Unretained(video_renderer_.get())));
513 508
514 // TODO(scherkus): Remove after VideoRenderer is taught to fire buffering 509 // TODO(scherkus): Remove after VideoRenderer is taught to fire buffering
515 // state callbacks http://crbug.com/144683 510 // state callbacks http://crbug.com/144683
516 bound_fns.Push(base::Bind(&Pipeline::BufferingStateChanged, 511 bound_fns.Push(base::Bind(&Pipeline::BufferingStateChanged,
517 base::Unretained(this), 512 base::Unretained(this),
518 &video_buffering_state_, 513 &video_buffering_state_,
519 BUFFERING_HAVE_NOTHING)); 514 BUFFERING_HAVE_NOTHING));
520 } 515 }
521
522 #if DCHECK_IS_ON
523 // Verify renderers reset their buffering states.
524 bound_fns.Push(base::Bind(&VerifyBufferingStates,
525 &audio_buffering_state_,
526 &video_buffering_state_));
527 #endif
528
529 if (text_renderer_) { 516 if (text_renderer_) {
530 bound_fns.Push(base::Bind( 517 bound_fns.Push(base::Bind(
531 &TextRenderer::Flush, base::Unretained(text_renderer_.get()))); 518 &TextRenderer::Flush, base::Unretained(text_renderer_.get())));
532 } 519 }
533 520
534 // Seek demuxer. 521 // Seek demuxer.
535 bound_fns.Push(base::Bind( 522 bound_fns.Push(base::Bind(
536 &Demuxer::Seek, base::Unretained(demuxer_), seek_timestamp)); 523 &Demuxer::Seek, base::Unretained(demuxer_), seek_timestamp));
537 524
538 // Preroll renderers. 525 // Preroll renderers.
539 if (audio_renderer_) { 526 if (audio_renderer_) {
540 bound_fns.Push(base::Bind(&AudioRenderer::StartPlayingFrom, 527 bound_fns.Push(base::Bind(
541 base::Unretained(audio_renderer_.get()), 528 &AudioRenderer::Preroll, base::Unretained(audio_renderer_.get()),
542 seek_timestamp)); 529 seek_timestamp));
543 } 530 }
544 531
545 if (video_renderer_) { 532 if (video_renderer_) {
546 bound_fns.Push(base::Bind( 533 bound_fns.Push(base::Bind(
547 &VideoRenderer::Preroll, base::Unretained(video_renderer_.get()), 534 &VideoRenderer::Preroll, base::Unretained(video_renderer_.get()),
548 seek_timestamp)); 535 seek_timestamp));
549 536
550 // TODO(scherkus): Remove after renderers are taught to fire buffering 537 // TODO(scherkus): Remove after renderers are taught to fire buffering
551 // state callbacks http://crbug.com/144683 538 // state callbacks http://crbug.com/144683
552 bound_fns.Push(base::Bind(&VideoRenderer::Play, 539 bound_fns.Push(base::Bind(&VideoRenderer::Play,
(...skipping 309 matching lines...) Expand 10 before | Expand all | Expand 10 after
862 } 849 }
863 850
864 void Pipeline::InitializeAudioRenderer(const PipelineStatusCB& done_cb) { 851 void Pipeline::InitializeAudioRenderer(const PipelineStatusCB& done_cb) {
865 DCHECK(task_runner_->BelongsToCurrentThread()); 852 DCHECK(task_runner_->BelongsToCurrentThread());
866 853
867 audio_renderer_ = filter_collection_->GetAudioRenderer(); 854 audio_renderer_ = filter_collection_->GetAudioRenderer();
868 audio_renderer_->Initialize( 855 audio_renderer_->Initialize(
869 demuxer_->GetStream(DemuxerStream::AUDIO), 856 demuxer_->GetStream(DemuxerStream::AUDIO),
870 done_cb, 857 done_cb,
871 base::Bind(&Pipeline::OnUpdateStatistics, base::Unretained(this)), 858 base::Bind(&Pipeline::OnUpdateStatistics, base::Unretained(this)),
859 base::Bind(&Pipeline::OnAudioUnderflow, base::Unretained(this)),
872 base::Bind(&Pipeline::OnAudioTimeUpdate, base::Unretained(this)), 860 base::Bind(&Pipeline::OnAudioTimeUpdate, base::Unretained(this)),
873 base::Bind(&Pipeline::BufferingStateChanged, base::Unretained(this),
874 &audio_buffering_state_),
875 base::Bind(&Pipeline::OnAudioRendererEnded, base::Unretained(this)), 861 base::Bind(&Pipeline::OnAudioRendererEnded, base::Unretained(this)),
876 base::Bind(&Pipeline::SetError, base::Unretained(this))); 862 base::Bind(&Pipeline::SetError, base::Unretained(this)));
877 } 863 }
878 864
879 void Pipeline::InitializeVideoRenderer(const PipelineStatusCB& done_cb) { 865 void Pipeline::InitializeVideoRenderer(const PipelineStatusCB& done_cb) {
880 DCHECK(task_runner_->BelongsToCurrentThread()); 866 DCHECK(task_runner_->BelongsToCurrentThread());
881 867
882 video_renderer_ = filter_collection_->GetVideoRenderer(); 868 video_renderer_ = filter_collection_->GetVideoRenderer();
883 video_renderer_->Initialize( 869 video_renderer_->Initialize(
884 demuxer_->GetStream(DemuxerStream::VIDEO), 870 demuxer_->GetStream(DemuxerStream::VIDEO),
885 demuxer_->GetLiveness() == Demuxer::LIVENESS_LIVE, 871 demuxer_->GetLiveness() == Demuxer::LIVENESS_LIVE,
886 done_cb, 872 done_cb,
887 base::Bind(&Pipeline::OnUpdateStatistics, base::Unretained(this)), 873 base::Bind(&Pipeline::OnUpdateStatistics, base::Unretained(this)),
888 base::Bind(&Pipeline::OnVideoTimeUpdate, base::Unretained(this)), 874 base::Bind(&Pipeline::OnVideoTimeUpdate, base::Unretained(this)),
889 base::Bind(&Pipeline::OnVideoRendererEnded, base::Unretained(this)), 875 base::Bind(&Pipeline::OnVideoRendererEnded, base::Unretained(this)),
890 base::Bind(&Pipeline::SetError, base::Unretained(this)), 876 base::Bind(&Pipeline::SetError, base::Unretained(this)),
891 base::Bind(&Pipeline::GetMediaTime, base::Unretained(this)), 877 base::Bind(&Pipeline::GetMediaTime, base::Unretained(this)),
892 base::Bind(&Pipeline::GetMediaDuration, base::Unretained(this))); 878 base::Bind(&Pipeline::GetMediaDuration, base::Unretained(this)));
893 } 879 }
894 880
881 void Pipeline::OnAudioUnderflow() {
882 if (!task_runner_->BelongsToCurrentThread()) {
883 task_runner_->PostTask(FROM_HERE, base::Bind(
884 &Pipeline::OnAudioUnderflow, base::Unretained(this)));
885 return;
886 }
887
888 if (state_ != kPlaying)
889 return;
890
891 if (audio_renderer_)
892 audio_renderer_->ResumeAfterUnderflow();
893 }
894
895 void Pipeline::BufferingStateChanged(BufferingState* buffering_state, 895 void Pipeline::BufferingStateChanged(BufferingState* buffering_state,
896 BufferingState new_buffering_state) { 896 BufferingState new_buffering_state) {
897 DVLOG(1) << __FUNCTION__ << "(" << *buffering_state << ", " 897 DVLOG(1) << __FUNCTION__ << "(" << *buffering_state << ", "
898 << " " << new_buffering_state << ") " 898 << " " << new_buffering_state << ") "
899 << (buffering_state == &audio_buffering_state_ ? "audio" : "video"); 899 << (buffering_state == &audio_buffering_state_ ? "audio" : "video");
900 DCHECK(task_runner_->BelongsToCurrentThread()); 900 DCHECK(task_runner_->BelongsToCurrentThread());
901 bool was_waiting_for_enough_data = WaitingForEnoughData(); 901 bool was_waiting_for_enough_data = WaitingForEnoughData();
902 *buffering_state = new_buffering_state; 902 *buffering_state = new_buffering_state;
903 903
904 // Renderer underflowed. 904 // Renderer underflowed.
905 if (!was_waiting_for_enough_data && WaitingForEnoughData()) { 905 if (!was_waiting_for_enough_data && WaitingForEnoughData()) {
906 PausePlayback(); 906 StartWaitingForEnoughData();
907 return; 907 return;
908 } 908 }
909 909
910 // Renderer prerolled. 910 // Renderer prerolled.
911 if (was_waiting_for_enough_data && !WaitingForEnoughData()) { 911 if (was_waiting_for_enough_data && !WaitingForEnoughData()) {
912 StartPlayback(); 912 StartPlayback();
913 return; 913 return;
914 } 914 }
915 } 915 }
916 916
917 bool Pipeline::WaitingForEnoughData() const { 917 bool Pipeline::WaitingForEnoughData() const {
918 DCHECK(task_runner_->BelongsToCurrentThread()); 918 DCHECK(task_runner_->BelongsToCurrentThread());
919 if (state_ != kPlaying) 919 if (state_ != kPlaying)
920 return false; 920 return false;
921 if (audio_renderer_ && audio_buffering_state_ != BUFFERING_HAVE_ENOUGH) 921 if (audio_renderer_ && audio_buffering_state_ != BUFFERING_HAVE_ENOUGH)
922 return true; 922 return true;
923 if (video_renderer_ && video_buffering_state_ != BUFFERING_HAVE_ENOUGH) 923 if (video_renderer_ && video_buffering_state_ != BUFFERING_HAVE_ENOUGH)
924 return true; 924 return true;
925 return false; 925 return false;
926 } 926 }
927 927
928 void Pipeline::PausePlayback() { 928 void Pipeline::StartWaitingForEnoughData() {
929 DVLOG(1) << __FUNCTION__; 929 DVLOG(1) << __FUNCTION__;
930 DCHECK_EQ(state_, kPlaying); 930 DCHECK_EQ(state_, kPlaying);
931 DCHECK(WaitingForEnoughData()); 931 DCHECK(WaitingForEnoughData());
932 DCHECK(task_runner_->BelongsToCurrentThread());
933 932
934 base::AutoLock auto_lock(lock_); 933 base::AutoLock auto_lock(lock_);
935 PauseClockAndStopRendering_Locked(); 934 PauseClockAndStopRendering_Locked();
936 } 935 }
937 936
938 void Pipeline::StartPlayback() { 937 void Pipeline::StartPlayback() {
939 DVLOG(1) << __FUNCTION__; 938 DVLOG(1) << __FUNCTION__;
940 DCHECK_EQ(state_, kPlaying); 939 DCHECK_EQ(state_, kPlaying);
941 DCHECK_EQ(clock_state_, CLOCK_PAUSED); 940 DCHECK_EQ(clock_state_, CLOCK_PAUSED);
942 DCHECK(!WaitingForEnoughData()); 941 DCHECK(!WaitingForEnoughData());
943 DCHECK(task_runner_->BelongsToCurrentThread());
944 942
945 if (audio_renderer_) { 943 if (audio_renderer_) {
946 // We use audio stream to update the clock. So if there is such a 944 // We use audio stream to update the clock. So if there is such a
947 // stream, we pause the clock until we receive a valid timestamp. 945 // stream, we pause the clock until we receive a valid timestamp.
948 base::AutoLock auto_lock(lock_); 946 base::AutoLock auto_lock(lock_);
949 clock_state_ = CLOCK_WAITING_FOR_AUDIO_TIME_UPDATE; 947 clock_state_ = CLOCK_WAITING_FOR_AUDIO_TIME_UPDATE;
950 audio_renderer_->StartRendering(); 948 audio_renderer_->StartRendering();
951 } else { 949 } else {
952 base::AutoLock auto_lock(lock_); 950 base::AutoLock auto_lock(lock_);
953 clock_state_ = CLOCK_PLAYING; 951 clock_state_ = CLOCK_PLAYING;
(...skipping 29 matching lines...) Expand all
983 void Pipeline::StartClockIfWaitingForTimeUpdate_Locked() { 981 void Pipeline::StartClockIfWaitingForTimeUpdate_Locked() {
984 lock_.AssertAcquired(); 982 lock_.AssertAcquired();
985 if (clock_state_ != CLOCK_WAITING_FOR_AUDIO_TIME_UPDATE) 983 if (clock_state_ != CLOCK_WAITING_FOR_AUDIO_TIME_UPDATE)
986 return; 984 return;
987 985
988 clock_state_ = CLOCK_PLAYING; 986 clock_state_ = CLOCK_PLAYING;
989 clock_->Play(); 987 clock_->Play();
990 } 988 }
991 989
992 } // namespace media 990 } // namespace media
OLDNEW
« no previous file with comments | « media/base/pipeline.h ('k') | media/base/pipeline_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698