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..4c47631c5549c95d83d972da138789596ec41c78 100644 |
| --- a/media/filters/source_buffer_stream.cc |
| +++ b/media/filters/source_buffer_stream.cc |
| @@ -28,6 +28,15 @@ static bool AllowSameTimestamp( |
| return prev_is_keyframe || !current_is_keyframe; |
| } |
| +// Returns the config ID of |buffer| if |buffer| has no fade out preroll or |
| +// |index| is out of range. Otherwise returns the config ID for the fade out |
| +// preroll buffer at position |index|. |
| +static int GetConfigId(StreamParserBuffer* buffer, size_t index) { |
| + return index < buffer->GetFadeOutPreroll().size() |
| + ? buffer->GetFadeOutPreroll()[index]->GetConfigId() |
| + : buffer->GetConfigId(); |
| +} |
| + |
| // Helper class representing a range of buffered data. All buffers in a |
| // SourceBufferRange are ordered sequentially in presentation order with no |
| // gaps. |
| @@ -341,7 +350,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 +373,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 +397,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 +682,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 +1106,75 @@ 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; |
| + } |
|
acolwell GONE FROM CHROMIUM
2014/01/15 19:28:50
nit: I think you should set *out_buffer = NULL her
DaleCurtis
2014/01/15 22:40:56
Done.
|
| + |
| + 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[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[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 is always |
| + // issued prior to handing out this buffer, any changes in config id have been |
| + // inherently handled. |
| + 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. |
| + if (GetConfigId(next_buffer, 0) != 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 +1410,12 @@ bool SourceBufferStream::UpdateVideoConfig(const VideoDecoderConfig& config) { |
| void SourceBufferStream::CompleteConfigChange() { |
| config_change_pending_ = false; |
| + if (fade_in_buffer_) { |
| + current_config_index_ = |
| + GetConfigId(fade_in_buffer_, fade_out_preroll_index_); |
| + return; |
| + } |
| + |
| if (!track_buffer_.empty()) { |
| current_config_index_ = track_buffer_.front()->GetConfigId(); |
|
acolwell GONE FROM CHROMIUM
2014/01/15 19:28:50
I think you need to use the helper function here t
DaleCurtis
2014/01/15 22:40:56
Done.
|
| return; |
| @@ -1846,7 +1924,7 @@ bool SourceBufferRange::GetNextBuffer( |
| if (!HasNextBuffer()) |
| return false; |
| - *out_buffer = buffers_.at(next_buffer_index_); |
| + *out_buffer = buffers_[next_buffer_index_]; |
| next_buffer_index_++; |
| return true; |
| } |
| @@ -1858,7 +1936,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_[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() ? |
|
acolwell GONE FROM CHROMIUM
2014/01/15 19:28:50
nit: Use the helper function here too.
DaleCurtis
2014/01/15 22:40:56
Done.
|
| + next_buffer->GetConfigId() : |
| + next_buffer->GetFadeOutPreroll()[0]->GetConfigId(); |
| } |
| base::TimeDelta SourceBufferRange::GetNextTimestamp() const { |
| @@ -1869,7 +1953,7 @@ base::TimeDelta SourceBufferRange::GetNextTimestamp() const { |
| return kNoTimestamp(); |
| } |
| - return buffers_.at(next_buffer_index_)->GetDecodeTimestamp(); |
| + return buffers_[next_buffer_index_]->GetDecodeTimestamp(); |
| } |
| bool SourceBufferRange::HasNextBufferPosition() const { |