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.
5 #include "media/base/text_ranges.h"
7 #include "base/logging.h"
11 TextRanges::TextRanges() {
15 TextRanges::~TextRanges() {
18 void TextRanges::Reset() {
19 curr_range_itr_
= range_map_
.end();
22 bool TextRanges::AddCue(base::TimeDelta start_time
) {
23 typedef RangeMap::iterator Itr
;
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().
29 if (range_map_
.empty()) {
34 if (start_time
< range_map_
.begin()->first
) {
39 const Itr itr
= --Itr(range_map_
.upper_bound(start_time
));
40 DCHECK(start_time
>= itr
->first
);
42 Range
& range
= itr
->second
;
44 if (start_time
> range
.last_time()) {
49 range
.ResetCount(start_time
);
50 curr_range_itr_
= itr
;
54 DCHECK(start_time
>= curr_range_itr_
->first
);
56 Range
& curr_range
= curr_range_itr_
->second
;
58 if (start_time
<= curr_range
.last_time())
59 return curr_range
.AddCue(start_time
);
61 const Itr next_range_itr
= ++Itr(curr_range_itr_
);
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
);
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.
72 Merge(curr_range
, next_range_itr
);
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.
84 curr_range
.SetLastTime(start_time
);
88 size_t TextRanges::RangeCountForTesting() const {
89 return range_map_
.size();
92 void TextRanges::NewRange(base::TimeDelta start_time
) {
94 range
.SetLastTime(start_time
);
96 std::pair
<RangeMap::iterator
, bool> result
=
97 range_map_
.insert(std::make_pair(start_time
, range
));
98 DCHECK(result
.second
);
100 curr_range_itr_
= result
.first
;
103 void TextRanges::Merge(
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
);
111 void TextRanges::Range::ResetCount(base::TimeDelta start_time
) {
112 count_
= (start_time
< last_time_
) ? 0 : 1;
115 void TextRanges::Range::SetLastTime(base::TimeDelta last_time
) {
116 last_time_
= last_time
;
121 bool TextRanges::Range::AddCue(base::TimeDelta start_time
) {
122 if (start_time
< last_time_
) {
123 DCHECK_EQ(count_
, 0);
127 DCHECK(start_time
== last_time_
);
130 if (count_
<= max_count_
)
137 base::TimeDelta
TextRanges::Range::last_time() const {