| Index: media/filters/source_buffer_range.h
 | 
| diff --git a/media/filters/source_buffer_range.h b/media/filters/source_buffer_range.h
 | 
| index f387ad83a96765dbba9d23e0c2785ec470d82501..7e35dbdeee7275abb51c6a3d0ce2ab02dcc617ea 100644
 | 
| --- a/media/filters/source_buffer_range.h
 | 
| +++ b/media/filters/source_buffer_range.h
 | 
| @@ -37,40 +37,59 @@ class SourceBufferRange {
 | 
|      ALLOW_GAPS
 | 
|    };
 | 
|  
 | 
| -  // Buffers with the same timestamp are only allowed under certain conditions.
 | 
| -  // More precisely, it is allowed in all situations except when the previous
 | 
| -  // frame is not a key frame and the current is a key frame.
 | 
| -  // Examples of situations where DTS of two consecutive frames can be equal:
 | 
| +  // Sequential buffers with the same decode timestamp make sense under certain
 | 
| +  // conditions, typically when the first buffer is a keyframe. Due to some
 | 
| +  // atypical media append behaviors where a new keyframe might have the same
 | 
| +  // timestamp as a previous non-keyframe, the playback of the sequence might
 | 
| +  // involve some throwaway decode work. This method supports detecting this
 | 
| +  // situation so that callers can log warnings (it returns true in this case
 | 
| +  // only).
 | 
| +  // For all other cases, including more typical same-DTS sequences, this method
 | 
| +  // returns false. Examples of typical situations where DTS of two consecutive
 | 
| +  // frames can be equal:
 | 
|    // - Video: VP8 Alt-Ref frames.
 | 
|    // - Video: IPBPBP...: DTS for I frame and for P frame can be equal.
 | 
|    // - Text track cues that start at same time.
 | 
|    // Returns true if |prev_is_keyframe| and |current_is_keyframe| indicate a
 | 
| -  // same timestamp situation that is allowed. False is returned otherwise.
 | 
| -  static bool AllowSameTimestamp(bool prev_is_keyframe,
 | 
| -                                 bool current_is_keyframe);
 | 
| +  // same timestamp situation that is atypical. False is returned otherwise.
 | 
| +  static bool IsUncommonSameTimestampSequence(bool prev_is_keyframe,
 | 
| +                                              bool current_is_keyframe);
 | 
|  
 | 
|    // 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.
 | 
| +  // |range_start_time| refers to the starting timestamp for the coded frame
 | 
| +  // group to which these buffers belong.
 | 
|    SourceBufferRange(GapPolicy gap_policy,
 | 
|                      const BufferQueue& new_buffers,
 | 
| -                    DecodeTimestamp media_segment_start_time,
 | 
| +                    DecodeTimestamp range_start_time,
 | 
|                      const InterbufferDistanceCB& interbuffer_distance_cb);
 | 
|  
 | 
|    ~SourceBufferRange();
 | 
|  
 | 
|    // 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;
 | 
| +  // it encounters new keyframes.
 | 
| +  // If |new_buffers_group_start_timestamp| is kNoDecodeTimestamp(), then the
 | 
| +  // first buffer in |buffers| must come directly after the last buffer in this
 | 
| +  // range (within the fudge room).
 | 
| +  // If |new_buffers_group_start_timestamp| is set otherwise, then that time
 | 
| +  // must come directly after the last buffer in this range (within the fudge
 | 
| +  // room). The latter scenario is required when a muxed coded frame group has
 | 
| +  // such a large jagged start across tracks that its first buffer is not within
 | 
| +  // the fudge room, yet its group start was.
 | 
| +  void AppendBuffersToEnd(const BufferQueue& buffers,
 | 
| +                          DecodeTimestamp new_buffers_group_start_timestamp);
 | 
| +  bool CanAppendBuffersToEnd(
 | 
| +      const BufferQueue& buffers,
 | 
| +      DecodeTimestamp new_buffers_group_start_timestamp) 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.
 | 
| +  // Note: Use these only to merge existing ranges. |range|'s first buffer
 | 
| +  // timestamp must be adjacent to this range. No group start timestamp
 | 
| +  // adjacency is involved in these methods.
 | 
|    void AppendRangeToEnd(const SourceBufferRange& range,
 | 
|                          bool transfer_current_position);
 | 
|    bool CanAppendRangeToEnd(const SourceBufferRange& range) const;
 | 
| @@ -94,7 +113,8 @@ class SourceBufferRange {
 | 
|    // 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 at or after |timestamp|, SplitRange()
 | 
| -  // returns null and this range is unmodified.
 | 
| +  // returns null and this range is unmodified. This range can become empty if
 | 
| +  // |timestamp| <= the DTS of the first buffer in this range.
 | 
|    SourceBufferRange* SplitRange(DecodeTimestamp timestamp);
 | 
|  
 | 
|    // Deletes the buffers from this range starting at |timestamp|, exclusive if
 | 
| @@ -203,7 +223,7 @@ class SourceBufferRange {
 | 
|  
 | 
|    // Returns true if |timestamp| is the timestamp of the next buffer in
 | 
|    // sequence after |buffers_.back()|, false otherwise.
 | 
| -  bool IsNextInSequence(DecodeTimestamp timestamp, bool is_key_frame) const;
 | 
| +  bool IsNextInSequence(DecodeTimestamp timestamp) const;
 | 
|  
 | 
|    // Adds all buffers which overlap [start, end) to the end of |buffers|.  If
 | 
|    // no buffers exist in the range returns false, true otherwise.
 | 
| @@ -279,15 +299,17 @@ class SourceBufferRange {
 | 
|    // GetNextBuffer(), set to -1 before Seek().
 | 
|    int next_buffer_index_;
 | 
|  
 | 
| -  // 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).
 | 
| -  DecodeTimestamp media_segment_start_time_;
 | 
| +  // If the first buffer in this range is the beginning of a coded frame group,
 | 
| +  // |range_start_time_| is the time when the coded frame group begins. This is
 | 
| +  // especially important in muxed media where the first coded frames for each
 | 
| +  // track do not necessarily begin at the same time.
 | 
| +  // |range_start_time_| may be <= the timestamp of the first buffer in
 | 
| +  // |buffers_|. |range_start_time_| is kNoDecodeTimestamp() if this range does
 | 
| +  // not start at the beginning of a coded frame group, which can happen by
 | 
| +  // range removal or split when we don't have a way of knowing, across
 | 
| +  // potentially multiple muxed streams, the coded frame group start timestamp
 | 
| +  // for the new range.
 | 
| +  DecodeTimestamp range_start_time_;
 | 
|  
 | 
|    // Called to get the largest interbuffer distance seen so far in the stream.
 | 
|    InterbufferDistanceCB interbuffer_distance_cb_;
 | 
| 
 |