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

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

Issue 284763002: Update AudioRenderer API to fire changes in BufferingState. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: rebase 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
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 394 matching lines...) Expand 10 before | Expand all | Expand 10 after
405 metadata.natural_size = stream->video_decoder_config().natural_size(); 405 metadata.natural_size = stream->video_decoder_config().natural_size();
406 metadata_cb_.Run(metadata); 406 metadata_cb_.Run(metadata);
407 } 407 }
408 408
409 return DoInitialPreroll(done_cb); 409 return DoInitialPreroll(done_cb);
410 410
411 case kPlaying: 411 case kPlaying:
412 PlaybackRateChangedTask(GetPlaybackRate()); 412 PlaybackRateChangedTask(GetPlaybackRate());
413 VolumeChangedTask(GetVolume()); 413 VolumeChangedTask(GetVolume());
414 414
415 // Handle renderers that immediately signal they have enough data.
416 if (!WaitingForEnoughData())
417 StartPlayback();
418
415 // We enter this state from either kInitPrerolling or kSeeking. As of now 419 // We enter this state from either kInitPrerolling or kSeeking. As of now
416 // both those states call Preroll(), which means by time we enter this 420 // both those states call Preroll(), which means by time we enter this
417 // state we've already buffered enough data. Forcefully update the 421 // state we've already buffered enough data. Forcefully update the
418 // buffering state, which start the clock and renderers and transition 422 // buffering state, which start the clock and renderers and transition
419 // into kPlaying state. 423 // into kPlaying state.
420 // 424 //
421 // TODO(scherkus): Remove after renderers are taught to fire buffering 425 // TODO(scherkus): Remove after renderers are taught to fire buffering
422 // state callbacks http://crbug.com/144683 426 // state callbacks http://crbug.com/144683
423 DCHECK(WaitingForEnoughData()); 427 if (video_renderer_) {
424 if (audio_renderer_) 428 DCHECK(WaitingForEnoughData());
425 BufferingStateChanged(&audio_buffering_state_, BUFFERING_HAVE_ENOUGH);
426 if (video_renderer_)
427 BufferingStateChanged(&video_buffering_state_, BUFFERING_HAVE_ENOUGH); 429 BufferingStateChanged(&video_buffering_state_, BUFFERING_HAVE_ENOUGH);
430 }
428 return; 431 return;
429 432
430 case kStopping: 433 case kStopping:
431 case kStopped: 434 case kStopped:
432 case kCreated: 435 case kCreated:
433 case kSeeking: 436 case kSeeking:
434 NOTREACHED() << "State has no transition: " << state_; 437 NOTREACHED() << "State has no transition: " << state_;
435 return; 438 return;
436 } 439 }
437 } 440 }
438 441
439 // Note that the usage of base::Unretained() with the audio/video renderers 442 // Note that the usage of base::Unretained() with the audio/video renderers
440 // in the following DoXXX() functions is considered safe as they are owned by 443 // in the following DoXXX() functions is considered safe as they are owned by
441 // |pending_callbacks_| and share the same lifetime. 444 // |pending_callbacks_| and share the same lifetime.
442 // 445 //
443 // That being said, deleting the renderers while keeping |pending_callbacks_| 446 // That being said, deleting the renderers while keeping |pending_callbacks_|
444 // running on the media thread would result in crashes. 447 // running on the media thread would result in crashes.
445 void Pipeline::DoInitialPreroll(const PipelineStatusCB& done_cb) { 448 void Pipeline::DoInitialPreroll(const PipelineStatusCB& done_cb) {
446 DCHECK(task_runner_->BelongsToCurrentThread()); 449 DCHECK(task_runner_->BelongsToCurrentThread());
447 DCHECK(!pending_callbacks_.get()); 450 DCHECK(!pending_callbacks_.get());
448 SerialRunner::Queue bound_fns; 451 SerialRunner::Queue bound_fns;
449 452
450 base::TimeDelta seek_timestamp = demuxer_->GetStartTime(); 453 base::TimeDelta seek_timestamp = demuxer_->GetStartTime();
451 454
452 // Preroll renderers. 455 // Preroll renderers.
453 if (audio_renderer_) { 456 if (audio_renderer_) {
454 bound_fns.Push(base::Bind( 457 bound_fns.Push(base::Bind(&AudioRenderer::StartPlayingFrom,
455 &AudioRenderer::Preroll, base::Unretained(audio_renderer_.get()), 458 base::Unretained(audio_renderer_.get()),
456 seek_timestamp)); 459 seek_timestamp));
457 } 460 }
458 461
459 if (video_renderer_) { 462 if (video_renderer_) {
460 bound_fns.Push(base::Bind( 463 bound_fns.Push(base::Bind(
461 &VideoRenderer::Preroll, base::Unretained(video_renderer_.get()), 464 &VideoRenderer::Preroll, base::Unretained(video_renderer_.get()),
462 seek_timestamp)); 465 seek_timestamp));
463 466
464 // TODO(scherkus): Remove after VideoRenderer is taught to fire buffering 467 // TODO(scherkus): Remove after VideoRenderer is taught to fire buffering
465 // state callbacks http://crbug.com/144683 468 // state callbacks http://crbug.com/144683
466 bound_fns.Push(base::Bind(&VideoRenderer::Play, 469 bound_fns.Push(base::Bind(&VideoRenderer::Play,
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
515 bound_fns.Push(base::Bind( 518 bound_fns.Push(base::Bind(
516 &TextRenderer::Flush, base::Unretained(text_renderer_.get()))); 519 &TextRenderer::Flush, base::Unretained(text_renderer_.get())));
517 } 520 }
518 521
519 // Seek demuxer. 522 // Seek demuxer.
520 bound_fns.Push(base::Bind( 523 bound_fns.Push(base::Bind(
521 &Demuxer::Seek, base::Unretained(demuxer_), seek_timestamp)); 524 &Demuxer::Seek, base::Unretained(demuxer_), seek_timestamp));
522 525
523 // Preroll renderers. 526 // Preroll renderers.
524 if (audio_renderer_) { 527 if (audio_renderer_) {
525 bound_fns.Push(base::Bind( 528 bound_fns.Push(base::Bind(&AudioRenderer::StartPlayingFrom,
526 &AudioRenderer::Preroll, base::Unretained(audio_renderer_.get()), 529 base::Unretained(audio_renderer_.get()),
527 seek_timestamp)); 530 seek_timestamp));
528 } 531 }
529 532
530 if (video_renderer_) { 533 if (video_renderer_) {
531 bound_fns.Push(base::Bind( 534 bound_fns.Push(base::Bind(
532 &VideoRenderer::Preroll, base::Unretained(video_renderer_.get()), 535 &VideoRenderer::Preroll, base::Unretained(video_renderer_.get()),
533 seek_timestamp)); 536 seek_timestamp));
534 537
535 // TODO(scherkus): Remove after renderers are taught to fire buffering 538 // TODO(scherkus): Remove after renderers are taught to fire buffering
536 // state callbacks http://crbug.com/144683 539 // state callbacks http://crbug.com/144683
537 bound_fns.Push(base::Bind(&VideoRenderer::Play, 540 bound_fns.Push(base::Bind(&VideoRenderer::Play,
(...skipping 312 matching lines...) Expand 10 before | Expand all | Expand 10 after
850 } 853 }
851 854
852 void Pipeline::InitializeAudioRenderer(const PipelineStatusCB& done_cb) { 855 void Pipeline::InitializeAudioRenderer(const PipelineStatusCB& done_cb) {
853 DCHECK(task_runner_->BelongsToCurrentThread()); 856 DCHECK(task_runner_->BelongsToCurrentThread());
854 857
855 audio_renderer_ = filter_collection_->GetAudioRenderer(); 858 audio_renderer_ = filter_collection_->GetAudioRenderer();
856 audio_renderer_->Initialize( 859 audio_renderer_->Initialize(
857 demuxer_->GetStream(DemuxerStream::AUDIO), 860 demuxer_->GetStream(DemuxerStream::AUDIO),
858 done_cb, 861 done_cb,
859 base::Bind(&Pipeline::OnUpdateStatistics, base::Unretained(this)), 862 base::Bind(&Pipeline::OnUpdateStatistics, base::Unretained(this)),
860 base::Bind(&Pipeline::OnAudioUnderflow, base::Unretained(this)),
861 base::Bind(&Pipeline::OnAudioTimeUpdate, base::Unretained(this)), 863 base::Bind(&Pipeline::OnAudioTimeUpdate, base::Unretained(this)),
864 base::Bind(&Pipeline::BufferingStateChanged, base::Unretained(this),
865 &audio_buffering_state_),
862 base::Bind(&Pipeline::OnAudioRendererEnded, base::Unretained(this)), 866 base::Bind(&Pipeline::OnAudioRendererEnded, base::Unretained(this)),
863 base::Bind(&Pipeline::SetError, base::Unretained(this))); 867 base::Bind(&Pipeline::SetError, base::Unretained(this)));
864 } 868 }
865 869
866 void Pipeline::InitializeVideoRenderer(const PipelineStatusCB& done_cb) { 870 void Pipeline::InitializeVideoRenderer(const PipelineStatusCB& done_cb) {
867 DCHECK(task_runner_->BelongsToCurrentThread()); 871 DCHECK(task_runner_->BelongsToCurrentThread());
868 872
869 video_renderer_ = filter_collection_->GetVideoRenderer(); 873 video_renderer_ = filter_collection_->GetVideoRenderer();
870 video_renderer_->Initialize( 874 video_renderer_->Initialize(
871 demuxer_->GetStream(DemuxerStream::VIDEO), 875 demuxer_->GetStream(DemuxerStream::VIDEO),
872 demuxer_->GetLiveness() == Demuxer::LIVENESS_LIVE, 876 demuxer_->GetLiveness() == Demuxer::LIVENESS_LIVE,
873 done_cb, 877 done_cb,
874 base::Bind(&Pipeline::OnUpdateStatistics, base::Unretained(this)), 878 base::Bind(&Pipeline::OnUpdateStatistics, base::Unretained(this)),
875 base::Bind(&Pipeline::OnVideoTimeUpdate, base::Unretained(this)), 879 base::Bind(&Pipeline::OnVideoTimeUpdate, base::Unretained(this)),
876 base::Bind(&Pipeline::OnVideoRendererEnded, base::Unretained(this)), 880 base::Bind(&Pipeline::OnVideoRendererEnded, base::Unretained(this)),
877 base::Bind(&Pipeline::SetError, base::Unretained(this)), 881 base::Bind(&Pipeline::SetError, base::Unretained(this)),
878 base::Bind(&Pipeline::GetMediaTime, base::Unretained(this)), 882 base::Bind(&Pipeline::GetMediaTime, base::Unretained(this)),
879 base::Bind(&Pipeline::GetMediaDuration, base::Unretained(this))); 883 base::Bind(&Pipeline::GetMediaDuration, base::Unretained(this)));
880 } 884 }
881 885
882 void Pipeline::OnAudioUnderflow() {
883 if (!task_runner_->BelongsToCurrentThread()) {
884 task_runner_->PostTask(FROM_HERE, base::Bind(
885 &Pipeline::OnAudioUnderflow, base::Unretained(this)));
886 return;
887 }
888
889 if (state_ != kPlaying)
890 return;
891
892 if (audio_renderer_)
893 audio_renderer_->ResumeAfterUnderflow();
894 }
895
896 void Pipeline::BufferingStateChanged(BufferingState* buffering_state, 886 void Pipeline::BufferingStateChanged(BufferingState* buffering_state,
897 BufferingState new_buffering_state) { 887 BufferingState new_buffering_state) {
898 DVLOG(1) << __FUNCTION__ << "(" << *buffering_state << ", " 888 DVLOG(1) << __FUNCTION__ << "(" << *buffering_state << ", "
899 << " " << new_buffering_state << ") " 889 << " " << new_buffering_state << ") "
900 << (buffering_state == &audio_buffering_state_ ? "audio" : "video"); 890 << (buffering_state == &audio_buffering_state_ ? "audio" : "video");
901 DCHECK(task_runner_->BelongsToCurrentThread()); 891 DCHECK(task_runner_->BelongsToCurrentThread());
902 bool was_waiting_for_enough_data = WaitingForEnoughData(); 892 bool was_waiting_for_enough_data = WaitingForEnoughData();
903 *buffering_state = new_buffering_state; 893 *buffering_state = new_buffering_state;
904 894
905 // Renderer underflowed. 895 // Renderer underflowed.
906 if (!was_waiting_for_enough_data && WaitingForEnoughData()) { 896 if (!was_waiting_for_enough_data && WaitingForEnoughData()) {
907 StartWaitingForEnoughData(); 897 PausePlayback();
908 return; 898 return;
909 } 899 }
910 900
911 // Renderer prerolled. 901 // Renderer prerolled.
912 if (was_waiting_for_enough_data && !WaitingForEnoughData()) { 902 if (was_waiting_for_enough_data && !WaitingForEnoughData()) {
913 StartPlayback(); 903 StartPlayback();
914 return; 904 return;
915 } 905 }
916 } 906 }
917 907
918 bool Pipeline::WaitingForEnoughData() const { 908 bool Pipeline::WaitingForEnoughData() const {
919 DCHECK(task_runner_->BelongsToCurrentThread()); 909 DCHECK(task_runner_->BelongsToCurrentThread());
920 if (state_ != kPlaying) 910 if (state_ != kPlaying)
921 return false; 911 return false;
922 if (audio_renderer_ && audio_buffering_state_ != BUFFERING_HAVE_ENOUGH) 912 if (audio_renderer_ && audio_buffering_state_ != BUFFERING_HAVE_ENOUGH)
923 return true; 913 return true;
924 if (video_renderer_ && video_buffering_state_ != BUFFERING_HAVE_ENOUGH) 914 if (video_renderer_ && video_buffering_state_ != BUFFERING_HAVE_ENOUGH)
925 return true; 915 return true;
926 return false; 916 return false;
927 } 917 }
928 918
929 void Pipeline::StartWaitingForEnoughData() { 919 void Pipeline::PausePlayback() {
930 DVLOG(1) << __FUNCTION__; 920 DVLOG(1) << __FUNCTION__;
931 DCHECK_EQ(state_, kPlaying); 921 DCHECK_EQ(state_, kPlaying);
932 DCHECK(WaitingForEnoughData()); 922 DCHECK(WaitingForEnoughData());
923 DCHECK(task_runner_->BelongsToCurrentThread());
933 924
934 if (audio_renderer_) 925 if (audio_renderer_)
935 audio_renderer_->StopRendering(); 926 audio_renderer_->StopRendering();
936 927
937 base::AutoLock auto_lock(lock_); 928 base::AutoLock auto_lock(lock_);
938 clock_->Pause(); 929 clock_->Pause();
939 } 930 }
940 931
941 void Pipeline::StartPlayback() { 932 void Pipeline::StartPlayback() {
942 DVLOG(1) << __FUNCTION__; 933 DVLOG(1) << __FUNCTION__;
943 DCHECK_EQ(state_, kPlaying); 934 DCHECK_EQ(state_, kPlaying);
944 DCHECK(!WaitingForEnoughData()); 935 DCHECK(!WaitingForEnoughData());
936 DCHECK(task_runner_->BelongsToCurrentThread());
945 937
946 if (audio_renderer_) { 938 if (audio_renderer_) {
947 // We use audio stream to update the clock. So if there is such a 939 // We use audio stream to update the clock. So if there is such a
948 // stream, we pause the clock until we receive a valid timestamp. 940 // stream, we pause the clock until we receive a valid timestamp.
949 base::AutoLock auto_lock(lock_); 941 base::AutoLock auto_lock(lock_);
950 waiting_for_clock_update_ = true; 942 waiting_for_clock_update_ = true;
951 audio_renderer_->StartRendering(); 943 audio_renderer_->StartRendering();
952 } else { 944 } else {
953 base::AutoLock auto_lock(lock_); 945 base::AutoLock auto_lock(lock_);
954 DCHECK(!waiting_for_clock_update_); 946 DCHECK(!waiting_for_clock_update_);
955 clock_->SetMaxTime(clock_->Duration()); 947 clock_->SetMaxTime(clock_->Duration());
956 clock_->Play(); 948 clock_->Play();
957 } 949 }
958 950
959 preroll_completed_cb_.Run(); 951 preroll_completed_cb_.Run();
960 if (!seek_cb_.is_null()) 952 if (!seek_cb_.is_null())
961 base::ResetAndReturn(&seek_cb_).Run(PIPELINE_OK); 953 base::ResetAndReturn(&seek_cb_).Run(PIPELINE_OK);
962 } 954 }
963 955
964 void Pipeline::StartClockIfWaitingForTimeUpdate_Locked() { 956 void Pipeline::StartClockIfWaitingForTimeUpdate_Locked() {
965 lock_.AssertAcquired(); 957 lock_.AssertAcquired();
966 if (!waiting_for_clock_update_) 958 if (!waiting_for_clock_update_)
967 return; 959 return;
968 960
969 waiting_for_clock_update_ = false; 961 waiting_for_clock_update_ = false;
970 clock_->Play(); 962 clock_->Play();
971 } 963 }
972 964
973 } // namespace media 965 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698