Remove list wrapper from FEC code.
Review URL: https://webrtc-codereview.appspot.com/350013 git-svn-id: http://webrtc.googlecode.com/svn/trunk@1489 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
parent
9165f1fe91
commit
95cf47932d
File diff suppressed because it is too large
Load Diff
@ -11,178 +11,222 @@
|
||||
#ifndef WEBRTC_MODULES_RTP_RTCP_SOURCE_FORWARD_ERROR_CORRECTION_H_
|
||||
#define WEBRTC_MODULES_RTP_RTCP_SOURCE_FORWARD_ERROR_CORRECTION_H_
|
||||
|
||||
#include <list>
|
||||
#include <vector>
|
||||
|
||||
#include "typedefs.h"
|
||||
#include "rtp_rtcp_defines.h"
|
||||
|
||||
#include "list_wrapper.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
// Forward declaration.
|
||||
struct FecPacket;
|
||||
|
||||
/**
|
||||
* Performs codec-independent forward error correction (FEC), based on RFC 5109.
|
||||
* Option exists to enable unequal protection (UEP) across packets.
|
||||
* This is not to be confused with protection within packets
|
||||
* (referred to as uneven level protection (ULP) in RFC 5109).
|
||||
*/
|
||||
class ForwardErrorCorrection
|
||||
{
|
||||
public:
|
||||
class ForwardErrorCorrection {
|
||||
public:
|
||||
// Maximum number of media packets we can protect
|
||||
static const int kMaxMediaPackets = 48;
|
||||
|
||||
// Maximum number of media packets we can protect
|
||||
static const int kMaxMediaPackets = 48;
|
||||
struct Packet {
|
||||
uint16_t length; /**> Length of packet in bytes. */
|
||||
uint8_t data[IP_PACKET_SIZE]; /**> Packet data. */
|
||||
};
|
||||
|
||||
/**
|
||||
* The ListWrapper parameters of #GenerateFEC() should reference structs of this type.
|
||||
*/
|
||||
struct Packet
|
||||
{
|
||||
WebRtc_UWord16 length; /**> Length of packet in bytes. */
|
||||
WebRtc_UWord8 data[IP_PACKET_SIZE]; /**> Packet data. */
|
||||
};
|
||||
/**
|
||||
* The received list parameter of #DecodeFEC() must reference structs of this
|
||||
* type. The lastMediaPktInFrame is not required to be used for correct
|
||||
* recovery, but will reduce delay by allowing #DecodeFEC() to pre-emptively
|
||||
* determine frame completion. If set, we assume a FEC stream, and the
|
||||
* following assumptions must hold:\n
|
||||
*
|
||||
* 1. The media packets in a frame have contiguous sequence numbers, i.e. the
|
||||
* frame's FEC packets have sequence numbers either lower than the first
|
||||
* media packet or higher than the last media packet.\n
|
||||
* 2. All FEC packets have a sequence number base equal to the first media
|
||||
* packet in the corresponding frame.\n
|
||||
*
|
||||
* The ssrc member is needed to ensure we can restore the SSRC field of
|
||||
* recovered packets. In most situations this could be retrieved from other
|
||||
* media packets, but in the case of an FEC packet protecting a single
|
||||
* missing media packet, we have no other means of obtaining it.
|
||||
*/
|
||||
struct ReceivedPacket {
|
||||
uint16_t seqNum; /**> Sequence number of packet. */
|
||||
uint32_t ssrc; /**> SSRC of the current frame. Must be set for FEC
|
||||
packets, but not required for media packets. */
|
||||
bool isFec; /**> Set to true if this is an FEC packet and false
|
||||
otherwise. */
|
||||
bool lastMediaPktInFrame; /**> Set to true to mark the last media packet in
|
||||
the frame and false otherwise. */
|
||||
Packet* pkt; /**> Pointer to the packet storage. */
|
||||
};
|
||||
|
||||
/**
|
||||
* The received list parameter of #DecodeFEC() must reference structs of this type.
|
||||
* The lastMediaPktInFrame is not required to be used for correct recovery, but will
|
||||
* reduce delay by allowing #DecodeFEC() to pre-emptively determine frame completion.
|
||||
* If set, we assume a FEC stream, and the following assumptions must hold:\n
|
||||
*
|
||||
* 1. The media packets in a frame have contiguous sequence numbers, i.e. the frame's
|
||||
* FEC packets have sequence numbers either lower than the first media packet or
|
||||
* higher than the last media packet.\n
|
||||
* 2. All FEC packets have a sequence number base equal to the first media packet in
|
||||
* the corresponding frame.\n
|
||||
*
|
||||
* The ssrc member is needed to ensure we can restore the SSRC field of recovered
|
||||
* packets. In most situations this could be retrieved from other media packets, but
|
||||
* in the case of an FEC packet protecting a single missing media packet, we have no
|
||||
* other means of obtaining it.
|
||||
*/
|
||||
struct ReceivedPacket
|
||||
{
|
||||
WebRtc_UWord16 seqNum; /**> Sequence number of packet. */
|
||||
WebRtc_UWord32 ssrc; /**> SSRC of the current frame. Must be set for FEC
|
||||
packets, but not required for media packets. */
|
||||
bool isFec; /**> Set to true if this is an FEC packet and false
|
||||
otherwise. */
|
||||
bool lastMediaPktInFrame; /**> Set to true to mark the last media packet in the
|
||||
frame and false otherwise. */
|
||||
Packet* pkt; /**> Pointer to the packet storage. */
|
||||
};
|
||||
/**
|
||||
* The recovered list parameter of #DecodeFEC() will reference structs of
|
||||
* this type.
|
||||
*/
|
||||
struct RecoveredPacket {
|
||||
bool wasRecovered; /**> Will be true if this packet was recovered by
|
||||
the FEC. Otherwise it was a media packet passed in
|
||||
through the received packet list. */
|
||||
uint16_t seqNum; /**> Sequence number of the packet. This is mostly for
|
||||
implementation convenience but could be utilized
|
||||
by the user if so desired. */
|
||||
Packet* pkt; /**> Pointer to the packet storage. */
|
||||
};
|
||||
|
||||
/**
|
||||
* The recovered list parameter of #DecodeFEC() will reference structs of this type.
|
||||
*/
|
||||
struct RecoveredPacket
|
||||
{
|
||||
bool wasRecovered; /**> Will be true if this packet was recovered by the FEC.
|
||||
Otherwise it was a media packet passed in through the
|
||||
received packet list. */
|
||||
WebRtc_UWord16 seqNum; /**> Sequence number of the packet. This is mostly for
|
||||
implementation convenience but could be utilized by the
|
||||
user if so desired. */
|
||||
Packet* pkt; /**> Pointer to the packet storage. */
|
||||
};
|
||||
/**
|
||||
* \param[in] id Module ID
|
||||
*/
|
||||
ForwardErrorCorrection(int32_t id);
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* \param[in] id Module ID
|
||||
*/
|
||||
ForwardErrorCorrection(WebRtc_Word32 id);
|
||||
virtual ~ForwardErrorCorrection();
|
||||
|
||||
/**
|
||||
* Destructor. Before freeing an instance of the class, #DecodeFEC() must be called
|
||||
* in a particular fashion to free outstanding memory. Refer to #DecodeFEC().
|
||||
*/
|
||||
virtual ~ForwardErrorCorrection();
|
||||
/**
|
||||
* Generates a list of FEC packets from supplied media packets.
|
||||
*
|
||||
* \param[in] mediaPacketList List of media packets to protect, of type
|
||||
* #Packet. All packets must belong to the
|
||||
* same frame and the list must not be empty.
|
||||
* \param[in] protectionFactor FEC protection overhead in the [0, 255]
|
||||
* domain. To obtain 100% overhead, or an
|
||||
* equal number of FEC packets as media
|
||||
* packets, use 255.
|
||||
* \param[in] numImportantPackets The number of "important" packets in the
|
||||
* frame. These packets may receive greater
|
||||
* protection than the remaining packets. The
|
||||
* important packets must be located at the
|
||||
* start of the media packet list. For codecs
|
||||
* with data partitioning, the important
|
||||
* packets may correspond to first partition
|
||||
* packets.
|
||||
* \param[in] useUnequalProtection Parameter to enable/disable unequal
|
||||
* protection (UEP) across packets. Enabling
|
||||
* UEP will allocate more protection to the
|
||||
* numImportantPackets from the start of the
|
||||
* mediaPacketList.
|
||||
* \param[out] fecPacketList List of FEC packets, of type #Packet. Must
|
||||
* be empty on entry. The memory available
|
||||
* through the list will be valid until the
|
||||
* next call to GenerateFEC().
|
||||
*
|
||||
* \return 0 on success, -1 on failure.
|
||||
*/
|
||||
int32_t GenerateFEC(const std::list<Packet*>& mediaPacketList,
|
||||
uint8_t protectionFactor,
|
||||
int numImportantPackets,
|
||||
bool useUnequalProtection,
|
||||
std::list<Packet*>* fecPacketList);
|
||||
|
||||
/**
|
||||
* Generates a list of FEC packets from supplied media packets.
|
||||
*
|
||||
* \param[in] mediaPacketList List of media packets to protect, of type #Packet.
|
||||
* All packets must belong to the same frame and the
|
||||
* list must not be empty.
|
||||
* \param[in] protectionFactor FEC protection overhead in the [0, 255] domain. To
|
||||
* obtain 100% overhead, or an equal number of FEC
|
||||
* packets as media packets, use 255.
|
||||
* \param[in] numImportantPackets The number of "important" packets in the frame.
|
||||
* These packets may receive greater protection than
|
||||
* the remaining packets. The important packets must
|
||||
* be located at the start of the media packet list.
|
||||
* For codecs with data partitioning, the important
|
||||
* packets may correspond to first partition packets.
|
||||
* \param[in] useUnequalProtection Parameter to enable/disable unequal protection
|
||||
* (UEP) across packets. Enabling UEP will allocate more
|
||||
* protection to the numImportantPackets from
|
||||
* the start of the mediaPacketList.
|
||||
* \param[out] fecPacketList List of FEC packets, of type #Packet. Must be empty
|
||||
* on entry. The memory available through the list
|
||||
* will be valid until the next call to GenerateFEC().
|
||||
*
|
||||
* \return 0 on success, -1 on failure.
|
||||
*/
|
||||
WebRtc_Word32 GenerateFEC(const ListWrapper& mediaPacketList,
|
||||
WebRtc_UWord8 protectionFactor,
|
||||
int numImportantPackets,
|
||||
bool useUnequalProtection,
|
||||
ListWrapper& fecPacketList);
|
||||
/**
|
||||
* Decodes a list of media and FEC packets. It will parse the input received
|
||||
* packet list, storing FEC packets internally and inserting media packets to
|
||||
* the output recovered packet list. The recovered list will be sorted by
|
||||
* as cending sequence number and have duplicates removed. The function
|
||||
* should be called as new packets arrive, with the recovered list being
|
||||
* progressively assembled with each call. The received packet list will be
|
||||
* empty at output.\n
|
||||
*
|
||||
* The user will allocate packets submitted through the received list. The
|
||||
* function will handle allocation of recovered packets and optionally
|
||||
* deleting of all packet memory. The user may delete the recovered list
|
||||
* packets, in which case they must remove deleted packets from the
|
||||
* recovered list.\n
|
||||
*
|
||||
* Before deleting an instance of the class, call the function with an empty
|
||||
* received packet list and the completion parameter set to true. This will
|
||||
* free any outstanding memory.
|
||||
*
|
||||
* \param[in] receivedPacketList List of new received packets, of type
|
||||
* #ReceivedPacket, beloning to a single
|
||||
* frame. At output the list will be empty,
|
||||
* with packets either stored internally,
|
||||
* or accessible through the recovered list.
|
||||
* \param[out] recoveredPacketList List of recovered media packets, of type
|
||||
* #RecoveredPacket, belonging to a single
|
||||
* frame. The memory available through the
|
||||
* list will be valid until the next call to
|
||||
* DecodeFEC() in which the completion
|
||||
* parameter is set to true.
|
||||
* \param[in] lastFECSeqNum Estimated last seqNumber before this frame.
|
||||
* \param[in,out] frameComplete Set to true on input to indicate the start
|
||||
* of a new frame. On output, this will be
|
||||
* set to true if all media packets in the
|
||||
* frame have been recovered. Note that the
|
||||
* frame may be complete without this
|
||||
* parameter having been set, as it may not
|
||||
* always be possible to determine frame
|
||||
* completion.
|
||||
*
|
||||
* \return 0 on success, -1 on failure.
|
||||
*/
|
||||
int32_t DecodeFEC(std::list<ReceivedPacket*>* receivedPacketList,
|
||||
std::list<RecoveredPacket*>* recoveredPacketList,
|
||||
uint16_t lastFECSeqNum,
|
||||
bool& frameComplete);
|
||||
/**
|
||||
* Gets the size in bytes of the FEC/ULP headers, which must be accounted for
|
||||
* as packet overhead.
|
||||
* \return Packet overhead in bytes.
|
||||
*/
|
||||
static uint16_t PacketOverhead();
|
||||
|
||||
/**
|
||||
* Decodes a list of media and FEC packets. It will parse the input received packet
|
||||
* list, storing FEC packets internally and inserting media packets to the output
|
||||
* recovered packet list. The recovered list will be sorted by ascending sequence
|
||||
* number and have duplicates removed. The function should be called as new packets
|
||||
* arrive, with the recovered list being progressively assembled with each call.
|
||||
* The received packet list will be empty at output.\n
|
||||
*
|
||||
* The user will allocate packets submitted through the received list. The function
|
||||
* will handle allocation of recovered packets and optionally deleting of all packet
|
||||
* memory. The user may delete the recovered list packets, in which case they must
|
||||
* remove deleted packets from the recovered list.\n
|
||||
*
|
||||
* Before deleting an instance of the class, call the function with an empty received
|
||||
* packet list and the completion parameter set to true. This will free any
|
||||
* outstanding memory.
|
||||
*
|
||||
* \param[in] receivedPacketList List of new received packets, of type
|
||||
* #ReceivedPacket, beloning to a single frame. At
|
||||
* output the list will be empty, with packets
|
||||
* either stored internally, or accessible through
|
||||
* the recovered list.
|
||||
* \param[out] recoveredPacketList List of recovered media packets, of type
|
||||
* #RecoveredPacket, belonging to a single frame.
|
||||
* The memory available through the list will be
|
||||
* valid until the next call to DecodeFEC() in which
|
||||
* the completion parameter is set to true.
|
||||
* \param[in] lastFECSeqNum Estimated last seqNumber before this frame
|
||||
* \param[in,out] frameComplete Set to true on input to indicate the start of a
|
||||
* new frame. On output, this will be set to true if
|
||||
* all media packets in the frame have been
|
||||
* recovered. Note that the frame may be complete
|
||||
* without this parameter having been set, as it may
|
||||
* not always be possible to determine frame
|
||||
* completion.
|
||||
*
|
||||
* \return 0 on success, -1 on failure.
|
||||
*/
|
||||
WebRtc_Word32 DecodeFEC(ListWrapper& receivedPacketList,
|
||||
ListWrapper& recoveredPacketList,
|
||||
WebRtc_UWord16 lastFECSeqNum,
|
||||
bool& frameComplete);
|
||||
/**
|
||||
* Gets the size in bytes of the FEC/ULP headers, which must be accounted for as
|
||||
* packet overhead.
|
||||
* \return Packet overhead in bytes.
|
||||
*/
|
||||
static WebRtc_UWord16 PacketOverhead();
|
||||
private:
|
||||
// True if first is <= than second.
|
||||
static bool CompareRecoveredPackets(RecoveredPacket* first,
|
||||
RecoveredPacket* second);
|
||||
|
||||
private:
|
||||
WebRtc_Word32 _id;
|
||||
Packet* _generatedFecPackets;
|
||||
ListWrapper _fecPacketList;
|
||||
WebRtc_UWord16 _seqNumBase;
|
||||
bool _lastMediaPacketReceived;
|
||||
bool _fecPacketReceived;
|
||||
void GenerateFecUlpHeaders(const std::list<Packet*>& mediaPacketList,
|
||||
uint8_t* packetMask,
|
||||
uint32_t numFecPackets);
|
||||
|
||||
void GenerateFecBitStrings(const std::list<Packet*>& mediaPacketList,
|
||||
uint8_t* packetMask,
|
||||
uint32_t numFecPackets);
|
||||
|
||||
// Reset internal states from last frame and clear the recoveredPacketList.
|
||||
void ResetState(std::list<RecoveredPacket*>* recoveredPacketList);
|
||||
|
||||
// Insert received packets into FEC or recovered list.
|
||||
void InsertPackets(std::list<ReceivedPacket*>* receivedPacketList,
|
||||
std::list<RecoveredPacket*>* recoveredPacketList);
|
||||
|
||||
// Insert media packet into recovered packet list. We delete duplicates.
|
||||
void InsertMediaPacket(ReceivedPacket* rxPacket,
|
||||
std::list<RecoveredPacket*>* recoveredPacketList);
|
||||
|
||||
// Insert packet into FEC list. We delete duplicates.
|
||||
void InsertFECPacket(ReceivedPacket* rxPacket);
|
||||
|
||||
// Insert into recovered list in correct position.
|
||||
void InsertRecoveredPacket(
|
||||
RecoveredPacket* recPacketToInsert,
|
||||
std::list<RecoveredPacket*>* recoveredPacketList);
|
||||
|
||||
// Attempt to recover missing packets.
|
||||
void AttemptRecover(std::list<RecoveredPacket*>* recoveredPacketList);
|
||||
|
||||
// Recover a missing packet.
|
||||
void RecoverPacket(const FecPacket& fecPacket,
|
||||
RecoveredPacket* recPacketToInsert);
|
||||
|
||||
// Get number of protected packet in the fecPacket.
|
||||
uint32_t NumberOfProtectedPackets(
|
||||
const FecPacket& fecPacket,
|
||||
std::list<RecoveredPacket*>* recoveredPacketList);
|
||||
|
||||
int32_t _id;
|
||||
std::vector<Packet> _generatedFecPackets;
|
||||
std::list<FecPacket*> _fecPacketList;
|
||||
uint16_t _seqNumBase;
|
||||
bool _lastMediaPacketReceived;
|
||||
bool _fecPacketReceived;
|
||||
};
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // WEBRTC_MODULES_RTP_RTCP_SOURCE_FORWARD_ERROR_CORRECTION_H_
|
||||
|
@ -16,42 +16,35 @@
|
||||
|
||||
// RFC 5109
|
||||
namespace webrtc {
|
||||
ReceiverFEC::ReceiverFEC(const WebRtc_Word32 id, RTPReceiverVideo* owner) :
|
||||
_owner(owner),
|
||||
_fec(new ForwardErrorCorrection(id)),
|
||||
_payloadTypeFEC(-1),
|
||||
_lastFECSeqNum(0),
|
||||
_frameComplete(true)
|
||||
{
|
||||
ReceiverFEC::ReceiverFEC(const WebRtc_Word32 id, RTPReceiverVideo* owner)
|
||||
: _owner(owner),
|
||||
_fec(new ForwardErrorCorrection(id)),
|
||||
_payloadTypeFEC(-1),
|
||||
_lastFECSeqNum(0),
|
||||
_frameComplete(true) {
|
||||
}
|
||||
|
||||
ReceiverFEC::~ReceiverFEC()
|
||||
{
|
||||
// Clean up DecodeFEC()
|
||||
while (_receivedPacketList.First() != NULL)
|
||||
{
|
||||
ForwardErrorCorrection::ReceivedPacket* receivedPacket =
|
||||
static_cast<ForwardErrorCorrection::ReceivedPacket*>(
|
||||
_receivedPacketList.First()->GetItem());
|
||||
delete receivedPacket->pkt;
|
||||
delete receivedPacket;
|
||||
receivedPacket = NULL;
|
||||
_receivedPacketList.PopFront();
|
||||
}
|
||||
assert(_receivedPacketList.Empty());
|
||||
ReceiverFEC::~ReceiverFEC() {
|
||||
// Clean up DecodeFEC()
|
||||
while (!_receivedPacketList.empty()){
|
||||
ForwardErrorCorrection::ReceivedPacket* receivedPacket =
|
||||
_receivedPacketList.front();
|
||||
delete receivedPacket->pkt;
|
||||
delete receivedPacket;
|
||||
_receivedPacketList.pop_front();
|
||||
}
|
||||
assert(_receivedPacketList.empty());
|
||||
|
||||
if (_fec != NULL)
|
||||
{
|
||||
bool frameComplete = true;
|
||||
_fec->DecodeFEC(_receivedPacketList, _recoveredPacketList,_lastFECSeqNum, frameComplete);
|
||||
delete _fec;
|
||||
}
|
||||
if (_fec != NULL) {
|
||||
bool frameComplete = true;
|
||||
_fec->DecodeFEC(&_receivedPacketList, &_recoveredPacketList,_lastFECSeqNum,
|
||||
frameComplete);
|
||||
delete _fec;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ReceiverFEC::SetPayloadTypeFEC(const WebRtc_Word8 payloadType)
|
||||
{
|
||||
_payloadTypeFEC = payloadType;
|
||||
void ReceiverFEC::SetPayloadTypeFEC(const WebRtc_Word8 payloadType) {
|
||||
_payloadTypeFEC = payloadType;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -84,279 +77,242 @@ RFC 2198 RTP Payload for Redundant Audio Data September 1997
|
||||
block excluding header.
|
||||
*/
|
||||
|
||||
WebRtc_Word32
|
||||
ReceiverFEC::AddReceivedFECPacket(const WebRtcRTPHeader* rtpHeader,
|
||||
const WebRtc_UWord8* incomingRtpPacket,
|
||||
const WebRtc_UWord16 payloadDataLength,
|
||||
bool& FECpacket,
|
||||
bool oldPacket)
|
||||
{
|
||||
if (_payloadTypeFEC == -1)
|
||||
{
|
||||
return -1;
|
||||
WebRtc_Word32 ReceiverFEC::AddReceivedFECPacket(
|
||||
const WebRtcRTPHeader* rtpHeader,
|
||||
const WebRtc_UWord8* incomingRtpPacket,
|
||||
const WebRtc_UWord16 payloadDataLength,
|
||||
bool& FECpacket,
|
||||
bool oldPacket) {
|
||||
if (_payloadTypeFEC == -1) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
WebRtc_UWord8 REDHeaderLength = 1;
|
||||
|
||||
// Add to list without RED header, aka a virtual RTP packet
|
||||
// we remove the RED header
|
||||
|
||||
ForwardErrorCorrection::ReceivedPacket* receivedPacket =
|
||||
new ForwardErrorCorrection::ReceivedPacket;
|
||||
receivedPacket->pkt = new ForwardErrorCorrection::Packet;
|
||||
|
||||
// get payload type from RED header
|
||||
WebRtc_UWord8 payloadType =
|
||||
incomingRtpPacket[rtpHeader->header.headerLength] & 0x7f;
|
||||
|
||||
// use the payloadType to decide if it's FEC or coded data
|
||||
if(_payloadTypeFEC == payloadType) {
|
||||
receivedPacket->isFec = true;
|
||||
FECpacket = true;
|
||||
// We don't need to parse old FEC packets.
|
||||
// Old FEC packets are sent to jitter buffer as empty packets in the
|
||||
// callback in rtp_receiver_video.
|
||||
if (oldPacket) return 0;
|
||||
} else {
|
||||
receivedPacket->isFec = false;
|
||||
FECpacket = false;
|
||||
}
|
||||
receivedPacket->lastMediaPktInFrame = rtpHeader->header.markerBit;
|
||||
receivedPacket->seqNum = rtpHeader->header.sequenceNumber;
|
||||
|
||||
WebRtc_UWord16 blockLength = 0;
|
||||
if(incomingRtpPacket[rtpHeader->header.headerLength] & 0x80) {
|
||||
// f bit set in RED header
|
||||
REDHeaderLength = 4;
|
||||
WebRtc_UWord16 timestampOffset =
|
||||
(incomingRtpPacket[rtpHeader->header.headerLength + 1]) << 8;
|
||||
timestampOffset += incomingRtpPacket[rtpHeader->header.headerLength+2];
|
||||
timestampOffset = timestampOffset >> 2;
|
||||
if(timestampOffset != 0) {
|
||||
// sanity timestampOffset must be 0
|
||||
assert(false);
|
||||
return -1;
|
||||
}
|
||||
blockLength =
|
||||
(0x03 & incomingRtpPacket[rtpHeader->header.headerLength + 2]) << 8;
|
||||
blockLength += (incomingRtpPacket[rtpHeader->header.headerLength + 3]);
|
||||
|
||||
// check next RED header
|
||||
if(incomingRtpPacket[rtpHeader->header.headerLength+4] & 0x80) {
|
||||
// more than 2 blocks in packet not supported
|
||||
assert(false);
|
||||
return -1;
|
||||
}
|
||||
if(blockLength > payloadDataLength - REDHeaderLength) {
|
||||
// block length longer than packet
|
||||
assert(false);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
ForwardErrorCorrection::ReceivedPacket* secondReceivedPacket = NULL;
|
||||
if (blockLength > 0) {
|
||||
// handle block length, split into 2 packets
|
||||
REDHeaderLength = 5;
|
||||
|
||||
// copy the RTP header
|
||||
memcpy(receivedPacket->pkt->data,
|
||||
incomingRtpPacket,
|
||||
rtpHeader->header.headerLength);
|
||||
|
||||
// replace the RED payload type
|
||||
receivedPacket->pkt->data[1] &= 0x80; // reset the payload
|
||||
receivedPacket->pkt->data[1] += payloadType; // set the media payload type
|
||||
|
||||
// copy the payload data
|
||||
memcpy(receivedPacket->pkt->data + rtpHeader->header.headerLength,
|
||||
incomingRtpPacket + rtpHeader->header.headerLength + REDHeaderLength,
|
||||
blockLength);
|
||||
|
||||
receivedPacket->pkt->length = blockLength;
|
||||
|
||||
secondReceivedPacket = new ForwardErrorCorrection::ReceivedPacket;
|
||||
secondReceivedPacket->pkt = new ForwardErrorCorrection::Packet;
|
||||
|
||||
secondReceivedPacket->isFec = true;
|
||||
secondReceivedPacket->lastMediaPktInFrame = false;
|
||||
secondReceivedPacket->seqNum = rtpHeader->header.sequenceNumber;
|
||||
|
||||
// copy the FEC payload data
|
||||
memcpy(secondReceivedPacket->pkt->data,
|
||||
incomingRtpPacket + rtpHeader->header.headerLength +
|
||||
REDHeaderLength + blockLength,
|
||||
payloadDataLength - REDHeaderLength - blockLength);
|
||||
|
||||
secondReceivedPacket->pkt->length = payloadDataLength - REDHeaderLength -
|
||||
blockLength;
|
||||
|
||||
} else if(receivedPacket->isFec) {
|
||||
// everything behind the RED header
|
||||
memcpy(receivedPacket->pkt->data,
|
||||
incomingRtpPacket + rtpHeader->header.headerLength + REDHeaderLength,
|
||||
payloadDataLength - REDHeaderLength);
|
||||
receivedPacket->pkt->length = payloadDataLength - REDHeaderLength;
|
||||
receivedPacket->ssrc =
|
||||
ModuleRTPUtility::BufferToUWord32(&incomingRtpPacket[8]);
|
||||
|
||||
} else {
|
||||
// copy the RTP header
|
||||
memcpy(receivedPacket->pkt->data,
|
||||
incomingRtpPacket,
|
||||
rtpHeader->header.headerLength);
|
||||
|
||||
// replace the RED payload type
|
||||
receivedPacket->pkt->data[1] &= 0x80; // reset the payload
|
||||
receivedPacket->pkt->data[1] += payloadType; // set the media payload type
|
||||
|
||||
// copy the media payload data
|
||||
memcpy(receivedPacket->pkt->data + rtpHeader->header.headerLength,
|
||||
incomingRtpPacket + rtpHeader->header.headerLength + REDHeaderLength,
|
||||
payloadDataLength - REDHeaderLength);
|
||||
|
||||
receivedPacket->pkt->length = rtpHeader->header.headerLength +
|
||||
payloadDataLength - REDHeaderLength;
|
||||
}
|
||||
|
||||
if(receivedPacket->isFec) {
|
||||
AddReceivedFECInfo(rtpHeader, NULL, FECpacket);
|
||||
}
|
||||
|
||||
if(receivedPacket->pkt->length == 0) {
|
||||
delete receivedPacket->pkt;
|
||||
delete receivedPacket;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Send any old media packets to jitter buffer, don't push them onto
|
||||
// received list for FEC decoding (we don't do FEC decoding on old packets).
|
||||
if (oldPacket && receivedPacket->isFec == false) {
|
||||
if (ParseAndReceivePacket(receivedPacket->pkt) != 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
WebRtc_UWord8 REDHeaderLength = 1;
|
||||
delete receivedPacket->pkt;
|
||||
delete receivedPacket;
|
||||
} else {
|
||||
_receivedPacketList.push_back(receivedPacket);
|
||||
if (secondReceivedPacket) {
|
||||
_receivedPacketList.push_back(secondReceivedPacket);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Add to list without RED header, aka a virtual RTP packet
|
||||
// we remove the RED header
|
||||
|
||||
ForwardErrorCorrection::ReceivedPacket* receivedPacket = new ForwardErrorCorrection::ReceivedPacket;
|
||||
receivedPacket->pkt = new ForwardErrorCorrection::Packet;
|
||||
void ReceiverFEC::AddReceivedFECInfo(const WebRtcRTPHeader* rtpHeader,
|
||||
const WebRtc_UWord8* incomingRtpPacket,
|
||||
bool& FECpacket) {
|
||||
// store the highest FEC seq num received
|
||||
if (_lastFECSeqNum >= rtpHeader->header.sequenceNumber) {
|
||||
if (_lastFECSeqNum > 0xff00 && rtpHeader->header.sequenceNumber < 0x0ff ) {
|
||||
// wrap
|
||||
_lastFECSeqNum = rtpHeader->header.sequenceNumber;
|
||||
} else {
|
||||
// old seqNum
|
||||
}
|
||||
} else {
|
||||
// check for a wrap
|
||||
if(rtpHeader->header.sequenceNumber > 0xff00 && _lastFECSeqNum < 0x0ff ) {
|
||||
// old seqNum
|
||||
} else {
|
||||
_lastFECSeqNum = rtpHeader->header.sequenceNumber;
|
||||
}
|
||||
}
|
||||
|
||||
if (incomingRtpPacket) {
|
||||
// get payload type from RED header
|
||||
WebRtc_UWord8 payloadType = incomingRtpPacket[rtpHeader->header.headerLength] & 0x7f;
|
||||
WebRtc_UWord8 payloadType =
|
||||
incomingRtpPacket[rtpHeader->header.headerLength] & 0x7f;
|
||||
|
||||
// use the payloadType to decide if it's FEC or coded data
|
||||
if(_payloadTypeFEC == payloadType)
|
||||
{
|
||||
receivedPacket->isFec = true;
|
||||
FECpacket = true;
|
||||
// We don't need to parse old FEC packets.
|
||||
// Old FEC packets are sent to jitter buffer as empty packets in the
|
||||
// callback in rtp_receiver_video.
|
||||
if (oldPacket)
|
||||
return 0;
|
||||
} else
|
||||
{
|
||||
receivedPacket->isFec = false;
|
||||
FECpacket = false;
|
||||
if(_payloadTypeFEC == payloadType) {
|
||||
FECpacket = true;
|
||||
} else {
|
||||
FECpacket = false;
|
||||
}
|
||||
receivedPacket->lastMediaPktInFrame = rtpHeader->header.markerBit;
|
||||
receivedPacket->seqNum = rtpHeader->header.sequenceNumber;
|
||||
|
||||
WebRtc_UWord16 blockLength = 0;
|
||||
if(incomingRtpPacket[rtpHeader->header.headerLength] & 0x80)
|
||||
{
|
||||
// f bit set in RED header
|
||||
REDHeaderLength = 4;
|
||||
WebRtc_UWord16 timestampOffset = (incomingRtpPacket[rtpHeader->header.headerLength + 1]) << 8;
|
||||
timestampOffset += incomingRtpPacket[rtpHeader->header.headerLength+2];
|
||||
timestampOffset = timestampOffset >> 2;
|
||||
if(timestampOffset != 0)
|
||||
{
|
||||
// sanity timestampOffset must be 0
|
||||
assert(false);
|
||||
return -1;
|
||||
}
|
||||
blockLength = (0x03 & incomingRtpPacket[rtpHeader->header.headerLength + 2]) << 8;
|
||||
blockLength += (incomingRtpPacket[rtpHeader->header.headerLength + 3]);
|
||||
|
||||
// check next RED header
|
||||
if(incomingRtpPacket[rtpHeader->header.headerLength+4] & 0x80)
|
||||
{
|
||||
// more than 2 blocks in packet not supported
|
||||
assert(false);
|
||||
return -1;
|
||||
}
|
||||
if(blockLength > payloadDataLength - REDHeaderLength)
|
||||
{
|
||||
// block length longer than packet
|
||||
assert(false);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
ForwardErrorCorrection::ReceivedPacket* secondReceivedPacket = NULL;
|
||||
if(blockLength > 0)
|
||||
{
|
||||
// handle block length, split into 2 packets
|
||||
REDHeaderLength = 5;
|
||||
|
||||
// copy the RTP header
|
||||
memcpy(receivedPacket->pkt->data,
|
||||
incomingRtpPacket,
|
||||
rtpHeader->header.headerLength);
|
||||
|
||||
// replace the RED payload type
|
||||
receivedPacket->pkt->data[1] &= 0x80; // reset the payload
|
||||
receivedPacket->pkt->data[1] += payloadType; // set the media payload type
|
||||
|
||||
// copy the payload data
|
||||
memcpy(receivedPacket->pkt->data + rtpHeader->header.headerLength,
|
||||
incomingRtpPacket + rtpHeader->header.headerLength + REDHeaderLength,
|
||||
blockLength);
|
||||
|
||||
receivedPacket->pkt->length = blockLength;
|
||||
|
||||
secondReceivedPacket = new ForwardErrorCorrection::ReceivedPacket;
|
||||
secondReceivedPacket->pkt = new ForwardErrorCorrection::Packet;
|
||||
|
||||
secondReceivedPacket->isFec = true;
|
||||
secondReceivedPacket->lastMediaPktInFrame = false;
|
||||
secondReceivedPacket->seqNum = rtpHeader->header.sequenceNumber;
|
||||
|
||||
// copy the FEC payload data
|
||||
memcpy(secondReceivedPacket->pkt->data,
|
||||
incomingRtpPacket + rtpHeader->header.headerLength + REDHeaderLength +
|
||||
blockLength, payloadDataLength - REDHeaderLength - blockLength);
|
||||
|
||||
secondReceivedPacket->pkt->length = payloadDataLength - REDHeaderLength -
|
||||
blockLength;
|
||||
|
||||
} else if(receivedPacket->isFec)
|
||||
{
|
||||
// everything behind the RED header
|
||||
memcpy(receivedPacket->pkt->data,
|
||||
incomingRtpPacket + rtpHeader->header.headerLength + REDHeaderLength,
|
||||
payloadDataLength - REDHeaderLength);
|
||||
receivedPacket->pkt->length = payloadDataLength - REDHeaderLength;
|
||||
receivedPacket->ssrc = ModuleRTPUtility::BufferToUWord32(&incomingRtpPacket[8]);
|
||||
|
||||
}else
|
||||
{
|
||||
// copy the RTP header
|
||||
memcpy(receivedPacket->pkt->data,
|
||||
incomingRtpPacket,
|
||||
rtpHeader->header.headerLength);
|
||||
|
||||
// replace the RED payload type
|
||||
receivedPacket->pkt->data[1] &= 0x80; // reset the payload
|
||||
receivedPacket->pkt->data[1] += payloadType; // set the media payload type
|
||||
|
||||
// copy the media payload data
|
||||
memcpy(receivedPacket->pkt->data + rtpHeader->header.headerLength,
|
||||
incomingRtpPacket + rtpHeader->header.headerLength + REDHeaderLength,
|
||||
payloadDataLength - REDHeaderLength);
|
||||
|
||||
receivedPacket->pkt->length = rtpHeader->header.headerLength +
|
||||
payloadDataLength - REDHeaderLength;
|
||||
}
|
||||
|
||||
if(receivedPacket->isFec)
|
||||
{
|
||||
AddReceivedFECInfo(rtpHeader, NULL, FECpacket);
|
||||
}
|
||||
|
||||
if(receivedPacket->pkt->length == 0)
|
||||
{
|
||||
delete receivedPacket->pkt;
|
||||
delete receivedPacket;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Send any old media packets to jitter buffer, don't push them onto
|
||||
// received list for FEC decoding (we don't do FEC decoding on old packets).
|
||||
if (oldPacket && receivedPacket->isFec == false)
|
||||
{
|
||||
if (ParseAndReceivePacket(receivedPacket->pkt) != 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
delete receivedPacket->pkt;
|
||||
delete receivedPacket;
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
_receivedPacketList.PushBack(receivedPacket);
|
||||
if (secondReceivedPacket)
|
||||
{
|
||||
_receivedPacketList.PushBack(secondReceivedPacket);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ReceiverFEC::AddReceivedFECInfo(const WebRtcRTPHeader* rtpHeader,
|
||||
const WebRtc_UWord8* incomingRtpPacket,
|
||||
bool& FECpacket)
|
||||
{
|
||||
// store the highest FEC seq num received
|
||||
if(_lastFECSeqNum >= rtpHeader->header.sequenceNumber)
|
||||
{
|
||||
if(_lastFECSeqNum > 0xff00 && rtpHeader->header.sequenceNumber < 0x0ff ) //detect wrap around
|
||||
{
|
||||
// wrap
|
||||
_lastFECSeqNum = rtpHeader->header.sequenceNumber;
|
||||
} else
|
||||
{
|
||||
// old seqNum
|
||||
}
|
||||
}else
|
||||
{
|
||||
// check for a wrap
|
||||
if(rtpHeader->header.sequenceNumber > 0xff00 && _lastFECSeqNum < 0x0ff ) //detect wrap around
|
||||
{
|
||||
// old seqNum
|
||||
}else
|
||||
{
|
||||
_lastFECSeqNum = rtpHeader->header.sequenceNumber;
|
||||
}
|
||||
WebRtc_Word32 ReceiverFEC::ProcessReceivedFEC(const bool forceFrameDecode) {
|
||||
if (!_receivedPacketList.empty()) {
|
||||
if (_fec->DecodeFEC(&_receivedPacketList, &_recoveredPacketList,
|
||||
_lastFECSeqNum, _frameComplete) != 0) {
|
||||
return -1;
|
||||
}
|
||||
assert(_receivedPacketList.empty());
|
||||
}
|
||||
if (forceFrameDecode) {
|
||||
_frameComplete = true;
|
||||
}
|
||||
if (_frameComplete) {
|
||||
while (!_recoveredPacketList.empty()) {
|
||||
ForwardErrorCorrection::RecoveredPacket* recoveredPacket =
|
||||
_recoveredPacketList.front();
|
||||
|
||||
if(incomingRtpPacket)
|
||||
{
|
||||
// get payload type from RED header
|
||||
WebRtc_UWord8 payloadType = incomingRtpPacket[rtpHeader->header.headerLength] & 0x7f;
|
||||
|
||||
// use the payloadType to decide if it's FEC or coded data
|
||||
if(_payloadTypeFEC == payloadType)
|
||||
{
|
||||
FECpacket = true;
|
||||
} else
|
||||
{
|
||||
FECpacket = false;
|
||||
}
|
||||
if (ParseAndReceivePacket(recoveredPacket->pkt) != 0) {
|
||||
return -1;
|
||||
}
|
||||
delete recoveredPacket->pkt;
|
||||
delete recoveredPacket;
|
||||
_recoveredPacketList.pop_front();
|
||||
}
|
||||
}
|
||||
|
||||
WebRtc_Word32
|
||||
ReceiverFEC::ProcessReceivedFEC(const bool forceFrameDecode)
|
||||
{
|
||||
if (!_receivedPacketList.Empty())
|
||||
{
|
||||
if (_fec->DecodeFEC(_receivedPacketList,
|
||||
_recoveredPacketList,
|
||||
_lastFECSeqNum,
|
||||
_frameComplete) != 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
assert(_receivedPacketList.Empty());
|
||||
}
|
||||
if (forceFrameDecode)
|
||||
{
|
||||
_frameComplete = true;
|
||||
}
|
||||
if (_frameComplete)
|
||||
{
|
||||
while (_recoveredPacketList.First() != NULL)
|
||||
{
|
||||
ForwardErrorCorrection::RecoveredPacket* recoveredPacket =
|
||||
static_cast<ForwardErrorCorrection::RecoveredPacket*>(_recoveredPacketList.First()->GetItem());
|
||||
|
||||
if (ParseAndReceivePacket(recoveredPacket->pkt) != 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
delete recoveredPacket->pkt;
|
||||
delete recoveredPacket;
|
||||
recoveredPacket = NULL;
|
||||
_recoveredPacketList.PopFront();
|
||||
}
|
||||
assert(_recoveredPacketList.Empty());
|
||||
}
|
||||
|
||||
return 0;
|
||||
assert(_recoveredPacketList.empty());
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ReceiverFEC::ParseAndReceivePacket(
|
||||
const ForwardErrorCorrection::Packet* packet) {
|
||||
|
||||
WebRtcRTPHeader header;
|
||||
memset(&header, 0, sizeof(header));
|
||||
ModuleRTPUtility::RTPHeaderParser parser(packet->data,
|
||||
packet->length);
|
||||
packet->length);
|
||||
if (!parser.Parse(header)) {
|
||||
return -1;
|
||||
}
|
||||
if (_owner->ReceiveRecoveredPacketCallback(
|
||||
&header,
|
||||
&packet->data[header.header.headerLength],
|
||||
packet->length - header.header.headerLength) != 0) {
|
||||
&header,
|
||||
&packet->data[header.header.headerLength],
|
||||
packet->length - header.header.headerLength) != 0) {
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
|
@ -11,12 +11,13 @@
|
||||
#ifndef WEBRTC_MODULES_RTP_RTCP_SOURCE_RECEIVER_FEC_H_
|
||||
#define WEBRTC_MODULES_RTP_RTCP_SOURCE_RECEIVER_FEC_H_
|
||||
|
||||
#include <list>
|
||||
|
||||
#include "rtp_rtcp_defines.h"
|
||||
// This header is included to get the nested declaration of Packet structure.
|
||||
#include "forward_error_correction.h"
|
||||
|
||||
#include "typedefs.h"
|
||||
#include "list_wrapper.h"
|
||||
|
||||
namespace webrtc {
|
||||
class RTPReceiverVideo;
|
||||
@ -45,8 +46,8 @@ private:
|
||||
int ParseAndReceivePacket(const ForwardErrorCorrection::Packet* packet);
|
||||
RTPReceiverVideo* _owner;
|
||||
ForwardErrorCorrection* _fec;
|
||||
ListWrapper _receivedPacketList;
|
||||
ListWrapper _recoveredPacketList;
|
||||
std::list<ForwardErrorCorrection::ReceivedPacket*> _receivedPacketList;
|
||||
std::list<ForwardErrorCorrection::RecoveredPacket*> _recoveredPacketList;
|
||||
WebRtc_Word8 _payloadTypeFEC;
|
||||
WebRtc_UWord16 _lastFECSeqNum;
|
||||
bool _frameComplete;
|
||||
|
@ -100,34 +100,29 @@ RTPSenderVideo::VideoCodecType() const
|
||||
return _videoType;
|
||||
}
|
||||
|
||||
WebRtc_Word32
|
||||
RTPSenderVideo::RegisterVideoPayload(
|
||||
const WebRtc_Word8 payloadName[RTP_PAYLOAD_NAME_SIZE],
|
||||
const WebRtc_Word8 payloadType,
|
||||
const WebRtc_UWord32 maxBitRate,
|
||||
ModuleRTPUtility::Payload*& payload)
|
||||
{
|
||||
CriticalSectionScoped cs(_sendVideoCritsect);
|
||||
WebRtc_Word32 RTPSenderVideo::RegisterVideoPayload(
|
||||
const char payloadName[RTP_PAYLOAD_NAME_SIZE],
|
||||
const WebRtc_Word8 payloadType,
|
||||
const WebRtc_UWord32 maxBitRate,
|
||||
ModuleRTPUtility::Payload*& payload) {
|
||||
CriticalSectionScoped cs(_sendVideoCritsect);
|
||||
|
||||
RtpVideoCodecTypes videoType = kRtpNoVideo;
|
||||
if (ModuleRTPUtility::StringCompare(payloadName, "VP8",3))
|
||||
{
|
||||
videoType = kRtpVp8Video;
|
||||
} else if (ModuleRTPUtility::StringCompare(payloadName, "I420", 4))
|
||||
{
|
||||
videoType = kRtpNoVideo;
|
||||
}else
|
||||
{
|
||||
videoType = kRtpNoVideo;
|
||||
return -1;
|
||||
}
|
||||
payload = new ModuleRTPUtility::Payload;
|
||||
strncpy(payload->name, payloadName, RTP_PAYLOAD_NAME_SIZE);
|
||||
payload->typeSpecific.Video.videoCodecType = videoType;
|
||||
payload->typeSpecific.Video.maxRate = maxBitRate;
|
||||
payload->audio = false;
|
||||
|
||||
return 0;
|
||||
RtpVideoCodecTypes videoType = kRtpNoVideo;
|
||||
if (ModuleRTPUtility::StringCompare(payloadName, "VP8",3)) {
|
||||
videoType = kRtpVp8Video;
|
||||
} else if (ModuleRTPUtility::StringCompare(payloadName, "I420", 4)) {
|
||||
videoType = kRtpNoVideo;
|
||||
} else {
|
||||
videoType = kRtpNoVideo;
|
||||
return -1;
|
||||
}
|
||||
payload = new ModuleRTPUtility::Payload;
|
||||
strncpy(payload->name, payloadName, RTP_PAYLOAD_NAME_SIZE - 1);
|
||||
payload->name[RTP_PAYLOAD_NAME_SIZE - 1] = 0; // Null terminate string.
|
||||
payload->typeSpecific.Video.videoCodecType = videoType;
|
||||
payload->typeSpecific.Video.maxRate = maxBitRate;
|
||||
payload->audio = false;
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct RtpPacket
|
||||
@ -156,19 +151,17 @@ RTPSenderVideo::SendVideoPacket(const FrameType frameType,
|
||||
ptrGenericFEC->pkt->length);
|
||||
|
||||
// Add packet to FEC list
|
||||
_rtpPacketListFec.PushBack(ptrGenericFEC);
|
||||
_rtpPacketListFec.push_back(ptrGenericFEC);
|
||||
// FEC can only protect up to kMaxMediaPackets packets
|
||||
if (static_cast<int>(_mediaPacketListFec.GetSize()) <
|
||||
if (static_cast<int>(_mediaPacketListFec.size()) <
|
||||
ForwardErrorCorrection::kMaxMediaPackets)
|
||||
{
|
||||
_mediaPacketListFec.PushBack(ptrGenericFEC->pkt);
|
||||
_mediaPacketListFec.push_back(ptrGenericFEC->pkt);
|
||||
}
|
||||
|
||||
// Last packet in frame
|
||||
if (markerBit)
|
||||
{
|
||||
// Interface for FEC
|
||||
ListWrapper fecPacketList;
|
||||
|
||||
// Retain the RTP header of the last media packet to construct FEC
|
||||
// packet RTP headers.
|
||||
@ -189,23 +182,22 @@ RTPSenderVideo::SendVideoPacket(const FrameType frameType,
|
||||
ForwardErrorCorrection::kMaxMediaPackets;
|
||||
}
|
||||
|
||||
std::list<ForwardErrorCorrection::Packet*> fecPacketList;
|
||||
retVal = _fec.GenerateFEC(_mediaPacketListFec,
|
||||
_fecProtectionFactor,
|
||||
_numberFirstPartition,
|
||||
_fecUseUepProtection,
|
||||
fecPacketList);
|
||||
&fecPacketList);
|
||||
|
||||
int fecOverheadSent = 0;
|
||||
int videoSent = 0;
|
||||
|
||||
while(!_rtpPacketListFec.Empty())
|
||||
while(!_rtpPacketListFec.empty())
|
||||
{
|
||||
WebRtc_UWord8 newDataBuffer[IP_PACKET_SIZE];
|
||||
memset(newDataBuffer, 0, sizeof(newDataBuffer));
|
||||
|
||||
ListItem* item = _rtpPacketListFec.First();
|
||||
RtpPacket* packetToSend =
|
||||
static_cast<RtpPacket*>(item->GetItem());
|
||||
RtpPacket* packetToSend = _rtpPacketListFec.front();
|
||||
|
||||
// Copy RTP header
|
||||
memcpy(newDataBuffer, packetToSend->pkt->data,
|
||||
@ -229,8 +221,8 @@ RTPSenderVideo::SendVideoPacket(const FrameType frameType,
|
||||
packetToSend->pkt->length -
|
||||
packetToSend->rtpHeaderLength);
|
||||
|
||||
_rtpPacketListFec.PopFront();
|
||||
_mediaPacketListFec.PopFront();
|
||||
_rtpPacketListFec.pop_front();
|
||||
_mediaPacketListFec.pop_front();
|
||||
|
||||
// Send normal packet with RED header
|
||||
int packetSuccess = _rtpSender.SendToNetwork(
|
||||
@ -252,19 +244,15 @@ RTPSenderVideo::SendVideoPacket(const FrameType frameType,
|
||||
delete packetToSend;
|
||||
packetToSend = NULL;
|
||||
}
|
||||
assert(_mediaPacketListFec.Empty());
|
||||
assert(_rtpPacketListFec.Empty());
|
||||
assert(_mediaPacketListFec.empty());
|
||||
assert(_rtpPacketListFec.empty());
|
||||
|
||||
while(!fecPacketList.Empty())
|
||||
while(!fecPacketList.empty())
|
||||
{
|
||||
WebRtc_UWord8 newDataBuffer[IP_PACKET_SIZE];
|
||||
|
||||
ListItem* item = fecPacketList.First();
|
||||
|
||||
// Build FEC packets
|
||||
ForwardErrorCorrection::Packet* packetToSend =
|
||||
static_cast<ForwardErrorCorrection::Packet*>
|
||||
(item->GetItem());
|
||||
ForwardErrorCorrection::Packet* packetToSend = fecPacketList.front();
|
||||
|
||||
// The returned FEC packets have no RTP headers.
|
||||
// Copy the last media packet's modified RTP header.
|
||||
@ -285,7 +273,7 @@ RTPSenderVideo::SendVideoPacket(const FrameType frameType,
|
||||
packetToSend->data,
|
||||
packetToSend->length);
|
||||
|
||||
fecPacketList.PopFront();
|
||||
fecPacketList.pop_front();
|
||||
|
||||
// Invalid FEC packet
|
||||
assert(packetToSend->length != 0);
|
||||
|
@ -11,22 +11,24 @@
|
||||
#ifndef WEBRTC_MODULES_RTP_RTCP_SOURCE_RTP_SENDER_VIDEO_H_
|
||||
#define WEBRTC_MODULES_RTP_RTCP_SOURCE_RTP_SENDER_VIDEO_H_
|
||||
|
||||
#include <list>
|
||||
|
||||
#include "typedefs.h"
|
||||
#include "common_types.h" // Transport
|
||||
#include "rtp_rtcp_config.h"
|
||||
|
||||
#include "rtp_rtcp_defines.h"
|
||||
#include "rtp_utility.h"
|
||||
#include "list_wrapper.h"
|
||||
|
||||
#include "video_codec_information.h"
|
||||
#include "forward_error_correction.h"
|
||||
#include "Bitrate.h"
|
||||
|
||||
#include "rtp_sender.h"
|
||||
|
||||
namespace webrtc {
|
||||
class CriticalSectionWrapper;
|
||||
struct RtpPacket;
|
||||
|
||||
class RTPSenderVideo
|
||||
{
|
||||
public:
|
||||
@ -42,10 +44,11 @@ public:
|
||||
|
||||
WebRtc_UWord16 FECPacketOverhead() const;
|
||||
|
||||
WebRtc_Word32 RegisterVideoPayload(const WebRtc_Word8 payloadName[RTP_PAYLOAD_NAME_SIZE],
|
||||
const WebRtc_Word8 payloadType,
|
||||
const WebRtc_UWord32 maxBitRate,
|
||||
ModuleRTPUtility::Payload*& payload);
|
||||
WebRtc_Word32 RegisterVideoPayload(
|
||||
const char payloadName[RTP_PAYLOAD_NAME_SIZE],
|
||||
const WebRtc_Word8 payloadType,
|
||||
const WebRtc_UWord32 maxBitRate,
|
||||
ModuleRTPUtility::Payload*& payload);
|
||||
|
||||
WebRtc_Word32 SendVideo(const RtpVideoCodecTypes videoType,
|
||||
const FrameType frameType,
|
||||
@ -133,8 +136,8 @@ private:
|
||||
WebRtc_UWord8 _fecProtectionFactor;
|
||||
bool _fecUseUepProtection;
|
||||
int _numberFirstPartition;
|
||||
ListWrapper _mediaPacketListFec;
|
||||
ListWrapper _rtpPacketListFec;
|
||||
std::list<ForwardErrorCorrection::Packet*> _mediaPacketListFec;
|
||||
std::list<RtpPacket*> _rtpPacketListFec;
|
||||
// Bitrate used for FEC payload, RED headers, RTP headers for FEC packets
|
||||
// and any padding overhead.
|
||||
Bitrate _fecOverheadRate;
|
||||
|
File diff suppressed because it is too large
Load Diff
Loading…
x
Reference in New Issue
Block a user