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/bind.h" | |
10 #include "base/logging.h" | 11 #include "base/logging.h" |
11 | 12 |
12 namespace media { | 13 namespace media { |
13 | 14 |
14 // Helper class representing a range of buffered data. All buffers in a | 15 // Helper class representing a range of buffered data. All buffers in a |
15 // SourceBufferRange are ordered sequentially in presentation order with no | 16 // SourceBufferRange are ordered sequentially in presentation order with no |
16 // gaps. | 17 // gaps. |
17 class SourceBufferRange { | 18 class SourceBufferRange { |
18 public: | 19 public: |
19 typedef std::deque<scoped_refptr<StreamParserBuffer> > BufferQueue; | 20 typedef std::deque<scoped_refptr<StreamParserBuffer> > BufferQueue; |
20 | 21 |
22 typedef base::Callback<base::TimeDelta()> InterbufferDistanceCB; | |
acolwell GONE FROM CHROMIUM
2012/07/09 18:15:55
nit: Add comment about what this callback's return
vrk (LEFT CHROMIUM)
2012/07/10 00:05:33
Done.
| |
23 | |
21 // Creates a source buffer range with |new_buffers|. |new_buffers| cannot be | 24 // Creates a source buffer range with |new_buffers|. |new_buffers| cannot be |
22 // empty and the front of |new_buffers| must be a keyframe. | 25 // empty and the front of |new_buffers| must be a keyframe. |
23 // |media_segment_start_time| refers to the starting timestamp for the media | 26 // |media_segment_start_time| refers to the starting timestamp for the media |
24 // segment to which these buffers belong. | 27 // segment to which these buffers belong. |
25 SourceBufferRange(const BufferQueue& new_buffers, | 28 SourceBufferRange(const BufferQueue& new_buffers, |
26 base::TimeDelta media_segment_start_time); | 29 base::TimeDelta media_segment_start_time, |
30 const InterbufferDistanceCB& interbuffer_distance_cb); | |
27 | 31 |
28 // Appends |buffers| to the end of the range and updates |keyframe_map_| as | 32 // Appends |buffers| to the end of the range and updates |keyframe_map_| as |
29 // it encounters new keyframes. Assumes |buffers| belongs at the end of the | 33 // it encounters new keyframes. Assumes |buffers| belongs at the end of the |
30 // range. | 34 // range. |
31 void AppendToEnd(const BufferQueue& buffers); | 35 void AppendToEnd(const BufferQueue& buffers); |
32 bool CanAppendToEnd(const BufferQueue& buffers) const; | 36 bool CanAppendToEnd(const BufferQueue& buffers) const; |
33 | 37 |
34 // Appends the buffers from |range| into this range. | 38 // Appends the buffers from |range| into this range. |
35 // The first buffer in |range| must come directly after the last buffer | 39 // The first buffer in |range| must come directly after the last buffer |
36 // in this range. | 40 // in this range. |
37 // If |transfer_current_position| is true, |range|'s |next_buffer_index_| | 41 // If |transfer_current_position| is true, |range|'s |next_buffer_index_| |
38 // is transfered to this SourceBufferRange. | 42 // is transfered to this SourceBufferRange. |
39 void AppendToEnd(const SourceBufferRange& range, | 43 void AppendToEnd(const SourceBufferRange& range, |
40 bool transfer_current_position); | 44 bool transfer_current_position); |
41 bool CanAppendToEnd(const SourceBufferRange& range) const; | 45 bool CanAppendToEnd(const SourceBufferRange& range) const; |
42 | 46 |
43 // Updates |next_buffer_index_| to point to the Buffer containing |timestamp|. | 47 // Updates |next_buffer_index_| to point to the Buffer containing |timestamp|. |
44 // Assumes |timestamp| is valid and in this range. | 48 // Assumes |timestamp| is valid and in this range. |
45 void Seek(base::TimeDelta timestamp); | 49 void Seek(base::TimeDelta timestamp); |
46 | 50 |
47 // Updates |next_buffer_index_| to point to next keyframe after or equal to | 51 // Updates |next_buffer_index_| to point to next keyframe after or equal to |
48 // |timestamp|. | 52 // |timestamp|. |
49 void SeekAfter(base::TimeDelta timestamp); | 53 void SeekAheadTo(base::TimeDelta timestamp); |
54 | |
55 // Updates |next_buffer_index_| to point to next keyframe strictly after | |
56 // |timestamp|. | |
57 void SeekAheadPast(base::TimeDelta timestamp); | |
50 | 58 |
51 // Finds the next keyframe from |buffers_| after |timestamp|, and creates and | 59 // Finds the next keyframe from |buffers_| after |timestamp|, and creates and |
52 // returns a new SourceBufferRange with the buffers from that keyframe onward. | 60 // 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 | 61 // 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 | 62 // there is no keyframe after |timestamp|, SplitRange() returns null and this |
55 // range is unmodified. | 63 // range is unmodified. |
56 SourceBufferRange* SplitRange(base::TimeDelta timestamp); | 64 SourceBufferRange* SplitRange(base::TimeDelta timestamp); |
57 | 65 |
58 // Deletes the buffers from this range whose timestamps are greater than or | 66 // Deletes the buffers from this range whose timestamps are greater than or |
59 // equal to |buffer|'s timestamp. | 67 // equal to |buffer|'s timestamp. |
60 // Resets |next_buffer_index_| if the buffer at |next_buffer_index_| was | 68 // Resets |next_buffer_index_| if the buffer at |next_buffer_index_| was |
61 // deleted, and deletes the |keyframe_map_| entries for the buffers that | 69 // deleted, and deletes the |keyframe_map_| entries for the buffers that |
62 // were removed. | 70 // were removed. |
63 // |deleted_buffers| contains the buffers that were deleted from this range, | 71 // |deleted_buffers| contains the buffers that were deleted from this range, |
64 // starting at the buffer that had been at |next_buffer_index_|. | 72 // 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 | 73 // Returns true if the |next_buffer_index_| is reset. Note that this method |
66 // deleted. | 74 // may return true even if it does not add any buffers to |deleted_buffers|. |
67 void DeleteAfter(scoped_refptr<StreamParserBuffer> buffer, | 75 // This indicates that the range had not buffered |next_buffer_index_|, but |
68 BufferQueue* deleted_buffers); | 76 // a buffer at that position would have been deleted. |
77 bool TruncateAt(scoped_refptr<StreamParserBuffer> buffer, | |
78 BufferQueue* deleted_buffers); | |
69 // Deletes all buffers in range. | 79 // Deletes all buffers in range. |
70 void DeleteAll(BufferQueue* deleted_buffers); | 80 bool DeleteAll(BufferQueue* deleted_buffers); |
71 | 81 |
72 // Updates |out_buffer| with the next buffer in presentation order. Seek() | 82 // Updates |out_buffer| with the next buffer in presentation order. Seek() |
73 // must be called before calls to GetNextBuffer(), and buffers are returned | 83 // 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 | 84 // 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 | 85 // filled with a valid buffer, false if there is not enough data to fulfill |
76 // the request. | 86 // the request. |
77 bool GetNextBuffer(scoped_refptr<StreamParserBuffer>* out_buffer); | 87 bool GetNextBuffer(scoped_refptr<StreamParserBuffer>* out_buffer); |
78 bool HasNextBuffer() const; | 88 bool HasNextBuffer() const; |
79 | 89 |
80 // Returns true if the range knows the position of the next buffer it should | 90 // 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 | 91 // return, i.e. it has been Seek()ed. This does not necessarily mean that it |
82 // has the next buffer yet. | 92 // has the next buffer yet. |
83 bool HasNextBufferPosition() const; | 93 bool HasNextBufferPosition() const; |
84 | 94 |
85 // Returns the timestamp of the next buffer that will be returned from | 95 // 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 | 96 // GetNextBuffer(), or kNoTimestamp() if the timestamp is unknown. |
87 // next buffer buffered. | |
88 base::TimeDelta GetNextTimestamp() const; | 97 base::TimeDelta GetNextTimestamp() const; |
89 | 98 |
90 // Returns the start timestamp of the range. | 99 // Returns the start timestamp of the range. |
91 base::TimeDelta GetStartTimestamp() const; | 100 base::TimeDelta GetStartTimestamp() const; |
92 | 101 |
93 // Returns the end timestamp of the buffered data. (Note that this is equal to | 102 // Returns the timestamp of the last buffer in the range. |
94 // the last buffer's timestamp + its duration.) | |
95 base::TimeDelta GetEndTimestamp() const; | 103 base::TimeDelta GetEndTimestamp() const; |
96 | 104 |
105 // Returns the timestamp for the end of the buffered region in this range. | |
106 // This is an approximation if the duration for the last buffer in the range | |
107 // is unset. | |
108 base::TimeDelta GetBufferedEndTimestamp() const; | |
109 | |
97 // Returns whether a buffer with a starting timestamp of |timestamp| would | 110 // 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 | 111 // belong in this range. This includes a buffer that would be appended to |
99 // the end of the range. | 112 // the end of the range. |
100 bool BelongsToRange(base::TimeDelta timestamp) const; | 113 bool BelongsToRange(base::TimeDelta timestamp) const; |
101 | 114 |
102 // Returns true if the range has enough data to seek to the specified | 115 // Returns true if the range has enough data to seek to the specified |
103 // |timestamp|, false otherwise. | 116 // |timestamp|, false otherwise. |
104 bool CanSeekTo(base::TimeDelta timestamp) const; | 117 bool CanSeekTo(base::TimeDelta timestamp) const; |
105 | 118 |
106 // Returns true if this range's buffered timespan completely overlaps the | 119 // Returns true if this range's buffered timespan completely overlaps the |
107 // buffered timespan of |range|. | 120 // buffered timespan of |range|. |
108 bool CompletelyOverlaps(const SourceBufferRange& range) const; | 121 bool CompletelyOverlaps(const SourceBufferRange& range) const; |
109 | 122 |
110 // Returns true if the end of this range contains buffers that overlaps with | 123 // Returns true if the end of this range contains buffers that overlaps with |
111 // the beginning of |range|. | 124 // the beginning of |range|. |
112 bool EndOverlaps(const SourceBufferRange& range) const; | 125 bool EndOverlaps(const SourceBufferRange& range) const; |
113 | 126 |
127 // Returns true if |timestamp| is the timestamp of the next buffer in | |
128 // sequence after |buffer|, false otherwise. | |
129 bool IsNextInSequence( | |
130 const scoped_refptr<media::StreamParserBuffer>& buffer, | |
131 base::TimeDelta timestamp) const; | |
132 | |
114 private: | 133 private: |
115 // Helper method to delete buffers in |buffers_| starting from | 134 typedef std::map<base::TimeDelta, size_t> KeyframeMap; |
135 | |
136 // Seeks the range to the next keyframe after |timestamp|. If | |
137 // |skip_given_timestamp| is true, the seek will go to a keyframe with a | |
138 // timestamp strictly greater than |timestamp|. | |
139 void SeekAhead(base::TimeDelta timestamp, bool skip_given_timestamp); | |
140 KeyframeMap::iterator GetFirstKeyframeAfter( | |
acolwell GONE FROM CHROMIUM
2012/07/09 18:15:55
nit: Remove After since this would be more of an A
vrk (LEFT CHROMIUM)
2012/07/10 00:05:33
Good call on both accounts, done.
| |
141 base::TimeDelta timestamp, bool skip_given_timestamp); | |
142 | |
143 // Helper method to delete buffers in |buffers_| starting at | |
116 // |starting_point|, an iterator in |buffers_|. | 144 // |starting_point|, an iterator in |buffers_|. |
117 void DeleteAfter(const BufferQueue::iterator& starting_point, | 145 bool TruncateAt(const BufferQueue::iterator& starting_point, |
118 BufferQueue* deleted_buffers); | 146 BufferQueue* deleted_buffers); |
147 | |
148 // Returns the distance in time estimating how far from the beginning or end | |
149 // of this range a buffer can be to considered in the range. | |
150 base::TimeDelta GetFudgeRoom() const; | |
151 | |
152 // Returns the approximate duration of a buffer in this range. | |
153 base::TimeDelta GetApproximateDuration() const; | |
119 | 154 |
120 // An ordered list of buffers in this range. | 155 // An ordered list of buffers in this range. |
121 BufferQueue buffers_; | 156 BufferQueue buffers_; |
122 | 157 |
123 // Maps keyframe timestamps to its index position in |buffers_|. | 158 // Maps keyframe timestamps to its index position in |buffers_|. |
124 typedef std::map<base::TimeDelta, size_t> KeyframeMap; | |
125 KeyframeMap keyframe_map_; | 159 KeyframeMap keyframe_map_; |
126 | 160 |
127 // Index into |buffers_| for the next buffer to be returned by | 161 // Index into |buffers_| for the next buffer to be returned by |
128 // GetNextBuffer(), set to -1 before Seek(). | 162 // GetNextBuffer(), set to -1 before Seek(). |
129 int next_buffer_index_; | 163 int next_buffer_index_; |
130 | 164 |
131 // True if the range needs to wait for the next keyframe to be appended before | 165 // True if the range needs to wait for the next keyframe to be appended before |
132 // returning buffers from GetNextBuffer(). | 166 // returning buffers from GetNextBuffer(). |
133 bool waiting_for_keyframe_; | 167 bool waiting_for_keyframe_; |
134 | 168 |
135 // If |waiting_for_keyframe_| is true, this range will wait for the next | 169 // If |waiting_for_keyframe_| is true, this range will wait for the next |
136 // keyframe with timestamp >= |next_keyframe_timestamp_|. | 170 // keyframe with timestamp >= |next_keyframe_timestamp_|. |
137 base::TimeDelta next_keyframe_timestamp_; | 171 base::TimeDelta next_keyframe_timestamp_; |
138 | 172 |
139 // If the first buffer in this range is the beginning of a media segment, | 173 // 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. | 174 // |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 | 175 // |media_segment_start_time_| may be <= the timestamp of the first buffer in |
142 // |buffers_|. |media_segment_start_time_| is kNoTimestamp() if this range | 176 // |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 | 177 // 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 | 178 // 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 | 179 // (we don't have a way of knowing the media segment timestamp for the new |
146 // range). | 180 // range). |
147 base::TimeDelta media_segment_start_time_; | 181 base::TimeDelta media_segment_start_time_; |
148 | 182 |
183 // Called to get the largest interbuffer distance seen so far in the stream. | |
184 InterbufferDistanceCB interbuffer_distance_cb_; | |
185 | |
149 DISALLOW_COPY_AND_ASSIGN(SourceBufferRange); | 186 DISALLOW_COPY_AND_ASSIGN(SourceBufferRange); |
150 }; | 187 }; |
151 | 188 |
152 } // namespace media | 189 } // namespace media |
153 | 190 |
154 // Helper method that returns true if |ranges| is sorted in increasing order, | 191 // Helper method that returns true if |ranges| is sorted in increasing order, |
155 // false otherwise. | 192 // false otherwise. |
156 static bool IsRangeListSorted( | 193 static bool IsRangeListSorted( |
157 const std::list<media::SourceBufferRange*>& ranges) { | 194 const std::list<media::SourceBufferRange*>& ranges) { |
158 base::TimeDelta prev = media::kNoTimestamp(); | 195 base::TimeDelta prev = media::kNoTimestamp(); |
159 for (std::list<media::SourceBufferRange*>::const_iterator itr = | 196 for (std::list<media::SourceBufferRange*>::const_iterator itr = |
160 ranges.begin(); itr != ranges.end(); itr++) { | 197 ranges.begin(); itr != ranges.end(); ++itr) { |
161 if (prev != media::kNoTimestamp() && prev >= (*itr)->GetStartTimestamp()) | 198 if (prev != media::kNoTimestamp() && prev >= (*itr)->GetStartTimestamp()) |
162 return false; | 199 return false; |
163 prev = (*itr)->GetEndTimestamp(); | 200 prev = (*itr)->GetEndTimestamp(); |
164 } | 201 } |
165 return true; | 202 return true; |
166 } | 203 } |
167 | 204 |
168 // Comparison function for two Buffers based on timestamp. | 205 // Comparison function for two Buffers based on timestamp. |
169 static bool BufferComparator( | 206 static bool BufferComparator( |
170 const scoped_refptr<media::StreamParserBuffer>& first, | 207 const scoped_refptr<media::StreamParserBuffer>& first, |
171 const scoped_refptr<media::StreamParserBuffer>& second) { | 208 const scoped_refptr<media::StreamParserBuffer>& second) { |
172 return first->GetDecodeTimestamp() < second->GetDecodeTimestamp(); | 209 return first->GetDecodeTimestamp() < second->GetDecodeTimestamp(); |
173 } | 210 } |
174 | 211 |
175 // Returns the upper bound for the starting timestamp for the next buffer | 212 // An arbitrarily-chosen number to estimate the duration of a buffer if none |
176 // in sequence after |buffer|. Assumes |buffer|'s timestamp and | 213 // is set and there's not enough information to get a better estimate. |
177 // duration are valid. | 214 static int kDefaultBufferDurationInMs = 125; |
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 | 215 |
195 namespace media { | 216 namespace media { |
196 | 217 |
197 SourceBufferStream::SourceBufferStream() | |
198 : seek_pending_(false), | |
199 seek_buffer_timestamp_(base::TimeDelta()), | |
200 selected_range_(NULL), | |
201 end_of_stream_(false) { | |
202 } | |
203 | |
204 SourceBufferStream::SourceBufferStream(const AudioDecoderConfig& audio_config) | 218 SourceBufferStream::SourceBufferStream(const AudioDecoderConfig& audio_config) |
205 : seek_pending_(false), | 219 : seek_pending_(false), |
206 seek_buffer_timestamp_(base::TimeDelta()), | 220 seek_buffer_timestamp_(kNoTimestamp()), |
207 selected_range_(NULL), | 221 selected_range_(NULL), |
208 end_of_stream_(false) { | 222 end_of_stream_(false), |
223 media_segment_start_time_(kNoTimestamp()), | |
224 range_for_next_append_(ranges_.end()), | |
225 new_media_segment_(false), | |
226 last_buffer_timestamp_(kNoTimestamp()), | |
227 max_interbuffer_distance_(kNoTimestamp()) { | |
209 audio_config_.CopyFrom(audio_config); | 228 audio_config_.CopyFrom(audio_config); |
210 } | 229 } |
211 | 230 |
212 SourceBufferStream::SourceBufferStream(const VideoDecoderConfig& video_config) | 231 SourceBufferStream::SourceBufferStream(const VideoDecoderConfig& video_config) |
213 : seek_pending_(false), | 232 : seek_pending_(false), |
214 seek_buffer_timestamp_(base::TimeDelta()), | 233 seek_buffer_timestamp_(kNoTimestamp()), |
215 selected_range_(NULL), | 234 selected_range_(NULL), |
216 end_of_stream_(false) { | 235 end_of_stream_(false), |
236 media_segment_start_time_(kNoTimestamp()), | |
237 range_for_next_append_(ranges_.end()), | |
238 new_media_segment_(false), | |
239 last_buffer_timestamp_(kNoTimestamp()), | |
240 max_interbuffer_distance_(kNoTimestamp()) { | |
217 video_config_.CopyFrom(video_config); | 241 video_config_.CopyFrom(video_config); |
218 } | 242 } |
219 | 243 |
220 SourceBufferStream::~SourceBufferStream() { | 244 SourceBufferStream::~SourceBufferStream() { |
221 while (!ranges_.empty()) { | 245 while (!ranges_.empty()) { |
222 delete ranges_.front(); | 246 delete ranges_.front(); |
223 ranges_.pop_front(); | 247 ranges_.pop_front(); |
224 } | 248 } |
225 } | 249 } |
226 | 250 |
251 void SourceBufferStream::OnNewMediaSegment( | |
252 base::TimeDelta media_segment_start_time) { | |
253 media_segment_start_time_ = media_segment_start_time; | |
254 | |
255 // Find the range that will house the buffers appended through the next | |
256 // Append() call. | |
257 range_for_next_append_ = FindExistingRangeFor(media_segment_start_time); | |
258 new_media_segment_ = true; | |
259 last_buffer_timestamp_ = kNoTimestamp(); | |
260 } | |
261 | |
227 bool SourceBufferStream::Append( | 262 bool SourceBufferStream::Append( |
228 const SourceBufferStream::BufferQueue& buffers, | 263 const SourceBufferStream::BufferQueue& buffers) { |
229 base::TimeDelta media_segment_start_time) { | |
230 DCHECK(!buffers.empty()); | 264 DCHECK(!buffers.empty()); |
231 DCHECK(media_segment_start_time != kNoTimestamp()); | 265 DCHECK(media_segment_start_time_ != kNoTimestamp()); |
232 | 266 |
233 // Find a range into which we'll append |buffers|. | 267 // New media segments must begin with a keyframe. |
234 RangeList::iterator range_for_new_buffers = FindExistingRangeFor(buffers); | 268 if (new_media_segment_ && !buffers.front()->IsKeyframe()) { |
vrk (LEFT CHROMIUM)
2012/07/04 02:50:18
I added this logic here to do a proper check to ma
acolwell GONE FROM CHROMIUM
2012/07/09 18:15:55
Yes. The file starts with a cluster that contains
vrk (LEFT CHROMIUM)
2012/07/10 00:05:33
Thanks Aaron! Bug filed and assigned: crbug.com/13
| |
269 DVLOG(1) << "Media segment did not begin with keyframe."; | |
270 return false; | |
271 } | |
235 | 272 |
273 // Buffers within a media segment should be monotonically increasing. | |
274 if (!IsMonotonicallyIncreasing(buffers)) { | |
275 DVLOG(1) << "Buffers were not monotonically increasing."; | |
276 return false; | |
277 } | |
278 | |
279 UpdateMaxInterbufferDistance(buffers); | |
280 | |
281 // Save a snapshot of the |selected_range_| state before range modifications | |
282 // are made. | |
283 base::TimeDelta next_buffer_timestamp = GetNextBufferTimestamp(); | |
284 base::TimeDelta end_buffer_timestamp = GetEndBufferTimestamp(); | |
285 | |
286 bool deleted_next_buffer = false; | |
287 BufferQueue deleted_buffers; | |
288 | |
289 RangeList::iterator range_for_new_buffers = range_for_next_append_; | |
236 // If there's a range for |buffers|, insert |buffers| accordingly. Otherwise, | 290 // If there's a range for |buffers|, insert |buffers| accordingly. Otherwise, |
237 // create a new range with |buffers|. | 291 // create a new range with |buffers|. |
238 if (range_for_new_buffers != ranges_.end()) { | 292 if (range_for_new_buffers != ranges_.end()) { |
239 InsertIntoExistingRange(range_for_new_buffers, buffers); | 293 InsertIntoExistingRange(range_for_new_buffers, buffers, |
294 &deleted_next_buffer, &deleted_buffers); | |
240 } else { | 295 } else { |
241 // Ranges must begin with a keyframe. | 296 DCHECK(new_media_segment_); |
242 if (!buffers.front()->IsKeyframe()) | |
243 return false; | |
244 range_for_new_buffers = | 297 range_for_new_buffers = |
245 AddToRanges(new SourceBufferRange(buffers, media_segment_start_time)); | 298 AddToRanges(new SourceBufferRange( |
299 buffers, media_segment_start_time_, | |
300 base::Bind(&SourceBufferStream::max_interbuffer_distance, | |
301 base::Unretained(this)))); | |
246 } | 302 } |
247 | 303 |
304 range_for_next_append_ = range_for_new_buffers; | |
305 new_media_segment_ = false; | |
306 last_buffer_timestamp_ = buffers.back()->GetDecodeTimestamp(); | |
307 | |
248 // Resolve overlaps. | 308 // Resolve overlaps. |
249 ResolveCompleteOverlaps(range_for_new_buffers); | 309 ResolveCompleteOverlaps( |
250 ResolveEndOverlap(range_for_new_buffers); | 310 range_for_new_buffers, &deleted_next_buffer, &deleted_buffers); |
311 ResolveEndOverlap( | |
312 range_for_new_buffers, &deleted_next_buffer, &deleted_buffers); | |
251 MergeWithAdjacentRangeIfNecessary(range_for_new_buffers); | 313 MergeWithAdjacentRangeIfNecessary(range_for_new_buffers); |
252 | 314 |
253 // If these were the first buffers appended to the stream, seek to the | 315 // If these were the first buffers appended to the stream, seek to the |
254 // beginning of the range. | 316 // beginning of the range. |
255 // TODO(vrk): This should be done by ChunkDemuxer. (crbug.com/132815) | 317 // TODO(vrk): This should be done by ChunkDemuxer. (crbug.com/132815) |
256 if (!seek_pending_ && !selected_range_) { | 318 if (!seek_pending_ && !selected_range_) { |
257 selected_range_ = *range_for_new_buffers; | 319 selected_range_ = *range_for_new_buffers; |
258 selected_range_->Seek(buffers.front()->GetDecodeTimestamp()); | 320 selected_range_->Seek(buffers.front()->GetDecodeTimestamp()); |
259 } | 321 } |
260 | 322 |
261 // Finally, try to complete pending seek if one exists. | 323 // Seek to try to fulfill a previous call to Seek(). |
262 if (seek_pending_) | 324 if (seek_pending_) { |
325 DCHECK(!selected_range_); | |
326 DCHECK(!deleted_next_buffer); | |
263 Seek(seek_buffer_timestamp_); | 327 Seek(seek_buffer_timestamp_); |
328 } | |
329 | |
330 // Seek because the Append() has deleted the buffer that would have been | |
331 // returned in the next call to GetNextBuffer(). | |
332 if (deleted_next_buffer) { | |
333 DCHECK(!seek_pending_); | |
334 selected_range_ = *range_for_new_buffers; | |
335 if (!deleted_buffers.empty()) { | |
336 // Seek the range to the keyframe at or after |next_buffer_timestamp|. | |
337 selected_range_->SeekAheadTo(next_buffer_timestamp); | |
338 } else { | |
339 // If we've deleted the next buffer but |deleted_buffers| is empty, | |
340 // that means we need to seek past the timestamp of the last buffer in | |
341 // the range (i.e. the keyframe timestamp needs to be strictly greater | |
342 // than |end_buffer_timestamp|). | |
343 selected_range_->SeekAheadPast(end_buffer_timestamp); | |
344 } | |
345 UpdateTrackBuffer(deleted_buffers); | |
acolwell GONE FROM CHROMIUM
2012/07/09 18:15:55
I believe this can be moved into the if() body abo
vrk (LEFT CHROMIUM)
2012/07/10 00:05:33
Moved UpdateTrackBuffer() accordingly.
Would rath
| |
346 } | |
264 | 347 |
265 DCHECK(IsRangeListSorted(ranges_)); | 348 DCHECK(IsRangeListSorted(ranges_)); |
266 return true; | 349 return true; |
267 } | 350 } |
268 | 351 |
352 bool SourceBufferStream::IsMonotonicallyIncreasing( | |
353 const BufferQueue& buffers) { | |
354 DCHECK(!buffers.empty()); | |
355 base::TimeDelta prev_timestamp = last_buffer_timestamp_; | |
356 for (BufferQueue::const_iterator itr = buffers.begin(); | |
357 itr != buffers.end(); ++itr) { | |
358 base::TimeDelta current_timestamp = (*itr)->GetDecodeTimestamp(); | |
359 DCHECK(current_timestamp != kNoTimestamp()); | |
360 | |
361 if (prev_timestamp != kNoTimestamp() && current_timestamp < prev_timestamp) | |
362 return false; | |
363 | |
364 prev_timestamp = current_timestamp; | |
365 } | |
366 return true; | |
367 } | |
368 | |
369 void SourceBufferStream::UpdateMaxInterbufferDistance( | |
370 const BufferQueue& buffers) { | |
371 DCHECK(!buffers.empty()); | |
372 base::TimeDelta prev_timestamp = last_buffer_timestamp_; | |
373 for (BufferQueue::const_iterator itr = buffers.begin(); | |
374 itr != buffers.end(); ++itr) { | |
375 base::TimeDelta current_timestamp = (*itr)->GetDecodeTimestamp(); | |
376 DCHECK(current_timestamp != kNoTimestamp()); | |
377 | |
378 if (prev_timestamp != kNoTimestamp()) { | |
379 base::TimeDelta interbuffer_distance = current_timestamp - prev_timestamp; | |
380 if (max_interbuffer_distance_ == kNoTimestamp()) { | |
381 max_interbuffer_distance_ = interbuffer_distance; | |
382 } else { | |
383 max_interbuffer_distance_ = | |
384 std::max(max_interbuffer_distance_, interbuffer_distance); | |
385 } | |
386 } | |
387 prev_timestamp = current_timestamp; | |
388 } | |
389 } | |
390 | |
269 void SourceBufferStream::InsertIntoExistingRange( | 391 void SourceBufferStream::InsertIntoExistingRange( |
270 const RangeList::iterator& range_for_new_buffers_itr, | 392 const RangeList::iterator& range_for_new_buffers_itr, |
271 const BufferQueue& new_buffers) { | 393 const BufferQueue& new_buffers, |
394 bool* deleted_next_buffer, BufferQueue* deleted_buffers) { | |
395 DCHECK(deleted_next_buffer); | |
396 DCHECK(deleted_buffers); | |
397 | |
272 SourceBufferRange* range_for_new_buffers = *range_for_new_buffers_itr; | 398 SourceBufferRange* range_for_new_buffers = *range_for_new_buffers_itr; |
273 | 399 |
274 // If this is a simple case where we can just append to the end of the range, | 400 // If this is a simple case where we can just append to the end of the range, |
275 // do so and return. | 401 // do so and return. |
276 if (range_for_new_buffers->CanAppendToEnd(new_buffers)) { | 402 if (range_for_new_buffers->CanAppendToEnd(new_buffers)) { |
277 range_for_new_buffers->AppendToEnd(new_buffers); | 403 range_for_new_buffers->AppendToEnd(new_buffers); |
278 return; | 404 return; |
279 } | 405 } |
280 | 406 |
281 // Otherwise, this is either a start overlap or an middle overlap. | 407 // Otherwise, this is either a start overlap or an middle overlap. |
282 | 408 |
283 // In case this is a middle overlap, save the buffers that come after the end | 409 // 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. | 410 // 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 = | 411 SourceBufferRange* new_next_range = |
288 range_for_new_buffers->SplitRange(new_buffers.back()->GetEndTimestamp()); | 412 range_for_new_buffers->SplitRange( |
413 new_buffers.back()->GetDecodeTimestamp()); | |
289 | 414 |
290 if (new_next_range) | 415 if (new_next_range) |
291 AddToRanges(new_next_range); | 416 AddToRanges(new_next_range); |
292 | 417 |
293 // Delete the buffers that are overlapped by |new_buffers|, then append | 418 // Delete the buffers that are overlapped by |new_buffers|, then append |
294 // |new_buffers| to the end of the range. | 419 // |new_buffers| to the end of the range. |
295 BufferQueue deleted_buffers; | 420 DCHECK(!*deleted_next_buffer); |
296 range_for_new_buffers->DeleteAfter(new_buffers.front(), &deleted_buffers); | 421 *deleted_next_buffer = |
422 range_for_new_buffers->TruncateAt(new_buffers.front(), deleted_buffers); | |
297 range_for_new_buffers->AppendToEnd(new_buffers); | 423 range_for_new_buffers->AppendToEnd(new_buffers); |
298 | 424 |
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()->GetDecodeTimestamp()) { | |
303 return; | |
304 } | |
305 | |
306 // If this was a middle overlap resulting in a new range, and the next buffer | 425 // 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 | 426 // position has been transferred to the newly created range, update the |
308 // |selected_range_| accordingly. | 427 // |selected_range_| accordingly. |
309 if (new_next_range && new_next_range->HasNextBufferPosition()) { | 428 if (new_next_range && new_next_range->HasNextBufferPosition()) { |
310 DCHECK(!range_for_new_buffers->HasNextBufferPosition()); | 429 DCHECK(!range_for_new_buffers->HasNextBufferPosition()); |
430 DCHECK(!*deleted_next_buffer); | |
311 selected_range_ = new_next_range; | 431 selected_range_ = new_next_range; |
312 return; | |
313 } | 432 } |
314 | |
315 selected_range_ = range_for_new_buffers; | |
316 selected_range_->SeekAfter(next_buffer_timestamp); | |
317 UpdateTrackBuffer(deleted_buffers); | |
318 } | 433 } |
319 | 434 |
320 void SourceBufferStream::ResolveCompleteOverlaps( | 435 void SourceBufferStream::ResolveCompleteOverlaps( |
321 const RangeList::iterator& range_with_new_buffers_itr) { | 436 const RangeList::iterator& range_with_new_buffers_itr, |
437 bool* deleted_next_buffer, BufferQueue* deleted_buffers) { | |
438 DCHECK(deleted_next_buffer); | |
439 DCHECK(deleted_buffers); | |
440 | |
322 SourceBufferRange* range_with_new_buffers = *range_with_new_buffers_itr; | 441 SourceBufferRange* range_with_new_buffers = *range_with_new_buffers_itr; |
323 RangeList::iterator next_range_itr = range_with_new_buffers_itr; | 442 RangeList::iterator next_range_itr = range_with_new_buffers_itr; |
324 next_range_itr++; | 443 next_range_itr++; |
325 base::TimeDelta next_buffer_timestamp = GetNextBufferTimestamp(); | |
326 | 444 |
327 while (next_range_itr != ranges_.end() && | 445 while (next_range_itr != ranges_.end() && |
328 range_with_new_buffers->CompletelyOverlaps(**next_range_itr)) { | 446 range_with_new_buffers->CompletelyOverlaps(**next_range_itr)) { |
329 if (*next_range_itr == selected_range_) { | 447 if (*next_range_itr == selected_range_) { |
330 // Transfer the next buffer position from the old selected range to the | 448 selected_range_ = NULL; |
331 // range with the new buffers. | 449 DCHECK(!*deleted_next_buffer); |
332 selected_range_ = range_with_new_buffers; | 450 *deleted_next_buffer = (*next_range_itr)->DeleteAll(deleted_buffers); |
333 selected_range_->SeekAfter(next_buffer_timestamp); | 451 DCHECK(*deleted_next_buffer); |
334 | |
335 // Delete everything from the old selected range and save the next | |
336 // buffers. | |
337 BufferQueue deleted_buffers; | |
338 (*next_range_itr)->DeleteAll(&deleted_buffers); | |
339 UpdateTrackBuffer(deleted_buffers); | |
340 } | 452 } |
341 delete *next_range_itr; | 453 delete *next_range_itr; |
342 next_range_itr = ranges_.erase(next_range_itr); | 454 next_range_itr = ranges_.erase(next_range_itr); |
343 } | 455 } |
344 } | 456 } |
345 | 457 |
346 void SourceBufferStream::ResolveEndOverlap( | 458 void SourceBufferStream::ResolveEndOverlap( |
347 const RangeList::iterator& range_with_new_buffers_itr) { | 459 const RangeList::iterator& range_with_new_buffers_itr, |
460 bool* deleted_next_buffer, BufferQueue* deleted_buffers) { | |
461 DCHECK(deleted_next_buffer); | |
462 DCHECK(deleted_buffers); | |
463 | |
348 SourceBufferRange* range_with_new_buffers = *range_with_new_buffers_itr; | 464 SourceBufferRange* range_with_new_buffers = *range_with_new_buffers_itr; |
349 RangeList::iterator next_range_itr = range_with_new_buffers_itr; | 465 RangeList::iterator next_range_itr = range_with_new_buffers_itr; |
350 next_range_itr++; | 466 next_range_itr++; |
351 base::TimeDelta next_buffer_timestamp = GetNextBufferTimestamp(); | |
352 | 467 |
353 if (next_range_itr == ranges_.end() || | 468 if (next_range_itr == ranges_.end() || |
354 !range_with_new_buffers->EndOverlaps(**next_range_itr)) { | 469 !range_with_new_buffers->EndOverlaps(**next_range_itr)) { |
355 return; | 470 return; |
356 } | 471 } |
357 | 472 |
358 // Split the overlapped range after |range_with_new_buffers|'s last buffer | 473 // Split the overlapped range after |range_with_new_buffers|'s last buffer |
359 // overlaps. Now |overlapped_range| contains only the buffers that do not | 474 // overlaps. Now |overlapped_range| contains only the buffers that do not |
360 // belong in |ranges_| anymore, and |new_next_range| contains buffers that | 475 // belong in |ranges_| anymore, and |new_next_range| contains buffers that |
361 // go after |range_with_new_buffers| (without overlap). | 476 // go after |range_with_new_buffers| (without overlap). |
(...skipping 12 matching lines...) Expand all Loading... | |
374 return; | 489 return; |
375 | 490 |
376 // If the |overlapped_range| transfers its next buffer position to | 491 // If the |overlapped_range| transfers its next buffer position to |
377 // |new_next_range|, make |new_next_range| the |selected_range_|. | 492 // |new_next_range|, make |new_next_range| the |selected_range_|. |
378 if (new_next_range && new_next_range->HasNextBufferPosition()) { | 493 if (new_next_range && new_next_range->HasNextBufferPosition()) { |
379 DCHECK(!overlapped_range->HasNextBufferPosition()); | 494 DCHECK(!overlapped_range->HasNextBufferPosition()); |
380 selected_range_ = new_next_range; | 495 selected_range_ = new_next_range; |
381 return; | 496 return; |
382 } | 497 } |
383 | 498 |
384 // Transfer the next buffer position from the old range to the range with | 499 // Save the buffers in |overlapped_range|. |
385 // the new buffers. | 500 DCHECK(!*deleted_next_buffer); |
386 selected_range_ = range_with_new_buffers; | 501 *deleted_next_buffer = overlapped_range->DeleteAll(deleted_buffers); |
387 selected_range_->SeekAfter(next_buffer_timestamp); | 502 DCHECK(*deleted_next_buffer); |
acolwell GONE FROM CHROMIUM
2012/07/09 18:15:55
nit: If we always expect DeleteAll() to return tru
vrk (LEFT CHROMIUM)
2012/07/10 00:05:33
Talked offline; leaving this as-is because technic
| |
388 | |
389 // Update track buffer with overlapped buffers. | |
390 BufferQueue deleted_buffers; | |
391 scoped_refptr<StreamParserBuffer> buffer; | |
392 while (overlapped_range->GetNextBuffer(&buffer)) { | |
393 deleted_buffers.push_back(buffer); | |
394 } | |
395 UpdateTrackBuffer(deleted_buffers); | |
396 } | 503 } |
397 | 504 |
398 void SourceBufferStream::UpdateTrackBuffer(const BufferQueue& deleted_buffers) { | 505 void SourceBufferStream::UpdateTrackBuffer(const BufferQueue& deleted_buffers) { |
399 if (!track_buffer_.empty() || deleted_buffers.empty()) | 506 if (!track_buffer_.empty() || deleted_buffers.empty()) |
acolwell GONE FROM CHROMIUM
2012/07/09 18:15:55
nit: You can move the deleted_buffers.empty() into
vrk (LEFT CHROMIUM)
2012/07/10 00:05:33
Good point! Done.
| |
400 return; | 507 return; |
401 | 508 |
402 DCHECK(selected_range_); | 509 DCHECK(selected_range_); |
403 DCHECK(selected_range_->HasNextBufferPosition()); | 510 DCHECK(selected_range_->HasNextBufferPosition()); |
404 | 511 |
405 base::TimeDelta next_keyframe_timestamp = selected_range_->GetNextTimestamp(); | 512 base::TimeDelta next_keyframe_timestamp = selected_range_->GetNextTimestamp(); |
406 | 513 |
407 // If there is no gap between what was deleted and what was added, nothing | 514 // If there is no gap between what was deleted and what was added, nothing |
408 // should be added to the track buffer. | 515 // should be added to the track buffer. |
409 if (selected_range_->HasNextBuffer() && | 516 if (selected_range_->HasNextBuffer() && |
(...skipping 17 matching lines...) Expand all Loading... | |
427 } | 534 } |
428 | 535 |
429 // Otherwise, the |selected_range_| is not ready to return data, so add all | 536 // Otherwise, the |selected_range_| is not ready to return data, so add all |
430 // the deleted buffers into the |track_buffer_|. | 537 // the deleted buffers into the |track_buffer_|. |
431 track_buffer_ = deleted_buffers; | 538 track_buffer_ = deleted_buffers; |
432 | 539 |
433 // See if the next range contains the keyframe after the end of the | 540 // See if the next range contains the keyframe after the end of the |
434 // |track_buffer_|, and if so, change |selected_range_|. | 541 // |track_buffer_|, and if so, change |selected_range_|. |
435 RangeList::iterator next_range_itr = ++(GetSelectedRangeItr()); | 542 RangeList::iterator next_range_itr = ++(GetSelectedRangeItr()); |
436 if (next_range_itr != ranges_.end()) { | 543 if (next_range_itr != ranges_.end()) { |
437 (*next_range_itr)->SeekAfter(track_buffer_.back()->GetEndTimestamp()); | 544 (*next_range_itr)->SeekAheadPast( |
545 track_buffer_.back()->GetDecodeTimestamp()); | |
438 if ((*next_range_itr)->HasNextBuffer() && | 546 if ((*next_range_itr)->HasNextBuffer() && |
439 IsNextInSequence(track_buffer_.back(), | 547 selected_range_->IsNextInSequence( |
440 (*next_range_itr)->GetNextTimestamp())) { | 548 track_buffer_.back(), (*next_range_itr)->GetNextTimestamp())) { |
441 selected_range_ = *next_range_itr; | 549 selected_range_ = *next_range_itr; |
442 } | 550 } |
443 } | 551 } |
444 } | 552 } |
445 | 553 |
446 void SourceBufferStream::MergeWithAdjacentRangeIfNecessary( | 554 void SourceBufferStream::MergeWithAdjacentRangeIfNecessary( |
447 const RangeList::iterator& range_with_new_buffers_itr) { | 555 const RangeList::iterator& range_with_new_buffers_itr) { |
448 SourceBufferRange* range_with_new_buffers = *range_with_new_buffers_itr; | 556 SourceBufferRange* range_with_new_buffers = *range_with_new_buffers_itr; |
449 RangeList::iterator next_range_itr = range_with_new_buffers_itr; | 557 RangeList::iterator next_range_itr = range_with_new_buffers_itr; |
450 next_range_itr++; | 558 next_range_itr++; |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
508 } | 616 } |
509 | 617 |
510 base::TimeDelta SourceBufferStream::GetNextBufferTimestamp() { | 618 base::TimeDelta SourceBufferStream::GetNextBufferTimestamp() { |
511 if (!selected_range_) | 619 if (!selected_range_) |
512 return kNoTimestamp(); | 620 return kNoTimestamp(); |
513 | 621 |
514 DCHECK(selected_range_->HasNextBufferPosition()); | 622 DCHECK(selected_range_->HasNextBufferPosition()); |
515 return selected_range_->GetNextTimestamp(); | 623 return selected_range_->GetNextTimestamp(); |
516 } | 624 } |
517 | 625 |
626 base::TimeDelta SourceBufferStream::GetEndBufferTimestamp() { | |
627 if (!selected_range_) | |
628 return kNoTimestamp(); | |
629 return selected_range_->GetEndTimestamp(); | |
630 } | |
631 | |
518 SourceBufferStream::RangeList::iterator | 632 SourceBufferStream::RangeList::iterator |
519 SourceBufferStream::FindExistingRangeFor(const BufferQueue& new_buffers) { | 633 SourceBufferStream::FindExistingRangeFor(base::TimeDelta start_timestamp) { |
520 DCHECK(!new_buffers.empty()); | |
521 base::TimeDelta start_timestamp = new_buffers.front()->GetDecodeTimestamp(); | |
522 for (RangeList::iterator itr = ranges_.begin(); itr != ranges_.end(); itr++) { | 634 for (RangeList::iterator itr = ranges_.begin(); itr != ranges_.end(); itr++) { |
523 if ((*itr)->BelongsToRange(start_timestamp)) | 635 if ((*itr)->BelongsToRange(start_timestamp)) |
524 return itr; | 636 return itr; |
525 } | 637 } |
526 return ranges_.end(); | 638 return ranges_.end(); |
527 } | 639 } |
528 | 640 |
529 SourceBufferStream::RangeList::iterator | 641 SourceBufferStream::RangeList::iterator |
530 SourceBufferStream::AddToRanges(SourceBufferRange* new_range) { | 642 SourceBufferStream::AddToRanges(SourceBufferRange* new_range) { |
531 base::TimeDelta start_timestamp = new_range->GetStartTimestamp(); | 643 base::TimeDelta start_timestamp = new_range->GetStartTimestamp(); |
(...skipping 14 matching lines...) Expand all Loading... | |
546 break; | 658 break; |
547 } | 659 } |
548 DCHECK(itr != ranges_.end()); | 660 DCHECK(itr != ranges_.end()); |
549 return itr; | 661 return itr; |
550 } | 662 } |
551 | 663 |
552 Ranges<base::TimeDelta> SourceBufferStream::GetBufferedTime() const { | 664 Ranges<base::TimeDelta> SourceBufferStream::GetBufferedTime() const { |
553 Ranges<base::TimeDelta> ranges; | 665 Ranges<base::TimeDelta> ranges; |
554 for (RangeList::const_iterator itr = ranges_.begin(); | 666 for (RangeList::const_iterator itr = ranges_.begin(); |
555 itr != ranges_.end(); itr++) { | 667 itr != ranges_.end(); itr++) { |
556 ranges.Add((*itr)->GetStartTimestamp(), (*itr)->GetEndTimestamp()); | 668 ranges.Add((*itr)->GetStartTimestamp(), (*itr)->GetBufferedEndTimestamp()); |
557 } | 669 } |
558 return ranges; | 670 return ranges; |
559 } | 671 } |
560 | 672 |
561 void SourceBufferStream::EndOfStream() { | 673 void SourceBufferStream::EndOfStream() { |
562 DCHECK(CanEndOfStream()); | 674 DCHECK(CanEndOfStream()); |
563 end_of_stream_ = true; | 675 end_of_stream_ = true; |
564 } | 676 } |
565 | 677 |
566 bool SourceBufferStream::CanEndOfStream() const { | 678 bool SourceBufferStream::CanEndOfStream() const { |
567 return ranges_.empty() || selected_range_ == ranges_.back(); | 679 return ranges_.empty() || selected_range_ == ranges_.back(); |
568 } | 680 } |
569 | 681 |
570 SourceBufferRange::SourceBufferRange(const BufferQueue& new_buffers, | 682 SourceBufferRange::SourceBufferRange( |
571 base::TimeDelta media_segment_start_time) | 683 const BufferQueue& new_buffers, base::TimeDelta media_segment_start_time, |
684 const InterbufferDistanceCB& interbuffer_distance_cb) | |
572 : next_buffer_index_(-1), | 685 : next_buffer_index_(-1), |
573 waiting_for_keyframe_(false), | 686 waiting_for_keyframe_(false), |
574 next_keyframe_timestamp_(kNoTimestamp()), | 687 next_keyframe_timestamp_(kNoTimestamp()), |
575 media_segment_start_time_(media_segment_start_time) { | 688 media_segment_start_time_(media_segment_start_time), |
689 interbuffer_distance_cb_(interbuffer_distance_cb) { | |
576 DCHECK(!new_buffers.empty()); | 690 DCHECK(!new_buffers.empty()); |
577 DCHECK(new_buffers.front()->IsKeyframe()); | 691 DCHECK(new_buffers.front()->IsKeyframe()); |
692 DCHECK(!interbuffer_distance_cb.is_null()); | |
578 AppendToEnd(new_buffers); | 693 AppendToEnd(new_buffers); |
579 } | 694 } |
580 | 695 |
581 void SourceBufferRange::AppendToEnd(const BufferQueue& new_buffers) { | 696 void SourceBufferRange::AppendToEnd(const BufferQueue& new_buffers) { |
697 DCHECK(!new_buffers.empty()); | |
698 base::TimeDelta prev_timestamp = kNoTimestamp(); | |
699 if (!buffers_.empty()) | |
700 prev_timestamp = buffers_.back()->GetDecodeTimestamp(); | |
acolwell GONE FROM CHROMIUM
2012/07/09 18:15:55
nit: I believe this is dead code now. I don't see
vrk (LEFT CHROMIUM)
2012/07/10 00:05:33
D'oh, yes, should have reverted all changes to thi
| |
701 | |
582 for (BufferQueue::const_iterator itr = new_buffers.begin(); | 702 for (BufferQueue::const_iterator itr = new_buffers.begin(); |
583 itr != new_buffers.end(); itr++) { | 703 itr != new_buffers.end(); itr++) { |
584 DCHECK((*itr)->GetDuration() > base::TimeDelta()); | 704 base::TimeDelta current_timestamp = (*itr)->GetDecodeTimestamp(); |
acolwell GONE FROM CHROMIUM
2012/07/09 18:15:55
nit: It doesn't look like current_timestamp is use
vrk (LEFT CHROMIUM)
2012/07/10 00:05:33
Reverted.
| |
585 DCHECK((*itr)->GetDecodeTimestamp() != kNoTimestamp()); | 705 DCHECK(current_timestamp != kNoTimestamp()); |
586 buffers_.push_back(*itr); | 706 buffers_.push_back(*itr); |
707 | |
708 // Update keyframe index with new entry if applicable. | |
587 if ((*itr)->IsKeyframe()) { | 709 if ((*itr)->IsKeyframe()) { |
588 keyframe_map_.insert( | 710 keyframe_map_.insert( |
589 std::make_pair((*itr)->GetDecodeTimestamp(), buffers_.size() - 1)); | 711 std::make_pair((*itr)->GetDecodeTimestamp(), buffers_.size() - 1)); |
590 | 712 |
591 if (waiting_for_keyframe_ && | 713 if (waiting_for_keyframe_ && |
592 (*itr)->GetDecodeTimestamp() >= next_keyframe_timestamp_) { | 714 (*itr)->GetDecodeTimestamp() >= next_keyframe_timestamp_) { |
593 next_buffer_index_ = buffers_.size() - 1; | 715 next_buffer_index_ = buffers_.size() - 1; |
594 next_keyframe_timestamp_ = base::TimeDelta(); | 716 next_keyframe_timestamp_ = base::TimeDelta(); |
595 waiting_for_keyframe_ = false; | 717 waiting_for_keyframe_ = false; |
596 } | 718 } |
(...skipping 13 matching lines...) Expand all Loading... | |
610 // previous element if it did not return the element exactly equal to | 732 // previous element if it did not return the element exactly equal to |
611 // |timestamp|. | 733 // |timestamp|. |
612 if (result != keyframe_map_.begin() && | 734 if (result != keyframe_map_.begin() && |
613 (result == keyframe_map_.end() || result->first != timestamp)) { | 735 (result == keyframe_map_.end() || result->first != timestamp)) { |
614 result--; | 736 result--; |
615 } | 737 } |
616 next_buffer_index_ = result->second; | 738 next_buffer_index_ = result->second; |
617 DCHECK_LT(next_buffer_index_, static_cast<int>(buffers_.size())); | 739 DCHECK_LT(next_buffer_index_, static_cast<int>(buffers_.size())); |
618 } | 740 } |
619 | 741 |
620 void SourceBufferRange::SeekAfter(base::TimeDelta timestamp) { | 742 void SourceBufferRange::SeekAheadTo(base::TimeDelta timestamp) { |
743 SeekAhead(timestamp, false); | |
744 } | |
745 | |
746 void SourceBufferRange::SeekAheadPast(base::TimeDelta timestamp) { | |
747 SeekAhead(timestamp, true); | |
748 } | |
749 | |
750 void SourceBufferRange::SeekAhead(base::TimeDelta timestamp, | |
751 bool skip_given_timestamp) { | |
621 DCHECK(!keyframe_map_.empty()); | 752 DCHECK(!keyframe_map_.empty()); |
622 | 753 |
623 // lower_bound() returns the first element >= |timestamp|, so |result| is the | 754 KeyframeMap::iterator result = |
624 // value that we want. | 755 GetFirstKeyframeAfter(timestamp, skip_given_timestamp); |
625 KeyframeMap::iterator result = keyframe_map_.lower_bound(timestamp); | |
626 | 756 |
627 // If there isn't a keyframe after |timestamp|, then seek to end and return | 757 // If there isn't a keyframe after |timestamp|, then seek to end and return |
628 // kNoTimestamp to signal such. | 758 // kNoTimestamp to signal such. |
629 if (result == keyframe_map_.end()) { | 759 if (result == keyframe_map_.end()) { |
630 waiting_for_keyframe_ = true; | 760 waiting_for_keyframe_ = true; |
631 next_buffer_index_ = -1; | 761 next_buffer_index_ = -1; |
632 next_keyframe_timestamp_ = timestamp; | 762 next_keyframe_timestamp_ = timestamp; |
633 return; | 763 return; |
634 } | 764 } |
635 | |
636 next_buffer_index_ = result->second; | 765 next_buffer_index_ = result->second; |
637 DCHECK_LT(next_buffer_index_, static_cast<int>(buffers_.size())); | 766 DCHECK_LT(next_buffer_index_, static_cast<int>(buffers_.size())); |
638 } | 767 } |
639 | 768 |
640 SourceBufferRange* SourceBufferRange::SplitRange(base::TimeDelta timestamp) { | 769 SourceBufferRange* SourceBufferRange::SplitRange(base::TimeDelta timestamp) { |
641 // Find the first keyframe after |timestamp|. | 770 // Find the first keyframe after |timestamp|, not including |timestamp|. |
642 KeyframeMap::iterator new_beginning_keyframe = | 771 KeyframeMap::iterator new_beginning_keyframe = |
643 keyframe_map_.lower_bound(timestamp); | 772 GetFirstKeyframeAfter(timestamp, true); |
644 | 773 |
645 // If there is no keyframe after |timestamp|, we can't split the range. | 774 // If there is no keyframe after |timestamp|, we can't split the range. |
646 if (new_beginning_keyframe == keyframe_map_.end()) | 775 if (new_beginning_keyframe == keyframe_map_.end()) |
647 return NULL; | 776 return NULL; |
648 | 777 |
649 // Remove the data beginning at |keyframe_index| from |buffers_| and save it | 778 // Remove the data beginning at |keyframe_index| from |buffers_| and save it |
650 // into |removed_buffers|. | 779 // into |removed_buffers|. |
651 int keyframe_index = new_beginning_keyframe->second; | 780 int keyframe_index = new_beginning_keyframe->second; |
652 DCHECK_LT(keyframe_index, static_cast<int>(buffers_.size())); | 781 DCHECK_LT(keyframe_index, static_cast<int>(buffers_.size())); |
653 BufferQueue::iterator starting_point = buffers_.begin() + keyframe_index; | 782 BufferQueue::iterator starting_point = buffers_.begin() + keyframe_index; |
654 BufferQueue removed_buffers(starting_point, buffers_.end()); | 783 BufferQueue removed_buffers(starting_point, buffers_.end()); |
655 keyframe_map_.erase(new_beginning_keyframe, keyframe_map_.end()); | 784 keyframe_map_.erase(new_beginning_keyframe, keyframe_map_.end()); |
656 buffers_.erase(starting_point, buffers_.end()); | 785 buffers_.erase(starting_point, buffers_.end()); |
657 | 786 |
658 // Create a new range with |removed_buffers|. | 787 // Create a new range with |removed_buffers|. |
659 SourceBufferRange* split_range = | 788 SourceBufferRange* split_range = |
660 new SourceBufferRange(removed_buffers, kNoTimestamp()); | 789 new SourceBufferRange( |
790 removed_buffers, kNoTimestamp(), interbuffer_distance_cb_); | |
661 | 791 |
662 // If |next_buffer_index_| points to a buffer in |split_range|, update the | 792 // If |next_buffer_index_| points to a buffer in |split_range|, update the |
663 // |next_buffer_index_| of this range and |split_range| accordingly. | 793 // |next_buffer_index_| of this range and |split_range| accordingly. |
664 if (next_buffer_index_ >= static_cast<int>(buffers_.size())) { | 794 if (next_buffer_index_ >= static_cast<int>(buffers_.size())) { |
665 split_range->next_buffer_index_ = next_buffer_index_ - keyframe_index; | 795 split_range->next_buffer_index_ = next_buffer_index_ - keyframe_index; |
666 next_buffer_index_ = -1; | 796 next_buffer_index_ = -1; |
667 } | 797 } |
668 return split_range; | 798 return split_range; |
669 } | 799 } |
670 | 800 |
671 void SourceBufferRange::DeleteAll(BufferQueue* removed_buffers) { | 801 SourceBufferRange::KeyframeMap::iterator |
672 DeleteAfter(buffers_.begin(), removed_buffers); | 802 SourceBufferRange::GetFirstKeyframeAfter(base::TimeDelta timestamp, |
803 bool skip_given_timestamp) { | |
804 KeyframeMap::iterator result = keyframe_map_.lower_bound(timestamp); | |
805 // lower_bound() returns the first element >= |timestamp|, so if we don't want | |
806 // to include keyframes == |timestamp|, we have to increment the iterator | |
807 // accordingly. | |
808 if (skip_given_timestamp && | |
809 result != keyframe_map_.end() && result->first == timestamp) { | |
810 ++result; | |
811 } | |
812 return result; | |
673 } | 813 } |
674 | 814 |
675 void SourceBufferRange::DeleteAfter( | 815 bool SourceBufferRange::DeleteAll(BufferQueue* removed_buffers) { |
816 return TruncateAt(buffers_.begin(), removed_buffers); | |
817 } | |
818 | |
819 bool SourceBufferRange::TruncateAt( | |
676 scoped_refptr<StreamParserBuffer> buffer, BufferQueue* removed_buffers) { | 820 scoped_refptr<StreamParserBuffer> buffer, BufferQueue* removed_buffers) { |
677 // Find the place in |buffers_| where we will begin deleting data. | 821 // Find the place in |buffers_| where we will begin deleting data. |
678 BufferQueue::iterator starting_point = | 822 BufferQueue::iterator starting_point = |
679 std::lower_bound(buffers_.begin(), buffers_.end(), | 823 std::lower_bound(buffers_.begin(), buffers_.end(), |
680 buffer, | 824 buffer, |
681 BufferComparator); | 825 BufferComparator); |
682 DeleteAfter(starting_point, removed_buffers); | 826 return TruncateAt(starting_point, removed_buffers); |
683 } | 827 } |
684 | 828 |
685 void SourceBufferRange::DeleteAfter( | 829 bool SourceBufferRange::TruncateAt( |
686 const BufferQueue::iterator& starting_point, BufferQueue* removed_buffers) { | 830 const BufferQueue::iterator& starting_point, BufferQueue* removed_buffers) { |
687 DCHECK(removed_buffers); | 831 DCHECK(removed_buffers); |
832 DCHECK(removed_buffers->empty()); | |
833 | |
688 // Return if we're not deleting anything. | 834 // Return if we're not deleting anything. |
689 if (starting_point == buffers_.end()) | 835 if (starting_point == buffers_.end()) |
690 return; | 836 return false; |
691 | 837 |
692 // Reset the next buffer index if we will be deleting the buffer that's next | 838 // Reset the next buffer index if we will be deleting the buffer that's next |
693 // in sequence. | 839 // in sequence. |
694 if (HasNextBuffer() && | 840 bool removed_next_buffer = false; |
695 GetNextTimestamp() >= (*starting_point)->GetDecodeTimestamp()) { | 841 if (HasNextBufferPosition()) { |
696 // Save the buffers we're about to delete if the output parameter is valid. | 842 base::TimeDelta next_buffer_timestamp = GetNextTimestamp(); |
697 int starting_offset = starting_point - buffers_.begin(); | 843 if (next_buffer_timestamp == kNoTimestamp() || |
698 int next_buffer_offset = next_buffer_index_ - starting_offset; | 844 next_buffer_timestamp >= (*starting_point)->GetDecodeTimestamp()) { |
699 DCHECK_GE(next_buffer_offset, 0); | 845 if (HasNextBuffer()) { |
700 BufferQueue saved(starting_point + next_buffer_offset, buffers_.end()); | 846 int starting_offset = starting_point - buffers_.begin(); |
701 removed_buffers->swap(saved); | 847 int next_buffer_offset = next_buffer_index_ - starting_offset; |
702 next_buffer_index_ = -1; | 848 DCHECK_GE(next_buffer_offset, 0); |
849 BufferQueue saved(starting_point + next_buffer_offset, buffers_.end()); | |
850 removed_buffers->swap(saved); | |
851 } | |
852 next_buffer_index_ = -1; | |
853 removed_next_buffer = true; | |
854 } | |
703 } | 855 } |
704 | 856 |
705 // Remove keyframes from |starting_point| onward. | 857 // Remove keyframes from |starting_point| onward. |
706 KeyframeMap::iterator starting_point_keyframe = | 858 KeyframeMap::iterator starting_point_keyframe = |
707 keyframe_map_.lower_bound((*starting_point)->GetDecodeTimestamp()); | 859 keyframe_map_.lower_bound((*starting_point)->GetDecodeTimestamp()); |
708 keyframe_map_.erase(starting_point_keyframe, keyframe_map_.end()); | 860 keyframe_map_.erase(starting_point_keyframe, keyframe_map_.end()); |
709 | 861 |
710 // Remove everything from |starting_point| onward. | 862 // Remove everything from |starting_point| onward. |
711 buffers_.erase(starting_point, buffers_.end()); | 863 buffers_.erase(starting_point, buffers_.end()); |
864 return removed_next_buffer; | |
712 } | 865 } |
713 | 866 |
714 bool SourceBufferRange::GetNextBuffer( | 867 bool SourceBufferRange::GetNextBuffer( |
715 scoped_refptr<StreamParserBuffer>* out_buffer) { | 868 scoped_refptr<StreamParserBuffer>* out_buffer) { |
716 if (waiting_for_keyframe_ || | 869 if (waiting_for_keyframe_ || |
717 next_buffer_index_ >= static_cast<int>(buffers_.size())) { | 870 next_buffer_index_ >= static_cast<int>(buffers_.size())) { |
718 return false; | 871 return false; |
719 } | 872 } |
720 | 873 |
721 DCHECK_GE(next_buffer_index_, 0); | 874 DCHECK_GE(next_buffer_index_, 0); |
722 *out_buffer = buffers_.at(next_buffer_index_); | 875 *out_buffer = buffers_.at(next_buffer_index_); |
723 next_buffer_index_++; | 876 next_buffer_index_++; |
724 return true; | 877 return true; |
725 } | 878 } |
726 | 879 |
727 bool SourceBufferRange::HasNextBuffer() const { | 880 bool SourceBufferRange::HasNextBuffer() const { |
728 return next_buffer_index_ >= 0 && | 881 return next_buffer_index_ >= 0 && |
729 next_buffer_index_ < static_cast<int>(buffers_.size()); | 882 next_buffer_index_ < static_cast<int>(buffers_.size()); |
730 } | 883 } |
731 | 884 |
732 base::TimeDelta SourceBufferRange::GetNextTimestamp() const { | 885 base::TimeDelta SourceBufferRange::GetNextTimestamp() const { |
733 DCHECK(!buffers_.empty()); | 886 DCHECK(!buffers_.empty()); |
734 DCHECK(HasNextBufferPosition()); | 887 DCHECK(HasNextBufferPosition()); |
735 | 888 |
736 if (waiting_for_keyframe_) | 889 if (waiting_for_keyframe_) |
737 return next_keyframe_timestamp_; | 890 return next_keyframe_timestamp_; |
738 | 891 |
739 if (next_buffer_index_ >= static_cast<int>(buffers_.size())) | 892 if (next_buffer_index_ >= static_cast<int>(buffers_.size())) |
740 return buffers_.back()->GetEndTimestamp(); | 893 return kNoTimestamp(); |
741 | 894 |
742 return buffers_.at(next_buffer_index_)->GetDecodeTimestamp(); | 895 return buffers_.at(next_buffer_index_)->GetDecodeTimestamp(); |
743 } | 896 } |
744 | 897 |
745 bool SourceBufferRange::HasNextBufferPosition() const { | 898 bool SourceBufferRange::HasNextBufferPosition() const { |
746 return next_buffer_index_ >= 0 || waiting_for_keyframe_; | 899 return next_buffer_index_ >= 0 || waiting_for_keyframe_; |
747 } | 900 } |
748 | 901 |
749 void SourceBufferRange::AppendToEnd(const SourceBufferRange& range, | 902 void SourceBufferRange::AppendToEnd(const SourceBufferRange& range, |
750 bool transfer_current_position) { | 903 bool transfer_current_position) { |
(...skipping 17 matching lines...) Expand all Loading... | |
768 } | 921 } |
769 | 922 |
770 bool SourceBufferRange::BelongsToRange(base::TimeDelta timestamp) const { | 923 bool SourceBufferRange::BelongsToRange(base::TimeDelta timestamp) const { |
771 DCHECK(!buffers_.empty()); | 924 DCHECK(!buffers_.empty()); |
772 | 925 |
773 return (IsNextInSequence(buffers_.back(), timestamp) || | 926 return (IsNextInSequence(buffers_.back(), timestamp) || |
774 (GetStartTimestamp() <= timestamp && timestamp <= GetEndTimestamp())); | 927 (GetStartTimestamp() <= timestamp && timestamp <= GetEndTimestamp())); |
775 } | 928 } |
776 | 929 |
777 bool SourceBufferRange::CanSeekTo(base::TimeDelta timestamp) const { | 930 bool SourceBufferRange::CanSeekTo(base::TimeDelta timestamp) const { |
778 return !keyframe_map_.empty() && GetStartTimestamp() <= timestamp && | 931 base::TimeDelta start_range = |
acolwell GONE FROM CHROMIUM
2012/07/09 18:15:55
nit: s/start_range/start_timestamp?
vrk (LEFT CHROMIUM)
2012/07/10 00:05:33
Done.
| |
779 GetEndTimestamp() > timestamp; | 932 std::max(base::TimeDelta(), GetStartTimestamp() - GetFudgeRoom()); |
933 return !keyframe_map_.empty() && start_range <= timestamp && | |
934 timestamp < GetBufferedEndTimestamp(); | |
780 } | 935 } |
781 | 936 |
782 bool SourceBufferRange::CompletelyOverlaps( | 937 bool SourceBufferRange::CompletelyOverlaps( |
783 const SourceBufferRange& range) const { | 938 const SourceBufferRange& range) const { |
784 return GetStartTimestamp() <= range.GetStartTimestamp() && | 939 return GetStartTimestamp() <= range.GetStartTimestamp() && |
785 GetEndTimestamp() >= range.GetEndTimestamp(); | 940 GetEndTimestamp() >= range.GetEndTimestamp(); |
786 } | 941 } |
787 | 942 |
788 bool SourceBufferRange::EndOverlaps(const SourceBufferRange& range) const { | 943 bool SourceBufferRange::EndOverlaps(const SourceBufferRange& range) const { |
789 return range.GetStartTimestamp() < GetEndTimestamp() && | 944 return range.GetStartTimestamp() <= GetEndTimestamp() && |
790 GetEndTimestamp() < range.GetEndTimestamp(); | 945 GetEndTimestamp() < range.GetEndTimestamp(); |
791 } | 946 } |
792 | 947 |
793 base::TimeDelta SourceBufferRange::GetStartTimestamp() const { | 948 base::TimeDelta SourceBufferRange::GetStartTimestamp() const { |
794 DCHECK(!buffers_.empty()); | 949 DCHECK(!buffers_.empty()); |
795 base::TimeDelta start_timestamp = media_segment_start_time_; | 950 base::TimeDelta start_timestamp = media_segment_start_time_; |
796 if (start_timestamp == kNoTimestamp()) | 951 if (start_timestamp == kNoTimestamp()) |
797 start_timestamp = buffers_.front()->GetDecodeTimestamp(); | 952 start_timestamp = buffers_.front()->GetDecodeTimestamp(); |
798 return start_timestamp; | 953 return start_timestamp; |
799 } | 954 } |
800 | 955 |
801 base::TimeDelta SourceBufferRange::GetEndTimestamp() const { | 956 base::TimeDelta SourceBufferRange::GetEndTimestamp() const { |
802 DCHECK(!buffers_.empty()); | 957 DCHECK(!buffers_.empty()); |
803 return buffers_.back()->GetEndTimestamp(); | 958 return buffers_.back()->GetDecodeTimestamp(); |
959 } | |
960 | |
961 base::TimeDelta SourceBufferRange::GetBufferedEndTimestamp() const { | |
962 DCHECK(!buffers_.empty()); | |
963 base::TimeDelta duration = buffers_.back()->GetDuration(); | |
964 if (duration == kNoTimestamp() || duration == base::TimeDelta()) | |
965 duration = GetApproximateDuration(); | |
966 return GetEndTimestamp() + duration; | |
967 } | |
968 | |
969 bool SourceBufferRange::IsNextInSequence( | |
970 const scoped_refptr<media::StreamParserBuffer>& buffer, | |
971 base::TimeDelta timestamp) const { | |
972 return buffer->GetDecodeTimestamp() < timestamp && | |
973 timestamp <= buffer->GetDecodeTimestamp() + GetFudgeRoom(); | |
974 } | |
975 | |
976 base::TimeDelta SourceBufferRange::GetFudgeRoom() const { | |
977 // Because we do not know exactly when is the next timestamp, any buffer | |
978 // that starts within 2x the approximate duration of a buffer is considered | |
979 // within this range. | |
980 return 2 * GetApproximateDuration(); | |
981 } | |
982 | |
983 base::TimeDelta SourceBufferRange::GetApproximateDuration() const { | |
984 base::TimeDelta max_interbuffer_distance = interbuffer_distance_cb_.Run(); | |
985 if (max_interbuffer_distance == kNoTimestamp()) | |
986 return base::TimeDelta::FromMilliseconds(kDefaultBufferDurationInMs); | |
acolwell GONE FROM CHROMIUM
2012/07/09 18:15:55
nit: I think the callback should always return som
vrk (LEFT CHROMIUM)
2012/07/10 00:05:33
Yes, that's a good point. Logic shuffled!
| |
987 return max_interbuffer_distance; | |
804 } | 988 } |
805 | 989 |
806 } // namespace media | 990 } // namespace media |
OLD | NEW |