Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(90)

Side by Side Diff: media/filters/source_buffer_stream.cc

Issue 10853013: Implement simple garbage collection in SourceBufferStream (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: . Created 8 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
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
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
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
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 // 12MB: approximately 5 minutes of 320Kbps content.
264 // 150MB: approximately 5 minutes of 4Mbps content.
265 static int kDefaultAudioMemoryLimit = 12 * 1024 * 1024;
266 static int kDefaultVideoMemoryLimit = 150 * 1024 * 1024;
239 267
240 namespace media { 268 namespace media {
241 269
242 SourceBufferStream::SourceBufferStream(const AudioDecoderConfig& audio_config) 270 SourceBufferStream::SourceBufferStream(const AudioDecoderConfig& audio_config)
243 : current_config_index_(0), 271 : current_config_index_(0),
244 append_config_index_(0), 272 append_config_index_(0),
245 audio_configs_(1), 273 audio_configs_(1),
246 video_configs_(0), 274 video_configs_(0),
247 stream_start_time_(kNoTimestamp()), 275 stream_start_time_(kNoTimestamp()),
248 seek_pending_(false), 276 seek_pending_(false),
249 seek_buffer_timestamp_(kNoTimestamp()), 277 seek_buffer_timestamp_(kNoTimestamp()),
250 selected_range_(NULL), 278 selected_range_(NULL),
251 media_segment_start_time_(kNoTimestamp()), 279 media_segment_start_time_(kNoTimestamp()),
252 range_for_next_append_(ranges_.end()), 280 range_for_next_append_(ranges_.end()),
253 new_media_segment_(false), 281 new_media_segment_(false),
254 last_buffer_timestamp_(kNoTimestamp()), 282 last_buffer_timestamp_(kNoTimestamp()),
255 max_interbuffer_distance_(kNoTimestamp()) { 283 max_interbuffer_distance_(kNoTimestamp()),
284 memory_limit_(kDefaultAudioMemoryLimit) {
256 audio_configs_[0] = new AudioDecoderConfig(); 285 audio_configs_[0] = new AudioDecoderConfig();
257 audio_configs_[0]->CopyFrom(audio_config); 286 audio_configs_[0]->CopyFrom(audio_config);
258 } 287 }
259 288
260 SourceBufferStream::SourceBufferStream(const VideoDecoderConfig& video_config) 289 SourceBufferStream::SourceBufferStream(const VideoDecoderConfig& video_config)
261 : current_config_index_(0), 290 : current_config_index_(0),
262 append_config_index_(0), 291 append_config_index_(0),
263 audio_configs_(0), 292 audio_configs_(0),
264 video_configs_(1), 293 video_configs_(1),
265 stream_start_time_(kNoTimestamp()), 294 stream_start_time_(kNoTimestamp()),
266 seek_pending_(false), 295 seek_pending_(false),
267 seek_buffer_timestamp_(kNoTimestamp()), 296 seek_buffer_timestamp_(kNoTimestamp()),
268 selected_range_(NULL), 297 selected_range_(NULL),
269 media_segment_start_time_(kNoTimestamp()), 298 media_segment_start_time_(kNoTimestamp()),
270 range_for_next_append_(ranges_.end()), 299 range_for_next_append_(ranges_.end()),
271 new_media_segment_(false), 300 new_media_segment_(false),
272 last_buffer_timestamp_(kNoTimestamp()), 301 last_buffer_timestamp_(kNoTimestamp()),
273 max_interbuffer_distance_(kNoTimestamp()) { 302 max_interbuffer_distance_(kNoTimestamp()),
303 memory_limit_(kDefaultVideoMemoryLimit) {
274 video_configs_[0] = new VideoDecoderConfig(); 304 video_configs_[0] = new VideoDecoderConfig();
275 video_configs_[0]->CopyFrom(video_config); 305 video_configs_[0]->CopyFrom(video_config);
276 } 306 }
277 307
278 SourceBufferStream::~SourceBufferStream() { 308 SourceBufferStream::~SourceBufferStream() {
279 while (!ranges_.empty()) { 309 while (!ranges_.empty()) {
280 delete ranges_.front(); 310 delete ranges_.front();
281 ranges_.pop_front(); 311 ranges_.pop_front();
282 } 312 }
283 313
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after
382 UpdateTrackBuffer(deleted_buffers); 412 UpdateTrackBuffer(deleted_buffers);
383 } else { 413 } else {
384 // If we've deleted the next buffer but |deleted_buffers| is empty, 414 // 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 415 // 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 416 // the range (i.e. the keyframe timestamp needs to be strictly greater
387 // than |end_buffer_timestamp|). 417 // than |end_buffer_timestamp|).
388 selected_range_->SeekAheadPast(end_buffer_timestamp); 418 selected_range_->SeekAheadPast(end_buffer_timestamp);
389 } 419 }
390 } 420 }
391 421
422 GarbageCollectIfNeeded();
423
392 DCHECK(IsRangeListSorted(ranges_)); 424 DCHECK(IsRangeListSorted(ranges_));
393 DCHECK(OnlySelectedRangeIsSeeked()); 425 DCHECK(OnlySelectedRangeIsSeeked());
394 return true; 426 return true;
395 } 427 }
396 428
397 bool SourceBufferStream::ShouldSeekToStartOfBuffered( 429 bool SourceBufferStream::ShouldSeekToStartOfBuffered(
398 base::TimeDelta seek_timestamp) const { 430 base::TimeDelta seek_timestamp) const {
399 if (ranges_.empty()) 431 if (ranges_.empty())
400 return false; 432 return false;
401 base::TimeDelta beginning_of_buffered = 433 base::TimeDelta beginning_of_buffered =
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
453 } 485 }
454 } 486 }
455 487
456 void SourceBufferStream::SetConfigIds(const BufferQueue& buffers) { 488 void SourceBufferStream::SetConfigIds(const BufferQueue& buffers) {
457 for (BufferQueue::const_iterator itr = buffers.begin(); 489 for (BufferQueue::const_iterator itr = buffers.begin();
458 itr != buffers.end(); ++itr) { 490 itr != buffers.end(); ++itr) {
459 (*itr)->SetConfigId(append_config_index_); 491 (*itr)->SetConfigId(append_config_index_);
460 } 492 }
461 } 493 }
462 494
495 void SourceBufferStream::GarbageCollectIfNeeded() {
496 // Compute size of |ranges_|.
497 int ranges_size = 0;
498 for (RangeList::iterator itr = ranges_.begin(); itr != ranges_.end(); ++itr)
499 ranges_size += (*itr)->size_in_bytes();
500
501 // Return if we're under or at the memory limit.
502 if (ranges_size <= memory_limit_)
503 return;
504
505 int bytes_to_free = ranges_size - memory_limit_;
506
507 // Begin deleting from the front.
508 while (!ranges_.empty() && bytes_to_free > 0) {
509 SourceBufferRange* current_range = ranges_.front();
510 bytes_to_free -= current_range->FreeFromStart(bytes_to_free);
511
512 // If the |current_range| still has data left after freeing, we should not
513 // delete any more data in this direction.
514 if (current_range->size_in_bytes() > 0)
515 break;
516
517 DCHECK_NE(current_range, selected_range_);
518 delete current_range;
519 ranges_.pop_front();
520 }
521
522 // Begin deleting from the back.
523 while (!ranges_.empty() && bytes_to_free > 0) {
524 SourceBufferRange* current_range = ranges_.back();
525 bytes_to_free -= current_range->FreeFromEnd(bytes_to_free);
526
527 // If the |current_range| still has data left after freeing, we should not
528 // delete any more data in this direction.
529 if (current_range->size_in_bytes() > 0)
530 break;
531
532 DCHECK_NE(current_range, selected_range_);
533 delete current_range;
534 ranges_.pop_back();
535 }
536 }
537
463 void SourceBufferStream::InsertIntoExistingRange( 538 void SourceBufferStream::InsertIntoExistingRange(
464 const RangeList::iterator& range_for_new_buffers_itr, 539 const RangeList::iterator& range_for_new_buffers_itr,
465 const BufferQueue& new_buffers, 540 const BufferQueue& new_buffers,
466 bool* deleted_next_buffer, BufferQueue* deleted_buffers) { 541 bool* deleted_next_buffer, BufferQueue* deleted_buffers) {
467 DCHECK(deleted_next_buffer); 542 DCHECK(deleted_next_buffer);
468 DCHECK(deleted_buffers); 543 DCHECK(deleted_buffers);
469 544
470 SourceBufferRange* range_for_new_buffers = *range_for_new_buffers_itr; 545 SourceBufferRange* range_for_new_buffers = *range_for_new_buffers_itr;
471 546
472 // If this is a simple case where we can just append to the end of the range, 547 // 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
869 current_config_index_ = selected_range_->GetNextConfigId(); 944 current_config_index_ = selected_range_->GetNextConfigId();
870 } 945 }
871 946
872 SourceBufferRange::SourceBufferRange( 947 SourceBufferRange::SourceBufferRange(
873 const BufferQueue& new_buffers, base::TimeDelta media_segment_start_time, 948 const BufferQueue& new_buffers, base::TimeDelta media_segment_start_time,
874 const InterbufferDistanceCB& interbuffer_distance_cb) 949 const InterbufferDistanceCB& interbuffer_distance_cb)
875 : next_buffer_index_(-1), 950 : next_buffer_index_(-1),
876 waiting_for_keyframe_(false), 951 waiting_for_keyframe_(false),
877 next_keyframe_timestamp_(kNoTimestamp()), 952 next_keyframe_timestamp_(kNoTimestamp()),
878 media_segment_start_time_(media_segment_start_time), 953 media_segment_start_time_(media_segment_start_time),
879 interbuffer_distance_cb_(interbuffer_distance_cb) { 954 interbuffer_distance_cb_(interbuffer_distance_cb),
955 size_in_bytes_(0) {
880 DCHECK(!new_buffers.empty()); 956 DCHECK(!new_buffers.empty());
881 DCHECK(new_buffers.front()->IsKeyframe()); 957 DCHECK(new_buffers.front()->IsKeyframe());
882 DCHECK(!interbuffer_distance_cb.is_null()); 958 DCHECK(!interbuffer_distance_cb.is_null());
883 AppendBuffersToEnd(new_buffers); 959 AppendBuffersToEnd(new_buffers);
884 } 960 }
885 961
886 void SourceBufferRange::AppendBuffersToEnd(const BufferQueue& new_buffers) { 962 void SourceBufferRange::AppendBuffersToEnd(const BufferQueue& new_buffers) {
887 for (BufferQueue::const_iterator itr = new_buffers.begin(); 963 for (BufferQueue::const_iterator itr = new_buffers.begin();
888 itr != new_buffers.end(); ++itr) { 964 itr != new_buffers.end(); ++itr) {
889 DCHECK((*itr)->GetDecodeTimestamp() != kNoTimestamp()); 965 DCHECK((*itr)->GetDecodeTimestamp() != kNoTimestamp());
890 buffers_.push_back(*itr); 966 buffers_.push_back(*itr);
967 size_in_bytes_ += (*itr)->GetDataSize();
968
891 if ((*itr)->IsKeyframe()) { 969 if ((*itr)->IsKeyframe()) {
892 keyframe_map_.insert( 970 keyframe_map_.insert(
893 std::make_pair((*itr)->GetDecodeTimestamp(), buffers_.size() - 1)); 971 std::make_pair((*itr)->GetDecodeTimestamp(), buffers_.size() - 1));
894 972
895 if (waiting_for_keyframe_ && 973 if (waiting_for_keyframe_ &&
896 (*itr)->GetDecodeTimestamp() >= next_keyframe_timestamp_) { 974 (*itr)->GetDecodeTimestamp() >= next_keyframe_timestamp_) {
897 next_buffer_index_ = buffers_.size() - 1; 975 next_buffer_index_ = buffers_.size() - 1;
898 next_keyframe_timestamp_ = base::TimeDelta(); 976 next_keyframe_timestamp_ = base::TimeDelta();
899 waiting_for_keyframe_ = false; 977 waiting_for_keyframe_ = false;
900 } 978 }
901 } 979 }
902 } 980 }
903 } 981 }
904 982
905 void SourceBufferRange::Seek(base::TimeDelta timestamp) { 983 void SourceBufferRange::Seek(base::TimeDelta timestamp) {
906 DCHECK(CanSeekTo(timestamp)); 984 DCHECK(CanSeekTo(timestamp));
907 DCHECK(!keyframe_map_.empty()); 985 DCHECK(!keyframe_map_.empty());
908 986
909 next_keyframe_timestamp_ = base::TimeDelta(); 987 next_keyframe_timestamp_ = base::TimeDelta();
910 waiting_for_keyframe_ = false; 988 waiting_for_keyframe_ = false;
911 989
912 KeyframeMap::iterator result = keyframe_map_.lower_bound(timestamp); 990 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; 991 next_buffer_index_ = result->second;
921 DCHECK_LT(next_buffer_index_, static_cast<int>(buffers_.size())); 992 DCHECK_LT(next_buffer_index_, static_cast<int>(buffers_.size()));
922 } 993 }
923 994
924 void SourceBufferRange::SeekAheadTo(base::TimeDelta timestamp) { 995 void SourceBufferRange::SeekAheadTo(base::TimeDelta timestamp) {
925 SeekAhead(timestamp, false); 996 SeekAhead(timestamp, false);
926 } 997 }
927 998
928 void SourceBufferRange::SeekAheadPast(base::TimeDelta timestamp) { 999 void SourceBufferRange::SeekAheadPast(base::TimeDelta timestamp) {
929 SeekAhead(timestamp, true); 1000 SeekAhead(timestamp, true);
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
962 if (new_beginning_keyframe == keyframe_map_.end()) 1033 if (new_beginning_keyframe == keyframe_map_.end())
963 return NULL; 1034 return NULL;
964 1035
965 // Remove the data beginning at |keyframe_index| from |buffers_| and save it 1036 // Remove the data beginning at |keyframe_index| from |buffers_| and save it
966 // into |removed_buffers|. 1037 // into |removed_buffers|.
967 int keyframe_index = new_beginning_keyframe->second; 1038 int keyframe_index = new_beginning_keyframe->second;
968 DCHECK_LT(keyframe_index, static_cast<int>(buffers_.size())); 1039 DCHECK_LT(keyframe_index, static_cast<int>(buffers_.size()));
969 BufferQueue::iterator starting_point = buffers_.begin() + keyframe_index; 1040 BufferQueue::iterator starting_point = buffers_.begin() + keyframe_index;
970 BufferQueue removed_buffers(starting_point, buffers_.end()); 1041 BufferQueue removed_buffers(starting_point, buffers_.end());
971 keyframe_map_.erase(new_beginning_keyframe, keyframe_map_.end()); 1042 keyframe_map_.erase(new_beginning_keyframe, keyframe_map_.end());
972 buffers_.erase(starting_point, buffers_.end()); 1043 FreeBufferRange(starting_point, buffers_.end());
973 1044
974 // Create a new range with |removed_buffers|. 1045 // Create a new range with |removed_buffers|.
975 SourceBufferRange* split_range = 1046 SourceBufferRange* split_range =
976 new SourceBufferRange( 1047 new SourceBufferRange(
977 removed_buffers, kNoTimestamp(), interbuffer_distance_cb_); 1048 removed_buffers, kNoTimestamp(), interbuffer_distance_cb_);
978 1049
979 // If the next buffer position is now in |split_range|, update the state of 1050 // If the next buffer position is now in |split_range|, update the state of
980 // this range and |split_range| accordingly. 1051 // this range and |split_range| accordingly.
981 if (next_buffer_index_ >= static_cast<int>(buffers_.size())) { 1052 if (next_buffer_index_ >= static_cast<int>(buffers_.size())) {
982 DCHECK(!waiting_for_keyframe_); 1053 DCHECK(!waiting_for_keyframe_);
(...skipping 15 matching lines...) Expand all
998 // lower_bound() returns the first element >= |timestamp|, so if we don't want 1069 // lower_bound() returns the first element >= |timestamp|, so if we don't want
999 // to include keyframes == |timestamp|, we have to increment the iterator 1070 // to include keyframes == |timestamp|, we have to increment the iterator
1000 // accordingly. 1071 // accordingly.
1001 if (skip_given_timestamp && 1072 if (skip_given_timestamp &&
1002 result != keyframe_map_.end() && result->first == timestamp) { 1073 result != keyframe_map_.end() && result->first == timestamp) {
1003 ++result; 1074 ++result;
1004 } 1075 }
1005 return result; 1076 return result;
1006 } 1077 }
1007 1078
1079 SourceBufferRange::KeyframeMap::iterator
1080 SourceBufferRange::GetFirstKeyframeBefore(base::TimeDelta timestamp) {
1081 KeyframeMap::iterator result = keyframe_map_.lower_bound(timestamp);
1082 // lower_bound() returns the first element >= |timestamp|, so we want the
1083 // previous element if it did not return the element exactly equal to
1084 // |timestamp|.
1085 if (result != keyframe_map_.begin() &&
1086 (result == keyframe_map_.end() || result->first != timestamp)) {
1087 --result;
1088 }
1089 return result;
1090 }
1091
1008 bool SourceBufferRange::DeleteAll(BufferQueue* removed_buffers) { 1092 bool SourceBufferRange::DeleteAll(BufferQueue* removed_buffers) {
1009 return TruncateAt(buffers_.begin(), removed_buffers); 1093 return TruncateAt(buffers_.begin(), removed_buffers);
1010 } 1094 }
1011 1095
1012 bool SourceBufferRange::TruncateAt( 1096 bool SourceBufferRange::TruncateAt(
1013 scoped_refptr<StreamParserBuffer> buffer, BufferQueue* removed_buffers) { 1097 scoped_refptr<StreamParserBuffer> buffer, BufferQueue* removed_buffers) {
1014 // Find the place in |buffers_| where we will begin deleting data. 1098 // Find the place in |buffers_| where we will begin deleting data.
1015 BufferQueue::iterator starting_point = 1099 BufferQueue::iterator starting_point =
1016 std::lower_bound(buffers_.begin(), buffers_.end(), 1100 std::lower_bound(buffers_.begin(), buffers_.end(),
1017 buffer, 1101 buffer,
1018 BufferComparator); 1102 BufferComparator);
1019 return TruncateAt(starting_point, removed_buffers); 1103 return TruncateAt(starting_point, removed_buffers);
1020 } 1104 }
1021 1105
1106 int SourceBufferRange::FreeFromStart(int bytes) {
1107 KeyframeMap::iterator deletion_limit = keyframe_map_.end();
1108 if (HasNextBufferPosition()) {
1109 base::TimeDelta next_timestamp = GetNextTimestamp();
1110 if (next_timestamp != kNoTimestamp()) {
1111 deletion_limit = GetFirstKeyframeBefore(next_timestamp);
1112 } else {
1113 // If |next_timestamp| is kNoTimestamp(), that means that the next buffer
1114 // hasn't been buffered yet, so just save the keyframe before the end.
1115 --deletion_limit;
1116 }
1117 }
1118
1119 int buffers_deleted = 0;
1120 int total_bytes_deleted = 0;
1121
1122 while (total_bytes_deleted < bytes) {
1123 KeyframeMap::iterator front = keyframe_map_.begin();
1124 if (front == deletion_limit)
1125 break;
1126 DCHECK(front != keyframe_map_.end());
1127
1128 // If we haven't reached |deletion_limit|, we begin by deleting the
1129 // keyframe at the start of |keyframe_map_|.
1130 keyframe_map_.erase(front);
1131 front = keyframe_map_.begin();
1132
1133 // Now we need to delete all the buffers that depend on the keyframe we've
1134 // just deleted. Determine the index in |buffers_| at which we should stop
1135 // deleting.
1136 int end_index = buffers_.size();
1137 if (front != keyframe_map_.end()) {
1138 // The indexes in |keyframe_map_| will be out of date after the first GOP
1139 // is deleted, so adjust the |end_index| by the |buffers_deleted| to get
acolwell GONE FROM CHROMIUM 2012/08/06 20:48:02 nit: s/end_index/front->second/ since that is what
vrk (LEFT CHROMIUM) 2012/08/06 20:52:46 Done.
1140 // the proper index value.
1141 end_index = front->second - buffers_deleted;
1142 }
1143
1144 // Delete buffers from the beginning of the buffered range up until (but not
1145 // including) the next keyframe.
1146 for (int i = 0; i < end_index; i++) {
1147 int bytes_deleted = buffers_.front()->GetDataSize();
1148 size_in_bytes_ -= bytes_deleted;
1149 total_bytes_deleted += bytes_deleted;
1150 buffers_.pop_front();
1151 ++buffers_deleted;
1152 }
1153 }
1154
1155 // Update indices to account for the deleted buffers.
1156 for (KeyframeMap::iterator itr = keyframe_map_.begin();
1157 itr != keyframe_map_.end(); ++itr) {
1158 itr->second -= buffers_deleted;
1159 DCHECK_GE(itr->second, 0u);
1160 }
1161 if (next_buffer_index_ > -1) {
1162 next_buffer_index_ -= buffers_deleted;
1163 DCHECK_GE(next_buffer_index_, 0);
1164 }
1165
1166 // Invalidate media segment start time if we've deleted the first buffer of
1167 // the range.
1168 if (buffers_deleted > 0)
1169 media_segment_start_time_ = kNoTimestamp();
1170
1171 return total_bytes_deleted;
1172 }
1173
1174 int SourceBufferRange::FreeFromEnd(int bytes) {
1175 // Don't delete anything if we're stalled waiting for more data.
1176 if (HasNextBufferPosition() && !HasNextBuffer())
1177 return 0;
1178
1179 // Delete until the current buffer or until we reach the beginning of the
1180 // range.
1181 int deletion_limit = next_buffer_index_;
1182 DCHECK(HasNextBufferPosition() || next_buffer_index_ == -1);
1183
1184 int total_bytes_deleted = 0;
1185 while (total_bytes_deleted < bytes &&
1186 static_cast<int>(buffers_.size() - 1) > deletion_limit) {
1187 int bytes_deleted = buffers_.back()->GetDataSize();
1188 size_in_bytes_ -= bytes_deleted;
1189 total_bytes_deleted += bytes_deleted;
1190
1191 // Delete the corresponding |keyframe_map_| entry if we're about to delete a
1192 // keyframe buffer.
1193 if (buffers_.back()->IsKeyframe()) {
1194 DCHECK(keyframe_map_.rbegin()->first ==
1195 buffers_.back()->GetDecodeTimestamp());
1196 keyframe_map_.erase(buffers_.back()->GetDecodeTimestamp());
1197 }
1198
1199 buffers_.pop_back();
1200 }
1201 return total_bytes_deleted;
1202 }
1203
1204 void SourceBufferRange::FreeBufferRange(
1205 const BufferQueue::iterator& starting_point,
1206 const BufferQueue::iterator& ending_point) {
1207 for (BufferQueue::iterator itr = starting_point;
1208 itr != ending_point; ++itr) {
1209 size_in_bytes_ -= (*itr)->GetDataSize();
1210 DCHECK_GE(size_in_bytes_, 0);
1211 }
1212 buffers_.erase(starting_point, ending_point);
1213 }
1214
1022 bool SourceBufferRange::TruncateAt( 1215 bool SourceBufferRange::TruncateAt(
1023 const BufferQueue::iterator& starting_point, BufferQueue* removed_buffers) { 1216 const BufferQueue::iterator& starting_point, BufferQueue* removed_buffers) {
1024 DCHECK(removed_buffers); 1217 DCHECK(removed_buffers);
1025 DCHECK(removed_buffers->empty()); 1218 DCHECK(removed_buffers->empty());
1026 1219
1027 // Return if we're not deleting anything. 1220 // Return if we're not deleting anything.
1028 if (starting_point == buffers_.end()) 1221 if (starting_point == buffers_.end())
1029 return false; 1222 return false;
1030 1223
1031 // Reset the next buffer index if we will be deleting the buffer that's next 1224 // Reset the next buffer index if we will be deleting the buffer that's next
(...skipping 14 matching lines...) Expand all
1046 removed_next_buffer = true; 1239 removed_next_buffer = true;
1047 } 1240 }
1048 } 1241 }
1049 1242
1050 // Remove keyframes from |starting_point| onward. 1243 // Remove keyframes from |starting_point| onward.
1051 KeyframeMap::iterator starting_point_keyframe = 1244 KeyframeMap::iterator starting_point_keyframe =
1052 keyframe_map_.lower_bound((*starting_point)->GetDecodeTimestamp()); 1245 keyframe_map_.lower_bound((*starting_point)->GetDecodeTimestamp());
1053 keyframe_map_.erase(starting_point_keyframe, keyframe_map_.end()); 1246 keyframe_map_.erase(starting_point_keyframe, keyframe_map_.end());
1054 1247
1055 // Remove everything from |starting_point| onward. 1248 // Remove everything from |starting_point| onward.
1056 buffers_.erase(starting_point, buffers_.end()); 1249 FreeBufferRange(starting_point, buffers_.end());
1057 return removed_next_buffer; 1250 return removed_next_buffer;
1058 } 1251 }
1059 1252
1060 bool SourceBufferRange::GetNextBuffer( 1253 bool SourceBufferRange::GetNextBuffer(
1061 scoped_refptr<StreamParserBuffer>* out_buffer) { 1254 scoped_refptr<StreamParserBuffer>* out_buffer) {
1062 if (!HasNextBuffer()) 1255 if (!HasNextBuffer())
1063 return false; 1256 return false;
1064 1257
1065 *out_buffer = buffers_.at(next_buffer_index_); 1258 *out_buffer = buffers_.at(next_buffer_index_);
1066 next_buffer_index_++; 1259 next_buffer_index_++;
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after
1185 return 2 * GetApproximateDuration(); 1378 return 2 * GetApproximateDuration();
1186 } 1379 }
1187 1380
1188 base::TimeDelta SourceBufferRange::GetApproximateDuration() const { 1381 base::TimeDelta SourceBufferRange::GetApproximateDuration() const {
1189 base::TimeDelta max_interbuffer_distance = interbuffer_distance_cb_.Run(); 1382 base::TimeDelta max_interbuffer_distance = interbuffer_distance_cb_.Run();
1190 DCHECK(max_interbuffer_distance != kNoTimestamp()); 1383 DCHECK(max_interbuffer_distance != kNoTimestamp());
1191 return max_interbuffer_distance; 1384 return max_interbuffer_distance;
1192 } 1385 }
1193 1386
1194 } // namespace media 1387 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698