Chromium Code Reviews| 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 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 77 playback_rate_change_pending_(false), | 77 playback_rate_change_pending_(false), |
| 78 did_loading_progress_(false), | 78 did_loading_progress_(false), |
| 79 total_bytes_(0), | 79 total_bytes_(0), |
| 80 natural_size_(0, 0), | 80 natural_size_(0, 0), |
| 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), | |
| 88 has_video_(false), | |
| 89 state_(kCreated), | 87 state_(kCreated), |
| 90 seek_timestamp_(kNoTimestamp()), | 88 seek_timestamp_(kNoTimestamp()), |
| 91 audio_ended_(false), | 89 audio_ended_(false), |
| 92 video_ended_(false), | 90 video_ended_(false), |
| 93 audio_disabled_(false), | 91 audio_disabled_(false), |
| 94 creation_time_(base::Time::Now()) { | 92 creation_time_(base::Time::Now()) { |
| 95 media_log_->AddEvent(media_log_->CreatePipelineStateChangedEvent(kCreated)); | 93 media_log_->AddEvent(media_log_->CreatePipelineStateChangedEvent(kCreated)); |
| 96 media_log_->AddEvent( | 94 media_log_->AddEvent( |
| 97 media_log_->CreateEvent(MediaLogEvent::PIPELINE_CREATED)); | 95 media_log_->CreateEvent(MediaLogEvent::PIPELINE_CREATED)); |
| 98 } | 96 } |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 139 &Pipeline::SeekTask, this, time, seek_cb)); | 137 &Pipeline::SeekTask, this, time, seek_cb)); |
| 140 } | 138 } |
| 141 | 139 |
| 142 bool Pipeline::IsRunning() const { | 140 bool Pipeline::IsRunning() const { |
| 143 base::AutoLock auto_lock(lock_); | 141 base::AutoLock auto_lock(lock_); |
| 144 return running_; | 142 return running_; |
| 145 } | 143 } |
| 146 | 144 |
| 147 bool Pipeline::HasAudio() const { | 145 bool Pipeline::HasAudio() const { |
| 148 base::AutoLock auto_lock(lock_); | 146 base::AutoLock auto_lock(lock_); |
| 149 return has_audio_; | 147 return audio_renderer_; |
| 150 } | 148 } |
| 151 | 149 |
| 152 bool Pipeline::HasVideo() const { | 150 bool Pipeline::HasVideo() const { |
| 153 base::AutoLock auto_lock(lock_); | 151 base::AutoLock auto_lock(lock_); |
| 154 return has_video_; | 152 return video_renderer_; |
| 155 } | 153 } |
| 156 | 154 |
| 157 float Pipeline::GetPlaybackRate() const { | 155 float Pipeline::GetPlaybackRate() const { |
| 158 base::AutoLock auto_lock(lock_); | 156 base::AutoLock auto_lock(lock_); |
| 159 return playback_rate_; | 157 return playback_rate_; |
| 160 } | 158 } |
| 161 | 159 |
| 162 void Pipeline::SetPlaybackRate(float playback_rate) { | 160 void Pipeline::SetPlaybackRate(float playback_rate) { |
| 163 if (playback_rate < 0.0f) | 161 if (playback_rate < 0.0f) |
| 164 return; | 162 return; |
| (...skipping 184 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 349 &Pipeline::AudioDisabledTask, this)); | 347 &Pipeline::AudioDisabledTask, this)); |
| 350 media_log_->AddEvent( | 348 media_log_->AddEvent( |
| 351 media_log_->CreateEvent(MediaLogEvent::AUDIO_RENDERER_DISABLED)); | 349 media_log_->CreateEvent(MediaLogEvent::AUDIO_RENDERER_DISABLED)); |
| 352 } | 350 } |
| 353 | 351 |
| 354 void Pipeline::OnAudioTimeUpdate(TimeDelta time, TimeDelta max_time) { | 352 void Pipeline::OnAudioTimeUpdate(TimeDelta time, TimeDelta max_time) { |
| 355 DCHECK_LE(time.InMicroseconds(), max_time.InMicroseconds()); | 353 DCHECK_LE(time.InMicroseconds(), max_time.InMicroseconds()); |
| 356 DCHECK(IsRunning()); | 354 DCHECK(IsRunning()); |
| 357 base::AutoLock auto_lock(lock_); | 355 base::AutoLock auto_lock(lock_); |
| 358 | 356 |
| 359 if (!has_audio_) | 357 if (!audio_renderer_) |
| 360 return; | 358 return; |
| 361 if (waiting_for_clock_update_ && time < clock_->Elapsed()) | 359 if (waiting_for_clock_update_ && time < clock_->Elapsed()) |
| 362 return; | 360 return; |
| 363 | 361 |
| 364 if (state_ == kSeeking) | 362 if (state_ == kSeeking) |
| 365 return; | 363 return; |
| 366 | 364 |
| 367 clock_->SetTime(time, max_time); | 365 clock_->SetTime(time, max_time); |
| 368 StartClockIfWaitingForTimeUpdate_Locked(); | 366 StartClockIfWaitingForTimeUpdate_Locked(); |
| 369 } | 367 } |
| 370 | 368 |
| 371 void Pipeline::OnVideoTimeUpdate(TimeDelta max_time) { | 369 void Pipeline::OnVideoTimeUpdate(TimeDelta max_time) { |
| 372 DCHECK(IsRunning()); | 370 DCHECK(IsRunning()); |
| 373 base::AutoLock auto_lock(lock_); | 371 base::AutoLock auto_lock(lock_); |
| 374 | 372 |
| 375 if (has_audio_) | 373 if (audio_renderer_) |
| 376 return; | 374 return; |
| 377 | 375 |
| 378 if (state_ == kSeeking) | 376 if (state_ == kSeeking) |
| 379 return; | 377 return; |
| 380 | 378 |
| 381 DCHECK(!waiting_for_clock_update_); | 379 DCHECK(!waiting_for_clock_update_); |
| 382 clock_->SetMaxTime(max_time); | 380 clock_->SetMaxTime(max_time); |
| 383 } | 381 } |
| 384 | 382 |
| 385 void Pipeline::SetDuration(TimeDelta duration) { | 383 void Pipeline::SetDuration(TimeDelta duration) { |
| (...skipping 231 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 617 // If this method returns false, then there's no audio stream. | 615 // If this method returns false, then there's no audio stream. |
| 618 if (InitializeAudioDecoder(demuxer_)) | 616 if (InitializeAudioDecoder(demuxer_)) |
| 619 return; | 617 return; |
| 620 } | 618 } |
| 621 | 619 |
| 622 // Assuming audio decoder was created, create audio renderer. | 620 // Assuming audio decoder was created, create audio renderer. |
| 623 if (state_ == kInitAudioDecoder) { | 621 if (state_ == kInitAudioDecoder) { |
| 624 SetState(kInitAudioRenderer); | 622 SetState(kInitAudioRenderer); |
| 625 | 623 |
| 626 // Returns false if there's no audio stream. | 624 // Returns false if there's no audio stream. |
| 627 if (InitializeAudioRenderer(pipeline_init_state_->audio_decoder)) { | 625 if (InitializeAudioRenderer(pipeline_init_state_->audio_decoder)) |
| 628 base::AutoLock auto_lock(lock_); | |
| 629 has_audio_ = true; | |
| 630 return; | 626 return; |
| 631 } | |
| 632 } | 627 } |
| 633 | 628 |
| 634 // Assuming audio renderer was created, create video renderer. | 629 // Assuming audio renderer was created, create video renderer. |
| 635 if (state_ == kInitAudioRenderer) { | 630 if (state_ == kInitAudioRenderer) { |
| 636 SetState(kInitVideoRenderer); | 631 SetState(kInitVideoRenderer); |
| 637 scoped_refptr<DemuxerStream> video_stream = | 632 scoped_refptr<DemuxerStream> video_stream = |
| 638 demuxer_->GetStream(DemuxerStream::VIDEO); | 633 demuxer_->GetStream(DemuxerStream::VIDEO); |
| 639 if (InitializeVideoRenderer(video_stream)) { | 634 if (InitializeVideoRenderer(video_stream)) { |
| 640 base::AutoLock auto_lock(lock_); | 635 base::AutoLock auto_lock(lock_); |
| 641 has_video_ = true; | |
| 642 | 636 |
| 643 // Get an initial natural size so we have something when we signal | 637 // Get an initial natural size so we have something when we signal |
| 644 // the kHaveMetadata buffering state. | 638 // the kHaveMetadata buffering state. |
| 645 natural_size_ = video_stream->video_decoder_config().natural_size(); | 639 natural_size_ = video_stream->video_decoder_config().natural_size(); |
| 646 return; | 640 return; |
| 647 } | 641 } |
| 648 } | 642 } |
| 649 | 643 |
| 650 if (state_ == kInitVideoRenderer) { | 644 if (state_ == kInitVideoRenderer) { |
| 651 if (!IsPipelineOk() || !(HasAudio() || HasVideo())) { | 645 if (!IsPipelineOk() || !(HasAudio() || HasVideo())) { |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 664 | 658 |
| 665 buffering_state_cb_.Run(kHaveMetadata); | 659 buffering_state_cb_.Run(kHaveMetadata); |
| 666 | 660 |
| 667 // Fire a seek request to get the renderers to preroll. We can skip a seek | 661 // Fire a seek request to get the renderers to preroll. We can skip a seek |
| 668 // here as the demuxer should be at the start of the stream. | 662 // here as the demuxer should be at the start of the stream. |
| 669 seek_pending_ = true; | 663 seek_pending_ = true; |
| 670 SetState(kSeeking); | 664 SetState(kSeeking); |
| 671 seek_timestamp_ = demuxer_->GetStartTime(); | 665 seek_timestamp_ = demuxer_->GetStartTime(); |
| 672 DoSeek(seek_timestamp_, true, | 666 DoSeek(seek_timestamp_, true, |
| 673 base::Bind(&Pipeline::OnFilterStateTransition, this)); | 667 base::Bind(&Pipeline::OnFilterStateTransition, this)); |
| 668 return; | |
| 674 } | 669 } |
| 670 | |
| 671 NOTREACHED() << "Unexpected state: " << state_; | |
|
Ami GONE FROM CHROMIUM
2012/08/30 07:09:10
Added b/c otherwise the control structures in this
| |
| 675 } | 672 } |
| 676 | 673 |
| 677 // This method is called as a result of the client calling Pipeline::Stop() or | 674 // This method is called as a result of the client calling Pipeline::Stop() or |
| 678 // as the result of an error condition. | 675 // as the result of an error condition. |
| 679 // We stop the filters in the reverse order. | 676 // We stop the filters in the reverse order. |
| 680 // | 677 // |
| 681 // TODO(scherkus): beware! this can get posted multiple times since we post | 678 // TODO(scherkus): beware! this can get posted multiple times since we post |
| 682 // Stop() tasks even if we've already stopped. Perhaps this should no-op for | 679 // Stop() tasks even if we've already stopped. Perhaps this should no-op for |
| 683 // additional calls, however most of this logic will be changing. | 680 // additional calls, however most of this logic will be changing. |
| 684 void Pipeline::StopTask(const base::Closure& stop_cb) { | 681 void Pipeline::StopTask(const base::Closure& stop_cb) { |
| (...skipping 171 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 856 clock_->EndOfStream(); | 853 clock_->EndOfStream(); |
| 857 } | 854 } |
| 858 | 855 |
| 859 ReportStatus(ended_cb_, status_); | 856 ReportStatus(ended_cb_, status_); |
| 860 } | 857 } |
| 861 | 858 |
| 862 void Pipeline::AudioDisabledTask() { | 859 void Pipeline::AudioDisabledTask() { |
| 863 DCHECK(message_loop_->BelongsToCurrentThread()); | 860 DCHECK(message_loop_->BelongsToCurrentThread()); |
| 864 | 861 |
| 865 base::AutoLock auto_lock(lock_); | 862 base::AutoLock auto_lock(lock_); |
| 866 has_audio_ = false; | 863 audio_renderer_ = NULL; |
| 867 audio_disabled_ = true; | 864 audio_disabled_ = true; |
| 868 | 865 |
| 869 // Notify our demuxer that we're no longer rendering audio. | 866 // Notify our demuxer that we're no longer rendering audio. |
| 870 demuxer_->OnAudioRendererDisabled(); | 867 demuxer_->OnAudioRendererDisabled(); |
| 871 | 868 |
| 872 // Start clock since there is no more audio to | 869 // Start clock since there is no more audio to |
| 873 // trigger clock updates. | 870 // trigger clock updates. |
| 874 clock_->SetMaxTime(clock_->Duration()); | 871 clock_->SetMaxTime(clock_->Duration()); |
| 875 StartClockIfWaitingForTimeUpdate_Locked(); | 872 StartClockIfWaitingForTimeUpdate_Locked(); |
| 876 } | 873 } |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 934 // the seek has compelted. | 931 // the seek has compelted. |
| 935 if (playback_rate_change_pending_) { | 932 if (playback_rate_change_pending_) { |
| 936 playback_rate_change_pending_ = false; | 933 playback_rate_change_pending_ = false; |
| 937 PlaybackRateChangedTask(pending_playback_rate_); | 934 PlaybackRateChangedTask(pending_playback_rate_); |
| 938 } | 935 } |
| 939 | 936 |
| 940 base::AutoLock auto_lock(lock_); | 937 base::AutoLock auto_lock(lock_); |
| 941 // We use audio stream to update the clock. So if there is such a stream, | 938 // We use audio stream to update the clock. So if there is such a stream, |
| 942 // we pause the clock until we receive a valid timestamp. | 939 // we pause the clock until we receive a valid timestamp. |
| 943 waiting_for_clock_update_ = true; | 940 waiting_for_clock_update_ = true; |
| 944 if (!has_audio_) { | 941 if (!audio_renderer_) { |
| 945 clock_->SetMaxTime(clock_->Duration()); | 942 clock_->SetMaxTime(clock_->Duration()); |
| 946 StartClockIfWaitingForTimeUpdate_Locked(); | 943 StartClockIfWaitingForTimeUpdate_Locked(); |
| 947 } | 944 } |
| 948 | 945 |
| 949 // Check if we have a pending stop request that needs to be honored. | 946 // Check if we have a pending stop request that needs to be honored. |
| 950 if (!stop_cb_.is_null()) { | 947 if (!stop_cb_.is_null()) { |
| 951 TearDownPipeline(); | 948 TearDownPipeline(); |
| 952 } | 949 } |
| 953 } else { | 950 } else { |
| 954 NOTREACHED() << "Unexpected state: " << state_; | 951 NOTREACHED() << "Unexpected state: " << state_; |
| (...skipping 280 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1235 void Pipeline::StartClockIfWaitingForTimeUpdate_Locked() { | 1232 void Pipeline::StartClockIfWaitingForTimeUpdate_Locked() { |
| 1236 lock_.AssertAcquired(); | 1233 lock_.AssertAcquired(); |
| 1237 if (!waiting_for_clock_update_) | 1234 if (!waiting_for_clock_update_) |
| 1238 return; | 1235 return; |
| 1239 | 1236 |
| 1240 waiting_for_clock_update_ = false; | 1237 waiting_for_clock_update_ = false; |
| 1241 clock_->Play(); | 1238 clock_->Play(); |
| 1242 } | 1239 } |
| 1243 | 1240 |
| 1244 } // namespace media | 1241 } // namespace media |
| OLD | NEW |