Chromium Code Reviews| 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 189 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 |
| OLD | NEW |