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 330 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
341 // are appended to the range covered by |track_buffer_|. | 341 // are appended to the range covered by |track_buffer_|. |
342 if (!track_buffer_.empty()) { | 342 if (!track_buffer_.empty()) { |
343 DecodeTimestamp keyframe_timestamp = | 343 DecodeTimestamp keyframe_timestamp = |
344 FindKeyframeAfterTimestamp(track_buffer_.front()->GetDecodeTimestamp()); | 344 FindKeyframeAfterTimestamp(track_buffer_.front()->GetDecodeTimestamp()); |
345 if (keyframe_timestamp != kNoDecodeTimestamp()) | 345 if (keyframe_timestamp != kNoDecodeTimestamp()) |
346 PruneTrackBuffer(keyframe_timestamp); | 346 PruneTrackBuffer(keyframe_timestamp); |
347 } | 347 } |
348 | 348 |
349 SetSelectedRangeIfNeeded(next_buffer_timestamp); | 349 SetSelectedRangeIfNeeded(next_buffer_timestamp); |
350 | 350 |
351 GarbageCollectIfNeeded(); | |
352 | |
353 DVLOG(1) << __FUNCTION__ << " " << GetStreamTypeName() | 351 DVLOG(1) << __FUNCTION__ << " " << GetStreamTypeName() |
354 << ": done. ranges_=" << RangesToString(ranges_); | 352 << ": done. ranges_=" << RangesToString(ranges_); |
355 DCHECK(IsRangeListSorted(ranges_)); | 353 DCHECK(IsRangeListSorted(ranges_)); |
356 DCHECK(OnlySelectedRangeIsSeeked()); | 354 DCHECK(OnlySelectedRangeIsSeeked()); |
357 return true; | 355 return true; |
358 } | 356 } |
359 | 357 |
360 void SourceBufferStream::Remove(base::TimeDelta start, base::TimeDelta end, | 358 void SourceBufferStream::Remove(base::TimeDelta start, base::TimeDelta end, |
361 base::TimeDelta duration) { | 359 base::TimeDelta duration) { |
362 DVLOG(1) << __FUNCTION__ << " " << GetStreamTypeName() | 360 DVLOG(1) << __FUNCTION__ << " " << GetStreamTypeName() |
(...skipping 213 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
576 } | 574 } |
577 } | 575 } |
578 | 576 |
579 void SourceBufferStream::SetConfigIds(const BufferQueue& buffers) { | 577 void SourceBufferStream::SetConfigIds(const BufferQueue& buffers) { |
580 for (BufferQueue::const_iterator itr = buffers.begin(); | 578 for (BufferQueue::const_iterator itr = buffers.begin(); |
581 itr != buffers.end(); ++itr) { | 579 itr != buffers.end(); ++itr) { |
582 (*itr)->SetConfigId(append_config_index_); | 580 (*itr)->SetConfigId(append_config_index_); |
583 } | 581 } |
584 } | 582 } |
585 | 583 |
586 void SourceBufferStream::GarbageCollectIfNeeded() { | 584 bool SourceBufferStream::GarbageCollectIfNeeded(DecodeTimestamp media_time) { |
587 // Compute size of |ranges_|. | 585 // Compute size of |ranges_|. |
588 int ranges_size = 0; | 586 int ranges_size = 0; |
589 for (RangeList::iterator itr = ranges_.begin(); itr != ranges_.end(); ++itr) | 587 for (RangeList::iterator itr = ranges_.begin(); itr != ranges_.end(); ++itr) |
590 ranges_size += (*itr)->size_in_bytes(); | 588 ranges_size += (*itr)->size_in_bytes(); |
591 | 589 |
592 // Return if we're under or at the memory limit. | 590 // Return if we're under or at the memory limit. |
593 if (ranges_size <= memory_limit_) | 591 if (ranges_size <= memory_limit_) |
594 return; | 592 return true; |
595 | 593 |
596 int bytes_to_free = ranges_size - memory_limit_; | 594 int bytes_to_free = ranges_size - memory_limit_; |
597 | 595 |
598 DVLOG(2) << __FUNCTION__ << " " << GetStreamTypeName() << ": Before GC" | 596 DVLOG(2) << __FUNCTION__ << " " << GetStreamTypeName() << ": Before GC" |
599 << " ranges_size=" << ranges_size | 597 << " ranges_size=" << ranges_size |
600 << " ranges_=" << RangesToString(ranges_) | 598 << " ranges_=" << RangesToString(ranges_) |
601 << " memory_limit_=" << memory_limit_; | 599 << " memory_limit_=" << memory_limit_; |
602 | 600 |
603 // Begin deleting after the last appended buffer. | 601 // Begin deleting after the last appended buffer. |
604 int bytes_freed = FreeBuffersAfterLastAppended(bytes_to_free); | 602 int bytes_freed = FreeBuffersAfterLastAppended(bytes_to_free); |
605 | 603 |
606 // Begin deleting from the front. | 604 // Begin deleting from the front. |
607 if (bytes_to_free - bytes_freed > 0) | 605 if (bytes_to_free - bytes_freed > 0) |
608 bytes_freed += FreeBuffers(bytes_to_free - bytes_freed, false); | 606 bytes_freed += FreeBuffers(bytes_to_free - bytes_freed, media_time, false); |
609 | 607 |
610 // Begin deleting from the back. | |
611 if (bytes_to_free - bytes_freed > 0) | 608 if (bytes_to_free - bytes_freed > 0) |
612 bytes_freed += FreeBuffers(bytes_to_free - bytes_freed, true); | 609 bytes_freed += FreeBuffers(bytes_to_free - bytes_freed, media_time, true); |
613 | 610 |
614 DVLOG(2) << __FUNCTION__ << " " << GetStreamTypeName() << ": After GC" | 611 DVLOG(2) << __FUNCTION__ << " " << GetStreamTypeName() << ": After GC" |
615 << " bytes_freed=" << bytes_freed | 612 << " bytes_freed=" << bytes_freed |
616 << " ranges_=" << RangesToString(ranges_); | 613 << " ranges_=" << RangesToString(ranges_); |
| 614 |
| 615 return bytes_freed >= bytes_to_free; |
617 } | 616 } |
618 | 617 |
619 int SourceBufferStream::FreeBuffersAfterLastAppended(int total_bytes_to_free) { | 618 int SourceBufferStream::FreeBuffersAfterLastAppended(int total_bytes_to_free) { |
620 DecodeTimestamp next_buffer_timestamp = GetNextBufferTimestamp(); | 619 DecodeTimestamp next_buffer_timestamp = GetNextBufferTimestamp(); |
621 if (last_appended_buffer_timestamp_ == kNoDecodeTimestamp() || | 620 if (last_appended_buffer_timestamp_ == kNoDecodeTimestamp() || |
622 next_buffer_timestamp == kNoDecodeTimestamp() || | 621 next_buffer_timestamp == kNoDecodeTimestamp() || |
623 last_appended_buffer_timestamp_ >= next_buffer_timestamp) { | 622 last_appended_buffer_timestamp_ >= next_buffer_timestamp) { |
624 return 0; | 623 return 0; |
625 } | 624 } |
626 | 625 |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
669 | 668 |
670 int bytes_removed = range->GetRemovalGOP( | 669 int bytes_removed = range->GetRemovalGOP( |
671 start_timestamp, end_timestamp, bytes_to_free, removal_end_timestamp); | 670 start_timestamp, end_timestamp, bytes_to_free, removal_end_timestamp); |
672 bytes_to_free -= bytes_removed; | 671 bytes_to_free -= bytes_removed; |
673 bytes_freed += bytes_removed; | 672 bytes_freed += bytes_removed; |
674 } | 673 } |
675 return bytes_freed; | 674 return bytes_freed; |
676 } | 675 } |
677 | 676 |
678 int SourceBufferStream::FreeBuffers(int total_bytes_to_free, | 677 int SourceBufferStream::FreeBuffers(int total_bytes_to_free, |
| 678 DecodeTimestamp media_time, |
679 bool reverse_direction) { | 679 bool reverse_direction) { |
680 TRACE_EVENT2("media", "SourceBufferStream::FreeBuffers", | 680 TRACE_EVENT2("media", "SourceBufferStream::FreeBuffers", |
681 "total bytes to free", total_bytes_to_free, | 681 "total bytes to free", total_bytes_to_free, |
682 "reverse direction", reverse_direction); | 682 "reverse direction", reverse_direction); |
683 | 683 |
684 DCHECK_GT(total_bytes_to_free, 0); | 684 DCHECK_GT(total_bytes_to_free, 0); |
685 int bytes_to_free = total_bytes_to_free; | 685 int bytes_to_free = total_bytes_to_free; |
686 int bytes_freed = 0; | 686 int bytes_freed = 0; |
687 | 687 |
688 // This range will save the last GOP appended to |range_for_next_append_| | 688 // This range will save the last GOP appended to |range_for_next_append_| |
(...skipping 11 matching lines...) Expand all Loading... |
700 DCHECK_EQ(current_range, selected_range_); | 700 DCHECK_EQ(current_range, selected_range_); |
701 break; | 701 break; |
702 } | 702 } |
703 bytes_deleted = current_range->DeleteGOPFromBack(&buffers); | 703 bytes_deleted = current_range->DeleteGOPFromBack(&buffers); |
704 } else { | 704 } else { |
705 current_range = ranges_.front(); | 705 current_range = ranges_.front(); |
706 if (current_range->FirstGOPContainsNextBufferPosition()) { | 706 if (current_range->FirstGOPContainsNextBufferPosition()) { |
707 DCHECK_EQ(current_range, selected_range_); | 707 DCHECK_EQ(current_range, selected_range_); |
708 break; | 708 break; |
709 } | 709 } |
| 710 if (media_time != kNoDecodeTimestamp() && |
| 711 !current_range->FirstGOPEarlierThanMediaTime(media_time)) { |
| 712 break; |
| 713 } |
710 bytes_deleted = current_range->DeleteGOPFromFront(&buffers); | 714 bytes_deleted = current_range->DeleteGOPFromFront(&buffers); |
711 } | 715 } |
712 | 716 |
713 // Check to see if we've just deleted the GOP that was last appended. | 717 // Check to see if we've just deleted the GOP that was last appended. |
714 DecodeTimestamp end_timestamp = buffers.back()->GetDecodeTimestamp(); | 718 DecodeTimestamp end_timestamp = buffers.back()->GetDecodeTimestamp(); |
715 if (end_timestamp == last_appended_buffer_timestamp_) { | 719 if (end_timestamp == last_appended_buffer_timestamp_) { |
716 DCHECK(last_appended_buffer_timestamp_ != kNoDecodeTimestamp()); | 720 DCHECK(last_appended_buffer_timestamp_ != kNoDecodeTimestamp()); |
717 DCHECK(!new_range_for_append); | 721 DCHECK(!new_range_for_append); |
| 722 |
718 // Create a new range containing these buffers. | 723 // Create a new range containing these buffers. |
719 new_range_for_append = new SourceBufferRange( | 724 new_range_for_append = new SourceBufferRange( |
720 TypeToGapPolicy(GetType()), | 725 TypeToGapPolicy(GetType()), |
721 buffers, kNoDecodeTimestamp(), | 726 buffers, kNoDecodeTimestamp(), |
722 base::Bind(&SourceBufferStream::GetMaxInterbufferDistance, | 727 base::Bind(&SourceBufferStream::GetMaxInterbufferDistance, |
723 base::Unretained(this))); | 728 base::Unretained(this))); |
724 range_for_next_append_ = ranges_.end(); | 729 range_for_next_append_ = ranges_.end(); |
725 } else { | 730 } else { |
726 bytes_to_free -= bytes_deleted; | 731 bytes_to_free -= bytes_deleted; |
727 bytes_freed += bytes_deleted; | 732 bytes_freed += bytes_deleted; |
728 } | 733 } |
729 | 734 |
730 if (current_range->size_in_bytes() == 0) { | 735 if (current_range->size_in_bytes() == 0) { |
731 DCHECK_NE(current_range, selected_range_); | 736 DCHECK_NE(current_range, selected_range_); |
732 DCHECK(range_for_next_append_ == ranges_.end() || | 737 DCHECK(range_for_next_append_ == ranges_.end() || |
733 *range_for_next_append_ != current_range); | 738 *range_for_next_append_ != current_range); |
734 delete current_range; | 739 delete current_range; |
735 reverse_direction ? ranges_.pop_back() : ranges_.pop_front(); | 740 reverse_direction ? ranges_.pop_back() : ranges_.pop_front(); |
736 } | 741 } |
| 742 |
| 743 if (reverse_direction && new_range_for_append) { |
| 744 // We don't want to delete any further, or we'll be creating gaps |
| 745 break; |
| 746 } |
737 } | 747 } |
738 | 748 |
739 // Insert |new_range_for_append| into |ranges_|, if applicable. | 749 // Insert |new_range_for_append| into |ranges_|, if applicable. |
740 if (new_range_for_append) { | 750 if (new_range_for_append) { |
741 range_for_next_append_ = AddToRanges(new_range_for_append); | 751 range_for_next_append_ = AddToRanges(new_range_for_append); |
742 DCHECK(range_for_next_append_ != ranges_.end()); | 752 DCHECK(range_for_next_append_ != ranges_.end()); |
743 | 753 |
744 // Check to see if we need to merge |new_range_for_append| with the range | 754 // Check to see if we need to merge |new_range_for_append| with the range |
745 // before or after it. |new_range_for_append| is created whenever the last | 755 // before or after it. |new_range_for_append| is created whenever the last |
746 // GOP appended is encountered, regardless of whether any buffers after it | 756 // GOP appended is encountered, regardless of whether any buffers after it |
(...skipping 815 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1562 return false; | 1572 return false; |
1563 | 1573 |
1564 DCHECK_NE(have_splice_buffers, have_preroll_buffer); | 1574 DCHECK_NE(have_splice_buffers, have_preroll_buffer); |
1565 splice_buffers_index_ = 0; | 1575 splice_buffers_index_ = 0; |
1566 pending_buffer_.swap(*out_buffer); | 1576 pending_buffer_.swap(*out_buffer); |
1567 pending_buffers_complete_ = false; | 1577 pending_buffers_complete_ = false; |
1568 return true; | 1578 return true; |
1569 } | 1579 } |
1570 | 1580 |
1571 } // namespace media | 1581 } // namespace media |
OLD | NEW |