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 "chromecast/media/cma/base/buffering_state.h"
6
7 #include <sstream>
8
9 #include "base/logging.h"
10 #include "base/strings/string_number_conversions.h"
11 #include "media/base/timestamp_constants.h"
12
13 namespace chromecast {
14 namespace media {
15
BufferingConfig(base::TimeDelta low_level_threshold,base::TimeDelta high_level_threshold)16 BufferingConfig::BufferingConfig(
17 base::TimeDelta low_level_threshold,
18 base::TimeDelta high_level_threshold)
19 : low_level_threshold_(low_level_threshold),
20 high_level_threshold_(high_level_threshold) {
21 }
22
~BufferingConfig()23 BufferingConfig::~BufferingConfig() {
24 }
25
BufferingState(const std::string & stream_id,const scoped_refptr<BufferingConfig> & config,const base::RepeatingClosure & state_changed_cb,const HighLevelBufferCB & high_level_buffer_cb)26 BufferingState::BufferingState(const std::string& stream_id,
27 const scoped_refptr<BufferingConfig>& config,
28 const base::RepeatingClosure& state_changed_cb,
29 const HighLevelBufferCB& high_level_buffer_cb)
30 : stream_id_(stream_id),
31 config_(config),
32 state_changed_cb_(state_changed_cb),
33 high_level_buffer_cb_(high_level_buffer_cb),
34 state_(kLowLevel),
35 media_time_(::media::kNoTimestamp),
36 max_rendering_time_(::media::kNoTimestamp),
37 buffered_time_(::media::kNoTimestamp) {}
38
~BufferingState()39 BufferingState::~BufferingState() {
40 }
41
OnConfigChanged()42 void BufferingState::OnConfigChanged() {
43 state_ = GetBufferLevelState();
44 }
45
SetMediaTime(base::TimeDelta media_time)46 void BufferingState::SetMediaTime(base::TimeDelta media_time) {
47 media_time_ = media_time;
48 switch (state_) {
49 case kLowLevel:
50 case kMediumLevel:
51 case kHighLevel:
52 UpdateState(GetBufferLevelState());
53 break;
54 case kEosReached:
55 break;
56 }
57 }
58
SetMaxRenderingTime(base::TimeDelta max_rendering_time)59 void BufferingState::SetMaxRenderingTime(base::TimeDelta max_rendering_time) {
60 max_rendering_time_ = max_rendering_time;
61 }
62
GetMaxRenderingTime() const63 base::TimeDelta BufferingState::GetMaxRenderingTime() const {
64 return max_rendering_time_;
65 }
66
SetBufferedTime(base::TimeDelta buffered_time)67 void BufferingState::SetBufferedTime(base::TimeDelta buffered_time) {
68 buffered_time_ = buffered_time;
69 switch (state_) {
70 case kLowLevel:
71 case kMediumLevel:
72 case kHighLevel:
73 UpdateState(GetBufferLevelState());
74 break;
75 case kEosReached:
76 break;
77 }
78 }
79
NotifyEos()80 void BufferingState::NotifyEos() {
81 UpdateState(kEosReached);
82 }
83
NotifyMaxCapacity(base::TimeDelta buffered_time)84 void BufferingState::NotifyMaxCapacity(base::TimeDelta buffered_time) {
85 if (media_time_ == ::media::kNoTimestamp ||
86 buffered_time == ::media::kNoTimestamp) {
87 LOG(WARNING) << "Max capacity with no timestamp";
88 return;
89 }
90 base::TimeDelta buffer_duration = buffered_time - media_time_;
91 if (buffer_duration < config_->high_level())
92 high_level_buffer_cb_.Run(buffer_duration);
93 }
94
StateToString(BufferingState::State state)95 static const char* StateToString(BufferingState::State state) {
96 switch (state) {
97 case BufferingState::kLowLevel:
98 return "kLowLevel";
99 case BufferingState::kMediumLevel:
100 return "kMediumLevel";
101 case BufferingState::kHighLevel:
102 return "kHighLevel";
103 case BufferingState::kEosReached:
104 return "kEosReached";
105 default:
106 NOTREACHED();
107 }
108 NOTREACHED();
109 return "";
110 }
111
TimeDeltaToString(const base::TimeDelta & t)112 static std::string TimeDeltaToString(const base::TimeDelta& t) {
113 if (t == ::media::kNoTimestamp)
114 return "kNoTimestamp";
115 return base::NumberToString(t.InSecondsF());
116 }
117
ToString() const118 std::string BufferingState::ToString() const {
119 std::ostringstream s;
120 s << stream_id_ << " state=" << StateToString(state_)
121 << " media_time=" << TimeDeltaToString(media_time_)
122 << " buffered_time=" << TimeDeltaToString(buffered_time_);
123 return s.str();
124 }
125
GetBufferLevelState() const126 BufferingState::State BufferingState::GetBufferLevelState() const {
127 if (media_time_ == ::media::kNoTimestamp ||
128 buffered_time_ == ::media::kNoTimestamp) {
129 return kLowLevel;
130 }
131
132 base::TimeDelta buffer_duration = buffered_time_ - media_time_;
133 if (buffer_duration <= config_->low_level())
134 return kLowLevel;
135 if (buffer_duration >= config_->high_level())
136 return kHighLevel;
137 return kMediumLevel;
138 }
139
UpdateState(State new_state)140 void BufferingState::UpdateState(State new_state) {
141 if (new_state == state_)
142 return;
143
144 state_ = new_state;
145 if (!state_changed_cb_.is_null())
146 state_changed_cb_.Run();
147 }
148
149 } // namespace media
150 } // namespace chromecast
151