Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(123)

Side by Side Diff: media/filters/source_buffer_stream.cc

Issue 1281113002: MSE: Warn when keyframe after track_buffer is significantly in future (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 5 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « media/filters/source_buffer_stream.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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 };
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;
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after
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
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 570 matching lines...) Expand 10 before | Expand all | Expand 10 after
1116 pending_buffer_ = NULL; 1126 pending_buffer_ = NULL;
1117 return SourceBufferStream::kSuccess; 1127 return SourceBufferStream::kSuccess;
1118 } 1128 }
1119 1129
1120 SourceBufferStream::Status SourceBufferStream::GetNextBufferInternal( 1130 SourceBufferStream::Status SourceBufferStream::GetNextBufferInternal(
1121 scoped_refptr<StreamParserBuffer>* out_buffer) { 1131 scoped_refptr<StreamParserBuffer>* out_buffer) {
1122 CHECK(!config_change_pending_); 1132 CHECK(!config_change_pending_);
1123 1133
1124 if (!track_buffer_.empty()) { 1134 if (!track_buffer_.empty()) {
1125 DCHECK(!selected_range_); 1135 DCHECK(!selected_range_);
1136 DCHECK(!just_exhausted_track_buffer_);
wolenetz 2015/08/08 00:51:35 I could think of no scenario where we exhaust trac
chcunningham 2015/08/10 18:02:18 What if we encounter this sequence: 1. Overlapped
wolenetz 2015/08/10 20:14:43 While I had thought bullet #3 shouldn't put anythi
wolenetz 2015/08/10 21:56:29 DCHECK was indeed possible. Removed.
1126 scoped_refptr<StreamParserBuffer>& next_buffer = track_buffer_.front(); 1137 scoped_refptr<StreamParserBuffer>& next_buffer = track_buffer_.front();
1127 1138
1128 // If the next buffer is an audio splice frame, the next effective config id 1139 // If the next buffer is an audio splice frame, the next effective config id
1129 // comes from the first splice buffer. 1140 // comes from the first splice buffer.
1130 if (next_buffer->GetSpliceBufferConfigId(0) != current_config_index_) { 1141 if (next_buffer->GetSpliceBufferConfigId(0) != current_config_index_) {
1131 config_change_pending_ = true; 1142 config_change_pending_ = true;
1132 DVLOG(1) << "Config change (track buffer config ID does not match)."; 1143 DVLOG(1) << "Config change (track buffer config ID does not match).";
1133 return kConfigChange; 1144 return kConfigChange;
1134 } 1145 }
1135 1146
1136 DVLOG(3) << __FUNCTION__ << " Next buffer coming from track_buffer_"; 1147 DVLOG(3) << __FUNCTION__ << " Next buffer coming from track_buffer_";
1137 *out_buffer = next_buffer; 1148 *out_buffer = next_buffer;
1138 track_buffer_.pop_front(); 1149 track_buffer_.pop_front();
1139 last_output_buffer_timestamp_ = (*out_buffer)->GetDecodeTimestamp(); 1150 last_output_buffer_timestamp_ = (*out_buffer)->GetDecodeTimestamp();
1140 1151
1141 // If the track buffer becomes empty, then try to set the selected range 1152 // If the track buffer becomes empty, then try to set the selected range
1142 // based on the timestamp of this buffer being returned. 1153 // based on the timestamp of this buffer being returned.
1143 if (track_buffer_.empty()) 1154 if (track_buffer_.empty()) {
1155 just_exhausted_track_buffer_ = true;
1144 SetSelectedRangeIfNeeded(last_output_buffer_timestamp_); 1156 SetSelectedRangeIfNeeded(last_output_buffer_timestamp_);
1157 }
1145 1158
1146 return kSuccess; 1159 return kSuccess;
1147 } 1160 }
1148 1161
1149 DCHECK(track_buffer_.empty()); 1162 DCHECK(track_buffer_.empty());
1150 if (!selected_range_ || !selected_range_->HasNextBuffer()) { 1163 if (!selected_range_ || !selected_range_->HasNextBuffer()) {
1151 if (IsEndOfStreamReached()) { 1164 if (IsEndOfStreamReached()) {
chcunningham 2015/08/10 18:02:18 Random out of scope question: I'm just reading the
wolenetz 2015/08/10 20:14:43 I think IsEndOfStreamReached's name is perhaps con
1152 return kEndOfStream; 1165 return kEndOfStream;
1153 } 1166 }
1154 DVLOG(3) << __FUNCTION__ << " " << GetStreamTypeName() 1167 DVLOG(3) << __FUNCTION__ << " " << GetStreamTypeName()
1155 << ": returning kNeedBuffer " 1168 << ": returning kNeedBuffer "
1156 << (selected_range_ ? "(selected range has no next buffer)" 1169 << (selected_range_ ? "(selected range has no next buffer)"
1157 : "(no selected range)"); 1170 : "(no selected range)");
1158 return kNeedBuffer; 1171 return kNeedBuffer;
1159 } 1172 }
1160 1173
1161 if (selected_range_->GetNextConfigId() != current_config_index_) { 1174 if (selected_range_->GetNextConfigId() != current_config_index_) {
1162 config_change_pending_ = true; 1175 config_change_pending_ = true;
1163 DVLOG(1) << "Config change (selected range config ID does not match)."; 1176 DVLOG(1) << "Config change (selected range config ID does not match).";
1164 return kConfigChange; 1177 return kConfigChange;
1165 } 1178 }
1166 1179
1167 CHECK(selected_range_->GetNextBuffer(out_buffer)); 1180 CHECK(selected_range_->GetNextBuffer(out_buffer));
1181
1182 DecodeTimestamp next_output_buffer_timestamp =
1183 (*out_buffer)->GetDecodeTimestamp();
1184 if (just_exhausted_track_buffer_) {
1185 DCHECK((*out_buffer)->is_key_frame());
1186 just_exhausted_track_buffer_ = false;
1187 base::TimeDelta delta =
1188 next_output_buffer_timestamp - last_output_buffer_timestamp_;
1189 DCHECK_GE(delta, base::TimeDelta());
1190 if (delta > GetMaxInterbufferDistance()) {
1191 LIMITED_MEDIA_LOG(DEBUG, media_log_, num_track_buffer_gap_warning_logs_,
1192 kMaxTrackBufferGapWarningLogs)
1193 << "Media append that overlapped current playback position caused "
1194 "time gap in playing "
1195 << GetStreamTypeName() << " stream because the next keyframe is "
1196 << delta.InMilliseconds() << "ms beyond last overlapped frame. Media "
1197 "may appear temporarily frozen.";
1198 }
1199 }
1200
1168 last_output_buffer_timestamp_ = (*out_buffer)->GetDecodeTimestamp(); 1201 last_output_buffer_timestamp_ = (*out_buffer)->GetDecodeTimestamp();
1169 return kSuccess; 1202 return kSuccess;
1170 } 1203 }
1171 1204
1172 DecodeTimestamp SourceBufferStream::GetNextBufferTimestamp() { 1205 DecodeTimestamp SourceBufferStream::GetNextBufferTimestamp() {
1173 if (!track_buffer_.empty()) 1206 if (!track_buffer_.empty())
1174 return track_buffer_.front()->GetDecodeTimestamp(); 1207 return track_buffer_.front()->GetDecodeTimestamp();
1175 1208
1176 if (!selected_range_) 1209 if (!selected_range_)
1177 return kNoDecodeTimestamp(); 1210 return kNoDecodeTimestamp();
(...skipping 489 matching lines...) Expand 10 before | Expand all | Expand 10 after
1667 return false; 1700 return false;
1668 1701
1669 DCHECK_NE(have_splice_buffers, have_preroll_buffer); 1702 DCHECK_NE(have_splice_buffers, have_preroll_buffer);
1670 splice_buffers_index_ = 0; 1703 splice_buffers_index_ = 0;
1671 pending_buffer_.swap(*out_buffer); 1704 pending_buffer_.swap(*out_buffer);
1672 pending_buffers_complete_ = false; 1705 pending_buffers_complete_ = false;
1673 return true; 1706 return true;
1674 } 1707 }
1675 1708
1676 } // namespace media 1709 } // namespace media
OLDNEW
« no previous file with comments | « media/filters/source_buffer_stream.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698