• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
TextRanges()11 TextRanges::TextRanges() {
12   Reset();
13 }
14 
~TextRanges()15 TextRanges::~TextRanges() {
16 }
17 
Reset()18 void TextRanges::Reset() {
19   curr_range_itr_ = range_map_.end();
20 }
21 
AddCue(base::TimeDelta start_time)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 
RangeCountForTesting() const88 size_t TextRanges::RangeCountForTesting() const {
89   return range_map_.size();
90 }
91 
NewRange(base::TimeDelta start_time)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 
Merge(Range & curr_range,const RangeMap::iterator & next_range_itr)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 
ResetCount(base::TimeDelta start_time)111 void TextRanges::Range::ResetCount(base::TimeDelta start_time) {
112   count_ = (start_time < last_time_) ? 0 : 1;
113 }
114 
SetLastTime(base::TimeDelta last_time)115 void TextRanges::Range::SetLastTime(base::TimeDelta last_time) {
116   last_time_ = last_time;
117   count_ = 1;
118   max_count_ = 1;
119 }
120 
AddCue(base::TimeDelta start_time)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 
last_time() const137 base::TimeDelta TextRanges::Range::last_time() const {
138   return last_time_;
139 }
140 
141 }  // namespace media
142