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

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 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
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
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
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698