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 #include <string> | |
10 | 11 |
11 #include "base/bind.h" | 12 #include "base/bind.h" |
12 #include "base/logging.h" | 13 #include "base/logging.h" |
13 #include "base/trace_event/trace_event.h" | 14 #include "base/trace_event/trace_event.h" |
14 #include "media/base/audio_splicer.h" | |
15 #include "media/base/timestamp_constants.h" | 15 #include "media/base/timestamp_constants.h" |
16 #include "media/filters/source_buffer_platform.h" | 16 #include "media/filters/source_buffer_platform.h" |
17 #include "media/filters/source_buffer_range.h" | 17 #include "media/filters/source_buffer_range.h" |
18 | 18 |
19 namespace media { | 19 namespace media { |
20 | 20 |
21 namespace { | 21 namespace { |
22 | 22 |
23 // 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 is |
24 // set and there's not enough information to get a better estimate. | 24 // set and there's not enough information to get a better estimate. |
25 const int kDefaultBufferDurationInMs = 125; | 25 const int kDefaultBufferDurationInMs = 125; |
26 | 26 |
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 | |
29 // media internals event cache (along with other events), these logs are | |
30 // important for debugging splice generation. | |
31 const int kMaxSpliceGenerationWarningLogs = 50; | |
32 const int kMaxSpliceGenerationSuccessLogs = 20; | |
33 | |
34 // Limit the number of MEDIA_LOG() logs for track buffer time gaps. | 27 // Limit the number of MEDIA_LOG() logs for track buffer time gaps. |
35 const int kMaxTrackBufferGapWarningLogs = 20; | 28 const int kMaxTrackBufferGapWarningLogs = 20; |
36 | 29 |
37 // Limit the number of MEDIA_LOG() logs for MSE GC algorithm warnings. | 30 // Limit the number of MEDIA_LOG() logs for MSE GC algorithm warnings. |
38 const int kMaxGarbageCollectAlgorithmWarningLogs = 20; | 31 const int kMaxGarbageCollectAlgorithmWarningLogs = 20; |
39 | 32 |
33 // Limit the number of MEDIA_LOG() logs for splice overlap trimming. | |
34 const int kMaxAudioSpliceLogs = 20; | |
35 | |
40 // Limit the number of MEDIA_LOG() logs for same DTS for non-keyframe followed | 36 // Limit the number of MEDIA_LOG() logs for same DTS for non-keyframe followed |
41 // by keyframe. Prior to relaxing the "media segments must begin with a | 37 // by keyframe. Prior to relaxing the "media segments must begin with a |
42 // keyframe" requirement, we issued decode error for this situation. That was | 38 // keyframe" requirement, we issued decode error for this situation. That was |
43 // likely too strict, and now that the keyframe requirement is relaxed, we have | 39 // likely too strict, and now that the keyframe requirement is relaxed, we have |
44 // no knowledge of media segment boundaries here. Now, we log but don't trigger | 40 // no knowledge of media segment boundaries here. Now, we log but don't trigger |
45 // decode error, since we allow these sequences which may cause extra decoder | 41 // decode error, since we allow these sequences which may cause extra decoder |
46 // work or other side-effects. | 42 // work or other side-effects. |
47 const int kMaxStrangeSameTimestampsLogs = 20; | 43 const int kMaxStrangeSameTimestampsLogs = 20; |
48 | 44 |
49 // Helper method that returns true if |ranges| is sorted in increasing order, | 45 // Helper method that returns true if |ranges| is sorted in increasing order, |
50 // false otherwise. | 46 // false otherwise. |
51 bool IsRangeListSorted(const std::list<media::SourceBufferRange*>& ranges) { | 47 bool IsRangeListSorted(const std::list<media::SourceBufferRange*>& ranges) { |
52 DecodeTimestamp prev = kNoDecodeTimestamp(); | 48 DecodeTimestamp prev = kNoDecodeTimestamp(); |
53 for (std::list<SourceBufferRange*>::const_iterator itr = | 49 for (std::list<SourceBufferRange*>::const_iterator itr = |
54 ranges.begin(); itr != ranges.end(); ++itr) { | 50 ranges.begin(); itr != ranges.end(); ++itr) { |
55 if (prev != kNoDecodeTimestamp() && prev >= (*itr)->GetStartTimestamp()) | 51 if (prev != kNoDecodeTimestamp() && prev >= (*itr)->GetStartTimestamp()) |
56 return false; | 52 return false; |
57 prev = (*itr)->GetEndTimestamp(); | 53 prev = (*itr)->GetEndTimestamp(); |
58 } | 54 } |
59 return true; | 55 return true; |
60 } | 56 } |
61 | 57 |
62 // Returns an estimate of how far from the beginning or end of a range a buffer | 58 // Returns an estimate of how far from the beginning or end of a range a buffer |
63 // can be to still be considered in the range, given the |approximate_duration| | 59 // can be to still be considered in the range, given the |approximate_duration| |
64 // of a buffer in the stream. | 60 // of a buffer in the stream. |
65 // TODO(wolenetz): Once all stream parsers emit accurate frame durations, use | 61 // TODO(wolenetz): Once all stream parsers emit accurate frame durations, use |
66 // logic like FrameProcessor (2*last_frame_duration + last_decode_timestamp) | 62 // logic like FrameProcessor (2*last_frame_duration + last_decode_timestamp) |
67 // instead of an overall maximum interbuffer delta for range discontinuity | 63 // instead of an overall maximum interbuffer delta for range discontinuity |
68 // detection, and adjust similarly for splice frame discontinuity detection. | 64 // detection. |
69 // See http://crbug.com/351489 and http://crbug.com/351166. | 65 // See http://crbug.com/351489 and http://crbug.com/351166. |
70 base::TimeDelta ComputeFudgeRoom(base::TimeDelta approximate_duration) { | 66 base::TimeDelta ComputeFudgeRoom(base::TimeDelta approximate_duration) { |
71 // Because we do not know exactly when is the next timestamp, any buffer | 67 // Because we do not know exactly when is the next timestamp, any buffer |
72 // that starts within 2x the approximate duration of a buffer is considered | 68 // that starts within 2x the approximate duration of a buffer is considered |
73 // within this range. | 69 // within this range. |
74 return 2 * approximate_duration; | 70 return 2 * approximate_duration; |
75 } | 71 } |
76 | 72 |
77 // The amount of time the beginning of the buffered data can differ from the | 73 // The amount of time the beginning of the buffered data can differ from the |
78 // start time in order to still be considered the start of stream. | 74 // start time in order to still be considered the start of stream. |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
135 return SourceBufferRange::ALLOW_GAPS; | 131 return SourceBufferRange::ALLOW_GAPS; |
136 } | 132 } |
137 | 133 |
138 NOTREACHED(); | 134 NOTREACHED(); |
139 return SourceBufferRange::NO_GAPS_ALLOWED; | 135 return SourceBufferRange::NO_GAPS_ALLOWED; |
140 } | 136 } |
141 | 137 |
142 } // namespace | 138 } // namespace |
143 | 139 |
144 SourceBufferStream::SourceBufferStream(const AudioDecoderConfig& audio_config, | 140 SourceBufferStream::SourceBufferStream(const AudioDecoderConfig& audio_config, |
145 const scoped_refptr<MediaLog>& media_log, | 141 const scoped_refptr<MediaLog>& media_log) |
146 bool splice_frames_enabled) | |
147 : media_log_(media_log), | 142 : media_log_(media_log), |
148 seek_buffer_timestamp_(kNoTimestamp), | 143 seek_buffer_timestamp_(kNoTimestamp), |
149 coded_frame_group_start_time_(kNoDecodeTimestamp()), | 144 coded_frame_group_start_time_(kNoDecodeTimestamp()), |
150 range_for_next_append_(ranges_.end()), | 145 range_for_next_append_(ranges_.end()), |
151 last_output_buffer_timestamp_(kNoDecodeTimestamp()), | 146 last_output_buffer_timestamp_(kNoDecodeTimestamp()), |
152 max_interbuffer_distance_(kNoTimestamp), | 147 max_interbuffer_distance_(kNoTimestamp), |
153 memory_limit_(kSourceBufferAudioMemoryLimit), | 148 memory_limit_(kSourceBufferAudioMemoryLimit) { |
154 splice_frames_enabled_(splice_frames_enabled) { | |
155 DCHECK(audio_config.IsValidConfig()); | 149 DCHECK(audio_config.IsValidConfig()); |
156 audio_configs_.push_back(audio_config); | 150 audio_configs_.push_back(audio_config); |
157 } | 151 } |
158 | 152 |
159 SourceBufferStream::SourceBufferStream(const VideoDecoderConfig& video_config, | 153 SourceBufferStream::SourceBufferStream(const VideoDecoderConfig& video_config, |
160 const scoped_refptr<MediaLog>& media_log, | 154 const scoped_refptr<MediaLog>& media_log) |
161 bool splice_frames_enabled) | |
162 : media_log_(media_log), | 155 : media_log_(media_log), |
163 seek_buffer_timestamp_(kNoTimestamp), | 156 seek_buffer_timestamp_(kNoTimestamp), |
164 coded_frame_group_start_time_(kNoDecodeTimestamp()), | 157 coded_frame_group_start_time_(kNoDecodeTimestamp()), |
165 range_for_next_append_(ranges_.end()), | 158 range_for_next_append_(ranges_.end()), |
166 last_output_buffer_timestamp_(kNoDecodeTimestamp()), | 159 last_output_buffer_timestamp_(kNoDecodeTimestamp()), |
167 max_interbuffer_distance_(kNoTimestamp), | 160 max_interbuffer_distance_(kNoTimestamp), |
168 memory_limit_(kSourceBufferVideoMemoryLimit), | 161 memory_limit_(kSourceBufferVideoMemoryLimit) { |
169 splice_frames_enabled_(splice_frames_enabled) { | |
170 DCHECK(video_config.IsValidConfig()); | 162 DCHECK(video_config.IsValidConfig()); |
171 video_configs_.push_back(video_config); | 163 video_configs_.push_back(video_config); |
172 } | 164 } |
173 | 165 |
174 SourceBufferStream::SourceBufferStream(const TextTrackConfig& text_config, | 166 SourceBufferStream::SourceBufferStream(const TextTrackConfig& text_config, |
175 const scoped_refptr<MediaLog>& media_log, | 167 const scoped_refptr<MediaLog>& media_log) |
176 bool splice_frames_enabled) | |
177 : media_log_(media_log), | 168 : media_log_(media_log), |
178 text_track_config_(text_config), | 169 text_track_config_(text_config), |
179 seek_buffer_timestamp_(kNoTimestamp), | 170 seek_buffer_timestamp_(kNoTimestamp), |
180 coded_frame_group_start_time_(kNoDecodeTimestamp()), | 171 coded_frame_group_start_time_(kNoDecodeTimestamp()), |
181 range_for_next_append_(ranges_.end()), | 172 range_for_next_append_(ranges_.end()), |
182 last_output_buffer_timestamp_(kNoDecodeTimestamp()), | 173 last_output_buffer_timestamp_(kNoDecodeTimestamp()), |
183 max_interbuffer_distance_(kNoTimestamp), | 174 max_interbuffer_distance_(kNoTimestamp), |
184 memory_limit_(kSourceBufferAudioMemoryLimit), | 175 memory_limit_(kSourceBufferAudioMemoryLimit) {} |
185 splice_frames_enabled_(splice_frames_enabled) {} | |
186 | 176 |
187 SourceBufferStream::~SourceBufferStream() { | 177 SourceBufferStream::~SourceBufferStream() { |
188 while (!ranges_.empty()) { | 178 while (!ranges_.empty()) { |
189 delete ranges_.front(); | 179 delete ranges_.front(); |
190 ranges_.pop_front(); | 180 ranges_.pop_front(); |
191 } | 181 } |
192 } | 182 } |
193 | 183 |
194 void SourceBufferStream::OnStartOfCodedFrameGroup( | 184 void SourceBufferStream::OnStartOfCodedFrameGroup( |
195 DecodeTimestamp coded_frame_group_start_time) { | 185 DecodeTimestamp coded_frame_group_start_time) { |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
256 | 246 |
257 // Save a snapshot of stream state before range modifications are made. | 247 // Save a snapshot of stream state before range modifications are made. |
258 DecodeTimestamp next_buffer_timestamp = GetNextBufferTimestamp(); | 248 DecodeTimestamp next_buffer_timestamp = GetNextBufferTimestamp(); |
259 BufferQueue deleted_buffers; | 249 BufferQueue deleted_buffers; |
260 | 250 |
261 PrepareRangesForNextAppend(buffers, &deleted_buffers); | 251 PrepareRangesForNextAppend(buffers, &deleted_buffers); |
262 | 252 |
263 // If there's a range for |buffers|, insert |buffers| accordingly. Otherwise, | 253 // If there's a range for |buffers|, insert |buffers| accordingly. Otherwise, |
264 // create a new range with |buffers|. | 254 // create a new range with |buffers|. |
265 if (range_for_next_append_ != ranges_.end()) { | 255 if (range_for_next_append_ != ranges_.end()) { |
266 if (new_coded_frame_group_ && (!splice_frames_enabled_ || | 256 if (new_coded_frame_group_) { |
267 buffers.front()->splice_buffers().empty())) { | |
268 // If the first append to this stream in a new coded frame group continues | 257 // If the first append to this stream in a new coded frame group continues |
269 // a previous range, use the new group's start time instead of the first | 258 // a previous range, use the new group's start time instead of the first |
270 // new buffer's timestamp as the proof of adjacency to the existing range. | 259 // new buffer's timestamp as the proof of adjacency to the existing range. |
271 // A large gap (larger than our normal buffer adjacency test) can occur in | 260 // A large gap (larger than our normal buffer adjacency test) can occur in |
272 // a muxed set of streams (which share a common coded frame group start | 261 // a muxed set of streams (which share a common coded frame group start |
273 // time) with a significantly jagged start across the streams. | 262 // time) with a significantly jagged start across the streams. |
274 // Don't do this logic if there was a splice frame generated for the first | |
275 // new buffer, since splices are guaranteed to be in the same range and | |
276 // adjacent, and since the splice frame's timestamp can be less than | |
277 // |coded_frame_group_start_time_| due to the splicing. | |
278 (*range_for_next_append_) | 263 (*range_for_next_append_) |
279 ->AppendBuffersToEnd(buffers, coded_frame_group_start_time_); | 264 ->AppendBuffersToEnd(buffers, coded_frame_group_start_time_); |
280 } else { | 265 } else { |
281 // Otherwise, use the first new buffer's timestamp as the proof of | 266 // Otherwise, use the first new buffer's timestamp as the proof of |
282 // adjacency. | 267 // adjacency. |
283 (*range_for_next_append_) | 268 (*range_for_next_append_) |
284 ->AppendBuffersToEnd(buffers, kNoDecodeTimestamp()); | 269 ->AppendBuffersToEnd(buffers, kNoDecodeTimestamp()); |
285 } | 270 } |
286 | 271 |
287 last_appended_buffer_timestamp_ = buffers.back()->GetDecodeTimestamp(); | 272 last_appended_buffer_timestamp_ = buffers.back()->GetDecodeTimestamp(); |
(...skipping 17 matching lines...) Expand all Loading... | |
305 } | 290 } |
306 | 291 |
307 // If we didn't find a key frame, then update the last appended | 292 // If we didn't find a key frame, then update the last appended |
308 // buffer state and return. | 293 // buffer state and return. |
309 if (itr == buffers.end()) { | 294 if (itr == buffers.end()) { |
310 last_appended_buffer_timestamp_ = buffers.back()->GetDecodeTimestamp(); | 295 last_appended_buffer_timestamp_ = buffers.back()->GetDecodeTimestamp(); |
311 last_appended_buffer_duration_ = buffers.back()->duration(); | 296 last_appended_buffer_duration_ = buffers.back()->duration(); |
312 last_appended_buffer_is_keyframe_ = buffers.back()->is_key_frame(); | 297 last_appended_buffer_is_keyframe_ = buffers.back()->is_key_frame(); |
313 DVLOG(1) << __func__ << " " << GetStreamTypeName() | 298 DVLOG(1) << __func__ << " " << GetStreamTypeName() |
314 << ": new buffers in the middle of coded frame group depend on" | 299 << ": new buffers in the middle of coded frame group depend on" |
315 "keyframe that has been removed, and contain no keyframes." | 300 " keyframe that has been removed, and contain no keyframes." |
316 "Skipping further processing."; | 301 " Skipping further processing."; |
317 DVLOG(1) << __func__ << " " << GetStreamTypeName() | 302 DVLOG(1) << __func__ << " " << GetStreamTypeName() |
318 << ": done. ranges_=" << RangesToString(ranges_); | 303 << ": done. ranges_=" << RangesToString(ranges_); |
319 return true; | 304 return true; |
320 } else if (itr != buffers.begin()) { | 305 } else if (itr != buffers.begin()) { |
321 // Copy the first key frame and everything after it into | 306 // Copy the first key frame and everything after it into |
322 // |trimmed_buffers|. | 307 // |trimmed_buffers|. |
323 trimmed_buffers.assign(itr, buffers.end()); | 308 trimmed_buffers.assign(itr, buffers.end()); |
324 buffers_for_new_range = &trimmed_buffers; | 309 buffers_for_new_range = &trimmed_buffers; |
325 } | 310 } |
326 | 311 |
(...skipping 269 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
596 DCHECK(IsRangeListSorted(ranges_)); | 581 DCHECK(IsRangeListSorted(ranges_)); |
597 DCHECK(OnlySelectedRangeIsSeeked()); | 582 DCHECK(OnlySelectedRangeIsSeeked()); |
598 } | 583 } |
599 | 584 |
600 void SourceBufferStream::ResetSeekState() { | 585 void SourceBufferStream::ResetSeekState() { |
601 SetSelectedRange(NULL); | 586 SetSelectedRange(NULL); |
602 track_buffer_.clear(); | 587 track_buffer_.clear(); |
603 config_change_pending_ = false; | 588 config_change_pending_ = false; |
604 last_output_buffer_timestamp_ = kNoDecodeTimestamp(); | 589 last_output_buffer_timestamp_ = kNoDecodeTimestamp(); |
605 just_exhausted_track_buffer_ = false; | 590 just_exhausted_track_buffer_ = false; |
606 splice_buffers_index_ = 0; | |
607 pending_buffer_ = NULL; | 591 pending_buffer_ = NULL; |
608 pending_buffers_complete_ = false; | 592 pending_buffers_complete_ = false; |
609 } | 593 } |
610 | 594 |
611 void SourceBufferStream::ResetLastAppendedState() { | 595 void SourceBufferStream::ResetLastAppendedState() { |
612 last_appended_buffer_timestamp_ = kNoDecodeTimestamp(); | 596 last_appended_buffer_timestamp_ = kNoDecodeTimestamp(); |
613 last_appended_buffer_duration_ = kNoTimestamp; | 597 last_appended_buffer_duration_ = kNoTimestamp; |
614 last_appended_buffer_is_keyframe_ = false; | 598 last_appended_buffer_is_keyframe_ = false; |
615 } | 599 } |
616 | 600 |
(...skipping 395 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1012 if (range_for_next_append_ != ranges_.begin()) { | 996 if (range_for_next_append_ != ranges_.begin()) { |
1013 RangeList::iterator range_before_next = range_for_next_append_; | 997 RangeList::iterator range_before_next = range_for_next_append_; |
1014 --range_before_next; | 998 --range_before_next; |
1015 MergeWithAdjacentRangeIfNecessary(range_before_next); | 999 MergeWithAdjacentRangeIfNecessary(range_before_next); |
1016 } | 1000 } |
1017 MergeWithAdjacentRangeIfNecessary(range_for_next_append_); | 1001 MergeWithAdjacentRangeIfNecessary(range_for_next_append_); |
1018 } | 1002 } |
1019 return bytes_freed; | 1003 return bytes_freed; |
1020 } | 1004 } |
1021 | 1005 |
1006 void SourceBufferStream::TrimSpliceOverlap(const BufferQueue& new_buffers) { | |
1007 DCHECK(!new_buffers.empty()); | |
1008 DCHECK_EQ(kAudio, GetType()); | |
1009 | |
1010 // Find the overlapped range (if any). | |
1011 const base::TimeDelta splice_timestamp = new_buffers.front()->timestamp(); | |
1012 const DecodeTimestamp splice_dts = | |
1013 DecodeTimestamp::FromPresentationTime(splice_timestamp); | |
1014 RangeList::iterator range_itr = FindExistingRangeFor(splice_dts); | |
1015 if (range_itr == ranges_.end()) { | |
1016 DVLOG(3) << __func__ << " No splice trimming. No range overlap at time " | |
1017 << splice_timestamp.InMicroseconds(); | |
1018 return; | |
1019 } | |
1020 | |
1021 // Search for overlapped buffer needs exclusive end value. Choosing smallest | |
1022 // possible value. | |
1023 const DecodeTimestamp end_dts = | |
1024 splice_dts + base::TimeDelta::FromInternalValue(1); | |
1025 | |
1026 // Find if new buffer's start would overlap an existing buffer. | |
1027 BufferQueue overlapped_buffers; | |
1028 if (!(*range_itr) | |
1029 ->GetBuffersInRange(splice_dts, end_dts, &overlapped_buffers)) { | |
1030 // Bail if no overlapped buffers found. | |
1031 DVLOG(3) << __func__ << " No splice trimming. No buffer overlap at time " | |
1032 << splice_timestamp.InMicroseconds(); | |
1033 return; | |
1034 } | |
1035 | |
1036 // At most one buffer should exist containing the time of the newly appended | |
1037 // buffer's start. GetBuffersInRange does not currently return buffers with | |
1038 // zero duration. | |
1039 DCHECK_EQ(overlapped_buffers.size(), 1U) | |
1040 << __func__ << " Found more than one overlapped buffer"; | |
1041 StreamParserBuffer* overlapped_buffer = overlapped_buffers.front().get(); | |
1042 | |
1043 if (overlapped_buffer->timestamp() == splice_timestamp) { | |
1044 // Ignore buffers with the same start time. They will be completely removed | |
1045 // in PrepareRangesForNextAppend(). | |
1046 DVLOG(3) << __func__ << " No splice trimming at time " | |
1047 << splice_timestamp.InMicroseconds() | |
1048 << ". Overlapped buffer will be completely removed."; | |
1049 return; | |
1050 } | |
1051 | |
1052 // Determine the duration of overlap. | |
1053 base::TimeDelta overlapped_end_time = | |
1054 overlapped_buffer->timestamp() + overlapped_buffer->duration(); | |
1055 base::TimeDelta overlap_duration = overlapped_end_time - splice_timestamp; | |
1056 | |
1057 // At this point overlap should be non-empty (ruled out same-timestamp above). | |
1058 DCHECK_NE(overlap_duration, base::TimeDelta()); | |
wolenetz
2016/10/28 23:08:19
nit: s/NE/GT/ for extra safety :)
chcunningham
2016/11/02 01:28:42
Done.
| |
1059 | |
1060 // Don't trim for overlaps of less than one millisecond (which is frequently | |
1061 // the extent of timestamp resolution for poorly encoded media). | |
1062 if (overlap_duration < base::TimeDelta::FromMilliseconds(1)) { | |
1063 std::stringstream log_string; | |
1064 log_string << "Skipping audio splice trimming at PTS=" | |
1065 << splice_timestamp.InMicroseconds() << "us. Found only " | |
1066 << overlap_duration.InMicroseconds() | |
1067 << "us of overlap, need at least 1000us. Multiple occurrences " | |
1068 << "may result in loss of A/V sync."; | |
1069 LIMITED_MEDIA_LOG(DEBUG, media_log_, num_splice_logs_, kMaxAudioSpliceLogs) | |
1070 << log_string.str(); | |
1071 DVLOG(1) << __func__ << log_string.str(); | |
1072 return; | |
1073 } | |
1074 | |
1075 // Trim overlap from the existing buffer. | |
1076 DecoderBuffer::DiscardPadding discard_padding = | |
1077 overlapped_buffer->discard_padding(); | |
1078 discard_padding.second += overlap_duration; | |
1079 overlapped_buffer->set_discard_padding(discard_padding); | |
1080 overlapped_buffer->set_duration(overlapped_buffer->duration() - | |
1081 overlap_duration); | |
1082 | |
1083 std::stringstream log_string; | |
1084 log_string << "Audio buffer splice at PTS=" | |
1085 << splice_timestamp.InMicroseconds() | |
1086 << "us. Trimmed tail of overlapped buffer (PTS=" | |
1087 << overlapped_buffer->timestamp().InMicroseconds() << "us) by " | |
1088 << overlap_duration.InMicroseconds() << "us."; | |
1089 LIMITED_MEDIA_LOG(DEBUG, media_log_, num_splice_logs_, kMaxAudioSpliceLogs) | |
1090 << log_string.str(); | |
1091 DVLOG(1) << __func__ << log_string.str(); | |
1092 } | |
1093 | |
1022 void SourceBufferStream::PrepareRangesForNextAppend( | 1094 void SourceBufferStream::PrepareRangesForNextAppend( |
1023 const BufferQueue& new_buffers, BufferQueue* deleted_buffers) { | 1095 const BufferQueue& new_buffers, BufferQueue* deleted_buffers) { |
1024 DCHECK(deleted_buffers); | 1096 DCHECK(deleted_buffers); |
1025 | 1097 |
1026 // Handle splices between the existing buffers and the new buffers. If a | 1098 if (GetType() == kAudio) |
1027 // splice is generated the timestamp and duration of the first buffer in | 1099 TrimSpliceOverlap(new_buffers); |
1028 // |new_buffers| will be modified. | |
1029 if (splice_frames_enabled_) | |
1030 GenerateSpliceFrame(new_buffers); | |
1031 | 1100 |
1101 base::TimeDelta prev_duration = last_appended_buffer_duration_; | |
1032 DecodeTimestamp prev_timestamp = last_appended_buffer_timestamp_; | 1102 DecodeTimestamp prev_timestamp = last_appended_buffer_timestamp_; |
1033 DecodeTimestamp next_timestamp = new_buffers.front()->GetDecodeTimestamp(); | 1103 DecodeTimestamp next_timestamp = new_buffers.front()->GetDecodeTimestamp(); |
1034 | 1104 |
1105 // 1. Clean up the old buffers between the last appended buffer and the | |
1106 // beginning of |new_buffers|. | |
1035 if (prev_timestamp != kNoDecodeTimestamp() && | 1107 if (prev_timestamp != kNoDecodeTimestamp() && |
1036 prev_timestamp != next_timestamp) { | 1108 prev_timestamp != next_timestamp) { |
1037 // Clean up the old buffers between the last appended buffer and the | |
1038 // beginning of |new_buffers|. | |
1039 RemoveInternal(prev_timestamp, next_timestamp, true, deleted_buffers); | 1109 RemoveInternal(prev_timestamp, next_timestamp, true, deleted_buffers); |
1040 } | 1110 } |
1041 | 1111 |
1042 // Always make the start of the delete range exclusive for same timestamp | 1112 // 2. Delete the buffers that |new_buffers| overlaps. |
1043 // across the last buffer in the previous append and the first buffer in the | |
1044 // current append. Never be exclusive if a splice frame was generated because | |
1045 // we don't generate splice frames for same timestamp situations. | |
1046 DCHECK(new_buffers.front()->splice_timestamp() != | |
1047 new_buffers.front()->timestamp()); | |
1048 const bool exclude_start = new_buffers.front()->splice_buffers().empty() && | |
1049 prev_timestamp == next_timestamp; | |
1050 | |
1051 // Delete the buffers that |new_buffers| overlaps. | |
1052 DecodeTimestamp start = new_buffers.front()->GetDecodeTimestamp(); | |
1053 if (new_coded_frame_group_) { | 1113 if (new_coded_frame_group_) { |
1054 // Extend the deletion range earlier to the coded frame group start time if | 1114 // Extend the deletion range earlier to the coded frame group start time if |
1055 // this is the first append in a new coded frame group. Note that |start| | 1115 // this is the first append in a new coded frame group. |
1056 // could already be less than |coded_frame_group_start_time_| if a splice | |
1057 // was generated. | |
1058 DCHECK(coded_frame_group_start_time_ != kNoDecodeTimestamp()); | 1116 DCHECK(coded_frame_group_start_time_ != kNoDecodeTimestamp()); |
1059 start = std::min(coded_frame_group_start_time_, start); | 1117 next_timestamp = std::min(coded_frame_group_start_time_, next_timestamp); |
1060 } | 1118 } |
1061 DecodeTimestamp end = new_buffers.back()->GetDecodeTimestamp(); | 1119 |
1062 base::TimeDelta duration = new_buffers.back()->duration(); | 1120 // Exclude the start from removal to avoid deleting the last appended buffer |
1121 // in cases where the timestamps match. Only do this for when either: | |
1122 // A. Type is video. This may occur in cases of VP9 alt-ref frames or frames | |
1123 // with incorrect timestamps. Removing a frame may break decode | |
1124 // dependencies and there are no downsides to just keeping it. | |
wolenetz
2016/10/28 23:08:19
nit: s/no downsides/no downsides, other than poten
chcunningham
2016/11/02 01:28:42
Done.
| |
1125 // B. Type is audio and overlapped duration is 0. We've encountered Vorbis | |
wolenetz
2016/10/28 23:08:19
nit: s/audio/audio or text/ + add a TODO+crbug, ab
chcunningham
2016/11/02 01:28:42
Done. For posterity, our f2f decision was to treat
| |
1126 // streams containing zero-duration buffers (i.e. no real overlap). For | |
1127 // non-zero duration removing overlapped frames is important to preserve | |
1128 // A/V sync (see AudioClock). | |
1129 const bool exclude_start = | |
1130 prev_timestamp == next_timestamp && | |
1131 (GetType() == kVideo || prev_duration == base::TimeDelta()); | |
1063 | 1132 |
1064 // Set end time for remove to include the duration of last buffer. If the | 1133 // Set end time for remove to include the duration of last buffer. If the |
1065 // duration is estimated, use 1 microsecond instead to ensure frames are not | 1134 // duration is estimated, use 1 microsecond instead to ensure frames are not |
1066 // accidentally removed due to over-estimation. | 1135 // accidentally removed due to over-estimation. |
1136 DecodeTimestamp end = new_buffers.back()->GetDecodeTimestamp(); | |
1137 base::TimeDelta duration = new_buffers.back()->duration(); | |
1067 if (duration != kNoTimestamp && duration > base::TimeDelta() && | 1138 if (duration != kNoTimestamp && duration > base::TimeDelta() && |
1068 !new_buffers.back()->is_duration_estimated()) { | 1139 !new_buffers.back()->is_duration_estimated()) { |
1069 end += duration; | 1140 end += duration; |
1070 } else { | 1141 } else { |
1071 // TODO(chcunningham): Emit warning when 0ms durations are not expected. | 1142 // TODO(chcunningham): Emit warning when 0ms durations are not expected. |
1072 // http://crbug.com/312836 | 1143 // http://crbug.com/312836 |
1073 end += base::TimeDelta::FromInternalValue(1); | 1144 end += base::TimeDelta::FromInternalValue(1); |
1074 } | 1145 } |
1075 | 1146 |
1076 RemoveInternal(start, end, exclude_start, deleted_buffers); | 1147 // Finally do the deletion of overlap. |
1148 RemoveInternal(next_timestamp, end, exclude_start, deleted_buffers); | |
1077 } | 1149 } |
1078 | 1150 |
1079 bool SourceBufferStream::AreAdjacentInSequence( | 1151 bool SourceBufferStream::AreAdjacentInSequence( |
1080 DecodeTimestamp first_timestamp, DecodeTimestamp second_timestamp) const { | 1152 DecodeTimestamp first_timestamp, DecodeTimestamp second_timestamp) const { |
1081 return first_timestamp < second_timestamp && | 1153 return first_timestamp < second_timestamp && |
1082 second_timestamp <= | 1154 second_timestamp <= |
1083 first_timestamp + ComputeFudgeRoom(GetMaxInterbufferDistance()); | 1155 first_timestamp + ComputeFudgeRoom(GetMaxInterbufferDistance()); |
1084 } | 1156 } |
1085 | 1157 |
1086 void SourceBufferStream::PruneTrackBuffer(const DecodeTimestamp timestamp) { | 1158 void SourceBufferStream::PruneTrackBuffer(const DecodeTimestamp timestamp) { |
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1191 if (!pending_buffer_.get()) { | 1263 if (!pending_buffer_.get()) { |
1192 const SourceBufferStream::Status status = GetNextBufferInternal(out_buffer); | 1264 const SourceBufferStream::Status status = GetNextBufferInternal(out_buffer); |
1193 if (status != SourceBufferStream::kSuccess || | 1265 if (status != SourceBufferStream::kSuccess || |
1194 !SetPendingBuffer(out_buffer)) { | 1266 !SetPendingBuffer(out_buffer)) { |
1195 DVLOG(2) << __func__ << " " << GetStreamTypeName() | 1267 DVLOG(2) << __func__ << " " << GetStreamTypeName() |
1196 << ": no pending buffer, returning status " << status; | 1268 << ": no pending buffer, returning status " << status; |
1197 return status; | 1269 return status; |
1198 } | 1270 } |
1199 } | 1271 } |
1200 | 1272 |
1201 if (!pending_buffer_->splice_buffers().empty()) { | |
1202 const SourceBufferStream::Status status = | |
1203 HandleNextBufferWithSplice(out_buffer); | |
1204 DVLOG(2) << __func__ << " " << GetStreamTypeName() | |
1205 << ": handled next buffer with splice, returning status " | |
1206 << status; | |
1207 return status; | |
1208 } | |
1209 | |
1210 DCHECK(pending_buffer_->preroll_buffer().get()); | 1273 DCHECK(pending_buffer_->preroll_buffer().get()); |
1211 | 1274 |
1212 const SourceBufferStream::Status status = | 1275 const SourceBufferStream::Status status = |
1213 HandleNextBufferWithPreroll(out_buffer); | 1276 HandleNextBufferWithPreroll(out_buffer); |
1214 DVLOG(2) << __func__ << " " << GetStreamTypeName() | 1277 DVLOG(2) << __func__ << " " << GetStreamTypeName() |
1215 << ": handled next buffer with preroll, returning status " << status; | 1278 << ": handled next buffer with preroll, returning status " << status; |
1216 return status; | 1279 return status; |
1217 } | 1280 } |
1218 | 1281 |
1219 SourceBufferStream::Status SourceBufferStream::HandleNextBufferWithSplice( | |
1220 scoped_refptr<StreamParserBuffer>* out_buffer) { | |
1221 const BufferQueue& splice_buffers = pending_buffer_->splice_buffers(); | |
1222 const size_t last_splice_buffer_index = splice_buffers.size() - 1; | |
1223 | |
1224 // Are there any splice buffers left to hand out? The last buffer should be | |
1225 // handed out separately since it represents the first post-splice buffer. | |
1226 if (splice_buffers_index_ < last_splice_buffer_index) { | |
1227 // Account for config changes which occur between fade out buffers. | |
1228 if (current_config_index_ != | |
1229 splice_buffers[splice_buffers_index_]->GetConfigId()) { | |
1230 config_change_pending_ = true; | |
1231 DVLOG(1) << "Config change (splice buffer config ID does not match)."; | |
1232 return SourceBufferStream::kConfigChange; | |
1233 } | |
1234 | |
1235 // Every pre splice buffer must have the same splice_timestamp(). | |
1236 DCHECK(pending_buffer_->splice_timestamp() == | |
1237 splice_buffers[splice_buffers_index_]->splice_timestamp()); | |
1238 | |
1239 // No pre splice buffers should have preroll. | |
1240 DCHECK(!splice_buffers[splice_buffers_index_]->preroll_buffer().get()); | |
1241 | |
1242 *out_buffer = splice_buffers[splice_buffers_index_++]; | |
1243 return SourceBufferStream::kSuccess; | |
1244 } | |
1245 | |
1246 // Did we hand out the last pre-splice buffer on the previous call? | |
1247 if (!pending_buffers_complete_) { | |
1248 DCHECK_EQ(splice_buffers_index_, last_splice_buffer_index); | |
1249 pending_buffers_complete_ = true; | |
1250 config_change_pending_ = true; | |
1251 DVLOG(1) << "Config change (forced for fade in of splice frame)."; | |
1252 return SourceBufferStream::kConfigChange; | |
1253 } | |
1254 | |
1255 // All pre-splice buffers have been handed out and a config change completed, | |
1256 // so hand out the final buffer for fade in. Because a config change is | |
1257 // always issued prior to handing out this buffer, any changes in config id | |
1258 // have been inherently handled. | |
1259 DCHECK(pending_buffers_complete_); | |
1260 DCHECK_EQ(splice_buffers_index_, splice_buffers.size() - 1); | |
1261 DCHECK(splice_buffers.back()->splice_timestamp() == kNoTimestamp); | |
1262 *out_buffer = splice_buffers.back(); | |
1263 pending_buffer_ = NULL; | |
1264 | |
1265 // If the last splice buffer has preroll, hand off to the preroll handler. | |
1266 return SetPendingBuffer(out_buffer) ? HandleNextBufferWithPreroll(out_buffer) | |
1267 : SourceBufferStream::kSuccess; | |
1268 } | |
1269 | |
1270 SourceBufferStream::Status SourceBufferStream::HandleNextBufferWithPreroll( | 1282 SourceBufferStream::Status SourceBufferStream::HandleNextBufferWithPreroll( |
1271 scoped_refptr<StreamParserBuffer>* out_buffer) { | 1283 scoped_refptr<StreamParserBuffer>* out_buffer) { |
1272 // Any config change should have already been handled. | 1284 // Any config change should have already been handled. |
1273 DCHECK_EQ(current_config_index_, pending_buffer_->GetConfigId()); | 1285 DCHECK_EQ(current_config_index_, pending_buffer_->GetConfigId()); |
1274 | 1286 |
1275 // Check if the preroll buffer has already been handed out. | 1287 // Check if the preroll buffer has already been handed out. |
1276 if (!pending_buffers_complete_) { | 1288 if (!pending_buffers_complete_) { |
1277 pending_buffers_complete_ = true; | 1289 pending_buffers_complete_ = true; |
1278 *out_buffer = pending_buffer_->preroll_buffer(); | 1290 *out_buffer = pending_buffer_->preroll_buffer(); |
1279 return SourceBufferStream::kSuccess; | 1291 return SourceBufferStream::kSuccess; |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1331 | 1343 |
1332 if (selected_range_->GetNextConfigId() != current_config_index_) { | 1344 if (selected_range_->GetNextConfigId() != current_config_index_) { |
1333 config_change_pending_ = true; | 1345 config_change_pending_ = true; |
1334 DVLOG(1) << "Config change (selected range config ID does not match)."; | 1346 DVLOG(1) << "Config change (selected range config ID does not match)."; |
1335 return kConfigChange; | 1347 return kConfigChange; |
1336 } | 1348 } |
1337 | 1349 |
1338 CHECK(selected_range_->GetNextBuffer(out_buffer)); | 1350 CHECK(selected_range_->GetNextBuffer(out_buffer)); |
1339 WarnIfTrackBufferExhaustionSkipsForward(*out_buffer); | 1351 WarnIfTrackBufferExhaustionSkipsForward(*out_buffer); |
1340 last_output_buffer_timestamp_ = (*out_buffer)->GetDecodeTimestamp(); | 1352 last_output_buffer_timestamp_ = (*out_buffer)->GetDecodeTimestamp(); |
1353 DVLOG(3) << "Last output buffer DTS:" | |
wolenetz
2016/10/28 23:08:19
nit: Also include similar log in line 1328, and di
chcunningham
2016/11/02 01:28:42
I actually don't mean to land this log. Its a bit
| |
1354 << last_output_buffer_timestamp_.InMicroseconds(); | |
1341 return kSuccess; | 1355 return kSuccess; |
1342 } | 1356 } |
1343 | 1357 |
1344 void SourceBufferStream::WarnIfTrackBufferExhaustionSkipsForward( | 1358 void SourceBufferStream::WarnIfTrackBufferExhaustionSkipsForward( |
1345 const scoped_refptr<StreamParserBuffer>& next_buffer) { | 1359 const scoped_refptr<StreamParserBuffer>& next_buffer) { |
1346 if (!just_exhausted_track_buffer_) | 1360 if (!just_exhausted_track_buffer_) |
1347 return; | 1361 return; |
1348 | 1362 |
1349 just_exhausted_track_buffer_ = false; | 1363 just_exhausted_track_buffer_ = false; |
1350 DCHECK(next_buffer->is_key_frame()); | 1364 DCHECK(next_buffer->is_key_frame()); |
(...skipping 217 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1568 append_config_index_ = video_configs_.size(); | 1582 append_config_index_ = video_configs_.size(); |
1569 DVLOG(2) << "New video config - index: " << append_config_index_; | 1583 DVLOG(2) << "New video config - index: " << append_config_index_; |
1570 video_configs_.resize(video_configs_.size() + 1); | 1584 video_configs_.resize(video_configs_.size() + 1); |
1571 video_configs_[append_config_index_] = config; | 1585 video_configs_[append_config_index_] = config; |
1572 return true; | 1586 return true; |
1573 } | 1587 } |
1574 | 1588 |
1575 void SourceBufferStream::CompleteConfigChange() { | 1589 void SourceBufferStream::CompleteConfigChange() { |
1576 config_change_pending_ = false; | 1590 config_change_pending_ = false; |
1577 | 1591 |
1578 if (pending_buffer_.get()) { | |
1579 current_config_index_ = | |
1580 pending_buffer_->GetSpliceBufferConfigId(splice_buffers_index_); | |
1581 return; | |
1582 } | |
1583 | |
1584 if (!track_buffer_.empty()) { | 1592 if (!track_buffer_.empty()) { |
1585 current_config_index_ = track_buffer_.front()->GetSpliceBufferConfigId(0); | 1593 current_config_index_ = track_buffer_.front()->GetSpliceBufferConfigId(0); |
1586 return; | 1594 return; |
1587 } | 1595 } |
1588 | 1596 |
1589 if (selected_range_ && selected_range_->HasNextBuffer()) | 1597 if (selected_range_ && selected_range_->HasNextBuffer()) |
1590 current_config_index_ = selected_range_->GetNextConfigId(); | 1598 current_config_index_ = selected_range_->GetNextConfigId(); |
1591 } | 1599 } |
1592 | 1600 |
1593 void SourceBufferStream::SetSelectedRangeIfNeeded( | 1601 void SourceBufferStream::SetSelectedRangeIfNeeded( |
(...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1720 if (*itr == range_for_next_append_) { | 1728 if (*itr == range_for_next_append_) { |
1721 DVLOG(1) << __func__ << " deleting range_for_next_append_."; | 1729 DVLOG(1) << __func__ << " deleting range_for_next_append_."; |
1722 range_for_next_append_ = ranges_.end(); | 1730 range_for_next_append_ = ranges_.end(); |
1723 ResetLastAppendedState(); | 1731 ResetLastAppendedState(); |
1724 } | 1732 } |
1725 | 1733 |
1726 delete **itr; | 1734 delete **itr; |
1727 *itr = ranges_.erase(*itr); | 1735 *itr = ranges_.erase(*itr); |
1728 } | 1736 } |
1729 | 1737 |
1730 void SourceBufferStream::GenerateSpliceFrame(const BufferQueue& new_buffers) { | |
1731 DCHECK(!new_buffers.empty()); | |
1732 | |
1733 // Splice frames are only supported for audio. | |
1734 if (GetType() != kAudio) | |
1735 return; | |
1736 | |
1737 // Find the overlapped range (if any). | |
1738 const base::TimeDelta splice_timestamp = new_buffers.front()->timestamp(); | |
1739 const DecodeTimestamp splice_dts = | |
1740 DecodeTimestamp::FromPresentationTime(splice_timestamp); | |
1741 RangeList::iterator range_itr = FindExistingRangeFor(splice_dts); | |
1742 if (range_itr == ranges_.end()) | |
1743 return; | |
1744 | |
1745 const DecodeTimestamp max_splice_end_dts = | |
1746 splice_dts + base::TimeDelta::FromMilliseconds( | |
1747 AudioSplicer::kCrossfadeDurationInMilliseconds); | |
1748 | |
1749 // Find all buffers involved before the splice point. | |
1750 BufferQueue pre_splice_buffers; | |
1751 if (!(*range_itr)->GetBuffersInRange( | |
1752 splice_dts, max_splice_end_dts, &pre_splice_buffers)) { | |
1753 return; | |
1754 } | |
1755 | |
1756 // If there are gaps in the timeline, it's possible that we only find buffers | |
1757 // after the splice point but within the splice range. For simplicity, we do | |
1758 // not generate splice frames in this case. | |
1759 // | |
1760 // We also do not want to generate splices if the first new buffer replaces an | |
1761 // existing buffer exactly. | |
1762 if (pre_splice_buffers.front()->timestamp() >= splice_timestamp) { | |
1763 LIMITED_MEDIA_LOG(DEBUG, media_log_, num_splice_generation_warning_logs_, | |
1764 kMaxSpliceGenerationWarningLogs) | |
1765 << "Skipping splice frame generation: first new buffer at " | |
1766 << splice_timestamp.InMicroseconds() | |
1767 << "us begins at or before existing buffer at " | |
1768 << pre_splice_buffers.front()->timestamp().InMicroseconds() << "us."; | |
1769 DVLOG(1) << "Skipping splice: overlapped buffers begin at or after the " | |
1770 "first new buffer."; | |
1771 return; | |
1772 } | |
1773 | |
1774 // If any |pre_splice_buffers| are already splices or preroll, do not generate | |
1775 // a splice. | |
1776 for (size_t i = 0; i < pre_splice_buffers.size(); ++i) { | |
1777 const BufferQueue& original_splice_buffers = | |
1778 pre_splice_buffers[i]->splice_buffers(); | |
1779 if (!original_splice_buffers.empty()) { | |
1780 LIMITED_MEDIA_LOG(DEBUG, media_log_, num_splice_generation_warning_logs_, | |
1781 kMaxSpliceGenerationWarningLogs) | |
1782 << "Skipping splice frame generation: overlapped buffers at " | |
1783 << pre_splice_buffers[i]->timestamp().InMicroseconds() | |
1784 << "us are in a previously buffered splice."; | |
1785 DVLOG(1) << "Can't generate splice: overlapped buffers contain a " | |
1786 "pre-existing splice."; | |
1787 return; | |
1788 } | |
1789 | |
1790 if (pre_splice_buffers[i]->preroll_buffer().get()) { | |
1791 LIMITED_MEDIA_LOG(DEBUG, media_log_, num_splice_generation_warning_logs_, | |
1792 kMaxSpliceGenerationWarningLogs) | |
1793 << "Skipping splice frame generation: overlapped buffers at " | |
1794 << pre_splice_buffers[i]->timestamp().InMicroseconds() | |
1795 << "us contain preroll."; | |
1796 DVLOG(1) << "Can't generate splice: overlapped buffers contain preroll."; | |
1797 return; | |
1798 } | |
1799 } | |
1800 | |
1801 // Don't generate splice frames which represent less than a millisecond (which | |
1802 // is frequently the extent of timestamp resolution for poorly encoded media) | |
1803 // or less than two samples (need at least two to crossfade). | |
1804 const base::TimeDelta splice_duration = | |
1805 pre_splice_buffers.back()->timestamp() + | |
1806 pre_splice_buffers.back()->duration() - splice_timestamp; | |
1807 const base::TimeDelta minimum_splice_duration = std::max( | |
1808 base::TimeDelta::FromMilliseconds(1), | |
1809 base::TimeDelta::FromSecondsD( | |
1810 2.0 / audio_configs_[append_config_index_].samples_per_second())); | |
1811 if (splice_duration < minimum_splice_duration) { | |
1812 LIMITED_MEDIA_LOG(DEBUG, media_log_, num_splice_generation_warning_logs_, | |
1813 kMaxSpliceGenerationWarningLogs) | |
1814 << "Skipping splice frame generation: not enough samples for splicing " | |
1815 "new buffer at " | |
1816 << splice_timestamp.InMicroseconds() << "us. Have " | |
1817 << splice_duration.InMicroseconds() << "us, but need " | |
1818 << minimum_splice_duration.InMicroseconds() << "us."; | |
1819 DVLOG(1) << "Can't generate splice: not enough samples for crossfade; have " | |
1820 << splice_duration.InMicroseconds() << "us, but need " | |
1821 << minimum_splice_duration.InMicroseconds() << "us."; | |
1822 return; | |
1823 } | |
1824 | |
1825 DVLOG(1) << "Generating splice frame @ " << new_buffers.front()->timestamp() | |
1826 << ", splice duration: " << splice_duration.InMicroseconds() | |
1827 << " us"; | |
1828 LIMITED_MEDIA_LOG(DEBUG, media_log_, num_splice_generation_success_logs_, | |
1829 kMaxSpliceGenerationSuccessLogs) | |
1830 << "Generated splice of overlap duration " | |
1831 << splice_duration.InMicroseconds() << "us into new buffer at " | |
1832 << splice_timestamp.InMicroseconds() << "us."; | |
1833 new_buffers.front()->ConvertToSpliceBuffer(pre_splice_buffers); | |
1834 } | |
1835 | |
1836 bool SourceBufferStream::SetPendingBuffer( | 1738 bool SourceBufferStream::SetPendingBuffer( |
1837 scoped_refptr<StreamParserBuffer>* out_buffer) { | 1739 scoped_refptr<StreamParserBuffer>* out_buffer) { |
1838 DCHECK(out_buffer->get()); | 1740 DCHECK(out_buffer->get()); |
1839 DCHECK(!pending_buffer_.get()); | 1741 DCHECK(!pending_buffer_.get()); |
1840 | 1742 |
1841 const bool have_splice_buffers = !(*out_buffer)->splice_buffers().empty(); | |
1842 const bool have_preroll_buffer = !!(*out_buffer)->preroll_buffer().get(); | 1743 const bool have_preroll_buffer = !!(*out_buffer)->preroll_buffer().get(); |
1843 | 1744 |
1844 if (!have_splice_buffers && !have_preroll_buffer) | 1745 if (!have_preroll_buffer) |
1845 return false; | 1746 return false; |
1846 | 1747 |
1847 DCHECK_NE(have_splice_buffers, have_preroll_buffer); | |
1848 splice_buffers_index_ = 0; | |
1849 pending_buffer_.swap(*out_buffer); | 1748 pending_buffer_.swap(*out_buffer); |
1850 pending_buffers_complete_ = false; | 1749 pending_buffers_complete_ = false; |
1851 return true; | 1750 return true; |
1852 } | 1751 } |
1853 | 1752 |
1854 } // namespace media | 1753 } // namespace media |
OLD | NEW |