Index: media/filters/source_buffer_stream.cc |
diff --git a/media/filters/source_buffer_stream.cc b/media/filters/source_buffer_stream.cc |
index 5fdc619bc896ef3e0bb9a4e599f26553d1982b8e..c0cb7ff6ef672b665059fb76501c1078cba6cc3e 100644 |
--- a/media/filters/source_buffer_stream.cc |
+++ b/media/filters/source_buffer_stream.cc |
@@ -7,11 +7,11 @@ |
#include <algorithm> |
#include <map> |
#include <sstream> |
+#include <string> |
#include "base/bind.h" |
#include "base/logging.h" |
#include "base/trace_event/trace_event.h" |
-#include "media/base/audio_splicer.h" |
#include "media/base/timestamp_constants.h" |
#include "media/filters/source_buffer_platform.h" |
#include "media/filters/source_buffer_range.h" |
@@ -24,19 +24,15 @@ namespace { |
// set and there's not enough information to get a better estimate. |
const int 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. |
-const int kMaxSpliceGenerationWarningLogs = 50; |
-const int kMaxSpliceGenerationSuccessLogs = 20; |
- |
// Limit the number of MEDIA_LOG() logs for track buffer time gaps. |
const int kMaxTrackBufferGapWarningLogs = 20; |
// Limit the number of MEDIA_LOG() logs for MSE GC algorithm warnings. |
const int kMaxGarbageCollectAlgorithmWarningLogs = 20; |
+// Limit the number of MEDIA_LOG() logs for splice overlap trimming. |
+const int kMaxAudioSpliceLogs = 20; |
+ |
// Limit the number of MEDIA_LOG() logs for same DTS for non-keyframe followed |
// by keyframe. Prior to relaxing the "media segments must begin with a |
// keyframe" requirement, we issued decode error for this situation. That was |
@@ -65,7 +61,7 @@ bool IsRangeListSorted(const std::list<media::SourceBufferRange*>& ranges) { |
// TODO(wolenetz): Once all stream parsers emit accurate frame durations, use |
// logic like FrameProcessor (2*last_frame_duration + last_decode_timestamp) |
// instead of an overall maximum interbuffer delta for range discontinuity |
-// detection, and adjust similarly for splice frame discontinuity detection. |
+// detection. |
// See http://crbug.com/351489 and http://crbug.com/351166. |
base::TimeDelta ComputeFudgeRoom(base::TimeDelta approximate_duration) { |
// Because we do not know exactly when is the next timestamp, any buffer |
@@ -142,38 +138,33 @@ SourceBufferRange::GapPolicy TypeToGapPolicy(SourceBufferStream::Type type) { |
} // namespace |
SourceBufferStream::SourceBufferStream(const AudioDecoderConfig& audio_config, |
- const scoped_refptr<MediaLog>& media_log, |
- bool splice_frames_enabled) |
+ const scoped_refptr<MediaLog>& media_log) |
: media_log_(media_log), |
seek_buffer_timestamp_(kNoTimestamp), |
coded_frame_group_start_time_(kNoDecodeTimestamp()), |
range_for_next_append_(ranges_.end()), |
last_output_buffer_timestamp_(kNoDecodeTimestamp()), |
max_interbuffer_distance_(kNoTimestamp), |
- memory_limit_(kSourceBufferAudioMemoryLimit), |
- splice_frames_enabled_(splice_frames_enabled) { |
+ memory_limit_(kSourceBufferAudioMemoryLimit) { |
DCHECK(audio_config.IsValidConfig()); |
audio_configs_.push_back(audio_config); |
} |
SourceBufferStream::SourceBufferStream(const VideoDecoderConfig& video_config, |
- const scoped_refptr<MediaLog>& media_log, |
- bool splice_frames_enabled) |
+ const scoped_refptr<MediaLog>& media_log) |
: media_log_(media_log), |
seek_buffer_timestamp_(kNoTimestamp), |
coded_frame_group_start_time_(kNoDecodeTimestamp()), |
range_for_next_append_(ranges_.end()), |
last_output_buffer_timestamp_(kNoDecodeTimestamp()), |
max_interbuffer_distance_(kNoTimestamp), |
- memory_limit_(kSourceBufferVideoMemoryLimit), |
- splice_frames_enabled_(splice_frames_enabled) { |
+ memory_limit_(kSourceBufferVideoMemoryLimit) { |
DCHECK(video_config.IsValidConfig()); |
video_configs_.push_back(video_config); |
} |
SourceBufferStream::SourceBufferStream(const TextTrackConfig& text_config, |
- const scoped_refptr<MediaLog>& media_log, |
- bool splice_frames_enabled) |
+ const scoped_refptr<MediaLog>& media_log) |
: media_log_(media_log), |
text_track_config_(text_config), |
seek_buffer_timestamp_(kNoTimestamp), |
@@ -181,8 +172,7 @@ SourceBufferStream::SourceBufferStream(const TextTrackConfig& text_config, |
range_for_next_append_(ranges_.end()), |
last_output_buffer_timestamp_(kNoDecodeTimestamp()), |
max_interbuffer_distance_(kNoTimestamp), |
- memory_limit_(kSourceBufferAudioMemoryLimit), |
- splice_frames_enabled_(splice_frames_enabled) {} |
+ memory_limit_(kSourceBufferAudioMemoryLimit) {} |
SourceBufferStream::~SourceBufferStream() { |
while (!ranges_.empty()) { |
@@ -263,18 +253,13 @@ bool SourceBufferStream::Append(const BufferQueue& buffers) { |
// If there's a range for |buffers|, insert |buffers| accordingly. Otherwise, |
// create a new range with |buffers|. |
if (range_for_next_append_ != ranges_.end()) { |
- if (new_coded_frame_group_ && (!splice_frames_enabled_ || |
- buffers.front()->splice_buffers().empty())) { |
+ if (new_coded_frame_group_) { |
// If the first append to this stream in a new coded frame group continues |
// a previous range, use the new group's start time instead of the first |
// new buffer's timestamp as the proof of adjacency to the existing range. |
// A large gap (larger than our normal buffer adjacency test) can occur in |
// a muxed set of streams (which share a common coded frame group start |
// time) with a significantly jagged start across the streams. |
- // Don't do this logic if there was a splice frame generated for the first |
- // new buffer, since splices are guaranteed to be in the same range and |
- // adjacent, and since the splice frame's timestamp can be less than |
- // |coded_frame_group_start_time_| due to the splicing. |
(*range_for_next_append_) |
->AppendBuffersToEnd(buffers, coded_frame_group_start_time_); |
} else { |
@@ -312,8 +297,8 @@ bool SourceBufferStream::Append(const BufferQueue& buffers) { |
last_appended_buffer_is_keyframe_ = buffers.back()->is_key_frame(); |
DVLOG(1) << __func__ << " " << GetStreamTypeName() |
<< ": new buffers in the middle of coded frame group depend on" |
- "keyframe that has been removed, and contain no keyframes." |
- "Skipping further processing."; |
+ " keyframe that has been removed, and contain no keyframes." |
+ " Skipping further processing."; |
DVLOG(1) << __func__ << " " << GetStreamTypeName() |
<< ": done. ranges_=" << RangesToString(ranges_); |
return true; |
@@ -603,7 +588,6 @@ void SourceBufferStream::ResetSeekState() { |
config_change_pending_ = false; |
last_output_buffer_timestamp_ = kNoDecodeTimestamp(); |
just_exhausted_track_buffer_ = false; |
- splice_buffers_index_ = 0; |
pending_buffer_ = NULL; |
pending_buffers_complete_ = false; |
} |
@@ -1019,51 +1003,141 @@ size_t SourceBufferStream::FreeBuffers(size_t total_bytes_to_free, |
return bytes_freed; |
} |
+void SourceBufferStream::TrimSpliceOverlap(const BufferQueue& new_buffers) { |
+ DCHECK(!new_buffers.empty()); |
+ DCHECK_EQ(kAudio, GetType()); |
+ |
+ // Find the overlapped range (if any). |
+ const base::TimeDelta splice_timestamp = new_buffers.front()->timestamp(); |
+ const DecodeTimestamp splice_dts = |
+ DecodeTimestamp::FromPresentationTime(splice_timestamp); |
+ RangeList::iterator range_itr = FindExistingRangeFor(splice_dts); |
+ if (range_itr == ranges_.end()) { |
+ DVLOG(3) << __func__ << " No splice trimming. No range overlap at time " |
+ << splice_timestamp.InMicroseconds(); |
+ return; |
+ } |
+ |
+ // Search for overlapped buffer needs exclusive end value. Choosing smallest |
+ // possible value. |
+ const DecodeTimestamp end_dts = |
+ splice_dts + base::TimeDelta::FromInternalValue(1); |
+ |
+ // Find if new buffer's start would overlap an existing buffer. |
+ BufferQueue overlapped_buffers; |
+ if (!(*range_itr) |
+ ->GetBuffersInRange(splice_dts, end_dts, &overlapped_buffers)) { |
+ // Bail if no overlapped buffers found. |
+ DVLOG(3) << __func__ << " No splice trimming. No buffer overlap at time " |
+ << splice_timestamp.InMicroseconds(); |
+ return; |
+ } |
+ |
+ // At most one buffer should exist containing the time of the newly appended |
+ // buffer's start. GetBuffersInRange does not currently return buffers with |
+ // zero duration. |
+ DCHECK_EQ(overlapped_buffers.size(), 1U) |
+ << __func__ << " Found more than one overlapped buffer"; |
+ StreamParserBuffer* overlapped_buffer = overlapped_buffers.front().get(); |
+ |
+ if (overlapped_buffer->timestamp() == splice_timestamp) { |
+ // Ignore buffers with the same start time. They will be completely removed |
+ // in PrepareRangesForNextAppend(). |
+ DVLOG(3) << __func__ << " No splice trimming at time " |
+ << splice_timestamp.InMicroseconds() |
+ << ". Overlapped buffer will be completely removed."; |
+ return; |
+ } |
+ |
+ // Determine the duration of overlap. |
+ base::TimeDelta overlapped_end_time = |
+ overlapped_buffer->timestamp() + overlapped_buffer->duration(); |
+ base::TimeDelta overlap_duration = overlapped_end_time - splice_timestamp; |
+ |
+ // At this point overlap should be non-empty (ruled out same-timestamp above). |
+ DCHECK_GT(overlap_duration, base::TimeDelta()); |
+ |
+ // Don't trim for overlaps of less than one millisecond (which is frequently |
+ // the extent of timestamp resolution for poorly encoded media). |
+ if (overlap_duration < base::TimeDelta::FromMilliseconds(1)) { |
+ std::stringstream log_string; |
+ log_string << "Skipping audio splice trimming at PTS=" |
+ << splice_timestamp.InMicroseconds() << "us. Found only " |
+ << overlap_duration.InMicroseconds() |
+ << "us of overlap, need at least 1000us. Multiple occurrences " |
+ << "may result in loss of A/V sync."; |
+ LIMITED_MEDIA_LOG(DEBUG, media_log_, num_splice_logs_, kMaxAudioSpliceLogs) |
+ << log_string.str(); |
+ DVLOG(1) << __func__ << log_string.str(); |
+ return; |
+ } |
+ |
+ // Trim overlap from the existing buffer. |
+ DecoderBuffer::DiscardPadding discard_padding = |
+ overlapped_buffer->discard_padding(); |
+ discard_padding.second += overlap_duration; |
+ overlapped_buffer->set_discard_padding(discard_padding); |
+ overlapped_buffer->set_duration(overlapped_buffer->duration() - |
+ overlap_duration); |
+ |
+ std::stringstream log_string; |
+ log_string << "Audio buffer splice at PTS=" |
+ << splice_timestamp.InMicroseconds() |
+ << "us. Trimmed tail of overlapped buffer (PTS=" |
+ << overlapped_buffer->timestamp().InMicroseconds() << "us) by " |
+ << overlap_duration.InMicroseconds() << "us."; |
+ LIMITED_MEDIA_LOG(DEBUG, media_log_, num_splice_logs_, kMaxAudioSpliceLogs) |
+ << log_string.str(); |
+ DVLOG(1) << __func__ << log_string.str(); |
+} |
+ |
void SourceBufferStream::PrepareRangesForNextAppend( |
const BufferQueue& new_buffers, BufferQueue* deleted_buffers) { |
DCHECK(deleted_buffers); |
- // Handle splices between the existing buffers and the new buffers. If a |
- // splice is generated the timestamp and duration of the first buffer in |
- // |new_buffers| will be modified. |
- if (splice_frames_enabled_) |
- GenerateSpliceFrame(new_buffers); |
+ if (GetType() == kAudio) |
+ TrimSpliceOverlap(new_buffers); |
+ base::TimeDelta prev_duration = last_appended_buffer_duration_; |
DecodeTimestamp prev_timestamp = last_appended_buffer_timestamp_; |
DecodeTimestamp next_timestamp = new_buffers.front()->GetDecodeTimestamp(); |
+ // 1. Clean up the old buffers between the last appended buffer and the |
+ // beginning of |new_buffers|. |
if (prev_timestamp != kNoDecodeTimestamp() && |
prev_timestamp != next_timestamp) { |
- // Clean up the old buffers between the last appended buffer and the |
- // beginning of |new_buffers|. |
RemoveInternal(prev_timestamp, next_timestamp, true, deleted_buffers); |
} |
- // Always make the start of the delete range exclusive for same timestamp |
- // across the last buffer in the previous append and the first buffer in the |
- // current append. Never be exclusive if a splice frame was generated because |
- // we don't generate splice frames for same timestamp situations. |
- DCHECK(new_buffers.front()->splice_timestamp() != |
- new_buffers.front()->timestamp()); |
- const bool exclude_start = new_buffers.front()->splice_buffers().empty() && |
- prev_timestamp == next_timestamp; |
- |
- // Delete the buffers that |new_buffers| overlaps. |
- DecodeTimestamp start = new_buffers.front()->GetDecodeTimestamp(); |
+ // 2. Delete the buffers that |new_buffers| overlaps. |
if (new_coded_frame_group_) { |
// Extend the deletion range earlier to the coded frame group start time if |
- // this is the first append in a new coded frame group. Note that |start| |
- // could already be less than |coded_frame_group_start_time_| if a splice |
- // was generated. |
+ // this is the first append in a new coded frame group. |
DCHECK(coded_frame_group_start_time_ != kNoDecodeTimestamp()); |
- start = std::min(coded_frame_group_start_time_, start); |
- } |
- DecodeTimestamp end = new_buffers.back()->GetDecodeTimestamp(); |
- base::TimeDelta duration = new_buffers.back()->duration(); |
+ next_timestamp = std::min(coded_frame_group_start_time_, next_timestamp); |
+ } |
+ |
+ // Exclude the start from removal to avoid deleting the last appended buffer |
+ // in cases where the timestamps match. Only do this when : |
+ // A. Type is video. This may occur in cases of VP9 alt-ref frames or frames |
+ // with incorrect timestamps. Removing a frame may break decode |
+ // dependencies and there are no downsides to just keeping it (other than |
+ // some throw-away decoder work). |
+ // B. Type is text. TODO(chcunningham): Implement text splicing. See |
+ // http://crbug.com/661408 |
+ // C. Type is audio and overlapped duration is 0. We've encountered Vorbis |
+ // streams containing zero-duration buffers (i.e. no real overlap). For |
+ // non-zero duration removing overlapped frames is important to preserve |
+ // A/V sync (see AudioClock). |
+ const bool exclude_start = prev_timestamp == next_timestamp && |
+ (GetType() == kVideo || GetType() == kText || |
+ prev_duration == base::TimeDelta()); |
// Set end time for remove to include the duration of last buffer. If the |
// duration is estimated, use 1 microsecond instead to ensure frames are not |
// accidentally removed due to over-estimation. |
+ DecodeTimestamp end = new_buffers.back()->GetDecodeTimestamp(); |
+ base::TimeDelta duration = new_buffers.back()->duration(); |
if (duration != kNoTimestamp && duration > base::TimeDelta() && |
!new_buffers.back()->is_duration_estimated()) { |
end += duration; |
@@ -1073,7 +1147,8 @@ void SourceBufferStream::PrepareRangesForNextAppend( |
end += base::TimeDelta::FromInternalValue(1); |
} |
- RemoveInternal(start, end, exclude_start, deleted_buffers); |
+ // Finally do the deletion of overlap. |
+ RemoveInternal(next_timestamp, end, exclude_start, deleted_buffers); |
} |
bool SourceBufferStream::AreAdjacentInSequence( |
@@ -1198,15 +1273,6 @@ SourceBufferStream::Status SourceBufferStream::GetNextBuffer( |
} |
} |
- if (!pending_buffer_->splice_buffers().empty()) { |
- const SourceBufferStream::Status status = |
- HandleNextBufferWithSplice(out_buffer); |
- DVLOG(2) << __func__ << " " << GetStreamTypeName() |
- << ": handled next buffer with splice, returning status " |
- << status; |
- return status; |
- } |
- |
DCHECK(pending_buffer_->preroll_buffer().get()); |
const SourceBufferStream::Status status = |
@@ -1216,57 +1282,6 @@ SourceBufferStream::Status SourceBufferStream::GetNextBuffer( |
return status; |
} |
-SourceBufferStream::Status SourceBufferStream::HandleNextBufferWithSplice( |
- scoped_refptr<StreamParserBuffer>* out_buffer) { |
- const BufferQueue& splice_buffers = pending_buffer_->splice_buffers(); |
- const size_t last_splice_buffer_index = splice_buffers.size() - 1; |
- |
- // Are there any splice buffers left to hand out? The last buffer should be |
- // handed out separately since it represents the first post-splice buffer. |
- if (splice_buffers_index_ < last_splice_buffer_index) { |
- // Account for config changes which occur between fade out buffers. |
- if (current_config_index_ != |
- splice_buffers[splice_buffers_index_]->GetConfigId()) { |
- config_change_pending_ = true; |
- DVLOG(1) << "Config change (splice buffer config ID does not match)."; |
- return SourceBufferStream::kConfigChange; |
- } |
- |
- // Every pre splice buffer must have the same splice_timestamp(). |
- DCHECK(pending_buffer_->splice_timestamp() == |
- splice_buffers[splice_buffers_index_]->splice_timestamp()); |
- |
- // No pre splice buffers should have preroll. |
- DCHECK(!splice_buffers[splice_buffers_index_]->preroll_buffer().get()); |
- |
- *out_buffer = splice_buffers[splice_buffers_index_++]; |
- return SourceBufferStream::kSuccess; |
- } |
- |
- // Did we hand out the last pre-splice buffer on the previous call? |
- if (!pending_buffers_complete_) { |
- DCHECK_EQ(splice_buffers_index_, last_splice_buffer_index); |
- pending_buffers_complete_ = true; |
- config_change_pending_ = true; |
- DVLOG(1) << "Config change (forced for fade in of splice frame)."; |
- return SourceBufferStream::kConfigChange; |
- } |
- |
- // All pre-splice buffers have been handed out and a config change completed, |
- // so hand out the final buffer for fade in. Because a config change is |
- // always issued prior to handing out this buffer, any changes in config id |
- // have been inherently handled. |
- DCHECK(pending_buffers_complete_); |
- DCHECK_EQ(splice_buffers_index_, splice_buffers.size() - 1); |
- DCHECK(splice_buffers.back()->splice_timestamp() == kNoTimestamp); |
- *out_buffer = splice_buffers.back(); |
- pending_buffer_ = NULL; |
- |
- // If the last splice buffer has preroll, hand off to the preroll handler. |
- return SetPendingBuffer(out_buffer) ? HandleNextBufferWithPreroll(out_buffer) |
- : SourceBufferStream::kSuccess; |
-} |
- |
SourceBufferStream::Status SourceBufferStream::HandleNextBufferWithPreroll( |
scoped_refptr<StreamParserBuffer>* out_buffer) { |
// Any config change should have already been handled. |
@@ -1575,12 +1590,6 @@ bool SourceBufferStream::UpdateVideoConfig(const VideoDecoderConfig& config) { |
void SourceBufferStream::CompleteConfigChange() { |
config_change_pending_ = false; |
- if (pending_buffer_.get()) { |
- current_config_index_ = |
- pending_buffer_->GetSpliceBufferConfigId(splice_buffers_index_); |
- return; |
- } |
- |
if (!track_buffer_.empty()) { |
current_config_index_ = track_buffer_.front()->GetSpliceBufferConfigId(0); |
return; |
@@ -1727,125 +1736,16 @@ void SourceBufferStream::DeleteAndRemoveRange(RangeList::iterator* itr) { |
*itr = ranges_.erase(*itr); |
} |
-void SourceBufferStream::GenerateSpliceFrame(const BufferQueue& new_buffers) { |
- DCHECK(!new_buffers.empty()); |
- |
- // Splice frames are only supported for audio. |
- if (GetType() != kAudio) |
- return; |
- |
- // Find the overlapped range (if any). |
- const base::TimeDelta splice_timestamp = new_buffers.front()->timestamp(); |
- const DecodeTimestamp splice_dts = |
- DecodeTimestamp::FromPresentationTime(splice_timestamp); |
- RangeList::iterator range_itr = FindExistingRangeFor(splice_dts); |
- if (range_itr == ranges_.end()) |
- return; |
- |
- const DecodeTimestamp max_splice_end_dts = |
- splice_dts + base::TimeDelta::FromMilliseconds( |
- AudioSplicer::kCrossfadeDurationInMilliseconds); |
- |
- // Find all buffers involved before the splice point. |
- BufferQueue pre_splice_buffers; |
- if (!(*range_itr)->GetBuffersInRange( |
- splice_dts, max_splice_end_dts, &pre_splice_buffers)) { |
- return; |
- } |
- |
- // If there are gaps in the timeline, it's possible that we only find buffers |
- // after the splice point but within the splice range. For simplicity, we do |
- // not generate splice frames in this case. |
- // |
- // 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) { |
- 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. |
- for (size_t i = 0; i < pre_splice_buffers.size(); ++i) { |
- 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; |
- } |
- } |
- |
- // 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 samples (need at least two to crossfade). |
- const base::TimeDelta splice_duration = |
- pre_splice_buffers.back()->timestamp() + |
- pre_splice_buffers.back()->duration() - splice_timestamp; |
- const base::TimeDelta minimum_splice_duration = std::max( |
- base::TimeDelta::FromMilliseconds(1), |
- 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."; |
- 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); |
-} |
- |
bool SourceBufferStream::SetPendingBuffer( |
scoped_refptr<StreamParserBuffer>* out_buffer) { |
DCHECK(out_buffer->get()); |
DCHECK(!pending_buffer_.get()); |
- const bool have_splice_buffers = !(*out_buffer)->splice_buffers().empty(); |
const bool have_preroll_buffer = !!(*out_buffer)->preroll_buffer().get(); |
- if (!have_splice_buffers && !have_preroll_buffer) |
+ if (!have_preroll_buffer) |
return false; |
- DCHECK_NE(have_splice_buffers, have_preroll_buffer); |
- splice_buffers_index_ = 0; |
pending_buffer_.swap(*out_buffer); |
pending_buffers_complete_ = false; |
return true; |