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

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

Issue 10836167: Move VideoDecoder initialization into VideoRendererBase. (Closed) Base URL: svn://svn.chromium.org/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
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 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
54 while (!notified_) 54 while (!notified_)
55 cv_.Wait(); 55 cv_.Wait();
56 } 56 }
57 57
58 media::PipelineStatus PipelineStatusNotification::status() { 58 media::PipelineStatus PipelineStatusNotification::status() {
59 base::AutoLock auto_lock(lock_); 59 base::AutoLock auto_lock(lock_);
60 DCHECK(notified_); 60 DCHECK(notified_);
61 return status_; 61 return status_;
62 } 62 }
63 63
64 struct Pipeline::PipelineInitState { 64 struct Pipeline::PipelineInitState {
Ami GONE FROM CHROMIUM 2012/08/09 20:30:18 drop this struct now (and bind the audio decoder i
acolwell GONE FROM CHROMIUM 2012/08/09 22:23:32 I can't really do this w/o moving the kInitAudioDe
65 scoped_refptr<AudioDecoder> audio_decoder; 65 scoped_refptr<AudioDecoder> audio_decoder;
66 scoped_refptr<VideoDecoder> video_decoder;
67 }; 66 };
68 67
69 Pipeline::Pipeline(MessageLoop* message_loop, MediaLog* media_log) 68 Pipeline::Pipeline(MessageLoop* message_loop, MediaLog* media_log)
70 : message_loop_(message_loop->message_loop_proxy()), 69 : message_loop_(message_loop->message_loop_proxy()),
71 media_log_(media_log), 70 media_log_(media_log),
72 running_(false), 71 running_(false),
73 seek_pending_(false), 72 seek_pending_(false),
74 stop_pending_(false), 73 stop_pending_(false),
75 tearing_down_(false), 74 tearing_down_(false),
76 error_caused_teardown_(false), 75 error_caused_teardown_(false),
(...skipping 525 matching lines...) Expand 10 before | Expand all | Expand 10 after
602 // FilterHost's InitializationComplete() method, the pipeline will update its 601 // FilterHost's InitializationComplete() method, the pipeline will update its
603 // state to kStarted and |init_cb_|, will be executed. 602 // state to kStarted and |init_cb_|, will be executed.
604 // 603 //
605 // TODO(hclam): InitializeTask() is now starting the pipeline asynchronously. It 604 // TODO(hclam): InitializeTask() is now starting the pipeline asynchronously. It
606 // works like a big state change table. If we no longer need to start filters 605 // works like a big state change table. If we no longer need to start filters
607 // in order, we need to get rid of all the state change. 606 // in order, we need to get rid of all the state change.
608 void Pipeline::InitializeTask(PipelineStatus last_stage_status) { 607 void Pipeline::InitializeTask(PipelineStatus last_stage_status) {
609 DCHECK(message_loop_->BelongsToCurrentThread()); 608 DCHECK(message_loop_->BelongsToCurrentThread());
610 609
611 if (last_stage_status != PIPELINE_OK) { 610 if (last_stage_status != PIPELINE_OK) {
612 // Currently only VideoDecoders have a recoverable error code. 611 SetError(last_stage_status);
613 if (state_ == kInitVideoDecoder && 612 return;
614 last_stage_status == DECODER_ERROR_NOT_SUPPORTED) {
615 state_ = kInitAudioRenderer;
616 } else {
617 SetError(last_stage_status);
618 return;
619 }
620 } 613 }
621 614
622 // If we have received the stop or error signal, return immediately. 615 // If we have received the stop or error signal, return immediately.
623 if (IsPipelineStopPending() || IsPipelineStopped() || !IsPipelineOk()) 616 if (IsPipelineStopPending() || IsPipelineStopped() || !IsPipelineOk())
624 return; 617 return;
625 618
626 DCHECK(state_ == kInitDemuxer || 619 DCHECK(state_ == kInitDemuxer ||
627 state_ == kInitAudioDecoder || 620 state_ == kInitAudioDecoder ||
628 state_ == kInitAudioRenderer || 621 state_ == kInitAudioRenderer ||
629 state_ == kInitVideoDecoder ||
630 state_ == kInitVideoRenderer); 622 state_ == kInitVideoRenderer);
631 623
632 // Demuxer created, create audio decoder. 624 // Demuxer created, create audio decoder.
633 if (state_ == kInitDemuxer) { 625 if (state_ == kInitDemuxer) {
634 SetState(kInitAudioDecoder); 626 SetState(kInitAudioDecoder);
635 // If this method returns false, then there's no audio stream. 627 // If this method returns false, then there's no audio stream.
636 if (InitializeAudioDecoder(demuxer_)) 628 if (InitializeAudioDecoder(demuxer_))
637 return; 629 return;
638 } 630 }
639 631
640 // Assuming audio decoder was created, create audio renderer. 632 // Assuming audio decoder was created, create audio renderer.
641 if (state_ == kInitAudioDecoder) { 633 if (state_ == kInitAudioDecoder) {
642 SetState(kInitAudioRenderer); 634 SetState(kInitAudioRenderer);
643 635
644 // Returns false if there's no audio stream. 636 // Returns false if there's no audio stream.
645 if (InitializeAudioRenderer(pipeline_init_state_->audio_decoder)) { 637 if (InitializeAudioRenderer(pipeline_init_state_->audio_decoder)) {
646 base::AutoLock auto_lock(lock_); 638 base::AutoLock auto_lock(lock_);
647 has_audio_ = true; 639 has_audio_ = true;
648 return; 640 return;
649 } 641 }
650 } 642 }
651 643
652 // Assuming audio renderer was created, create video decoder. 644 // Assuming audio renderer was created, create video decoder.
Ami GONE FROM CHROMIUM 2012/08/09 20:30:18 s/decoder/renderer/
acolwell GONE FROM CHROMIUM 2012/08/09 22:23:32 Done.
653 if (state_ == kInitAudioRenderer) { 645 if (state_ == kInitAudioRenderer) {
654 // Then perform the stage of initialization, i.e. initialize video decoder.
655 SetState(kInitVideoDecoder);
656 if (InitializeVideoDecoder(demuxer_))
657 return;
658 }
659
660 // Assuming video decoder was created, create video renderer.
661 if (state_ == kInitVideoDecoder) {
662 SetState(kInitVideoRenderer); 646 SetState(kInitVideoRenderer);
663 if (InitializeVideoRenderer(pipeline_init_state_->video_decoder)) { 647 if (InitializeVideoRenderer(demuxer_->GetStream(DemuxerStream::VIDEO))) {
664 base::AutoLock auto_lock(lock_); 648 base::AutoLock auto_lock(lock_);
665 has_video_ = true; 649 has_video_ = true;
666 return; 650 return;
667 } 651 }
668 } 652 }
669 653
670 if (state_ == kInitVideoRenderer) { 654 if (state_ == kInitVideoRenderer) {
671 if (!IsPipelineOk() || !(HasAudio() || HasVideo())) { 655 if (!IsPipelineOk() || !(HasAudio() || HasVideo())) {
672 SetError(PIPELINE_ERROR_COULD_NOT_RENDER); 656 SetError(PIPELINE_ERROR_COULD_NOT_RENDER);
673 return; 657 return;
(...skipping 23 matching lines...) Expand all
697 // We stop the filters in the reverse order. 681 // We stop the filters in the reverse order.
698 // 682 //
699 // TODO(scherkus): beware! this can get posted multiple times since we post 683 // TODO(scherkus): beware! this can get posted multiple times since we post
700 // Stop() tasks even if we've already stopped. Perhaps this should no-op for 684 // Stop() tasks even if we've already stopped. Perhaps this should no-op for
701 // additional calls, however most of this logic will be changing. 685 // additional calls, however most of this logic will be changing.
702 void Pipeline::StopTask(const base::Closure& stop_cb) { 686 void Pipeline::StopTask(const base::Closure& stop_cb) {
703 DCHECK(message_loop_->BelongsToCurrentThread()); 687 DCHECK(message_loop_->BelongsToCurrentThread());
704 DCHECK(!IsPipelineStopPending()); 688 DCHECK(!IsPipelineStopPending());
705 DCHECK_NE(state_, kStopped); 689 DCHECK_NE(state_, kStopped);
706 690
707 if (video_decoder_) { 691 if (video_renderer_)
708 video_decoder_->PrepareForShutdownHack(); 692 video_renderer_->PrepareForShutdownHack();
709 video_decoder_ = NULL;
710 }
711 693
712 if (IsPipelineTearingDown() && error_caused_teardown_) { 694 if (IsPipelineTearingDown() && error_caused_teardown_) {
713 // If we are stopping due to SetError(), stop normally instead of 695 // If we are stopping due to SetError(), stop normally instead of
714 // going to error state and calling |error_cb_|. This converts 696 // going to error state and calling |error_cb_|. This converts
715 // the teardown in progress from an error teardown into one that acts 697 // the teardown in progress from an error teardown into one that acts
716 // like the error never occurred. 698 // like the error never occurred.
717 base::AutoLock auto_lock(lock_); 699 base::AutoLock auto_lock(lock_);
718 status_ = PIPELINE_OK; 700 status_ = PIPELINE_OK;
719 error_caused_teardown_ = false; 701 error_caused_teardown_ = false;
720 } 702 }
(...skipping 257 matching lines...) Expand 10 before | Expand all | Expand 10 after
978 case kFlushing: 960 case kFlushing:
979 SetState(kStopping); 961 SetState(kStopping);
980 DoStop(base::Bind(&Pipeline::OnTeardownStateTransition, this)); 962 DoStop(base::Bind(&Pipeline::OnTeardownStateTransition, this));
981 break; 963 break;
982 964
983 case kCreated: 965 case kCreated:
984 case kError: 966 case kError:
985 case kInitDemuxer: 967 case kInitDemuxer:
986 case kInitAudioDecoder: 968 case kInitAudioDecoder:
987 case kInitAudioRenderer: 969 case kInitAudioRenderer:
988 case kInitVideoDecoder:
989 case kInitVideoRenderer: 970 case kInitVideoRenderer:
990 case kSeeking: 971 case kSeeking:
991 case kStarting: 972 case kStarting:
992 case kStopped: 973 case kStopped:
993 case kStarted: 974 case kStarted:
994 case kEnded: 975 case kEnded:
995 NOTREACHED() << "Unexpected state for teardown: " << state_; 976 NOTREACHED() << "Unexpected state for teardown: " << state_;
996 break; 977 break;
997 // default: intentionally left out to force new states to cause compiler 978 // default: intentionally left out to force new states to cause compiler
998 // errors. 979 // errors.
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after
1079 return false; 1060 return false;
1080 } 1061 }
1081 1062
1082 pipeline_init_state_->audio_decoder->Initialize( 1063 pipeline_init_state_->audio_decoder->Initialize(
1083 stream, 1064 stream,
1084 base::Bind(&Pipeline::OnFilterInitialize, this), 1065 base::Bind(&Pipeline::OnFilterInitialize, this),
1085 base::Bind(&Pipeline::OnUpdateStatistics, this)); 1066 base::Bind(&Pipeline::OnUpdateStatistics, this));
1086 return true; 1067 return true;
1087 } 1068 }
1088 1069
1089 bool Pipeline::InitializeVideoDecoder(
1090 const scoped_refptr<Demuxer>& demuxer) {
1091 DCHECK(message_loop_->BelongsToCurrentThread());
1092 DCHECK(IsPipelineOk());
1093 DCHECK(demuxer);
1094
1095 scoped_refptr<DemuxerStream> stream =
1096 demuxer->GetStream(DemuxerStream::VIDEO);
1097
1098 if (!stream)
1099 return false;
1100
1101 filter_collection_->SelectVideoDecoder(&pipeline_init_state_->video_decoder);
1102
1103 if (!pipeline_init_state_->video_decoder) {
1104 SetError(PIPELINE_ERROR_REQUIRED_FILTER_MISSING);
1105 return false;
1106 }
1107
1108 pipeline_init_state_->video_decoder->Initialize(
1109 stream,
1110 base::Bind(&Pipeline::OnFilterInitialize, this),
1111 base::Bind(&Pipeline::OnUpdateStatistics, this));
1112
1113 video_decoder_ = pipeline_init_state_->video_decoder;
1114 return true;
1115 }
1116
1117 bool Pipeline::InitializeAudioRenderer( 1070 bool Pipeline::InitializeAudioRenderer(
1118 const scoped_refptr<AudioDecoder>& decoder) { 1071 const scoped_refptr<AudioDecoder>& decoder) {
1119 DCHECK(message_loop_->BelongsToCurrentThread()); 1072 DCHECK(message_loop_->BelongsToCurrentThread());
1120 DCHECK(IsPipelineOk()); 1073 DCHECK(IsPipelineOk());
1121 1074
1122 if (!decoder) 1075 if (!decoder)
1123 return false; 1076 return false;
1124 1077
1125 filter_collection_->SelectAudioRenderer(&audio_renderer_); 1078 filter_collection_->SelectAudioRenderer(&audio_renderer_);
1126 if (!audio_renderer_) { 1079 if (!audio_renderer_) {
1127 SetError(PIPELINE_ERROR_REQUIRED_FILTER_MISSING); 1080 SetError(PIPELINE_ERROR_REQUIRED_FILTER_MISSING);
1128 return false; 1081 return false;
1129 } 1082 }
1130 1083
1131 audio_renderer_->Initialize( 1084 audio_renderer_->Initialize(
1132 decoder, 1085 decoder,
1133 base::Bind(&Pipeline::OnFilterInitialize, this), 1086 base::Bind(&Pipeline::OnFilterInitialize, this),
1134 base::Bind(&Pipeline::OnAudioUnderflow, this), 1087 base::Bind(&Pipeline::OnAudioUnderflow, this),
1135 base::Bind(&Pipeline::OnAudioTimeUpdate, this), 1088 base::Bind(&Pipeline::OnAudioTimeUpdate, this),
1136 base::Bind(&Pipeline::OnRendererEnded, this), 1089 base::Bind(&Pipeline::OnRendererEnded, this),
1137 base::Bind(&Pipeline::OnAudioDisabled, this), 1090 base::Bind(&Pipeline::OnAudioDisabled, this),
1138 base::Bind(&Pipeline::SetError, this)); 1091 base::Bind(&Pipeline::SetError, this));
1139 return true; 1092 return true;
1140 } 1093 }
1141 1094
1142 bool Pipeline::InitializeVideoRenderer( 1095 bool Pipeline::InitializeVideoRenderer(
1143 const scoped_refptr<VideoDecoder>& decoder) { 1096 const scoped_refptr<DemuxerStream>& stream) {
1144 DCHECK(message_loop_->BelongsToCurrentThread()); 1097 DCHECK(message_loop_->BelongsToCurrentThread());
1145 DCHECK(IsPipelineOk()); 1098 DCHECK(IsPipelineOk());
1146 1099
1147 if (!decoder) 1100 if (!stream)
1148 return false; 1101 return false;
1149 1102
1150 filter_collection_->SelectVideoRenderer(&video_renderer_); 1103 filter_collection_->SelectVideoRenderer(&video_renderer_);
1151 if (!video_renderer_) { 1104 if (!video_renderer_) {
1152 SetError(PIPELINE_ERROR_REQUIRED_FILTER_MISSING); 1105 SetError(PIPELINE_ERROR_REQUIRED_FILTER_MISSING);
1153 return false; 1106 return false;
1154 } 1107 }
1155 1108
1156 video_renderer_->Initialize( 1109 video_renderer_->Initialize(
1157 decoder, 1110 stream,
1111 filter_collection_->GetVideoDecoders(),
1158 base::Bind(&Pipeline::OnFilterInitialize, this), 1112 base::Bind(&Pipeline::OnFilterInitialize, this),
1159 base::Bind(&Pipeline::OnUpdateStatistics, this), 1113 base::Bind(&Pipeline::OnUpdateStatistics, this),
1160 base::Bind(&Pipeline::OnVideoTimeUpdate, this), 1114 base::Bind(&Pipeline::OnVideoTimeUpdate, this),
1161 base::Bind(&Pipeline::OnNaturalVideoSizeChanged, this), 1115 base::Bind(&Pipeline::OnNaturalVideoSizeChanged, this),
1162 base::Bind(&Pipeline::OnRendererEnded, this), 1116 base::Bind(&Pipeline::OnRendererEnded, this),
1163 base::Bind(&Pipeline::SetError, this), 1117 base::Bind(&Pipeline::SetError, this),
1164 base::Bind(&Pipeline::GetMediaTime, this), 1118 base::Bind(&Pipeline::GetMediaTime, this),
1165 base::Bind(&Pipeline::GetMediaDuration, this)); 1119 base::Bind(&Pipeline::GetMediaDuration, this));
1120 filter_collection_->GetVideoDecoders().clear();
1166 return true; 1121 return true;
1167 } 1122 }
1168 1123
1169 void Pipeline::TearDownPipeline() { 1124 void Pipeline::TearDownPipeline() {
1170 DCHECK(message_loop_->BelongsToCurrentThread()); 1125 DCHECK(message_loop_->BelongsToCurrentThread());
1171 DCHECK_NE(kStopped, state_); 1126 DCHECK_NE(kStopped, state_);
1172 1127
1173 DCHECK(!tearing_down_ || // Teardown on Stop(). 1128 DCHECK(!tearing_down_ || // Teardown on Stop().
1174 (tearing_down_ && error_caused_teardown_) || // Teardown on error. 1129 (tearing_down_ && error_caused_teardown_) || // Teardown on error.
1175 (tearing_down_ && stop_pending_)); // Stop during teardown by error. 1130 (tearing_down_ && stop_pending_)); // Stop during teardown by error.
(...skipping 10 matching lines...) Expand all
1186 SetState(kStopped); 1141 SetState(kStopped);
1187 // Need to put this in the message loop to make sure that it comes 1142 // Need to put this in the message loop to make sure that it comes
1188 // after any pending callback tasks that are already queued. 1143 // after any pending callback tasks that are already queued.
1189 message_loop_->PostTask(FROM_HERE, base::Bind( 1144 message_loop_->PostTask(FROM_HERE, base::Bind(
1190 &Pipeline::FinishDestroyingFiltersTask, this)); 1145 &Pipeline::FinishDestroyingFiltersTask, this));
1191 break; 1146 break;
1192 1147
1193 case kInitDemuxer: 1148 case kInitDemuxer:
1194 case kInitAudioDecoder: 1149 case kInitAudioDecoder:
1195 case kInitAudioRenderer: 1150 case kInitAudioRenderer:
1196 case kInitVideoDecoder:
1197 case kInitVideoRenderer: 1151 case kInitVideoRenderer:
1198 // Make it look like initialization was successful. 1152 // Make it look like initialization was successful.
1199 filter_collection_.reset(); 1153 filter_collection_.reset();
1200 pipeline_init_state_.reset(); 1154 pipeline_init_state_.reset();
1201 1155
1202 SetState(kStopping); 1156 SetState(kStopping);
1203 DoStop(base::Bind(&Pipeline::OnTeardownStateTransition, this)); 1157 DoStop(base::Bind(&Pipeline::OnTeardownStateTransition, this));
1204 1158
1205 FinishInitialization(); 1159 FinishInitialization();
1206 break; 1160 break;
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
1276 void Pipeline::StartClockIfWaitingForTimeUpdate_Locked() { 1230 void Pipeline::StartClockIfWaitingForTimeUpdate_Locked() {
1277 lock_.AssertAcquired(); 1231 lock_.AssertAcquired();
1278 if (!waiting_for_clock_update_) 1232 if (!waiting_for_clock_update_)
1279 return; 1233 return;
1280 1234
1281 waiting_for_clock_update_ = false; 1235 waiting_for_clock_update_ = false;
1282 clock_->Play(); 1236 clock_->Play();
1283 } 1237 }
1284 1238
1285 } // namespace media 1239 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698