Index: media/filters/source_buffer_stream.cc |
diff --git a/media/filters/source_buffer_stream.cc b/media/filters/source_buffer_stream.cc |
index 2b1911a93d37f52b5e7d1b350879257a8d07c3ca..71b5c13f953407339cfae950cd598d5c51ac6482 100644 |
--- a/media/filters/source_buffer_stream.cc |
+++ b/media/filters/source_buffer_stream.cc |
@@ -90,6 +90,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; |
xhwang
2012/07/12 18:09:12
s/ID/Id?
acolwell GONE FROM CHROMIUM
2012/07/12 23:07:58
Done.
|
+ |
// 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. |
@@ -223,7 +227,11 @@ static int kDefaultBufferDurationInMs = 125; |
namespace media { |
SourceBufferStream::SourceBufferStream(const AudioDecoderConfig& audio_config) |
- : seek_pending_(false), |
+ : current_config_index_(0), |
+ append_config_index_(0), |
+ audio_configs_(1), |
+ video_configs_(0), |
+ seek_pending_(false), |
seek_buffer_timestamp_(kNoTimestamp()), |
selected_range_(NULL), |
end_of_stream_(false), |
@@ -232,11 +240,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) |
- : seek_pending_(false), |
+ : current_config_index_(0), |
+ append_config_index_(0), |
+ audio_configs_(0), |
+ video_configs_(1), |
+ seek_pending_(false), |
seek_buffer_timestamp_(kNoTimestamp()), |
selected_range_(NULL), |
end_of_stream_(false), |
@@ -245,7 +258,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() { |
@@ -253,6 +267,14 @@ SourceBufferStream::~SourceBufferStream() { |
delete ranges_.front(); |
ranges_.pop_front(); |
} |
+ |
+ for (size_t i = 0; i < audio_configs_.size(); ++i) |
+ delete audio_configs_[i]; |
+ audio_configs_.clear(); |
+ |
+ for (size_t i = 0; i < video_configs_.size(); ++i) |
+ delete video_configs_[i]; |
+ video_configs_.clear(); |
xhwang
2012/07/12 18:09:12
Use STLDeleteElements here and above?
acolwell GONE FROM CHROMIUM
2012/07/12 23:07:58
Done.
|
} |
void SourceBufferStream::OnNewMediaSegment( |
@@ -284,6 +306,7 @@ bool SourceBufferStream::Append( |
} |
UpdateMaxInterbufferDistance(buffers); |
+ SetConfigIDs(buffers); |
// Save a snapshot of the |selected_range_| state before range modifications |
// are made. |
@@ -395,6 +418,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_); |
xhwang
2012/07/12 18:09:12
The comment in .h file uses set_config_id, which s
acolwell GONE FROM CHROMIUM
2012/07/12 23:07:58
I just fixed the comment to reflect the SetConfigI
|
+ } |
+} |
+ |
void SourceBufferStream::InsertIntoExistingRange( |
const RangeList::iterator& range_for_new_buffers_itr, |
const BufferQueue& new_buffers, |
@@ -606,21 +636,30 @@ 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; |
} |
if (end_of_stream_ && (!selected_range_ || |
!selected_range_->HasNextBuffer())) { |
*out_buffer = StreamParserBuffer::CreateEOSBuffer(); |
- 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; |
+ |
+ return selected_range_->GetNextBuffer(out_buffer) ? kSuccess : kNeedBuffer; |
vrk (LEFT CHROMIUM)
2012/07/12 19:37:55
At this point, shouldn't selected_range_->GetNextB
acolwell GONE FROM CHROMIUM
2012/07/12 23:07:58
I wasn't sure. The guard in SourceBufferRange::Get
|
} |
base::TimeDelta SourceBufferStream::GetNextBufferTimestamp() { |
@@ -693,6 +732,99 @@ base::TimeDelta SourceBufferStream::GetMaxInterbufferDistance() const { |
return max_interbuffer_distance_; |
} |
+bool SourceBufferStream::UpdateAudioConfig(const AudioDecoderConfig& config) { |
+ DCHECK(!audio_configs_.empty()); |
vrk (LEFT CHROMIUM)
2012/07/12 19:37:55
DCHECK(video_configs_.empty())?
acolwell GONE FROM CHROMIUM
2012/07/12 23:07:58
Done.
|
+ |
+ 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) { |
+ const AudioDecoderConfig& existing_config = *audio_configs_[i]; |
+ if ((existing_config.codec() == config.codec()) && |
+ (existing_config.bits_per_channel() == config.bits_per_channel()) && |
+ (existing_config.channel_layout() == config.channel_layout()) && |
+ (existing_config.samples_per_second() == config.samples_per_second()) && |
+ (existing_config.extra_data_size() == config.extra_data_size()) && |
+ (!existing_config.extra_data() || |
+ !memcmp(existing_config.extra_data(), config.extra_data(), |
+ existing_config.extra_data_size()))) { |
xhwang
2012/07/12 18:09:12
How about having helper functions for this and bel
acolwell GONE FROM CHROMIUM
2012/07/12 23:07:58
Done.
|
+ append_config_index_ = i; |
+ return true; |
+ } |
+ } |
+ |
+ // No matches found so lets add this one to the list. |
vrk (LEFT CHROMIUM)
2012/07/12 19:37:55
nit: "let's"
acolwell GONE FROM CHROMIUM
2012/07/12 23:07:58
Done.
|
+ 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()); |
vrk (LEFT CHROMIUM)
2012/07/12 19:37:55
DCHECK(audio_configs_.empty())?
acolwell GONE FROM CHROMIUM
2012/07/12 23:07:58
Done.
|
+ |
+ 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) { |
+ const VideoDecoderConfig& existing_config = *video_configs_[i]; |
+ if ((existing_config.codec() == config.codec()) && |
+ (existing_config.format() == config.format()) && |
+ (existing_config.profile() == config.profile()) && |
+ (existing_config.coded_size() == config.coded_size()) && |
+ (existing_config.visible_rect() == config.visible_rect()) && |
+ (existing_config.natural_size() == config.natural_size()) && |
+ (existing_config.extra_data_size() == config.extra_data_size()) && |
+ (!existing_config.extra_data() || |
+ !memcmp(existing_config.extra_data(), config.extra_data(), |
+ existing_config.extra_data_size()))) { |
+ append_config_index_ = i; |
+ return true; |
+ } |
+ } |
+ |
+ // No matches found so lets add this one to the list. |
vrk (LEFT CHROMIUM)
2012/07/12 19:37:55
nit: "let's"
acolwell GONE FROM CHROMIUM
2012/07/12 23:07:58
Done.
|
+ 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::UpdateCurrentConfigIndex() { |
+ 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) |
@@ -888,6 +1020,12 @@ bool SourceBufferRange::HasNextBuffer() const { |
next_buffer_index_ < static_cast<int>(buffers_.size()); |
vrk (LEFT CHROMIUM)
2012/07/12 19:37:55
nit: indentation + add "&& !waiting_for_keyframe_"
acolwell GONE FROM CHROMIUM
2012/07/12 23:07:58
Done. Changed GetNextBuffer() to use this now that
|
} |
+int SourceBufferRange::GetNextConfigID() const { |
+ DCHECK(HasNextBuffer()); |
+ return buffers_.at(next_buffer_index_)->GetConfigID(); |
+} |
+ |
+ |
base::TimeDelta SourceBufferRange::GetNextTimestamp() const { |
DCHECK(!buffers_.empty()); |
DCHECK(HasNextBufferPosition()); |