Some re-organization of the fec-uep code: updated protection modes, comments, and some variable/function re-naming.

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

git-svn-id: http://webrtc.googlecode.com/svn/trunk@752 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
marpan@webrtc.org 2011-10-14 16:28:02 +00:00
parent 55c39f0940
commit 14aaaf116a

View File

@ -16,15 +16,14 @@
namespace {
// Allow for two different modes of protection for residual packets.
// The residual packets are the remaining packets beyond the important ones.
enum ResidualProtectionMode
// Allow for different modes of protection for packets in UEP case.
enum ProtectionMode
{
kModeNoOverlap,
kModeOverlap,
kModeBiasFirstPacket,
};
/**
* Fits an input mask (subMask) to an output mask.
* The mask is a matrix where the rows are the FEC packets,
@ -158,12 +157,12 @@ void ShiftFitSubMask(WebRtc_UWord16 numMaskBytes,
namespace webrtc {
namespace internal {
// Residual protection for remaining packets
void ResidualPacketProtection(WebRtc_UWord16 numMediaPackets,
WebRtc_UWord16 numFecPackets,
WebRtc_UWord16 numImpPackets,
// Remaining protection after important (first partition) packet protection
void RemainingPacketProtection(WebRtc_UWord16 numMediaPackets,
WebRtc_UWord16 numFecRemaining,
WebRtc_UWord16 numFecForImpPackets,
WebRtc_UWord16 numMaskBytes,
ResidualProtectionMode mode,
ProtectionMode mode,
WebRtc_UWord8* packetMask)
{
if (mode == kModeNoOverlap)
@ -171,34 +170,38 @@ void ResidualPacketProtection(WebRtc_UWord16 numMediaPackets,
// subMask21
const WebRtc_UWord8 lBit =
(numMediaPackets - numImpPackets) > 16 ? 1 : 0;
(numMediaPackets - numFecForImpPackets) > 16 ? 1 : 0;
const WebRtc_UWord16 resMaskBytes =
(lBit == 1)? kMaskSizeLBitSet : kMaskSizeLBitClear;
const WebRtc_UWord8* packetMaskSub21 =
packetMaskTbl[numMediaPackets - numImpPackets - 1]
[numFecPackets - numImpPackets - 1];
packetMaskTbl[numMediaPackets - numFecForImpPackets - 1]
[numFecRemaining - 1];
ShiftFitSubMask(numMaskBytes, resMaskBytes,
numImpPackets, numFecPackets,
ShiftFitSubMask(numMaskBytes, resMaskBytes, numFecForImpPackets,
(numFecForImpPackets + numFecRemaining),
packetMaskSub21, packetMask);
}
else if (mode == kModeOverlap)
else if (mode == kModeOverlap || mode == kModeBiasFirstPacket)
{
// subMask22
const WebRtc_UWord16 numFecForResidual =
numFecPackets - numImpPackets;
const WebRtc_UWord8* packetMaskSub22 =
packetMaskTbl[numMediaPackets - 1]
[numFecForResidual - 1];
packetMaskTbl[numMediaPackets - 1][numFecRemaining - 1];
FitSubMask(numMaskBytes, numMaskBytes,
numFecForResidual,
packetMaskSub22,
&packetMask[numImpPackets * numMaskBytes]);
FitSubMask(numMaskBytes, numMaskBytes, numFecRemaining, packetMaskSub22,
&packetMask[numFecForImpPackets * numMaskBytes]);
if (mode == kModeBiasFirstPacket)
{
for (WebRtc_UWord32 i = 0; i < numFecRemaining; i++)
{
WebRtc_UWord32 pktMaskIdx = i * numMaskBytes;
packetMask[pktMaskIdx] = packetMask[pktMaskIdx] | (1 << 7);
}
}
}
else
{
@ -207,8 +210,8 @@ void ResidualPacketProtection(WebRtc_UWord16 numMediaPackets,
}
// Higher protection for numImpPackets
void ImportantPacketProtection(WebRtc_UWord16 numFecPackets,
// Protection for important (first partition) packets
void ImportantPacketProtection(WebRtc_UWord16 numFecForImpPackets,
WebRtc_UWord16 numImpPackets,
WebRtc_UWord16 numMaskBytes,
WebRtc_UWord8* packetMask)
@ -217,72 +220,127 @@ void ImportantPacketProtection(WebRtc_UWord16 numFecPackets,
const WebRtc_UWord16 numImpMaskBytes =
(lBit == 1)? kMaskSizeLBitSet : kMaskSizeLBitClear;
WebRtc_UWord32 numFecForImpPackets = numImpPackets;
if (numFecPackets < numImpPackets)
{
numFecForImpPackets = numFecPackets;
}
// Get subMask1 from table
const WebRtc_UWord8* packetMaskSub1 =
packetMaskTbl[numImpPackets - 1][numFecForImpPackets - 1];
FitSubMask(numMaskBytes, numImpMaskBytes,
numFecForImpPackets,
packetMaskSub1,
packetMask);
numFecForImpPackets, packetMaskSub1, packetMask);
}
// Modification for UEP: reuse the tables (designed for equal protection).
// First version is to build mask from two sub-masks.
// Longer-term, may add another set of tables for UEP cases for more
// flexibility in protection between important and residual packets.
// This function sets the protection allocation: i.e., how many FEC packets
// to use for numImp (1st partition) packets, given the: number of media
// packets, number of FEC packets, and number of 1st partition packets.
WebRtc_UWord32 SetProtectionAllocation(const WebRtc_UWord16 numMediaPackets,
const WebRtc_UWord16 numFecPackets,
const WebRtc_UWord16 numImpPackets)
{
// UEP scheme:
// First subMask is for higher protection for important packets.
// Other subMask is the residual protection for remaining packets.
// TODO (marpan): test different cases for protection allocation:
// Use at most (allocPar * numFecPackets) for important packets.
float allocPar = 0.5;
WebRtc_UWord16 maxNumFecForImp = static_cast<WebRtc_UWord16>
(allocPar * numFecPackets);
WebRtc_UWord16 numFecForImpPackets = (numImpPackets < maxNumFecForImp) ?
numImpPackets : maxNumFecForImp;
// Fall back to equal protection in this case
if (numFecPackets == 1 && (numMediaPackets > 2 * numImpPackets))
{
numFecForImpPackets = 0;
}
return numFecForImpPackets;
}
// Modification for UEP: reuse the off-line tables for the packet masks.
// Note: these masks were designed for equal packet protection case,
// assuming random packet loss.
// Current version has 3 modes (options) to build UEP mask from existing ones.
// Various other combinations may be added in future versions.
// Longer-term, we may add another set of tables specifically for UEP cases.
// TODO (marpan): also consider modification of masks for bursty loss cases.
// Mask is characterized as (#packets_to_protect, #fec_for_protection).
// Protection defined as: (#fec_for_protection / #packets_to_protect).
// Protection factor defined as: (#fec_for_protection / #packets_to_protect).
// So if k = numMediaPackets, n=total#packets, (n-k)=numFecPackets,
// and m=numImpPackets, then we will have the following:
// Let k=numMediaPackets, n=total#packets, (n-k)=numFecPackets, m=numImpPackets.
// For important packets:
// subMask1 = (m, t): protection = m/(t), where t=min(m,n-k).
// For ProtectionMode 0 and 1:
// one mask (subMask1) is used for 1st partition packets,
// the other mask (subMask21/22, for 0/1) is for the remaining FEC packets.
// For the residual protection, we currently have two options:
// In both mode 0 and 1, the packets of 1st partition (numImpPackets) are
// treated equally important, and are afforded more protection than the
// residual partition packets.
// Mode 0: subMask21 = (k-m,n-k-m): protection = (n-k-m)/(k-m):
// no protection overlap between the two partitions.
// For numImpPackets:
// subMask1 = (m, t): protection = t/(m), where t=F(k,n-k,m).
// t=F(k,n-k,m) is the number of packets used to protect first partition in
// subMask1. This is determined from the function SetProtectionAllocation().
// Mode 1: subMask22 = (k, n-k-m), with protection (n-k-m)/(k):
// some protection overlap between the two partitions.
// For the left-over protection:
// Mode 0: subMask21 = (k-m,n-k-t): protection = (n-k-t)/(k-m)
// mode 0 has no protection overlap between the two partitions.
// For mode 0, we would typically set t = min(m, n-k).
// Mode 1: subMask22 = (k, n-k-t), with protection (n-k-t)/(k)
// mode 1 has protection overlap between the two partitions (preferred).
// For ProtectionMode 2:
// This gives 1st packet of list (which is 1st packet of 1st partition) more
// protection. In mode 2, the equal protection mask (which is obtained from
// mode 1 for t=0) is modified (more "1s" added in 1st column of packet mask)
// to bias higher protection for the 1st source packet.
// Protection Mode 2 may be extended for a sort of sliding protection
// (i.e., vary the number/density of "1s" across columns) across packets.
void UnequalProtectionMask(const WebRtc_UWord16 numMediaPackets,
const WebRtc_UWord16 numFecPackets,
const WebRtc_UWord16 numImpPackets,
const WebRtc_UWord16 numMaskBytes,
const ResidualProtectionMode mode,
WebRtc_UWord8* packetMask)
{
//
// Generate subMask1: higher protection for numImpPackets:
//
ImportantPacketProtection(numFecPackets, numImpPackets,
numMaskBytes, packetMask);
// Set Protection type and allocation
// TODO (marpan): test/update for best mode and some combinations thereof.
//
// Generate subMask2: left-over protection (for remaining partition data),
// if we still have some some FEC packets
//
if (numFecPackets > numImpPackets)
ProtectionMode mode = kModeOverlap;
WebRtc_UWord16 numFecForImpPackets = 0;
if (mode != kModeBiasFirstPacket)
{
numFecForImpPackets = SetProtectionAllocation(numMediaPackets,
numFecPackets,
numImpPackets);
}
ResidualPacketProtection(numMediaPackets,numFecPackets,
numImpPackets, numMaskBytes,
WebRtc_UWord16 numFecRemaining = numFecPackets - numFecForImpPackets;
// Done with setting protection type and allocation
//
// Generate subMask1
//
if (numFecForImpPackets > 0)
{
ImportantPacketProtection(numFecForImpPackets, numImpPackets,
numMaskBytes, packetMask);
}
//
// Generate subMask2
//
if (numFecRemaining > 0)
{
RemainingPacketProtection(numMediaPackets, numFecRemaining,
numFecForImpPackets, numMaskBytes,
mode, packetMask);
}
@ -304,15 +362,8 @@ void GeneratePacketMasks(int numMediaPackets,
const WebRtc_UWord16 numMaskBytes =
(lBit == 1)? kMaskSizeLBitSet : kMaskSizeLBitClear;
// Default: use overlap mode for residual protection.
const ResidualProtectionMode kResidualProtectionMode = kModeOverlap;
// Force equal-protection for these cases.
// Equal protection is also used for: (numImpPackets == 1 && numFecPackets == 1).
// UEP=off would generally be more efficient than the UEP=on for this case.
// TODO (marpan): check/test this condition.
if (!useUnequalProtection || numImpPackets == 0 ||
(numImpPackets == 1 && numFecPackets == 1))
// Equal-protection for these cases
if (!useUnequalProtection || numImpPackets == 0)
{
// Retrieve corresponding mask table directly:for equal-protection case.
// Mask = (k,n-k), with protection factor = (n-k)/k,
@ -323,8 +374,7 @@ void GeneratePacketMasks(int numMediaPackets,
else //UEP case
{
UnequalProtectionMask(numMediaPackets, numFecPackets, numImpPackets,
numMaskBytes, kResidualProtectionMode,
packetMask);
numMaskBytes, packetMask);
} // End of UEP modification