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 // 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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 |
OLD | NEW |