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 |