Chromium Code Reviews| Index: media/filters/chunk_demuxer.cc |
| diff --git a/media/filters/chunk_demuxer.cc b/media/filters/chunk_demuxer.cc |
| index 1e1615465a4b53dc727f56b6d1b6ea49ea7fd0ee..f0fd62b3bbb1b477d54c6b1144713f640a36391e 100644 |
| --- a/media/filters/chunk_demuxer.cc |
| +++ b/media/filters/chunk_demuxer.cc |
| @@ -133,6 +133,9 @@ class ChunkDemuxerStream : public DemuxerStream { |
| // Returns true if buffers were successfully added. |
| bool Append(const StreamParser::BufferQueue& buffers); |
| + // Returns a list of the buffered time ranges. |
| + SourceBufferStream::TimespanList GetBufferedTime() const; |
| + |
| // Called when mid-stream config updates occur. |
| // Returns true if the new config is accepted. |
| // Returns false if the new config should trigger an error. |
| @@ -246,6 +249,11 @@ bool ChunkDemuxerStream::Append(const StreamParser::BufferQueue& buffers) { |
| return true; |
| } |
| +SourceBufferStream::TimespanList ChunkDemuxerStream::GetBufferedTime() const { |
| + base::AutoLock auto_lock(lock_); |
| + return stream_->GetBufferedTime(); |
| +} |
| + |
| bool ChunkDemuxerStream::UpdateAudioConfig(const AudioDecoderConfig& config) { |
| DCHECK(config.IsValidConfig()); |
| DCHECK_EQ(type_, AUDIO); |
| @@ -580,12 +588,102 @@ bool ChunkDemuxer::GetBufferedRanges(const std::string& id, |
| Ranges* ranges_out) const { |
| DCHECK(!id.empty()); |
| DCHECK_GT(stream_parser_map_.count(id), 0u); |
| + DCHECK(id == source_id_audio_ || id == source_id_video_); |
| DCHECK(ranges_out); |
| base::AutoLock auto_lock(lock_); |
| + bool success = false; |
| + |
| + if (id == source_id_audio_ && id != source_id_video_) { |
| + // Only include ranges that have been buffered in |audio_| |
|
acolwell GONE FROM CHROMIUM
2012/06/12 22:48:13
Move this to a helper method so we don't have dupl
annacc
2012/06/13 00:00:01
Done.
|
| + SourceBufferStream::TimespanList audio_ranges = audio_->GetBufferedTime(); |
| + for (SourceBufferStream::TimespanList::iterator itr = audio_ranges.begin(); |
| + itr != audio_ranges.end(); ++itr) { |
| + ranges_out->push_back(*itr); |
| + success = true; |
| + } |
| + return success; |
| + } |
| - // TODO(annacc): Calculate buffered ranges (http://crbug.com/129852 ). |
| - return false; |
| + if (id != source_id_audio_ && id == source_id_video_) { |
| + // Only include ranges that have been buffered in |video_| |
| + SourceBufferStream::TimespanList video_ranges = video_->GetBufferedTime(); |
| + for (SourceBufferStream::TimespanList::iterator itr = video_ranges.begin(); |
| + itr != video_ranges.end(); ++itr) { |
| + ranges_out->push_back(*itr); |
| + success = true; |
| + } |
| + return success; |
| + } |
| + |
| + // Include ranges that have been buffered in both |audio_| and |video_|. |
| + SourceBufferStream::TimespanList audio_ranges = audio_->GetBufferedTime(); |
| + SourceBufferStream::TimespanList video_ranges = video_->GetBufferedTime(); |
| + SourceBufferStream::TimespanList::const_iterator video_ranges_itr = |
| + video_ranges.begin(); |
| + SourceBufferStream::TimespanList::const_iterator audio_ranges_itr = |
| + audio_ranges.begin(); |
| + |
| + while (audio_ranges_itr != audio_ranges.end() && |
| + video_ranges_itr != video_ranges.end()) { |
| + |
|
acolwell GONE FROM CHROMIUM
2012/06/12 22:48:13
Precompute the "last ranges" condition into a bool
annacc
2012/06/13 00:00:01
Done.
|
| + // Audio range start time is within the video range. |
| + if ((*audio_ranges_itr).first >= (*video_ranges_itr).first && |
| + (*audio_ranges_itr).first <= (*video_ranges_itr).second) { |
| + AddIntersectionRange(audio_ranges_itr, video_ranges_itr, |
|
acolwell GONE FROM CHROMIUM
2012/06/12 22:48:13
How about passing in *xxx_itr instead of the itera
annacc
2012/06/13 00:00:01
I think I've realized your suggestion here, but yo
|
| + audio_ranges.end(), video_ranges.end(), |
| + ranges_out); |
| + success = true; |
| + continue; |
| + } |
| + |
| + // Video range start time is within the audio range. |
| + if ((*video_ranges_itr).first >= (*audio_ranges_itr).first && |
| + (*video_ranges_itr).first <= (*audio_ranges_itr).second) { |
| + AddIntersectionRange(video_ranges_itr, audio_ranges_itr, |
| + video_ranges.end(), audio_ranges.end(), |
| + ranges_out); |
| + success = true; |
| + continue; |
| + } |
| + |
| + // No overlap was found. Increment the smallest one and keep looking. |
|
acolwell GONE FROM CHROMIUM
2012/06/12 22:48:13
nit: smallest -> earliest?
annacc
2012/06/13 00:00:01
Done.
|
| + if ((*audio_ranges_itr).first < (*video_ranges_itr).first) |
| + audio_ranges_itr++; |
| + else |
| + video_ranges_itr++; |
| + } |
| + |
| + return success; |
| +} |
| + |
| +void ChunkDemuxer::AddIntersectionRange( |
| + SourceBufferStream::TimespanList::const_iterator& itr_a, |
| + SourceBufferStream::TimespanList::const_iterator& itr_b, |
| + SourceBufferStream::TimespanList::const_iterator itr_a_end, |
| + SourceBufferStream::TimespanList::const_iterator itr_b_end, |
| + Ranges* ranges_out) const { |
| + base::TimeDelta start = (*itr_a).first; |
| + |
| + // If this is the last range and EndOfStream() was called (i.e. all data |
| + // has been appended), choose the max end point of the ranges. |
| + base::TimeDelta end; |
| + if (state_ == ENDED && |
| + next(itr_a) == itr_a_end && |
|
acolwell GONE FROM CHROMIUM
2012/06/12 22:48:13
nit: Use (itr_a + 1) instead.
annacc
2012/06/13 00:00:01
Done.
|
| + next(itr_b) == itr_b_end) { |
| + end = std::max((*itr_a).second, (*itr_b).second); |
| + } else { |
| + end = std::min((*itr_a).second, (*itr_b).second); |
| + } |
| + |
| + ranges_out->push_back(std::make_pair(start, end)); |
| + |
| + itr_a++; |
| +} |
| + |
| +SourceBufferStream::TimespanList::const_iterator ChunkDemuxer::next( |
|
acolwell GONE FROM CHROMIUM
2012/06/12 22:48:13
nit: I'd prefer you use (itr + 1) instead of defin
annacc
2012/06/13 00:00:01
Done.
|
| + SourceBufferStream::TimespanList::const_iterator itr) const { |
| + return ++itr; |
| } |
| bool ChunkDemuxer::AppendData(const std::string& id, |