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

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: woot for RunInSeries/Parallel 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
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 305 matching lines...) Expand 10 before | Expand all | Expand 10 after
383 TimeDelta Pipeline::GetTime() const { 383 TimeDelta Pipeline::GetTime() const {
384 DCHECK(IsRunning()); 384 DCHECK(IsRunning());
385 return GetCurrentTime(); 385 return GetCurrentTime();
386 } 386 }
387 387
388 TimeDelta Pipeline::GetDuration() const { 388 TimeDelta Pipeline::GetDuration() const {
389 DCHECK(IsRunning()); 389 DCHECK(IsRunning());
390 return GetMediaDuration(); 390 return GetMediaDuration();
391 } 391 }
392 392
393 void Pipeline::OnAudioDisabled() {
394 DCHECK(IsRunning());
395 message_loop_->PostTask(FROM_HERE, base::Bind(
396 &Pipeline::AudioDisabledTask, this));
397 media_log_->AddEvent(
398 media_log_->CreateEvent(MediaLogEvent::AUDIO_RENDERER_DISABLED));
399 }
400
393 void Pipeline::OnAudioTimeUpdate(TimeDelta time, TimeDelta max_time) { 401 void Pipeline::OnAudioTimeUpdate(TimeDelta time, TimeDelta max_time) {
394 DCHECK(time <= max_time); 402 DCHECK(time <= max_time);
395 DCHECK(IsRunning()); 403 DCHECK(IsRunning());
396 base::AutoLock auto_lock(lock_); 404 base::AutoLock auto_lock(lock_);
397 405
398 if (!has_audio_) 406 if (!has_audio_)
399 return; 407 return;
400 if (waiting_for_clock_update_ && time < clock_->Elapsed()) 408 if (waiting_for_clock_update_ && time < clock_->Elapsed())
401 return; 409 return;
402 410
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
453 // Since the byte->time calculation is approximate, fudge the beginning & 461 // Since the byte->time calculation is approximate, fudge the beginning &
454 // ending areas to look better. 462 // ending areas to look better.
455 TimeDelta epsilon = clock_->Duration() / 100; 463 TimeDelta epsilon = clock_->Duration() / 100;
456 if (time_offset < epsilon) 464 if (time_offset < epsilon)
457 return TimeDelta(); 465 return TimeDelta();
458 if (time_offset + epsilon > clock_->Duration()) 466 if (time_offset + epsilon > clock_->Duration())
459 return clock_->Duration(); 467 return clock_->Duration();
460 return time_offset; 468 return time_offset;
461 } 469 }
462 470
471 void Pipeline::DoPause(const base::Closure& done_cb) {
472 scoped_ptr<std::queue<ClosureCB> > closures(new std::queue<ClosureCB>);
473
474 if (audio_renderer_)
475 closures->push(base::Bind(&AudioRenderer::Pause, audio_renderer_));
476
477 if (pipeline_filter_)
478 closures->push(base::Bind(&Filter::Pause, pipeline_filter_));
479
480 RunInSeries(closures.Pass(), done_cb);
481 }
482
483 void Pipeline::DoFlush(const base::Closure& done_cb) {
484 scoped_ptr<std::queue<ClosureCB> > closures(new std::queue<ClosureCB>);
485
486 if (audio_renderer_)
487 closures->push(base::Bind(&AudioRenderer::Flush, audio_renderer_));
488
489 if (pipeline_filter_)
490 closures->push(base::Bind(&Filter::Flush, pipeline_filter_));
491
492 RunInParallel(closures.Pass(), done_cb);
493 }
494
495 void Pipeline::DoPlay(const base::Closure& done_cb) {
496 scoped_ptr<std::queue<ClosureCB> > closures(new std::queue<ClosureCB>);
497
498 if (audio_renderer_)
499 closures->push(base::Bind(&AudioRenderer::Play, audio_renderer_));
500
501 if (pipeline_filter_)
502 closures->push(base::Bind(&Filter::Play, pipeline_filter_));
503
504 RunInSeries(closures.Pass(), done_cb);
505 }
506
507 void Pipeline::DoStop(const base::Closure& done_cb) {
508 scoped_ptr<std::queue<ClosureCB> > closures(new std::queue<ClosureCB>);
509
510 if (demuxer_)
511 closures->push(base::Bind(&Demuxer::Stop, demuxer_));
512
513 if (audio_renderer_)
514 closures->push(base::Bind(&AudioRenderer::Stop, audio_renderer_));
515
516 if (pipeline_filter_)
517 closures->push(base::Bind(&Filter::Stop, pipeline_filter_));
518
519 RunInSeries(closures.Pass(), done_cb);
520 }
521
463 void Pipeline::AddBufferedByteRange(int64 start, int64 end) { 522 void Pipeline::AddBufferedByteRange(int64 start, int64 end) {
464 DCHECK(IsRunning()); 523 DCHECK(IsRunning());
465 base::AutoLock auto_lock(lock_); 524 base::AutoLock auto_lock(lock_);
466 buffered_byte_ranges_.Add(start, end); 525 buffered_byte_ranges_.Add(start, end);
467 did_loading_progress_ = true; 526 did_loading_progress_ = true;
468 } 527 }
469 528
470 void Pipeline::AddBufferedTimeRange(base::TimeDelta start, 529 void Pipeline::AddBufferedTimeRange(base::TimeDelta start,
471 base::TimeDelta end) { 530 base::TimeDelta end) {
472 DCHECK(IsRunning()); 531 DCHECK(IsRunning());
(...skipping 11 matching lines...) Expand all
484 natural_size_ = size; 543 natural_size_ = size;
485 } 544 }
486 545
487 void Pipeline::NotifyEnded() { 546 void Pipeline::NotifyEnded() {
488 DCHECK(IsRunning()); 547 DCHECK(IsRunning());
489 message_loop_->PostTask(FROM_HERE, base::Bind( 548 message_loop_->PostTask(FROM_HERE, base::Bind(
490 &Pipeline::NotifyEndedTask, this)); 549 &Pipeline::NotifyEndedTask, this));
491 media_log_->AddEvent(media_log_->CreateEvent(MediaLogEvent::ENDED)); 550 media_log_->AddEvent(media_log_->CreateEvent(MediaLogEvent::ENDED));
492 } 551 }
493 552
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. 553 // Called from any thread.
505 void Pipeline::OnFilterInitialize(PipelineStatus status) { 554 void Pipeline::OnFilterInitialize(PipelineStatus status) {
506 // Continue the initialize task by proceeding to the next stage. 555 // Continue the initialize task by proceeding to the next stage.
507 message_loop_->PostTask(FROM_HERE, base::Bind( 556 message_loop_->PostTask(FROM_HERE, base::Bind(
508 &Pipeline::InitializeTask, this, status)); 557 &Pipeline::InitializeTask, this, status));
509 } 558 }
510 559
511 // Called from any thread. 560 // Called from any thread.
512 void Pipeline::OnFilterStateTransition() { 561 void Pipeline::OnFilterStateTransition() {
513 message_loop_->PostTask(FROM_HERE, base::Bind( 562 message_loop_->PostTask(FROM_HERE, base::Bind(
(...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after
656 // Initialization was successful, we are now considered paused, so it's safe 705 // Initialization was successful, we are now considered paused, so it's safe
657 // to set the initial playback rate and volume. 706 // to set the initial playback rate and volume.
658 PlaybackRateChangedTask(GetPlaybackRate()); 707 PlaybackRateChangedTask(GetPlaybackRate());
659 VolumeChangedTask(GetVolume()); 708 VolumeChangedTask(GetVolume());
660 709
661 // Fire a seek request to get the renderers to preroll. We don't need to 710 // Fire a seek request to get the renderers to preroll. We don't need to
662 // tell the demuxer to seek since it should already be at the start. 711 // tell the demuxer to seek since it should already be at the start.
663 seek_pending_ = true; 712 seek_pending_ = true;
664 SetState(kSeeking); 713 SetState(kSeeking);
665 seek_timestamp_ = demuxer_->GetStartTime(); 714 seek_timestamp_ = demuxer_->GetStartTime();
666 OnDemuxerSeekDone(seek_timestamp_, PIPELINE_OK); 715 OnDemuxerSeekDone(
716 base::Bind(&Pipeline::OnFilterStateTransitionWithStatus, this),
717 seek_timestamp_, PIPELINE_OK);
667 } 718 }
668 } 719 }
669 720
670 // This method is called as a result of the client calling Pipeline::Stop() or 721 // This method is called as a result of the client calling Pipeline::Stop() or
671 // as the result of an error condition. 722 // as the result of an error condition.
672 // We stop the filters in the reverse order. 723 // We stop the filters in the reverse order.
673 // 724 //
674 // TODO(scherkus): beware! this can get posted multiple times since we post 725 // 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 726 // 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. 727 // additional calls, however most of this logic will be changing.
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
745 796
746 { 797 {
747 base::AutoLock auto_lock(lock_); 798 base::AutoLock auto_lock(lock_);
748 clock_->SetPlaybackRate(playback_rate); 799 clock_->SetPlaybackRate(playback_rate);
749 } 800 }
750 801
751 // Notify |pipeline_filter_| if it has been initialized. If initialization 802 // Notify |pipeline_filter_| if it has been initialized. If initialization
752 // hasn't completed yet, the playback rate will be set when initialization 803 // hasn't completed yet, the playback rate will be set when initialization
753 // completes. 804 // completes.
754 if (pipeline_filter_) { 805 if (pipeline_filter_) {
755 DCHECK(demuxer_);
756 demuxer_->SetPlaybackRate(playback_rate); 806 demuxer_->SetPlaybackRate(playback_rate);
757 pipeline_filter_->SetPlaybackRate(playback_rate); 807 pipeline_filter_->SetPlaybackRate(playback_rate);
808
809 if (audio_renderer_)
810 audio_renderer_->SetPlaybackRate(playback_rate_);
758 } 811 }
759 } 812 }
760 813
761 void Pipeline::VolumeChangedTask(float volume) { 814 void Pipeline::VolumeChangedTask(float volume) {
762 DCHECK(message_loop_->BelongsToCurrentThread()); 815 DCHECK(message_loop_->BelongsToCurrentThread());
763 if (!running_ || tearing_down_) 816 if (!running_ || tearing_down_)
764 return; 817 return;
765 818
766 if (audio_renderer_) 819 if (audio_renderer_)
767 audio_renderer_->SetVolume(volume); 820 audio_renderer_->SetVolume(volume);
(...skipping 25 matching lines...) Expand all
793 SetState(kPausing); 846 SetState(kPausing);
794 seek_timestamp_ = std::max(time, demuxer_->GetStartTime()); 847 seek_timestamp_ = std::max(time, demuxer_->GetStartTime());
795 seek_cb_ = seek_cb; 848 seek_cb_ = seek_cb;
796 849
797 // Kick off seeking! 850 // Kick off seeking!
798 { 851 {
799 base::AutoLock auto_lock(lock_); 852 base::AutoLock auto_lock(lock_);
800 if (clock_->IsPlaying()) 853 if (clock_->IsPlaying())
801 clock_->Pause(); 854 clock_->Pause();
802 } 855 }
803 pipeline_filter_->Pause( 856 DoPause(base::Bind(&Pipeline::OnFilterStateTransition, this));
804 base::Bind(&Pipeline::OnFilterStateTransition, this));
805 } 857 }
806 858
807 void Pipeline::NotifyEndedTask() { 859 void Pipeline::NotifyEndedTask() {
808 DCHECK(message_loop_->BelongsToCurrentThread()); 860 DCHECK(message_loop_->BelongsToCurrentThread());
809 861
810 // We can only end if we were actually playing. 862 // We can only end if we were actually playing.
811 if (state_ != kStarted) { 863 if (state_ != kStarted) {
812 return; 864 return;
813 } 865 }
814 866
(...skipping 19 matching lines...) Expand all
834 // Transition to ended, executing the callback if present. 886 // Transition to ended, executing the callback if present.
835 SetState(kEnded); 887 SetState(kEnded);
836 { 888 {
837 base::AutoLock auto_lock(lock_); 889 base::AutoLock auto_lock(lock_);
838 clock_->EndOfStream(); 890 clock_->EndOfStream();
839 } 891 }
840 892
841 ReportStatus(ended_cb_, status_); 893 ReportStatus(ended_cb_, status_);
842 } 894 }
843 895
844 void Pipeline::DisableAudioRendererTask() { 896 void Pipeline::AudioDisabledTask() {
845 DCHECK(message_loop_->BelongsToCurrentThread()); 897 DCHECK(message_loop_->BelongsToCurrentThread());
846 898
847 base::AutoLock auto_lock(lock_); 899 base::AutoLock auto_lock(lock_);
848 has_audio_ = false; 900 has_audio_ = false;
849 audio_disabled_ = true; 901 audio_disabled_ = true;
850 902
851 // Notify our demuxer that we're no longer rendering audio. 903 // Notify our demuxer that we're no longer rendering audio.
852 demuxer_->OnAudioRendererDisabled(); 904 demuxer_->OnAudioRendererDisabled();
853 905
854 // Start clock since there is no more audio to 906 // Start clock since there is no more audio to
(...skipping 26 matching lines...) Expand all
881 // to the next state if needed. 933 // to the next state if needed.
882 SetState(FindNextState(state_)); 934 SetState(FindNextState(state_));
883 if (state_ == kSeeking) { 935 if (state_ == kSeeking) {
884 base::AutoLock auto_lock(lock_); 936 base::AutoLock auto_lock(lock_);
885 clock_->SetTime(seek_timestamp_, seek_timestamp_); 937 clock_->SetTime(seek_timestamp_, seek_timestamp_);
886 } 938 }
887 939
888 // Carry out the action for the current state. 940 // Carry out the action for the current state.
889 if (TransientState(state_)) { 941 if (TransientState(state_)) {
890 if (state_ == kPausing) { 942 if (state_ == kPausing) {
891 pipeline_filter_->Pause( 943 DoPause(base::Bind(&Pipeline::OnFilterStateTransition, this));
892 base::Bind(&Pipeline::OnFilterStateTransition, this));
893 } else if (state_ == kFlushing) { 944 } else if (state_ == kFlushing) {
894 pipeline_filter_->Flush( 945 DoFlush(base::Bind(&Pipeline::OnFilterStateTransition, this));
895 base::Bind(&Pipeline::OnFilterStateTransition, this));
896 } else if (state_ == kSeeking) { 946 } else if (state_ == kSeeking) {
897 DoSeek(seek_timestamp_); 947 DoSeek(base::Bind(&Pipeline::OnFilterStateTransitionWithStatus, this),
948 seek_timestamp_);
898 } else if (state_ == kStarting) { 949 } else if (state_ == kStarting) {
899 pipeline_filter_->Play( 950 DoPlay(base::Bind(&Pipeline::OnFilterStateTransition, this));
900 base::Bind(&Pipeline::OnFilterStateTransition, this));
901 } else if (state_ == kStopping) { 951 } else if (state_ == kStopping) {
902 DoStop(base::Bind(&Pipeline::OnFilterStateTransition, this)); 952 DoStop(base::Bind(&Pipeline::OnFilterStateTransition, this));
903 } else { 953 } else {
904 NOTREACHED() << "Unexpected state: " << state_; 954 NOTREACHED() << "Unexpected state: " << state_;
905 } 955 }
906 } else if (state_ == kStarted) { 956 } else if (state_ == kStarted) {
907 FinishInitialization(); 957 FinishInitialization();
908 958
909 // Finally, complete the seek. 959 // Finally, complete the seek.
910 seek_pending_ = false; 960 seek_pending_ = false;
(...skipping 25 matching lines...) Expand all
936 986
937 void Pipeline::TeardownStateTransitionTask() { 987 void Pipeline::TeardownStateTransitionTask() {
938 DCHECK(IsPipelineTearingDown()); 988 DCHECK(IsPipelineTearingDown());
939 switch (state_) { 989 switch (state_) {
940 case kStopping: 990 case kStopping:
941 SetState(error_caused_teardown_ ? kError : kStopped); 991 SetState(error_caused_teardown_ ? kError : kStopped);
942 FinishDestroyingFiltersTask(); 992 FinishDestroyingFiltersTask();
943 break; 993 break;
944 case kPausing: 994 case kPausing:
945 SetState(kFlushing); 995 SetState(kFlushing);
946 pipeline_filter_->Flush( 996 DoFlush(base::Bind(&Pipeline::OnTeardownStateTransition, this));
947 base::Bind(&Pipeline::OnTeardownStateTransition, this));
948 break; 997 break;
949 case kFlushing: 998 case kFlushing:
950 SetState(kStopping); 999 SetState(kStopping);
951 DoStop(base::Bind(&Pipeline::OnTeardownStateTransition, this)); 1000 DoStop(base::Bind(&Pipeline::OnTeardownStateTransition, this));
952 break; 1001 break;
953 1002
954 case kCreated: 1003 case kCreated:
955 case kError: 1004 case kError:
956 case kInitDemuxer: 1005 case kInitDemuxer:
957 case kInitAudioDecoder: 1006 case kInitAudioDecoder:
(...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after
1085 } 1134 }
1086 1135
1087 bool Pipeline::InitializeAudioRenderer( 1136 bool Pipeline::InitializeAudioRenderer(
1088 const scoped_refptr<AudioDecoder>& decoder) { 1137 const scoped_refptr<AudioDecoder>& decoder) {
1089 DCHECK(message_loop_->BelongsToCurrentThread()); 1138 DCHECK(message_loop_->BelongsToCurrentThread());
1090 DCHECK(IsPipelineOk()); 1139 DCHECK(IsPipelineOk());
1091 1140
1092 if (!decoder) 1141 if (!decoder)
1093 return false; 1142 return false;
1094 1143
1095 filter_collection_->SelectAudioRenderer( 1144 filter_collection_->SelectAudioRenderer(&audio_renderer_);
1096 &pipeline_init_state_->audio_renderer); 1145 if (!audio_renderer_) {
1097 if (!pipeline_init_state_->audio_renderer) {
1098 SetError(PIPELINE_ERROR_REQUIRED_FILTER_MISSING); 1146 SetError(PIPELINE_ERROR_REQUIRED_FILTER_MISSING);
1099 return false; 1147 return false;
1100 } 1148 }
1101 1149
1102 pipeline_init_state_->composite->AddFilter( 1150 audio_renderer_->Initialize(
1103 pipeline_init_state_->audio_renderer);
1104
1105 pipeline_init_state_->audio_renderer->Initialize(
1106 decoder, 1151 decoder,
1107 base::Bind(&Pipeline::OnFilterInitialize, this), 1152 base::Bind(&Pipeline::OnFilterInitialize, this),
1108 base::Bind(&Pipeline::OnAudioUnderflow, this), 1153 base::Bind(&Pipeline::OnAudioUnderflow, this),
1109 base::Bind(&Pipeline::OnAudioTimeUpdate, this)); 1154 base::Bind(&Pipeline::OnAudioTimeUpdate, this),
1110 1155 base::Bind(&Pipeline::NotifyEnded, this),
1111 audio_renderer_ = pipeline_init_state_->audio_renderer; 1156 base::Bind(&Pipeline::OnAudioDisabled, this));
1112 return true; 1157 return true;
1113 } 1158 }
1114 1159
1115 bool Pipeline::InitializeVideoRenderer( 1160 bool Pipeline::InitializeVideoRenderer(
1116 const scoped_refptr<VideoDecoder>& decoder) { 1161 const scoped_refptr<VideoDecoder>& decoder) {
1117 DCHECK(message_loop_->BelongsToCurrentThread()); 1162 DCHECK(message_loop_->BelongsToCurrentThread());
1118 DCHECK(IsPipelineOk()); 1163 DCHECK(IsPipelineOk());
1119 1164
1120 if (!decoder) 1165 if (!decoder)
1121 return false; 1166 return false;
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
1187 if (seek_pending_) { 1232 if (seek_pending_) {
1188 seek_pending_ = false; 1233 seek_pending_ = false;
1189 FinishInitialization(); 1234 FinishInitialization();
1190 } 1235 }
1191 1236
1192 break; 1237 break;
1193 1238
1194 case kStarted: 1239 case kStarted:
1195 case kEnded: 1240 case kEnded:
1196 SetState(kPausing); 1241 SetState(kPausing);
1197 pipeline_filter_->Pause( 1242 DoPause(base::Bind(&Pipeline::OnTeardownStateTransition, this));
1198 base::Bind(&Pipeline::OnTeardownStateTransition, this));
1199 break; 1243 break;
1200 1244
1201 case kStopping: 1245 case kStopping:
1202 case kStopped: 1246 case kStopped:
1203 NOTREACHED() << "Unexpected state for teardown: " << state_; 1247 NOTREACHED() << "Unexpected state for teardown: " << state_;
1204 break; 1248 break;
1205 // default: intentionally left out to force new states to cause compiler 1249 // default: intentionally left out to force new states to cause compiler
1206 // errors. 1250 // errors.
1207 }; 1251 };
1208 } 1252 }
1209 1253
1210 void Pipeline::DoStop(const base::Closure& callback) { 1254 void Pipeline::DoSeek(const PipelineStatusCB& done_cb,
1211 if (demuxer_) { 1255 TimeDelta seek_timestamp) {
1212 demuxer_->Stop(base::Bind( 1256 demuxer_->Seek(seek_timestamp, base::Bind(
acolwell GONE FROM CHROMIUM 2012/07/19 00:58:18 It feels like you should be able to do the same th
scherkus (not reviewing) 2012/07/19 21:29:02 Done and using the power of Bind() we don't need t
1213 &Pipeline::OnDemuxerStopDone, this, callback)); 1257 &Pipeline::OnDemuxerSeekDone, this, done_cb, seek_timestamp));
1258 }
1259
1260 void Pipeline::OnDemuxerSeekDone(const PipelineStatusCB& done_cb,
1261 TimeDelta seek_timestamp,
1262 PipelineStatus status) {
1263 if (!message_loop_->BelongsToCurrentThread()) {
1264 message_loop_->PostTask(FROM_HERE, base::Bind(
1265 &Pipeline::OnDemuxerSeekDone, this, done_cb, seek_timestamp, status));
1214 return; 1266 return;
1215 } 1267 }
1216 1268
1217 OnDemuxerStopDone(callback); 1269 if (status == PIPELINE_OK && audio_renderer_) {
1218 } 1270 audio_renderer_->Seek(seek_timestamp, base::Bind(
1219 1271 &Pipeline::OnAudioRendererSeekDone, this, done_cb, seek_timestamp));
1220 void Pipeline::OnDemuxerStopDone(const base::Closure& callback) {
1221 if (!message_loop_->BelongsToCurrentThread()) {
1222 message_loop_->PostTask(FROM_HERE, base::Bind(
1223 &Pipeline::OnDemuxerStopDone, this, callback));
1224 return; 1272 return;
1225 } 1273 }
1226 1274
1227 if (pipeline_filter_) { 1275 OnAudioRendererSeekDone(done_cb, seek_timestamp, status);
1228 pipeline_filter_->Stop(callback); 1276 }
1277
1278 void Pipeline::OnAudioRendererSeekDone(const PipelineStatusCB& done_cb,
1279 base::TimeDelta seek_timestamp,
1280 PipelineStatus status) {
1281 if (!message_loop_->BelongsToCurrentThread()) {
1282 message_loop_->PostTask(FROM_HERE, base::Bind(
1283 &Pipeline::OnAudioRendererSeekDone, this, done_cb, seek_timestamp,
1284 status));
1229 return; 1285 return;
1230 } 1286 }
1231 1287
1232 callback.Run(); 1288 if (status == PIPELINE_OK && pipeline_filter_) {
1233 } 1289 pipeline_filter_->Seek(seek_timestamp, base::Bind(
1234 1290 &Pipeline::OnPipelineFilterSeekDone, this, done_cb));
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; 1291 return;
1246 } 1292 }
1247 1293
1248 PipelineStatusCB done_cb = 1294 OnPipelineFilterSeekDone(done_cb, status);
1249 base::Bind(&Pipeline::OnFilterStateTransitionWithStatus, this); 1295 }
1250 1296
1251 if (status == PIPELINE_OK && pipeline_filter_) { 1297 void Pipeline::OnPipelineFilterSeekDone(const PipelineStatusCB& done_cb,
1252 pipeline_filter_->Seek(seek_timestamp, done_cb); 1298 PipelineStatus status) {
1299 if (!message_loop_->BelongsToCurrentThread()) {
1300 message_loop_->PostTask(FROM_HERE, base::Bind(
1301 &Pipeline::OnPipelineFilterSeekDone, this, done_cb, status));
1253 return; 1302 return;
1254 } 1303 }
1255 1304
1256 ReportStatus(done_cb, status); 1305 ReportStatus(done_cb, status);
1257 } 1306 }
1258 1307
1259 void Pipeline::OnAudioUnderflow() { 1308 void Pipeline::OnAudioUnderflow() {
1260 if (!message_loop_->BelongsToCurrentThread()) { 1309 if (!message_loop_->BelongsToCurrentThread()) {
1261 message_loop_->PostTask(FROM_HERE, base::Bind( 1310 message_loop_->PostTask(FROM_HERE, base::Bind(
1262 &Pipeline::OnAudioUnderflow, this)); 1311 &Pipeline::OnAudioUnderflow, this));
(...skipping 10 matching lines...) Expand all
1273 void Pipeline::StartClockIfWaitingForTimeUpdate_Locked() { 1322 void Pipeline::StartClockIfWaitingForTimeUpdate_Locked() {
1274 lock_.AssertAcquired(); 1323 lock_.AssertAcquired();
1275 if (!waiting_for_clock_update_) 1324 if (!waiting_for_clock_update_)
1276 return; 1325 return;
1277 1326
1278 waiting_for_clock_update_ = false; 1327 waiting_for_clock_update_ = false;
1279 clock_->Play(); 1328 clock_->Play();
1280 } 1329 }
1281 1330
1282 } // namespace media 1331 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698