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