// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "media/filters/source_buffer_stream.h"

#include <algorithm>
#include <map>

#include "base/basictypes.h"
#include "base/bind.h"
#include "base/logging.h"
#include "base/stl_util.h"

#if defined(__LB_SHELL__) || defined(COBALT)
#include "media/base/shell_media_platform.h"
#endif

namespace media {

// Helper class representing a range of buffered data. All buffers in a
// SourceBufferRange are ordered sequentially in presentation order with no
// gaps.
class SourceBufferRange {
 public:
  typedef std::deque<scoped_refptr<StreamParserBuffer> > BufferQueue;

  // Returns the maximum distance in time between any buffer seen in this
  // stream. Used to estimate the duration of a buffer if its duration is not
  // known.
  typedef base::Callback<base::TimeDelta()> InterbufferDistanceCB;

  // Creates a source buffer range with |new_buffers|. |new_buffers| cannot be
  // empty and the front of |new_buffers| must be a keyframe.
  // |media_segment_start_time| refers to the starting timestamp for the media
  // segment to which these buffers belong.
  SourceBufferRange(const BufferQueue& new_buffers,
                    base::TimeDelta media_segment_start_time,
                    const InterbufferDistanceCB& interbuffer_distance_cb);

  // 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 AppendBuffersToEnd(const BufferQueue& buffers);
  bool CanAppendBuffersToEnd(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 AppendRangeToEnd(const SourceBufferRange& range,
                        bool transfer_current_position);
  bool CanAppendRangeToEnd(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|.
  void SeekAheadTo(base::TimeDelta timestamp);

  // Updates |next_buffer_index_| to point to next keyframe strictly after
  // |timestamp|.
  void SeekAheadPast(base::TimeDelta timestamp);

  // Seeks to the beginning of the range.
  void SeekToStart();

  // Finds the next keyframe from |buffers_| after |timestamp| (or at
  // |timestamp| if |is_exclusive| is false) 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, bool is_exclusive);

  // Deletes the buffers from this range starting at |timestamp|, exclusive if
  // |is_exclusive| is true, inclusive otherwise.
  // 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.
  // |deleted_buffers| contains the buffers that were deleted from this range,
  // starting at the buffer that had been at |next_buffer_index_|.
  // Returns true if the |next_buffer_index_| is reset. Note that this method
  // may return true even if it does not add any buffers to |deleted_buffers|.
  // This indicates that the range had not buffered |next_buffer_index_|, but
  // a buffer at that position would have been deleted.
  bool TruncateAt(base::TimeDelta timestamp,
                  BufferQueue* deleted_buffers, bool is_exclusive);
  // Deletes all buffers in range.
  bool DeleteAll(BufferQueue* deleted_buffers);

  // Deletes a GOP from the front or back of the range and moves these
  // buffers into |deleted_buffers|. Returns the number of bytes deleted from
  // the range (i.e. the size in bytes of |deleted_buffers|).
  int DeleteGOPFromFront(BufferQueue* deleted_buffers);
  int DeleteGOPFromBack(BufferQueue* deleted_buffers);

  // Indicates whether the GOP at the beginning or end of the range contains the
  // next buffer position.
  bool FirstGOPContainsNextBufferPosition() const;
  bool LastGOPContainsNextBufferPosition() const;

  // Updates |out_buffer| with the next buffer in presentation order. Seek()
  // must be called before calls to GetNextBuffer(), and buffers are returned
  // in order from the last call to Seek(). Returns true if |out_buffer| is
  // filled with a valid buffer, false if there is not enough data to fulfill
  // the request.
  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.
  bool HasNextBufferPosition() const;

  // Resets this range to an "unseeked" state.
  void ResetNextBufferPosition();

  // Returns the timestamp of the next buffer that will be returned from
  // GetNextBuffer(), or kNoTimestamp() if the timestamp is unknown.
  base::TimeDelta GetNextTimestamp() const;

  // Returns the start timestamp of the range.
  base::TimeDelta GetStartTimestamp() const;

  // Returns the timestamp of the last buffer in the range.
  base::TimeDelta GetEndTimestamp() const;

  // Returns the timestamp for the end of the buffered region in this range.
  // This is an approximation if the duration for the last buffer in the range
  // is unset.
  base::TimeDelta GetBufferedEndTimestamp() 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.
  bool BelongsToRange(base::TimeDelta timestamp) const;

  // Returns true if the range has enough data to seek to the specified
  // |timestamp|, false otherwise.
  bool CanSeekTo(base::TimeDelta timestamp) const;

  // Returns true if this range's buffered timespan completely overlaps the
  // buffered timespan of |range|.
  bool CompletelyOverlaps(const SourceBufferRange& range) const;

  // Returns true if the end of this range contains buffers that overlaps with
  // the beginning of |range|.
  bool EndOverlaps(const SourceBufferRange& range) const;

  // Returns true if |timestamp| is the timestamp of the next buffer in
  // sequence after |buffer|, false otherwise.
  bool IsNextInSequence(
      const scoped_refptr<media::StreamParserBuffer>& buffer,
      base::TimeDelta timestamp) const;

  int size_in_bytes() const { return size_in_bytes_; }

 private:
  typedef std::map<base::TimeDelta, int> KeyframeMap;

  // Seeks the range to the next keyframe after |timestamp|. If
  // |skip_given_timestamp| is true, the seek will go to a keyframe with a
  // timestamp strictly greater than |timestamp|.
  void SeekAhead(base::TimeDelta timestamp, bool skip_given_timestamp);

  // Returns an iterator in |buffers_| pointing to the buffer at |timestamp|.
  // If |skip_given_timestamp| is true, this returns the first buffer with
  // timestamp greater than |timestamp|.
  BufferQueue::iterator GetBufferItrAt(
      base::TimeDelta timestamp, bool skip_given_timestamp);

  // Returns an iterator in |keyframe_map_| pointing to the next keyframe after
  // |timestamp|. If |skip_given_timestamp| is true, this returns the first
  // keyframe with a timestamp strictly greater than |timestamp|.
  KeyframeMap::iterator GetFirstKeyframeAt(
      base::TimeDelta timestamp, bool skip_given_timestamp);

  // Returns an iterator in |keyframe_map_| pointing to the first keyframe
  // before or at |timestamp|.
  KeyframeMap::iterator GetFirstKeyframeBefore(base::TimeDelta timestamp);

  // Helper method to delete buffers in |buffers_| starting at
  // |starting_point|, an iterator in |buffers_|.
  bool TruncateAt(const BufferQueue::iterator& starting_point,
                  BufferQueue* deleted_buffers);

  // Frees the buffers in |buffers_| from [|start_point|,|ending_point|) and
  // updates the |size_in_bytes_| accordingly. Does not update |keyframe_map_|.
  void FreeBufferRange(const BufferQueue::iterator& starting_point,
                       const BufferQueue::iterator& ending_point);

  // Returns the distance in time estimating how far from the beginning or end
  // of this range a buffer can be to considered in the range.
  base::TimeDelta GetFudgeRoom() const;

  // Returns the approximate duration of a buffer in this range.
  base::TimeDelta GetApproximateDuration() const;

  // An ordered list of buffers in this range.
  BufferQueue buffers_;

  // Maps keyframe timestamps to its index position in |buffers_|.
  KeyframeMap keyframe_map_;

  // Index base of all positions in |keyframe_map_|. In other words, the
  // real position of entry |k| of |keyframe_map_| in the range is:
  //   keyframe_map_[k] - keyframe_map_index_base_
  int keyframe_map_index_base_;

  // Index into |buffers_| for the next buffer to be returned by
  // GetNextBuffer(), 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_;

  // If the first buffer in this range is the beginning of a media segment,
  // |media_segment_start_time_| is the time when the media segment begins.
  // |media_segment_start_time_| may be <= the timestamp of the first buffer in
  // |buffers_|. |media_segment_start_time_| is kNoTimestamp() if this range
  // does not start at the beginning of a media segment, which can only happen
  // garbage collection or after an end overlap that results in a split range
  // (we don't have a way of knowing the media segment timestamp for the new
  // range).
  base::TimeDelta media_segment_start_time_;

  // Called to get the largest interbuffer distance seen so far in the stream.
  InterbufferDistanceCB interbuffer_distance_cb_;

  // Stores the amount of memory taken up by the data in |buffers_|.
  int size_in_bytes_;

  DISALLOW_COPY_AND_ASSIGN(SourceBufferRange);
};

}  // namespace media

// Helper method that returns true if |ranges| is sorted in increasing order,
// false otherwise.
static bool IsRangeListSorted(
    const std::list<media::SourceBufferRange*>& ranges) {
  base::TimeDelta prev = media::kNoTimestamp();
  for (std::list<media::SourceBufferRange*>::const_iterator itr =
       ranges.begin(); itr != ranges.end(); ++itr) {
    if (prev != media::kNoTimestamp() && prev >= (*itr)->GetStartTimestamp())
      return false;
    prev = (*itr)->GetEndTimestamp();
  }
  return true;
}

// Comparison function for two Buffers based on timestamp.
static bool BufferComparator(
    const scoped_refptr<media::StreamParserBuffer>& first,
    const scoped_refptr<media::StreamParserBuffer>& second) {
  return first->GetDecodeTimestamp() < second->GetDecodeTimestamp();
}

// Returns an estimate of how far from the beginning or end of a range a buffer
// can be to still be considered in the range, given the |approximate_duration|
// of a buffer in the stream.
static base::TimeDelta ComputeFudgeRoom(base::TimeDelta approximate_duration) {
  // Because we do not know exactly when is the next timestamp, any buffer
  // that starts within 2x the approximate duration of a buffer is considered
  // within this range.
  return 2 * approximate_duration;
}

// An arbitrarily-chosen number to estimate the duration of a buffer if none
// is set and there's not enough information to get a better estimate.
static int kDefaultBufferDurationInMs = 125;

// The amount of time the beginning of the buffered data can differ from the
// start time in order to still be considered the start of stream.
static base::TimeDelta kSeekToStartFudgeRoom() {
  return base::TimeDelta::FromMilliseconds(1000);
}

// The maximum amount of data in bytes the stream will keep in memory.
// 12MB: approximately 5 minutes of 320Kbps content.
// 150MB: approximately 5 minutes of 4Mbps content.
#if !defined(__LB_SHELL__) || defined(COBALT)
static const int kDefaultAudioMemoryLimit = 12 * 1024 * 1024;
static const int kDefaultVideoMemoryLimit = 150 * 1024 * 1024;
#endif

namespace media {

#if defined(__LB_SHELL__) || defined(COBALT)
SourceBufferStream::SourceBufferStream(
    const AudioDecoderConfig& audio_config,
    const LogCB& log_cb)
    : log_cb_(log_cb),
      current_config_index_(0),
      append_config_index_(0),
      seek_pending_(false),
      seek_buffer_timestamp_(kNoTimestamp()),
      selected_range_(NULL),
      media_segment_start_time_(kNoTimestamp()),
      range_for_next_append_(ranges_.end()),
      new_media_segment_(false),
      last_buffer_timestamp_(kNoTimestamp()),
      max_interbuffer_distance_(kNoTimestamp()),
#if defined(__LB_SHELL__) || defined(COBALT)
      memory_limit_(ShellMediaPlatform::Instance()->
                        GetSourceBufferStreamAudioMemoryLimit()),
#else  // defined(__LB_SHELL__) || defined(COBALT)
      memory_limit_(kDefaultAudioMemoryLimit),
#endif  // defined(__LB_SHELL__) || defined(COBALT)
      config_change_pending_(false) {
  DCHECK(audio_config.IsValidConfig());
  audio_configs_.push_back(new AudioDecoderConfig());
  audio_configs_.back()->CopyFrom(audio_config);
}

SourceBufferStream::SourceBufferStream(
    const VideoDecoderConfig& video_config,
    const LogCB& log_cb)
    : log_cb_(log_cb),
      current_config_index_(0),
      append_config_index_(0),
      seek_pending_(false),
      seek_buffer_timestamp_(kNoTimestamp()),
      selected_range_(NULL),
      media_segment_start_time_(kNoTimestamp()),
      range_for_next_append_(ranges_.end()),
      new_media_segment_(false),
      last_buffer_timestamp_(kNoTimestamp()),
      max_interbuffer_distance_(kNoTimestamp()),
#if defined(__LB_SHELL__) || defined(COBALT)
      memory_limit_(ShellMediaPlatform::Instance()->
                        GetSourceBufferStreamVideoMemoryLimit()),
#else  // defined(__LB_SHELL__) || defined(COBALT)
      memory_limit_(kDefaultVideoMemoryLimit),
#endif  // defined(__LB_SHELL__) || defined(COBALT)
      config_change_pending_(false) {
  DCHECK(video_config.IsValidConfig());
  video_configs_.push_back(new VideoDecoderConfig());
  video_configs_.back()->CopyFrom(video_config);
}
#else
SourceBufferStream::SourceBufferStream(const AudioDecoderConfig& audio_config,
                                       const LogCB& log_cb)
    : log_cb_(log_cb),
      current_config_index_(0),
      append_config_index_(0),
      seek_pending_(false),
      seek_buffer_timestamp_(kNoTimestamp()),
      selected_range_(NULL),
      media_segment_start_time_(kNoTimestamp()),
      range_for_next_append_(ranges_.end()),
      new_media_segment_(false),
      last_buffer_timestamp_(kNoTimestamp()),
      max_interbuffer_distance_(kNoTimestamp()),
      memory_limit_(kDefaultAudioMemoryLimit),
      config_change_pending_(false) {
  DCHECK(audio_config.IsValidConfig());
  audio_configs_.push_back(new AudioDecoderConfig());
  audio_configs_.back()->CopyFrom(audio_config);
}

SourceBufferStream::SourceBufferStream(const VideoDecoderConfig& video_config,
                                       const LogCB& log_cb)
    : log_cb_(log_cb),
      current_config_index_(0),
      append_config_index_(0),
      seek_pending_(false),
      seek_buffer_timestamp_(kNoTimestamp()),
      selected_range_(NULL),
      media_segment_start_time_(kNoTimestamp()),
      range_for_next_append_(ranges_.end()),
      new_media_segment_(false),
      last_buffer_timestamp_(kNoTimestamp()),
      max_interbuffer_distance_(kNoTimestamp()),
      memory_limit_(kDefaultVideoMemoryLimit),
      config_change_pending_(false) {
  DCHECK(video_config.IsValidConfig());
  video_configs_.push_back(new VideoDecoderConfig());
  video_configs_.back()->CopyFrom(video_config);
}
#endif

SourceBufferStream::~SourceBufferStream() {
  while (!ranges_.empty()) {
    delete ranges_.front();
    ranges_.pop_front();
  }

  STLDeleteElements(&audio_configs_);
  STLDeleteElements(&video_configs_);
}

void SourceBufferStream::OnNewMediaSegment(
    base::TimeDelta media_segment_start_time) {
  media_segment_start_time_ = media_segment_start_time;
  new_media_segment_ = true;

  RangeList::iterator last_range = range_for_next_append_;
  range_for_next_append_ = FindExistingRangeFor(media_segment_start_time);

  // Only reset |last_buffer_timestamp_| if this new media segment is not
  // adjacent to the previous media segment appended to the stream.
  if (range_for_next_append_ == ranges_.end() ||
      !AreAdjacentInSequence(
          last_buffer_timestamp_, media_segment_start_time)) {
    last_buffer_timestamp_ = kNoTimestamp();
  } else {
    DCHECK(last_range == range_for_next_append_);
  }
}

bool SourceBufferStream::Append(
    const SourceBufferStream::BufferQueue& buffers) {
  DCHECK(!buffers.empty());
  DCHECK(media_segment_start_time_ != kNoTimestamp());

  // New media segments must begin with a keyframe.
  if (new_media_segment_ && !buffers.front()->IsKeyframe()) {
    MEDIA_LOG(log_cb_) << "Media segment did not begin with keyframe.";
    return false;
  }

  // Buffers within a media segment should be monotonically increasing.
  if (!IsMonotonicallyIncreasing(buffers)) {
    MEDIA_LOG(log_cb_) << "Buffers were not monotonically increasing.";
    return false;
  }

  if (media_segment_start_time_ < base::TimeDelta() ||
      buffers.front()->GetDecodeTimestamp() < base::TimeDelta()) {
    MEDIA_LOG(log_cb_)
        << "Cannot append a media segment with negative timestamps.";
    return false;
  }

  UpdateMaxInterbufferDistance(buffers);
  SetConfigIds(buffers);

  // Save a snapshot of stream state before range modifications are made.
  base::TimeDelta next_buffer_timestamp = GetNextBufferTimestamp();
  base::TimeDelta end_buffer_timestamp = GetEndBufferTimestamp();

  bool deleted_next_buffer = false;
  BufferQueue deleted_buffers;

  RangeList::iterator range_for_new_buffers = range_for_next_append_;
  // If there's a range for |buffers|, insert |buffers| accordingly. Otherwise,
  // create a new range with |buffers|.
  if (range_for_new_buffers != ranges_.end()) {
    InsertIntoExistingRange(range_for_new_buffers, buffers,
                            &deleted_next_buffer, &deleted_buffers);
  } else {
    DCHECK(new_media_segment_);
#if defined(__LB_SHELL__) || defined(COBALT)
    range_for_new_buffers =
        AddToRanges(new SourceBufferRange(
            buffers, media_segment_start_time_,
            base::Bind(&SourceBufferStream::GetMaxInterbufferDistance,
                       base::Unretained(this))));
#else
    range_for_new_buffers =
        AddToRanges(new SourceBufferRange(
            buffers, media_segment_start_time_,
            base::Bind(&SourceBufferStream::GetMaxInterbufferDistance,
                       base::Unretained(this))));
#endif
  }

  range_for_next_append_ = range_for_new_buffers;
  new_media_segment_ = false;
  last_buffer_timestamp_ = buffers.back()->GetDecodeTimestamp();

  // Resolve overlaps.
  ResolveCompleteOverlaps(
      range_for_new_buffers, &deleted_next_buffer, &deleted_buffers);
  ResolveEndOverlap(
      range_for_new_buffers, &deleted_next_buffer, &deleted_buffers);
  MergeWithAdjacentRangeIfNecessary(range_for_new_buffers);

  // Seek to try to fulfill a previous call to Seek().
  if (seek_pending_) {
    DCHECK(!selected_range_);
    DCHECK(!deleted_next_buffer);
    Seek(seek_buffer_timestamp_);
  }

  // Seek because the Append() has deleted the buffer that would have been
  // returned in the next call to GetNextBuffer().
  if (deleted_next_buffer) {
    DCHECK(!seek_pending_);
    SetSelectedRange(*range_for_new_buffers);
    if (next_buffer_timestamp != kNoTimestamp()) {
      // Seek ahead to the keyframe at or after |next_buffer_timestamp|, the
      // timestamp of the deleted next buffer.
      selected_range_->SeekAheadTo(next_buffer_timestamp);
      // Update track buffer with non-keyframe buffers leading up to the current
      // position of |selected_range_|.
      PruneTrackBuffer();
      if (!deleted_buffers.empty())
        UpdateTrackBuffer(deleted_buffers);
    } else {
      // If |next_buffer_timestamp| is kNoTimestamp(), it means the range
      // we've overlapped didn't actually have the next buffer buffered, and it
      // was waiting for the next buffer whose timestamp was greater than
      // |end_buffer_timestamp|. Seek the |selected_range_| to the next keyframe
      // after |end_buffer_timestamp|.
      DCHECK(track_buffer_.empty());
      DCHECK(deleted_buffers.empty());
      selected_range_->SeekAheadPast(end_buffer_timestamp);
    }
  }

  GarbageCollectIfNeeded();

  DCHECK(IsRangeListSorted(ranges_));
  DCHECK(OnlySelectedRangeIsSeeked());
  return true;
}

void SourceBufferStream::ResetSeekState() {
  SetSelectedRange(NULL);
  track_buffer_.clear();
  config_change_pending_ = false;
}

bool SourceBufferStream::ShouldSeekToStartOfBuffered(
    base::TimeDelta seek_timestamp) const {
  if (ranges_.empty())
    return false;
  base::TimeDelta beginning_of_buffered =
      ranges_.front()->GetStartTimestamp();
  return (seek_timestamp <= beginning_of_buffered &&
          beginning_of_buffered < kSeekToStartFudgeRoom());
}

bool SourceBufferStream::IsMonotonicallyIncreasing(
    const BufferQueue& buffers) const {
  DCHECK(!buffers.empty());
  base::TimeDelta prev_timestamp = last_buffer_timestamp_;
  for (BufferQueue::const_iterator itr = buffers.begin();
       itr != buffers.end(); ++itr) {
    base::TimeDelta current_timestamp = (*itr)->GetDecodeTimestamp();
    DCHECK(current_timestamp != kNoTimestamp());

    if (prev_timestamp != kNoTimestamp() && current_timestamp < prev_timestamp)
      return false;

    prev_timestamp = current_timestamp;
  }
  return true;
}

bool SourceBufferStream::OnlySelectedRangeIsSeeked() const {
  for (RangeList::const_iterator itr = ranges_.begin();
       itr != ranges_.end(); ++itr) {
    if ((*itr)->HasNextBufferPosition() && (*itr) != selected_range_)
      return false;
  }
  return !selected_range_ || selected_range_->HasNextBufferPosition();
}

void SourceBufferStream::UpdateMaxInterbufferDistance(
    const BufferQueue& buffers) {
  DCHECK(!buffers.empty());
  base::TimeDelta prev_timestamp = last_buffer_timestamp_;
  for (BufferQueue::const_iterator itr = buffers.begin();
       itr != buffers.end(); ++itr) {
    base::TimeDelta current_timestamp = (*itr)->GetDecodeTimestamp();
    DCHECK(current_timestamp != kNoTimestamp());

    base::TimeDelta interbuffer_distance;
    // WebMStreamParser in M25 doesn't guarantee that a duration is always set.
    if ((*itr)->GetDuration() != kNoTimestamp())
      interbuffer_distance = (*itr)->GetDuration();

    if (prev_timestamp != kNoTimestamp()) {
      interbuffer_distance =
          std::max(current_timestamp - prev_timestamp, interbuffer_distance);
    }

    if (interbuffer_distance > base::TimeDelta()) {
      if (max_interbuffer_distance_ == kNoTimestamp()) {
        max_interbuffer_distance_ = interbuffer_distance;
      } else {
        max_interbuffer_distance_ =
            std::max(max_interbuffer_distance_, interbuffer_distance);
      }
    }
    prev_timestamp = current_timestamp;
  }
}

void SourceBufferStream::SetConfigIds(const BufferQueue& buffers) {
  for (BufferQueue::const_iterator itr = buffers.begin();
       itr != buffers.end(); ++itr) {
    (*itr)->SetConfigId(append_config_index_);
  }
}

void SourceBufferStream::GarbageCollectIfNeeded() {
  // Compute size of |ranges_|.
  int ranges_size = 0;
  for (RangeList::iterator itr = ranges_.begin(); itr != ranges_.end(); ++itr)
    ranges_size += (*itr)->size_in_bytes();

  // Return if we're under or at the memory limit.
  if (ranges_size <= memory_limit_)
    return;

  LogMediaSourceTimeRanges("before garbage collect", GetBufferedTime());

  int bytes_to_free = ranges_size - memory_limit_;

  // Begin deleting from the front.
  int bytes_freed = FreeBuffers(bytes_to_free, false);

  LogMediaSourceTimeRanges("after garbage collect from front",
                           GetBufferedTime());

  // Begin deleting from the back.
  if (bytes_to_free - bytes_freed > 0) {
    FreeBuffers(bytes_to_free - bytes_freed, true);
    LogMediaSourceTimeRanges("after garbage collect from back",
                             GetBufferedTime());
  }
}

int SourceBufferStream::FreeBuffers(int total_bytes_to_free,
                                    bool reverse_direction) {
  DCHECK_GT(total_bytes_to_free, 0);
  int bytes_to_free = total_bytes_to_free;
  int bytes_freed = 0;

  // This range will save the last GOP appended to |range_for_next_append_|
  // if the buffers surrounding it get deleted during garbage collection.
  SourceBufferRange* new_range_for_append = NULL;

  while (!ranges_.empty() && bytes_to_free > 0) {
    SourceBufferRange* current_range = NULL;
    BufferQueue buffers;
    int bytes_deleted = 0;

    if (reverse_direction) {
      current_range = ranges_.back();
      if (current_range->LastGOPContainsNextBufferPosition()) {
        DCHECK_EQ(current_range, selected_range_);
        break;
      }
      bytes_deleted = current_range->DeleteGOPFromBack(&buffers);
    } else {
      current_range = ranges_.front();
      if (current_range->FirstGOPContainsNextBufferPosition()) {
        DCHECK_EQ(current_range, selected_range_);
        break;
      }
      bytes_deleted = current_range->DeleteGOPFromFront(&buffers);
    }

    // Check to see if we've just deleted the GOP that was last appended.
    if (buffers.back()->GetDecodeTimestamp() == last_buffer_timestamp_) {
      DCHECK(last_buffer_timestamp_ != kNoTimestamp());
      DCHECK(!new_range_for_append);
      // Create a new range containing these buffers.
#if defined(__LB_SHELL__) || defined(COBALT)
      new_range_for_append = new SourceBufferRange(
            buffers, kNoTimestamp(),
            base::Bind(&SourceBufferStream::GetMaxInterbufferDistance,
                       base::Unretained(this)));
#else
      new_range_for_append = new SourceBufferRange(
            buffers, kNoTimestamp(),
            base::Bind(&SourceBufferStream::GetMaxInterbufferDistance,
                       base::Unretained(this)));
#endif
      range_for_next_append_ = ranges_.end();
    } else {
      bytes_to_free -= bytes_deleted;
      bytes_freed += bytes_deleted;
    }

    if (current_range->size_in_bytes() == 0) {
      DCHECK_NE(current_range, selected_range_);
      DCHECK(range_for_next_append_ == ranges_.end() ||
             *range_for_next_append_ != current_range);
      delete current_range;
      reverse_direction ? ranges_.pop_back() : ranges_.pop_front();
    }
  }

  // Insert |new_range_for_append| into |ranges_|, if applicable.
  if (new_range_for_append) {
    range_for_next_append_ = AddToRanges(new_range_for_append);
    DCHECK(range_for_next_append_ != ranges_.end());

    // Check to see if we need to merge |new_range_for_append| with the range
    // before or after it. |new_range_for_append| is created whenever the last
    // GOP appended is encountered, regardless of whether any buffers after it
    // are ultimately deleted. Merging is necessary if there were no buffers
    // (or very few buffers) deleted after creating |new_range_for_append|.
    if (range_for_next_append_ != ranges_.begin()) {
      RangeList::iterator range_before_next = range_for_next_append_;
      --range_before_next;
      MergeWithAdjacentRangeIfNecessary(range_before_next);
    }
    MergeWithAdjacentRangeIfNecessary(range_for_next_append_);
  }
  return bytes_freed;
}

void SourceBufferStream::InsertIntoExistingRange(
    const RangeList::iterator& range_for_new_buffers_itr,
    const BufferQueue& new_buffers,
    bool* deleted_next_buffer, BufferQueue* deleted_buffers) {
  DCHECK(deleted_next_buffer);
  DCHECK(deleted_buffers);

  SourceBufferRange* range_for_new_buffers = *range_for_new_buffers_itr;

  if (last_buffer_timestamp_ != kNoTimestamp()) {
    // Clean up the old buffers between the last appended buffer and the
    // beginning of |new_buffers|.
    *deleted_next_buffer =
        DeleteBetween(
            range_for_new_buffers, last_buffer_timestamp_,
            new_buffers.front()->GetDecodeTimestamp(), true,
            deleted_buffers);
  }

  // If we cannot append the |new_buffers| to the end of the existing range,
  // this is either a start overlap or an middle overlap. Delete the buffers
  // that |new_buffers| overlaps.
  if (!range_for_new_buffers->CanAppendBuffersToEnd(new_buffers)) {
    *deleted_next_buffer |=
        DeleteBetween(
            range_for_new_buffers, new_buffers.front()->GetDecodeTimestamp(),
            new_buffers.back()->GetDecodeTimestamp(), false,
            deleted_buffers);
  }

  range_for_new_buffers->AppendBuffersToEnd(new_buffers);
}

bool SourceBufferStream::DeleteBetween(
    SourceBufferRange* range, base::TimeDelta start_timestamp,
    base::TimeDelta end_timestamp, bool is_range_exclusive,
    BufferQueue* deleted_buffers) {
  SourceBufferRange* new_next_range =
      range->SplitRange(end_timestamp, is_range_exclusive);

  if (new_next_range)
    AddToRanges(new_next_range);

  BufferQueue saved_buffers;
  bool deleted_next_buffer =
      range->TruncateAt(start_timestamp, &saved_buffers, is_range_exclusive);

  if (selected_range_ != range)
    return deleted_next_buffer;

  DCHECK(deleted_buffers->empty());
  *deleted_buffers = saved_buffers;

  // If the next buffer position has transferred to the split range, set the
  // selected range accordingly.
  if (new_next_range && new_next_range->HasNextBufferPosition()) {
    DCHECK(!range->HasNextBufferPosition());
    DCHECK(!deleted_next_buffer);
    SetSelectedRange(new_next_range);
  }
  return deleted_next_buffer;
}

bool SourceBufferStream::AreAdjacentInSequence(
    base::TimeDelta first_timestamp, base::TimeDelta second_timestamp) const {
  return first_timestamp < second_timestamp &&
      second_timestamp <=
      first_timestamp + ComputeFudgeRoom(GetMaxInterbufferDistance());
}

void SourceBufferStream::ResolveCompleteOverlaps(
    const RangeList::iterator& range_with_new_buffers_itr,
    bool* deleted_next_buffer, BufferQueue* deleted_buffers) {
  DCHECK(deleted_next_buffer);
  DCHECK(deleted_buffers);

  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_) {
      DCHECK(!*deleted_next_buffer);
      *deleted_next_buffer = selected_range_->DeleteAll(deleted_buffers);
      DCHECK(*deleted_next_buffer);
      SetSelectedRange(NULL);
    }
    delete *next_range_itr;
    next_range_itr = ranges_.erase(next_range_itr);
  }
}

void SourceBufferStream::ResolveEndOverlap(
    const RangeList::iterator& range_with_new_buffers_itr,
    bool* deleted_next_buffer, BufferQueue* deleted_buffers) {
  DCHECK(deleted_next_buffer);
  DCHECK(deleted_buffers);

  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(), true);

