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 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 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()), | 142 last_appended_buffer_timestamp_(kNoDecodeTimestamp()), |
| 143 last_appended_buffer_duration_(kNoTimestamp()), | |
|
wolenetz
2015/12/01 01:12:43
nit: some of these common initializers can now hap
servolk
2015/12/01 18:51:49
Done.
| |
| 143 last_output_buffer_timestamp_(kNoDecodeTimestamp()), | 144 last_output_buffer_timestamp_(kNoDecodeTimestamp()), |
| 144 max_interbuffer_distance_(kNoTimestamp()), | 145 max_interbuffer_distance_(kNoTimestamp()), |
| 145 memory_limit_(kSourceBufferAudioMemoryLimit), | 146 memory_limit_(kSourceBufferAudioMemoryLimit), |
| 146 splice_frames_enabled_(splice_frames_enabled) { | 147 splice_frames_enabled_(splice_frames_enabled) { |
| 147 DCHECK(audio_config.IsValidConfig()); | 148 DCHECK(audio_config.IsValidConfig()); |
| 148 audio_configs_.push_back(audio_config); | 149 audio_configs_.push_back(audio_config); |
| 149 } | 150 } |
| 150 | 151 |
| 151 SourceBufferStream::SourceBufferStream(const VideoDecoderConfig& video_config, | 152 SourceBufferStream::SourceBufferStream(const VideoDecoderConfig& video_config, |
| 152 const scoped_refptr<MediaLog>& media_log, | 153 const scoped_refptr<MediaLog>& media_log, |
| 153 bool splice_frames_enabled) | 154 bool splice_frames_enabled) |
| 154 : media_log_(media_log), | 155 : media_log_(media_log), |
| 155 seek_buffer_timestamp_(kNoTimestamp()), | 156 seek_buffer_timestamp_(kNoTimestamp()), |
| 156 media_segment_start_time_(kNoDecodeTimestamp()), | 157 media_segment_start_time_(kNoDecodeTimestamp()), |
| 157 range_for_next_append_(ranges_.end()), | 158 range_for_next_append_(ranges_.end()), |
| 158 last_appended_buffer_timestamp_(kNoDecodeTimestamp()), | 159 last_appended_buffer_timestamp_(kNoDecodeTimestamp()), |
| 160 last_appended_buffer_duration_(kNoTimestamp()), | |
| 159 last_output_buffer_timestamp_(kNoDecodeTimestamp()), | 161 last_output_buffer_timestamp_(kNoDecodeTimestamp()), |
| 160 max_interbuffer_distance_(kNoTimestamp()), | 162 max_interbuffer_distance_(kNoTimestamp()), |
| 161 memory_limit_(kSourceBufferVideoMemoryLimit), | 163 memory_limit_(kSourceBufferVideoMemoryLimit), |
| 162 splice_frames_enabled_(splice_frames_enabled) { | 164 splice_frames_enabled_(splice_frames_enabled) { |
| 163 DCHECK(video_config.IsValidConfig()); | 165 DCHECK(video_config.IsValidConfig()); |
| 164 video_configs_.push_back(video_config); | 166 video_configs_.push_back(video_config); |
| 165 } | 167 } |
| 166 | 168 |
| 167 SourceBufferStream::SourceBufferStream(const TextTrackConfig& text_config, | 169 SourceBufferStream::SourceBufferStream(const TextTrackConfig& text_config, |
| 168 const scoped_refptr<MediaLog>& media_log, | 170 const scoped_refptr<MediaLog>& media_log, |
| 169 bool splice_frames_enabled) | 171 bool splice_frames_enabled) |
| 170 : media_log_(media_log), | 172 : media_log_(media_log), |
| 171 text_track_config_(text_config), | 173 text_track_config_(text_config), |
| 172 seek_buffer_timestamp_(kNoTimestamp()), | 174 seek_buffer_timestamp_(kNoTimestamp()), |
| 173 media_segment_start_time_(kNoDecodeTimestamp()), | 175 media_segment_start_time_(kNoDecodeTimestamp()), |
| 174 range_for_next_append_(ranges_.end()), | 176 range_for_next_append_(ranges_.end()), |
| 175 last_appended_buffer_timestamp_(kNoDecodeTimestamp()), | 177 last_appended_buffer_timestamp_(kNoDecodeTimestamp()), |
| 178 last_appended_buffer_duration_(kNoTimestamp()), | |
| 176 last_output_buffer_timestamp_(kNoDecodeTimestamp()), | 179 last_output_buffer_timestamp_(kNoDecodeTimestamp()), |
| 177 max_interbuffer_distance_(kNoTimestamp()), | 180 max_interbuffer_distance_(kNoTimestamp()), |
| 178 memory_limit_(kSourceBufferAudioMemoryLimit), | 181 memory_limit_(kSourceBufferAudioMemoryLimit), |
| 179 splice_frames_enabled_(splice_frames_enabled) {} | 182 splice_frames_enabled_(splice_frames_enabled) {} |
| 180 | 183 |
| 181 SourceBufferStream::~SourceBufferStream() { | 184 SourceBufferStream::~SourceBufferStream() { |
| 182 while (!ranges_.empty()) { | 185 while (!ranges_.empty()) { |
| 183 delete ranges_.front(); | 186 delete ranges_.front(); |
| 184 ranges_.pop_front(); | 187 ranges_.pop_front(); |
| 185 } | 188 } |
| 186 } | 189 } |
| 187 | 190 |
| 188 void SourceBufferStream::OnNewMediaSegment( | 191 void SourceBufferStream::OnNewMediaSegment( |
| 189 DecodeTimestamp media_segment_start_time) { | 192 DecodeTimestamp media_segment_start_time) { |
| 190 DVLOG(1) << __FUNCTION__ << " " << GetStreamTypeName() | 193 DVLOG(1) << __FUNCTION__ << " " << GetStreamTypeName() |
| 191 << " (" << media_segment_start_time.InSecondsF() << ")"; | 194 << " (" << media_segment_start_time.InSecondsF() << ")"; |
| 192 DCHECK(!end_of_stream_); | 195 DCHECK(!end_of_stream_); |
| 193 media_segment_start_time_ = media_segment_start_time; | 196 media_segment_start_time_ = media_segment_start_time; |
| 194 new_media_segment_ = true; | 197 new_media_segment_ = true; |
| 195 | 198 |
| 196 RangeList::iterator last_range = range_for_next_append_; | 199 RangeList::iterator last_range = range_for_next_append_; |
| 197 range_for_next_append_ = FindExistingRangeFor(media_segment_start_time); | 200 range_for_next_append_ = FindExistingRangeFor(media_segment_start_time); |
| 198 | 201 |
| 199 // Only reset |last_appended_buffer_timestamp_| if this new media segment is | 202 // Only reset |last_appended_buffer_timestamp_| if this new media segment is |
| 200 // not adjacent to the previous media segment appended to the stream. | 203 // not adjacent to the previous media segment appended to the stream. |
| 201 if (range_for_next_append_ == ranges_.end() || | 204 if (range_for_next_append_ == ranges_.end() || |
| 202 !AreAdjacentInSequence(last_appended_buffer_timestamp_, | 205 !AreAdjacentInSequence(last_appended_buffer_timestamp_, |
| 203 media_segment_start_time)) { | 206 media_segment_start_time)) { |
| 204 last_appended_buffer_timestamp_ = kNoDecodeTimestamp(); | 207 last_appended_buffer_timestamp_ = kNoDecodeTimestamp(); |
| 208 last_appended_buffer_duration_ = kNoTimestamp(); | |
| 205 last_appended_buffer_is_keyframe_ = false; | 209 last_appended_buffer_is_keyframe_ = false; |
| 206 DVLOG(3) << __FUNCTION__ << " next appended buffers will be in a new range"; | 210 DVLOG(3) << __FUNCTION__ << " next appended buffers will be in a new range"; |
| 207 } else if (last_range != ranges_.end()) { | 211 } else if (last_range != ranges_.end()) { |
| 208 DCHECK(last_range == range_for_next_append_); | 212 DCHECK(last_range == range_for_next_append_); |
| 209 DVLOG(3) << __FUNCTION__ << " next appended buffers will continue range " | 213 DVLOG(3) << __FUNCTION__ << " next appended buffers will continue range " |
| 210 << "unless intervening remove makes discontinuity"; | 214 << "unless intervening remove makes discontinuity"; |
| 211 } | 215 } |
| 212 } | 216 } |
| 213 | 217 |
| 214 bool SourceBufferStream::Append(const BufferQueue& buffers) { | 218 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(); | 266 DecodeTimestamp next_buffer_timestamp = GetNextBufferTimestamp(); |
| 263 BufferQueue deleted_buffers; | 267 BufferQueue deleted_buffers; |
| 264 | 268 |
| 265 PrepareRangesForNextAppend(buffers, &deleted_buffers); | 269 PrepareRangesForNextAppend(buffers, &deleted_buffers); |
| 266 | 270 |
| 267 // If there's a range for |buffers|, insert |buffers| accordingly. Otherwise, | 271 // If there's a range for |buffers|, insert |buffers| accordingly. Otherwise, |
| 268 // create a new range with |buffers|. | 272 // create a new range with |buffers|. |
| 269 if (range_for_next_append_ != ranges_.end()) { | 273 if (range_for_next_append_ != ranges_.end()) { |
| 270 (*range_for_next_append_)->AppendBuffersToEnd(buffers); | 274 (*range_for_next_append_)->AppendBuffersToEnd(buffers); |
| 271 last_appended_buffer_timestamp_ = buffers.back()->GetDecodeTimestamp(); | 275 last_appended_buffer_timestamp_ = buffers.back()->GetDecodeTimestamp(); |
| 276 last_appended_buffer_duration_ = buffers.back()->duration(); | |
| 272 last_appended_buffer_is_keyframe_ = buffers.back()->is_key_frame(); | 277 last_appended_buffer_is_keyframe_ = buffers.back()->is_key_frame(); |
| 273 } else { | 278 } else { |
| 274 DecodeTimestamp new_range_start_time = std::min( | 279 DecodeTimestamp new_range_start_time = std::min( |
| 275 media_segment_start_time_, buffers.front()->GetDecodeTimestamp()); | 280 media_segment_start_time_, buffers.front()->GetDecodeTimestamp()); |
| 276 const BufferQueue* buffers_for_new_range = &buffers; | 281 const BufferQueue* buffers_for_new_range = &buffers; |
| 277 BufferQueue trimmed_buffers; | 282 BufferQueue trimmed_buffers; |
| 278 | 283 |
| 279 // If the new range is not being created because of a new media | 284 // 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. | 285 // 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 | 286 // This can happen if the GOP in the previous append gets destroyed |
| 282 // by a Remove() call. | 287 // by a Remove() call. |
| 283 if (!new_media_segment_) { | 288 if (!new_media_segment_) { |
| 284 BufferQueue::const_iterator itr = buffers.begin(); | 289 BufferQueue::const_iterator itr = buffers.begin(); |
| 285 | 290 |
| 286 // Scan past all the non-key-frames. | 291 // Scan past all the non-key-frames. |
| 287 while (itr != buffers.end() && !(*itr)->is_key_frame()) { | 292 while (itr != buffers.end() && !(*itr)->is_key_frame()) { |
| 288 ++itr; | 293 ++itr; |
| 289 } | 294 } |
| 290 | 295 |
| 291 // If we didn't find a key frame, then update the last appended | 296 // If we didn't find a key frame, then update the last appended |
| 292 // buffer state and return. | 297 // buffer state and return. |
| 293 if (itr == buffers.end()) { | 298 if (itr == buffers.end()) { |
| 294 last_appended_buffer_timestamp_ = buffers.back()->GetDecodeTimestamp(); | 299 last_appended_buffer_timestamp_ = buffers.back()->GetDecodeTimestamp(); |
| 300 last_appended_buffer_duration_ = buffers.back()->duration(); | |
| 295 last_appended_buffer_is_keyframe_ = buffers.back()->is_key_frame(); | 301 last_appended_buffer_is_keyframe_ = buffers.back()->is_key_frame(); |
| 296 DVLOG(1) << __FUNCTION__ << " " << GetStreamTypeName() | 302 DVLOG(1) << __FUNCTION__ << " " << GetStreamTypeName() |
| 297 << ": new buffers in the middle of media segment depend on" | 303 << ": new buffers in the middle of media segment depend on" |
| 298 "keyframe that has been removed, and contain no keyframes." | 304 "keyframe that has been removed, and contain no keyframes." |
| 299 "Skipping further processing."; | 305 "Skipping further processing."; |
| 300 DVLOG(1) << __FUNCTION__ << " " << GetStreamTypeName() | 306 DVLOG(1) << __FUNCTION__ << " " << GetStreamTypeName() |
| 301 << ": done. ranges_=" << RangesToString(ranges_); | 307 << ": done. ranges_=" << RangesToString(ranges_); |
| 302 return true; | 308 return true; |
| 303 } else if (itr != buffers.begin()) { | 309 } else if (itr != buffers.begin()) { |
| 304 // Copy the first key frame and everything after it into | 310 // Copy the first key frame and everything after it into |
| 305 // |trimmed_buffers|. | 311 // |trimmed_buffers|. |
| 306 trimmed_buffers.assign(itr, buffers.end()); | 312 trimmed_buffers.assign(itr, buffers.end()); |
| 307 buffers_for_new_range = &trimmed_buffers; | 313 buffers_for_new_range = &trimmed_buffers; |
| 308 } | 314 } |
| 309 | 315 |
| 310 new_range_start_time = | 316 new_range_start_time = |
| 311 buffers_for_new_range->front()->GetDecodeTimestamp(); | 317 buffers_for_new_range->front()->GetDecodeTimestamp(); |
| 312 } | 318 } |
| 313 | 319 |
| 314 range_for_next_append_ = | 320 range_for_next_append_ = |
| 315 AddToRanges(new SourceBufferRange( | 321 AddToRanges(new SourceBufferRange( |
| 316 TypeToGapPolicy(GetType()), | 322 TypeToGapPolicy(GetType()), |
| 317 *buffers_for_new_range, new_range_start_time, | 323 *buffers_for_new_range, new_range_start_time, |
| 318 base::Bind(&SourceBufferStream::GetMaxInterbufferDistance, | 324 base::Bind(&SourceBufferStream::GetMaxInterbufferDistance, |
| 319 base::Unretained(this)))); | 325 base::Unretained(this)))); |
| 320 last_appended_buffer_timestamp_ = | 326 last_appended_buffer_timestamp_ = |
| 321 buffers_for_new_range->back()->GetDecodeTimestamp(); | 327 buffers_for_new_range->back()->GetDecodeTimestamp(); |
| 328 last_appended_buffer_duration_ = buffers_for_new_range->back()->duration(); | |
| 322 last_appended_buffer_is_keyframe_ = | 329 last_appended_buffer_is_keyframe_ = |
| 323 buffers_for_new_range->back()->is_key_frame(); | 330 buffers_for_new_range->back()->is_key_frame(); |
| 324 } | 331 } |
| 325 | 332 |
| 326 new_media_segment_ = false; | 333 new_media_segment_ = false; |
| 327 | 334 |
| 328 MergeWithAdjacentRangeIfNecessary(range_for_next_append_); | 335 MergeWithAdjacentRangeIfNecessary(range_for_next_append_); |
| 329 | 336 |
| 330 // Seek to try to fulfill a previous call to Seek(). | 337 // Seek to try to fulfill a previous call to Seek(). |
| 331 if (seek_pending_) { | 338 if (seek_pending_) { |
| (...skipping 317 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 649 << " newDataSize=" << newDataSize | 656 << " newDataSize=" << newDataSize |
| 650 << " memory_limit_=" << memory_limit_ | 657 << " memory_limit_=" << memory_limit_ |
| 651 << " last_appended_buffer_timestamp_=" | 658 << " last_appended_buffer_timestamp_=" |
| 652 << last_appended_buffer_timestamp_.InSecondsF(); | 659 << last_appended_buffer_timestamp_.InSecondsF(); |
| 653 | 660 |
| 654 size_t bytes_freed = 0; | 661 size_t bytes_freed = 0; |
| 655 | 662 |
| 656 // If last appended buffer position was earlier than the current playback time | 663 // If last appended buffer position was earlier than the current playback time |
| 657 // then try deleting data between last append and current media_time. | 664 // then try deleting data between last append and current media_time. |
| 658 if (last_appended_buffer_timestamp_ != kNoDecodeTimestamp() && | 665 if (last_appended_buffer_timestamp_ != kNoDecodeTimestamp() && |
| 659 last_appended_buffer_timestamp_ < media_time) { | 666 last_appended_buffer_duration_ != kNoTimestamp() && |
| 667 media_time > | |
| 668 last_appended_buffer_timestamp_ + last_appended_buffer_duration_) { | |
| 660 size_t between = FreeBuffersAfterLastAppended(bytes_to_free, media_time); | 669 size_t between = FreeBuffersAfterLastAppended(bytes_to_free, media_time); |
| 661 DVLOG(3) << __FUNCTION__ << " FreeBuffersAfterLastAppended " | 670 DVLOG(3) << __FUNCTION__ << " FreeBuffersAfterLastAppended " |
| 662 << " released " << between << " bytes" | 671 << " released " << between << " bytes" |
| 663 << " ranges_=" << RangesToString(ranges_); | 672 << " ranges_=" << RangesToString(ranges_); |
| 664 bytes_freed += between; | 673 bytes_freed += between; |
| 665 | 674 |
| 666 // Some players start appending data at the new seek target position before | 675 // 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 | 676 // actually initiating the seek operation (i.e. they try to improve seek |
| 668 // performance by prebuffering some data at the seek target position and | 677 // 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 | 678 // 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 | 679 // 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 | 680 // 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 | 681 // the most recently appended data, i.e. data belonging to the same buffered |
| 673 // range as the most recent append. | 682 // range as the most recent append. |
| 674 if (range_for_next_append_ != ranges_.end()) { | 683 if (range_for_next_append_ != ranges_.end()) { |
| 675 DCHECK((*range_for_next_append_)->GetStartTimestamp() <= media_time); | 684 DCHECK((*range_for_next_append_)->GetStartTimestamp() <= media_time); |
| 676 media_time = (*range_for_next_append_)->GetStartTimestamp(); | 685 media_time = (*range_for_next_append_)->GetStartTimestamp(); |
| 686 DVLOG(3) << __FUNCTION__ << " media_time adjusted to " | |
| 687 << media_time.InSecondsF(); | |
| 677 } | 688 } |
| 678 } | 689 } |
| 679 | 690 |
| 680 // If there is an unsatisfied pending seek, we can safely remove all data that | 691 // 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 | 692 // 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 | 693 // most recently appended GOP and then remove from the front if we still don't |
| 683 // have enough space for the upcoming append. | 694 // have enough space for the upcoming append. |
| 684 if (bytes_freed < bytes_to_free && seek_pending_) { | 695 if (bytes_freed < bytes_to_free && seek_pending_) { |
| 685 DCHECK(!ranges_.empty()); | 696 DCHECK(!ranges_.empty()); |
| 686 // All data earlier than the seek target |media_time| can be removed safely | 697 // 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; | 1766 return false; |
| 1756 | 1767 |
| 1757 DCHECK_NE(have_splice_buffers, have_preroll_buffer); | 1768 DCHECK_NE(have_splice_buffers, have_preroll_buffer); |
| 1758 splice_buffers_index_ = 0; | 1769 splice_buffers_index_ = 0; |
| 1759 pending_buffer_.swap(*out_buffer); | 1770 pending_buffer_.swap(*out_buffer); |
| 1760 pending_buffers_complete_ = false; | 1771 pending_buffers_complete_ = false; |
| 1761 return true; | 1772 return true; |
| 1762 } | 1773 } |
| 1763 | 1774 |
| 1764 } // namespace media | 1775 } // namespace media |
| OLD | NEW |