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 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
138 NOTREACHED(); | 138 NOTREACHED(); |
139 return SourceBufferRange::NO_GAPS_ALLOWED; | 139 return SourceBufferRange::NO_GAPS_ALLOWED; |
140 } | 140 } |
141 | 141 |
142 } // namespace | 142 } // namespace |
143 | 143 |
144 SourceBufferStream::SourceBufferStream(const AudioDecoderConfig& audio_config, | 144 SourceBufferStream::SourceBufferStream(const AudioDecoderConfig& audio_config, |
145 const scoped_refptr<MediaLog>& media_log, | 145 const scoped_refptr<MediaLog>& media_log, |
146 bool splice_frames_enabled) | 146 bool splice_frames_enabled) |
147 : media_log_(media_log), | 147 : media_log_(media_log), |
148 seek_buffer_timestamp_(kNoTimestamp()), | 148 seek_buffer_timestamp_(kNoTimestamp), |
149 coded_frame_group_start_time_(kNoDecodeTimestamp()), | 149 coded_frame_group_start_time_(kNoDecodeTimestamp()), |
150 range_for_next_append_(ranges_.end()), | 150 range_for_next_append_(ranges_.end()), |
151 last_output_buffer_timestamp_(kNoDecodeTimestamp()), | 151 last_output_buffer_timestamp_(kNoDecodeTimestamp()), |
152 max_interbuffer_distance_(kNoTimestamp()), | 152 max_interbuffer_distance_(kNoTimestamp), |
153 memory_limit_(kSourceBufferAudioMemoryLimit), | 153 memory_limit_(kSourceBufferAudioMemoryLimit), |
154 splice_frames_enabled_(splice_frames_enabled) { | 154 splice_frames_enabled_(splice_frames_enabled) { |
155 DCHECK(audio_config.IsValidConfig()); | 155 DCHECK(audio_config.IsValidConfig()); |
156 audio_configs_.push_back(audio_config); | 156 audio_configs_.push_back(audio_config); |
157 } | 157 } |
158 | 158 |
159 SourceBufferStream::SourceBufferStream(const VideoDecoderConfig& video_config, | 159 SourceBufferStream::SourceBufferStream(const VideoDecoderConfig& video_config, |
160 const scoped_refptr<MediaLog>& media_log, | 160 const scoped_refptr<MediaLog>& media_log, |
161 bool splice_frames_enabled) | 161 bool splice_frames_enabled) |
162 : media_log_(media_log), | 162 : media_log_(media_log), |
163 seek_buffer_timestamp_(kNoTimestamp()), | 163 seek_buffer_timestamp_(kNoTimestamp), |
164 coded_frame_group_start_time_(kNoDecodeTimestamp()), | 164 coded_frame_group_start_time_(kNoDecodeTimestamp()), |
165 range_for_next_append_(ranges_.end()), | 165 range_for_next_append_(ranges_.end()), |
166 last_output_buffer_timestamp_(kNoDecodeTimestamp()), | 166 last_output_buffer_timestamp_(kNoDecodeTimestamp()), |
167 max_interbuffer_distance_(kNoTimestamp()), | 167 max_interbuffer_distance_(kNoTimestamp), |
168 memory_limit_(kSourceBufferVideoMemoryLimit), | 168 memory_limit_(kSourceBufferVideoMemoryLimit), |
169 splice_frames_enabled_(splice_frames_enabled) { | 169 splice_frames_enabled_(splice_frames_enabled) { |
170 DCHECK(video_config.IsValidConfig()); | 170 DCHECK(video_config.IsValidConfig()); |
171 video_configs_.push_back(video_config); | 171 video_configs_.push_back(video_config); |
172 } | 172 } |
173 | 173 |
174 SourceBufferStream::SourceBufferStream(const TextTrackConfig& text_config, | 174 SourceBufferStream::SourceBufferStream(const TextTrackConfig& text_config, |
175 const scoped_refptr<MediaLog>& media_log, | 175 const scoped_refptr<MediaLog>& media_log, |
176 bool splice_frames_enabled) | 176 bool splice_frames_enabled) |
177 : media_log_(media_log), | 177 : media_log_(media_log), |
178 text_track_config_(text_config), | 178 text_track_config_(text_config), |
179 seek_buffer_timestamp_(kNoTimestamp()), | 179 seek_buffer_timestamp_(kNoTimestamp), |
180 coded_frame_group_start_time_(kNoDecodeTimestamp()), | 180 coded_frame_group_start_time_(kNoDecodeTimestamp()), |
181 range_for_next_append_(ranges_.end()), | 181 range_for_next_append_(ranges_.end()), |
182 last_output_buffer_timestamp_(kNoDecodeTimestamp()), | 182 last_output_buffer_timestamp_(kNoDecodeTimestamp()), |
183 max_interbuffer_distance_(kNoTimestamp()), | 183 max_interbuffer_distance_(kNoTimestamp), |
184 memory_limit_(kSourceBufferAudioMemoryLimit), | 184 memory_limit_(kSourceBufferAudioMemoryLimit), |
185 splice_frames_enabled_(splice_frames_enabled) {} | 185 splice_frames_enabled_(splice_frames_enabled) {} |
186 | 186 |
187 SourceBufferStream::~SourceBufferStream() { | 187 SourceBufferStream::~SourceBufferStream() { |
188 while (!ranges_.empty()) { | 188 while (!ranges_.empty()) { |
189 delete ranges_.front(); | 189 delete ranges_.front(); |
190 ranges_.pop_front(); | 190 ranges_.pop_front(); |
191 } | 191 } |
192 } | 192 } |
193 | 193 |
194 void SourceBufferStream::OnStartOfCodedFrameGroup( | 194 void SourceBufferStream::OnStartOfCodedFrameGroup( |
195 DecodeTimestamp coded_frame_group_start_time) { | 195 DecodeTimestamp coded_frame_group_start_time) { |
196 DVLOG(1) << __FUNCTION__ << " " << GetStreamTypeName() << " (" | 196 DVLOG(1) << __FUNCTION__ << " " << GetStreamTypeName() << " (" |
197 << coded_frame_group_start_time.InSecondsF() << ")"; | 197 << coded_frame_group_start_time.InSecondsF() << ")"; |
198 DCHECK(!end_of_stream_); | 198 DCHECK(!end_of_stream_); |
199 coded_frame_group_start_time_ = coded_frame_group_start_time; | 199 coded_frame_group_start_time_ = coded_frame_group_start_time; |
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 last_appended_buffer_timestamp_ = kNoDecodeTimestamp(); |
211 last_appended_buffer_duration_ = kNoTimestamp(); | 211 last_appended_buffer_duration_ = kNoTimestamp; |
212 last_appended_buffer_is_keyframe_ = false; | 212 last_appended_buffer_is_keyframe_ = false; |
213 DVLOG(3) << __FUNCTION__ << " next appended buffers will " | 213 DVLOG(3) << __FUNCTION__ << " next appended buffers will " |
214 << (range_for_next_append_ == ranges_.end() | 214 << (range_for_next_append_ == ranges_.end() |
215 ? "be in a new range" | 215 ? "be in a new range" |
216 : "overlap an existing range"); | 216 : "overlap an existing range"); |
217 } else if (last_range != ranges_.end()) { | 217 } else if (last_range != ranges_.end()) { |
218 DCHECK(last_range == range_for_next_append_); | 218 DCHECK(last_range == range_for_next_append_); |
219 DVLOG(3) << __FUNCTION__ << " next appended buffers will continue range " | 219 DVLOG(3) << __FUNCTION__ << " next appended buffers will continue range " |
220 << "unless intervening remove makes discontinuity"; | 220 << "unless intervening remove makes discontinuity"; |
221 } | 221 } |
(...skipping 172 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
394 } | 394 } |
395 | 395 |
396 void SourceBufferStream::Remove(base::TimeDelta start, base::TimeDelta end, | 396 void SourceBufferStream::Remove(base::TimeDelta start, base::TimeDelta end, |
397 base::TimeDelta duration) { | 397 base::TimeDelta duration) { |
398 DVLOG(1) << __FUNCTION__ << " " << GetStreamTypeName() | 398 DVLOG(1) << __FUNCTION__ << " " << GetStreamTypeName() |
399 << " (" << start.InSecondsF() << ", " << end.InSecondsF() | 399 << " (" << start.InSecondsF() << ", " << end.InSecondsF() |
400 << ", " << duration.InSecondsF() << ")"; | 400 << ", " << duration.InSecondsF() << ")"; |
401 DCHECK(start >= base::TimeDelta()) << start.InSecondsF(); | 401 DCHECK(start >= base::TimeDelta()) << start.InSecondsF(); |
402 DCHECK(start < end) << "start " << start.InSecondsF() | 402 DCHECK(start < end) << "start " << start.InSecondsF() |
403 << " end " << end.InSecondsF(); | 403 << " end " << end.InSecondsF(); |
404 DCHECK(duration != kNoTimestamp()); | 404 DCHECK(duration != kNoTimestamp); |
405 | 405 |
406 DecodeTimestamp start_dts = DecodeTimestamp::FromPresentationTime(start); | 406 DecodeTimestamp start_dts = DecodeTimestamp::FromPresentationTime(start); |
407 DecodeTimestamp end_dts = DecodeTimestamp::FromPresentationTime(end); | 407 DecodeTimestamp end_dts = DecodeTimestamp::FromPresentationTime(end); |
408 DecodeTimestamp remove_end_timestamp = | 408 DecodeTimestamp remove_end_timestamp = |
409 DecodeTimestamp::FromPresentationTime(duration); | 409 DecodeTimestamp::FromPresentationTime(duration); |
410 DecodeTimestamp keyframe_timestamp = FindKeyframeAfterTimestamp(end_dts); | 410 DecodeTimestamp keyframe_timestamp = FindKeyframeAfterTimestamp(end_dts); |
411 if (keyframe_timestamp != kNoDecodeTimestamp()) { | 411 if (keyframe_timestamp != kNoDecodeTimestamp()) { |
412 remove_end_timestamp = keyframe_timestamp; | 412 remove_end_timestamp = keyframe_timestamp; |
413 } else if (end_dts < remove_end_timestamp) { | 413 } else if (end_dts < remove_end_timestamp) { |
414 remove_end_timestamp = end_dts; | 414 remove_end_timestamp = end_dts; |
(...skipping 218 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
633 | 633 |
634 base::TimeDelta interbuffer_distance = (*itr)->duration(); | 634 base::TimeDelta interbuffer_distance = (*itr)->duration(); |
635 DCHECK(interbuffer_distance >= base::TimeDelta()); | 635 DCHECK(interbuffer_distance >= base::TimeDelta()); |
636 | 636 |
637 if (prev_timestamp != kNoDecodeTimestamp()) { | 637 if (prev_timestamp != kNoDecodeTimestamp()) { |
638 interbuffer_distance = | 638 interbuffer_distance = |
639 std::max(current_timestamp - prev_timestamp, interbuffer_distance); | 639 std::max(current_timestamp - prev_timestamp, interbuffer_distance); |
640 } | 640 } |
641 | 641 |
642 if (interbuffer_distance > base::TimeDelta()) { | 642 if (interbuffer_distance > base::TimeDelta()) { |
643 if (max_interbuffer_distance_ == kNoTimestamp()) { | 643 if (max_interbuffer_distance_ == kNoTimestamp) { |
644 max_interbuffer_distance_ = interbuffer_distance; | 644 max_interbuffer_distance_ = interbuffer_distance; |
645 } else { | 645 } else { |
646 max_interbuffer_distance_ = | 646 max_interbuffer_distance_ = |
647 std::max(max_interbuffer_distance_, interbuffer_distance); | 647 std::max(max_interbuffer_distance_, interbuffer_distance); |
648 } | 648 } |
649 } | 649 } |
650 prev_timestamp = current_timestamp; | 650 prev_timestamp = current_timestamp; |
651 } | 651 } |
652 } | 652 } |
653 | 653 |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
715 << "] clamping media_time to be " | 715 << "] clamping media_time to be " |
716 << selected_buffered_end.InSecondsF(); | 716 << selected_buffered_end.InSecondsF(); |
717 media_time = selected_buffered_end; | 717 media_time = selected_buffered_end; |
718 } | 718 } |
719 | 719 |
720 size_t bytes_freed = 0; | 720 size_t bytes_freed = 0; |
721 | 721 |
722 // If last appended buffer position was earlier than the current playback time | 722 // If last appended buffer position was earlier than the current playback time |
723 // then try deleting data between last append and current media_time. | 723 // then try deleting data between last append and current media_time. |
724 if (last_appended_buffer_timestamp_ != kNoDecodeTimestamp() && | 724 if (last_appended_buffer_timestamp_ != kNoDecodeTimestamp() && |
725 last_appended_buffer_duration_ != kNoTimestamp() && | 725 last_appended_buffer_duration_ != kNoTimestamp && |
726 media_time > | 726 media_time > |
727 last_appended_buffer_timestamp_ + last_appended_buffer_duration_) { | 727 last_appended_buffer_timestamp_ + last_appended_buffer_duration_) { |
728 size_t between = FreeBuffersAfterLastAppended(bytes_to_free, media_time); | 728 size_t between = FreeBuffersAfterLastAppended(bytes_to_free, media_time); |
729 DVLOG(3) << __FUNCTION__ << " FreeBuffersAfterLastAppended " | 729 DVLOG(3) << __FUNCTION__ << " FreeBuffersAfterLastAppended " |
730 << " released " << between << " bytes" | 730 << " released " << between << " bytes" |
731 << " ranges_=" << RangesToString(ranges_); | 731 << " ranges_=" << RangesToString(ranges_); |
732 bytes_freed += between; | 732 bytes_freed += between; |
733 | 733 |
734 // Some players start appending data at the new seek target position before | 734 // Some players start appending data at the new seek target position before |
735 // actually initiating the seek operation (i.e. they try to improve seek | 735 // actually initiating the seek operation (i.e. they try to improve seek |
(...skipping 272 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1008 // was generated. | 1008 // was generated. |
1009 DCHECK(coded_frame_group_start_time_ != kNoDecodeTimestamp()); | 1009 DCHECK(coded_frame_group_start_time_ != kNoDecodeTimestamp()); |
1010 start = std::min(coded_frame_group_start_time_, start); | 1010 start = std::min(coded_frame_group_start_time_, start); |
1011 } | 1011 } |
1012 DecodeTimestamp end = new_buffers.back()->GetDecodeTimestamp(); | 1012 DecodeTimestamp end = new_buffers.back()->GetDecodeTimestamp(); |
1013 base::TimeDelta duration = new_buffers.back()->duration(); | 1013 base::TimeDelta duration = new_buffers.back()->duration(); |
1014 | 1014 |
1015 // Set end time for remove to include the duration of last buffer. If the | 1015 // Set end time for remove to include the duration of last buffer. If the |
1016 // duration is estimated, use 1 microsecond instead to ensure frames are not | 1016 // duration is estimated, use 1 microsecond instead to ensure frames are not |
1017 // accidentally removed due to over-estimation. | 1017 // accidentally removed due to over-estimation. |
1018 if (duration != kNoTimestamp() && duration > base::TimeDelta() && | 1018 if (duration != kNoTimestamp && duration > base::TimeDelta() && |
1019 !new_buffers.back()->is_duration_estimated()) { | 1019 !new_buffers.back()->is_duration_estimated()) { |
1020 end += duration; | 1020 end += duration; |
1021 } else { | 1021 } else { |
1022 // TODO(chcunningham): Emit warning when 0ms durations are not expected. | 1022 // TODO(chcunningham): Emit warning when 0ms durations are not expected. |
1023 // http://crbug.com/312836 | 1023 // http://crbug.com/312836 |
1024 end += base::TimeDelta::FromInternalValue(1); | 1024 end += base::TimeDelta::FromInternalValue(1); |
1025 } | 1025 } |
1026 | 1026 |
1027 RemoveInternal(start, end, exclude_start, deleted_buffers); | 1027 RemoveInternal(start, end, exclude_start, deleted_buffers); |
1028 } | 1028 } |
(...skipping 188 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1217 DVLOG(1) << "Config change (forced for fade in of splice frame)."; | 1217 DVLOG(1) << "Config change (forced for fade in of splice frame)."; |
1218 return SourceBufferStream::kConfigChange; | 1218 return SourceBufferStream::kConfigChange; |
1219 } | 1219 } |
1220 | 1220 |
1221 // All pre-splice buffers have been handed out and a config change completed, | 1221 // All pre-splice buffers have been handed out and a config change completed, |
1222 // so hand out the final buffer for fade in. Because a config change is | 1222 // so hand out the final buffer for fade in. Because a config change is |
1223 // always issued prior to handing out this buffer, any changes in config id | 1223 // always issued prior to handing out this buffer, any changes in config id |
1224 // have been inherently handled. | 1224 // have been inherently handled. |
1225 DCHECK(pending_buffers_complete_); | 1225 DCHECK(pending_buffers_complete_); |
1226 DCHECK_EQ(splice_buffers_index_, splice_buffers.size() - 1); | 1226 DCHECK_EQ(splice_buffers_index_, splice_buffers.size() - 1); |
1227 DCHECK(splice_buffers.back()->splice_timestamp() == kNoTimestamp()); | 1227 DCHECK(splice_buffers.back()->splice_timestamp() == kNoTimestamp); |
1228 *out_buffer = splice_buffers.back(); | 1228 *out_buffer = splice_buffers.back(); |
1229 pending_buffer_ = NULL; | 1229 pending_buffer_ = NULL; |
1230 | 1230 |
1231 // If the last splice buffer has preroll, hand off to the preroll handler. | 1231 // If the last splice buffer has preroll, hand off to the preroll handler. |
1232 return SetPendingBuffer(out_buffer) ? HandleNextBufferWithPreroll(out_buffer) | 1232 return SetPendingBuffer(out_buffer) ? HandleNextBufferWithPreroll(out_buffer) |
1233 : SourceBufferStream::kSuccess; | 1233 : SourceBufferStream::kSuccess; |
1234 } | 1234 } |
1235 | 1235 |
1236 SourceBufferStream::Status SourceBufferStream::HandleNextBufferWithPreroll( | 1236 SourceBufferStream::Status SourceBufferStream::HandleNextBufferWithPreroll( |
1237 scoped_refptr<StreamParserBuffer>* out_buffer) { | 1237 scoped_refptr<StreamParserBuffer>* out_buffer) { |
(...skipping 225 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1463 if (config_change_pending_) | 1463 if (config_change_pending_) |
1464 CompleteConfigChange(); | 1464 CompleteConfigChange(); |
1465 return video_configs_[current_config_index_]; | 1465 return video_configs_[current_config_index_]; |
1466 } | 1466 } |
1467 | 1467 |
1468 const TextTrackConfig& SourceBufferStream::GetCurrentTextTrackConfig() { | 1468 const TextTrackConfig& SourceBufferStream::GetCurrentTextTrackConfig() { |
1469 return text_track_config_; | 1469 return text_track_config_; |
1470 } | 1470 } |
1471 | 1471 |
1472 base::TimeDelta SourceBufferStream::GetMaxInterbufferDistance() const { | 1472 base::TimeDelta SourceBufferStream::GetMaxInterbufferDistance() const { |
1473 if (max_interbuffer_distance_ == kNoTimestamp()) | 1473 if (max_interbuffer_distance_ == kNoTimestamp) |
1474 return base::TimeDelta::FromMilliseconds(kDefaultBufferDurationInMs); | 1474 return base::TimeDelta::FromMilliseconds(kDefaultBufferDurationInMs); |
1475 return max_interbuffer_distance_; | 1475 return max_interbuffer_distance_; |
1476 } | 1476 } |
1477 | 1477 |
1478 bool SourceBufferStream::UpdateAudioConfig(const AudioDecoderConfig& config) { | 1478 bool SourceBufferStream::UpdateAudioConfig(const AudioDecoderConfig& config) { |
1479 DCHECK(!audio_configs_.empty()); | 1479 DCHECK(!audio_configs_.empty()); |
1480 DCHECK(video_configs_.empty()); | 1480 DCHECK(video_configs_.empty()); |
1481 DVLOG(3) << "UpdateAudioConfig."; | 1481 DVLOG(3) << "UpdateAudioConfig."; |
1482 | 1482 |
1483 if (audio_configs_[0].codec() != config.codec()) { | 1483 if (audio_configs_[0].codec() != config.codec()) { |
(...skipping 329 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1813 return false; | 1813 return false; |
1814 | 1814 |
1815 DCHECK_NE(have_splice_buffers, have_preroll_buffer); | 1815 DCHECK_NE(have_splice_buffers, have_preroll_buffer); |
1816 splice_buffers_index_ = 0; | 1816 splice_buffers_index_ = 0; |
1817 pending_buffer_.swap(*out_buffer); | 1817 pending_buffer_.swap(*out_buffer); |
1818 pending_buffers_complete_ = false; | 1818 pending_buffers_complete_ = false; |
1819 return true; | 1819 return true; |
1820 } | 1820 } |
1821 | 1821 |
1822 } // namespace media | 1822 } // namespace media |
OLD | NEW |