diff options
Diffstat (limited to 'media/base/text_ranges.cc')
-rw-r--r-- | media/base/text_ranges.cc | 141 |
1 files changed, 141 insertions, 0 deletions
diff --git a/media/base/text_ranges.cc b/media/base/text_ranges.cc new file mode 100644 index 0000000..41bc7d0 --- /dev/null +++ b/media/base/text_ranges.cc @@ -0,0 +1,141 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "media/base/text_ranges.h" + +#include "base/logging.h" + +namespace media { + +TextRanges::TextRanges() { + Reset(); +} + +TextRanges::~TextRanges() { +} + +void TextRanges::Reset() { + curr_range_itr_ = range_map_.end(); +} + +bool TextRanges::AddCue(base::TimeDelta start_time) { + typedef RangeMap::iterator Itr; + + if (curr_range_itr_ == range_map_.end()) { + // There is no active time range, so this is the first AddCue() + // attempt that follows a Reset(). + + if (range_map_.empty()) { + NewRange(start_time); + return true; + } + + if (start_time < range_map_.begin()->first) { + NewRange(start_time); + return true; + } + + const Itr itr = --Itr(range_map_.upper_bound(start_time)); + DCHECK(start_time >= itr->first); + + Range& range = itr->second; + + if (start_time > range.last_time()) { + NewRange(start_time); + return true; + } + + range.ResetCount(start_time); + curr_range_itr_ = itr; + return false; + } + + DCHECK(start_time >= curr_range_itr_->first); + + Range& curr_range = curr_range_itr_->second; + + if (start_time <= curr_range.last_time()) + return curr_range.AddCue(start_time); + + const Itr next_range_itr = ++Itr(curr_range_itr_); + + if (next_range_itr != range_map_.end()) { + DCHECK(next_range_itr->first > curr_range.last_time()); + DCHECK(start_time <= next_range_itr->first); + + if (start_time == next_range_itr->first) { + // We have walked off the current range, and onto the next one. + // There is now no ambiguity about where the current time range + // ends, and so we coalesce the current and next ranges. + + Merge(curr_range, next_range_itr); + return false; + } + } + + // Either |curr_range| is the last range in the map, or there is a + // next range beyond |curr_range|, but its start time is ahead of + // this cue's start time. In either case, this cue becomes the new + // last_time for |curr_range|. Eventually we will see a cue whose + // time matches the start time of the next range, in which case we + // coalesce the current and next ranges. + + curr_range.SetLastTime(start_time); + return true; +} + +size_t TextRanges::RangeCountForTesting() const { + return range_map_.size(); +} + +void TextRanges::NewRange(base::TimeDelta start_time) { + Range range; + range.SetLastTime(start_time); + + std::pair<RangeMap::iterator, bool> result = + range_map_.insert(std::make_pair(start_time, range)); + DCHECK(result.second); + + curr_range_itr_ = result.first; +} + +void TextRanges::Merge( + Range& curr_range, + const RangeMap::iterator& next_range_itr) { + curr_range = next_range_itr->second; + curr_range.ResetCount(next_range_itr->first); + range_map_.erase(next_range_itr); +} + +void TextRanges::Range::ResetCount(base::TimeDelta start_time) { + count_ = (start_time < last_time_) ? 0 : 1; +} + +void TextRanges::Range::SetLastTime(base::TimeDelta last_time) { + last_time_ = last_time; + count_ = 1; + max_count_ = 1; +} + +bool TextRanges::Range::AddCue(base::TimeDelta start_time) { + if (start_time < last_time_) { + DCHECK_EQ(count_, 0); + return false; + } + + DCHECK(start_time == last_time_); + + ++count_; + if (count_ <= max_count_) + return false; + + ++max_count_; + return true; +} + +base::TimeDelta TextRanges::Range::last_time() const { + return last_time_; +} + +} // namespace media |