From 9f5ebb525130f207229dfa350ce8c2bdd22163c7 Mon Sep 17 00:00:00 2001 From: "mflodman@webrtc.org" <mflodman@webrtc.org@4adac7df-926f-26a2-2b94-8c16560cd09d> Date: Fri, 12 Apr 2013 14:55:46 +0000 Subject: [PATCH] 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 --- webrtc/modules/rtp_rtcp/interface/rtp_rtcp.h | 23 +++++++---- .../rtp_rtcp/interface/rtp_rtcp_defines.h | 2 + webrtc/modules/rtp_rtcp/mocks/mock_rtp_rtcp.h | 20 ++++++---- .../rtp_rtcp/source/nack_rtx_unittest.cc | 13 ++++--- .../rtp_rtcp/source/rtp_payload_registry.h | 4 ++ .../modules/rtp_rtcp/source/rtp_receiver.cc | 32 +++++++++++++--- webrtc/modules/rtp_rtcp/source/rtp_receiver.h | 7 +++- .../modules/rtp_rtcp/source/rtp_rtcp_impl.cc | 34 ++++++++++------- .../modules/rtp_rtcp/source/rtp_rtcp_impl.h | 12 ++++-- webrtc/modules/rtp_rtcp/source/rtp_sender.cc | 24 +++++++++--- webrtc/modules/rtp_rtcp/source/rtp_sender.h | 8 ++-- .../modules/rtp_rtcp/test/testAPI/test_api.cc | 24 ++++++++++-- webrtc/video_engine/include/vie_rtp_rtcp.h | 8 ++++ webrtc/video_engine/vie_channel.cc | 27 ++++++++++++- webrtc/video_engine/vie_channel.h | 3 ++ webrtc/video_engine/vie_rtp_rtcp_impl.cc | 38 +++++++++++++++++++ webrtc/video_engine/vie_rtp_rtcp_impl.h | 4 ++ 17 files changed, 222 insertions(+), 61 deletions(-) diff --git a/webrtc/modules/rtp_rtcp/interface/rtp_rtcp.h b/webrtc/modules/rtp_rtcp/interface/rtp_rtcp.h index 385520487..d7676d989 100644 --- a/webrtc/modules/rtp_rtcp/interface/rtp_rtcp.h +++ b/webrtc/modules/rtp_rtcp/interface/rtp_rtcp.h @@ -232,14 +232,18 @@ class RtpRtcp : public Module { /* * Turn on/off receiving RTX (RFC 4588) on a specific SSRC. */ - virtual int32_t SetRTXReceiveStatus(const bool enable, - const uint32_t SSRC) = 0; + virtual int32_t SetRTXReceiveStatus(bool enable, 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. */ 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 @@ -416,15 +420,18 @@ class RtpRtcp : public Module { /* * Turn on/off sending RTX (RFC 4588) on a specific SSRC. */ - virtual int32_t SetRTXSendStatus(const RtxMode mode, - const bool setSSRC, - const uint32_t SSRC) = 0; + virtual int32_t SetRTXSendStatus(RtxMode mode, bool set_ssrc, + 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. */ - virtual int32_t RTXSendStatus(RtxMode* mode, - uint32_t* SSRC) const = 0; + virtual int32_t RTXSendStatus(RtxMode* mode, uint32_t* ssrc, + int* payloadType) const = 0; /* * sends kRtcpByeCode when going from true to false diff --git a/webrtc/modules/rtp_rtcp/interface/rtp_rtcp_defines.h b/webrtc/modules/rtp_rtcp/interface/rtp_rtcp_defines.h index 616e5345d..3da5d7526 100644 --- a/webrtc/modules/rtp_rtcp/interface/rtp_rtcp_defines.h +++ b/webrtc/modules/rtp_rtcp/interface/rtp_rtcp_defines.h @@ -113,6 +113,8 @@ enum RtxMode { kRtxAll = 2 // Apply RTX to all packets (source + retransmissions). }; +const int kRtxHeaderSize = 2; + struct RTCPSenderInfo { uint32_t NTPseconds; diff --git a/webrtc/modules/rtp_rtcp/mocks/mock_rtp_rtcp.h b/webrtc/modules/rtp_rtcp/mocks/mock_rtp_rtcp.h index 76cc31680..2d0206296 100644 --- a/webrtc/modules/rtp_rtcp/mocks/mock_rtp_rtcp.h +++ b/webrtc/modules/rtp_rtcp/mocks/mock_rtp_rtcp.h @@ -76,11 +76,14 @@ class MockRtpRtcp : public RtpRtcp { MOCK_METHOD2(SetSSRCFilter, int32_t(const bool enable, const uint32_t allowedSSRC)); MOCK_METHOD2(SetRTXReceiveStatus, - int32_t(const bool enable, const uint32_t SSRC)); - MOCK_CONST_METHOD2(RTXReceiveStatus, - int32_t(bool* enable, uint32_t* SSRC)); + int32_t(bool enable, uint32_t ssrc)); + MOCK_CONST_METHOD3(RTXReceiveStatus, + int32_t(bool* enable, uint32_t* ssrc, int* payload_type)); + MOCK_METHOD1(SetRtxReceivePayloadType, + void(int)); 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, int32_t(const uint32_t audioReceivedNTPsecs, const uint32_t audioReceivedNTPfrac, @@ -128,10 +131,11 @@ class MockRtpRtcp : public RtpRtcp { MOCK_METHOD1(SetCSRCStatus, int32_t(const bool include)); MOCK_METHOD3(SetRTXSendStatus, - int32_t(const RtxMode mode, const bool setSSRC, - const uint32_t SSRC)); - MOCK_CONST_METHOD2(RTXSendStatus, - int32_t(RtxMode* mode, uint32_t* SSRC)); + int32_t(RtxMode mode, bool setSSRC, uint32_t ssrc)); + MOCK_CONST_METHOD3(RTXSendStatus, + int32_t(RtxMode* mode, uint32_t* ssrc, int* payload_type)); + MOCK_METHOD1(SetRtxSendPayloadType, + void(int)); MOCK_METHOD1(SetSendingStatus, int32_t(const bool sending)); MOCK_CONST_METHOD0(Sending, diff --git a/webrtc/modules/rtp_rtcp/source/nack_rtx_unittest.cc b/webrtc/modules/rtp_rtcp/source/nack_rtx_unittest.cc index 925db94e7..b1d494c6e 100644 --- a/webrtc/modules/rtp_rtcp/source/nack_rtx_unittest.cc +++ b/webrtc/modules/rtp_rtcp/source/nack_rtx_unittest.cc @@ -193,8 +193,10 @@ TEST_F(RtpRtcpRtxNackTest, RTCP) { TEST_F(RtpRtcpRtxNackTest, RTXNack) { EXPECT_EQ(0, rtp_rtcp_module_->SetRTXReceiveStatus(true, kTestSsrc + 1)); - EXPECT_EQ(0, rtp_rtcp_module_->SetRTXSendStatus(kRtxRetransmitted, - true, kTestSsrc + 1)); + rtp_rtcp_module_->SetRtxReceivePayloadType(119); + EXPECT_EQ(0, rtp_rtcp_module_->SetRTXSendStatus(kRtxRetransmitted, true, + kTestSsrc + 1)); + rtp_rtcp_module_->SetRtxSendPayloadType(119); transport_.DropEveryNthPacket(10); @@ -251,8 +253,8 @@ TEST_F(RtpRtcpRtxNackTest, RTXNack) { TEST_F(RtpRtcpRtxNackTest, RTXAllNoLoss) { EXPECT_EQ(0, rtp_rtcp_module_->SetRTXReceiveStatus(true, kTestSsrc + 1)); - EXPECT_EQ(0, rtp_rtcp_module_->SetRTXSendStatus(kRtxAll, - true, kTestSsrc + 1)); + EXPECT_EQ(0, rtp_rtcp_module_->SetRTXSendStatus(kRtxAll, true, + kTestSsrc + 1)); transport_.DropEveryNthPacket(0); uint32_t timestamp = 3000; @@ -285,8 +287,7 @@ TEST_F(RtpRtcpRtxNackTest, RTXAllNoLoss) { TEST_F(RtpRtcpRtxNackTest, RTXAllWithLoss) { EXPECT_EQ(0, rtp_rtcp_module_->SetRTXReceiveStatus(true, kTestSsrc + 1)); - EXPECT_EQ(0, rtp_rtcp_module_->SetRTXSendStatus(kRtxAll, - true, + EXPECT_EQ(0, rtp_rtcp_module_->SetRTXSendStatus(kRtxAll, true, kTestSsrc + 1)); int loss = 10; diff --git a/webrtc/modules/rtp_rtcp/source/rtp_payload_registry.h b/webrtc/modules/rtp_rtcp/source/rtp_payload_registry.h index 7ba4c2517..465a4edd9 100644 --- a/webrtc/modules/rtp_rtcp/source/rtp_payload_registry.h +++ b/webrtc/modules/rtp_rtcp/source/rtp_payload_registry.h @@ -93,6 +93,10 @@ class RTPPayloadRegistry { last_received_payload_type_ = last_received_payload_type; } + int8_t last_received_media_payload_type() const { + return last_received_media_payload_type_; + }; + private: // Prunes the payload type map of the specific payload type, if it exists. void DeregisterAudioCodecOrRedTypeRegardlessOfPayloadType( diff --git a/webrtc/modules/rtp_rtcp/source/rtp_receiver.cc b/webrtc/modules/rtp_rtcp/source/rtp_receiver.cc index 6db157eee..7a811659a 100644 --- a/webrtc/modules/rtp_rtcp/source/rtp_receiver.cc +++ b/webrtc/modules/rtp_rtcp/source/rtp_receiver.cc @@ -94,7 +94,8 @@ RTPReceiver::RTPReceiver(const int32_t id, nack_method_(kNackOff), max_reordering_threshold_(kDefaultMaxReorderingThreshold), rtx_(false), - ssrc_rtx_(0) { + ssrc_rtx_(0), + payload_type_rtx_(-1) { assert(incoming_audio_messages_callback && incoming_messages_callback && incoming_payload_callback); @@ -288,17 +289,23 @@ int32_t RTPReceiver::SetNACKStatus(const NACKMethod method, return 0; } -void RTPReceiver::SetRTXStatus(const bool enable, - const uint32_t ssrc) { +void RTPReceiver::SetRTXStatus(bool enable, uint32_t ssrc) { CriticalSectionScoped lock(critical_section_rtp_receiver_); rtx_ = enable; 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_); *enable = 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 { @@ -350,10 +357,23 @@ int32_t RTPReceiver::IncomingRTPPacket( } if (rtx_) { if (ssrc_rtx_ == rtp_header->header.ssrc) { - // Sanity check. - if (rtp_header->header.headerLength + 2 > packet_length) { + // Sanity check, RTX packets has 2 extra header bytes. + if (rtp_header->header.headerLength + kRtxHeaderSize > packet_length) { 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.sequenceNumber = (packet[rtp_header->header.headerLength] << 8) + diff --git a/webrtc/modules/rtp_rtcp/source/rtp_receiver.h b/webrtc/modules/rtp_rtcp/source/rtp_receiver.h index 8d794ced3..eaaab79c6 100644 --- a/webrtc/modules/rtp_rtcp/source/rtp_receiver.h +++ b/webrtc/modules/rtp_rtcp/source/rtp_receiver.h @@ -141,9 +141,11 @@ class RTPReceiver : public Bitrate { void GetHeaderExtensionMapCopy(RtpHeaderExtensionMap* map) const; // 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; @@ -234,6 +236,7 @@ class RTPReceiver : public Bitrate { bool rtx_; uint32_t ssrc_rtx_; + int payload_type_rtx_; }; } // namespace webrtc diff --git a/webrtc/modules/rtp_rtcp/source/rtp_rtcp_impl.cc b/webrtc/modules/rtp_rtcp/source/rtp_rtcp_impl.cc index 1597ab2cd..bda7f1218 100644 --- a/webrtc/modules/rtp_rtcp/source/rtp_rtcp_impl.cc +++ b/webrtc/modules/rtp_rtcp/source/rtp_rtcp_impl.cc @@ -314,7 +314,7 @@ void ModuleRtpRtcpImpl::ProcessDeadOrAliveTimer() { bool do_callback = false; // 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()); if (dead_or_alive_active_) { @@ -325,7 +325,7 @@ void ModuleRtpRtcpImpl::ProcessDeadOrAliveTimer() { if (rtcp_receiver_.LastReceived() + 12000 > now) RTCPalive = true; - + do_callback = true; } } @@ -532,32 +532,38 @@ int32_t ModuleRtpRtcpImpl::RemoteCSRCs( return rtp_receiver_->CSRCs(arr_of_csrc); } -int32_t ModuleRtpRtcpImpl::SetRTXSendStatus( - const RtxMode mode, - const bool set_ssrc, - const uint32_t ssrc) { +int32_t ModuleRtpRtcpImpl::SetRTXSendStatus(RtxMode mode, bool set_ssrc, + uint32_t ssrc) { rtp_sender_.SetRTXStatus(mode, set_ssrc, ssrc); return 0; } -int32_t ModuleRtpRtcpImpl::RTXSendStatus(RtxMode* mode, uint32_t* ssrc) const { - rtp_sender_.RTXStatus(mode, ssrc); +int32_t ModuleRtpRtcpImpl::RTXSendStatus(RtxMode* mode, uint32_t* ssrc, + int* payload_type) const { + rtp_sender_.RTXStatus(mode, ssrc, payload_type); return 0; } -int32_t ModuleRtpRtcpImpl::SetRTXReceiveStatus( - const bool enable, - const uint32_t ssrc) { +int32_t ModuleRtpRtcpImpl::SetRTXReceiveStatus(bool enable, + uint32_t ssrc) { rtp_receiver_->SetRTXStatus(enable, ssrc); return 0; } -int32_t ModuleRtpRtcpImpl::RTXReceiveStatus(bool* enable, - uint32_t* ssrc) const { - rtp_receiver_->RTXStatus(enable, ssrc); +int32_t ModuleRtpRtcpImpl::RTXReceiveStatus(bool* enable, uint32_t* ssrc, + int* payload_type) const { + rtp_receiver_->RTXStatus(enable, ssrc, payload_type); 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. int32_t ModuleRtpRtcpImpl::IncomingPacket( const uint8_t* incoming_packet, diff --git a/webrtc/modules/rtp_rtcp/source/rtp_rtcp_impl.h b/webrtc/modules/rtp_rtcp/source/rtp_rtcp_impl.h index 3d0be8be4..8311388cb 100644 --- a/webrtc/modules/rtp_rtcp/source/rtp_rtcp_impl.h +++ b/webrtc/modules/rtp_rtcp/source/rtp_rtcp_impl.h @@ -103,8 +103,10 @@ class ModuleRtpRtcpImpl : public RtpRtcp { virtual int32_t SetRTXReceiveStatus(const bool enable, const uint32_t ssrc); - virtual int32_t RTXReceiveStatus(bool* enable, - uint32_t* ssrc) const; + virtual int32_t RTXReceiveStatus(bool* enable, uint32_t* ssrc, + int* payloadType) const; + + virtual void SetRtxReceivePayloadType(int payload_type); // Called by the network module when we receive a packet. virtual int32_t IncomingPacket(const uint8_t* incoming_packet, @@ -161,7 +163,11 @@ class ModuleRtpRtcpImpl : public RtpRtcp { const bool set_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. virtual int32_t SetSendingStatus(const bool sending); diff --git a/webrtc/modules/rtp_rtcp/source/rtp_sender.cc b/webrtc/modules/rtp_rtcp/source/rtp_sender.cc index 0e481c752..54c242d05 100644 --- a/webrtc/modules/rtp_rtcp/source/rtp_sender.cc +++ b/webrtc/modules/rtp_rtcp/source/rtp_sender.cc @@ -58,7 +58,7 @@ RTPSender::RTPSender(const int32_t id, const bool audio, Clock *clock, start_time_stamp_(0), ssrc_db_(*SSRCDatabase::GetSSRCDatabase()), remote_ssrc_(0), sequence_number_forced_(false), ssrc_forced_(false), 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_, 0, sizeof(nack_byte_count_)); memset(csrc_, 0, sizeof(csrc_)); @@ -255,8 +255,7 @@ uint16_t RTPSender::MaxPayloadLength() const { uint16_t RTPSender::PacketOverHead() const { return packet_over_head_; } -void RTPSender::SetRTXStatus(const RtxMode mode, const bool set_ssrc, - const uint32_t ssrc) { +void RTPSender::SetRTXStatus(RtxMode mode, bool set_ssrc, uint32_t ssrc) { CriticalSectionScoped cs(send_critsect_); rtx_ = mode; 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_); *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, @@ -1222,6 +1229,13 @@ void RTPSender::BuildRtxPacket(uint8_t* buffer, uint16_t* length, // Add original RTP header. 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. uint8_t *ptr = data_buffer_rtx + 2; ModuleRTPUtility::AssignUWord16ToBuffer(ptr, sequence_number_rtx_++); diff --git a/webrtc/modules/rtp_rtcp/source/rtp_sender.h b/webrtc/modules/rtp_rtcp/source/rtp_sender.h index b57bcf484..0f4163279 100644 --- a/webrtc/modules/rtp_rtcp/source/rtp_sender.h +++ b/webrtc/modules/rtp_rtcp/source/rtp_sender.h @@ -174,10 +174,11 @@ class RTPSender : public Bitrate, public RTPSenderInterface { bool ProcessNACKBitRate(const uint32_t now); // RTX. - void SetRTXStatus(const RtxMode mode, const bool set_ssrc, - const uint32_t SSRC); + void SetRTXStatus(RtxMode mode, bool set_ssrc, 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. virtual int32_t BuildRTPheader( @@ -310,6 +311,7 @@ class RTPSender : public Bitrate, public RTPSenderInterface { bool include_csrcs_; RtxMode rtx_; uint32_t ssrc_rtx_; + int payload_type_rtx_; }; } // namespace webrtc diff --git a/webrtc/modules/rtp_rtcp/test/testAPI/test_api.cc b/webrtc/modules/rtp_rtcp/test/testAPI/test_api.cc index 4a00935d6..1eaf0f02c 100644 --- a/webrtc/modules/rtp_rtcp/test/testAPI/test_api.cc +++ b/webrtc/modules/rtp_rtcp/test/testAPI/test_api.cc @@ -111,24 +111,40 @@ TEST_F(RtpRtcpAPITest, RTCP) { TEST_F(RtpRtcpAPITest, RTXSender) { unsigned int ssrc = 0; RtxMode rtx_mode = kRtxOff; + const int kRtxPayloadType = 119; + int payload_type = -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(1u, ssrc); + EXPECT_EQ(kRtxPayloadType, payload_type); rtx_mode = kRtxOff; 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(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) { bool enable = false; unsigned int ssrc = 0; + const int kRtxPayloadType = 119; + int payload_type = -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_EQ(1u, ssrc); + EXPECT_EQ(kRtxPayloadType ,payload_type); 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_EQ(kRtxPayloadType ,payload_type); } diff --git a/webrtc/video_engine/include/vie_rtp_rtcp.h b/webrtc/video_engine/include/vie_rtp_rtcp.h index a178ea111..b1fd90c53 100644 --- a/webrtc/video_engine/include/vie_rtp_rtcp.h +++ b/webrtc/video_engine/include/vie_rtp_rtcp.h @@ -133,6 +133,14 @@ class WEBRTC_DLLEXPORT ViERTP_RTCP { virtual int GetRemoteCSRCs(const int video_channel, 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 // start sequence number is normally a random number. virtual int SetStartSequenceNumber(const int video_channel, diff --git a/webrtc/video_engine/vie_channel.cc b/webrtc/video_engine/vie_channel.cc index a8fecbee9..7aeb6a14d 100644 --- a/webrtc/video_engine/vie_channel.cc +++ b/webrtc/video_engine/vie_channel.cc @@ -973,8 +973,31 @@ int32_t ViEChannel::GetRemoteCSRC(uint32_t CSRCs[kRtpCsrcSize]) { return 0; } -int32_t ViEChannel::SetStartSequenceNumber( - uint16_t sequence_number) { +int ViEChannel::SetRtxSendPayloadType(int payload_type) { + 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", __FUNCTION__); diff --git a/webrtc/video_engine/vie_channel.h b/webrtc/video_engine/vie_channel.h index 3aacd9c37..620d64e28 100644 --- a/webrtc/video_engine/vie_channel.h +++ b/webrtc/video_engine/vie_channel.h @@ -139,6 +139,9 @@ class ViEChannel // Gets the CSRC for the incoming stream. 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. int32_t SetStartSequenceNumber(uint16_t sequence_number); diff --git a/webrtc/video_engine/vie_rtp_rtcp_impl.cc b/webrtc/video_engine/vie_rtp_rtcp_impl.cc index a23019349..4233894df 100644 --- a/webrtc/video_engine/vie_rtp_rtcp_impl.cc +++ b/webrtc/video_engine/vie_rtp_rtcp_impl.cc @@ -233,6 +233,44 @@ int ViERTP_RTCPImpl::GetRemoteCSRCs(const int video_channel, 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, uint16_t sequence_number) { WEBRTC_TRACE(kTraceApiCall, kTraceVideo, diff --git a/webrtc/video_engine/vie_rtp_rtcp_impl.h b/webrtc/video_engine/vie_rtp_rtcp_impl.h index 1c1971ae0..257974ce3 100644 --- a/webrtc/video_engine/vie_rtp_rtcp_impl.h +++ b/webrtc/video_engine/vie_rtp_rtcp_impl.h @@ -39,6 +39,10 @@ class ViERTP_RTCPImpl unsigned int& SSRC) const; // NOLINT virtual int GetRemoteCSRCs(const int video_channel, 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, uint16_t sequence_number); virtual int SetRTCPStatus(const int video_channel,