Default to always NACKing residual losses when having both FEC and NACK.
BUG= TEST= Review URL: http://webrtc-codereview.appspot.com/296002 git-svn-id: http://webrtc.googlecode.com/svn/trunk@1047 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
parent
4b80eb4fcd
commit
932ab18d32
@ -16,7 +16,6 @@
|
|||||||
#include "jitter_buffer.h"
|
#include "jitter_buffer.h"
|
||||||
#include "jitter_buffer_common.h"
|
#include "jitter_buffer_common.h"
|
||||||
#include "jitter_estimator.h"
|
#include "jitter_estimator.h"
|
||||||
#include "media_optimization.h" // hybrid NACK/FEC thresholds.
|
|
||||||
#include "packet.h"
|
#include "packet.h"
|
||||||
|
|
||||||
#include "event.h"
|
#include "event.h"
|
||||||
@ -86,6 +85,8 @@ VCMJitterBuffer::VCMJitterBuffer(WebRtc_Word32 vcmId, WebRtc_Word32 receiverId,
|
|||||||
_jitterEstimate(vcmId, receiverId),
|
_jitterEstimate(vcmId, receiverId),
|
||||||
_rttMs(0),
|
_rttMs(0),
|
||||||
_nackMode(kNoNack),
|
_nackMode(kNoNack),
|
||||||
|
_lowRttNackThresholdMs(-1),
|
||||||
|
_highRttNackThresholdMs(-1),
|
||||||
_NACKSeqNum(),
|
_NACKSeqNum(),
|
||||||
_NACKSeqNumLength(0),
|
_NACKSeqNumLength(0),
|
||||||
_waitingForKeyFrame(false),
|
_waitingForKeyFrame(false),
|
||||||
@ -870,8 +871,10 @@ VCMJitterBuffer::GetEstimatedJitterMsInternal()
|
|||||||
WebRtc_UWord32 estimate = VCMJitterEstimator::OPERATING_SYSTEM_JITTER;
|
WebRtc_UWord32 estimate = VCMJitterEstimator::OPERATING_SYSTEM_JITTER;
|
||||||
|
|
||||||
// Compute RTT multiplier for estimation
|
// Compute RTT multiplier for estimation
|
||||||
|
// _lowRttNackThresholdMs == -1 means no FEC.
|
||||||
double rttMult = 1.0f;
|
double rttMult = 1.0f;
|
||||||
if (_nackMode == kNackHybrid && _rttMs > kLowRttNackMs)
|
if (_nackMode == kNackHybrid && (_lowRttNackThresholdMs >= 0 &&
|
||||||
|
static_cast<int>(_rttMs) > _lowRttNackThresholdMs))
|
||||||
{
|
{
|
||||||
// from here we count on FEC
|
// from here we count on FEC
|
||||||
rttMult = 0.0f;
|
rttMult = 0.0f;
|
||||||
@ -1775,10 +1778,18 @@ VCMJitterBuffer::GetNackMode() const
|
|||||||
|
|
||||||
// Set NACK mode
|
// Set NACK mode
|
||||||
void
|
void
|
||||||
VCMJitterBuffer::SetNackMode(VCMNackMode mode)
|
VCMJitterBuffer::SetNackMode(VCMNackMode mode,
|
||||||
|
int lowRttNackThresholdMs,
|
||||||
|
int highRttNackThresholdMs)
|
||||||
{
|
{
|
||||||
CriticalSectionScoped cs(_critSect);
|
CriticalSectionScoped cs(_critSect);
|
||||||
_nackMode = mode;
|
_nackMode = mode;
|
||||||
|
assert(lowRttNackThresholdMs >= -1 && highRttNackThresholdMs >= -1);
|
||||||
|
assert(highRttNackThresholdMs == -1 ||
|
||||||
|
lowRttNackThresholdMs <= highRttNackThresholdMs);
|
||||||
|
assert(lowRttNackThresholdMs > -1 || highRttNackThresholdMs == -1);
|
||||||
|
_lowRttNackThresholdMs = lowRttNackThresholdMs;
|
||||||
|
_highRttNackThresholdMs = highRttNackThresholdMs;
|
||||||
if (_nackMode == kNoNack)
|
if (_nackMode == kNoNack)
|
||||||
{
|
{
|
||||||
_jitterEstimate.ResetNackCount();
|
_jitterEstimate.ResetNackCount();
|
||||||
@ -2037,7 +2048,8 @@ VCMJitterBuffer::WaitForNack()
|
|||||||
}
|
}
|
||||||
// else: hybrid mode, evaluate
|
// else: hybrid mode, evaluate
|
||||||
// RTT high, don't wait
|
// RTT high, don't wait
|
||||||
if (_rttMs >= kHighRttNackMs)
|
if (_highRttNackThresholdMs >= 0 &&
|
||||||
|
_rttMs >= static_cast<unsigned int>(_highRttNackThresholdMs))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -2045,5 +2057,4 @@ VCMJitterBuffer::WaitForNack()
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} // namespace webrtc
|
||||||
}
|
|
||||||
|
@ -121,7 +121,15 @@ public:
|
|||||||
void UpdateRtt(WebRtc_UWord32 rttMs);
|
void UpdateRtt(WebRtc_UWord32 rttMs);
|
||||||
|
|
||||||
// NACK
|
// NACK
|
||||||
void SetNackMode(VCMNackMode mode); // Enable/disable nack
|
// Set the NACK mode. "highRttNackThreshold" is an RTT threshold in ms above
|
||||||
|
// which NACK will be disabled if the NACK mode is "kNackHybrid",
|
||||||
|
// -1 meaning that NACK is always enabled in the Hybrid mode.
|
||||||
|
// "lowRttNackThreshold" is an RTT threshold in ms below which we expect to
|
||||||
|
// rely on NACK only, and therefore are using larger buffers to have time to
|
||||||
|
// wait for retransmissions.
|
||||||
|
void SetNackMode(VCMNackMode mode,
|
||||||
|
int lowRttNackThresholdMs,
|
||||||
|
int highRttNackThresholdMs);
|
||||||
VCMNackMode GetNackMode() const; // Get nack mode
|
VCMNackMode GetNackMode() const; // Get nack mode
|
||||||
// Get list of missing sequence numbers (size in number of elements)
|
// Get list of missing sequence numbers (size in number of elements)
|
||||||
WebRtc_UWord16* GetNackList(WebRtc_UWord16& nackSize,
|
WebRtc_UWord16* GetNackList(WebRtc_UWord16& nackSize,
|
||||||
@ -236,6 +244,8 @@ private:
|
|||||||
|
|
||||||
// NACK
|
// NACK
|
||||||
VCMNackMode _nackMode;
|
VCMNackMode _nackMode;
|
||||||
|
int _lowRttNackThresholdMs;
|
||||||
|
int _highRttNackThresholdMs;
|
||||||
// Holds the internal nack list (the missing sequence numbers)
|
// Holds the internal nack list (the missing sequence numbers)
|
||||||
WebRtc_Word32 _NACKSeqNumInternal[kNackHistoryLength];
|
WebRtc_Word32 _NACKSeqNumInternal[kNackHistoryLength];
|
||||||
WebRtc_UWord16 _NACKSeqNum[kNackHistoryLength];
|
WebRtc_UWord16 _NACKSeqNum[kNackHistoryLength];
|
||||||
|
@ -49,10 +49,16 @@ VCMProtectionMethod::UpdateContentMetrics(const
|
|||||||
_qmRobustness->UpdateContent(contentMetrics);
|
_qmRobustness->UpdateContent(contentMetrics);
|
||||||
}
|
}
|
||||||
|
|
||||||
VCMNackFecMethod::VCMNackFecMethod():
|
VCMNackFecMethod::VCMNackFecMethod(int lowRttNackThresholdMs,
|
||||||
VCMFecMethod()
|
int highRttNackThresholdMs)
|
||||||
{
|
: VCMFecMethod(),
|
||||||
_type = kNackFec;
|
_lowRttNackMs(lowRttNackThresholdMs),
|
||||||
|
_highRttNackMs(highRttNackThresholdMs) {
|
||||||
|
assert(lowRttNackThresholdMs >= -1 && highRttNackThresholdMs >= -1);
|
||||||
|
assert(highRttNackThresholdMs == -1 ||
|
||||||
|
lowRttNackThresholdMs <= highRttNackThresholdMs);
|
||||||
|
assert(lowRttNackThresholdMs > -1 || highRttNackThresholdMs == -1);
|
||||||
|
_type = kNackFec;
|
||||||
}
|
}
|
||||||
|
|
||||||
VCMNackFecMethod::~VCMNackFecMethod()
|
VCMNackFecMethod::~VCMNackFecMethod()
|
||||||
@ -60,13 +66,13 @@ VCMNackFecMethod::~VCMNackFecMethod()
|
|||||||
//
|
//
|
||||||
}
|
}
|
||||||
bool
|
bool
|
||||||
VCMNackFecMethod::ProtectionFactor(const
|
VCMNackFecMethod::ProtectionFactor(const VCMProtectionParameters* parameters)
|
||||||
VCMProtectionParameters* parameters)
|
|
||||||
{
|
{
|
||||||
// Hybrid Nack FEC has three operational modes:
|
// Hybrid Nack FEC has three operational modes:
|
||||||
// 1. Low RTT (below kLowRttNackMs) - Nack only: Set FEC rate
|
// 1. Low RTT (below kLowRttNackMs) - Nack only: Set FEC rate
|
||||||
// (_protectionFactorD) to zero.
|
// (_protectionFactorD) to zero. -1 means no FEC.
|
||||||
// 2. High RTT (above kHighRttNackMs) - FEC Only: Keep FEC factors.
|
// 2. High RTT (above _highRttNackMs) - FEC Only: Keep FEC factors.
|
||||||
|
// -1 means always allow NACK.
|
||||||
// 3. Medium RTT values - Hybrid mode: We will only nack the
|
// 3. Medium RTT values - Hybrid mode: We will only nack the
|
||||||
// residual following the decoding of the FEC (refer to JB logic). FEC
|
// residual following the decoding of the FEC (refer to JB logic). FEC
|
||||||
// delta protection factor will be adjusted based on the RTT.
|
// delta protection factor will be adjusted based on the RTT.
|
||||||
@ -76,7 +82,7 @@ VCMNackFecMethod::ProtectionFactor(const
|
|||||||
|
|
||||||
// Compute the protection factors
|
// Compute the protection factors
|
||||||
VCMFecMethod::ProtectionFactor(parameters);
|
VCMFecMethod::ProtectionFactor(parameters);
|
||||||
if (parameters->rtt < kLowRttNackMs)
|
if (_lowRttNackMs == -1 || parameters->rtt < _lowRttNackMs)
|
||||||
{
|
{
|
||||||
_protectionFactorD = 0;
|
_protectionFactorD = 0;
|
||||||
VCMFecMethod::UpdateProtectionFactorD(_protectionFactorD);
|
VCMFecMethod::UpdateProtectionFactorD(_protectionFactorD);
|
||||||
@ -84,7 +90,7 @@ VCMNackFecMethod::ProtectionFactor(const
|
|||||||
|
|
||||||
// When in Hybrid mode (RTT range), adjust FEC rates based on the
|
// When in Hybrid mode (RTT range), adjust FEC rates based on the
|
||||||
// RTT (NACK effectiveness) - adjustment factor is in the range [0,1].
|
// RTT (NACK effectiveness) - adjustment factor is in the range [0,1].
|
||||||
else if (parameters->rtt < kHighRttNackMs)
|
else if (_highRttNackMs == -1 || parameters->rtt < _highRttNackMs)
|
||||||
{
|
{
|
||||||
// TODO(mikhal): Disabling adjustment temporarily.
|
// TODO(mikhal): Disabling adjustment temporarily.
|
||||||
// WebRtc_UWord16 rttIndex = (WebRtc_UWord16) parameters->rtt;
|
// WebRtc_UWord16 rttIndex = (WebRtc_UWord16) parameters->rtt;
|
||||||
@ -103,8 +109,7 @@ VCMNackFecMethod::ProtectionFactor(const
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
VCMNackFecMethod::EffectivePacketLoss(const
|
VCMNackFecMethod::EffectivePacketLoss(const VCMProtectionParameters* parameters)
|
||||||
VCMProtectionParameters* parameters)
|
|
||||||
{
|
{
|
||||||
// Set the effective packet loss for encoder (based on FEC code).
|
// Set the effective packet loss for encoder (based on FEC code).
|
||||||
// Compute the effective packet loss and residual packet loss due to FEC.
|
// Compute the effective packet loss and residual packet loss due to FEC.
|
||||||
@ -125,7 +130,7 @@ VCMNackFecMethod::UpdateParameters(const VCMProtectionParameters* parameters)
|
|||||||
_efficiency = parameters->bitRate * fecRate * _corrFecCost;
|
_efficiency = parameters->bitRate * fecRate * _corrFecCost;
|
||||||
|
|
||||||
// Add NACK cost, when applicable
|
// Add NACK cost, when applicable
|
||||||
if (parameters->rtt < kHighRttNackMs)
|
if (_highRttNackMs == -1 || parameters->rtt < _highRttNackMs)
|
||||||
{
|
{
|
||||||
// nackCost = (bitRate - nackCost) * (lossPr)
|
// nackCost = (bitRate - nackCost) * (lossPr)
|
||||||
_efficiency += parameters->bitRate * _residualPacketLossFec /
|
_efficiency += parameters->bitRate * _residualPacketLossFec /
|
||||||
@ -603,7 +608,8 @@ VCMLossProtectionLogic::SetMethod(enum VCMProtectionMethodEnum newMethodType)
|
|||||||
}
|
}
|
||||||
case kNackFec:
|
case kNackFec:
|
||||||
{
|
{
|
||||||
newMethod = new VCMNackFecMethod();
|
// Default to always having NACK enabled for the hybrid mode.
|
||||||
|
newMethod = new VCMNackFecMethod(kLowRttNackMs, -1);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
|
@ -49,7 +49,7 @@ struct VCMProtectionParameters
|
|||||||
residualPacketLossFec(0.0f), codecWidth(0), codecHeight(0)
|
residualPacketLossFec(0.0f), codecWidth(0), codecHeight(0)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
WebRtc_UWord32 rtt;
|
int rtt;
|
||||||
float lossPr;
|
float lossPr;
|
||||||
float bitRate;
|
float bitRate;
|
||||||
float packetsPerFrame;
|
float packetsPerFrame;
|
||||||
@ -195,13 +195,18 @@ public:
|
|||||||
class VCMNackFecMethod : public VCMFecMethod
|
class VCMNackFecMethod : public VCMFecMethod
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
VCMNackFecMethod();
|
VCMNackFecMethod(int lowRttNackThresholdMs,
|
||||||
|
int highRttNackThresholdMs);
|
||||||
virtual ~VCMNackFecMethod();
|
virtual ~VCMNackFecMethod();
|
||||||
virtual bool UpdateParameters(const VCMProtectionParameters* parameters);
|
virtual bool UpdateParameters(const VCMProtectionParameters* parameters);
|
||||||
// Get the effective packet loss for ER
|
// Get the effective packet loss for ER
|
||||||
bool EffectivePacketLoss(const VCMProtectionParameters* parameters);
|
bool EffectivePacketLoss(const VCMProtectionParameters* parameters);
|
||||||
// Get the protection factors
|
// Get the protection factors
|
||||||
bool ProtectionFactor(const VCMProtectionParameters* parameters);
|
bool ProtectionFactor(const VCMProtectionParameters* parameters);
|
||||||
|
|
||||||
|
private:
|
||||||
|
int _lowRttNackMs;
|
||||||
|
int _highRttNackMs;
|
||||||
};
|
};
|
||||||
|
|
||||||
class VCMLossProtectionLogic
|
class VCMLossProtectionLogic
|
||||||
|
@ -8,12 +8,14 @@
|
|||||||
* be found in the AUTHORS file in the root of the source tree.
|
* be found in the AUTHORS file in the root of the source tree.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "video_coding.h"
|
#include "receiver.h"
|
||||||
#include "trace.h"
|
|
||||||
#include "encoded_frame.h"
|
#include "encoded_frame.h"
|
||||||
#include "internal_defines.h"
|
#include "internal_defines.h"
|
||||||
#include "receiver.h"
|
#include "media_opt_util.h"
|
||||||
#include "tick_time.h"
|
#include "tick_time.h"
|
||||||
|
#include "trace.h"
|
||||||
|
#include "video_coding.h"
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
|
||||||
@ -373,7 +375,8 @@ void
|
|||||||
VCMReceiver::SetNackMode(VCMNackMode nackMode)
|
VCMReceiver::SetNackMode(VCMNackMode nackMode)
|
||||||
{
|
{
|
||||||
CriticalSectionScoped cs(_critSect);
|
CriticalSectionScoped cs(_critSect);
|
||||||
_jitterBuffer.SetNackMode(nackMode);
|
// Default to always having NACK enabled in hybrid mode.
|
||||||
|
_jitterBuffer.SetNackMode(nackMode, kLowRttNackMs, -1);
|
||||||
if (!_master)
|
if (!_master)
|
||||||
{
|
{
|
||||||
_state = kPassive; // The dual decoder defaults to passive
|
_state = kPassive; // The dual decoder defaults to passive
|
||||||
|
@ -8,20 +8,22 @@
|
|||||||
* be found in the AUTHORS file in the root of the source tree.
|
* be found in the AUTHORS file in the root of the source tree.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "common_types.h"
|
|
||||||
#include "jitter_buffer.h"
|
|
||||||
#include "jitter_estimator.h"
|
|
||||||
#include "inter_frame_delay.h"
|
|
||||||
#include "packet.h"
|
|
||||||
#include "tick_time.h"
|
|
||||||
#include "../source/event.h"
|
|
||||||
#include "frame_buffer.h"
|
|
||||||
#include "jitter_estimate_test.h"
|
|
||||||
#include "test_util.h"
|
|
||||||
#include "test_macros.h"
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
|
||||||
|
#include "common_types.h"
|
||||||
|
#include "../source/event.h"
|
||||||
|
#include "frame_buffer.h"
|
||||||
|
#include "inter_frame_delay.h"
|
||||||
|
#include "jitter_buffer.h"
|
||||||
|
#include "jitter_estimate_test.h"
|
||||||
|
#include "jitter_estimator.h"
|
||||||
|
#include "media_opt_util.h"
|
||||||
|
#include "packet.h"
|
||||||
|
#include "test_util.h"
|
||||||
|
#include "test_macros.h"
|
||||||
|
#include "tick_time.h"
|
||||||
|
|
||||||
using namespace webrtc;
|
using namespace webrtc;
|
||||||
|
|
||||||
int CheckOutFrame(VCMEncodedFrame* frameOut, unsigned int size, bool startCode)
|
int CheckOutFrame(VCMEncodedFrame* frameOut, unsigned int size, bool startCode)
|
||||||
@ -1568,7 +1570,7 @@ int JitterBufferTest(CmdArgs& args)
|
|||||||
// ---------------------------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------------------------
|
||||||
// | 3 | 4 | 5 | 6 | 7 | 9 | x | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | x | 21 |.....| 102 |
|
// | 3 | 4 | 5 | 6 | 7 | 9 | x | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | x | 21 |.....| 102 |
|
||||||
// ---------------------------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------------------------
|
||||||
jb.SetNackMode(kNackInfinite);
|
jb.SetNackMode(kNackInfinite, -1, -1);
|
||||||
|
|
||||||
TEST(jb.GetNackMode() == kNackInfinite);
|
TEST(jb.GetNackMode() == kNackInfinite);
|
||||||
|
|
||||||
@ -2039,7 +2041,7 @@ int JitterBufferTest(CmdArgs& args)
|
|||||||
|
|
||||||
// testing that empty packets do not clog the jitter buffer
|
// testing that empty packets do not clog the jitter buffer
|
||||||
// Set hybrid mode
|
// Set hybrid mode
|
||||||
jb.SetNackMode(kNackHybrid);
|
jb.SetNackMode(kNackHybrid, kLowRttNackMs, -1);
|
||||||
TEST(jb.GetNackMode() == kNackHybrid);
|
TEST(jb.GetNackMode() == kNackHybrid);
|
||||||
|
|
||||||
int maxSize = 100;
|
int maxSize = 100;
|
||||||
@ -2067,7 +2069,7 @@ int JitterBufferTest(CmdArgs& args)
|
|||||||
testFrame = jb.GetFrame(packet);
|
testFrame = jb.GetFrame(packet);
|
||||||
TEST(frameIn != 0);
|
TEST(frameIn != 0);
|
||||||
|
|
||||||
jb.SetNackMode(kNoNack);
|
jb.SetNackMode(kNoNack, -1, -1);
|
||||||
jb.Flush();
|
jb.Flush();
|
||||||
|
|
||||||
// Testing that 1 empty packet inserted last will not be set for decoding
|
// Testing that 1 empty packet inserted last will not be set for decoding
|
||||||
@ -2103,7 +2105,7 @@ int JitterBufferTest(CmdArgs& args)
|
|||||||
// Test incomplete NALU frames
|
// Test incomplete NALU frames
|
||||||
|
|
||||||
jb.Flush();
|
jb.Flush();
|
||||||
jb.SetNackMode(kNoNack);
|
jb.SetNackMode(kNoNack, -1, -1);
|
||||||
seqNum ++;
|
seqNum ++;
|
||||||
timeStamp += 33*90;
|
timeStamp += 33*90;
|
||||||
int insertedLength=0;
|
int insertedLength=0;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user