Chromium Code Reviews| Index: webrtc/modules/video_coding/protection_bitrate_calculator.cc |
| diff --git a/webrtc/modules/video_coding/media_optimization.cc b/webrtc/modules/video_coding/protection_bitrate_calculator.cc |
| similarity index 17% |
| copy from webrtc/modules/video_coding/media_optimization.cc |
| copy to webrtc/modules/video_coding/protection_bitrate_calculator.cc |
| index d5fbadc122fc34c92ea71debad7aa5ee04bc2742..811d0e704a50bdff8238f4547b0698f879d3562d 100644 |
| --- a/webrtc/modules/video_coding/media_optimization.cc |
| +++ b/webrtc/modules/video_coding/protection_bitrate_calculator.cc |
| @@ -1,5 +1,5 @@ |
| /* |
| - * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. |
| + * Copyright (c) 2016 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 |
| @@ -8,311 +8,176 @@ |
| * be found in the AUTHORS file in the root of the source tree. |
| */ |
| -#include "webrtc/modules/video_coding/media_optimization.h" |
| - |
| -#include "webrtc/base/logging.h" |
| -#include "webrtc/modules/video_coding/utility/frame_dropper.h" |
| -#include "webrtc/system_wrappers/include/clock.h" |
| +#include <webrtc/modules/video_coding/protection_bitrate_calculator.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(); |
| - // 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 |
| +using rtc::CritScope; |
| -struct MediaOptimization::EncodedFrameSample { |
| +struct ProtectionBitrateCalculator::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), |
| - encoded_frame_samples_(), |
| - avg_sent_bit_rate_bps_(0), |
| - avg_sent_framerate_(0), |
| - key_frame_cnt_(0), |
| - delta_frame_cnt_(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_)); |
| -} |
| +ProtectionBitrateCalculator::ProtectionBitrateCalculator( |
| + Clock* clock, |
| + VCMProtectionCallback* protection_callback) |
| + : clock_(clock), |
| + protection_callback_(protection_callback), |
| + loss_prot_logic_(new media_optimization::VCMLossProtectionLogic( |
| + clock_->TimeInMilliseconds())), |
| + max_payload_size_(1460) {} |
| -MediaOptimization::~MediaOptimization(void) { |
| +ProtectionBitrateCalculator::~ProtectionBitrateCalculator(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); |
| - 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; |
| - 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) { |
| +void ProtectionBitrateCalculator::SetEncodingData(uint32_t target_bitrate, |
| + uint16_t width, |
| + uint16_t height, |
| + uint32_t frame_rate, |
| + size_t num_temporal_layers, |
| + size_t max_payload_size) { |
| + CritScope lock(&crit_sect_); |
| // Everything codec specific should be reset here since this means the codec |
| // has changed. |
| - |
| - 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; |
| + loss_prot_logic_->UpdateNumLayers(num_temporal_layers); |
| + max_payload_size_ = max_payload_size; |
| } |
| -uint32_t MediaOptimization::SetTargetRates( |
| - uint32_t target_bitrate, |
| +uint32_t ProtectionBitrateCalculator::SetTargetRates( |
| + uint32_t estimated_bitrate_bps, |
| + float actual_framerate_fps, |
| uint8_t fraction_lost, |
| - int64_t round_trip_time_ms, |
| - VCMProtectionCallback* protection_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(); |
| - |
| + int64_t round_trip_time_ms) { |
| + float target_bitrate_kbps = |
| + static_cast<float>(estimated_bitrate_bps) / 1000.0f; |
| // Sanity check. |
| - if (actual_frame_rate < 1.0) { |
| - actual_frame_rate = 1.0; |
| + if (actual_framerate_fps < 1.0) { |
| + actual_framerate_fps = 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; |
| + FecProtectionParams delta_fec_params; |
| + FecProtectionParams key_fec_params; |
| + { |
| + CritScope lock(&crit_sect_); |
| + |
| + loss_prot_logic_->UpdateBitRate(target_bitrate_kbps); |
| + loss_prot_logic_->UpdateRtt(round_trip_time_ms); |
| + |
| + // Update frame rate for the loss protection logic class: frame rate should |
| + // be the actual/sent rate. |
| + loss_prot_logic_->UpdateFrameRate(actual_framerate_fps); |
| + |
| + // 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. |
| + media_optimization::FilterPacketLossMode filter_mode = |
| + media_optimization::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); |
| + |
| + if (loss_prot_logic_->SelectedType() == media_optimization::kNone) { |
| + return estimated_bitrate_bps; |
| + } |
| - // Update protection settings, when applicable. |
| - if (loss_prot_logic_->SelectedType() != kNone) { |
| // 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(); |
| - } |
| - |
| - // 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_); |
| + // Get the FEC code rate for Key frames (set to 0 when NA). |
| + key_fec_params.fec_rate = |
| + loss_prot_logic_->SelectedMethod()->RequiredProtectionFactorK(); |
| - CheckSuspendConditions(); |
| + // Get the FEC code rate for Delta frames (set to 0 when NA). |
| + delta_fec_params.fec_rate = |
| + loss_prot_logic_->SelectedMethod()->RequiredProtectionFactorD(); |
| - return video_target_bitrate_; |
| -} |
| - |
| -void MediaOptimization::SetProtectionMethod(VCMProtectionMethodEnum method) { |
| - CriticalSectionScoped lock(crit_sect_.get()); |
| - loss_prot_logic_->SetMethod(method); |
| -} |
| + // The RTP module currently requires the same |max_fec_frames| for both |
| + // key and delta frames. |
| + delta_fec_params.max_fec_frames = |
| + loss_prot_logic_->SelectedMethod()->MaxFramesFec(); |
| + key_fec_params.max_fec_frames = |
| + loss_prot_logic_->SelectedMethod()->MaxFramesFec(); |
| + } // |crit_sect_.Leave()| |
|
stefan-webrtc
2016/06/02 07:42:37
We typically don't add comments like this, it's fa
perkj_webrtc
2016/06/02 10:16:20
Done.
|
| -uint32_t MediaOptimization::InputFrameRate() { |
| - CriticalSectionScoped lock(crit_sect_.get()); |
| - return InputFrameRateInternal(); |
| -} |
| + // 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; |
| -uint32_t MediaOptimization::InputFrameRateInternal() { |
| - ProcessIncomingFrameRate(clock_->TimeInMilliseconds()); |
| - return uint32_t(incoming_frame_rate_ + 0.5f); |
| -} |
| + // 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; |
| + // Rate cost of the protection methods. |
| + float protection_overhead_rate = 0.0f; |
| -uint32_t MediaOptimization::SentFrameRate() { |
| - CriticalSectionScoped lock(crit_sect_.get()); |
| - return SentFrameRateInternal(); |
| -} |
| + // TODO(Marco): Pass FEC protection values per layer. |
| + protection_callback_->ProtectionRequest( |
| + &delta_fec_params, &key_fec_params, &sent_video_rate_bps, |
| + &sent_nack_rate_bps, &sent_fec_rate_bps); |
| + |
| + 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; |
| -uint32_t MediaOptimization::SentFrameRateInternal() { |
| - PurgeOldFrameSamples(clock_->TimeInMilliseconds()); |
| - UpdateSentFramerate(); |
| - return avg_sent_framerate_; |
| + // Source coding rate: total rate - protection overhead. |
| + return estimated_bitrate_bps * (1.0 - protection_overhead_rate); |
| } |
| -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_; |
| +void ProtectionBitrateCalculator::SetProtectionMethod(bool enable_fec, |
| + bool enable_nack) { |
| + media_optimization::VCMProtectionMethodEnum method(media_optimization::kNone); |
| + if (enable_fec && enable_nack) { |
| + method = media_optimization::kNackFec; |
| + } else if (enable_nack) { |
| + method = media_optimization::kNack; |
| + } else if (enable_fec) { |
| + method = media_optimization::kFec; |
| + } |
| + CritScope lock(&crit_sect_); |
| + loss_prot_logic_->SetMethod(method); |
| } |
| -int32_t MediaOptimization::UpdateWithEncodedData( |
| +void ProtectionBitrateCalculator::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(); |
| + const size_t& encoded_length = encoded_image._length; |
|
stefan-webrtc
2016/06/02 07:42:37
I don't think there's a point in making this a con
perkj_webrtc
2016/06/02 10:16:20
Should be the same.
|
| + CritScope lock(&crit_sect_); |
| 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_); |
| @@ -327,151 +192,7 @@ int32_t MediaOptimization::UpdateWithEncodedData( |
| 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::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::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); |
| -} |
| - |
| -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(); |
| - } |
| -} |
| - |
| -// 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 |