Implements selective retransmissions.
Default is set to not retransmit VP8 non-base layer packets or FEC packets. BUG= TEST= Review URL: http://webrtc-codereview.appspot.com/323010 git-svn-id: http://webrtc.googlecode.com/svn/trunk@1290 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
parent
51faeed6be
commit
6a4bef4e65
@ -810,13 +810,33 @@ public:
|
|||||||
*/
|
*/
|
||||||
virtual WebRtc_Word32 SetNACKStatus(const NACKMethod method) = 0;
|
virtual WebRtc_Word32 SetNACKStatus(const NACKMethod method) = 0;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* TODO(holmer): Propagate this API to VideoEngine.
|
||||||
|
* Returns the currently configured selective retransmission settings.
|
||||||
|
*/
|
||||||
|
virtual int SelectiveRetransmissions() const = 0;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* TODO(holmer): Propagate this API to VideoEngine.
|
||||||
|
* Sets the selective retransmission settings, which will decide which
|
||||||
|
* packets will be retransmitted if NACKed. Settings are constructed by
|
||||||
|
* combining the constants in enum RetransmissionMode with bitwise OR.
|
||||||
|
* All packets are retransmitted if kRetransmitAllPackets is set, while no
|
||||||
|
* packets are retransmitted if kRetransmitOff is set.
|
||||||
|
* By default all packets except FEC packets are retransmitted. For VP8
|
||||||
|
* with temporal scalability only base layer packets are retransmitted.
|
||||||
|
*
|
||||||
|
* Returns -1 on failure, otherwise 0.
|
||||||
|
*/
|
||||||
|
virtual int SetSelectiveRetransmissions(uint8_t settings) = 0;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Send a Negative acknowledgement packet
|
* Send a Negative acknowledgement packet
|
||||||
*
|
*
|
||||||
* return -1 on failure else 0
|
* return -1 on failure else 0
|
||||||
*/
|
*/
|
||||||
virtual WebRtc_Word32 SendNACK(const WebRtc_UWord16* nackList,
|
virtual WebRtc_Word32 SendNACK(const WebRtc_UWord16* nackList,
|
||||||
const WebRtc_UWord16 size) = 0;
|
const WebRtc_UWord16 size) = 0;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Store the sent packets, needed to answer to a Negative acknowledgement requests
|
* Store the sent packets, needed to answer to a Negative acknowledgement requests
|
||||||
|
@ -89,6 +89,14 @@ enum NACKMethod
|
|||||||
kNackRtcp = 2
|
kNackRtcp = 2
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum RetransmissionMode {
|
||||||
|
kRetransmitOff = 0x0,
|
||||||
|
kRetransmitFECPackets = 0x1,
|
||||||
|
kRetransmitBaseLayer = 0x2,
|
||||||
|
kRetransmitHigherLayers = 0x4,
|
||||||
|
kRetransmitAllPackets = 0xFF
|
||||||
|
};
|
||||||
|
|
||||||
struct RTCPSenderInfo
|
struct RTCPSenderInfo
|
||||||
{
|
{
|
||||||
WebRtc_UWord32 NTPseconds;
|
WebRtc_UWord32 NTPseconds;
|
||||||
|
@ -194,6 +194,10 @@ class MockRtpRtcp : public RtpRtcp {
|
|||||||
NACKMethod());
|
NACKMethod());
|
||||||
MOCK_METHOD1(SetNACKStatus,
|
MOCK_METHOD1(SetNACKStatus,
|
||||||
WebRtc_Word32(const NACKMethod method));
|
WebRtc_Word32(const NACKMethod method));
|
||||||
|
MOCK_CONST_METHOD0(SelectiveRetransmissions,
|
||||||
|
int());
|
||||||
|
MOCK_METHOD1(SetSelectiveRetransmissions,
|
||||||
|
int(uint8_t settings));
|
||||||
MOCK_METHOD2(SendNACK,
|
MOCK_METHOD2(SendNACK,
|
||||||
WebRtc_Word32(const WebRtc_UWord16* nackList, const WebRtc_UWord16 size));
|
WebRtc_Word32(const WebRtc_UWord16* nackList, const WebRtc_UWord16 size));
|
||||||
MOCK_METHOD2(SetStorePacketsStatus,
|
MOCK_METHOD2(SetStorePacketsStatus,
|
||||||
|
@ -1963,6 +1963,26 @@ WebRtc_Word32 ModuleRtpRtcpImpl::SetNACKStatus(NACKMethod method)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Returns the currently configured retransmission mode.
|
||||||
|
int ModuleRtpRtcpImpl::SelectiveRetransmissions() const {
|
||||||
|
WEBRTC_TRACE(kTraceModuleCall,
|
||||||
|
kTraceRtpRtcp,
|
||||||
|
_id,
|
||||||
|
"SelectiveRetransmissions()");
|
||||||
|
return _rtpSender.SelectiveRetransmissions();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Enable or disable a retransmission mode, which decides which packets will
|
||||||
|
// be retransmitted if NACKed.
|
||||||
|
int ModuleRtpRtcpImpl::SetSelectiveRetransmissions(uint8_t settings) {
|
||||||
|
WEBRTC_TRACE(kTraceModuleCall,
|
||||||
|
kTraceRtpRtcp,
|
||||||
|
_id,
|
||||||
|
"SetSelectiveRetransmissions(%u)",
|
||||||
|
settings);
|
||||||
|
return _rtpSender.SetSelectiveRetransmissions(settings);
|
||||||
|
}
|
||||||
|
|
||||||
// Send a Negative acknowledgement packet
|
// Send a Negative acknowledgement packet
|
||||||
WebRtc_Word32
|
WebRtc_Word32
|
||||||
ModuleRtpRtcpImpl::SendNACK(const WebRtc_UWord16* nackList,
|
ModuleRtpRtcpImpl::SendNACK(const WebRtc_UWord16* nackList,
|
||||||
|
@ -381,6 +381,10 @@ public:
|
|||||||
// Turn negative acknowledgement requests on/off
|
// Turn negative acknowledgement requests on/off
|
||||||
virtual WebRtc_Word32 SetNACKStatus(const NACKMethod method);
|
virtual WebRtc_Word32 SetNACKStatus(const NACKMethod method);
|
||||||
|
|
||||||
|
virtual int SelectiveRetransmissions() const;
|
||||||
|
|
||||||
|
virtual int SetSelectiveRetransmissions(uint8_t settings);
|
||||||
|
|
||||||
// Send a Negative acknowledgement packet
|
// Send a Negative acknowledgement packet
|
||||||
virtual WebRtc_Word32 SendNACK(const WebRtc_UWord16* nackList,
|
virtual WebRtc_Word32 SendNACK(const WebRtc_UWord16* nackList,
|
||||||
const WebRtc_UWord16 size);
|
const WebRtc_UWord16 size);
|
||||||
|
@ -554,7 +554,7 @@ RTPSender::SendRTPKeepalivePacket()
|
|||||||
BuildRTPheader(dataBuffer, _keepAlivePayloadType, false, 0, false);
|
BuildRTPheader(dataBuffer, _keepAlivePayloadType, false, 0, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
return SendToNetwork(dataBuffer, 0, rtpHeaderLength);
|
return SendToNetwork(dataBuffer, 0, rtpHeaderLength, kAllowRetransmission);
|
||||||
}
|
}
|
||||||
|
|
||||||
WebRtc_Word32
|
WebRtc_Word32
|
||||||
@ -899,11 +899,11 @@ RTPSender::ReSendToNetwork(WebRtc_UWord16 packetID,
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(length ==0)
|
if (length == 0)
|
||||||
{
|
{
|
||||||
WEBRTC_TRACE(kTraceWarning, kTraceRtpRtcp, _id,
|
// This is a valid case since packets which we decide not to
|
||||||
"Resend packet length == 0 for seqNum %u", seqNum);
|
// retransmit are stored but with length zero.
|
||||||
return -1;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// copy to local buffer for callback
|
// copy to local buffer for callback
|
||||||
@ -942,6 +942,16 @@ RTPSender::ReSendToNetwork(WebRtc_UWord16 packetID,
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int RTPSender::SelectiveRetransmissions() const {
|
||||||
|
if (!_video) return -1;
|
||||||
|
return _video->SelectiveRetransmissions();
|
||||||
|
}
|
||||||
|
|
||||||
|
int RTPSender::SetSelectiveRetransmissions(uint8_t settings) {
|
||||||
|
if (!_video) return -1;
|
||||||
|
return _video->SetSelectiveRetransmissions(settings);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
RTPSender::OnReceivedNACK(const WebRtc_UWord16 nackSequenceNumbersLength,
|
RTPSender::OnReceivedNACK(const WebRtc_UWord16 nackSequenceNumbersLength,
|
||||||
const WebRtc_UWord16* nackSequenceNumbers,
|
const WebRtc_UWord16* nackSequenceNumbers,
|
||||||
@ -1069,7 +1079,7 @@ WebRtc_Word32
|
|||||||
RTPSender::SendToNetwork(const WebRtc_UWord8* buffer,
|
RTPSender::SendToNetwork(const WebRtc_UWord8* buffer,
|
||||||
const WebRtc_UWord16 length,
|
const WebRtc_UWord16 length,
|
||||||
const WebRtc_UWord16 rtpLength,
|
const WebRtc_UWord16 rtpLength,
|
||||||
const bool dontStore)
|
const StorageType storage)
|
||||||
{
|
{
|
||||||
WebRtc_Word32 retVal = -1;
|
WebRtc_Word32 retVal = -1;
|
||||||
// sanity
|
// sanity
|
||||||
@ -1078,34 +1088,22 @@ RTPSender::SendToNetwork(const WebRtc_UWord8* buffer,
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!dontStore)
|
// Make sure the packet is big enough for us to parse the sequence number.
|
||||||
{
|
assert(length + rtpLength > 3);
|
||||||
// Store my packets
|
// Parse the sequence number from the RTP header.
|
||||||
// Used for NACK
|
WebRtc_UWord16 sequenceNumber = (buffer[2] << 8) + buffer[3];
|
||||||
CriticalSectionScoped lock(_prevSentPacketsCritsect);
|
switch (storage) {
|
||||||
if(_storeSentPackets && length > 0)
|
case kAllowRetransmission:
|
||||||
{
|
StorePacket(buffer, length + rtpLength, sequenceNumber);
|
||||||
if(_ptrPrevSentPackets[0] == NULL)
|
break;
|
||||||
{
|
case kDontRetransmit:
|
||||||
for(WebRtc_Word32 i=0; i< _storeSentPacketsNumber; i++)
|
// Store an empty packet. Won't be retransmitted if NACKed.
|
||||||
{
|
StorePacket(NULL, 0, sequenceNumber);
|
||||||
_ptrPrevSentPackets[i] = new char[_maxPayloadLength];
|
break;
|
||||||
memset(_ptrPrevSentPackets[i],0, _maxPayloadLength);
|
case kDontStore:
|
||||||
}
|
break;
|
||||||
}
|
default:
|
||||||
|
assert(false);
|
||||||
const WebRtc_UWord16 sequenceNumber = (buffer[2] << 8) + buffer[3];
|
|
||||||
|
|
||||||
memcpy(_ptrPrevSentPackets[_prevSentPacketsIndex], buffer, length + rtpLength);
|
|
||||||
_prevSentPacketsSeqNum[_prevSentPacketsIndex] = sequenceNumber;
|
|
||||||
_prevSentPacketsLength[_prevSentPacketsIndex]= length + rtpLength;
|
|
||||||
_prevSentPacketsResendTime[_prevSentPacketsIndex]=0; // Packet has not been re-sent.
|
|
||||||
_prevSentPacketsIndex++;
|
|
||||||
if(_prevSentPacketsIndex >= _storeSentPacketsNumber)
|
|
||||||
{
|
|
||||||
_prevSentPacketsIndex = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
// Send packet
|
// Send packet
|
||||||
{
|
{
|
||||||
@ -1133,6 +1131,32 @@ RTPSender::SendToNetwork(const WebRtc_UWord8* buffer,
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RTPSender::StorePacket(const uint8_t* buffer, uint16_t length,
|
||||||
|
uint16_t sequence_number) {
|
||||||
|
// Store packet to be used for NACK.
|
||||||
|
CriticalSectionScoped lock(_prevSentPacketsCritsect);
|
||||||
|
if(_storeSentPackets) {
|
||||||
|
if(_ptrPrevSentPackets[0] == NULL) {
|
||||||
|
for(WebRtc_Word32 i = 0; i < _storeSentPacketsNumber; i++) {
|
||||||
|
_ptrPrevSentPackets[i] = new char[_maxPayloadLength];
|
||||||
|
memset(_ptrPrevSentPackets[i], 0, _maxPayloadLength);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (buffer != NULL && length > 0) {
|
||||||
|
memcpy(_ptrPrevSentPackets[_prevSentPacketsIndex], buffer, length);
|
||||||
|
}
|
||||||
|
_prevSentPacketsSeqNum[_prevSentPacketsIndex] = sequence_number;
|
||||||
|
_prevSentPacketsLength[_prevSentPacketsIndex] = length;
|
||||||
|
// Packet has not been re-sent.
|
||||||
|
_prevSentPacketsResendTime[_prevSentPacketsIndex] = 0;
|
||||||
|
_prevSentPacketsIndex++;
|
||||||
|
if(_prevSentPacketsIndex >= _storeSentPacketsNumber) {
|
||||||
|
_prevSentPacketsIndex = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
RTPSender::ProcessBitrate()
|
RTPSender::ProcessBitrate()
|
||||||
{
|
{
|
||||||
|
@ -31,6 +31,12 @@ class CriticalSectionWrapper;
|
|||||||
class RTPSenderAudio;
|
class RTPSenderAudio;
|
||||||
class RTPSenderVideo;
|
class RTPSenderVideo;
|
||||||
|
|
||||||
|
enum StorageType {
|
||||||
|
kDontStore,
|
||||||
|
kDontRetransmit,
|
||||||
|
kAllowRetransmission
|
||||||
|
};
|
||||||
|
|
||||||
class RTPSenderInterface
|
class RTPSenderInterface
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -57,9 +63,9 @@ public:
|
|||||||
virtual WebRtc_UWord16 ActualSendBitrateKbit() const = 0;
|
virtual WebRtc_UWord16 ActualSendBitrateKbit() const = 0;
|
||||||
|
|
||||||
virtual WebRtc_Word32 SendToNetwork(const WebRtc_UWord8* dataBuffer,
|
virtual WebRtc_Word32 SendToNetwork(const WebRtc_UWord8* dataBuffer,
|
||||||
const WebRtc_UWord16 payloadLength,
|
const WebRtc_UWord16 payloadLength,
|
||||||
const WebRtc_UWord16 rtpHeaderLength,
|
const WebRtc_UWord16 rtpHeaderLength,
|
||||||
const bool dontStore = false) = 0;
|
const StorageType storage) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
class RTPSender : public Bitrate, public RTPSenderInterface
|
class RTPSender : public Bitrate, public RTPSenderInterface
|
||||||
@ -162,6 +168,8 @@ public:
|
|||||||
/*
|
/*
|
||||||
* NACK
|
* NACK
|
||||||
*/
|
*/
|
||||||
|
int SelectiveRetransmissions() const;
|
||||||
|
int SetSelectiveRetransmissions(uint8_t settings);
|
||||||
void OnReceivedNACK(const WebRtc_UWord16 nackSequenceNumbersLength,
|
void OnReceivedNACK(const WebRtc_UWord16 nackSequenceNumbersLength,
|
||||||
const WebRtc_UWord16* nackSequenceNumbers,
|
const WebRtc_UWord16* nackSequenceNumbers,
|
||||||
const WebRtc_UWord16 avgRTT);
|
const WebRtc_UWord16 avgRTT);
|
||||||
@ -216,9 +224,9 @@ public:
|
|||||||
virtual WebRtc_UWord32 SSRC() const;
|
virtual WebRtc_UWord32 SSRC() const;
|
||||||
|
|
||||||
virtual WebRtc_Word32 SendToNetwork(const WebRtc_UWord8* dataBuffer,
|
virtual WebRtc_Word32 SendToNetwork(const WebRtc_UWord8* dataBuffer,
|
||||||
const WebRtc_UWord16 payloadLength,
|
const WebRtc_UWord16 payloadLength,
|
||||||
const WebRtc_UWord16 rtpHeaderLength,
|
const WebRtc_UWord16 rtpHeaderLength,
|
||||||
const bool dontStore = false);
|
const StorageType storage);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Audio
|
* Audio
|
||||||
@ -282,6 +290,9 @@ protected:
|
|||||||
WebRtc_Word32 CheckPayloadType(const WebRtc_Word8 payloadType, RtpVideoCodecTypes& videoType);
|
WebRtc_Word32 CheckPayloadType(const WebRtc_Word8 payloadType, RtpVideoCodecTypes& videoType);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void StorePacket(const uint8_t* buffer, uint16_t length,
|
||||||
|
uint16_t sequence_number);
|
||||||
|
|
||||||
WebRtc_Word32 _id;
|
WebRtc_Word32 _id;
|
||||||
const bool _audioConfigured;
|
const bool _audioConfigured;
|
||||||
RTPSenderAudio* _audio;
|
RTPSenderAudio* _audio;
|
||||||
|
@ -527,7 +527,11 @@ RTPSenderAudio::SendAudio(const FrameType frameType,
|
|||||||
|
|
||||||
} // end critical section
|
} // end critical section
|
||||||
|
|
||||||
return _rtpSender->SendToNetwork(dataBuffer, payloadSize, (WebRtc_UWord16)rtpHeaderLength);
|
return _rtpSender->SendToNetwork(
|
||||||
|
dataBuffer,
|
||||||
|
payloadSize,
|
||||||
|
static_cast<WebRtc_UWord16>(rtpHeaderLength),
|
||||||
|
kAllowRetransmission);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -662,7 +666,8 @@ RTPSenderAudio::SendTelephoneEventPacket(const bool ended,
|
|||||||
ModuleRTPUtility::AssignUWord16ToBuffer(dtmfbuffer+14, duration);
|
ModuleRTPUtility::AssignUWord16ToBuffer(dtmfbuffer+14, duration);
|
||||||
|
|
||||||
_sendAudioCritsect->Leave();
|
_sendAudioCritsect->Leave();
|
||||||
retVal = _rtpSender->SendToNetwork(dtmfbuffer, 4, 12);
|
retVal = _rtpSender->SendToNetwork(dtmfbuffer, 4, 12,
|
||||||
|
kAllowRetransmission);
|
||||||
sendCount--;
|
sendCount--;
|
||||||
|
|
||||||
}while (sendCount > 0 && retVal == 0);
|
}while (sendCount > 0 && retVal == 0);
|
||||||
|
@ -35,6 +35,7 @@ RTPSenderVideo::RTPSenderVideo(const WebRtc_Word32 id,
|
|||||||
_videoType(kRtpNoVideo),
|
_videoType(kRtpNoVideo),
|
||||||
_videoCodecInformation(NULL),
|
_videoCodecInformation(NULL),
|
||||||
_maxBitrate(0),
|
_maxBitrate(0),
|
||||||
|
_retransmissionSettings(kRetransmitBaseLayer),
|
||||||
|
|
||||||
// Generic FEC
|
// Generic FEC
|
||||||
_fec(id),
|
_fec(id),
|
||||||
@ -71,6 +72,7 @@ RTPSenderVideo::Init()
|
|||||||
{
|
{
|
||||||
CriticalSectionScoped cs(_sendVideoCritsect);
|
CriticalSectionScoped cs(_sendVideoCritsect);
|
||||||
|
|
||||||
|
_retransmissionSettings = kRetransmitBaseLayer;
|
||||||
_fecEnabled = false;
|
_fecEnabled = false;
|
||||||
_payloadTypeRED = -1;
|
_payloadTypeRED = -1;
|
||||||
_payloadTypeFEC = -1;
|
_payloadTypeFEC = -1;
|
||||||
@ -157,7 +159,8 @@ WebRtc_Word32
|
|||||||
RTPSenderVideo::SendVideoPacket(const FrameType frameType,
|
RTPSenderVideo::SendVideoPacket(const FrameType frameType,
|
||||||
const WebRtc_UWord8* dataBuffer,
|
const WebRtc_UWord8* dataBuffer,
|
||||||
const WebRtc_UWord16 payloadLength,
|
const WebRtc_UWord16 payloadLength,
|
||||||
const WebRtc_UWord16 rtpHeaderLength)
|
const WebRtc_UWord16 rtpHeaderLength,
|
||||||
|
StorageType storage)
|
||||||
{
|
{
|
||||||
if(_fecEnabled)
|
if(_fecEnabled)
|
||||||
{
|
{
|
||||||
@ -254,11 +257,11 @@ RTPSenderVideo::SendVideoPacket(const FrameType frameType,
|
|||||||
|
|
||||||
// Send normal packet with RED header
|
// Send normal packet with RED header
|
||||||
int packetSuccess = _rtpSender.SendToNetwork(
|
int packetSuccess = _rtpSender.SendToNetwork(
|
||||||
newDataBuffer,
|
newDataBuffer,
|
||||||
packetToSend->pkt->length -
|
packetToSend->pkt->length - packetToSend->rtpHeaderLength +
|
||||||
packetToSend->rtpHeaderLength +
|
REDForFECHeaderLength,
|
||||||
REDForFECHeaderLength,
|
packetToSend->rtpHeaderLength,
|
||||||
packetToSend->rtpHeaderLength);
|
storage);
|
||||||
|
|
||||||
retVal |= packetSuccess;
|
retVal |= packetSuccess;
|
||||||
|
|
||||||
@ -313,12 +316,18 @@ RTPSenderVideo::SendVideoPacket(const FrameType frameType,
|
|||||||
// Invalid FEC packet
|
// Invalid FEC packet
|
||||||
assert(packetToSend->length != 0);
|
assert(packetToSend->length != 0);
|
||||||
|
|
||||||
|
StorageType storage = kDontRetransmit;
|
||||||
|
if (_retransmissionSettings & kRetransmitFECPackets) {
|
||||||
|
storage = kAllowRetransmission;
|
||||||
|
}
|
||||||
|
|
||||||
// No marker bit on FEC packets, last media packet have the
|
// No marker bit on FEC packets, last media packet have the
|
||||||
// marker send FEC packet with RED header
|
// marker send FEC packet with RED header
|
||||||
int packetSuccess = _rtpSender.SendToNetwork(
|
int packetSuccess = _rtpSender.SendToNetwork(
|
||||||
newDataBuffer,
|
newDataBuffer,
|
||||||
packetToSend->length + REDForFECHeaderLength,
|
packetToSend->length + REDForFECHeaderLength,
|
||||||
lastMediaRtpHeader.length);
|
lastMediaRtpHeader.length,
|
||||||
|
storage);
|
||||||
|
|
||||||
retVal |= packetSuccess;
|
retVal |= packetSuccess;
|
||||||
|
|
||||||
@ -335,7 +344,8 @@ RTPSenderVideo::SendVideoPacket(const FrameType frameType,
|
|||||||
}
|
}
|
||||||
int retVal = _rtpSender.SendToNetwork(dataBuffer,
|
int retVal = _rtpSender.SendToNetwork(dataBuffer,
|
||||||
payloadLength,
|
payloadLength,
|
||||||
rtpHeaderLength);
|
rtpHeaderLength,
|
||||||
|
storage);
|
||||||
if (retVal == 0)
|
if (retVal == 0)
|
||||||
{
|
{
|
||||||
_videoBitrate.Update(payloadLength + rtpHeaderLength);
|
_videoBitrate.Update(payloadLength + rtpHeaderLength);
|
||||||
@ -358,7 +368,7 @@ RTPSenderVideo::SendRTPIntraRequest()
|
|||||||
|
|
||||||
ModuleRTPUtility::AssignUWord32ToBuffer(data+4, _rtpSender.SSRC());
|
ModuleRTPUtility::AssignUWord32ToBuffer(data+4, _rtpSender.SSRC());
|
||||||
|
|
||||||
return _rtpSender.SendToNetwork(data, 0, length);
|
return _rtpSender.SendToNetwork(data, 0, length, kAllowRetransmission);
|
||||||
}
|
}
|
||||||
|
|
||||||
WebRtc_Word32
|
WebRtc_Word32
|
||||||
@ -537,7 +547,8 @@ RTPSenderVideo::SendGeneric(const WebRtc_Word8 payloadType,
|
|||||||
if(-1 == SendVideoPacket(kVideoFrameKey,
|
if(-1 == SendVideoPacket(kVideoFrameKey,
|
||||||
dataBuffer,
|
dataBuffer,
|
||||||
payloadBytesInPacket,
|
payloadBytesInPacket,
|
||||||
rtpHeaderLength))
|
rtpHeaderLength,
|
||||||
|
kAllowRetransmission))
|
||||||
{
|
{
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@ -589,7 +600,8 @@ void RTPSenderVideo::SendPadData(WebRtc_Word8 payload_type,
|
|||||||
// Send the packet
|
// Send the packet
|
||||||
_rtpSender.SendToNetwork(data_buffer,
|
_rtpSender.SendToNetwork(data_buffer,
|
||||||
padding_bytes_in_packet,
|
padding_bytes_in_packet,
|
||||||
header_length);
|
header_length,
|
||||||
|
kDontRetransmit);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -666,7 +678,7 @@ RTPSenderVideo::SendMPEG4(const FrameType frameType,
|
|||||||
}while(payloadBytesToSend);
|
}while(payloadBytesToSend);
|
||||||
|
|
||||||
if (-1 == SendVideoPacket(frameType, dataBuffer, payloadBytes,
|
if (-1 == SendVideoPacket(frameType, dataBuffer, payloadBytes,
|
||||||
rtpHeaderLength))
|
rtpHeaderLength, kAllowRetransmission))
|
||||||
{
|
{
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@ -934,7 +946,7 @@ RTPSenderVideo::SendH263(const FrameType frameType,
|
|||||||
if (-1 == SendVideoPacket(frameType,
|
if (-1 == SendVideoPacket(frameType,
|
||||||
dataBuffer,
|
dataBuffer,
|
||||||
payloadBytesInPacket + h263HeaderLength,
|
payloadBytesInPacket + h263HeaderLength,
|
||||||
rtpHeaderLength))
|
rtpHeaderLength, kAllowRetransmission))
|
||||||
{
|
{
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@ -1072,8 +1084,11 @@ RTPSenderVideo::SendH2631998(const FrameType frameType,
|
|||||||
memcpy(&dataBuffer[rtpHeaderLength + h2631998HeaderLength],
|
memcpy(&dataBuffer[rtpHeaderLength + h2631998HeaderLength],
|
||||||
data, payloadBytesInPacket);
|
data, payloadBytesInPacket);
|
||||||
|
|
||||||
if(-1 == SendVideoPacket(frameType, dataBuffer, payloadBytesInPacket +
|
if(-1 == SendVideoPacket(frameType,
|
||||||
h2631998HeaderLength, rtpHeaderLength))
|
dataBuffer,
|
||||||
|
payloadBytesInPacket + h2631998HeaderLength,
|
||||||
|
rtpHeaderLength,
|
||||||
|
kAllowRetransmission))
|
||||||
{
|
{
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@ -1250,7 +1265,8 @@ RTPSenderVideo::SendH263MBs(const FrameType frameType,
|
|||||||
if (-1 == SendVideoPacket(frameType,
|
if (-1 == SendVideoPacket(frameType,
|
||||||
dataBuffer,
|
dataBuffer,
|
||||||
payloadBytesInPacket + h263HeaderLength,
|
payloadBytesInPacket + h263HeaderLength,
|
||||||
rtpHeaderLength))
|
rtpHeaderLength,
|
||||||
|
kAllowRetransmission))
|
||||||
{
|
{
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@ -1281,6 +1297,16 @@ RTPSenderVideo::SendVP8(const FrameType frameType,
|
|||||||
RtpFormatVp8 packetizer(data, payloadBytesToSend, rtpTypeHdr->VP8,
|
RtpFormatVp8 packetizer(data, payloadBytesToSend, rtpTypeHdr->VP8,
|
||||||
maxPayloadLengthVP8, *fragmentation, kAggregate);
|
maxPayloadLengthVP8, *fragmentation, kAggregate);
|
||||||
|
|
||||||
|
StorageType storage = kAllowRetransmission;
|
||||||
|
if (rtpTypeHdr->VP8.temporalIdx == 0 &&
|
||||||
|
!(_retransmissionSettings & kRetransmitBaseLayer)) {
|
||||||
|
storage = kDontRetransmit;
|
||||||
|
}
|
||||||
|
if (rtpTypeHdr->VP8.temporalIdx > 0 &&
|
||||||
|
!(_retransmissionSettings & kRetransmitHigherLayers)) {
|
||||||
|
storage = kDontRetransmit;
|
||||||
|
}
|
||||||
|
|
||||||
bool last = false;
|
bool last = false;
|
||||||
_numberFirstPartition = 0;
|
_numberFirstPartition = 0;
|
||||||
while (!last)
|
while (!last)
|
||||||
@ -1305,7 +1331,7 @@ RTPSenderVideo::SendVP8(const FrameType frameType,
|
|||||||
_rtpSender.BuildRTPheader(dataBuffer, payloadType, last,
|
_rtpSender.BuildRTPheader(dataBuffer, payloadType, last,
|
||||||
captureTimeStamp);
|
captureTimeStamp);
|
||||||
if (-1 == SendVideoPacket(frameType, dataBuffer, payloadBytesInPacket,
|
if (-1 == SendVideoPacket(frameType, dataBuffer, payloadBytesInPacket,
|
||||||
rtpHeaderLength))
|
rtpHeaderLength, storage))
|
||||||
{
|
{
|
||||||
WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id,
|
WEBRTC_TRACE(kTraceError, kTraceRtpRtcp, _id,
|
||||||
"RTPSenderVideo::SendVP8 failed to send packet number"
|
"RTPSenderVideo::SendVP8 failed to send packet number"
|
||||||
@ -1328,4 +1354,13 @@ WebRtc_UWord32 RTPSenderVideo::FecOverheadRate() const {
|
|||||||
return _fecOverheadRate.BitrateLast();
|
return _fecOverheadRate.BitrateLast();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int RTPSenderVideo::SelectiveRetransmissions() const {
|
||||||
|
return _retransmissionSettings;
|
||||||
|
}
|
||||||
|
|
||||||
|
int RTPSenderVideo::SetSelectiveRetransmissions(uint8_t settings) {
|
||||||
|
_retransmissionSettings = settings;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace webrtc
|
} // namespace webrtc
|
||||||
|
@ -92,11 +92,15 @@ public:
|
|||||||
WebRtc_UWord32 VideoBitrateSent() const;
|
WebRtc_UWord32 VideoBitrateSent() const;
|
||||||
WebRtc_UWord32 FecOverheadRate() const;
|
WebRtc_UWord32 FecOverheadRate() const;
|
||||||
|
|
||||||
|
int SelectiveRetransmissions() const;
|
||||||
|
int SetSelectiveRetransmissions(uint8_t settings);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual WebRtc_Word32 SendVideoPacket(const FrameType frameType,
|
virtual WebRtc_Word32 SendVideoPacket(const FrameType frameType,
|
||||||
const WebRtc_UWord8* dataBuffer,
|
const WebRtc_UWord8* dataBuffer,
|
||||||
const WebRtc_UWord16 payloadLength,
|
const WebRtc_UWord16 payloadLength,
|
||||||
const WebRtc_UWord16 rtpHeaderLength);
|
const WebRtc_UWord16 rtpHeaderLength,
|
||||||
|
StorageType storage);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
WebRtc_Word32 SendGeneric(const WebRtc_Word8 payloadType,
|
WebRtc_Word32 SendGeneric(const WebRtc_Word8 payloadType,
|
||||||
@ -155,6 +159,7 @@ private:
|
|||||||
RtpVideoCodecTypes _videoType;
|
RtpVideoCodecTypes _videoType;
|
||||||
VideoCodecInformation* _videoCodecInformation;
|
VideoCodecInformation* _videoCodecInformation;
|
||||||
WebRtc_UWord32 _maxBitrate;
|
WebRtc_UWord32 _maxBitrate;
|
||||||
|
WebRtc_Word32 _retransmissionSettings;
|
||||||
|
|
||||||
// FEC
|
// FEC
|
||||||
ForwardErrorCorrection _fec;
|
ForwardErrorCorrection _fec;
|
||||||
|
Loading…
Reference in New Issue
Block a user