From e54556d60748ec7d73ade8bdb0794ab700a924af Mon Sep 17 00:00:00 2001
From: "vrk@google.com" <vrk@google.com@0039d316-1c4b-4281-b951-d872f2087c98>
Date: Wed, 6 Jun 2012 18:23:26 +0000
Subject: Implement start, end, and middle overlaps for SourceBufferStream

Handles cases where the selected range is overlapped.
Does not handle buffer sizes of differing durations.

BUG=126560,125072
TEST=media_unittests

Review URL: https://chromiumcodereview.appspot.com/10389185

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@140797 0039d316-1c4b-4281-b951-d872f2087c98
---
 media/filters/source_buffer_stream.cc          | 565 +++++++++++++--------
 media/filters/source_buffer_stream.h           |  48 +-
 media/filters/source_buffer_stream_unittest.cc | 673 +++++++++++++++++++++----
 3 files changed, 971 insertions(+), 315 deletions(-)

(limited to 'media')

diff --git a/media/filters/source_buffer_stream.cc b/media/filters/source_buffer_stream.cc
index e12af6b..7000bda 100644
--- a/media/filters/source_buffer_stream.cc
+++ b/media/filters/source_buffer_stream.cc
@@ -18,21 +18,57 @@ class SourceBufferRange {
  public:
   typedef std::deque<scoped_refptr<StreamParserBuffer> > BufferQueue;
 
-  SourceBufferRange();
+  // Creates a source buffer range with |new_buffers|. |new_buffers| cannot be
+  // empty and the front of |new_buffers| must be a keyframe.
+  explicit SourceBufferRange(const BufferQueue& new_buffers);
 
-  // Adds |new_buffers| into this range. |new_buffers| must belong to this
-  // range. Garbage collection may occur after Append().
-  void Append(const BufferQueue& new_buffers);
+  // Appends |buffers| to the end of the range and updates |keyframe_map_| as
+  // it encounters new keyframes. Assumes |buffers| belongs at the end of the
+  // range.
+  void AppendToEnd(const BufferQueue& buffers);
+  bool CanAppendToEnd(const BufferQueue& buffers) const;
+
+  // Appends the buffers from |range| into this range.
+  // The first buffer in |range| must come directly after the last buffer
+  // in this range.
+  // If |transfer_current_position| is true, |range|'s |next_buffer_index_|
+  // is transfered to this SourceBufferRange.
+  void AppendToEnd(const SourceBufferRange& range,
+                   bool transfer_current_position);
+  bool CanAppendToEnd(const SourceBufferRange& range) const;
 
   // Updates |next_buffer_index_| to point to the Buffer containing |timestamp|.
   // Assumes |timestamp| is valid and in this range.
   void Seek(base::TimeDelta timestamp);
 
   // Updates |next_buffer_index_| to point to next keyframe after or equal to
-  // |timestamp|. If there is no such keyframe, then this range will seek to
-  // the end and return kNoTimestamp().
-  // Assumes |timestamp| is valid and in this range.
-  base::TimeDelta SeekAfter(base::TimeDelta timestamp);
+  // |timestamp|.
+  void SeekAfter(base::TimeDelta timestamp);
+
+  // Finds the next keyframe from |buffers_| after |timestamp|, and creates and
+  // returns a new SourceBufferRange with the buffers from that keyframe onward.
+  // The buffers in the new SourceBufferRange are moved out of this range. If
+  // there is no keyframe after |timestamp|, SplitRange() returns null and this
+  // range is unmodified.
+  SourceBufferRange* SplitRange(base::TimeDelta timestamp);
+
+  // Deletes the buffers from this range whose timestamps are greater than or
+  // equal to |buffer|'s timestamp.
+  // Resets |next_buffer_index_| if the buffer at |next_buffer_index_| was
+  // deleted, and deletes the |keyframe_map_| entries for the buffers that
+  // were removed.
+  // If |deleted_buffers| or |next_buffer| are null, they are ignored.
+  // Otherwise, |deleted_buffers| contains the buffers that were deleted from
+  // this range, and |next_buffer| points to the buffer in |deleted_buffers|
+  // that had been at |next_buffer_index_|. If |next_buffer_index_| did not
+  // point to any buffer added to |deleted_buffers|, then |next_buffer| points
+  // to |deleted_buffers.end()|.
+  void DeleteAfter(scoped_refptr<StreamParserBuffer> buffer,
+                   BufferQueue* deleted_buffers,
+                   BufferQueue::iterator* next_buffer);
+  // Deletes all buffers in range.
+  void DeleteAll(BufferQueue* deleted_buffers,
+                 BufferQueue::iterator* next_buffer);
 
   // Updates |out_buffer| with the next buffer in presentation order. Seek()
   // must be called before calls to GetNextBuffer(), and buffers are returned
@@ -41,21 +77,19 @@ class SourceBufferRange {
   // the request.
   bool GetNextBuffer(scoped_refptr<StreamParserBuffer>* out_buffer);
   bool HasNextBuffer() const;
+
+  // Returns the timestamp of the next buffer that will be returned from
+  // GetNextBuffer(). Returns kNoTimestamp() if Seek() has never been called or
+  // if this range does not have the next buffer yet.
   base::TimeDelta GetNextTimestamp() const;
 
+  // Returns the end timestamp of the buffered data. (Note that this is equal to
+  // the last buffer's timestamp + its duration.)
+  base::TimeDelta GetEndTimestamp() const;
+
   // Returns the Timespan of buffered time in this range.
   SourceBufferStream::Timespan GetBufferedTime() const;
 
-  // Appends the buffers from |range| into this range.
-  // The first buffer in |range| must come directly after the last buffer
-  // in this range.
-  // If |transfer_current_position| is true, |range|'s |next_buffer_position_|
-  // is transfered to this SourceBufferRange.
-  void AppendToEnd(const SourceBufferRange& range,
-                   bool transfer_current_position);
-  bool CanAppendToEnd(const SourceBufferRange& range) const;
-  bool CanAppendToEnd(const BufferQueue& buffers) const;
-
   // Returns whether a buffer with a starting timestamp of |timestamp| would
   // belong in this range. This includes a buffer that would be appended to
   // the end of the range.
@@ -75,27 +109,15 @@ class SourceBufferRange {
   // the beginning of |range|.
   bool EndOverlaps(const SourceBufferRange& range) const;
 
-  // Functions that tell how |buffers| intersects with this range.
-  // TODO(vrk): These functions should be unnecessary when overlapping the
-  // selected range is implemented properly. (crbug.com/126560)
-  bool IsStartOverlappedBy(const BufferQueue& buffers) const;
-  bool IsEndOverlappedBy(const BufferQueue& buffers) const;
-  bool IsCompletelyOverlappedBy(const BufferQueue& buffers) const;
-
  private:
-  // Appends |buffers| to the end of the range and updates |keyframe_map_| as
-  // it encounters new keyframes. Assumes |buffers| belongs at the end of the
-  // range.
-  void AppendToEnd(const BufferQueue& buffers);
+  // Helper method to delete buffers in |buffers_| starting from
+  // |starting_point|, an iterator in |buffers_|.
+  void DeleteAfter(BufferQueue::iterator starting_point,
+                   BufferQueue* deleted_buffers,
+                   BufferQueue::iterator* next_buffer);
 
-  // Returns the start timestamp of the range, or kNoTimestamp if the range is
-  // empty.
-  base::TimeDelta BufferedStart() const;
-
-  // Returns the end timestamp of the buffered data. (Note that this is equal to
-  // the last buffer's timestamp + its duration.) Returns kNoTimestamp if the
-  // range is empty.
-  base::TimeDelta BufferedEnd() const;
+  // Returns the start timestamp of the range.
+  base::TimeDelta GetStartTimestamp() const;
 
   // An ordered list of buffers in this range.
   BufferQueue buffers_;
@@ -108,6 +130,14 @@ class SourceBufferRange {
   // GetBufferedTime(), set to -1 before Seek().
   int next_buffer_index_;
 
+  // True if the range needs to wait for the next keyframe to be appended before
+  // returning buffers from GetNextBuffer().
+  bool waiting_for_keyframe_;
+
+  // If |waiting_for_keyframe_| is true, this range will wait for the next
+  // keyframe with timestamp >= |next_keyframe_timestamp_|.
+  base::TimeDelta next_keyframe_timestamp_;
+
   DISALLOW_COPY_AND_ASSIGN(SourceBufferRange);
 };
 
@@ -129,8 +159,9 @@ static bool IsRangeListSorted(
 }
 
 // Comparison function for two Buffers based on timestamp.
-static bool BufferComparator(scoped_refptr<media::Buffer> first,
-                             scoped_refptr<media::Buffer> second) {
+static bool BufferComparator(
+    const scoped_refptr<media::StreamParserBuffer>& first,
+    const scoped_refptr<media::StreamParserBuffer>& second) {
   return first->GetTimestamp() < second->GetTimestamp();
 }
 
@@ -160,7 +191,6 @@ SourceBufferStream::SourceBufferStream()
     : seek_pending_(true),
       seek_buffer_timestamp_(base::TimeDelta()),
       selected_range_(NULL),
-      waiting_for_keyframe_(false),
       end_of_stream_(false) {
 }
 
@@ -168,7 +198,6 @@ SourceBufferStream::SourceBufferStream(const AudioDecoderConfig& audio_config)
     : seek_pending_(true),
       seek_buffer_timestamp_(base::TimeDelta()),
       selected_range_(NULL),
-      waiting_for_keyframe_(false),
       end_of_stream_(false) {
   audio_config_.CopyFrom(audio_config);
 }
@@ -177,7 +206,6 @@ SourceBufferStream::SourceBufferStream(const VideoDecoderConfig& video_config)
     : seek_pending_(true),
       seek_buffer_timestamp_(base::TimeDelta()),
       selected_range_(NULL),
-      waiting_for_keyframe_(false),
       end_of_stream_(false) {
   video_config_.CopyFrom(video_config);
 }
@@ -193,65 +221,38 @@ bool SourceBufferStream::Append(
     const SourceBufferStream::BufferQueue& buffers) {
   DCHECK(!buffers.empty());
 
-  // Check to see if |buffers| will overlap the currently |selected_range_|,
-  // and if so, ignore this Append() request.
-  // TODO(vrk): Support overlapping selected range properly. (crbug.com/126560)
-  if (selected_range_ &&
-      (selected_range_->IsEndOverlappedBy(buffers) ||
-       selected_range_->IsStartOverlappedBy(buffers))) {
-    return false;
-  }
-
-  SourceBufferRange* range = NULL;
+  RangeList::iterator range_for_new_buffers = ranges_.end();
   RangeList::iterator itr = ranges_.end();
   base::TimeDelta start_timestamp = buffers.front()->GetTimestamp();
   for (itr = ranges_.begin(); itr != ranges_.end(); itr++) {
     int range_value = (*itr)->BelongsToRange(start_timestamp);
-
     // |start_timestamp| is before the current range in this loop. Because
-    // |ranges_| is sorted, this means that we need to create a new range and it
+    // |ranges_| is sorted, this means that we need to create a new range and
     // should be placed before |itr|.
-    // TODO(vrk): We also break out of the loop if |buffers| completely overlaps
-    // the current range. This is to cover the case when |buffers| belongs to
-    // the current range, but also completely overlaps it. This should be
-    // removed when start overlap is handled properly.
-    if (range_value < 0 || (*itr)->IsCompletelyOverlappedBy(buffers))
+    if (range_value < 0)
       break;
 
     if (range_value == 0) {
       // Found an existing range into which we can append buffers.
-      range = *itr;
-
-      if (range->CanAppendToEnd(buffers) && waiting_for_keyframe_) {
-        // Currently we do not support the case where the next buffer after the
-        // buffers in the track buffer is not a keyframe.
-        if (!buffers.front()->IsKeyframe())
-          return false;
-        waiting_for_keyframe_ = false;
-      }
+      range_for_new_buffers = itr;
       break;
     }
   }
 
-  if (!range) {
+  if (range_for_new_buffers == ranges_.end()) {
     // Ranges must begin with a keyframe.
     if (!buffers.front()->IsKeyframe())
       return false;
-
-    range = new SourceBufferRange();
-    itr = ranges_.insert(itr, range);
+    range_for_new_buffers =
+        ranges_.insert(itr, new SourceBufferRange(buffers));
+  } else {
+    InsertIntoExistingRange(range_for_new_buffers, buffers);
   }
 
-  // Append buffers to the appropriate range.
-  range->Append(buffers);
-
-  // Increment |itr| to be the range after |range|.
-  itr++;
-
   // Resolve overlaps.
-  itr = ResolveCompleteOverlaps(itr, range);
-  itr = ResolveEndOverlaps(itr, range);
-  MergeWithAdjacentRangeIfNecessary(itr, range);
+  ResolveCompleteOverlaps(range_for_new_buffers);
+  ResolveEndOverlap(range_for_new_buffers);
+  MergeWithAdjacentRangeIfNecessary(range_for_new_buffers);
 
   // Finally, try to complete pending seek if one exists.
   if (seek_pending_)
@@ -261,74 +262,183 @@ bool SourceBufferStream::Append(
   return true;
 }
 
-SourceBufferStream::RangeList::iterator
-SourceBufferStream::ResolveCompleteOverlaps(
-    const RangeList::iterator& range_itr, SourceBufferRange* new_range) {
-  RangeList::iterator itr = range_itr;
-  while (itr != ranges_.end() && new_range->CompletelyOverlaps(**itr)) {
-    if (*itr == selected_range_) {
-      // Get the timestamp for the next buffer in the sequence.
-      base::TimeDelta next_timestamp = selected_range_->GetNextTimestamp();
-      // Then seek to the next keyframe after (or equal to) |next_timestamp|.
-      // This will allow us to transition from the old buffers to the new
-      // buffers seamlessly.
-      base::TimeDelta next_keyframe_timestamp =
-          new_range->SeekAfter(next_timestamp);
-
-      // If there's no keyframe after |next_timestamp|, then set flag to wait
-      // for the next keyframe in this range to be appended.
-      if (next_keyframe_timestamp == kNoTimestamp())
-        waiting_for_keyframe_ = true;
-
-      // Add all the old buffers up until |next_keyframe_timestamp| into
-      // |track_buffer_|. If there was no keyframe, then we add all buffers into
-      // |track_buffer_|.
-      scoped_refptr<StreamParserBuffer> next_buffer;
-      while (selected_range_->GetNextBuffer(&next_buffer) &&
-             (waiting_for_keyframe_ ||
-             next_buffer->GetTimestamp() < next_keyframe_timestamp)) {
-        track_buffer_.push_back(next_buffer);
-      }
+void SourceBufferStream::InsertIntoExistingRange(
+    const RangeList::iterator& range_for_new_buffers_itr,
+    const BufferQueue& new_buffers) {
+  SourceBufferRange* range_for_new_buffers = *range_for_new_buffers_itr;
+  RangeList::iterator next_range_itr = range_for_new_buffers_itr;
+  next_range_itr++;
+
+  // In case this is a middle overlap, save the buffers that come after the end
+  // of |new_buffers|, and add them into a new range.
+  SourceBufferRange* new_portion =
+      range_for_new_buffers->SplitRange(new_buffers.back()->GetEndTimestamp());
+
+  if (new_portion) {
+    next_range_itr = ranges_.insert(next_range_itr, new_portion);
+    // If |range_for_new_buffers| was selected and the next buffer was in the
+    // |new_portion| half, update |selected_range_|.
+    if (selected_range_ == range_for_new_buffers &&
+        new_portion->GetNextTimestamp() != kNoTimestamp()) {
+      selected_range_ = new_portion;
+    }
+  }
+
+  BufferQueue deleted_buffers;
+  BufferQueue::iterator next_buffer;
+  range_for_new_buffers->DeleteAfter(
+      new_buffers.front(), &deleted_buffers, &next_buffer);
+  range_for_new_buffers->AppendToEnd(new_buffers);
+
+  if (selected_range_ == range_for_new_buffers &&
+      !deleted_buffers.empty() && next_buffer != deleted_buffers.end()) {
+    UpdateTrackBuffer(range_for_new_buffers_itr, deleted_buffers, next_buffer);
+  }
+}
 
-      selected_range_ = new_range;
+void SourceBufferStream::ResolveCompleteOverlaps(
+    const RangeList::iterator& range_with_new_buffers_itr) {
+  SourceBufferRange* range_with_new_buffers = *range_with_new_buffers_itr;
+  RangeList::iterator next_range_itr = range_with_new_buffers_itr;
+  next_range_itr++;
+
+  while (next_range_itr != ranges_.end() &&
+         range_with_new_buffers->CompletelyOverlaps(**next_range_itr)) {
+    if (*next_range_itr == selected_range_) {
+      // Delete everything from the selected range that |new_range| overlaps,
+      // and save the next buffers.
+      BufferQueue deleted_buffers;
+      BufferQueue::iterator next_buffer;
+      (*next_range_itr)->DeleteAll(&deleted_buffers, &next_buffer);
+      UpdateTrackBuffer(range_with_new_buffers_itr, deleted_buffers,
+                        next_buffer);
+      DCHECK_NE(selected_range_, *next_range_itr);
     }
-    delete *itr;
-    itr = ranges_.erase(itr);
+    delete *next_range_itr;
+    next_range_itr = ranges_.erase(next_range_itr);
   }
-  return itr;
 }
 
-SourceBufferStream::RangeList::iterator
-SourceBufferStream::ResolveEndOverlaps(
-    const RangeList::iterator& range_itr, SourceBufferRange* new_range) {
-  RangeList::iterator itr = range_itr;
-  while (itr != ranges_.end() && new_range->EndOverlaps(**itr)) {
-    DCHECK_NE(*itr, selected_range_);
-    delete *itr;
-    itr = ranges_.erase(itr);
+void SourceBufferStream::ResolveEndOverlap(
+    const RangeList::iterator& range_with_new_buffers_itr) {
+  SourceBufferRange* range_with_new_buffers = *range_with_new_buffers_itr;
+  RangeList::iterator next_range_itr = range_with_new_buffers_itr;
+  next_range_itr++;
+
+  if (next_range_itr == ranges_.end() ||
+      !range_with_new_buffers->EndOverlaps(**next_range_itr)) {
+    return;
+  }
+
+  // Split the overlapped range after |range_with_new_buffers|'s last buffer
+  // overlaps. Now |overlapped_range| contains only the buffers that do not
+  // belong in |ranges_| anymore, and |new_next_range| contains buffers that
+  // go after |range_with_new_buffers| (without overlap).
+  scoped_ptr<SourceBufferRange> overlapped_range(*next_range_itr);
+  next_range_itr = ranges_.erase(next_range_itr);
+
+  SourceBufferRange* new_next_range =
+      overlapped_range->SplitRange(range_with_new_buffers->GetEndTimestamp());
+
+  // If there were non-overlapped buffers, add the new range to |ranges_|.
+  if (new_next_range)
+    ranges_.insert(next_range_itr, new_next_range);
+
+  // If we didn't overlap a selected range, return.
+  if (selected_range_ != overlapped_range.get())
+    return;
+
+  // If the next buffer was in the |new_next_range| half of the overlapped
+  // range, then the |selected_range_| is now |new_next_range|.
+  if (new_next_range &&
+      new_next_range->GetNextTimestamp() != kNoTimestamp()) {
+    selected_range_ = new_next_range;
+    return;
+  }
+
+  // Otherwise, update track buffer with overlapped buffers.
+  BufferQueue deleted_buffers;
+  scoped_refptr<StreamParserBuffer> buffer;
+  while (overlapped_range->GetNextBuffer(&buffer)) {
+    deleted_buffers.push_back(buffer);
+  }
+  BufferQueue::iterator next_buffer = deleted_buffers.begin();
+
+  // This will update |selected_range_| to no longer point to
+  // |overlapped_range|.
+  UpdateTrackBuffer(range_with_new_buffers_itr, deleted_buffers, next_buffer);
+  DCHECK_NE(selected_range_, overlapped_range.get());
+}
+
+void SourceBufferStream::UpdateTrackBuffer(
+    const RangeList::iterator& range_with_new_buffers_itr,
+    const BufferQueue& deleted_buffers,
+    const BufferQueue::iterator& next_buffer) {
+  DCHECK(!deleted_buffers.empty() && next_buffer != deleted_buffers.end());
+
+  SourceBufferRange* range_with_new_buffers = *range_with_new_buffers_itr;
+
+  // Seek to the next keyframe after (or equal to) the timestamp of the next
+  // buffer being overlapped.
+  range_with_new_buffers->SeekAfter((*next_buffer)->GetTimestamp());
+  selected_range_ = range_with_new_buffers;
+
+  base::TimeDelta next_keyframe_timestamp =
+      range_with_new_buffers->GetNextTimestamp();
+
+  if (track_buffer_.empty()) {
+    // Add all the old buffers up until |next_keyframe_timestamp| into
+    // |track_buffer_|. If there was no next keyframe, then we add all buffers
+    // into |track_buffer_|.
+    BufferQueue::iterator next_buffer_itr = next_buffer;
+    while (next_buffer_itr != deleted_buffers.end() &&
+           (next_keyframe_timestamp == kNoTimestamp() ||
+            (*next_buffer_itr)->GetTimestamp() < next_keyframe_timestamp)) {
+      track_buffer_.push_back(*next_buffer_itr);
+      next_buffer_itr++;
+    }
+  }
+
+  // See if the next range contains the keyframe after the end of the
+  // |track_buffer_|, and if so, change |selected_range_|.
+  if (next_keyframe_timestamp == kNoTimestamp()) {
+    DCHECK(!track_buffer_.empty());
+    RangeList::iterator next_range_itr = range_with_new_buffers_itr;
+    next_range_itr++;
+    if (next_range_itr != ranges_.end()) {
+      (*next_range_itr)->SeekAfter(track_buffer_.back()->GetEndTimestamp());
+      if (IsNextInSequence(track_buffer_.back(),
+                           (*next_range_itr)->GetNextTimestamp())) {
+        selected_range_ = *next_range_itr;
+      }
+    }
   }
-  return itr;
 }
 
 void SourceBufferStream::MergeWithAdjacentRangeIfNecessary(
-    const RangeList::iterator& itr, SourceBufferRange* new_range) {
-  if (itr != ranges_.end() && new_range->CanAppendToEnd(**itr)) {
-    bool transfer_current_position = selected_range_ == *itr;
-    new_range->AppendToEnd(**itr, transfer_current_position);
+    const RangeList::iterator& range_with_new_buffers_itr) {
+  SourceBufferRange* range_with_new_buffers = *range_with_new_buffers_itr;
+  RangeList::iterator next_range_itr = range_with_new_buffers_itr;
+  next_range_itr++;
+
+  if (next_range_itr != ranges_.end() &&
+      range_with_new_buffers->CanAppendToEnd(**next_range_itr)) {
+    bool transfer_current_position = selected_range_ == *next_range_itr;
+    range_with_new_buffers->AppendToEnd(**next_range_itr,
+                                        transfer_current_position);
     // Update |selected_range_| pointer if |range| has become selected after
     // merges.
     if (transfer_current_position)
-      selected_range_ = new_range;
+      selected_range_ = range_with_new_buffers;
 
-    delete *itr;
-    ranges_.erase(itr);
+    delete *next_range_itr;
+    ranges_.erase(next_range_itr);
   }
 }
 
 void SourceBufferStream::Seek(base::TimeDelta timestamp) {
   selected_range_ = NULL;
   track_buffer_.clear();
-  waiting_for_keyframe_ = false;
 
   seek_buffer_timestamp_ = timestamp;
   seek_pending_ = true;
@@ -388,26 +498,12 @@ bool SourceBufferStream::CanEndOfStream() const {
   return ranges_.empty() || selected_range_ == ranges_.back();
 }
 
-SourceBufferRange::SourceBufferRange()
-    : next_buffer_index_(-1) {
-}
-
-void SourceBufferRange::Append(const BufferQueue& new_buffers) {
-  base::TimeDelta start_timestamp = new_buffers.front()->GetTimestamp();
-
-  if (!buffers_.empty() && start_timestamp < BufferedEnd()) {
-    // We are overwriting existing data, so find the starting point where
-    // things will get overwritten.
-    BufferQueue::iterator starting_point =
-        std::lower_bound(buffers_.begin(), buffers_.end(),
-                         new_buffers.front(),
-                         BufferComparator);
-
-    // Remove everything from |starting_point| onward.
-    buffers_.erase(starting_point, buffers_.end());
-  }
-
-  // Append data.
+SourceBufferRange::SourceBufferRange(const BufferQueue& new_buffers)
+    : next_buffer_index_(-1),
+      waiting_for_keyframe_(false),
+      next_keyframe_timestamp_(kNoTimestamp()) {
+  DCHECK(!new_buffers.empty());
+  DCHECK(new_buffers.front()->IsKeyframe());
   AppendToEnd(new_buffers);
 }
 
@@ -420,6 +516,13 @@ void SourceBufferRange::AppendToEnd(const BufferQueue& new_buffers) {
     if ((*itr)->IsKeyframe()) {
       keyframe_map_.insert(
           std::make_pair((*itr)->GetTimestamp(), buffers_.size() - 1));
+
+      if (waiting_for_keyframe_ &&
+          (*itr)->GetTimestamp() >= next_keyframe_timestamp_) {
+        next_buffer_index_ = buffers_.size() - 1;
+        next_keyframe_timestamp_ = base::TimeDelta();
+        waiting_for_keyframe_ = false;
+      }
     }
   }
 }
@@ -428,6 +531,9 @@ void SourceBufferRange::Seek(base::TimeDelta timestamp) {
   DCHECK(CanSeekTo(timestamp));
   DCHECK(!keyframe_map_.empty());
 
+  next_keyframe_timestamp_ = base::TimeDelta();
+  waiting_for_keyframe_ = false;
+
   KeyframeMap::iterator result = keyframe_map_.lower_bound(timestamp);
   // lower_bound() returns the first element >= |timestamp|, so we want the
   // previous element if it did not return the element exactly equal to
@@ -440,8 +546,7 @@ void SourceBufferRange::Seek(base::TimeDelta timestamp) {
   DCHECK_LT(next_buffer_index_, static_cast<int>(buffers_.size()));
 }
 
-base::TimeDelta SourceBufferRange::SeekAfter(base::TimeDelta timestamp) {
-  DCHECK_EQ(BelongsToRange(timestamp), 0);
+void SourceBufferRange::SeekAfter(base::TimeDelta timestamp) {
   DCHECK(!keyframe_map_.empty());
 
   // lower_bound() returns the first element >= |timestamp|, so |result| is the
@@ -451,21 +556,106 @@ base::TimeDelta SourceBufferRange::SeekAfter(base::TimeDelta timestamp) {
   // If there isn't a keyframe after |timestamp|, then seek to end and return
   // kNoTimestamp to signal such.
   if (result == keyframe_map_.end()) {
-    next_buffer_index_ = buffers_.size();
-    return kNoTimestamp();
+    waiting_for_keyframe_ = true;
+    next_buffer_index_ = -1;
+    next_keyframe_timestamp_ = timestamp;
+    return;
   }
 
   next_buffer_index_ = result->second;
   DCHECK_LT(next_buffer_index_, static_cast<int>(buffers_.size()));
-  return result->first;
+}
+
+SourceBufferRange* SourceBufferRange::SplitRange(base::TimeDelta timestamp) {
+  // Find the first keyframe after |timestamp|.
+  KeyframeMap::iterator new_beginning_keyframe =
+      keyframe_map_.lower_bound(timestamp);
+
+  // If there is no keyframe after |timestamp|, we can't split the range.
+  if (new_beginning_keyframe == keyframe_map_.end())
+    return NULL;
+
+  int keyframe_index = new_beginning_keyframe->second;
+  DCHECK_LT(keyframe_index, static_cast<int>(buffers_.size()));
+
+  BufferQueue removed_buffers;
+  BufferQueue::iterator next_buffer;
+  DeleteAfter(
+      buffers_.begin() + keyframe_index, &removed_buffers, &next_buffer);
+
+  SourceBufferRange* split_range = new SourceBufferRange(removed_buffers);
+  if (next_buffer != removed_buffers.end()) {
+    split_range->next_buffer_index_ = next_buffer - removed_buffers.begin();
+  }
+  return split_range;
+}
+
+void SourceBufferRange::DeleteAll(BufferQueue* removed_buffers,
+                                  BufferQueue::iterator* next_buffer) {
+  DeleteAfter(buffers_.begin(), removed_buffers, next_buffer);
+}
+
+void SourceBufferRange::DeleteAfter(
+    scoped_refptr<StreamParserBuffer> buffer,
+    BufferQueue* removed_buffers,
+    BufferQueue::iterator* next_buffer) {
+  // Find the place in |buffers_| where we will begin deleting data.
+  BufferQueue::iterator starting_point =
+      std::lower_bound(buffers_.begin(), buffers_.end(),
+                       buffer,
+                       BufferComparator);
+  DeleteAfter(starting_point, removed_buffers, next_buffer);
+}
+
+void SourceBufferRange::DeleteAfter(
+    BufferQueue::iterator starting_point,
+    BufferQueue* removed_buffers,
+    BufferQueue::iterator* next_buffer) {
+  // Return if we're not deleting anything.
+  if (starting_point == buffers_.end())
+    return;
+
+  // Find the first keyframe after |starting_point|.
+  KeyframeMap::iterator starting_point_keyframe =
+      keyframe_map_.lower_bound((*starting_point)->GetTimestamp());
+
+  // Save the buffers we're about to delete.
+  if (removed_buffers) {
+    BufferQueue saved(starting_point, buffers_.end());
+    removed_buffers->swap(saved);
+    if (next_buffer)
+      *next_buffer = removed_buffers->end();
+  }
+
+  // Reset the next buffer index if we will be deleting the buffer that's next
+  // in sequence.
+  base::TimeDelta next_buffer_timestamp = GetNextTimestamp();
+  if (next_buffer_timestamp != kNoTimestamp() &&
+      next_buffer_timestamp >= (*starting_point)->GetTimestamp()) {
+    if (removed_buffers && next_buffer) {
+      int starting_offset = starting_point - buffers_.begin();
+      int next_buffer_offset = next_buffer_index_ - starting_offset;
+      DCHECK_GE(next_buffer_offset, 0);
+      *next_buffer = removed_buffers->begin() + next_buffer_offset;
+    }
+    next_buffer_index_ = -1;
+  }
+
+  // Remove keyframes from |starting_point| onward.
+  keyframe_map_.erase(starting_point_keyframe, keyframe_map_.end());
+
+  // Remove everything from |starting_point| onward.
+  buffers_.erase(starting_point, buffers_.end());
 }
 
 bool SourceBufferRange::GetNextBuffer(
     scoped_refptr<StreamParserBuffer>* out_buffer) {
-  DCHECK_GE(next_buffer_index_, 0);
-  if (next_buffer_index_ >= static_cast<int>(buffers_.size()))
+  if (waiting_for_keyframe_ ||
+      next_buffer_index_ >= static_cast<int>(buffers_.size())) {
     return false;
+  }
 
+  DCHECK_GE(next_buffer_index_, 0);
   *out_buffer = buffers_.at(next_buffer_index_);
   next_buffer_index_++;
   return true;
@@ -477,18 +667,19 @@ bool SourceBufferRange::HasNextBuffer() const {
 }
 
 base::TimeDelta SourceBufferRange::GetNextTimestamp() const {
-  DCHECK_GE(next_buffer_index_, 0);
   DCHECK(!buffers_.empty());
 
-  if (next_buffer_index_ >= static_cast<int>(buffers_.size()))
-    return buffers_.back()->GetEndTimestamp();
+  if (next_buffer_index_ >= static_cast<int>(buffers_.size()) ||
+      next_buffer_index_ < 0 || waiting_for_keyframe_) {
+    return kNoTimestamp();
+  }
 
   return buffers_.at(next_buffer_index_)->GetTimestamp();
 }
 
 SourceBufferStream::Timespan
 SourceBufferRange::GetBufferedTime() const {
-  return std::make_pair(BufferedStart(), BufferedEnd());
+  return std::make_pair(GetStartTimestamp(), GetEndTimestamp());
 }
 
 void SourceBufferRange::AppendToEnd(const SourceBufferRange& range,
@@ -507,20 +698,19 @@ bool SourceBufferRange::CanAppendToEnd(const SourceBufferRange& range) const {
 }
 
 bool SourceBufferRange::CanAppendToEnd(const BufferQueue& buffers) const {
-  return buffers_.empty() ||
-      IsNextInSequence(buffers_.back(), buffers.front()->GetTimestamp());
+  DCHECK(!buffers_.empty());
+  return IsNextInSequence(buffers_.back(), buffers.front()->GetTimestamp());
 }
 
 int SourceBufferRange::BelongsToRange(base::TimeDelta timestamp) const {
-  if (buffers_.empty())
-    return 1;
+  DCHECK(!buffers_.empty());
 
   if (IsNextInSequence(buffers_.back(), timestamp) ||
-      (BufferedEnd() >= timestamp && BufferedStart() <= timestamp)) {
+      (GetEndTimestamp() >= timestamp && GetStartTimestamp() <= timestamp)) {
     return 0;
   }
 
-  if (BufferedStart() > timestamp)
+  if (GetStartTimestamp() > timestamp)
     return -1;
 
   // |timestamp| must be after this range.
@@ -528,49 +718,28 @@ int SourceBufferRange::BelongsToRange(base::TimeDelta timestamp) const {
 }
 
 bool SourceBufferRange::CanSeekTo(base::TimeDelta timestamp) const {
-  return !keyframe_map_.empty() && BufferedStart() <= timestamp &&
-      BufferedEnd() > timestamp;
+  return !keyframe_map_.empty() && GetStartTimestamp() <= timestamp &&
+      GetEndTimestamp() > timestamp;
 }
 
 bool SourceBufferRange::CompletelyOverlaps(
     const SourceBufferRange& range) const {
-  return BufferedStart() <= range.BufferedStart() &&
-      BufferedEnd() >= range.BufferedEnd();
+  return GetStartTimestamp() <= range.GetStartTimestamp() &&
+      GetEndTimestamp() >= range.GetEndTimestamp();
 }
 
 bool SourceBufferRange::EndOverlaps(const SourceBufferRange& range) const {
-  return range.BufferedStart() < BufferedEnd() &&
-      BufferedEnd() < range.BufferedEnd();
-}
-
-bool SourceBufferRange::IsStartOverlappedBy(const BufferQueue& buffers) const {
-  base::TimeDelta start_timestamp = buffers.front()->GetTimestamp();
-  return BufferedStart() < start_timestamp && start_timestamp < BufferedEnd();
-}
-
-bool SourceBufferRange::IsEndOverlappedBy(const BufferQueue& buffers) const {
-  base::TimeDelta end_timestamp = buffers.back()->GetEndTimestamp();
-  return BufferedStart() < end_timestamp && end_timestamp < BufferedEnd();
-}
-
-bool SourceBufferRange::IsCompletelyOverlappedBy(
-    const BufferQueue& buffers) const {
-  base::TimeDelta start_timestamp = buffers.front()->GetTimestamp();
-  base::TimeDelta end_timestamp = buffers.back()->GetEndTimestamp();
-  return start_timestamp <= BufferedStart() && BufferedEnd() <= end_timestamp;
+  return range.GetStartTimestamp() < GetEndTimestamp() &&
+      GetEndTimestamp() < range.GetEndTimestamp();
 }
 
-base::TimeDelta SourceBufferRange::BufferedStart() const {
-  if (buffers_.empty())
-    return kNoTimestamp();
-
+base::TimeDelta SourceBufferRange::GetStartTimestamp() const {
+  DCHECK(!buffers_.empty());
   return buffers_.front()->GetTimestamp();
 }
 
-base::TimeDelta SourceBufferRange::BufferedEnd() const {
-  if (buffers_.empty())
-    return kNoTimestamp();
-
+base::TimeDelta SourceBufferRange::GetEndTimestamp() const {
+  DCHECK(!buffers_.empty());
   return buffers_.back()->GetEndTimestamp();
 }
 
diff --git a/media/filters/source_buffer_stream.h b/media/filters/source_buffer_stream.h
index ed3dfc3..5df241d3 100644
--- a/media/filters/source_buffer_stream.h
+++ b/media/filters/source_buffer_stream.h
@@ -40,8 +40,6 @@ class MEDIA_EXPORT SourceBufferStream {
   // of order or overlapping. Assumes all buffers within |buffers| are in
   // presentation order and are non-overlapping.
   // Returns true if Append() was successful, false if |buffers| are not added.
-  // TODO(vrk): Implement proper end-overlapping. (crbug.com/125072)
-  // This may trigger garbage collection.
   // TODO(vrk): Implement garbage collection. (crbug.com/125070)
   bool Append(const BufferQueue& buffers);
 
@@ -84,20 +82,37 @@ class MEDIA_EXPORT SourceBufferStream {
  private:
   typedef std::list<SourceBufferRange*> RangeList;
 
+  // Appends |new_buffers| into |range_for_new_buffers_itr|, handling start and
+  // end overlaps if necessary.
+  void InsertIntoExistingRange(
+      const RangeList::iterator& range_for_new_buffers_itr,
+      const BufferQueue& new_buffers);
+
   // Resolve overlapping ranges such that no ranges overlap anymore.
-  // |range_itr| points to the iterator in |ranges_| immediately after
-  // |new_range|. Returns the iterator in |ranges_| immediately after
-  // |new_range|, which may be different from the original |range_itr|.
-  RangeList::iterator ResolveCompleteOverlaps(
-      const RangeList::iterator& range_itr, SourceBufferRange* new_range);
-  RangeList::iterator ResolveEndOverlaps(
-      const RangeList::iterator& range_itr, SourceBufferRange* new_range);
-
-  // Checks to see if the range pointed to by |range_itr| can be appended to the
-  // end of |new_range|, and if so, appends the range and updates |ranges_| to
-  // reflect this.
+  // |range_with_new_buffers_itr| points to the range that has newly appended
+  // buffers.
+  void ResolveCompleteOverlaps(
+      const RangeList::iterator& range_with_new_buffers_itr);
+  void ResolveEndOverlap(const RangeList::iterator& range_with_new_buffers_itr);
+
+  // Adds buffers to |track_buffer_| and updates |selected_range_| accordingly.
+  // |range_with_new_buffers_itr| points to the range containing the newly
+  // appended buffers.
+  // |deleted_buffers| contains all the buffers that were deleted as a result
+  // of appending new buffers into |range_with_new_buffers_itr|. |next_buffer|
+  // points to the buffer in |deleted_buffers| that should be returned by the
+  // next call to GetNextBuffer(). Assumes |deleted_buffers| and |next_buffer|
+  // are valid.
+  // TODO(vrk): This is a little crazy! Ideas for cleanup in crbug.com/129623.
+  void UpdateTrackBuffer(
+      const RangeList::iterator& range_with_new_buffers_itr,
+      const BufferQueue& deleted_buffers,
+      const BufferQueue::iterator& next_buffer);
+
+  // Checks to see if |range_with_new_buffers_itr| can be merged with the range
+  // next to it, and merges them if so.
   void MergeWithAdjacentRangeIfNecessary(
-      const RangeList::iterator& range_itr, SourceBufferRange* new_range);
+      const RangeList::iterator& range_with_new_buffers_itr);
 
   // List of disjoint buffered ranges, ordered by start time.
   RangeList ranges_;
@@ -121,11 +136,6 @@ class MEDIA_EXPORT SourceBufferStream {
   // |track_buffer_| is empty, return buffers from |selected_range_|.
   BufferQueue track_buffer_;
 
-  // True if the next buffer after the end of the |track_buffer_| is not
-  // buffered yet and we need to wait for the next keyframe after
-  // |track_buffer_| to be appended.
-  bool waiting_for_keyframe_;
-
   // True when EndOfStream() has been called and GetNextBuffer() should return
   // EOS buffers for read requests beyond the buffered data.  False initially.
   bool end_of_stream_;
diff --git a/media/filters/source_buffer_stream_unittest.cc b/media/filters/source_buffer_stream_unittest.cc
index 7e043d51..07fc967 100644
--- a/media/filters/source_buffer_stream_unittest.cc
+++ b/media/filters/source_buffer_stream_unittest.cc
@@ -52,6 +52,12 @@ class SourceBufferStreamTest : public testing::Test {
         start_position * frame_duration_, (end_position + 1) * frame_duration_);
   }
 
+  void CheckExpectedTimespan(int start_position, int end_position) {
+    SourceBufferStream::TimespanList expected;
+    expected.push_back(CreateTimespan(start_position, end_position));
+    CheckExpectedTimespans(expected);
+  }
+
   void CheckExpectedTimespans(
       SourceBufferStream::TimespanList expected_times) {
     SourceBufferStream::TimespanList actual_times = stream_.GetBufferedTime();
@@ -62,10 +68,10 @@ class SourceBufferStreamTest : public testing::Test {
          actual_itr != actual_times.end() &&
          expected_itr != expected_times.end();
          actual_itr++, expected_itr++) {
-      EXPECT_EQ(actual_itr->first / frame_duration_,
-                expected_itr->first / frame_duration_);
-      EXPECT_EQ(actual_itr->second / frame_duration_,
-                expected_itr->second / frame_duration_);
+      EXPECT_EQ(expected_itr->first / frame_duration_,
+                actual_itr->first / frame_duration_);
+      EXPECT_EQ(expected_itr->second / frame_duration_,
+                actual_itr->second / frame_duration_);
     }
   }
 
@@ -108,16 +114,21 @@ class SourceBufferStreamTest : public testing::Test {
       if (expected_data) {
         const uint8* actual_data = buffer->GetData();
         const int  actual_size = buffer->GetDataSize();
-        EXPECT_EQ(actual_size, expected_size);
+        EXPECT_EQ(expected_size, actual_size);
         for (int i = 0; i < std::min(actual_size, expected_size); i++) {
-          EXPECT_EQ(actual_data[i], expected_data[i]);
+          EXPECT_EQ(expected_data[i], actual_data[i]);
         }
       }
 
       EXPECT_EQ(buffer->GetTimestamp() / frame_duration_, current_position);
     }
 
-    EXPECT_EQ(current_position, ending_position + 1);
+    EXPECT_EQ(ending_position + 1, current_position);
+  }
+
+  void CheckNoNextBuffer() {
+    scoped_refptr<StreamParserBuffer> buffer;
+    EXPECT_FALSE(stream_.GetNextBuffer(&buffer));
   }
 
   base::TimeDelta frame_duration() const { return frame_duration_; }
@@ -158,9 +169,7 @@ TEST_F(SourceBufferStreamTest, Append_SingleRange) {
   AppendBuffers(0, 15);
 
   // Check expected range.
-  SourceBufferStream::TimespanList expected;
-  expected.push_back(CreateTimespan(0, 14));
-  CheckExpectedTimespans(expected);
+  CheckExpectedTimespan(0, 14);
   // Check buffers in range.
   Seek(0);
   CheckExpectedBuffers(0, 14);
@@ -172,9 +181,7 @@ TEST_F(SourceBufferStreamTest, Append_SingleRange_OneBufferAtATime) {
     AppendBuffers(i, 1);
 
   // Check expected range.
-  SourceBufferStream::TimespanList expected;
-  expected.push_back(CreateTimespan(0, 14));
-  CheckExpectedTimespans(expected);
+  CheckExpectedTimespan(0, 14);
   // Check buffers in range.
   Seek(0);
   CheckExpectedBuffers(0, 14);
@@ -210,9 +217,7 @@ TEST_F(SourceBufferStreamTest, Append_AdjacentRanges) {
   AppendBuffers(12, 3);
 
   // Check expected range.
-  SourceBufferStream::TimespanList expected;
-  expected.push_back(CreateTimespan(0, 25));
-  CheckExpectedTimespans(expected);
+  CheckExpectedTimespan(0, 25);
   // Check buffers in range.
   Seek(0);
   CheckExpectedBuffers(0, 25);
@@ -226,21 +231,19 @@ TEST_F(SourceBufferStreamTest, Append_DoesNotBeginWithKeyframe) {
   AppendBuffers(5, 10);
 
   // Check expected range.
-  SourceBufferStream::TimespanList expected;
-  expected.push_back(CreateTimespan(5, 14));
-  CheckExpectedTimespans(expected);
+  CheckExpectedTimespan(5, 14);
   // Check buffers in range.
   Seek(5);
   CheckExpectedBuffers(5, 14);
 
   // Append fails because the range doesn't begin with a keyframe.
   AppendBuffers_ExpectFailure(17, 10);
-  CheckExpectedTimespans(expected);
+  CheckExpectedTimespan(5, 14);
   Seek(5);
   CheckExpectedBuffers(5, 14);
 }
 
-TEST_F(SourceBufferStreamTest, Overlap_Complete) {
+TEST_F(SourceBufferStreamTest, Complete_Overlap) {
   // Append 5 buffers at positions 5 through 9.
   AppendBuffers(5, 5);
 
@@ -248,15 +251,13 @@ TEST_F(SourceBufferStreamTest, Overlap_Complete) {
   AppendBuffers(0, 15);
 
   // Check expected range.
-  SourceBufferStream::TimespanList expected;
-  expected.push_back(CreateTimespan(0, 14));
-  CheckExpectedTimespans(expected);
+  CheckExpectedTimespan(0, 14);
   // Check buffers in range.
   Seek(0);
   CheckExpectedBuffers(0, 14);
 }
 
-TEST_F(SourceBufferStreamTest, Overlap_Complete_EdgeCase) {
+TEST_F(SourceBufferStreamTest, Complete_Overlap_EdgeCase) {
   // Make each frame a keyframe so that it's okay to overlap frames at any point
   // (instead of needing to respect keyframe boundaries).
   SetStreamInfo(30, 30);
@@ -268,15 +269,13 @@ TEST_F(SourceBufferStreamTest, Overlap_Complete_EdgeCase) {
   AppendBuffers(5, 8);
 
   // Check expected range.
-  SourceBufferStream::TimespanList expected;
-  expected.push_back(CreateTimespan(5, 12));
-  CheckExpectedTimespans(expected);
+  CheckExpectedTimespan(5, 12);
   // Check buffers in range.
   Seek(5);
   CheckExpectedBuffers(5, 12);
 }
 
-TEST_F(SourceBufferStreamTest, Overlap_Start) {
+TEST_F(SourceBufferStreamTest, Start_Overlap) {
   // Append 5 buffers at positions 5 through 9.
   AppendBuffers(5, 5);
 
@@ -284,31 +283,50 @@ TEST_F(SourceBufferStreamTest, Overlap_Start) {
   AppendBuffers(8, 6);
 
   // Check expected range.
-  SourceBufferStream::TimespanList expected;
-  expected.push_back(CreateTimespan(5, 13));
-  CheckExpectedTimespans(expected);
+  CheckExpectedTimespan(5, 13);
   // Check buffers in range.
   Seek(5);
   CheckExpectedBuffers(5, 13);
 }
 
-TEST_F(SourceBufferStreamTest, Overlap_End) {
-  // Append 6 buffers at positions 10 through 15.
-  AppendBuffers(10, 6);
+TEST_F(SourceBufferStreamTest, End_Overlap) {
+  // Append 10 buffers at positions 10 through 19.
+  AppendBuffers(10, 10);
+
+  // Append 10 buffers at positions 5 through 14.
+  AppendBuffers(5, 10);
+
+  // Check expected range.
+  CheckExpectedTimespan(5, 19);
+  // Check buffers in range.
+  Seek(5);
+  CheckExpectedBuffers(5, 19);
+}
+
+TEST_F(SourceBufferStreamTest, End_Overlap_Several) {
+  // Append 10 buffers at positions 10 through 19.
+  AppendBuffers(10, 10);
 
   // Append 8 buffers at positions 5 through 12.
   AppendBuffers(5, 8);
 
-  // Check expected range.
+  // Check expected ranges: stream should not have kept buffers 13 and 14
+  // because the keyframe on which they depended was overwritten.
   SourceBufferStream::TimespanList expected;
   expected.push_back(CreateTimespan(5, 12));
+  expected.push_back(CreateTimespan(15, 19));
   CheckExpectedTimespans(expected);
+
   // Check buffers in range.
   Seek(5);
   CheckExpectedBuffers(5, 12);
+  CheckNoNextBuffer();
+
+  Seek(19);
+  CheckExpectedBuffers(15, 19);
 }
 
-TEST_F(SourceBufferStreamTest, Overlap_Several) {
+TEST_F(SourceBufferStreamTest, Complete_Overlap_Several) {
   // Append 2 buffers at positions 5 through 6.
   AppendBuffers(5, 2);
 
@@ -337,7 +355,7 @@ TEST_F(SourceBufferStreamTest, Overlap_Several) {
   CheckExpectedBuffers(0, 19);
 }
 
-TEST_F(SourceBufferStreamTest, Overlap_SeveralThenMerge) {
+TEST_F(SourceBufferStreamTest, Complete_Overlap_Several_Then_Merge) {
   // Append 2 buffers at positions 5 through 6.
   AppendBuffers(5, 2);
 
@@ -354,15 +372,13 @@ TEST_F(SourceBufferStreamTest, Overlap_SeveralThenMerge) {
   AppendBuffers(0, 20);
 
   // Check expected ranges.
-  SourceBufferStream::TimespanList expected;
-  expected.push_back(CreateTimespan(0, 21));
-  CheckExpectedTimespans(expected);
+  CheckExpectedTimespan(0, 21);
   // Check buffers in range.
   Seek(0);
   CheckExpectedBuffers(0, 21);
 }
 
-TEST_F(SourceBufferStreamTest, Overlap_Selected_Complete) {
+TEST_F(SourceBufferStreamTest, Complete_Overlap_Selected) {
   // Append 10 buffers at positions 5 through 14.
   AppendBuffers(5, 10, &kDataA);
 
@@ -373,9 +389,7 @@ TEST_F(SourceBufferStreamTest, Overlap_Selected_Complete) {
   AppendBuffers(5, 10, &kDataB);
 
   // Check timespans are correct.
-  SourceBufferStream::TimespanList expected;
-  expected.push_back(CreateTimespan(5, 14));
-  CheckExpectedTimespans(expected);
+  CheckExpectedTimespan(5, 14);
 
   // Check that data has been replaced with new data.
   CheckExpectedBuffers(5, 14, &kDataB);
@@ -385,7 +399,7 @@ TEST_F(SourceBufferStreamTest, Overlap_Selected_Complete) {
 // overlaps the range from which the client is currently grabbing buffers. We
 // would expect that the SourceBufferStream would return old data until it hits
 // the keyframe of the new data, after which it will return the new data.
-TEST_F(SourceBufferStreamTest, Overlap_Selected_Complete_TrackBuffer) {
+TEST_F(SourceBufferStreamTest, Complete_Overlap_Selected_TrackBuffer) {
   // Append 10 buffers at positions 5 through 14.
   AppendBuffers(5, 10, &kDataA);
 
@@ -396,10 +410,8 @@ TEST_F(SourceBufferStreamTest, Overlap_Selected_Complete_TrackBuffer) {
   // Do a complete overlap by appending 20 buffers at positions 0 through 19.
   AppendBuffers(0, 20, &kDataB);
 
-  // Check timespans are correct.
-  SourceBufferStream::TimespanList expected;
-  expected.push_back(CreateTimespan(0, 19));
-  CheckExpectedTimespans(expected);
+  // Check timespan is correct.
+  CheckExpectedTimespan(0, 19);
 
   // Expect old data up until next keyframe in new data.
   CheckExpectedBuffers(6, 9, &kDataA);
@@ -413,10 +425,10 @@ TEST_F(SourceBufferStreamTest, Overlap_Selected_Complete_TrackBuffer) {
   CheckExpectedBuffers(0, 19, &kDataB);
 
   // Check timespan continues to be correct.
-  CheckExpectedTimespans(expected);
+  CheckExpectedTimespan(0, 19);
 }
 
-TEST_F(SourceBufferStreamTest, Overlap_Selected_Complete_EdgeCase) {
+TEST_F(SourceBufferStreamTest, Complete_Overlap_Selected_EdgeCase) {
   // Append 10 buffers at positions 5 through 14.
   AppendBuffers(5, 10, &kDataA);
 
@@ -428,9 +440,7 @@ TEST_F(SourceBufferStreamTest, Overlap_Selected_Complete_EdgeCase) {
   AppendBuffers(5, 10, &kDataB);
 
   // Check timespans are correct.
-  SourceBufferStream::TimespanList expected;
-  expected.push_back(CreateTimespan(5, 14));
-  CheckExpectedTimespans(expected);
+  CheckExpectedTimespan(5, 14);
 
   // Expect old data up until next keyframe in new data.
   CheckExpectedBuffers(6, 9, &kDataA);
@@ -444,10 +454,10 @@ TEST_F(SourceBufferStreamTest, Overlap_Selected_Complete_EdgeCase) {
   CheckExpectedBuffers(5, 14, &kDataB);
 
   // Check timespan continues to be correct.
-  CheckExpectedTimespans(expected);
+  CheckExpectedTimespan(5, 14);
 }
 
-TEST_F(SourceBufferStreamTest, Overlap_Selected_Complete_Multiple) {
+TEST_F(SourceBufferStreamTest, Complete_Overlap_Selected_Multiple) {
   static const uint8 kDataC = 0x55;
   static const uint8 kDataD = 0x77;
 
@@ -476,14 +486,511 @@ TEST_F(SourceBufferStreamTest, Overlap_Selected_Complete_Multiple) {
   CheckExpectedBuffers(10, 14, &kDataD);
 
   // At this point we cannot fulfill request.
-  scoped_refptr<StreamParserBuffer> buffer;
-  EXPECT_FALSE(stream_.GetNextBuffer(&buffer));
+  CheckNoNextBuffer();
 
   // Seek back to beginning; all data should be new.
   Seek(5);
   CheckExpectedBuffers(5, 14, &kDataD);
 }
 
+TEST_F(SourceBufferStreamTest, Start_Overlap_Selected) {
+  // Append 10 buffers at positions 0 through 9.
+  AppendBuffers(0, 10, &kDataA);
+
+  // Seek to position 5, then add buffers to overlap data at that position.
+  Seek(5);
+  AppendBuffers(5, 10, &kDataB);
+
+  // Check expected range.
+  CheckExpectedTimespan(0, 14);
+
+  // Because we seeked to a keyframe, the next buffers should all be new data.
+  CheckExpectedBuffers(5, 14, &kDataB);
+
+  // Make sure all data is correct.
+  Seek(0);
+  CheckExpectedBuffers(0, 4, &kDataA);
+  CheckExpectedBuffers(5, 14, &kDataB);
+}
+
+TEST_F(SourceBufferStreamTest, Start_Overlap_Selected_TrackBuffer) {
+  // Append 15 buffers at positions 0 through 14.
+  AppendBuffers(0, 15, &kDataA);
+
+  // Seek to 10 and get buffer.
+  Seek(10);
+  CheckExpectedBuffers(10, 10, &kDataA);
+
+  // Now append 10 buffers of new data at positions 10 through 19.
+  AppendBuffers(10, 10, &kDataB);
+
+  // Check expected range.
+  CheckExpectedTimespan(0, 19);
+
+  // The next 4 buffers should be a from the old buffer, followed by a keyframe
+  // from the new data.
+  CheckExpectedBuffers(11, 14, &kDataA);
+  CheckExpectedBuffers(15, 15, &kDataB, true);
+
+  // The rest of the buffers should be new data.
+  CheckExpectedBuffers(16, 19, &kDataB);
+
+  // Now seek to the beginning; positions 0 through 9 should be the original
+  // data, positions 10 through 19 should be the new data.
+  Seek(0);
+  CheckExpectedBuffers(0, 9, &kDataA);
+  CheckExpectedBuffers(10, 19, &kDataB);
+
+  // Make sure timespan is still correct.
+  CheckExpectedTimespan(0, 19);
+}
+
+TEST_F(SourceBufferStreamTest, Start_Overlap_Selected_EdgeCase) {
+  // Append 10 buffers at positions 5 through 14.
+  AppendBuffers(5, 10, &kDataA);
+
+  Seek(10);
+  CheckExpectedBuffers(10, 10, &kDataA);
+
+  // Now replace the last 5 buffers with new data.
+  AppendBuffers(10, 5, &kDataB);
+
+  // The next 4 buffers should be the origial data, held in the track buffer.
+  CheckExpectedBuffers(11, 14, &kDataA);
+
+  // The next buffer is at position 15, so we should fail to fulfill the
+  // request.
+  CheckNoNextBuffer();
+
+  // Now append data at 15 through 19 and check to make sure it's correct.
+  AppendBuffers(15, 5, &kDataB);
+  CheckExpectedBuffers(15, 19, &kDataB);
+
+  // Seek to beginning of buffered range and check buffers.
+  Seek(5);
+  CheckExpectedBuffers(5, 9, &kDataA);
+  CheckExpectedBuffers(10, 19, &kDataB);
+
+  // Check expected range.
+  CheckExpectedTimespan(5, 19);
+}
+
+// This test covers the case where new buffers end-overlap an existing, selected
+// range, and the next buffer is a keyframe that's being overlapped by new
+// buffers.
+// index:  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0
+// old  :           *A*a a a a A a a a a
+// new  :  B b b b b B b b b b
+// after:  B b b b b*B*b b b b A a a a a
+TEST_F(SourceBufferStreamTest, End_Overlap_Selected) {
+  // Append 10 buffers at positions 5 through 14.
+  AppendBuffers(5, 10, &kDataA);
+
+  // Seek to position 5.
+  Seek(5);
+
+  // Now append 10 buffers at positions 0 through 9.
+  AppendBuffers(0, 10, &kDataB);
+
+  // Check expected range.
+  CheckExpectedTimespan(0, 14);
+
+  // Because we seeked to a keyframe, the next buffers should be new.
+  CheckExpectedBuffers(5, 9, &kDataB);
+
+  // Make sure all data is correct.
+  Seek(0);
+  CheckExpectedBuffers(0, 9, &kDataB);
+  CheckExpectedBuffers(10, 14, &kDataA);
+}
+
+// This test covers the case where new buffers end-overlap an existing, selected
+// range, and the next buffer in the range is after the newly appended buffers.
+// In this particular case, the end overlap does not require a split.
+//
+// index:  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0
+// old  :           |A a a a a A a a*a*a|
+// new  :  B b b b b B b b b b
+// after: |B b b b b B b b b b A a a*a*a|
+TEST_F(SourceBufferStreamTest, End_Overlap_Selected_AfterEndOfNew_1) {
+  // Append 10 buffers at positions 5 through 14.
+  AppendBuffers(5, 10, &kDataA);
+
+  // Seek to position 10, then move to position 13.
+  Seek(10);
+  CheckExpectedBuffers(10, 12, &kDataA);
+
+  // Now append 10 buffers at positions 0 through 9.
+  AppendBuffers(0, 10, &kDataB);
+
+  // Check expected range.
+  CheckExpectedTimespan(0, 14);
+
+  // Make sure rest of data is as expected.
+  CheckExpectedBuffers(13, 14, &kDataA);
+
+  // Make sure all data is correct.
+  Seek(0);
+  CheckExpectedBuffers(0, 9, &kDataB);
+  CheckExpectedBuffers(10, 14, &kDataA);
+}
+
+// This test covers the case where new buffers end-overlap an existing, selected
+// range, and the next buffer in the range is after the newly appended buffers.
+// In this particular case, the end overlap requires a split, and the next
+// buffer is in the split range.
+//
+// index:  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0
+// old  :           |A a a a a A a a*a*a|
+// new  :  B b b b b B b b
+// after: |B b b b b B b b|   |A a a*a*a|
+TEST_F(SourceBufferStreamTest, End_Overlap_Selected_AfterEndOfNew_2) {
+  // Append 10 buffers at positions 5 through 14.
+  AppendBuffers(5, 10, &kDataA);
+
+  // Seek to position 10, then move to position 13.
+  Seek(10);
+  CheckExpectedBuffers(10, 12, &kDataA);
+
+  // Now append 8 buffers at positions 0 through 7.
+  AppendBuffers(0, 8, &kDataB);
+
+  // Check expected ranges.
+  SourceBufferStream::TimespanList expected;
+  expected.push_back(CreateTimespan(0, 7));
+  expected.push_back(CreateTimespan(10, 14));
+  CheckExpectedTimespans(expected);
+
+  // Make sure rest of data is as expected.
+  CheckExpectedBuffers(13, 14, &kDataA);
+
+  // Make sure all data is correct.
+  Seek(0);
+  CheckExpectedBuffers(0, 7, &kDataB);
+  CheckNoNextBuffer();
+
+  Seek(10);
+  CheckExpectedBuffers(10, 14, &kDataA);
+}
+
+// This test covers the case where new buffers end-overlap an existing, selected
+// range, and the next buffer in the range is after the newly appended buffers.
+// In this particular case, the end overlap requires a split, and the next
+// buffer was in between the end of the new data and the split range.
+//
+// index:  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0
+// old  :           |A a a*a*a A a a a a|
+// new  :  B b b b b B b b
+// after: |B b b b b B b b|   |A a a a a|
+// track:                 |a a|
+TEST_F(SourceBufferStreamTest, End_Overlap_Selected_AfterEndOfNew_3) {
+  // Append 10 buffers at positions 5 through 14.
+  AppendBuffers(5, 10, &kDataA);
+
+  // Seek to position 5, then move to position 8.
+  Seek(5);
+  CheckExpectedBuffers(5, 7, &kDataA);
+
+  // Now append 8 buffers at positions 0 through 7.
+  AppendBuffers(0, 8, &kDataB);
+
+  // Check expected ranges.
+  SourceBufferStream::TimespanList expected;
+  expected.push_back(CreateTimespan(0, 7));
+  expected.push_back(CreateTimespan(10, 14));
+  CheckExpectedTimespans(expected);
+
+  // Check for data in the track buffer.
+  CheckExpectedBuffers(8, 9, &kDataA);
+  // The buffer immediately after the track buffer should be a keyframe.
+  CheckExpectedBuffers(10, 10, &kDataA, true);
+
+  // Make sure all data is correct.
+  Seek(0);
+  CheckExpectedBuffers(0, 7, &kDataB);
+  Seek(10);
+  CheckExpectedBuffers(10, 14, &kDataA);
+}
+
+// This test covers the case where new buffers end-overlap an existing, selected
+// range, and the next buffer in the range is overlapped by the new buffers.
+// In this particular case, the end overlap does not require a split.
+//
+// index:  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0
+// old  :           |A a a*a*a A a a a a|
+// new  :  B b b b b B b b b b
+// after: |B b b b b B b b b b A a a a a|
+// track:                 |a a|
+TEST_F(SourceBufferStreamTest, End_Overlap_Selected_OverlappedByNew_1) {
+  // Append 10 buffers at positions 5 through 14.
+  AppendBuffers(5, 10, &kDataA);
+
+  // Seek to position 5, then move to position 8.
+  Seek(5);
+  CheckExpectedBuffers(5, 7, &kDataA);
+
+  // Now append 10 buffers at positions 0 through 9.
+  AppendBuffers(0, 10, &kDataB);
+
+  // Check expected range.
+  CheckExpectedTimespan(0, 14);
+
+  // Check for data in the track buffer.
+  CheckExpectedBuffers(8, 9, &kDataA);
+  // The buffer immediately after the track buffer should be a keyframe.
+  CheckExpectedBuffers(10, 10, &kDataA, true);
+
+  // Make sure all data is correct.
+  Seek(0);
+  CheckExpectedBuffers(0, 9, &kDataB);
+  CheckExpectedBuffers(10, 14, &kDataA);
+}
+
+// This test covers the case where new buffers end-overlap an existing, selected
+// range, and the next buffer in the range is overlapped by the new buffers.
+// In this particular case, the end overlap requires a split, and the next
+// keyframe after the track buffer is in the split range.
+//
+// index:  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0
+// old  :           |A*a*a a a A a a a a|
+// new  :  B b b b b B b
+// after: |B b b b b B b|     |A a a a a|
+// track:             |a a a a|
+TEST_F(SourceBufferStreamTest, End_Overlap_Selected_OverlappedByNew_2) {
+  // Append 10 buffers at positions 5 through 14.
+  AppendBuffers(5, 10, &kDataA);
+
+  // Seek to position 5, then move to position 6.
+  Seek(5);
+  CheckExpectedBuffers(5, 5, &kDataA);
+
+  // Now append 7 buffers at positions 0 through 6.
+  AppendBuffers(0, 7, &kDataB);
+
+  // Check expected ranges.
+  SourceBufferStream::TimespanList expected;
+  expected.push_back(CreateTimespan(0, 6));
+  expected.push_back(CreateTimespan(10, 14));
+  CheckExpectedTimespans(expected);
+
+  // Check for data in the track buffer.
+  CheckExpectedBuffers(6, 9, &kDataA);
+  // The buffer immediately after the track buffer should be a keyframe.
+  CheckExpectedBuffers(10, 10, &kDataA, true);
+
+  // Make sure all data is correct.
+  Seek(0);
+  CheckExpectedBuffers(0, 6, &kDataB);
+  CheckNoNextBuffer();
+
+  Seek(10);
+  CheckExpectedBuffers(10, 14, &kDataA);
+}
+
+// This test covers the case where new buffers end-overlap an existing, selected
+// range, and the next buffer in the range is overlapped by the new buffers.
+// In this particular case, the end overlap requires a split, and the next
+// keyframe after the track buffer is in the range with the new buffers.
+//
+// index:  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0
+// old  :           |A*a*a a a A a a a a A a a a a|
+// new  :  B b b b b B b b b b B b b
+// after: |B b b b b B b b b b B b b|   |A a a a a|
+// track:             |a a a a|
+TEST_F(SourceBufferStreamTest, End_Overlap_Selected_OverlappedByNew_3) {
+  // Append 15 buffers at positions 5 through 19.
+  AppendBuffers(5, 15, &kDataA);
+
+  // Seek to position 5, then move to position 6.
+  Seek(5);
+  CheckExpectedBuffers(5, 5, &kDataA);
+
+  // Now append 13 buffers at positions 0 through 12.
+  AppendBuffers(0, 13, &kDataB);
+
+  // Check expected ranges.
+  SourceBufferStream::TimespanList expected;
+  expected.push_back(CreateTimespan(0, 12));
+  expected.push_back(CreateTimespan(15, 19));
+  CheckExpectedTimespans(expected);
+
+  // Check for data in the track buffer.
+  CheckExpectedBuffers(6, 9, &kDataA);
+  // The buffer immediately after the track buffer should be a keyframe
+  // from the new data.
+  CheckExpectedBuffers(10, 10, &kDataB, true);
+
+  // Make sure all data is correct.
+  Seek(0);
+  CheckExpectedBuffers(0, 12, &kDataB);
+  CheckNoNextBuffer();
+
+  Seek(15);
+  CheckExpectedBuffers(15, 19, &kDataA);
+}
+
+// This test covers the case where new buffers end-overlap an existing, selected
+// range, and there is no keyframe after the end of the new buffers.
+// index:  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0
+// old  :           |A*a*a a a|
+// new  :  B b b b b B
+// after: |B b b b b B|
+// track:             |a a a a|
+TEST_F(SourceBufferStreamTest, End_Overlap_Selected_NoKeyframeAfterNew) {
+  // Append 5 buffers at positions 5 through 9.
+  AppendBuffers(5, 5, &kDataA);
+
+  // Seek to position 5, then move to position 6.
+  Seek(5);
+  CheckExpectedBuffers(5, 5, &kDataA);
+
+  // Now append 6 buffers at positions 0 through 5.
+  AppendBuffers(0, 6, &kDataB);
+
+  // Check expected range.
+  CheckExpectedTimespan(0, 5);
+
+  // Check for data in the track buffer.
+  CheckExpectedBuffers(6, 9, &kDataA);
+
+  // Now there's no data to fulfill the request.
+  CheckNoNextBuffer();
+
+  // Let's fill in the gap, buffers 6 through 10.
+  AppendBuffers(6, 5, &kDataB);
+
+  // We should be able to get the next buffer.
+  CheckExpectedBuffers(10, 10, &kDataB);
+}
+
+// This test covers the case when new buffers overlap the middle of a selected
+// range. This tests the case when there is no split and the next buffer is a
+// keyframe.
+// index:  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0
+// old  :  A a a a a*A*a a a a A a a a a
+// new  :            B b b b b
+// after:  A a a a a*B*b b b b A a a a a
+TEST_F(SourceBufferStreamTest, Middle_Overlap_Selected_1) {
+  // Append 15 buffers at positions 0 through 14.
+  AppendBuffers(0, 15, &kDataA);
+
+  // Seek to position 5.
+  Seek(5);
+
+  // Now append 5 buffers at positions 5 through 9.
+  AppendBuffers(5, 5, &kDataB);
+
+  // Check expected range.
+  CheckExpectedTimespan(0, 14);
+
+  // Check for next data; should be new data.
+  CheckExpectedBuffers(5, 9, &kDataB);
+
+  // Make sure all data is correct.
+  Seek(0);
+  CheckExpectedBuffers(0, 4, &kDataA);
+  CheckExpectedBuffers(5, 9, &kDataB);
+  CheckExpectedBuffers(10, 14, &kDataA);
+}
+
+// This test covers the case when new buffers overlap the middle of a selected
+// range. This tests the case when there is no split and the next buffer is
+// after the new buffers.
+// index:  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0
+// old  :  A a a a a A a a a a A*a*a a a
+// new  :            B b b b b
+// after:  A a a a a B b b b b A*a*a a a
+TEST_F(SourceBufferStreamTest, Middle_Overlap_Selected_2) {
+  // Append 15 buffers at positions 0 through 14.
+  AppendBuffers(0, 15, &kDataA);
+
+  // Seek to 10 then move to position 11.
+  Seek(10);
+  CheckExpectedBuffers(10, 10, &kDataA);
+
+  // Now append 5 buffers at positions 5 through 9.
+  AppendBuffers(5, 5, &kDataB);
+
+  // Check expected range.
+  CheckExpectedTimespan(0, 14);
+
+  // Make sure data is correct.
+  CheckExpectedBuffers(11, 14, &kDataA);
+  Seek(0);
+  CheckExpectedBuffers(0, 4, &kDataA);
+  CheckExpectedBuffers(5, 9, &kDataB);
+  CheckExpectedBuffers(10, 14, &kDataA);
+}
+
+// This test covers the case when new buffers overlap the middle of a selected
+// range. This tests the case when there is a split and the next buffer is
+// before the new buffers.
+// index:  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0
+// old  :  A a*a*a a A a a a a A a a a a
+// new  :            B b b
+// after:  A a*a*a a B b b|   |A a a a a
+TEST_F(SourceBufferStreamTest, Middle_Overlap_Selected_3) {
+  // Append 15 buffers at positions 0 through 14.
+  AppendBuffers(0, 15, &kDataA);
+
+  // Seek to beginning then move to position 2.
+  Seek(0);
+  CheckExpectedBuffers(0, 1, &kDataA);
+
+  // Now append 3 buffers at positions 5 through 7.
+  AppendBuffers(5, 3, &kDataB);
+
+  // Check expected range.
+  SourceBufferStream::TimespanList expected;
+  expected.push_back(CreateTimespan(0, 7));
+  expected.push_back(CreateTimespan(10, 14));
+  CheckExpectedTimespans(expected);
+
+  // Make sure data is correct.
+  CheckExpectedBuffers(2, 4, &kDataA);
+  CheckExpectedBuffers(5, 7, &kDataB);
+  Seek(10);
+  CheckExpectedBuffers(10, 14, &kDataA);
+}
+
+// This test covers the case when new buffers overlap the middle of a selected
+// range. This tests the case when there is a split and the next buffer is after
+// the new buffers but before the split range.
+// index:  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0
+// old  :  A a a a a A a a*a*a A a a a a
+// new  :            B b b
+// after: |A a a a a B b b|   |A a a a a|
+// track:                 |a a|
+TEST_F(SourceBufferStreamTest, Middle_Overlap_Selected_4) {
+  // Append 15 buffers at positions 0 through 14.
+  AppendBuffers(0, 15, &kDataA);
+
+  // Seek to 5 then move to position 8.
+  Seek(5);
+  CheckExpectedBuffers(5, 7, &kDataA);
+
+  // Now append 3 buffers at positions 5 through 7.
+  AppendBuffers(5, 3, &kDataB);
+
+  // Check expected range.
+  SourceBufferStream::TimespanList expected;
+  expected.push_back(CreateTimespan(0, 7));
+  expected.push_back(CreateTimespan(10, 14));
+  CheckExpectedTimespans(expected);
+
+  // Buffers 8 and 9 should be in the track buffer.
+  CheckExpectedBuffers(8, 9, &kDataA);
+  // The buffer immediately after the track buffer should be a keyframe.
+  CheckExpectedBuffers(10, 10, &kDataA, true);
+
+  // Make sure all data is correct.
+  Seek(0);
+  CheckExpectedBuffers(0, 4, &kDataA);
+  CheckExpectedBuffers(5, 7, &kDataB);
+  Seek(10);
+  CheckExpectedBuffers(10, 14, &kDataA);
+}
+
 TEST_F(SourceBufferStreamTest, Seek_Keyframe) {
   // Append 6 buffers at positions 0 through 5.
   AppendBuffers(0, 6);
@@ -515,8 +1022,7 @@ TEST_F(SourceBufferStreamTest, Seek_NotBuffered) {
   Seek(0);
 
   // Try to get buffer; nothing's appended.
-  scoped_refptr<StreamParserBuffer> buffer;
-  EXPECT_FALSE(stream_.GetNextBuffer(&buffer));
+  CheckNoNextBuffer();
 
   // Append 2 buffers at positions 0.
   AppendBuffers(0, 2);
@@ -525,7 +1031,7 @@ TEST_F(SourceBufferStreamTest, Seek_NotBuffered) {
 
   // Try to get buffer out of range.
   Seek(2);
-  EXPECT_FALSE(stream_.GetNextBuffer(&buffer));
+  CheckNoNextBuffer();
 }
 
 TEST_F(SourceBufferStreamTest, Seek_InBetweenTimestamps) {
@@ -559,38 +1065,15 @@ TEST_F(SourceBufferStreamTest, Seek_After_TrackBuffer_Filled) {
   // Do a complete overlap by appending 20 buffers at positions 0 through 19.
   AppendBuffers(0, 20, &kDataB);
 
-  // Check timespans are correct.
-  SourceBufferStream::TimespanList expected;
-  expected.push_back(CreateTimespan(0, 19));
-  CheckExpectedTimespans(expected);
+  // Check timespan is correct.
+  CheckExpectedTimespan(0, 19);
 
   // Seek to beginning; all data should be new.
   Seek(0);
   CheckExpectedBuffers(0, 19, &kDataB);
 
   // Check timespan continues to be correct.
-  CheckExpectedTimespans(expected);
-}
-
-// TODO(vrk): When overlaps are handled more elegantly, this test should be
-// rewritten to test for more meaningful outcomes. Right now we are just
-// testing to make sure nothing crazy happens in this scenario (like losing
-// the seek position or garbage collecting the data at position 13).
-// Bug for overlaps is crbug.com/125072.
-TEST_F(SourceBufferStreamTest, GetNextBuffer_AfterOverlap) {
-  // Append 15 buffers at positions 0 through 14.
-  AppendBuffers(0, 15);
-
-  // Seek to buffer at position 13.
-  Seek(13);
-
-  // Append 5 buffers at positions 10 through 14.
-  // The current implementation expects a failure, though fixing
-  // crbug.com/125072 should change this expectation.
-  AppendBuffers_ExpectFailure(10, 5);
-
-  // Make sure we can still get the buffer at 13.
-  CheckExpectedBuffers(10, 13);
+  CheckExpectedTimespan(0, 19);
 }
 
 TEST_F(SourceBufferStreamTest, GetNextBuffer_AfterMerges) {
@@ -604,18 +1087,14 @@ TEST_F(SourceBufferStreamTest, GetNextBuffer_AfterMerges) {
   AppendBuffers(5, 5);
 
   // Make sure ranges are merged.
-  SourceBufferStream::TimespanList expected;
-  expected.push_back(CreateTimespan(5, 14));
-  CheckExpectedTimespans(expected);
+  CheckExpectedTimespan(5, 14);
 
   // Make sure the next buffer is correct.
   CheckExpectedBuffers(10, 10);
 
   // Append 5 buffers at positions 15 through 19.
   AppendBuffers(15, 5);
-  expected.clear();
-  expected.push_back(CreateTimespan(5, 19));
-  CheckExpectedTimespans(expected);
+  CheckExpectedTimespan(5, 19);
 
   // Make sure the remaining next buffers are correct.
   CheckExpectedBuffers(11, 14);
@@ -630,8 +1109,7 @@ TEST_F(SourceBufferStreamTest, GetNextBuffer_ExhaustThenAppend) {
   CheckExpectedBuffers(0, 3);
 
   // Next buffer is at position 4, so should not be able to fulfill request.
-  scoped_refptr<StreamParserBuffer> buffer;
-  EXPECT_FALSE(stream_.GetNextBuffer(&buffer));
+  CheckNoNextBuffer();
 
   // Append 2 buffers at positions 4 through 5.
   AppendBuffers(4, 2);
@@ -659,8 +1137,7 @@ TEST_F(SourceBufferStreamTest, GetNextBuffer_Overlap_Selected_Complete) {
 
   // Next buffer is at position 10, so should not be able to fulfill the
   // request.
-  scoped_refptr<StreamParserBuffer> buffer;
-  EXPECT_FALSE(stream_.GetNextBuffer(&buffer));
+  CheckNoNextBuffer();
 
   // Now add 5 new buffers at positions 10 through 14.
   AppendBuffers(10, 5, &kDataB);
-- 
cgit v1.1