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

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: 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
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 1756 matching lines...) Expand 10 before | Expand all | Expand 10 after
1767 DCHECK_LT(next_buffer_index_, static_cast<int>(buffers_.size())); 1767 DCHECK_LT(next_buffer_index_, static_cast<int>(buffers_.size()));
1768 } 1768 }
1769 1769
1770 void SourceBufferRange::SeekToStart() { 1770 void SourceBufferRange::SeekToStart() {
1771 DCHECK(!buffers_.empty()); 1771 DCHECK(!buffers_.empty());
1772 next_buffer_index_ = 0; 1772 next_buffer_index_ = 0;
1773 } 1773 }
1774 1774
1775 SourceBufferRange* SourceBufferRange::SplitRange( 1775 SourceBufferRange* SourceBufferRange::SplitRange(
1776 base::TimeDelta timestamp, bool is_exclusive) { 1776 base::TimeDelta timestamp, bool is_exclusive) {
1777 CHECK(!buffers_.empty());
1778
1777 // Find the first keyframe after |timestamp|. If |is_exclusive|, do not 1779 // Find the first keyframe after |timestamp|. If |is_exclusive|, do not
1778 // include keyframes at |timestamp|. 1780 // include keyframes at |timestamp|.
1779 KeyframeMap::iterator new_beginning_keyframe = 1781 KeyframeMap::iterator new_beginning_keyframe =
1780 GetFirstKeyframeAt(timestamp, is_exclusive); 1782 GetFirstKeyframeAt(timestamp, is_exclusive);
1781 1783
1782 // If there is no keyframe after |timestamp|, we can't split the range. 1784 // If there is no keyframe after |timestamp|, we can't split the range.
1783 if (new_beginning_keyframe == keyframe_map_.end()) 1785 if (new_beginning_keyframe == keyframe_map_.end())
1784 return NULL; 1786 return NULL;
1785 1787
1786 // Remove the data beginning at |keyframe_index| from |buffers_| and save it 1788 // Remove the data beginning at |keyframe_index| from |buffers_| and save it
1787 // into |removed_buffers|. 1789 // into |removed_buffers|.
1788 int keyframe_index = 1790 int keyframe_index =
1789 new_beginning_keyframe->second - keyframe_map_index_base_; 1791 new_beginning_keyframe->second - keyframe_map_index_base_;
1790 DCHECK_LT(keyframe_index, static_cast<int>(buffers_.size())); 1792 DCHECK_LT(keyframe_index, static_cast<int>(buffers_.size()));
1791 BufferQueue::iterator starting_point = buffers_.begin() + keyframe_index; 1793 BufferQueue::iterator starting_point = buffers_.begin() + keyframe_index;
1792 BufferQueue removed_buffers(starting_point, buffers_.end()); 1794 BufferQueue removed_buffers(starting_point, buffers_.end());
1795
1796 base::TimeDelta new_range_start_timestamp = kNoTimestamp();
1797 if (!removed_buffers.empty() &&
1798 media_segment_start_time_ < buffers_.front()->GetDecodeTimestamp() &&
wolenetz 2014/06/12 00:00:16 Can |media_segment_start_time_| be kNoTimestamp()
acolwell GONE FROM CHROMIUM 2014/06/12 01:19:27 Oops. Changed code to use GetStartTimestamp() so t
1799 timestamp < removed_buffers.front()->GetDecodeTimestamp()) {
1800 // The split is in the gap between |media_segment_start_time_| and
1801 // the first buffer of the new range so we should set the start
1802 // time of the new range to |timestamp| so we preserve part of the
1803 // gap in the new range.
1804 new_range_start_timestamp = timestamp;
1805 }
1806
1793 keyframe_map_.erase(new_beginning_keyframe, keyframe_map_.end()); 1807 keyframe_map_.erase(new_beginning_keyframe, keyframe_map_.end());
1794 FreeBufferRange(starting_point, buffers_.end()); 1808 FreeBufferRange(starting_point, buffers_.end());
1795 1809
1796 // Create a new range with |removed_buffers|. 1810 // Create a new range with |removed_buffers|.
wolenetz 2014/06/12 00:00:16 If |removed_buffers| is empty(), why create an emp
acolwell GONE FROM CHROMIUM 2014/06/12 01:19:27 Removed the check above. There is a DCHECK() in th
1797 SourceBufferRange* split_range = 1811 SourceBufferRange* split_range =
1798 new SourceBufferRange( 1812 new SourceBufferRange(
1799 type_, removed_buffers, kNoTimestamp(), interbuffer_distance_cb_); 1813 type_, removed_buffers, new_range_start_timestamp,
1814 interbuffer_distance_cb_);
1800 1815
1801 // If the next buffer position is now in |split_range|, update the state of 1816 // If the next buffer position is now in |split_range|, update the state of
1802 // this range and |split_range| accordingly. 1817 // this range and |split_range| accordingly.
1803 if (next_buffer_index_ >= static_cast<int>(buffers_.size())) { 1818 if (next_buffer_index_ >= static_cast<int>(buffers_.size())) {
1804 split_range->next_buffer_index_ = next_buffer_index_ - keyframe_index; 1819 split_range->next_buffer_index_ = next_buffer_index_ - keyframe_index;
1805 ResetNextBufferPosition(); 1820 ResetNextBufferPosition();
1806 } 1821 }
1807 1822
1808 return split_range; 1823 return split_range;
1809 } 1824 }
(...skipping 198 matching lines...) Expand 10 before | Expand all | Expand 10 after
2008 } 2023 }
2009 buffers_.erase(starting_point, ending_point); 2024 buffers_.erase(starting_point, ending_point);
2010 } 2025 }
2011 2026
2012 bool SourceBufferRange::TruncateAt( 2027 bool SourceBufferRange::TruncateAt(
2013 const BufferQueue::iterator& starting_point, BufferQueue* removed_buffers) { 2028 const BufferQueue::iterator& starting_point, BufferQueue* removed_buffers) {
2014 DCHECK(!removed_buffers || removed_buffers->empty()); 2029 DCHECK(!removed_buffers || removed_buffers->empty());
2015 2030
2016 // Return if we're not deleting anything. 2031 // Return if we're not deleting anything.
2017 if (starting_point == buffers_.end()) 2032 if (starting_point == buffers_.end())
2018 return false; 2033 return buffers_.empty();
2019 2034
2020 // Reset the next buffer index if we will be deleting the buffer that's next 2035 // Reset the next buffer index if we will be deleting the buffer that's next
2021 // in sequence. 2036 // in sequence.
2022 if (HasNextBufferPosition()) { 2037 if (HasNextBufferPosition()) {
2023 base::TimeDelta next_buffer_timestamp = GetNextTimestamp(); 2038 base::TimeDelta next_buffer_timestamp = GetNextTimestamp();
2024 if (next_buffer_timestamp == kNoTimestamp() || 2039 if (next_buffer_timestamp == kNoTimestamp() ||
2025 next_buffer_timestamp >= (*starting_point)->GetDecodeTimestamp()) { 2040 next_buffer_timestamp >= (*starting_point)->GetDecodeTimestamp()) {
2026 if (HasNextBuffer() && removed_buffers) { 2041 if (HasNextBuffer() && removed_buffers) {
2027 int starting_offset = starting_point - buffers_.begin(); 2042 int starting_offset = starting_point - buffers_.begin();
2028 int next_buffer_offset = next_buffer_index_ - starting_offset; 2043 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( 2172 base::TimeDelta SourceBufferRange::NextKeyframeTimestamp(
2158 base::TimeDelta timestamp) { 2173 base::TimeDelta timestamp) {
2159 DCHECK(!keyframe_map_.empty()); 2174 DCHECK(!keyframe_map_.empty());
2160 2175
2161 if (timestamp < GetStartTimestamp() || timestamp >= GetBufferedEndTimestamp()) 2176 if (timestamp < GetStartTimestamp() || timestamp >= GetBufferedEndTimestamp())
2162 return kNoTimestamp(); 2177 return kNoTimestamp();
2163 2178
2164 KeyframeMap::iterator itr = GetFirstKeyframeAt(timestamp, false); 2179 KeyframeMap::iterator itr = GetFirstKeyframeAt(timestamp, false);
2165 if (itr == keyframe_map_.end()) 2180 if (itr == keyframe_map_.end())
2166 return kNoTimestamp(); 2181 return kNoTimestamp();
2182
2183 // If the timestamp is inside the gap between the start of the media
wolenetz 2014/06/12 00:00:16 nit: Update the method declaration's comment, too?
acolwell GONE FROM CHROMIUM 2014/06/12 01:19:27 Done.
2184 // segment and the first buffer, then just pretend there is a
2185 // keyframe at the specified timestamp.
wolenetz 2014/06/12 00:00:16 I'm not totally clear why this pretending is neces
acolwell GONE FROM CHROMIUM 2014/06/12 01:19:27 It makes the buffered ranges behave in a way that
2186 if (itr == keyframe_map_.begin() &&
2187 timestamp >= media_segment_start_time_ &&
wolenetz 2014/06/12 19:20:49 nit: If timestamp == media_segment_start_time_, do
acolwell GONE FROM CHROMIUM 2014/06/12 20:17:58 Probably not. Made this >.
2188 timestamp < itr->first) {
2189 return timestamp;
2190 }
2191
2167 return itr->first; 2192 return itr->first;
2168 } 2193 }
2169 2194
2170 base::TimeDelta SourceBufferRange::KeyframeBeforeTimestamp( 2195 base::TimeDelta SourceBufferRange::KeyframeBeforeTimestamp(
2171 base::TimeDelta timestamp) { 2196 base::TimeDelta timestamp) {
2172 DCHECK(!keyframe_map_.empty()); 2197 DCHECK(!keyframe_map_.empty());
2173 2198
2174 if (timestamp < GetStartTimestamp() || timestamp >= GetBufferedEndTimestamp()) 2199 if (timestamp < GetStartTimestamp() || timestamp >= GetBufferedEndTimestamp())
2175 return kNoTimestamp(); 2200 return kNoTimestamp();
2176 2201
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
2240 return false; 2265 return false;
2241 2266
2242 DCHECK_NE(have_splice_buffers, have_preroll_buffer); 2267 DCHECK_NE(have_splice_buffers, have_preroll_buffer);
2243 splice_buffers_index_ = 0; 2268 splice_buffers_index_ = 0;
2244 pending_buffer_.swap(*out_buffer); 2269 pending_buffer_.swap(*out_buffer);
2245 pending_buffers_complete_ = false; 2270 pending_buffers_complete_ = false;
2246 return true; 2271 return true;
2247 } 2272 }
2248 2273
2249 } // namespace media 2274 } // namespace media
OLDNEW
« no previous file with comments | « no previous file | media/filters/source_buffer_stream_unittest.cc » ('j') | media/filters/source_buffer_stream_unittest.cc » ('J')

Powered by Google App Engine
This is Rietveld 408576698