| 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 #include <sstream> | 9 #include <sstream> |
| 10 | 10 |
| (...skipping 344 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 355 // are appended to the range covered by |track_buffer_|. | 355 // are appended to the range covered by |track_buffer_|. |
| 356 if (!track_buffer_.empty()) { | 356 if (!track_buffer_.empty()) { |
| 357 DecodeTimestamp keyframe_timestamp = | 357 DecodeTimestamp keyframe_timestamp = |
| 358 FindKeyframeAfterTimestamp(track_buffer_.front()->GetDecodeTimestamp()); | 358 FindKeyframeAfterTimestamp(track_buffer_.front()->GetDecodeTimestamp()); |
| 359 if (keyframe_timestamp != kNoDecodeTimestamp()) | 359 if (keyframe_timestamp != kNoDecodeTimestamp()) |
| 360 PruneTrackBuffer(keyframe_timestamp); | 360 PruneTrackBuffer(keyframe_timestamp); |
| 361 } | 361 } |
| 362 | 362 |
| 363 SetSelectedRangeIfNeeded(next_buffer_timestamp); | 363 SetSelectedRangeIfNeeded(next_buffer_timestamp); |
| 364 | 364 |
| 365 GarbageCollectIfNeeded(); | |
| 366 | |
| 367 DVLOG(1) << __FUNCTION__ << " " << GetStreamTypeName() | 365 DVLOG(1) << __FUNCTION__ << " " << GetStreamTypeName() |
| 368 << ": done. ranges_=" << RangesToString(ranges_); | 366 << ": done. ranges_=" << RangesToString(ranges_); |
| 369 DCHECK(IsRangeListSorted(ranges_)); | 367 DCHECK(IsRangeListSorted(ranges_)); |
| 370 DCHECK(OnlySelectedRangeIsSeeked()); | 368 DCHECK(OnlySelectedRangeIsSeeked()); |
| 371 return true; | 369 return true; |
| 372 } | 370 } |
| 373 | 371 |
| 374 void SourceBufferStream::Remove(base::TimeDelta start, base::TimeDelta end, | 372 void SourceBufferStream::Remove(base::TimeDelta start, base::TimeDelta end, |
| 375 base::TimeDelta duration) { | 373 base::TimeDelta duration) { |
| 376 DVLOG(1) << __FUNCTION__ << " " << GetStreamTypeName() | 374 DVLOG(1) << __FUNCTION__ << " " << GetStreamTypeName() |
| (...skipping 228 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 605 } | 603 } |
| 606 } | 604 } |
| 607 | 605 |
| 608 void SourceBufferStream::SetConfigIds(const BufferQueue& buffers) { | 606 void SourceBufferStream::SetConfigIds(const BufferQueue& buffers) { |
| 609 for (BufferQueue::const_iterator itr = buffers.begin(); | 607 for (BufferQueue::const_iterator itr = buffers.begin(); |
| 610 itr != buffers.end(); ++itr) { | 608 itr != buffers.end(); ++itr) { |
| 611 (*itr)->SetConfigId(append_config_index_); | 609 (*itr)->SetConfigId(append_config_index_); |
| 612 } | 610 } |
| 613 } | 611 } |
| 614 | 612 |
| 615 void SourceBufferStream::GarbageCollectIfNeeded() { | 613 bool SourceBufferStream::GarbageCollectIfNeeded(DecodeTimestamp media_time, |
| 614 size_t newDataSize) { |
| 615 DCHECK(media_time != kNoDecodeTimestamp()); |
| 616 // Compute size of |ranges_|. | 616 // Compute size of |ranges_|. |
| 617 size_t ranges_size = 0; | 617 size_t ranges_size = GetBufferedSize(); |
| 618 for (RangeList::iterator itr = ranges_.begin(); itr != ranges_.end(); ++itr) | 618 |
| 619 ranges_size += (*itr)->size_in_bytes(); | 619 // Sanity and overflow checks |
| 620 if ((newDataSize > memory_limit_) || |
| 621 (ranges_size + newDataSize < ranges_size)) |
| 622 return false; |
| 620 | 623 |
| 621 // Return if we're under or at the memory limit. | 624 // Return if we're under or at the memory limit. |
| 622 if (ranges_size <= memory_limit_) | 625 if (ranges_size + newDataSize <= memory_limit_) |
| 623 return; | 626 return true; |
| 624 | 627 |
| 625 size_t bytes_to_free = ranges_size - memory_limit_; | 628 size_t bytes_to_free = ranges_size + newDataSize - memory_limit_; |
| 626 | 629 |
| 627 DVLOG(2) << __FUNCTION__ << " " << GetStreamTypeName() << ": Before GC" | 630 DVLOG(2) << __FUNCTION__ << " " << GetStreamTypeName() << ": Before GC" |
| 631 << " media_time=" << media_time.InSecondsF() |
| 632 << " ranges_=" << RangesToString(ranges_) |
| 628 << " ranges_size=" << ranges_size | 633 << " ranges_size=" << ranges_size |
| 629 << " ranges_=" << RangesToString(ranges_) | 634 << " newDataSize=" << newDataSize |
| 630 << " memory_limit_=" << memory_limit_; | 635 << " memory_limit_=" << memory_limit_ |
| 636 << " last_appended_buffer_timestamp_=" |
| 637 << last_appended_buffer_timestamp_.InSecondsF(); |
| 631 | 638 |
| 632 // Begin deleting after the last appended buffer. | 639 size_t bytes_freed = 0; |
| 633 size_t bytes_freed = FreeBuffersAfterLastAppended(bytes_to_free); | |
| 634 | 640 |
| 635 // Begin deleting from the front. | 641 // If last appended buffer position was earlier than the current playback time |
| 636 if (bytes_freed < bytes_to_free) | 642 // then try deleting data between last append and current media_time. |
| 637 bytes_freed += FreeBuffers(bytes_to_free - bytes_freed, false); | 643 if (last_appended_buffer_timestamp_ != kNoDecodeTimestamp() && |
| 644 last_appended_buffer_timestamp_ < media_time) { |
| 645 size_t between = FreeBuffersAfterLastAppended(bytes_to_free, media_time); |
| 646 DVLOG(3) << __FUNCTION__ << " FreeBuffersAfterLastAppended " |
| 647 << " released " << between << " bytes" |
| 648 << " ranges_=" << RangesToString(ranges_); |
| 649 bytes_freed += between; |
| 638 | 650 |
| 639 // Begin deleting from the back. | 651 // If the last append happened before the current playback position |
| 640 if (bytes_freed < bytes_to_free) | 652 // |media_time|, then JS player is probably preparing to seek back and we |
| 641 bytes_freed += FreeBuffers(bytes_to_free - bytes_freed, true); | 653 // should try to preserve all most recently appended data (which is in |
| 654 // range_for_next_append_) from being removed by GC (see crbug.com/440173) |
| 655 if (range_for_next_append_ != ranges_.end()) { |
| 656 DCHECK((*range_for_next_append_)->GetStartTimestamp() <= media_time); |
| 657 media_time = (*range_for_next_append_)->GetStartTimestamp(); |
| 658 } |
| 659 } |
| 660 |
| 661 // Try removing data from the front of the SourceBuffer up to |media_time| |
| 662 // position. |
| 663 if (bytes_freed < bytes_to_free) { |
| 664 size_t front = FreeBuffers(bytes_to_free - bytes_freed, media_time, false); |
| 665 DVLOG(3) << __FUNCTION__ << " Removed " << front << " bytes from the front" |
| 666 << " ranges_=" << RangesToString(ranges_); |
| 667 bytes_freed += front; |
| 668 } |
| 669 |
| 670 // Try removing data from the back of the SourceBuffer, until we reach the |
| 671 // most recent append position. |
| 672 if (bytes_freed < bytes_to_free) { |
| 673 size_t back = FreeBuffers(bytes_to_free - bytes_freed, media_time, true); |
| 674 DVLOG(3) << __FUNCTION__ << " Removed " << back << " bytes from the back" |
| 675 << " ranges_=" << RangesToString(ranges_); |
| 676 bytes_freed += back; |
| 677 } |
| 642 | 678 |
| 643 DVLOG(2) << __FUNCTION__ << " " << GetStreamTypeName() << ": After GC" | 679 DVLOG(2) << __FUNCTION__ << " " << GetStreamTypeName() << ": After GC" |
| 680 << " bytes_to_free=" << bytes_to_free |
| 644 << " bytes_freed=" << bytes_freed | 681 << " bytes_freed=" << bytes_freed |
| 645 << " ranges_=" << RangesToString(ranges_); | 682 << " ranges_=" << RangesToString(ranges_); |
| 683 |
| 684 return bytes_freed >= bytes_to_free; |
| 646 } | 685 } |
| 647 | 686 |
| 648 size_t SourceBufferStream::FreeBuffersAfterLastAppended( | 687 size_t SourceBufferStream::FreeBuffersAfterLastAppended( |
| 649 size_t total_bytes_to_free) { | 688 size_t total_bytes_to_free, DecodeTimestamp media_time) { |
| 650 DecodeTimestamp next_buffer_timestamp = GetNextBufferTimestamp(); | 689 DVLOG(4) << __FUNCTION__ << " last_appended_buffer_timestamp_=" |
| 651 if (last_appended_buffer_timestamp_ == kNoDecodeTimestamp() || | 690 << last_appended_buffer_timestamp_.InSecondsF() |
| 652 next_buffer_timestamp == kNoDecodeTimestamp() || | 691 << " media_time=" << media_time.InSecondsF(); |
| 653 last_appended_buffer_timestamp_ >= next_buffer_timestamp) { | |
| 654 return 0; | |
| 655 } | |
| 656 | 692 |
| 657 DecodeTimestamp remove_range_start = last_appended_buffer_timestamp_; | 693 DecodeTimestamp remove_range_start = last_appended_buffer_timestamp_; |
| 658 if (last_appended_buffer_is_keyframe_) | 694 if (last_appended_buffer_is_keyframe_) |
| 659 remove_range_start += GetMaxInterbufferDistance(); | 695 remove_range_start += GetMaxInterbufferDistance(); |
| 660 | 696 |
| 661 DecodeTimestamp remove_range_start_keyframe = FindKeyframeAfterTimestamp( | 697 DecodeTimestamp remove_range_start_keyframe = FindKeyframeAfterTimestamp( |
| 662 remove_range_start); | 698 remove_range_start); |
| 663 if (remove_range_start_keyframe != kNoDecodeTimestamp()) | 699 if (remove_range_start_keyframe != kNoDecodeTimestamp()) |
| 664 remove_range_start = remove_range_start_keyframe; | 700 remove_range_start = remove_range_start_keyframe; |
| 665 if (remove_range_start >= next_buffer_timestamp) | 701 if (remove_range_start >= media_time) |
| 666 return 0; | 702 return 0; |
| 667 | 703 |
| 668 DecodeTimestamp remove_range_end; | 704 DecodeTimestamp remove_range_end; |
| 669 size_t bytes_freed = GetRemovalRange(remove_range_start, | 705 size_t bytes_freed = GetRemovalRange(remove_range_start, |
| 670 next_buffer_timestamp, | 706 media_time, |
| 671 total_bytes_to_free, | 707 total_bytes_to_free, |
| 672 &remove_range_end); | 708 &remove_range_end); |
| 673 if (bytes_freed > 0) { | 709 if (bytes_freed > 0) { |
| 710 DVLOG(4) << __FUNCTION__ << " removing [" |
| 711 << remove_range_start.ToPresentationTime().InSecondsF() << ";" |
| 712 << remove_range_end.ToPresentationTime().InSecondsF() << "]"; |
| 674 Remove(remove_range_start.ToPresentationTime(), | 713 Remove(remove_range_start.ToPresentationTime(), |
| 675 remove_range_end.ToPresentationTime(), | 714 remove_range_end.ToPresentationTime(), |
| 676 next_buffer_timestamp.ToPresentationTime()); | 715 media_time.ToPresentationTime()); |
| 677 } | 716 } |
| 678 | 717 |
| 679 return bytes_freed; | 718 return bytes_freed; |
| 680 } | 719 } |
| 681 | 720 |
| 682 size_t SourceBufferStream::GetRemovalRange( | 721 size_t SourceBufferStream::GetRemovalRange( |
| 683 DecodeTimestamp start_timestamp, DecodeTimestamp end_timestamp, | 722 DecodeTimestamp start_timestamp, DecodeTimestamp end_timestamp, |
| 684 size_t total_bytes_to_free, DecodeTimestamp* removal_end_timestamp) { | 723 size_t total_bytes_to_free, DecodeTimestamp* removal_end_timestamp) { |
| 685 DCHECK(start_timestamp >= DecodeTimestamp()) << start_timestamp.InSecondsF(); | 724 DCHECK(start_timestamp >= DecodeTimestamp()) << start_timestamp.InSecondsF(); |
| 686 DCHECK(start_timestamp < end_timestamp) | 725 DCHECK(start_timestamp < end_timestamp) |
| (...skipping 12 matching lines...) Expand all Loading... |
| 699 | 738 |
| 700 size_t bytes_to_free = total_bytes_to_free - bytes_freed; | 739 size_t bytes_to_free = total_bytes_to_free - bytes_freed; |
| 701 size_t bytes_removed = range->GetRemovalGOP( | 740 size_t bytes_removed = range->GetRemovalGOP( |
| 702 start_timestamp, end_timestamp, bytes_to_free, removal_end_timestamp); | 741 start_timestamp, end_timestamp, bytes_to_free, removal_end_timestamp); |
| 703 bytes_freed += bytes_removed; | 742 bytes_freed += bytes_removed; |
| 704 } | 743 } |
| 705 return bytes_freed; | 744 return bytes_freed; |
| 706 } | 745 } |
| 707 | 746 |
| 708 size_t SourceBufferStream::FreeBuffers(size_t total_bytes_to_free, | 747 size_t SourceBufferStream::FreeBuffers(size_t total_bytes_to_free, |
| 748 DecodeTimestamp media_time, |
| 709 bool reverse_direction) { | 749 bool reverse_direction) { |
| 710 TRACE_EVENT2("media", "SourceBufferStream::FreeBuffers", | 750 TRACE_EVENT2("media", "SourceBufferStream::FreeBuffers", |
| 711 "total bytes to free", total_bytes_to_free, | 751 "total bytes to free", total_bytes_to_free, |
| 712 "reverse direction", reverse_direction); | 752 "reverse direction", reverse_direction); |
| 713 | 753 |
| 714 DCHECK_GT(total_bytes_to_free, 0u); | 754 DCHECK_GT(total_bytes_to_free, 0u); |
| 715 size_t bytes_freed = 0; | 755 size_t bytes_freed = 0; |
| 716 | 756 |
| 717 // This range will save the last GOP appended to |range_for_next_append_| | 757 // This range will save the last GOP appended to |range_for_next_append_| |
| 718 // if the buffers surrounding it get deleted during garbage collection. | 758 // if the buffers surrounding it get deleted during garbage collection. |
| 719 SourceBufferRange* new_range_for_append = NULL; | 759 SourceBufferRange* new_range_for_append = NULL; |
| 720 | 760 |
| 721 while (!ranges_.empty() && bytes_freed < total_bytes_to_free) { | 761 while (!ranges_.empty() && bytes_freed < total_bytes_to_free) { |
| 722 SourceBufferRange* current_range = NULL; | 762 SourceBufferRange* current_range = NULL; |
| 723 BufferQueue buffers; | 763 BufferQueue buffers; |
| 724 size_t bytes_deleted = 0; | 764 size_t bytes_deleted = 0; |
| 725 | 765 |
| 726 if (reverse_direction) { | 766 if (reverse_direction) { |
| 727 current_range = ranges_.back(); | 767 current_range = ranges_.back(); |
| 768 DVLOG(5) << "current_range=" << RangeToString(*current_range); |
| 728 if (current_range->LastGOPContainsNextBufferPosition()) { | 769 if (current_range->LastGOPContainsNextBufferPosition()) { |
| 729 DCHECK_EQ(current_range, selected_range_); | 770 DCHECK_EQ(current_range, selected_range_); |
| 771 DVLOG(5) << "current_range contains next read position, stopping GC"; |
| 730 break; | 772 break; |
| 731 } | 773 } |
| 774 DVLOG(5) << "Deleting GOP from back: " << RangeToString(*current_range); |
| 732 bytes_deleted = current_range->DeleteGOPFromBack(&buffers); | 775 bytes_deleted = current_range->DeleteGOPFromBack(&buffers); |
| 733 } else { | 776 } else { |
| 734 current_range = ranges_.front(); | 777 current_range = ranges_.front(); |
| 735 if (current_range->FirstGOPContainsNextBufferPosition()) { | 778 DVLOG(5) << "current_range=" << RangeToString(*current_range); |
| 736 DCHECK_EQ(current_range, selected_range_); | 779 if (!current_range->FirstGOPEarlierThanMediaTime(media_time)) { |
| 780 // We have removed all data up to the GOP that contains current playback |
| 781 // position, we can't delete any further. |
| 782 DVLOG(5) << "current_range contains playback position, stopping GC"; |
| 737 break; | 783 break; |
| 738 } | 784 } |
| 785 DVLOG(4) << "Deleting GOP from front: " << RangeToString(*current_range); |
| 739 bytes_deleted = current_range->DeleteGOPFromFront(&buffers); | 786 bytes_deleted = current_range->DeleteGOPFromFront(&buffers); |
| 740 } | 787 } |
| 741 | 788 |
| 742 // Check to see if we've just deleted the GOP that was last appended. | 789 // Check to see if we've just deleted the GOP that was last appended. |
| 743 DecodeTimestamp end_timestamp = buffers.back()->GetDecodeTimestamp(); | 790 DecodeTimestamp end_timestamp = buffers.back()->GetDecodeTimestamp(); |
| 744 if (end_timestamp == last_appended_buffer_timestamp_) { | 791 if (end_timestamp == last_appended_buffer_timestamp_) { |
| 745 DCHECK(last_appended_buffer_timestamp_ != kNoDecodeTimestamp()); | 792 DCHECK(last_appended_buffer_timestamp_ != kNoDecodeTimestamp()); |
| 746 DCHECK(!new_range_for_append); | 793 DCHECK(!new_range_for_append); |
| 794 |
| 747 // Create a new range containing these buffers. | 795 // Create a new range containing these buffers. |
| 748 new_range_for_append = new SourceBufferRange( | 796 new_range_for_append = new SourceBufferRange( |
| 749 TypeToGapPolicy(GetType()), | 797 TypeToGapPolicy(GetType()), |
| 750 buffers, kNoDecodeTimestamp(), | 798 buffers, kNoDecodeTimestamp(), |
| 751 base::Bind(&SourceBufferStream::GetMaxInterbufferDistance, | 799 base::Bind(&SourceBufferStream::GetMaxInterbufferDistance, |
| 752 base::Unretained(this))); | 800 base::Unretained(this))); |
| 753 range_for_next_append_ = ranges_.end(); | 801 range_for_next_append_ = ranges_.end(); |
| 754 } else { | 802 } else { |
| 755 bytes_freed += bytes_deleted; | 803 bytes_freed += bytes_deleted; |
| 756 } | 804 } |
| 757 | 805 |
| 758 if (current_range->size_in_bytes() == 0) { | 806 if (current_range->size_in_bytes() == 0) { |
| 759 DCHECK_NE(current_range, selected_range_); | 807 DCHECK_NE(current_range, selected_range_); |
| 760 DCHECK(range_for_next_append_ == ranges_.end() || | 808 DCHECK(range_for_next_append_ == ranges_.end() || |
| 761 *range_for_next_append_ != current_range); | 809 *range_for_next_append_ != current_range); |
| 762 delete current_range; | 810 delete current_range; |
| 763 reverse_direction ? ranges_.pop_back() : ranges_.pop_front(); | 811 reverse_direction ? ranges_.pop_back() : ranges_.pop_front(); |
| 764 } | 812 } |
| 813 |
| 814 if (reverse_direction && new_range_for_append) { |
| 815 // We don't want to delete any further, or we'll be creating gaps |
| 816 break; |
| 817 } |
| 765 } | 818 } |
| 766 | 819 |
| 767 // Insert |new_range_for_append| into |ranges_|, if applicable. | 820 // Insert |new_range_for_append| into |ranges_|, if applicable. |
| 768 if (new_range_for_append) { | 821 if (new_range_for_append) { |
| 769 range_for_next_append_ = AddToRanges(new_range_for_append); | 822 range_for_next_append_ = AddToRanges(new_range_for_append); |
| 770 DCHECK(range_for_next_append_ != ranges_.end()); | 823 DCHECK(range_for_next_append_ != ranges_.end()); |
| 771 | 824 |
| 772 // Check to see if we need to merge |new_range_for_append| with the range | 825 // Check to see if we need to merge |new_range_for_append| with the range |
| 773 // before or after it. |new_range_for_append| is created whenever the last | 826 // before or after it. |new_range_for_append| is created whenever the last |
| 774 // GOP appended is encountered, regardless of whether any buffers after it | 827 // GOP appended is encountered, regardless of whether any buffers after it |
| (...skipping 439 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1214 } | 1267 } |
| 1215 | 1268 |
| 1216 void SourceBufferStream::SeekAndSetSelectedRange( | 1269 void SourceBufferStream::SeekAndSetSelectedRange( |
| 1217 SourceBufferRange* range, DecodeTimestamp seek_timestamp) { | 1270 SourceBufferRange* range, DecodeTimestamp seek_timestamp) { |
| 1218 if (range) | 1271 if (range) |
| 1219 range->Seek(seek_timestamp); | 1272 range->Seek(seek_timestamp); |
| 1220 SetSelectedRange(range); | 1273 SetSelectedRange(range); |
| 1221 } | 1274 } |
| 1222 | 1275 |
| 1223 void SourceBufferStream::SetSelectedRange(SourceBufferRange* range) { | 1276 void SourceBufferStream::SetSelectedRange(SourceBufferRange* range) { |
| 1224 DVLOG(1) << __FUNCTION__ << " " << GetStreamTypeName() | 1277 DVLOG(1) << __FUNCTION__ << " " << GetStreamTypeName() << ": " |
| 1225 << ": " << selected_range_ << " -> " << range; | 1278 << selected_range_ << " " |
| 1279 << (selected_range_ ? RangeToString(*selected_range_) : "") |
| 1280 << " -> " << range << " " << (range ? RangeToString(*range) : ""); |
| 1226 if (selected_range_) | 1281 if (selected_range_) |
| 1227 selected_range_->ResetNextBufferPosition(); | 1282 selected_range_->ResetNextBufferPosition(); |
| 1228 DCHECK(!range || range->HasNextBufferPosition()); | 1283 DCHECK(!range || range->HasNextBufferPosition()); |
| 1229 selected_range_ = range; | 1284 selected_range_ = range; |
| 1230 } | 1285 } |
| 1231 | 1286 |
| 1232 Ranges<base::TimeDelta> SourceBufferStream::GetBufferedTime() const { | 1287 Ranges<base::TimeDelta> SourceBufferStream::GetBufferedTime() const { |
| 1233 Ranges<base::TimeDelta> ranges; | 1288 Ranges<base::TimeDelta> ranges; |
| 1234 for (RangeList::const_iterator itr = ranges_.begin(); | 1289 for (RangeList::const_iterator itr = ranges_.begin(); |
| 1235 itr != ranges_.end(); ++itr) { | 1290 itr != ranges_.end(); ++itr) { |
| 1236 ranges.Add((*itr)->GetStartTimestamp().ToPresentationTime(), | 1291 ranges.Add((*itr)->GetStartTimestamp().ToPresentationTime(), |
| 1237 (*itr)->GetBufferedEndTimestamp().ToPresentationTime()); | 1292 (*itr)->GetBufferedEndTimestamp().ToPresentationTime()); |
| 1238 } | 1293 } |
| 1239 return ranges; | 1294 return ranges; |
| 1240 } | 1295 } |
| 1241 | 1296 |
| 1242 base::TimeDelta SourceBufferStream::GetBufferedDuration() const { | 1297 base::TimeDelta SourceBufferStream::GetBufferedDuration() const { |
| 1243 if (ranges_.empty()) | 1298 if (ranges_.empty()) |
| 1244 return base::TimeDelta(); | 1299 return base::TimeDelta(); |
| 1245 | 1300 |
| 1246 return ranges_.back()->GetBufferedEndTimestamp().ToPresentationTime(); | 1301 return ranges_.back()->GetBufferedEndTimestamp().ToPresentationTime(); |
| 1247 } | 1302 } |
| 1248 | 1303 |
| 1304 size_t SourceBufferStream::GetBufferedSize() const { |
| 1305 size_t ranges_size = 0; |
| 1306 for (const auto& range : ranges_) |
| 1307 ranges_size += range->size_in_bytes(); |
| 1308 return ranges_size; |
| 1309 } |
| 1310 |
| 1249 void SourceBufferStream::MarkEndOfStream() { | 1311 void SourceBufferStream::MarkEndOfStream() { |
| 1250 DCHECK(!end_of_stream_); | 1312 DCHECK(!end_of_stream_); |
| 1251 end_of_stream_ = true; | 1313 end_of_stream_ = true; |
| 1252 } | 1314 } |
| 1253 | 1315 |
| 1254 void SourceBufferStream::UnmarkEndOfStream() { | 1316 void SourceBufferStream::UnmarkEndOfStream() { |
| 1255 DCHECK(end_of_stream_); | 1317 DCHECK(end_of_stream_); |
| 1256 end_of_stream_ = false; | 1318 end_of_stream_ = false; |
| 1257 } | 1319 } |
| 1258 | 1320 |
| (...skipping 409 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1668 return false; | 1730 return false; |
| 1669 | 1731 |
| 1670 DCHECK_NE(have_splice_buffers, have_preroll_buffer); | 1732 DCHECK_NE(have_splice_buffers, have_preroll_buffer); |
| 1671 splice_buffers_index_ = 0; | 1733 splice_buffers_index_ = 0; |
| 1672 pending_buffer_.swap(*out_buffer); | 1734 pending_buffer_.swap(*out_buffer); |
| 1673 pending_buffers_complete_ = false; | 1735 pending_buffers_complete_ = false; |
| 1674 return true; | 1736 return true; |
| 1675 } | 1737 } |
| 1676 | 1738 |
| 1677 } // namespace media | 1739 } // namespace media |
| OLD | NEW |