Have RTX be enabled by setting an RTX payload type instead of by setting an RTX SSRC.

This makes it easier to disable RTX by filtering out the RTX codec during call setup/signaling, and won't require that also the SSRCs are filtered out.

BUG=1811
R=mflodman@webrtc.org, pbos@webrtc.org

Review URL: https://webrtc-codereview.appspot.com/15629005

git-svn-id: http://webrtc.googlecode.com/svn/trunk@6335 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
stefan@webrtc.org 2014-06-05 08:25:29 +00:00
parent c578962006
commit ef92755780
21 changed files with 99 additions and 95 deletions

View File

@ -75,10 +75,10 @@ class RTPPayloadRegistry {
const uint32_t rate,
int8_t* payload_type) const;
void SetRtxStatus(bool enable, uint32_t ssrc);
bool RtxEnabled() const;
void SetRtxSsrc(uint32_t ssrc);
void SetRtxPayloadType(int payload_type);
bool IsRtx(const RTPHeader& header) const;

View File

@ -213,7 +213,7 @@ class RtpRtcp : public Module {
*
* return -1 on failure else 0
*/
virtual int32_t SetSSRC(const uint32_t ssrc) = 0;
virtual void SetSSRC(const uint32_t ssrc) = 0;
/*
* Get CSRC
@ -249,10 +249,14 @@ class RtpRtcp : public Module {
virtual int32_t SetCSRCStatus(const bool include) = 0;
/*
* Turn on/off sending RTX (RFC 4588) on a specific SSRC.
* Turn on/off sending RTX (RFC 4588). The modes can be set as a combination
* of values of the enumerator RtxMode.
*/
virtual int32_t SetRTXSendStatus(int modes, bool set_ssrc,
uint32_t ssrc) = 0;
virtual void SetRTXSendStatus(int modes) = 0;
// Sets the SSRC to use when sending RTX packets. This doesn't enable RTX,
// only the SSRC is set.
virtual void SetRtxSsrc(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.
@ -261,8 +265,8 @@ class RtpRtcp : public Module {
/*
* Get status of sending RTX (RFC 4588) on a specific SSRC.
*/
virtual int32_t RTXSendStatus(int* modes, uint32_t* ssrc,
int* payloadType) const = 0;
virtual void RTXSendStatus(int* modes, uint32_t* ssrc,
int* payloadType) const = 0;
/*
* sends kRtcpByeCode when going from true to false

View File

@ -77,17 +77,19 @@ class MockRtpRtcp : public RtpRtcp {
MOCK_CONST_METHOD0(SSRC,
uint32_t());
MOCK_METHOD1(SetSSRC,
int32_t(const uint32_t ssrc));
void(const uint32_t ssrc));
MOCK_CONST_METHOD1(CSRCs,
int32_t(uint32_t arrOfCSRC[kRtpCsrcSize]));
MOCK_METHOD2(SetCSRCs,
int32_t(const uint32_t arrOfCSRC[kRtpCsrcSize], const uint8_t arrLength));
MOCK_METHOD1(SetCSRCStatus,
int32_t(const bool include));
MOCK_METHOD3(SetRTXSendStatus,
int32_t(int modes, bool setSSRC, uint32_t ssrc));
MOCK_METHOD1(SetRTXSendStatus,
void(int modes));
MOCK_CONST_METHOD3(RTXSendStatus,
int32_t(int* modes, uint32_t* ssrc, int* payload_type));
void(int* modes, uint32_t* ssrc, int* payload_type));
MOCK_METHOD1(SetRtxSsrc,
void(uint32_t));
MOCK_METHOD1(SetRtxSendPayloadType,
void(int));
MOCK_METHOD1(SetSendingStatus,

View File

@ -188,7 +188,7 @@ class RtpRtcpRtxNackTest : public ::testing::Test {
kTestId, &fake_clock, &receiver_, rtp_feedback_.get(),
&rtp_payload_registry_));
EXPECT_EQ(0, rtp_rtcp_module_->SetSSRC(kTestSsrc));
rtp_rtcp_module_->SetSSRC(kTestSsrc);
EXPECT_EQ(0, rtp_rtcp_module_->SetRTCPStatus(kRtcpCompound));
rtp_receiver_->SetNACKStatus(kNackRtcp);
EXPECT_EQ(0, rtp_rtcp_module_->SetStorePacketsStatus(true, 600));
@ -253,9 +253,9 @@ class RtpRtcpRtxNackTest : public ::testing::Test {
}
void RunRtxTest(RtxMode rtx_method, int loss) {
rtp_payload_registry_.SetRtxStatus(true, kTestSsrc + 1);
EXPECT_EQ(0, rtp_rtcp_module_->SetRTXSendStatus(rtx_method, true,
kTestSsrc + 1));
rtp_payload_registry_.SetRtxSsrc(kTestSsrc + 1);
rtp_rtcp_module_->SetRTXSendStatus(rtx_method);
rtp_rtcp_module_->SetRtxSsrc(kTestSsrc + 1);
transport_.DropEveryNthPacket(loss);
uint32_t timestamp = 3000;
uint16_t nack_list[kVideoNackListSize];

View File

@ -228,12 +228,6 @@ int32_t RTPPayloadRegistry::ReceivePayloadType(
return -1;
}
void RTPPayloadRegistry::SetRtxStatus(bool enable, uint32_t ssrc) {
CriticalSectionScoped cs(crit_sect_.get());
rtx_ = enable;
ssrc_rtx_ = ssrc;
}
bool RTPPayloadRegistry::RtxEnabled() const {
CriticalSectionScoped cs(crit_sect_.get());
return rtx_;
@ -288,9 +282,17 @@ bool RTPPayloadRegistry::RestoreOriginalPacket(uint8_t** restored_packet,
return true;
}
void RTPPayloadRegistry::SetRtxSsrc(uint32_t ssrc) {
CriticalSectionScoped cs(crit_sect_.get());
ssrc_rtx_ = ssrc;
rtx_ = true;
}
void RTPPayloadRegistry::SetRtxPayloadType(int payload_type) {
CriticalSectionScoped cs(crit_sect_.get());
assert(payload_type >= 0);
payload_type_rtx_ = payload_type;
rtx_ = true;
}
bool RTPPayloadRegistry::IsRed(const RTPHeader& header) const {

View File

@ -248,16 +248,17 @@ int32_t ModuleRtpRtcpImpl::Process() {
return 0;
}
int32_t ModuleRtpRtcpImpl::SetRTXSendStatus(int mode, bool set_ssrc,
uint32_t ssrc) {
rtp_sender_.SetRTXStatus(mode, set_ssrc, ssrc);
return 0;
void ModuleRtpRtcpImpl::SetRTXSendStatus(int mode) {
rtp_sender_.SetRTXStatus(mode);
}
int32_t ModuleRtpRtcpImpl::RTXSendStatus(int* mode, uint32_t* ssrc,
void ModuleRtpRtcpImpl::RTXSendStatus(int* mode, uint32_t* ssrc,
int* payload_type) const {
rtp_sender_.RTXStatus(mode, ssrc, payload_type);
return 0;
}
void ModuleRtpRtcpImpl::SetRtxSsrc(uint32_t ssrc) {
rtp_sender_.SetRtxSsrc(ssrc);
}
void ModuleRtpRtcpImpl::SetRtxSendPayloadType(int payload_type) {
@ -347,12 +348,10 @@ uint32_t ModuleRtpRtcpImpl::SSRC() const {
}
// Configure SSRC, default is a random number.
int32_t ModuleRtpRtcpImpl::SetSSRC(const uint32_t ssrc) {
void ModuleRtpRtcpImpl::SetSSRC(const uint32_t ssrc) {
rtp_sender_.SetSSRC(ssrc);
rtcp_sender_.SetSSRC(ssrc);
SetRtcpReceiverSsrcs(ssrc);
return 0; // TODO(pwestin): change to void.
}
int32_t ModuleRtpRtcpImpl::SetCSRCStatus(const bool include) {

View File

@ -80,7 +80,7 @@ class ModuleRtpRtcpImpl : public RtpRtcp {
virtual uint32_t SSRC() const OVERRIDE;
// Configure SSRC, default is a random number.
virtual int32_t SetSSRC(const uint32_t ssrc) OVERRIDE;
virtual void SetSSRC(const uint32_t ssrc) OVERRIDE;
virtual int32_t CSRCs(uint32_t arr_of_csrc[kRtpCsrcSize]) const OVERRIDE;
@ -95,13 +95,12 @@ class ModuleRtpRtcpImpl : public RtpRtcp {
virtual uint32_t ByteCountSent() const;
virtual int32_t SetRTXSendStatus(const int mode,
const bool set_ssrc,
const uint32_t ssrc) OVERRIDE;
virtual void SetRTXSendStatus(const int mode) OVERRIDE;
virtual int32_t RTXSendStatus(int* mode, uint32_t* ssrc,
int* payloadType) const OVERRIDE;
virtual void RTXSendStatus(int* mode, uint32_t* ssrc,
int* payloadType) const OVERRIDE;
virtual void SetRtxSsrc(uint32_t ssrc) OVERRIDE;
virtual void SetRtxSendPayloadType(int payload_type) OVERRIDE;

View File

@ -107,11 +107,11 @@ class RtpRtcpImplTest : public ::testing::Test {
receiver_(&clock_) {
// Send module.
EXPECT_EQ(0, sender_.impl_->SetSendingStatus(true));
EXPECT_EQ(0, sender_.impl_->SetSSRC(kSenderSsrc));
sender_.impl_->SetSSRC(kSenderSsrc);
sender_.impl_->SetRemoteSSRC(kReceiverSsrc);
// Receive module.
EXPECT_EQ(0, receiver_.impl_->SetSendingStatus(false));
EXPECT_EQ(0, receiver_.impl_->SetSSRC(kReceiverSsrc));
receiver_.impl_->SetSSRC(kReceiverSsrc);
receiver_.impl_->SetRemoteSSRC(kSenderSsrc);
// Transport settings.
sender_.transport_.SetRtpRtcpModule(receiver_.impl_.get());

View File

@ -312,16 +312,14 @@ uint16_t RTPSender::MaxPayloadLength() const {
uint16_t RTPSender::PacketOverHead() const { return packet_over_head_; }
void RTPSender::SetRTXStatus(int mode, bool set_ssrc, uint32_t ssrc) {
void RTPSender::SetRTXStatus(int mode) {
CriticalSectionScoped cs(send_critsect_);
rtx_ = mode;
if (rtx_ != kRtxOff) {
if (set_ssrc) {
ssrc_rtx_ = ssrc;
} else {
ssrc_rtx_ = ssrc_db_.CreateSSRC(); // Can't be 0.
}
}
}
void RTPSender::SetRtxSsrc(uint32_t ssrc) {
CriticalSectionScoped cs(send_critsect_);
ssrc_rtx_ = ssrc;
}
void RTPSender::RTXStatus(int* mode, uint32_t* ssrc,

View File

@ -184,10 +184,12 @@ class RTPSender : public RTPSenderInterface, public Bitrate::Observer {
bool ProcessNACKBitRate(const uint32_t now);
// RTX.
void SetRTXStatus(int mode, bool set_ssrc, uint32_t ssrc);
void SetRTXStatus(int mode);
void RTXStatus(int* mode, uint32_t* ssrc, int* payload_type) const;
void SetRtxSsrc(uint32_t ssrc);
void SetRtxPayloadType(int payloadType);
// Functions wrapping RTPSenderInterface.

View File

@ -687,8 +687,8 @@ TEST_F(RtpSenderTest, SendRedundantPayloads) {
rtp_header_len += 4; // 4 bytes extension.
rtp_header_len += 4; // 4 extra bytes common to all extension headers.
rtp_sender_->SetRTXStatus(kRtxRetransmitted | kRtxRedundantPayloads, true,
1234);
rtp_sender_->SetRTXStatus(kRtxRetransmitted | kRtxRedundantPayloads);
rtp_sender_->SetRtxSsrc(1234);
// Create and set up parser.
scoped_ptr<webrtc::RtpHeaderParser> rtp_parser(

View File

@ -80,7 +80,7 @@ TEST_F(RtpRtcpAPITest, MTU) {
}
TEST_F(RtpRtcpAPITest, SSRC) {
EXPECT_EQ(0, module->SetSSRC(test_ssrc));
module->SetSSRC(test_ssrc);
EXPECT_EQ(test_ssrc, module->SSRC());
}
@ -119,21 +119,22 @@ TEST_F(RtpRtcpAPITest, RtxSender) {
int rtx_mode = kRtxOff;
const int kRtxPayloadType = 119;
int payload_type = -1;
EXPECT_EQ(0, module->SetRTXSendStatus(kRtxRetransmitted, true, 1));
module->SetRTXSendStatus(kRtxRetransmitted);
module->SetRtxSendPayloadType(kRtxPayloadType);
EXPECT_EQ(0, module->RTXSendStatus(&rtx_mode, &ssrc, &payload_type));
module->SetRtxSsrc(1);
module->RTXSendStatus(&rtx_mode, &ssrc, &payload_type);
EXPECT_EQ(kRtxRetransmitted, rtx_mode);
EXPECT_EQ(1u, ssrc);
EXPECT_EQ(kRtxPayloadType, payload_type);
rtx_mode = kRtxOff;
EXPECT_EQ(0, module->SetRTXSendStatus(kRtxOff, true, 0));
module->SetRTXSendStatus(kRtxOff);
payload_type = -1;
module->SetRtxSendPayloadType(kRtxPayloadType);
EXPECT_EQ(0, module->RTXSendStatus(&rtx_mode, &ssrc, &payload_type));
module->RTXSendStatus(&rtx_mode, &ssrc, &payload_type);
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(kRtxPayloadType, payload_type);
module->SetRTXSendStatus(kRtxRetransmitted);
module->RTXSendStatus(&rtx_mode, &ssrc, &payload_type);
EXPECT_EQ(kRtxRetransmitted, rtx_mode);
EXPECT_EQ(kRtxPayloadType, payload_type);
}
@ -141,7 +142,8 @@ TEST_F(RtpRtcpAPITest, RtxSender) {
TEST_F(RtpRtcpAPITest, RtxReceiver) {
const uint32_t kRtxSsrc = 1;
const int kRtxPayloadType = 119;
rtp_payload_registry_->SetRtxStatus(true, kRtxSsrc);
EXPECT_FALSE(rtp_payload_registry_->RtxEnabled());
rtp_payload_registry_->SetRtxSsrc(kRtxSsrc);
rtp_payload_registry_->SetRtxPayloadType(kRtxPayloadType);
EXPECT_TRUE(rtp_payload_registry_->RtxEnabled());
RTPHeader rtx_header;
@ -150,8 +152,7 @@ TEST_F(RtpRtcpAPITest, RtxReceiver) {
EXPECT_TRUE(rtp_payload_registry_->IsRtx(rtx_header));
rtx_header.ssrc = 0;
EXPECT_FALSE(rtp_payload_registry_->IsRtx(rtx_header));
rtp_payload_registry_->SetRtxStatus(false, kRtxSsrc);
EXPECT_FALSE(rtp_payload_registry_->RtxEnabled());
rtx_header.ssrc = kRtxSsrc;
EXPECT_FALSE(rtp_payload_registry_->IsRtx(rtx_header));
rtx_header.payloadType = 0;
EXPECT_TRUE(rtp_payload_registry_->IsRtx(rtx_header));
}

View File

@ -189,7 +189,7 @@ class RtpRtcpAudioTest : public ::testing::Test {
};
TEST_F(RtpRtcpAudioTest, Basic) {
EXPECT_EQ(0, module1->SetSSRC(test_ssrc));
module1->SetSSRC(test_ssrc);
EXPECT_EQ(0, module1->SetStartTimestamp(test_timestamp));
// Test detection at the end of a DTMF tone.
@ -260,7 +260,7 @@ TEST_F(RtpRtcpAudioTest, RED) {
voice_codec.channels,
(voice_codec.rate < 0) ? 0 : voice_codec.rate));
EXPECT_EQ(0, module1->SetSSRC(test_ssrc));
module1->SetSSRC(test_ssrc);
EXPECT_EQ(0, module1->SetStartTimestamp(test_timestamp));
EXPECT_EQ(0, module1->SetSendingStatus(true));
@ -333,7 +333,7 @@ TEST_F(RtpRtcpAudioTest, DTMF) {
voice_codec.channels,
(voice_codec.rate < 0) ? 0 : voice_codec.rate));
EXPECT_EQ(0, module1->SetSSRC(test_ssrc));
module1->SetSSRC(test_ssrc);
EXPECT_EQ(0, module1->SetStartTimestamp(test_timestamp));
EXPECT_EQ(0, module1->SetSendingStatus(true));

View File

@ -152,8 +152,8 @@ class RtpRtcpRtcpTest : public ::testing::Test {
EXPECT_EQ(0, module1->SetRTCPStatus(kRtcpCompound));
EXPECT_EQ(0, module2->SetRTCPStatus(kRtcpCompound));
EXPECT_EQ(0, module2->SetSSRC(test_ssrc + 1));
EXPECT_EQ(0, module1->SetSSRC(test_ssrc));
module2->SetSSRC(test_ssrc + 1);
module1->SetSSRC(test_ssrc);
EXPECT_EQ(0, module1->SetSequenceNumber(test_sequence_number));
EXPECT_EQ(0, module1->SetStartTimestamp(test_timestamp));
EXPECT_EQ(0, module1->SetCSRCs(test_CSRC, 2));

View File

@ -51,7 +51,7 @@ class RtpRtcpVideoTest : public ::testing::Test {
test_id_, &fake_clock, receiver_, NULL, &rtp_payload_registry_));
EXPECT_EQ(0, video_module_->SetRTCPStatus(kRtcpCompound));
EXPECT_EQ(0, video_module_->SetSSRC(test_ssrc_));
video_module_->SetSSRC(test_ssrc_);
rtp_receiver_->SetNACKStatus(kNackRtcp);
EXPECT_EQ(0, video_module_->SetStorePacketsStatus(true, 600));
EXPECT_EQ(0, video_module_->SetSendingStatus(true));

View File

@ -411,8 +411,8 @@ bool VideoSendStream::ReconfigureVideoEncoder(
static_cast<unsigned char>(i));
}
if (config_.rtp.rtx.payload_type != 0)
rtp_rtcp_->SetRtxSendPayloadType(channel_, config_.rtp.rtx.payload_type);
assert(config_.rtp.rtx.payload_type >= 0);
rtp_rtcp_->SetRtxSendPayloadType(channel_, config_.rtp.rtx.payload_type);
return true;
}

View File

@ -792,14 +792,13 @@ int32_t ViEChannel::EnableKeyFrameRequestCallback(const bool enable) {
int32_t ViEChannel::SetSSRC(const uint32_t SSRC,
const StreamType usage,
const uint8_t simulcast_idx) {
int rtx_settings = kRtxRetransmitted;
if (config_.Get<PaddingStrategy>().redundant_payloads)
rtx_settings |= kRtxRedundantPayloads;
if (simulcast_idx == 0) {
if (usage == kViEStreamTypeRtx) {
return rtp_rtcp_->SetRTXSendStatus(rtx_settings, true, SSRC);
rtp_rtcp_->SetRtxSsrc(SSRC);
} else {
rtp_rtcp_->SetSSRC(SSRC);
}
return rtp_rtcp_->SetSSRC(SSRC);
return 0;
}
CriticalSectionScoped cs(rtp_rtcp_cs_.get());
if (simulcast_idx > simulcast_rtp_rtcp_.size()) {
@ -813,14 +812,16 @@ int32_t ViEChannel::SetSSRC(const uint32_t SSRC,
}
RtpRtcp* rtp_rtcp_module = *it;
if (usage == kViEStreamTypeRtx) {
return rtp_rtcp_module->SetRTXSendStatus(rtx_settings, true, SSRC);
rtp_rtcp_module->SetRtxSsrc(SSRC);
} else {
rtp_rtcp_module->SetSSRC(SSRC);
}
return rtp_rtcp_module->SetSSRC(SSRC);
return 0;
}
int32_t ViEChannel::SetRemoteSSRCType(const StreamType usage,
const uint32_t SSRC) {
vie_receiver_.SetRtxStatus(true, SSRC);
vie_receiver_.SetRtxSsrc(SSRC);
return 0;
}
@ -860,14 +861,16 @@ int32_t ViEChannel::GetRemoteCSRC(uint32_t CSRCs[kRtpCsrcSize]) {
}
int ViEChannel::SetRtxSendPayloadType(int payload_type) {
if (rtp_rtcp_->Sending()) {
return -1;
}
int rtx_settings = kRtxRetransmitted;
if (config_.Get<PaddingStrategy>().redundant_payloads)
rtx_settings |= kRtxRedundantPayloads;
rtp_rtcp_->SetRtxSendPayloadType(payload_type);
rtp_rtcp_->SetRTXSendStatus(rtx_settings);
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);
(*it)->SetRTXSendStatus(rtx_settings);
}
return 0;
}

View File

@ -96,12 +96,12 @@ void ViEReceiver::SetNackStatus(bool enable,
rtp_receiver_->SetNACKStatus(enable ? kNackRtcp : kNackOff);
}
void ViEReceiver::SetRtxStatus(bool enable, uint32_t ssrc) {
rtp_payload_registry_->SetRtxStatus(enable, ssrc);
void ViEReceiver::SetRtxPayloadType(int payload_type) {
rtp_payload_registry_->SetRtxPayloadType(payload_type);
}
void ViEReceiver::SetRtxPayloadType(uint32_t payload_type) {
rtp_payload_registry_->SetRtxPayloadType(payload_type);
void ViEReceiver::SetRtxSsrc(uint32_t ssrc) {
rtp_payload_registry_->SetRtxSsrc(ssrc);
}
uint32_t ViEReceiver::GetRemoteSsrc() const {

View File

@ -47,8 +47,8 @@ class ViEReceiver : public RtpData {
bool RegisterPayload(const VideoCodec& video_codec);
void SetNackStatus(bool enable, int max_nack_reordering_threshold);
void SetRtxStatus(bool enable, uint32_t ssrc);
void SetRtxPayloadType(uint32_t payload_type);
void SetRtxPayloadType(int payload_type);
void SetRtxSsrc(uint32_t ssrc);
uint32_t GetRemoteSsrc() const;
int GetCsrcs(uint32_t* csrcs) const;

View File

@ -114,7 +114,7 @@ class VideoSendStream {
// Settings for RTP retransmission payload format, see RFC 4588 for
// details.
struct Rtx {
Rtx() : payload_type(0) {}
Rtx() : payload_type(-1) {}
std::string ToString() const;
// SSRCs to use for the RTX streams.
std::vector<uint32_t> ssrcs;

View File

@ -3072,13 +3072,7 @@ Channel::SetLocalSSRC(unsigned int ssrc)
"SetLocalSSRC() already sending");
return -1;
}
if (_rtpRtcpModule->SetSSRC(ssrc) != 0)
{
_engineStatisticsPtr->SetLastError(
VE_RTP_RTCP_MODULE_ERROR, kTraceError,
"SetLocalSSRC() failed to set SSRC");
return -1;
}
_rtpRtcpModule->SetSSRC(ssrc);
return 0;
}