  // If there were non-overlapped buffers, add the new range to |ranges_|.
  if (new_next_range)
    AddToRanges(new_next_range);

  // If we didn't overlap a selected range, return.
  if (selected_range_ != overlapped_range.get())
    return;

  // If the |overlapped_range| transfers its next buffer position to
  // |new_next_range|, make |new_next_range| the |selected_range_|.
  if (new_next_range && new_next_range->HasNextBufferPosition()) {
    DCHECK(!overlapped_range->HasNextBufferPosition());
    SetSelectedRange(new_next_range);
    return;
  }

  // Save the buffers in |overlapped_range|.
  DCHECK(!*deleted_next_buffer);
  DCHECK_EQ(overlapped_range.get(), selected_range_);
  *deleted_next_buffer = overlapped_range->DeleteAll(deleted_buffers);
  DCHECK(*deleted_next_buffer);

  // |overlapped_range| will be deleted, so set |selected_range_| to NULL.
  SetSelectedRange(NULL);
}

void SourceBufferStream::PruneTrackBuffer() {
  DCHECK(selected_range_);
  DCHECK(selected_range_->HasNextBufferPosition());
  base::TimeDelta next_timestamp = selected_range_->GetNextTimestamp();

  // If we don't have the next timestamp, we don't have anything to delete.
  if (next_timestamp == kNoTimestamp())
    return;

  while (!track_buffer_.empty() &&
         track_buffer_.back()->GetDecodeTimestamp() >= next_timestamp) {
    track_buffer_.pop_back();
  }
}

