Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1066)

Unified Diff: media/filters/source_buffer_stream.cc

Issue 125543002: Add plumbing and support for crossfading StreamParserBuffers. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Comments. Created 6 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
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 {

Powered by Google App Engine
This is Rietveld 408576698