Index: webrtc/modules/video_coding/main/source/media_optimization.cc |
diff --git a/webrtc/modules/video_coding/main/source/media_optimization.cc b/webrtc/modules/video_coding/main/source/media_optimization.cc |
deleted file mode 100644 |
index bf0b14423740ad262ff2b2e6f742028e03ee2804..0000000000000000000000000000000000000000 |
--- a/webrtc/modules/video_coding/main/source/media_optimization.cc |
+++ /dev/null |
@@ -1,648 +0,0 @@ |
-/* |
- * 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. |
- */ |
- |
-#include "webrtc/modules/video_coding/main/source/media_optimization.h" |
- |
-#include "webrtc/base/logging.h" |
-#include "webrtc/modules/video_coding/main/source/content_metrics_processing.h" |
-#include "webrtc/modules/video_coding/main/source/qm_select.h" |
-#include "webrtc/modules/video_coding/utility/include/frame_dropper.h" |
-#include "webrtc/system_wrappers/include/clock.h" |
- |
-namespace webrtc { |
-namespace media_optimization { |
-namespace { |
-void UpdateProtectionCallback( |
- VCMProtectionMethod* selected_method, |
- uint32_t* video_rate_bps, |
- uint32_t* nack_overhead_rate_bps, |
- uint32_t* fec_overhead_rate_bps, |
- VCMProtectionCallback* video_protection_callback) { |
- FecProtectionParams delta_fec_params; |
- FecProtectionParams key_fec_params; |
- // Get the FEC code rate for Key frames (set to 0 when NA). |
- key_fec_params.fec_rate = selected_method->RequiredProtectionFactorK(); |
- |
- // Get the FEC code rate for Delta frames (set to 0 when NA). |
- delta_fec_params.fec_rate = selected_method->RequiredProtectionFactorD(); |
- |
- // Get the FEC-UEP protection status for Key frames: UEP on/off. |
- key_fec_params.use_uep_protection = selected_method->RequiredUepProtectionK(); |
- |
- // Get the FEC-UEP protection status for Delta frames: UEP on/off. |
- delta_fec_params.use_uep_protection = |
- selected_method->RequiredUepProtectionD(); |
- |
- // The RTP module currently requires the same |max_fec_frames| for both |
- // key and delta frames. |
- delta_fec_params.max_fec_frames = selected_method->MaxFramesFec(); |
- key_fec_params.max_fec_frames = selected_method->MaxFramesFec(); |
- |
- // Set the FEC packet mask type. |kFecMaskBursty| is more effective for |
- // consecutive losses and little/no packet re-ordering. As we currently |
- // do not have feedback data on the degree of correlated losses and packet |
- // re-ordering, we keep default setting to |kFecMaskRandom| for now. |
- delta_fec_params.fec_mask_type = kFecMaskRandom; |
- key_fec_params.fec_mask_type = kFecMaskRandom; |
- |
- // TODO(Marco): Pass FEC protection values per layer. |
- video_protection_callback->ProtectionRequest(&delta_fec_params, |
- &key_fec_params, |
- video_rate_bps, |
- nack_overhead_rate_bps, |
- fec_overhead_rate_bps); |
-} |
-} // namespace |
- |
-struct MediaOptimization::EncodedFrameSample { |
- EncodedFrameSample(size_t size_bytes, |
- uint32_t timestamp, |
- int64_t time_complete_ms) |
- : size_bytes(size_bytes), |
- timestamp(timestamp), |
- time_complete_ms(time_complete_ms) {} |
- |
- size_t size_bytes; |
- uint32_t timestamp; |
- int64_t time_complete_ms; |
-}; |
- |
-MediaOptimization::MediaOptimization(Clock* clock) |
- : crit_sect_(CriticalSectionWrapper::CreateCriticalSection()), |
- clock_(clock), |
- max_bit_rate_(0), |
- send_codec_type_(kVideoCodecUnknown), |
- codec_width_(0), |
- codec_height_(0), |
- user_frame_rate_(0), |
- frame_dropper_(new FrameDropper), |
- loss_prot_logic_( |
- new VCMLossProtectionLogic(clock_->TimeInMilliseconds())), |
- fraction_lost_(0), |
- send_statistics_zero_encode_(0), |
- max_payload_size_(1460), |
- video_target_bitrate_(0), |
- incoming_frame_rate_(0), |
- enable_qm_(false), |
- encoded_frame_samples_(), |
- avg_sent_bit_rate_bps_(0), |
- avg_sent_framerate_(0), |
- key_frame_cnt_(0), |
- delta_frame_cnt_(0), |
- content_(new VCMContentMetricsProcessing()), |
- qm_resolution_(new VCMQmResolution()), |
- last_qm_update_time_(0), |
- last_change_time_(0), |
- num_layers_(0), |
- suspension_enabled_(false), |
- video_suspended_(false), |
- suspension_threshold_bps_(0), |
- suspension_window_bps_(0) { |
- memset(send_statistics_, 0, sizeof(send_statistics_)); |
- memset(incoming_frame_times_, -1, sizeof(incoming_frame_times_)); |
-} |
- |
-MediaOptimization::~MediaOptimization(void) { |
- loss_prot_logic_->Release(); |
-} |
- |
-void MediaOptimization::Reset() { |
- CriticalSectionScoped lock(crit_sect_.get()); |
- SetEncodingDataInternal( |
- kVideoCodecUnknown, 0, 0, 0, 0, 0, 0, max_payload_size_); |
- memset(incoming_frame_times_, -1, sizeof(incoming_frame_times_)); |
- incoming_frame_rate_ = 0.0; |
- frame_dropper_->Reset(); |
- loss_prot_logic_->Reset(clock_->TimeInMilliseconds()); |
- frame_dropper_->SetRates(0, 0); |
- content_->Reset(); |
- qm_resolution_->Reset(); |
- loss_prot_logic_->UpdateFrameRate(incoming_frame_rate_); |
- loss_prot_logic_->Reset(clock_->TimeInMilliseconds()); |
- send_statistics_zero_encode_ = 0; |
- video_target_bitrate_ = 0; |
- codec_width_ = 0; |
- codec_height_ = 0; |
- user_frame_rate_ = 0; |
- key_frame_cnt_ = 0; |
- delta_frame_cnt_ = 0; |
- last_qm_update_time_ = 0; |
- last_change_time_ = 0; |
- encoded_frame_samples_.clear(); |
- avg_sent_bit_rate_bps_ = 0; |
- num_layers_ = 1; |
-} |
- |
-void MediaOptimization::SetEncodingData(VideoCodecType send_codec_type, |
- int32_t max_bit_rate, |
- uint32_t target_bitrate, |
- uint16_t width, |
- uint16_t height, |
- uint32_t frame_rate, |
- int num_layers, |
- int32_t mtu) { |
- CriticalSectionScoped lock(crit_sect_.get()); |
- SetEncodingDataInternal(send_codec_type, |
- max_bit_rate, |
- frame_rate, |
- target_bitrate, |
- width, |
- height, |
- num_layers, |
- mtu); |
-} |
- |
-void MediaOptimization::SetEncodingDataInternal(VideoCodecType send_codec_type, |
- int32_t max_bit_rate, |
- uint32_t frame_rate, |
- uint32_t target_bitrate, |
- uint16_t width, |
- uint16_t height, |
- int num_layers, |
- int32_t mtu) { |
- // Everything codec specific should be reset here since this means the codec |
- // has changed. If native dimension values have changed, then either user |
- // initiated change, or QM initiated change. Will be able to determine only |
- // after the processing of the first frame. |
- last_change_time_ = clock_->TimeInMilliseconds(); |
- content_->Reset(); |
- content_->UpdateFrameRate(frame_rate); |
- |
- max_bit_rate_ = max_bit_rate; |
- send_codec_type_ = send_codec_type; |
- video_target_bitrate_ = target_bitrate; |
- float target_bitrate_kbps = static_cast<float>(target_bitrate) / 1000.0f; |
- loss_prot_logic_->UpdateBitRate(target_bitrate_kbps); |
- loss_prot_logic_->UpdateFrameRate(static_cast<float>(frame_rate)); |
- loss_prot_logic_->UpdateFrameSize(width, height); |
- loss_prot_logic_->UpdateNumLayers(num_layers); |
- frame_dropper_->Reset(); |
- frame_dropper_->SetRates(target_bitrate_kbps, static_cast<float>(frame_rate)); |
- user_frame_rate_ = static_cast<float>(frame_rate); |
- codec_width_ = width; |
- codec_height_ = height; |
- num_layers_ = (num_layers <= 1) ? 1 : num_layers; // Can also be zero. |
- max_payload_size_ = mtu; |
- qm_resolution_->Initialize(target_bitrate_kbps, |
- user_frame_rate_, |
- codec_width_, |
- codec_height_, |
- num_layers_); |
-} |
- |
-uint32_t MediaOptimization::SetTargetRates( |
- uint32_t target_bitrate, |
- uint8_t fraction_lost, |
- int64_t round_trip_time_ms, |
- VCMProtectionCallback* protection_callback, |
- VCMQMSettingsCallback* qmsettings_callback) { |
- CriticalSectionScoped lock(crit_sect_.get()); |
- VCMProtectionMethod* selected_method = loss_prot_logic_->SelectedMethod(); |
- float target_bitrate_kbps = static_cast<float>(target_bitrate) / 1000.0f; |
- loss_prot_logic_->UpdateBitRate(target_bitrate_kbps); |
- loss_prot_logic_->UpdateRtt(round_trip_time_ms); |
- |
- // Get frame rate for encoder: this is the actual/sent frame rate. |
- float actual_frame_rate = SentFrameRateInternal(); |
- |
- // Sanity check. |
- if (actual_frame_rate < 1.0) { |
- actual_frame_rate = 1.0; |
- } |
- |
- // Update frame rate for the loss protection logic class: frame rate should |
- // be the actual/sent rate. |
- loss_prot_logic_->UpdateFrameRate(actual_frame_rate); |
- |
- fraction_lost_ = fraction_lost; |
- |
- // Returns the filtered packet loss, used for the protection setting. |
- // The filtered loss may be the received loss (no filter), or some |
- // filtered value (average or max window filter). |
- // Use max window filter for now. |
- FilterPacketLossMode filter_mode = kMaxFilter; |
- uint8_t packet_loss_enc = loss_prot_logic_->FilteredLoss( |
- clock_->TimeInMilliseconds(), filter_mode, fraction_lost); |
- |
- // For now use the filtered loss for computing the robustness settings. |
- loss_prot_logic_->UpdateFilteredLossPr(packet_loss_enc); |
- |
- // Rate cost of the protection methods. |
- float protection_overhead_rate = 0.0f; |
- |
- // Update protection settings, when applicable. |
- float sent_video_rate_kbps = 0.0f; |
- if (loss_prot_logic_->SelectedType() != kNone) { |
- // Update protection method with content metrics. |
- selected_method->UpdateContentMetrics(content_->ShortTermAvgData()); |
- |
- // Update method will compute the robustness settings for the given |
- // protection method and the overhead cost |
- // the protection method is set by the user via SetVideoProtection. |
- loss_prot_logic_->UpdateMethod(); |
- |
- // Update protection callback with protection settings. |
- uint32_t sent_video_rate_bps = 0; |
- uint32_t sent_nack_rate_bps = 0; |
- uint32_t sent_fec_rate_bps = 0; |
- // Get the bit cost of protection method, based on the amount of |
- // overhead data actually transmitted (including headers) the last |
- // second. |
- if (protection_callback) { |
- UpdateProtectionCallback(selected_method, |
- &sent_video_rate_bps, |
- &sent_nack_rate_bps, |
- &sent_fec_rate_bps, |
- protection_callback); |
- } |
- uint32_t sent_total_rate_bps = |
- sent_video_rate_bps + sent_nack_rate_bps + sent_fec_rate_bps; |
- // Estimate the overhead costs of the next second as staying the same |
- // wrt the source bitrate. |
- if (sent_total_rate_bps > 0) { |
- protection_overhead_rate = |
- static_cast<float>(sent_nack_rate_bps + sent_fec_rate_bps) / |
- sent_total_rate_bps; |
- } |
- // Cap the overhead estimate to 50%. |
- if (protection_overhead_rate > 0.5) |
- protection_overhead_rate = 0.5; |
- |
- // Get the effective packet loss for encoder ER when applicable. Should be |
- // passed to encoder via fraction_lost. |
- packet_loss_enc = selected_method->RequiredPacketLossER(); |
- sent_video_rate_kbps = static_cast<float>(sent_video_rate_bps) / 1000.0f; |
- } |
- |
- // Source coding rate: total rate - protection overhead. |
- video_target_bitrate_ = target_bitrate * (1.0 - protection_overhead_rate); |
- |
- // Cap target video bitrate to codec maximum. |
- if (max_bit_rate_ > 0 && video_target_bitrate_ > max_bit_rate_) { |
- video_target_bitrate_ = max_bit_rate_; |
- } |
- |
- // Update encoding rates following protection settings. |
- float target_video_bitrate_kbps = |
- static_cast<float>(video_target_bitrate_) / 1000.0f; |
- frame_dropper_->SetRates(target_video_bitrate_kbps, incoming_frame_rate_); |
- |
- if (enable_qm_ && qmsettings_callback) { |
- // Update QM with rates. |
- qm_resolution_->UpdateRates(target_video_bitrate_kbps, |
- sent_video_rate_kbps, |
- incoming_frame_rate_, |
- fraction_lost_); |
- // Check for QM selection. |
- bool select_qm = CheckStatusForQMchange(); |
- if (select_qm) { |
- SelectQuality(qmsettings_callback); |
- } |
- // Reset the short-term averaged content data. |
- content_->ResetShortTermAvgData(); |
- } |
- |
- CheckSuspendConditions(); |
- |
- return video_target_bitrate_; |
-} |
- |
-void MediaOptimization::SetProtectionMethod(VCMProtectionMethodEnum method) { |
- CriticalSectionScoped lock(crit_sect_.get()); |
- loss_prot_logic_->SetMethod(method); |
-} |
- |
-uint32_t MediaOptimization::InputFrameRate() { |
- CriticalSectionScoped lock(crit_sect_.get()); |
- return InputFrameRateInternal(); |
-} |
- |
-uint32_t MediaOptimization::InputFrameRateInternal() { |
- ProcessIncomingFrameRate(clock_->TimeInMilliseconds()); |
- return uint32_t(incoming_frame_rate_ + 0.5f); |
-} |
- |
-uint32_t MediaOptimization::SentFrameRate() { |
- CriticalSectionScoped lock(crit_sect_.get()); |
- return SentFrameRateInternal(); |
-} |
- |
-uint32_t MediaOptimization::SentFrameRateInternal() { |
- PurgeOldFrameSamples(clock_->TimeInMilliseconds()); |
- UpdateSentFramerate(); |
- return avg_sent_framerate_; |
-} |
- |
-uint32_t MediaOptimization::SentBitRate() { |
- CriticalSectionScoped lock(crit_sect_.get()); |
- const int64_t now_ms = clock_->TimeInMilliseconds(); |
- PurgeOldFrameSamples(now_ms); |
- UpdateSentBitrate(now_ms); |
- return avg_sent_bit_rate_bps_; |
-} |
- |
-int32_t MediaOptimization::UpdateWithEncodedData( |
- const EncodedImage& encoded_image) { |
- size_t encoded_length = encoded_image._length; |
- uint32_t timestamp = encoded_image._timeStamp; |
- CriticalSectionScoped lock(crit_sect_.get()); |
- const int64_t now_ms = clock_->TimeInMilliseconds(); |
- PurgeOldFrameSamples(now_ms); |
- if (encoded_frame_samples_.size() > 0 && |
- encoded_frame_samples_.back().timestamp == timestamp) { |
- // Frames having the same timestamp are generated from the same input |
- // frame. We don't want to double count them, but only increment the |
- // size_bytes. |
- encoded_frame_samples_.back().size_bytes += encoded_length; |
- encoded_frame_samples_.back().time_complete_ms = now_ms; |
- } else { |
- encoded_frame_samples_.push_back( |
- EncodedFrameSample(encoded_length, timestamp, now_ms)); |
- } |
- UpdateSentBitrate(now_ms); |
- UpdateSentFramerate(); |
- if (encoded_length > 0) { |
- const bool delta_frame = encoded_image._frameType != kVideoFrameKey; |
- |
- frame_dropper_->Fill(encoded_length, delta_frame); |
- if (max_payload_size_ > 0 && encoded_length > 0) { |
- const float min_packets_per_frame = |
- encoded_length / static_cast<float>(max_payload_size_); |
- if (delta_frame) { |
- loss_prot_logic_->UpdatePacketsPerFrame(min_packets_per_frame, |
- clock_->TimeInMilliseconds()); |
- } else { |
- loss_prot_logic_->UpdatePacketsPerFrameKey( |
- min_packets_per_frame, clock_->TimeInMilliseconds()); |
- } |
- |
- if (enable_qm_) { |
- // Update quality select with encoded length. |
- qm_resolution_->UpdateEncodedSize(encoded_length); |
- } |
- } |
- if (!delta_frame && encoded_length > 0) { |
- loss_prot_logic_->UpdateKeyFrameSize(static_cast<float>(encoded_length)); |
- } |
- |
- // Updating counters. |
- if (delta_frame) { |
- delta_frame_cnt_++; |
- } else { |
- key_frame_cnt_++; |
- } |
- } |
- |
- return VCM_OK; |
-} |
- |
-void MediaOptimization::EnableQM(bool enable) { |
- CriticalSectionScoped lock(crit_sect_.get()); |
- enable_qm_ = enable; |
-} |
- |
-void MediaOptimization::EnableFrameDropper(bool enable) { |
- CriticalSectionScoped lock(crit_sect_.get()); |
- frame_dropper_->Enable(enable); |
-} |
- |
-void MediaOptimization::SuspendBelowMinBitrate(int threshold_bps, |
- int window_bps) { |
- CriticalSectionScoped lock(crit_sect_.get()); |
- assert(threshold_bps > 0 && window_bps >= 0); |
- suspension_threshold_bps_ = threshold_bps; |
- suspension_window_bps_ = window_bps; |
- suspension_enabled_ = true; |
- video_suspended_ = false; |
-} |
- |
-bool MediaOptimization::IsVideoSuspended() const { |
- CriticalSectionScoped lock(crit_sect_.get()); |
- return video_suspended_; |
-} |
- |
-bool MediaOptimization::DropFrame() { |
- CriticalSectionScoped lock(crit_sect_.get()); |
- UpdateIncomingFrameRate(); |
- // Leak appropriate number of bytes. |
- frame_dropper_->Leak((uint32_t)(InputFrameRateInternal() + 0.5f)); |
- if (video_suspended_) { |
- return true; // Drop all frames when muted. |
- } |
- return frame_dropper_->DropFrame(); |
-} |
- |
-void MediaOptimization::UpdateContentData( |
- const VideoContentMetrics* content_metrics) { |
- CriticalSectionScoped lock(crit_sect_.get()); |
- // Updating content metrics. |
- if (content_metrics == NULL) { |
- // Disable QM if metrics are NULL. |
- enable_qm_ = false; |
- qm_resolution_->Reset(); |
- } else { |
- content_->UpdateContentData(content_metrics); |
- } |
-} |
- |
-void MediaOptimization::UpdateIncomingFrameRate() { |
- int64_t now = clock_->TimeInMilliseconds(); |
- if (incoming_frame_times_[0] == 0) { |
- // No shifting if this is the first time. |
- } else { |
- // Shift all times one step. |
- for (int32_t i = (kFrameCountHistorySize - 2); i >= 0; i--) { |
- incoming_frame_times_[i + 1] = incoming_frame_times_[i]; |
- } |
- } |
- incoming_frame_times_[0] = now; |
- ProcessIncomingFrameRate(now); |
-} |
- |
-int32_t MediaOptimization::SelectQuality( |
- VCMQMSettingsCallback* video_qmsettings_callback) { |
- // Reset quantities for QM select. |
- qm_resolution_->ResetQM(); |
- |
- // Update QM will long-term averaged content metrics. |
- qm_resolution_->UpdateContent(content_->LongTermAvgData()); |
- |
- // Select quality mode. |
- VCMResolutionScale* qm = NULL; |
- int32_t ret = qm_resolution_->SelectResolution(&qm); |
- if (ret < 0) { |
- return ret; |
- } |
- |
- // Check for updates to spatial/temporal modes. |
- QMUpdate(qm, video_qmsettings_callback); |
- |
- // Reset all the rate and related frame counters quantities. |
- qm_resolution_->ResetRates(); |
- |
- // Reset counters. |
- last_qm_update_time_ = clock_->TimeInMilliseconds(); |
- |
- // Reset content metrics. |
- content_->Reset(); |
- |
- return VCM_OK; |
-} |
- |
-void MediaOptimization::PurgeOldFrameSamples(int64_t now_ms) { |
- while (!encoded_frame_samples_.empty()) { |
- if (now_ms - encoded_frame_samples_.front().time_complete_ms > |
- kBitrateAverageWinMs) { |
- encoded_frame_samples_.pop_front(); |
- } else { |
- break; |
- } |
- } |
-} |
- |
-void MediaOptimization::UpdateSentBitrate(int64_t now_ms) { |
- if (encoded_frame_samples_.empty()) { |
- avg_sent_bit_rate_bps_ = 0; |
- return; |
- } |
- size_t framesize_sum = 0; |
- for (FrameSampleList::iterator it = encoded_frame_samples_.begin(); |
- it != encoded_frame_samples_.end(); |
- ++it) { |
- framesize_sum += it->size_bytes; |
- } |
- float denom = static_cast<float>( |
- now_ms - encoded_frame_samples_.front().time_complete_ms); |
- if (denom >= 1.0f) { |
- avg_sent_bit_rate_bps_ = |
- static_cast<uint32_t>(framesize_sum * 8.0f * 1000.0f / denom + 0.5f); |
- } else { |
- avg_sent_bit_rate_bps_ = framesize_sum * 8; |
- } |
-} |
- |
-void MediaOptimization::UpdateSentFramerate() { |
- if (encoded_frame_samples_.size() <= 1) { |
- avg_sent_framerate_ = encoded_frame_samples_.size(); |
- return; |
- } |
- int denom = encoded_frame_samples_.back().timestamp - |
- encoded_frame_samples_.front().timestamp; |
- if (denom > 0) { |
- avg_sent_framerate_ = |
- (90000 * (encoded_frame_samples_.size() - 1) + denom / 2) / denom; |
- } else { |
- avg_sent_framerate_ = encoded_frame_samples_.size(); |
- } |
-} |
- |
-bool MediaOptimization::QMUpdate( |
- VCMResolutionScale* qm, |
- VCMQMSettingsCallback* video_qmsettings_callback) { |
- // Check for no change. |
- if (!qm->change_resolution_spatial && !qm->change_resolution_temporal) { |
- return false; |
- } |
- |
- // Check for change in frame rate. |
- if (qm->change_resolution_temporal) { |
- incoming_frame_rate_ = qm->frame_rate; |
- // Reset frame rate estimate. |
- memset(incoming_frame_times_, -1, sizeof(incoming_frame_times_)); |
- } |
- |
- // Check for change in frame size. |
- if (qm->change_resolution_spatial) { |
- codec_width_ = qm->codec_width; |
- codec_height_ = qm->codec_height; |
- } |
- |
- LOG(LS_INFO) << "Media optimizer requests the video resolution to be changed " |
- "to " << qm->codec_width << "x" << qm->codec_height << "@" |
- << qm->frame_rate; |
- |
- // Update VPM with new target frame rate and frame size. |
- // Note: use |qm->frame_rate| instead of |_incoming_frame_rate| for updating |
- // target frame rate in VPM frame dropper. The quantity |_incoming_frame_rate| |
- // will vary/fluctuate, and since we don't want to change the state of the |
- // VPM frame dropper, unless a temporal action was selected, we use the |
- // quantity |qm->frame_rate| for updating. |
- video_qmsettings_callback->SetVideoQMSettings( |
- qm->frame_rate, codec_width_, codec_height_); |
- content_->UpdateFrameRate(qm->frame_rate); |
- qm_resolution_->UpdateCodecParameters( |
- qm->frame_rate, codec_width_, codec_height_); |
- return true; |
-} |
- |
-// Check timing constraints and look for significant change in: |
-// (1) scene content, |
-// (2) target bit rate. |
-bool MediaOptimization::CheckStatusForQMchange() { |
- bool status = true; |
- |
- // Check that we do not call QMSelect too often, and that we waited some time |
- // (to sample the metrics) from the event last_change_time |
- // last_change_time is the time where user changed the size/rate/frame rate |
- // (via SetEncodingData). |
- int64_t now = clock_->TimeInMilliseconds(); |
- if ((now - last_qm_update_time_) < kQmMinIntervalMs || |
- (now - last_change_time_) < kQmMinIntervalMs) { |
- status = false; |
- } |
- |
- return status; |
-} |
- |
-// Allowing VCM to keep track of incoming frame rate. |
-void MediaOptimization::ProcessIncomingFrameRate(int64_t now) { |
- int32_t num = 0; |
- int32_t nr_of_frames = 0; |
- for (num = 1; num < (kFrameCountHistorySize - 1); ++num) { |
- if (incoming_frame_times_[num] <= 0 || |
- // don't use data older than 2 s |
- now - incoming_frame_times_[num] > kFrameHistoryWinMs) { |
- break; |
- } else { |
- nr_of_frames++; |
- } |
- } |
- if (num > 1) { |
- const int64_t diff = |
- incoming_frame_times_[0] - incoming_frame_times_[num - 1]; |
- incoming_frame_rate_ = 0.0; // No frame rate estimate available. |
- if (diff > 0) { |
- incoming_frame_rate_ = nr_of_frames * 1000.0f / static_cast<float>(diff); |
- } |
- } |
-} |
- |
-void MediaOptimization::CheckSuspendConditions() { |
- // Check conditions for SuspendBelowMinBitrate. |video_target_bitrate_| is in |
- // bps. |
- if (suspension_enabled_) { |
- if (!video_suspended_) { |
- // Check if we just went below the threshold. |
- if (video_target_bitrate_ < suspension_threshold_bps_) { |
- video_suspended_ = true; |
- } |
- } else { |
- // Video is already suspended. Check if we just went over the threshold |
- // with a margin. |
- if (video_target_bitrate_ > |
- suspension_threshold_bps_ + suspension_window_bps_) { |
- video_suspended_ = false; |
- } |
- } |
- } |
-} |
- |
-} // namespace media_optimization |
-} // namespace webrtc |