void SourceBufferStream::UpdateTrackBuffer(const BufferQueue& deleted_buffers) {
  DCHECK(!deleted_buffers.empty());
  DCHECK(selected_range_);
  DCHECK(selected_range_->HasNextBufferPosition());

  base::TimeDelta next_keyframe_timestamp = selected_range_->GetNextTimestamp();
  base::TimeDelta start_of_deleted =
      deleted_buffers.front()->GetDecodeTimestamp();

  // |deleted_buffers| should always come after the buffers in |track_buffer|.
  if (!track_buffer_.empty())
    DCHECK(track_buffer_.back()->GetDecodeTimestamp() < start_of_deleted);

  // If there is no gap between what was deleted and what was added, nothing
  // should be added to the track buffer.
  if (selected_range_->HasNextBuffer() &&
      next_keyframe_timestamp <= start_of_deleted) {
    return;
  }

  // If the |selected_range_| is ready to return data, fill the track buffer
  // with all buffers that come before |next_keyframe_timestamp| and return.
  if (selected_range_->HasNextBuffer()) {
    for (BufferQueue::const_iterator itr = deleted_buffers.begin();
         itr != deleted_buffers.end() &&
         (*itr)->GetDecodeTimestamp() < next_keyframe_timestamp; ++itr) {
      track_buffer_.push_back(*itr);
    }
    return;
  }

  // Otherwise, the |selected_range_| is not ready to return data, so add all
  // the deleted buffers into the |track_buffer_|.
  track_buffer_.insert(track_buffer_.end(),
                       deleted_buffers.begin(), deleted_buffers.end());

  // See if the next range contains the keyframe after the end of the
  // |track_buffer_|, and if so, change |selected_range_|.
  RangeList::iterator next_range_itr = ++(GetSelectedRangeItr());
  if (next_range_itr == ranges_.end())
    return;

  (*next_range_itr)->SeekAheadPast(
      track_buffer_.back()->GetDecodeTimestamp());

  if (!(*next_range_itr)->HasNextBuffer())
    return;

  if (!selected_range_->IsNextInSequence(
          track_buffer_.back(), (*next_range_itr)->GetNextTimestamp())) {
    (*next_range_itr)->ResetNextBufferPosition();
    return;
  }
  SetSelectedRange(*next_range_itr);
}

