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/bind.h" |
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
79 // starting at the buffer that had been at |next_buffer_index_|. | 79 // starting at the buffer that had been at |next_buffer_index_|. |
80 // Returns true if the |next_buffer_index_| is reset. Note that this method | 80 // Returns true if the |next_buffer_index_| is reset. Note that this method |
81 // may return true even if it does not add any buffers to |deleted_buffers|. | 81 // may return true even if it does not add any buffers to |deleted_buffers|. |
82 // This indicates that the range had not buffered |next_buffer_index_|, but | 82 // This indicates that the range had not buffered |next_buffer_index_|, but |
83 // a buffer at that position would have been deleted. | 83 // a buffer at that position would have been deleted. |
84 bool TruncateAt(scoped_refptr<StreamParserBuffer> buffer, | 84 bool TruncateAt(scoped_refptr<StreamParserBuffer> buffer, |
85 BufferQueue* deleted_buffers); | 85 BufferQueue* deleted_buffers); |
86 // Deletes all buffers in range. | 86 // Deletes all buffers in range. |
87 bool DeleteAll(BufferQueue* deleted_buffers); | 87 bool DeleteAll(BufferQueue* deleted_buffers); |
88 | 88 |
89 // Attempts to free |bytes| data from the range, preferring to delete at the | |
90 // beginning of the range. Deletes data in GOPS at a time so that the range | |
91 // always begins with a keyframe. Returns the number of bytes freed. | |
92 int FreeFromStart(int bytes); | |
93 | |
94 // Attempts to free |bytes| data from the range, preferring to delete at the | |
95 // end of the range. Returns the number of bytes freed. | |
96 int FreeFromEnd(int bytes); | |
97 | |
89 // Updates |out_buffer| with the next buffer in presentation order. Seek() | 98 // Updates |out_buffer| with the next buffer in presentation order. Seek() |
90 // must be called before calls to GetNextBuffer(), and buffers are returned | 99 // must be called before calls to GetNextBuffer(), and buffers are returned |
91 // in order from the last call to Seek(). Returns true if |out_buffer| is | 100 // in order from the last call to Seek(). Returns true if |out_buffer| is |
92 // filled with a valid buffer, false if there is not enough data to fulfill | 101 // filled with a valid buffer, false if there is not enough data to fulfill |
93 // the request. | 102 // the request. |
94 bool GetNextBuffer(scoped_refptr<StreamParserBuffer>* out_buffer); | 103 bool GetNextBuffer(scoped_refptr<StreamParserBuffer>* out_buffer); |
95 bool HasNextBuffer() const; | 104 bool HasNextBuffer() const; |
96 | 105 |
97 // Returns the config ID for the buffer that will be returned by | 106 // Returns the config ID for the buffer that will be returned by |
98 // GetNextBuffer(). | 107 // GetNextBuffer(). |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
137 // Returns true if the end of this range contains buffers that overlaps with | 146 // Returns true if the end of this range contains buffers that overlaps with |
138 // the beginning of |range|. | 147 // the beginning of |range|. |
139 bool EndOverlaps(const SourceBufferRange& range) const; | 148 bool EndOverlaps(const SourceBufferRange& range) const; |
140 | 149 |
141 // Returns true if |timestamp| is the timestamp of the next buffer in | 150 // Returns true if |timestamp| is the timestamp of the next buffer in |
142 // sequence after |buffer|, false otherwise. | 151 // sequence after |buffer|, false otherwise. |
143 bool IsNextInSequence( | 152 bool IsNextInSequence( |
144 const scoped_refptr<media::StreamParserBuffer>& buffer, | 153 const scoped_refptr<media::StreamParserBuffer>& buffer, |
145 base::TimeDelta timestamp) const; | 154 base::TimeDelta timestamp) const; |
146 | 155 |
156 int size_in_bytes() const { return size_in_bytes_; } | |
157 | |
147 private: | 158 private: |
148 typedef std::map<base::TimeDelta, size_t> KeyframeMap; | 159 typedef std::map<base::TimeDelta, size_t> KeyframeMap; |
149 | 160 |
150 // Seeks the range to the next keyframe after |timestamp|. If | 161 // Seeks the range to the next keyframe after |timestamp|. If |
151 // |skip_given_timestamp| is true, the seek will go to a keyframe with a | 162 // |skip_given_timestamp| is true, the seek will go to a keyframe with a |
152 // timestamp strictly greater than |timestamp|. | 163 // timestamp strictly greater than |timestamp|. |
153 void SeekAhead(base::TimeDelta timestamp, bool skip_given_timestamp); | 164 void SeekAhead(base::TimeDelta timestamp, bool skip_given_timestamp); |
154 | 165 |
155 // Returns an iterator in |keyframe_map_| pointing to the next keyframe after | 166 // Returns an iterator in |keyframe_map_| pointing to the next keyframe after |
156 // |timestamp|. If |skip_given_timestamp| is true, this returns the first | 167 // |timestamp|. If |skip_given_timestamp| is true, this returns the first |
157 // keyframe with a timestamp strictly greater than |timestamp|. | 168 // keyframe with a timestamp strictly greater than |timestamp|. |
158 KeyframeMap::iterator GetFirstKeyframeAt( | 169 KeyframeMap::iterator GetFirstKeyframeAt( |
159 base::TimeDelta timestamp, bool skip_given_timestamp); | 170 base::TimeDelta timestamp, bool skip_given_timestamp); |
160 | 171 |
172 // Returns an iterator in |keyframe_map_| pointing to the first keyframe | |
173 // before or at |timestamp|. | |
174 KeyframeMap::iterator GetFirstKeyframeBefore(base::TimeDelta timestamp); | |
175 | |
161 // Helper method to delete buffers in |buffers_| starting at | 176 // Helper method to delete buffers in |buffers_| starting at |
162 // |starting_point|, an iterator in |buffers_|. | 177 // |starting_point|, an iterator in |buffers_|. |
163 bool TruncateAt(const BufferQueue::iterator& starting_point, | 178 bool TruncateAt(const BufferQueue::iterator& starting_point, |
164 BufferQueue* deleted_buffers); | 179 BufferQueue* deleted_buffers); |
165 | 180 |
181 // Frees the buffers in |buffers_| from [|start_point|,|ending_point|) and | |
182 // updates the |size_in_bytes_| accordingly. Does not update |keyframe_map_|. | |
183 void FreeBufferRange(const BufferQueue::iterator& starting_point, | |
184 const BufferQueue::iterator& ending_point); | |
185 | |
166 // Returns the distance in time estimating how far from the beginning or end | 186 // Returns the distance in time estimating how far from the beginning or end |
167 // of this range a buffer can be to considered in the range. | 187 // of this range a buffer can be to considered in the range. |
168 base::TimeDelta GetFudgeRoom() const; | 188 base::TimeDelta GetFudgeRoom() const; |
169 | 189 |
170 // Returns the approximate duration of a buffer in this range. | 190 // Returns the approximate duration of a buffer in this range. |
171 base::TimeDelta GetApproximateDuration() const; | 191 base::TimeDelta GetApproximateDuration() const; |
172 | 192 |
173 // An ordered list of buffers in this range. | 193 // An ordered list of buffers in this range. |
174 BufferQueue buffers_; | 194 BufferQueue buffers_; |
175 | 195 |
(...skipping 18 matching lines...) Expand all Loading... | |
194 // |buffers_|. |media_segment_start_time_| is kNoTimestamp() if this range | 214 // |buffers_|. |media_segment_start_time_| is kNoTimestamp() if this range |
195 // does not start at the beginning of a media segment, which can only happen | 215 // does not start at the beginning of a media segment, which can only happen |
196 // garbage collection or after an end overlap that results in a split range | 216 // garbage collection or after an end overlap that results in a split range |
197 // (we don't have a way of knowing the media segment timestamp for the new | 217 // (we don't have a way of knowing the media segment timestamp for the new |
198 // range). | 218 // range). |
199 base::TimeDelta media_segment_start_time_; | 219 base::TimeDelta media_segment_start_time_; |
200 | 220 |
201 // Called to get the largest interbuffer distance seen so far in the stream. | 221 // Called to get the largest interbuffer distance seen so far in the stream. |
202 InterbufferDistanceCB interbuffer_distance_cb_; | 222 InterbufferDistanceCB interbuffer_distance_cb_; |
203 | 223 |
224 // Stores the amount of memory taken up by the data in |buffers_|. | |
225 int size_in_bytes_; | |
226 | |
204 DISALLOW_COPY_AND_ASSIGN(SourceBufferRange); | 227 DISALLOW_COPY_AND_ASSIGN(SourceBufferRange); |
205 }; | 228 }; |
206 | 229 |
207 } // namespace media | 230 } // namespace media |
208 | 231 |
209 // Helper method that returns true if |ranges| is sorted in increasing order, | 232 // Helper method that returns true if |ranges| is sorted in increasing order, |
210 // false otherwise. | 233 // false otherwise. |
211 static bool IsRangeListSorted( | 234 static bool IsRangeListSorted( |
212 const std::list<media::SourceBufferRange*>& ranges) { | 235 const std::list<media::SourceBufferRange*>& ranges) { |
213 base::TimeDelta prev = media::kNoTimestamp(); | 236 base::TimeDelta prev = media::kNoTimestamp(); |
(...skipping 15 matching lines...) Expand all Loading... | |
229 | 252 |
230 // An arbitrarily-chosen number to estimate the duration of a buffer if none | 253 // An arbitrarily-chosen number to estimate the duration of a buffer if none |
231 // is set and there's not enough information to get a better estimate. | 254 // is set and there's not enough information to get a better estimate. |
232 static int kDefaultBufferDurationInMs = 125; | 255 static int kDefaultBufferDurationInMs = 125; |
233 | 256 |
234 // The amount of time the beginning of the buffered data can differ from the | 257 // The amount of time the beginning of the buffered data can differ from the |
235 // start time in order to still be considered the start of stream. | 258 // start time in order to still be considered the start of stream. |
236 static base::TimeDelta kSeekToStartFudgeRoom() { | 259 static base::TimeDelta kSeekToStartFudgeRoom() { |
237 return base::TimeDelta::FromMilliseconds(1000); | 260 return base::TimeDelta::FromMilliseconds(1000); |
238 } | 261 } |
262 // The maximum amount of data in bytes the stream will keep in memory. | |
263 static int kDefaultMemoryLimit = 20 * 1024 * 1024; | |
vrk (LEFT CHROMIUM)
2012/08/04 01:32:31
Not sure what I should actually set this to.
Also
acolwell GONE FROM CHROMIUM
2012/08/06 16:44:52
I think we should have audio & video specific limi
vrk (LEFT CHROMIUM)
2012/08/06 20:27:14
Done.
| |
239 | 264 |
240 namespace media { | 265 namespace media { |
241 | 266 |
242 SourceBufferStream::SourceBufferStream(const AudioDecoderConfig& audio_config) | 267 SourceBufferStream::SourceBufferStream(const AudioDecoderConfig& audio_config) |
243 : current_config_index_(0), | 268 : current_config_index_(0), |
244 append_config_index_(0), | 269 append_config_index_(0), |
245 audio_configs_(1), | 270 audio_configs_(1), |
246 video_configs_(0), | 271 video_configs_(0), |
247 stream_start_time_(kNoTimestamp()), | 272 stream_start_time_(kNoTimestamp()), |
248 seek_pending_(false), | 273 seek_pending_(false), |
249 seek_buffer_timestamp_(kNoTimestamp()), | 274 seek_buffer_timestamp_(kNoTimestamp()), |
250 selected_range_(NULL), | 275 selected_range_(NULL), |
251 media_segment_start_time_(kNoTimestamp()), | 276 media_segment_start_time_(kNoTimestamp()), |
252 range_for_next_append_(ranges_.end()), | 277 range_for_next_append_(ranges_.end()), |
253 new_media_segment_(false), | 278 new_media_segment_(false), |
254 last_buffer_timestamp_(kNoTimestamp()), | 279 last_buffer_timestamp_(kNoTimestamp()), |
255 max_interbuffer_distance_(kNoTimestamp()) { | 280 max_interbuffer_distance_(kNoTimestamp()), |
281 memory_limit_(kDefaultMemoryLimit) { | |
256 audio_configs_[0] = new AudioDecoderConfig(); | 282 audio_configs_[0] = new AudioDecoderConfig(); |
257 audio_configs_[0]->CopyFrom(audio_config); | 283 audio_configs_[0]->CopyFrom(audio_config); |
258 } | 284 } |
259 | 285 |
260 SourceBufferStream::SourceBufferStream(const VideoDecoderConfig& video_config) | 286 SourceBufferStream::SourceBufferStream(const VideoDecoderConfig& video_config) |
261 : current_config_index_(0), | 287 : current_config_index_(0), |
262 append_config_index_(0), | 288 append_config_index_(0), |
263 audio_configs_(0), | 289 audio_configs_(0), |
264 video_configs_(1), | 290 video_configs_(1), |
265 stream_start_time_(kNoTimestamp()), | 291 stream_start_time_(kNoTimestamp()), |
266 seek_pending_(false), | 292 seek_pending_(false), |
267 seek_buffer_timestamp_(kNoTimestamp()), | 293 seek_buffer_timestamp_(kNoTimestamp()), |
268 selected_range_(NULL), | 294 selected_range_(NULL), |
269 media_segment_start_time_(kNoTimestamp()), | 295 media_segment_start_time_(kNoTimestamp()), |
270 range_for_next_append_(ranges_.end()), | 296 range_for_next_append_(ranges_.end()), |
271 new_media_segment_(false), | 297 new_media_segment_(false), |
272 last_buffer_timestamp_(kNoTimestamp()), | 298 last_buffer_timestamp_(kNoTimestamp()), |
273 max_interbuffer_distance_(kNoTimestamp()) { | 299 max_interbuffer_distance_(kNoTimestamp()), |
300 memory_limit_(kDefaultMemoryLimit) { | |
274 video_configs_[0] = new VideoDecoderConfig(); | 301 video_configs_[0] = new VideoDecoderConfig(); |
275 video_configs_[0]->CopyFrom(video_config); | 302 video_configs_[0]->CopyFrom(video_config); |
276 } | 303 } |
277 | 304 |
278 SourceBufferStream::~SourceBufferStream() { | 305 SourceBufferStream::~SourceBufferStream() { |
279 while (!ranges_.empty()) { | 306 while (!ranges_.empty()) { |
280 delete ranges_.front(); | 307 delete ranges_.front(); |
281 ranges_.pop_front(); | 308 ranges_.pop_front(); |
282 } | 309 } |
283 | 310 |
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
382 UpdateTrackBuffer(deleted_buffers); | 409 UpdateTrackBuffer(deleted_buffers); |
383 } else { | 410 } else { |
384 // If we've deleted the next buffer but |deleted_buffers| is empty, | 411 // If we've deleted the next buffer but |deleted_buffers| is empty, |
385 // that means we need to seek past the timestamp of the last buffer in | 412 // that means we need to seek past the timestamp of the last buffer in |
386 // the range (i.e. the keyframe timestamp needs to be strictly greater | 413 // the range (i.e. the keyframe timestamp needs to be strictly greater |
387 // than |end_buffer_timestamp|). | 414 // than |end_buffer_timestamp|). |
388 selected_range_->SeekAheadPast(end_buffer_timestamp); | 415 selected_range_->SeekAheadPast(end_buffer_timestamp); |
389 } | 416 } |
390 } | 417 } |
391 | 418 |
419 GarbageCollectIfNeeded(); | |
420 | |
392 DCHECK(IsRangeListSorted(ranges_)); | 421 DCHECK(IsRangeListSorted(ranges_)); |
393 DCHECK(OnlySelectedRangeIsSeeked()); | 422 DCHECK(OnlySelectedRangeIsSeeked()); |
394 return true; | 423 return true; |
395 } | 424 } |
396 | 425 |
397 bool SourceBufferStream::ShouldSeekToStartOfBuffered( | 426 bool SourceBufferStream::ShouldSeekToStartOfBuffered( |
398 base::TimeDelta seek_timestamp) const { | 427 base::TimeDelta seek_timestamp) const { |
399 if (ranges_.empty()) | 428 if (ranges_.empty()) |
400 return false; | 429 return false; |
401 base::TimeDelta beginning_of_buffered = | 430 base::TimeDelta beginning_of_buffered = |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
453 } | 482 } |
454 } | 483 } |
455 | 484 |
456 void SourceBufferStream::SetConfigIds(const BufferQueue& buffers) { | 485 void SourceBufferStream::SetConfigIds(const BufferQueue& buffers) { |
457 for (BufferQueue::const_iterator itr = buffers.begin(); | 486 for (BufferQueue::const_iterator itr = buffers.begin(); |
458 itr != buffers.end(); ++itr) { | 487 itr != buffers.end(); ++itr) { |
459 (*itr)->SetConfigId(append_config_index_); | 488 (*itr)->SetConfigId(append_config_index_); |
460 } | 489 } |
461 } | 490 } |
462 | 491 |
492 void SourceBufferStream::GarbageCollectIfNeeded() { | |
493 // Compute size of |ranges_|. | |
494 int ranges_size = 0; | |
495 for (RangeList::iterator itr = ranges_.begin(); itr != ranges_.end(); ++itr) | |
496 ranges_size += (*itr)->size_in_bytes(); | |
497 | |
498 // Return if we're under or at the memory limit. | |
499 if (ranges_size <= memory_limit_) | |
500 return; | |
501 | |
502 int bytes_to_free = ranges_size - memory_limit_; | |
503 | |
504 // Begin deleting from the front. | |
505 while (!ranges_.empty() && bytes_to_free > 0) { | |
506 SourceBufferRange* current_range = ranges_.front(); | |
507 bytes_to_free -= current_range->FreeFromStart(bytes_to_free); | |
508 | |
509 // If the |current_range| still has data left after freeing, we should not | |
510 // delete any more data in this direction. | |
511 if (current_range->size_in_bytes() > 0) | |
512 break; | |
513 | |
514 DCHECK_NE(current_range, selected_range_); | |
515 delete current_range; | |
516 ranges_.pop_front(); | |
517 } | |
518 | |
519 // Begin deleting from the back. | |
520 while (!ranges_.empty() && bytes_to_free > 0) { | |
521 SourceBufferRange* current_range = ranges_.back(); | |
522 bytes_to_free -= current_range->FreeFromEnd(bytes_to_free); | |
523 | |
524 // If the |current_range| still has data left after freeing, we should not | |
525 // delete any more data in this direction. | |
526 if (current_range->size_in_bytes() > 0) | |
527 break; | |
528 | |
529 DCHECK_NE(current_range, selected_range_); | |
530 delete current_range; | |
531 ranges_.pop_back(); | |
532 } | |
533 } | |
534 | |
463 void SourceBufferStream::InsertIntoExistingRange( | 535 void SourceBufferStream::InsertIntoExistingRange( |
464 const RangeList::iterator& range_for_new_buffers_itr, | 536 const RangeList::iterator& range_for_new_buffers_itr, |
465 const BufferQueue& new_buffers, | 537 const BufferQueue& new_buffers, |
466 bool* deleted_next_buffer, BufferQueue* deleted_buffers) { | 538 bool* deleted_next_buffer, BufferQueue* deleted_buffers) { |
467 DCHECK(deleted_next_buffer); | 539 DCHECK(deleted_next_buffer); |
468 DCHECK(deleted_buffers); | 540 DCHECK(deleted_buffers); |
469 | 541 |
470 SourceBufferRange* range_for_new_buffers = *range_for_new_buffers_itr; | 542 SourceBufferRange* range_for_new_buffers = *range_for_new_buffers_itr; |
471 | 543 |
472 // If this is a simple case where we can just append to the end of the range, | 544 // If this is a simple case where we can just append to the end of the range, |
(...skipping 396 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
869 current_config_index_ = selected_range_->GetNextConfigId(); | 941 current_config_index_ = selected_range_->GetNextConfigId(); |
870 } | 942 } |
871 | 943 |
872 SourceBufferRange::SourceBufferRange( | 944 SourceBufferRange::SourceBufferRange( |
873 const BufferQueue& new_buffers, base::TimeDelta media_segment_start_time, | 945 const BufferQueue& new_buffers, base::TimeDelta media_segment_start_time, |
874 const InterbufferDistanceCB& interbuffer_distance_cb) | 946 const InterbufferDistanceCB& interbuffer_distance_cb) |
875 : next_buffer_index_(-1), | 947 : next_buffer_index_(-1), |
876 waiting_for_keyframe_(false), | 948 waiting_for_keyframe_(false), |
877 next_keyframe_timestamp_(kNoTimestamp()), | 949 next_keyframe_timestamp_(kNoTimestamp()), |
878 media_segment_start_time_(media_segment_start_time), | 950 media_segment_start_time_(media_segment_start_time), |
879 interbuffer_distance_cb_(interbuffer_distance_cb) { | 951 interbuffer_distance_cb_(interbuffer_distance_cb), |
952 size_in_bytes_(0) { | |
880 DCHECK(!new_buffers.empty()); | 953 DCHECK(!new_buffers.empty()); |
881 DCHECK(new_buffers.front()->IsKeyframe()); | 954 DCHECK(new_buffers.front()->IsKeyframe()); |
882 DCHECK(!interbuffer_distance_cb.is_null()); | 955 DCHECK(!interbuffer_distance_cb.is_null()); |
883 AppendBuffersToEnd(new_buffers); | 956 AppendBuffersToEnd(new_buffers); |
884 } | 957 } |
885 | 958 |
886 void SourceBufferRange::AppendBuffersToEnd(const BufferQueue& new_buffers) { | 959 void SourceBufferRange::AppendBuffersToEnd(const BufferQueue& new_buffers) { |
887 for (BufferQueue::const_iterator itr = new_buffers.begin(); | 960 for (BufferQueue::const_iterator itr = new_buffers.begin(); |
888 itr != new_buffers.end(); ++itr) { | 961 itr != new_buffers.end(); ++itr) { |
889 DCHECK((*itr)->GetDecodeTimestamp() != kNoTimestamp()); | 962 DCHECK((*itr)->GetDecodeTimestamp() != kNoTimestamp()); |
890 buffers_.push_back(*itr); | 963 buffers_.push_back(*itr); |
964 size_in_bytes_ += (*itr)->GetDataSize(); | |
965 | |
891 if ((*itr)->IsKeyframe()) { | 966 if ((*itr)->IsKeyframe()) { |
892 keyframe_map_.insert( | 967 keyframe_map_.insert( |
893 std::make_pair((*itr)->GetDecodeTimestamp(), buffers_.size() - 1)); | 968 std::make_pair((*itr)->GetDecodeTimestamp(), buffers_.size() - 1)); |
894 | 969 |
895 if (waiting_for_keyframe_ && | 970 if (waiting_for_keyframe_ && |
896 (*itr)->GetDecodeTimestamp() >= next_keyframe_timestamp_) { | 971 (*itr)->GetDecodeTimestamp() >= next_keyframe_timestamp_) { |
897 next_buffer_index_ = buffers_.size() - 1; | 972 next_buffer_index_ = buffers_.size() - 1; |
898 next_keyframe_timestamp_ = base::TimeDelta(); | 973 next_keyframe_timestamp_ = base::TimeDelta(); |
899 waiting_for_keyframe_ = false; | 974 waiting_for_keyframe_ = false; |
900 } | 975 } |
901 } | 976 } |
902 } | 977 } |
903 } | 978 } |
904 | 979 |
905 void SourceBufferRange::Seek(base::TimeDelta timestamp) { | 980 void SourceBufferRange::Seek(base::TimeDelta timestamp) { |
906 DCHECK(CanSeekTo(timestamp)); | 981 DCHECK(CanSeekTo(timestamp)); |
907 DCHECK(!keyframe_map_.empty()); | 982 DCHECK(!keyframe_map_.empty()); |
908 | 983 |
909 next_keyframe_timestamp_ = base::TimeDelta(); | 984 next_keyframe_timestamp_ = base::TimeDelta(); |
910 waiting_for_keyframe_ = false; | 985 waiting_for_keyframe_ = false; |
911 | 986 |
912 KeyframeMap::iterator result = keyframe_map_.lower_bound(timestamp); | 987 KeyframeMap::iterator result = GetFirstKeyframeBefore(timestamp); |
913 // lower_bound() returns the first element >= |timestamp|, so we want the | |
914 // previous element if it did not return the element exactly equal to | |
915 // |timestamp|. | |
916 if (result != keyframe_map_.begin() && | |
917 (result == keyframe_map_.end() || result->first != timestamp)) { | |
918 result--; | |
919 } | |
920 next_buffer_index_ = result->second; | 988 next_buffer_index_ = result->second; |
921 DCHECK_LT(next_buffer_index_, static_cast<int>(buffers_.size())); | 989 DCHECK_LT(next_buffer_index_, static_cast<int>(buffers_.size())); |
922 } | 990 } |
923 | 991 |
924 void SourceBufferRange::SeekAheadTo(base::TimeDelta timestamp) { | 992 void SourceBufferRange::SeekAheadTo(base::TimeDelta timestamp) { |
925 SeekAhead(timestamp, false); | 993 SeekAhead(timestamp, false); |
926 } | 994 } |
927 | 995 |
928 void SourceBufferRange::SeekAheadPast(base::TimeDelta timestamp) { | 996 void SourceBufferRange::SeekAheadPast(base::TimeDelta timestamp) { |
929 SeekAhead(timestamp, true); | 997 SeekAhead(timestamp, true); |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
962 if (new_beginning_keyframe == keyframe_map_.end()) | 1030 if (new_beginning_keyframe == keyframe_map_.end()) |
963 return NULL; | 1031 return NULL; |
964 | 1032 |
965 // Remove the data beginning at |keyframe_index| from |buffers_| and save it | 1033 // Remove the data beginning at |keyframe_index| from |buffers_| and save it |
966 // into |removed_buffers|. | 1034 // into |removed_buffers|. |
967 int keyframe_index = new_beginning_keyframe->second; | 1035 int keyframe_index = new_beginning_keyframe->second; |
968 DCHECK_LT(keyframe_index, static_cast<int>(buffers_.size())); | 1036 DCHECK_LT(keyframe_index, static_cast<int>(buffers_.size())); |
969 BufferQueue::iterator starting_point = buffers_.begin() + keyframe_index; | 1037 BufferQueue::iterator starting_point = buffers_.begin() + keyframe_index; |
970 BufferQueue removed_buffers(starting_point, buffers_.end()); | 1038 BufferQueue removed_buffers(starting_point, buffers_.end()); |
971 keyframe_map_.erase(new_beginning_keyframe, keyframe_map_.end()); | 1039 keyframe_map_.erase(new_beginning_keyframe, keyframe_map_.end()); |
972 buffers_.erase(starting_point, buffers_.end()); | 1040 FreeBufferRange(starting_point, buffers_.end()); |
973 | 1041 |
974 // Create a new range with |removed_buffers|. | 1042 // Create a new range with |removed_buffers|. |
975 SourceBufferRange* split_range = | 1043 SourceBufferRange* split_range = |
976 new SourceBufferRange( | 1044 new SourceBufferRange( |
977 removed_buffers, kNoTimestamp(), interbuffer_distance_cb_); | 1045 removed_buffers, kNoTimestamp(), interbuffer_distance_cb_); |
978 | 1046 |
979 // If the next buffer position is now in |split_range|, update the state of | 1047 // If the next buffer position is now in |split_range|, update the state of |
980 // this range and |split_range| accordingly. | 1048 // this range and |split_range| accordingly. |
981 if (next_buffer_index_ >= static_cast<int>(buffers_.size())) { | 1049 if (next_buffer_index_ >= static_cast<int>(buffers_.size())) { |
982 DCHECK(!waiting_for_keyframe_); | 1050 DCHECK(!waiting_for_keyframe_); |
(...skipping 15 matching lines...) Expand all Loading... | |
998 // lower_bound() returns the first element >= |timestamp|, so if we don't want | 1066 // lower_bound() returns the first element >= |timestamp|, so if we don't want |
999 // to include keyframes == |timestamp|, we have to increment the iterator | 1067 // to include keyframes == |timestamp|, we have to increment the iterator |
1000 // accordingly. | 1068 // accordingly. |
1001 if (skip_given_timestamp && | 1069 if (skip_given_timestamp && |
1002 result != keyframe_map_.end() && result->first == timestamp) { | 1070 result != keyframe_map_.end() && result->first == timestamp) { |
1003 ++result; | 1071 ++result; |
1004 } | 1072 } |
1005 return result; | 1073 return result; |
1006 } | 1074 } |
1007 | 1075 |
1076 SourceBufferRange::KeyframeMap::iterator | |
1077 SourceBufferRange::GetFirstKeyframeBefore(base::TimeDelta timestamp) { | |
1078 KeyframeMap::iterator result = keyframe_map_.lower_bound(timestamp); | |
1079 // lower_bound() returns the first element >= |timestamp|, so we want the | |
1080 // previous element if it did not return the element exactly equal to | |
1081 // |timestamp|. | |
1082 if (result != keyframe_map_.begin() && | |
1083 (result == keyframe_map_.end() || result->first != timestamp)) { | |
1084 --result; | |
1085 } | |
1086 return result; | |
1087 } | |
1088 | |
1008 bool SourceBufferRange::DeleteAll(BufferQueue* removed_buffers) { | 1089 bool SourceBufferRange::DeleteAll(BufferQueue* removed_buffers) { |
1009 return TruncateAt(buffers_.begin(), removed_buffers); | 1090 return TruncateAt(buffers_.begin(), removed_buffers); |
1010 } | 1091 } |
1011 | 1092 |
1012 bool SourceBufferRange::TruncateAt( | 1093 bool SourceBufferRange::TruncateAt( |
1013 scoped_refptr<StreamParserBuffer> buffer, BufferQueue* removed_buffers) { | 1094 scoped_refptr<StreamParserBuffer> buffer, BufferQueue* removed_buffers) { |
1014 // Find the place in |buffers_| where we will begin deleting data. | 1095 // Find the place in |buffers_| where we will begin deleting data. |
1015 BufferQueue::iterator starting_point = | 1096 BufferQueue::iterator starting_point = |
1016 std::lower_bound(buffers_.begin(), buffers_.end(), | 1097 std::lower_bound(buffers_.begin(), buffers_.end(), |
1017 buffer, | 1098 buffer, |
1018 BufferComparator); | 1099 BufferComparator); |
1019 return TruncateAt(starting_point, removed_buffers); | 1100 return TruncateAt(starting_point, removed_buffers); |
1020 } | 1101 } |
1021 | 1102 |
1103 int SourceBufferRange::FreeFromStart(int bytes) { | |
1104 KeyframeMap::iterator deletion_limit = keyframe_map_.end(); | |
1105 if (HasNextBufferPosition()) { | |
1106 base::TimeDelta next_timestamp = GetNextTimestamp(); | |
1107 if (next_timestamp != kNoTimestamp()) { | |
1108 deletion_limit = GetFirstKeyframeBefore(next_timestamp); | |
1109 } else { | |
1110 // If |next_timestamp| is kNoTimestamp(), that means that the next buffer | |
1111 // hasn't been buffered yet, so just save the keyframe before the end. | |
1112 --deletion_limit; | |
1113 } | |
1114 } | |
1115 | |
1116 int buffers_deleted = 0; | |
1117 int total_bytes_deleted = 0; | |
1118 | |
1119 while (total_bytes_deleted < bytes) { | |
1120 KeyframeMap::iterator front = keyframe_map_.begin(); | |
1121 if (front == deletion_limit) | |
1122 break; | |
1123 DCHECK(front != keyframe_map_.end()); | |
1124 | |
1125 // Delete buffers up until the next keyframe, i.e. the new front. | |
1126 int start_index = front->second; | |
1127 keyframe_map_.erase(front); | |
1128 | |
1129 front = keyframe_map_.begin(); | |
1130 int end_index = start_index + buffers_.size(); | |
acolwell GONE FROM CHROMIUM
2012/08/06 16:44:52
Is this right? I'm assuming this is trying to spec
vrk (LEFT CHROMIUM)
2012/08/06 20:27:14
Yes and yes.
| |
1131 if (front != keyframe_map_.end()) | |
1132 end_index = front->second; | |
1133 | |
1134 // Note that the |keyframe_map_| points to the wrong indices after the first | |
1135 // GOP is deleted. However, the distances between keyframes are the same, so | |
acolwell GONE FROM CHROMIUM
2012/08/06 16:44:52
nit: Consider rewording "the distances between key
vrk (LEFT CHROMIUM)
2012/08/06 20:27:14
Good point! Upon re-reading this morning, that's e
| |
1136 // we can use the indices to calculate how many buffers to delete from the | |
1137 // front. | |
1138 for (int i = start_index; i < end_index; i++) { | |
acolwell GONE FROM CHROMIUM
2012/08/06 16:44:52
I think it might be clearer if you changed this to
vrk (LEFT CHROMIUM)
2012/08/06 20:27:14
Made the loop 0-based but kept end_index; let me k
| |
1139 int bytes_deleted = buffers_.front()->GetDataSize(); | |
1140 size_in_bytes_ -= bytes_deleted; | |
1141 total_bytes_deleted += bytes_deleted; | |
1142 buffers_.pop_front(); | |
1143 ++buffers_deleted; | |
1144 } | |
1145 } | |
1146 | |
1147 // Update indexes to account for the deleted buffers. | |
1148 for (KeyframeMap::iterator itr = keyframe_map_.begin(); | |
1149 itr != keyframe_map_.end(); ++itr) { | |
1150 itr->second -= buffers_deleted; | |
1151 DCHECK_GE(itr->second, 0u); | |
1152 } | |
1153 if (next_buffer_index_ > -1) { | |
1154 next_buffer_index_ -= buffers_deleted; | |
1155 DCHECK_GE(next_buffer_index_, 0); | |
1156 } | |
1157 | |
1158 // Invalidate media segment start time if we've deleted the first buffer of | |
1159 // the range. | |
1160 if (buffers_deleted > 0) | |
1161 media_segment_start_time_ = kNoTimestamp(); | |
1162 | |
1163 return total_bytes_deleted; | |
1164 } | |
1165 | |
1166 int SourceBufferRange::FreeFromEnd(int bytes) { | |
1167 // Don't delete anything if we're stalled waiting for more data. | |
1168 if (HasNextBufferPosition() && !HasNextBuffer()) | |
1169 return 0; | |
1170 | |
1171 // Delete until the current buffer or until we reach the beginning of the | |
1172 // range. | |
1173 int deletion_limit = next_buffer_index_; | |
1174 DCHECK(HasNextBufferPosition() || next_buffer_index_ == -1); | |
1175 | |
1176 int total_bytes_deleted = 0; | |
1177 while (total_bytes_deleted < bytes && | |
1178 static_cast<int>(buffers_.size() - 1) > deletion_limit) { | |
1179 int bytes_deleted = buffers_.back()->GetDataSize(); | |
1180 size_in_bytes_ -= bytes_deleted; | |
1181 total_bytes_deleted += bytes_deleted; | |
1182 | |
1183 // Delete the corresponding |keyframe_map_| entry if we're about to delete a | |
1184 // keyframe buffer. | |
1185 if (buffers_.back()->IsKeyframe()) { | |
1186 DCHECK(keyframe_map_.rbegin()->first == | |
1187 buffers_.back()->GetDecodeTimestamp()); | |
1188 keyframe_map_.erase(buffers_.back()->GetDecodeTimestamp()); | |
1189 } | |
1190 | |
1191 buffers_.pop_back(); | |
1192 } | |
1193 return total_bytes_deleted; | |
1194 } | |
1195 | |
1196 void SourceBufferRange::FreeBufferRange( | |
1197 const BufferQueue::iterator& starting_point, | |
1198 const BufferQueue::iterator& ending_point) { | |
1199 for (BufferQueue::iterator itr = starting_point; | |
1200 itr != ending_point; ++itr) { | |
1201 size_in_bytes_ -= (*itr)->GetDataSize(); | |
1202 DCHECK_GE(size_in_bytes_, 0); | |
1203 } | |
1204 buffers_.erase(starting_point, ending_point); | |
1205 } | |
1206 | |
1022 bool SourceBufferRange::TruncateAt( | 1207 bool SourceBufferRange::TruncateAt( |
1023 const BufferQueue::iterator& starting_point, BufferQueue* removed_buffers) { | 1208 const BufferQueue::iterator& starting_point, BufferQueue* removed_buffers) { |
1024 DCHECK(removed_buffers); | 1209 DCHECK(removed_buffers); |
1025 DCHECK(removed_buffers->empty()); | 1210 DCHECK(removed_buffers->empty()); |
1026 | 1211 |
1027 // Return if we're not deleting anything. | 1212 // Return if we're not deleting anything. |
1028 if (starting_point == buffers_.end()) | 1213 if (starting_point == buffers_.end()) |
1029 return false; | 1214 return false; |
1030 | 1215 |
1031 // Reset the next buffer index if we will be deleting the buffer that's next | 1216 // Reset the next buffer index if we will be deleting the buffer that's next |
(...skipping 14 matching lines...) Expand all Loading... | |
1046 removed_next_buffer = true; | 1231 removed_next_buffer = true; |
1047 } | 1232 } |
1048 } | 1233 } |
1049 | 1234 |
1050 // Remove keyframes from |starting_point| onward. | 1235 // Remove keyframes from |starting_point| onward. |
1051 KeyframeMap::iterator starting_point_keyframe = | 1236 KeyframeMap::iterator starting_point_keyframe = |
1052 keyframe_map_.lower_bound((*starting_point)->GetDecodeTimestamp()); | 1237 keyframe_map_.lower_bound((*starting_point)->GetDecodeTimestamp()); |
1053 keyframe_map_.erase(starting_point_keyframe, keyframe_map_.end()); | 1238 keyframe_map_.erase(starting_point_keyframe, keyframe_map_.end()); |
1054 | 1239 |
1055 // Remove everything from |starting_point| onward. | 1240 // Remove everything from |starting_point| onward. |
1056 buffers_.erase(starting_point, buffers_.end()); | 1241 FreeBufferRange(starting_point, buffers_.end()); |
1057 return removed_next_buffer; | 1242 return removed_next_buffer; |
1058 } | 1243 } |
1059 | 1244 |
1060 bool SourceBufferRange::GetNextBuffer( | 1245 bool SourceBufferRange::GetNextBuffer( |
1061 scoped_refptr<StreamParserBuffer>* out_buffer) { | 1246 scoped_refptr<StreamParserBuffer>* out_buffer) { |
1062 if (!HasNextBuffer()) | 1247 if (!HasNextBuffer()) |
1063 return false; | 1248 return false; |
1064 | 1249 |
1065 *out_buffer = buffers_.at(next_buffer_index_); | 1250 *out_buffer = buffers_.at(next_buffer_index_); |
1066 next_buffer_index_++; | 1251 next_buffer_index_++; |
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1185 return 2 * GetApproximateDuration(); | 1370 return 2 * GetApproximateDuration(); |
1186 } | 1371 } |
1187 | 1372 |
1188 base::TimeDelta SourceBufferRange::GetApproximateDuration() const { | 1373 base::TimeDelta SourceBufferRange::GetApproximateDuration() const { |
1189 base::TimeDelta max_interbuffer_distance = interbuffer_distance_cb_.Run(); | 1374 base::TimeDelta max_interbuffer_distance = interbuffer_distance_cb_.Run(); |
1190 DCHECK(max_interbuffer_distance != kNoTimestamp()); | 1375 DCHECK(max_interbuffer_distance != kNoTimestamp()); |
1191 return max_interbuffer_distance; | 1376 return max_interbuffer_distance; |
1192 } | 1377 } |
1193 | 1378 |
1194 } // namespace media | 1379 } // namespace media |
OLD | NEW |