Fix bug on key frame boost allocation, and some update/cleanup to same function.

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

git-svn-id: http://webrtc.googlecode.com/svn/trunk@123 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
marpan@google.com 2011-06-23 16:36:33 +00:00
parent 3c45dfd178
commit 0d7e5bc712

View File

@ -21,7 +21,6 @@
namespace webrtc { namespace webrtc {
bool bool
VCMProtectionMethod::BetterThan(VCMProtectionMethod *pm) VCMProtectionMethod::BetterThan(VCMProtectionMethod *pm)
{ {
@ -317,9 +316,16 @@ VCMFecMethod::ProtectionFactor(const VCMProtectionParameters* parameters)
{ {
// FEC PROTECTION SETTINGS: varies with packet loss and bitrate // FEC PROTECTION SETTINGS: varies with packet loss and bitrate
const float bitRate = parameters->bitRate;
WebRtc_UWord8 packetLoss = (WebRtc_UWord8) (255 * parameters->lossPr); WebRtc_UWord8 packetLoss = (WebRtc_UWord8) (255 * parameters->lossPr);
// No protection if (filtered) packetLoss is 0
if (packetLoss == 0)
{
_protectionFactorK = 0;
_protectionFactorD = 0;
return true;
}
// Size of tables // Size of tables
const WebRtc_UWord16 maxFecTableSize = 6450; const WebRtc_UWord16 maxFecTableSize = 6450;
// Parameters for range of rate and packet loss for tables // Parameters for range of rate and packet loss for tables
@ -327,36 +333,36 @@ VCMFecMethod::ProtectionFactor(const VCMProtectionParameters* parameters)
const WebRtc_UWord8 ratePar2 = 49; const WebRtc_UWord8 ratePar2 = 49;
const WebRtc_UWord8 plossMax = 129; const WebRtc_UWord8 plossMax = 129;
// const float bitRate = parameters->bitRate;
// Just for testing: for the case where we randomly lose slices instead of
// RTP packets and use SingleMode packetization in RTP module
// const WebRtc_UWord16 slice_size = 3000/6; //@ 1000k with 4 cores
//float slice_mtu = (float)_maxPayloadSize/(float)slice_size; // Total (avg) bits available per frame: total rate over actual/frame_rate.
const float slice_mtu = 1.0; // Units are kbits/frame
//
//Total (avg) bits available per frame: total rate over actual/sent frame
// rate. Units are kbits/frame
const WebRtc_UWord16 bitRatePerFrame = static_cast<WebRtc_UWord16> const WebRtc_UWord16 bitRatePerFrame = static_cast<WebRtc_UWord16>
(slice_mtu * bitRate (bitRate /
/ (parameters->frameRate)); (parameters->frameRate));
//Total (avg) number of packets per frame (source and fec): // Total (avg) number of packets per frame (source and fec):
const WebRtc_UWord8 avgTotPackets = 1 + (WebRtc_UWord8) const WebRtc_UWord8 avgTotPackets = 1 + (WebRtc_UWord8)
((float) bitRatePerFrame * 1000.0 ((float) bitRatePerFrame * 1000.0
/ (float) (8.0 * _maxPayloadSize) + 0.5); / (float) (8.0 * _maxPayloadSize) + 0.5);
// TODO(marpan): Tune model for FEC Protection.
// Better modulation of protection with available bits/frame // First partition protection: ~ 20%
// (or avgTotpackets) using weight factors WebRtc_UWord8 firstPartitionProt = (WebRtc_UWord8) (255 * 0.20);
// FEC Tables include this effect already, but need to tune model off-line
// Threshold on packetLoss and bitRrate/frameRate (=average #packets),
// above which we allocate protection to cover at least roughly
// first partition size.
WebRtc_UWord8 lossThr = 0;
WebRtc_UWord8 packetNumThr = 1;
// Modulation of protection with available bits/frame (or avgTotpackets)
float weight1 = 0.5; float weight1 = 0.5;
float weight2 = 0.5; float weight2 = 0.5;
if (avgTotPackets > 4) if (avgTotPackets > 4)
{ {
weight1 = 1.0; weight1 = 0.75;
weight2 = 0.; weight2 = 0.25;
} }
if (avgTotPackets > 6) if (avgTotPackets > 6)
{ {
@ -364,41 +370,62 @@ VCMFecMethod::ProtectionFactor(const VCMProtectionParameters* parameters)
weight2 = 0.; weight2 = 0.;
} }
// Fec rate parameters: for P and I frame // FEC rate parameters: for P and I frame
WebRtc_UWord8 codeRateDelta = 0; WebRtc_UWord8 codeRateDelta = 0;
WebRtc_UWord8 codeRateKey = 0; WebRtc_UWord8 codeRateKey = 0;
// Get index for new table: the FEC protection depends on the (average) // Get index for table: the FEC protection depends on the (average)
// available bits/frame the range on the rate index corresponds to rates // available bits/frame. The range on the rate index corresponds to rates
// (bps) from 200k to 8000k, for 30fps // (bps) from 200k to 8000k, for 30fps
WebRtc_UWord8 rateIndexTable = WebRtc_UWord8 rateIndexTable =
(WebRtc_UWord8) VCM_MAX(VCM_MIN((bitRatePerFrame - ratePar1) / (WebRtc_UWord8) VCM_MAX(VCM_MIN((bitRatePerFrame - ratePar1) /
ratePar1, ratePar2), 0); ratePar1, ratePar2), 0);
// Restrict packet loss range to 50 for now%: current tables defined only // Restrict packet loss range to 50:
// up to 50% // current tables defined only up to 50%
if (packetLoss >= plossMax) if (packetLoss >= plossMax)
{ {
packetLoss = plossMax - 1; packetLoss = plossMax - 1;
} }
WebRtc_UWord16 indexTable = rateIndexTable * plossMax + packetLoss; WebRtc_UWord16 indexTable = rateIndexTable * plossMax + packetLoss;
// check on table index // Check on table index
if (indexTable >= maxFecTableSize) assert(indexTable < maxFecTableSize);
// Protection factor for P frame
codeRateDelta = VCMCodeRateXORTable[indexTable];
if (packetLoss > lossThr && avgTotPackets > packetNumThr)
{ {
assert("FEC table index too large\n"); // Average with minimum protection level given by (average) total
// number of packets
codeRateDelta = static_cast<WebRtc_UWord8>((weight1 *
(float) codeRateDelta + weight2 * 255.0 / (float) avgTotPackets));
// Set a minimum based on first partition size.
if (codeRateDelta < firstPartitionProt)
{
codeRateDelta = firstPartitionProt;
}
} }
// For Key frame: effectively at a higher rate, so we scale/boost the rate // Check limit on amount of protection for P frame; 50% is max.
// index. The boost factor may depend on several factors: ratio of packet if (codeRateDelta >= plossMax)
{
codeRateDelta = plossMax - 1;
}
// For Key frame:
// Effectively at a higher rate, so we scale/boost the rate
// The boost factor may depend on several factors: ratio of packet
// number of I to P frames, how much protection placed on P frames, etc. // number of I to P frames, how much protection placed on P frames, etc.
// default is 2
const WebRtc_UWord8 packetFrameDelta = (WebRtc_UWord8) const WebRtc_UWord8 packetFrameDelta = (WebRtc_UWord8)
(0.5 + parameters->packetsPerFrame); (0.5 + parameters->packetsPerFrame);
const WebRtc_UWord8 packetFrameKey = (WebRtc_UWord8) const WebRtc_UWord8 packetFrameKey = (WebRtc_UWord8)
(0.5 + parameters->packetsPerFrameKey); (0.5 + parameters->packetsPerFrameKey);
const WebRtc_UWord8 boostKey = BoostCodeRateKey(packetFrameDelta, const WebRtc_UWord8 boostKey = BoostCodeRateKey(packetFrameDelta,
packetFrameKey); packetFrameKey);
rateIndexTable = (WebRtc_UWord8) VCM_MAX(VCM_MIN( rateIndexTable = (WebRtc_UWord8) VCM_MAX(VCM_MIN(
1 + (boostKey * bitRatePerFrame - ratePar1) / 1 + (boostKey * bitRatePerFrame - ratePar1) /
ratePar1,ratePar2),0); ratePar1,ratePar2),0);
@ -406,32 +433,25 @@ VCMFecMethod::ProtectionFactor(const VCMProtectionParameters* parameters)
indexTableKey = VCM_MIN(indexTableKey, maxFecTableSize); indexTableKey = VCM_MIN(indexTableKey, maxFecTableSize);
// protection factor for P frame // Check on table index
codeRateDelta = VCMCodeRateXORTable[indexTable]; assert(indexTableKey < maxFecTableSize);
// protection factor for I frame
// Protection factor for I frame
codeRateKey = VCMCodeRateXORTable[indexTableKey]; codeRateKey = VCMCodeRateXORTable[indexTableKey];
// average with minimum protection level given by (average) total // Boosting for Key frame.
// number of packets WebRtc_UWord32 boostKeyProt = _scaleProtKey * codeRateDelta;
if (packetLoss > 0) if ( boostKeyProt >= plossMax)
{ {
codeRateDelta = static_cast<WebRtc_UWord8> ((weight1 * (float) boostKeyProt = plossMax - 1;
codeRateDelta + weight2 * 255.0
/ (float) avgTotPackets));
} }
//check limit on amount of protection for P frame; 50% is max // Make sure I frame protection is at least larger than P frame protection,
if (codeRateDelta >= plossMax) // and at least as high as filtered packet loss.
{
codeRateDelta = plossMax - 1;
}
// make sure I frame protection is at least larger than P frame protection,
// and at least as high as received loss
codeRateKey = static_cast<WebRtc_UWord8> (VCM_MAX(packetLoss, codeRateKey = static_cast<WebRtc_UWord8> (VCM_MAX(packetLoss,
VCM_MAX(_scaleProtKey * codeRateDelta, codeRateKey))); VCM_MAX(boostKeyProt, codeRateKey)));
//check limit on amount of protection for I frame: 50% is max // Check limit on amount of protection for I frame: 50% is max.
if (codeRateKey >= plossMax) if (codeRateKey >= plossMax)
{ {
codeRateKey = plossMax - 1; codeRateKey = plossMax - 1;