void SourceBufferStream::MergeWithAdjacentRangeIfNecessary(
    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->CanAppendRangeToEnd(**next_range_itr)) {
    bool transfer_current_position = selected_range_ == *next_range_itr;
    range_with_new_buffers->AppendRangeToEnd(**next_range_itr,
                                             transfer_current_position);
    // Update |selected_range_| pointer if |range| has become selected after
    // merges.
    if (transfer_current_position)
      SetSelectedRange(range_with_new_buffers);

    if (next_range_itr == range_for_next_append_)
      range_for_next_append_ = range_with_new_buffers_itr;

    delete *next_range_itr;
    ranges_.erase(next_range_itr);
  }
}

void SourceBufferStream::Seek(base::TimeDelta timestamp) {
  DCHECK(timestamp >= base::TimeDelta());
  ResetSeekState();

  if (ShouldSeekToStartOfBuffered(timestamp)) {
    SetSelectedRange(ranges_.front());
    ranges_.front()->SeekToStart();
    seek_pending_ = false;
    seek_buffer_timestamp_ = GetNextBufferTimestamp();
    return;
  }

  seek_buffer_timestamp_ = timestamp;
  seek_pending_ = true;

  RangeList::iterator itr = ranges_.end();
  for (itr = ranges_.begin(); itr != ranges_.end(); ++itr) {
    if ((*itr)->CanSeekTo(timestamp))
      break;
  }

  if (itr == ranges_.end())
    return;

  SetSelectedRange(*itr);
  selected_range_->Seek(timestamp);
  seek_pending_ = false;
  seek_buffer_timestamp_ = GetNextBufferTimestamp();
}

