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 |