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 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
132 | 132 |
133 } // namespace | 133 } // namespace |
134 | 134 |
135 SourceBufferStream::SourceBufferStream(const AudioDecoderConfig& audio_config, | 135 SourceBufferStream::SourceBufferStream(const AudioDecoderConfig& audio_config, |
136 const scoped_refptr<MediaLog>& media_log, | 136 const scoped_refptr<MediaLog>& media_log, |
137 bool splice_frames_enabled) | 137 bool splice_frames_enabled) |
138 : media_log_(media_log), | 138 : media_log_(media_log), |
139 seek_buffer_timestamp_(kNoTimestamp()), | 139 seek_buffer_timestamp_(kNoTimestamp()), |
140 media_segment_start_time_(kNoDecodeTimestamp()), | 140 media_segment_start_time_(kNoDecodeTimestamp()), |
141 range_for_next_append_(ranges_.end()), | 141 range_for_next_append_(ranges_.end()), |
142 last_appended_buffer_timestamp_(kNoDecodeTimestamp()), | |
143 last_output_buffer_timestamp_(kNoDecodeTimestamp()), | 142 last_output_buffer_timestamp_(kNoDecodeTimestamp()), |
144 max_interbuffer_distance_(kNoTimestamp()), | 143 max_interbuffer_distance_(kNoTimestamp()), |
145 memory_limit_(kSourceBufferAudioMemoryLimit), | 144 memory_limit_(kSourceBufferAudioMemoryLimit), |
146 splice_frames_enabled_(splice_frames_enabled) { | 145 splice_frames_enabled_(splice_frames_enabled) { |
147 DCHECK(audio_config.IsValidConfig()); | 146 DCHECK(audio_config.IsValidConfig()); |
148 audio_configs_.push_back(audio_config); | 147 audio_configs_.push_back(audio_config); |
149 } | 148 } |
150 | 149 |
151 SourceBufferStream::SourceBufferStream(const VideoDecoderConfig& video_config, | 150 SourceBufferStream::SourceBufferStream(const VideoDecoderConfig& video_config, |
152 const scoped_refptr<MediaLog>& media_log, | 151 const scoped_refptr<MediaLog>& media_log, |
153 bool splice_frames_enabled) | 152 bool splice_frames_enabled) |
154 : media_log_(media_log), | 153 : media_log_(media_log), |
155 seek_buffer_timestamp_(kNoTimestamp()), | 154 seek_buffer_timestamp_(kNoTimestamp()), |
156 media_segment_start_time_(kNoDecodeTimestamp()), | 155 media_segment_start_time_(kNoDecodeTimestamp()), |
157 range_for_next_append_(ranges_.end()), | 156 range_for_next_append_(ranges_.end()), |
158 last_appended_buffer_timestamp_(kNoDecodeTimestamp()), | |
159 last_output_buffer_timestamp_(kNoDecodeTimestamp()), | 157 last_output_buffer_timestamp_(kNoDecodeTimestamp()), |
160 max_interbuffer_distance_(kNoTimestamp()), | 158 max_interbuffer_distance_(kNoTimestamp()), |
161 memory_limit_(kSourceBufferVideoMemoryLimit), | 159 memory_limit_(kSourceBufferVideoMemoryLimit), |
162 splice_frames_enabled_(splice_frames_enabled) { | 160 splice_frames_enabled_(splice_frames_enabled) { |
163 DCHECK(video_config.IsValidConfig()); | 161 DCHECK(video_config.IsValidConfig()); |
164 video_configs_.push_back(video_config); | 162 video_configs_.push_back(video_config); |
165 } | 163 } |
166 | 164 |
167 SourceBufferStream::SourceBufferStream(const TextTrackConfig& text_config, | 165 SourceBufferStream::SourceBufferStream(const TextTrackConfig& text_config, |
168 const scoped_refptr<MediaLog>& media_log, | 166 const scoped_refptr<MediaLog>& media_log, |
169 bool splice_frames_enabled) | 167 bool splice_frames_enabled) |
170 : media_log_(media_log), | 168 : media_log_(media_log), |
171 text_track_config_(text_config), | 169 text_track_config_(text_config), |
172 seek_buffer_timestamp_(kNoTimestamp()), | 170 seek_buffer_timestamp_(kNoTimestamp()), |
173 media_segment_start_time_(kNoDecodeTimestamp()), | 171 media_segment_start_time_(kNoDecodeTimestamp()), |
174 range_for_next_append_(ranges_.end()), | 172 range_for_next_append_(ranges_.end()), |
175 last_appended_buffer_timestamp_(kNoDecodeTimestamp()), | |
176 last_output_buffer_timestamp_(kNoDecodeTimestamp()), | 173 last_output_buffer_timestamp_(kNoDecodeTimestamp()), |
177 max_interbuffer_distance_(kNoTimestamp()), | 174 max_interbuffer_distance_(kNoTimestamp()), |
178 memory_limit_(kSourceBufferAudioMemoryLimit), | 175 memory_limit_(kSourceBufferAudioMemoryLimit), |
179 splice_frames_enabled_(splice_frames_enabled) {} | 176 splice_frames_enabled_(splice_frames_enabled) {} |
180 | 177 |
181 SourceBufferStream::~SourceBufferStream() { | 178 SourceBufferStream::~SourceBufferStream() { |
182 while (!ranges_.empty()) { | 179 while (!ranges_.empty()) { |
183 delete ranges_.front(); | 180 delete ranges_.front(); |
184 ranges_.pop_front(); | 181 ranges_.pop_front(); |
185 } | 182 } |
186 } | 183 } |
187 | 184 |
188 void SourceBufferStream::OnNewMediaSegment( | 185 void SourceBufferStream::OnNewMediaSegment( |
189 DecodeTimestamp media_segment_start_time) { | 186 DecodeTimestamp media_segment_start_time) { |
190 DVLOG(1) << __FUNCTION__ << " " << GetStreamTypeName() | 187 DVLOG(1) << __FUNCTION__ << " " << GetStreamTypeName() |
191 << " (" << media_segment_start_time.InSecondsF() << ")"; | 188 << " (" << media_segment_start_time.InSecondsF() << ")"; |
192 DCHECK(!end_of_stream_); | 189 DCHECK(!end_of_stream_); |
193 media_segment_start_time_ = media_segment_start_time; | 190 media_segment_start_time_ = media_segment_start_time; |
194 new_media_segment_ = true; | 191 new_media_segment_ = true; |
195 | 192 |
196 RangeList::iterator last_range = range_for_next_append_; | 193 RangeList::iterator last_range = range_for_next_append_; |
197 range_for_next_append_ = FindExistingRangeFor(media_segment_start_time); | 194 range_for_next_append_ = FindExistingRangeFor(media_segment_start_time); |
198 | 195 |
199 // Only reset |last_appended_buffer_timestamp_| if this new media segment is | 196 // Only reset |last_appended_buffer_timestamp_| if this new media segment is |
200 // not adjacent to the previous media segment appended to the stream. | 197 // not adjacent to the previous media segment appended to the stream. |
201 if (range_for_next_append_ == ranges_.end() || | 198 if (range_for_next_append_ == ranges_.end() || |
202 !AreAdjacentInSequence(last_appended_buffer_timestamp_, | 199 !AreAdjacentInSequence(last_appended_buffer_timestamp_, |
203 media_segment_start_time)) { | 200 media_segment_start_time)) { |
204 last_appended_buffer_timestamp_ = kNoDecodeTimestamp(); | 201 last_appended_buffer_timestamp_ = kNoDecodeTimestamp(); |
| 202 last_appended_buffer_duration_ = kNoTimestamp(); |
205 last_appended_buffer_is_keyframe_ = false; | 203 last_appended_buffer_is_keyframe_ = false; |
206 DVLOG(3) << __FUNCTION__ << " next appended buffers will be in a new range"; | 204 DVLOG(3) << __FUNCTION__ << " next appended buffers will be in a new range"; |
207 } else if (last_range != ranges_.end()) { | 205 } else if (last_range != ranges_.end()) { |
208 DCHECK(last_range == range_for_next_append_); | 206 DCHECK(last_range == range_for_next_append_); |
209 DVLOG(3) << __FUNCTION__ << " next appended buffers will continue range " | 207 DVLOG(3) << __FUNCTION__ << " next appended buffers will continue range " |
210 << "unless intervening remove makes discontinuity"; | 208 << "unless intervening remove makes discontinuity"; |
211 } | 209 } |
212 } | 210 } |
213 | 211 |
214 bool SourceBufferStream::Append(const BufferQueue& buffers) { | 212 bool SourceBufferStream::Append(const BufferQueue& buffers) { |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
262 DecodeTimestamp next_buffer_timestamp = GetNextBufferTimestamp(); | 260 DecodeTimestamp next_buffer_timestamp = GetNextBufferTimestamp(); |
263 BufferQueue deleted_buffers; | 261 BufferQueue deleted_buffers; |
264 | 262 |
265 PrepareRangesForNextAppend(buffers, &deleted_buffers); | 263 PrepareRangesForNextAppend(buffers, &deleted_buffers); |
266 | 264 |
267 // If there's a range for |buffers|, insert |buffers| accordingly. Otherwise, | 265 // If there's a range for |buffers|, insert |buffers| accordingly. Otherwise, |
268 // create a new range with |buffers|. | 266 // create a new range with |buffers|. |
269 if (range_for_next_append_ != ranges_.end()) { | 267 if (range_for_next_append_ != ranges_.end()) { |
270 (*range_for_next_append_)->AppendBuffersToEnd(buffers); | 268 (*range_for_next_append_)->AppendBuffersToEnd(buffers); |
271 last_appended_buffer_timestamp_ = buffers.back()->GetDecodeTimestamp(); | 269 last_appended_buffer_timestamp_ = buffers.back()->GetDecodeTimestamp(); |
| 270 last_appended_buffer_duration_ = buffers.back()->duration(); |
272 last_appended_buffer_is_keyframe_ = buffers.back()->is_key_frame(); | 271 last_appended_buffer_is_keyframe_ = buffers.back()->is_key_frame(); |
273 } else { | 272 } else { |
274 DecodeTimestamp new_range_start_time = std::min( | 273 DecodeTimestamp new_range_start_time = std::min( |
275 media_segment_start_time_, buffers.front()->GetDecodeTimestamp()); | 274 media_segment_start_time_, buffers.front()->GetDecodeTimestamp()); |
276 const BufferQueue* buffers_for_new_range = &buffers; | 275 const BufferQueue* buffers_for_new_range = &buffers; |
277 BufferQueue trimmed_buffers; | 276 BufferQueue trimmed_buffers; |
278 | 277 |
279 // If the new range is not being created because of a new media | 278 // If the new range is not being created because of a new media |
280 // segment, then we must make sure that we start with a key frame. | 279 // segment, then we must make sure that we start with a key frame. |
281 // This can happen if the GOP in the previous append gets destroyed | 280 // This can happen if the GOP in the previous append gets destroyed |
282 // by a Remove() call. | 281 // by a Remove() call. |
283 if (!new_media_segment_) { | 282 if (!new_media_segment_) { |
284 BufferQueue::const_iterator itr = buffers.begin(); | 283 BufferQueue::const_iterator itr = buffers.begin(); |
285 | 284 |
286 // Scan past all the non-key-frames. | 285 // Scan past all the non-key-frames. |
287 while (itr != buffers.end() && !(*itr)->is_key_frame()) { | 286 while (itr != buffers.end() && !(*itr)->is_key_frame()) { |
288 ++itr; | 287 ++itr; |
289 } | 288 } |
290 | 289 |
291 // If we didn't find a key frame, then update the last appended | 290 // If we didn't find a key frame, then update the last appended |
292 // buffer state and return. | 291 // buffer state and return. |
293 if (itr == buffers.end()) { | 292 if (itr == buffers.end()) { |
294 last_appended_buffer_timestamp_ = buffers.back()->GetDecodeTimestamp(); | 293 last_appended_buffer_timestamp_ = buffers.back()->GetDecodeTimestamp(); |
| 294 last_appended_buffer_duration_ = buffers.back()->duration(); |
295 last_appended_buffer_is_keyframe_ = buffers.back()->is_key_frame(); | 295 last_appended_buffer_is_keyframe_ = buffers.back()->is_key_frame(); |
296 DVLOG(1) << __FUNCTION__ << " " << GetStreamTypeName() | 296 DVLOG(1) << __FUNCTION__ << " " << GetStreamTypeName() |
297 << ": new buffers in the middle of media segment depend on" | 297 << ": new buffers in the middle of media segment depend on" |
298 "keyframe that has been removed, and contain no keyframes." | 298 "keyframe that has been removed, and contain no keyframes." |
299 "Skipping further processing."; | 299 "Skipping further processing."; |
300 DVLOG(1) << __FUNCTION__ << " " << GetStreamTypeName() | 300 DVLOG(1) << __FUNCTION__ << " " << GetStreamTypeName() |
301 << ": done. ranges_=" << RangesToString(ranges_); | 301 << ": done. ranges_=" << RangesToString(ranges_); |
302 return true; | 302 return true; |
303 } else if (itr != buffers.begin()) { | 303 } else if (itr != buffers.begin()) { |
304 // Copy the first key frame and everything after it into | 304 // Copy the first key frame and everything after it into |
305 // |trimmed_buffers|. | 305 // |trimmed_buffers|. |
306 trimmed_buffers.assign(itr, buffers.end()); | 306 trimmed_buffers.assign(itr, buffers.end()); |
307 buffers_for_new_range = &trimmed_buffers; | 307 buffers_for_new_range = &trimmed_buffers; |
308 } | 308 } |
309 | 309 |
310 new_range_start_time = | 310 new_range_start_time = |
311 buffers_for_new_range->front()->GetDecodeTimestamp(); | 311 buffers_for_new_range->front()->GetDecodeTimestamp(); |
312 } | 312 } |
313 | 313 |
314 range_for_next_append_ = | 314 range_for_next_append_ = |
315 AddToRanges(new SourceBufferRange( | 315 AddToRanges(new SourceBufferRange( |
316 TypeToGapPolicy(GetType()), | 316 TypeToGapPolicy(GetType()), |
317 *buffers_for_new_range, new_range_start_time, | 317 *buffers_for_new_range, new_range_start_time, |
318 base::Bind(&SourceBufferStream::GetMaxInterbufferDistance, | 318 base::Bind(&SourceBufferStream::GetMaxInterbufferDistance, |
319 base::Unretained(this)))); | 319 base::Unretained(this)))); |
320 last_appended_buffer_timestamp_ = | 320 last_appended_buffer_timestamp_ = |
321 buffers_for_new_range->back()->GetDecodeTimestamp(); | 321 buffers_for_new_range->back()->GetDecodeTimestamp(); |
| 322 last_appended_buffer_duration_ = buffers_for_new_range->back()->duration(); |
322 last_appended_buffer_is_keyframe_ = | 323 last_appended_buffer_is_keyframe_ = |
323 buffers_for_new_range->back()->is_key_frame(); | 324 buffers_for_new_range->back()->is_key_frame(); |
324 } | 325 } |
325 | 326 |
326 new_media_segment_ = false; | 327 new_media_segment_ = false; |
327 | 328 |
328 MergeWithAdjacentRangeIfNecessary(range_for_next_append_); | 329 MergeWithAdjacentRangeIfNecessary(range_for_next_append_); |
329 | 330 |
330 // Seek to try to fulfill a previous call to Seek(). | 331 // Seek to try to fulfill a previous call to Seek(). |
331 if (seek_pending_) { | 332 if (seek_pending_) { |
(...skipping 312 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
644 DVLOG(2) << __FUNCTION__ << " " << GetStreamTypeName() << ": Before GC" | 645 DVLOG(2) << __FUNCTION__ << " " << GetStreamTypeName() << ": Before GC" |
645 << " media_time=" << media_time.InSecondsF() | 646 << " media_time=" << media_time.InSecondsF() |
646 << " ranges_=" << RangesToString(ranges_) | 647 << " ranges_=" << RangesToString(ranges_) |
647 << " seek_pending_=" << seek_pending_ | 648 << " seek_pending_=" << seek_pending_ |
648 << " ranges_size=" << ranges_size | 649 << " ranges_size=" << ranges_size |
649 << " newDataSize=" << newDataSize | 650 << " newDataSize=" << newDataSize |
650 << " memory_limit_=" << memory_limit_ | 651 << " memory_limit_=" << memory_limit_ |
651 << " last_appended_buffer_timestamp_=" | 652 << " last_appended_buffer_timestamp_=" |
652 << last_appended_buffer_timestamp_.InSecondsF(); | 653 << last_appended_buffer_timestamp_.InSecondsF(); |
653 | 654 |
| 655 if (selected_range_ && !seek_pending_ && |
| 656 media_time > selected_range_->GetBufferedEndTimestamp()) { |
| 657 // Strictly speaking |media_time| (taken from HTMLMediaElement::currentTime) |
| 658 // should always be in the buffered ranges, but media::Pipeline uses audio |
| 659 // stream as the main time source, when audio is present. |
| 660 // In cases when audio and video streams have different buffered ranges, the |
| 661 // |media_time| value might be slightly outside of the video stream buffered |
| 662 // range. In those cases we need to clamp |media_time| value to the current |
| 663 // stream buffered ranges, to ensure the MSE garbage collection algorithm |
| 664 // works correctly (see crbug.com/563292 for details). |
| 665 DecodeTimestamp selected_buffered_end = |
| 666 selected_range_->GetBufferedEndTimestamp(); |
| 667 |
| 668 DVLOG(2) << __FUNCTION__ << " media_time " << media_time.InSecondsF() |
| 669 << " is outside of selected_range_=[" |
| 670 << selected_range_->GetStartTimestamp().InSecondsF() << ";" |
| 671 << selected_buffered_end.InSecondsF() |
| 672 << "] clamping media_time to be " |
| 673 << selected_buffered_end.InSecondsF(); |
| 674 media_time = selected_buffered_end; |
| 675 } |
| 676 |
654 size_t bytes_freed = 0; | 677 size_t bytes_freed = 0; |
655 | 678 |
656 // If last appended buffer position was earlier than the current playback time | 679 // If last appended buffer position was earlier than the current playback time |
657 // then try deleting data between last append and current media_time. | 680 // then try deleting data between last append and current media_time. |
658 if (last_appended_buffer_timestamp_ != kNoDecodeTimestamp() && | 681 if (last_appended_buffer_timestamp_ != kNoDecodeTimestamp() && |
659 last_appended_buffer_timestamp_ < media_time) { | 682 last_appended_buffer_duration_ != kNoTimestamp() && |
| 683 media_time > |
| 684 last_appended_buffer_timestamp_ + last_appended_buffer_duration_) { |
660 size_t between = FreeBuffersAfterLastAppended(bytes_to_free, media_time); | 685 size_t between = FreeBuffersAfterLastAppended(bytes_to_free, media_time); |
661 DVLOG(3) << __FUNCTION__ << " FreeBuffersAfterLastAppended " | 686 DVLOG(3) << __FUNCTION__ << " FreeBuffersAfterLastAppended " |
662 << " released " << between << " bytes" | 687 << " released " << between << " bytes" |
663 << " ranges_=" << RangesToString(ranges_); | 688 << " ranges_=" << RangesToString(ranges_); |
664 bytes_freed += between; | 689 bytes_freed += between; |
665 | 690 |
666 // Some players start appending data at the new seek target position before | 691 // Some players start appending data at the new seek target position before |
667 // actually initiating the seek operation (i.e. they try to improve seek | 692 // actually initiating the seek operation (i.e. they try to improve seek |
668 // performance by prebuffering some data at the seek target position and | 693 // performance by prebuffering some data at the seek target position and |
669 // initiating seek once enough data is pre-buffered. In those cases we'll | 694 // initiating seek once enough data is pre-buffered. In those cases we'll |
670 // see that data is being appended at some new position, but there is no | 695 // see that data is being appended at some new position, but there is no |
671 // pending seek reported yet. In this situation we need to try preserving | 696 // pending seek reported yet. In this situation we need to try preserving |
672 // the most recently appended data, i.e. data belonging to the same buffered | 697 // the most recently appended data, i.e. data belonging to the same buffered |
673 // range as the most recent append. | 698 // range as the most recent append. |
674 if (range_for_next_append_ != ranges_.end()) { | 699 if (range_for_next_append_ != ranges_.end()) { |
675 DCHECK((*range_for_next_append_)->GetStartTimestamp() <= media_time); | 700 DCHECK((*range_for_next_append_)->GetStartTimestamp() <= media_time); |
676 media_time = (*range_for_next_append_)->GetStartTimestamp(); | 701 media_time = (*range_for_next_append_)->GetStartTimestamp(); |
| 702 DVLOG(3) << __FUNCTION__ << " media_time adjusted to " |
| 703 << media_time.InSecondsF(); |
677 } | 704 } |
678 } | 705 } |
679 | 706 |
680 // If there is an unsatisfied pending seek, we can safely remove all data that | 707 // If there is an unsatisfied pending seek, we can safely remove all data that |
681 // is earlier than seek target, then remove from the back until we reach the | 708 // is earlier than seek target, then remove from the back until we reach the |
682 // most recently appended GOP and then remove from the front if we still don't | 709 // most recently appended GOP and then remove from the front if we still don't |
683 // have enough space for the upcoming append. | 710 // have enough space for the upcoming append. |
684 if (bytes_freed < bytes_to_free && seek_pending_) { | 711 if (bytes_freed < bytes_to_free && seek_pending_) { |
685 DCHECK(!ranges_.empty()); | 712 DCHECK(!ranges_.empty()); |
686 // All data earlier than the seek target |media_time| can be removed safely | 713 // All data earlier than the seek target |media_time| can be removed safely |
(...skipping 1068 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1755 return false; | 1782 return false; |
1756 | 1783 |
1757 DCHECK_NE(have_splice_buffers, have_preroll_buffer); | 1784 DCHECK_NE(have_splice_buffers, have_preroll_buffer); |
1758 splice_buffers_index_ = 0; | 1785 splice_buffers_index_ = 0; |
1759 pending_buffer_.swap(*out_buffer); | 1786 pending_buffer_.swap(*out_buffer); |
1760 pending_buffers_complete_ = false; | 1787 pending_buffers_complete_ = false; |
1761 return true; | 1788 return true; |
1762 } | 1789 } |
1763 | 1790 |
1764 } // namespace media | 1791 } // namespace media |
OLD | NEW |