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

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

Issue 328223002: Fix crash caused by removing the gap at the beginning of a media segment. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Address CR comments Created 6 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
« no previous file with comments | « no previous file | media/filters/source_buffer_stream_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 9
10 #include "base/bind.h" 10 #include "base/bind.h"
(...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after
161 // Returns the timestamp of the last buffer in the range. 161 // Returns the timestamp of the last buffer in the range.
162 base::TimeDelta GetEndTimestamp() const; 162 base::TimeDelta GetEndTimestamp() const;
163 163
164 // Returns the timestamp for the end of the buffered region in this range. 164 // Returns the timestamp for the end of the buffered region in this range.
165 // This is an approximation if the duration for the last buffer in the range 165 // This is an approximation if the duration for the last buffer in the range
166 // is unset. 166 // is unset.
167 base::TimeDelta GetBufferedEndTimestamp() const; 167 base::TimeDelta GetBufferedEndTimestamp() const;
168 168
169 // Gets the timestamp for the keyframe that is after |timestamp|. If 169 // Gets the timestamp for the keyframe that is after |timestamp|. If
170 // there isn't a keyframe in the range after |timestamp| then kNoTimestamp() 170 // there isn't a keyframe in the range after |timestamp| then kNoTimestamp()
171 // is returned. 171 // is returned. If |timestamp| is in the "gap" between the value
wolenetz 2014/06/12 19:20:49 nit: these new pieces seem wrapped at less than 80
acolwell GONE FROM CHROMIUM 2014/06/12 20:17:59 Done.
172 // returned by GetStartTimestamp() and the timestamp on the first
173 // buffer in |buffers_|, then |timestamp| is returned.
172 base::TimeDelta NextKeyframeTimestamp(base::TimeDelta timestamp); 174 base::TimeDelta NextKeyframeTimestamp(base::TimeDelta timestamp);
173 175
174 // Gets the timestamp for the closest keyframe that is <= |timestamp|. If 176 // Gets the timestamp for the closest keyframe that is <= |timestamp|. If
175 // there isn't a keyframe before |timestamp| or |timestamp| is outside 177 // there isn't a keyframe before |timestamp| or |timestamp| is outside
176 // this range, then kNoTimestamp() is returned. 178 // this range, then kNoTimestamp() is returned.
177 base::TimeDelta KeyframeBeforeTimestamp(base::TimeDelta timestamp); 179 base::TimeDelta KeyframeBeforeTimestamp(base::TimeDelta timestamp);
178 180
179 // Returns whether a buffer with a starting timestamp of |timestamp| would 181 // Returns whether a buffer with a starting timestamp of |timestamp| would
180 // belong in this range. This includes a buffer that would be appended to 182 // belong in this range. This includes a buffer that would be appended to
181 // the end of the range. 183 // the end of the range.
(...skipping 1518 matching lines...) Expand 10 before | Expand all | Expand 10 after
1700 SourceBufferRange::SourceBufferRange( 1702 SourceBufferRange::SourceBufferRange(
1701 SourceBufferStream::Type type, const BufferQueue& new_buffers, 1703 SourceBufferStream::Type type, const BufferQueue& new_buffers,
1702 base::TimeDelta media_segment_start_time, 1704 base::TimeDelta media_segment_start_time,
1703 const InterbufferDistanceCB& interbuffer_distance_cb) 1705 const InterbufferDistanceCB& interbuffer_distance_cb)
1704 : type_(type), 1706 : type_(type),
1705 keyframe_map_index_base_(0), 1707 keyframe_map_index_base_(0),
1706 next_buffer_index_(-1), 1708 next_buffer_index_(-1),
1707 media_segment_start_time_(media_segment_start_time), 1709 media_segment_start_time_(media_segment_start_time),
1708 interbuffer_distance_cb_(interbuffer_distance_cb), 1710 interbuffer_distance_cb_(interbuffer_distance_cb),
1709 size_in_bytes_(0) { 1711 size_in_bytes_(0) {
1710 DCHECK(!new_buffers.empty()); 1712 DCHECK(!new_buffers.empty());
wolenetz 2014/06/12 19:20:49 nit: to better protect against undefined behavior
acolwell GONE FROM CHROMIUM 2014/06/12 20:17:59 Done.
1711 DCHECK(new_buffers.front()->IsKeyframe()); 1713 DCHECK(new_buffers.front()->IsKeyframe());
1712 DCHECK(!interbuffer_distance_cb.is_null()); 1714 DCHECK(!interbuffer_distance_cb.is_null());
1713 AppendBuffersToEnd(new_buffers); 1715 AppendBuffersToEnd(new_buffers);
1714 } 1716 }
1715 1717
1716 void SourceBufferRange::AppendBuffersToEnd(const BufferQueue& new_buffers) { 1718 void SourceBufferRange::AppendBuffersToEnd(const BufferQueue& new_buffers) {
1717 DCHECK(buffers_.empty() || CanAppendBuffersToEnd(new_buffers)); 1719 DCHECK(buffers_.empty() || CanAppendBuffersToEnd(new_buffers));
1718 DCHECK(media_segment_start_time_ == kNoTimestamp() || 1720 DCHECK(media_segment_start_time_ == kNoTimestamp() ||
1719 media_segment_start_time_ <= 1721 media_segment_start_time_ <=
1720 new_buffers.front()->GetDecodeTimestamp()); 1722 new_buffers.front()->GetDecodeTimestamp());
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
1767 DCHECK_LT(next_buffer_index_, static_cast<int>(buffers_.size())); 1769 DCHECK_LT(next_buffer_index_, static_cast<int>(buffers_.size()));
1768 } 1770 }
1769 1771
1770 void SourceBufferRange::SeekToStart() { 1772 void SourceBufferRange::SeekToStart() {
1771 DCHECK(!buffers_.empty()); 1773 DCHECK(!buffers_.empty());
1772 next_buffer_index_ = 0; 1774 next_buffer_index_ = 0;
1773 } 1775 }
1774 1776
1775 SourceBufferRange* SourceBufferRange::SplitRange( 1777 SourceBufferRange* SourceBufferRange::SplitRange(
1776 base::TimeDelta timestamp, bool is_exclusive) { 1778 base::TimeDelta timestamp, bool is_exclusive) {
1779 CHECK(!buffers_.empty());
1780
1777 // Find the first keyframe after |timestamp|. If |is_exclusive|, do not 1781 // Find the first keyframe after |timestamp|. If |is_exclusive|, do not
1778 // include keyframes at |timestamp|. 1782 // include keyframes at |timestamp|.
1779 KeyframeMap::iterator new_beginning_keyframe = 1783 KeyframeMap::iterator new_beginning_keyframe =
1780 GetFirstKeyframeAt(timestamp, is_exclusive); 1784 GetFirstKeyframeAt(timestamp, is_exclusive);
1781 1785
1782 // If there is no keyframe after |timestamp|, we can't split the range. 1786 // If there is no keyframe after |timestamp|, we can't split the range.
1783 if (new_beginning_keyframe == keyframe_map_.end()) 1787 if (new_beginning_keyframe == keyframe_map_.end())
1784 return NULL; 1788 return NULL;
1785 1789
1786 // Remove the data beginning at |keyframe_index| from |buffers_| and save it 1790 // Remove the data beginning at |keyframe_index| from |buffers_| and save it
1787 // into |removed_buffers|. 1791 // into |removed_buffers|.
1788 int keyframe_index = 1792 int keyframe_index =
1789 new_beginning_keyframe->second - keyframe_map_index_base_; 1793 new_beginning_keyframe->second - keyframe_map_index_base_;
1790 DCHECK_LT(keyframe_index, static_cast<int>(buffers_.size())); 1794 DCHECK_LT(keyframe_index, static_cast<int>(buffers_.size()));
1791 BufferQueue::iterator starting_point = buffers_.begin() + keyframe_index; 1795 BufferQueue::iterator starting_point = buffers_.begin() + keyframe_index;
1792 BufferQueue removed_buffers(starting_point, buffers_.end()); 1796 BufferQueue removed_buffers(starting_point, buffers_.end());
1797
1798 base::TimeDelta new_range_start_timestamp = kNoTimestamp();
1799 if (GetStartTimestamp() < buffers_.front()->GetDecodeTimestamp() &&
1800 timestamp < removed_buffers.front()->GetDecodeTimestamp()) {
1801 // The split is in the gap between |media_segment_start_time_| and
1802 // the first buffer of the new range so we should set the start
1803 // time of the new range to |timestamp| so we preserve part of the
1804 // gap in the new range.
1805 new_range_start_timestamp = timestamp;
1806 }
1807
1793 keyframe_map_.erase(new_beginning_keyframe, keyframe_map_.end()); 1808 keyframe_map_.erase(new_beginning_keyframe, keyframe_map_.end());
1794 FreeBufferRange(starting_point, buffers_.end()); 1809 FreeBufferRange(starting_point, buffers_.end());
1795 1810
1796 // Create a new range with |removed_buffers|. 1811 // Create a new range with |removed_buffers|.
1797 SourceBufferRange* split_range = 1812 SourceBufferRange* split_range =
1798 new SourceBufferRange( 1813 new SourceBufferRange(
1799 type_, removed_buffers, kNoTimestamp(), interbuffer_distance_cb_); 1814 type_, removed_buffers, new_range_start_timestamp,
1815 interbuffer_distance_cb_);
1800 1816
1801 // If the next buffer position is now in |split_range|, update the state of 1817 // If the next buffer position is now in |split_range|, update the state of
1802 // this range and |split_range| accordingly. 1818 // this range and |split_range| accordingly.
1803 if (next_buffer_index_ >= static_cast<int>(buffers_.size())) { 1819 if (next_buffer_index_ >= static_cast<int>(buffers_.size())) {
1804 split_range->next_buffer_index_ = next_buffer_index_ - keyframe_index; 1820 split_range->next_buffer_index_ = next_buffer_index_ - keyframe_index;
1805 ResetNextBufferPosition(); 1821 ResetNextBufferPosition();
1806 } 1822 }
1807 1823
1808 return split_range; 1824 return split_range;
1809 } 1825 }
(...skipping 198 matching lines...) Expand 10 before | Expand all | Expand 10 after
2008 } 2024 }
2009 buffers_.erase(starting_point, ending_point); 2025 buffers_.erase(starting_point, ending_point);
2010 } 2026 }
2011 2027
2012 bool SourceBufferRange::TruncateAt( 2028 bool SourceBufferRange::TruncateAt(
2013 const BufferQueue::iterator& starting_point, BufferQueue* removed_buffers) { 2029 const BufferQueue::iterator& starting_point, BufferQueue* removed_buffers) {
2014 DCHECK(!removed_buffers || removed_buffers->empty()); 2030 DCHECK(!removed_buffers || removed_buffers->empty());
2015 2031
2016 // Return if we're not deleting anything. 2032 // Return if we're not deleting anything.
2017 if (starting_point == buffers_.end()) 2033 if (starting_point == buffers_.end())
2018 return false; 2034 return buffers_.empty();
2019 2035
2020 // Reset the next buffer index if we will be deleting the buffer that's next 2036 // Reset the next buffer index if we will be deleting the buffer that's next
2021 // in sequence. 2037 // in sequence.
2022 if (HasNextBufferPosition()) { 2038 if (HasNextBufferPosition()) {
2023 base::TimeDelta next_buffer_timestamp = GetNextTimestamp(); 2039 base::TimeDelta next_buffer_timestamp = GetNextTimestamp();
2024 if (next_buffer_timestamp == kNoTimestamp() || 2040 if (next_buffer_timestamp == kNoTimestamp() ||
2025 next_buffer_timestamp >= (*starting_point)->GetDecodeTimestamp()) { 2041 next_buffer_timestamp >= (*starting_point)->GetDecodeTimestamp()) {
2026 if (HasNextBuffer() && removed_buffers) { 2042 if (HasNextBuffer() && removed_buffers) {
2027 int starting_offset = starting_point - buffers_.begin(); 2043 int starting_offset = starting_point - buffers_.begin();
2028 int next_buffer_offset = next_buffer_index_ - starting_offset; 2044 int next_buffer_offset = next_buffer_index_ - starting_offset;
(...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after
2157 base::TimeDelta SourceBufferRange::NextKeyframeTimestamp( 2173 base::TimeDelta SourceBufferRange::NextKeyframeTimestamp(
2158 base::TimeDelta timestamp) { 2174 base::TimeDelta timestamp) {
2159 DCHECK(!keyframe_map_.empty()); 2175 DCHECK(!keyframe_map_.empty());
2160 2176
2161 if (timestamp < GetStartTimestamp() || timestamp >= GetBufferedEndTimestamp()) 2177 if (timestamp < GetStartTimestamp() || timestamp >= GetBufferedEndTimestamp())
2162 return kNoTimestamp(); 2178 return kNoTimestamp();
2163 2179
2164 KeyframeMap::iterator itr = GetFirstKeyframeAt(timestamp, false); 2180 KeyframeMap::iterator itr = GetFirstKeyframeAt(timestamp, false);
2165 if (itr == keyframe_map_.end()) 2181 if (itr == keyframe_map_.end())
2166 return kNoTimestamp(); 2182 return kNoTimestamp();
2183
2184 // If the timestamp is inside the gap between the start of the media
2185 // segment and the first buffer, then just pretend there is a
2186 // keyframe at the specified timestamp.
2187 if (itr == keyframe_map_.begin() &&
2188 timestamp >= media_segment_start_time_ &&
2189 timestamp < itr->first) {
2190 return timestamp;
2191 }
2192
2167 return itr->first; 2193 return itr->first;
2168 } 2194 }
2169 2195
2170 base::TimeDelta SourceBufferRange::KeyframeBeforeTimestamp( 2196 base::TimeDelta SourceBufferRange::KeyframeBeforeTimestamp(
2171 base::TimeDelta timestamp) { 2197 base::TimeDelta timestamp) {
2172 DCHECK(!keyframe_map_.empty()); 2198 DCHECK(!keyframe_map_.empty());
2173 2199
2174 if (timestamp < GetStartTimestamp() || timestamp >= GetBufferedEndTimestamp()) 2200 if (timestamp < GetStartTimestamp() || timestamp >= GetBufferedEndTimestamp())
2175 return kNoTimestamp(); 2201 return kNoTimestamp();
2176 2202
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
2240 return false; 2266 return false;
2241 2267
2242 DCHECK_NE(have_splice_buffers, have_preroll_buffer); 2268 DCHECK_NE(have_splice_buffers, have_preroll_buffer);
2243 splice_buffers_index_ = 0; 2269 splice_buffers_index_ = 0;
2244 pending_buffer_.swap(*out_buffer); 2270 pending_buffer_.swap(*out_buffer);
2245 pending_buffers_complete_ = false; 2271 pending_buffers_complete_ = false;
2246 return true; 2272 return true;
2247 } 2273 }
2248 2274
2249 } // namespace media 2275 } // namespace media
OLDNEW
« no previous file with comments | « no previous file | media/filters/source_buffer_stream_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698