bool SourceBufferStream::IsSeekPending() const {
  return seek_pending_;
}

base::TimeDelta SourceBufferStream::GetSeekKeyframeTimestamp() const {
  DCHECK(!IsSeekPending());
  return seek_buffer_timestamp_;
}

void SourceBufferStream::OnSetDuration(base::TimeDelta duration) {
  RangeList::iterator itr = ranges_.end();
  for (itr = ranges_.begin(); itr != ranges_.end(); ++itr) {
    if ((*itr)->GetEndTimestamp() > duration)
      break;
  }
  if (itr == ranges_.end())
    return;

  // Need to partially truncate this range.
  if ((*itr)->GetStartTimestamp() < duration) {
    bool deleted_seek_point = (*itr)->TruncateAt(duration, NULL, false);
    if (deleted_seek_point)
      ResetSeekState();
    ++itr;
  }

  // Delete all ranges that begin after |duration|.
  while (itr != ranges_.end()) {
    // If we're about to delete the selected range, also reset the seek state.
    DCHECK((*itr)->GetStartTimestamp() >= duration);
    if (*itr== selected_range_)
      ResetSeekState();
    delete *itr;
    itr = ranges_.erase(itr);
  }
}

SourceBufferStream::Status SourceBufferStream::GetNextBuffer(
    scoped_refptr<StreamParserBuffer>* out_buffer) {
  CHECK(!config_change_pending_);

  if (!track_buffer_.empty()) {
    DCHECK(selected_range_);
    if (track_buffer_.front()->GetConfigId() != current_config_index_) {
      config_change_pending_ = true;
      DVLOG(1) << "Config change (track buffer config ID does not match).";
      return kConfigChange;
    }

    *out_buffer = track_buffer_.front();
    track_buffer_.pop_front();
    return kSuccess;
  }

  if (!selected_range_ || !selected_range_->HasNextBuffer())
    return kNeedBuffer;

  if (selected_range_->GetNextConfigId() != current_config_index_) {
    config_change_pending_ = true;
    DVLOG(1) << "Config change (selected range config ID does not match).";
    return kConfigChange;
  }

  CHECK(selected_range_->GetNextBuffer(out_buffer));
  return kSuccess;
}

base::TimeDelta SourceBufferStream::GetNextBufferTimestamp() {
  if (!selected_range_) {
    DCHECK(track_buffer_.empty());
    return kNoTimestamp();
  }

  DCHECK(selected_range_->HasNextBufferPosition());
  if (!track_buffer_.empty())
    return track_buffer_.front()->GetDecodeTimestamp();
  return selected_range_->GetNextTimestamp();
}

