// 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_CONTROLLER_H #define CHROMECAST_MEDIA_CMA_BASE_BUFFERING_CONTROLLER_H #include <list> #include "base/callback.h" #include "base/macros.h" #include "base/memory/ref_counted.h" #include "base/memory/weak_ptr.h" #include "base/threading/thread_checker.h" #include "base/time/time.h" namespace chromecast { namespace media { class BufferingConfig; class BufferingState; class BufferingController { public: typedef base::Callback<void(bool)> BufferingNotificationCB; // Creates a buffering controller where the conditions to trigger rebuffering // are given by |config|. The whole point of the buffering controller is to // derive a single buffering state from the buffering state of various // streams. // |buffering_notification_cb| is a callback invoked to inform about possible // changes of the buffering state. BufferingController( const scoped_refptr<BufferingConfig>& config, const BufferingNotificationCB& buffering_notification_cb); ~BufferingController(); // Creates a buffering state for one stream. This state is added to the list // of streams monitored by the buffering controller. scoped_refptr<BufferingState> AddStream(); // Sets the playback time. void SetMediaTime(base::TimeDelta time); // Returns the maximum media time available for rendering. // Return kNoTimestamp() if unknown. base::TimeDelta GetMaxRenderingTime() const; // Returns whether there is an active buffering phase. bool IsBuffering() const { return is_buffering_; } // Resets the buffering controller. This includes removing all the streams // that were previously added. void Reset(); private: // Invoked each time the buffering state of one of the streams has changed. // If |force_notification| is set, |buffering_notification_cb_| is invoked // regardless whether the buffering state has changed or not. // If |buffering_timeout| is set, then the condition to leave the buffering // state is relaxed (we don't want to wait more). void OnBufferingStateChanged(bool force_notification, bool buffering_timeout); // Updates the high buffer level threshold to |high_level_threshold| // if needed. // This condition is triggered when one of the stream reached its maximum // capacity. In that case, to avoid possible race condition (the buffering // controller waits for more data to come but the buffer is to small to // accomodate additional data), the thresholds in |config_| are adjusted // accordingly. void UpdateHighLevelThreshold(base::TimeDelta high_level_threshold); // Determines the overall buffer level based on the buffer level of each // stream. bool IsHighBufferLevel(); bool IsLowBufferLevel(); // Logs the state of the buffering controller. void DumpState() const; base::ThreadChecker thread_checker_; // Settings used to determine when to start/stop buffering. scoped_refptr<BufferingConfig> config_; // Callback invoked each time there is a change of the buffering state. BufferingNotificationCB buffering_notification_cb_; // State of the buffering controller. bool is_buffering_; // Start time of a re-buffering phase. base::Time begin_buffering_time_; // Buffering level for each individual stream. typedef std::list<scoped_refptr<BufferingState> > StreamList; StreamList stream_list_; base::WeakPtrFactory<BufferingController> weak_factory_; base::WeakPtr<BufferingController> weak_this_; DISALLOW_COPY_AND_ASSIGN(BufferingController); }; } // namespace media } // namespace chromecast #endif // CHROMECAST_MEDIA_CMA_BASE_BUFFERING_CONTROLLER_H