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

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

Issue 2385423002: MediaSource: Fix CHECK crash in append fudge room edge case. (Closed)
Patch Set: Fix new CFG logic Created 4 years, 2 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 189 matching lines...) Expand 10 before | Expand all | Expand 10 after
200 new_coded_frame_group_ = true; 200 new_coded_frame_group_ = true;
201 201
202 RangeList::iterator last_range = range_for_next_append_; 202 RangeList::iterator last_range = range_for_next_append_;
203 range_for_next_append_ = FindExistingRangeFor(coded_frame_group_start_time); 203 range_for_next_append_ = FindExistingRangeFor(coded_frame_group_start_time);
204 204
205 // Only reset |last_appended_buffer_timestamp_| if this new coded frame group 205 // Only reset |last_appended_buffer_timestamp_| if this new coded frame group
206 // is not adjacent to the previous coded frame group appended to the stream. 206 // is not adjacent to the previous coded frame group appended to the stream.
207 if (range_for_next_append_ == ranges_.end() || 207 if (range_for_next_append_ == ranges_.end() ||
208 !AreAdjacentInSequence(last_appended_buffer_timestamp_, 208 !AreAdjacentInSequence(last_appended_buffer_timestamp_,
209 coded_frame_group_start_time)) { 209 coded_frame_group_start_time)) {
210 last_appended_buffer_timestamp_ = kNoDecodeTimestamp(); 210 ResetLastAppendedState();
211 last_appended_buffer_duration_ = kNoTimestamp;
212 last_appended_buffer_is_keyframe_ = false;
213 DVLOG(3) << __func__ << " next appended buffers will " 211 DVLOG(3) << __func__ << " next appended buffers will "
214 << (range_for_next_append_ == ranges_.end() 212 << (range_for_next_append_ == ranges_.end()
215 ? "be in a new range" 213 ? "be in a new range"
216 : "overlap an existing range"); 214 : "overlap an existing range");
217 } else if (last_range != ranges_.end()) { 215 } else if (last_range != ranges_.end()) {
218 DCHECK(last_range == range_for_next_append_); 216 DCHECK(last_range == range_for_next_append_);
219 DVLOG(3) << __func__ << " next appended buffers will continue range unless " 217 DVLOG(3) << __func__ << " next appended buffers will continue range unless "
220 << "intervening remove makes discontinuity"; 218 << "intervening remove makes discontinuity";
221 } 219 }
222 } 220 }
(...skipping 224 matching lines...) Expand 10 before | Expand all | Expand 10 after
447 if (new_coded_frame_group_) 445 if (new_coded_frame_group_)
448 return coded_frame_group_start_time_; 446 return coded_frame_group_start_time_;
449 447
450 // If we still don't know a potential next append timestamp, then we have 448 // If we still don't know a potential next append timestamp, then we have
451 // removed the ranged to which it previously belonged and have not completed a 449 // removed the ranged to which it previously belonged and have not completed a
452 // subsequent append or received a subsequent OnStartOfCodedFrameGroup() 450 // subsequent append or received a subsequent OnStartOfCodedFrameGroup()
453 // signal. 451 // signal.
454 return kNoDecodeTimestamp(); 452 return kNoDecodeTimestamp();
455 } 453 }
456 454
455 void SourceBufferStream::UpdateLastAppendStateForRemove(
456 DecodeTimestamp remove_start,
457 DecodeTimestamp remove_end,
458 bool exclude_start) {
459 // TODO(chcunningham): change exclude_start to include_start in this class and
460 // SourceBufferRange. Negatives are hard to reason about.
461 bool include_start = !exclude_start;
462
463 // No need to check previous append's GOP if starting a new CFG. New CFG is
464 // already required to begin with a key frame.
465 if (new_coded_frame_group_)
466 return;
467
468 if (range_for_next_append_ != ranges_.end()) {
469 if (last_appended_buffer_timestamp_ != kNoDecodeTimestamp()) {
470 DCHECK((*range_for_next_append_)
471 ->BelongsToRange(last_appended_buffer_timestamp_));
472
473 // Note start and end of last appended GOP.
474 DecodeTimestamp gop_end = last_appended_buffer_timestamp_;
475 DecodeTimestamp gop_start =
476 (*range_for_next_append_)->KeyframeBeforeTimestamp(gop_end);
477
478 // If last append is about to be disrupted, reset associated state so we
479 // know to create a new range for future appends and require an initial
480 // key frame.
481 if (((include_start && remove_start == gop_end) ||
482 remove_start < gop_end) &&
483 remove_end > gop_start) {
484 DVLOG(2) << __func__ << " " << GetStreamTypeName()
485 << " Resetting next append state for remove ("
486 << remove_start.InSecondsF() << ", " << remove_end.InSecondsF()
487 << ", " << exclude_start << ")";
488 range_for_next_append_ = ranges_.end();
489 ResetLastAppendedState();
490 }
491 } else {
492 NOTREACHED() << __func__ << " " << GetStreamTypeName()
493 << " range_for_next_append_ set, but not tracking last"
494 << " append nor new coded frame group.";
495 }
496 }
497 }
498
457 void SourceBufferStream::RemoveInternal(DecodeTimestamp start, 499 void SourceBufferStream::RemoveInternal(DecodeTimestamp start,
458 DecodeTimestamp end, 500 DecodeTimestamp end,
459 bool exclude_start, 501 bool exclude_start,
460 BufferQueue* deleted_buffers) { 502 BufferQueue* deleted_buffers) {
461 DVLOG(2) << __func__ << " " << GetStreamTypeName() << " (" 503 DVLOG(2) << __func__ << " " << GetStreamTypeName() << " ("
462 << start.InSecondsF() << ", " << end.InSecondsF() << ", " 504 << start.InSecondsF() << ", " << end.InSecondsF() << ", "
463 << exclude_start << ")"; 505 << exclude_start << ")";
464 DVLOG(3) << __func__ << " " << GetStreamTypeName() 506 DVLOG(3) << __func__ << " " << GetStreamTypeName()
465 << ": before remove ranges_=" << RangesToString(ranges_); 507 << ": before remove ranges_=" << RangesToString(ranges_);
466 508
467 DCHECK(start >= DecodeTimestamp()); 509 DCHECK(start >= DecodeTimestamp());
468 DCHECK(start < end) << "start " << start.InSecondsF() 510 DCHECK(start < end) << "start " << start.InSecondsF()
469 << " end " << end.InSecondsF(); 511 << " end " << end.InSecondsF();
470 DCHECK(deleted_buffers); 512 DCHECK(deleted_buffers);
471 513
514 // Doing this upfront simplifies decisions about range_for_next_append_ below.
515 UpdateLastAppendStateForRemove(start, end, exclude_start);
516
472 RangeList::iterator itr = ranges_.begin(); 517 RangeList::iterator itr = ranges_.begin();
473
474 while (itr != ranges_.end()) { 518 while (itr != ranges_.end()) {
475 SourceBufferRange* range = *itr; 519 SourceBufferRange* range = *itr;
476 if (range->GetStartTimestamp() >= end) 520 if (range->GetStartTimestamp() >= end)
477 break; 521 break;
478 522
479 // Split off any remaining GOPs starting at or after |end| and add it to 523 // Split off any remaining GOPs starting at or after |end| and add it to
480 // |ranges_|. 524 // |ranges_|.
481 SourceBufferRange* new_range = range->SplitRange(end); 525 SourceBufferRange* new_range = range->SplitRange(end);
482 if (new_range) { 526 if (new_range) {
483 itr = ranges_.insert(++itr, new_range); 527 itr = ranges_.insert(++itr, new_range);
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after
557 SetSelectedRange(NULL); 601 SetSelectedRange(NULL);
558 track_buffer_.clear(); 602 track_buffer_.clear();
559 config_change_pending_ = false; 603 config_change_pending_ = false;
560 last_output_buffer_timestamp_ = kNoDecodeTimestamp(); 604 last_output_buffer_timestamp_ = kNoDecodeTimestamp();
561 just_exhausted_track_buffer_ = false; 605 just_exhausted_track_buffer_ = false;
562 splice_buffers_index_ = 0; 606 splice_buffers_index_ = 0;
563 pending_buffer_ = NULL; 607 pending_buffer_ = NULL;
564 pending_buffers_complete_ = false; 608 pending_buffers_complete_ = false;
565 } 609 }
566 610
611 void SourceBufferStream::ResetLastAppendedState() {
612 last_appended_buffer_timestamp_ = kNoDecodeTimestamp();
613 last_appended_buffer_duration_ = kNoTimestamp;
614 last_appended_buffer_is_keyframe_ = false;
615 }
616
567 bool SourceBufferStream::ShouldSeekToStartOfBuffered( 617 bool SourceBufferStream::ShouldSeekToStartOfBuffered(
568 base::TimeDelta seek_timestamp) const { 618 base::TimeDelta seek_timestamp) const {
569 if (ranges_.empty()) 619 if (ranges_.empty())
570 return false; 620 return false;
571 base::TimeDelta beginning_of_buffered = 621 base::TimeDelta beginning_of_buffered =
572 ranges_.front()->GetStartTimestamp().ToPresentationTime(); 622 ranges_.front()->GetStartTimestamp().ToPresentationTime();
573 return (seek_timestamp <= beginning_of_buffered && 623 return (seek_timestamp <= beginning_of_buffered &&
574 beginning_of_buffered < kSeekToStartFudgeRoom()); 624 beginning_of_buffered < kSeekToStartFudgeRoom());
575 } 625 }
576 626
(...skipping 529 matching lines...) Expand 10 before | Expand all | Expand 10 after
1106 1156
1107 SeekAndSetSelectedRange(*itr, seek_dts); 1157 SeekAndSetSelectedRange(*itr, seek_dts);
1108 seek_pending_ = false; 1158 seek_pending_ = false;
1109 } 1159 }
1110 1160
1111 bool SourceBufferStream::IsSeekPending() const { 1161 bool SourceBufferStream::IsSeekPending() const {
1112 return seek_pending_ && !IsEndOfStreamReached(); 1162 return seek_pending_ && !IsEndOfStreamReached();
1113 } 1163 }
1114 1164
1115 void SourceBufferStream::OnSetDuration(base::TimeDelta duration) { 1165 void SourceBufferStream::OnSetDuration(base::TimeDelta duration) {
1116 DecodeTimestamp duration_dts = 1166 if (ranges_.empty())
wolenetz 2016/10/05 22:41:09 nit: why remove the DVLOG? Maybe retain it but wit
chcunningham 2016/10/06 21:57:33 Added back.
1117 DecodeTimestamp::FromPresentationTime(duration);
1118 DVLOG(1) << __func__ << " " << GetStreamTypeName() << " ("
1119 << duration.InSecondsF() << ")";
1120
1121 RangeList::iterator itr = ranges_.end();
1122 for (itr = ranges_.begin(); itr != ranges_.end(); ++itr) {
1123 if ((*itr)->GetEndTimestamp() > duration_dts)
1124 break;
1125 }
1126 if (itr == ranges_.end())
1127 return; 1167 return;
1128 1168
1129 // Need to partially truncate this range. 1169 DecodeTimestamp start = DecodeTimestamp::FromPresentationTime(duration);
1130 if ((*itr)->GetStartTimestamp() < duration_dts) { 1170 DecodeTimestamp end = ranges_.back()->GetBufferedEndTimestamp();
1131 bool delete_range = (*itr)->TruncateAt(duration_dts, NULL, false); 1171
1132 if ((*itr == selected_range_) && !selected_range_->HasNextBufferPosition()) 1172 // Trim the end if it exceeds the new duration.
1173 if (start < end) {
wolenetz 2016/10/05 22:41:09 aside: this truncate-on-duration-reduction behavio
chcunningham 2016/10/06 21:57:32 Acknowledged.
1174 BufferQueue deleted_buffers;
1175 RemoveInternal(start, end, false, &deleted_buffers);
1176
1177 if (!deleted_buffers.empty()) {
1178 // Truncation removed current seek position. Clear selected range.
wolenetz 2016/10/05 22:41:09 nit: let's be careful not to confuse seek position
chcunningham 2016/10/06 21:57:32 Done.
1133 SetSelectedRange(NULL); 1179 SetSelectedRange(NULL);
1134
1135 if (delete_range) {
1136 DeleteAndRemoveRange(&itr);
1137 } else {
1138 ++itr;
1139 } 1180 }
1140 } 1181 }
1141
1142 // Delete all ranges that begin after |duration_dts|.
1143 while (itr != ranges_.end()) {
1144 // If we're about to delete the selected range, also reset the seek state.
1145 DCHECK((*itr)->GetStartTimestamp() >= duration_dts);
1146 if (*itr == selected_range_)
1147 ResetSeekState();
1148 DeleteAndRemoveRange(&itr);
1149 }
1150 } 1182 }
1151 1183
1152 SourceBufferStream::Status SourceBufferStream::GetNextBuffer( 1184 SourceBufferStream::Status SourceBufferStream::GetNextBuffer(
1153 scoped_refptr<StreamParserBuffer>* out_buffer) { 1185 scoped_refptr<StreamParserBuffer>* out_buffer) {
1154 DVLOG(2) << __func__ << " " << GetStreamTypeName(); 1186 DVLOG(2) << __func__ << " " << GetStreamTypeName();
1155 if (!pending_buffer_.get()) { 1187 if (!pending_buffer_.get()) {
1156 const SourceBufferStream::Status status = GetNextBufferInternal(out_buffer); 1188 const SourceBufferStream::Status status = GetNextBufferInternal(out_buffer);
1157 if (status != SourceBufferStream::kSuccess || 1189 if (status != SourceBufferStream::kSuccess ||
1158 !SetPendingBuffer(out_buffer)) { 1190 !SetPendingBuffer(out_buffer)) {
1159 DVLOG(2) << __func__ << " " << GetStreamTypeName() 1191 DVLOG(2) << __func__ << " " << GetStreamTypeName()
(...skipping 517 matching lines...) Expand 10 before | Expand all | Expand 10 after
1677 1709
1678 DCHECK(*itr != ranges_.end()); 1710 DCHECK(*itr != ranges_.end());
1679 if (**itr == selected_range_) { 1711 if (**itr == selected_range_) {
1680 DVLOG(1) << __func__ << " deleting selected range."; 1712 DVLOG(1) << __func__ << " deleting selected range.";
1681 SetSelectedRange(NULL); 1713 SetSelectedRange(NULL);
1682 } 1714 }
1683 1715
1684 if (*itr == range_for_next_append_) { 1716 if (*itr == range_for_next_append_) {
1685 DVLOG(1) << __func__ << " deleting range_for_next_append_."; 1717 DVLOG(1) << __func__ << " deleting range_for_next_append_.";
1686 range_for_next_append_ = ranges_.end(); 1718 range_for_next_append_ = ranges_.end();
1687 last_appended_buffer_timestamp_ = kNoDecodeTimestamp(); 1719 ResetLastAppendedState();
1688 last_appended_buffer_is_keyframe_ = false;
1689 } 1720 }
1690 1721
1691 delete **itr; 1722 delete **itr;
1692 *itr = ranges_.erase(*itr); 1723 *itr = ranges_.erase(*itr);
1693 } 1724 }
1694 1725
1695 void SourceBufferStream::GenerateSpliceFrame(const BufferQueue& new_buffers) { 1726 void SourceBufferStream::GenerateSpliceFrame(const BufferQueue& new_buffers) {
1696 DCHECK(!new_buffers.empty()); 1727 DCHECK(!new_buffers.empty());
1697 1728
1698 // Splice frames are only supported for audio. 1729 // Splice frames are only supported for audio.
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after
1810 return false; 1841 return false;
1811 1842
1812 DCHECK_NE(have_splice_buffers, have_preroll_buffer); 1843 DCHECK_NE(have_splice_buffers, have_preroll_buffer);
1813 splice_buffers_index_ = 0; 1844 splice_buffers_index_ = 0;
1814 pending_buffer_.swap(*out_buffer); 1845 pending_buffer_.swap(*out_buffer);
1815 pending_buffers_complete_ = false; 1846 pending_buffers_complete_ = false;
1816 return true; 1847 return true;
1817 } 1848 }
1818 1849
1819 } // namespace media 1850 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698