base::TimeDelta SourceBufferStream::GetEndBufferTimestamp() {
  if (!selected_range_)
    return kNoTimestamp();
  return selected_range_->GetEndTimestamp();
}

SourceBufferStream::RangeList::iterator
SourceBufferStream::FindExistingRangeFor(base::TimeDelta start_timestamp) {
  for (RangeList::iterator itr = ranges_.begin(); itr != ranges_.end(); ++itr) {
    if ((*itr)->BelongsToRange(start_timestamp))
      return itr;
  }
  return ranges_.end();
}

SourceBufferStream::RangeList::iterator
SourceBufferStream::AddToRanges(SourceBufferRange* new_range) {
  base::TimeDelta start_timestamp = new_range->GetStartTimestamp();
  RangeList::iterator itr = ranges_.end();
  for (itr = ranges_.begin(); itr != ranges_.end(); ++itr) {
    if ((*itr)->GetStartTimestamp() > start_timestamp)
      break;
  }
  return ranges_.insert(itr, new_range);
}

SourceBufferStream::RangeList::iterator
SourceBufferStream::GetSelectedRangeItr() {
  DCHECK(selected_range_);
  RangeList::iterator itr = ranges_.end();
  for (itr = ranges_.begin(); itr != ranges_.end(); ++itr) {
    if (*itr == selected_range_)
      break;
  }
  DCHECK(itr != ranges_.end());
  return itr;
}

void SourceBufferStream::SetSelectedRange(SourceBufferRange* range) {
  if (selected_range_)
    selected_range_->ResetNextBufferPosition();
  selected_range_ = range;
}

Ranges<base::TimeDelta> SourceBufferStream::GetBufferedTime() const {
  Ranges<base::TimeDelta> ranges;
  for (RangeList::const_iterator itr = ranges_.begin();
       itr != ranges_.end(); ++itr) {
    ranges.Add((*itr)->GetStartTimestamp(), (*itr)->GetBufferedEndTimestamp());
  }
  return ranges;
}

bool SourceBufferStream::IsEndSelected() const {
  return ranges_.empty() || selected_range_ == ranges_.back();
}

const AudioDecoderConfig& SourceBufferStream::GetCurrentAudioDecoderConfig() {
  if (config_change_pending_)
    CompleteConfigChange();
  return *audio_configs_[current_config_index_];
}

