123a941481b632554a110054dba146eb60b88afc
[platform/framework/web/chromium-efl.git] / media / filters / source_buffer_stream.cc
1 // Copyright 2012 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "media/filters/source_buffer_stream.h"
6
7 #include <algorithm>
8 #include <map>
9 #include <memory>
10 #include <sstream>
11 #include <string>
12
13 #include "base/bind.h"
14 #include "base/logging.h"
15 #include "base/trace_event/trace_event.h"
16 #include "media/base/demuxer_memory_limit.h"
17 #include "media/base/media_switches.h"
18 #include "media/base/stream_parser_buffer.h"
19 #include "media/base/timestamp_constants.h"
20
21 namespace media {
22
23 namespace {
24
25 // The minimum interbuffer decode timestamp delta (or buffer duration) for use
26 // in fudge room for range membership, adjacency and coalescing.
27 const int kMinimumInterbufferDistanceInMs = 1;
28
29 // Limit the number of MEDIA_LOG() logs for track buffer time gaps.
30 const int kMaxTrackBufferGapWarningLogs = 20;
31
32 // Limit the number of MEDIA_LOG() logs for MSE GC algorithm warnings.
33 const int kMaxGarbageCollectAlgorithmWarningLogs = 20;
34
35 // Limit the number of MEDIA_LOG() logs for splice overlap trimming.
36 const int kMaxAudioSpliceLogs = 20;
37
38 // Helper method that returns true if |ranges| is sorted in increasing order,
39 // false otherwise.
40 bool IsRangeListSorted(const SourceBufferStream::RangeList& ranges) {
41   base::TimeDelta prev = kNoTimestamp;
42   for (const auto& range_ptr : ranges) {
43     if (prev != kNoTimestamp && prev >= range_ptr->GetStartTimestamp())
44       return false;
45     prev = range_ptr->GetBufferedEndTimestamp();
46   }
47   return true;
48 }
49
50 // Returns an estimate of how far from the beginning or end of a range a buffer
51 // can be to still be considered in the range, given the |approximate_duration|
52 // of a buffer in the stream.
53 // TODO(wolenetz): Once all stream parsers emit accurate frame durations, use
54 // logic like FrameProcessor (2*last_frame_duration + last_decode_timestamp)
55 // instead of an overall maximum interbuffer delta for range discontinuity
56 // detection.
57 // See http://crbug.com/351489 and http://crbug.com/351166.
58 base::TimeDelta ComputeFudgeRoom(base::TimeDelta approximate_duration) {
59   // Because we do not know exactly when is the next timestamp, any buffer
60   // that starts within 2x the approximate duration of a buffer is considered
61   // within this range.
62   return 2 * approximate_duration;
63 }
64
65 // The amount of time the beginning of the buffered data can differ from the
66 // start time in order to still be considered the start of stream.
67 base::TimeDelta kSeekToStartFudgeRoom() {
68   return base::Milliseconds(1000);
69 }
70
71 // Helper method for logging.
72 std::string StatusToString(const SourceBufferStreamStatus& status) {
73   switch (status) {
74     case SourceBufferStreamStatus::kSuccess:
75       return "kSuccess";
76     case SourceBufferStreamStatus::kNeedBuffer:
77       return "kNeedBuffer";
78     case SourceBufferStreamStatus::kConfigChange:
79       return "kConfigChange";
80     case SourceBufferStreamStatus::kEndOfStream:
81       return "kEndOfStream";
82   }
83   NOTREACHED();
84   return "";
85 }
86
87 // Helper method for logging, converts a range into a readable string.
88 std::string RangeToString(const SourceBufferRange& range) {
89   if (range.size_in_bytes() == 0) {
90     return "[]";
91   }
92   std::stringstream ss;
93   ss << "[" << range.GetStartTimestamp().InMicroseconds() << "us;"
94      << range.GetEndTimestamp().InMicroseconds() << "us("
95      << range.GetBufferedEndTimestamp().InMicroseconds() << "us)]";
96   return ss.str();
97 }
98
99 // Helper method for logging, converts a set of ranges into a readable string.
100 std::string RangesToString(const SourceBufferStream::RangeList& ranges) {
101   if (ranges.empty())
102     return "<EMPTY>";
103
104   std::stringstream ss;
105   for (const auto& range_ptr : ranges) {
106     if (range_ptr != ranges.front())
107       ss << " ";
108     ss << RangeToString(*range_ptr);
109   }
110   return ss.str();
111 }
112
113 std::string BufferQueueBuffersToLogString(
114     const SourceBufferStream::BufferQueue& buffers) {
115   std::stringstream result;
116
117   result << "Buffers:\n";
118   for (const auto& buf : buffers) {
119     result << "\tdts=" << buf->GetDecodeTimestamp().InMicroseconds() << " "
120            << buf->AsHumanReadableString()
121            << ", is_duration_estimated=" << buf->is_duration_estimated()
122            << "\n";
123   }
124
125   return result.str();
126 }
127
128 std::string BufferQueueMetadataToLogString(
129     const SourceBufferStream::BufferQueue& buffers) {
130   std::stringstream result;
131   base::TimeDelta pts_interval_start;
132   base::TimeDelta pts_interval_end;
133   SourceBufferStream::GetTimestampInterval(buffers, &pts_interval_start,
134                                            &pts_interval_end);
135
136   result << "dts=[" << buffers.front()->GetDecodeTimestamp().InMicroseconds()
137          << "us;" << buffers.back()->GetDecodeTimestamp().InMicroseconds()
138          << "us(last frame dur=" << buffers.back()->duration().InMicroseconds()
139          << "us)], pts interval=[" << pts_interval_start.InMicroseconds()
140          << "us," << pts_interval_end.InMicroseconds() << "us)";
141   return result.str();
142 }
143
144 SourceBufferRange::GapPolicy TypeToGapPolicy(SourceBufferStreamType type) {
145   switch (type) {
146     case SourceBufferStreamType::kAudio:
147     case SourceBufferStreamType::kVideo:
148       return SourceBufferRange::NO_GAPS_ALLOWED;
149     case SourceBufferStreamType::kText:
150       return SourceBufferRange::ALLOW_GAPS;
151   }
152
153   NOTREACHED();
154   return SourceBufferRange::NO_GAPS_ALLOWED;
155 }
156
157 }  // namespace
158
159 SourceBufferStream::SourceBufferStream(const AudioDecoderConfig& audio_config,
160                                        MediaLog* media_log)
161     : media_log_(media_log),
162       seek_buffer_timestamp_(kNoTimestamp),
163       coded_frame_group_start_pts_(kNoTimestamp),
164       range_for_next_append_(ranges_.end()),
165       highest_output_buffer_timestamp_(kNoTimestamp),
166       max_interbuffer_distance_(
167           base::Milliseconds(kMinimumInterbufferDistanceInMs)),
168       memory_limit_(GetDemuxerStreamAudioMemoryLimit(&audio_config)) {
169   DCHECK(audio_config.IsValidConfig());
170   audio_configs_.push_back(audio_config);
171   DVLOG(2) << __func__ << ": audio_buffer_size= " << memory_limit_;
172 }
173
174 SourceBufferStream::SourceBufferStream(const VideoDecoderConfig& video_config,
175                                        MediaLog* media_log)
176     : media_log_(media_log),
177       seek_buffer_timestamp_(kNoTimestamp),
178       coded_frame_group_start_pts_(kNoTimestamp),
179       range_for_next_append_(ranges_.end()),
180       highest_output_buffer_timestamp_(kNoTimestamp),
181       max_interbuffer_distance_(
182           base::Milliseconds(kMinimumInterbufferDistanceInMs)),
183       memory_limit_(
184           GetDemuxerStreamVideoMemoryLimit(Demuxer::DemuxerTypes::kChunkDemuxer,
185                                            &video_config)) {
186   DCHECK(video_config.IsValidConfig());
187   video_configs_.push_back(video_config);
188   DVLOG(2) << __func__ << ": video_buffer_size= " << memory_limit_;
189 }
190
191 SourceBufferStream::SourceBufferStream(const TextTrackConfig& text_config,
192                                        MediaLog* media_log)
193     : media_log_(media_log),
194       text_track_config_(text_config),
195       seek_buffer_timestamp_(kNoTimestamp),
196       coded_frame_group_start_pts_(kNoTimestamp),
197       range_for_next_append_(ranges_.end()),
198       highest_output_buffer_timestamp_(kNoTimestamp),
199       max_interbuffer_distance_(
200           base::Milliseconds(kMinimumInterbufferDistanceInMs)),
201       memory_limit_(
202           GetDemuxerStreamAudioMemoryLimit(nullptr /*audio_config*/)) {}
203
204 SourceBufferStream::~SourceBufferStream() = default;
205
206 void SourceBufferStream::OnStartOfCodedFrameGroup(
207     base::TimeDelta coded_frame_group_start_pts) {
208   DVLOG(1) << __func__ << " " << GetStreamTypeName() << " (pts "
209            << coded_frame_group_start_pts.InMicroseconds() << "us)";
210   DCHECK(!end_of_stream_);
211   coded_frame_group_start_pts_ = coded_frame_group_start_pts;
212   new_coded_frame_group_ = true;
213
214   auto last_range = range_for_next_append_;
215   range_for_next_append_ = FindExistingRangeFor(coded_frame_group_start_pts_);
216
217   // Only reset |last_appended_buffer_timestamp_| if this new coded frame group
218   // is not adjacent to the previous coded frame group appended to the stream.
219   if (range_for_next_append_ == ranges_.end() ||
220       !IsNextGopAdjacentToEndOfCurrentAppendSequence(
221           coded_frame_group_start_pts_)) {
222     ResetLastAppendedState();
223     DVLOG(3) << __func__ << " next appended buffers will "
224              << (range_for_next_append_ == ranges_.end()
225                      ? "be in a new range"
226                      : "overlap an existing range");
227
228     if (range_for_next_append_ != ranges_.end()) {
229       // If this new coded frame group overlaps an existing range, preserve
230       // continuity from that range to the new group by moving the start time
231       // earlier (but not at or beyond the most recent buffered frame's time
232       // before |coded_frame_group_start_pts_| in the range, and not beyond the
233       // range's start time. This update helps prevent discontinuity from being
234       // introduced by the ::RemoveInternal processing during the next ::Append
235       // call.
236       base::TimeDelta adjusted_start_time =
237           (*range_for_next_append_)
238               ->FindHighestBufferedTimestampAtOrBefore(
239                   coded_frame_group_start_pts_);
240       if (adjusted_start_time < coded_frame_group_start_pts_) {
241         // Exclude removal of that earlier frame during later Append
242         // processing by adjusting the removal range slightly forward.
243         coded_frame_group_start_pts_ =
244             adjusted_start_time + base::Microseconds(1);
245       }
246     }
247   } else if (last_range != ranges_.end()) {
248     DCHECK(last_range == range_for_next_append_);
249     DVLOG(3) << __func__ << " next appended buffers will continue range unless "
250              << "intervening remove makes discontinuity";
251   }
252 }
253
254 void SourceBufferStream::Append(const BufferQueue& buffers) {
255   TRACE_EVENT2("media", "SourceBufferStream::Append",
256                "stream type", GetStreamTypeName(),
257                "buffers to append", buffers.size());
258
259   DCHECK(!buffers.empty());
260   DCHECK(coded_frame_group_start_pts_ != kNoTimestamp);
261   DCHECK(!end_of_stream_);
262
263   DVLOG(1) << __func__ << " " << GetStreamTypeName() << ": buffers "
264            << BufferQueueMetadataToLogString(buffers);
265   DVLOG(4) << BufferQueueBuffersToLogString(buffers);
266
267   DCHECK(!buffers.front()->is_key_frame() ||
268          coded_frame_group_start_pts_ <= buffers.front()->timestamp());
269   DVLOG_IF(2, coded_frame_group_start_pts_ > buffers.front()->timestamp())
270       << __func__
271       << " Suspected SAP-Type-2 occurrence: coded_frame_group_start_pts_="
272       << coded_frame_group_start_pts_.InMicroseconds()
273       << "us, first new buffer has timestamp="
274       << buffers.front()->timestamp().InMicroseconds() << "us";
275
276   // New coded frame groups emitted by the coded frame processor must begin with
277   // a keyframe. Avoid propagating with escalating impact if this assumption is
278   // broken.
279   CHECK(!new_coded_frame_group_ || buffers.front()->is_key_frame());
280
281   // Buffers within each GOP in a coded frame group must be monotonically
282   // increasing in DTS order.
283   DCHECK(IsDtsMonotonicallyIncreasing(buffers));
284
285   // Both of these checks enforce what should be guaranteed by how
286   // FrameProcessor signals OnStartOfCodedFrameGroup and the buffers it tells us
287   // to Append.
288   DCHECK(coded_frame_group_start_pts_ >= base::TimeDelta());
289   DCHECK(buffers.front()->timestamp() >= base::TimeDelta());
290
291   if (UpdateMaxInterbufferDtsDistance(buffers)) {
292     // Coalesce |ranges_| using the new fudge room. This helps keep |ranges_|
293     // sorted in complex scenarios.  See https://crbug.com/793247.
294     MergeAllAdjacentRanges();
295   }
296
297   SetConfigIds(buffers);
298
299   // Save a snapshot of stream state before range modifications are made.
300   base::TimeDelta next_buffer_timestamp = GetNextBufferTimestamp();
301   BufferQueue deleted_buffers;
302
303   PrepareRangesForNextAppend(buffers, &deleted_buffers);
304
305   // If there's a range for |buffers|, insert |buffers| accordingly. Otherwise,
306   // create a new range with |buffers|.
307   if (range_for_next_append_ != ranges_.end()) {
308     if (new_coded_frame_group_) {
309       // If the first append to this stream in a new coded frame group continues
310       // a previous range, use the new group's start time instead of the first
311       // new buffer's timestamp as the proof of adjacency to the existing range.
312       // A large gap (larger than our normal buffer adjacency test) can occur in
313       // a muxed set of streams (which share a common coded frame group start
314       // time) with a significantly jagged start across the streams.
315       (*range_for_next_append_)
316           ->AppendBuffersToEnd(buffers, coded_frame_group_start_pts_);
317     } else {
318       // Otherwise, use the first new buffer as proof of adjacency.
319       (*range_for_next_append_)->AppendBuffersToEnd(buffers, kNoTimestamp);
320     }
321
322     last_appended_buffer_timestamp_ = buffers.back()->timestamp();
323     last_appended_buffer_duration_ = buffers.back()->duration();
324     last_appended_buffer_is_keyframe_ = buffers.back()->is_key_frame();
325     last_appended_buffer_decode_timestamp_ =
326         buffers.back()->GetDecodeTimestamp();
327     highest_timestamp_in_append_sequence_ =
328         (*range_for_next_append_)->GetEndTimestamp();
329     highest_buffered_end_time_in_append_sequence_ =
330         (*range_for_next_append_)->GetBufferedEndTimestamp();
331   } else {
332     base::TimeDelta new_range_start_time =
333         std::min(coded_frame_group_start_pts_, buffers.front()->timestamp());
334
335     const BufferQueue* buffers_for_new_range = &buffers;
336     BufferQueue trimmed_buffers;
337
338     // If the new range is not being created because of a new coded frame group,
339     // then we must make sure that we start with a key frame.  This can happen
340     // if the GOP in the previous append gets destroyed by a Remove() call.
341     if (!new_coded_frame_group_) {
342       BufferQueue::const_iterator itr = buffers.begin();
343
344       // Scan past all the non-key-frames.
345       while (itr != buffers.end() && !(*itr)->is_key_frame()) {
346         ++itr;
347       }
348
349       // If we didn't find a key frame, then update the last appended
350       // buffer state and return.
351       if (itr == buffers.end()) {
352         last_appended_buffer_timestamp_ = buffers.back()->timestamp();
353         last_appended_buffer_duration_ = buffers.back()->duration();
354         last_appended_buffer_is_keyframe_ = buffers.back()->is_key_frame();
355         last_appended_buffer_decode_timestamp_ =
356             buffers.back()->GetDecodeTimestamp();
357         // Since we didn't buffer anything, don't update
358         // |highest_timestamp_in_append_sequence_|.
359         DVLOG(1) << __func__ << " " << GetStreamTypeName()
360                  << ": new buffers in the middle of coded frame group depend on"
361                     " keyframe that has been removed, and contain no keyframes."
362                     " Skipping further processing.";
363         DVLOG(1) << __func__ << " " << GetStreamTypeName()
364                  << ": done. ranges_=" << RangesToString(ranges_);
365         return;
366       } else if (itr != buffers.begin()) {
367         // Copy the first key frame and everything after it into
368         // |trimmed_buffers|.
369         trimmed_buffers.assign(itr, buffers.end());
370         buffers_for_new_range = &trimmed_buffers;
371       }
372
373       new_range_start_time = buffers_for_new_range->front()->timestamp();
374     }
375
376     range_for_next_append_ = AddToRanges(std::make_unique<SourceBufferRange>(
377         TypeToGapPolicy(GetType()), *buffers_for_new_range,
378         new_range_start_time,
379         base::BindRepeating(&SourceBufferStream::GetMaxInterbufferDistance,
380                             base::Unretained(this))));
381
382     last_appended_buffer_timestamp_ =
383         buffers_for_new_range->back()->timestamp();
384     last_appended_buffer_duration_ = buffers_for_new_range->back()->duration();
385     last_appended_buffer_is_keyframe_ =
386         buffers_for_new_range->back()->is_key_frame();
387     last_appended_buffer_decode_timestamp_ =
388         buffers_for_new_range->back()->GetDecodeTimestamp();
389     highest_timestamp_in_append_sequence_ =
390         (*range_for_next_append_)->GetEndTimestamp();
391     highest_buffered_end_time_in_append_sequence_ =
392         (*range_for_next_append_)->GetBufferedEndTimestamp();
393   }
394
395   new_coded_frame_group_ = false;
396
397   MergeWithNextRangeIfNecessary(range_for_next_append_);
398
399   // Some SAP-Type-2 append sequences require that we coalesce
400   // |range_for_next_append_| with the range that is *before* it.
401   if (range_for_next_append_ != ranges_.begin()) {
402     auto prior_range = range_for_next_append_;
403     prior_range--;
404     MergeWithNextRangeIfNecessary(prior_range);
405   }
406
407   // Seek to try to fulfill a previous call to Seek().
408   if (seek_pending_) {
409     DCHECK(!selected_range_);
410     DCHECK(deleted_buffers.empty());
411     Seek(seek_buffer_timestamp_);
412   }
413
414   if (!deleted_buffers.empty()) {
415     track_buffer_.insert(track_buffer_.end(), deleted_buffers.begin(),
416                          deleted_buffers.end());
417     DVLOG(3) << __func__ << " " << GetStreamTypeName() << " Added "
418              << deleted_buffers.size()
419              << " buffers to track buffer. TB size is now "
420              << track_buffer_.size();
421   } else {
422     DVLOG(3) << __func__ << " " << GetStreamTypeName()
423              << " No deleted buffers for track buffer";
424   }
425
426   // Prune any extra buffers in |track_buffer_| if new keyframes
427   // are appended to the range covered by |track_buffer_|.
428   if (!track_buffer_.empty()) {
429     base::TimeDelta keyframe_timestamp =
430         FindKeyframeAfterTimestamp(track_buffer_.front()->timestamp());
431     if (keyframe_timestamp != kNoTimestamp)
432       PruneTrackBuffer(keyframe_timestamp);
433   }
434
435   SetSelectedRangeIfNeeded(next_buffer_timestamp);
436
437   DVLOG(1) << __func__ << " " << GetStreamTypeName()
438            << ": done. ranges_=" << RangesToString(ranges_);
439   DCHECK(IsRangeListSorted(ranges_));
440   DCHECK(OnlySelectedRangeIsSeeked());
441 }
442
443 void SourceBufferStream::Remove(base::TimeDelta start,
444                                 base::TimeDelta end,
445                                 base::TimeDelta duration) {
446   DVLOG(1) << __func__ << " " << GetStreamTypeName() << " ("
447            << start.InMicroseconds() << "us, " << end.InMicroseconds() << "us, "
448            << duration.InMicroseconds() << "us)";
449   DCHECK(start >= base::TimeDelta()) << start.InMicroseconds() << "us";
450   DCHECK(start < end) << "start " << start.InMicroseconds() << "us, end "
451                       << end.InMicroseconds() << "us";
452   DCHECK(duration != kNoTimestamp);
453
454   base::TimeDelta remove_end_timestamp = duration;
455   base::TimeDelta keyframe_timestamp = FindKeyframeAfterTimestamp(end);
456   if (keyframe_timestamp != kNoTimestamp) {
457     remove_end_timestamp = keyframe_timestamp;
458   } else if (end < remove_end_timestamp) {
459     remove_end_timestamp = end;
460   }
461
462   BufferQueue deleted_buffers;
463   RemoveInternal(start, remove_end_timestamp, false, &deleted_buffers);
464
465   if (!deleted_buffers.empty()) {
466     // Buffers for the current position have been removed.
467     SetSelectedRangeIfNeeded(deleted_buffers.front()->timestamp());
468     if (highest_output_buffer_timestamp_ == kNoTimestamp) {
469       // We just removed buffers for the current playback position for this
470       // stream, yet we also had output no buffer since the last Seek.
471       // Re-seek to prevent stall.
472       DVLOG(1) << __func__ << " " << GetStreamTypeName() << ": re-seeking to "
473                << seek_buffer_timestamp_
474                << " to prevent stall if this time becomes buffered again";
475       Seek(seek_buffer_timestamp_);
476     }
477   }
478
479   DCHECK(OnlySelectedRangeIsSeeked());
480   DCHECK(IsRangeListSorted(ranges_));
481 }
482
483 base::TimeDelta SourceBufferStream::PotentialNextAppendTimestamp() const {
484   // The next potential append will either be in a GOP adjacent to
485   // |highest_timestamp_in_append_sequence_| (if known), or if unknown and we
486   // are still at the beginning of a new coded frame group, then will be into
487   // the range (if any) to which |coded_frame_group_start_pts_| belongs.
488   if (highest_timestamp_in_append_sequence_ != kNoTimestamp)
489     return highest_timestamp_in_append_sequence_;
490
491   if (new_coded_frame_group_)
492     return coded_frame_group_start_pts_;
493
494   // If we still don't know a potential next append timestamp, then we have
495   // removed the range to which it previously belonged and have not completed a
496   // subsequent append or received a subsequent OnStartOfCodedFrameGroup()
497   // signal.
498   return kNoTimestamp;
499 }
500
501 void SourceBufferStream::UpdateLastAppendStateForRemove(
502     base::TimeDelta remove_start,
503     base::TimeDelta remove_end,
504     bool exclude_start) {
505   // TODO(chcunningham): change exclude_start to include_start in this class and
506   // SourceBufferRange. Negatives are hard to reason about.
507   bool include_start = !exclude_start;
508
509   // No need to check previous append's GOP if starting a new CFG. New CFG is
510   // already required to begin with a key frame.
511   if (new_coded_frame_group_)
512     return;
513
514   if (range_for_next_append_ != ranges_.end()) {
515     if (last_appended_buffer_timestamp_ != kNoTimestamp) {
516       // Note start and end of last appended GOP.
517       base::TimeDelta gop_end = highest_timestamp_in_append_sequence_;
518       base::TimeDelta gop_start =
519           (*range_for_next_append_)->KeyframeBeforeTimestamp(gop_end);
520
521       // If last append is about to be disrupted, reset associated state so we
522       // know to create a new range for future appends and require an initial
523       // key frame.
524       if (((include_start && remove_start == gop_end) ||
525            remove_start < gop_end) &&
526           remove_end > gop_start) {
527         DVLOG(2) << __func__ << " " << GetStreamTypeName()
528                  << " Resetting next append state for remove ("
529                  << remove_start.InMicroseconds() << "us, "
530                  << remove_end.InMicroseconds() << "us, " << exclude_start
531                  << ")";
532         range_for_next_append_ = ranges_.end();
533         ResetLastAppendedState();
534       }
535     } else {
536       NOTREACHED() << __func__ << " " << GetStreamTypeName()
537                    << " range_for_next_append_ set, but not tracking last"
538                    << " append nor new coded frame group.";
539     }
540   }
541 }
542
543 void SourceBufferStream::RemoveInternal(base::TimeDelta start,
544                                         base::TimeDelta end,
545                                         bool exclude_start,
546                                         BufferQueue* deleted_buffers) {
547   DVLOG(2) << __func__ << " " << GetStreamTypeName() << " ("
548            << start.InMicroseconds() << "us, " << end.InMicroseconds() << "us, "
549            << exclude_start << ")";
550   DVLOG(3) << __func__ << " " << GetStreamTypeName()
551            << ": before remove ranges_=" << RangesToString(ranges_);
552
553   DCHECK(start >= base::TimeDelta());
554   DCHECK(start < end) << "start " << start.InMicroseconds() << "us, end "
555                       << end.InMicroseconds() << "us";
556   DCHECK(deleted_buffers);
557
558   // Doing this up-front simplifies decisions about |range_for_next_append_|
559   // below.
560   UpdateLastAppendStateForRemove(start, end, exclude_start);
561
562   auto itr = ranges_.begin();
563   while (itr != ranges_.end()) {
564     SourceBufferRange* range = itr->get();
565     if (range->GetStartTimestamp() >= end)
566       break;
567
568     // Split off any remaining GOPs starting at or after |end| and add it to
569     // |ranges_|.
570     std::unique_ptr<SourceBufferRange> new_range = range->SplitRange(end);
571     if (new_range) {
572       itr = ranges_.insert(++itr, std::move(new_range));
573
574       // Update |range_for_next_append_| if it was previously |range| and should
575       // be the new range (that |itr| is at) now.
576       if (range_for_next_append_ != ranges_.end() &&
577           range_for_next_append_->get() == range) {
578         base::TimeDelta potential_next_append_timestamp =
579             PotentialNextAppendTimestamp();
580         if (potential_next_append_timestamp != kNoTimestamp &&
581             (*itr)->BelongsToRange(potential_next_append_timestamp)) {
582           range_for_next_append_ = itr;
583         }
584       }
585
586       // Update the selected range if the next buffer position was transferred
587       // to the newly inserted range (that |itr| is at now).
588       if ((*itr)->HasNextBufferPosition())
589         SetSelectedRange(itr->get());
590
591       --itr;
592     }
593
594     // Truncate the current range so that it only contains data before
595     // the removal range.
596     BufferQueue saved_buffers;
597     bool delete_range = range->TruncateAt(start, &saved_buffers, exclude_start);
598
599     // Check to see if the current playback position was removed and update the
600     // selected range appropriately.
601     if (!saved_buffers.empty()) {
602       DCHECK(!range->HasNextBufferPosition());
603       DCHECK(deleted_buffers->empty());
604
605       *deleted_buffers = saved_buffers;
606     }
607
608     if (range == selected_range_ && !range->HasNextBufferPosition())
609       SetSelectedRange(NULL);
610
611     // If the current range now is completely covered by the removal
612     // range then delete it and move on.
613     if (delete_range) {
614       DeleteAndRemoveRange(&itr);
615       continue;
616     }
617
618     // Clear |range_for_next_append_| if we determine that the removal
619     // operation makes it impossible for the next append to be added
620     // to the current range.
621     if (range_for_next_append_ != ranges_.end() &&
622         range_for_next_append_->get() == range) {
623       base::TimeDelta potential_next_append_timestamp =
624           PotentialNextAppendTimestamp();
625
626       if (!range->BelongsToRange(potential_next_append_timestamp)) {
627         DVLOG(1) << "Resetting range_for_next_append_ since the next append"
628                  <<  " can't add to the current range.";
629         range_for_next_append_ =
630             FindExistingRangeFor(potential_next_append_timestamp);
631       }
632     }
633
634     // Move on to the next range.
635     ++itr;
636   }
637
638   DVLOG(3) << __func__ << " " << GetStreamTypeName()
639            << ": after remove ranges_=" << RangesToString(ranges_);
640
641   DCHECK(OnlySelectedRangeIsSeeked());
642 }
643
644 void SourceBufferStream::ResetSeekState() {
645   SetSelectedRange(NULL);
646   track_buffer_.clear();
647   config_change_pending_ = false;
648   highest_output_buffer_timestamp_ = kNoTimestamp;
649   just_exhausted_track_buffer_ = false;
650   pending_buffer_.reset();
651   pending_buffers_complete_ = false;
652 }
653
654 void SourceBufferStream::ResetLastAppendedState() {
655   last_appended_buffer_timestamp_ = kNoTimestamp;
656   last_appended_buffer_duration_ = kNoTimestamp;
657   last_appended_buffer_is_keyframe_ = false;
658   last_appended_buffer_decode_timestamp_ = kNoDecodeTimestamp;
659   highest_timestamp_in_append_sequence_ = kNoTimestamp;
660   highest_buffered_end_time_in_append_sequence_ = kNoTimestamp;
661 }
662
663 bool SourceBufferStream::ShouldSeekToStartOfBuffered(
664     base::TimeDelta seek_timestamp) const {
665   if (ranges_.empty())
666     return false;
667   base::TimeDelta beginning_of_buffered = ranges_.front()->GetStartTimestamp();
668   return (seek_timestamp <= beginning_of_buffered &&
669           beginning_of_buffered < kSeekToStartFudgeRoom());
670 }
671
672 bool SourceBufferStream::IsDtsMonotonicallyIncreasing(
673     const BufferQueue& buffers) {
674   DCHECK(!buffers.empty());
675   DecodeTimestamp prev_dts = last_appended_buffer_decode_timestamp_;
676   for (BufferQueue::const_iterator itr = buffers.begin();
677        itr != buffers.end(); ++itr) {
678     DecodeTimestamp current_dts = (*itr)->GetDecodeTimestamp();
679     bool current_is_keyframe = (*itr)->is_key_frame();
680     DCHECK(current_dts != kNoDecodeTimestamp);
681     DCHECK((*itr)->duration() >= base::TimeDelta())
682         << "Packet with invalid duration."
683         << " pts " << (*itr)->timestamp().InMicroseconds() << "us dts "
684         << (*itr)->GetDecodeTimestamp().InMicroseconds() << "us dur "
685         << (*itr)->duration().InMicroseconds() << "us";
686
687     // Only verify DTS monotonicity within the current GOP (since the last
688     // keyframe). FrameProcessor should have enforced that all audio frames are
689     // keyframes already, or are nonkeyframes with monotonically increasing PTS
690     // since the last keyframe for those types of audio for which nonkeyframes
691     // may be involved, e.g. xHE-AAC. Video nonkeyframes are not restricted to
692     // being in-order by PTS, but both audio and video nonkeyframes must be in
693     // decode sequence since the last keyframe.
694     if (current_is_keyframe) {
695       // Reset prev_dts tracking since a new GOP is starting.
696       prev_dts = kNoDecodeTimestamp;
697     }
698
699     if (prev_dts != kNoDecodeTimestamp) {
700       if (current_dts < prev_dts) {
701         MEDIA_LOG(ERROR, media_log_)
702             << "Buffers did not monotonically increase.";
703         return false;
704       }
705     }
706
707     prev_dts = current_dts;
708   }
709   return true;
710 }
711
712 bool SourceBufferStream::OnlySelectedRangeIsSeeked() const {
713   for (auto itr = ranges_.begin(); itr != ranges_.end(); ++itr) {
714     if ((*itr)->HasNextBufferPosition() && itr->get() != selected_range_)
715       return false;
716   }
717   return !selected_range_ || selected_range_->HasNextBufferPosition();
718 }
719
720 bool SourceBufferStream::UpdateMaxInterbufferDtsDistance(
721     const BufferQueue& buffers) {
722   DCHECK(!buffers.empty());
723   base::TimeDelta old_distance = max_interbuffer_distance_;
724   DecodeTimestamp prev_dts = last_appended_buffer_decode_timestamp_;
725   for (BufferQueue::const_iterator itr = buffers.begin();
726        itr != buffers.end(); ++itr) {
727     DecodeTimestamp current_dts = (*itr)->GetDecodeTimestamp();
728     DCHECK(current_dts != kNoDecodeTimestamp);
729
730     base::TimeDelta interbuffer_distance = (*itr)->duration();
731     DCHECK(interbuffer_distance >= base::TimeDelta());
732
733     if (prev_dts != kNoDecodeTimestamp) {
734       interbuffer_distance =
735           std::max(current_dts - prev_dts, interbuffer_distance);
736     }
737
738     DCHECK(max_interbuffer_distance_ >=
739            base::Milliseconds(kMinimumInterbufferDistanceInMs));
740     max_interbuffer_distance_ =
741         std::max(max_interbuffer_distance_, interbuffer_distance);
742     prev_dts = current_dts;
743   }
744   bool changed_max = max_interbuffer_distance_ != old_distance;
745   DVLOG_IF(2, changed_max) << __func__ << " " << GetStreamTypeName()
746                            << " Changed max interbuffer DTS distance from "
747                            << old_distance.InMicroseconds() << "us to "
748                            << max_interbuffer_distance_.InMicroseconds()
749                            << "us";
750   return changed_max;
751 }
752
753 void SourceBufferStream::SetConfigIds(const BufferQueue& buffers) {
754   for (BufferQueue::const_iterator itr = buffers.begin();
755        itr != buffers.end(); ++itr) {
756     (*itr)->SetConfigId(append_config_index_);
757   }
758 }
759
760 void SourceBufferStream::OnMemoryPressure(
761     base::TimeDelta media_time,
762     base::MemoryPressureListener::MemoryPressureLevel memory_pressure_level,
763     bool force_instant_gc) {
764   DVLOG(4) << __func__ << " level=" << memory_pressure_level;
765   // TODO(sebmarchand): Check if MEMORY_PRESSURE_LEVEL_MODERATE should also be
766   // ignored.
767   if (memory_pressure_level ==
768       base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_NONE) {
769     return;
770   }
771
772   memory_pressure_level_ = memory_pressure_level;
773
774   if (force_instant_gc)
775     GarbageCollectIfNeeded(media_time, 0);
776 }
777
778 bool SourceBufferStream::GarbageCollectIfNeeded(base::TimeDelta media_time,
779                                                 size_t newDataSize) {
780   DCHECK(media_time != kNoTimestamp);
781   // Garbage collection should only happen before/during appending new data,
782   // which should not happen in end-of-stream state. Unless we also allow GC to
783   // happen on memory pressure notifications, which might happen even in EOS
784   // state.
785   if (!base::FeatureList::IsEnabled(kMemoryPressureBasedSourceBufferGC))
786     DCHECK(!end_of_stream_);
787   // Compute size of |ranges_|.
788   size_t ranges_size = GetBufferedSize();
789
790   // Sanity and overflow checks
791   if ((newDataSize > memory_limit_) ||
792       (ranges_size + newDataSize < ranges_size)) {
793     LIMITED_MEDIA_LOG(DEBUG, media_log_, num_garbage_collect_algorithm_logs_,
794                       kMaxGarbageCollectAlgorithmWarningLogs)
795         << GetStreamTypeName() << " stream: "
796         << "new append of newDataSize=" << newDataSize
797         << " bytes exceeds memory_limit_=" << memory_limit_
798         << ", currently buffered ranges_size=" << ranges_size;
799     return false;
800   }
801
802   size_t effective_memory_limit = memory_limit_;
803   if (base::FeatureList::IsEnabled(kMemoryPressureBasedSourceBufferGC)) {
804     switch (memory_pressure_level_) {
805       case base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE:
806         effective_memory_limit = memory_limit_ / 2;
807         break;
808       case base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL:
809         effective_memory_limit = 0;
810         break;
811       case base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_NONE:
812         break;
813     }
814   }
815
816   // Return if we're under or at the memory limit.
817   if (ranges_size + newDataSize <= effective_memory_limit)
818     return true;
819
820   size_t bytes_over_hard_memory_limit = 0;
821   if (ranges_size + newDataSize > memory_limit_)
822     bytes_over_hard_memory_limit = ranges_size + newDataSize - memory_limit_;
823
824   size_t bytes_to_free = ranges_size + newDataSize - effective_memory_limit;
825
826   DVLOG(2) << __func__ << " " << GetStreamTypeName()
827            << ": Before GC media_time=" << media_time.InMicroseconds()
828            << "us ranges_=" << RangesToString(ranges_)
829            << " seek_pending_=" << seek_pending_
830            << " ranges_size=" << ranges_size << " newDataSize=" << newDataSize
831            << " memory_limit_=" << memory_limit_
832            << " effective_memory_limit=" << effective_memory_limit
833            << " last_appended_buffer_timestamp_="
834            << last_appended_buffer_timestamp_.InMicroseconds()
835            << "us highest_timestamp_in_append_sequence_="
836            << highest_timestamp_in_append_sequence_.InMicroseconds()
837            << "us highest_buffered_end_time_in_append_sequence_="
838            << highest_buffered_end_time_in_append_sequence_.InMicroseconds()
839            << "us";
840
841   if (selected_range_ && !seek_pending_ &&
842       media_time > selected_range_->GetBufferedEndTimestamp()) {
843     // Strictly speaking |media_time| (taken from HTMLMediaElement::currentTime)
844     // should always be in the buffered ranges, but media::Pipeline uses audio
845     // stream as the main time source, when audio is present.
846     // In cases when audio and video streams have different buffered ranges, the
847     // |media_time| value might be slightly outside of the video stream buffered
848     // range. In those cases we need to clamp |media_time| value to the current
849     // stream buffered ranges, to ensure the MSE garbage collection algorithm
850     // works correctly (see crbug.com/563292 for details).
851     base::TimeDelta selected_buffered_end =
852         selected_range_->GetBufferedEndTimestamp();
853
854     DVLOG(2) << __func__ << " media_time " << media_time.InMicroseconds()
855              << "us is outside of selected_range_=["
856              << selected_range_->GetStartTimestamp().InMicroseconds() << "us;"
857              << selected_buffered_end.InMicroseconds()
858              << "us] clamping media_time to be "
859              << selected_buffered_end.InMicroseconds() << "us";
860     media_time = selected_buffered_end;
861   }
862
863   size_t bytes_freed = 0;
864
865   // If last appended buffer position was earlier than the current playback time
866   // then try deleting data between last append and current media_time.
867   if (last_appended_buffer_timestamp_ != kNoTimestamp &&
868       last_appended_buffer_duration_ != kNoTimestamp &&
869       highest_buffered_end_time_in_append_sequence_ != kNoTimestamp &&
870       media_time > highest_buffered_end_time_in_append_sequence_) {
871     size_t between = FreeBuffersAfterLastAppended(bytes_to_free, media_time);
872     DVLOG(3) << __func__ << " FreeBuffersAfterLastAppended "
873              << " released " << between << " bytes"
874              << " ranges_=" << RangesToString(ranges_);
875     bytes_freed += between;
876
877     // Some players start appending data at the new seek target position before
878     // actually initiating the seek operation (i.e. they try to improve seek
879     // performance by prebuffering some data at the seek target position and
880     // initiating seek once enough data is pre-buffered. In those cases we'll
881     // see that data is being appended at some new position, but there is no
882     // pending seek reported yet. In this situation we need to try preserving
883     // the most recently appended data, i.e. data belonging to the same buffered
884     // range as the most recent append.
885     if (range_for_next_append_ != ranges_.end()) {
886       DCHECK((*range_for_next_append_)->GetStartTimestamp() <= media_time);
887       media_time = (*range_for_next_append_)->GetStartTimestamp();
888       DVLOG(3) << __func__ << " media_time adjusted to "
889                << media_time.InMicroseconds() << "us";
890     }
891   }
892
893   // If there is an unsatisfied pending seek, we can safely remove all data that
894   // is earlier than seek target, then remove from the back until we reach the
895   // most recently appended GOP and then remove from the front if we still don't
896   // have enough space for the upcoming append.
897   if (bytes_freed < bytes_to_free && seek_pending_) {
898     DCHECK(!ranges_.empty());
899     // All data earlier than the seek target |media_time| can be removed safely
900     size_t front = FreeBuffers(bytes_to_free - bytes_freed, media_time, false);
901     DVLOG(3) << __func__ << " Removed " << front
902              << " bytes from the front. ranges_=" << RangesToString(ranges_);
903     bytes_freed += front;
904
905     // If removing data earlier than |media_time| didn't free up enough space,
906     // then try deleting from the back until we reach most recently appended GOP
907     if (bytes_freed < bytes_to_free) {
908       size_t back = FreeBuffers(bytes_to_free - bytes_freed, media_time, true);
909       DVLOG(3) << __func__ << " Removed " << back
910                << " bytes from the back. ranges_=" << RangesToString(ranges_);
911       bytes_freed += back;
912     }
913
914     // If even that wasn't enough, then try greedily deleting from the front,
915     // that should allow us to remove as much data as necessary to succeed.
916     if (bytes_freed < bytes_to_free) {
917       size_t front2 = FreeBuffers(bytes_to_free - bytes_freed,
918                                   ranges_.back()->GetEndTimestamp(), false);
919       DVLOG(3) << __func__ << " Removed " << front2
920                << " bytes from the front. ranges_=" << RangesToString(ranges_);
921       bytes_freed += front2;
922     }
923     DCHECK(bytes_freed >= bytes_to_free);
924   }
925
926   // Try removing data from the front of the SourceBuffer up to |media_time|
927   // position.
928   if (bytes_freed < bytes_to_free) {
929     size_t front = FreeBuffers(bytes_to_free - bytes_freed, media_time, false);
930     DVLOG(3) << __func__ << " Removed " << front
931              << " bytes from the front. ranges_=" << RangesToString(ranges_);
932     bytes_freed += front;
933   }
934
935   // Try removing data from the back of the SourceBuffer, until we reach the
936   // most recent append position.
937   if (bytes_freed < bytes_to_free) {
938     size_t back = FreeBuffers(bytes_to_free - bytes_freed, media_time, true);
939     DVLOG(3) << __func__ << " Removed " << back
940              << " bytes from the back. ranges_=" << RangesToString(ranges_);
941     bytes_freed += back;
942   }
943
944   DVLOG(2) << __func__ << " " << GetStreamTypeName()
945            << ": After GC bytes_to_free=" << bytes_to_free
946            << " bytes_freed=" << bytes_freed
947            << " bytes_over_hard_memory_limit=" << bytes_over_hard_memory_limit
948            << " ranges_=" << RangesToString(ranges_);
949
950   return bytes_freed >= bytes_over_hard_memory_limit;
951 }
952
953 size_t SourceBufferStream::FreeBuffersAfterLastAppended(
954     size_t total_bytes_to_free,
955     base::TimeDelta media_time) {
956   DVLOG(4) << __func__ << " highest_buffered_end_time_in_append_sequence_="
957            << highest_buffered_end_time_in_append_sequence_.InMicroseconds()
958            << "us media_time=" << media_time.InMicroseconds() << "us";
959
960   base::TimeDelta remove_range_start =
961       highest_buffered_end_time_in_append_sequence_;
962   if (last_appended_buffer_is_keyframe_)
963     remove_range_start += GetMaxInterbufferDistance();
964
965   base::TimeDelta remove_range_start_keyframe =
966       FindKeyframeAfterTimestamp(remove_range_start);
967   if (remove_range_start_keyframe != kNoTimestamp)
968     remove_range_start = remove_range_start_keyframe;
969   if (remove_range_start >= media_time)
970     return 0;
971
972   base::TimeDelta remove_range_end;
973   size_t bytes_freed = GetRemovalRange(remove_range_start,
974                                        media_time,
975                                        total_bytes_to_free,
976                                        &remove_range_end);
977   if (bytes_freed > 0) {
978     DVLOG(4) << __func__ << " removing [" << remove_range_start.InMicroseconds()
979              << "us;" << remove_range_end.InMicroseconds() << "us]";
980     Remove(remove_range_start, remove_range_end, media_time);
981   }
982
983   return bytes_freed;
984 }
985
986 size_t SourceBufferStream::GetRemovalRange(
987     base::TimeDelta start_timestamp,
988     base::TimeDelta end_timestamp,
989     size_t total_bytes_to_free,
990     base::TimeDelta* removal_end_timestamp) {
991   DCHECK(start_timestamp >= base::TimeDelta())
992       << start_timestamp.InMicroseconds() << "us";
993   DCHECK(start_timestamp < end_timestamp)
994       << "start " << start_timestamp.InMicroseconds() << "us, end "
995       << end_timestamp.InMicroseconds() << "us";
996
997   size_t bytes_freed = 0;
998
999   for (auto itr = ranges_.begin();
1000        itr != ranges_.end() && bytes_freed < total_bytes_to_free; ++itr) {
1001     SourceBufferRange* range = itr->get();
1002     if (range->GetStartTimestamp() >= end_timestamp)
1003       break;
1004     if (range->GetEndTimestamp() < start_timestamp)
1005       continue;
1006
1007     size_t bytes_to_free = total_bytes_to_free - bytes_freed;
1008     size_t bytes_removed = range->GetRemovalGOP(
1009         start_timestamp, end_timestamp, bytes_to_free, removal_end_timestamp);
1010     bytes_freed += bytes_removed;
1011   }
1012   return bytes_freed;
1013 }
1014
1015 size_t SourceBufferStream::FreeBuffers(size_t total_bytes_to_free,
1016                                        base::TimeDelta media_time,
1017                                        bool reverse_direction) {
1018   TRACE_EVENT2("media", "SourceBufferStream::FreeBuffers",
1019                "total bytes to free", total_bytes_to_free,
1020                "reverse direction", reverse_direction);
1021
1022   DCHECK_GT(total_bytes_to_free, 0u);
1023   size_t bytes_freed = 0;
1024
1025   // This range will save the last GOP appended to |range_for_next_append_|
1026   // if the buffers surrounding it get deleted during garbage collection.
1027   std::unique_ptr<SourceBufferRange> new_range_for_append;
1028
1029   while (!ranges_.empty() && bytes_freed < total_bytes_to_free) {
1030     SourceBufferRange* current_range = NULL;
1031     BufferQueue buffers;
1032     size_t bytes_deleted = 0;
1033
1034     if (reverse_direction) {
1035       current_range = ranges_.back().get();
1036       DVLOG(5) << "current_range=" << RangeToString(*current_range);
1037       if (current_range->LastGOPContainsNextBufferPosition()) {
1038         DCHECK_EQ(current_range, selected_range_);
1039         DVLOG(5) << "current_range contains next read position, stopping GC";
1040         break;
1041       }
1042       DVLOG(5) << "Deleting GOP from back: " << RangeToString(*current_range);
1043       bytes_deleted = current_range->DeleteGOPFromBack(&buffers);
1044     } else {
1045       current_range = ranges_.front().get();
1046       DVLOG(5) << "current_range=" << RangeToString(*current_range);
1047
1048       // FirstGOPEarlierThanMediaTime() is useful here especially if
1049       // |seek_pending_| (such that no range contains next buffer
1050       // position).
1051       // FirstGOPContainsNextBufferPosition() is useful here especially if
1052       // |!seek_pending_| to protect against DeleteGOPFromFront() if
1053       // FirstGOPEarlierThanMediaTime() was insufficient alone.
1054       if (!current_range->FirstGOPEarlierThanMediaTime(media_time) ||
1055           current_range->FirstGOPContainsNextBufferPosition()) {
1056         // We have removed all data up to the GOP that contains current playback
1057         // position, we can't delete any further.
1058         DVLOG(5) << "current_range contains playback position, stopping GC";
1059         break;
1060       }
1061       DVLOG(4) << "Deleting GOP from front: " << RangeToString(*current_range)
1062                << ", media_time: " << media_time.InMicroseconds()
1063                << ", current_range->HasNextBufferPosition(): "
1064                << current_range->HasNextBufferPosition();
1065       bytes_deleted = current_range->DeleteGOPFromFront(&buffers);
1066     }
1067
1068     // Check to see if we've just deleted the GOP that was last appended.
1069     base::TimeDelta end_timestamp = buffers.back()->timestamp();
1070     if (end_timestamp == last_appended_buffer_timestamp_) {
1071       DCHECK(last_appended_buffer_timestamp_ != kNoTimestamp);
1072       DCHECK(!new_range_for_append);
1073
1074       // Create a new range containing these buffers.
1075       new_range_for_append = std::make_unique<SourceBufferRange>(
1076           TypeToGapPolicy(GetType()), buffers, kNoTimestamp,
1077           base::BindRepeating(&SourceBufferStream::GetMaxInterbufferDistance,
1078                               base::Unretained(this)));
1079
1080       range_for_next_append_ = ranges_.end();
1081     } else {
1082       bytes_freed += bytes_deleted;
1083     }
1084
1085     if (current_range->size_in_bytes() == 0) {
1086       DCHECK_NE(current_range, selected_range_);
1087       DCHECK(range_for_next_append_ == ranges_.end() ||
1088              range_for_next_append_->get() != current_range);
1089
1090       // Delete |current_range| by popping it out of |ranges_|.
1091       reverse_direction ? ranges_.pop_back() : ranges_.pop_front();
1092     }
1093
1094     if (reverse_direction && new_range_for_append) {
1095       // We don't want to delete any further, or we'll be creating gaps
1096       break;
1097     }
1098   }
1099
1100   // Insert |new_range_for_append| into |ranges_|, if applicable.
1101   if (new_range_for_append) {
1102     range_for_next_append_ = AddToRanges(std::move(new_range_for_append));
1103     DCHECK(range_for_next_append_ != ranges_.end());
1104
1105     // Check to see if we need to merge the just added range that was in
1106     // |new_range_for_append| with the range before or after it. That added
1107     // range is created whenever the last GOP appended is encountered,
1108     // regardless of whether any buffers after it are ultimately deleted.
1109     // Merging is necessary if there were no buffers (or very few buffers)
1110     // deleted after creating that added range.
1111     if (range_for_next_append_ != ranges_.begin()) {
1112       auto range_before_next = range_for_next_append_;
1113       --range_before_next;
1114       MergeWithNextRangeIfNecessary(range_before_next);
1115     }
1116     MergeWithNextRangeIfNecessary(range_for_next_append_);
1117   }
1118   return bytes_freed;
1119 }
1120
1121 void SourceBufferStream::TrimSpliceOverlap(const BufferQueue& new_buffers) {
1122   DCHECK(!new_buffers.empty());
1123   DCHECK_EQ(SourceBufferStreamType::kAudio, GetType());
1124
1125   const base::TimeDelta splice_timestamp = new_buffers.front()->timestamp();
1126
1127   // Since some audio formats may have nonkeyframes (in PTS order since last
1128   // keyframe), if the front of the new buffers is one of those, it cannot be
1129   // used to begin a decode following an overlap. Here, we bail in this case,
1130   // since such a splice could not be coherently decoded.
1131   if (!new_buffers.front()->is_key_frame()) {
1132     DVLOG(3) << __func__
1133              << " No splice trimming. Front of |new_buffers| is not a "
1134                 "keyframe, at time "
1135              << splice_timestamp.InMicroseconds();
1136     return;
1137   }
1138
1139   // Find the overlapped range (if any).
1140   auto range_itr = FindExistingRangeFor(splice_timestamp);
1141   if (range_itr == ranges_.end()) {
1142     DVLOG(3) << __func__ << " No splice trimming. No range overlap at time "
1143              << splice_timestamp.InMicroseconds();
1144     return;
1145   }
1146
1147   // Search for overlapped buffer needs exclusive end value. Choosing smallest
1148   // possible value.
1149   const base::TimeDelta end_pts = splice_timestamp + base::Microseconds(1);
1150
1151   // Find if new buffer's start would overlap an existing buffer. Note that
1152   // overlapped audio buffers might be nonkeyframes, but if so, FrameProcessor
1153   // ensures they are in PTS order since the previous keyframe.
1154   BufferQueue overlapped_buffers;
1155   if (!(*range_itr)
1156            ->GetBuffersInRange(splice_timestamp, end_pts,
1157                                &overlapped_buffers)) {
1158     // Bail if no overlapped buffers found.
1159     DVLOG(3) << __func__ << " No splice trimming. No buffer overlap at time "
1160              << splice_timestamp.InMicroseconds();
1161     return;
1162   }
1163
1164   // At most one buffer should exist containing the time of the newly appended
1165   // buffer's start. It may happen that bad content appends buffers with
1166   // durations that cause nonsensical overlap. Trimming should not be performed
1167   // in these cases, as the content is already in a bad state.
1168   if (overlapped_buffers.size() != 1U) {
1169     DVLOG(3) << __func__
1170              << " No splice trimming. Found more than one overlapped buffer"
1171                 " (bad content) at time "
1172              << splice_timestamp.InMicroseconds();
1173
1174     MEDIA_LOG(WARNING, media_log_)
1175         << "Media is badly muxed. Detected " << overlapped_buffers.size()
1176         << " overlapping audio buffers at time "
1177         << splice_timestamp.InMicroseconds();
1178     return;
1179   }
1180   StreamParserBuffer* overlapped_buffer = overlapped_buffers.front().get();
1181
1182   if (overlapped_buffer->timestamp() == splice_timestamp) {
1183     // Ignore buffers with the same start time. They will be completely removed
1184     // in PrepareRangesForNextAppend().
1185     DVLOG(3) << __func__ << " No splice trimming at time "
1186              << splice_timestamp.InMicroseconds()
1187              << ". Overlapped buffer will be completely removed.";
1188     return;
1189   }
1190
1191   // Trimming a buffer with estimated duration is too risky. Estimates are rough
1192   // and what appears to be overlap may really just be a bad estimate. Imprecise
1193   // trimming may lead to loss of AV sync.
1194   if (overlapped_buffer->is_duration_estimated()) {
1195     DVLOG(3) << __func__ << " Skipping audio splice trimming at PTS="
1196              << splice_timestamp.InMicroseconds() << ". Overlapped buffer has "
1197              << "estimated duration.";
1198     return;
1199   }
1200
1201   // Determine the duration of overlap.
1202   base::TimeDelta overlapped_end_time =
1203       overlapped_buffer->timestamp() + overlapped_buffer->duration();
1204   base::TimeDelta overlap_duration = overlapped_end_time - splice_timestamp;
1205
1206   // At this point overlap should be non-empty (ruled out same-timestamp above).
1207   DCHECK_GT(overlap_duration, base::TimeDelta());
1208
1209   // Don't trim for overlaps of less than one millisecond (which is frequently
1210   // the extent of timestamp resolution for poorly encoded media).
1211   if (overlap_duration < base::Milliseconds(1)) {
1212     std::stringstream log_string;
1213     log_string << "Skipping audio splice trimming at PTS="
1214                << splice_timestamp.InMicroseconds() << "us. Found only "
1215                << overlap_duration.InMicroseconds()
1216                << "us of overlap, need at least 1000us. Multiple occurrences "
1217                << "may result in loss of A/V sync.";
1218     LIMITED_MEDIA_LOG(DEBUG, media_log_, num_splice_logs_, kMaxAudioSpliceLogs)
1219         << log_string.str();
1220     DVLOG(1) << __func__ << log_string.str();
1221     return;
1222   }
1223
1224   // Trim overlap from the existing buffer.
1225   DecoderBuffer::DiscardPadding discard_padding =
1226       overlapped_buffer->discard_padding();
1227   discard_padding.second += overlap_duration;
1228   overlapped_buffer->set_discard_padding(discard_padding);
1229   overlapped_buffer->set_duration(overlapped_buffer->duration() -
1230                                   overlap_duration);
1231
1232   // Note that the range's end time tracking shouldn't need explicit updating
1233   // here due to the overlapped buffer's truncation because the range tracks
1234   // that end time using a pointer to the buffer (which should be
1235   // |overlapped_buffer| if the overlap occurred at the end of the range).
1236   // Every audio frame is either a keyframe, or if a nonkeyframe is in PTS order
1237   // since the last keyframe, so there is no out-of-order PTS vs DTS sequencing
1238   // to overcome. If the overlap occurs in the middle of the range, the caller
1239   // invokes methods on the range which internally update the end time(s) of the
1240   // resulting range(s) involved in the append.
1241
1242   std::stringstream log_string;
1243   log_string << "Audio buffer splice at PTS="
1244              << splice_timestamp.InMicroseconds()
1245              << "us. Trimmed tail of overlapped buffer (PTS="
1246              << overlapped_buffer->timestamp().InMicroseconds() << "us) by "
1247              << overlap_duration.InMicroseconds() << "us.";
1248   LIMITED_MEDIA_LOG(DEBUG, media_log_, num_splice_logs_, kMaxAudioSpliceLogs)
1249       << log_string.str();
1250   DVLOG(1) << __func__ << log_string.str();
1251 }
1252
1253 void SourceBufferStream::PrepareRangesForNextAppend(
1254     const BufferQueue& new_buffers,
1255     BufferQueue* deleted_buffers) {
1256   DCHECK(deleted_buffers);
1257
1258   if (GetType() == SourceBufferStreamType::kAudio)
1259     TrimSpliceOverlap(new_buffers);
1260
1261   base::TimeDelta buffers_start_timestamp = kNoTimestamp;
1262   base::TimeDelta buffers_end_timestamp = kNoTimestamp;
1263   GetTimestampInterval(new_buffers, &buffers_start_timestamp,
1264                        &buffers_end_timestamp);
1265   DCHECK(buffers_start_timestamp != kNoTimestamp);
1266   DCHECK(buffers_end_timestamp != kNoTimestamp);
1267
1268   // 1. Clean up the old buffers between the last appended buffers and the
1269   //    beginning of |new_buffers|.
1270   if (highest_timestamp_in_append_sequence_ != kNoTimestamp &&
1271       highest_timestamp_in_append_sequence_ < buffers_start_timestamp) {
1272     RemoveInternal(highest_timestamp_in_append_sequence_,
1273                    buffers_start_timestamp, true, deleted_buffers);
1274   }
1275
1276   // 2. Delete the buffers that |new_buffers| overlaps.
1277   // There may be buffers in |new_buffers| with timestamp before
1278   // |highest_timestamp_in_append_sequence_| that shouldn't trigger removal of
1279   // stuff before |highest_timestamp_in_append_sequence_|.
1280   if (highest_timestamp_in_append_sequence_ != kNoTimestamp &&
1281       buffers_start_timestamp < highest_timestamp_in_append_sequence_) {
1282     DCHECK(highest_timestamp_in_append_sequence_ <=
1283            highest_buffered_end_time_in_append_sequence_);
1284     buffers_start_timestamp = highest_buffered_end_time_in_append_sequence_;
1285   }
1286
1287   if (new_coded_frame_group_) {
1288     // Extend the deletion range earlier to the coded frame group start time if
1289     // this is the first append in a new coded frame group.
1290     DCHECK(coded_frame_group_start_pts_ != kNoTimestamp);
1291     buffers_start_timestamp =
1292         std::min(coded_frame_group_start_pts_, buffers_start_timestamp);
1293   }
1294
1295   // Return early if no further overlap removal is needed. First check if
1296   // |buffers_start_timestamp| is in the middle of the range; we could be
1297   // overlap-appending the middle of a previous coded frame sequence's range
1298   // with non-keyframes prior to |highest_timestamp_in_append_sequence_|, so we
1299   // need to split that range appropriately here and then return early. If we
1300   // don't return early here, overlap removal (including any necessary range
1301   // splitting) will occur.
1302   if (buffers_start_timestamp >= buffers_end_timestamp) {
1303     DCHECK(highest_timestamp_in_append_sequence_ != kNoTimestamp);
1304     DCHECK(range_for_next_append_ != ranges_.end());
1305     DCHECK((*range_for_next_append_)->BelongsToRange(buffers_start_timestamp));
1306
1307     // Split the range at |buffers_start_timestamp|, if necessary, then return
1308     // early.
1309     std::unique_ptr<SourceBufferRange> new_range =
1310         (*range_for_next_append_)->SplitRange(buffers_start_timestamp);
1311     if (!new_range)
1312       return;
1313
1314     range_for_next_append_ =
1315         ranges_.insert(++range_for_next_append_, std::move(new_range));
1316
1317     // Update the selected range if the next buffer position was transferred
1318     // to the newly inserted range.
1319     if ((*range_for_next_append_)->HasNextBufferPosition())
1320       SetSelectedRange(range_for_next_append_->get());
1321
1322     --range_for_next_append_;
1323     return;
1324   }
1325
1326   // Exclude the start from removal to avoid deleting the highest appended
1327   // buffer in cases where the first buffer in |new_buffers| has same timestamp
1328   // as the highest appended buffer (even in out-of-order DTS vs PTS sequence).
1329   // Only do this when :
1330   //   A. Type is video. This may occur in cases of VP9 alt-ref frames or frames
1331   //      with incorrect timestamps. Removing a frame may break decode
1332   //      dependencies and there are no downsides to just keeping it (other than
1333   //      some throw-away decoder work).
1334   //   B. Type is text. TODO(chcunningham): Implement text splicing. See
1335   //      http://crbug.com/661408
1336   //   C. Type is audio and overlapped duration is 0. We've encountered Vorbis
1337   //      streams containing zero-duration buffers (i.e. no real overlap). For
1338   //      non-zero duration removing overlapped frames is important to preserve
1339   //      A/V sync (see AudioClock).
1340   const bool exclude_start =
1341       highest_timestamp_in_append_sequence_ ==
1342           new_buffers.front()->timestamp() &&
1343       (GetType() == SourceBufferStreamType::kVideo ||
1344        GetType() == SourceBufferStreamType::kText ||
1345        last_appended_buffer_duration_ == base::TimeDelta());
1346
1347   // Finally do the deletion of overlap.
1348   RemoveInternal(buffers_start_timestamp, buffers_end_timestamp, exclude_start,
1349                  deleted_buffers);
1350 }
1351
1352 // static
1353 void SourceBufferStream::GetTimestampInterval(const BufferQueue& buffers,
1354                                               base::TimeDelta* start,
1355                                               base::TimeDelta* end) {
1356   base::TimeDelta start_pts = buffers.front()->timestamp();
1357   base::TimeDelta end_pts = start_pts;
1358
1359   for (const auto& buffer : buffers) {
1360     base::TimeDelta timestamp = buffer->timestamp();
1361     start_pts = std::min(timestamp, start_pts);
1362     base::TimeDelta duration = buffer->duration();
1363
1364     // FrameProcessor should protect against unknown buffer durations.
1365     DCHECK_NE(duration, kNoTimestamp);
1366
1367     if (duration.is_positive() && !buffer->is_duration_estimated()) {
1368       timestamp += duration;
1369     } else {
1370       // TODO(chcunningham): Emit warning when 0ms durations are not expected.
1371       // http://crbug.com/312836
1372       timestamp += base::Microseconds(1);
1373     }
1374     end_pts = std::max(timestamp, end_pts);
1375   }
1376   *start = start_pts;
1377   *end = end_pts;
1378 }
1379
1380 bool SourceBufferStream::IsNextGopAdjacentToEndOfCurrentAppendSequence(
1381     base::TimeDelta next_gop_timestamp) const {
1382   base::TimeDelta upper_bound = highest_timestamp_in_append_sequence_ +
1383                                 ComputeFudgeRoom(GetMaxInterbufferDistance());
1384   DVLOG(4) << __func__ << " " << GetStreamTypeName()
1385            << " next_gop_timestamp=" << next_gop_timestamp.InMicroseconds()
1386            << "us, highest_timestamp_in_append_sequence_="
1387            << highest_timestamp_in_append_sequence_.InMicroseconds()
1388            << "us, upper_bound=" << upper_bound.InMicroseconds() << "us";
1389   return highest_timestamp_in_append_sequence_ < next_gop_timestamp &&
1390          next_gop_timestamp <= upper_bound;
1391 }
1392
1393 void SourceBufferStream::PruneTrackBuffer(const base::TimeDelta timestamp) {
1394   DCHECK(timestamp != kNoTimestamp);
1395
1396   // Scan forward until we find a buffer with timestamp at or beyond the limit.
1397   // Then remove all those at and beyond that point.
1398   size_t goal_size = 0;  // The number of buffers we will keep in the result.
1399   for (const auto& buf : track_buffer_) {
1400     if (buf->timestamp() >= timestamp)
1401       break;
1402     goal_size++;
1403   }
1404
1405   while (track_buffer_.size() > goal_size) {
1406     track_buffer_.pop_back();
1407   }
1408
1409   DVLOG(3) << __func__ << " " << GetStreamTypeName()
1410            << " Removed all buffers in track buffer sequence starting with the "
1411               "first at timestamp >= "
1412            << timestamp.InMicroseconds()
1413            << "us. New track buffer size:" << track_buffer_.size();
1414 }
1415
1416 void SourceBufferStream::MergeWithNextRangeIfNecessary(
1417     const RangeList::iterator& range_with_new_buffers_itr) {
1418   DCHECK(range_with_new_buffers_itr != ranges_.end());
1419
1420   SourceBufferRange* range_with_new_buffers = range_with_new_buffers_itr->get();
1421   RangeList::iterator next_range_itr = range_with_new_buffers_itr;
1422   ++next_range_itr;
1423
1424   if (next_range_itr == ranges_.end() ||
1425       !range_with_new_buffers->CanAppendRangeToEnd(**next_range_itr)) {
1426     return;
1427   }
1428
1429   bool transfer_current_position = selected_range_ == next_range_itr->get();
1430   DVLOG(3) << __func__ << " " << GetStreamTypeName() << " merging "
1431            << RangeToString(*range_with_new_buffers) << " into "
1432            << RangeToString(**next_range_itr);
1433   range_with_new_buffers->AppendRangeToEnd(**next_range_itr,
1434                                            transfer_current_position);
1435   // Update |selected_range_| pointer if |range| has become selected after
1436   // merges.
1437   if (transfer_current_position)
1438     SetSelectedRange(range_with_new_buffers);
1439
1440   if (next_range_itr == range_for_next_append_)
1441     range_for_next_append_ = range_with_new_buffers_itr;
1442
1443   DeleteAndRemoveRange(&next_range_itr);
1444 }
1445
1446 void SourceBufferStream::MergeAllAdjacentRanges() {
1447   DVLOG(1) << __func__ << " " << GetStreamTypeName()
1448            << ": Before: ranges_=" << RangesToString(ranges_);
1449
1450   auto range_itr = ranges_.begin();
1451
1452   while (range_itr != ranges_.end()) {
1453     const size_t old_ranges_size = ranges_.size();
1454     MergeWithNextRangeIfNecessary(range_itr);
1455
1456     // Only proceed to the next range if the current range didn't merge with it.
1457     if (old_ranges_size == ranges_.size())
1458       range_itr++;
1459   }
1460
1461   DVLOG(1) << __func__ << " " << GetStreamTypeName()
1462            << ": After: ranges_=" << RangesToString(ranges_);
1463 }
1464
1465 void SourceBufferStream::Seek(base::TimeDelta timestamp) {
1466   DCHECK(timestamp >= base::TimeDelta());
1467   DVLOG(1) << __func__ << " " << GetStreamTypeName() << " ("
1468            << timestamp.InMicroseconds() << "us)";
1469   ResetSeekState();
1470
1471   seek_buffer_timestamp_ = timestamp;
1472   seek_pending_ = true;
1473
1474   if (ShouldSeekToStartOfBuffered(timestamp)) {
1475     ranges_.front()->SeekToStart();
1476     SetSelectedRange(ranges_.front().get());
1477     seek_pending_ = false;
1478     return;
1479   }
1480
1481   auto itr = ranges_.end();
1482   for (itr = ranges_.begin(); itr != ranges_.end(); ++itr) {
1483     if ((*itr)->CanSeekTo(timestamp))
1484       break;
1485   }
1486
1487   if (itr == ranges_.end())
1488     return;
1489
1490   if (!audio_configs_.empty()) {
1491     // Adjust |timestamp| for an Opus stream backward up to the config's seek
1492     // preroll, but not further than the range start time, and not at all if
1493     // there is a config change in the middle of that preroll interval. If
1494     // |timestamp| is already before the range start time, as can happen due to
1495     // fudge room, do not adjust it.
1496     const auto& config = audio_configs_[(*itr)->GetConfigIdAtTime(timestamp)];
1497     if (config.codec() == AudioCodec::kOpus &&
1498         timestamp > (*itr)->GetStartTimestamp()) {
1499       base::TimeDelta preroll_timestamp = std::max(
1500           timestamp - config.seek_preroll(), (*itr)->GetStartTimestamp());
1501       if ((*itr)->CanSeekTo(preroll_timestamp) &&
1502           (*itr)->SameConfigThruRange(preroll_timestamp, timestamp)) {
1503         timestamp = preroll_timestamp;
1504       }
1505     }
1506   }
1507
1508   SeekAndSetSelectedRange(itr->get(), timestamp);
1509   seek_pending_ = false;
1510 }
1511
1512 bool SourceBufferStream::IsSeekPending() const {
1513   return seek_pending_ && !IsEndOfStreamReached();
1514 }
1515
1516 // TODO(wolenetz): Disallow duration changes that truncate buffered media. See
1517 // https://crbug.com/623729.
1518 void SourceBufferStream::OnSetDuration(base::TimeDelta duration) {
1519   DVLOG(1) << __func__ << " " << GetStreamTypeName() << " ("
1520            << duration.InMicroseconds() << "us)";
1521   DCHECK(!end_of_stream_);
1522
1523   if (ranges_.empty())
1524     return;
1525
1526   base::TimeDelta start = duration;
1527   base::TimeDelta end = ranges_.back()->GetBufferedEndTimestamp();
1528
1529   // Trim the end if it exceeds the new duration.
1530   if (start < end) {
1531     BufferQueue deleted_buffers;
1532     RemoveInternal(start, end, false, &deleted_buffers);
1533
1534     if (!deleted_buffers.empty()) {
1535       // Truncation removed current position. Clear selected range.
1536       SetSelectedRange(NULL);
1537     }
1538   }
1539 }
1540
1541 SourceBufferStreamStatus SourceBufferStream::GetNextBuffer(
1542     scoped_refptr<StreamParserBuffer>* out_buffer) {
1543   DVLOG(2) << __func__ << " " << GetStreamTypeName();
1544   if (!pending_buffer_.get()) {
1545     const SourceBufferStreamStatus status = GetNextBufferInternal(out_buffer);
1546     if (status != SourceBufferStreamStatus::kSuccess ||
1547         !SetPendingBuffer(out_buffer)) {
1548       DVLOG(2) << __func__ << " " << GetStreamTypeName()
1549                << ": no pending buffer, returning status "
1550                << StatusToString(status);
1551       return status;
1552     }
1553   }
1554
1555   DCHECK(pending_buffer_->preroll_buffer().get());
1556
1557   const SourceBufferStreamStatus status =
1558       HandleNextBufferWithPreroll(out_buffer);
1559   DVLOG(2) << __func__ << " " << GetStreamTypeName()
1560            << ": handled next buffer with preroll, returning status "
1561            << StatusToString(status);
1562   return status;
1563 }
1564
1565 SourceBufferStreamStatus SourceBufferStream::HandleNextBufferWithPreroll(
1566     scoped_refptr<StreamParserBuffer>* out_buffer) {
1567   // Any config change should have already been handled.
1568   DCHECK_EQ(current_config_index_, pending_buffer_->GetConfigId());
1569
1570   // Check if the preroll buffer has already been handed out.
1571   if (!pending_buffers_complete_) {
1572     pending_buffers_complete_ = true;
1573     *out_buffer = pending_buffer_->preroll_buffer();
1574     return SourceBufferStreamStatus::kSuccess;
1575   }
1576
1577   // Preroll complete, hand out the final buffer.
1578   *out_buffer = std::move(pending_buffer_);
1579   return SourceBufferStreamStatus::kSuccess;
1580 }
1581
1582 SourceBufferStreamStatus SourceBufferStream::GetNextBufferInternal(
1583     scoped_refptr<StreamParserBuffer>* out_buffer) {
1584   CHECK(!config_change_pending_);
1585
1586   if (!track_buffer_.empty()) {
1587     DCHECK(!selected_range_);
1588
1589     if (track_buffer_.front()->GetConfigId() != current_config_index_) {
1590       config_change_pending_ = true;
1591       DVLOG(1) << "Config change (track buffer config ID does not match).";
1592       return SourceBufferStreamStatus::kConfigChange;
1593     }
1594
1595     DVLOG(3) << __func__ << " Next buffer coming from track_buffer_";
1596     *out_buffer = std::move(track_buffer_.front());
1597     track_buffer_.pop_front();
1598     WarnIfTrackBufferExhaustionSkipsForward(*out_buffer);
1599     highest_output_buffer_timestamp_ =
1600         std::max(highest_output_buffer_timestamp_, (*out_buffer)->timestamp());
1601
1602     // If the track buffer becomes empty, then try to set the selected range
1603     // based on the timestamp of this buffer being returned.
1604     if (track_buffer_.empty()) {
1605       just_exhausted_track_buffer_ = true;
1606       SetSelectedRangeIfNeeded(highest_output_buffer_timestamp_);
1607     }
1608
1609     return SourceBufferStreamStatus::kSuccess;
1610   }
1611
1612   DCHECK(track_buffer_.empty());
1613   if (!selected_range_ || !selected_range_->HasNextBuffer()) {
1614     if (IsEndOfStreamReached()) {
1615       return SourceBufferStreamStatus::kEndOfStream;
1616     }
1617     DVLOG(3) << __func__ << " " << GetStreamTypeName()
1618              << ": returning kNeedBuffer "
1619              << (selected_range_ ? "(selected range has no next buffer)"
1620                                  : "(no selected range)");
1621     return SourceBufferStreamStatus::kNeedBuffer;
1622   }
1623
1624   if (selected_range_->GetNextConfigId() != current_config_index_) {
1625     config_change_pending_ = true;
1626     DVLOG(1) << "Config change (selected range config ID does not match).";
1627     return SourceBufferStreamStatus::kConfigChange;
1628   }
1629
1630   CHECK(selected_range_->GetNextBuffer(out_buffer));
1631   WarnIfTrackBufferExhaustionSkipsForward(*out_buffer);
1632   highest_output_buffer_timestamp_ =
1633       std::max(highest_output_buffer_timestamp_, (*out_buffer)->timestamp());
1634   return SourceBufferStreamStatus::kSuccess;
1635 }
1636
1637 void SourceBufferStream::WarnIfTrackBufferExhaustionSkipsForward(
1638     scoped_refptr<StreamParserBuffer> next_buffer) {
1639   if (!just_exhausted_track_buffer_)
1640     return;
1641
1642   just_exhausted_track_buffer_ = false;
1643   DCHECK(next_buffer->is_key_frame());
1644   base::TimeDelta next_output_buffer_timestamp = next_buffer->timestamp();
1645   base::TimeDelta delta =
1646       next_output_buffer_timestamp - highest_output_buffer_timestamp_;
1647   if (delta > GetMaxInterbufferDistance()) {
1648     LIMITED_MEDIA_LOG(DEBUG, media_log_, num_track_buffer_gap_warning_logs_,
1649                       kMaxTrackBufferGapWarningLogs)
1650         << "Media append that overlapped current playback position may cause "
1651            "time gap in playing "
1652         << GetStreamTypeName() << " stream because the next keyframe is "
1653         << delta.InMilliseconds()
1654         << "ms beyond last overlapped frame. Media may appear temporarily "
1655            "frozen.";
1656   }
1657 }
1658
1659 bool SourceBufferStream::IsNextBufferConfigChanged() {
1660   if (!track_buffer_.empty())
1661     return track_buffer_.front()->GetConfigId() != current_config_index_;
1662
1663   if (!selected_range_ || !selected_range_->HasNextBuffer())
1664     return false;
1665
1666   return selected_range_->GetNextConfigId() != current_config_index_;
1667 }
1668
1669 base::TimeDelta SourceBufferStream::GetNextBufferTimestamp() {
1670   if (!track_buffer_.empty())
1671     return track_buffer_.front()->timestamp();
1672
1673   if (!selected_range_)
1674     return kNoTimestamp;
1675
1676   DCHECK(selected_range_->HasNextBufferPosition());
1677   return selected_range_->GetNextTimestamp();
1678 }
1679
1680 SourceBufferStream::RangeList::iterator
1681 SourceBufferStream::FindExistingRangeFor(base::TimeDelta start_timestamp) {
1682   for (auto itr = ranges_.begin(); itr != ranges_.end(); ++itr) {
1683     if ((*itr)->BelongsToRange(start_timestamp))
1684       return itr;
1685   }
1686   return ranges_.end();
1687 }
1688
1689 SourceBufferStream::RangeList::iterator SourceBufferStream::AddToRanges(
1690     std::unique_ptr<SourceBufferRange> new_range) {
1691   base::TimeDelta start_timestamp = new_range->GetStartTimestamp();
1692   auto itr = ranges_.end();
1693   for (itr = ranges_.begin(); itr != ranges_.end(); ++itr) {
1694     if ((*itr)->GetStartTimestamp() > start_timestamp)
1695       break;
1696   }
1697   return ranges_.insert(itr, std::move(new_range));
1698 }
1699
1700 void SourceBufferStream::SeekAndSetSelectedRange(
1701     SourceBufferRange* range,
1702     base::TimeDelta seek_timestamp) {
1703   if (range)
1704     range->Seek(seek_timestamp);
1705   SetSelectedRange(range);
1706 }
1707
1708 void SourceBufferStream::SetSelectedRange(SourceBufferRange* range) {
1709   DVLOG(1) << __func__ << " " << GetStreamTypeName() << ": " << selected_range_
1710            << " " << (selected_range_ ? RangeToString(*selected_range_) : "")
1711            << " -> " << range << " " << (range ? RangeToString(*range) : "");
1712   if (selected_range_)
1713     selected_range_->ResetNextBufferPosition();
1714   DCHECK(!range || range->HasNextBufferPosition());
1715   selected_range_ = range;
1716 }
1717
1718 Ranges<base::TimeDelta> SourceBufferStream::GetBufferedTime() const {
1719   Ranges<base::TimeDelta> ranges;
1720   for (auto itr = ranges_.begin(); itr != ranges_.end(); ++itr) {
1721     ranges.Add((*itr)->GetStartTimestamp(), (*itr)->GetBufferedEndTimestamp());
1722   }
1723   return ranges;
1724 }
1725
1726 base::TimeDelta SourceBufferStream::GetHighestPresentationTimestamp() const {
1727   if (ranges_.empty())
1728     return base::TimeDelta();
1729
1730   return ranges_.back()->GetEndTimestamp();
1731 }
1732
1733 base::TimeDelta SourceBufferStream::GetBufferedDuration() const {
1734   if (ranges_.empty())
1735     return base::TimeDelta();
1736
1737   return ranges_.back()->GetBufferedEndTimestamp();
1738 }
1739
1740 size_t SourceBufferStream::GetBufferedSize() const {
1741   size_t ranges_size = 0;
1742   for (const auto& range_ptr : ranges_)
1743     ranges_size += range_ptr->size_in_bytes();
1744   return ranges_size;
1745 }
1746
1747 void SourceBufferStream::MarkEndOfStream() {
1748   DCHECK(!end_of_stream_);
1749   end_of_stream_ = true;
1750 }
1751
1752 void SourceBufferStream::UnmarkEndOfStream() {
1753   DCHECK(end_of_stream_);
1754   end_of_stream_ = false;
1755 }
1756
1757 bool SourceBufferStream::IsEndOfStreamReached() const {
1758   if (!end_of_stream_ || !track_buffer_.empty())
1759     return false;
1760
1761   if (ranges_.empty())
1762     return true;
1763
1764   if (seek_pending_) {
1765     base::TimeDelta last_range_end_time =
1766         ranges_.back()->GetBufferedEndTimestamp();
1767     return seek_buffer_timestamp_ >= last_range_end_time;
1768   }
1769
1770   if (!selected_range_)
1771     return true;
1772
1773   return selected_range_ == ranges_.back().get();
1774 }
1775
1776 const AudioDecoderConfig& SourceBufferStream::GetCurrentAudioDecoderConfig() {
1777   if (config_change_pending_)
1778     CompleteConfigChange();
1779   // Trying to track down crash. http://crbug.com/715761
1780   CHECK(current_config_index_ >= 0 &&
1781         static_cast<size_t>(current_config_index_) < audio_configs_.size());
1782   return audio_configs_[current_config_index_];
1783 }
1784
1785 const VideoDecoderConfig& SourceBufferStream::GetCurrentVideoDecoderConfig() {
1786   if (config_change_pending_)
1787     CompleteConfigChange();
1788   // Trying to track down crash. http://crbug.com/715761
1789   CHECK(current_config_index_ >= 0 &&
1790         static_cast<size_t>(current_config_index_) < video_configs_.size());
1791   return video_configs_[current_config_index_];
1792 }
1793
1794 const TextTrackConfig& SourceBufferStream::GetCurrentTextTrackConfig() {
1795   return text_track_config_;
1796 }
1797
1798 base::TimeDelta SourceBufferStream::GetMaxInterbufferDistance() const {
1799   return max_interbuffer_distance_;
1800 }
1801
1802 bool SourceBufferStream::UpdateAudioConfig(const AudioDecoderConfig& config,
1803                                            bool allow_codec_change) {
1804   DCHECK(!audio_configs_.empty());
1805   DCHECK(video_configs_.empty());
1806   DVLOG(3) << "UpdateAudioConfig.";
1807
1808   if (!allow_codec_change &&
1809       audio_configs_[append_config_index_].codec() != config.codec()) {
1810     // TODO(wolenetz): When we relax addSourceBuffer() and changeType() codec
1811     // strictness, codec changes should be allowed even without changing the
1812     // bytestream.
1813     // TODO(wolenetz): Remove "experimental" from this error message when
1814     // changeType() ships without needing experimental blink flag.
1815     MEDIA_LOG(ERROR, media_log_) << "Audio codec changes not allowed unless "
1816                                     "using experimental changeType().";
1817     return false;
1818   }
1819
1820   // Check to see if the new config matches an existing one.
1821   for (size_t i = 0; i < audio_configs_.size(); ++i) {
1822     if (config.Matches(audio_configs_[i])) {
1823       append_config_index_ = i;
1824       return true;
1825     }
1826   }
1827
1828   // No matches found so let's add this one to the list.
1829   append_config_index_ = audio_configs_.size();
1830   DVLOG(2) << "New audio config - index: " << append_config_index_;
1831   audio_configs_.resize(audio_configs_.size() + 1);
1832   audio_configs_[append_config_index_] = config;
1833   return true;
1834 }
1835
1836 bool SourceBufferStream::UpdateVideoConfig(const VideoDecoderConfig& config,
1837                                            bool allow_codec_change) {
1838   DCHECK(!video_configs_.empty());
1839   DCHECK(audio_configs_.empty());
1840   DVLOG(3) << "UpdateVideoConfig.";
1841
1842   if (!allow_codec_change &&
1843       video_configs_[append_config_index_].codec() != config.codec()) {
1844     // TODO(wolenetz): When we relax addSourceBuffer() and changeType() codec
1845     // strictness, codec changes should be allowed even without changing the
1846     // bytestream.
1847     // TODO(wolenetz): Remove "experimental" from this error message when
1848     // changeType() ships without needing experimental blink flag.
1849     MEDIA_LOG(ERROR, media_log_) << "Video codec changes not allowed unless "
1850                                     "using experimental changeType()";
1851     return false;
1852   }
1853
1854   // Check to see if the new config matches an existing one.
1855   for (size_t i = 0; i < video_configs_.size(); ++i) {
1856     if (config.Matches(video_configs_[i])) {
1857       append_config_index_ = i;
1858       return true;
1859     }
1860   }
1861
1862   // No matches found so let's add this one to the list.
1863   append_config_index_ = video_configs_.size();
1864   DVLOG(2) << "New video config - index: " << append_config_index_;
1865   video_configs_.resize(video_configs_.size() + 1);
1866   video_configs_[append_config_index_] = config;
1867   return true;
1868 }
1869
1870 void SourceBufferStream::CompleteConfigChange() {
1871   config_change_pending_ = false;
1872
1873   if (!track_buffer_.empty()) {
1874     current_config_index_ = track_buffer_.front()->GetConfigId();
1875     return;
1876   }
1877
1878   if (selected_range_ && selected_range_->HasNextBuffer())
1879     current_config_index_ = selected_range_->GetNextConfigId();
1880 }
1881
1882 void SourceBufferStream::SetSelectedRangeIfNeeded(
1883     const base::TimeDelta timestamp) {
1884   DVLOG(2) << __func__ << " " << GetStreamTypeName() << "("
1885            << timestamp.InMicroseconds() << "us)";
1886
1887   if (selected_range_) {
1888     DCHECK(track_buffer_.empty());
1889     return;
1890   }
1891
1892   if (!track_buffer_.empty()) {
1893     DCHECK(!selected_range_);
1894     return;
1895   }
1896
1897   base::TimeDelta start_timestamp = timestamp;
1898
1899   // If the next buffer timestamp is not known then use a timestamp just after
1900   // the timestamp on the last buffer returned by GetNextBuffer().
1901   if (start_timestamp == kNoTimestamp) {
1902     if (highest_output_buffer_timestamp_ == kNoTimestamp) {
1903       DVLOG(2) << __func__ << " " << GetStreamTypeName()
1904                << " no previous output timestamp";
1905       return;
1906     }
1907
1908     start_timestamp = highest_output_buffer_timestamp_ + base::Microseconds(1);
1909   }
1910
1911   base::TimeDelta seek_timestamp =
1912       FindNewSelectedRangeSeekTimestamp(start_timestamp);
1913
1914   // If we don't have buffered data to seek to, then return.
1915   if (seek_timestamp == kNoTimestamp) {
1916     DVLOG(2) << __func__ << " " << GetStreamTypeName()
1917              << " couldn't find new selected range seek timestamp";
1918     return;
1919   }
1920
1921   DCHECK(track_buffer_.empty());
1922   SeekAndSetSelectedRange(FindExistingRangeFor(seek_timestamp)->get(),
1923                           seek_timestamp);
1924 }
1925
1926 base::TimeDelta SourceBufferStream::FindNewSelectedRangeSeekTimestamp(
1927     const base::TimeDelta start_timestamp) {
1928   DCHECK(start_timestamp != kNoTimestamp);
1929   DCHECK(start_timestamp >= base::TimeDelta());
1930
1931   auto itr = ranges_.begin();
1932
1933   // When checking a range to see if it has or begins soon enough after
1934   // |start_timestamp|, use the fudge room to determine "soon enough".
1935   base::TimeDelta start_timestamp_plus_fudge =
1936       start_timestamp + ComputeFudgeRoom(GetMaxInterbufferDistance());
1937
1938   // Multiple ranges could be within the fudge room, because the fudge room is
1939   // dynamic based on max inter-buffer distance seen so far. Optimistically
1940   // check the earliest ones first.
1941   for (; itr != ranges_.end(); ++itr) {
1942     base::TimeDelta range_start = (*itr)->GetStartTimestamp();
1943     if (range_start >= start_timestamp_plus_fudge)
1944       break;
1945     if ((*itr)->GetEndTimestamp() < start_timestamp)
1946       continue;
1947     base::TimeDelta search_timestamp = start_timestamp;
1948     if (start_timestamp < range_start &&
1949         start_timestamp_plus_fudge >= range_start) {
1950       search_timestamp = range_start;
1951     }
1952     base::TimeDelta keyframe_timestamp =
1953         (*itr)->NextKeyframeTimestamp(search_timestamp);
1954     if (keyframe_timestamp != kNoTimestamp)
1955       return keyframe_timestamp;
1956   }
1957
1958   DVLOG(2) << __func__ << " " << GetStreamTypeName()
1959            << " no buffered data for pts=" << start_timestamp.InMicroseconds()
1960            << "us";
1961   return kNoTimestamp;
1962 }
1963
1964 base::TimeDelta SourceBufferStream::FindKeyframeAfterTimestamp(
1965     const base::TimeDelta timestamp) {
1966   DCHECK(timestamp != kNoTimestamp);
1967
1968   auto itr = FindExistingRangeFor(timestamp);
1969
1970   if (itr == ranges_.end())
1971     return kNoTimestamp;
1972
1973   // First check for a keyframe timestamp >= |timestamp|
1974   // in the current range.
1975   return (*itr)->NextKeyframeTimestamp(timestamp);
1976 }
1977
1978 std::string SourceBufferStream::GetStreamTypeName() const {
1979   switch (GetType()) {
1980     case SourceBufferStreamType::kAudio:
1981       return "AUDIO";
1982     case SourceBufferStreamType::kVideo:
1983       return "VIDEO";
1984     case SourceBufferStreamType::kText:
1985       return "TEXT";
1986   }
1987   NOTREACHED();
1988   return "";
1989 }
1990
1991 SourceBufferStreamType SourceBufferStream::GetType() const {
1992   if (!audio_configs_.empty())
1993     return SourceBufferStreamType::kAudio;
1994   if (!video_configs_.empty())
1995     return SourceBufferStreamType::kVideo;
1996   DCHECK_NE(text_track_config_.kind(), kTextNone);
1997   return SourceBufferStreamType::kText;
1998 }
1999
2000 void SourceBufferStream::DeleteAndRemoveRange(RangeList::iterator* itr) {
2001   DVLOG(1) << __func__;
2002
2003   DCHECK(*itr != ranges_.end());
2004   if ((*itr)->get() == selected_range_) {
2005     DVLOG(1) << __func__ << " deleting selected range.";
2006     SetSelectedRange(NULL);
2007   }
2008
2009   if (*itr == range_for_next_append_) {
2010     DVLOG(1) << __func__ << " deleting range_for_next_append_.";
2011     range_for_next_append_ = ranges_.end();
2012     ResetLastAppendedState();
2013   }
2014
2015   *itr = ranges_.erase(*itr);
2016 }
2017
2018 bool SourceBufferStream::SetPendingBuffer(
2019     scoped_refptr<StreamParserBuffer>* out_buffer) {
2020   DCHECK(out_buffer->get());
2021   DCHECK(!pending_buffer_.get());
2022
2023   const bool have_preroll_buffer = !!(*out_buffer)->preroll_buffer().get();
2024
2025   if (!have_preroll_buffer)
2026     return false;
2027
2028   pending_buffer_.swap(*out_buffer);
2029   pending_buffers_complete_ = false;
2030   return true;
2031 }
2032
2033 }  // namespace media