1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #ifndef MEDIA_FILTERS_SOURCE_BUFFER_RANGE_H_
6 #define MEDIA_FILTERS_SOURCE_BUFFER_RANGE_H_
10 #include "base/basictypes.h"
11 #include "base/callback.h"
12 #include "base/memory/ref_counted.h"
13 #include "media/base/stream_parser_buffer.h"
17 // Helper class representing a range of buffered data. All buffers in a
18 // SourceBufferRange are ordered sequentially in decode timestamp order with no
20 class SourceBufferRange
{
22 // Returns the maximum distance in time between any buffer seen in this
23 // stream. Used to estimate the duration of a buffer if its duration is not
25 typedef base::Callback
<base::TimeDelta()> InterbufferDistanceCB
;
27 typedef StreamParser::BufferQueue BufferQueue
;
29 // Policy for handling large gaps between buffers. Continuous media like
30 // audio & video should use NO_GAPS_ALLOWED. Discontinuous media like
31 // timed text should use ALLOW_GAPS because large differences in timestamps
32 // are common and acceptable.
38 // Buffers with the same timestamp are only allowed under certain conditions.
39 // More precisely, it is allowed in all situations except when the previous
40 // frame is not a key frame and the current is a key frame.
41 // Examples of situations where DTS of two consecutive frames can be equal:
42 // - Video: VP8 Alt-Ref frames.
43 // - Video: IPBPBP...: DTS for I frame and for P frame can be equal.
44 // - Text track cues that start at same time.
45 // Returns true if |prev_is_keyframe| and |current_is_keyframe| indicate a
46 // same timestamp situation that is allowed. False is returned otherwise.
47 static bool AllowSameTimestamp(bool prev_is_keyframe
,
48 bool current_is_keyframe
);
50 // Creates a source buffer range with |new_buffers|. |new_buffers| cannot be
51 // empty and the front of |new_buffers| must be a keyframe.
52 // |media_segment_start_time| refers to the starting timestamp for the media
53 // segment to which these buffers belong.
54 SourceBufferRange(GapPolicy gap_policy
,
55 const BufferQueue
& new_buffers
,
56 DecodeTimestamp media_segment_start_time
,
57 const InterbufferDistanceCB
& interbuffer_distance_cb
);
61 // Appends |buffers| to the end of the range and updates |keyframe_map_| as
62 // it encounters new keyframes. Assumes |buffers| belongs at the end of the
64 void AppendBuffersToEnd(const BufferQueue
& buffers
);
65 bool CanAppendBuffersToEnd(const BufferQueue
& buffers
) const;
67 // Appends the buffers from |range| into this range.
68 // The first buffer in |range| must come directly after the last buffer
70 // If |transfer_current_position| is true, |range|'s |next_buffer_index_|
71 // is transfered to this SourceBufferRange.
72 void AppendRangeToEnd(const SourceBufferRange
& range
,
73 bool transfer_current_position
);
74 bool CanAppendRangeToEnd(const SourceBufferRange
& range
) const;
76 // Updates |next_buffer_index_| to point to the Buffer containing |timestamp|.
77 // Assumes |timestamp| is valid and in this range.
78 void Seek(DecodeTimestamp timestamp
);
80 // Updates |next_buffer_index_| to point to next keyframe after or equal to
82 void SeekAheadTo(DecodeTimestamp timestamp
);
84 // Updates |next_buffer_index_| to point to next keyframe strictly after
86 void SeekAheadPast(DecodeTimestamp timestamp
);
88 // Seeks to the beginning of the range.
91 // Finds the next keyframe from |buffers_| starting at or after |timestamp|
92 // and creates and returns a new SourceBufferRange with the buffers from that
93 // keyframe onward. The buffers in the new SourceBufferRange are moved out of
94 // this range. If there is no keyframe at or after |timestamp|, SplitRange()
95 // returns null and this range is unmodified.
96 SourceBufferRange
* SplitRange(DecodeTimestamp timestamp
);
98 // Deletes the buffers from this range starting at |timestamp|, exclusive if
99 // |is_exclusive| is true, inclusive otherwise.
100 // Resets |next_buffer_index_| if the buffer at |next_buffer_index_| was
101 // deleted, and deletes the |keyframe_map_| entries for the buffers that
103 // |deleted_buffers| contains the buffers that were deleted from this range,
104 // starting at the buffer that had been at |next_buffer_index_|.
105 // Returns true if everything in the range was deleted. Otherwise
107 bool TruncateAt(DecodeTimestamp timestamp
,
108 BufferQueue
* deleted_buffers
, bool is_exclusive
);
109 // Deletes all buffers in range.
110 void DeleteAll(BufferQueue
* deleted_buffers
);
112 // Deletes a GOP from the front or back of the range and moves these
113 // buffers into |deleted_buffers|. Returns the number of bytes deleted from
114 // the range (i.e. the size in bytes of |deleted_buffers|).
115 size_t DeleteGOPFromFront(BufferQueue
* deleted_buffers
);
116 size_t DeleteGOPFromBack(BufferQueue
* deleted_buffers
);
118 // Gets the range of GOP to secure at least |bytes_to_free| from
119 // [|start_timestamp|, |end_timestamp|).
120 // Returns the size of the buffers to secure if the buffers of
121 // [|start_timestamp|, |end_removal_timestamp|) is removed.
122 // Will not update |end_removal_timestamp| if the returned size is 0.
123 size_t GetRemovalGOP(
124 DecodeTimestamp start_timestamp
, DecodeTimestamp end_timestamp
,
125 size_t bytes_to_free
, DecodeTimestamp
* end_removal_timestamp
);
127 bool FirstGOPEarlierThanMediaTime(DecodeTimestamp media_time
) const;
129 // Indicates whether the GOP at the beginning or end of the range contains the
130 // next buffer position.
131 bool FirstGOPContainsNextBufferPosition() const;
132 bool LastGOPContainsNextBufferPosition() const;
134 // Updates |out_buffer| with the next buffer in presentation order. Seek()
135 // must be called before calls to GetNextBuffer(), and buffers are returned
136 // in order from the last call to Seek(). Returns true if |out_buffer| is
137 // filled with a valid buffer, false if there is not enough data to fulfill
139 bool GetNextBuffer(scoped_refptr
<StreamParserBuffer
>* out_buffer
);
140 bool HasNextBuffer() const;
142 // Returns the config ID for the buffer that will be returned by
144 int GetNextConfigId() const;
146 // Returns true if the range knows the position of the next buffer it should
147 // return, i.e. it has been Seek()ed. This does not necessarily mean that it
148 // has the next buffer yet.
149 bool HasNextBufferPosition() const;
151 // Resets this range to an "unseeked" state.
152 void ResetNextBufferPosition();
154 // Returns the timestamp of the next buffer that will be returned from
155 // GetNextBuffer(), or kNoTimestamp() if the timestamp is unknown.
156 DecodeTimestamp
GetNextTimestamp() const;
158 // Returns the start timestamp of the range.
159 DecodeTimestamp
GetStartTimestamp() const;
161 // Returns the timestamp of the last buffer in the range.
162 DecodeTimestamp
GetEndTimestamp() const;
164 // Returns the timestamp for the end of the buffered region in this range.
165 // This is an approximation if the duration for the last buffer in the range
167 DecodeTimestamp
GetBufferedEndTimestamp() const;
169 // Gets the timestamp for the keyframe that is after |timestamp|. If
170 // there isn't a keyframe in the range after |timestamp| then kNoTimestamp()
171 // is returned. If |timestamp| is in the "gap" between the value returned by
172 // GetStartTimestamp() and the timestamp on the first buffer in |buffers_|,
173 // then |timestamp| is returned.
174 DecodeTimestamp
NextKeyframeTimestamp(DecodeTimestamp timestamp
);
176 // Gets the timestamp for the closest keyframe that is <= |timestamp|. If
177 // there isn't a keyframe before |timestamp| or |timestamp| is outside
178 // this range, then kNoTimestamp() is returned.
179 DecodeTimestamp
KeyframeBeforeTimestamp(DecodeTimestamp timestamp
);
181 // Returns whether a buffer with a starting timestamp of |timestamp| would
182 // belong in this range. This includes a buffer that would be appended to
183 // the end of the range.
184 bool BelongsToRange(DecodeTimestamp timestamp
) const;
186 // Returns true if the range has enough data to seek to the specified
187 // |timestamp|, false otherwise.
188 bool CanSeekTo(DecodeTimestamp timestamp
) const;
190 // Returns true if this range's buffered timespan completely overlaps the
191 // buffered timespan of |range|.
192 bool CompletelyOverlaps(const SourceBufferRange
& range
) const;
194 // Returns true if the end of this range contains buffers that overlaps with
195 // the beginning of |range|.
196 bool EndOverlaps(const SourceBufferRange
& range
) const;
198 // Returns true if |timestamp| is the timestamp of the next buffer in
199 // sequence after |buffers_.back()|, false otherwise.
200 bool IsNextInSequence(DecodeTimestamp timestamp
, bool is_key_frame
) const;
202 // Adds all buffers which overlap [start, end) to the end of |buffers|. If
203 // no buffers exist in the range returns false, true otherwise.
204 bool GetBuffersInRange(DecodeTimestamp start
, DecodeTimestamp end
,
205 BufferQueue
* buffers
);
207 size_t size_in_bytes() const { return size_in_bytes_
; }
210 typedef std::map
<DecodeTimestamp
, int> KeyframeMap
;
212 // Called during AppendBuffersToEnd to adjust estimated duration at the
213 // end of the last append to match the delta in timestamps between
214 // the last append and the upcoming append. This is a workaround for
215 // WebM media where a duration is not always specified.
216 void AdjustEstimatedDurationForNewAppend(const BufferQueue
& new_buffers
);
218 // Seeks the range to the next keyframe after |timestamp|. If
219 // |skip_given_timestamp| is true, the seek will go to a keyframe with a
220 // timestamp strictly greater than |timestamp|.
221 void SeekAhead(DecodeTimestamp timestamp
, bool skip_given_timestamp
);
223 // Returns an iterator in |buffers_| pointing to the buffer at |timestamp|.
224 // If |skip_given_timestamp| is true, this returns the first buffer with
225 // timestamp greater than |timestamp|.
226 BufferQueue::iterator
GetBufferItrAt(
227 DecodeTimestamp timestamp
, bool skip_given_timestamp
);
229 // Returns an iterator in |keyframe_map_| pointing to the next keyframe after
230 // |timestamp|. If |skip_given_timestamp| is true, this returns the first
231 // keyframe with a timestamp strictly greater than |timestamp|.
232 KeyframeMap::iterator
GetFirstKeyframeAt(
233 DecodeTimestamp timestamp
, bool skip_given_timestamp
);
235 // Returns an iterator in |keyframe_map_| pointing to the first keyframe
236 // before or at |timestamp|.
237 KeyframeMap::iterator
GetFirstKeyframeAtOrBefore(DecodeTimestamp timestamp
);
239 // Helper method to delete buffers in |buffers_| starting at
240 // |starting_point|, an iterator in |buffers_|.
241 // Returns true if everything in the range was removed. Returns
242 // false if the range still contains buffers.
243 bool TruncateAt(const BufferQueue::iterator
& starting_point
,
244 BufferQueue
* deleted_buffers
);
246 // Frees the buffers in |buffers_| from [|start_point|,|ending_point|) and
247 // updates the |size_in_bytes_| accordingly. Does not update |keyframe_map_|.
248 void FreeBufferRange(const BufferQueue::iterator
& starting_point
,
249 const BufferQueue::iterator
& ending_point
);
251 // Returns the distance in time estimating how far from the beginning or end
252 // of this range a buffer can be to considered in the range.
253 base::TimeDelta
GetFudgeRoom() const;
255 // Returns the approximate duration of a buffer in this range.
256 base::TimeDelta
GetApproximateDuration() const;
258 // Keeps track of whether gaps are allowed.
259 const GapPolicy gap_policy_
;
261 // An ordered list of buffers in this range.
262 BufferQueue buffers_
;
264 // Maps keyframe timestamps to its index position in |buffers_|.
265 KeyframeMap keyframe_map_
;
267 // Index base of all positions in |keyframe_map_|. In other words, the
268 // real position of entry |k| of |keyframe_map_| in the range is:
269 // keyframe_map_[k] - keyframe_map_index_base_
270 int keyframe_map_index_base_
;
272 // Index into |buffers_| for the next buffer to be returned by
273 // GetNextBuffer(), set to -1 before Seek().
274 int next_buffer_index_
;
276 // If the first buffer in this range is the beginning of a media segment,
277 // |media_segment_start_time_| is the time when the media segment begins.
278 // |media_segment_start_time_| may be <= the timestamp of the first buffer in
279 // |buffers_|. |media_segment_start_time_| is kNoTimestamp() if this range
280 // does not start at the beginning of a media segment, which can only happen
281 // garbage collection or after an end overlap that results in a split range
282 // (we don't have a way of knowing the media segment timestamp for the new
284 DecodeTimestamp media_segment_start_time_
;
286 // Called to get the largest interbuffer distance seen so far in the stream.
287 InterbufferDistanceCB interbuffer_distance_cb_
;
289 // Stores the amount of memory taken up by the data in |buffers_|.
290 size_t size_in_bytes_
;
292 DISALLOW_COPY_AND_ASSIGN(SourceBufferRange
);
297 #endif // MEDIA_FILTERS_SOURCE_BUFFER_RANGE_H_