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#ifndef CHROMECAST_MEDIA_CMA_BASE_BUFFERING_STATE_H_
6#define CHROMECAST_MEDIA_CMA_BASE_BUFFERING_STATE_H_
7
8#include <string>
9
10#include "base/callback.h"
11#include "base/macros.h"
12#include "base/memory/ref_counted.h"
13#include "base/time/time.h"
14
15namespace chromecast {
16namespace media {
17
18class BufferingConfig : public base::RefCountedThreadSafe<BufferingConfig> {
19 public:
20  BufferingConfig(base::TimeDelta low_level_threshold,
21                  base::TimeDelta high_level_threshold);
22
23  base::TimeDelta low_level() const { return low_level_threshold_; }
24  base::TimeDelta high_level() const { return high_level_threshold_; }
25
26  void set_low_level(base::TimeDelta low_level) {
27    low_level_threshold_ = low_level;
28  }
29  void set_high_level(base::TimeDelta high_level) {
30    high_level_threshold_ = high_level;
31  }
32
33 private:
34  friend class base::RefCountedThreadSafe<BufferingConfig>;
35  virtual ~BufferingConfig();
36
37  base::TimeDelta low_level_threshold_;
38  base::TimeDelta high_level_threshold_;
39
40  DISALLOW_COPY_AND_ASSIGN(BufferingConfig);
41};
42
43class BufferingState
44    : public base::RefCountedThreadSafe<BufferingState> {
45 public:
46  typedef base::Callback<void(base::TimeDelta)> HighLevelBufferCB;
47
48  enum State {
49    kLowLevel,
50    kMediumLevel,
51    kHighLevel,
52    kEosReached,
53  };
54
55  // Creates a new buffering state. The initial state is |kLowLevel|.
56  // |state_changed_cb| is used to notify about possible state changes.
57  // |high_level_buffer_cb| is used to adjust the high buffer threshold
58  // when the underlying buffer is not large enough to accomodate
59  // the current high buffer level.
60  BufferingState(const scoped_refptr<BufferingConfig>& config,
61                 const base::Closure& state_changed_cb,
62                 const HighLevelBufferCB& high_level_buffer_cb);
63
64  // Returns the buffering state.
65  State GetState() const { return state_; }
66
67  // Invoked when the buffering configuration has changed.
68  // Based on the new configuration, the buffering state might change.
69  // However, |state_changed_cb_| is not triggered in that case.
70  void OnConfigChanged();
71
72  // Sets the current rendering time for this stream.
73  void SetMediaTime(base::TimeDelta media_time);
74
75  // Sets/gets the maximum rendering media time for this stream.
76  // The maximum rendering time is always lower than the buffered time.
77  void SetMaxRenderingTime(base::TimeDelta max_rendering_time);
78  base::TimeDelta GetMaxRenderingTime() const;
79
80  // Sets the buffered time.
81  void SetBufferedTime(base::TimeDelta buffered_time);
82
83  // Notifies the buffering state that all the frames for this stream have been
84  // buffered, i.e. the end of stream has been reached.
85  void NotifyEos();
86
87  // Notifies the buffering state the underlying buffer has reached
88  // its maximum capacity.
89  // The maximum frame timestamp in the buffer is given by |buffered_time|.
90  // Note: this timestamp can be different from the one provided through
91  // SetBufferedTime since SetBufferedTime takes the timestamp of a playable
92  // frame which is not necessarily the case here (e.g. missing key id).
93  void NotifyMaxCapacity(base::TimeDelta buffered_time);
94
95  // Buffering state as a human readable string, for debugging.
96  std::string ToString() const;
97
98 private:
99  friend class base::RefCountedThreadSafe<BufferingState>;
100  virtual ~BufferingState();
101
102  // Returns the state solely based on the buffered time.
103  State GetBufferLevelState() const;
104
105  // Updates the state to |new_state|.
106  void UpdateState(State new_state);
107
108  scoped_refptr<BufferingConfig> const config_;
109
110  // Callback invoked each time there is a change of state.
111  base::Closure state_changed_cb_;
112
113  // Callback invoked to adjust the high buffer level.
114  HighLevelBufferCB high_level_buffer_cb_;
115
116  // State.
117  State state_;
118
119  // Playback media time.
120  // Equal to kNoTimestamp() when not known.
121  base::TimeDelta media_time_;
122
123  // Maximum rendering media time.
124  // This corresponds to the timestamp of the last frame sent to the hardware
125  // decoder/renderer.
126  base::TimeDelta max_rendering_time_;
127
128  // Buffered media time.
129  // Equal to kNoTimestamp() when not known.
130  base::TimeDelta buffered_time_;
131
132  DISALLOW_COPY_AND_ASSIGN(BufferingState);
133};
134
135}  // namespace media
136}  // namespace chromecast
137
138#endif  // CHROMECAST_MEDIA_CMA_BASE_BUFFERING_STATE_H_
139