Chromium Code Reviews| Index: media/filters/source_buffer_stream.cc |
| diff --git a/media/filters/source_buffer_stream.cc b/media/filters/source_buffer_stream.cc |
| index 20e9156ad02e207ed8b676deac038553d6cafdeb..3d8a6c21586574c7faa7ee7f2f99c3992a69b968 100644 |
| --- a/media/filters/source_buffer_stream.cc |
| +++ b/media/filters/source_buffer_stream.cc |
| @@ -341,7 +341,8 @@ SourceBufferStream::SourceBufferStream(const AudioDecoderConfig& audio_config, |
| last_output_buffer_timestamp_(kNoTimestamp()), |
| max_interbuffer_distance_(kNoTimestamp()), |
| memory_limit_(kDefaultAudioMemoryLimit), |
| - config_change_pending_(false) { |
| + config_change_pending_(false), |
| + fade_out_preroll_index_(0) { |
| DCHECK(audio_config.IsValidConfig()); |
| audio_configs_.push_back(audio_config); |
| } |
| @@ -363,7 +364,8 @@ SourceBufferStream::SourceBufferStream(const VideoDecoderConfig& video_config, |
| last_output_buffer_timestamp_(kNoTimestamp()), |
| max_interbuffer_distance_(kNoTimestamp()), |
| memory_limit_(kDefaultVideoMemoryLimit), |
| - config_change_pending_(false) { |
| + config_change_pending_(false), |
| + fade_out_preroll_index_(0) { |
| DCHECK(video_config.IsValidConfig()); |
| video_configs_.push_back(video_config); |
| } |
| @@ -386,7 +388,8 @@ SourceBufferStream::SourceBufferStream(const TextTrackConfig& text_config, |
| last_output_buffer_timestamp_(kNoTimestamp()), |
| max_interbuffer_distance_(kNoTimestamp()), |
| memory_limit_(kDefaultAudioMemoryLimit), |
| - config_change_pending_(false) { |
| + config_change_pending_(false), |
| + fade_out_preroll_index_(0) { |
| } |
| SourceBufferStream::~SourceBufferStream() { |
| @@ -670,6 +673,8 @@ void SourceBufferStream::ResetSeekState() { |
| track_buffer_.clear(); |
| config_change_pending_ = false; |
| last_output_buffer_timestamp_ = kNoTimestamp(); |
| + fade_out_preroll_index_ = 0; |
| + fade_in_buffer_ = NULL; |
| } |
| bool SourceBufferStream::ShouldSeekToStartOfBuffered( |
| @@ -1092,17 +1097,78 @@ void SourceBufferStream::OnSetDuration(base::TimeDelta duration) { |
| SourceBufferStream::Status SourceBufferStream::GetNextBuffer( |
| scoped_refptr<StreamParserBuffer>* out_buffer) { |
| + if (!fade_in_buffer_) { |
| + const SourceBufferStream::Status status = GetNextBufferInternal(out_buffer); |
| + |
| + // Just return if GetNextBufferInternal() failed or there's no fade out |
| + // preroll, there's nothing else to do. |
| + if (status != SourceBufferStream::kSuccess || |
| + (*out_buffer)->GetFadeOutPreroll().empty()) { |
| + return status; |
| + } |
| + |
| + // Setup fade in buffer and fall through into splice frame buffer handling. |
| + fade_out_preroll_index_ = 0; |
| + fade_in_buffer_ = *out_buffer; |
| + } |
| + |
| + DCHECK(fade_in_buffer_); |
| + const std::vector<scoped_refptr<StreamParserBuffer> >& fade_out_preroll = |
| + fade_in_buffer_->GetFadeOutPreroll(); |
| + |
| + // Are there any fade out buffers left to hand out? |
| + if (fade_out_preroll_index_ < fade_out_preroll.size()) { |
| + // Account for config changes which occur between fade out buffers. |
| + if (current_config_index_ != |
| + fade_out_preroll.at(fade_out_preroll_index_)->GetConfigId()) { |
| + config_change_pending_ = true; |
| + DVLOG(1) << "Config change (fade out preroll config ID does not match)."; |
| + return SourceBufferStream::kConfigChange; |
| + } |
| + |
| + *out_buffer = fade_out_preroll.at(fade_out_preroll_index_++); |
| + return SourceBufferStream::kSuccess; |
| + } |
| + |
| + // Did we hand out the last fade out buffer on the last call? |
| + if (fade_out_preroll_index_ == fade_out_preroll.size()) { |
| + fade_out_preroll_index_++; |
| + config_change_pending_ = true; |
| + DVLOG(1) << "Config change (forced for fade in of splice frame)."; |
| + return SourceBufferStream::kConfigChange; |
| + } |
| + |
| + // All fade out buffers have been handed out and a config change completed, so |
| + // hand out the final buffer for fade in. Because a config change has already |
| + // been issued, we don't need to account for |
|
acolwell GONE FROM CHROMIUM
2014/01/10 22:53:31
nit: Finish the sentence. :)
DaleCurtis
2014/01/10 23:03:49
Haha, awesome, I accidentally a sentence.
|
| + DCHECK_GT(fade_out_preroll_index_, fade_out_preroll.size()); |
| + *out_buffer = fade_in_buffer_; |
| + fade_in_buffer_ = NULL; |
| + fade_out_preroll_index_ = 0; |
| + return SourceBufferStream::kSuccess; |
| +} |
| + |
| +SourceBufferStream::Status SourceBufferStream::GetNextBufferInternal( |
| + scoped_refptr<StreamParserBuffer>* out_buffer) { |
| CHECK(!config_change_pending_); |
| if (!track_buffer_.empty()) { |
| DCHECK(!selected_range_); |
| - if (track_buffer_.front()->GetConfigId() != current_config_index_) { |
| + scoped_refptr<StreamParserBuffer>& next_buffer = track_buffer_.front(); |
| + |
| + // If the next buffer is an audio splice frame, the next effective config id |
| + // comes from the first fade out preroll buffer. |
| + const int next_config_id = next_buffer->GetFadeOutPreroll().empty() ? |
| + next_buffer->GetConfigId() : |
| + next_buffer->GetFadeOutPreroll().at(0)->GetConfigId(); |
|
acolwell GONE FROM CHROMIUM
2014/01/10 22:53:31
nit: Any reason you can't use the [0] instead of .
DaleCurtis
2014/01/10 23:03:49
I switched to .at() since that seemed to be the st
|
| + |
| + if (next_config_id != current_config_index_) { |
| config_change_pending_ = true; |
| DVLOG(1) << "Config change (track buffer config ID does not match)."; |
| return kConfigChange; |
| } |
| - *out_buffer = track_buffer_.front(); |
| + *out_buffer = next_buffer; |
| track_buffer_.pop_front(); |
| last_output_buffer_timestamp_ = (*out_buffer)->GetDecodeTimestamp(); |
| @@ -1338,6 +1404,15 @@ bool SourceBufferStream::UpdateVideoConfig(const VideoDecoderConfig& config) { |
| void SourceBufferStream::CompleteConfigChange() { |
| config_change_pending_ = false; |
| + if (fade_in_buffer_) { |
| + const std::vector<scoped_refptr<StreamParserBuffer> >& fade_out_preroll = |
| + fade_in_buffer_->GetFadeOutPreroll(); |
| + current_config_index_ = fade_out_preroll_index_ < fade_out_preroll.size() ? |
| + fade_out_preroll.at(fade_out_preroll_index_)->GetConfigId() : |
| + fade_in_buffer_->GetConfigId(); |
| + return; |
| + } |
| + |
| if (!track_buffer_.empty()) { |
| current_config_index_ = track_buffer_.front()->GetConfigId(); |
| return; |
| @@ -1858,7 +1933,13 @@ bool SourceBufferRange::HasNextBuffer() const { |
| int SourceBufferRange::GetNextConfigId() const { |
| DCHECK(HasNextBuffer()); |
| - return buffers_.at(next_buffer_index_)->GetConfigId(); |
| + const scoped_refptr<StreamParserBuffer>& next_buffer = |
| + buffers_.at(next_buffer_index_); |
| + // If the next buffer is an audio splice frame, the next effective config id |
| + // comes from the first fade out preroll buffer. |
| + return next_buffer->GetFadeOutPreroll().empty() ? |
| + next_buffer->GetConfigId() : |
| + next_buffer->GetFadeOutPreroll().at(0)->GetConfigId(); |
| } |
| base::TimeDelta SourceBufferRange::GetNextTimestamp() const { |