| Index: media/filters/source_buffer_stream.cc
|
| diff --git a/media/filters/source_buffer_stream.cc b/media/filters/source_buffer_stream.cc
|
| index 785643b58e015f39d1e575584cf88eae87ecb0ad..6be1420ad885a8f89f709eaa7c72beca1bd7ad4c 100644
|
| --- a/media/filters/source_buffer_stream.cc
|
| +++ b/media/filters/source_buffer_stream.cc
|
| @@ -29,6 +29,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.
|
| @@ -346,7 +355,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);
|
| }
|
| @@ -368,7 +378,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);
|
| }
|
| @@ -391,7 +402,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(
|
| @@ -1097,17 +1111,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_.swap(*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[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->swap(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();
|
|
|
| @@ -1343,8 +1415,14 @@ 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();
|
| + current_config_index_ = GetConfigId(track_buffer_.front(), 0);
|
| return;
|
| }
|
|
|
| @@ -1864,7 +1942,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;
|
| }
|
| @@ -1876,7 +1954,9 @@ bool SourceBufferRange::HasNextBuffer() const {
|
|
|
| int SourceBufferRange::GetNextConfigId() const {
|
| DCHECK(HasNextBuffer());
|
| - return buffers_.at(next_buffer_index_)->GetConfigId();
|
| + // If the next buffer is an audio splice frame, the next effective config id
|
| + // comes from the first fade out preroll buffer.
|
| + return GetConfigId(buffers_[next_buffer_index_], 0);
|
| }
|
|
|
| base::TimeDelta SourceBufferRange::GetNextTimestamp() const {
|
| @@ -1887,7 +1967,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 {
|
|
|