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 | 10 |
(...skipping 19 matching lines...) Expand all Loading... |
30 // important for debugging splice generation. | 30 // important for debugging splice generation. |
31 const int kMaxSpliceGenerationWarningLogs = 50; | 31 const int kMaxSpliceGenerationWarningLogs = 50; |
32 const int kMaxSpliceGenerationSuccessLogs = 20; | 32 const int kMaxSpliceGenerationSuccessLogs = 20; |
33 | 33 |
34 // Limit the number of MEDIA_LOG() logs for track buffer time gaps. | 34 // Limit the number of MEDIA_LOG() logs for track buffer time gaps. |
35 const int kMaxTrackBufferGapWarningLogs = 20; | 35 const int kMaxTrackBufferGapWarningLogs = 20; |
36 | 36 |
37 // Limit the number of MEDIA_LOG() logs for MSE GC algorithm warnings. | 37 // Limit the number of MEDIA_LOG() logs for MSE GC algorithm warnings. |
38 const int kMaxGarbageCollectAlgorithmWarningLogs = 20; | 38 const int kMaxGarbageCollectAlgorithmWarningLogs = 20; |
39 | 39 |
| 40 // 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 |
| 42 // 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 |
| 44 // 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 |
| 46 // work or other side-effects. |
| 47 const int kMaxStrangeSameTimestampsLogs = 20; |
| 48 |
40 // Helper method that returns true if |ranges| is sorted in increasing order, | 49 // Helper method that returns true if |ranges| is sorted in increasing order, |
41 // false otherwise. | 50 // false otherwise. |
42 bool IsRangeListSorted(const std::list<media::SourceBufferRange*>& ranges) { | 51 bool IsRangeListSorted(const std::list<media::SourceBufferRange*>& ranges) { |
43 DecodeTimestamp prev = kNoDecodeTimestamp(); | 52 DecodeTimestamp prev = kNoDecodeTimestamp(); |
44 for (std::list<SourceBufferRange*>::const_iterator itr = | 53 for (std::list<SourceBufferRange*>::const_iterator itr = |
45 ranges.begin(); itr != ranges.end(); ++itr) { | 54 ranges.begin(); itr != ranges.end(); ++itr) { |
46 if (prev != kNoDecodeTimestamp() && prev >= (*itr)->GetStartTimestamp()) | 55 if (prev != kNoDecodeTimestamp() && prev >= (*itr)->GetStartTimestamp()) |
47 return false; | 56 return false; |
48 prev = (*itr)->GetEndTimestamp(); | 57 prev = (*itr)->GetEndTimestamp(); |
49 } | 58 } |
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
130 return SourceBufferRange::NO_GAPS_ALLOWED; | 139 return SourceBufferRange::NO_GAPS_ALLOWED; |
131 } | 140 } |
132 | 141 |
133 } // namespace | 142 } // namespace |
134 | 143 |
135 SourceBufferStream::SourceBufferStream(const AudioDecoderConfig& audio_config, | 144 SourceBufferStream::SourceBufferStream(const AudioDecoderConfig& audio_config, |
136 const scoped_refptr<MediaLog>& media_log, | 145 const scoped_refptr<MediaLog>& media_log, |
137 bool splice_frames_enabled) | 146 bool splice_frames_enabled) |
138 : media_log_(media_log), | 147 : media_log_(media_log), |
139 seek_buffer_timestamp_(kNoTimestamp()), | 148 seek_buffer_timestamp_(kNoTimestamp()), |
140 media_segment_start_time_(kNoDecodeTimestamp()), | 149 coded_frame_group_start_time_(kNoDecodeTimestamp()), |
141 range_for_next_append_(ranges_.end()), | 150 range_for_next_append_(ranges_.end()), |
142 last_output_buffer_timestamp_(kNoDecodeTimestamp()), | 151 last_output_buffer_timestamp_(kNoDecodeTimestamp()), |
143 max_interbuffer_distance_(kNoTimestamp()), | 152 max_interbuffer_distance_(kNoTimestamp()), |
144 memory_limit_(kSourceBufferAudioMemoryLimit), | 153 memory_limit_(kSourceBufferAudioMemoryLimit), |
145 splice_frames_enabled_(splice_frames_enabled) { | 154 splice_frames_enabled_(splice_frames_enabled) { |
146 DCHECK(audio_config.IsValidConfig()); | 155 DCHECK(audio_config.IsValidConfig()); |
147 audio_configs_.push_back(audio_config); | 156 audio_configs_.push_back(audio_config); |
148 } | 157 } |
149 | 158 |
150 SourceBufferStream::SourceBufferStream(const VideoDecoderConfig& video_config, | 159 SourceBufferStream::SourceBufferStream(const VideoDecoderConfig& video_config, |
151 const scoped_refptr<MediaLog>& media_log, | 160 const scoped_refptr<MediaLog>& media_log, |
152 bool splice_frames_enabled) | 161 bool splice_frames_enabled) |
153 : media_log_(media_log), | 162 : media_log_(media_log), |
154 seek_buffer_timestamp_(kNoTimestamp()), | 163 seek_buffer_timestamp_(kNoTimestamp()), |
155 media_segment_start_time_(kNoDecodeTimestamp()), | 164 coded_frame_group_start_time_(kNoDecodeTimestamp()), |
156 range_for_next_append_(ranges_.end()), | 165 range_for_next_append_(ranges_.end()), |
157 last_output_buffer_timestamp_(kNoDecodeTimestamp()), | 166 last_output_buffer_timestamp_(kNoDecodeTimestamp()), |
158 max_interbuffer_distance_(kNoTimestamp()), | 167 max_interbuffer_distance_(kNoTimestamp()), |
159 memory_limit_(kSourceBufferVideoMemoryLimit), | 168 memory_limit_(kSourceBufferVideoMemoryLimit), |
160 splice_frames_enabled_(splice_frames_enabled) { | 169 splice_frames_enabled_(splice_frames_enabled) { |
161 DCHECK(video_config.IsValidConfig()); | 170 DCHECK(video_config.IsValidConfig()); |
162 video_configs_.push_back(video_config); | 171 video_configs_.push_back(video_config); |
163 } | 172 } |
164 | 173 |
165 SourceBufferStream::SourceBufferStream(const TextTrackConfig& text_config, | 174 SourceBufferStream::SourceBufferStream(const TextTrackConfig& text_config, |
166 const scoped_refptr<MediaLog>& media_log, | 175 const scoped_refptr<MediaLog>& media_log, |
167 bool splice_frames_enabled) | 176 bool splice_frames_enabled) |
168 : media_log_(media_log), | 177 : media_log_(media_log), |
169 text_track_config_(text_config), | 178 text_track_config_(text_config), |
170 seek_buffer_timestamp_(kNoTimestamp()), | 179 seek_buffer_timestamp_(kNoTimestamp()), |
171 media_segment_start_time_(kNoDecodeTimestamp()), | 180 coded_frame_group_start_time_(kNoDecodeTimestamp()), |
172 range_for_next_append_(ranges_.end()), | 181 range_for_next_append_(ranges_.end()), |
173 last_output_buffer_timestamp_(kNoDecodeTimestamp()), | 182 last_output_buffer_timestamp_(kNoDecodeTimestamp()), |
174 max_interbuffer_distance_(kNoTimestamp()), | 183 max_interbuffer_distance_(kNoTimestamp()), |
175 memory_limit_(kSourceBufferAudioMemoryLimit), | 184 memory_limit_(kSourceBufferAudioMemoryLimit), |
176 splice_frames_enabled_(splice_frames_enabled) {} | 185 splice_frames_enabled_(splice_frames_enabled) {} |
177 | 186 |
178 SourceBufferStream::~SourceBufferStream() { | 187 SourceBufferStream::~SourceBufferStream() { |
179 while (!ranges_.empty()) { | 188 while (!ranges_.empty()) { |
180 delete ranges_.front(); | 189 delete ranges_.front(); |
181 ranges_.pop_front(); | 190 ranges_.pop_front(); |
182 } | 191 } |
183 } | 192 } |
184 | 193 |
185 void SourceBufferStream::OnNewMediaSegment( | 194 void SourceBufferStream::OnStartOfCodedFrameGroup( |
186 DecodeTimestamp media_segment_start_time) { | 195 DecodeTimestamp coded_frame_group_start_time) { |
187 DVLOG(1) << __FUNCTION__ << " " << GetStreamTypeName() | 196 DVLOG(1) << __FUNCTION__ << " " << GetStreamTypeName() << " (" |
188 << " (" << media_segment_start_time.InSecondsF() << ")"; | 197 << coded_frame_group_start_time.InSecondsF() << ")"; |
189 DCHECK(!end_of_stream_); | 198 DCHECK(!end_of_stream_); |
190 media_segment_start_time_ = media_segment_start_time; | 199 coded_frame_group_start_time_ = coded_frame_group_start_time; |
191 new_media_segment_ = true; | 200 new_coded_frame_group_ = true; |
192 | 201 |
193 RangeList::iterator last_range = range_for_next_append_; | 202 RangeList::iterator last_range = range_for_next_append_; |
194 range_for_next_append_ = FindExistingRangeFor(media_segment_start_time); | 203 range_for_next_append_ = FindExistingRangeFor(coded_frame_group_start_time); |
195 | 204 |
196 // Only reset |last_appended_buffer_timestamp_| if this new media segment is | 205 // Only reset |last_appended_buffer_timestamp_| if this new coded frame group |
197 // not adjacent to the previous media segment appended to the stream. | 206 // is not adjacent to the previous coded frame group appended to the stream. |
198 if (range_for_next_append_ == ranges_.end() || | 207 if (range_for_next_append_ == ranges_.end() || |
199 !AreAdjacentInSequence(last_appended_buffer_timestamp_, | 208 !AreAdjacentInSequence(last_appended_buffer_timestamp_, |
200 media_segment_start_time)) { | 209 coded_frame_group_start_time)) { |
201 last_appended_buffer_timestamp_ = kNoDecodeTimestamp(); | 210 last_appended_buffer_timestamp_ = kNoDecodeTimestamp(); |
202 last_appended_buffer_duration_ = kNoTimestamp(); | 211 last_appended_buffer_duration_ = kNoTimestamp(); |
203 last_appended_buffer_is_keyframe_ = false; | 212 last_appended_buffer_is_keyframe_ = false; |
204 DVLOG(3) << __FUNCTION__ << " next appended buffers will be in a new range"; | 213 DVLOG(3) << __FUNCTION__ << " next appended buffers will be in a new range"; |
205 } else if (last_range != ranges_.end()) { | 214 } else if (last_range != ranges_.end()) { |
206 DCHECK(last_range == range_for_next_append_); | 215 DCHECK(last_range == range_for_next_append_); |
207 DVLOG(3) << __FUNCTION__ << " next appended buffers will continue range " | 216 DVLOG(3) << __FUNCTION__ << " next appended buffers will continue range " |
208 << "unless intervening remove makes discontinuity"; | 217 << "unless intervening remove makes discontinuity"; |
209 } | 218 } |
210 } | 219 } |
211 | 220 |
212 bool SourceBufferStream::Append(const BufferQueue& buffers) { | 221 bool SourceBufferStream::Append(const BufferQueue& buffers) { |
213 TRACE_EVENT2("media", "SourceBufferStream::Append", | 222 TRACE_EVENT2("media", "SourceBufferStream::Append", |
214 "stream type", GetStreamTypeName(), | 223 "stream type", GetStreamTypeName(), |
215 "buffers to append", buffers.size()); | 224 "buffers to append", buffers.size()); |
216 | 225 |
217 DCHECK(!buffers.empty()); | 226 DCHECK(!buffers.empty()); |
218 DCHECK(media_segment_start_time_ != kNoDecodeTimestamp()); | 227 DCHECK(coded_frame_group_start_time_ != kNoDecodeTimestamp()); |
219 DCHECK(media_segment_start_time_ <= buffers.front()->GetDecodeTimestamp()); | 228 DCHECK(coded_frame_group_start_time_ <= |
| 229 buffers.front()->GetDecodeTimestamp()); |
220 DCHECK(!end_of_stream_); | 230 DCHECK(!end_of_stream_); |
221 | 231 |
222 DVLOG(1) << __FUNCTION__ << " " << GetStreamTypeName() | 232 DVLOG(1) << __FUNCTION__ << " " << GetStreamTypeName() |
223 << ": buffers " << BufferQueueToLogString(buffers); | 233 << ": buffers " << BufferQueueToLogString(buffers); |
224 | 234 |
225 // New media segments must begin with a keyframe. | 235 // New coded frame groups emitted by the coded frame processor must begin with |
226 // TODO(wolenetz): Relax this requirement. See http://crbug.com/229412. | 236 // a keyframe. TODO(wolenetz): Change this to [DCHECK + MEDIA_LOG(ERROR...) + |
227 if (new_media_segment_ && !buffers.front()->is_key_frame()) { | 237 // return false] once the CHECK has baked in a stable release. See |
228 MEDIA_LOG(ERROR, media_log_) << "Media segment did not begin with key " | 238 // https://crbug.com/580621. |
229 "frame. Support for such segments will be " | 239 CHECK(!new_coded_frame_group_ || buffers.front()->is_key_frame()); |
230 "available in a future version. Please see " | 240 |
231 "https://crbug.com/229412."; | 241 // Buffers within a coded frame group should be monotonically increasing. |
| 242 if (!IsMonotonicallyIncreasing(buffers)) { |
232 return false; | 243 return false; |
233 } | 244 } |
234 | 245 |
235 // Buffers within a media segment should be monotonically increasing. | 246 if (coded_frame_group_start_time_ < DecodeTimestamp() || |
236 if (!IsMonotonicallyIncreasing(buffers)) | |
237 return false; | |
238 | |
239 if (media_segment_start_time_ < DecodeTimestamp() || | |
240 buffers.front()->GetDecodeTimestamp() < DecodeTimestamp()) { | 247 buffers.front()->GetDecodeTimestamp() < DecodeTimestamp()) { |
241 MEDIA_LOG(ERROR, media_log_) | 248 MEDIA_LOG(ERROR, media_log_) |
242 << "Cannot append a media segment with negative timestamps."; | 249 << "Cannot append a coded frame group with negative timestamps."; |
243 return false; | 250 return false; |
244 } | 251 } |
245 | 252 |
246 if (!IsNextTimestampValid(buffers.front()->GetDecodeTimestamp(), | |
247 buffers.front()->is_key_frame())) { | |
248 const DecodeTimestamp& dts = buffers.front()->GetDecodeTimestamp(); | |
249 MEDIA_LOG(ERROR, media_log_) | |
250 << "Invalid same timestamp construct detected at" | |
251 << " time " << dts.InSecondsF(); | |
252 | |
253 return false; | |
254 } | |
255 | |
256 UpdateMaxInterbufferDistance(buffers); | 253 UpdateMaxInterbufferDistance(buffers); |
257 SetConfigIds(buffers); | 254 SetConfigIds(buffers); |
258 | 255 |
259 // Save a snapshot of stream state before range modifications are made. | 256 // Save a snapshot of stream state before range modifications are made. |
260 DecodeTimestamp next_buffer_timestamp = GetNextBufferTimestamp(); | 257 DecodeTimestamp next_buffer_timestamp = GetNextBufferTimestamp(); |
261 BufferQueue deleted_buffers; | 258 BufferQueue deleted_buffers; |
262 | 259 |
263 PrepareRangesForNextAppend(buffers, &deleted_buffers); | 260 PrepareRangesForNextAppend(buffers, &deleted_buffers); |
264 | 261 |
265 // If there's a range for |buffers|, insert |buffers| accordingly. Otherwise, | 262 // If there's a range for |buffers|, insert |buffers| accordingly. Otherwise, |
266 // create a new range with |buffers|. | 263 // create a new range with |buffers|. |
267 if (range_for_next_append_ != ranges_.end()) { | 264 if (range_for_next_append_ != ranges_.end()) { |
268 (*range_for_next_append_)->AppendBuffersToEnd(buffers); | 265 (*range_for_next_append_)->AppendBuffersToEnd(buffers); |
269 last_appended_buffer_timestamp_ = buffers.back()->GetDecodeTimestamp(); | 266 last_appended_buffer_timestamp_ = buffers.back()->GetDecodeTimestamp(); |
270 last_appended_buffer_duration_ = buffers.back()->duration(); | 267 last_appended_buffer_duration_ = buffers.back()->duration(); |
271 last_appended_buffer_is_keyframe_ = buffers.back()->is_key_frame(); | 268 last_appended_buffer_is_keyframe_ = buffers.back()->is_key_frame(); |
272 } else { | 269 } else { |
273 DecodeTimestamp new_range_start_time = std::min( | 270 DecodeTimestamp new_range_start_time = std::min( |
274 media_segment_start_time_, buffers.front()->GetDecodeTimestamp()); | 271 coded_frame_group_start_time_, buffers.front()->GetDecodeTimestamp()); |
275 const BufferQueue* buffers_for_new_range = &buffers; | 272 const BufferQueue* buffers_for_new_range = &buffers; |
276 BufferQueue trimmed_buffers; | 273 BufferQueue trimmed_buffers; |
277 | 274 |
278 // If the new range is not being created because of a new media | 275 // If the new range is not being created because of a new coded frame group, |
279 // segment, then we must make sure that we start with a key frame. | 276 // then we must make sure that we start with a key frame. This can happen |
280 // This can happen if the GOP in the previous append gets destroyed | 277 // if the GOP in the previous append gets destroyed by a Remove() call. |
281 // by a Remove() call. | 278 if (!new_coded_frame_group_) { |
282 if (!new_media_segment_) { | |
283 BufferQueue::const_iterator itr = buffers.begin(); | 279 BufferQueue::const_iterator itr = buffers.begin(); |
284 | 280 |
285 // Scan past all the non-key-frames. | 281 // Scan past all the non-key-frames. |
286 while (itr != buffers.end() && !(*itr)->is_key_frame()) { | 282 while (itr != buffers.end() && !(*itr)->is_key_frame()) { |
287 ++itr; | 283 ++itr; |
288 } | 284 } |
289 | 285 |
290 // If we didn't find a key frame, then update the last appended | 286 // If we didn't find a key frame, then update the last appended |
291 // buffer state and return. | 287 // buffer state and return. |
292 if (itr == buffers.end()) { | 288 if (itr == buffers.end()) { |
293 last_appended_buffer_timestamp_ = buffers.back()->GetDecodeTimestamp(); | 289 last_appended_buffer_timestamp_ = buffers.back()->GetDecodeTimestamp(); |
294 last_appended_buffer_duration_ = buffers.back()->duration(); | 290 last_appended_buffer_duration_ = buffers.back()->duration(); |
295 last_appended_buffer_is_keyframe_ = buffers.back()->is_key_frame(); | 291 last_appended_buffer_is_keyframe_ = buffers.back()->is_key_frame(); |
296 DVLOG(1) << __FUNCTION__ << " " << GetStreamTypeName() | 292 DVLOG(1) << __FUNCTION__ << " " << GetStreamTypeName() |
297 << ": new buffers in the middle of media segment depend on" | 293 << ": new buffers in the middle of coded frame group depend on" |
298 "keyframe that has been removed, and contain no keyframes." | 294 "keyframe that has been removed, and contain no keyframes." |
299 "Skipping further processing."; | 295 "Skipping further processing."; |
300 DVLOG(1) << __FUNCTION__ << " " << GetStreamTypeName() | 296 DVLOG(1) << __FUNCTION__ << " " << GetStreamTypeName() |
301 << ": done. ranges_=" << RangesToString(ranges_); | 297 << ": done. ranges_=" << RangesToString(ranges_); |
302 return true; | 298 return true; |
303 } else if (itr != buffers.begin()) { | 299 } else if (itr != buffers.begin()) { |
304 // Copy the first key frame and everything after it into | 300 // Copy the first key frame and everything after it into |
305 // |trimmed_buffers|. | 301 // |trimmed_buffers|. |
306 trimmed_buffers.assign(itr, buffers.end()); | 302 trimmed_buffers.assign(itr, buffers.end()); |
307 buffers_for_new_range = &trimmed_buffers; | 303 buffers_for_new_range = &trimmed_buffers; |
308 } | 304 } |
309 | 305 |
310 new_range_start_time = | 306 new_range_start_time = |
311 buffers_for_new_range->front()->GetDecodeTimestamp(); | 307 buffers_for_new_range->front()->GetDecodeTimestamp(); |
312 } | 308 } |
313 | 309 |
314 range_for_next_append_ = | 310 range_for_next_append_ = |
315 AddToRanges(new SourceBufferRange( | 311 AddToRanges(new SourceBufferRange( |
316 TypeToGapPolicy(GetType()), | 312 TypeToGapPolicy(GetType()), |
317 *buffers_for_new_range, new_range_start_time, | 313 *buffers_for_new_range, new_range_start_time, |
318 base::Bind(&SourceBufferStream::GetMaxInterbufferDistance, | 314 base::Bind(&SourceBufferStream::GetMaxInterbufferDistance, |
319 base::Unretained(this)))); | 315 base::Unretained(this)))); |
320 last_appended_buffer_timestamp_ = | 316 last_appended_buffer_timestamp_ = |
321 buffers_for_new_range->back()->GetDecodeTimestamp(); | 317 buffers_for_new_range->back()->GetDecodeTimestamp(); |
322 last_appended_buffer_duration_ = buffers_for_new_range->back()->duration(); | 318 last_appended_buffer_duration_ = buffers_for_new_range->back()->duration(); |
323 last_appended_buffer_is_keyframe_ = | 319 last_appended_buffer_is_keyframe_ = |
324 buffers_for_new_range->back()->is_key_frame(); | 320 buffers_for_new_range->back()->is_key_frame(); |
325 } | 321 } |
326 | 322 |
327 new_media_segment_ = false; | 323 new_coded_frame_group_ = false; |
328 | 324 |
329 MergeWithAdjacentRangeIfNecessary(range_for_next_append_); | 325 MergeWithAdjacentRangeIfNecessary(range_for_next_append_); |
330 | 326 |
331 // Seek to try to fulfill a previous call to Seek(). | 327 // Seek to try to fulfill a previous call to Seek(). |
332 if (seek_pending_) { | 328 if (seek_pending_) { |
333 DCHECK(!selected_range_); | 329 DCHECK(!selected_range_); |
334 DCHECK(deleted_buffers.empty()); | 330 DCHECK(deleted_buffers.empty()); |
335 Seek(seek_buffer_timestamp_); | 331 Seek(seek_buffer_timestamp_); |
336 } | 332 } |
337 | 333 |
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
433 while (itr != ranges_.end()) { | 429 while (itr != ranges_.end()) { |
434 SourceBufferRange* range = *itr; | 430 SourceBufferRange* range = *itr; |
435 if (range->GetStartTimestamp() >= end) | 431 if (range->GetStartTimestamp() >= end) |
436 break; | 432 break; |
437 | 433 |
438 // Split off any remaining GOPs starting at or after |end| and add it to | 434 // Split off any remaining GOPs starting at or after |end| and add it to |
439 // |ranges_|. | 435 // |ranges_|. |
440 SourceBufferRange* new_range = range->SplitRange(end); | 436 SourceBufferRange* new_range = range->SplitRange(end); |
441 if (new_range) { | 437 if (new_range) { |
442 itr = ranges_.insert(++itr, new_range); | 438 itr = ranges_.insert(++itr, new_range); |
| 439 |
| 440 // Update |range_for_next_append_| if it was previously |range| and should |
| 441 // be |new_range| now. |
| 442 if (range_for_next_append_ != ranges_.end() && |
| 443 *range_for_next_append_ == range && |
| 444 last_appended_buffer_timestamp_ != kNoDecodeTimestamp()) { |
| 445 DecodeTimestamp potential_next_append_timestamp = |
| 446 last_appended_buffer_timestamp_ + |
| 447 base::TimeDelta::FromInternalValue(1); |
| 448 if (new_range->BelongsToRange(potential_next_append_timestamp)) |
| 449 range_for_next_append_ = itr; |
| 450 } |
| 451 |
443 --itr; | 452 --itr; |
444 | 453 |
445 // Update the selected range if the next buffer position was transferred | 454 // Update the selected range if the next buffer position was transferred |
446 // to |new_range|. | 455 // to |new_range|. |
447 if (new_range->HasNextBufferPosition()) | 456 if (new_range->HasNextBufferPosition()) |
448 SetSelectedRange(new_range); | 457 SetSelectedRange(new_range); |
449 } | 458 } |
450 | 459 |
451 // Truncate the current range so that it only contains data before | 460 // Truncate the current range so that it only contains data before |
452 // the removal range. | 461 // the removal range. |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
515 bool SourceBufferStream::ShouldSeekToStartOfBuffered( | 524 bool SourceBufferStream::ShouldSeekToStartOfBuffered( |
516 base::TimeDelta seek_timestamp) const { | 525 base::TimeDelta seek_timestamp) const { |
517 if (ranges_.empty()) | 526 if (ranges_.empty()) |
518 return false; | 527 return false; |
519 base::TimeDelta beginning_of_buffered = | 528 base::TimeDelta beginning_of_buffered = |
520 ranges_.front()->GetStartTimestamp().ToPresentationTime(); | 529 ranges_.front()->GetStartTimestamp().ToPresentationTime(); |
521 return (seek_timestamp <= beginning_of_buffered && | 530 return (seek_timestamp <= beginning_of_buffered && |
522 beginning_of_buffered < kSeekToStartFudgeRoom()); | 531 beginning_of_buffered < kSeekToStartFudgeRoom()); |
523 } | 532 } |
524 | 533 |
525 bool SourceBufferStream::IsMonotonicallyIncreasing( | 534 bool SourceBufferStream::IsMonotonicallyIncreasing(const BufferQueue& buffers) { |
526 const BufferQueue& buffers) const { | |
527 DCHECK(!buffers.empty()); | 535 DCHECK(!buffers.empty()); |
528 DecodeTimestamp prev_timestamp = last_appended_buffer_timestamp_; | 536 DecodeTimestamp prev_timestamp = last_appended_buffer_timestamp_; |
529 bool prev_is_keyframe = last_appended_buffer_is_keyframe_; | 537 bool prev_is_keyframe = last_appended_buffer_is_keyframe_; |
530 for (BufferQueue::const_iterator itr = buffers.begin(); | 538 for (BufferQueue::const_iterator itr = buffers.begin(); |
531 itr != buffers.end(); ++itr) { | 539 itr != buffers.end(); ++itr) { |
532 DecodeTimestamp current_timestamp = (*itr)->GetDecodeTimestamp(); | 540 DecodeTimestamp current_timestamp = (*itr)->GetDecodeTimestamp(); |
533 bool current_is_keyframe = (*itr)->is_key_frame(); | 541 bool current_is_keyframe = (*itr)->is_key_frame(); |
534 DCHECK(current_timestamp != kNoDecodeTimestamp()); | 542 DCHECK(current_timestamp != kNoDecodeTimestamp()); |
535 DCHECK((*itr)->duration() >= base::TimeDelta()) | 543 DCHECK((*itr)->duration() >= base::TimeDelta()) |
536 << "Packet with invalid duration." | 544 << "Packet with invalid duration." |
537 << " pts " << (*itr)->timestamp().InSecondsF() | 545 << " pts " << (*itr)->timestamp().InSecondsF() |
538 << " dts " << (*itr)->GetDecodeTimestamp().InSecondsF() | 546 << " dts " << (*itr)->GetDecodeTimestamp().InSecondsF() |
539 << " dur " << (*itr)->duration().InSecondsF(); | 547 << " dur " << (*itr)->duration().InSecondsF(); |
540 | 548 |
541 if (prev_timestamp != kNoDecodeTimestamp()) { | 549 if (prev_timestamp != kNoDecodeTimestamp()) { |
542 if (current_timestamp < prev_timestamp) { | 550 if (current_timestamp < prev_timestamp) { |
543 MEDIA_LOG(ERROR, media_log_) | 551 MEDIA_LOG(ERROR, media_log_) |
544 << "Buffers did not monotonically increase."; | 552 << "Buffers did not monotonically increase."; |
545 return false; | 553 return false; |
546 } | 554 } |
547 | 555 |
548 if (current_timestamp == prev_timestamp && | 556 if (current_timestamp == prev_timestamp && |
549 !SourceBufferRange::AllowSameTimestamp(prev_is_keyframe, | 557 SourceBufferRange::IsUncommonSameTimestampSequence( |
550 current_is_keyframe)) { | 558 prev_is_keyframe, current_is_keyframe)) { |
551 MEDIA_LOG(ERROR, media_log_) << "Unexpected combination of buffers with" | 559 LIMITED_MEDIA_LOG(DEBUG, media_log_, num_strange_same_timestamps_logs_, |
552 << " the same timestamp detected at " | 560 kMaxStrangeSameTimestampsLogs) |
553 << current_timestamp.InSecondsF(); | 561 << "Detected an append sequence with keyframe following a " |
554 return false; | 562 "non-keyframe, both with the same decode timestamp of " |
| 563 << current_timestamp.InSecondsF(); |
555 } | 564 } |
556 } | 565 } |
557 | 566 |
558 prev_timestamp = current_timestamp; | 567 prev_timestamp = current_timestamp; |
559 prev_is_keyframe = current_is_keyframe; | 568 prev_is_keyframe = current_is_keyframe; |
560 } | 569 } |
561 return true; | 570 return true; |
562 } | 571 } |
563 | 572 |
564 bool SourceBufferStream::IsNextTimestampValid( | |
565 DecodeTimestamp next_timestamp, bool next_is_keyframe) const { | |
566 return (last_appended_buffer_timestamp_ != next_timestamp) || | |
567 new_media_segment_ || | |
568 SourceBufferRange::AllowSameTimestamp(last_appended_buffer_is_keyframe_, | |
569 next_is_keyframe); | |
570 } | |
571 | |
572 | |
573 bool SourceBufferStream::OnlySelectedRangeIsSeeked() const { | 573 bool SourceBufferStream::OnlySelectedRangeIsSeeked() const { |
574 for (RangeList::const_iterator itr = ranges_.begin(); | 574 for (RangeList::const_iterator itr = ranges_.begin(); |
575 itr != ranges_.end(); ++itr) { | 575 itr != ranges_.end(); ++itr) { |
576 if ((*itr)->HasNextBufferPosition() && (*itr) != selected_range_) | 576 if ((*itr)->HasNextBufferPosition() && (*itr) != selected_range_) |
577 return false; | 577 return false; |
578 } | 578 } |
579 return !selected_range_ || selected_range_->HasNextBufferPosition(); | 579 return !selected_range_ || selected_range_->HasNextBufferPosition(); |
580 } | 580 } |
581 | 581 |
582 void SourceBufferStream::UpdateMaxInterbufferDistance( | 582 void SourceBufferStream::UpdateMaxInterbufferDistance( |
(...skipping 337 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
920 const BufferQueue& new_buffers, BufferQueue* deleted_buffers) { | 920 const BufferQueue& new_buffers, BufferQueue* deleted_buffers) { |
921 DCHECK(deleted_buffers); | 921 DCHECK(deleted_buffers); |
922 | 922 |
923 // Handle splices between the existing buffers and the new buffers. If a | 923 // Handle splices between the existing buffers and the new buffers. If a |
924 // splice is generated the timestamp and duration of the first buffer in | 924 // splice is generated the timestamp and duration of the first buffer in |
925 // |new_buffers| will be modified. | 925 // |new_buffers| will be modified. |
926 if (splice_frames_enabled_) | 926 if (splice_frames_enabled_) |
927 GenerateSpliceFrame(new_buffers); | 927 GenerateSpliceFrame(new_buffers); |
928 | 928 |
929 DecodeTimestamp prev_timestamp = last_appended_buffer_timestamp_; | 929 DecodeTimestamp prev_timestamp = last_appended_buffer_timestamp_; |
930 bool prev_is_keyframe = last_appended_buffer_is_keyframe_; | |
931 DecodeTimestamp next_timestamp = new_buffers.front()->GetDecodeTimestamp(); | 930 DecodeTimestamp next_timestamp = new_buffers.front()->GetDecodeTimestamp(); |
932 bool next_is_keyframe = new_buffers.front()->is_key_frame(); | |
933 | 931 |
934 if (prev_timestamp != kNoDecodeTimestamp() && | 932 if (prev_timestamp != kNoDecodeTimestamp() && |
935 prev_timestamp != next_timestamp) { | 933 prev_timestamp != next_timestamp) { |
936 // Clean up the old buffers between the last appended buffer and the | 934 // Clean up the old buffers between the last appended buffer and the |
937 // beginning of |new_buffers|. | 935 // beginning of |new_buffers|. |
938 RemoveInternal(prev_timestamp, next_timestamp, true, deleted_buffers); | 936 RemoveInternal(prev_timestamp, next_timestamp, true, deleted_buffers); |
939 } | 937 } |
940 | 938 |
941 // Make the delete range exclusive if we are dealing with an allowed same | 939 // Always make the start of the delete range exclusive for same timestamp |
942 // timestamp situation. This prevents the first buffer in the current append | 940 // across the last buffer in the previous append and the first buffer in the |
943 // from deleting the last buffer in the previous append if both buffers | 941 // current append. Never be exclusive if a splice frame was generated because |
944 // have the same timestamp. | 942 // we don't generate splice frames for same timestamp situations. |
945 // | |
946 // The delete range should never be exclusive if a splice frame was generated | |
947 // because we don't generate splice frames for same timestamp situations. | |
948 DCHECK(new_buffers.front()->splice_timestamp() != | 943 DCHECK(new_buffers.front()->splice_timestamp() != |
949 new_buffers.front()->timestamp()); | 944 new_buffers.front()->timestamp()); |
950 const bool exclude_start = | 945 const bool exclude_start = new_buffers.front()->splice_buffers().empty() && |
951 new_buffers.front()->splice_buffers().empty() && | 946 prev_timestamp == next_timestamp; |
952 prev_timestamp == next_timestamp && | |
953 SourceBufferRange::AllowSameTimestamp(prev_is_keyframe, next_is_keyframe); | |
954 | 947 |
955 // Delete the buffers that |new_buffers| overlaps. | 948 // Delete the buffers that |new_buffers| overlaps. |
956 DecodeTimestamp start = new_buffers.front()->GetDecodeTimestamp(); | 949 DecodeTimestamp start = new_buffers.front()->GetDecodeTimestamp(); |
957 DecodeTimestamp end = new_buffers.back()->GetDecodeTimestamp(); | 950 DecodeTimestamp end = new_buffers.back()->GetDecodeTimestamp(); |
958 base::TimeDelta duration = new_buffers.back()->duration(); | 951 base::TimeDelta duration = new_buffers.back()->duration(); |
959 | 952 |
960 // Set end time for remove to include the duration of last buffer. If the | 953 // Set end time for remove to include the duration of last buffer. If the |
961 // duration is estimated, use 1 microsecond instead to ensure frames are not | 954 // duration is estimated, use 1 microsecond instead to ensure frames are not |
962 // accidentally removed due to over-estimation. | 955 // accidentally removed due to over-estimation. |
963 if (duration != kNoTimestamp() && duration > base::TimeDelta() && | 956 if (duration != kNoTimestamp() && duration > base::TimeDelta() && |
(...skipping 818 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1782 return false; | 1775 return false; |
1783 | 1776 |
1784 DCHECK_NE(have_splice_buffers, have_preroll_buffer); | 1777 DCHECK_NE(have_splice_buffers, have_preroll_buffer); |
1785 splice_buffers_index_ = 0; | 1778 splice_buffers_index_ = 0; |
1786 pending_buffer_.swap(*out_buffer); | 1779 pending_buffer_.swap(*out_buffer); |
1787 pending_buffers_complete_ = false; | 1780 pending_buffers_complete_ = false; |
1788 return true; | 1781 return true; |
1789 } | 1782 } |
1790 | 1783 |
1791 } // namespace media | 1784 } // namespace media |
OLD | NEW |