Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / media / filters / source_buffer_range.cc
1 // Copyright 2014 The Chromium Authors. All rights reserved.
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_range.h"
6
7 #include <algorithm>
8
9 namespace media {
10
11 // Comparison operators for std::upper_bound() and std::lower_bound().
12 static bool CompareTimeDeltaToStreamParserBuffer(
13     const DecodeTimestamp& decode_timestamp,
14     const scoped_refptr<StreamParserBuffer>& buffer) {
15   return decode_timestamp < buffer->GetDecodeTimestamp();
16 }
17 static bool CompareStreamParserBufferToTimeDelta(
18     const scoped_refptr<StreamParserBuffer>& buffer,
19     const DecodeTimestamp& decode_timestamp) {
20   return buffer->GetDecodeTimestamp() < decode_timestamp;
21 }
22
23 bool SourceBufferRange::AllowSameTimestamp(
24     bool prev_is_keyframe, bool current_is_keyframe) {
25   return prev_is_keyframe || !current_is_keyframe;
26 }
27
28 SourceBufferRange::SourceBufferRange(
29     GapPolicy gap_policy, const BufferQueue& new_buffers,
30     DecodeTimestamp media_segment_start_time,
31     const InterbufferDistanceCB& interbuffer_distance_cb)
32     : gap_policy_(gap_policy),
33       keyframe_map_index_base_(0),
34       next_buffer_index_(-1),
35       media_segment_start_time_(media_segment_start_time),
36       interbuffer_distance_cb_(interbuffer_distance_cb),
37       size_in_bytes_(0) {
38   CHECK(!new_buffers.empty());
39   DCHECK(new_buffers.front()->IsKeyframe());
40   DCHECK(!interbuffer_distance_cb.is_null());
41   AppendBuffersToEnd(new_buffers);
42 }
43
44 SourceBufferRange::~SourceBufferRange() {}
45
46 void SourceBufferRange::AppendBuffersToEnd(const BufferQueue& new_buffers) {
47   DCHECK(buffers_.empty() || CanAppendBuffersToEnd(new_buffers));
48   DCHECK(media_segment_start_time_ == kNoDecodeTimestamp() ||
49          media_segment_start_time_ <=
50              new_buffers.front()->GetDecodeTimestamp());
51   for (BufferQueue::const_iterator itr = new_buffers.begin();
52        itr != new_buffers.end();
53        ++itr) {
54     DCHECK((*itr)->GetDecodeTimestamp() != kNoDecodeTimestamp());
55     buffers_.push_back(*itr);
56     size_in_bytes_ += (*itr)->data_size();
57
58     if ((*itr)->IsKeyframe()) {
59       keyframe_map_.insert(
60           std::make_pair((*itr)->GetDecodeTimestamp(),
61                          buffers_.size() - 1 + keyframe_map_index_base_));
62     }
63   }
64 }
65
66 void SourceBufferRange::Seek(DecodeTimestamp timestamp) {
67   DCHECK(CanSeekTo(timestamp));
68   DCHECK(!keyframe_map_.empty());
69
70   KeyframeMap::iterator result = GetFirstKeyframeBefore(timestamp);
71   next_buffer_index_ = result->second - keyframe_map_index_base_;
72   DCHECK_LT(next_buffer_index_, static_cast<int>(buffers_.size()));
73 }
74
75 void SourceBufferRange::SeekAheadTo(DecodeTimestamp timestamp) {
76   SeekAhead(timestamp, false);
77 }
78
79 void SourceBufferRange::SeekAheadPast(DecodeTimestamp timestamp) {
80   SeekAhead(timestamp, true);
81 }
82
83 void SourceBufferRange::SeekAhead(DecodeTimestamp timestamp,
84                                   bool skip_given_timestamp) {
85   DCHECK(!keyframe_map_.empty());
86
87   KeyframeMap::iterator result =
88       GetFirstKeyframeAt(timestamp, skip_given_timestamp);
89
90   // If there isn't a keyframe after |timestamp|, then seek to end and return
91   // kNoTimestamp to signal such.
92   if (result == keyframe_map_.end()) {
93     next_buffer_index_ = -1;
94     return;
95   }
96   next_buffer_index_ = result->second - keyframe_map_index_base_;
97   DCHECK_LT(next_buffer_index_, static_cast<int>(buffers_.size()));
98 }
99
100 void SourceBufferRange::SeekToStart() {
101   DCHECK(!buffers_.empty());
102   next_buffer_index_ = 0;
103 }
104
105 SourceBufferRange* SourceBufferRange::SplitRange(
106     DecodeTimestamp timestamp, bool is_exclusive) {
107   CHECK(!buffers_.empty());
108
109   // Find the first keyframe after |timestamp|. If |is_exclusive|, do not
110   // include keyframes at |timestamp|.
111   KeyframeMap::iterator new_beginning_keyframe =
112       GetFirstKeyframeAt(timestamp, is_exclusive);
113
114   // If there is no keyframe after |timestamp|, we can't split the range.
115   if (new_beginning_keyframe == keyframe_map_.end())
116     return NULL;
117
118   // Remove the data beginning at |keyframe_index| from |buffers_| and save it
119   // into |removed_buffers|.
120   int keyframe_index =
121       new_beginning_keyframe->second - keyframe_map_index_base_;
122   DCHECK_LT(keyframe_index, static_cast<int>(buffers_.size()));
123   BufferQueue::iterator starting_point = buffers_.begin() + keyframe_index;
124   BufferQueue removed_buffers(starting_point, buffers_.end());
125
126   DecodeTimestamp new_range_start_timestamp = kNoDecodeTimestamp();
127   if (GetStartTimestamp() < buffers_.front()->GetDecodeTimestamp() &&
128       timestamp < removed_buffers.front()->GetDecodeTimestamp()) {
129     // The split is in the gap between |media_segment_start_time_| and
130     // the first buffer of the new range so we should set the start
131     // time of the new range to |timestamp| so we preserve part of the
132     // gap in the new range.
133     new_range_start_timestamp = timestamp;
134   }
135
136   keyframe_map_.erase(new_beginning_keyframe, keyframe_map_.end());
137   FreeBufferRange(starting_point, buffers_.end());
138
139   // Create a new range with |removed_buffers|.
140   SourceBufferRange* split_range =
141       new SourceBufferRange(
142           gap_policy_, removed_buffers, new_range_start_timestamp,
143           interbuffer_distance_cb_);
144
145   // If the next buffer position is now in |split_range|, update the state of
146   // this range and |split_range| accordingly.
147   if (next_buffer_index_ >= static_cast<int>(buffers_.size())) {
148     split_range->next_buffer_index_ = next_buffer_index_ - keyframe_index;
149     ResetNextBufferPosition();
150   }
151
152   return split_range;
153 }
154
155 SourceBufferRange::BufferQueue::iterator SourceBufferRange::GetBufferItrAt(
156     DecodeTimestamp timestamp,
157     bool skip_given_timestamp) {
158   return skip_given_timestamp
159              ? std::upper_bound(buffers_.begin(),
160                                 buffers_.end(),
161                                 timestamp,
162                                 CompareTimeDeltaToStreamParserBuffer)
163              : std::lower_bound(buffers_.begin(),
164                                 buffers_.end(),
165                                 timestamp,
166                                 CompareStreamParserBufferToTimeDelta);
167 }
168
169 SourceBufferRange::KeyframeMap::iterator
170 SourceBufferRange::GetFirstKeyframeAt(DecodeTimestamp timestamp,
171                                       bool skip_given_timestamp) {
172   return skip_given_timestamp ?
173       keyframe_map_.upper_bound(timestamp) :
174       keyframe_map_.lower_bound(timestamp);
175 }
176
177 SourceBufferRange::KeyframeMap::iterator
178 SourceBufferRange::GetFirstKeyframeBefore(DecodeTimestamp timestamp) {
179   KeyframeMap::iterator result = keyframe_map_.lower_bound(timestamp);
180   // lower_bound() returns the first element >= |timestamp|, so we want the
181   // previous element if it did not return the element exactly equal to
182   // |timestamp|.
183   if (result != keyframe_map_.begin() &&
184       (result == keyframe_map_.end() || result->first != timestamp)) {
185     --result;
186   }
187   return result;
188 }
189
190 void SourceBufferRange::DeleteAll(BufferQueue* removed_buffers) {
191   TruncateAt(buffers_.begin(), removed_buffers);
192 }
193
194 bool SourceBufferRange::TruncateAt(
195     DecodeTimestamp timestamp, BufferQueue* removed_buffers,
196     bool is_exclusive) {
197   // Find the place in |buffers_| where we will begin deleting data.
198   BufferQueue::iterator starting_point =
199       GetBufferItrAt(timestamp, is_exclusive);
200   return TruncateAt(starting_point, removed_buffers);
201 }
202
203 int SourceBufferRange::DeleteGOPFromFront(BufferQueue* deleted_buffers) {
204   DCHECK(!FirstGOPContainsNextBufferPosition());
205   DCHECK(deleted_buffers);
206
207   int buffers_deleted = 0;
208   int total_bytes_deleted = 0;
209
210   KeyframeMap::iterator front = keyframe_map_.begin();
211   DCHECK(front != keyframe_map_.end());
212
213   // Delete the keyframe at the start of |keyframe_map_|.
214   keyframe_map_.erase(front);
215
216   // Now we need to delete all the buffers that depend on the keyframe we've
217   // just deleted.
218   int end_index = keyframe_map_.size() > 0 ?
219       keyframe_map_.begin()->second - keyframe_map_index_base_ :
220       buffers_.size();
221
222   // Delete buffers from the beginning of the buffered range up until (but not
223   // including) the next keyframe.
224   for (int i = 0; i < end_index; i++) {
225     int bytes_deleted = buffers_.front()->data_size();
226     size_in_bytes_ -= bytes_deleted;
227     total_bytes_deleted += bytes_deleted;
228     deleted_buffers->push_back(buffers_.front());
229     buffers_.pop_front();
230     ++buffers_deleted;
231   }
232
233   // Update |keyframe_map_index_base_| to account for the deleted buffers.
234   keyframe_map_index_base_ += buffers_deleted;
235
236   if (next_buffer_index_ > -1) {
237     next_buffer_index_ -= buffers_deleted;
238     DCHECK_GE(next_buffer_index_, 0);
239   }
240
241   // Invalidate media segment start time if we've deleted the first buffer of
242   // the range.
243   if (buffers_deleted > 0)
244     media_segment_start_time_ = kNoDecodeTimestamp();
245
246   return total_bytes_deleted;
247 }
248
249 int SourceBufferRange::DeleteGOPFromBack(BufferQueue* deleted_buffers) {
250   DCHECK(!LastGOPContainsNextBufferPosition());
251   DCHECK(deleted_buffers);
252
253   // Remove the last GOP's keyframe from the |keyframe_map_|.
254   KeyframeMap::iterator back = keyframe_map_.end();
255   DCHECK_GT(keyframe_map_.size(), 0u);
256   --back;
257
258   // The index of the first buffer in the last GOP is equal to the new size of
259   // |buffers_| after that GOP is deleted.
260   size_t goal_size = back->second - keyframe_map_index_base_;
261   keyframe_map_.erase(back);
262
263   int total_bytes_deleted = 0;
264   while (buffers_.size() != goal_size) {
265     int bytes_deleted = buffers_.back()->data_size();
266     size_in_bytes_ -= bytes_deleted;
267     total_bytes_deleted += bytes_deleted;
268     // We're removing buffers from the back, so push each removed buffer to the
269     // front of |deleted_buffers| so that |deleted_buffers| are in nondecreasing
270     // order.
271     deleted_buffers->push_front(buffers_.back());
272     buffers_.pop_back();
273   }
274
275   return total_bytes_deleted;
276 }
277
278 int SourceBufferRange::GetRemovalGOP(
279     DecodeTimestamp start_timestamp, DecodeTimestamp end_timestamp,
280     int total_bytes_to_free, DecodeTimestamp* removal_end_timestamp) {
281   int bytes_to_free = total_bytes_to_free;
282   int bytes_removed = 0;
283
284   KeyframeMap::iterator gop_itr = GetFirstKeyframeAt(start_timestamp, false);
285   if (gop_itr == keyframe_map_.end())
286     return 0;
287   int keyframe_index = gop_itr->second - keyframe_map_index_base_;
288   BufferQueue::iterator buffer_itr = buffers_.begin() + keyframe_index;
289   KeyframeMap::iterator gop_end = keyframe_map_.end();
290   if (end_timestamp < GetBufferedEndTimestamp())
291     gop_end = GetFirstKeyframeBefore(end_timestamp);
292
293   // Check if the removal range is within a GOP and skip the loop if so.
294   // [keyframe]...[start_timestamp]...[end_timestamp]...[keyframe]
295   KeyframeMap::iterator gop_itr_prev = gop_itr;
296   if (gop_itr_prev != keyframe_map_.begin() && --gop_itr_prev == gop_end)
297     gop_end = gop_itr;
298
299   while (gop_itr != gop_end && bytes_to_free > 0) {
300     ++gop_itr;
301
302     int gop_size = 0;
303     int next_gop_index = gop_itr == keyframe_map_.end() ?
304         buffers_.size() : gop_itr->second - keyframe_map_index_base_;
305     BufferQueue::iterator next_gop_start = buffers_.begin() + next_gop_index;
306     for (; buffer_itr != next_gop_start; ++buffer_itr)
307       gop_size += (*buffer_itr)->data_size();
308
309     bytes_removed += gop_size;
310     bytes_to_free -= gop_size;
311   }
312   if (bytes_removed > 0) {
313     *removal_end_timestamp = gop_itr == keyframe_map_.end() ?
314         GetBufferedEndTimestamp() : gop_itr->first;
315   }
316   return bytes_removed;
317 }
318
319 bool SourceBufferRange::FirstGOPContainsNextBufferPosition() const {
320   if (!HasNextBufferPosition())
321     return false;
322
323   // If there is only one GOP, it must contain the next buffer position.
324   if (keyframe_map_.size() == 1u)
325     return true;
326
327   KeyframeMap::const_iterator second_gop = keyframe_map_.begin();
328   ++second_gop;
329   return next_buffer_index_ < second_gop->second - keyframe_map_index_base_;
330 }
331
332 bool SourceBufferRange::LastGOPContainsNextBufferPosition() const {
333   if (!HasNextBufferPosition())
334     return false;
335
336   // If there is only one GOP, it must contain the next buffer position.
337   if (keyframe_map_.size() == 1u)
338     return true;
339
340   KeyframeMap::const_iterator last_gop = keyframe_map_.end();
341   --last_gop;
342   return last_gop->second - keyframe_map_index_base_ <= next_buffer_index_;
343 }
344
345 void SourceBufferRange::FreeBufferRange(
346     const BufferQueue::iterator& starting_point,
347     const BufferQueue::iterator& ending_point) {
348   for (BufferQueue::iterator itr = starting_point;
349        itr != ending_point; ++itr) {
350     size_in_bytes_ -= (*itr)->data_size();
351     DCHECK_GE(size_in_bytes_, 0);
352   }
353   buffers_.erase(starting_point, ending_point);
354 }
355
356 bool SourceBufferRange::TruncateAt(
357     const BufferQueue::iterator& starting_point, BufferQueue* removed_buffers) {
358   DCHECK(!removed_buffers || removed_buffers->empty());
359
360   // Return if we're not deleting anything.
361   if (starting_point == buffers_.end())
362     return buffers_.empty();
363
364   // Reset the next buffer index if we will be deleting the buffer that's next
365   // in sequence.
366   if (HasNextBufferPosition()) {
367     DecodeTimestamp next_buffer_timestamp = GetNextTimestamp();
368     if (next_buffer_timestamp == kNoDecodeTimestamp() ||
369         next_buffer_timestamp >= (*starting_point)->GetDecodeTimestamp()) {
370       if (HasNextBuffer() && removed_buffers) {
371         int starting_offset = starting_point - buffers_.begin();
372         int next_buffer_offset = next_buffer_index_ - starting_offset;
373         DCHECK_GE(next_buffer_offset, 0);
374         BufferQueue saved(starting_point + next_buffer_offset, buffers_.end());
375         removed_buffers->swap(saved);
376       }
377       ResetNextBufferPosition();
378     }
379   }
380
381   // Remove keyframes from |starting_point| onward.
382   KeyframeMap::iterator starting_point_keyframe =
383       keyframe_map_.lower_bound((*starting_point)->GetDecodeTimestamp());
384   keyframe_map_.erase(starting_point_keyframe, keyframe_map_.end());
385
386   // Remove everything from |starting_point| onward.
387   FreeBufferRange(starting_point, buffers_.end());
388   return buffers_.empty();
389 }
390
391 bool SourceBufferRange::GetNextBuffer(
392     scoped_refptr<StreamParserBuffer>* out_buffer) {
393   if (!HasNextBuffer())
394     return false;
395
396   *out_buffer = buffers_[next_buffer_index_];
397   next_buffer_index_++;
398   return true;
399 }
400
401 bool SourceBufferRange::HasNextBuffer() const {
402   return next_buffer_index_ >= 0 &&
403       next_buffer_index_ < static_cast<int>(buffers_.size());
404 }
405
406 int SourceBufferRange::GetNextConfigId() const {
407   DCHECK(HasNextBuffer());
408   // If the next buffer is an audio splice frame, the next effective config id
409   // comes from the first fade out preroll buffer.
410   return buffers_[next_buffer_index_]->GetSpliceBufferConfigId(0);
411 }
412
413 DecodeTimestamp SourceBufferRange::GetNextTimestamp() const {
414   DCHECK(!buffers_.empty());
415   DCHECK(HasNextBufferPosition());
416
417   if (next_buffer_index_ >= static_cast<int>(buffers_.size())) {
418     return kNoDecodeTimestamp();
419   }
420
421   return buffers_[next_buffer_index_]->GetDecodeTimestamp();
422 }
423
424 bool SourceBufferRange::HasNextBufferPosition() const {
425   return next_buffer_index_ >= 0;
426 }
427
428 void SourceBufferRange::ResetNextBufferPosition() {
429   next_buffer_index_ = -1;
430 }
431
432 void SourceBufferRange::AppendRangeToEnd(const SourceBufferRange& range,
433                                          bool transfer_current_position) {
434   DCHECK(CanAppendRangeToEnd(range));
435   DCHECK(!buffers_.empty());
436
437   if (transfer_current_position && range.next_buffer_index_ >= 0)
438     next_buffer_index_ = range.next_buffer_index_ + buffers_.size();
439
440   AppendBuffersToEnd(range.buffers_);
441 }
442
443 bool SourceBufferRange::CanAppendRangeToEnd(
444     const SourceBufferRange& range) const {
445   return CanAppendBuffersToEnd(range.buffers_);
446 }
447
448 bool SourceBufferRange::CanAppendBuffersToEnd(
449     const BufferQueue& buffers) const {
450   DCHECK(!buffers_.empty());
451   return IsNextInSequence(buffers.front()->GetDecodeTimestamp(),
452                           buffers.front()->IsKeyframe());
453 }
454
455 bool SourceBufferRange::BelongsToRange(DecodeTimestamp timestamp) const {
456   DCHECK(!buffers_.empty());
457
458   return (IsNextInSequence(timestamp, false) ||
459           (GetStartTimestamp() <= timestamp && timestamp <= GetEndTimestamp()));
460 }
461
462 bool SourceBufferRange::CanSeekTo(DecodeTimestamp timestamp) const {
463   DecodeTimestamp start_timestamp =
464       std::max(DecodeTimestamp(), GetStartTimestamp() - GetFudgeRoom());
465   return !keyframe_map_.empty() && start_timestamp <= timestamp &&
466       timestamp < GetBufferedEndTimestamp();
467 }
468
469 bool SourceBufferRange::CompletelyOverlaps(
470     const SourceBufferRange& range) const {
471   return GetStartTimestamp() <= range.GetStartTimestamp() &&
472       GetEndTimestamp() >= range.GetEndTimestamp();
473 }
474
475 bool SourceBufferRange::EndOverlaps(const SourceBufferRange& range) const {
476   return range.GetStartTimestamp() <= GetEndTimestamp() &&
477       GetEndTimestamp() < range.GetEndTimestamp();
478 }
479
480 DecodeTimestamp SourceBufferRange::GetStartTimestamp() const {
481   DCHECK(!buffers_.empty());
482   DecodeTimestamp start_timestamp = media_segment_start_time_;
483   if (start_timestamp == kNoDecodeTimestamp())
484     start_timestamp = buffers_.front()->GetDecodeTimestamp();
485   return start_timestamp;
486 }
487
488 DecodeTimestamp SourceBufferRange::GetEndTimestamp() const {
489   DCHECK(!buffers_.empty());
490   return buffers_.back()->GetDecodeTimestamp();
491 }
492
493 DecodeTimestamp SourceBufferRange::GetBufferedEndTimestamp() const {
494   DCHECK(!buffers_.empty());
495   base::TimeDelta duration = buffers_.back()->duration();
496   if (duration == kNoTimestamp() || duration == base::TimeDelta())
497     duration = GetApproximateDuration();
498   return GetEndTimestamp() + duration;
499 }
500
501 DecodeTimestamp SourceBufferRange::NextKeyframeTimestamp(
502     DecodeTimestamp timestamp) {
503   DCHECK(!keyframe_map_.empty());
504
505   if (timestamp < GetStartTimestamp() || timestamp >= GetBufferedEndTimestamp())
506     return kNoDecodeTimestamp();
507
508   KeyframeMap::iterator itr = GetFirstKeyframeAt(timestamp, false);
509   if (itr == keyframe_map_.end())
510     return kNoDecodeTimestamp();
511
512   // If the timestamp is inside the gap between the start of the media
513   // segment and the first buffer, then just pretend there is a
514   // keyframe at the specified timestamp.
515   if (itr == keyframe_map_.begin() &&
516       timestamp > media_segment_start_time_ &&
517       timestamp < itr->first) {
518     return timestamp;
519   }
520
521   return itr->first;
522 }
523
524 DecodeTimestamp SourceBufferRange::KeyframeBeforeTimestamp(
525     DecodeTimestamp timestamp) {
526   DCHECK(!keyframe_map_.empty());
527
528   if (timestamp < GetStartTimestamp() || timestamp >= GetBufferedEndTimestamp())
529     return kNoDecodeTimestamp();
530
531   return GetFirstKeyframeBefore(timestamp)->first;
532 }
533
534 bool SourceBufferRange::IsNextInSequence(
535     DecodeTimestamp timestamp, bool is_keyframe) const {
536   DecodeTimestamp end = buffers_.back()->GetDecodeTimestamp();
537   if (end < timestamp &&
538       (gap_policy_ == ALLOW_GAPS ||
539        timestamp <= end + GetFudgeRoom())) {
540     return true;
541   }
542
543   return timestamp == end && AllowSameTimestamp(
544       buffers_.back()->IsKeyframe(), is_keyframe);
545 }
546
547 base::TimeDelta SourceBufferRange::GetFudgeRoom() const {
548   // Because we do not know exactly when is the next timestamp, any buffer
549   // that starts within 2x the approximate duration of a buffer is considered
550   // within this range.
551   return 2 * GetApproximateDuration();
552 }
553
554 base::TimeDelta SourceBufferRange::GetApproximateDuration() const {
555   base::TimeDelta max_interbuffer_distance = interbuffer_distance_cb_.Run();
556   DCHECK(max_interbuffer_distance != kNoTimestamp());
557   return max_interbuffer_distance;
558 }
559
560 bool SourceBufferRange::GetBuffersInRange(DecodeTimestamp start,
561                                           DecodeTimestamp end,
562                                           BufferQueue* buffers) {
563   // Find the nearest buffer with a decode timestamp <= start.
564   const DecodeTimestamp first_timestamp = KeyframeBeforeTimestamp(start);
565   if (first_timestamp == kNoDecodeTimestamp())
566     return false;
567
568   // Find all buffers involved in the range.
569   const size_t previous_size = buffers->size();
570   for (BufferQueue::iterator it = GetBufferItrAt(first_timestamp, false);
571        it != buffers_.end();
572        ++it) {
573     const scoped_refptr<StreamParserBuffer>& buffer = *it;
574     // Buffers without duration are not supported, so bail if we encounter any.
575     if (buffer->duration() == kNoTimestamp() ||
576         buffer->duration() <= base::TimeDelta()) {
577       return false;
578     }
579     if (buffer->end_of_stream() ||
580         buffer->timestamp() >= end.ToPresentationTime()) {
581       break;
582     }
583
584     if (buffer->timestamp() + buffer->duration() <= start.ToPresentationTime())
585       continue;
586     buffers->push_back(buffer);
587   }
588   return previous_size < buffers->size();
589 }
590
591 }  // namespace media