Adding a payload type for RTX.
BUG=736 TEST=Modified RTP unittests. Review URL: https://webrtc-codereview.appspot.com/1278004 git-svn-id: http://webrtc.googlecode.com/svn/trunk@3843 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
parent
b8e7f4cc97
commit
9f5ebb5251
@ -232,14 +232,18 @@ class RtpRtcp : public Module {
|
|||||||
/*
|
/*
|
||||||
* Turn on/off receiving RTX (RFC 4588) on a specific SSRC.
|
* Turn on/off receiving RTX (RFC 4588) on a specific SSRC.
|
||||||
*/
|
*/
|
||||||
virtual int32_t SetRTXReceiveStatus(const bool enable,
|
virtual int32_t SetRTXReceiveStatus(bool enable, uint32_t SSRC) = 0;
|
||||||
const uint32_t SSRC) = 0;
|
|
||||||
|
// Sets the payload type to expected for received RTX packets. Note
|
||||||
|
// that this doesn't enable RTX, only the payload type is set.
|
||||||
|
virtual void SetRtxReceivePayloadType(int payload_type) = 0;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Get status of receiving RTX (RFC 4588) on a specific SSRC.
|
* Get status of receiving RTX (RFC 4588) on a specific SSRC.
|
||||||
*/
|
*/
|
||||||
virtual int32_t RTXReceiveStatus(bool* enable,
|
virtual int32_t RTXReceiveStatus(bool* enable,
|
||||||
uint32_t* SSRC) const = 0;
|
uint32_t* SSRC,
|
||||||
|
int* payloadType) const = 0;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* called by the network module when we receive a packet
|
* called by the network module when we receive a packet
|
||||||
@ -416,15 +420,18 @@ class RtpRtcp : public Module {
|
|||||||
/*
|
/*
|
||||||
* Turn on/off sending RTX (RFC 4588) on a specific SSRC.
|
* Turn on/off sending RTX (RFC 4588) on a specific SSRC.
|
||||||
*/
|
*/
|
||||||
virtual int32_t SetRTXSendStatus(const RtxMode mode,
|
virtual int32_t SetRTXSendStatus(RtxMode mode, bool set_ssrc,
|
||||||
const bool setSSRC,
|
uint32_t ssrc) = 0;
|
||||||
const uint32_t SSRC) = 0;
|
|
||||||
|
// Sets the payload type to use when sending RTX packets. Note that this
|
||||||
|
// doesn't enable RTX, only the payload type is set.
|
||||||
|
virtual void SetRtxSendPayloadType(int payload_type) = 0;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Get status of sending RTX (RFC 4588) on a specific SSRC.
|
* Get status of sending RTX (RFC 4588) on a specific SSRC.
|
||||||
*/
|
*/
|
||||||
virtual int32_t RTXSendStatus(RtxMode* mode,
|
virtual int32_t RTXSendStatus(RtxMode* mode, uint32_t* ssrc,
|
||||||
uint32_t* SSRC) const = 0;
|
int* payloadType) const = 0;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* sends kRtcpByeCode when going from true to false
|
* sends kRtcpByeCode when going from true to false
|
||||||
|
@ -113,6 +113,8 @@ enum RtxMode {
|
|||||||
kRtxAll = 2 // Apply RTX to all packets (source + retransmissions).
|
kRtxAll = 2 // Apply RTX to all packets (source + retransmissions).
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const int kRtxHeaderSize = 2;
|
||||||
|
|
||||||
struct RTCPSenderInfo
|
struct RTCPSenderInfo
|
||||||
{
|
{
|
||||||
uint32_t NTPseconds;
|
uint32_t NTPseconds;
|
||||||
|
@ -76,11 +76,14 @@ class MockRtpRtcp : public RtpRtcp {
|
|||||||
MOCK_METHOD2(SetSSRCFilter,
|
MOCK_METHOD2(SetSSRCFilter,
|
||||||
int32_t(const bool enable, const uint32_t allowedSSRC));
|
int32_t(const bool enable, const uint32_t allowedSSRC));
|
||||||
MOCK_METHOD2(SetRTXReceiveStatus,
|
MOCK_METHOD2(SetRTXReceiveStatus,
|
||||||
int32_t(const bool enable, const uint32_t SSRC));
|
int32_t(bool enable, uint32_t ssrc));
|
||||||
MOCK_CONST_METHOD2(RTXReceiveStatus,
|
MOCK_CONST_METHOD3(RTXReceiveStatus,
|
||||||
int32_t(bool* enable, uint32_t* SSRC));
|
int32_t(bool* enable, uint32_t* ssrc, int* payload_type));
|
||||||
|
MOCK_METHOD1(SetRtxReceivePayloadType,
|
||||||
|
void(int));
|
||||||
MOCK_METHOD2(IncomingPacket,
|
MOCK_METHOD2(IncomingPacket,
|
||||||
int32_t(const uint8_t* incomingPacket, const uint16_t packetLength));
|
int32_t(const WebRtc_UWord8* incomingPacket,
|
||||||
|
const WebRtc_UWord16 packetLength));
|
||||||
MOCK_METHOD4(IncomingAudioNTP,
|
MOCK_METHOD4(IncomingAudioNTP,
|
||||||
int32_t(const uint32_t audioReceivedNTPsecs,
|
int32_t(const uint32_t audioReceivedNTPsecs,
|
||||||
const uint32_t audioReceivedNTPfrac,
|
const uint32_t audioReceivedNTPfrac,
|
||||||
@ -128,10 +131,11 @@ class MockRtpRtcp : public RtpRtcp {
|
|||||||
MOCK_METHOD1(SetCSRCStatus,
|
MOCK_METHOD1(SetCSRCStatus,
|
||||||
int32_t(const bool include));
|
int32_t(const bool include));
|
||||||
MOCK_METHOD3(SetRTXSendStatus,
|
MOCK_METHOD3(SetRTXSendStatus,
|
||||||
int32_t(const RtxMode mode, const bool setSSRC,
|
int32_t(RtxMode mode, bool setSSRC, uint32_t ssrc));
|
||||||
const uint32_t SSRC));
|
MOCK_CONST_METHOD3(RTXSendStatus,
|
||||||
MOCK_CONST_METHOD2(RTXSendStatus,
|
int32_t(RtxMode* mode, uint32_t* ssrc, int* payload_type));
|
||||||
int32_t(RtxMode* mode, uint32_t* SSRC));
|
MOCK_METHOD1(SetRtxSendPayloadType,
|
||||||
|
void(int));
|
||||||
MOCK_METHOD1(SetSendingStatus,
|
MOCK_METHOD1(SetSendingStatus,
|
||||||
int32_t(const bool sending));
|
int32_t(const bool sending));
|
||||||
MOCK_CONST_METHOD0(Sending,
|
MOCK_CONST_METHOD0(Sending,
|
||||||
|
@ -193,8 +193,10 @@ TEST_F(RtpRtcpRtxNackTest, RTCP) {
|
|||||||
|
|
||||||
TEST_F(RtpRtcpRtxNackTest, RTXNack) {
|
TEST_F(RtpRtcpRtxNackTest, RTXNack) {
|
||||||
EXPECT_EQ(0, rtp_rtcp_module_->SetRTXReceiveStatus(true, kTestSsrc + 1));
|
EXPECT_EQ(0, rtp_rtcp_module_->SetRTXReceiveStatus(true, kTestSsrc + 1));
|
||||||
EXPECT_EQ(0, rtp_rtcp_module_->SetRTXSendStatus(kRtxRetransmitted,
|
rtp_rtcp_module_->SetRtxReceivePayloadType(119);
|
||||||
true, kTestSsrc + 1));
|
EXPECT_EQ(0, rtp_rtcp_module_->SetRTXSendStatus(kRtxRetransmitted, true,
|
||||||
|
kTestSsrc + 1));
|
||||||
|
rtp_rtcp_module_->SetRtxSendPayloadType(119);
|
||||||
|
|
||||||
transport_.DropEveryNthPacket(10);
|
transport_.DropEveryNthPacket(10);
|
||||||
|
|
||||||
@ -251,8 +253,8 @@ TEST_F(RtpRtcpRtxNackTest, RTXNack) {
|
|||||||
|
|
||||||
TEST_F(RtpRtcpRtxNackTest, RTXAllNoLoss) {
|
TEST_F(RtpRtcpRtxNackTest, RTXAllNoLoss) {
|
||||||
EXPECT_EQ(0, rtp_rtcp_module_->SetRTXReceiveStatus(true, kTestSsrc + 1));
|
EXPECT_EQ(0, rtp_rtcp_module_->SetRTXReceiveStatus(true, kTestSsrc + 1));
|
||||||
EXPECT_EQ(0, rtp_rtcp_module_->SetRTXSendStatus(kRtxAll,
|
EXPECT_EQ(0, rtp_rtcp_module_->SetRTXSendStatus(kRtxAll, true,
|
||||||
true, kTestSsrc + 1));
|
kTestSsrc + 1));
|
||||||
transport_.DropEveryNthPacket(0);
|
transport_.DropEveryNthPacket(0);
|
||||||
|
|
||||||
uint32_t timestamp = 3000;
|
uint32_t timestamp = 3000;
|
||||||
@ -285,8 +287,7 @@ TEST_F(RtpRtcpRtxNackTest, RTXAllNoLoss) {
|
|||||||
|
|
||||||
TEST_F(RtpRtcpRtxNackTest, RTXAllWithLoss) {
|
TEST_F(RtpRtcpRtxNackTest, RTXAllWithLoss) {
|
||||||
EXPECT_EQ(0, rtp_rtcp_module_->SetRTXReceiveStatus(true, kTestSsrc + 1));
|
EXPECT_EQ(0, rtp_rtcp_module_->SetRTXReceiveStatus(true, kTestSsrc + 1));
|
||||||
EXPECT_EQ(0, rtp_rtcp_module_->SetRTXSendStatus(kRtxAll,
|
EXPECT_EQ(0, rtp_rtcp_module_->SetRTXSendStatus(kRtxAll, true,
|
||||||
true,
|
|
||||||
kTestSsrc + 1));
|
kTestSsrc + 1));
|
||||||
|
|
||||||
int loss = 10;
|
int loss = 10;
|
||||||
|
@ -93,6 +93,10 @@ class RTPPayloadRegistry {
|
|||||||
last_received_payload_type_ = last_received_payload_type;
|
last_received_payload_type_ = last_received_payload_type;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int8_t last_received_media_payload_type() const {
|
||||||
|
return last_received_media_payload_type_;
|
||||||
|
};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Prunes the payload type map of the specific payload type, if it exists.
|
// Prunes the payload type map of the specific payload type, if it exists.
|
||||||
void DeregisterAudioCodecOrRedTypeRegardlessOfPayloadType(
|
void DeregisterAudioCodecOrRedTypeRegardlessOfPayloadType(
|
||||||
|
@ -94,7 +94,8 @@ RTPReceiver::RTPReceiver(const int32_t id,
|
|||||||
nack_method_(kNackOff),
|
nack_method_(kNackOff),
|
||||||
max_reordering_threshold_(kDefaultMaxReorderingThreshold),
|
max_reordering_threshold_(kDefaultMaxReorderingThreshold),
|
||||||
rtx_(false),
|
rtx_(false),
|
||||||
ssrc_rtx_(0) {
|
ssrc_rtx_(0),
|
||||||
|
payload_type_rtx_(-1) {
|
||||||
assert(incoming_audio_messages_callback &&
|
assert(incoming_audio_messages_callback &&
|
||||||
incoming_messages_callback &&
|
incoming_messages_callback &&
|
||||||
incoming_payload_callback);
|
incoming_payload_callback);
|
||||||
@ -288,17 +289,23 @@ int32_t RTPReceiver::SetNACKStatus(const NACKMethod method,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void RTPReceiver::SetRTXStatus(const bool enable,
|
void RTPReceiver::SetRTXStatus(bool enable, uint32_t ssrc) {
|
||||||
const uint32_t ssrc) {
|
|
||||||
CriticalSectionScoped lock(critical_section_rtp_receiver_);
|
CriticalSectionScoped lock(critical_section_rtp_receiver_);
|
||||||
rtx_ = enable;
|
rtx_ = enable;
|
||||||
ssrc_rtx_ = ssrc;
|
ssrc_rtx_ = ssrc;
|
||||||
}
|
}
|
||||||
|
|
||||||
void RTPReceiver::RTXStatus(bool* enable, uint32_t* ssrc) const {
|
void RTPReceiver::RTXStatus(bool* enable, uint32_t* ssrc,
|
||||||
|
int* payload_type) const {
|
||||||
CriticalSectionScoped lock(critical_section_rtp_receiver_);
|
CriticalSectionScoped lock(critical_section_rtp_receiver_);
|
||||||
*enable = rtx_;
|
*enable = rtx_;
|
||||||
*ssrc = ssrc_rtx_;
|
*ssrc = ssrc_rtx_;
|
||||||
|
*payload_type = payload_type_rtx_;
|
||||||
|
}
|
||||||
|
|
||||||
|
void RTPReceiver::SetRtxPayloadType(int payload_type) {
|
||||||
|
CriticalSectionScoped cs(critical_section_rtp_receiver_);
|
||||||
|
payload_type_rtx_ = payload_type;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t RTPReceiver::SSRC() const {
|
uint32_t RTPReceiver::SSRC() const {
|
||||||
@ -350,10 +357,23 @@ int32_t RTPReceiver::IncomingRTPPacket(
|
|||||||
}
|
}
|
||||||
if (rtx_) {
|
if (rtx_) {
|
||||||
if (ssrc_rtx_ == rtp_header->header.ssrc) {
|
if (ssrc_rtx_ == rtp_header->header.ssrc) {
|
||||||
// Sanity check.
|
// Sanity check, RTX packets has 2 extra header bytes.
|
||||||
if (rtp_header->header.headerLength + 2 > packet_length) {
|
if (rtp_header->header.headerLength + kRtxHeaderSize > packet_length) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
// If a specific RTX payload type is negotiated, set back to the media
|
||||||
|
// payload type and treat it like a media packet from here.
|
||||||
|
if (payload_type_rtx_ != -1) {
|
||||||
|
if (payload_type_rtx_ == rtp_header->header.payloadType &&
|
||||||
|
rtp_payload_registry_->last_received_media_payload_type() != -1) {
|
||||||
|
rtp_header->header.payloadType =
|
||||||
|
rtp_payload_registry_->last_received_media_payload_type();
|
||||||
|
} else {
|
||||||
|
WEBRTC_TRACE(kTraceWarning, kTraceRtpRtcp, id_,
|
||||||
|
"Incorrect RTX configuration, dropping packet.");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
rtp_header->header.ssrc = ssrc_;
|
rtp_header->header.ssrc = ssrc_;
|
||||||
rtp_header->header.sequenceNumber =
|
rtp_header->header.sequenceNumber =
|
||||||
(packet[rtp_header->header.headerLength] << 8) +
|
(packet[rtp_header->header.headerLength] << 8) +
|
||||||
|
@ -141,9 +141,11 @@ class RTPReceiver : public Bitrate {
|
|||||||
void GetHeaderExtensionMapCopy(RtpHeaderExtensionMap* map) const;
|
void GetHeaderExtensionMapCopy(RtpHeaderExtensionMap* map) const;
|
||||||
|
|
||||||
// RTX.
|
// RTX.
|
||||||
void SetRTXStatus(const bool enable, const uint32_t ssrc);
|
void SetRTXStatus(bool enable, uint32_t ssrc);
|
||||||
|
|
||||||
void RTXStatus(bool* enable, uint32_t* ssrc) const;
|
void RTXStatus(bool* enable, uint32_t* ssrc, int* payload_type) const;
|
||||||
|
|
||||||
|
void SetRtxPayloadType(int payload_type);
|
||||||
|
|
||||||
virtual int8_t REDPayloadType() const;
|
virtual int8_t REDPayloadType() const;
|
||||||
|
|
||||||
@ -234,6 +236,7 @@ class RTPReceiver : public Bitrate {
|
|||||||
|
|
||||||
bool rtx_;
|
bool rtx_;
|
||||||
uint32_t ssrc_rtx_;
|
uint32_t ssrc_rtx_;
|
||||||
|
int payload_type_rtx_;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace webrtc
|
} // namespace webrtc
|
||||||
|
@ -314,7 +314,7 @@ void ModuleRtpRtcpImpl::ProcessDeadOrAliveTimer() {
|
|||||||
bool do_callback = false;
|
bool do_callback = false;
|
||||||
|
|
||||||
// Do operations on members under lock but avoid making the
|
// Do operations on members under lock but avoid making the
|
||||||
// ProcessDeadOrAlive() callback under the same lock.
|
// ProcessDeadOrAlive() callback under the same lock.
|
||||||
{
|
{
|
||||||
CriticalSectionScoped lock(critical_section_module_ptrs_.get());
|
CriticalSectionScoped lock(critical_section_module_ptrs_.get());
|
||||||
if (dead_or_alive_active_) {
|
if (dead_or_alive_active_) {
|
||||||
@ -325,7 +325,7 @@ void ModuleRtpRtcpImpl::ProcessDeadOrAliveTimer() {
|
|||||||
|
|
||||||
if (rtcp_receiver_.LastReceived() + 12000 > now)
|
if (rtcp_receiver_.LastReceived() + 12000 > now)
|
||||||
RTCPalive = true;
|
RTCPalive = true;
|
||||||
|
|
||||||
do_callback = true;
|
do_callback = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -532,32 +532,38 @@ int32_t ModuleRtpRtcpImpl::RemoteCSRCs(
|
|||||||
return rtp_receiver_->CSRCs(arr_of_csrc);
|
return rtp_receiver_->CSRCs(arr_of_csrc);
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t ModuleRtpRtcpImpl::SetRTXSendStatus(
|
int32_t ModuleRtpRtcpImpl::SetRTXSendStatus(RtxMode mode, bool set_ssrc,
|
||||||
const RtxMode mode,
|
uint32_t ssrc) {
|
||||||
const bool set_ssrc,
|
|
||||||
const uint32_t ssrc) {
|
|
||||||
rtp_sender_.SetRTXStatus(mode, set_ssrc, ssrc);
|
rtp_sender_.SetRTXStatus(mode, set_ssrc, ssrc);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t ModuleRtpRtcpImpl::RTXSendStatus(RtxMode* mode, uint32_t* ssrc) const {
|
int32_t ModuleRtpRtcpImpl::RTXSendStatus(RtxMode* mode, uint32_t* ssrc,
|
||||||
rtp_sender_.RTXStatus(mode, ssrc);
|
int* payload_type) const {
|
||||||
|
rtp_sender_.RTXStatus(mode, ssrc, payload_type);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t ModuleRtpRtcpImpl::SetRTXReceiveStatus(
|
int32_t ModuleRtpRtcpImpl::SetRTXReceiveStatus(bool enable,
|
||||||
const bool enable,
|
uint32_t ssrc) {
|
||||||
const uint32_t ssrc) {
|
|
||||||
rtp_receiver_->SetRTXStatus(enable, ssrc);
|
rtp_receiver_->SetRTXStatus(enable, ssrc);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t ModuleRtpRtcpImpl::RTXReceiveStatus(bool* enable,
|
int32_t ModuleRtpRtcpImpl::RTXReceiveStatus(bool* enable, uint32_t* ssrc,
|
||||||
uint32_t* ssrc) const {
|
int* payload_type) const {
|
||||||
rtp_receiver_->RTXStatus(enable, ssrc);
|
rtp_receiver_->RTXStatus(enable, ssrc, payload_type);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ModuleRtpRtcpImpl::SetRtxSendPayloadType(int payload_type) {
|
||||||
|
rtp_sender_.SetRtxPayloadType(payload_type);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ModuleRtpRtcpImpl::SetRtxReceivePayloadType(int payload_type) {
|
||||||
|
rtp_receiver_->SetRtxPayloadType(payload_type);
|
||||||
|
}
|
||||||
|
|
||||||
// Called by the network module when we receive a packet.
|
// Called by the network module when we receive a packet.
|
||||||
int32_t ModuleRtpRtcpImpl::IncomingPacket(
|
int32_t ModuleRtpRtcpImpl::IncomingPacket(
|
||||||
const uint8_t* incoming_packet,
|
const uint8_t* incoming_packet,
|
||||||
|
@ -103,8 +103,10 @@ class ModuleRtpRtcpImpl : public RtpRtcp {
|
|||||||
virtual int32_t SetRTXReceiveStatus(const bool enable,
|
virtual int32_t SetRTXReceiveStatus(const bool enable,
|
||||||
const uint32_t ssrc);
|
const uint32_t ssrc);
|
||||||
|
|
||||||
virtual int32_t RTXReceiveStatus(bool* enable,
|
virtual int32_t RTXReceiveStatus(bool* enable, uint32_t* ssrc,
|
||||||
uint32_t* ssrc) const;
|
int* payloadType) const;
|
||||||
|
|
||||||
|
virtual void SetRtxReceivePayloadType(int payload_type);
|
||||||
|
|
||||||
// Called by the network module when we receive a packet.
|
// Called by the network module when we receive a packet.
|
||||||
virtual int32_t IncomingPacket(const uint8_t* incoming_packet,
|
virtual int32_t IncomingPacket(const uint8_t* incoming_packet,
|
||||||
@ -161,7 +163,11 @@ class ModuleRtpRtcpImpl : public RtpRtcp {
|
|||||||
const bool set_ssrc,
|
const bool set_ssrc,
|
||||||
const uint32_t ssrc);
|
const uint32_t ssrc);
|
||||||
|
|
||||||
virtual int32_t RTXSendStatus(RtxMode* mode, uint32_t* ssrc) const;
|
virtual int32_t RTXSendStatus(RtxMode* mode, uint32_t* ssrc,
|
||||||
|
int* payloadType) const;
|
||||||
|
|
||||||
|
|
||||||
|
virtual void SetRtxSendPayloadType(int payload_type);
|
||||||
|
|
||||||
// Sends kRtcpByeCode when going from true to false.
|
// Sends kRtcpByeCode when going from true to false.
|
||||||
virtual int32_t SetSendingStatus(const bool sending);
|
virtual int32_t SetSendingStatus(const bool sending);
|
||||||
|
@ -58,7 +58,7 @@ RTPSender::RTPSender(const int32_t id, const bool audio, Clock *clock,
|
|||||||
start_time_stamp_(0), ssrc_db_(*SSRCDatabase::GetSSRCDatabase()),
|
start_time_stamp_(0), ssrc_db_(*SSRCDatabase::GetSSRCDatabase()),
|
||||||
remote_ssrc_(0), sequence_number_forced_(false), ssrc_forced_(false),
|
remote_ssrc_(0), sequence_number_forced_(false), ssrc_forced_(false),
|
||||||
time_stamp_(0), csrcs_(0), csrc_(), include_csrcs_(true),
|
time_stamp_(0), csrcs_(0), csrc_(), include_csrcs_(true),
|
||||||
rtx_(kRtxOff) {
|
rtx_(kRtxOff), payload_type_rtx_(-1) {
|
||||||
memset(nack_byte_count_times_, 0, sizeof(nack_byte_count_times_));
|
memset(nack_byte_count_times_, 0, sizeof(nack_byte_count_times_));
|
||||||
memset(nack_byte_count_, 0, sizeof(nack_byte_count_));
|
memset(nack_byte_count_, 0, sizeof(nack_byte_count_));
|
||||||
memset(csrc_, 0, sizeof(csrc_));
|
memset(csrc_, 0, sizeof(csrc_));
|
||||||
@ -255,8 +255,7 @@ uint16_t RTPSender::MaxPayloadLength() const {
|
|||||||
|
|
||||||
uint16_t RTPSender::PacketOverHead() const { return packet_over_head_; }
|
uint16_t RTPSender::PacketOverHead() const { return packet_over_head_; }
|
||||||
|
|
||||||
void RTPSender::SetRTXStatus(const RtxMode mode, const bool set_ssrc,
|
void RTPSender::SetRTXStatus(RtxMode mode, bool set_ssrc, uint32_t ssrc) {
|
||||||
const uint32_t ssrc) {
|
|
||||||
CriticalSectionScoped cs(send_critsect_);
|
CriticalSectionScoped cs(send_critsect_);
|
||||||
rtx_ = mode;
|
rtx_ = mode;
|
||||||
if (rtx_ != kRtxOff) {
|
if (rtx_ != kRtxOff) {
|
||||||
@ -268,10 +267,18 @@ void RTPSender::SetRTXStatus(const RtxMode mode, const bool set_ssrc,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void RTPSender::RTXStatus(RtxMode* mode, uint32_t *SSRC) const {
|
void RTPSender::RTXStatus(RtxMode* mode, uint32_t* ssrc,
|
||||||
|
int* payload_type) const {
|
||||||
CriticalSectionScoped cs(send_critsect_);
|
CriticalSectionScoped cs(send_critsect_);
|
||||||
*mode = rtx_;
|
*mode = rtx_;
|
||||||
*SSRC = ssrc_rtx_;
|
*ssrc = ssrc_rtx_;
|
||||||
|
*payload_type = payload_type_rtx_;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void RTPSender::SetRtxPayloadType(int payload_type) {
|
||||||
|
CriticalSectionScoped cs(send_critsect_);
|
||||||
|
payload_type_rtx_ = payload_type;
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t RTPSender::CheckPayloadType(const int8_t payload_type,
|
int32_t RTPSender::CheckPayloadType(const int8_t payload_type,
|
||||||
@ -1222,6 +1229,13 @@ void RTPSender::BuildRtxPacket(uint8_t* buffer, uint16_t* length,
|
|||||||
// Add original RTP header.
|
// Add original RTP header.
|
||||||
memcpy(data_buffer_rtx, buffer, rtp_header.header.headerLength);
|
memcpy(data_buffer_rtx, buffer, rtp_header.header.headerLength);
|
||||||
|
|
||||||
|
// Replace payload type, if a specific type is set for RTX.
|
||||||
|
if (payload_type_rtx_ != -1) {
|
||||||
|
data_buffer_rtx[1] = static_cast<uint8_t>(payload_type_rtx_);
|
||||||
|
if (rtp_header.header.markerBit)
|
||||||
|
data_buffer_rtx[1] |= kRtpMarkerBitMask;
|
||||||
|
}
|
||||||
|
|
||||||
// Replace sequence number.
|
// Replace sequence number.
|
||||||
uint8_t *ptr = data_buffer_rtx + 2;
|
uint8_t *ptr = data_buffer_rtx + 2;
|
||||||
ModuleRTPUtility::AssignUWord16ToBuffer(ptr, sequence_number_rtx_++);
|
ModuleRTPUtility::AssignUWord16ToBuffer(ptr, sequence_number_rtx_++);
|
||||||
|
@ -174,10 +174,11 @@ class RTPSender : public Bitrate, public RTPSenderInterface {
|
|||||||
bool ProcessNACKBitRate(const uint32_t now);
|
bool ProcessNACKBitRate(const uint32_t now);
|
||||||
|
|
||||||
// RTX.
|
// RTX.
|
||||||
void SetRTXStatus(const RtxMode mode, const bool set_ssrc,
|
void SetRTXStatus(RtxMode mode, bool set_ssrc, uint32_t ssrc);
|
||||||
const uint32_t SSRC);
|
|
||||||
|
|
||||||
void RTXStatus(RtxMode* mode, uint32_t *SSRC) const;
|
void RTXStatus(RtxMode* mode, uint32_t* ssrc, int* payload_type) const;
|
||||||
|
|
||||||
|
void SetRtxPayloadType(int payloadType);
|
||||||
|
|
||||||
// Functions wrapping RTPSenderInterface.
|
// Functions wrapping RTPSenderInterface.
|
||||||
virtual int32_t BuildRTPheader(
|
virtual int32_t BuildRTPheader(
|
||||||
@ -310,6 +311,7 @@ class RTPSender : public Bitrate, public RTPSenderInterface {
|
|||||||
bool include_csrcs_;
|
bool include_csrcs_;
|
||||||
RtxMode rtx_;
|
RtxMode rtx_;
|
||||||
uint32_t ssrc_rtx_;
|
uint32_t ssrc_rtx_;
|
||||||
|
int payload_type_rtx_;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace webrtc
|
} // namespace webrtc
|
||||||
|
@ -111,24 +111,40 @@ TEST_F(RtpRtcpAPITest, RTCP) {
|
|||||||
TEST_F(RtpRtcpAPITest, RTXSender) {
|
TEST_F(RtpRtcpAPITest, RTXSender) {
|
||||||
unsigned int ssrc = 0;
|
unsigned int ssrc = 0;
|
||||||
RtxMode rtx_mode = kRtxOff;
|
RtxMode rtx_mode = kRtxOff;
|
||||||
|
const int kRtxPayloadType = 119;
|
||||||
|
int payload_type = -1;
|
||||||
EXPECT_EQ(0, module->SetRTXSendStatus(kRtxRetransmitted, true, 1));
|
EXPECT_EQ(0, module->SetRTXSendStatus(kRtxRetransmitted, true, 1));
|
||||||
EXPECT_EQ(0, module->RTXSendStatus(&rtx_mode, &ssrc));
|
module->SetRtxSendPayloadType(kRtxPayloadType);
|
||||||
|
EXPECT_EQ(0, module->RTXSendStatus(&rtx_mode, &ssrc, &payload_type));
|
||||||
EXPECT_EQ(kRtxRetransmitted, rtx_mode);
|
EXPECT_EQ(kRtxRetransmitted, rtx_mode);
|
||||||
EXPECT_EQ(1u, ssrc);
|
EXPECT_EQ(1u, ssrc);
|
||||||
|
EXPECT_EQ(kRtxPayloadType, payload_type);
|
||||||
rtx_mode = kRtxOff;
|
rtx_mode = kRtxOff;
|
||||||
EXPECT_EQ(0, module->SetRTXSendStatus(kRtxOff, true, 0));
|
EXPECT_EQ(0, module->SetRTXSendStatus(kRtxOff, true, 0));
|
||||||
EXPECT_EQ(0, module->RTXSendStatus(&rtx_mode, &ssrc));
|
payload_type = -1;
|
||||||
|
module->SetRtxSendPayloadType(kRtxPayloadType);
|
||||||
|
EXPECT_EQ(0, module->RTXSendStatus(&rtx_mode, &ssrc, &payload_type));
|
||||||
EXPECT_EQ(kRtxOff, rtx_mode);
|
EXPECT_EQ(kRtxOff, rtx_mode);
|
||||||
|
EXPECT_EQ(kRtxPayloadType ,payload_type);
|
||||||
|
EXPECT_EQ(0, module->SetRTXSendStatus(kRtxRetransmitted, false, 1));
|
||||||
|
EXPECT_EQ(0, module->RTXSendStatus(&rtx_mode, &ssrc, &payload_type));
|
||||||
|
EXPECT_EQ(kRtxRetransmitted, rtx_mode);
|
||||||
|
EXPECT_EQ(kRtxPayloadType ,payload_type);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(RtpRtcpAPITest, RTXReceiver) {
|
TEST_F(RtpRtcpAPITest, RTXReceiver) {
|
||||||
bool enable = false;
|
bool enable = false;
|
||||||
unsigned int ssrc = 0;
|
unsigned int ssrc = 0;
|
||||||
|
const int kRtxPayloadType = 119;
|
||||||
|
int payload_type = -1;
|
||||||
EXPECT_EQ(0, module->SetRTXReceiveStatus(true, 1));
|
EXPECT_EQ(0, module->SetRTXReceiveStatus(true, 1));
|
||||||
EXPECT_EQ(0, module->RTXReceiveStatus(&enable, &ssrc));
|
module->SetRtxReceivePayloadType(kRtxPayloadType);
|
||||||
|
EXPECT_EQ(0, module->RTXReceiveStatus(&enable, &ssrc, &payload_type));
|
||||||
EXPECT_TRUE(enable);
|
EXPECT_TRUE(enable);
|
||||||
EXPECT_EQ(1u, ssrc);
|
EXPECT_EQ(1u, ssrc);
|
||||||
|
EXPECT_EQ(kRtxPayloadType ,payload_type);
|
||||||
EXPECT_EQ(0, module->SetRTXReceiveStatus(false, 0));
|
EXPECT_EQ(0, module->SetRTXReceiveStatus(false, 0));
|
||||||
EXPECT_EQ(0, module->RTXReceiveStatus(&enable, &ssrc));
|
EXPECT_EQ(0, module->RTXReceiveStatus(&enable, &ssrc, &payload_type));
|
||||||
EXPECT_FALSE(enable);
|
EXPECT_FALSE(enable);
|
||||||
|
EXPECT_EQ(kRtxPayloadType ,payload_type);
|
||||||
}
|
}
|
||||||
|
@ -133,6 +133,14 @@ class WEBRTC_DLLEXPORT ViERTP_RTCP {
|
|||||||
virtual int GetRemoteCSRCs(const int video_channel,
|
virtual int GetRemoteCSRCs(const int video_channel,
|
||||||
unsigned int CSRCs[kRtpCsrcSize]) const = 0;
|
unsigned int CSRCs[kRtpCsrcSize]) const = 0;
|
||||||
|
|
||||||
|
// This sets a specific payload type for the RTX stream. Note that this
|
||||||
|
// doesn't enable RTX, SetLocalSSRC must still be called to enable RTX.
|
||||||
|
virtual int SetRtxSendPayloadType(const int video_channel,
|
||||||
|
const uint8_t payload_type) = 0;
|
||||||
|
|
||||||
|
virtual int SetRtxReceivePayloadType(const int video_channel,
|
||||||
|
const uint8_t payload_type) = 0;
|
||||||
|
|
||||||
// This function enables manual initialization of the sequence number. The
|
// This function enables manual initialization of the sequence number. The
|
||||||
// start sequence number is normally a random number.
|
// start sequence number is normally a random number.
|
||||||
virtual int SetStartSequenceNumber(const int video_channel,
|
virtual int SetStartSequenceNumber(const int video_channel,
|
||||||
|
@ -973,8 +973,31 @@ int32_t ViEChannel::GetRemoteCSRC(uint32_t CSRCs[kRtpCsrcSize]) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t ViEChannel::SetStartSequenceNumber(
|
int ViEChannel::SetRtxSendPayloadType(int payload_type) {
|
||||||
uint16_t sequence_number) {
|
if (rtp_rtcp_->Sending()) {
|
||||||
|
WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(engine_id_, channel_id_),
|
||||||
|
"%s: already sending", __FUNCTION__);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
rtp_rtcp_->SetRtxSendPayloadType(payload_type);
|
||||||
|
CriticalSectionScoped cs(rtp_rtcp_cs_.get());
|
||||||
|
for (std::list<RtpRtcp*>::iterator it = simulcast_rtp_rtcp_.begin();
|
||||||
|
it != simulcast_rtp_rtcp_.end(); it++) {
|
||||||
|
(*it)->SetRtxSendPayloadType(payload_type);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ViEChannel::SetRtxReceivePayloadType(int payload_type) {
|
||||||
|
rtp_rtcp_->SetRtxReceivePayloadType(payload_type);
|
||||||
|
CriticalSectionScoped cs(rtp_rtcp_cs_.get());
|
||||||
|
for (std::list<RtpRtcp*>::iterator it = simulcast_rtp_rtcp_.begin();
|
||||||
|
it != simulcast_rtp_rtcp_.end(); it++) {
|
||||||
|
(*it)->SetRtxReceivePayloadType(payload_type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t ViEChannel::SetStartSequenceNumber(uint16_t sequence_number) {
|
||||||
WEBRTC_TRACE(kTraceInfo, kTraceVideo, ViEId(engine_id_, channel_id_), "%s",
|
WEBRTC_TRACE(kTraceInfo, kTraceVideo, ViEId(engine_id_, channel_id_), "%s",
|
||||||
__FUNCTION__);
|
__FUNCTION__);
|
||||||
|
|
||||||
|
@ -139,6 +139,9 @@ class ViEChannel
|
|||||||
// Gets the CSRC for the incoming stream.
|
// Gets the CSRC for the incoming stream.
|
||||||
int32_t GetRemoteCSRC(uint32_t CSRCs[kRtpCsrcSize]);
|
int32_t GetRemoteCSRC(uint32_t CSRCs[kRtpCsrcSize]);
|
||||||
|
|
||||||
|
int SetRtxSendPayloadType(int payload_type);
|
||||||
|
void SetRtxReceivePayloadType(int payload_type);
|
||||||
|
|
||||||
// Sets the starting sequence number, must be called before StartSend.
|
// Sets the starting sequence number, must be called before StartSend.
|
||||||
int32_t SetStartSequenceNumber(uint16_t sequence_number);
|
int32_t SetStartSequenceNumber(uint16_t sequence_number);
|
||||||
|
|
||||||
|
@ -233,6 +233,44 @@ int ViERTP_RTCPImpl::GetRemoteCSRCs(const int video_channel,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int ViERTP_RTCPImpl::SetRtxSendPayloadType(const int video_channel,
|
||||||
|
const uint8_t payload_type) {
|
||||||
|
WEBRTC_TRACE(kTraceApiCall, kTraceVideo,
|
||||||
|
ViEId(shared_data_->instance_id(), video_channel),
|
||||||
|
"%s(channel: %d)", __FUNCTION__, video_channel);
|
||||||
|
ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
|
||||||
|
ViEChannel* vie_channel = cs.Channel(video_channel);
|
||||||
|
if (!vie_channel) {
|
||||||
|
WEBRTC_TRACE(kTraceError, kTraceVideo,
|
||||||
|
ViEId(shared_data_->instance_id(), video_channel),
|
||||||
|
"%s: Channel %d doesn't exist", __FUNCTION__, video_channel);
|
||||||
|
shared_data_->SetLastError(kViERtpRtcpInvalidChannelId);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (!vie_channel->SetRtxSendPayloadType(payload_type)) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ViERTP_RTCPImpl::SetRtxReceivePayloadType(const int video_channel,
|
||||||
|
const uint8_t payload_type) {
|
||||||
|
WEBRTC_TRACE(kTraceApiCall, kTraceVideo,
|
||||||
|
ViEId(shared_data_->instance_id(), video_channel),
|
||||||
|
"%s(channel: %d)", __FUNCTION__, video_channel);
|
||||||
|
ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
|
||||||
|
ViEChannel* vie_channel = cs.Channel(video_channel);
|
||||||
|
if (!vie_channel) {
|
||||||
|
WEBRTC_TRACE(kTraceError, kTraceVideo,
|
||||||
|
ViEId(shared_data_->instance_id(), video_channel),
|
||||||
|
"%s: Channel %d doesn't exist", __FUNCTION__, video_channel);
|
||||||
|
shared_data_->SetLastError(kViERtpRtcpInvalidChannelId);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
vie_channel->SetRtxReceivePayloadType(payload_type);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int ViERTP_RTCPImpl::SetStartSequenceNumber(const int video_channel,
|
int ViERTP_RTCPImpl::SetStartSequenceNumber(const int video_channel,
|
||||||
uint16_t sequence_number) {
|
uint16_t sequence_number) {
|
||||||
WEBRTC_TRACE(kTraceApiCall, kTraceVideo,
|
WEBRTC_TRACE(kTraceApiCall, kTraceVideo,
|
||||||
|
@ -39,6 +39,10 @@ class ViERTP_RTCPImpl
|
|||||||
unsigned int& SSRC) const; // NOLINT
|
unsigned int& SSRC) const; // NOLINT
|
||||||
virtual int GetRemoteCSRCs(const int video_channel,
|
virtual int GetRemoteCSRCs(const int video_channel,
|
||||||
unsigned int CSRCs[kRtpCsrcSize]) const;
|
unsigned int CSRCs[kRtpCsrcSize]) const;
|
||||||
|
virtual int SetRtxSendPayloadType(const int video_channel,
|
||||||
|
const uint8_t payload_type);
|
||||||
|
virtual int SetRtxReceivePayloadType(const int video_channel,
|
||||||
|
const uint8_t payload_type);
|
||||||
virtual int SetStartSequenceNumber(const int video_channel,
|
virtual int SetStartSequenceNumber(const int video_channel,
|
||||||
uint16_t sequence_number);
|
uint16_t sequence_number);
|
||||||
virtual int SetRTCPStatus(const int video_channel,
|
virtual int SetRTCPStatus(const int video_channel,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user