const VideoDecoderConfig& SourceBufferStream::GetCurrentVideoDecoderConfig() {
  if (config_change_pending_)
    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());
  DVLOG(3) << "UpdateAudioConfig.";

  if (audio_configs_[0]->codec() != config.codec()) {
    MEDIA_LOG(log_cb_) << "Audio codec changes not allowed.";
    return false;
  }

  if (audio_configs_[0]->samples_per_second() != config.samples_per_second()) {
    MEDIA_LOG(log_cb_) << "Audio sample rate changes not allowed.";
    return false;
  }

  if (audio_configs_[0]->channel_layout() != config.channel_layout()) {
    MEDIA_LOG(log_cb_) << "Audio channel layout changes not allowed.";
    return false;
  }

  if (audio_configs_[0]->bits_per_channel() != config.bits_per_channel()) {
    MEDIA_LOG(log_cb_) << "Audio bits per channel changes not allowed.";
    return false;
  }

  if (audio_configs_[0]->is_encrypted() != config.is_encrypted()) {
    MEDIA_LOG(log_cb_) << "Audio encryption 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();
  DVLOG(2) << "New audio config - index: " << append_config_index_;
  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());
  DVLOG(3) << "UpdateVideoConfig.";

  if (video_configs_[0]->is_encrypted() != config.is_encrypted()) {
    MEDIA_LOG(log_cb_) << "Video Encryption changes not allowed.";
    return false;
  }

  if (video_configs_[0]->codec() != config.codec()) {
    MEDIA_LOG(log_cb_) << "Video codec changes not allowed.";
    return false;
  }

  if (video_configs_[0]->is_encrypted() != config.is_encrypted()) {
    MEDIA_LOG(log_cb_) << "Video encryption 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();
  DVLOG(2) << "New video config - index: " << append_config_index_;
  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() {
  config_change_pending_ = false;

  if (!track_buffer_.empty()) {
    current_config_index_ = track_buffer_.front()->GetConfigId();
    return;
  }

  if (selected_range_ && selected_range_->HasNextBuffer())
    current_config_index_ = selected_range_->GetNextConfigId();
}

#if defined(__LB_SHELL__) || defined(COBALT)
SourceBufferRange::SourceBufferRange(
    const BufferQueue& new_buffers, base::TimeDelta media_segment_start_time,
    const InterbufferDistanceCB& interbuffer_distance_cb)
    : keyframe_map_index_base_(0),
      next_buffer_index_(-1),
      waiting_for_keyframe_(false),
      next_keyframe_timestamp_(kNoTimestamp()),
      media_segment_start_time_(media_segment_start_time),
      interbuffer_distance_cb_(interbuffer_distance_cb),
      size_in_bytes_(0) {
  DCHECK(!new_buffers.empty());
  DCHECK(new_buffers.front()->IsKeyframe());
  DCHECK(!interbuffer_distance_cb.is_null());
  AppendBuffersToEnd(new_buffers);
}
#else
SourceBufferRange::SourceBufferRange(
    const BufferQueue& new_buffers, base::TimeDelta media_segment_start_time,
    const InterbufferDistanceCB& interbuffer_distance_cb)
    : keyframe_map_index_base_(0),
      next_buffer_index_(-1),
      waiting_for_keyframe_(false),
      next_keyframe_timestamp_(kNoTimestamp()),
      media_segment_start_time_(media_segment_start_time),
      interbuffer_distance_cb_(interbuffer_distance_cb),
      size_in_bytes_(0) {
  DCHECK(!new_buffers.empty());
  DCHECK(new_buffers.front()->IsKeyframe());
  DCHECK(!interbuffer_distance_cb.is_null());
  AppendBuffersToEnd(new_buffers);
}
#endif

void SourceBufferRange::AppendBuffersToEnd(const BufferQueue& new_buffers) {
  for (BufferQueue::const_iterator itr = new_buffers.begin();
       itr != new_buffers.end(); ++itr) {
    DCHECK((*itr)->GetDecodeTimestamp() != kNoTimestamp());
    buffers_.push_back(*itr);
    size_in_bytes_ += (*itr)->GetDataSize();

    if ((*itr)->IsKeyframe()) {
      keyframe_map_.insert(
          std::make_pair((*itr)->GetDecodeTimestamp(),
                         static_cast<int>(buffers_.size()) - 1 +
                                          keyframe_map_index_base_));

      if (waiting_for_keyframe_ &&
          (*itr)->GetDecodeTimestamp() >= next_keyframe_timestamp_) {
        next_buffer_index_ = buffers_.size() - 1;
        next_keyframe_timestamp_ = kNoTimestamp();
        waiting_for_keyframe_ = false;
      }
    }
  }
}

void SourceBufferRange::Seek(base::TimeDelta timestamp) {
  DCHECK(CanSeekTo(timestamp));
  DCHECK(!keyframe_map_.empty());

  next_keyframe_timestamp_ = kNoTimestamp();
  waiting_for_keyframe_ = false;

  KeyframeMap::iterator result = GetFirstKeyframeBefore(timestamp);
  next_buffer_index_ = result->second - keyframe_map_index_base_;
  DCHECK_LT(next_buffer_index_, static_cast<int>(buffers_.size()));
}

void SourceBufferRange::SeekAheadTo(base::TimeDelta timestamp) {
  SeekAhead(timestamp, false);
}

void SourceBufferRange::SeekAheadPast(base::TimeDelta timestamp) {
  SeekAhead(timestamp, true);
}

void SourceBufferRange::SeekAhead(base::TimeDelta timestamp,
                                  bool skip_given_timestamp) {
  DCHECK(!keyframe_map_.empty());

  KeyframeMap::iterator result =
      GetFirstKeyframeAt(timestamp, skip_given_timestamp);

  // If there isn't a keyframe after |timestamp|, then seek to end and return
  // kNoTimestamp to signal such.
  if (result == keyframe_map_.end()) {
    waiting_for_keyframe_ = true;
    next_buffer_index_ = -1;
    next_keyframe_timestamp_ = timestamp;
    return;
  }
  next_buffer_index_ = result->second - keyframe_map_index_base_;
  DCHECK_LT(next_buffer_index_, static_cast<int>(buffers_.size()));
}

void SourceBufferRange::SeekToStart() {
  DCHECK(!buffers_.empty());
  next_buffer_index_ = 0;
}

SourceBufferRange* SourceBufferRange::SplitRange(
    base::TimeDelta timestamp, bool is_exclusive) {
  // Find the first keyframe after |timestamp|. If |is_exclusive|, do not
  // include keyframes at |timestamp|.
  KeyframeMap::iterator new_beginning_keyframe =
      GetFirstKeyframeAt(timestamp, is_exclusive);

  // If there is no keyframe after |timestamp|, we can't split the range.
  if (new_beginning_keyframe == keyframe_map_.end())
    return NULL;

  // Remove the data beginning at |keyframe_index| from |buffers_| and save it
  // into |removed_buffers|.
  int keyframe_index =
      new_beginning_keyframe->second - keyframe_map_index_base_;
  DCHECK_LT(keyframe_index, static_cast<int>(buffers_.size()));
  BufferQueue::iterator starting_point = buffers_.begin() + keyframe_index;
  BufferQueue removed_buffers(starting_point, buffers_.end());
  keyframe_map_.erase(new_beginning_keyframe, keyframe_map_.end());
  FreeBufferRange(starting_point, buffers_.end());

  // Create a new range with |removed_buffers|.
#if defined(__LB_SHELL__) || defined(COBALT)
  SourceBufferRange* split_range =
      new SourceBufferRange(
          removed_buffers, kNoTimestamp(), interbuffer_distance_cb_);
#else
  SourceBufferRange* split_range =
      new SourceBufferRange(
          removed_buffers, kNoTimestamp(), interbuffer_distance_cb_);
#endif

  // If the next buffer position is now in |split_range|, update the state of
  // this range and |split_range| accordingly.
  if (next_buffer_index_ >= static_cast<int>(buffers_.size())) {
    DCHECK(!waiting_for_keyframe_);
    split_range->next_buffer_index_ = next_buffer_index_ - keyframe_index;
    ResetNextBufferPosition();
  } else if (waiting_for_keyframe_) {
    split_range->waiting_for_keyframe_ = true;
    split_range->next_keyframe_timestamp_ = next_keyframe_timestamp_;
    ResetNextBufferPosition();
  }

  return split_range;
}

SourceBufferRange::BufferQueue::iterator SourceBufferRange::GetBufferItrAt(
    base::TimeDelta timestamp, bool skip_given_timestamp) {
  // Need to make a dummy buffer with timestamp |timestamp| in order to search
  // the |buffers_| container.
  scoped_refptr<StreamParserBuffer> dummy_buffer =
      StreamParserBuffer::CopyFrom(NULL, 0, false);
  dummy_buffer->SetDecodeTimestamp(timestamp);

  if (skip_given_timestamp) {
    return std::upper_bound(
        buffers_.begin(), buffers_.end(), dummy_buffer, BufferComparator);
  }
  return std::lower_bound(
      buffers_.begin(), buffers_.end(), dummy_buffer, BufferComparator);
}

SourceBufferRange::KeyframeMap::iterator
SourceBufferRange::GetFirstKeyframeAt(base::TimeDelta timestamp,
                                      bool skip_given_timestamp) {
  return skip_given_timestamp ?
      keyframe_map_.upper_bound(timestamp) :
      keyframe_map_.lower_bound(timestamp);
}

SourceBufferRange::KeyframeMap::iterator
SourceBufferRange::GetFirstKeyframeBefore(base::TimeDelta timestamp) {
  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
  // |timestamp|.
  if (result != keyframe_map_.begin() &&
      (result == keyframe_map_.end() || result->first != timestamp)) {
    --result;
  }
  return result;
}

bool SourceBufferRange::DeleteAll(BufferQueue* removed_buffers) {
  return TruncateAt(buffers_.begin(), removed_buffers);
}

bool SourceBufferRange::TruncateAt(
    base::TimeDelta timestamp, BufferQueue* removed_buffers,
    bool is_exclusive) {
  // Find the place in |buffers_| where we will begin deleting data.
  BufferQueue::iterator starting_point =
      GetBufferItrAt(timestamp, is_exclusive);
  return TruncateAt(starting_point, removed_buffers);
}

int SourceBufferRange::DeleteGOPFromFront(BufferQueue* deleted_buffers) {
  DCHECK(!FirstGOPContainsNextBufferPosition());
  DCHECK(deleted_buffers);

  int buffers_deleted = 0;
  int total_bytes_deleted = 0;

  KeyframeMap::iterator front = keyframe_map_.begin();
  DCHECK(front != keyframe_map_.end());

  // Delete the keyframe at the start of |keyframe_map_|.
  keyframe_map_.erase(front);

  // Now we need to delete all the buffers that depend on the keyframe we've
  // just deleted.
  int end_index = keyframe_map_.size() > 0 ?
      keyframe_map_.begin()->second - keyframe_map_index_base_ :
      buffers_.size();

  // Delete buffers from the beginning of the buffered range up until (but not
  // including) the next keyframe.
  for (int i = 0; i < end_index; i++) {
    int bytes_deleted = buffers_.front()->GetDataSize();
    size_in_bytes_ -= bytes_deleted;
    total_bytes_deleted += bytes_deleted;
    deleted_buffers->push_back(buffers_.front());
    buffers_.pop_front();
    ++buffers_deleted;
  }

  // Update |keyframe_map_index_base_| to account for the deleted buffers.
  keyframe_map_index_base_ += buffers_deleted;

  if (next_buffer_index_ > -1) {
    next_buffer_index_ -= buffers_deleted;
    DCHECK_GE(next_buffer_index_, 0);
  }

  // Invalidate media segment start time if we've deleted the first buffer of
  // the range.
  if (buffers_deleted > 0)
    media_segment_start_time_ = kNoTimestamp();

  return total_bytes_deleted;
}

int SourceBufferRange::DeleteGOPFromBack(BufferQueue* deleted_buffers) {
  DCHECK(!LastGOPContainsNextBufferPosition());
  DCHECK(deleted_buffers);

  // Remove the last GOP's keyframe from the |keyframe_map_|.
  KeyframeMap::iterator back = keyframe_map_.end();
  DCHECK_GT(keyframe_map_.size(), 0u);
  --back;

  // The index of the first buffer in the last GOP is equal to the new size of
  // |buffers_| after that GOP is deleted.
  size_t goal_size = back->second - keyframe_map_index_base_;
  keyframe_map_.erase(back);

  int total_bytes_deleted = 0;
  while (buffers_.size() != goal_size) {
    int bytes_deleted = buffers_.back()->GetDataSize();
    size_in_bytes_ -= bytes_deleted;
    total_bytes_deleted += bytes_deleted;
    // We're removing buffers from the back, so push each removed buffer to the
    // front of |deleted_buffers| so that |deleted_buffers| are in nondecreasing
    // order.
    deleted_buffers->push_front(buffers_.back());
    buffers_.pop_back();
  }

  return total_bytes_deleted;
}

bool SourceBufferRange::FirstGOPContainsNextBufferPosition() const {
  if (!HasNextBufferPosition())
    return false;

  // If there is only one GOP, it must contain the next buffer position.
  if (keyframe_map_.size() == 1u)
    return true;

  KeyframeMap::const_iterator second_gop = keyframe_map_.begin();
  ++second_gop;
  return !waiting_for_keyframe_ &&
      next_buffer_index_ < second_gop->second - keyframe_map_index_base_;
}

bool SourceBufferRange::LastGOPContainsNextBufferPosition() const {
  if (!HasNextBufferPosition())
    return false;

  // If there is only one GOP, it must contain the next buffer position.
  if (keyframe_map_.size() == 1u)
    return true;

  KeyframeMap::const_iterator last_gop = keyframe_map_.end();
  --last_gop;
  return waiting_for_keyframe_ ||
      last_gop->second - keyframe_map_index_base_ <= next_buffer_index_;
}

void SourceBufferRange::FreeBufferRange(
    const BufferQueue::iterator& starting_point,
    const BufferQueue::iterator& ending_point) {
  for (BufferQueue::iterator itr = starting_point;
       itr != ending_point; ++itr) {
    size_in_bytes_ -= (*itr)->GetDataSize();
    DCHECK_GE(size_in_bytes_, 0);
  }
  buffers_.erase(starting_point, ending_point);
}

bool SourceBufferRange::TruncateAt(
    const BufferQueue::iterator& starting_point, BufferQueue* removed_buffers) {
  DCHECK(!removed_buffers || removed_buffers->empty());

  // Return if we're not deleting anything.
  if (starting_point == buffers_.end())
    return false;

  // Reset the next buffer index if we will be deleting the buffer that's next
  // in sequence.
  bool removed_next_buffer = false;
  if (HasNextBufferPosition()) {
    base::TimeDelta next_buffer_timestamp = GetNextTimestamp();
    if (next_buffer_timestamp == kNoTimestamp() ||
        next_buffer_timestamp >= (*starting_point)->GetDecodeTimestamp()) {
      if (HasNextBuffer() && removed_buffers) {
        int starting_offset = starting_point - buffers_.begin();
        int next_buffer_offset = next_buffer_index_ - starting_offset;
        DCHECK_GE(next_buffer_offset, 0);
        BufferQueue saved(starting_point + next_buffer_offset, buffers_.end());
        removed_buffers->swap(saved);
      }
      ResetNextBufferPosition();
      removed_next_buffer = true;
    }
  }

  // Remove keyframes from |starting_point| onward.
  KeyframeMap::iterator starting_point_keyframe =
      keyframe_map_.lower_bound((*starting_point)->GetDecodeTimestamp());
  keyframe_map_.erase(starting_point_keyframe, keyframe_map_.end());

  // Remove everything from |starting_point| onward.
  FreeBufferRange(starting_point, buffers_.end());
  return removed_next_buffer;
}

bool SourceBufferRange::GetNextBuffer(
    scoped_refptr<StreamParserBuffer>* out_buffer) {
  if (!HasNextBuffer())
    return false;

  *out_buffer = buffers_.at(next_buffer_index_);
  next_buffer_index_++;
  return true;
}

bool SourceBufferRange::HasNextBuffer() const {
  return next_buffer_index_ >= 0 &&
      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());

  if (waiting_for_keyframe_ ||
      next_buffer_index_ >= static_cast<int>(buffers_.size())) {
    return kNoTimestamp();
  }

  return buffers_.at(next_buffer_index_)->GetDecodeTimestamp();
}

