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

Unified Diff: media/filters/source_buffer_stream.cc

Issue 10696182: Add config change handling to SourceBufferStream & ChunkDemuxer (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Added unittests Created 8 years, 5 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 015fc6c610d180822a466a255babdc4bf9797f45..2ffbb6abb140eaabe0f5d9d2c920623d8db24577 100644
--- a/media/filters/source_buffer_stream.cc
+++ b/media/filters/source_buffer_stream.cc
@@ -9,6 +9,7 @@
#include "base/bind.h"
#include "base/logging.h"
+#include "base/stl_util.h"
namespace media {
@@ -93,6 +94,10 @@ class SourceBufferRange {
bool GetNextBuffer(scoped_refptr<StreamParserBuffer>* out_buffer);
bool HasNextBuffer() const;
+ // Returns the config ID for the buffer that will be returned by
+ // GetNextBuffer().
+ int GetNextConfigId() const;
+
// Returns true if the range knows the position of the next buffer it should
// return, i.e. it has been Seek()ed. This does not necessarily mean that it
// has the next buffer yet.
@@ -229,7 +234,11 @@ static int kDefaultBufferDurationInMs = 125;
namespace media {
SourceBufferStream::SourceBufferStream(const AudioDecoderConfig& audio_config)
- : stream_start_time_(kNoTimestamp()),
+ : current_config_index_(0),
+ append_config_index_(0),
+ audio_configs_(1),
+ video_configs_(0),
+ stream_start_time_(kNoTimestamp()),
seek_pending_(false),
seek_buffer_timestamp_(kNoTimestamp()),
selected_range_(NULL),
@@ -238,11 +247,16 @@ SourceBufferStream::SourceBufferStream(const AudioDecoderConfig& audio_config)
new_media_segment_(false),
last_buffer_timestamp_(kNoTimestamp()),
max_interbuffer_distance_(kNoTimestamp()) {
- audio_config_.CopyFrom(audio_config);
+ audio_configs_[0] = new AudioDecoderConfig();
+ audio_configs_[0]->CopyFrom(audio_config);
}
SourceBufferStream::SourceBufferStream(const VideoDecoderConfig& video_config)
- : stream_start_time_(kNoTimestamp()),
+ : current_config_index_(0),
+ append_config_index_(0),
+ audio_configs_(0),
+ video_configs_(1),
+ stream_start_time_(kNoTimestamp()),
seek_pending_(false),
seek_buffer_timestamp_(kNoTimestamp()),
selected_range_(NULL),
@@ -251,7 +265,8 @@ SourceBufferStream::SourceBufferStream(const VideoDecoderConfig& video_config)
new_media_segment_(false),
last_buffer_timestamp_(kNoTimestamp()),
max_interbuffer_distance_(kNoTimestamp()) {
- video_config_.CopyFrom(video_config);
+ video_configs_[0] = new VideoDecoderConfig();
+ video_configs_[0]->CopyFrom(video_config);
}
SourceBufferStream::~SourceBufferStream() {
@@ -259,6 +274,9 @@ SourceBufferStream::~SourceBufferStream() {
delete ranges_.front();
ranges_.pop_front();
}
+
+ STLDeleteElements(&audio_configs_);
+ STLDeleteElements(&video_configs_);
}
void SourceBufferStream::OnNewMediaSegment(
@@ -305,6 +323,7 @@ bool SourceBufferStream::Append(
}
UpdateMaxInterbufferDistance(buffers);
+ SetConfigIds(buffers);
// Save a snapshot of stream state before range modifications are made.
base::TimeDelta next_buffer_timestamp = GetNextBufferTimestamp();
@@ -423,6 +442,13 @@ void SourceBufferStream::UpdateMaxInterbufferDistance(
}
}
+void SourceBufferStream::SetConfigIds(const BufferQueue& buffers) {
+ for (BufferQueue::const_iterator itr = buffers.begin();
+ itr != buffers.end(); ++itr) {
+ (*itr)->SetConfigId(append_config_index_);
+ }
+}
+
void SourceBufferStream::InsertIntoExistingRange(
const RangeList::iterator& range_for_new_buffers_itr,
const BufferQueue& new_buffers,
@@ -653,15 +679,25 @@ bool SourceBufferStream::IsSeekPending() const {
return seek_pending_;
}
-bool SourceBufferStream::GetNextBuffer(
+SourceBufferStream::Status SourceBufferStream::GetNextBuffer(
scoped_refptr<StreamParserBuffer>* out_buffer) {
if (!track_buffer_.empty()) {
+ if (track_buffer_.front()->GetConfigId() != current_config_index_)
+ return kConfigChange;
+
*out_buffer = track_buffer_.front();
track_buffer_.pop_front();
- return true;
+ return kSuccess;
}
- return selected_range_ && selected_range_->GetNextBuffer(out_buffer);
+ if (!selected_range_ || !selected_range_->HasNextBuffer())
+ return kNeedBuffer;
+
+ if (selected_range_->GetNextConfigId() != current_config_index_)
+ return kConfigChange;
+
+ CHECK(selected_range_->GetNextBuffer(out_buffer));
+ return kSuccess;
}
base::TimeDelta SourceBufferStream::GetNextBufferTimestamp() {
@@ -729,12 +765,99 @@ bool SourceBufferStream::IsEndSelected() const {
return ranges_.empty() || selected_range_ == ranges_.back();
}
+const AudioDecoderConfig& SourceBufferStream::GetCurrentAudioDecoderConfig() {
+ CompleteConfigChange();
+ return *audio_configs_[current_config_index_];
+}
+
+const VideoDecoderConfig& SourceBufferStream::GetCurrentVideoDecoderConfig() {
+ CompleteConfigChange();
+ return *video_configs_[current_config_index_];
+}
+
base::TimeDelta SourceBufferStream::GetMaxInterbufferDistance() const {
if (max_interbuffer_distance_ == kNoTimestamp())
return base::TimeDelta::FromMilliseconds(kDefaultBufferDurationInMs);
return max_interbuffer_distance_;
}
+bool SourceBufferStream::UpdateAudioConfig(const AudioDecoderConfig& config) {
+ DCHECK(!audio_configs_.empty());
+ DCHECK(video_configs_.empty());
+
+ if (audio_configs_[0]->codec() != config.codec()) {
+ DVLOG(1) << "UpdateAudioConfig() : Codec changes not allowed.";
+ return false;
+ }
+
+ if (audio_configs_[0]->samples_per_second() != config.samples_per_second()) {
+ DVLOG(1) << "UpdateAudioConfig() : Sample rate changes not allowed.";
+ return false;
+ }
+
+ if (audio_configs_[0]->channel_layout() != config.channel_layout()) {
+ DVLOG(1) << "UpdateAudioConfig() : Channel layout changes not allowed.";
+ return false;
+ }
+
+ if (audio_configs_[0]->bits_per_channel() != config.bits_per_channel()) {
+ DVLOG(1) << "UpdateAudioConfig() : Bits per channel changes not allowed.";
+ return false;
+ }
+
+ // Check to see if the new config matches an existing one.
+ for (size_t i = 0; i < audio_configs_.size(); ++i) {
+ if (config.Matches(*audio_configs_[i])) {
+ append_config_index_ = i;
+ return true;
+ }
+ }
+
+ // No matches found so let's add this one to the list.
+ append_config_index_ = audio_configs_.size();
+ audio_configs_.resize(audio_configs_.size() + 1);
+ audio_configs_[append_config_index_] = new AudioDecoderConfig();
+ audio_configs_[append_config_index_]->CopyFrom(config);
+ return true;
+}
+
+bool SourceBufferStream::UpdateVideoConfig(const VideoDecoderConfig& config) {
+ DCHECK(!video_configs_.empty());
+ DCHECK(audio_configs_.empty());
+
+ if (video_configs_[0]->codec() != config.codec()) {
+ DVLOG(1) << "UpdateVideoConfig() : Codec changes not allowed.";
+ return false;
+ }
+
+ // Check to see if the new config matches an existing one.
+ for (size_t i = 0; i < video_configs_.size(); ++i) {
+ if (config.Matches(*video_configs_[i])) {
+ append_config_index_ = i;
+ return true;
+ }
+ }
+
+ // No matches found so let's add this one to the list.
+ append_config_index_ = video_configs_.size();
+ video_configs_.resize(video_configs_.size() + 1);
+ video_configs_[append_config_index_] = new VideoDecoderConfig();
+ video_configs_[append_config_index_]->CopyFrom(config);
+ return true;
+}
+
+void SourceBufferStream::CompleteConfigChange() {
+ if (!track_buffer_.empty()) {
+ current_config_index_ = track_buffer_.front()->GetConfigId();
+ return;
+ }
+
+ if (!selected_range_ || !selected_range_->HasNextBuffer())
+ return;
+
+ current_config_index_ = selected_range_->GetNextConfigId();
+}
+
SourceBufferRange::SourceBufferRange(
const BufferQueue& new_buffers, base::TimeDelta media_segment_start_time,
const InterbufferDistanceCB& interbuffer_distance_cb)
@@ -925,12 +1048,9 @@ bool SourceBufferRange::TruncateAt(
bool SourceBufferRange::GetNextBuffer(
scoped_refptr<StreamParserBuffer>* out_buffer) {
- if (waiting_for_keyframe_ ||
- next_buffer_index_ >= static_cast<int>(buffers_.size())) {
+ if (!HasNextBuffer())
return false;
- }
- DCHECK_GE(next_buffer_index_, 0);
*out_buffer = buffers_.at(next_buffer_index_);
next_buffer_index_++;
return true;
@@ -938,9 +1058,16 @@ bool SourceBufferRange::GetNextBuffer(
bool SourceBufferRange::HasNextBuffer() const {
return next_buffer_index_ >= 0 &&
- next_buffer_index_ < static_cast<int>(buffers_.size());
+ next_buffer_index_ < static_cast<int>(buffers_.size()) &&
+ !waiting_for_keyframe_;
}
+int SourceBufferRange::GetNextConfigId() const {
+ DCHECK(HasNextBuffer());
+ return buffers_.at(next_buffer_index_)->GetConfigId();
+}
+
+
base::TimeDelta SourceBufferRange::GetNextTimestamp() const {
DCHECK(!buffers_.empty());
DCHECK(HasNextBufferPosition());

Powered by Google App Engine
This is Rietveld 408576698