// 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.
#ifndef CHROMECAST_MEDIA_CMA_BASE_BUFFERING_STATE_H_
#define CHROMECAST_MEDIA_CMA_BASE_BUFFERING_STATE_H_
#include <string>
#include "base/callback.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/time/time.h"
namespace chromecast {
namespace media {
class BufferingConfig : public base::RefCountedThreadSafe<BufferingConfig> {
public:
BufferingConfig(base::TimeDelta low_level_threshold,
base::TimeDelta high_level_threshold);
base::TimeDelta low_level() const { return low_level_threshold_; }
base::TimeDelta high_level() const { return high_level_threshold_; }
void set_low_level(base::TimeDelta low_level) {
low_level_threshold_ = low_level;
}
void set_high_level(base::TimeDelta high_level) {
high_level_threshold_ = high_level;
}
private:
friend class base::RefCountedThreadSafe<BufferingConfig>;
virtual ~BufferingConfig();
base::TimeDelta low_level_threshold_;
base::TimeDelta high_level_threshold_;
DISALLOW_COPY_AND_ASSIGN(BufferingConfig);
};
class BufferingState
: public base::RefCountedThreadSafe<BufferingState> {
public:
typedef base::Callback<void(base::TimeDelta)> HighLevelBufferCB;
enum State {
kLowLevel,
kMediumLevel,
kHighLevel,
kEosReached,
};
// Creates a new buffering state. The initial state is |kLowLevel|.
// |state_changed_cb| is used to notify about possible state changes.
// |high_level_buffer_cb| is used to adjust the high buffer threshold
// when the underlying buffer is not large enough to accomodate
// the current high buffer level.
BufferingState(const scoped_refptr<BufferingConfig>& config,
const base::Closure& state_changed_cb,
const HighLevelBufferCB& high_level_buffer_cb);
// Returns the buffering state.
State GetState() const { return state_; }
// Invoked when the buffering configuration has changed.
// Based on the new configuration, the buffering state might change.
// However, |state_changed_cb_| is not triggered in that case.
void OnConfigChanged();
// Sets the current rendering time for this stream.
void SetMediaTime(base::TimeDelta media_time);
// Sets/gets the maximum rendering media time for this stream.
// The maximum rendering time is always lower than the buffered time.
void SetMaxRenderingTime(base::TimeDelta max_rendering_time);
base::TimeDelta GetMaxRenderingTime() const;
// Sets the buffered time.
void SetBufferedTime(base::TimeDelta buffered_time);
// Notifies the buffering state that all the frames for this stream have been
// buffered, i.e. the end of stream has been reached.
void NotifyEos();
// Notifies the buffering state the underlying buffer has reached
// its maximum capacity.
// The maximum frame timestamp in the buffer is given by |buffered_time|.
// Note: this timestamp can be different from the one provided through
// SetBufferedTime since SetBufferedTime takes the timestamp of a playable
// frame which is not necessarily the case here (e.g. missing key id).
void NotifyMaxCapacity(base::TimeDelta buffered_time);
// Buffering state as a human readable string, for debugging.
std::string ToString() const;
private:
friend class base::RefCountedThreadSafe<BufferingState>;
virtual ~BufferingState();
// Returns the state solely based on the buffered time.
State GetBufferLevelState() const;
// Updates the state to |new_state|.
void UpdateState(State new_state);
scoped_refptr<BufferingConfig> const config_;
// Callback invoked each time there is a change of state.
base::Closure state_changed_cb_;
// Callback invoked to adjust the high buffer level.
HighLevelBufferCB high_level_buffer_cb_;
// State.
State state_;
// Playback media time.
// Equal to kNoTimestamp() when not known.
base::TimeDelta media_time_;
// Maximum rendering media time.
// This corresponds to the timestamp of the last frame sent to the hardware
// decoder/renderer.
base::TimeDelta max_rendering_time_;
// Buffered media time.
// Equal to kNoTimestamp() when not known.
base::TimeDelta buffered_time_;
DISALLOW_COPY_AND_ASSIGN(BufferingState);
};
} // namespace media
} // namespace chromecast
#endif // CHROMECAST_MEDIA_CMA_BASE_BUFFERING_STATE_H_