Index: media/filters/source_buffer_stream.cc |
diff --git a/media/filters/source_buffer_stream.cc b/media/filters/source_buffer_stream.cc |
index d20969f00c96c81089b8a94436700cf6aee9c5bf..32328dac273365b359f53ed1b401a6b95f4e45e9 100644 |
--- a/media/filters/source_buffer_stream.cc |
+++ b/media/filters/source_buffer_stream.cc |
@@ -17,10 +17,24 @@ |
namespace media { |
+namespace { |
+ |
+enum { |
+ // An arbitrarily-chosen number to estimate the duration of a buffer if none |
+ // is set and there's not enough information to get a better estimate. |
+ kDefaultBufferDurationInMs = 125, |
+ |
+ // Limit the number of MEDIA_LOG() logs for splice buffer generation warnings |
+ // and successes. Though these values are high enough to possibly exhaust the |
+ // media internals event cache (along with other events), these logs are |
+ // important for debugging splice generation. |
+ kMaxSpliceGenerationWarningLogs = 50, |
+ kMaxSpliceGenerationSuccessLogs = 20, |
+}; |
+ |
// Helper method that returns true if |ranges| is sorted in increasing order, |
// false otherwise. |
-static bool IsRangeListSorted( |
- const std::list<media::SourceBufferRange*>& ranges) { |
+bool IsRangeListSorted(const std::list<media::SourceBufferRange*>& ranges) { |
DecodeTimestamp prev = kNoDecodeTimestamp(); |
for (std::list<SourceBufferRange*>::const_iterator itr = |
ranges.begin(); itr != ranges.end(); ++itr) { |
@@ -39,25 +53,21 @@ static bool IsRangeListSorted( |
// instead of an overall maximum interbuffer delta for range discontinuity |
// detection, and adjust similarly for splice frame discontinuity detection. |
// See http://crbug.com/351489 and http://crbug.com/351166. |
-static base::TimeDelta ComputeFudgeRoom(base::TimeDelta approximate_duration) { |
+base::TimeDelta ComputeFudgeRoom(base::TimeDelta approximate_duration) { |
// Because we do not know exactly when is the next timestamp, any buffer |
// that starts within 2x the approximate duration of a buffer is considered |
// within this range. |
return 2 * approximate_duration; |
} |
-// An arbitrarily-chosen number to estimate the duration of a buffer if none |
-// is set and there's not enough information to get a better estimate. |
-static int kDefaultBufferDurationInMs = 125; |
- |
// The amount of time the beginning of the buffered data can differ from the |
// start time in order to still be considered the start of stream. |
-static base::TimeDelta kSeekToStartFudgeRoom() { |
+base::TimeDelta kSeekToStartFudgeRoom() { |
return base::TimeDelta::FromMilliseconds(1000); |
} |
// Helper method for logging, converts a range into a readable string. |
-static std::string RangeToString(const SourceBufferRange& range) { |
+std::string RangeToString(const SourceBufferRange& range) { |
std::stringstream ss; |
ss << "[" << range.GetStartTimestamp().InSecondsF() |
<< ";" << range.GetEndTimestamp().InSecondsF() |
@@ -66,7 +76,7 @@ static std::string RangeToString(const SourceBufferRange& range) { |
} |
// Helper method for logging, converts a set of ranges into a readable string. |
-static std::string RangesToString(const SourceBufferStream::RangeList& ranges) { |
+std::string RangesToString(const SourceBufferStream::RangeList& ranges) { |
if (ranges.empty()) |
return "<EMPTY>"; |
@@ -79,8 +89,7 @@ static std::string RangesToString(const SourceBufferStream::RangeList& ranges) { |
return ss.str(); |
} |
-static SourceBufferRange::GapPolicy TypeToGapPolicy( |
- SourceBufferStream::Type type) { |
+SourceBufferRange::GapPolicy TypeToGapPolicy(SourceBufferStream::Type type) { |
switch (type) { |
case SourceBufferStream::kAudio: |
case SourceBufferStream::kVideo: |
@@ -93,6 +102,8 @@ static SourceBufferRange::GapPolicy TypeToGapPolicy( |
return SourceBufferRange::NO_GAPS_ALLOWED; |
} |
+} // namespace |
+ |
SourceBufferStream::SourceBufferStream(const AudioDecoderConfig& audio_config, |
const scoped_refptr<MediaLog>& media_log, |
bool splice_frames_enabled) |
@@ -114,7 +125,9 @@ SourceBufferStream::SourceBufferStream(const AudioDecoderConfig& audio_config, |
config_change_pending_(false), |
splice_buffers_index_(0), |
pending_buffers_complete_(false), |
- splice_frames_enabled_(splice_frames_enabled) { |
+ splice_frames_enabled_(splice_frames_enabled), |
+ num_splice_generation_warning_logs_(0), |
+ num_splice_generation_success_logs_(0) { |
DCHECK(audio_config.IsValidConfig()); |
audio_configs_.push_back(audio_config); |
} |
@@ -140,7 +153,9 @@ SourceBufferStream::SourceBufferStream(const VideoDecoderConfig& video_config, |
config_change_pending_(false), |
splice_buffers_index_(0), |
pending_buffers_complete_(false), |
- splice_frames_enabled_(splice_frames_enabled) { |
+ splice_frames_enabled_(splice_frames_enabled), |
+ num_splice_generation_warning_logs_(0), |
+ num_splice_generation_success_logs_(0) { |
DCHECK(video_config.IsValidConfig()); |
video_configs_.push_back(video_config); |
} |
@@ -167,8 +182,9 @@ SourceBufferStream::SourceBufferStream(const TextTrackConfig& text_config, |
config_change_pending_(false), |
splice_buffers_index_(0), |
pending_buffers_complete_(false), |
- splice_frames_enabled_(splice_frames_enabled) { |
-} |
+ splice_frames_enabled_(splice_frames_enabled), |
+ num_splice_generation_warning_logs_(0), |
+ num_splice_generation_success_logs_(0) {} |
SourceBufferStream::~SourceBufferStream() { |
while (!ranges_.empty()) { |
@@ -1548,8 +1564,17 @@ void SourceBufferStream::GenerateSpliceFrame(const BufferQueue& new_buffers) { |
// |
// We also do not want to generate splices if the first new buffer replaces an |
// existing buffer exactly. |
- if (pre_splice_buffers.front()->timestamp() >= splice_timestamp) |
+ if (pre_splice_buffers.front()->timestamp() >= splice_timestamp) { |
+ LIMITED_MEDIA_LOG(DEBUG, media_log_, num_splice_generation_warning_logs_, |
+ kMaxSpliceGenerationWarningLogs) |
+ << "Skipping splice frame generation: first new buffer at " |
+ << splice_timestamp.InMicroseconds() |
+ << "us begins at or before existing buffer at " |
+ << pre_splice_buffers.front()->timestamp().InMicroseconds() << "us."; |
+ DVLOG(1) << "Skipping splice: overlapped buffers begin at or after the " |
+ "first new buffer."; |
return; |
+ } |
// If any |pre_splice_buffers| are already splices or preroll, do not generate |
// a splice. |
@@ -1557,12 +1582,22 @@ void SourceBufferStream::GenerateSpliceFrame(const BufferQueue& new_buffers) { |
const BufferQueue& original_splice_buffers = |
pre_splice_buffers[i]->splice_buffers(); |
if (!original_splice_buffers.empty()) { |
+ LIMITED_MEDIA_LOG(DEBUG, media_log_, num_splice_generation_warning_logs_, |
+ kMaxSpliceGenerationWarningLogs) |
+ << "Skipping splice frame generation: overlapped buffers at " |
+ << pre_splice_buffers[i]->timestamp().InMicroseconds() |
+ << "us are in a previously buffered splice."; |
DVLOG(1) << "Can't generate splice: overlapped buffers contain a " |
"pre-existing splice."; |
return; |
} |
if (pre_splice_buffers[i]->preroll_buffer().get()) { |
+ LIMITED_MEDIA_LOG(DEBUG, media_log_, num_splice_generation_warning_logs_, |
+ kMaxSpliceGenerationWarningLogs) |
+ << "Skipping splice frame generation: overlapped buffers at " |
+ << pre_splice_buffers[i]->timestamp().InMicroseconds() |
+ << "us contain preroll."; |
DVLOG(1) << "Can't generate splice: overlapped buffers contain preroll."; |
return; |
} |
@@ -1570,7 +1605,7 @@ void SourceBufferStream::GenerateSpliceFrame(const BufferQueue& new_buffers) { |
// Don't generate splice frames which represent less than a millisecond (which |
// is frequently the extent of timestamp resolution for poorly encoded media) |
- // or less than two frames (need at least two to crossfade). |
+ // or less than two samples (need at least two to crossfade). |
const base::TimeDelta splice_duration = |
pre_splice_buffers.back()->timestamp() + |
pre_splice_buffers.back()->duration() - splice_timestamp; |
@@ -1579,15 +1614,27 @@ void SourceBufferStream::GenerateSpliceFrame(const BufferQueue& new_buffers) { |
base::TimeDelta::FromSecondsD( |
2.0 / audio_configs_[append_config_index_].samples_per_second())); |
if (splice_duration < minimum_splice_duration) { |
+ LIMITED_MEDIA_LOG(DEBUG, media_log_, num_splice_generation_warning_logs_, |
+ kMaxSpliceGenerationWarningLogs) |
+ << "Skipping splice frame generation: not enough samples for splicing " |
+ "new buffer at " |
+ << splice_timestamp.InMicroseconds() << "us. Have " |
+ << splice_duration.InMicroseconds() << "us, but need " |
+ << minimum_splice_duration.InMicroseconds() << "us."; |
DVLOG(1) << "Can't generate splice: not enough samples for crossfade; have " |
- << splice_duration.InMicroseconds() << " us, but need " |
- << minimum_splice_duration.InMicroseconds() << " us."; |
+ << splice_duration.InMicroseconds() << "us, but need " |
+ << minimum_splice_duration.InMicroseconds() << "us."; |
return; |
} |
DVLOG(1) << "Generating splice frame @ " << new_buffers.front()->timestamp() |
<< ", splice duration: " << splice_duration.InMicroseconds() |
<< " us"; |
+ LIMITED_MEDIA_LOG(DEBUG, media_log_, num_splice_generation_success_logs_, |
+ kMaxSpliceGenerationSuccessLogs) |
+ << "Generated splice of overlap duration " |
+ << splice_duration.InMicroseconds() << "us into new buffer at " |
+ << splice_timestamp.InMicroseconds() << "us."; |
new_buffers.front()->ConvertToSpliceBuffer(pre_splice_buffers); |
} |