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 12 matching lines...) Expand all Loading... | |
| 23 // An arbitrarily-chosen number to estimate the duration of a buffer if none | 23 // An arbitrarily-chosen number to estimate the duration of a buffer if none |
| 24 // is set and there's not enough information to get a better estimate. | 24 // is set and there's not enough information to get a better estimate. |
| 25 kDefaultBufferDurationInMs = 125, | 25 kDefaultBufferDurationInMs = 125, |
| 26 | 26 |
| 27 // Limit the number of MEDIA_LOG() logs for splice buffer generation warnings | 27 // Limit the number of MEDIA_LOG() logs for splice buffer generation warnings |
| 28 // and successes. Though these values are high enough to possibly exhaust the | 28 // and successes. Though these values are high enough to possibly exhaust the |
| 29 // media internals event cache (along with other events), these logs are | 29 // media internals event cache (along with other events), these logs are |
| 30 // important for debugging splice generation. | 30 // important for debugging splice generation. |
| 31 kMaxSpliceGenerationWarningLogs = 50, | 31 kMaxSpliceGenerationWarningLogs = 50, |
| 32 kMaxSpliceGenerationSuccessLogs = 20, | 32 kMaxSpliceGenerationSuccessLogs = 20, |
| 33 | |
| 34 // Limit the number of MEDIA_LOG() logs for track buffer time gaps. | |
| 35 kMaxTrackBufferGapWarningLogs = 20, | |
| 33 }; | 36 }; |
|
xhwang
2015/08/10 23:51:08
nit: As discussed before, these could just be "con
wolenetz
2015/08/11 02:53:31
Oops! Done :)
| |
| 34 | 37 |
| 35 // Helper method that returns true if |ranges| is sorted in increasing order, | 38 // Helper method that returns true if |ranges| is sorted in increasing order, |
| 36 // false otherwise. | 39 // false otherwise. |
| 37 bool IsRangeListSorted(const std::list<media::SourceBufferRange*>& ranges) { | 40 bool IsRangeListSorted(const std::list<media::SourceBufferRange*>& ranges) { |
| 38 DecodeTimestamp prev = kNoDecodeTimestamp(); | 41 DecodeTimestamp prev = kNoDecodeTimestamp(); |
| 39 for (std::list<SourceBufferRange*>::const_iterator itr = | 42 for (std::list<SourceBufferRange*>::const_iterator itr = |
| 40 ranges.begin(); itr != ranges.end(); ++itr) { | 43 ranges.begin(); itr != ranges.end(); ++itr) { |
| 41 if (prev != kNoDecodeTimestamp() && prev >= (*itr)->GetStartTimestamp()) | 44 if (prev != kNoDecodeTimestamp() && prev >= (*itr)->GetStartTimestamp()) |
| 42 return false; | 45 return false; |
| 43 prev = (*itr)->GetEndTimestamp(); | 46 prev = (*itr)->GetEndTimestamp(); |
| (...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 127 SourceBufferStream::SourceBufferStream(const AudioDecoderConfig& audio_config, | 130 SourceBufferStream::SourceBufferStream(const AudioDecoderConfig& audio_config, |
| 128 const scoped_refptr<MediaLog>& media_log, | 131 const scoped_refptr<MediaLog>& media_log, |
| 129 bool splice_frames_enabled) | 132 bool splice_frames_enabled) |
| 130 : media_log_(media_log), | 133 : media_log_(media_log), |
| 131 current_config_index_(0), | 134 current_config_index_(0), |
| 132 append_config_index_(0), | 135 append_config_index_(0), |
| 133 seek_pending_(false), | 136 seek_pending_(false), |
| 134 end_of_stream_(false), | 137 end_of_stream_(false), |
| 135 seek_buffer_timestamp_(kNoTimestamp()), | 138 seek_buffer_timestamp_(kNoTimestamp()), |
| 136 selected_range_(NULL), | 139 selected_range_(NULL), |
| 140 just_exhausted_track_buffer_(false), | |
| 137 media_segment_start_time_(kNoDecodeTimestamp()), | 141 media_segment_start_time_(kNoDecodeTimestamp()), |
| 138 range_for_next_append_(ranges_.end()), | 142 range_for_next_append_(ranges_.end()), |
| 139 new_media_segment_(false), | 143 new_media_segment_(false), |
| 140 last_appended_buffer_timestamp_(kNoDecodeTimestamp()), | 144 last_appended_buffer_timestamp_(kNoDecodeTimestamp()), |
| 141 last_appended_buffer_is_keyframe_(false), | 145 last_appended_buffer_is_keyframe_(false), |
| 142 last_output_buffer_timestamp_(kNoDecodeTimestamp()), | 146 last_output_buffer_timestamp_(kNoDecodeTimestamp()), |
| 143 max_interbuffer_distance_(kNoTimestamp()), | 147 max_interbuffer_distance_(kNoTimestamp()), |
| 144 memory_limit_(kSourceBufferAudioMemoryLimit), | 148 memory_limit_(kSourceBufferAudioMemoryLimit), |
| 145 config_change_pending_(false), | 149 config_change_pending_(false), |
| 146 splice_buffers_index_(0), | 150 splice_buffers_index_(0), |
| 147 pending_buffers_complete_(false), | 151 pending_buffers_complete_(false), |
| 148 splice_frames_enabled_(splice_frames_enabled), | 152 splice_frames_enabled_(splice_frames_enabled), |
| 149 num_splice_generation_warning_logs_(0), | 153 num_splice_generation_warning_logs_(0), |
| 150 num_splice_generation_success_logs_(0) { | 154 num_splice_generation_success_logs_(0), |
| 155 num_track_buffer_gap_warning_logs_(0) { | |
| 151 DCHECK(audio_config.IsValidConfig()); | 156 DCHECK(audio_config.IsValidConfig()); |
| 152 audio_configs_.push_back(audio_config); | 157 audio_configs_.push_back(audio_config); |
| 153 } | 158 } |
| 154 | 159 |
| 155 SourceBufferStream::SourceBufferStream(const VideoDecoderConfig& video_config, | 160 SourceBufferStream::SourceBufferStream(const VideoDecoderConfig& video_config, |
| 156 const scoped_refptr<MediaLog>& media_log, | 161 const scoped_refptr<MediaLog>& media_log, |
| 157 bool splice_frames_enabled) | 162 bool splice_frames_enabled) |
| 158 : media_log_(media_log), | 163 : media_log_(media_log), |
| 159 current_config_index_(0), | 164 current_config_index_(0), |
| 160 append_config_index_(0), | 165 append_config_index_(0), |
| 161 seek_pending_(false), | 166 seek_pending_(false), |
| 162 end_of_stream_(false), | 167 end_of_stream_(false), |
| 163 seek_buffer_timestamp_(kNoTimestamp()), | 168 seek_buffer_timestamp_(kNoTimestamp()), |
| 164 selected_range_(NULL), | 169 selected_range_(NULL), |
| 170 just_exhausted_track_buffer_(false), | |
| 165 media_segment_start_time_(kNoDecodeTimestamp()), | 171 media_segment_start_time_(kNoDecodeTimestamp()), |
| 166 range_for_next_append_(ranges_.end()), | 172 range_for_next_append_(ranges_.end()), |
| 167 new_media_segment_(false), | 173 new_media_segment_(false), |
| 168 last_appended_buffer_timestamp_(kNoDecodeTimestamp()), | 174 last_appended_buffer_timestamp_(kNoDecodeTimestamp()), |
| 169 last_appended_buffer_is_keyframe_(false), | 175 last_appended_buffer_is_keyframe_(false), |
| 170 last_output_buffer_timestamp_(kNoDecodeTimestamp()), | 176 last_output_buffer_timestamp_(kNoDecodeTimestamp()), |
| 171 max_interbuffer_distance_(kNoTimestamp()), | 177 max_interbuffer_distance_(kNoTimestamp()), |
| 172 memory_limit_(kSourceBufferVideoMemoryLimit), | 178 memory_limit_(kSourceBufferVideoMemoryLimit), |
| 173 config_change_pending_(false), | 179 config_change_pending_(false), |
| 174 splice_buffers_index_(0), | 180 splice_buffers_index_(0), |
| 175 pending_buffers_complete_(false), | 181 pending_buffers_complete_(false), |
| 176 splice_frames_enabled_(splice_frames_enabled), | 182 splice_frames_enabled_(splice_frames_enabled), |
| 177 num_splice_generation_warning_logs_(0), | 183 num_splice_generation_warning_logs_(0), |
| 178 num_splice_generation_success_logs_(0) { | 184 num_splice_generation_success_logs_(0), |
| 185 num_track_buffer_gap_warning_logs_(0) { | |
| 179 DCHECK(video_config.IsValidConfig()); | 186 DCHECK(video_config.IsValidConfig()); |
| 180 video_configs_.push_back(video_config); | 187 video_configs_.push_back(video_config); |
| 181 } | 188 } |
| 182 | 189 |
| 183 SourceBufferStream::SourceBufferStream(const TextTrackConfig& text_config, | 190 SourceBufferStream::SourceBufferStream(const TextTrackConfig& text_config, |
| 184 const scoped_refptr<MediaLog>& media_log, | 191 const scoped_refptr<MediaLog>& media_log, |
| 185 bool splice_frames_enabled) | 192 bool splice_frames_enabled) |
| 186 : media_log_(media_log), | 193 : media_log_(media_log), |
| 187 current_config_index_(0), | 194 current_config_index_(0), |
| 188 append_config_index_(0), | 195 append_config_index_(0), |
| 189 text_track_config_(text_config), | 196 text_track_config_(text_config), |
| 190 seek_pending_(false), | 197 seek_pending_(false), |
| 191 end_of_stream_(false), | 198 end_of_stream_(false), |
| 192 seek_buffer_timestamp_(kNoTimestamp()), | 199 seek_buffer_timestamp_(kNoTimestamp()), |
| 193 selected_range_(NULL), | 200 selected_range_(NULL), |
| 201 just_exhausted_track_buffer_(false), | |
| 194 media_segment_start_time_(kNoDecodeTimestamp()), | 202 media_segment_start_time_(kNoDecodeTimestamp()), |
| 195 range_for_next_append_(ranges_.end()), | 203 range_for_next_append_(ranges_.end()), |
| 196 new_media_segment_(false), | 204 new_media_segment_(false), |
| 197 last_appended_buffer_timestamp_(kNoDecodeTimestamp()), | 205 last_appended_buffer_timestamp_(kNoDecodeTimestamp()), |
| 198 last_appended_buffer_is_keyframe_(false), | 206 last_appended_buffer_is_keyframe_(false), |
| 199 last_output_buffer_timestamp_(kNoDecodeTimestamp()), | 207 last_output_buffer_timestamp_(kNoDecodeTimestamp()), |
| 200 max_interbuffer_distance_(kNoTimestamp()), | 208 max_interbuffer_distance_(kNoTimestamp()), |
| 201 memory_limit_(kSourceBufferAudioMemoryLimit), | 209 memory_limit_(kSourceBufferAudioMemoryLimit), |
| 202 config_change_pending_(false), | 210 config_change_pending_(false), |
| 203 splice_buffers_index_(0), | 211 splice_buffers_index_(0), |
| 204 pending_buffers_complete_(false), | 212 pending_buffers_complete_(false), |
| 205 splice_frames_enabled_(splice_frames_enabled), | 213 splice_frames_enabled_(splice_frames_enabled), |
| 206 num_splice_generation_warning_logs_(0), | 214 num_splice_generation_warning_logs_(0), |
| 207 num_splice_generation_success_logs_(0) {} | 215 num_splice_generation_success_logs_(0), |
| 216 num_track_buffer_gap_warning_logs_(0) {} | |
| 208 | 217 |
| 209 SourceBufferStream::~SourceBufferStream() { | 218 SourceBufferStream::~SourceBufferStream() { |
| 210 while (!ranges_.empty()) { | 219 while (!ranges_.empty()) { |
| 211 delete ranges_.front(); | 220 delete ranges_.front(); |
| 212 ranges_.pop_front(); | 221 ranges_.pop_front(); |
| 213 } | 222 } |
| 214 } | 223 } |
| 215 | 224 |
| 216 void SourceBufferStream::OnNewMediaSegment( | 225 void SourceBufferStream::OnNewMediaSegment( |
| 217 DecodeTimestamp media_segment_start_time) { | 226 DecodeTimestamp media_segment_start_time) { |
| (...skipping 308 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 526 | 535 |
| 527 DCHECK(IsRangeListSorted(ranges_)); | 536 DCHECK(IsRangeListSorted(ranges_)); |
| 528 DCHECK(OnlySelectedRangeIsSeeked()); | 537 DCHECK(OnlySelectedRangeIsSeeked()); |
| 529 } | 538 } |
| 530 | 539 |
| 531 void SourceBufferStream::ResetSeekState() { | 540 void SourceBufferStream::ResetSeekState() { |
| 532 SetSelectedRange(NULL); | 541 SetSelectedRange(NULL); |
| 533 track_buffer_.clear(); | 542 track_buffer_.clear(); |
| 534 config_change_pending_ = false; | 543 config_change_pending_ = false; |
| 535 last_output_buffer_timestamp_ = kNoDecodeTimestamp(); | 544 last_output_buffer_timestamp_ = kNoDecodeTimestamp(); |
| 545 just_exhausted_track_buffer_ = false; | |
| 536 splice_buffers_index_ = 0; | 546 splice_buffers_index_ = 0; |
| 537 pending_buffer_ = NULL; | 547 pending_buffer_ = NULL; |
| 538 pending_buffers_complete_ = false; | 548 pending_buffers_complete_ = false; |
| 539 } | 549 } |
| 540 | 550 |
| 541 bool SourceBufferStream::ShouldSeekToStartOfBuffered( | 551 bool SourceBufferStream::ShouldSeekToStartOfBuffered( |
| 542 base::TimeDelta seek_timestamp) const { | 552 base::TimeDelta seek_timestamp) const { |
| 543 if (ranges_.empty()) | 553 if (ranges_.empty()) |
| 544 return false; | 554 return false; |
| 545 base::TimeDelta beginning_of_buffered = | 555 base::TimeDelta beginning_of_buffered = |
| (...skipping 587 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1133 return kConfigChange; | 1143 return kConfigChange; |
| 1134 } | 1144 } |
| 1135 | 1145 |
| 1136 DVLOG(3) << __FUNCTION__ << " Next buffer coming from track_buffer_"; | 1146 DVLOG(3) << __FUNCTION__ << " Next buffer coming from track_buffer_"; |
| 1137 *out_buffer = next_buffer; | 1147 *out_buffer = next_buffer; |
| 1138 track_buffer_.pop_front(); | 1148 track_buffer_.pop_front(); |
| 1139 last_output_buffer_timestamp_ = (*out_buffer)->GetDecodeTimestamp(); | 1149 last_output_buffer_timestamp_ = (*out_buffer)->GetDecodeTimestamp(); |
| 1140 | 1150 |
| 1141 // If the track buffer becomes empty, then try to set the selected range | 1151 // If the track buffer becomes empty, then try to set the selected range |
| 1142 // based on the timestamp of this buffer being returned. | 1152 // based on the timestamp of this buffer being returned. |
| 1143 if (track_buffer_.empty()) | 1153 if (track_buffer_.empty()) { |
| 1154 just_exhausted_track_buffer_ = true; | |
| 1144 SetSelectedRangeIfNeeded(last_output_buffer_timestamp_); | 1155 SetSelectedRangeIfNeeded(last_output_buffer_timestamp_); |
| 1156 } | |
| 1145 | 1157 |
| 1146 return kSuccess; | 1158 return kSuccess; |
| 1147 } | 1159 } |
| 1148 | 1160 |
| 1149 DCHECK(track_buffer_.empty()); | 1161 DCHECK(track_buffer_.empty()); |
| 1150 if (!selected_range_ || !selected_range_->HasNextBuffer()) { | 1162 if (!selected_range_ || !selected_range_->HasNextBuffer()) { |
| 1151 if (IsEndOfStreamReached()) { | 1163 if (IsEndOfStreamReached()) { |
| 1152 return kEndOfStream; | 1164 return kEndOfStream; |
| 1153 } | 1165 } |
| 1154 DVLOG(3) << __FUNCTION__ << " " << GetStreamTypeName() | 1166 DVLOG(3) << __FUNCTION__ << " " << GetStreamTypeName() |
| 1155 << ": returning kNeedBuffer " | 1167 << ": returning kNeedBuffer " |
| 1156 << (selected_range_ ? "(selected range has no next buffer)" | 1168 << (selected_range_ ? "(selected range has no next buffer)" |
| 1157 : "(no selected range)"); | 1169 : "(no selected range)"); |
| 1158 return kNeedBuffer; | 1170 return kNeedBuffer; |
| 1159 } | 1171 } |
| 1160 | 1172 |
| 1161 if (selected_range_->GetNextConfigId() != current_config_index_) { | 1173 if (selected_range_->GetNextConfigId() != current_config_index_) { |
| 1162 config_change_pending_ = true; | 1174 config_change_pending_ = true; |
| 1163 DVLOG(1) << "Config change (selected range config ID does not match)."; | 1175 DVLOG(1) << "Config change (selected range config ID does not match)."; |
| 1164 return kConfigChange; | 1176 return kConfigChange; |
| 1165 } | 1177 } |
| 1166 | 1178 |
| 1167 CHECK(selected_range_->GetNextBuffer(out_buffer)); | 1179 CHECK(selected_range_->GetNextBuffer(out_buffer)); |
| 1180 | |
| 1181 DecodeTimestamp next_output_buffer_timestamp = | |
| 1182 (*out_buffer)->GetDecodeTimestamp(); | |
| 1183 if (just_exhausted_track_buffer_) { | |
| 1184 DCHECK((*out_buffer)->is_key_frame()); | |
| 1185 just_exhausted_track_buffer_ = false; | |
| 1186 base::TimeDelta delta = | |
| 1187 next_output_buffer_timestamp - last_output_buffer_timestamp_; | |
| 1188 DCHECK_GE(delta, base::TimeDelta()); | |
| 1189 if (delta > GetMaxInterbufferDistance()) { | |
| 1190 LIMITED_MEDIA_LOG(DEBUG, media_log_, num_track_buffer_gap_warning_logs_, | |
| 1191 kMaxTrackBufferGapWarningLogs) | |
| 1192 << "Media append that overlapped current playback position caused " | |
| 1193 "time gap in playing " | |
| 1194 << GetStreamTypeName() << " stream because the next keyframe is " | |
| 1195 << delta.InMilliseconds() << "ms beyond last overlapped frame. Media " | |
| 1196 "may appear temporarily frozen."; | |
| 1197 } | |
| 1198 } | |
| 1199 | |
| 1168 last_output_buffer_timestamp_ = (*out_buffer)->GetDecodeTimestamp(); | 1200 last_output_buffer_timestamp_ = (*out_buffer)->GetDecodeTimestamp(); |
| 1169 return kSuccess; | 1201 return kSuccess; |
| 1170 } | 1202 } |
| 1171 | 1203 |
| 1172 DecodeTimestamp SourceBufferStream::GetNextBufferTimestamp() { | 1204 DecodeTimestamp SourceBufferStream::GetNextBufferTimestamp() { |
| 1173 if (!track_buffer_.empty()) | 1205 if (!track_buffer_.empty()) |
| 1174 return track_buffer_.front()->GetDecodeTimestamp(); | 1206 return track_buffer_.front()->GetDecodeTimestamp(); |
| 1175 | 1207 |
| 1176 if (!selected_range_) | 1208 if (!selected_range_) |
| 1177 return kNoDecodeTimestamp(); | 1209 return kNoDecodeTimestamp(); |
| (...skipping 489 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1667 return false; | 1699 return false; |
| 1668 | 1700 |
| 1669 DCHECK_NE(have_splice_buffers, have_preroll_buffer); | 1701 DCHECK_NE(have_splice_buffers, have_preroll_buffer); |
| 1670 splice_buffers_index_ = 0; | 1702 splice_buffers_index_ = 0; |
| 1671 pending_buffer_.swap(*out_buffer); | 1703 pending_buffer_.swap(*out_buffer); |
| 1672 pending_buffers_complete_ = false; | 1704 pending_buffers_complete_ = false; |
| 1673 return true; | 1705 return true; |
| 1674 } | 1706 } |
| 1675 | 1707 |
| 1676 } // namespace media | 1708 } // namespace media |
| OLD | NEW |