| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "media/filters/source_buffer_stream.h" | 5 #include "media/filters/source_buffer_stream.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 #include <map> | 8 #include <map> |
| 9 | 9 |
| 10 #include "base/bind.h" | 10 #include "base/bind.h" |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 76 // deleted, and deletes the |keyframe_map_| entries for the buffers that | 76 // deleted, and deletes the |keyframe_map_| entries for the buffers that |
| 77 // were removed. | 77 // were removed. |
| 78 // |deleted_buffers| contains the buffers that were deleted from this range, | 78 // |deleted_buffers| contains the buffers that were deleted from this range, |
| 79 // starting at the buffer that had been at |next_buffer_index_|. | 79 // starting at the buffer that had been at |next_buffer_index_|. |
| 80 // Returns true if the |next_buffer_index_| is reset. Note that this method | 80 // Returns true if the |next_buffer_index_| is reset. Note that this method |
| 81 // may return true even if it does not add any buffers to |deleted_buffers|. | 81 // may return true even if it does not add any buffers to |deleted_buffers|. |
| 82 // This indicates that the range had not buffered |next_buffer_index_|, but | 82 // This indicates that the range had not buffered |next_buffer_index_|, but |
| 83 // a buffer at that position would have been deleted. | 83 // a buffer at that position would have been deleted. |
| 84 bool TruncateAt(scoped_refptr<StreamParserBuffer> buffer, | 84 bool TruncateAt(scoped_refptr<StreamParserBuffer> buffer, |
| 85 BufferQueue* deleted_buffers); | 85 BufferQueue* deleted_buffers); |
| 86 bool TruncateAt(base::TimeDelta timestamp); |
| 86 // Deletes all buffers in range. | 87 // Deletes all buffers in range. |
| 87 bool DeleteAll(BufferQueue* deleted_buffers); | 88 bool DeleteAll(BufferQueue* deleted_buffers); |
| 88 | 89 |
| 89 // Attempts to free |bytes| data from the range, preferring to delete at the | 90 // Attempts to free |bytes| data from the range, preferring to delete at the |
| 90 // beginning of the range. Deletes data in GOPS at a time so that the range | 91 // beginning of the range. Deletes data in GOPS at a time so that the range |
| 91 // always begins with a keyframe. Returns the number of bytes freed. | 92 // always begins with a keyframe. Returns the number of bytes freed. |
| 92 int FreeFromStart(int bytes); | 93 int FreeFromStart(int bytes); |
| 93 | 94 |
| 94 // Attempts to free |bytes| data from the range, preferring to delete at the | 95 // Attempts to free |bytes| data from the range, preferring to delete at the |
| 95 // end of the range. Returns the number of bytes freed. | 96 // end of the range. Returns the number of bytes freed. |
| (...skipping 312 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 408 } | 409 } |
| 409 } | 410 } |
| 410 | 411 |
| 411 GarbageCollectIfNeeded(); | 412 GarbageCollectIfNeeded(); |
| 412 | 413 |
| 413 DCHECK(IsRangeListSorted(ranges_)); | 414 DCHECK(IsRangeListSorted(ranges_)); |
| 414 DCHECK(OnlySelectedRangeIsSeeked()); | 415 DCHECK(OnlySelectedRangeIsSeeked()); |
| 415 return true; | 416 return true; |
| 416 } | 417 } |
| 417 | 418 |
| 419 void SourceBufferStream::ResetSeekState() { |
| 420 SetSelectedRange(NULL); |
| 421 track_buffer_.clear(); |
| 422 config_change_pending_ = false; |
| 423 } |
| 424 |
| 418 bool SourceBufferStream::ShouldSeekToStartOfBuffered( | 425 bool SourceBufferStream::ShouldSeekToStartOfBuffered( |
| 419 base::TimeDelta seek_timestamp) const { | 426 base::TimeDelta seek_timestamp) const { |
| 420 if (ranges_.empty()) | 427 if (ranges_.empty()) |
| 421 return false; | 428 return false; |
| 422 base::TimeDelta beginning_of_buffered = | 429 base::TimeDelta beginning_of_buffered = |
| 423 ranges_.front()->GetStartTimestamp(); | 430 ranges_.front()->GetStartTimestamp(); |
| 424 return (seek_timestamp <= beginning_of_buffered && | 431 return (seek_timestamp <= beginning_of_buffered && |
| 425 beginning_of_buffered < kSeekToStartFudgeRoom()); | 432 beginning_of_buffered < kSeekToStartFudgeRoom()); |
| 426 } | 433 } |
| 427 | 434 |
| (...skipping 286 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 714 if (transfer_current_position) | 721 if (transfer_current_position) |
| 715 SetSelectedRange(range_with_new_buffers); | 722 SetSelectedRange(range_with_new_buffers); |
| 716 | 723 |
| 717 delete *next_range_itr; | 724 delete *next_range_itr; |
| 718 ranges_.erase(next_range_itr); | 725 ranges_.erase(next_range_itr); |
| 719 } | 726 } |
| 720 } | 727 } |
| 721 | 728 |
| 722 void SourceBufferStream::Seek(base::TimeDelta timestamp) { | 729 void SourceBufferStream::Seek(base::TimeDelta timestamp) { |
| 723 DCHECK(timestamp >= base::TimeDelta()); | 730 DCHECK(timestamp >= base::TimeDelta()); |
| 724 SetSelectedRange(NULL); | 731 ResetSeekState(); |
| 725 track_buffer_.clear(); | |
| 726 config_change_pending_ = false; | |
| 727 | 732 |
| 728 if (ShouldSeekToStartOfBuffered(timestamp)) { | 733 if (ShouldSeekToStartOfBuffered(timestamp)) { |
| 729 SetSelectedRange(ranges_.front()); | 734 SetSelectedRange(ranges_.front()); |
| 730 ranges_.front()->SeekToStart(); | 735 ranges_.front()->SeekToStart(); |
| 731 seek_pending_ = false; | 736 seek_pending_ = false; |
| 732 return; | 737 return; |
| 733 } | 738 } |
| 734 | 739 |
| 735 seek_buffer_timestamp_ = timestamp; | 740 seek_buffer_timestamp_ = timestamp; |
| 736 seek_pending_ = true; | 741 seek_pending_ = true; |
| 737 | 742 |
| 738 RangeList::iterator itr = ranges_.end(); | 743 RangeList::iterator itr = ranges_.end(); |
| 739 for (itr = ranges_.begin(); itr != ranges_.end(); ++itr) { | 744 for (itr = ranges_.begin(); itr != ranges_.end(); ++itr) { |
| 740 if ((*itr)->CanSeekTo(timestamp)) | 745 if ((*itr)->CanSeekTo(timestamp)) |
| 741 break; | 746 break; |
| 742 } | 747 } |
| 743 | 748 |
| 744 if (itr == ranges_.end()) | 749 if (itr == ranges_.end()) |
| 745 return; | 750 return; |
| 746 | 751 |
| 747 SetSelectedRange(*itr); | 752 SetSelectedRange(*itr); |
| 748 selected_range_->Seek(timestamp); | 753 selected_range_->Seek(timestamp); |
| 749 seek_pending_ = false; | 754 seek_pending_ = false; |
| 750 } | 755 } |
| 751 | 756 |
| 752 bool SourceBufferStream::IsSeekPending() const { | 757 bool SourceBufferStream::IsSeekPending() const { |
| 753 return seek_pending_; | 758 return seek_pending_; |
| 754 } | 759 } |
| 755 | 760 |
| 761 void SourceBufferStream::OnSetDuration(base::TimeDelta duration) { |
| 762 RangeList::iterator itr = ranges_.end(); |
| 763 for (itr = ranges_.begin(); itr != ranges_.end(); ++itr) { |
| 764 if ((*itr)->GetEndTimestamp() > duration) |
| 765 break; |
| 766 } |
| 767 if (itr == ranges_.end()) |
| 768 return; |
| 769 |
| 770 // Need to partially truncate this range. |
| 771 if ((*itr)->GetStartTimestamp() < duration) { |
| 772 bool deleted_seek_point = (*itr)->TruncateAt(duration); |
| 773 if (deleted_seek_point) |
| 774 ResetSeekState(); |
| 775 ++itr; |
| 776 } |
| 777 |
| 778 // Delete all ranges that begin after |duration|. |
| 779 while (itr != ranges_.end()) { |
| 780 // If we're about to delete the selected range, also reset the seek state. |
| 781 DCHECK((*itr)->GetStartTimestamp() >= duration); |
| 782 if (*itr== selected_range_) |
| 783 ResetSeekState(); |
| 784 delete *itr; |
| 785 itr = ranges_.erase(itr); |
| 786 } |
| 787 } |
| 788 |
| 756 SourceBufferStream::Status SourceBufferStream::GetNextBuffer( | 789 SourceBufferStream::Status SourceBufferStream::GetNextBuffer( |
| 757 scoped_refptr<StreamParserBuffer>* out_buffer) { | 790 scoped_refptr<StreamParserBuffer>* out_buffer) { |
| 758 CHECK(!config_change_pending_); | 791 CHECK(!config_change_pending_); |
| 759 | 792 |
| 760 if (!track_buffer_.empty()) { | 793 if (!track_buffer_.empty()) { |
| 761 if (track_buffer_.front()->GetConfigId() != current_config_index_) { | 794 if (track_buffer_.front()->GetConfigId() != current_config_index_) { |
| 762 config_change_pending_ = true; | 795 config_change_pending_ = true; |
| 763 return kConfigChange; | 796 return kConfigChange; |
| 764 } | 797 } |
| 765 | 798 |
| (...skipping 316 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1082 (result == keyframe_map_.end() || result->first != timestamp)) { | 1115 (result == keyframe_map_.end() || result->first != timestamp)) { |
| 1083 --result; | 1116 --result; |
| 1084 } | 1117 } |
| 1085 return result; | 1118 return result; |
| 1086 } | 1119 } |
| 1087 | 1120 |
| 1088 bool SourceBufferRange::DeleteAll(BufferQueue* removed_buffers) { | 1121 bool SourceBufferRange::DeleteAll(BufferQueue* removed_buffers) { |
| 1089 return TruncateAt(buffers_.begin(), removed_buffers); | 1122 return TruncateAt(buffers_.begin(), removed_buffers); |
| 1090 } | 1123 } |
| 1091 | 1124 |
| 1125 bool SourceBufferRange::TruncateAt(base::TimeDelta timestamp) { |
| 1126 // Need to make a dummy buffer with timestamp |timestamp| in order to search |
| 1127 // the |buffers_| container. |
| 1128 scoped_refptr<StreamParserBuffer> dummy_buffer = |
| 1129 StreamParserBuffer::CopyFrom(NULL, 0, false); |
| 1130 dummy_buffer->SetDecodeTimestamp(timestamp); |
| 1131 return TruncateAt(dummy_buffer, NULL); |
| 1132 } |
| 1133 |
| 1092 bool SourceBufferRange::TruncateAt( | 1134 bool SourceBufferRange::TruncateAt( |
| 1093 scoped_refptr<StreamParserBuffer> buffer, BufferQueue* removed_buffers) { | 1135 scoped_refptr<StreamParserBuffer> buffer, BufferQueue* removed_buffers) { |
| 1094 // Find the place in |buffers_| where we will begin deleting data. | 1136 // Find the place in |buffers_| where we will begin deleting data. |
| 1095 BufferQueue::iterator starting_point = | 1137 BufferQueue::iterator starting_point = |
| 1096 std::lower_bound(buffers_.begin(), buffers_.end(), | 1138 std::lower_bound(buffers_.begin(), buffers_.end(), |
| 1097 buffer, | 1139 buffer, |
| 1098 BufferComparator); | 1140 BufferComparator); |
| 1099 return TruncateAt(starting_point, removed_buffers); | 1141 return TruncateAt(starting_point, removed_buffers); |
| 1100 } | 1142 } |
| 1101 | 1143 |
| (...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1203 for (BufferQueue::iterator itr = starting_point; | 1245 for (BufferQueue::iterator itr = starting_point; |
| 1204 itr != ending_point; ++itr) { | 1246 itr != ending_point; ++itr) { |
| 1205 size_in_bytes_ -= (*itr)->GetDataSize(); | 1247 size_in_bytes_ -= (*itr)->GetDataSize(); |
| 1206 DCHECK_GE(size_in_bytes_, 0); | 1248 DCHECK_GE(size_in_bytes_, 0); |
| 1207 } | 1249 } |
| 1208 buffers_.erase(starting_point, ending_point); | 1250 buffers_.erase(starting_point, ending_point); |
| 1209 } | 1251 } |
| 1210 | 1252 |
| 1211 bool SourceBufferRange::TruncateAt( | 1253 bool SourceBufferRange::TruncateAt( |
| 1212 const BufferQueue::iterator& starting_point, BufferQueue* removed_buffers) { | 1254 const BufferQueue::iterator& starting_point, BufferQueue* removed_buffers) { |
| 1213 DCHECK(removed_buffers); | 1255 DCHECK(!removed_buffers || removed_buffers->empty()); |
| 1214 DCHECK(removed_buffers->empty()); | |
| 1215 | 1256 |
| 1216 // Return if we're not deleting anything. | 1257 // Return if we're not deleting anything. |
| 1217 if (starting_point == buffers_.end()) | 1258 if (starting_point == buffers_.end()) |
| 1218 return false; | 1259 return false; |
| 1219 | 1260 |
| 1220 // Reset the next buffer index if we will be deleting the buffer that's next | 1261 // Reset the next buffer index if we will be deleting the buffer that's next |
| 1221 // in sequence. | 1262 // in sequence. |
| 1222 bool removed_next_buffer = false; | 1263 bool removed_next_buffer = false; |
| 1223 if (HasNextBufferPosition()) { | 1264 if (HasNextBufferPosition()) { |
| 1224 base::TimeDelta next_buffer_timestamp = GetNextTimestamp(); | 1265 base::TimeDelta next_buffer_timestamp = GetNextTimestamp(); |
| 1225 if (next_buffer_timestamp == kNoTimestamp() || | 1266 if (next_buffer_timestamp == kNoTimestamp() || |
| 1226 next_buffer_timestamp >= (*starting_point)->GetDecodeTimestamp()) { | 1267 next_buffer_timestamp >= (*starting_point)->GetDecodeTimestamp()) { |
| 1227 if (HasNextBuffer()) { | 1268 if (HasNextBuffer() && removed_buffers) { |
| 1228 int starting_offset = starting_point - buffers_.begin(); | 1269 int starting_offset = starting_point - buffers_.begin(); |
| 1229 int next_buffer_offset = next_buffer_index_ - starting_offset; | 1270 int next_buffer_offset = next_buffer_index_ - starting_offset; |
| 1230 DCHECK_GE(next_buffer_offset, 0); | 1271 DCHECK_GE(next_buffer_offset, 0); |
| 1231 BufferQueue saved(starting_point + next_buffer_offset, buffers_.end()); | 1272 BufferQueue saved(starting_point + next_buffer_offset, buffers_.end()); |
| 1232 removed_buffers->swap(saved); | 1273 removed_buffers->swap(saved); |
| 1233 } | 1274 } |
| 1234 ResetNextBufferPosition(); | 1275 ResetNextBufferPosition(); |
| 1235 removed_next_buffer = true; | 1276 removed_next_buffer = true; |
| 1236 } | 1277 } |
| 1237 } | 1278 } |
| (...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1374 return 2 * GetApproximateDuration(); | 1415 return 2 * GetApproximateDuration(); |
| 1375 } | 1416 } |
| 1376 | 1417 |
| 1377 base::TimeDelta SourceBufferRange::GetApproximateDuration() const { | 1418 base::TimeDelta SourceBufferRange::GetApproximateDuration() const { |
| 1378 base::TimeDelta max_interbuffer_distance = interbuffer_distance_cb_.Run(); | 1419 base::TimeDelta max_interbuffer_distance = interbuffer_distance_cb_.Run(); |
| 1379 DCHECK(max_interbuffer_distance != kNoTimestamp()); | 1420 DCHECK(max_interbuffer_distance != kNoTimestamp()); |
| 1380 return max_interbuffer_distance; | 1421 return max_interbuffer_distance; |
| 1381 } | 1422 } |
| 1382 | 1423 |
| 1383 } // namespace media | 1424 } // namespace media |
| OLD | NEW |