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

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: Fixes xhwang@'s nits 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
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
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698