From 1dd8d4bca49482c4c1f776bdc89c09c2704cd685 Mon Sep 17 00:00:00 2001 From: "marpan@webrtc.org" Date: Tue, 9 Oct 2012 20:43:56 +0000 Subject: [PATCH] Put some bounds on VCM frame dropper. Review URL: https://webrtc-codereview.appspot.com/873005 git-svn-id: http://webrtc.googlecode.com/svn/trunk@2893 4adac7df-926f-26a2-2b94-8c16560cd09d --- .../video_coding/main/source/frame_dropper.cc | 35 ++++++++++++++----- .../video_coding/main/source/frame_dropper.h | 8 +++-- .../main/source/media_optimization.cc | 3 +- 3 files changed, 35 insertions(+), 11 deletions(-) diff --git a/src/modules/video_coding/main/source/frame_dropper.cc b/src/modules/video_coding/main/source/frame_dropper.cc index 065e4523e..47aa819fb 100644 --- a/src/modules/video_coding/main/source/frame_dropper.cc +++ b/src/modules/video_coding/main/source/frame_dropper.cc @@ -35,8 +35,8 @@ VCMFrameDropper::Reset() _accumulator = 0.0f; _accumulatorMax = 150.0f; // assume 300 kb/s and 0.5 s window _targetBitRate = 300.0f; - _userFrameRate = 30; - _keyFrameSpreadFrames = 0.5f * _userFrameRate; + _incoming_frame_rate = 30; + _keyFrameSpreadFrames = 0.5f * _incoming_frame_rate; _dropNext = false; _dropRatio.Reset(0.9f); _dropRatio.Apply(0.0f, 0.0f); // Initialize to 0 @@ -45,6 +45,10 @@ VCMFrameDropper::Reset() _wasBelowMax = true; _enabled = true; _fastMode = false; // start with normal (non-aggressive) mode + // Cap for the encoder buffer level/accumulator, in secs. + _cap_buffer_size = 3.0f; + // Cap on maximum amount of dropped frames between kept frames, in secs. + _max_time_drops = 4.0f; } void @@ -98,6 +102,7 @@ VCMFrameDropper::Fill(WebRtc_UWord32 frameSizeBytes, bool deltaFrame) } // Change the level of the accumulator (bucket) _accumulator += frameSizeKbits; + CapAccumulator(); } void @@ -135,7 +140,6 @@ VCMFrameDropper::Leak(WebRtc_UWord32 inputFrameRate) } _accumulator -= T; UpdateRatio(); - } void @@ -222,6 +226,13 @@ VCMFrameDropper::DropFrame() denom = (float)1e-5; } WebRtc_Word32 limit = static_cast(1.0f / denom - 1.0f + 0.5f); + // Put a bound on the max amount of dropped frames between each kept + // frame, in terms of frame rate and window size (secs). + int max_limit = static_cast(_incoming_frame_rate * + _max_time_drops); + if (limit > max_limit) { + limit = max_limit; + } if (_dropCount < 0) { // Reset the _dropCount since it was negative and should be positive. @@ -302,7 +313,7 @@ VCMFrameDropper::DropFrame() } void -VCMFrameDropper::SetRates(float bitRate, float userFrameRate) +VCMFrameDropper::SetRates(float bitRate, float incoming_frame_rate) { // Bit rate of -1 means infinite bandwidth. _accumulatorMax = bitRate * _windowSize; // bitRate * windowSize (in seconds) @@ -312,10 +323,8 @@ VCMFrameDropper::SetRates(float bitRate, float userFrameRate) _accumulator = bitRate / _targetBitRate * _accumulator; } _targetBitRate = bitRate; - if (userFrameRate > 0.0f) - { - _userFrameRate = userFrameRate; - } + CapAccumulator(); + _incoming_frame_rate = incoming_frame_rate; } float @@ -328,4 +337,14 @@ VCMFrameDropper::ActualFrameRate(WebRtc_UWord32 inputFrameRate) const return inputFrameRate * (1.0f - _dropRatio.Value()); } +// Put a cap on the accumulator, i.e., don't let it grow beyond some level. +// This is a temporary fix for screencasting where very large frames from +// encoder will cause very slow response (too many frame drops). +void VCMFrameDropper::CapAccumulator() { + float max_accumulator = _targetBitRate * _cap_buffer_size; + if (_accumulator > max_accumulator) { + _accumulator = max_accumulator; + } +} + } diff --git a/src/modules/video_coding/main/source/frame_dropper.h b/src/modules/video_coding/main/source/frame_dropper.h index 5e7e8a16b..fdf024ca8 100644 --- a/src/modules/video_coding/main/source/frame_dropper.h +++ b/src/modules/video_coding/main/source/frame_dropper.h @@ -60,16 +60,18 @@ public: // // Input: // - bitRate : The target bit rate - void SetRates(float bitRate, float userFrameRate); + void SetRates(float bitRate, float incoming_frame_rate); // Return value : The current average frame rate produced // if the DropFrame() function is used as // instruction of when to drop frames. float ActualFrameRate(WebRtc_UWord32 inputFrameRate) const; + private: void FillBucket(float inKbits, float outKbits); void UpdateRatio(); + void CapAccumulator(); WebRtc_Word32 _vcmId; VCMExpFilter _keyFrameSizeAvgKbits; @@ -83,10 +85,12 @@ private: VCMExpFilter _dropRatio; WebRtc_Word32 _dropCount; float _windowSize; - float _userFrameRate; + float _incoming_frame_rate; bool _wasBelowMax; bool _enabled; bool _fastMode; + float _cap_buffer_size; + float _max_time_drops; }; // end of VCMFrameDropper class } // namespace webrtc diff --git a/src/modules/video_coding/main/source/media_optimization.cc b/src/modules/video_coding/main/source/media_optimization.cc index b2ed54c80..48b7b4761 100644 --- a/src/modules/video_coding/main/source/media_optimization.cc +++ b/src/modules/video_coding/main/source/media_optimization.cc @@ -176,7 +176,8 @@ VCMMediaOptimization::SetTargetRates(WebRtc_UWord32 bitRate, _targetBitRate = bitRate - protection_overhead_kbps; // Update encoding rates following protection settings - _frameDropper->SetRates(static_cast(_targetBitRate), 0); + _frameDropper->SetRates(static_cast(_targetBitRate), + _incomingFrameRate); if (_enableQm) {