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 337 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
348 // are appended to the range covered by |track_buffer_|. | 348 // are appended to the range covered by |track_buffer_|. |
349 if (!track_buffer_.empty()) { | 349 if (!track_buffer_.empty()) { |
350 DecodeTimestamp keyframe_timestamp = | 350 DecodeTimestamp keyframe_timestamp = |
351 FindKeyframeAfterTimestamp(track_buffer_.front()->GetDecodeTimestamp()); | 351 FindKeyframeAfterTimestamp(track_buffer_.front()->GetDecodeTimestamp()); |
352 if (keyframe_timestamp != kNoDecodeTimestamp()) | 352 if (keyframe_timestamp != kNoDecodeTimestamp()) |
353 PruneTrackBuffer(keyframe_timestamp); | 353 PruneTrackBuffer(keyframe_timestamp); |
354 } | 354 } |
355 | 355 |
356 SetSelectedRangeIfNeeded(next_buffer_timestamp); | 356 SetSelectedRangeIfNeeded(next_buffer_timestamp); |
357 | 357 |
358 GarbageCollectIfNeeded(); | |
359 | |
360 DVLOG(1) << __FUNCTION__ << " " << GetStreamTypeName() | 358 DVLOG(1) << __FUNCTION__ << " " << GetStreamTypeName() |
361 << ": done. ranges_=" << RangesToString(ranges_); | 359 << ": done. ranges_=" << RangesToString(ranges_); |
362 DCHECK(IsRangeListSorted(ranges_)); | 360 DCHECK(IsRangeListSorted(ranges_)); |
363 DCHECK(OnlySelectedRangeIsSeeked()); | 361 DCHECK(OnlySelectedRangeIsSeeked()); |
364 return true; | 362 return true; |
365 } | 363 } |
366 | 364 |
367 void SourceBufferStream::Remove(base::TimeDelta start, base::TimeDelta end, | 365 void SourceBufferStream::Remove(base::TimeDelta start, base::TimeDelta end, |
368 base::TimeDelta duration) { | 366 base::TimeDelta duration) { |
369 DVLOG(1) << __FUNCTION__ << " " << GetStreamTypeName() | 367 DVLOG(1) << __FUNCTION__ << " " << GetStreamTypeName() |
(...skipping 215 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
585 } | 583 } |
586 } | 584 } |
587 | 585 |
588 void SourceBufferStream::SetConfigIds(const BufferQueue& buffers) { | 586 void SourceBufferStream::SetConfigIds(const BufferQueue& buffers) { |
589 for (BufferQueue::const_iterator itr = buffers.begin(); | 587 for (BufferQueue::const_iterator itr = buffers.begin(); |
590 itr != buffers.end(); ++itr) { | 588 itr != buffers.end(); ++itr) { |
591 (*itr)->SetConfigId(append_config_index_); | 589 (*itr)->SetConfigId(append_config_index_); |
592 } | 590 } |
593 } | 591 } |
594 | 592 |
595 void SourceBufferStream::GarbageCollectIfNeeded() { | 593 bool SourceBufferStream::GarbageCollectIfNeeded(DecodeTimestamp media_time) { |
596 // Compute size of |ranges_|. | 594 // Compute size of |ranges_|. |
597 int ranges_size = 0; | 595 int ranges_size = 0; |
598 for (RangeList::iterator itr = ranges_.begin(); itr != ranges_.end(); ++itr) | 596 for (RangeList::iterator itr = ranges_.begin(); itr != ranges_.end(); ++itr) |
599 ranges_size += (*itr)->size_in_bytes(); | 597 ranges_size += (*itr)->size_in_bytes(); |
600 | 598 |
601 // Return if we're under or at the memory limit. | 599 // Return if we're under or at the memory limit. |
602 if (ranges_size <= memory_limit_) | 600 if (ranges_size <= memory_limit_) |
603 return; | 601 return true; |
604 | 602 |
605 int bytes_to_free = ranges_size - memory_limit_; | 603 int bytes_to_free = ranges_size - memory_limit_; |
606 | 604 |
607 DVLOG(2) << __FUNCTION__ << " " << GetStreamTypeName() << ": Before GC" | 605 DVLOG(2) << __FUNCTION__ << " " << GetStreamTypeName() << ": Before GC" |
608 << " ranges_size=" << ranges_size | 606 << " ranges_size=" << ranges_size |
609 << " ranges_=" << RangesToString(ranges_) | 607 << " ranges_=" << RangesToString(ranges_) |
610 << " memory_limit_=" << memory_limit_; | 608 << " memory_limit_=" << memory_limit_; |
611 | 609 |
612 // Begin deleting after the last appended buffer. | 610 // Begin deleting after the last appended buffer. |
613 int bytes_freed = FreeBuffersAfterLastAppended(bytes_to_free); | 611 int bytes_freed = FreeBuffersAfterLastAppended(bytes_to_free); |
614 | 612 |
615 // Begin deleting from the front. | 613 // Begin deleting from the front. |
616 if (bytes_to_free - bytes_freed > 0) | 614 if (bytes_to_free - bytes_freed > 0) |
617 bytes_freed += FreeBuffers(bytes_to_free - bytes_freed, false); | 615 bytes_freed += FreeBuffers(bytes_to_free - bytes_freed, media_time, false); |
618 | 616 |
619 // Begin deleting from the back. | |
620 if (bytes_to_free - bytes_freed > 0) | 617 if (bytes_to_free - bytes_freed > 0) |
621 bytes_freed += FreeBuffers(bytes_to_free - bytes_freed, true); | 618 bytes_freed += FreeBuffers(bytes_to_free - bytes_freed, media_time, true); |
622 | 619 |
623 DVLOG(2) << __FUNCTION__ << " " << GetStreamTypeName() << ": After GC" | 620 DVLOG(2) << __FUNCTION__ << " " << GetStreamTypeName() << ": After GC" |
624 << " bytes_freed=" << bytes_freed | 621 << " bytes_freed=" << bytes_freed |
625 << " ranges_=" << RangesToString(ranges_); | 622 << " ranges_=" << RangesToString(ranges_); |
| 623 |
| 624 return bytes_freed >= bytes_to_free; |
626 } | 625 } |
627 | 626 |
628 int SourceBufferStream::FreeBuffersAfterLastAppended(int total_bytes_to_free) { | 627 int SourceBufferStream::FreeBuffersAfterLastAppended(int total_bytes_to_free) { |
629 DecodeTimestamp next_buffer_timestamp = GetNextBufferTimestamp(); | 628 DecodeTimestamp next_buffer_timestamp = GetNextBufferTimestamp(); |
630 if (last_appended_buffer_timestamp_ == kNoDecodeTimestamp() || | 629 if (last_appended_buffer_timestamp_ == kNoDecodeTimestamp() || |
631 next_buffer_timestamp == kNoDecodeTimestamp() || | 630 next_buffer_timestamp == kNoDecodeTimestamp() || |
632 last_appended_buffer_timestamp_ >= next_buffer_timestamp) { | 631 last_appended_buffer_timestamp_ >= next_buffer_timestamp) { |
633 return 0; | 632 return 0; |
634 } | 633 } |
635 | 634 |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
678 | 677 |
679 int bytes_removed = range->GetRemovalGOP( | 678 int bytes_removed = range->GetRemovalGOP( |
680 start_timestamp, end_timestamp, bytes_to_free, removal_end_timestamp); | 679 start_timestamp, end_timestamp, bytes_to_free, removal_end_timestamp); |
681 bytes_to_free -= bytes_removed; | 680 bytes_to_free -= bytes_removed; |
682 bytes_freed += bytes_removed; | 681 bytes_freed += bytes_removed; |
683 } | 682 } |
684 return bytes_freed; | 683 return bytes_freed; |
685 } | 684 } |
686 | 685 |
687 int SourceBufferStream::FreeBuffers(int total_bytes_to_free, | 686 int SourceBufferStream::FreeBuffers(int total_bytes_to_free, |
| 687 DecodeTimestamp media_time, |
688 bool reverse_direction) { | 688 bool reverse_direction) { |
689 TRACE_EVENT2("media", "SourceBufferStream::FreeBuffers", | 689 TRACE_EVENT2("media", "SourceBufferStream::FreeBuffers", |
690 "total bytes to free", total_bytes_to_free, | 690 "total bytes to free", total_bytes_to_free, |
691 "reverse direction", reverse_direction); | 691 "reverse direction", reverse_direction); |
692 | 692 |
693 DCHECK_GT(total_bytes_to_free, 0); | 693 DCHECK_GT(total_bytes_to_free, 0); |
694 int bytes_to_free = total_bytes_to_free; | 694 int bytes_to_free = total_bytes_to_free; |
695 int bytes_freed = 0; | 695 int bytes_freed = 0; |
696 | 696 |
697 // This range will save the last GOP appended to |range_for_next_append_| | 697 // This range will save the last GOP appended to |range_for_next_append_| |
(...skipping 11 matching lines...) Expand all Loading... |
709 DCHECK_EQ(current_range, selected_range_); | 709 DCHECK_EQ(current_range, selected_range_); |
710 break; | 710 break; |
711 } | 711 } |
712 bytes_deleted = current_range->DeleteGOPFromBack(&buffers); | 712 bytes_deleted = current_range->DeleteGOPFromBack(&buffers); |
713 } else { | 713 } else { |
714 current_range = ranges_.front(); | 714 current_range = ranges_.front(); |
715 if (current_range->FirstGOPContainsNextBufferPosition()) { | 715 if (current_range->FirstGOPContainsNextBufferPosition()) { |
716 DCHECK_EQ(current_range, selected_range_); | 716 DCHECK_EQ(current_range, selected_range_); |
717 break; | 717 break; |
718 } | 718 } |
| 719 if (media_time != kNoDecodeTimestamp() && |
| 720 !current_range->FirstGOPEarlierThanMediaTime(media_time)) { |
| 721 break; |
| 722 } |
719 bytes_deleted = current_range->DeleteGOPFromFront(&buffers); | 723 bytes_deleted = current_range->DeleteGOPFromFront(&buffers); |
720 } | 724 } |
721 | 725 |
722 // Check to see if we've just deleted the GOP that was last appended. | 726 // Check to see if we've just deleted the GOP that was last appended. |
723 DecodeTimestamp end_timestamp = buffers.back()->GetDecodeTimestamp(); | 727 DecodeTimestamp end_timestamp = buffers.back()->GetDecodeTimestamp(); |
724 if (end_timestamp == last_appended_buffer_timestamp_) { | 728 if (end_timestamp == last_appended_buffer_timestamp_) { |
725 DCHECK(last_appended_buffer_timestamp_ != kNoDecodeTimestamp()); | 729 DCHECK(last_appended_buffer_timestamp_ != kNoDecodeTimestamp()); |
726 DCHECK(!new_range_for_append); | 730 DCHECK(!new_range_for_append); |
| 731 |
727 // Create a new range containing these buffers. | 732 // Create a new range containing these buffers. |
728 new_range_for_append = new SourceBufferRange( | 733 new_range_for_append = new SourceBufferRange( |
729 TypeToGapPolicy(GetType()), | 734 TypeToGapPolicy(GetType()), |
730 buffers, kNoDecodeTimestamp(), | 735 buffers, kNoDecodeTimestamp(), |
731 base::Bind(&SourceBufferStream::GetMaxInterbufferDistance, | 736 base::Bind(&SourceBufferStream::GetMaxInterbufferDistance, |
732 base::Unretained(this))); | 737 base::Unretained(this))); |
733 range_for_next_append_ = ranges_.end(); | 738 range_for_next_append_ = ranges_.end(); |
734 } else { | 739 } else { |
735 bytes_to_free -= bytes_deleted; | 740 bytes_to_free -= bytes_deleted; |
736 bytes_freed += bytes_deleted; | 741 bytes_freed += bytes_deleted; |
737 } | 742 } |
738 | 743 |
739 if (current_range->size_in_bytes() == 0) { | 744 if (current_range->size_in_bytes() == 0) { |
740 DCHECK_NE(current_range, selected_range_); | 745 DCHECK_NE(current_range, selected_range_); |
741 DCHECK(range_for_next_append_ == ranges_.end() || | 746 DCHECK(range_for_next_append_ == ranges_.end() || |
742 *range_for_next_append_ != current_range); | 747 *range_for_next_append_ != current_range); |
743 delete current_range; | 748 delete current_range; |
744 reverse_direction ? ranges_.pop_back() : ranges_.pop_front(); | 749 reverse_direction ? ranges_.pop_back() : ranges_.pop_front(); |
745 } | 750 } |
| 751 |
| 752 if (reverse_direction && new_range_for_append) { |
| 753 // We don't want to delete any further, or we'll be creating gaps |
| 754 break; |
| 755 } |
746 } | 756 } |
747 | 757 |
748 // Insert |new_range_for_append| into |ranges_|, if applicable. | 758 // Insert |new_range_for_append| into |ranges_|, if applicable. |
749 if (new_range_for_append) { | 759 if (new_range_for_append) { |
750 range_for_next_append_ = AddToRanges(new_range_for_append); | 760 range_for_next_append_ = AddToRanges(new_range_for_append); |
751 DCHECK(range_for_next_append_ != ranges_.end()); | 761 DCHECK(range_for_next_append_ != ranges_.end()); |
752 | 762 |
753 // Check to see if we need to merge |new_range_for_append| with the range | 763 // Check to see if we need to merge |new_range_for_append| with the range |
754 // before or after it. |new_range_for_append| is created whenever the last | 764 // before or after it. |new_range_for_append| is created whenever the last |
755 // GOP appended is encountered, regardless of whether any buffers after it | 765 // GOP appended is encountered, regardless of whether any buffers after it |
(...skipping 832 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1588 return false; | 1598 return false; |
1589 | 1599 |
1590 DCHECK_NE(have_splice_buffers, have_preroll_buffer); | 1600 DCHECK_NE(have_splice_buffers, have_preroll_buffer); |
1591 splice_buffers_index_ = 0; | 1601 splice_buffers_index_ = 0; |
1592 pending_buffer_.swap(*out_buffer); | 1602 pending_buffer_.swap(*out_buffer); |
1593 pending_buffers_complete_ = false; | 1603 pending_buffers_complete_ = false; |
1594 return true; | 1604 return true; |
1595 } | 1605 } |
1596 | 1606 |
1597 } // namespace media | 1607 } // namespace media |
OLD | NEW |