OLD | NEW |
---|---|
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "media/filters/source_buffer_stream.h" | 5 #include "media/filters/source_buffer_stream.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 #include <map> | 8 #include <map> |
9 | 9 |
10 #include "base/logging.h" | 10 #include "base/logging.h" |
(...skipping 28 matching lines...) Expand all Loading... | |
39 void AppendToEnd(const SourceBufferRange& range, | 39 void AppendToEnd(const SourceBufferRange& range, |
40 bool transfer_current_position); | 40 bool transfer_current_position); |
41 bool CanAppendToEnd(const SourceBufferRange& range) const; | 41 bool CanAppendToEnd(const SourceBufferRange& range) const; |
42 | 42 |
43 // Updates |next_buffer_index_| to point to the Buffer containing |timestamp|. | 43 // Updates |next_buffer_index_| to point to the Buffer containing |timestamp|. |
44 // Assumes |timestamp| is valid and in this range. | 44 // Assumes |timestamp| is valid and in this range. |
45 void Seek(base::TimeDelta timestamp); | 45 void Seek(base::TimeDelta timestamp); |
46 | 46 |
47 // Updates |next_buffer_index_| to point to next keyframe after or equal to | 47 // Updates |next_buffer_index_| to point to next keyframe after or equal to |
48 // |timestamp|. | 48 // |timestamp|. |
49 void SeekAfter(base::TimeDelta timestamp); | 49 void SeekAheadTo(base::TimeDelta timestamp); |
50 | |
51 // Updates |next_buffer_index_| to point to next keyframe strictly after | |
52 // |timestamp|. | |
53 void SeekAheadPast(base::TimeDelta timestamp); | |
50 | 54 |
51 // Finds the next keyframe from |buffers_| after |timestamp|, and creates and | 55 // Finds the next keyframe from |buffers_| after |timestamp|, and creates and |
52 // returns a new SourceBufferRange with the buffers from that keyframe onward. | 56 // returns a new SourceBufferRange with the buffers from that keyframe onward. |
53 // The buffers in the new SourceBufferRange are moved out of this range. If | 57 // The buffers in the new SourceBufferRange are moved out of this range. If |
54 // there is no keyframe after |timestamp|, SplitRange() returns null and this | 58 // there is no keyframe after |timestamp|, SplitRange() returns null and this |
55 // range is unmodified. | 59 // range is unmodified. |
56 SourceBufferRange* SplitRange(base::TimeDelta timestamp); | 60 SourceBufferRange* SplitRange(base::TimeDelta timestamp); |
57 | 61 |
58 // Deletes the buffers from this range whose timestamps are greater than or | 62 // Deletes the buffers from this range whose timestamps are greater than or |
59 // equal to |buffer|'s timestamp. | 63 // equal to |buffer|'s timestamp. |
60 // Resets |next_buffer_index_| if the buffer at |next_buffer_index_| was | 64 // Resets |next_buffer_index_| if the buffer at |next_buffer_index_| was |
61 // deleted, and deletes the |keyframe_map_| entries for the buffers that | 65 // deleted, and deletes the |keyframe_map_| entries for the buffers that |
62 // were removed. | 66 // were removed. |
63 // |deleted_buffers| contains the buffers that were deleted from this range, | 67 // |deleted_buffers| contains the buffers that were deleted from this range, |
64 // starting at the buffer that had been at |next_buffer_index_|. | 68 // starting at the buffer that had been at |next_buffer_index_|. |
65 // |deleted_buffers| is empty if the buffer at |next_buffer_index_| was not | 69 // Returns true if the |next_buffer_index_| is reset. Note that this method |
66 // deleted. | 70 // may return true even if it does not add any buffers to |deleted_buffers|. |
67 void DeleteAfter(scoped_refptr<StreamParserBuffer> buffer, | 71 // This indicates that the range had not buffered |next_buffer_index_|, but |
68 BufferQueue* deleted_buffers); | 72 // a buffer at that position would have been deleted. |
73 bool TruncateAt(scoped_refptr<StreamParserBuffer> buffer, | |
74 BufferQueue* deleted_buffers); | |
69 // Deletes all buffers in range. | 75 // Deletes all buffers in range. |
70 void DeleteAll(BufferQueue* deleted_buffers); | 76 bool DeleteAll(BufferQueue* deleted_buffers); |
71 | 77 |
72 // Updates |out_buffer| with the next buffer in presentation order. Seek() | 78 // Updates |out_buffer| with the next buffer in presentation order. Seek() |
73 // must be called before calls to GetNextBuffer(), and buffers are returned | 79 // must be called before calls to GetNextBuffer(), and buffers are returned |
74 // in order from the last call to Seek(). Returns true if |out_buffer| is | 80 // in order from the last call to Seek(). Returns true if |out_buffer| is |
75 // filled with a valid buffer, false if there is not enough data to fulfill | 81 // filled with a valid buffer, false if there is not enough data to fulfill |
76 // the request. | 82 // the request. |
77 bool GetNextBuffer(scoped_refptr<StreamParserBuffer>* out_buffer); | 83 bool GetNextBuffer(scoped_refptr<StreamParserBuffer>* out_buffer); |
78 bool HasNextBuffer() const; | 84 bool HasNextBuffer() const; |
79 | 85 |
80 // Returns true if the range knows the position of the next buffer it should | 86 // Returns true if the range knows the position of the next buffer it should |
81 // return, i.e. it has been Seek()ed. This does not necessarily mean that it | 87 // return, i.e. it has been Seek()ed. This does not necessarily mean that it |
82 // has the next buffer yet. | 88 // has the next buffer yet. |
83 bool HasNextBufferPosition() const; | 89 bool HasNextBufferPosition() const; |
84 | 90 |
85 // Returns the timestamp of the next buffer that will be returned from | 91 // Returns the timestamp of the next buffer that will be returned from |
86 // GetNextBuffer(). This may be an approximation if the range does not have | 92 // GetNextBuffer(). This may be an approximation if the range does not have |
87 // next buffer buffered. | 93 // next buffer buffered. |
88 base::TimeDelta GetNextTimestamp() const; | 94 base::TimeDelta GetNextTimestamp() const; |
89 | 95 |
90 // Returns the start timestamp of the range. | 96 // Returns the start timestamp of the range. |
91 base::TimeDelta GetStartTimestamp() const; | 97 base::TimeDelta GetStartTimestamp() const; |
92 | 98 |
93 // Returns the end timestamp of the buffered data. (Note that this is equal to | 99 // Returns the end timestamp of the buffered data. |
94 // the last buffer's timestamp + its duration.) | |
95 base::TimeDelta GetEndTimestamp() const; | 100 base::TimeDelta GetEndTimestamp() const; |
96 | 101 |
97 // Returns whether a buffer with a starting timestamp of |timestamp| would | 102 // Returns whether a buffer with a starting timestamp of |timestamp| would |
98 // belong in this range. This includes a buffer that would be appended to | 103 // belong in this range. This includes a buffer that would be appended to |
99 // the end of the range. | 104 // the end of the range. |
100 bool BelongsToRange(base::TimeDelta timestamp) const; | 105 bool BelongsToRange(base::TimeDelta timestamp) const; |
101 | 106 |
102 // Returns true if the range has enough data to seek to the specified | 107 // Returns true if the range has enough data to seek to the specified |
103 // |timestamp|, false otherwise. | 108 // |timestamp|, false otherwise. |
104 bool CanSeekTo(base::TimeDelta timestamp) const; | 109 bool CanSeekTo(base::TimeDelta timestamp) const; |
105 | 110 |
106 // Returns true if this range's buffered timespan completely overlaps the | 111 // Returns true if this range's buffered timespan completely overlaps the |
107 // buffered timespan of |range|. | 112 // buffered timespan of |range|. |
108 bool CompletelyOverlaps(const SourceBufferRange& range) const; | 113 bool CompletelyOverlaps(const SourceBufferRange& range) const; |
109 | 114 |
110 // Returns true if the end of this range contains buffers that overlaps with | 115 // Returns true if the end of this range contains buffers that overlaps with |
111 // the beginning of |range|. | 116 // the beginning of |range|. |
112 bool EndOverlaps(const SourceBufferRange& range) const; | 117 bool EndOverlaps(const SourceBufferRange& range) const; |
113 | 118 |
119 // Returns true if |timestamp| is the timestamp of the next buffer in | |
120 // sequence after |buffer|, false otherwise. | |
121 bool IsNextInSequence( | |
122 const scoped_refptr<media::StreamParserBuffer>& buffer, | |
123 base::TimeDelta timestamp) const; | |
124 | |
125 // Returns the distance in time estimating how far from the beginning or end | |
126 // of this range a buffer can be to considered in the range. | |
127 base::TimeDelta GetFudgeRoom() const; | |
128 | |
114 private: | 129 private: |
115 // Helper method to delete buffers in |buffers_| starting from | 130 typedef std::map<base::TimeDelta, size_t> KeyframeMap; |
131 | |
132 // Seeks the range to the next keyframe after |timestamp|. If | |
133 // |skip_given_timestamp| is true, the seek will go to a keyframe with a | |
134 // timestamp strictly greater than |timestamp|. | |
135 void SeekAhead(base::TimeDelta timestamp, bool skip_given_timestamp); | |
136 KeyframeMap::iterator GetFirstKeyframeAfter( | |
137 base::TimeDelta timestamp, bool skip_given_timestamp); | |
138 | |
139 // Helper method to delete buffers in |buffers_| starting at | |
116 // |starting_point|, an iterator in |buffers_|. | 140 // |starting_point|, an iterator in |buffers_|. |
117 void DeleteAfter(const BufferQueue::iterator& starting_point, | 141 bool TruncateAt(const BufferQueue::iterator& starting_point, |
118 BufferQueue* deleted_buffers); | 142 BufferQueue* deleted_buffers); |
119 | 143 |
144 // Returns true if |timestamp| is the timestamp of the next buffer in | |
145 // sequence after |buffer|, false otherwise. | |
acolwell GONE FROM CHROMIUM
2012/07/02 17:12:33
? Is this supposed to be above the TruncateAt() de
vrk (LEFT CHROMIUM)
2012/07/04 02:50:18
Oops wow, not sure why this is here! (Was the comm
| |
120 // An ordered list of buffers in this range. | 146 // An ordered list of buffers in this range. |
121 BufferQueue buffers_; | 147 BufferQueue buffers_; |
122 | 148 |
123 // Maps keyframe timestamps to its index position in |buffers_|. | 149 // Maps keyframe timestamps to its index position in |buffers_|. |
124 typedef std::map<base::TimeDelta, size_t> KeyframeMap; | |
125 KeyframeMap keyframe_map_; | 150 KeyframeMap keyframe_map_; |
126 | 151 |
127 // Index into |buffers_| for the next buffer to be returned by | 152 // Index into |buffers_| for the next buffer to be returned by |
128 // GetNextBuffer(), set to -1 before Seek(). | 153 // GetNextBuffer(), set to -1 before Seek(). |
129 int next_buffer_index_; | 154 int next_buffer_index_; |
130 | 155 |
131 // True if the range needs to wait for the next keyframe to be appended before | 156 // True if the range needs to wait for the next keyframe to be appended before |
132 // returning buffers from GetNextBuffer(). | 157 // returning buffers from GetNextBuffer(). |
133 bool waiting_for_keyframe_; | 158 bool waiting_for_keyframe_; |
134 | 159 |
135 // If |waiting_for_keyframe_| is true, this range will wait for the next | 160 // If |waiting_for_keyframe_| is true, this range will wait for the next |
136 // keyframe with timestamp >= |next_keyframe_timestamp_|. | 161 // keyframe with timestamp >= |next_keyframe_timestamp_|. |
137 base::TimeDelta next_keyframe_timestamp_; | 162 base::TimeDelta next_keyframe_timestamp_; |
138 | 163 |
139 // If the first buffer in this range is the beginning of a media segment, | 164 // If the first buffer in this range is the beginning of a media segment, |
140 // |media_segment_start_time_| is the time when the media segment begins. | 165 // |media_segment_start_time_| is the time when the media segment begins. |
141 // |media_segment_start_time_| may be <= the timestamp of the first buffer in | 166 // |media_segment_start_time_| may be <= the timestamp of the first buffer in |
142 // |buffers_|. |media_segment_start_time_| is kNoTimestamp() if this range | 167 // |buffers_|. |media_segment_start_time_| is kNoTimestamp() if this range |
143 // does not start at the beginning of a media segment, which can only happen | 168 // does not start at the beginning of a media segment, which can only happen |
144 // garbage collection or after an end overlap that results in a split range | 169 // garbage collection or after an end overlap that results in a split range |
145 // (we don't have a way of knowing the media segment timestamp for the new | 170 // (we don't have a way of knowing the media segment timestamp for the new |
146 // range). | 171 // range). |
147 base::TimeDelta media_segment_start_time_; | 172 base::TimeDelta media_segment_start_time_; |
148 | 173 |
174 // Stores the largest distance between two adjacent buffers in this range. | |
175 base::TimeDelta max_interbuffer_distance_; | |
acolwell GONE FROM CHROMIUM
2012/07/02 17:12:33
Do we really want to keep track of this on a per-S
vrk (LEFT CHROMIUM)
2012/07/04 02:50:18
Moved to SourceBufferStream and added a callback f
| |
176 | |
149 DISALLOW_COPY_AND_ASSIGN(SourceBufferRange); | 177 DISALLOW_COPY_AND_ASSIGN(SourceBufferRange); |
150 }; | 178 }; |
151 | 179 |
152 } // namespace media | 180 } // namespace media |
153 | 181 |
154 // Helper method that returns true if |ranges| is sorted in increasing order, | 182 // Helper method that returns true if |ranges| is sorted in increasing order, |
155 // false otherwise. | 183 // false otherwise. |
156 static bool IsRangeListSorted( | 184 static bool IsRangeListSorted( |
157 const std::list<media::SourceBufferRange*>& ranges) { | 185 const std::list<media::SourceBufferRange*>& ranges) { |
158 base::TimeDelta prev = media::kNoTimestamp(); | 186 base::TimeDelta prev = media::kNoTimestamp(); |
159 for (std::list<media::SourceBufferRange*>::const_iterator itr = | 187 for (std::list<media::SourceBufferRange*>::const_iterator itr = |
160 ranges.begin(); itr != ranges.end(); itr++) { | 188 ranges.begin(); itr != ranges.end(); ++itr) { |
161 if (prev != media::kNoTimestamp() && prev >= (*itr)->GetStartTimestamp()) | 189 if (prev != media::kNoTimestamp() && prev >= (*itr)->GetStartTimestamp()) |
162 return false; | 190 return false; |
163 prev = (*itr)->GetEndTimestamp(); | 191 prev = (*itr)->GetEndTimestamp(); |
164 } | 192 } |
165 return true; | 193 return true; |
166 } | 194 } |
167 | 195 |
168 // Comparison function for two Buffers based on timestamp. | 196 // Comparison function for two Buffers based on timestamp. |
169 static bool BufferComparator( | 197 static bool BufferComparator( |
170 const scoped_refptr<media::StreamParserBuffer>& first, | 198 const scoped_refptr<media::StreamParserBuffer>& first, |
171 const scoped_refptr<media::StreamParserBuffer>& second) { | 199 const scoped_refptr<media::StreamParserBuffer>& second) { |
172 return first->GetTimestamp() < second->GetTimestamp(); | 200 return first->GetTimestamp() < second->GetTimestamp(); |
173 } | 201 } |
174 | 202 |
175 // Returns the upper bound for the starting timestamp for the next buffer | |
176 // in sequence after |buffer|. Assumes |buffer|'s timestamp and | |
177 // duration are valid. | |
178 static base::TimeDelta MaxNextTimestamp( | |
179 const scoped_refptr<media::StreamParserBuffer>& buffer) { | |
180 // Because we do not know exactly when is the next timestamp, any buffer | |
181 // that starts within 1/3 of the duration past the end of this buffer | |
182 // is considered the next buffer in the sequence. | |
183 return buffer->GetEndTimestamp() + buffer->GetDuration() / 3; | |
184 } | |
185 | |
186 // Returns true if |timestamp| is the timestamp of the next buffer in | |
187 // sequence after |buffer|, false otherwise. | |
188 static bool IsNextInSequence( | |
189 const scoped_refptr<media::StreamParserBuffer>& buffer, | |
190 base::TimeDelta timestamp) { | |
191 return timestamp >= buffer->GetEndTimestamp() && | |
192 timestamp <= MaxNextTimestamp(buffer); | |
193 } | |
194 | |
195 namespace media { | 203 namespace media { |
196 | 204 |
197 SourceBufferStream::SourceBufferStream() | 205 SourceBufferStream::SourceBufferStream() |
vrk (LEFT CHROMIUM)
2012/07/04 02:50:18
FYI: Also deleted this constructor; it was only be
| |
198 : seek_pending_(false), | 206 : seek_pending_(false), |
199 seek_buffer_timestamp_(base::TimeDelta()), | 207 seek_buffer_timestamp_(kNoTimestamp()), |
200 selected_range_(NULL), | 208 selected_range_(NULL), |
201 end_of_stream_(false) { | 209 end_of_stream_(false), |
210 deleted_next_buffer_(false), | |
211 media_segment_start_time_(kNoTimestamp()), | |
212 range_for_next_append_(ranges_.end()) { | |
202 } | 213 } |
203 | 214 |
204 SourceBufferStream::SourceBufferStream(const AudioDecoderConfig& audio_config) | 215 SourceBufferStream::SourceBufferStream(const AudioDecoderConfig& audio_config) |
205 : seek_pending_(false), | 216 : seek_pending_(false), |
206 seek_buffer_timestamp_(base::TimeDelta()), | 217 seek_buffer_timestamp_(kNoTimestamp()), |
207 selected_range_(NULL), | 218 selected_range_(NULL), |
208 end_of_stream_(false) { | 219 end_of_stream_(false), |
220 deleted_next_buffer_(false), | |
221 media_segment_start_time_(kNoTimestamp()), | |
222 range_for_next_append_(ranges_.end()) { | |
209 audio_config_.CopyFrom(audio_config); | 223 audio_config_.CopyFrom(audio_config); |
210 } | 224 } |
211 | 225 |
212 SourceBufferStream::SourceBufferStream(const VideoDecoderConfig& video_config) | 226 SourceBufferStream::SourceBufferStream(const VideoDecoderConfig& video_config) |
213 : seek_pending_(false), | 227 : seek_pending_(false), |
214 seek_buffer_timestamp_(base::TimeDelta()), | 228 seek_buffer_timestamp_(kNoTimestamp()), |
215 selected_range_(NULL), | 229 selected_range_(NULL), |
216 end_of_stream_(false) { | 230 end_of_stream_(false), |
231 deleted_next_buffer_(false), | |
232 media_segment_start_time_(kNoTimestamp()), | |
233 range_for_next_append_(ranges_.end()) { | |
217 video_config_.CopyFrom(video_config); | 234 video_config_.CopyFrom(video_config); |
218 } | 235 } |
219 | 236 |
220 SourceBufferStream::~SourceBufferStream() { | 237 SourceBufferStream::~SourceBufferStream() { |
221 while (!ranges_.empty()) { | 238 while (!ranges_.empty()) { |
222 delete ranges_.front(); | 239 delete ranges_.front(); |
223 ranges_.pop_front(); | 240 ranges_.pop_front(); |
224 } | 241 } |
225 } | 242 } |
226 | 243 |
244 void SourceBufferStream::OnNewMediaSegment( | |
245 base::TimeDelta media_segment_start_time) { | |
246 media_segment_start_time_ = media_segment_start_time; | |
247 range_for_next_append_ = ranges_.end(); | |
248 } | |
249 | |
227 bool SourceBufferStream::Append( | 250 bool SourceBufferStream::Append( |
228 const SourceBufferStream::BufferQueue& buffers, | 251 const SourceBufferStream::BufferQueue& buffers) { |
229 base::TimeDelta media_segment_start_time) { | |
230 DCHECK(!buffers.empty()); | 252 DCHECK(!buffers.empty()); |
231 DCHECK(media_segment_start_time != kNoTimestamp()); | 253 DCHECK(media_segment_start_time_ != kNoTimestamp()); |
232 | 254 |
233 // Find a range into which we'll append |buffers|. | 255 // Save a snapshot of the |next_buffer_timestamp| before range modifications |
234 RangeList::iterator range_for_new_buffers = FindExistingRangeFor(buffers); | 256 // are made. |
257 base::TimeDelta next_buffer_timestamp = GetNextBufferTimestamp(); | |
258 | |
259 // Find a range into which we'll append |buffers|. Use the last range if a new | |
260 // media segment hasn't been signalled since the last Append() call. | |
261 RangeList::iterator range_for_new_buffers = range_for_next_append_; | |
262 if (range_for_next_append_ == ranges_.end()) | |
263 range_for_new_buffers = FindExistingRangeFor(buffers); | |
acolwell GONE FROM CHROMIUM
2012/07/02 17:12:33
Could this line be moved to OnNewMediaSegment() an
vrk (LEFT CHROMIUM)
2012/07/04 02:50:18
Good idea! Done.
| |
235 | 264 |
236 // If there's a range for |buffers|, insert |buffers| accordingly. Otherwise, | 265 // If there's a range for |buffers|, insert |buffers| accordingly. Otherwise, |
237 // create a new range with |buffers|. | 266 // create a new range with |buffers|. |
238 if (range_for_new_buffers != ranges_.end()) { | 267 if (range_for_new_buffers != ranges_.end()) { |
239 InsertIntoExistingRange(range_for_new_buffers, buffers); | 268 InsertIntoExistingRange(range_for_new_buffers, buffers); |
240 } else { | 269 } else { |
241 // Ranges must begin with a keyframe. | 270 // Ranges must begin with a keyframe. |
242 if (!buffers.front()->IsKeyframe()) | 271 if (!buffers.front()->IsKeyframe()) |
243 return false; | 272 return false; |
244 range_for_new_buffers = | 273 range_for_new_buffers = |
245 AddToRanges(new SourceBufferRange(buffers, media_segment_start_time)); | 274 AddToRanges(new SourceBufferRange(buffers, media_segment_start_time_)); |
246 } | 275 } |
247 | 276 |
277 range_for_next_append_ = range_for_new_buffers; | |
278 | |
248 // Resolve overlaps. | 279 // Resolve overlaps. |
249 ResolveCompleteOverlaps(range_for_new_buffers); | 280 ResolveCompleteOverlaps(range_for_new_buffers); |
250 ResolveEndOverlap(range_for_new_buffers); | 281 ResolveEndOverlap(range_for_new_buffers); |
251 MergeWithAdjacentRangeIfNecessary(range_for_new_buffers); | 282 MergeWithAdjacentRangeIfNecessary(range_for_new_buffers); |
252 | 283 |
253 // If these were the first buffers appended to the stream, seek to the | 284 // If these were the first buffers appended to the stream, seek to the |
254 // beginning of the range. | 285 // beginning of the range. |
255 // TODO(vrk): This should be done by ChunkDemuxer. (crbug.com/132815) | 286 // TODO(vrk): This should be done by ChunkDemuxer. (crbug.com/132815) |
256 if (!seek_pending_ && !selected_range_) { | 287 if (!seek_pending_ && !selected_range_) { |
257 selected_range_ = *range_for_new_buffers; | 288 selected_range_ = *range_for_new_buffers; |
258 selected_range_->Seek(buffers.front()->GetTimestamp()); | 289 selected_range_->Seek(buffers.front()->GetTimestamp()); |
259 } | 290 } |
260 | 291 |
261 // Finally, try to complete pending seek if one exists. | 292 // Seek to try to fulfill a previous call to Seek(). |
262 if (seek_pending_) | 293 if (seek_pending_) { |
294 DCHECK(!selected_range_); | |
295 DCHECK(!deleted_next_buffer_); | |
263 Seek(seek_buffer_timestamp_); | 296 Seek(seek_buffer_timestamp_); |
297 } | |
264 | 298 |
299 // Seek because the Append() has deleted the buffer that would have been | |
300 // returned in the next call to GetNextBuffer(). | |
301 if (deleted_next_buffer_) { | |
acolwell GONE FROM CHROMIUM
2012/07/02 17:12:33
I'm not thrilled about deleted_next_buffer_ & dele
vrk (LEFT CHROMIUM)
2012/07/04 02:50:18
Yeah, I knew it was a wrong thing to do but was th
| |
302 DCHECK(!seek_pending_); | |
303 selected_range_ = *range_for_new_buffers; | |
304 if (!deleted_buffers_.empty()) { | |
305 // Seek the range to the keyframe at or after |next_buffer_timestamp|. | |
306 selected_range_->SeekAheadTo(next_buffer_timestamp); | |
307 } else { | |
308 // If we've deleted the next buffer but |deleted_buffers_| is empty, | |
309 // that means |next_buffer_timestamp| represents the time we need to | |
310 // seek past (i.e. the keyframe timestamp needs to be strictly greater | |
311 // than |next_buffer_timestamp|). | |
312 selected_range_->SeekAheadPast(next_buffer_timestamp); | |
313 } | |
314 UpdateTrackBuffer(); | |
315 deleted_buffers_.clear(); | |
316 deleted_next_buffer_ = false; | |
317 } | |
318 | |
319 DCHECK(!deleted_next_buffer_); | |
265 DCHECK(IsRangeListSorted(ranges_)); | 320 DCHECK(IsRangeListSorted(ranges_)); |
266 return true; | 321 return true; |
267 } | 322 } |
268 | 323 |
269 void SourceBufferStream::InsertIntoExistingRange( | 324 void SourceBufferStream::InsertIntoExistingRange( |
270 const RangeList::iterator& range_for_new_buffers_itr, | 325 const RangeList::iterator& range_for_new_buffers_itr, |
271 const BufferQueue& new_buffers) { | 326 const BufferQueue& new_buffers) { |
272 SourceBufferRange* range_for_new_buffers = *range_for_new_buffers_itr; | 327 SourceBufferRange* range_for_new_buffers = *range_for_new_buffers_itr; |
273 | 328 |
274 // If this is a simple case where we can just append to the end of the range, | 329 // If this is a simple case where we can just append to the end of the range, |
275 // do so and return. | 330 // do so and return. |
276 if (range_for_new_buffers->CanAppendToEnd(new_buffers)) { | 331 if (range_for_new_buffers->CanAppendToEnd(new_buffers)) { |
277 range_for_new_buffers->AppendToEnd(new_buffers); | 332 range_for_new_buffers->AppendToEnd(new_buffers); |
278 return; | 333 return; |
279 } | 334 } |
280 | 335 |
281 // Otherwise, this is either a start overlap or an middle overlap. | 336 // Otherwise, this is either a start overlap or an middle overlap. |
282 | 337 |
283 // In case this is a middle overlap, save the buffers that come after the end | 338 // In case this is a middle overlap, save the buffers that come after the end |
284 // of |new_buffers|, and add them into a new range. | 339 // of |new_buffers|, and add them into a new range. |
285 base::TimeDelta next_buffer_timestamp = GetNextBufferTimestamp(); | |
286 bool had_next_buffer = range_for_new_buffers->HasNextBuffer(); | |
287 SourceBufferRange* new_next_range = | 340 SourceBufferRange* new_next_range = |
288 range_for_new_buffers->SplitRange(new_buffers.back()->GetEndTimestamp()); | 341 range_for_new_buffers->SplitRange(new_buffers.back()->GetTimestamp()); |
289 | 342 |
290 if (new_next_range) | 343 if (new_next_range) |
291 AddToRanges(new_next_range); | 344 AddToRanges(new_next_range); |
292 | 345 |
293 // Delete the buffers that are overlapped by |new_buffers|, then append | 346 // Delete the buffers that are overlapped by |new_buffers|, then append |
294 // |new_buffers| to the end of the range. | 347 // |new_buffers| to the end of the range. |
295 BufferQueue deleted_buffers; | 348 bool deleted_next_buffer = |
296 range_for_new_buffers->DeleteAfter(new_buffers.front(), &deleted_buffers); | 349 range_for_new_buffers->TruncateAt(new_buffers.front(), &deleted_buffers_); |
297 range_for_new_buffers->AppendToEnd(new_buffers); | 350 range_for_new_buffers->AppendToEnd(new_buffers); |
298 | 351 |
299 // If |new_buffers| doesn't overlap the selected range, no need to do anything | |
300 // more. | |
301 if (selected_range_ != range_for_new_buffers || !had_next_buffer || | |
302 next_buffer_timestamp < new_buffers.front()->GetTimestamp()) { | |
303 return; | |
304 } | |
305 | |
306 // If this was a middle overlap resulting in a new range, and the next buffer | 352 // If this was a middle overlap resulting in a new range, and the next buffer |
307 // position has been transferred to the newly created range, update the | 353 // position has been transferred to the newly created range, update the |
308 // |selected_range_| accordingly. | 354 // |selected_range_| accordingly. |
309 if (new_next_range && new_next_range->HasNextBufferPosition()) { | 355 if (new_next_range && new_next_range->HasNextBufferPosition()) { |
310 DCHECK(!range_for_new_buffers->HasNextBufferPosition()); | 356 DCHECK(!range_for_new_buffers->HasNextBufferPosition()); |
357 DCHECK(!deleted_next_buffer); | |
311 selected_range_ = new_next_range; | 358 selected_range_ = new_next_range; |
312 return; | |
313 } | 359 } |
314 | 360 |
315 selected_range_ = range_for_new_buffers; | 361 DCHECK(!deleted_next_buffer_); |
316 selected_range_->SeekAfter(next_buffer_timestamp); | 362 deleted_next_buffer_ = deleted_next_buffer; |
317 UpdateTrackBuffer(deleted_buffers); | |
318 } | 363 } |
319 | 364 |
320 void SourceBufferStream::ResolveCompleteOverlaps( | 365 void SourceBufferStream::ResolveCompleteOverlaps( |
321 const RangeList::iterator& range_with_new_buffers_itr) { | 366 const RangeList::iterator& range_with_new_buffers_itr) { |
322 SourceBufferRange* range_with_new_buffers = *range_with_new_buffers_itr; | 367 SourceBufferRange* range_with_new_buffers = *range_with_new_buffers_itr; |
323 RangeList::iterator next_range_itr = range_with_new_buffers_itr; | 368 RangeList::iterator next_range_itr = range_with_new_buffers_itr; |
324 next_range_itr++; | 369 next_range_itr++; |
325 base::TimeDelta next_buffer_timestamp = GetNextBufferTimestamp(); | |
326 | 370 |
327 while (next_range_itr != ranges_.end() && | 371 while (next_range_itr != ranges_.end() && |
328 range_with_new_buffers->CompletelyOverlaps(**next_range_itr)) { | 372 range_with_new_buffers->CompletelyOverlaps(**next_range_itr)) { |
329 if (*next_range_itr == selected_range_) { | 373 if (*next_range_itr == selected_range_) { |
330 // Transfer the next buffer position from the old selected range to the | 374 selected_range_ = NULL; |
331 // range with the new buffers. | 375 bool deleted_next_buffer = |
332 selected_range_ = range_with_new_buffers; | 376 (*next_range_itr)->DeleteAll(&deleted_buffers_); |
333 selected_range_->SeekAfter(next_buffer_timestamp); | 377 DCHECK(deleted_next_buffer); |
334 | 378 DCHECK(!deleted_next_buffer_); |
335 // Delete everything from the old selected range and save the next | 379 deleted_next_buffer_ = true; |
336 // buffers. | |
337 BufferQueue deleted_buffers; | |
338 (*next_range_itr)->DeleteAll(&deleted_buffers); | |
339 UpdateTrackBuffer(deleted_buffers); | |
340 } | 380 } |
341 delete *next_range_itr; | 381 delete *next_range_itr; |
342 next_range_itr = ranges_.erase(next_range_itr); | 382 next_range_itr = ranges_.erase(next_range_itr); |
343 } | 383 } |
344 } | 384 } |
345 | 385 |
346 void SourceBufferStream::ResolveEndOverlap( | 386 void SourceBufferStream::ResolveEndOverlap( |
347 const RangeList::iterator& range_with_new_buffers_itr) { | 387 const RangeList::iterator& range_with_new_buffers_itr) { |
348 SourceBufferRange* range_with_new_buffers = *range_with_new_buffers_itr; | 388 SourceBufferRange* range_with_new_buffers = *range_with_new_buffers_itr; |
349 RangeList::iterator next_range_itr = range_with_new_buffers_itr; | 389 RangeList::iterator next_range_itr = range_with_new_buffers_itr; |
350 next_range_itr++; | 390 next_range_itr++; |
351 base::TimeDelta next_buffer_timestamp = GetNextBufferTimestamp(); | |
352 | 391 |
353 if (next_range_itr == ranges_.end() || | 392 if (next_range_itr == ranges_.end() || |
354 !range_with_new_buffers->EndOverlaps(**next_range_itr)) { | 393 !range_with_new_buffers->EndOverlaps(**next_range_itr)) { |
355 return; | 394 return; |
356 } | 395 } |
357 | 396 |
358 // Split the overlapped range after |range_with_new_buffers|'s last buffer | 397 // Split the overlapped range after |range_with_new_buffers|'s last buffer |
359 // overlaps. Now |overlapped_range| contains only the buffers that do not | 398 // overlaps. Now |overlapped_range| contains only the buffers that do not |
360 // belong in |ranges_| anymore, and |new_next_range| contains buffers that | 399 // belong in |ranges_| anymore, and |new_next_range| contains buffers that |
361 // go after |range_with_new_buffers| (without overlap). | 400 // go after |range_with_new_buffers| (without overlap). |
(...skipping 12 matching lines...) Expand all Loading... | |
374 return; | 413 return; |
375 | 414 |
376 // If the |overlapped_range| transfers its next buffer position to | 415 // If the |overlapped_range| transfers its next buffer position to |
377 // |new_next_range|, make |new_next_range| the |selected_range_|. | 416 // |new_next_range|, make |new_next_range| the |selected_range_|. |
378 if (new_next_range && new_next_range->HasNextBufferPosition()) { | 417 if (new_next_range && new_next_range->HasNextBufferPosition()) { |
379 DCHECK(!overlapped_range->HasNextBufferPosition()); | 418 DCHECK(!overlapped_range->HasNextBufferPosition()); |
380 selected_range_ = new_next_range; | 419 selected_range_ = new_next_range; |
381 return; | 420 return; |
382 } | 421 } |
383 | 422 |
384 // Transfer the next buffer position from the old range to the range with | 423 // Save the buffers in |overlapped_range|. |
385 // the new buffers. | 424 bool deleted_next_buffer = overlapped_range->DeleteAll(&deleted_buffers_); |
386 selected_range_ = range_with_new_buffers; | 425 DCHECK(deleted_next_buffer); |
387 selected_range_->SeekAfter(next_buffer_timestamp); | |
388 | 426 |
389 // Update track buffer with overlapped buffers. | 427 // If we end-overlap the |selected_range_|, the next buffer is either |
390 BufferQueue deleted_buffers; | 428 // in |new_next_range| or |deleted_buffers_|. Because we've already returned |
391 scoped_refptr<StreamParserBuffer> buffer; | 429 // early in the former case, we set |deleted_next_buffer_| to true. |
392 while (overlapped_range->GetNextBuffer(&buffer)) { | 430 DCHECK(!deleted_next_buffer_); |
393 deleted_buffers.push_back(buffer); | 431 deleted_next_buffer_ = true; |
394 } | |
395 UpdateTrackBuffer(deleted_buffers); | |
396 } | 432 } |
397 | 433 |
398 void SourceBufferStream::UpdateTrackBuffer(const BufferQueue& deleted_buffers) { | 434 void SourceBufferStream::UpdateTrackBuffer() { |
399 if (!track_buffer_.empty() || deleted_buffers.empty()) | 435 if (!track_buffer_.empty() || deleted_buffers_.empty()) |
400 return; | 436 return; |
401 | 437 |
402 DCHECK(selected_range_); | 438 DCHECK(selected_range_); |
403 DCHECK(selected_range_->HasNextBufferPosition()); | 439 DCHECK(selected_range_->HasNextBufferPosition()); |
404 | 440 |
405 base::TimeDelta next_keyframe_timestamp = selected_range_->GetNextTimestamp(); | 441 base::TimeDelta next_keyframe_timestamp = selected_range_->GetNextTimestamp(); |
406 | 442 |
407 // If there is no gap between what was deleted and what was added, nothing | 443 // If there is no gap between what was deleted and what was added, nothing |
408 // should be added to the track buffer. | 444 // should be added to the track buffer. |
409 if (selected_range_->HasNextBuffer() && | 445 if (selected_range_->HasNextBuffer() && |
410 next_keyframe_timestamp == deleted_buffers.front()->GetTimestamp()) { | 446 next_keyframe_timestamp == deleted_buffers_.front()->GetTimestamp()) { |
411 return; | 447 return; |
412 } | 448 } |
413 | 449 |
414 DCHECK(next_keyframe_timestamp >= deleted_buffers.front()->GetTimestamp()); | 450 DCHECK(next_keyframe_timestamp >= deleted_buffers_.front()->GetTimestamp()); |
415 | 451 |
416 // If the |selected_range_| is ready to return data, fill the track buffer | 452 // If the |selected_range_| is ready to return data, fill the track buffer |
417 // with all buffers that come before |next_keyframe_timestamp| and return. | 453 // with all buffers that come before |next_keyframe_timestamp| and return. |
418 if (selected_range_->HasNextBuffer()) { | 454 if (selected_range_->HasNextBuffer()) { |
419 for (BufferQueue::const_iterator itr = deleted_buffers.begin(); | 455 for (BufferQueue::const_iterator itr = deleted_buffers_.begin(); |
420 itr != deleted_buffers.end() && | 456 itr != deleted_buffers_.end() && |
421 (*itr)->GetTimestamp() < next_keyframe_timestamp; ++itr) { | 457 (*itr)->GetTimestamp() < next_keyframe_timestamp; ++itr) { |
422 track_buffer_.push_back(*itr); | 458 track_buffer_.push_back(*itr); |
423 } | 459 } |
424 return; | 460 return; |
425 } | 461 } |
426 | 462 |
427 // Otherwise, the |selected_range_| is not ready to return data, so add all | 463 // Otherwise, the |selected_range_| is not ready to return data, so add all |
428 // the deleted buffers into the |track_buffer_|. | 464 // the deleted buffers into the |track_buffer_|. |
429 track_buffer_ = deleted_buffers; | 465 track_buffer_.swap(deleted_buffers_); |
430 | 466 |
431 // See if the next range contains the keyframe after the end of the | 467 // See if the next range contains the keyframe after the end of the |
432 // |track_buffer_|, and if so, change |selected_range_|. | 468 // |track_buffer_|, and if so, change |selected_range_|. |
433 RangeList::iterator next_range_itr = ++(GetSelectedRangeItr()); | 469 RangeList::iterator next_range_itr = ++(GetSelectedRangeItr()); |
434 if (next_range_itr != ranges_.end()) { | 470 if (next_range_itr != ranges_.end()) { |
435 (*next_range_itr)->SeekAfter(track_buffer_.back()->GetEndTimestamp()); | 471 (*next_range_itr)->SeekAheadPast(track_buffer_.back()->GetTimestamp()); |
436 if ((*next_range_itr)->HasNextBuffer() && | 472 if ((*next_range_itr)->HasNextBuffer() && |
437 IsNextInSequence(track_buffer_.back(), | 473 selected_range_->IsNextInSequence( |
438 (*next_range_itr)->GetNextTimestamp())) { | 474 track_buffer_.back(), (*next_range_itr)->GetNextTimestamp())) { |
439 selected_range_ = *next_range_itr; | 475 selected_range_ = *next_range_itr; |
440 } | 476 } |
441 } | 477 } |
442 } | 478 } |
443 | 479 |
444 void SourceBufferStream::MergeWithAdjacentRangeIfNecessary( | 480 void SourceBufferStream::MergeWithAdjacentRangeIfNecessary( |
445 const RangeList::iterator& range_with_new_buffers_itr) { | 481 const RangeList::iterator& range_with_new_buffers_itr) { |
446 SourceBufferRange* range_with_new_buffers = *range_with_new_buffers_itr; | 482 SourceBufferRange* range_with_new_buffers = *range_with_new_buffers_itr; |
447 RangeList::iterator next_range_itr = range_with_new_buffers_itr; | 483 RangeList::iterator next_range_itr = range_with_new_buffers_itr; |
448 next_range_itr++; | 484 next_range_itr++; |
449 | 485 |
450 if (next_range_itr != ranges_.end() && | 486 if (next_range_itr != ranges_.end() && |
451 range_with_new_buffers->CanAppendToEnd(**next_range_itr)) { | 487 range_with_new_buffers->CanAppendToEnd(**next_range_itr)) { |
452 bool transfer_current_position = selected_range_ == *next_range_itr; | 488 bool transfer_current_position = selected_range_ == *next_range_itr; |
453 range_with_new_buffers->AppendToEnd(**next_range_itr, | 489 range_with_new_buffers->AppendToEnd(**next_range_itr, |
454 transfer_current_position); | 490 transfer_current_position); |
455 // Update |selected_range_| pointer if |range| has become selected after | 491 // Update |selected_range_| pointer if |range| has become selected after |
456 // merges. | 492 // merges. |
457 if (transfer_current_position) | 493 if (transfer_current_position) |
458 selected_range_ = range_with_new_buffers; | 494 selected_range_ = range_with_new_buffers; |
459 | 495 |
460 delete *next_range_itr; | 496 delete *next_range_itr; |
461 ranges_.erase(next_range_itr); | 497 ranges_.erase(next_range_itr); |
462 } | 498 } |
463 } | 499 } |
464 | 500 |
465 void SourceBufferStream::Seek(base::TimeDelta timestamp) { | 501 void SourceBufferStream::Seek(base::TimeDelta timestamp) { |
502 DCHECK(!deleted_next_buffer_); | |
503 | |
466 selected_range_ = NULL; | 504 selected_range_ = NULL; |
467 track_buffer_.clear(); | 505 track_buffer_.clear(); |
468 | 506 |
469 seek_buffer_timestamp_ = timestamp; | 507 seek_buffer_timestamp_ = timestamp; |
470 seek_pending_ = true; | 508 seek_pending_ = true; |
471 | 509 |
472 RangeList::iterator itr = ranges_.end(); | 510 RangeList::iterator itr = ranges_.end(); |
473 for (itr = ranges_.begin(); itr != ranges_.end(); itr++) { | 511 for (itr = ranges_.begin(); itr != ranges_.end(); itr++) { |
474 if ((*itr)->CanSeekTo(timestamp)) | 512 if ((*itr)->CanSeekTo(timestamp)) |
475 break; | 513 break; |
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
563 | 601 |
564 bool SourceBufferStream::CanEndOfStream() const { | 602 bool SourceBufferStream::CanEndOfStream() const { |
565 return ranges_.empty() || selected_range_ == ranges_.back(); | 603 return ranges_.empty() || selected_range_ == ranges_.back(); |
566 } | 604 } |
567 | 605 |
568 SourceBufferRange::SourceBufferRange(const BufferQueue& new_buffers, | 606 SourceBufferRange::SourceBufferRange(const BufferQueue& new_buffers, |
569 base::TimeDelta media_segment_start_time) | 607 base::TimeDelta media_segment_start_time) |
570 : next_buffer_index_(-1), | 608 : next_buffer_index_(-1), |
571 waiting_for_keyframe_(false), | 609 waiting_for_keyframe_(false), |
572 next_keyframe_timestamp_(kNoTimestamp()), | 610 next_keyframe_timestamp_(kNoTimestamp()), |
573 media_segment_start_time_(media_segment_start_time) { | 611 media_segment_start_time_(media_segment_start_time), |
612 max_interbuffer_distance_(kNoTimestamp()) { | |
574 DCHECK(!new_buffers.empty()); | 613 DCHECK(!new_buffers.empty()); |
575 DCHECK(new_buffers.front()->IsKeyframe()); | 614 DCHECK(new_buffers.front()->IsKeyframe()); |
576 AppendToEnd(new_buffers); | 615 AppendToEnd(new_buffers); |
577 } | 616 } |
578 | 617 |
579 void SourceBufferRange::AppendToEnd(const BufferQueue& new_buffers) { | 618 void SourceBufferRange::AppendToEnd(const BufferQueue& new_buffers) { |
619 DCHECK(!new_buffers.empty()); | |
620 base::TimeDelta prev_timestamp = kNoTimestamp(); | |
621 if (!buffers_.empty()) | |
622 prev_timestamp = buffers_.back()->GetTimestamp(); | |
623 | |
580 for (BufferQueue::const_iterator itr = new_buffers.begin(); | 624 for (BufferQueue::const_iterator itr = new_buffers.begin(); |
581 itr != new_buffers.end(); itr++) { | 625 itr != new_buffers.end(); itr++) { |
582 DCHECK((*itr)->GetDuration() > base::TimeDelta()); | 626 base::TimeDelta current_timestamp = (*itr)->GetTimestamp(); |
583 DCHECK((*itr)->GetTimestamp() != kNoTimestamp()); | 627 DCHECK(current_timestamp != kNoTimestamp()); |
584 buffers_.push_back(*itr); | 628 buffers_.push_back(*itr); |
629 | |
630 // Save the max interbuffer distance seen in the range. | |
631 if (prev_timestamp != kNoTimestamp()) { | |
632 base::TimeDelta interbuffer_distance = current_timestamp - prev_timestamp; | |
633 if (max_interbuffer_distance_ == kNoTimestamp()) { | |
634 max_interbuffer_distance_ = interbuffer_distance; | |
635 } else { | |
636 max_interbuffer_distance_ = | |
637 std::max(max_interbuffer_distance_, interbuffer_distance); | |
638 } | |
639 } | |
640 prev_timestamp = current_timestamp; | |
641 | |
642 // Update keyframe index with new entry if applicable. | |
585 if ((*itr)->IsKeyframe()) { | 643 if ((*itr)->IsKeyframe()) { |
586 keyframe_map_.insert( | 644 keyframe_map_.insert( |
587 std::make_pair((*itr)->GetTimestamp(), buffers_.size() - 1)); | 645 std::make_pair((*itr)->GetTimestamp(), buffers_.size() - 1)); |
588 | 646 |
589 if (waiting_for_keyframe_ && | 647 if (waiting_for_keyframe_ && |
590 (*itr)->GetTimestamp() >= next_keyframe_timestamp_) { | 648 (*itr)->GetTimestamp() >= next_keyframe_timestamp_) { |
591 next_buffer_index_ = buffers_.size() - 1; | 649 next_buffer_index_ = buffers_.size() - 1; |
592 next_keyframe_timestamp_ = base::TimeDelta(); | 650 next_keyframe_timestamp_ = base::TimeDelta(); |
593 waiting_for_keyframe_ = false; | 651 waiting_for_keyframe_ = false; |
594 } | 652 } |
(...skipping 13 matching lines...) Expand all Loading... | |
608 // previous element if it did not return the element exactly equal to | 666 // previous element if it did not return the element exactly equal to |
609 // |timestamp|. | 667 // |timestamp|. |
610 if (result != keyframe_map_.begin() && | 668 if (result != keyframe_map_.begin() && |
611 (result == keyframe_map_.end() || result->first != timestamp)) { | 669 (result == keyframe_map_.end() || result->first != timestamp)) { |
612 result--; | 670 result--; |
613 } | 671 } |
614 next_buffer_index_ = result->second; | 672 next_buffer_index_ = result->second; |
615 DCHECK_LT(next_buffer_index_, static_cast<int>(buffers_.size())); | 673 DCHECK_LT(next_buffer_index_, static_cast<int>(buffers_.size())); |
616 } | 674 } |
617 | 675 |
618 void SourceBufferRange::SeekAfter(base::TimeDelta timestamp) { | 676 void SourceBufferRange::SeekAheadTo(base::TimeDelta timestamp) { |
677 SeekAhead(timestamp, false); | |
678 } | |
679 | |
680 void SourceBufferRange::SeekAheadPast(base::TimeDelta timestamp) { | |
681 SeekAhead(timestamp, true); | |
682 } | |
683 | |
684 void SourceBufferRange::SeekAhead(base::TimeDelta timestamp, | |
685 bool skip_given_timestamp) { | |
619 DCHECK(!keyframe_map_.empty()); | 686 DCHECK(!keyframe_map_.empty()); |
620 | 687 |
621 // lower_bound() returns the first element >= |timestamp|, so |result| is the | 688 KeyframeMap::iterator result = |
622 // value that we want. | 689 GetFirstKeyframeAfter(timestamp, skip_given_timestamp); |
623 KeyframeMap::iterator result = keyframe_map_.lower_bound(timestamp); | |
624 | 690 |
625 // If there isn't a keyframe after |timestamp|, then seek to end and return | 691 // If there isn't a keyframe after |timestamp|, then seek to end and return |
626 // kNoTimestamp to signal such. | 692 // kNoTimestamp to signal such. |
627 if (result == keyframe_map_.end()) { | 693 if (result == keyframe_map_.end()) { |
628 waiting_for_keyframe_ = true; | 694 waiting_for_keyframe_ = true; |
629 next_buffer_index_ = -1; | 695 next_buffer_index_ = -1; |
630 next_keyframe_timestamp_ = timestamp; | 696 next_keyframe_timestamp_ = timestamp; |
631 return; | 697 return; |
632 } | 698 } |
633 | |
634 next_buffer_index_ = result->second; | 699 next_buffer_index_ = result->second; |
635 DCHECK_LT(next_buffer_index_, static_cast<int>(buffers_.size())); | 700 DCHECK_LT(next_buffer_index_, static_cast<int>(buffers_.size())); |
636 } | 701 } |
637 | 702 |
638 SourceBufferRange* SourceBufferRange::SplitRange(base::TimeDelta timestamp) { | 703 SourceBufferRange* SourceBufferRange::SplitRange(base::TimeDelta timestamp) { |
639 // Find the first keyframe after |timestamp|. | 704 // Find the first keyframe after |timestamp|, not including |timestamp|. |
640 KeyframeMap::iterator new_beginning_keyframe = | 705 KeyframeMap::iterator new_beginning_keyframe = |
641 keyframe_map_.lower_bound(timestamp); | 706 GetFirstKeyframeAfter(timestamp, true); |
642 | 707 |
643 // If there is no keyframe after |timestamp|, we can't split the range. | 708 // If there is no keyframe after |timestamp|, we can't split the range. |
644 if (new_beginning_keyframe == keyframe_map_.end()) | 709 if (new_beginning_keyframe == keyframe_map_.end()) |
645 return NULL; | 710 return NULL; |
646 | 711 |
647 // Remove the data beginning at |keyframe_index| from |buffers_| and save it | 712 // Remove the data beginning at |keyframe_index| from |buffers_| and save it |
648 // into |removed_buffers|. | 713 // into |removed_buffers|. |
649 int keyframe_index = new_beginning_keyframe->second; | 714 int keyframe_index = new_beginning_keyframe->second; |
650 DCHECK_LT(keyframe_index, static_cast<int>(buffers_.size())); | 715 DCHECK_LT(keyframe_index, static_cast<int>(buffers_.size())); |
651 BufferQueue::iterator starting_point = buffers_.begin() + keyframe_index; | 716 BufferQueue::iterator starting_point = buffers_.begin() + keyframe_index; |
652 BufferQueue removed_buffers(starting_point, buffers_.end()); | 717 BufferQueue removed_buffers(starting_point, buffers_.end()); |
653 keyframe_map_.erase(new_beginning_keyframe, keyframe_map_.end()); | 718 keyframe_map_.erase(new_beginning_keyframe, keyframe_map_.end()); |
654 buffers_.erase(starting_point, buffers_.end()); | 719 buffers_.erase(starting_point, buffers_.end()); |
655 | 720 |
656 // Create a new range with |removed_buffers|. | 721 // Create a new range with |removed_buffers|. |
657 SourceBufferRange* split_range = | 722 SourceBufferRange* split_range = |
658 new SourceBufferRange(removed_buffers, kNoTimestamp()); | 723 new SourceBufferRange(removed_buffers, kNoTimestamp()); |
659 | 724 |
660 // If |next_buffer_index_| points to a buffer in |split_range|, update the | 725 // If |next_buffer_index_| points to a buffer in |split_range|, update the |
661 // |next_buffer_index_| of this range and |split_range| accordingly. | 726 // |next_buffer_index_| of this range and |split_range| accordingly. |
662 if (next_buffer_index_ >= static_cast<int>(buffers_.size())) { | 727 if (next_buffer_index_ >= static_cast<int>(buffers_.size())) { |
663 split_range->next_buffer_index_ = next_buffer_index_ - keyframe_index; | 728 split_range->next_buffer_index_ = next_buffer_index_ - keyframe_index; |
664 next_buffer_index_ = -1; | 729 next_buffer_index_ = -1; |
665 } | 730 } |
666 return split_range; | 731 return split_range; |
667 } | 732 } |
668 | 733 |
669 void SourceBufferRange::DeleteAll(BufferQueue* removed_buffers) { | 734 SourceBufferRange::KeyframeMap::iterator |
670 DeleteAfter(buffers_.begin(), removed_buffers); | 735 SourceBufferRange::GetFirstKeyframeAfter(base::TimeDelta timestamp, |
736 bool skip_given_timestamp) { | |
737 KeyframeMap::iterator result = keyframe_map_.lower_bound(timestamp); | |
738 // lower_bound() returns the first element >= |timestamp|, so if we don't want | |
739 // to include keyframes == |timestamp|, we have to increment the iterator | |
740 // accordingly. | |
741 if (skip_given_timestamp && | |
742 result != keyframe_map_.end() && result->first == timestamp) { | |
743 ++result; | |
744 } | |
745 return result; | |
671 } | 746 } |
672 | 747 |
673 void SourceBufferRange::DeleteAfter( | 748 bool SourceBufferRange::DeleteAll(BufferQueue* removed_buffers) { |
749 return TruncateAt(buffers_.begin(), removed_buffers); | |
750 } | |
751 | |
752 bool SourceBufferRange::TruncateAt( | |
674 scoped_refptr<StreamParserBuffer> buffer, BufferQueue* removed_buffers) { | 753 scoped_refptr<StreamParserBuffer> buffer, BufferQueue* removed_buffers) { |
675 // Find the place in |buffers_| where we will begin deleting data. | 754 // Find the place in |buffers_| where we will begin deleting data. |
676 BufferQueue::iterator starting_point = | 755 BufferQueue::iterator starting_point = |
677 std::lower_bound(buffers_.begin(), buffers_.end(), | 756 std::lower_bound(buffers_.begin(), buffers_.end(), |
678 buffer, | 757 buffer, |
679 BufferComparator); | 758 BufferComparator); |
680 DeleteAfter(starting_point, removed_buffers); | 759 return TruncateAt(starting_point, removed_buffers); |
681 } | 760 } |
682 | 761 |
683 void SourceBufferRange::DeleteAfter( | 762 bool SourceBufferRange::TruncateAt( |
684 const BufferQueue::iterator& starting_point, BufferQueue* removed_buffers) { | 763 const BufferQueue::iterator& starting_point, BufferQueue* removed_buffers) { |
685 DCHECK(removed_buffers); | 764 DCHECK(removed_buffers); |
765 DCHECK(removed_buffers->empty()); | |
766 | |
686 // Return if we're not deleting anything. | 767 // Return if we're not deleting anything. |
687 if (starting_point == buffers_.end()) | 768 if (starting_point == buffers_.end()) |
688 return; | 769 return false; |
689 | 770 |
771 bool removed_next_buffer = false; | |
690 // Reset the next buffer index if we will be deleting the buffer that's next | 772 // Reset the next buffer index if we will be deleting the buffer that's next |
691 // in sequence. | 773 // in sequence. |
692 if (HasNextBuffer() && | 774 if (HasNextBufferPosition() && |
693 GetNextTimestamp() >= (*starting_point)->GetTimestamp()) { | 775 GetNextTimestamp() >= (*starting_point)->GetTimestamp()) { |
694 // Save the buffers we're about to delete if the output parameter is valid. | 776 if (HasNextBuffer()) { |
695 int starting_offset = starting_point - buffers_.begin(); | 777 int starting_offset = starting_point - buffers_.begin(); |
696 int next_buffer_offset = next_buffer_index_ - starting_offset; | 778 int next_buffer_offset = next_buffer_index_ - starting_offset; |
697 DCHECK_GE(next_buffer_offset, 0); | 779 DCHECK_GE(next_buffer_offset, 0); |
698 BufferQueue saved(starting_point + next_buffer_offset, buffers_.end()); | 780 BufferQueue saved(starting_point + next_buffer_offset, buffers_.end()); |
699 removed_buffers->swap(saved); | 781 removed_buffers->swap(saved); |
782 } | |
700 next_buffer_index_ = -1; | 783 next_buffer_index_ = -1; |
784 removed_next_buffer = true; | |
701 } | 785 } |
702 | 786 |
703 // Remove keyframes from |starting_point| onward. | 787 // Remove keyframes from |starting_point| onward. |
704 KeyframeMap::iterator starting_point_keyframe = | 788 KeyframeMap::iterator starting_point_keyframe = |
705 keyframe_map_.lower_bound((*starting_point)->GetTimestamp()); | 789 keyframe_map_.lower_bound((*starting_point)->GetTimestamp()); |
706 keyframe_map_.erase(starting_point_keyframe, keyframe_map_.end()); | 790 keyframe_map_.erase(starting_point_keyframe, keyframe_map_.end()); |
707 | 791 |
708 // Remove everything from |starting_point| onward. | 792 // Remove everything from |starting_point| onward. |
709 buffers_.erase(starting_point, buffers_.end()); | 793 buffers_.erase(starting_point, buffers_.end()); |
794 return removed_next_buffer; | |
710 } | 795 } |
711 | 796 |
712 bool SourceBufferRange::GetNextBuffer( | 797 bool SourceBufferRange::GetNextBuffer( |
713 scoped_refptr<StreamParserBuffer>* out_buffer) { | 798 scoped_refptr<StreamParserBuffer>* out_buffer) { |
714 if (waiting_for_keyframe_ || | 799 if (waiting_for_keyframe_ || |
715 next_buffer_index_ >= static_cast<int>(buffers_.size())) { | 800 next_buffer_index_ >= static_cast<int>(buffers_.size())) { |
716 return false; | 801 return false; |
717 } | 802 } |
718 | 803 |
719 DCHECK_GE(next_buffer_index_, 0); | 804 DCHECK_GE(next_buffer_index_, 0); |
720 *out_buffer = buffers_.at(next_buffer_index_); | 805 *out_buffer = buffers_.at(next_buffer_index_); |
721 next_buffer_index_++; | 806 next_buffer_index_++; |
722 return true; | 807 return true; |
723 } | 808 } |
724 | 809 |
725 bool SourceBufferRange::HasNextBuffer() const { | 810 bool SourceBufferRange::HasNextBuffer() const { |
726 return next_buffer_index_ >= 0 && | 811 return next_buffer_index_ >= 0 && |
727 next_buffer_index_ < static_cast<int>(buffers_.size()); | 812 next_buffer_index_ < static_cast<int>(buffers_.size()); |
728 } | 813 } |
729 | 814 |
730 base::TimeDelta SourceBufferRange::GetNextTimestamp() const { | 815 base::TimeDelta SourceBufferRange::GetNextTimestamp() const { |
731 DCHECK(!buffers_.empty()); | 816 DCHECK(!buffers_.empty()); |
732 DCHECK(HasNextBufferPosition()); | 817 DCHECK(HasNextBufferPosition()); |
733 | 818 |
734 if (waiting_for_keyframe_) | 819 if (waiting_for_keyframe_) |
735 return next_keyframe_timestamp_; | 820 return next_keyframe_timestamp_; |
736 | 821 |
737 if (next_buffer_index_ >= static_cast<int>(buffers_.size())) | 822 if (next_buffer_index_ >= static_cast<int>(buffers_.size())) |
738 return buffers_.back()->GetEndTimestamp(); | 823 return buffers_.back()->GetTimestamp(); |
acolwell GONE FROM CHROMIUM
2012/07/02 17:12:33
Why is this ok? Wouldn't we want to use fudge room
vrk (LEFT CHROMIUM)
2012/07/04 02:50:18
Talked offline, returning kNoTimestamp() instead a
| |
739 | 824 |
740 return buffers_.at(next_buffer_index_)->GetTimestamp(); | 825 return buffers_.at(next_buffer_index_)->GetTimestamp(); |
741 } | 826 } |
742 | 827 |
743 bool SourceBufferRange::HasNextBufferPosition() const { | 828 bool SourceBufferRange::HasNextBufferPosition() const { |
744 return next_buffer_index_ >= 0 || waiting_for_keyframe_; | 829 return next_buffer_index_ >= 0 || waiting_for_keyframe_; |
745 } | 830 } |
746 | 831 |
747 void SourceBufferRange::AppendToEnd(const SourceBufferRange& range, | 832 void SourceBufferRange::AppendToEnd(const SourceBufferRange& range, |
748 bool transfer_current_position) { | 833 bool transfer_current_position) { |
(...skipping 16 matching lines...) Expand all Loading... | |
765 } | 850 } |
766 | 851 |
767 bool SourceBufferRange::BelongsToRange(base::TimeDelta timestamp) const { | 852 bool SourceBufferRange::BelongsToRange(base::TimeDelta timestamp) const { |
768 DCHECK(!buffers_.empty()); | 853 DCHECK(!buffers_.empty()); |
769 | 854 |
770 return (IsNextInSequence(buffers_.back(), timestamp) || | 855 return (IsNextInSequence(buffers_.back(), timestamp) || |
771 (GetStartTimestamp() <= timestamp && timestamp <= GetEndTimestamp())); | 856 (GetStartTimestamp() <= timestamp && timestamp <= GetEndTimestamp())); |
772 } | 857 } |
773 | 858 |
774 bool SourceBufferRange::CanSeekTo(base::TimeDelta timestamp) const { | 859 bool SourceBufferRange::CanSeekTo(base::TimeDelta timestamp) const { |
775 return !keyframe_map_.empty() && GetStartTimestamp() <= timestamp && | 860 base::TimeDelta start_range = |
776 GetEndTimestamp() > timestamp; | 861 std::max(base::TimeDelta(), GetStartTimestamp() - GetFudgeRoom()); |
862 return !keyframe_map_.empty() && start_range <= timestamp && | |
863 timestamp <= GetEndTimestamp(); | |
777 } | 864 } |
778 | 865 |
779 bool SourceBufferRange::CompletelyOverlaps( | 866 bool SourceBufferRange::CompletelyOverlaps( |
780 const SourceBufferRange& range) const { | 867 const SourceBufferRange& range) const { |
781 return GetStartTimestamp() <= range.GetStartTimestamp() && | 868 return GetStartTimestamp() <= range.GetStartTimestamp() && |
782 GetEndTimestamp() >= range.GetEndTimestamp(); | 869 GetEndTimestamp() >= range.GetEndTimestamp(); |
783 } | 870 } |
784 | 871 |
785 bool SourceBufferRange::EndOverlaps(const SourceBufferRange& range) const { | 872 bool SourceBufferRange::EndOverlaps(const SourceBufferRange& range) const { |
786 return range.GetStartTimestamp() < GetEndTimestamp() && | 873 return range.GetStartTimestamp() <= GetEndTimestamp() && |
787 GetEndTimestamp() < range.GetEndTimestamp(); | 874 GetEndTimestamp() < range.GetEndTimestamp(); |
788 } | 875 } |
789 | 876 |
790 base::TimeDelta SourceBufferRange::GetStartTimestamp() const { | 877 base::TimeDelta SourceBufferRange::GetStartTimestamp() const { |
791 DCHECK(!buffers_.empty()); | 878 DCHECK(!buffers_.empty()); |
792 base::TimeDelta start_timestamp = media_segment_start_time_; | 879 base::TimeDelta start_timestamp = media_segment_start_time_; |
793 if (start_timestamp == kNoTimestamp()) | 880 if (start_timestamp == kNoTimestamp()) |
794 start_timestamp = buffers_.front()->GetTimestamp(); | 881 start_timestamp = buffers_.front()->GetTimestamp(); |
795 return start_timestamp; | 882 return start_timestamp; |
796 } | 883 } |
797 | 884 |
798 base::TimeDelta SourceBufferRange::GetEndTimestamp() const { | 885 base::TimeDelta SourceBufferRange::GetEndTimestamp() const { |
799 DCHECK(!buffers_.empty()); | 886 DCHECK(!buffers_.empty()); |
800 return buffers_.back()->GetEndTimestamp(); | 887 return buffers_.back()->GetTimestamp(); |
acolwell GONE FROM CHROMIUM
2012/07/02 17:12:33
Shouldn't we be using fudge here?
vrk (LEFT CHROMIUM)
2012/07/04 02:50:18
I avoided it here because this was being used in t
| |
888 } | |
889 | |
890 bool SourceBufferRange::IsNextInSequence( | |
891 const scoped_refptr<media::StreamParserBuffer>& buffer, | |
892 base::TimeDelta timestamp) const { | |
893 return buffer->GetTimestamp() < timestamp && | |
894 timestamp <= buffer->GetTimestamp() + GetFudgeRoom(); | |
895 } | |
896 | |
897 base::TimeDelta SourceBufferRange::GetFudgeRoom() const { | |
898 // Use a constant default fudge room of 250ms if we've seen fewer than 2 | |
899 // buffers in this range. | |
900 base::TimeDelta fudge = base::TimeDelta::FromMilliseconds(250); | |
901 | |
902 // Because we do not know exactly when is the next timestamp, any buffer | |
903 // that starts within 2x the |max_interbuffer_distance_| seen so far in this | |
904 // range is considered the next buffer in the sequence. | |
905 if (max_interbuffer_distance_ != kNoTimestamp()) | |
acolwell GONE FROM CHROMIUM
2012/07/02 17:12:33
nit: Reverse check and early return default then j
vrk (LEFT CHROMIUM)
2012/07/04 02:50:18
Done.
| |
906 fudge = 2 * max_interbuffer_distance_; | |
907 return fudge; | |
801 } | 908 } |
802 | 909 |
803 } // namespace media | 910 } // namespace media |
OLD | NEW |