Chromium Code Reviews| 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/logging.h" | 10 #include "base/logging.h" |
| 11 | 11 |
| 12 namespace media { | 12 namespace media { |
| 13 | 13 |
| 14 // Helper class representing a range of buffered data. All buffers in a | 14 // Helper class representing a range of buffered data. All buffers in a |
| 15 // SourceBufferRange are ordered sequentially in presentation order with no | 15 // SourceBufferRange are ordered sequentially in presentation order with no |
| 16 // gaps. | 16 // gaps. |
| 17 class SourceBufferRange { | 17 class SourceBufferRange { |
| 18 public: | 18 public: |
| 19 typedef std::deque<scoped_refptr<StreamParserBuffer> > BufferQueue; | 19 typedef std::deque<scoped_refptr<StreamParserBuffer> > BufferQueue; |
| 20 | 20 |
| 21 SourceBufferRange(); | 21 // Creates a source buffer range with |new_buffers|. |new_buffers| cannot be |
| 22 // empty and the front of |new_buffers| must be a keyframe. | |
| 23 SourceBufferRange(const BufferQueue& new_buffers); | |
|
acolwell GONE FROM CHROMIUM
2012/05/22 19:35:23
add explicit
vrk (LEFT CHROMIUM)
2012/05/24 20:06:30
Good catch, done.
| |
| 22 | 24 |
| 23 // Adds |new_buffers| into this range. |new_buffers| must belong to this | 25 // Appends |buffers| to the end of the range and updates |keyframe_map_| as |
| 24 // range. Garbage collection may occur after Append(). | 26 // it encounters new keyframes. Assumes |buffers| belongs at the end of the |
| 25 void Append(const BufferQueue& new_buffers); | 27 // range. |
| 28 void AppendToEnd(const BufferQueue& buffers); | |
| 29 bool CanAppendToEnd(const BufferQueue& buffers) const; | |
| 30 | |
| 31 // Appends the buffers from |range| into this range. | |
| 32 // The first buffer in |range| must come directly after the last buffer | |
| 33 // in this range. | |
| 34 // If |transfer_current_position| is true, |range|'s |next_buffer_position_| | |
|
acolwell GONE FROM CHROMIUM
2012/05/22 19:35:23
next_buffer_position_ -> next_buffer_index_?
vrk (LEFT CHROMIUM)
2012/05/24 20:06:30
Done.
| |
| 35 // is transfered to this SourceBufferRange. | |
| 36 void AppendToEnd(const SourceBufferRange& range, | |
| 37 bool transfer_current_position); | |
| 38 bool CanAppendToEnd(const SourceBufferRange& range) const; | |
| 26 | 39 |
| 27 // Updates |next_buffer_index_| to point to the Buffer containing |timestamp|. | 40 // Updates |next_buffer_index_| to point to the Buffer containing |timestamp|. |
| 28 // Assumes |timestamp| is valid and in this range. | 41 // Assumes |timestamp| is valid and in this range. |
| 29 void Seek(base::TimeDelta timestamp); | 42 void Seek(base::TimeDelta timestamp); |
| 30 | 43 |
| 31 // Updates |next_buffer_index_| to point to next keyframe after or equal to | 44 // Updates |next_buffer_index_| to point to next keyframe after or equal to |
| 32 // |timestamp|. If there is no such keyframe, then this range will seek to | 45 // |timestamp|. |
| 33 // the end and return kNoTimestamp(). | 46 void SeekAfter(base::TimeDelta timestamp); |
| 34 // Assumes |timestamp| is valid and in this range. | 47 |
| 35 base::TimeDelta SeekAfter(base::TimeDelta timestamp); | 48 // Finds the next keyframe from |buffers_| after |timestamp|, and creates and |
| 49 // returns a new SourceBufferRange with the buffers from that keyframe onward. | |
| 50 // The buffers in the new SourceBufferRange are moved out of this range. If | |
| 51 // there is no keyframe after |timestamp|, SplitRange() returns null and this | |
| 52 // range is unmodified. | |
| 53 SourceBufferRange* SplitRange(base::TimeDelta timestamp); | |
| 54 | |
| 55 // Deletes the buffers from this range whose timestamps are greater than or | |
| 56 // equal to |buffer|'s timestamp. | |
| 57 // Resets |next_buffer_index_| if the buffer after |next_buffer_index_| was | |
| 58 // deleted. | |
| 59 // If |deleted_buffers| or |next_buffer| are null, they are ignored. | |
| 60 // Otherwise, |deleted_buffers| contains the buffers that were deleted from | |
| 61 // this range, and |next_buffer| points to the deleted next buffer or to | |
|
acolwell GONE FROM CHROMIUM
2012/05/22 19:35:23
nit: Perhaps reword "deleted next buffer" to somet
vrk (LEFT CHROMIUM)
2012/05/24 20:06:30
Did some rewording, and also deleted the other com
| |
| 62 // |deleted_buffers.end()| if the next buffer was not deleted. | |
|
acolwell GONE FROM CHROMIUM
2012/05/22 19:35:23
nit: "the next buffer was not deleted" -> "|next_b
vrk (LEFT CHROMIUM)
2012/05/24 20:06:30
Done.
| |
| 63 void DeleteAfter(scoped_refptr<StreamParserBuffer> buffer, | |
|
acolwell GONE FROM CHROMIUM
2012/05/22 19:35:23
nit: It might be good to mention that keyframe_map
vrk (LEFT CHROMIUM)
2012/05/24 20:06:30
Done.
| |
| 64 BufferQueue* deleted_buffers, | |
| 65 BufferQueue::iterator* next_buffer); | |
| 66 | |
| 67 // Deletes all buffers in range. | |
| 68 // If |deleted_buffers| or |next_buffer| are null, they are ignored. | |
| 69 // Otherwise, |deleted_buffers| contains the buffers that were deleted from | |
| 70 // this range, and |next_buffer| points to the deleted next buffer or to | |
| 71 // |deleted_buffers.end()| if the next buffer was not deleted. | |
| 72 void DeleteAll(BufferQueue* deleted_buffers, | |
| 73 BufferQueue::iterator* next_buffer); | |
| 36 | 74 |
| 37 // Updates |out_buffer| with the next buffer in presentation order. Seek() | 75 // Updates |out_buffer| with the next buffer in presentation order. Seek() |
| 38 // must be called before calls to GetNextBuffer(), and buffers are returned | 76 // must be called before calls to GetNextBuffer(), and buffers are returned |
| 39 // in order from the last call to Seek(). Returns true if |out_buffer| is | 77 // in order from the last call to Seek(). Returns true if |out_buffer| is |
| 40 // filled with a valid buffer, false if there is not enough data to fulfill | 78 // filled with a valid buffer, false if there is not enough data to fulfill |
| 41 // the request. | 79 // the request. |
| 42 bool GetNextBuffer(scoped_refptr<StreamParserBuffer>* out_buffer); | 80 bool GetNextBuffer(scoped_refptr<StreamParserBuffer>* out_buffer); |
| 81 | |
| 82 // Returns the timestamp of the next buffer that will be returned from | |
| 83 // GetNextBuffer(). Returns kNoTimestamp() if Seek() has never been called or | |
| 84 // if this range does not have the next buffer yet. | |
| 43 base::TimeDelta GetNextTimestamp() const; | 85 base::TimeDelta GetNextTimestamp() const; |
| 44 | 86 |
| 87 // Returns the end timestamp of the buffered data. (Note that this is equal to | |
| 88 // the last buffer's timestamp + its duration.) Returns kNoTimestamp if the | |
|
acolwell GONE FROM CHROMIUM
2012/05/22 19:35:23
nit: Can we have an empty range? If not remove tha
vrk (LEFT CHROMIUM)
2012/05/24 20:06:30
It is possible (e.g. after completely overlapping
| |
| 89 // range is empty. | |
| 90 base::TimeDelta GetEndTimestamp() const; | |
| 91 | |
| 45 // Returns the Timespan of buffered time in this range. | 92 // Returns the Timespan of buffered time in this range. |
| 46 SourceBufferStream::Timespan GetBufferedTime() const; | 93 SourceBufferStream::Timespan GetBufferedTime() const; |
| 47 | 94 |
| 48 // Appends the buffers from |range| into this range. | |
| 49 // The first buffer in |range| must come directly after the last buffer | |
| 50 // in this range. | |
| 51 // If |transfer_current_position| is true, |range|'s |next_buffer_position_| | |
| 52 // is transfered to this SourceBufferRange. | |
| 53 void AppendToEnd(const SourceBufferRange& range, | |
| 54 bool transfer_current_position); | |
| 55 bool CanAppendToEnd(const SourceBufferRange& range) const; | |
| 56 bool CanAppendToEnd(const BufferQueue& buffers) const; | |
| 57 | |
| 58 // Returns whether a buffer with a starting timestamp of |timestamp| would | 95 // Returns whether a buffer with a starting timestamp of |timestamp| would |
| 59 // belong in this range. This includes a buffer that would be appended to | 96 // belong in this range. This includes a buffer that would be appended to |
| 60 // the end of the range. | 97 // the end of the range. |
| 61 // Returns 0 if |timestamp| is in this range, -1 if |timestamp| appears | 98 // Returns 0 if |timestamp| is in this range, -1 if |timestamp| appears |
| 62 // before this range, or 1 if |timestamp| appears after this range. | 99 // before this range, or 1 if |timestamp| appears after this range. |
| 63 int BelongsToRange(base::TimeDelta timestamp) const; | 100 int BelongsToRange(base::TimeDelta timestamp) const; |
| 64 | 101 |
| 65 // Returns true if the range has enough data to seek to the specified | 102 // Returns true if the range has enough data to seek to the specified |
| 66 // |timestamp|, false otherwise. | 103 // |timestamp|, false otherwise. |
| 67 bool CanSeekTo(base::TimeDelta timestamp) const; | 104 bool CanSeekTo(base::TimeDelta timestamp) const; |
| 68 | 105 |
| 69 // Returns true if this range's buffered timespan completely overlaps the | 106 // Returns true if this range's buffered timespan completely overlaps the |
| 70 // buffered timespan of |range|. | 107 // buffered timespan of |range|. |
| 71 bool CompletelyOverlaps(const SourceBufferRange& range) const; | 108 bool CompletelyOverlaps(const SourceBufferRange& range) const; |
| 72 | 109 |
| 73 // Returns true if the end of this range contains buffers that overlaps with | 110 // Returns true if the end of this range contains buffers that overlaps with |
| 74 // the beginning of |range|. | 111 // the beginning of |range|. |
| 75 bool EndOverlaps(const SourceBufferRange& range) const; | 112 bool EndOverlaps(const SourceBufferRange& range) const; |
| 76 | 113 |
| 77 // Functions that tell how |buffers| intersects with this range. | |
| 78 // TODO(vrk): These functions should be unnecessary when overlapping the | |
| 79 // selected range is implemented properly. (crbug.com/126560) | |
| 80 bool IsStartOverlappedBy(const BufferQueue& buffers) const; | |
| 81 bool IsEndOverlappedBy(const BufferQueue& buffers) const; | |
| 82 bool IsCompletelyOverlappedBy(const BufferQueue& buffers) const; | |
| 83 | |
| 84 private: | 114 private: |
| 85 // Appends |buffers| to the end of the range and updates |keyframe_map_| as | 115 // Helper method to delete buffers in |buffers_| starting from |
| 86 // it encounters new keyframes. Assumes |buffers| belongs at the end of the | 116 // |starting_point|, an iterator in |buffers_|. |
| 87 // range. | 117 // If |deleted_buffers| or |next_buffer| are null, they are ignored. |
| 88 void AppendToEnd(const BufferQueue& buffers); | 118 // Otherwise, |deleted_buffers| contains the buffers that were deleted from |
| 119 // this range, and |next_buffer| points to the deleted next buffer or to | |
| 120 // |deleted_buffers.end()| if the next buffer was not deleted. | |
| 121 void DeleteAfter(BufferQueue::iterator starting_point, | |
| 122 BufferQueue* deleted_buffers, | |
| 123 BufferQueue::iterator* next_buffer); | |
| 89 | 124 |
| 90 // Returns the start timestamp of the range, or kNoTimestamp if the range is | 125 // Returns the start timestamp of the range, or kNoTimestamp if the range is |
| 91 // empty. | 126 // empty. |
| 92 base::TimeDelta BufferedStart() const; | 127 base::TimeDelta BufferedStart() const; |
| 93 | 128 |
| 94 // Returns the end timestamp of the buffered data. (Note that this is equal to | 129 // Returns the end timestamp of the buffered data. (Note that this is equal to |
| 95 // the last buffer's timestamp + its duration.) Returns kNoTimestamp if the | 130 // the last buffer's timestamp + its duration.) Returns kNoTimestamp if the |
| 96 // range is empty. | 131 // range is empty. |
| 97 base::TimeDelta BufferedEnd() const; | 132 base::TimeDelta BufferedEnd() const; |
| 98 | 133 |
| 99 // An ordered list of buffers in this range. | 134 // An ordered list of buffers in this range. |
| 100 BufferQueue buffers_; | 135 BufferQueue buffers_; |
| 101 | 136 |
| 102 // Maps keyframe timestamps to its index position in |buffers_|. | 137 // Maps keyframe timestamps to its index position in |buffers_|. |
| 103 typedef std::map<base::TimeDelta, size_t> KeyframeMap; | 138 typedef std::map<base::TimeDelta, size_t> KeyframeMap; |
| 104 KeyframeMap keyframe_map_; | 139 KeyframeMap keyframe_map_; |
| 105 | 140 |
| 106 // Index into |buffers_| for the next buffer to be returned by | 141 // Index into |buffers_| for the next buffer to be returned by |
| 107 // GetBufferedTime(), set to -1 before Seek(). | 142 // GetBufferedTime(), set to -1 before Seek(). |
| 108 int next_buffer_index_; | 143 int next_buffer_index_; |
| 109 | 144 |
| 145 // True if the range needs to wait for the next keyframe to be appended before | |
| 146 // returning buffers from GetNextBuffer(). | |
| 147 bool waiting_for_keyframe_; | |
| 148 | |
| 149 // If |waiting_for_keyframe_| is true, this range will wait for the next | |
| 150 // keyframe with timestamp >= |next_keyframe_timestamp_|. | |
| 151 base::TimeDelta next_keyframe_timestamp_; | |
| 152 | |
| 110 DISALLOW_COPY_AND_ASSIGN(SourceBufferRange); | 153 DISALLOW_COPY_AND_ASSIGN(SourceBufferRange); |
| 111 }; | 154 }; |
| 112 | 155 |
| 113 } // namespace media | 156 } // namespace media |
| 114 | 157 |
| 115 // Helper method that returns true if |ranges| is sorted in increasing order, | 158 // Helper method that returns true if |ranges| is sorted in increasing order, |
| 116 // false otherwise. | 159 // false otherwise. |
| 117 static bool IsRangeListSorted( | 160 static bool IsRangeListSorted( |
| 118 const std::list<media::SourceBufferRange*>& ranges) { | 161 const std::list<media::SourceBufferRange*>& ranges) { |
| 119 base::TimeDelta prev = media::kNoTimestamp(); | 162 base::TimeDelta prev = media::kNoTimestamp(); |
| 120 for (std::list<media::SourceBufferRange*>::const_iterator itr = | 163 for (std::list<media::SourceBufferRange*>::const_iterator itr = |
| 121 ranges.begin(); itr != ranges.end(); itr++) { | 164 ranges.begin(); itr != ranges.end(); itr++) { |
| 122 media::SourceBufferStream::Timespan buffered = (*itr)->GetBufferedTime(); | 165 media::SourceBufferStream::Timespan buffered = (*itr)->GetBufferedTime(); |
| 123 if (prev != media::kNoTimestamp() && prev >= buffered.first) | 166 if (prev != media::kNoTimestamp() && prev >= buffered.first) |
| 124 return false; | 167 return false; |
| 125 prev = buffered.second; | 168 prev = buffered.second; |
| 126 } | 169 } |
| 127 return true; | 170 return true; |
| 128 } | 171 } |
| 129 | 172 |
| 130 // Comparison function for two Buffers based on timestamp. | 173 // Comparison function for two Buffers based on timestamp. |
| 131 static bool BufferComparator(scoped_refptr<media::Buffer> first, | 174 static bool BufferComparator( |
| 132 scoped_refptr<media::Buffer> second) { | 175 const scoped_refptr<media::StreamParserBuffer>& first, |
| 176 const scoped_refptr<media::StreamParserBuffer>& second) { | |
| 133 return first->GetTimestamp() < second->GetTimestamp(); | 177 return first->GetTimestamp() < second->GetTimestamp(); |
| 134 } | 178 } |
| 135 | 179 |
| 136 // Returns the upper bound for the starting timestamp for the next buffer | 180 // Returns the upper bound for the starting timestamp for the next buffer |
| 137 // in sequence after |buffer|. Assumes |buffer|'s timestamp and | 181 // in sequence after |buffer|. Assumes |buffer|'s timestamp and |
| 138 // duration are valid. | 182 // duration are valid. |
| 139 static base::TimeDelta MaxNextTimestamp( | 183 static base::TimeDelta MaxNextTimestamp( |
| 140 const scoped_refptr<media::StreamParserBuffer>& buffer) { | 184 const scoped_refptr<media::StreamParserBuffer>& buffer) { |
| 141 // Because we do not know exactly when is the next timestamp, any buffer | 185 // Because we do not know exactly when is the next timestamp, any buffer |
| 142 // that starts within 1/3 of the duration past the end of this buffer | 186 // that starts within 1/3 of the duration past the end of this buffer |
| 143 // is considered the next buffer in the sequence. | 187 // is considered the next buffer in the sequence. |
| 144 return buffer->GetEndTimestamp() + buffer->GetDuration() / 3; | 188 return buffer->GetEndTimestamp() + buffer->GetDuration() / 3; |
| 145 } | 189 } |
| 146 | 190 |
| 147 // Returns true if |timestamp| is the timestamp of the next buffer in | 191 // Returns true if |timestamp| is the timestamp of the next buffer in |
| 148 // sequence after |buffer|, false otherwise. | 192 // sequence after |buffer|, false otherwise. |
| 149 static bool IsNextInSequence( | 193 static bool IsNextInSequence( |
| 150 const scoped_refptr<media::StreamParserBuffer>& buffer, | 194 const scoped_refptr<media::StreamParserBuffer>& buffer, |
| 151 base::TimeDelta timestamp) { | 195 base::TimeDelta timestamp) { |
| 152 return timestamp >= buffer->GetEndTimestamp() && | 196 return timestamp >= buffer->GetEndTimestamp() && |
| 153 timestamp <= MaxNextTimestamp(buffer); | 197 timestamp <= MaxNextTimestamp(buffer); |
| 154 } | 198 } |
| 155 | 199 |
| 156 namespace media { | 200 namespace media { |
| 157 | 201 |
| 158 SourceBufferStream::SourceBufferStream() | 202 SourceBufferStream::SourceBufferStream() |
| 159 : seek_pending_(false), | 203 : seek_pending_(false), |
| 160 seek_buffer_timestamp_(kNoTimestamp()), | 204 seek_buffer_timestamp_(kNoTimestamp()), |
| 161 selected_range_(NULL), | 205 selected_range_(NULL) { |
| 162 waiting_for_keyframe_(false) { | |
| 163 } | 206 } |
| 164 | 207 |
| 165 SourceBufferStream::~SourceBufferStream() { | 208 SourceBufferStream::~SourceBufferStream() { |
| 166 while (!ranges_.empty()) { | 209 while (!ranges_.empty()) { |
| 167 delete ranges_.front(); | 210 delete ranges_.front(); |
| 168 ranges_.pop_front(); | 211 ranges_.pop_front(); |
| 169 } | 212 } |
| 170 } | 213 } |
| 171 | 214 |
| 172 bool SourceBufferStream::Append( | 215 bool SourceBufferStream::Append( |
| 173 const SourceBufferStream::BufferQueue& buffers) { | 216 const SourceBufferStream::BufferQueue& buffers) { |
| 174 DCHECK(!buffers.empty()); | 217 DCHECK(!buffers.empty()); |
| 175 | 218 |
| 176 // Check to see if |buffers| will overlap the currently |selected_range_|, | 219 RangeList::iterator range_for_new_buffers = ranges_.end(); |
| 177 // and if so, ignore this Append() request. | |
| 178 // TODO(vrk): Support overlapping selected range properly. (crbug.com/126560) | |
| 179 if (selected_range_ && | |
| 180 (selected_range_->IsEndOverlappedBy(buffers) || | |
| 181 selected_range_->IsStartOverlappedBy(buffers))) { | |
| 182 return false; | |
| 183 } | |
| 184 | |
| 185 SourceBufferRange* range = NULL; | |
| 186 RangeList::iterator itr = ranges_.end(); | 220 RangeList::iterator itr = ranges_.end(); |
| 187 base::TimeDelta start_timestamp = buffers.front()->GetTimestamp(); | 221 base::TimeDelta start_timestamp = buffers.front()->GetTimestamp(); |
| 188 for (itr = ranges_.begin(); itr != ranges_.end(); itr++) { | 222 for (itr = ranges_.begin(); itr != ranges_.end(); itr++) { |
| 189 int range_value = (*itr)->BelongsToRange(start_timestamp); | 223 int range_value = (*itr)->BelongsToRange(start_timestamp); |
| 190 | 224 if (range_value < 0) |
| 191 // |start_timestamp| is before the current range in this loop. Because | |
| 192 // |ranges_| is sorted, this means that we need to create a new range and it | |
| 193 // should be placed before |itr|. | |
| 194 // TODO(vrk): We also break out of the loop if |buffers| completely overlaps | |
| 195 // the current range. This is to cover the case when |buffers| belongs to | |
| 196 // the current range, but also completely overlaps it. This should be | |
| 197 // removed when start overlap is handled properly. | |
| 198 if (range_value < 0 || (*itr)->IsCompletelyOverlappedBy(buffers)) | |
| 199 break; | 225 break; |
| 200 | 226 |
| 201 if (range_value == 0) { | 227 if (range_value == 0) { |
| 202 // Found an existing range into which we can append buffers. | 228 // Found an existing range into which we can append buffers. |
| 203 range = *itr; | 229 range_for_new_buffers = itr; |
| 204 | |
| 205 if (range->CanAppendToEnd(buffers) && waiting_for_keyframe_) { | |
| 206 // Currently we do not support the case where the next buffer after the | |
| 207 // buffers in the track buffer is not a keyframe. | |
| 208 if (!buffers.front()->IsKeyframe()) | |
| 209 return false; | |
| 210 waiting_for_keyframe_ = false; | |
| 211 } | |
| 212 break; | 230 break; |
| 213 } | 231 } |
| 214 } | 232 } |
| 215 | 233 |
| 216 if (!range) { | 234 if (range_for_new_buffers == ranges_.end()) { |
| 217 // Ranges must begin with a keyframe. | 235 // Ranges must begin with a keyframe. |
| 218 if (!buffers.front()->IsKeyframe()) | 236 if (!buffers.front()->IsKeyframe()) |
| 219 return false; | 237 return false; |
| 220 | 238 range_for_new_buffers = |
| 221 range = new SourceBufferRange(); | 239 ranges_.insert(itr, new SourceBufferRange(buffers)); |
| 222 itr = ranges_.insert(itr, range); | 240 } else { |
| 241 InsertIntoExistingRange(range_for_new_buffers, buffers); | |
| 223 } | 242 } |
| 224 | 243 |
| 225 // Append buffers to the appropriate range. | |
| 226 range->Append(buffers); | |
| 227 | |
| 228 // Increment |itr| to be the range after |range|. | |
| 229 itr++; | |
| 230 | |
| 231 // Resolve overlaps. | 244 // Resolve overlaps. |
| 232 itr = ResolveCompleteOverlaps(itr, range); | 245 ResolveCompleteOverlaps(range_for_new_buffers); |
| 233 itr = ResolveEndOverlaps(itr, range); | 246 ResolveEndOverlap(range_for_new_buffers); |
| 234 MergeWithAdjacentRangeIfNecessary(itr, range); | 247 MergeWithAdjacentRangeIfNecessary(range_for_new_buffers); |
| 235 | 248 |
| 236 // Finally, try to complete pending seek if one exists. | 249 // Finally, try to complete pending seek if one exists. |
| 237 if (seek_pending_) | 250 if (seek_pending_) |
| 238 Seek(seek_buffer_timestamp_); | 251 Seek(seek_buffer_timestamp_); |
| 239 | 252 |
| 240 DCHECK(IsRangeListSorted(ranges_)); | 253 DCHECK(IsRangeListSorted(ranges_)); |
| 241 return true; | 254 return true; |
| 242 } | 255 } |
| 243 | 256 |
| 244 SourceBufferStream::RangeList::iterator | 257 void SourceBufferStream::InsertIntoExistingRange( |
| 245 SourceBufferStream::ResolveCompleteOverlaps( | 258 const RangeList::iterator& range_for_new_buffers_itr, |
| 246 const RangeList::iterator& range_itr, SourceBufferRange* new_range) { | 259 const BufferQueue& new_buffers) { |
| 247 RangeList::iterator itr = range_itr; | 260 SourceBufferRange* range_for_new_buffers = *range_for_new_buffers_itr; |
| 248 while (itr != ranges_.end() && new_range->CompletelyOverlaps(**itr)) { | 261 RangeList::iterator next_range_itr = range_for_new_buffers_itr; |
| 249 if (*itr == selected_range_) { | 262 next_range_itr++; |
| 250 // Get the timestamp for the next buffer in the sequence. | |
| 251 base::TimeDelta next_timestamp = selected_range_->GetNextTimestamp(); | |
| 252 // Then seek to the next keyframe after (or equal to) |next_timestamp|. | |
| 253 // This will allow us to transition from the old buffers to the new | |
| 254 // buffers seamlessly. | |
| 255 base::TimeDelta next_keyframe_timestamp = | |
| 256 new_range->SeekAfter(next_timestamp); | |
| 257 | 263 |
| 258 // If there's no keyframe after |next_timestamp|, then set flag to wait | 264 // In case this is a middle overlap, save the buffers that come after the end |
| 259 // for the next keyframe in this range to be appended. | 265 // of |new_buffers|, and add them into a new range. |
| 260 if (next_keyframe_timestamp == kNoTimestamp()) | 266 SourceBufferRange* new_portion = |
| 261 waiting_for_keyframe_ = true; | 267 range_for_new_buffers->SplitRange(new_buffers.back()->GetEndTimestamp()); |
| 262 | 268 |
| 263 // Add all the old buffers up until |next_keyframe_timestamp| into | 269 if (new_portion) { |
| 264 // |track_buffer_|. If there was no keyframe, then we add all buffers into | 270 next_range_itr = ranges_.insert(next_range_itr, new_portion); |
| 265 // |track_buffer_|. | 271 // If |range_for_new_buffers| was selected and the next buffer was in the |
| 266 scoped_refptr<StreamParserBuffer> next_buffer; | 272 // |new_portion| half, update |selected_range_|. |
| 267 while (selected_range_->GetNextBuffer(&next_buffer) && | 273 if (selected_range_ == range_for_new_buffers && |
| 268 (waiting_for_keyframe_ || | 274 new_portion->GetNextTimestamp() != kNoTimestamp()) { |
| 269 next_buffer->GetTimestamp() < next_keyframe_timestamp)) { | 275 selected_range_ = new_portion; |
| 270 track_buffer_.push_back(next_buffer); | 276 } |
| 271 } | 277 } |
| 272 | 278 |
| 273 selected_range_ = new_range; | 279 BufferQueue deleted_buffers; |
| 274 } | 280 BufferQueue::iterator next_buffer; |
| 275 delete *itr; | 281 range_for_new_buffers->DeleteAfter( |
| 276 itr = ranges_.erase(itr); | 282 new_buffers.front(), &deleted_buffers, &next_buffer); |
| 283 range_for_new_buffers->AppendToEnd(new_buffers); | |
| 284 | |
| 285 if (selected_range_ == range_for_new_buffers && | |
| 286 !deleted_buffers.empty() && next_buffer != deleted_buffers.end()) { | |
| 287 UpdateTrackBuffer(range_for_new_buffers_itr, deleted_buffers, next_buffer); | |
| 277 } | 288 } |
| 278 return itr; | |
| 279 } | 289 } |
| 280 | 290 |
| 281 SourceBufferStream::RangeList::iterator | 291 void SourceBufferStream::ResolveCompleteOverlaps( |
| 282 SourceBufferStream::ResolveEndOverlaps( | 292 const RangeList::iterator& range_with_new_buffers_itr) { |
| 283 const RangeList::iterator& range_itr, SourceBufferRange* new_range) { | 293 SourceBufferRange* range_with_new_buffers = *range_with_new_buffers_itr; |
| 284 RangeList::iterator itr = range_itr; | 294 RangeList::iterator next_range_itr = range_with_new_buffers_itr; |
| 285 while (itr != ranges_.end() && new_range->EndOverlaps(**itr)) { | 295 next_range_itr++; |
| 286 DCHECK_NE(*itr, selected_range_); | 296 |
| 287 delete *itr; | 297 while (next_range_itr != ranges_.end() && |
| 288 itr = ranges_.erase(itr); | 298 range_with_new_buffers->CompletelyOverlaps(**next_range_itr)) { |
| 299 if (*next_range_itr == selected_range_) { | |
| 300 // Delete everything from the selected range that |new_range| overlaps, | |
| 301 // and save the next buffers. | |
| 302 BufferQueue deleted_buffers; | |
| 303 BufferQueue::iterator next_buffer; | |
| 304 (*next_range_itr)->DeleteAll(&deleted_buffers, &next_buffer); | |
| 305 | |
| 306 // Update |selected_range_| then update the track buffer. | |
| 307 selected_range_ = range_with_new_buffers; | |
|
acolwell GONE FROM CHROMIUM
2012/05/22 19:35:23
This might not be necessary. It looks like UpdateT
vrk (LEFT CHROMIUM)
2012/05/24 20:06:30
Yes, you're right, removed and added DCHECK_NE(sel
| |
| 308 UpdateTrackBuffer(range_with_new_buffers_itr, | |
| 309 deleted_buffers, next_buffer); | |
| 310 } | |
| 311 delete *next_range_itr; | |
| 312 next_range_itr = ranges_.erase(next_range_itr); | |
| 289 } | 313 } |
| 290 return itr; | 314 } |
| 315 | |
| 316 void SourceBufferStream::ResolveEndOverlap( | |
| 317 const RangeList::iterator& range_with_new_buffers_itr) { | |
| 318 SourceBufferRange* range_with_new_buffers = *range_with_new_buffers_itr; | |
| 319 RangeList::iterator next_range_itr = range_with_new_buffers_itr; | |
| 320 next_range_itr++; | |
| 321 | |
| 322 if (next_range_itr == ranges_.end() || | |
| 323 !range_with_new_buffers->EndOverlaps(**next_range_itr)) { | |
| 324 return; | |
| 325 } | |
| 326 | |
| 327 // Split the overlapped range after |range_with_new_buffers|'s last buffer | |
| 328 // overlaps. Now |overlapped_range| contains only the buffers that do not | |
| 329 // belong in |ranges_| anymore, and |new_next_range| contains buffers that | |
| 330 // go after |range_with_new_buffers| (without overlap). | |
| 331 scoped_ptr<SourceBufferRange> overlapped_range(*next_range_itr); | |
| 332 SourceBufferRange* new_next_range = | |
| 333 overlapped_range->SplitRange(range_with_new_buffers->GetEndTimestamp()); | |
| 334 | |
| 335 // Remove |overlapped_range| from the range list, since it now contains only | |
| 336 // buffers that are redundant with |range_with_new_buffers|. | |
| 337 next_range_itr = ranges_.erase(next_range_itr); | |
|
acolwell GONE FROM CHROMIUM
2012/05/22 19:35:23
I think it would be better to put this above the p
vrk (LEFT CHROMIUM)
2012/05/24 20:06:30
Good idea, done.
| |
| 338 | |
| 339 // If there were non-overlapped buffers, add the new range to |ranges_|. | |
| 340 if (new_next_range) | |
| 341 ranges_.insert(next_range_itr, new_next_range); | |
| 342 | |
| 343 // If we didn't overlap a selected range, return. | |
| 344 if (selected_range_ != overlapped_range.get()) | |
| 345 return; | |
| 346 | |
| 347 // If the next buffer was in the |new_next_range| half of the overlapped | |
| 348 // range, then the |selected_range_| is now |new_next_range|. | |
| 349 if (new_next_range && | |
| 350 new_next_range->GetNextTimestamp() != kNoTimestamp()) { | |
| 351 selected_range_ = new_next_range; | |
| 352 return; | |
| 353 } | |
| 354 | |
| 355 // Otherwise, update track buffer with overlapped buffers. | |
| 356 BufferQueue deleted_buffers; | |
| 357 scoped_refptr<StreamParserBuffer> buffer; | |
| 358 while (overlapped_range->GetNextBuffer(&buffer)) { | |
| 359 deleted_buffers.push_back(buffer); | |
| 360 } | |
| 361 BufferQueue::iterator next_buffer = deleted_buffers.begin(); | |
| 362 UpdateTrackBuffer(range_with_new_buffers_itr, deleted_buffers, next_buffer); | |
|
acolwell GONE FROM CHROMIUM
2012/05/22 19:35:23
You might want to add a comment here indicating th
vrk (LEFT CHROMIUM)
2012/05/24 20:06:30
Added a DCHECK and comment.
| |
| 363 } | |
| 364 | |
| 365 void SourceBufferStream::UpdateTrackBuffer( | |
| 366 const RangeList::iterator& range_with_new_buffers_itr, | |
| 367 const BufferQueue& deleted_buffers, | |
| 368 const BufferQueue::iterator& next_buffer) { | |
| 369 DCHECK(!deleted_buffers.empty() && next_buffer != deleted_buffers.end()); | |
| 370 | |
| 371 SourceBufferRange* range_with_new_buffers = *range_with_new_buffers_itr; | |
| 372 | |
| 373 // Seek to the next keyframe after (or equal to) the timestamp of the next | |
| 374 // buffer being overlapped. | |
| 375 range_with_new_buffers->SeekAfter((*next_buffer)->GetTimestamp()); | |
| 376 selected_range_ = range_with_new_buffers; | |
| 377 | |
| 378 base::TimeDelta next_keyframe_timestamp = | |
| 379 range_with_new_buffers->GetNextTimestamp(); | |
| 380 | |
| 381 if (track_buffer_.empty()) { | |
| 382 // Add all the old buffers up until |next_keyframe_timestamp| into | |
| 383 // |track_buffer_|. If there was no next keyframe, then we add all buffers | |
| 384 // into |track_buffer_|. | |
| 385 BufferQueue::iterator next_buffer_itr = next_buffer; | |
| 386 while (next_buffer_itr != deleted_buffers.end() && | |
| 387 (next_keyframe_timestamp == kNoTimestamp() || | |
| 388 (*next_buffer_itr)->GetTimestamp() < next_keyframe_timestamp)) { | |
| 389 track_buffer_.push_back(*next_buffer_itr); | |
| 390 next_buffer_itr++; | |
| 391 } | |
| 392 } | |
| 393 | |
| 394 // See if the next range contains the keyframe after the end of the | |
| 395 // |track_buffer_|, and if so, change |selected_range_|. | |
| 396 if (next_keyframe_timestamp == kNoTimestamp()) { | |
| 397 DCHECK(!track_buffer_.empty()); | |
| 398 RangeList::iterator next_range_itr = range_with_new_buffers_itr; | |
| 399 next_range_itr++; | |
| 400 if (next_range_itr != ranges_.end()) { | |
|
acolwell GONE FROM CHROMIUM
2012/05/22 19:35:23
I don't think I really understand what is going on
vrk (LEFT CHROMIUM)
2012/05/24 20:06:30
Close: the track buffer should never overlap with
| |
| 401 (*next_range_itr)->SeekAfter(track_buffer_.back()->GetEndTimestamp()); | |
| 402 if (IsNextInSequence(track_buffer_.back(), | |
| 403 (*next_range_itr)->GetNextTimestamp())) { | |
| 404 selected_range_ = *next_range_itr; | |
| 405 } | |
| 406 } | |
| 407 } | |
| 291 } | 408 } |
| 292 | 409 |
| 293 void SourceBufferStream::MergeWithAdjacentRangeIfNecessary( | 410 void SourceBufferStream::MergeWithAdjacentRangeIfNecessary( |
| 294 const RangeList::iterator& itr, SourceBufferRange* new_range) { | 411 const RangeList::iterator& range_with_new_buffers_itr) { |
| 295 if (itr != ranges_.end() && new_range->CanAppendToEnd(**itr)) { | 412 SourceBufferRange* range_with_new_buffers = *range_with_new_buffers_itr; |
| 296 bool transfer_current_position = selected_range_ == *itr; | 413 RangeList::iterator next_range_itr = range_with_new_buffers_itr; |
| 297 new_range->AppendToEnd(**itr, transfer_current_position); | 414 next_range_itr++; |
| 415 | |
| 416 if (next_range_itr != ranges_.end() && | |
| 417 range_with_new_buffers->CanAppendToEnd(**next_range_itr)) { | |
| 418 bool transfer_current_position = selected_range_ == *next_range_itr; | |
| 419 range_with_new_buffers->AppendToEnd(**next_range_itr, | |
| 420 transfer_current_position); | |
| 298 // Update |selected_range_| pointer if |range| has become selected after | 421 // Update |selected_range_| pointer if |range| has become selected after |
| 299 // merges. | 422 // merges. |
| 300 if (transfer_current_position) | 423 if (transfer_current_position) |
| 301 selected_range_ = new_range; | 424 selected_range_ = range_with_new_buffers; |
| 302 | 425 |
| 303 delete *itr; | 426 delete *next_range_itr; |
| 304 ranges_.erase(itr); | 427 ranges_.erase(next_range_itr); |
| 305 } | 428 } |
| 306 } | 429 } |
| 307 | 430 |
| 308 void SourceBufferStream::Seek(base::TimeDelta timestamp) { | 431 void SourceBufferStream::Seek(base::TimeDelta timestamp) { |
| 309 selected_range_ = NULL; | 432 selected_range_ = NULL; |
| 310 track_buffer_.clear(); | 433 track_buffer_.clear(); |
| 311 waiting_for_keyframe_ = false; | |
| 312 | 434 |
| 313 seek_buffer_timestamp_ = timestamp; | 435 seek_buffer_timestamp_ = timestamp; |
| 314 seek_pending_ = true; | 436 seek_pending_ = true; |
| 315 | 437 |
| 316 RangeList::iterator itr = ranges_.end(); | 438 RangeList::iterator itr = ranges_.end(); |
| 317 for (itr = ranges_.begin(); itr != ranges_.end(); itr++) { | 439 for (itr = ranges_.begin(); itr != ranges_.end(); itr++) { |
| 318 if ((*itr)->CanSeekTo(timestamp)) | 440 if ((*itr)->CanSeekTo(timestamp)) |
| 319 break; | 441 break; |
| 320 } | 442 } |
| 321 | 443 |
| (...skipping 18 matching lines...) Expand all Loading... | |
| 340 std::list<SourceBufferStream::Timespan> | 462 std::list<SourceBufferStream::Timespan> |
| 341 SourceBufferStream::GetBufferedTime() const { | 463 SourceBufferStream::GetBufferedTime() const { |
| 342 std::list<Timespan> timespans; | 464 std::list<Timespan> timespans; |
| 343 for (RangeList::const_iterator itr = ranges_.begin(); | 465 for (RangeList::const_iterator itr = ranges_.begin(); |
| 344 itr != ranges_.end(); itr++) { | 466 itr != ranges_.end(); itr++) { |
| 345 timespans.push_back((*itr)->GetBufferedTime()); | 467 timespans.push_back((*itr)->GetBufferedTime()); |
| 346 } | 468 } |
| 347 return timespans; | 469 return timespans; |
| 348 } | 470 } |
| 349 | 471 |
| 350 SourceBufferRange::SourceBufferRange() | 472 SourceBufferRange::SourceBufferRange(const BufferQueue& new_buffers) |
| 351 : next_buffer_index_(-1) { | 473 : next_buffer_index_(-1), |
| 352 } | 474 waiting_for_keyframe_(false), |
| 353 | 475 next_keyframe_timestamp_(kNoTimestamp()) { |
| 354 void SourceBufferRange::Append(const BufferQueue& new_buffers) { | 476 DCHECK(!new_buffers.empty()); |
| 355 base::TimeDelta start_timestamp = new_buffers.front()->GetTimestamp(); | 477 DCHECK(new_buffers.front()->IsKeyframe()); |
| 356 | |
| 357 if (!buffers_.empty() && start_timestamp < BufferedEnd()) { | |
| 358 // We are overwriting existing data, so find the starting point where | |
| 359 // things will get overwritten. | |
| 360 BufferQueue::iterator starting_point = | |
| 361 std::lower_bound(buffers_.begin(), buffers_.end(), | |
| 362 new_buffers.front(), | |
| 363 BufferComparator); | |
| 364 | |
| 365 // Remove everything from |starting_point| onward. | |
| 366 buffers_.erase(starting_point, buffers_.end()); | |
| 367 } | |
| 368 | |
| 369 // Append data. | |
| 370 AppendToEnd(new_buffers); | 478 AppendToEnd(new_buffers); |
| 371 } | 479 } |
| 372 | 480 |
| 373 void SourceBufferRange::AppendToEnd(const BufferQueue& new_buffers) { | 481 void SourceBufferRange::AppendToEnd(const BufferQueue& new_buffers) { |
| 374 for (BufferQueue::const_iterator itr = new_buffers.begin(); | 482 for (BufferQueue::const_iterator itr = new_buffers.begin(); |
| 375 itr != new_buffers.end(); itr++) { | 483 itr != new_buffers.end(); itr++) { |
| 376 DCHECK((*itr)->GetDuration() > base::TimeDelta()); | 484 DCHECK((*itr)->GetDuration() > base::TimeDelta()); |
| 377 DCHECK((*itr)->GetTimestamp() != kNoTimestamp()); | 485 DCHECK((*itr)->GetTimestamp() != kNoTimestamp()); |
| 378 buffers_.push_back(*itr); | 486 buffers_.push_back(*itr); |
| 379 if ((*itr)->IsKeyframe()) { | 487 if ((*itr)->IsKeyframe()) { |
| 380 keyframe_map_.insert( | 488 keyframe_map_.insert( |
| 381 std::make_pair((*itr)->GetTimestamp(), buffers_.size() - 1)); | 489 std::make_pair((*itr)->GetTimestamp(), buffers_.size() - 1)); |
| 490 | |
| 491 if (waiting_for_keyframe_ && | |
| 492 (*itr)->GetTimestamp() >= next_keyframe_timestamp_) { | |
| 493 next_buffer_index_ = buffers_.size() - 1; | |
| 494 next_keyframe_timestamp_ = base::TimeDelta(); | |
| 495 waiting_for_keyframe_ = false; | |
| 496 } | |
| 382 } | 497 } |
| 383 } | 498 } |
| 384 } | 499 } |
| 385 | 500 |
| 386 void SourceBufferRange::Seek(base::TimeDelta timestamp) { | 501 void SourceBufferRange::Seek(base::TimeDelta timestamp) { |
| 387 DCHECK(CanSeekTo(timestamp)); | 502 DCHECK(CanSeekTo(timestamp)); |
| 388 DCHECK(!keyframe_map_.empty()); | 503 DCHECK(!keyframe_map_.empty()); |
| 389 | 504 |
| 505 next_keyframe_timestamp_ = base::TimeDelta(); | |
| 506 waiting_for_keyframe_ = false; | |
| 507 | |
| 390 KeyframeMap::iterator result = keyframe_map_.lower_bound(timestamp); | 508 KeyframeMap::iterator result = keyframe_map_.lower_bound(timestamp); |
| 391 // lower_bound() returns the first element >= |timestamp|, so we want the | 509 // lower_bound() returns the first element >= |timestamp|, so we want the |
| 392 // previous element if it did not return the element exactly equal to | 510 // previous element if it did not return the element exactly equal to |
| 393 // |timestamp|. | 511 // |timestamp|. |
| 394 if (result == keyframe_map_.end() || result->first != timestamp) { | 512 if (result == keyframe_map_.end() || result->first != timestamp) { |
| 395 DCHECK(result != keyframe_map_.begin()); | 513 DCHECK(result != keyframe_map_.begin()); |
| 396 result--; | 514 result--; |
| 397 } | 515 } |
| 398 next_buffer_index_ = result->second; | 516 next_buffer_index_ = result->second; |
| 399 DCHECK_LT(next_buffer_index_, static_cast<int>(buffers_.size())); | 517 DCHECK_LT(next_buffer_index_, static_cast<int>(buffers_.size())); |
| 400 } | 518 } |
| 401 | 519 |
| 402 base::TimeDelta SourceBufferRange::SeekAfter(base::TimeDelta timestamp) { | 520 void SourceBufferRange::SeekAfter(base::TimeDelta timestamp) { |
| 403 DCHECK_EQ(BelongsToRange(timestamp), 0); | |
| 404 DCHECK(!keyframe_map_.empty()); | 521 DCHECK(!keyframe_map_.empty()); |
| 405 | 522 |
| 406 // lower_bound() returns the first element >= |timestamp|, so |result| is the | 523 // lower_bound() returns the first element >= |timestamp|, so |result| is the |
| 407 // value that we want. | 524 // value that we want. |
| 408 KeyframeMap::iterator result = keyframe_map_.lower_bound(timestamp); | 525 KeyframeMap::iterator result = keyframe_map_.lower_bound(timestamp); |
| 409 | 526 |
| 410 // If there isn't a keyframe after |timestamp|, then seek to end and return | 527 // If there isn't a keyframe after |timestamp|, then seek to end and return |
| 411 // kNoTimestamp to signal such. | 528 // kNoTimestamp to signal such. |
| 412 if (result == keyframe_map_.end()) { | 529 if (result == keyframe_map_.end()) { |
| 413 next_buffer_index_ = buffers_.size(); | 530 waiting_for_keyframe_ = true; |
| 414 return kNoTimestamp(); | 531 next_buffer_index_ = -1; |
| 532 next_keyframe_timestamp_ = timestamp; | |
| 533 return; | |
| 415 } | 534 } |
| 416 | 535 |
| 417 next_buffer_index_ = result->second; | 536 next_buffer_index_ = result->second; |
| 418 DCHECK_LT(next_buffer_index_, static_cast<int>(buffers_.size())); | 537 DCHECK_LT(next_buffer_index_, static_cast<int>(buffers_.size())); |
| 419 return result->first; | |
| 420 } | 538 } |
| 421 | 539 |
| 540 SourceBufferRange* SourceBufferRange::SplitRange(base::TimeDelta timestamp) { | |
| 541 // Find the first keyframe after |timestamp|. | |
| 542 KeyframeMap::iterator new_beginning_keyframe = | |
| 543 keyframe_map_.lower_bound(timestamp); | |
| 544 | |
| 545 // If there is no keyframe after |timestamp|, we can't split the range. | |
| 546 if (new_beginning_keyframe == keyframe_map_.end()) | |
| 547 return NULL; | |
| 548 | |
| 549 int keyframe_index = new_beginning_keyframe->second; | |
| 550 DCHECK_LT(keyframe_index, static_cast<int>(buffers_.size())); | |
| 551 | |
| 552 BufferQueue removed_buffers; | |
| 553 BufferQueue::iterator next_buffer; | |
| 554 DeleteAfter( | |
| 555 buffers_.begin() + keyframe_index, &removed_buffers, &next_buffer); | |
| 556 | |
| 557 SourceBufferRange* split_range = new SourceBufferRange(removed_buffers); | |
| 558 if (next_buffer != removed_buffers.end()) { | |
| 559 split_range->next_buffer_index_ = next_buffer - removed_buffers.begin(); | |
| 560 } | |
| 561 return split_range; | |
| 562 } | |
| 563 | |
| 564 void SourceBufferRange::DeleteAll(BufferQueue* removed_buffers, | |
| 565 BufferQueue::iterator* next_buffer) { | |
| 566 DeleteAfter(buffers_.begin(), removed_buffers, next_buffer); | |
| 567 } | |
| 568 | |
| 569 void SourceBufferRange::DeleteAfter( | |
| 570 scoped_refptr<StreamParserBuffer> buffer, | |
| 571 BufferQueue* removed_buffers, | |
| 572 BufferQueue::iterator* next_buffer) { | |
| 573 // Find the place in |buffers_| where we will begin deleting data. | |
| 574 BufferQueue::iterator starting_point = | |
| 575 std::lower_bound(buffers_.begin(), buffers_.end(), | |
| 576 buffer, | |
| 577 BufferComparator); | |
| 578 DeleteAfter(starting_point, removed_buffers, next_buffer); | |
| 579 } | |
| 580 | |
| 581 void SourceBufferRange::DeleteAfter( | |
| 582 BufferQueue::iterator starting_point, | |
| 583 BufferQueue* removed_buffers, | |
| 584 BufferQueue::iterator* next_buffer) { | |
| 585 // Return if we're not deleting anything. | |
| 586 if (starting_point == buffers_.end()) | |
| 587 return; | |
| 588 | |
| 589 // Find the first keyframe after |starting_point|. | |
| 590 KeyframeMap::iterator starting_point_keyframe = | |
| 591 keyframe_map_.lower_bound((*starting_point)->GetTimestamp()); | |
| 592 | |
| 593 // Save the buffers we're about to delete. | |
| 594 if (removed_buffers) { | |
| 595 BufferQueue saved(starting_point, buffers_.end()); | |
| 596 removed_buffers->swap(saved); | |
| 597 if (next_buffer) | |
| 598 *next_buffer = removed_buffers->end(); | |
| 599 } | |
| 600 | |
| 601 // Reset the next buffer index if we will be deleting the buffer that's next | |
| 602 // in sequence. | |
| 603 base::TimeDelta next_buffer_timestamp = GetNextTimestamp(); | |
| 604 if (next_buffer_timestamp != kNoTimestamp() && | |
| 605 next_buffer_timestamp >= (*starting_point)->GetTimestamp()) { | |
| 606 if (removed_buffers && next_buffer) { | |
| 607 int starting_offset = starting_point - buffers_.begin(); | |
| 608 int next_buffer_offset = next_buffer_index_ - starting_offset; | |
| 609 DCHECK_GE(next_buffer_offset, 0); | |
| 610 *next_buffer = removed_buffers->begin() + next_buffer_offset; | |
| 611 } | |
| 612 next_buffer_index_ = -1; | |
| 613 } | |
| 614 | |
| 615 // Remove keyframes from |starting_point| onward. | |
| 616 keyframe_map_.erase(starting_point_keyframe, keyframe_map_.end()); | |
| 617 | |
| 618 // Remove everything from |starting_point| onward. | |
| 619 buffers_.erase(starting_point, buffers_.end()); | |
| 620 } | |
| 422 | 621 |
| 423 bool SourceBufferRange::GetNextBuffer( | 622 bool SourceBufferRange::GetNextBuffer( |
| 424 scoped_refptr<StreamParserBuffer>* out_buffer) { | 623 scoped_refptr<StreamParserBuffer>* out_buffer) { |
| 624 if (waiting_for_keyframe_ || | |
| 625 next_buffer_index_ >= static_cast<int>(buffers_.size())) { | |
| 626 return false; | |
| 627 } | |
| 628 | |
| 425 DCHECK_GE(next_buffer_index_, 0); | 629 DCHECK_GE(next_buffer_index_, 0); |
| 426 if (next_buffer_index_ >= static_cast<int>(buffers_.size())) | |
| 427 return false; | |
| 428 | |
| 429 *out_buffer = buffers_.at(next_buffer_index_); | 630 *out_buffer = buffers_.at(next_buffer_index_); |
| 430 next_buffer_index_++; | 631 next_buffer_index_++; |
| 431 return true; | 632 return true; |
| 432 } | 633 } |
| 433 | 634 |
| 434 base::TimeDelta SourceBufferRange::GetNextTimestamp() const { | 635 base::TimeDelta SourceBufferRange::GetNextTimestamp() const { |
| 435 DCHECK_GE(next_buffer_index_, 0); | |
| 436 DCHECK(!buffers_.empty()); | 636 DCHECK(!buffers_.empty()); |
| 437 | 637 |
| 438 if (next_buffer_index_ >= static_cast<int>(buffers_.size())) | 638 if (next_buffer_index_ >= static_cast<int>(buffers_.size()) || |
| 439 return buffers_.back()->GetEndTimestamp(); | 639 next_buffer_index_ < 0 || waiting_for_keyframe_) { |
| 640 return kNoTimestamp(); | |
| 641 } | |
| 440 | 642 |
| 441 return buffers_.at(next_buffer_index_)->GetTimestamp(); | 643 return buffers_.at(next_buffer_index_)->GetTimestamp(); |
| 442 } | 644 } |
| 443 | 645 |
| 646 base::TimeDelta SourceBufferRange::GetEndTimestamp() const { | |
| 647 return BufferedEnd(); | |
|
acolwell GONE FROM CHROMIUM
2012/05/22 19:35:23
nit: One of these two methods should be removed si
vrk (LEFT CHROMIUM)
2012/05/24 20:06:30
Done.
| |
| 648 } | |
| 649 | |
| 444 SourceBufferStream::Timespan | 650 SourceBufferStream::Timespan |
| 445 SourceBufferRange::GetBufferedTime() const { | 651 SourceBufferRange::GetBufferedTime() const { |
| 446 return std::make_pair(BufferedStart(), BufferedEnd()); | 652 return std::make_pair(BufferedStart(), BufferedEnd()); |
| 447 } | 653 } |
| 448 | 654 |
| 449 void SourceBufferRange::AppendToEnd(const SourceBufferRange& range, | 655 void SourceBufferRange::AppendToEnd(const SourceBufferRange& range, |
| 450 bool transfer_current_position) { | 656 bool transfer_current_position) { |
| 451 DCHECK(CanAppendToEnd(range)); | 657 DCHECK(CanAppendToEnd(range)); |
| 452 DCHECK(!buffers_.empty()); | 658 DCHECK(!buffers_.empty()); |
| 453 | 659 |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 491 const SourceBufferRange& range) const { | 697 const SourceBufferRange& range) const { |
| 492 return BufferedStart() <= range.BufferedStart() && | 698 return BufferedStart() <= range.BufferedStart() && |
| 493 BufferedEnd() >= range.BufferedEnd(); | 699 BufferedEnd() >= range.BufferedEnd(); |
| 494 } | 700 } |
| 495 | 701 |
| 496 bool SourceBufferRange::EndOverlaps(const SourceBufferRange& range) const { | 702 bool SourceBufferRange::EndOverlaps(const SourceBufferRange& range) const { |
| 497 return range.BufferedStart() < BufferedEnd() && | 703 return range.BufferedStart() < BufferedEnd() && |
| 498 BufferedEnd() < range.BufferedEnd(); | 704 BufferedEnd() < range.BufferedEnd(); |
| 499 } | 705 } |
| 500 | 706 |
| 501 bool SourceBufferRange::IsStartOverlappedBy(const BufferQueue& buffers) const { | |
| 502 base::TimeDelta start_timestamp = buffers.front()->GetTimestamp(); | |
| 503 return BufferedStart() < start_timestamp && start_timestamp < BufferedEnd(); | |
| 504 } | |
| 505 | |
| 506 bool SourceBufferRange::IsEndOverlappedBy(const BufferQueue& buffers) const { | |
| 507 base::TimeDelta end_timestamp = buffers.back()->GetEndTimestamp(); | |
| 508 return BufferedStart() < end_timestamp && end_timestamp < BufferedEnd(); | |
| 509 } | |
| 510 | |
| 511 bool SourceBufferRange::IsCompletelyOverlappedBy( | |
| 512 const BufferQueue& buffers) const { | |
| 513 base::TimeDelta start_timestamp = buffers.front()->GetTimestamp(); | |
| 514 base::TimeDelta end_timestamp = buffers.back()->GetEndTimestamp(); | |
| 515 return start_timestamp <= BufferedStart() && BufferedEnd() <= end_timestamp; | |
| 516 } | |
| 517 | |
| 518 base::TimeDelta SourceBufferRange::BufferedStart() const { | 707 base::TimeDelta SourceBufferRange::BufferedStart() const { |
| 519 if (buffers_.empty()) | 708 if (buffers_.empty()) |
| 520 return kNoTimestamp(); | 709 return kNoTimestamp(); |
| 521 | |
| 522 return buffers_.front()->GetTimestamp(); | 710 return buffers_.front()->GetTimestamp(); |
| 523 } | 711 } |
| 524 | 712 |
| 525 base::TimeDelta SourceBufferRange::BufferedEnd() const { | 713 base::TimeDelta SourceBufferRange::BufferedEnd() const { |
| 526 if (buffers_.empty()) | 714 if (buffers_.empty()) |
| 527 return kNoTimestamp(); | 715 return kNoTimestamp(); |
| 528 | |
| 529 return buffers_.back()->GetEndTimestamp(); | 716 return buffers_.back()->GetEndTimestamp(); |
| 530 } | 717 } |
| 531 | 718 |
| 532 } // namespace media | 719 } // namespace media |
| OLD | NEW |