| OLD | NEW |
| 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 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 82 base::AutoLock auto_lock(lock_); | 82 base::AutoLock auto_lock(lock_); |
| 83 DCHECK(!running_) << "Stop() must complete before destroying object"; | 83 DCHECK(!running_) << "Stop() must complete before destroying object"; |
| 84 DCHECK(!stop_pending_); | 84 DCHECK(!stop_pending_); |
| 85 DCHECK(!seek_pending_); | 85 DCHECK(!seek_pending_); |
| 86 | 86 |
| 87 media_log_->AddEvent( | 87 media_log_->AddEvent( |
| 88 media_log_->CreateEvent(MediaLogEvent::PIPELINE_DESTROYED)); | 88 media_log_->CreateEvent(MediaLogEvent::PIPELINE_DESTROYED)); |
| 89 } | 89 } |
| 90 | 90 |
| 91 void Pipeline::Start(scoped_ptr<FilterCollection> collection, | 91 void Pipeline::Start(scoped_ptr<FilterCollection> collection, |
| 92 const std::string& url, | |
| 93 const PipelineStatusCB& ended_cb, | 92 const PipelineStatusCB& ended_cb, |
| 94 const PipelineStatusCB& error_cb, | 93 const PipelineStatusCB& error_cb, |
| 95 const NetworkEventCB& network_cb, | 94 const NetworkEventCB& network_cb, |
| 96 const PipelineStatusCB& start_cb) { | 95 const PipelineStatusCB& start_cb) { |
| 97 base::AutoLock auto_lock(lock_); | 96 base::AutoLock auto_lock(lock_); |
| 98 CHECK(!running_) << "Media pipeline is already running"; | 97 CHECK(!running_) << "Media pipeline is already running"; |
| 99 | 98 |
| 100 running_ = true; | 99 running_ = true; |
| 101 message_loop_->PostTask(FROM_HERE, base::Bind( | 100 message_loop_->PostTask(FROM_HERE, base::Bind( |
| 102 &Pipeline::StartTask, this, base::Passed(&collection), | 101 &Pipeline::StartTask, this, base::Passed(&collection), |
| 103 url, ended_cb, error_cb, network_cb, start_cb)); | 102 ended_cb, error_cb, network_cb, start_cb)); |
| 104 } | 103 } |
| 105 | 104 |
| 106 void Pipeline::Stop(const base::Closure& stop_cb) { | 105 void Pipeline::Stop(const base::Closure& stop_cb) { |
| 107 base::AutoLock auto_lock(lock_); | 106 base::AutoLock auto_lock(lock_); |
| 108 CHECK(running_) << "Media pipeline isn't running"; | 107 CHECK(running_) << "Media pipeline isn't running"; |
| 109 | 108 |
| 110 // Stop the pipeline, which will set |running_| to false on our behalf. | 109 // Stop the pipeline, which will set |running_| to false on our behalf. |
| 111 message_loop_->PostTask(FROM_HERE, base::Bind( | 110 message_loop_->PostTask(FROM_HERE, base::Bind( |
| 112 &Pipeline::StopTask, this, stop_cb)); | 111 &Pipeline::StopTask, this, stop_cb)); |
| 113 } | 112 } |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 183 return; | 182 return; |
| 184 | 183 |
| 185 base::AutoLock auto_lock(lock_); | 184 base::AutoLock auto_lock(lock_); |
| 186 volume_ = volume; | 185 volume_ = volume; |
| 187 if (running_ && !tearing_down_) { | 186 if (running_ && !tearing_down_) { |
| 188 message_loop_->PostTask(FROM_HERE, base::Bind( | 187 message_loop_->PostTask(FROM_HERE, base::Bind( |
| 189 &Pipeline::VolumeChangedTask, this, volume)); | 188 &Pipeline::VolumeChangedTask, this, volume)); |
| 190 } | 189 } |
| 191 } | 190 } |
| 192 | 191 |
| 193 Preload Pipeline::GetPreload() const { | |
| 194 base::AutoLock auto_lock(lock_); | |
| 195 return preload_; | |
| 196 } | |
| 197 | |
| 198 void Pipeline::SetPreload(Preload preload) { | |
| 199 base::AutoLock auto_lock(lock_); | |
| 200 preload_ = preload; | |
| 201 if (running_ && !tearing_down_) { | |
| 202 message_loop_->PostTask(FROM_HERE, base::Bind( | |
| 203 &Pipeline::PreloadChangedTask, this, preload)); | |
| 204 } | |
| 205 } | |
| 206 | |
| 207 base::TimeDelta Pipeline::GetCurrentTime() const { | 192 base::TimeDelta Pipeline::GetCurrentTime() const { |
| 208 base::AutoLock auto_lock(lock_); | 193 base::AutoLock auto_lock(lock_); |
| 209 return GetCurrentTime_Locked(); | 194 return GetCurrentTime_Locked(); |
| 210 } | 195 } |
| 211 | 196 |
| 212 base::TimeDelta Pipeline::GetCurrentTime_Locked() const { | 197 base::TimeDelta Pipeline::GetCurrentTime_Locked() const { |
| 213 lock_.AssertAcquired(); | 198 lock_.AssertAcquired(); |
| 214 return clock_->Elapsed(); | 199 return clock_->Elapsed(); |
| 215 } | 200 } |
| 216 | 201 |
| (...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 317 tearing_down_ = false; | 302 tearing_down_ = false; |
| 318 error_caused_teardown_ = false; | 303 error_caused_teardown_ = false; |
| 319 playback_rate_change_pending_ = false; | 304 playback_rate_change_pending_ = false; |
| 320 buffered_time_ = kZero; | 305 buffered_time_ = kZero; |
| 321 buffered_bytes_ = 0; | 306 buffered_bytes_ = 0; |
| 322 streaming_ = false; | 307 streaming_ = false; |
| 323 local_source_ = false; | 308 local_source_ = false; |
| 324 total_bytes_ = 0; | 309 total_bytes_ = 0; |
| 325 natural_size_.SetSize(0, 0); | 310 natural_size_.SetSize(0, 0); |
| 326 volume_ = 1.0f; | 311 volume_ = 1.0f; |
| 327 preload_ = AUTO; | |
| 328 playback_rate_ = 0.0f; | 312 playback_rate_ = 0.0f; |
| 329 pending_playback_rate_ = 0.0f; | 313 pending_playback_rate_ = 0.0f; |
| 330 status_ = PIPELINE_OK; | 314 status_ = PIPELINE_OK; |
| 331 has_audio_ = false; | 315 has_audio_ = false; |
| 332 has_video_ = false; | 316 has_video_ = false; |
| 333 waiting_for_clock_update_ = false; | 317 waiting_for_clock_update_ = false; |
| 334 audio_disabled_ = false; | 318 audio_disabled_ = false; |
| 335 clock_->Reset(); | 319 clock_->Reset(); |
| 336 download_rate_monitor_.Reset(); | 320 download_rate_monitor_.Reset(); |
| 337 } | 321 } |
| (...skipping 263 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 601 void Pipeline::OnUpdateStatistics(const PipelineStatistics& stats) { | 585 void Pipeline::OnUpdateStatistics(const PipelineStatistics& stats) { |
| 602 base::AutoLock auto_lock(lock_); | 586 base::AutoLock auto_lock(lock_); |
| 603 statistics_.audio_bytes_decoded += stats.audio_bytes_decoded; | 587 statistics_.audio_bytes_decoded += stats.audio_bytes_decoded; |
| 604 statistics_.video_bytes_decoded += stats.video_bytes_decoded; | 588 statistics_.video_bytes_decoded += stats.video_bytes_decoded; |
| 605 statistics_.video_frames_decoded += stats.video_frames_decoded; | 589 statistics_.video_frames_decoded += stats.video_frames_decoded; |
| 606 statistics_.video_frames_dropped += stats.video_frames_dropped; | 590 statistics_.video_frames_dropped += stats.video_frames_dropped; |
| 607 media_log_->QueueStatisticsUpdatedEvent(statistics_); | 591 media_log_->QueueStatisticsUpdatedEvent(statistics_); |
| 608 } | 592 } |
| 609 | 593 |
| 610 void Pipeline::StartTask(scoped_ptr<FilterCollection> filter_collection, | 594 void Pipeline::StartTask(scoped_ptr<FilterCollection> filter_collection, |
| 611 const std::string& url, | |
| 612 const PipelineStatusCB& ended_cb, | 595 const PipelineStatusCB& ended_cb, |
| 613 const PipelineStatusCB& error_cb, | 596 const PipelineStatusCB& error_cb, |
| 614 const NetworkEventCB& network_cb, | 597 const NetworkEventCB& network_cb, |
| 615 const PipelineStatusCB& start_cb) { | 598 const PipelineStatusCB& start_cb) { |
| 616 DCHECK_EQ(MessageLoop::current(), message_loop_); | 599 DCHECK_EQ(MessageLoop::current(), message_loop_); |
| 617 DCHECK_EQ(kCreated, state_); | 600 DCHECK_EQ(kCreated, state_); |
| 618 filter_collection_ = filter_collection.Pass(); | 601 filter_collection_ = filter_collection.Pass(); |
| 619 url_ = url; | |
| 620 ended_cb_ = ended_cb; | 602 ended_cb_ = ended_cb; |
| 621 error_cb_ = error_cb; | 603 error_cb_ = error_cb; |
| 622 network_cb_ = network_cb; | 604 network_cb_ = network_cb; |
| 623 seek_cb_ = start_cb; | 605 seek_cb_ = start_cb; |
| 624 | 606 |
| 625 // Kick off initialization. | 607 // Kick off initialization. |
| 626 pipeline_init_state_.reset(new PipelineInitState()); | 608 pipeline_init_state_.reset(new PipelineInitState()); |
| 627 pipeline_init_state_->composite = new CompositeFilter(message_loop_); | 609 pipeline_init_state_->composite = new CompositeFilter(message_loop_); |
| 628 pipeline_init_state_->composite->set_host(this); | 610 pipeline_init_state_->composite->set_host(this); |
| 629 | 611 |
| (...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 725 | 707 |
| 726 if (audio_disabled_) { | 708 if (audio_disabled_) { |
| 727 // Audio was disabled at some point during initialization. Notify | 709 // Audio was disabled at some point during initialization. Notify |
| 728 // the pipeline filter now that it has been initialized. | 710 // the pipeline filter now that it has been initialized. |
| 729 demuxer_->OnAudioRendererDisabled(); | 711 demuxer_->OnAudioRendererDisabled(); |
| 730 pipeline_filter_->OnAudioRendererDisabled(); | 712 pipeline_filter_->OnAudioRendererDisabled(); |
| 731 } | 713 } |
| 732 | 714 |
| 733 // Initialization was successful, we are now considered paused, so it's safe | 715 // Initialization was successful, we are now considered paused, so it's safe |
| 734 // to set the initial playback rate and volume. | 716 // to set the initial playback rate and volume. |
| 735 PreloadChangedTask(GetPreload()); | |
| 736 PlaybackRateChangedTask(GetPlaybackRate()); | 717 PlaybackRateChangedTask(GetPlaybackRate()); |
| 737 VolumeChangedTask(GetVolume()); | 718 VolumeChangedTask(GetVolume()); |
| 738 | 719 |
| 739 // Fire the seek request to get the filters to preroll. | 720 // Fire the seek request to get the filters to preroll. |
| 740 seek_pending_ = true; | 721 seek_pending_ = true; |
| 741 SetState(kSeeking); | 722 SetState(kSeeking); |
| 742 seek_timestamp_ = demuxer_->GetStartTime(); | 723 seek_timestamp_ = demuxer_->GetStartTime(); |
| 743 DoSeek(seek_timestamp_); | 724 DoSeek(seek_timestamp_); |
| 744 } | 725 } |
| 745 } | 726 } |
| (...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 837 | 818 |
| 838 void Pipeline::VolumeChangedTask(float volume) { | 819 void Pipeline::VolumeChangedTask(float volume) { |
| 839 DCHECK_EQ(MessageLoop::current(), message_loop_); | 820 DCHECK_EQ(MessageLoop::current(), message_loop_); |
| 840 if (!running_ || tearing_down_) | 821 if (!running_ || tearing_down_) |
| 841 return; | 822 return; |
| 842 | 823 |
| 843 if (audio_renderer_) | 824 if (audio_renderer_) |
| 844 audio_renderer_->SetVolume(volume); | 825 audio_renderer_->SetVolume(volume); |
| 845 } | 826 } |
| 846 | 827 |
| 847 void Pipeline::PreloadChangedTask(Preload preload) { | |
| 848 DCHECK_EQ(MessageLoop::current(), message_loop_); | |
| 849 if (!running_ || tearing_down_) | |
| 850 return; | |
| 851 | |
| 852 if (demuxer_) | |
| 853 demuxer_->SetPreload(preload); | |
| 854 } | |
| 855 | |
| 856 void Pipeline::SeekTask(base::TimeDelta time, | 828 void Pipeline::SeekTask(base::TimeDelta time, |
| 857 const PipelineStatusCB& seek_cb) { | 829 const PipelineStatusCB& seek_cb) { |
| 858 DCHECK_EQ(MessageLoop::current(), message_loop_); | 830 DCHECK_EQ(MessageLoop::current(), message_loop_); |
| 859 DCHECK(!IsPipelineStopPending()); | 831 DCHECK(!IsPipelineStopPending()); |
| 860 | 832 |
| 861 // Suppress seeking if we're not fully started. | 833 // Suppress seeking if we're not fully started. |
| 862 if (state_ != kStarted && state_ != kEnded) { | 834 if (state_ != kStarted && state_ != kEnded) { |
| 863 // TODO(scherkus): should we run the callback? I'm tempted to say the API | 835 // TODO(scherkus): should we run the callback? I'm tempted to say the API |
| 864 // will only execute the first Seek() request. | 836 // will only execute the first Seek() request. |
| 865 VLOG(1) << "Media pipeline has not started, ignoring seek to " | 837 VLOG(1) << "Media pipeline has not started, ignoring seek to " |
| (...skipping 240 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1106 } | 1078 } |
| 1107 | 1079 |
| 1108 tearing_down_ = false; | 1080 tearing_down_ = false; |
| 1109 error_caused_teardown_ = false; | 1081 error_caused_teardown_ = false; |
| 1110 } | 1082 } |
| 1111 | 1083 |
| 1112 void Pipeline::InitializeDemuxer() { | 1084 void Pipeline::InitializeDemuxer() { |
| 1113 DCHECK_EQ(MessageLoop::current(), message_loop_); | 1085 DCHECK_EQ(MessageLoop::current(), message_loop_); |
| 1114 DCHECK(IsPipelineOk()); | 1086 DCHECK(IsPipelineOk()); |
| 1115 | 1087 |
| 1116 filter_collection_->GetDemuxerFactory()->Build( | 1088 demuxer_ = filter_collection_->GetDemuxer(); |
| 1117 url_, base::Bind(&Pipeline::OnDemuxerBuilt, this)); | 1089 if (!demuxer_) { |
| 1118 } | 1090 SetError(PIPELINE_ERROR_REQUIRED_FILTER_MISSING); |
| 1119 | |
| 1120 void Pipeline::OnDemuxerBuilt(PipelineStatus status, Demuxer* demuxer) { | |
| 1121 if (MessageLoop::current() != message_loop_) { | |
| 1122 message_loop_->PostTask(FROM_HERE, base::Bind( | |
| 1123 &Pipeline::OnDemuxerBuilt, this, status, make_scoped_refptr(demuxer))); | |
| 1124 return; | 1091 return; |
| 1125 } | 1092 } |
| 1126 | 1093 |
| 1127 demuxer_ = demuxer; | 1094 demuxer_->set_host(this); |
| 1095 demuxer_->Initialize(base::Bind(&Pipeline::OnDemuxerInitialized, this)); |
| 1096 } |
| 1097 |
| 1098 void Pipeline::OnDemuxerInitialized(PipelineStatus status) { |
| 1099 if (MessageLoop::current() != message_loop_) { |
| 1100 message_loop_->PostTask(FROM_HERE, base::Bind( |
| 1101 &Pipeline::OnDemuxerInitialized, this, status)); |
| 1102 return; |
| 1103 } |
| 1104 |
| 1128 if (status != PIPELINE_OK) { | 1105 if (status != PIPELINE_OK) { |
| 1129 SetError(status); | 1106 SetError(status); |
| 1130 return; | 1107 return; |
| 1131 } | 1108 } |
| 1132 | 1109 |
| 1133 CHECK(demuxer_) << "Null demuxer encountered despite PIPELINE_OK."; | |
| 1134 demuxer_->set_host(this); | |
| 1135 | |
| 1136 { | 1110 { |
| 1137 base::AutoLock auto_lock(lock_); | 1111 base::AutoLock auto_lock(lock_); |
| 1138 // We do not want to start the clock running. We only want to set the base | 1112 // We do not want to start the clock running. We only want to set the base |
| 1139 // media time so our timestamp calculations will be correct. | 1113 // media time so our timestamp calculations will be correct. |
| 1140 clock_->SetTime(demuxer_->GetStartTime(), demuxer_->GetStartTime()); | 1114 clock_->SetTime(demuxer_->GetStartTime(), demuxer_->GetStartTime()); |
| 1141 } | 1115 } |
| 1142 | 1116 |
| 1143 OnFilterInitialize(PIPELINE_OK); | 1117 OnFilterInitialize(PIPELINE_OK); |
| 1144 } | 1118 } |
| 1145 | 1119 |
| (...skipping 251 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1397 void Pipeline::StartClockIfWaitingForTimeUpdate_Locked() { | 1371 void Pipeline::StartClockIfWaitingForTimeUpdate_Locked() { |
| 1398 lock_.AssertAcquired(); | 1372 lock_.AssertAcquired(); |
| 1399 if (!waiting_for_clock_update_) | 1373 if (!waiting_for_clock_update_) |
| 1400 return; | 1374 return; |
| 1401 | 1375 |
| 1402 waiting_for_clock_update_ = false; | 1376 waiting_for_clock_update_ = false; |
| 1403 clock_->Play(); | 1377 clock_->Play(); |
| 1404 } | 1378 } |
| 1405 | 1379 |
| 1406 } // namespace media | 1380 } // namespace media |
| OLD | NEW |