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

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

Issue 10753021: Move AudioRenderer out of Filter heirarchy. (Closed) Base URL: svn://chrome-svn/chrome/trunk/src
Patch Set: error_cb Created 8 years, 5 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"
11 #include "base/callback_helpers.h" 11 #include "base/callback_helpers.h"
12 #include "base/compiler_specific.h" 12 #include "base/compiler_specific.h"
13 #include "base/metrics/histogram.h" 13 #include "base/metrics/histogram.h"
14 #include "base/message_loop.h" 14 #include "base/message_loop.h"
15 #include "base/stl_util.h" 15 #include "base/stl_util.h"
16 #include "base/string_util.h" 16 #include "base/string_util.h"
17 #include "base/synchronization/condition_variable.h" 17 #include "base/synchronization/condition_variable.h"
18 #include "media/base/audio_decoder.h" 18 #include "media/base/audio_decoder.h"
19 #include "media/base/audio_renderer.h" 19 #include "media/base/audio_renderer.h"
20 #include "media/base/callback_util.h"
20 #include "media/base/clock.h" 21 #include "media/base/clock.h"
21 #include "media/base/composite_filter.h" 22 #include "media/base/composite_filter.h"
22 #include "media/base/filter_collection.h" 23 #include "media/base/filter_collection.h"
23 #include "media/base/media_log.h" 24 #include "media/base/media_log.h"
24 #include "media/base/video_decoder.h" 25 #include "media/base/video_decoder.h"
25 #include "media/base/video_renderer.h" 26 #include "media/base/video_renderer.h"
26 27
27 using base::TimeDelta; 28 using base::TimeDelta;
28 29
29 namespace media { 30 namespace media {
(...skipping 27 matching lines...) Expand all
57 58
58 media::PipelineStatus PipelineStatusNotification::status() { 59 media::PipelineStatus PipelineStatusNotification::status() {
59 base::AutoLock auto_lock(lock_); 60 base::AutoLock auto_lock(lock_);
60 DCHECK(notified_); 61 DCHECK(notified_);
61 return status_; 62 return status_;
62 } 63 }
63 64
64 struct Pipeline::PipelineInitState { 65 struct Pipeline::PipelineInitState {
65 scoped_refptr<AudioDecoder> audio_decoder; 66 scoped_refptr<AudioDecoder> audio_decoder;
66 scoped_refptr<VideoDecoder> video_decoder; 67 scoped_refptr<VideoDecoder> video_decoder;
67 scoped_refptr<AudioRenderer> audio_renderer;
68 scoped_refptr<VideoRenderer> video_renderer; 68 scoped_refptr<VideoRenderer> video_renderer;
69 scoped_refptr<CompositeFilter> composite; 69 scoped_refptr<CompositeFilter> composite;
70 }; 70 };
71 71
72 Pipeline::Pipeline(MessageLoop* message_loop, MediaLog* media_log) 72 Pipeline::Pipeline(MessageLoop* message_loop, MediaLog* media_log)
73 : message_loop_(message_loop->message_loop_proxy()), 73 : message_loop_(message_loop->message_loop_proxy()),
74 media_log_(media_log), 74 media_log_(media_log),
75 clock_(new Clock(&base::Time::Now)), 75 clock_(new Clock(&base::Time::Now)),
76 waiting_for_clock_update_(false), 76 waiting_for_clock_update_(false),
77 state_(kCreated), 77 state_(kCreated),
(...skipping 232 matching lines...) Expand 10 before | Expand all | Expand 10 after
310 DCHECK(message_loop_->BelongsToCurrentThread()); 310 DCHECK(message_loop_->BelongsToCurrentThread());
311 if (!seek_pending_) 311 if (!seek_pending_)
312 return false; 312 return false;
313 DCHECK(kSeeking == state_ || kPausing == state_ || 313 DCHECK(kSeeking == state_ || kPausing == state_ ||
314 kFlushing == state_ || kStarting == state_) 314 kFlushing == state_ || kStarting == state_)
315 << "Current state : " << state_; 315 << "Current state : " << state_;
316 return true; 316 return true;
317 } 317 }
318 318
319 void Pipeline::ReportStatus(const PipelineStatusCB& cb, PipelineStatus status) { 319 void Pipeline::ReportStatus(const PipelineStatusCB& cb, PipelineStatus status) {
320 DCHECK(message_loop_->BelongsToCurrentThread());
320 if (cb.is_null()) 321 if (cb.is_null())
321 return; 322 return;
322 cb.Run(status); 323 cb.Run(status);
323 // Prevent double-reporting of errors to clients. 324 // Prevent double-reporting of errors to clients.
324 if (status != PIPELINE_OK) 325 if (status != PIPELINE_OK)
325 error_cb_.Reset(); 326 error_cb_.Reset();
326 } 327 }
327 328
328 void Pipeline::FinishInitialization() { 329 void Pipeline::FinishInitialization() {
329 DCHECK(message_loop_->BelongsToCurrentThread()); 330 DCHECK(message_loop_->BelongsToCurrentThread());
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
383 TimeDelta Pipeline::GetTime() const { 384 TimeDelta Pipeline::GetTime() const {
384 DCHECK(IsRunning()); 385 DCHECK(IsRunning());
385 return GetCurrentTime(); 386 return GetCurrentTime();
386 } 387 }
387 388
388 TimeDelta Pipeline::GetDuration() const { 389 TimeDelta Pipeline::GetDuration() const {
389 DCHECK(IsRunning()); 390 DCHECK(IsRunning());
390 return GetMediaDuration(); 391 return GetMediaDuration();
391 } 392 }
392 393
394 void Pipeline::OnAudioDisabled() {
395 DCHECK(IsRunning());
396 message_loop_->PostTask(FROM_HERE, base::Bind(
397 &Pipeline::AudioDisabledTask, this));
398 media_log_->AddEvent(
399 media_log_->CreateEvent(MediaLogEvent::AUDIO_RENDERER_DISABLED));
400 }
401
393 void Pipeline::OnAudioTimeUpdate(TimeDelta time, TimeDelta max_time) { 402 void Pipeline::OnAudioTimeUpdate(TimeDelta time, TimeDelta max_time) {
394 DCHECK(time <= max_time); 403 DCHECK(time <= max_time);
395 DCHECK(IsRunning()); 404 DCHECK(IsRunning());
396 base::AutoLock auto_lock(lock_); 405 base::AutoLock auto_lock(lock_);
397 406
398 if (!has_audio_) 407 if (!has_audio_)
399 return; 408 return;
400 if (waiting_for_clock_update_ && time < clock_->Elapsed()) 409 if (waiting_for_clock_update_ && time < clock_->Elapsed())
401 return; 410 return;
402 411
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
453 // Since the byte->time calculation is approximate, fudge the beginning & 462 // Since the byte->time calculation is approximate, fudge the beginning &
454 // ending areas to look better. 463 // ending areas to look better.
455 TimeDelta epsilon = clock_->Duration() / 100; 464 TimeDelta epsilon = clock_->Duration() / 100;
456 if (time_offset < epsilon) 465 if (time_offset < epsilon)
457 return TimeDelta(); 466 return TimeDelta();
458 if (time_offset + epsilon > clock_->Duration()) 467 if (time_offset + epsilon > clock_->Duration())
459 return clock_->Duration(); 468 return clock_->Duration();
460 return time_offset; 469 return time_offset;
461 } 470 }
462 471
472 void Pipeline::DoPause(const base::Closure& done_cb) {
473 DCHECK(message_loop_->BelongsToCurrentThread());
474 scoped_ptr<std::queue<ClosureFunc> > closures(new std::queue<ClosureFunc>);
475
476 if (audio_renderer_)
477 closures->push(base::Bind(&AudioRenderer::Pause, audio_renderer_));
478
479 if (pipeline_filter_)
480 closures->push(base::Bind(&Filter::Pause, pipeline_filter_));
481
482 RunInSeries(closures.Pass(), done_cb);
483 }
484
485 void Pipeline::DoFlush(const base::Closure& done_cb) {
486 DCHECK(message_loop_->BelongsToCurrentThread());
487 scoped_ptr<std::queue<ClosureFunc> > closures(new std::queue<ClosureFunc>);
488
489 if (audio_renderer_)
490 closures->push(base::Bind(&AudioRenderer::Flush, audio_renderer_));
491
492 if (pipeline_filter_)
493 closures->push(base::Bind(&Filter::Flush, pipeline_filter_));
494
495 RunInParallel(closures.Pass(), done_cb);
496 }
497
498 void Pipeline::DoPlay(const base::Closure& done_cb) {
499 DCHECK(message_loop_->BelongsToCurrentThread());
500 scoped_ptr<std::queue<ClosureFunc> > closures(new std::queue<ClosureFunc>);
501
502 if (audio_renderer_)
503 closures->push(base::Bind(&AudioRenderer::Play, audio_renderer_));
504
505 if (pipeline_filter_)
506 closures->push(base::Bind(&Filter::Play, pipeline_filter_));
507
508 RunInSeries(closures.Pass(), done_cb);
509 }
510
511 void Pipeline::DoStop(const base::Closure& done_cb) {
512 DCHECK(message_loop_->BelongsToCurrentThread());
513 scoped_ptr<std::queue<ClosureFunc> > closures(new std::queue<ClosureFunc>);
514
515 if (demuxer_)
516 closures->push(base::Bind(&Demuxer::Stop, demuxer_));
517
518 if (audio_renderer_)
519 closures->push(base::Bind(&AudioRenderer::Stop, audio_renderer_));
520
521 if (pipeline_filter_)
522 closures->push(base::Bind(&Filter::Stop, pipeline_filter_));
523
524 RunInSeries(closures.Pass(), done_cb);
525 }
526
463 void Pipeline::AddBufferedByteRange(int64 start, int64 end) { 527 void Pipeline::AddBufferedByteRange(int64 start, int64 end) {
464 DCHECK(IsRunning()); 528 DCHECK(IsRunning());
465 base::AutoLock auto_lock(lock_); 529 base::AutoLock auto_lock(lock_);
466 buffered_byte_ranges_.Add(start, end); 530 buffered_byte_ranges_.Add(start, end);
467 did_loading_progress_ = true; 531 did_loading_progress_ = true;
468 } 532 }
469 533
470 void Pipeline::AddBufferedTimeRange(base::TimeDelta start, 534 void Pipeline::AddBufferedTimeRange(base::TimeDelta start,
471 base::TimeDelta end) { 535 base::TimeDelta end) {
472 DCHECK(IsRunning()); 536 DCHECK(IsRunning());
(...skipping 11 matching lines...) Expand all
484 natural_size_ = size; 548 natural_size_ = size;
485 } 549 }
486 550
487 void Pipeline::NotifyEnded() { 551 void Pipeline::NotifyEnded() {
488 DCHECK(IsRunning()); 552 DCHECK(IsRunning());
489 message_loop_->PostTask(FROM_HERE, base::Bind( 553 message_loop_->PostTask(FROM_HERE, base::Bind(
490 &Pipeline::NotifyEndedTask, this)); 554 &Pipeline::NotifyEndedTask, this));
491 media_log_->AddEvent(media_log_->CreateEvent(MediaLogEvent::ENDED)); 555 media_log_->AddEvent(media_log_->CreateEvent(MediaLogEvent::ENDED));
492 } 556 }
493 557
494 void Pipeline::DisableAudioRenderer() {
495 DCHECK(IsRunning());
496
497 // Disable renderer on the message loop.
498 message_loop_->PostTask(FROM_HERE, base::Bind(
499 &Pipeline::DisableAudioRendererTask, this));
500 media_log_->AddEvent(
501 media_log_->CreateEvent(MediaLogEvent::AUDIO_RENDERER_DISABLED));
502 }
503
504 // Called from any thread. 558 // Called from any thread.
505 void Pipeline::OnFilterInitialize(PipelineStatus status) { 559 void Pipeline::OnFilterInitialize(PipelineStatus status) {
506 // Continue the initialize task by proceeding to the next stage. 560 // Continue the initialize task by proceeding to the next stage.
507 message_loop_->PostTask(FROM_HERE, base::Bind( 561 message_loop_->PostTask(FROM_HERE, base::Bind(
508 &Pipeline::InitializeTask, this, status)); 562 &Pipeline::InitializeTask, this, status));
509 } 563 }
510 564
511 // Called from any thread. 565 // Called from any thread.
512 void Pipeline::OnFilterStateTransition() { 566 void Pipeline::OnFilterStateTransition() {
513 message_loop_->PostTask(FROM_HERE, base::Bind( 567 message_loop_->PostTask(FROM_HERE, base::Bind(
(...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after
651 pipeline_filter_ = pipeline_init_state_->composite; 705 pipeline_filter_ = pipeline_init_state_->composite;
652 706
653 // Clear init state since we're done initializing. 707 // Clear init state since we're done initializing.
654 pipeline_init_state_.reset(); 708 pipeline_init_state_.reset();
655 709
656 // Initialization was successful, we are now considered paused, so it's safe 710 // Initialization was successful, we are now considered paused, so it's safe
657 // to set the initial playback rate and volume. 711 // to set the initial playback rate and volume.
658 PlaybackRateChangedTask(GetPlaybackRate()); 712 PlaybackRateChangedTask(GetPlaybackRate());
659 VolumeChangedTask(GetVolume()); 713 VolumeChangedTask(GetVolume());
660 714
661 // Fire a seek request to get the renderers to preroll. We don't need to 715 // Fire a seek request to get the renderers to preroll. We can skip a seek
662 // tell the demuxer to seek since it should already be at the start. 716 // here as the demuxer should be at the start of the stream.
663 seek_pending_ = true; 717 seek_pending_ = true;
664 SetState(kSeeking); 718 SetState(kSeeking);
665 seek_timestamp_ = demuxer_->GetStartTime(); 719 seek_timestamp_ = demuxer_->GetStartTime();
666 OnDemuxerSeekDone(seek_timestamp_, PIPELINE_OK); 720 DoSeek(seek_timestamp_, true,
721 base::Bind(&Pipeline::OnFilterStateTransitionWithStatus, this));
667 } 722 }
668 } 723 }
669 724
670 // This method is called as a result of the client calling Pipeline::Stop() or 725 // This method is called as a result of the client calling Pipeline::Stop() or
671 // as the result of an error condition. 726 // as the result of an error condition.
672 // We stop the filters in the reverse order. 727 // We stop the filters in the reverse order.
673 // 728 //
674 // TODO(scherkus): beware! this can get posted multiple times since we post 729 // TODO(scherkus): beware! this can get posted multiple times since we post
675 // Stop() tasks even if we've already stopped. Perhaps this should no-op for 730 // Stop() tasks even if we've already stopped. Perhaps this should no-op for
676 // additional calls, however most of this logic will be changing. 731 // additional calls, however most of this logic will be changing.
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
745 800
746 { 801 {
747 base::AutoLock auto_lock(lock_); 802 base::AutoLock auto_lock(lock_);
748 clock_->SetPlaybackRate(playback_rate); 803 clock_->SetPlaybackRate(playback_rate);
749 } 804 }
750 805
751 // Notify |pipeline_filter_| if it has been initialized. If initialization 806 // Notify |pipeline_filter_| if it has been initialized. If initialization
752 // hasn't completed yet, the playback rate will be set when initialization 807 // hasn't completed yet, the playback rate will be set when initialization
753 // completes. 808 // completes.
754 if (pipeline_filter_) { 809 if (pipeline_filter_) {
755 DCHECK(demuxer_);
756 demuxer_->SetPlaybackRate(playback_rate); 810 demuxer_->SetPlaybackRate(playback_rate);
757 pipeline_filter_->SetPlaybackRate(playback_rate); 811 pipeline_filter_->SetPlaybackRate(playback_rate);
812
813 if (audio_renderer_)
814 audio_renderer_->SetPlaybackRate(playback_rate_);
758 } 815 }
759 } 816 }
760 817
761 void Pipeline::VolumeChangedTask(float volume) { 818 void Pipeline::VolumeChangedTask(float volume) {
762 DCHECK(message_loop_->BelongsToCurrentThread()); 819 DCHECK(message_loop_->BelongsToCurrentThread());
763 if (!running_ || tearing_down_) 820 if (!running_ || tearing_down_)
764 return; 821 return;
765 822
766 if (audio_renderer_) 823 if (audio_renderer_)
767 audio_renderer_->SetVolume(volume); 824 audio_renderer_->SetVolume(volume);
(...skipping 25 matching lines...) Expand all
793 SetState(kPausing); 850 SetState(kPausing);
794 seek_timestamp_ = std::max(time, demuxer_->GetStartTime()); 851 seek_timestamp_ = std::max(time, demuxer_->GetStartTime());
795 seek_cb_ = seek_cb; 852 seek_cb_ = seek_cb;
796 853
797 // Kick off seeking! 854 // Kick off seeking!
798 { 855 {
799 base::AutoLock auto_lock(lock_); 856 base::AutoLock auto_lock(lock_);
800 if (clock_->IsPlaying()) 857 if (clock_->IsPlaying())
801 clock_->Pause(); 858 clock_->Pause();
802 } 859 }
803 pipeline_filter_->Pause( 860 DoPause(base::Bind(&Pipeline::OnFilterStateTransition, this));
804 base::Bind(&Pipeline::OnFilterStateTransition, this));
805 } 861 }
806 862
807 void Pipeline::NotifyEndedTask() { 863 void Pipeline::NotifyEndedTask() {
808 DCHECK(message_loop_->BelongsToCurrentThread()); 864 DCHECK(message_loop_->BelongsToCurrentThread());
809 865
810 // We can only end if we were actually playing. 866 // We can only end if we were actually playing.
811 if (state_ != kStarted) { 867 if (state_ != kStarted) {
812 return; 868 return;
813 } 869 }
814 870
(...skipping 19 matching lines...) Expand all
834 // Transition to ended, executing the callback if present. 890 // Transition to ended, executing the callback if present.
835 SetState(kEnded); 891 SetState(kEnded);
836 { 892 {
837 base::AutoLock auto_lock(lock_); 893 base::AutoLock auto_lock(lock_);
838 clock_->EndOfStream(); 894 clock_->EndOfStream();
839 } 895 }
840 896
841 ReportStatus(ended_cb_, status_); 897 ReportStatus(ended_cb_, status_);
842 } 898 }
843 899
844 void Pipeline::DisableAudioRendererTask() { 900 void Pipeline::AudioDisabledTask() {
845 DCHECK(message_loop_->BelongsToCurrentThread()); 901 DCHECK(message_loop_->BelongsToCurrentThread());
846 902
847 base::AutoLock auto_lock(lock_); 903 base::AutoLock auto_lock(lock_);
848 has_audio_ = false; 904 has_audio_ = false;
849 audio_disabled_ = true; 905 audio_disabled_ = true;
850 906
851 // Notify our demuxer that we're no longer rendering audio. 907 // Notify our demuxer that we're no longer rendering audio.
852 demuxer_->OnAudioRendererDisabled(); 908 demuxer_->OnAudioRendererDisabled();
853 909
854 // Start clock since there is no more audio to 910 // Start clock since there is no more audio to
(...skipping 26 matching lines...) Expand all
881 // to the next state if needed. 937 // to the next state if needed.
882 SetState(FindNextState(state_)); 938 SetState(FindNextState(state_));
883 if (state_ == kSeeking) { 939 if (state_ == kSeeking) {
884 base::AutoLock auto_lock(lock_); 940 base::AutoLock auto_lock(lock_);
885 clock_->SetTime(seek_timestamp_, seek_timestamp_); 941 clock_->SetTime(seek_timestamp_, seek_timestamp_);
886 } 942 }
887 943
888 // Carry out the action for the current state. 944 // Carry out the action for the current state.
889 if (TransientState(state_)) { 945 if (TransientState(state_)) {
890 if (state_ == kPausing) { 946 if (state_ == kPausing) {
891 pipeline_filter_->Pause( 947 DoPause(base::Bind(&Pipeline::OnFilterStateTransition, this));
892 base::Bind(&Pipeline::OnFilterStateTransition, this));
893 } else if (state_ == kFlushing) { 948 } else if (state_ == kFlushing) {
894 pipeline_filter_->Flush( 949 DoFlush(base::Bind(&Pipeline::OnFilterStateTransition, this));
895 base::Bind(&Pipeline::OnFilterStateTransition, this));
896 } else if (state_ == kSeeking) { 950 } else if (state_ == kSeeking) {
897 DoSeek(seek_timestamp_); 951 DoSeek(seek_timestamp_, false,
952 base::Bind(&Pipeline::OnFilterStateTransitionWithStatus, this));
898 } else if (state_ == kStarting) { 953 } else if (state_ == kStarting) {
899 pipeline_filter_->Play( 954 DoPlay(base::Bind(&Pipeline::OnFilterStateTransition, this));
900 base::Bind(&Pipeline::OnFilterStateTransition, this));
901 } else if (state_ == kStopping) { 955 } else if (state_ == kStopping) {
902 DoStop(base::Bind(&Pipeline::OnFilterStateTransition, this)); 956 DoStop(base::Bind(&Pipeline::OnFilterStateTransition, this));
903 } else { 957 } else {
904 NOTREACHED() << "Unexpected state: " << state_; 958 NOTREACHED() << "Unexpected state: " << state_;
905 } 959 }
906 } else if (state_ == kStarted) { 960 } else if (state_ == kStarted) {
907 FinishInitialization(); 961 FinishInitialization();
908 962
909 // Finally, complete the seek. 963 // Finally, complete the seek.
910 seek_pending_ = false; 964 seek_pending_ = false;
(...skipping 25 matching lines...) Expand all
936 990
937 void Pipeline::TeardownStateTransitionTask() { 991 void Pipeline::TeardownStateTransitionTask() {
938 DCHECK(IsPipelineTearingDown()); 992 DCHECK(IsPipelineTearingDown());
939 switch (state_) { 993 switch (state_) {
940 case kStopping: 994 case kStopping:
941 SetState(error_caused_teardown_ ? kError : kStopped); 995 SetState(error_caused_teardown_ ? kError : kStopped);
942 FinishDestroyingFiltersTask(); 996 FinishDestroyingFiltersTask();
943 break; 997 break;
944 case kPausing: 998 case kPausing:
945 SetState(kFlushing); 999 SetState(kFlushing);
946 pipeline_filter_->Flush( 1000 DoFlush(base::Bind(&Pipeline::OnTeardownStateTransition, this));
947 base::Bind(&Pipeline::OnTeardownStateTransition, this));
948 break; 1001 break;
949 case kFlushing: 1002 case kFlushing:
950 SetState(kStopping); 1003 SetState(kStopping);
951 DoStop(base::Bind(&Pipeline::OnTeardownStateTransition, this)); 1004 DoStop(base::Bind(&Pipeline::OnTeardownStateTransition, this));
952 break; 1005 break;
953 1006
954 case kCreated: 1007 case kCreated:
955 case kError: 1008 case kError:
956 case kInitDemuxer: 1009 case kInitDemuxer:
957 case kInitAudioDecoder: 1010 case kInitAudioDecoder:
(...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after
1085 } 1138 }
1086 1139
1087 bool Pipeline::InitializeAudioRenderer( 1140 bool Pipeline::InitializeAudioRenderer(
1088 const scoped_refptr<AudioDecoder>& decoder) { 1141 const scoped_refptr<AudioDecoder>& decoder) {
1089 DCHECK(message_loop_->BelongsToCurrentThread()); 1142 DCHECK(message_loop_->BelongsToCurrentThread());
1090 DCHECK(IsPipelineOk()); 1143 DCHECK(IsPipelineOk());
1091 1144
1092 if (!decoder) 1145 if (!decoder)
1093 return false; 1146 return false;
1094 1147
1095 filter_collection_->SelectAudioRenderer( 1148 filter_collection_->SelectAudioRenderer(&audio_renderer_);
1096 &pipeline_init_state_->audio_renderer); 1149 if (!audio_renderer_) {
1097 if (!pipeline_init_state_->audio_renderer) {
1098 SetError(PIPELINE_ERROR_REQUIRED_FILTER_MISSING); 1150 SetError(PIPELINE_ERROR_REQUIRED_FILTER_MISSING);
1099 return false; 1151 return false;
1100 } 1152 }
1101 1153
1102 pipeline_init_state_->composite->AddFilter( 1154 audio_renderer_->Initialize(
1103 pipeline_init_state_->audio_renderer);
1104
1105 pipeline_init_state_->audio_renderer->Initialize(
1106 decoder, 1155 decoder,
1107 base::Bind(&Pipeline::OnFilterInitialize, this), 1156 base::Bind(&Pipeline::OnFilterInitialize, this),
1108 base::Bind(&Pipeline::OnAudioUnderflow, this), 1157 base::Bind(&Pipeline::OnAudioUnderflow, this),
1109 base::Bind(&Pipeline::OnAudioTimeUpdate, this)); 1158 base::Bind(&Pipeline::OnAudioTimeUpdate, this),
1110 1159 base::Bind(&Pipeline::NotifyEnded, this),
1111 audio_renderer_ = pipeline_init_state_->audio_renderer; 1160 base::Bind(&Pipeline::OnAudioDisabled, this),
1161 base::Bind(&Pipeline::SetError, this));
1112 return true; 1162 return true;
1113 } 1163 }
1114 1164
1115 bool Pipeline::InitializeVideoRenderer( 1165 bool Pipeline::InitializeVideoRenderer(
1116 const scoped_refptr<VideoDecoder>& decoder) { 1166 const scoped_refptr<VideoDecoder>& decoder) {
1117 DCHECK(message_loop_->BelongsToCurrentThread()); 1167 DCHECK(message_loop_->BelongsToCurrentThread());
1118 DCHECK(IsPipelineOk()); 1168 DCHECK(IsPipelineOk());
1119 1169
1120 if (!decoder) 1170 if (!decoder)
1121 return false; 1171 return false;
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
1187 if (seek_pending_) { 1237 if (seek_pending_) {
1188 seek_pending_ = false; 1238 seek_pending_ = false;
1189 FinishInitialization(); 1239 FinishInitialization();
1190 } 1240 }
1191 1241
1192 break; 1242 break;
1193 1243
1194 case kStarted: 1244 case kStarted:
1195 case kEnded: 1245 case kEnded:
1196 SetState(kPausing); 1246 SetState(kPausing);
1197 pipeline_filter_->Pause( 1247 DoPause(base::Bind(&Pipeline::OnTeardownStateTransition, this));
1198 base::Bind(&Pipeline::OnTeardownStateTransition, this));
1199 break; 1248 break;
1200 1249
1201 case kStopping: 1250 case kStopping:
1202 case kStopped: 1251 case kStopped:
1203 NOTREACHED() << "Unexpected state for teardown: " << state_; 1252 NOTREACHED() << "Unexpected state for teardown: " << state_;
1204 break; 1253 break;
1205 // default: intentionally left out to force new states to cause compiler 1254 // default: intentionally left out to force new states to cause compiler
1206 // errors. 1255 // errors.
1207 }; 1256 };
1208 } 1257 }
1209 1258
1210 void Pipeline::DoStop(const base::Closure& callback) { 1259 void Pipeline::DoSeek(base::TimeDelta seek_timestamp,
1211 if (demuxer_) { 1260 bool skip_demuxer_seek,
1212 demuxer_->Stop(base::Bind( 1261 const PipelineStatusCB& done_cb) {
1213 &Pipeline::OnDemuxerStopDone, this, callback)); 1262 DCHECK(message_loop_->BelongsToCurrentThread());
1214 return; 1263 scoped_ptr<std::queue<PipelineStatusCBFunc> > status_cbs(
1215 } 1264 new std::queue<PipelineStatusCBFunc>());
1216 1265
1217 OnDemuxerStopDone(callback); 1266 if (!skip_demuxer_seek)
1218 } 1267 status_cbs->push(base::Bind(&Demuxer::Seek, demuxer_, seek_timestamp));
1219 1268
1220 void Pipeline::OnDemuxerStopDone(const base::Closure& callback) { 1269 if (audio_renderer_)
1221 if (!message_loop_->BelongsToCurrentThread()) { 1270 status_cbs->push(base::Bind(
1222 message_loop_->PostTask(FROM_HERE, base::Bind( 1271 &AudioRenderer::Seek, audio_renderer_, seek_timestamp));
1223 &Pipeline::OnDemuxerStopDone, this, callback));
1224 return;
1225 }
1226 1272
1227 if (pipeline_filter_) { 1273 if (pipeline_filter_)
1228 pipeline_filter_->Stop(callback); 1274 status_cbs->push(base::Bind(
1229 return; 1275 &Filter::Seek, pipeline_filter_, seek_timestamp));
1230 }
1231 1276
1232 callback.Run(); 1277 RunInSeriesWithStatus(status_cbs.Pass(), base::Bind(
1233 } 1278 &Pipeline::ReportStatus, this, done_cb));
1234
1235 void Pipeline::DoSeek(TimeDelta seek_timestamp) {
1236 demuxer_->Seek(seek_timestamp, base::Bind(
1237 &Pipeline::OnDemuxerSeekDone, this, seek_timestamp));
1238 }
1239
1240 void Pipeline::OnDemuxerSeekDone(TimeDelta seek_timestamp,
1241 PipelineStatus status) {
1242 if (!message_loop_->BelongsToCurrentThread()) {
1243 message_loop_->PostTask(FROM_HERE, base::Bind(
1244 &Pipeline::OnDemuxerSeekDone, this, seek_timestamp, status));
1245 return;
1246 }
1247
1248 PipelineStatusCB done_cb =
1249 base::Bind(&Pipeline::OnFilterStateTransitionWithStatus, this);
1250
1251 if (status == PIPELINE_OK && pipeline_filter_) {
1252 pipeline_filter_->Seek(seek_timestamp, done_cb);
1253 return;
1254 }
1255
1256 ReportStatus(done_cb, status);
1257 } 1279 }
1258 1280
1259 void Pipeline::OnAudioUnderflow() { 1281 void Pipeline::OnAudioUnderflow() {
1260 if (!message_loop_->BelongsToCurrentThread()) { 1282 if (!message_loop_->BelongsToCurrentThread()) {
1261 message_loop_->PostTask(FROM_HERE, base::Bind( 1283 message_loop_->PostTask(FROM_HERE, base::Bind(
1262 &Pipeline::OnAudioUnderflow, this)); 1284 &Pipeline::OnAudioUnderflow, this));
1263 return; 1285 return;
1264 } 1286 }
1265 1287
1266 if (state_ != kStarted) 1288 if (state_ != kStarted)
1267 return; 1289 return;
1268 1290
1269 if (audio_renderer_) 1291 if (audio_renderer_)
1270 audio_renderer_->ResumeAfterUnderflow(true); 1292 audio_renderer_->ResumeAfterUnderflow(true);
1271 } 1293 }
1272 1294
1273 void Pipeline::StartClockIfWaitingForTimeUpdate_Locked() { 1295 void Pipeline::StartClockIfWaitingForTimeUpdate_Locked() {
1274 lock_.AssertAcquired(); 1296 lock_.AssertAcquired();
1275 if (!waiting_for_clock_update_) 1297 if (!waiting_for_clock_update_)
1276 return; 1298 return;
1277 1299
1278 waiting_for_clock_update_ = false; 1300 waiting_for_clock_update_ = false;
1279 clock_->Play(); 1301 clock_->Play();
1280 } 1302 }
1281 1303
1282 } // namespace media 1304 } // 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