Pass NACK and FEC overhead rates through the ProtectionCallback to VCM.

These overhead rates are used by the VCM to compensate the source
coding rate for NACK and FEC.

BUG=
TEST=

Review URL: http://webrtc-codereview.appspot.com/323003

git-svn-id: http://webrtc.googlecode.com/svn/trunk@1171 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
stefan@webrtc.org 2011-12-13 15:38:14 +00:00
parent 1ced840893
commit f4c8286222
8 changed files with 113 additions and 59 deletions

@ -2363,6 +2363,15 @@ void ModuleRtpRtcpImpl::BitrateSent(WebRtc_UWord32* totalRate,
// for default we need to update the send bitrate // for default we need to update the send bitrate
CriticalSectionScoped lock(_criticalSectionModulePtrsFeedback); CriticalSectionScoped lock(_criticalSectionModulePtrsFeedback);
if (totalRate != NULL)
*totalRate = 0;
if (videoRate != NULL)
*videoRate = 0;
if (fecRate != NULL)
*fecRate = 0;
if (nackRate != NULL)
*nackRate = 0;
std::list<ModuleRtpRtcpImpl*>::const_iterator it = std::list<ModuleRtpRtcpImpl*>::const_iterator it =
_childModules.begin(); _childModules.begin();
while (it != _childModules.end()) { while (it != _childModules.end()) {
@ -2378,6 +2387,8 @@ void ModuleRtpRtcpImpl::BitrateSent(WebRtc_UWord32* totalRate,
&childNackRate); &childNackRate);
if (totalRate != NULL && childTotalRate > *totalRate) if (totalRate != NULL && childTotalRate > *totalRate)
*totalRate = childTotalRate; *totalRate = childTotalRate;
if (videoRate != NULL && childVideoRate > *videoRate)
*videoRate = childVideoRate;
if (fecRate != NULL && childFecRate > *fecRate) if (fecRate != NULL && childFecRate > *fecRate)
*fecRate = childFecRate; *fecRate = childFecRate;
if (nackRate != NULL && childNackRate > *nackRate) if (nackRate != NULL && childNackRate > *nackRate)

@ -147,11 +147,15 @@ protected:
class VCMProtectionCallback class VCMProtectionCallback
{ {
public: public:
virtual WebRtc_Word32 ProtectionRequest(const WebRtc_UWord8 deltaFECRate, virtual int ProtectionRequest(
const WebRtc_UWord8 keyFECRate, uint8_t delta_fec_rate,
const bool deltaUseUepProtection, uint8_t key_fec_rate,
const bool keyUseUepProtection, bool delta_use_uep_protection,
const bool nack) = 0; bool key_use_uep_protection,
bool nack_enabled,
uint32_t* sent_video_rate_bps,
uint32_t* sent_nack_rate_bps,
uint32_t* sent_fec_rate_bps) = 0;
protected: protected:
virtual ~VCMProtectionCallback() {} virtual ~VCMProtectionCallback() {}

@ -22,7 +22,6 @@ _sendCodecType(kVideoCodecUnknown),
_codecWidth(0), _codecWidth(0),
_codecHeight(0), _codecHeight(0),
_userFrameRate(0), _userFrameRate(0),
_lossProtOverhead(0),
_packetLossEnc(0), _packetLossEnc(0),
_fractionLost(0), _fractionLost(0),
_sendStatisticsZeroEncode(0), _sendStatisticsZeroEncode(0),
@ -71,7 +70,6 @@ VCMMediaOptimization::Reset()
_lossProtLogic->Reset(); _lossProtLogic->Reset();
_sendStatisticsZeroEncode = 0; _sendStatisticsZeroEncode = 0;
_targetBitRate = 0; _targetBitRate = 0;
_lossProtOverhead = 0;
_codecWidth = 0; _codecWidth = 0;
_codecHeight = 0; _codecHeight = 0;
_userFrameRate = 0; _userFrameRate = 0;
@ -124,7 +122,7 @@ VCMMediaOptimization::SetTargetRates(WebRtc_UWord32 bitRate,
_lossProtLogic->UpdateFilteredLossPr(packetLossEnc); _lossProtLogic->UpdateFilteredLossPr(packetLossEnc);
// Rate cost of the protection methods // Rate cost of the protection methods
_lossProtOverhead = 0; uint32_t protection_overhead_kbps = 0;
// Update protection settings, when applicable // Update protection settings, when applicable
if (selectedMethod) if (selectedMethod)
@ -137,24 +135,40 @@ VCMMediaOptimization::SetTargetRates(WebRtc_UWord32 bitRate,
// the protection method is set by the user via SetVideoProtection. // the protection method is set by the user via SetVideoProtection.
_lossProtLogic->UpdateMethod(); _lossProtLogic->UpdateMethod();
// Update protection callback with protection settings // Update protection callback with protection settings.
UpdateProtectionCallback(selectedMethod); uint32_t sent_video_rate_bps = 0;
uint32_t sent_nack_rate_bps = 0;
// Get the bit cost of protection method uint32_t sent_fec_rate_bps = 0;
_lossProtOverhead = static_cast<WebRtc_UWord32> // Get the bit cost of protection method, based on the amount of
(_lossProtLogic->RequiredBitRate() + 0.5f); // overhead data actually transmitted (including headers) the last
// second.
UpdateProtectionCallback(selectedMethod,
&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_kbps = static_cast<uint32_t>(bitRate *
static_cast<double>(sent_nack_rate_bps + sent_fec_rate_bps) /
sent_total_rate_bps + 0.5);
}
// Cap the overhead estimate to 50%.
if (protection_overhead_kbps > bitRate / 2)
protection_overhead_kbps = bitRate / 2;
// Get the effective packet loss for encoder ER // Get the effective packet loss for encoder ER
// when applicable, should be passed to encoder via fractionLost // when applicable, should be passed to encoder via fractionLost
packetLossEnc = selectedMethod->RequiredPacketLossER(); packetLossEnc = selectedMethod->RequiredPacketLossER();
} }
// Update encoding rates following protection settings
_frameDropper->SetRates(static_cast<float>(bitRate -
_lossProtOverhead), 0);
// Source coding rate: total rate - protection overhead // Source coding rate: total rate - protection overhead
_targetBitRate = bitRate - _lossProtOverhead; _targetBitRate = bitRate - protection_overhead_kbps;
// Update encoding rates following protection settings
_frameDropper->SetRates(static_cast<float>(_targetBitRate), 0);
if (_enableQm) if (_enableQm)
{ {
@ -174,9 +188,11 @@ VCMMediaOptimization::SetTargetRates(WebRtc_UWord32 bitRate,
return _targetBitRate; return _targetBitRate;
} }
WebRtc_UWord32 int VCMMediaOptimization::UpdateProtectionCallback(
VCMMediaOptimization::UpdateProtectionCallback(VCMProtectionMethod VCMProtectionMethod *selected_method,
*selectedMethod) uint32_t* video_rate_bps,
uint32_t* nack_overhead_rate_bps,
uint32_t* fec_overhead_rate_bps)
{ {
if (!_videoProtectionCallback) if (!_videoProtectionCallback)
{ {
@ -184,29 +200,32 @@ VCMMediaOptimization::UpdateProtectionCallback(VCMProtectionMethod
} }
// Get the FEC code rate for Key frames (set to 0 when NA) // Get the FEC code rate for Key frames (set to 0 when NA)
const WebRtc_UWord8 const WebRtc_UWord8
codeRateKeyRTP = selectedMethod->RequiredProtectionFactorK(); codeRateKeyRTP = selected_method->RequiredProtectionFactorK();
// Get the FEC code rate for Delta frames (set to 0 when NA) // Get the FEC code rate for Delta frames (set to 0 when NA)
const WebRtc_UWord8 const WebRtc_UWord8
codeRateDeltaRTP = selectedMethod->RequiredProtectionFactorD(); codeRateDeltaRTP = selected_method->RequiredProtectionFactorD();
// Get the FEC-UEP protection status for Key frames: UEP on/off // Get the FEC-UEP protection status for Key frames: UEP on/off
const bool const bool
useUepProtectionKeyRTP = selectedMethod->RequiredUepProtectionK(); useUepProtectionKeyRTP = selected_method->RequiredUepProtectionK();
// Get the FEC-UEP protection status for Delta frames: UEP on/off // Get the FEC-UEP protection status for Delta frames: UEP on/off
const bool const bool
useUepProtectionDeltaRTP = selectedMethod->RequiredUepProtectionD(); useUepProtectionDeltaRTP = selected_method->RequiredUepProtectionD();
// NACK is on for NACK and NackFec protection method: off for FEC method // NACK is on for NACK and NackFec protection method: off for FEC method
bool nackStatus = (selectedMethod->Type() == kNackFec || bool nackStatus = (selected_method->Type() == kNackFec ||
selectedMethod->Type() == kNack); selected_method->Type() == kNack);
return _videoProtectionCallback->ProtectionRequest(codeRateDeltaRTP, return _videoProtectionCallback->ProtectionRequest(codeRateDeltaRTP,
codeRateKeyRTP, codeRateKeyRTP,
useUepProtectionDeltaRTP, useUepProtectionDeltaRTP,
useUepProtectionKeyRTP, useUepProtectionKeyRTP,
nackStatus); nackStatus,
video_rate_bps,
nack_overhead_rate_bps,
fec_overhead_rate_bps);
} }
bool bool

@ -139,7 +139,10 @@ private:
/* /*
* Update protection callback with protection settings * Update protection callback with protection settings
*/ */
WebRtc_UWord32 UpdateProtectionCallback(VCMProtectionMethod *selectedMethod); int UpdateProtectionCallback(VCMProtectionMethod *selected_method,
uint32_t* total_video_rate_bps,
uint32_t* nack_overhead_rate_bps,
uint32_t* fec_overhead_rate_bps);
void UpdateBitRateEstimate(WebRtc_Word64 encodedLength, WebRtc_Word64 nowMs); void UpdateBitRateEstimate(WebRtc_Word64 encodedLength, WebRtc_Word64 nowMs);
/* /*
@ -168,7 +171,6 @@ private:
VCMFrameDropper* _frameDropper; VCMFrameDropper* _frameDropper;
VCMLossProtectionLogic* _lossProtLogic; VCMLossProtectionLogic* _lossProtLogic;
WebRtc_UWord32 _lossProtOverhead;
WebRtc_UWord8 _packetLossEnc; WebRtc_UWord8 _packetLossEnc;
WebRtc_UWord8 _fractionLost; WebRtc_UWord8 _fractionLost;

@ -438,17 +438,20 @@ VideoProtectionCallback::~VideoProtectionCallback()
} }
WebRtc_Word32 WebRtc_Word32
VideoProtectionCallback::ProtectionRequest(const WebRtc_UWord8 deltaFECRate, VideoProtectionCallback::ProtectionRequest(WebRtc_UWord8 deltaFECRate,
const WebRtc_UWord8 keyFECRate, WebRtc_UWord8 keyFECRate,
const bool deltaUseUepProtection, bool deltaUseUepProtection,
const bool keyUseUepProtection, bool keyUseUepProtection,
const bool nack) bool nack_enabled,
WebRtc_UWord32* sent_video_rate_bps,
WebRtc_UWord32* sent_nack_rate_bps,
WebRtc_UWord32* sent_fec_rate_bps)
{ {
_deltaFECRate = deltaFECRate; _deltaFECRate = deltaFECRate;
_keyFECRate = keyFECRate; _keyFECRate = keyFECRate;
_deltaUseUepProtection = deltaUseUepProtection; _deltaUseUepProtection = deltaUseUepProtection;
_keyUseUepProtection = keyUseUepProtection; _keyUseUepProtection = keyUseUepProtection;
if (nack == true) if (nack_enabled)
{ {
_nack = kNackRtcp; _nack = kNackRtcp;
} }

@ -236,11 +236,14 @@ public:
VideoProtectionCallback(); VideoProtectionCallback();
virtual ~VideoProtectionCallback(); virtual ~VideoProtectionCallback();
void RegisterRtpModule(RtpRtcp* rtp) {_rtp = rtp;} void RegisterRtpModule(RtpRtcp* rtp) {_rtp = rtp;}
WebRtc_Word32 ProtectionRequest(const WebRtc_UWord8 deltaFECRate, WebRtc_Word32 ProtectionRequest(WebRtc_UWord8 deltaFECRate,
const WebRtc_UWord8 keyFECRate, WebRtc_UWord8 keyFECRate,
const bool deltaUseUepProtection, bool deltaUseUepProtection,
const bool keyUseUepProtection, bool keyUseUepProtection,
const bool nack); bool nack_enabled,
WebRtc_UWord32* sent_video_rate_bps,
WebRtc_UWord32* sent_nack_rate_bps,
WebRtc_UWord32* sent_fec_rate_bps);
enum NACKMethod NACKMethod(); enum NACKMethod NACKMethod();
WebRtc_UWord8 FECDeltaRate(); WebRtc_UWord8 FECDeltaRate();
WebRtc_UWord8 FECKeyRate(); WebRtc_UWord8 FECKeyRate();

@ -649,17 +649,21 @@ WebRtc_Word32 ViEEncoder::SendData(
rtp_video_hdr); rtp_video_hdr);
} }
WebRtc_Word32 ViEEncoder::ProtectionRequest(const WebRtc_UWord8 delta_fecrate, WebRtc_Word32 ViEEncoder::ProtectionRequest(
const WebRtc_UWord8 key_fecrate, WebRtc_UWord8 delta_fecrate,
const bool delta_use_uep_protection, WebRtc_UWord8 key_fecrate,
const bool key_use_uep_protection, bool delta_use_uep_protection,
const bool nack) { bool key_use_uep_protection,
bool nack_enabled,
WebRtc_UWord32* sent_video_rate_bps,
WebRtc_UWord32* sent_nack_rate_bps,
WebRtc_UWord32* sent_fec_rate_bps) {
WEBRTC_TRACE(webrtc::kTraceStream, webrtc::kTraceVideo, WEBRTC_TRACE(webrtc::kTraceStream, webrtc::kTraceVideo,
ViEId(engine_id_, channel_id_), ViEId(engine_id_, channel_id_),
"%s, deltaFECRate: %u, key_fecrate: %u, " "%s, deltaFECRate: %u, key_fecrate: %u, "
"delta_use_uep_protection: %d, key_use_uep_protection: %d, " "delta_use_uep_protection: %d, key_use_uep_protection: %d, ",
"nack: %d", __FUNCTION__, delta_fecrate, key_fecrate, __FUNCTION__, delta_fecrate, key_fecrate,
delta_use_uep_protection, key_use_uep_protection, nack); delta_use_uep_protection, key_use_uep_protection);
if (default_rtp_rtcp_.SetFECCodeRate(key_fecrate, delta_fecrate) != 0) { if (default_rtp_rtcp_.SetFECCodeRate(key_fecrate, delta_fecrate) != 0) {
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo, WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo,
@ -672,6 +676,10 @@ WebRtc_Word32 ViEEncoder::ProtectionRequest(const WebRtc_UWord8 delta_fecrate,
ViEId(engine_id_, channel_id_), ViEId(engine_id_, channel_id_),
"%s: Could not update FEC-UEP protection", __FUNCTION__); "%s: Could not update FEC-UEP protection", __FUNCTION__);
} }
default_rtp_rtcp_.BitrateSent(NULL,
sent_video_rate_bps,
sent_fec_rate_bps,
sent_nack_rate_bps);
return 0; return 0;
} }

@ -101,11 +101,15 @@ class ViEEncoder
const RTPVideoHeader* rtp_video_hdr); const RTPVideoHeader* rtp_video_hdr);
// Implements VideoProtectionCallback. // Implements VideoProtectionCallback.
virtual WebRtc_Word32 ProtectionRequest(const WebRtc_UWord8 delta_fecrate, virtual WebRtc_Word32 ProtectionRequest(
const WebRtc_UWord8 key_fecrate, WebRtc_UWord8 delta_fecrate,
const bool delta_use_uep_protection, WebRtc_UWord8 key_fecrate,
const bool key_use_uep_protection, bool delta_use_uep_protection,
const bool nack); bool key_use_uep_protection,
bool nack_enabled,
WebRtc_UWord32* sent_video_rate_bps,
WebRtc_UWord32* sent_nack_rate_bps,
WebRtc_UWord32* sent_fec_rate_bps);
// Implements VideoSendStatisticsCallback. // Implements VideoSendStatisticsCallback.
virtual WebRtc_Word32 SendStatistics(const WebRtc_UWord32 bit_rate, virtual WebRtc_Word32 SendStatistics(const WebRtc_UWord32 bit_rate,