bool SourceBufferRange::HasNextBufferPosition() const {
  return next_buffer_index_ >= 0 || waiting_for_keyframe_;
}

void SourceBufferRange::ResetNextBufferPosition() {
  next_buffer_index_ = -1;
  waiting_for_keyframe_ = false;
  next_keyframe_timestamp_ = kNoTimestamp();
}

void SourceBufferRange::AppendRangeToEnd(const SourceBufferRange& range,
                                         bool transfer_current_position) {
  DCHECK(CanAppendRangeToEnd(range));
  DCHECK(!buffers_.empty());

  if (transfer_current_position)
    next_buffer_index_ = range.next_buffer_index_ + buffers_.size();

  AppendBuffersToEnd(range.buffers_);
}

bool SourceBufferRange::CanAppendRangeToEnd(
    const SourceBufferRange& range) const {
  return CanAppendBuffersToEnd(range.buffers_);
}

bool SourceBufferRange::CanAppendBuffersToEnd(
    const BufferQueue& buffers) const {
  DCHECK(!buffers_.empty());
  return IsNextInSequence(buffers_.back(),
                          buffers.front()->GetDecodeTimestamp());
}

bool SourceBufferRange::BelongsToRange(base::TimeDelta timestamp) const {
  DCHECK(!buffers_.empty());

  return (IsNextInSequence(buffers_.back(), timestamp) ||
          (GetStartTimestamp() <= timestamp && timestamp <= GetEndTimestamp()));
}

bool SourceBufferRange::CanSeekTo(base::TimeDelta timestamp) const {
  base::TimeDelta start_timestamp =
      std::max(base::TimeDelta(), GetStartTimestamp() - GetFudgeRoom());
  return !keyframe_map_.empty() && start_timestamp <= timestamp &&
      timestamp < GetBufferedEndTimestamp();
}

bool SourceBufferRange::CompletelyOverlaps(
    const SourceBufferRange& range) const {
  return GetStartTimestamp() <= range.GetStartTimestamp() &&
      GetEndTimestamp() >= range.GetEndTimestamp();
}

bool SourceBufferRange::EndOverlaps(const SourceBufferRange& range) const {
  return range.GetStartTimestamp() <= GetEndTimestamp() &&
      GetEndTimestamp() < range.GetEndTimestamp();
}

base::TimeDelta SourceBufferRange::GetStartTimestamp() const {
  DLOG_IF(WARNING, buffers_.empty()) << "|buffers_| cannot be empty.";
  base::TimeDelta start_timestamp = media_segment_start_time_;
  if (start_timestamp == kNoTimestamp())
    start_timestamp = buffers_.front()->GetDecodeTimestamp();
  return start_timestamp;
}

base::TimeDelta SourceBufferRange::GetEndTimestamp() const {
  DCHECK(!buffers_.empty());
  return buffers_.back()->GetDecodeTimestamp();
}

base::TimeDelta SourceBufferRange::GetBufferedEndTimestamp() const {
  DCHECK(!buffers_.empty());
  base::TimeDelta duration = buffers_.back()->GetDuration();
  if (duration == kNoTimestamp() || duration == base::TimeDelta())
    duration = GetApproximateDuration();
  return GetEndTimestamp() + duration;
}

bool SourceBufferRange::IsNextInSequence(
    const scoped_refptr<media::StreamParserBuffer>& buffer,
    base::TimeDelta timestamp) const {
  return buffer->GetDecodeTimestamp() < timestamp &&
      timestamp <= buffer->GetDecodeTimestamp() + GetFudgeRoom();
}

base::TimeDelta SourceBufferRange::GetFudgeRoom() const {
  return ComputeFudgeRoom(GetApproximateDuration());
}

base::TimeDelta SourceBufferRange::GetApproximateDuration() const {
  base::TimeDelta max_interbuffer_distance = interbuffer_distance_cb_.Run();
  DCHECK(max_interbuffer_distance != kNoTimestamp());
  return max_interbuffer_distance;
}

void LogMediaSourceTimeRanges(const std::string& desc,
                              const Ranges<base::TimeDelta>& time_ranges) {
#if LOG_MEDIA_SOURCE_ACTIVITIES
  LOG(INFO) << ("======== " + desc + " ========");
  for (size_t i = 0; i < time_ranges.size(); ++i)
    LOG(INFO) << "\t\tRange " << i << " : "
              << time_ranges.start(i).InMicroseconds() << " - "
              << time_ranges.end(i).InMicroseconds();
#endif  // LOG_MEDIA_SOURCE_ACTIVITIES
}

}  // namespace media
