Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(172)

Side by Side Diff: media/filters/source_buffer_stream.cc

Issue 1008463002: Fix MSE GC, make it less aggressive, more spec-compliant (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Added new test case: GarbageCollection_SaveDataAtPlaybackPosition Created 5 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698