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