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

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

Issue 9325044: Remove AudioDecoder from the Filter heirarchy. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: CR responses. Created 8 years, 10 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_status.h » ('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/compiler_specific.h" 11 #include "base/compiler_specific.h"
12 #include "base/metrics/histogram.h" 12 #include "base/metrics/histogram.h"
13 #include "base/message_loop.h" 13 #include "base/message_loop.h"
14 #include "base/stl_util.h" 14 #include "base/stl_util.h"
15 #include "base/string_util.h" 15 #include "base/string_util.h"
16 #include "base/synchronization/condition_variable.h" 16 #include "base/synchronization/condition_variable.h"
17 #include "media/base/audio_decoder.h"
17 #include "media/base/clock.h" 18 #include "media/base/clock.h"
18 #include "media/base/composite_filter.h" 19 #include "media/base/composite_filter.h"
20 #include "media/base/composite_filter.h"
19 #include "media/base/filter_collection.h" 21 #include "media/base/filter_collection.h"
22 #include "media/base/filters.h"
20 #include "media/base/media_log.h" 23 #include "media/base/media_log.h"
21 24
22 namespace media { 25 namespace media {
23 26
24 PipelineStatusNotification::PipelineStatusNotification() 27 PipelineStatusNotification::PipelineStatusNotification()
25 : cv_(&lock_), status_(PIPELINE_OK), notified_(false) { 28 : cv_(&lock_), status_(PIPELINE_OK), notified_(false) {
26 } 29 }
27 30
28 PipelineStatusNotification::~PipelineStatusNotification() { 31 PipelineStatusNotification::~PipelineStatusNotification() {
29 DCHECK(notified_); 32 DCHECK(notified_);
(...skipping 17 matching lines...) Expand all
47 while (!notified_) 50 while (!notified_)
48 cv_.Wait(); 51 cv_.Wait();
49 } 52 }
50 53
51 media::PipelineStatus PipelineStatusNotification::status() { 54 media::PipelineStatus PipelineStatusNotification::status() {
52 base::AutoLock auto_lock(lock_); 55 base::AutoLock auto_lock(lock_);
53 DCHECK(notified_); 56 DCHECK(notified_);
54 return status_; 57 return status_;
55 } 58 }
56 59
57 class Pipeline::PipelineInitState { 60 struct Pipeline::PipelineInitState {
58 public: 61 scoped_refptr<AudioDecoder> audio_decoder;
59 scoped_refptr<AudioDecoder> audio_decoder_; 62 scoped_refptr<VideoDecoder> video_decoder;
60 scoped_refptr<VideoDecoder> video_decoder_; 63 scoped_refptr<CompositeFilter> composite;
61 scoped_refptr<CompositeFilter> composite_;
62 }; 64 };
63 65
64 Pipeline::Pipeline(MessageLoop* message_loop, MediaLog* media_log) 66 Pipeline::Pipeline(MessageLoop* message_loop, MediaLog* media_log)
65 : message_loop_(message_loop), 67 : message_loop_(message_loop),
66 media_log_(media_log), 68 media_log_(media_log),
67 clock_(new Clock(&base::Time::Now)), 69 clock_(new Clock(&base::Time::Now)),
68 waiting_for_clock_update_(false), 70 waiting_for_clock_update_(false),
69 state_(kCreated), 71 state_(kCreated),
70 current_bytes_(0), 72 current_bytes_(0),
71 creation_time_(base::Time::Now()), 73 creation_time_(base::Time::Now()),
(...skipping 542 matching lines...) Expand 10 before | Expand all | Expand 10 after
614 DCHECK_EQ(kCreated, state_); 616 DCHECK_EQ(kCreated, state_);
615 filter_collection_ = filter_collection.Pass(); 617 filter_collection_ = filter_collection.Pass();
616 url_ = url; 618 url_ = url;
617 ended_callback_ = ended_callback; 619 ended_callback_ = ended_callback;
618 error_callback_ = error_callback; 620 error_callback_ = error_callback;
619 network_callback_ = network_callback; 621 network_callback_ = network_callback;
620 seek_callback_ = start_callback; 622 seek_callback_ = start_callback;
621 623
622 // Kick off initialization. 624 // Kick off initialization.
623 pipeline_init_state_.reset(new PipelineInitState()); 625 pipeline_init_state_.reset(new PipelineInitState());
624 pipeline_init_state_->composite_ = new CompositeFilter(message_loop_); 626 pipeline_init_state_->composite = new CompositeFilter(message_loop_);
625 pipeline_init_state_->composite_->set_host(this); 627 pipeline_init_state_->composite->set_host(this);
626 628
627 SetState(kInitDemuxer); 629 SetState(kInitDemuxer);
628 InitializeDemuxer(); 630 InitializeDemuxer();
629 } 631 }
630 632
631 // Main initialization method called on the pipeline thread. This code attempts 633 // Main initialization method called on the pipeline thread. This code attempts
632 // to use the specified filter factory to build a pipeline. 634 // to use the specified filter factory to build a pipeline.
633 // Initialization step performed in this method depends on current state of this 635 // Initialization step performed in this method depends on current state of this
634 // object, indicated by |state_|. After each step of initialization, this 636 // object, indicated by |state_|. After each step of initialization, this
635 // object transits to the next stage. It starts by creating a Demuxer, and then 637 // object transits to the next stage. It starts by creating a Demuxer, and then
636 // connects the Demuxer's audio stream to an AudioDecoder which is then 638 // connects the Demuxer's audio stream to an AudioDecoder which is then
637 // connected to an AudioRenderer. If the media has video, then it connects a 639 // connected to an AudioRenderer. If the media has video, then it connects a
638 // VideoDecoder to the Demuxer's video stream, and then connects the 640 // VideoDecoder to the Demuxer's video stream, and then connects the
639 // VideoDecoder to a VideoRenderer. 641 // VideoDecoder to a VideoRenderer.
640 // 642 //
641 // When all required filters have been created and have called their 643 // When all required filters have been created and have called their
642 // FilterHost's InitializationComplete() method, the pipeline will update its 644 // FilterHost's InitializationComplete() method, the pipeline will update its
643 // state to kStarted and |init_callback_|, will be executed. 645 // state to kStarted and |init_callback_|, will be executed.
644 // 646 //
645 // TODO(hclam): InitializeTask() is now starting the pipeline asynchronously. It 647 // TODO(hclam): InitializeTask() is now starting the pipeline asynchronously. It
646 // works like a big state change table. If we no longer need to start filters 648 // works like a big state change table. If we no longer need to start filters
647 // in order, we need to get rid of all the state change. 649 // in order, we need to get rid of all the state change.
648 void Pipeline::InitializeTask(PipelineStatus last_stage_status) { 650 void Pipeline::InitializeTask(PipelineStatus last_stage_status) {
649 DCHECK_EQ(MessageLoop::current(), message_loop_); 651 DCHECK_EQ(MessageLoop::current(), message_loop_);
650 652
651 if (last_stage_status != PIPELINE_OK) { 653 if (last_stage_status != PIPELINE_OK) {
652 // Currently only VideoDecoders have a recoverable error code. 654 // Currently only VideoDecoders have a recoverable error code.
653 if (state_ == kInitVideoDecoder && 655 if (state_ == kInitVideoDecoder &&
654 last_stage_status == DECODER_ERROR_NOT_SUPPORTED) { 656 last_stage_status == DECODER_ERROR_NOT_SUPPORTED) {
655 pipeline_init_state_->composite_->RemoveFilter( 657 pipeline_init_state_->composite->RemoveFilter(
656 pipeline_init_state_->video_decoder_.get()); 658 pipeline_init_state_->video_decoder.get());
657 state_ = kInitAudioRenderer; 659 state_ = kInitAudioRenderer;
658 } else { 660 } else {
659 SetError(last_stage_status); 661 SetError(last_stage_status);
660 } 662 }
661 } 663 }
662 664
663 // If we have received the stop or error signal, return immediately. 665 // If we have received the stop or error signal, return immediately.
664 if (IsPipelineStopPending() || IsPipelineStopped() || !IsPipelineOk()) 666 if (IsPipelineStopPending() || IsPipelineStopped() || !IsPipelineOk())
665 return; 667 return;
666 668
667 DCHECK(state_ == kInitDemuxer || 669 DCHECK(state_ == kInitDemuxer ||
668 state_ == kInitAudioDecoder || 670 state_ == kInitAudioDecoder ||
669 state_ == kInitAudioRenderer || 671 state_ == kInitAudioRenderer ||
670 state_ == kInitVideoDecoder || 672 state_ == kInitVideoDecoder ||
671 state_ == kInitVideoRenderer); 673 state_ == kInitVideoRenderer);
672 674
673 // Demuxer created, create audio decoder. 675 // Demuxer created, create audio decoder.
674 if (state_ == kInitDemuxer) { 676 if (state_ == kInitDemuxer) {
675 SetState(kInitAudioDecoder); 677 SetState(kInitAudioDecoder);
676 // If this method returns false, then there's no audio stream. 678 // If this method returns false, then there's no audio stream.
677 if (InitializeAudioDecoder(demuxer_)) 679 if (InitializeAudioDecoder(demuxer_))
678 return; 680 return;
679 } 681 }
680 682
681 // Assuming audio decoder was created, create audio renderer. 683 // Assuming audio decoder was created, create audio renderer.
682 if (state_ == kInitAudioDecoder) { 684 if (state_ == kInitAudioDecoder) {
683 SetState(kInitAudioRenderer); 685 SetState(kInitAudioRenderer);
684 686
685 // Returns false if there's no audio stream. 687 // Returns false if there's no audio stream.
686 if (InitializeAudioRenderer(pipeline_init_state_->audio_decoder_)) { 688 if (InitializeAudioRenderer(pipeline_init_state_->audio_decoder)) {
687 base::AutoLock auto_lock(lock_); 689 base::AutoLock auto_lock(lock_);
688 has_audio_ = true; 690 has_audio_ = true;
689 return; 691 return;
690 } 692 }
691 } 693 }
692 694
693 // Assuming audio renderer was created, create video decoder. 695 // Assuming audio renderer was created, create video decoder.
694 if (state_ == kInitAudioRenderer) { 696 if (state_ == kInitAudioRenderer) {
695 // Then perform the stage of initialization, i.e. initialize video decoder. 697 // Then perform the stage of initialization, i.e. initialize video decoder.
696 SetState(kInitVideoDecoder); 698 SetState(kInitVideoDecoder);
697 if (InitializeVideoDecoder(demuxer_)) 699 if (InitializeVideoDecoder(demuxer_))
698 return; 700 return;
699 } 701 }
700 702
701 // Assuming video decoder was created, create video renderer. 703 // Assuming video decoder was created, create video renderer.
702 if (state_ == kInitVideoDecoder) { 704 if (state_ == kInitVideoDecoder) {
703 SetState(kInitVideoRenderer); 705 SetState(kInitVideoRenderer);
704 if (InitializeVideoRenderer(pipeline_init_state_->video_decoder_)) { 706 if (InitializeVideoRenderer(pipeline_init_state_->video_decoder)) {
705 base::AutoLock auto_lock(lock_); 707 base::AutoLock auto_lock(lock_);
706 has_video_ = true; 708 has_video_ = true;
707 return; 709 return;
708 } 710 }
709 } 711 }
710 712
711 if (state_ == kInitVideoRenderer) { 713 if (state_ == kInitVideoRenderer) {
712 if (!IsPipelineOk() || !(HasAudio() || HasVideo())) { 714 if (!IsPipelineOk() || !(HasAudio() || HasVideo())) {
713 SetError(PIPELINE_ERROR_COULD_NOT_RENDER); 715 SetError(PIPELINE_ERROR_COULD_NOT_RENDER);
714 return; 716 return;
715 } 717 }
716 718
717 // Clear the collection of filters. 719 // Clear the collection of filters.
718 filter_collection_->Clear(); 720 filter_collection_->Clear();
719 721
720 pipeline_filter_ = pipeline_init_state_->composite_; 722 pipeline_filter_ = pipeline_init_state_->composite;
721 723
722 // Clear init state since we're done initializing. 724 // Clear init state since we're done initializing.
723 pipeline_init_state_.reset(); 725 pipeline_init_state_.reset();
724 726
725 if (audio_disabled_) { 727 if (audio_disabled_) {
726 // Audio was disabled at some point during initialization. Notify 728 // Audio was disabled at some point during initialization. Notify
727 // the pipeline filter now that it has been initialized. 729 // the pipeline filter now that it has been initialized.
728 demuxer_->OnAudioRendererDisabled(); 730 demuxer_->OnAudioRendererDisabled();
729 pipeline_filter_->OnAudioRendererDisabled(); 731 pipeline_filter_->OnAudioRendererDisabled();
730 } 732 }
(...skipping 291 matching lines...) Expand 10 before | Expand all | Expand 10 after
1022 // We use audio stream to update the clock. So if there is such a stream, 1024 // We use audio stream to update the clock. So if there is such a stream,
1023 // we pause the clock until we receive a valid timestamp. 1025 // we pause the clock until we receive a valid timestamp.
1024 waiting_for_clock_update_ = true; 1026 waiting_for_clock_update_ = true;
1025 if (!has_audio_) { 1027 if (!has_audio_) {
1026 clock_->SetMaxTime(clock_->Duration()); 1028 clock_->SetMaxTime(clock_->Duration());
1027 StartClockIfWaitingForTimeUpdate_Locked(); 1029 StartClockIfWaitingForTimeUpdate_Locked();
1028 } 1030 }
1029 1031
1030 // Start monitoring rate of downloading. 1032 // Start monitoring rate of downloading.
1031 int bitrate = 0; 1033 int bitrate = 0;
1032 if (demuxer_.get()) { 1034 if (demuxer_) {
1033 bitrate = demuxer_->GetBitrate(); 1035 bitrate = demuxer_->GetBitrate();
1034 local_source_ = demuxer_->IsLocalSource(); 1036 local_source_ = demuxer_->IsLocalSource();
1035 streaming_ = !demuxer_->IsSeekable(); 1037 streaming_ = !demuxer_->IsSeekable();
1036 } 1038 }
1037 // Needs to be locked because most other calls to |download_rate_monitor_| 1039 // Needs to be locked because most other calls to |download_rate_monitor_|
1038 // occur on the renderer thread. 1040 // occur on the renderer thread.
1039 download_rate_monitor_.Start( 1041 download_rate_monitor_.Start(
1040 base::Bind(&Pipeline::OnCanPlayThrough, this), 1042 base::Bind(&Pipeline::OnCanPlayThrough, this),
1041 bitrate, streaming_, local_source_); 1043 bitrate, streaming_, local_source_);
1042 download_rate_monitor_.SetBufferedBytes(buffered_bytes_, base::Time::Now()); 1044 download_rate_monitor_.SetBufferedBytes(buffered_bytes_, base::Time::Now());
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
1109 if (!stop_cb.is_null()) { 1111 if (!stop_cb.is_null()) {
1110 stop_cb.Run(status_); 1112 stop_cb.Run(status_);
1111 } 1113 }
1112 } 1114 }
1113 1115
1114 tearing_down_ = false; 1116 tearing_down_ = false;
1115 error_caused_teardown_ = false; 1117 error_caused_teardown_ = false;
1116 } 1118 }
1117 1119
1118 bool Pipeline::PrepareFilter(scoped_refptr<Filter> filter) { 1120 bool Pipeline::PrepareFilter(scoped_refptr<Filter> filter) {
1119 bool ret = pipeline_init_state_->composite_->AddFilter(filter.get()); 1121 bool ret = pipeline_init_state_->composite->AddFilter(filter.get());
1120 if (!ret) 1122 if (!ret)
1121 SetError(PIPELINE_ERROR_INITIALIZATION_FAILED); 1123 SetError(PIPELINE_ERROR_INITIALIZATION_FAILED);
1122 return ret; 1124 return ret;
1123 } 1125 }
1124 1126
1125 void Pipeline::InitializeDemuxer() { 1127 void Pipeline::InitializeDemuxer() {
1126 DCHECK_EQ(MessageLoop::current(), message_loop_); 1128 DCHECK_EQ(MessageLoop::current(), message_loop_);
1127 DCHECK(IsPipelineOk()); 1129 DCHECK(IsPipelineOk());
1128 1130
1129 filter_collection_->GetDemuxerFactory()->Build( 1131 filter_collection_->GetDemuxerFactory()->Build(
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
1164 const scoped_refptr<Demuxer>& demuxer) { 1166 const scoped_refptr<Demuxer>& demuxer) {
1165 DCHECK_EQ(MessageLoop::current(), message_loop_); 1167 DCHECK_EQ(MessageLoop::current(), message_loop_);
1166 DCHECK(IsPipelineOk()); 1168 DCHECK(IsPipelineOk());
1167 1169
1168 scoped_refptr<DemuxerStream> stream = 1170 scoped_refptr<DemuxerStream> stream =
1169 demuxer->GetStream(DemuxerStream::AUDIO); 1171 demuxer->GetStream(DemuxerStream::AUDIO);
1170 1172
1171 if (!stream) 1173 if (!stream)
1172 return false; 1174 return false;
1173 1175
1174 scoped_refptr<AudioDecoder> audio_decoder; 1176 filter_collection_->SelectAudioDecoder(&pipeline_init_state_->audio_decoder);
1175 filter_collection_->SelectAudioDecoder(&audio_decoder);
1176 1177
1177 if (!audio_decoder) { 1178 if (!pipeline_init_state_->audio_decoder) {
1178 SetError(PIPELINE_ERROR_REQUIRED_FILTER_MISSING); 1179 SetError(PIPELINE_ERROR_REQUIRED_FILTER_MISSING);
1179 return false; 1180 return false;
1180 } 1181 }
1181 1182
1182 if (!PrepareFilter(audio_decoder)) 1183 pipeline_init_state_->audio_decoder->Initialize(
1183 return false;
1184
1185 pipeline_init_state_->audio_decoder_ = audio_decoder;
1186 audio_decoder->Initialize(
1187 stream, 1184 stream,
1188 base::Bind(&Pipeline::OnFilterInitialize, this), 1185 base::Bind(&Pipeline::OnFilterInitialize, this),
1189 base::Bind(&Pipeline::OnUpdateStatistics, this)); 1186 base::Bind(&Pipeline::OnUpdateStatistics, this));
1190 return true; 1187 return true;
1191 } 1188 }
1192 1189
1193 bool Pipeline::InitializeVideoDecoder( 1190 bool Pipeline::InitializeVideoDecoder(
1194 const scoped_refptr<Demuxer>& demuxer) { 1191 const scoped_refptr<Demuxer>& demuxer) {
1195 DCHECK_EQ(MessageLoop::current(), message_loop_); 1192 DCHECK_EQ(MessageLoop::current(), message_loop_);
1196 DCHECK(IsPipelineOk()); 1193 DCHECK(IsPipelineOk());
(...skipping 10 matching lines...) Expand all
1207 filter_collection_->SelectVideoDecoder(&video_decoder_); 1204 filter_collection_->SelectVideoDecoder(&video_decoder_);
1208 1205
1209 if (!video_decoder_) { 1206 if (!video_decoder_) {
1210 SetError(PIPELINE_ERROR_REQUIRED_FILTER_MISSING); 1207 SetError(PIPELINE_ERROR_REQUIRED_FILTER_MISSING);
1211 return false; 1208 return false;
1212 } 1209 }
1213 1210
1214 if (!PrepareFilter(video_decoder_)) 1211 if (!PrepareFilter(video_decoder_))
1215 return false; 1212 return false;
1216 1213
1217 pipeline_init_state_->video_decoder_ = video_decoder_; 1214 pipeline_init_state_->video_decoder = video_decoder_;
1218 video_decoder_->Initialize( 1215 video_decoder_->Initialize(
1219 stream, 1216 stream,
1220 base::Bind(&Pipeline::OnFilterInitialize, this), 1217 base::Bind(&Pipeline::OnFilterInitialize, this),
1221 base::Bind(&Pipeline::OnUpdateStatistics, this)); 1218 base::Bind(&Pipeline::OnUpdateStatistics, this));
1222 return true; 1219 return true;
1223 } 1220 }
1224 1221
1225 bool Pipeline::InitializeAudioRenderer( 1222 bool Pipeline::InitializeAudioRenderer(
1226 const scoped_refptr<AudioDecoder>& decoder) { 1223 const scoped_refptr<AudioDecoder>& decoder) {
1227 DCHECK_EQ(MessageLoop::current(), message_loop_); 1224 DCHECK_EQ(MessageLoop::current(), message_loop_);
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
1293 message_loop_->PostTask(FROM_HERE, base::Bind( 1290 message_loop_->PostTask(FROM_HERE, base::Bind(
1294 &Pipeline::FinishDestroyingFiltersTask, this)); 1291 &Pipeline::FinishDestroyingFiltersTask, this));
1295 break; 1292 break;
1296 1293
1297 case kInitDemuxer: 1294 case kInitDemuxer:
1298 case kInitAudioDecoder: 1295 case kInitAudioDecoder:
1299 case kInitAudioRenderer: 1296 case kInitAudioRenderer:
1300 case kInitVideoDecoder: 1297 case kInitVideoDecoder:
1301 case kInitVideoRenderer: 1298 case kInitVideoRenderer:
1302 // Make it look like initialization was successful. 1299 // Make it look like initialization was successful.
1303 pipeline_filter_ = pipeline_init_state_->composite_; 1300 pipeline_filter_ = pipeline_init_state_->composite;
1304 pipeline_init_state_.reset(); 1301 pipeline_init_state_.reset();
1305 filter_collection_.reset(); 1302 filter_collection_.reset();
1306 1303
1307 SetState(kStopping); 1304 SetState(kStopping);
1308 DoStop(base::Bind(&Pipeline::OnTeardownStateTransition, this)); 1305 DoStop(base::Bind(&Pipeline::OnTeardownStateTransition, this));
1309 1306
1310 FinishInitialization(); 1307 FinishInitialization();
1311 break; 1308 break;
1312 1309
1313 case kPausing: 1310 case kPausing:
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after
1425 void Pipeline::StartClockIfWaitingForTimeUpdate_Locked() { 1422 void Pipeline::StartClockIfWaitingForTimeUpdate_Locked() {
1426 lock_.AssertAcquired(); 1423 lock_.AssertAcquired();
1427 if (!waiting_for_clock_update_) 1424 if (!waiting_for_clock_update_)
1428 return; 1425 return;
1429 1426
1430 waiting_for_clock_update_ = false; 1427 waiting_for_clock_update_ = false;
1431 clock_->Play(); 1428 clock_->Play();
1432 } 1429 }
1433 1430
1434 } // namespace media 1431 } // namespace media
OLDNEW
« no previous file with comments | « media/base/pipeline.h ('k') | media/base/pipeline_status.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698