text: /*
   *  Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
   *
   *  Use of this source code is governed by a BSD-style license
   *  that can be found in the LICENSE file in the root of the source
   *  tree. An additional intellectual property rights grant can be found
   *  in the file PATENTS.  All contributing project authors may
   *  be found in the AUTHORS file in the root of the source tree.
   */
  
  #ifndef WEBRTC_MODULES_VIDEO_CODING_MEDIA_OPTIMIZATION_H_
  #define WEBRTC_MODULES_VIDEO_CODING_MEDIA_OPTIMIZATION_H_
  
  #include <list>
  #include <memory>
  
  #include "webrtc/modules/include/module_common_types.h"
  #include "webrtc/modules/video_coding/include/video_coding.h"
  #include "webrtc/modules/video_coding/media_opt_util.h"
  #include "webrtc/modules/video_coding/qm_select.h"
  #include "webrtc/system_wrappers/include/critical_section_wrapper.h"
  
  namespace webrtc {
  
  // Forward declarations.
  class Clock;
  class FrameDropper;
  class VCMContentMetricsProcessing;
  
  namespace media_optimization {
  
  class MediaOptimization {
   public:
    explicit MediaOptimization(Clock* clock);
    ~MediaOptimization();
  
    // TODO(andresp): Can Reset and SetEncodingData be done at construction time
    // only?
    void Reset();
  
    // Informs media optimization of initial encoding state.
    void SetEncodingData(VideoCodecType send_codec_type,
                         int32_t max_bit_rate,
                         uint32_t bit_rate,
                         uint16_t width,
                         uint16_t height,
                         uint32_t frame_rate,
                         int num_temporal_layers,
                         int32_t mtu);
  
    // Sets target rates for the encoder given the channel parameters.
    // Inputs:  target bitrate - the encoder target bitrate in bits/s.
    //          fraction_lost - packet loss rate in % in the network.
    //          round_trip_time_ms - round trip time in milliseconds.
    //          min_bit_rate - the bit rate of the end-point with lowest rate.
    //          max_bit_rate - the bit rate of the end-point with highest rate.
    // TODO(andresp): Find if the callbacks can be triggered only after releasing
    // an internal critical section.
    uint32_t SetTargetRates(uint32_t target_bitrate,
                            uint8_t fraction_lost,
                            int64_t round_trip_time_ms,
                            VCMProtectionCallback* protection_callback,
                            VCMQMSettingsCallback* qmsettings_callback);
  
    void SetProtectionMethod(VCMProtectionMethodEnum method);
    void EnableQM(bool enable);
    void EnableFrameDropper(bool enable);
  
    // Lets the sender suspend video when the rate drops below
    // |threshold_bps|, and turns back on when the rate goes back up above
    // |threshold_bps| + |window_bps|.
    void SuspendBelowMinBitrate(int threshold_bps, int window_bps);
    bool IsVideoSuspended() const;
  
    bool DropFrame();
  
    void UpdateContentData(const VideoContentMetrics* content_metrics);
  
    // Informs Media Optimization of encoded output.
    int32_t UpdateWithEncodedData(const EncodedImage& encoded_image);
  
    // InputFrameRate 0 = no frame rate estimate available.
    uint32_t InputFrameRate();
    uint32_t SentFrameRate();
    uint32_t SentBitRate();
  
   private:
    enum { kFrameCountHistorySize = 90 };
    enum { kFrameHistoryWinMs = 2000 };
    enum { kBitrateAverageWinMs = 1000 };
  
    struct EncodedFrameSample;
    typedef std::list<EncodedFrameSample> FrameSampleList;
  
    void UpdateIncomingFrameRate() EXCLUSIVE_LOCKS_REQUIRED(crit_sect_);
    void PurgeOldFrameSamples(int64_t now_ms)
        EXCLUSIVE_LOCKS_REQUIRED(crit_sect_);
    void UpdateSentBitrate(int64_t now_ms) EXCLUSIVE_LOCKS_REQUIRED(crit_sect_);
    void UpdateSentFramerate() EXCLUSIVE_LOCKS_REQUIRED(crit_sect_);
  
    // Computes new Quality Mode.
    int32_t SelectQuality(VCMQMSettingsCallback* qmsettings_callback)
        EXCLUSIVE_LOCKS_REQUIRED(crit_sect_);
  
    // Verifies if QM settings differ from default, i.e. if an update is required.
    // Computes actual values, as will be sent to the encoder.
    bool QMUpdate(VCMResolutionScale* qm,
                  VCMQMSettingsCallback* qmsettings_callback)
        EXCLUSIVE_LOCKS_REQUIRED(crit_sect_);
  
    // Checks if we should make a QM change. Return true if yes, false otherwise.
    bool CheckStatusForQMchange() EXCLUSIVE_LOCKS_REQUIRED(crit_sect_);
  
    void ProcessIncomingFrameRate(int64_t now)
        EXCLUSIVE_LOCKS_REQUIRED(crit_sect_);
  
    // Checks conditions for suspending the video. The method compares
    // |video_target_bitrate_| with the threshold values for suspension, and
    // changes the state of |video_suspended_| accordingly.
    void CheckSuspendConditions() EXCLUSIVE_LOCKS_REQUIRED(crit_sect_);
  
    void SetEncodingDataInternal(VideoCodecType send_codec_type,
                                 int32_t max_bit_rate,
                                 uint32_t frame_rate,
                                 uint32_t bit_rate,
                                 uint16_t width,
                                 uint16_t height,
                                 int num_temporal_layers,
                                 int32_t mtu)
        EXCLUSIVE_LOCKS_REQUIRED(crit_sect_);
  
    uint32_t InputFrameRateInternal() EXCLUSIVE_LOCKS_REQUIRED(crit_sect_);
  
    uint32_t SentFrameRateInternal() EXCLUSIVE_LOCKS_REQUIRED(crit_sect_);
  
    // Protect all members.
    std::unique_ptr<CriticalSectionWrapper> crit_sect_;
  
    Clock* clock_ GUARDED_BY(crit_sect_);
    int32_t max_bit_rate_ GUARDED_BY(crit_sect_);
    VideoCodecType send_codec_type_ GUARDED_BY(crit_sect_);
    uint16_t codec_width_ GUARDED_BY(crit_sect_);
    uint16_t codec_height_ GUARDED_BY(crit_sect_);
    float user_frame_rate_ GUARDED_BY(crit_sect_);
    std::unique_ptr<FrameDropper> frame_dropper_ GUARDED_BY(crit_sect_);
    std::unique_ptr<VCMLossProtectionLogic> loss_prot_logic_
        GUARDED_BY(crit_sect_);
    uint8_t fraction_lost_ GUARDED_BY(crit_sect_);
    uint32_t send_statistics_[4] GUARDED_BY(crit_sect_);
    uint32_t send_statistics_zero_encode_ GUARDED_BY(crit_sect_);
    int32_t max_payload_size_ GUARDED_BY(crit_sect_);
    int video_target_bitrate_ GUARDED_BY(crit_sect_);
    float incoming_frame_rate_ GUARDED_BY(crit_sect_);
    int64_t incoming_frame_times_[kFrameCountHistorySize] GUARDED_BY(crit_sect_);
    bool enable_qm_ GUARDED_BY(crit_sect_);
    std::list<EncodedFrameSample> encoded_frame_samples_ GUARDED_BY(crit_sect_);
    uint32_t avg_sent_bit_rate_bps_ GUARDED_BY(crit_sect_);
    uint32_t avg_sent_framerate_ GUARDED_BY(crit_sect_);
    uint32_t key_frame_cnt_ GUARDED_BY(crit_sect_);
    uint32_t delta_frame_cnt_ GUARDED_BY(crit_sect_);
    std::unique_ptr<VCMContentMetricsProcessing> content_ GUARDED_BY(crit_sect_);
    std::unique_ptr<VCMQmResolution> qm_resolution_ GUARDED_BY(crit_sect_);
    int64_t last_qm_update_time_ GUARDED_BY(crit_sect_);
    int64_t last_change_time_ GUARDED_BY(crit_sect_);  // Content/user triggered.
    int num_layers_ GUARDED_BY(crit_sect_);
    bool suspension_enabled_ GUARDED_BY(crit_sect_);
    bool video_suspended_ GUARDED_BY(crit_sect_);
    int suspension_threshold_bps_ GUARDED_BY(crit_sect_);
    int suspension_window_bps_ GUARDED_BY(crit_sect_);
  };
  }  // namespace media_optimization
  }  // namespace webrtc
  
  #endif  // WEBRTC_MODULES_VIDEO_CODING_MEDIA_OPTIMIZATION_H_
  