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

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

Issue 10834236: Replace Pipeline::kEnded state and HasEnded() methods with renderer-specific bools. (Closed) Base URL: svn://chrome-svn/chrome/trunk/src
Patch Set: Created 8 years, 4 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 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
81 volume_(1.0f), 81 volume_(1.0f),
82 playback_rate_(0.0f), 82 playback_rate_(0.0f),
83 pending_playback_rate_(0.0f), 83 pending_playback_rate_(0.0f),
84 clock_(new Clock(&base::Time::Now)), 84 clock_(new Clock(&base::Time::Now)),
85 waiting_for_clock_update_(false), 85 waiting_for_clock_update_(false),
86 status_(PIPELINE_OK), 86 status_(PIPELINE_OK),
87 has_audio_(false), 87 has_audio_(false),
88 has_video_(false), 88 has_video_(false),
89 state_(kCreated), 89 state_(kCreated),
90 seek_timestamp_(kNoTimestamp()), 90 seek_timestamp_(kNoTimestamp()),
91 audio_ended_(false),
92 video_ended_(false),
91 audio_disabled_(false), 93 audio_disabled_(false),
92 creation_time_(base::Time::Now()) { 94 creation_time_(base::Time::Now()) {
93 media_log_->AddEvent(media_log_->CreatePipelineStateChangedEvent(kCreated)); 95 media_log_->AddEvent(media_log_->CreatePipelineStateChangedEvent(kCreated));
94 media_log_->AddEvent( 96 media_log_->AddEvent(
95 media_log_->CreateEvent(MediaLogEvent::PIPELINE_CREATED)); 97 media_log_->CreateEvent(MediaLogEvent::PIPELINE_CREATED));
96 } 98 }
97 99
98 Pipeline::~Pipeline() { 100 Pipeline::~Pipeline() {
99 base::AutoLock auto_lock(lock_); 101 base::AutoLock auto_lock(lock_);
100 DCHECK(!running_) << "Stop() must complete before destroying object"; 102 DCHECK(!running_) << "Stop() must complete before destroying object";
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
144 // TODO(scherkus): perhaps replace this with a bool that is set/get under the 146 // TODO(scherkus): perhaps replace this with a bool that is set/get under the
145 // lock, because this is breaching the contract that |state_| is only accessed 147 // lock, because this is breaching the contract that |state_| is only accessed
146 // on |message_loop_|. 148 // on |message_loop_|.
147 base::AutoLock auto_lock(lock_); 149 base::AutoLock auto_lock(lock_);
148 switch (state_) { 150 switch (state_) {
149 case kPausing: 151 case kPausing:
150 case kFlushing: 152 case kFlushing:
151 case kSeeking: 153 case kSeeking:
152 case kStarting: 154 case kStarting:
153 case kStarted: 155 case kStarted:
154 case kEnded:
155 return true; 156 return true;
156 default: 157 default:
157 return false; 158 return false;
158 } 159 }
159 } 160 }
160 161
161 bool Pipeline::HasAudio() const { 162 bool Pipeline::HasAudio() const {
162 base::AutoLock auto_lock(lock_); 163 base::AutoLock auto_lock(lock_);
163 return has_audio_; 164 return has_audio_;
164 } 165 }
(...skipping 355 matching lines...) Expand 10 before | Expand all | Expand 10 after
520 521
521 void Pipeline::OnNaturalVideoSizeChanged(const gfx::Size& size) { 522 void Pipeline::OnNaturalVideoSizeChanged(const gfx::Size& size) {
522 DCHECK(IsRunning()); 523 DCHECK(IsRunning());
523 media_log_->AddEvent(media_log_->CreateVideoSizeSetEvent( 524 media_log_->AddEvent(media_log_->CreateVideoSizeSetEvent(
524 size.width(), size.height())); 525 size.width(), size.height()));
525 526
526 base::AutoLock auto_lock(lock_); 527 base::AutoLock auto_lock(lock_);
527 natural_size_ = size; 528 natural_size_ = size;
528 } 529 }
529 530
530 void Pipeline::OnRendererEnded() { 531 void Pipeline::OnAudioRendererEnded() {
531 DCHECK(IsRunning()); 532 // Force post to process ended messages after current execution frame.
532 message_loop_->PostTask(FROM_HERE, base::Bind( 533 message_loop_->PostTask(FROM_HERE, base::Bind(
533 &Pipeline::OnRendererEndedTask, this)); 534 &Pipeline::DoAudioRendererEnded, this));
534 media_log_->AddEvent(media_log_->CreateEvent(MediaLogEvent::ENDED)); 535 media_log_->AddEvent(media_log_->CreateEvent(MediaLogEvent::AUDIO_ENDED));
536 }
537
538 void Pipeline::OnVideoRendererEnded() {
539 // Force post to process ended messages after current execution frame.
540 message_loop_->PostTask(FROM_HERE, base::Bind(
541 &Pipeline::DoVideoRendererEnded, this));
542 media_log_->AddEvent(media_log_->CreateEvent(MediaLogEvent::VIDEO_ENDED));
535 } 543 }
536 544
537 // Called from any thread. 545 // Called from any thread.
538 void Pipeline::OnFilterInitialize(PipelineStatus status) { 546 void Pipeline::OnFilterInitialize(PipelineStatus status) {
539 // Continue the initialize task by proceeding to the next stage. 547 // Continue the initialize task by proceeding to the next stage.
540 message_loop_->PostTask(FROM_HERE, base::Bind( 548 message_loop_->PostTask(FROM_HERE, base::Bind(
541 &Pipeline::InitializeTask, this, status)); 549 &Pipeline::InitializeTask, this, status));
542 } 550 }
543 551
544 // Called from any thread. 552 // Called from any thread.
(...skipping 244 matching lines...) Expand 10 before | Expand all | Expand 10 after
789 797
790 if (audio_renderer_) 798 if (audio_renderer_)
791 audio_renderer_->SetVolume(volume); 799 audio_renderer_->SetVolume(volume);
792 } 800 }
793 801
794 void Pipeline::SeekTask(TimeDelta time, const PipelineStatusCB& seek_cb) { 802 void Pipeline::SeekTask(TimeDelta time, const PipelineStatusCB& seek_cb) {
795 DCHECK(message_loop_->BelongsToCurrentThread()); 803 DCHECK(message_loop_->BelongsToCurrentThread());
796 DCHECK(!IsPipelineStopPending()); 804 DCHECK(!IsPipelineStopPending());
797 805
798 // Suppress seeking if we're not fully started. 806 // Suppress seeking if we're not fully started.
799 if (state_ != kStarted && state_ != kEnded) { 807 if (state_ != kStarted) {
800 // TODO(scherkus): should we run the callback? I'm tempted to say the API 808 // TODO(scherkus): should we run the callback? I'm tempted to say the API
801 // will only execute the first Seek() request. 809 // will only execute the first Seek() request.
802 DVLOG(1) << "Media pipeline has not started, ignoring seek to " 810 DVLOG(1) << "Media pipeline has not started, ignoring seek to "
803 << time.InMicroseconds() << " (current state: " << state_ << ")"; 811 << time.InMicroseconds() << " (current state: " << state_ << ")";
804 return; 812 return;
805 } 813 }
806 814
807 DCHECK(!seek_pending_); 815 DCHECK(!seek_pending_);
808 seek_pending_ = true; 816 seek_pending_ = true;
809 817
810 // We'll need to pause every filter before seeking. The state transition 818 // We'll need to pause every filter before seeking. The state transition
811 // is as follows: 819 // is as follows:
812 // kStarted/kEnded 820 // kStarted
813 // kPausing (for each filter) 821 // kPausing (for each filter)
814 // kSeeking (for each filter) 822 // kSeeking (for each filter)
815 // kStarting (for each filter) 823 // kStarting (for each filter)
816 // kStarted 824 // kStarted
817 SetState(kPausing); 825 SetState(kPausing);
826 audio_ended_ = false;
827 video_ended_ = false;
818 seek_timestamp_ = std::max(time, demuxer_->GetStartTime()); 828 seek_timestamp_ = std::max(time, demuxer_->GetStartTime());
819 seek_cb_ = seek_cb; 829 seek_cb_ = seek_cb;
820 830
821 // Kick off seeking! 831 // Kick off seeking!
822 { 832 {
823 base::AutoLock auto_lock(lock_); 833 base::AutoLock auto_lock(lock_);
824 if (clock_->IsPlaying()) 834 if (clock_->IsPlaying())
825 clock_->Pause(); 835 clock_->Pause();
826 } 836 }
827 DoPause(base::Bind(&Pipeline::OnFilterStateTransition, this)); 837 DoPause(base::Bind(&Pipeline::OnFilterStateTransition, this));
828 } 838 }
829 839
830 void Pipeline::OnRendererEndedTask() { 840 void Pipeline::DoAudioRendererEnded() {
831 DCHECK(message_loop_->BelongsToCurrentThread()); 841 DCHECK(message_loop_->BelongsToCurrentThread());
832 842
833 // We can only end if we were actually playing. 843 if (state_ != kStarted)
834 if (state_ != kStarted) {
835 return; 844 return;
836 }
837 845
838 DCHECK(audio_renderer_ || video_renderer_); 846 DCHECK(!audio_ended_);
847 audio_ended_ = true;
839 848
840 // Make sure every extant renderer has ended. 849 // Start clock since there is no more audio to trigger clock updates.
841 if (audio_renderer_ && !audio_disabled_) { 850 if (!audio_disabled_) {
842 if (!audio_renderer_->HasEnded()) {
843 return;
844 }
845
846 // Start clock since there is no more audio to
847 // trigger clock updates.
848 base::AutoLock auto_lock(lock_); 851 base::AutoLock auto_lock(lock_);
849 clock_->SetMaxTime(clock_->Duration()); 852 clock_->SetMaxTime(clock_->Duration());
850 StartClockIfWaitingForTimeUpdate_Locked(); 853 StartClockIfWaitingForTimeUpdate_Locked();
851 } 854 }
852 855
853 if (video_renderer_ && !video_renderer_->HasEnded()) { 856 RunEndedCallbackIfNeeded();
857 }
858
859 void Pipeline::DoVideoRendererEnded() {
860 DCHECK(message_loop_->BelongsToCurrentThread());
861
862 if (state_ != kStarted)
854 return; 863 return;
855 }
856 864
857 // Transition to ended, executing the callback if present. 865 DCHECK(!video_ended_);
858 SetState(kEnded); 866 video_ended_ = true;
867
868 RunEndedCallbackIfNeeded();
869 }
870
871 void Pipeline::RunEndedCallbackIfNeeded() {
872 DCHECK(message_loop_->BelongsToCurrentThread());
873
874 if (audio_renderer_ && !audio_ended_ && !audio_disabled_)
875 return;
876
877 if (video_renderer_ && !video_ended_)
878 return;
879
859 { 880 {
860 base::AutoLock auto_lock(lock_); 881 base::AutoLock auto_lock(lock_);
861 clock_->EndOfStream(); 882 clock_->EndOfStream();
862 } 883 }
863 884
864 ReportStatus(ended_cb_, status_); 885 ReportStatus(ended_cb_, status_);
865 } 886 }
866 887
867 void Pipeline::AudioDisabledTask() { 888 void Pipeline::AudioDisabledTask() {
868 DCHECK(message_loop_->BelongsToCurrentThread()); 889 DCHECK(message_loop_->BelongsToCurrentThread());
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after
983 case kError: 1004 case kError:
984 case kInitDemuxer: 1005 case kInitDemuxer:
985 case kInitAudioDecoder: 1006 case kInitAudioDecoder:
986 case kInitAudioRenderer: 1007 case kInitAudioRenderer:
987 case kInitVideoDecoder: 1008 case kInitVideoDecoder:
988 case kInitVideoRenderer: 1009 case kInitVideoRenderer:
989 case kSeeking: 1010 case kSeeking:
990 case kStarting: 1011 case kStarting:
991 case kStopped: 1012 case kStopped:
992 case kStarted: 1013 case kStarted:
993 case kEnded:
994 NOTREACHED() << "Unexpected state for teardown: " << state_; 1014 NOTREACHED() << "Unexpected state for teardown: " << state_;
995 break; 1015 break;
996 // default: intentionally left out to force new states to cause compiler 1016 // default: intentionally left out to force new states to cause compiler
997 // errors. 1017 // errors.
998 }; 1018 };
999 } 1019 }
1000 1020
1001 void Pipeline::FinishDestroyingFiltersTask() { 1021 void Pipeline::FinishDestroyingFiltersTask() {
1002 DCHECK(message_loop_->BelongsToCurrentThread()); 1022 DCHECK(message_loop_->BelongsToCurrentThread());
1003 DCHECK(IsPipelineStopped()); 1023 DCHECK(IsPipelineStopped());
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after
1125 if (!audio_renderer_) { 1145 if (!audio_renderer_) {
1126 SetError(PIPELINE_ERROR_REQUIRED_FILTER_MISSING); 1146 SetError(PIPELINE_ERROR_REQUIRED_FILTER_MISSING);
1127 return false; 1147 return false;
1128 } 1148 }
1129 1149
1130 audio_renderer_->Initialize( 1150 audio_renderer_->Initialize(
1131 decoder, 1151 decoder,
1132 base::Bind(&Pipeline::OnFilterInitialize, this), 1152 base::Bind(&Pipeline::OnFilterInitialize, this),
1133 base::Bind(&Pipeline::OnAudioUnderflow, this), 1153 base::Bind(&Pipeline::OnAudioUnderflow, this),
1134 base::Bind(&Pipeline::OnAudioTimeUpdate, this), 1154 base::Bind(&Pipeline::OnAudioTimeUpdate, this),
1135 base::Bind(&Pipeline::OnRendererEnded, this), 1155 base::Bind(&Pipeline::OnAudioRendererEnded, this),
1136 base::Bind(&Pipeline::OnAudioDisabled, this), 1156 base::Bind(&Pipeline::OnAudioDisabled, this),
1137 base::Bind(&Pipeline::SetError, this)); 1157 base::Bind(&Pipeline::SetError, this));
1138 return true; 1158 return true;
1139 } 1159 }
1140 1160
1141 bool Pipeline::InitializeVideoRenderer( 1161 bool Pipeline::InitializeVideoRenderer(
1142 const scoped_refptr<VideoDecoder>& decoder) { 1162 const scoped_refptr<VideoDecoder>& decoder) {
1143 DCHECK(message_loop_->BelongsToCurrentThread()); 1163 DCHECK(message_loop_->BelongsToCurrentThread());
1144 DCHECK(IsPipelineOk()); 1164 DCHECK(IsPipelineOk());
1145 1165
1146 if (!decoder) 1166 if (!decoder)
1147 return false; 1167 return false;
1148 1168
1149 filter_collection_->SelectVideoRenderer(&video_renderer_); 1169 filter_collection_->SelectVideoRenderer(&video_renderer_);
1150 if (!video_renderer_) { 1170 if (!video_renderer_) {
1151 SetError(PIPELINE_ERROR_REQUIRED_FILTER_MISSING); 1171 SetError(PIPELINE_ERROR_REQUIRED_FILTER_MISSING);
1152 return false; 1172 return false;
1153 } 1173 }
1154 1174
1155 video_renderer_->Initialize( 1175 video_renderer_->Initialize(
1156 decoder, 1176 decoder,
1157 base::Bind(&Pipeline::OnFilterInitialize, this), 1177 base::Bind(&Pipeline::OnFilterInitialize, this),
1158 base::Bind(&Pipeline::OnUpdateStatistics, this), 1178 base::Bind(&Pipeline::OnUpdateStatistics, this),
1159 base::Bind(&Pipeline::OnVideoTimeUpdate, this), 1179 base::Bind(&Pipeline::OnVideoTimeUpdate, this),
1160 base::Bind(&Pipeline::OnNaturalVideoSizeChanged, this), 1180 base::Bind(&Pipeline::OnNaturalVideoSizeChanged, this),
1161 base::Bind(&Pipeline::OnRendererEnded, this), 1181 base::Bind(&Pipeline::OnVideoRendererEnded, this),
1162 base::Bind(&Pipeline::SetError, this), 1182 base::Bind(&Pipeline::SetError, this),
1163 base::Bind(&Pipeline::GetMediaTime, this), 1183 base::Bind(&Pipeline::GetMediaTime, this),
1164 base::Bind(&Pipeline::GetMediaDuration, this)); 1184 base::Bind(&Pipeline::GetMediaDuration, this));
1165 return true; 1185 return true;
1166 } 1186 }
1167 1187
1168 void Pipeline::TearDownPipeline() { 1188 void Pipeline::TearDownPipeline() {
1169 DCHECK(message_loop_->BelongsToCurrentThread()); 1189 DCHECK(message_loop_->BelongsToCurrentThread());
1170 DCHECK_NE(kStopped, state_); 1190 DCHECK_NE(kStopped, state_);
1171 1191
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
1212 DoStop(base::Bind(&Pipeline::OnTeardownStateTransition, this)); 1232 DoStop(base::Bind(&Pipeline::OnTeardownStateTransition, this));
1213 1233
1214 if (seek_pending_) { 1234 if (seek_pending_) {
1215 seek_pending_ = false; 1235 seek_pending_ = false;
1216 FinishInitialization(); 1236 FinishInitialization();
1217 } 1237 }
1218 1238
1219 break; 1239 break;
1220 1240
1221 case kStarted: 1241 case kStarted:
1222 case kEnded:
1223 SetState(kPausing); 1242 SetState(kPausing);
1224 DoPause(base::Bind(&Pipeline::OnTeardownStateTransition, this)); 1243 DoPause(base::Bind(&Pipeline::OnTeardownStateTransition, this));
1225 break; 1244 break;
1226 1245
1227 case kStopping: 1246 case kStopping:
1228 case kStopped: 1247 case kStopped:
1229 NOTREACHED() << "Unexpected state for teardown: " << state_; 1248 NOTREACHED() << "Unexpected state for teardown: " << state_;
1230 break; 1249 break;
1231 // default: intentionally left out to force new states to cause compiler 1250 // default: intentionally left out to force new states to cause compiler
1232 // errors. 1251 // errors.
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
1275 void Pipeline::StartClockIfWaitingForTimeUpdate_Locked() { 1294 void Pipeline::StartClockIfWaitingForTimeUpdate_Locked() {
1276 lock_.AssertAcquired(); 1295 lock_.AssertAcquired();
1277 if (!waiting_for_clock_update_) 1296 if (!waiting_for_clock_update_)
1278 return; 1297 return;
1279 1298
1280 waiting_for_clock_update_ = false; 1299 waiting_for_clock_update_ = false;
1281 clock_->Play(); 1300 clock_->Play();
1282 } 1301 }
1283 1302
1284 } // namespace media 1303 } // 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