Home | History | Annotate | Download | only in base
      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/base/text_ranges.h"
      6 
      7 #include "base/logging.h"
      8 
      9 namespace media {
     10 
     11 TextRanges::TextRanges() {
     12   Reset();
     13 }
     14 
     15 TextRanges::~TextRanges() {
     16 }
     17 
     18 void TextRanges::Reset() {
     19   curr_range_itr_ = range_map_.end();
     20 }
     21 
     22 bool TextRanges::AddCue(base::TimeDelta start_time) {
     23   typedef RangeMap::iterator Itr;
     24 
     25   if (curr_range_itr_ == range_map_.end()) {
     26     // There is no active time range, so this is the first AddCue()
     27     // attempt that follows a Reset().
     28 
     29     if (range_map_.empty()) {
     30       NewRange(start_time);
     31       return true;
     32     }
     33 
     34     if (start_time < range_map_.begin()->first) {
     35       NewRange(start_time);
     36       return true;
     37     }
     38 
     39     const Itr itr = --Itr(range_map_.upper_bound(start_time));
     40     DCHECK(start_time >= itr->first);
     41 
     42     Range& range = itr->second;
     43 
     44     if (start_time > range.last_time()) {
     45       NewRange(start_time);
     46       return true;
     47     }
     48 
     49     range.ResetCount(start_time);
     50     curr_range_itr_ = itr;
     51     return false;
     52   }
     53 
     54   DCHECK(start_time >= curr_range_itr_->first);
     55 
     56   Range& curr_range = curr_range_itr_->second;
     57 
     58   if (start_time <= curr_range.last_time())
     59     return curr_range.AddCue(start_time);
     60 
     61   const Itr next_range_itr = ++Itr(curr_range_itr_);
     62 
     63   if (next_range_itr != range_map_.end()) {
     64     DCHECK(next_range_itr->first > curr_range.last_time());
     65     DCHECK(start_time <= next_range_itr->first);
     66 
     67     if (start_time == next_range_itr->first) {
     68       // We have walked off the current range, and onto the next one.
     69       // There is now no ambiguity about where the current time range
     70       // ends, and so we coalesce the current and next ranges.
     71 
     72       Merge(curr_range, next_range_itr);
     73       return false;
     74     }
     75   }
     76 
     77   // Either |curr_range| is the last range in the map, or there is a
     78   // next range beyond |curr_range|, but its start time is ahead of
     79   // this cue's start time.  In either case, this cue becomes the new
     80   // last_time for |curr_range|.  Eventually we will see a cue whose
     81   // time matches the start time of the next range, in which case we
     82   // coalesce the current and next ranges.
     83 
     84   curr_range.SetLastTime(start_time);
     85   return true;
     86 }
     87 
     88 size_t TextRanges::RangeCountForTesting() const {
     89   return range_map_.size();
     90 }
     91 
     92 void TextRanges::NewRange(base::TimeDelta start_time) {
     93   Range range;
     94   range.SetLastTime(start_time);
     95 
     96   std::pair<RangeMap::iterator, bool> result =
     97       range_map_.insert(std::make_pair(start_time, range));
     98   DCHECK(result.second);
     99 
    100   curr_range_itr_ = result.first;
    101 }
    102 
    103 void TextRanges::Merge(
    104     Range& curr_range,
    105     const RangeMap::iterator& next_range_itr) {
    106   curr_range = next_range_itr->second;
    107   curr_range.ResetCount(next_range_itr->first);
    108   range_map_.erase(next_range_itr);
    109 }
    110 
    111 void TextRanges::Range::ResetCount(base::TimeDelta start_time) {
    112   count_ = (start_time < last_time_) ? 0 : 1;
    113 }
    114 
    115 void TextRanges::Range::SetLastTime(base::TimeDelta last_time) {
    116   last_time_ = last_time;
    117   count_ = 1;
    118   max_count_ = 1;
    119 }
    120 
    121 bool TextRanges::Range::AddCue(base::TimeDelta start_time) {
    122   if (start_time < last_time_) {
    123     DCHECK_EQ(count_, 0);
    124     return false;
    125   }
    126 
    127   DCHECK(start_time == last_time_);
    128 
    129   ++count_;
    130   if (count_ <= max_count_)
    131     return false;
    132 
    133   ++max_count_;
    134   return true;
    135 }
    136 
    137 base::TimeDelta TextRanges::Range::last_time() const {
    138   return last_time_;
    139 }
    140 
    141 }  // namespace media
    142