Review URL: http://webrtc-codereview.appspot.com/23013
git-svn-id: http://webrtc.googlecode.com/svn/trunk@75 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
@@ -171,7 +171,7 @@ public:
|
|||||||
unsigned int name, const char* data,
|
unsigned int name, const char* data,
|
||||||
unsigned short dataLengthInBytes) = 0;
|
unsigned short dataLengthInBytes) = 0;
|
||||||
|
|
||||||
// This function enables Negative Acknowledgement (NACK) using RTCP,
|
// This function enables Negative Acknowledgment (NACK) using RTCP,
|
||||||
// implemented based on RFC 4585. NACK retransmits RTP packets if lost on
|
// implemented based on RFC 4585. NACK retransmits RTP packets if lost on
|
||||||
// the network. This creates a lossless transport at the expense of delay.
|
// the network. This creates a lossless transport at the expense of delay.
|
||||||
// If using NACK, NACK should be enabled on both endpoints in a call.
|
// If using NACK, NACK should be enabled on both endpoints in a call.
|
||||||
@@ -185,6 +185,19 @@ public:
|
|||||||
const unsigned char payloadTypeRED,
|
const unsigned char payloadTypeRED,
|
||||||
const unsigned char payloadTypeFEC) = 0;
|
const unsigned char payloadTypeFEC) = 0;
|
||||||
|
|
||||||
|
// This function enables hybrid Negative Acknowledgment using RTCP
|
||||||
|
// and Forward Error Correction (FEC) implemented based on RFC 5109,
|
||||||
|
// to improve packet loss robustness. Extra
|
||||||
|
// FEC packets are sent together with the usual media packets, hence will
|
||||||
|
// part of the bitrate be used for FEC packets.
|
||||||
|
// The hybrid mode will choose between nack only, fec only and both based on
|
||||||
|
// network conditions. When both are applied, only packets that were not
|
||||||
|
// recovered by the FEC will be nacked.
|
||||||
|
virtual int SetHybridNACKFECStatus(const int videoChannel,
|
||||||
|
const bool enable,
|
||||||
|
const unsigned char payloadTypeRED,
|
||||||
|
const unsigned char payloadTypeFEC) = 0;
|
||||||
|
|
||||||
// This function enables RTCP key frame requests.
|
// This function enables RTCP key frame requests.
|
||||||
virtual int SetKeyFrameRequestMethod(
|
virtual int SetKeyFrameRequestMethod(
|
||||||
const int videoChannel, const ViEKeyFrameRequestMethod method) = 0;
|
const int videoChannel, const ViEKeyFrameRequestMethod method) = 0;
|
||||||
|
|||||||
@@ -419,7 +419,7 @@ WebRtc_Word32 ViEChannel::RegisterCodecObserver(ViEDecoderObserver* observer)
|
|||||||
if (_codecObserver)
|
if (_codecObserver)
|
||||||
{
|
{
|
||||||
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo,
|
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo,
|
||||||
ViEId(_engineId, _channelId), "%s: alread added",
|
ViEId(_engineId, _channelId), "%s: already added",
|
||||||
__FUNCTION__);
|
__FUNCTION__);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@@ -615,23 +615,44 @@ WebRtc_Word32 ViEChannel::GetRTCPMode(RTCPMethod& rtcpMode)
|
|||||||
|
|
||||||
WebRtc_Word32 ViEChannel::SetNACKStatus(const bool enable)
|
WebRtc_Word32 ViEChannel::SetNACKStatus(const bool enable)
|
||||||
{
|
{
|
||||||
WEBRTC_TRACE(webrtc::kTraceInfo, webrtc::kTraceVideo, ViEId(_engineId, _channelId),
|
WEBRTC_TRACE(webrtc::kTraceInfo, webrtc::kTraceVideo,
|
||||||
"%s(enable: %d)", __FUNCTION__, enable);
|
ViEId(_engineId, _channelId),
|
||||||
|
"%s(enable: %d)", __FUNCTION__, enable);
|
||||||
|
|
||||||
// Update the decoding VCM
|
// Update the decoding VCM
|
||||||
if (_vcm.SetVideoProtection(kProtectionNack, enable) != VCM_OK)
|
if (_vcm.SetVideoProtection(kProtectionNack, enable) != VCM_OK)
|
||||||
{
|
{
|
||||||
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo,
|
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo,
|
||||||
ViEId(_engineId, _channelId),
|
ViEId(_engineId, _channelId),
|
||||||
"%s: Could not set VCM NACK protection: %d", __FUNCTION__,
|
"%s: Could not set VCM NACK protection: %d", __FUNCTION__,
|
||||||
enable);
|
enable);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if (enable)
|
if (enable)
|
||||||
{
|
{
|
||||||
// Disable possible FEC
|
// Disable possible FEC
|
||||||
SetFECStatus(false, 0, 0);
|
SetFECStatus(false, 0, 0);
|
||||||
|
}
|
||||||
|
// Update the decoding VCM
|
||||||
|
if (_vcm.SetVideoProtection(kProtectionNack, enable) != VCM_OK)
|
||||||
|
{
|
||||||
|
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo,
|
||||||
|
ViEId(_engineId, _channelId),
|
||||||
|
"%s: Could not set VCM NACK protection: %d", __FUNCTION__,
|
||||||
|
enable);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return ProcessNACKRequest(enable);
|
||||||
|
}
|
||||||
|
|
||||||
|
WebRtc_Word32 ViEChannel::ProcessNACKRequest(const bool enable)
|
||||||
|
{
|
||||||
|
WEBRTC_TRACE(webrtc::kTraceInfo, webrtc::kTraceVideo,
|
||||||
|
ViEId(_engineId, _channelId),
|
||||||
|
"%s(enable: %d)", __FUNCTION__, enable);
|
||||||
|
|
||||||
|
if (enable)
|
||||||
|
{
|
||||||
// Turn on NACK,
|
// Turn on NACK,
|
||||||
NACKMethod nackMethod = kNackRtcp;
|
NACKMethod nackMethod = kNackRtcp;
|
||||||
if (_rtpRtcp.RTCP() == kRtcpOff)
|
if (_rtpRtcp.RTCP() == kRtcpOff)
|
||||||
@@ -649,8 +670,9 @@ WebRtc_Word32 ViEChannel::SetNACKStatus(const bool enable)
|
|||||||
nackMethod);
|
nackMethod);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
WEBRTC_TRACE(webrtc::kTraceInfo, webrtc::kTraceVideo, ViEId(_engineId, _channelId),
|
WEBRTC_TRACE(webrtc::kTraceInfo, webrtc::kTraceVideo,
|
||||||
"%s: Using NACK method %d", __FUNCTION__, nackMethod);
|
ViEId(_engineId, _channelId),
|
||||||
|
"%s: Using NACK method %d", __FUNCTION__, nackMethod);
|
||||||
_rtpRtcp.SetStorePacketsStatus(true, kNackHistorySize);
|
_rtpRtcp.SetStorePacketsStatus(true, kNackHistorySize);
|
||||||
_vcm.RegisterPacketRequestCallback(this);
|
_vcm.RegisterPacketRequestCallback(this);
|
||||||
}
|
}
|
||||||
@@ -677,16 +699,25 @@ WebRtc_Word32 ViEChannel::SetFECStatus(const bool enable,
|
|||||||
const unsigned char payloadTypeRED,
|
const unsigned char payloadTypeRED,
|
||||||
const unsigned char payloadTypeFEC)
|
const unsigned char payloadTypeFEC)
|
||||||
{
|
{
|
||||||
WEBRTC_TRACE(webrtc::kTraceApiCall, webrtc::kTraceVideo, ViEId(_engineId, _channelId),
|
|
||||||
"%s(enable: %d, payloadTypeRED: %u, payloadTypeFEC: %u)",
|
|
||||||
__FUNCTION__, enable, payloadTypeRED, payloadTypeFEC);
|
|
||||||
|
|
||||||
// Disable possible NACK
|
// Disable possible NACK
|
||||||
if (enable)
|
if (enable)
|
||||||
{
|
{
|
||||||
SetNACKStatus(false);
|
SetNACKStatus(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return ProcessFECRequest(enable, payloadTypeRED, payloadTypeFEC);
|
||||||
|
|
||||||
|
}
|
||||||
|
WebRtc_Word32
|
||||||
|
ViEChannel::ProcessFECRequest(const bool enable,
|
||||||
|
const unsigned char payloadTypeRED,
|
||||||
|
const unsigned char payloadTypeFEC)
|
||||||
|
{
|
||||||
|
WEBRTC_TRACE(webrtc::kTraceApiCall, webrtc::kTraceVideo,
|
||||||
|
ViEId(_engineId, _channelId),
|
||||||
|
"%s(enable: %d, payloadTypeRED: %u, payloadTypeFEC: %u)",
|
||||||
|
__FUNCTION__, enable, payloadTypeRED, payloadTypeFEC);
|
||||||
|
|
||||||
if (_rtpRtcp.SetGenericFECStatus(enable, payloadTypeRED, payloadTypeFEC)
|
if (_rtpRtcp.SetGenericFECStatus(enable, payloadTypeRED, payloadTypeFEC)
|
||||||
!= 0)
|
!= 0)
|
||||||
{
|
{
|
||||||
@@ -700,6 +731,34 @@ WebRtc_Word32 ViEChannel::SetFECStatus(const bool enable,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
// EnableNACKFECStatus
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
WebRtc_Word32
|
||||||
|
ViEChannel::SetHybridNACKFECStatus(const bool enable,
|
||||||
|
const unsigned char payloadTypeRED,
|
||||||
|
const unsigned char payloadTypeFEC)
|
||||||
|
{
|
||||||
|
// Update the decoding VCM with hybrid mode
|
||||||
|
if (_vcm.SetVideoProtection(kProtectionNackFEC, enable) != VCM_OK)
|
||||||
|
{
|
||||||
|
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo,
|
||||||
|
ViEId(_engineId, _channelId),
|
||||||
|
"%s: Could not set VCM NACK protection: %d", __FUNCTION__,
|
||||||
|
enable);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
WebRtc_Word32 retVal = 0;
|
||||||
|
retVal = ProcessNACKRequest(enable);
|
||||||
|
if (retVal < 0)
|
||||||
|
{
|
||||||
|
return retVal;
|
||||||
|
}
|
||||||
|
return ProcessFECRequest(enable, payloadTypeRED, payloadTypeFEC);
|
||||||
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
// KeyFrameRequestMethod
|
// KeyFrameRequestMethod
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
|||||||
@@ -111,6 +111,9 @@ public:
|
|||||||
WebRtc_Word32 SetFECStatus(const bool enable,
|
WebRtc_Word32 SetFECStatus(const bool enable,
|
||||||
const unsigned char payloadTypeRED,
|
const unsigned char payloadTypeRED,
|
||||||
const unsigned char payloadTypeFEC);
|
const unsigned char payloadTypeFEC);
|
||||||
|
WebRtc_Word32 SetHybridNACKFECStatus(const bool enable,
|
||||||
|
const unsigned char payloadTypeRED,
|
||||||
|
const unsigned char payloadTypeFEC);
|
||||||
|
|
||||||
WebRtc_Word32
|
WebRtc_Word32
|
||||||
SetKeyFrameRequestMethod(const KeyFrameRequestMethod method);
|
SetKeyFrameRequestMethod(const KeyFrameRequestMethod method);
|
||||||
@@ -410,6 +413,13 @@ private:
|
|||||||
WebRtc_Word32 StartDecodeThread();
|
WebRtc_Word32 StartDecodeThread();
|
||||||
WebRtc_Word32 StopDecodeThread();
|
WebRtc_Word32 StopDecodeThread();
|
||||||
|
|
||||||
|
// Protection
|
||||||
|
WebRtc_Word32 ProcessNACKRequest(const bool enable);
|
||||||
|
|
||||||
|
WebRtc_Word32 ProcessFECRequest(const bool enable,
|
||||||
|
const unsigned char payloadTypeRED,
|
||||||
|
const unsigned char payloadTypeFEC);
|
||||||
|
|
||||||
// General members
|
// General members
|
||||||
WebRtc_Word32 _channelId;
|
WebRtc_Word32 _channelId;
|
||||||
WebRtc_Word32 _engineId;
|
WebRtc_Word32 _engineId;
|
||||||
|
|||||||
@@ -40,8 +40,10 @@ ViEEncoder::ViEEncoder(WebRtc_Word32 engineId, WebRtc_Word32 channelId,
|
|||||||
_engineId(engineId),
|
_engineId(engineId),
|
||||||
_channelId(channelId),
|
_channelId(channelId),
|
||||||
_numberOfCores(numberOfCores),
|
_numberOfCores(numberOfCores),
|
||||||
_vcm(*webrtc::VideoCodingModule::Create(ViEModuleId(engineId, channelId))),
|
_vcm(*webrtc::VideoCodingModule::Create(ViEModuleId(engineId,
|
||||||
_vpm(*webrtc::VideoProcessingModule::Create(ViEModuleId(engineId, channelId))),
|
channelId))),
|
||||||
|
_vpm(*webrtc::VideoProcessingModule::Create(ViEModuleId(engineId,
|
||||||
|
channelId))),
|
||||||
_rtpRtcp(*RtpRtcp::CreateRtpRtcp(ViEModuleId(engineId,
|
_rtpRtcp(*RtpRtcp::CreateRtpRtcp(ViEModuleId(engineId,
|
||||||
channelId),
|
channelId),
|
||||||
false)),
|
false)),
|
||||||
@@ -49,14 +51,15 @@ ViEEncoder::ViEEncoder(WebRtc_Word32 engineId, WebRtc_Word32 channelId,
|
|||||||
_dataCritsect(*CriticalSectionWrapper::CreateCriticalSection()),
|
_dataCritsect(*CriticalSectionWrapper::CreateCriticalSection()),
|
||||||
_paused(false), _timeLastIntraRequestMs(0),
|
_paused(false), _timeLastIntraRequestMs(0),
|
||||||
_channelsDroppingDeltaFrames(0), _dropNextFrame(false),
|
_channelsDroppingDeltaFrames(0), _dropNextFrame(false),
|
||||||
_fecEnabled(false), _codecObserver(NULL), _effectFilter(NULL),
|
_fecEnabled(false), _nackEnabled(false), _codecObserver(NULL),
|
||||||
_moduleProcessThread(moduleProcessThread), _hasReceivedSLI(false),
|
_effectFilter(NULL), _moduleProcessThread(moduleProcessThread),
|
||||||
_pictureIdSLI(0), _hasReceivedRPSI(false), _pictureIdRPSI(0),
|
_hasReceivedSLI(false), _pictureIdSLI(0), _hasReceivedRPSI(false),
|
||||||
_fileRecorder(channelId)
|
_pictureIdRPSI(0), _fileRecorder(channelId)
|
||||||
{
|
{
|
||||||
WEBRTC_TRACE(webrtc::kTraceMemory, webrtc::kTraceVideo, ViEId(engineId, channelId),
|
WEBRTC_TRACE(webrtc::kTraceMemory, webrtc::kTraceVideo,
|
||||||
"%s(engineId: %d) 0x%p - Constructor", __FUNCTION__, engineId,
|
ViEId(engineId, channelId),
|
||||||
this);
|
"%s(engineId: %d) 0x%p - Constructor", __FUNCTION__, engineId,
|
||||||
|
this);
|
||||||
|
|
||||||
_vcm.InitializeSender();
|
_vcm.InitializeSender();
|
||||||
_vpm.EnableTemporalDecimation(true);
|
_vpm.EnableTemporalDecimation(true);
|
||||||
@@ -80,7 +83,8 @@ ViEEncoder::ViEEncoder(WebRtc_Word32 engineId, WebRtc_Word32 channelId,
|
|||||||
VideoCodec videoCodec;
|
VideoCodec videoCodec;
|
||||||
if (_vcm.Codec(webrtc::kVideoCodecVP8, &videoCodec) == VCM_OK)
|
if (_vcm.Codec(webrtc::kVideoCodecVP8, &videoCodec) == VCM_OK)
|
||||||
{
|
{
|
||||||
_vcm.RegisterSendCodec(&videoCodec, _numberOfCores, _rtpRtcp.MaxDataPayloadLength());
|
_vcm.RegisterSendCodec(&videoCodec, _numberOfCores,
|
||||||
|
_rtpRtcp.MaxDataPayloadLength());
|
||||||
_rtpRtcp.RegisterSendPayload(videoCodec.plName, videoCodec.plType);
|
_rtpRtcp.RegisterSendPayload(videoCodec.plName, videoCodec.plType);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -91,7 +95,8 @@ ViEEncoder::ViEEncoder(WebRtc_Word32 engineId, WebRtc_Word32 channelId,
|
|||||||
VideoCodec videoCodec;
|
VideoCodec videoCodec;
|
||||||
if (_vcm.Codec(webrtc::kVideoCodecI420, &videoCodec) == VCM_OK)
|
if (_vcm.Codec(webrtc::kVideoCodecI420, &videoCodec) == VCM_OK)
|
||||||
{
|
{
|
||||||
_vcm.RegisterSendCodec(&videoCodec, _numberOfCores, _rtpRtcp.MaxDataPayloadLength());
|
_vcm.RegisterSendCodec(&videoCodec, _numberOfCores,
|
||||||
|
_rtpRtcp.MaxDataPayloadLength());
|
||||||
_rtpRtcp.RegisterSendPayload(videoCodec.plName, videoCodec.plType);
|
_rtpRtcp.RegisterSendPayload(videoCodec.plName, videoCodec.plType);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -127,8 +132,9 @@ ViEEncoder::ViEEncoder(WebRtc_Word32 engineId, WebRtc_Word32 channelId,
|
|||||||
|
|
||||||
ViEEncoder::~ViEEncoder()
|
ViEEncoder::~ViEEncoder()
|
||||||
{
|
{
|
||||||
WEBRTC_TRACE(webrtc::kTraceMemory, webrtc::kTraceVideo, ViEId(_engineId, _channelId),
|
WEBRTC_TRACE(webrtc::kTraceMemory, webrtc::kTraceVideo,
|
||||||
"ViEEncoder Destructor 0x%p, engineId: %d", this, _engineId);
|
ViEId(_engineId, _channelId),
|
||||||
|
"ViEEncoder Destructor 0x%p, engineId: %d", this, _engineId);
|
||||||
|
|
||||||
if (_rtpRtcp.NumberChildModules() > 0)
|
if (_rtpRtcp.NumberChildModules() > 0)
|
||||||
{
|
{
|
||||||
@@ -161,16 +167,18 @@ ViEEncoder::~ViEEncoder()
|
|||||||
|
|
||||||
void ViEEncoder::Pause()
|
void ViEEncoder::Pause()
|
||||||
{
|
{
|
||||||
WEBRTC_TRACE(webrtc::kTraceInfo, webrtc::kTraceVideo, ViEId(_engineId, _channelId),
|
WEBRTC_TRACE(webrtc::kTraceInfo, webrtc::kTraceVideo,
|
||||||
"%s", __FUNCTION__);
|
ViEId(_engineId, _channelId),
|
||||||
|
"%s", __FUNCTION__);
|
||||||
CriticalSectionScoped cs(_dataCritsect);
|
CriticalSectionScoped cs(_dataCritsect);
|
||||||
_paused = true;
|
_paused = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ViEEncoder::Restart()
|
void ViEEncoder::Restart()
|
||||||
{
|
{
|
||||||
WEBRTC_TRACE(webrtc::kTraceInfo, webrtc::kTraceVideo, ViEId(_engineId, _channelId),
|
WEBRTC_TRACE(webrtc::kTraceInfo, webrtc::kTraceVideo,
|
||||||
"%s", __FUNCTION__);
|
ViEId(_engineId, _channelId),
|
||||||
|
"%s", __FUNCTION__);
|
||||||
CriticalSectionScoped cs(_dataCritsect);
|
CriticalSectionScoped cs(_dataCritsect);
|
||||||
_paused = false;
|
_paused = false;
|
||||||
}
|
}
|
||||||
@@ -183,8 +191,9 @@ void ViEEncoder::Restart()
|
|||||||
|
|
||||||
WebRtc_Word32 ViEEncoder::DropDeltaAfterKey(bool enable)
|
WebRtc_Word32 ViEEncoder::DropDeltaAfterKey(bool enable)
|
||||||
{
|
{
|
||||||
WEBRTC_TRACE(webrtc::kTraceInfo, webrtc::kTraceVideo, ViEId(_engineId, _channelId),
|
WEBRTC_TRACE(webrtc::kTraceInfo, webrtc::kTraceVideo,
|
||||||
"%s(%d)", __FUNCTION__, enable);
|
ViEId(_engineId, _channelId),
|
||||||
|
"%s(%d)", __FUNCTION__, enable);
|
||||||
CriticalSectionScoped cs(_dataCritsect);
|
CriticalSectionScoped cs(_dataCritsect);
|
||||||
|
|
||||||
if (enable)
|
if (enable)
|
||||||
@@ -196,9 +205,9 @@ WebRtc_Word32 ViEEncoder::DropDeltaAfterKey(bool enable)
|
|||||||
if (_channelsDroppingDeltaFrames < 0)
|
if (_channelsDroppingDeltaFrames < 0)
|
||||||
{
|
{
|
||||||
_channelsDroppingDeltaFrames = 0;
|
_channelsDroppingDeltaFrames = 0;
|
||||||
WEBRTC_TRACE(webrtc::kTraceInfo, webrtc::kTraceVideo, ViEId(_engineId,
|
WEBRTC_TRACE(webrtc::kTraceInfo, webrtc::kTraceVideo,
|
||||||
_channelId),
|
ViEId(_engineId, _channelId),
|
||||||
"%s: Called too many times", __FUNCTION__, enable);
|
"%s: Called too many times", __FUNCTION__, enable);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -238,12 +247,12 @@ WebRtc_Word32 ViEEncoder::GetCodec(WebRtc_UWord8 listIndex,
|
|||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
// External encoder
|
// External encoder
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
WebRtc_Word32 ViEEncoder::RegisterExternalEncoder(
|
WebRtc_Word32 ViEEncoder::RegisterExternalEncoder(webrtc::VideoEncoder* encoder,
|
||||||
webrtc::VideoEncoder* encoder,
|
|
||||||
WebRtc_UWord8 plType)
|
WebRtc_UWord8 plType)
|
||||||
{
|
{
|
||||||
WEBRTC_TRACE(webrtc::kTraceInfo, webrtc::kTraceVideo, ViEId(_engineId, _channelId),
|
WEBRTC_TRACE(webrtc::kTraceInfo, webrtc::kTraceVideo,
|
||||||
"%s: pltype %u", __FUNCTION__, plType);
|
ViEId(_engineId, _channelId),
|
||||||
|
"%s: pltype %u", __FUNCTION__, plType);
|
||||||
|
|
||||||
if (encoder == NULL)
|
if (encoder == NULL)
|
||||||
return -1;
|
return -1;
|
||||||
@@ -260,8 +269,9 @@ WebRtc_Word32 ViEEncoder::RegisterExternalEncoder(
|
|||||||
|
|
||||||
WebRtc_Word32 ViEEncoder::DeRegisterExternalEncoder(WebRtc_UWord8 plType)
|
WebRtc_Word32 ViEEncoder::DeRegisterExternalEncoder(WebRtc_UWord8 plType)
|
||||||
{
|
{
|
||||||
WEBRTC_TRACE(webrtc::kTraceInfo, webrtc::kTraceVideo, ViEId(_engineId, _channelId),
|
WEBRTC_TRACE(webrtc::kTraceInfo, webrtc::kTraceVideo,
|
||||||
"%s: pltype %u", __FUNCTION__, plType);
|
ViEId(_engineId, _channelId),
|
||||||
|
"%s: pltype %u", __FUNCTION__, plType);
|
||||||
|
|
||||||
webrtc::VideoCodec currentSendCodec;
|
webrtc::VideoCodec currentSendCodec;
|
||||||
if (_vcm.SendCodec(¤tSendCodec) == VCM_OK)
|
if (_vcm.SendCodec(¤tSendCodec) == VCM_OK)
|
||||||
@@ -284,9 +294,9 @@ WebRtc_Word32 ViEEncoder::DeRegisterExternalEncoder(WebRtc_UWord8 plType)
|
|||||||
if (_vcm.RegisterSendCodec(¤tSendCodec, _numberOfCores,
|
if (_vcm.RegisterSendCodec(¤tSendCodec, _numberOfCores,
|
||||||
maxDataPayloadLength) != VCM_OK)
|
maxDataPayloadLength) != VCM_OK)
|
||||||
{
|
{
|
||||||
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo, ViEId(_engineId,
|
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo,
|
||||||
_channelId),
|
ViEId(_engineId, _channelId),
|
||||||
"Could not use internal encoder");
|
"Could not use internal encoder");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -299,8 +309,9 @@ WebRtc_Word32 ViEEncoder::DeRegisterExternalEncoder(WebRtc_UWord8 plType)
|
|||||||
|
|
||||||
WebRtc_Word32 ViEEncoder::SetEncoder(const webrtc::VideoCodec& videoCodec)
|
WebRtc_Word32 ViEEncoder::SetEncoder(const webrtc::VideoCodec& videoCodec)
|
||||||
{
|
{
|
||||||
WEBRTC_TRACE( webrtc::kTraceInfo, webrtc::kTraceVideo, ViEId(_engineId, _channelId),
|
WEBRTC_TRACE(webrtc::kTraceInfo, webrtc::kTraceVideo,
|
||||||
"%s: CodecType: %d, width: %u, height: %u, maxPayloadLength: %u",
|
ViEId(_engineId, _channelId),
|
||||||
|
"%s: CodecType: %d, width: %u, height: %u, maxPayloadLength: %u",
|
||||||
__FUNCTION__, videoCodec.codecType, videoCodec.width,
|
__FUNCTION__, videoCodec.codecType, videoCodec.width,
|
||||||
videoCodec.height);
|
videoCodec.height);
|
||||||
|
|
||||||
@@ -687,6 +698,7 @@ WebRtc_Word32 ViEEncoder::UpdateProtectionMethod()
|
|||||||
WebRtc_UWord8 dummyPTypeRed = 0;
|
WebRtc_UWord8 dummyPTypeRed = 0;
|
||||||
WebRtc_UWord8 dummyPTypeFEC = 0;
|
WebRtc_UWord8 dummyPTypeFEC = 0;
|
||||||
|
|
||||||
|
// check if fec is enabled
|
||||||
WebRtc_Word32 error = _rtpRtcp.GenericFECStatus(fecEnabled, dummyPTypeRed,
|
WebRtc_Word32 error = _rtpRtcp.GenericFECStatus(fecEnabled, dummyPTypeRed,
|
||||||
dummyPTypeFEC);
|
dummyPTypeFEC);
|
||||||
if (error)
|
if (error)
|
||||||
@@ -694,19 +706,35 @@ WebRtc_Word32 ViEEncoder::UpdateProtectionMethod()
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_fecEnabled != fecEnabled)
|
// check if nack is enabled
|
||||||
|
bool nackEnabled = (_rtpRtcp.NACK() == kNackOff) ? false : true;
|
||||||
|
if (_fecEnabled == fecEnabled && _nackEnabled == nackEnabled)
|
||||||
{
|
{
|
||||||
WEBRTC_TRACE(webrtc::kTraceInfo, webrtc::kTraceVideo, ViEId(_engineId, _channelId),
|
// no change to current state
|
||||||
"%s: FEC status ", __FUNCTION__, fecEnabled);
|
return 0;
|
||||||
|
}
|
||||||
|
_fecEnabled = fecEnabled;
|
||||||
|
_nackEnabled = nackEnabled;
|
||||||
|
|
||||||
_vcm.SetVideoProtection(webrtc::kProtectionFEC, fecEnabled);
|
// Set Video Protection for VCM
|
||||||
if (fecEnabled)
|
if (fecEnabled && nackEnabled)
|
||||||
{
|
{
|
||||||
_vcm.RegisterProtectionCallback(this);
|
_vcm.SetVideoProtection(webrtc::kProtectionNackFEC, true);
|
||||||
} else
|
}
|
||||||
{
|
else
|
||||||
_vcm.RegisterProtectionCallback(NULL);
|
{
|
||||||
}
|
_vcm.SetVideoProtection(webrtc::kProtectionFEC, _fecEnabled);
|
||||||
|
_vcm.SetVideoProtection(webrtc::kProtectionNack, _nackEnabled);
|
||||||
|
_vcm.SetVideoProtection(webrtc::kProtectionNackFEC, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
// If nack and/or fec is enalbed, the following should be triggered
|
||||||
|
if (fecEnabled || nackEnabled)
|
||||||
|
{
|
||||||
|
WEBRTC_TRACE(webrtc::kTraceInfo, webrtc::kTraceVideo,
|
||||||
|
ViEId(_engineId, _channelId),
|
||||||
|
"%s: FEC status ", __FUNCTION__, fecEnabled);
|
||||||
|
_vcm.RegisterProtectionCallback(this);
|
||||||
// Need to reregister the send codec in order to set the new MTU
|
// Need to reregister the send codec in order to set the new MTU
|
||||||
webrtc::VideoCodec codec;
|
webrtc::VideoCodec codec;
|
||||||
if (_vcm.SendCodec(&codec) == 0)
|
if (_vcm.SendCodec(&codec) == 0)
|
||||||
@@ -715,19 +743,20 @@ WebRtc_Word32 ViEEncoder::UpdateProtectionMethod()
|
|||||||
codec.startBitrate = _vcm.Bitrate();
|
codec.startBitrate = _vcm.Bitrate();
|
||||||
if (_vcm.RegisterSendCodec(&codec, _numberOfCores, maxPayLoad) != 0)
|
if (_vcm.RegisterSendCodec(&codec, _numberOfCores, maxPayLoad) != 0)
|
||||||
{
|
{
|
||||||
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo, ViEId(_engineId,
|
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo,
|
||||||
_channelId),
|
ViEId(_engineId, _channelId),
|
||||||
"%s: Failed to update Sendcodec when enabling FEC",
|
"%s: Failed to update Sendcodec when enabling FEC",
|
||||||
__FUNCTION__, fecEnabled);
|
__FUNCTION__, fecEnabled);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_fecEnabled = fecEnabled;
|
return 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// FEC and NACK are disabled
|
||||||
|
_vcm.RegisterProtectionCallback(NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update NACK status
|
|
||||||
_vcm.SetVideoProtection(webrtc::kProtectionNack, _rtpRtcp.NACK() != kNackOff);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -162,6 +162,7 @@ private:
|
|||||||
bool _dropNextFrame;
|
bool _dropNextFrame;
|
||||||
//Loss protection
|
//Loss protection
|
||||||
bool _fecEnabled;
|
bool _fecEnabled;
|
||||||
|
bool _nackEnabled;
|
||||||
// Uses
|
// Uses
|
||||||
ViEEncoderObserver* _codecObserver;
|
ViEEncoderObserver* _codecObserver;
|
||||||
ViEEffectFilter* _effectFilter;
|
ViEEffectFilter* _effectFilter;
|
||||||
|
|||||||
@@ -279,12 +279,7 @@ WebRtc_Word32 ViEReceiver::OnReceivedPayloadData(const WebRtc_UWord8* payloadDat
|
|||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if (rtpHeader->frameType == webrtc::kFrameEmpty)
|
|
||||||
{
|
|
||||||
// Don't care about empty rtp packets, we might
|
|
||||||
// get this e.g. when using FEC
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
if (_vcm.IncomingPacket(payloadData, payloadSize, *rtpHeader) != 0)
|
if (_vcm.IncomingPacket(payloadData, payloadSize, *rtpHeader) != 0)
|
||||||
{
|
{
|
||||||
// Check this...
|
// Check this...
|
||||||
|
|||||||
@@ -651,6 +651,7 @@ int ViERTP_RTCPImpl::SetFECStatus(const int videoChannel, const bool enable,
|
|||||||
const unsigned char payloadTypeRED,
|
const unsigned char payloadTypeRED,
|
||||||
const unsigned char payloadTypeFEC)
|
const unsigned char payloadTypeFEC)
|
||||||
{
|
{
|
||||||
|
|
||||||
WEBRTC_TRACE(webrtc::kTraceApiCall, webrtc::kTraceVideo,
|
WEBRTC_TRACE(webrtc::kTraceApiCall, webrtc::kTraceVideo,
|
||||||
ViEId(_instanceId, videoChannel),
|
ViEId(_instanceId, videoChannel),
|
||||||
"%s(channel: %d, enable: %d, payloadTypeRED: %u, "
|
"%s(channel: %d, enable: %d, payloadTypeRED: %u, "
|
||||||
@@ -698,6 +699,64 @@ int ViERTP_RTCPImpl::SetFECStatus(const int videoChannel, const bool enable,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
// SetHybridNACKFECStatus
|
||||||
|
//
|
||||||
|
// Enables/disables hybrid NACK/FEC and sets the payloadtypes
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
int ViERTP_RTCPImpl::SetHybridNACKFECStatus(const int videoChannel,
|
||||||
|
const bool enable,
|
||||||
|
const unsigned char payloadTypeRED,
|
||||||
|
const unsigned char payloadTypeFEC)
|
||||||
|
{
|
||||||
|
WEBRTC_TRACE(webrtc::kTraceApiCall, webrtc::kTraceVideo,
|
||||||
|
ViEId(_instanceId, videoChannel),
|
||||||
|
"%s(channel: %d, enable: %d, payloadTypeRED: %u, "
|
||||||
|
"payloadTypeFEC: %u)",
|
||||||
|
__FUNCTION__, videoChannel, enable, payloadTypeRED,
|
||||||
|
payloadTypeFEC);
|
||||||
|
|
||||||
|
// Get the channel
|
||||||
|
ViEChannelManagerScoped cs(_channelManager);
|
||||||
|
ViEChannel* ptrViEChannel = cs.Channel(videoChannel);
|
||||||
|
if (ptrViEChannel == NULL)
|
||||||
|
{
|
||||||
|
// The channel doesn't exists
|
||||||
|
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo,
|
||||||
|
ViEId(_instanceId, videoChannel),
|
||||||
|
"%s: Channel %d doesn't exist", __FUNCTION__,
|
||||||
|
videoChannel);
|
||||||
|
SetLastError(kViERtpRtcpInvalidChannelId);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update the channel status with hybrid NACK FEC mode
|
||||||
|
if (ptrViEChannel->SetHybridNACKFECStatus(enable, payloadTypeRED,
|
||||||
|
payloadTypeFEC) != 0)
|
||||||
|
{
|
||||||
|
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo,
|
||||||
|
ViEId(_instanceId, videoChannel),
|
||||||
|
"%s: failed for channel %d", __FUNCTION__, videoChannel);
|
||||||
|
SetLastError(kViERtpRtcpUnknownError);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update the encoder
|
||||||
|
ViEEncoder* ptrViEEncoder = cs.Encoder(videoChannel);
|
||||||
|
if (ptrViEEncoder == NULL)
|
||||||
|
{
|
||||||
|
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo,
|
||||||
|
ViEId(_instanceId, videoChannel),
|
||||||
|
"%s: Could not get encoder for channel %d", __FUNCTION__,
|
||||||
|
videoChannel);
|
||||||
|
SetLastError(kViERtpRtcpUnknownError);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
ptrViEEncoder->UpdateProtectionMethod();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
// SetKeyFrameRequestMethod
|
// SetKeyFrameRequestMethod
|
||||||
//
|
//
|
||||||
|
|||||||
@@ -76,6 +76,9 @@ public:
|
|||||||
virtual int SetFECStatus(const int videoChannel, const bool enable,
|
virtual int SetFECStatus(const int videoChannel, const bool enable,
|
||||||
const unsigned char payloadTypeRED,
|
const unsigned char payloadTypeRED,
|
||||||
const unsigned char payloadTypeFEC);
|
const unsigned char payloadTypeFEC);
|
||||||
|
virtual int SetHybridNACKFECStatus(const int videoChannel, const bool enable,
|
||||||
|
const unsigned char payloadTypeRED,
|
||||||
|
const unsigned char payloadTypeFEC);
|
||||||
|
|
||||||
virtual int SetKeyFrameRequestMethod(const int videoChannel,
|
virtual int SetKeyFrameRequestMethod(const int videoChannel,
|
||||||
const ViEKeyFrameRequestMethod method);
|
const ViEKeyFrameRequestMethod method);
|
||||||
|
|||||||
Reference in New Issue
Block a user