Support associated payload type when registering Rtx payload type.
Major changes include,
- Add associated payload type for SetRtxSendPayloadType & SetRtxReceivePayloadType.
- Receiver: Restore RTP packets by the new RTX-APT map.
- Sender: Send RTP packets by checking RTX-APT map.
- Add RTX payload type for RED in the default codec list.
BUG=4024
R=pbos@webrtc.org, stefan@webrtc.org
TBR=mflodman@webrtc.org
Review URL: https://webrtc-codereview.appspot.com/26259004
Patch from Changbin Shao <changbin.shao@intel.com>.
git-svn-id: http://webrtc.googlecode.com/svn/trunk@8028 4adac7df-926f-26a2-2b94-8c16560cd09d
diff --git a/talk/libjingle_tests.gyp b/talk/libjingle_tests.gyp
index ac13a4c..19ce82b 100755
--- a/talk/libjingle_tests.gyp
+++ b/talk/libjingle_tests.gyp
@@ -88,10 +88,16 @@
'target_name': 'libjingle_media_unittest',
'type': 'executable',
'dependencies': [
+ '<(DEPTH)/testing/gmock.gyp:gmock',
'<(webrtc_root)/base/base_tests.gyp:rtc_base_tests_utils',
'libjingle.gyp:libjingle_media',
'libjingle_unittest_main',
],
+ 'direct_dependent_settings': {
+ 'include_dirs': [
+ '<(DEPTH)/testing/gmock/include',
+ ],
+ },
'sources': [
# TODO(ronghuawu): Reenable this test.
# 'media/base/capturemanager_unittest.cc',
diff --git a/talk/media/webrtc/fakewebrtcvideoengine.h b/talk/media/webrtc/fakewebrtcvideoengine.h
index aaa2f3b..dff6d01 100644
--- a/talk/media/webrtc/fakewebrtcvideoengine.h
+++ b/talk/media/webrtc/fakewebrtcvideoengine.h
@@ -266,8 +266,6 @@
receive_(false),
can_transmit_(true),
remote_rtx_ssrc_(-1),
- rtx_send_payload_type(-1),
- rtx_recv_payload_type(-1),
rtcp_status_(webrtc::kRtcpNone),
key_frame_request_method_(webrtc::kViEKeyFrameRequestNone),
tmmbr_(false),
@@ -305,8 +303,8 @@
std::map<int, int> ssrcs_;
std::map<int, int> rtx_ssrcs_;
int remote_rtx_ssrc_;
- int rtx_send_payload_type;
- int rtx_recv_payload_type;
+ std::map<int, int> rtx_send_payload_types;
+ std::map<int, int> rtx_recv_payload_types;
std::string cname_;
webrtc::ViERTCPMode rtcp_status_;
webrtc::ViEKeyFrameRequestMethod key_frame_request_method_;
@@ -614,14 +612,30 @@
WEBRTC_ASSERT_CHANNEL(channel);
channels_[GetOriginalChannelId(channel)]->receive_bandwidth_ =
receive_bandwidth;
- };
- int GetRtxSendPayloadType(int channel) {
- WEBRTC_CHECK_CHANNEL(channel);
- return channels_[channel]->rtx_send_payload_type;
}
- int GetRtxRecvPayloadType(int channel) {
- WEBRTC_CHECK_CHANNEL(channel);
- return channels_[channel]->rtx_recv_payload_type;
+ std::set<int> GetRtxSendPayloadType(int channel) {
+ std::set<int> rtx_payload_types;
+ if (channels_.find(channel) == channels_.end())
+ return rtx_payload_types;
+
+ std::map<int, int>::const_iterator it;
+ for (it = channels_[channel]->rtx_send_payload_types.begin();
+ it != channels_[channel]->rtx_send_payload_types.end(); ++it) {
+ rtx_payload_types.insert(it->first);
+ }
+ return rtx_payload_types;
+ }
+ std::set<int> GetRtxRecvPayloadType(int channel) {
+ std::set<int> rtx_payload_types;
+ if (channels_.find(channel) == channels_.end())
+ return rtx_payload_types;
+
+ std::map<int, int>::const_iterator it;
+ for (it = channels_[channel]->rtx_recv_payload_types.begin();
+ it != channels_[channel]->rtx_recv_payload_types.end(); ++it) {
+ rtx_payload_types.insert(it->first);
+ }
+ return rtx_payload_types;
}
int GetRemoteRtxSsrc(int channel) {
WEBRTC_CHECK_CHANNEL(channel);
@@ -1006,17 +1020,27 @@
WEBRTC_STUB_CONST(GetRemoteSSRC, (const int, unsigned int&));
WEBRTC_STUB_CONST(GetRemoteCSRCs, (const int, unsigned int*));
- WEBRTC_FUNC(SetRtxSendPayloadType, (const int channel,
- const uint8 payload_type)) {
+ WEBRTC_FUNC(SetRtxSendPayloadType,
+ (const int channel,
+ const uint8 payload_type,
+ const uint8 associated_payload_type)) {
WEBRTC_CHECK_CHANNEL(channel);
- channels_[channel]->rtx_send_payload_type = payload_type;
+ assert(payload_type >= 0);
+ assert(associated_payload_type >= 0);
+ channels_[channel]->rtx_send_payload_types[payload_type] =
+ associated_payload_type;
return 0;
}
- WEBRTC_FUNC(SetRtxReceivePayloadType, (const int channel,
- const uint8 payload_type)) {
+ WEBRTC_FUNC(SetRtxReceivePayloadType,
+ (const int channel,
+ const uint8 payload_type,
+ const uint8 associated_payload_type)) {
WEBRTC_CHECK_CHANNEL(channel);
- channels_[channel]->rtx_recv_payload_type = payload_type;
+ assert(payload_type >= 0);
+ assert(associated_payload_type >= 0);
+ channels_[channel]->rtx_recv_payload_types[payload_type] =
+ associated_payload_type;
return 0;
}
diff --git a/talk/media/webrtc/webrtcvideoengine.cc b/talk/media/webrtc/webrtcvideoengine.cc
index 689aef3..3cce243 100644
--- a/talk/media/webrtc/webrtcvideoengine.cc
+++ b/talk/media/webrtc/webrtcvideoengine.cc
@@ -180,6 +180,13 @@
const char kVp8CodecName[] = "VP8";
const char kVp9CodecName[] = "VP9";
+const int kDefaultVp8PlType = 100;
+const int kDefaultVp9PlType = 101;
+const int kDefaultRedPlType = 116;
+const int kDefaultUlpfecType = 117;
+const int kDefaultRtxVp8PlType = 96;
+const int kDefaultRtxRedPlType = 97;
+
// TODO(ronghuawu): Change to 640x360.
const int kDefaultVideoMaxWidth = 640;
const int kDefaultVideoMaxHeight = 400;
@@ -305,14 +312,16 @@
std::vector<VideoCodec> DefaultVideoCodecList() {
std::vector<VideoCodec> codecs;
if (CodecIsInternallySupported(kVp9CodecName)) {
- codecs.push_back(
- MakeVideoCodecWithDefaultFeedbackParams(101, kVp9CodecName));
+ codecs.push_back(MakeVideoCodecWithDefaultFeedbackParams(kDefaultVp9PlType,
+ kVp9CodecName));
// TODO(andresp): Add rtx codec for vp9 and verify it works.
}
- codecs.push_back(MakeVideoCodecWithDefaultFeedbackParams(100, kVp8CodecName));
- codecs.push_back(MakeRtxCodec(96, 100));
- codecs.push_back(MakeVideoCodec(116, kRedCodecName));
- codecs.push_back(MakeVideoCodec(117, kUlpfecCodecName));
+ codecs.push_back(MakeVideoCodecWithDefaultFeedbackParams(kDefaultVp8PlType,
+ kVp8CodecName));
+ codecs.push_back(MakeRtxCodec(kDefaultRtxVp8PlType, kDefaultVp8PlType));
+ codecs.push_back(MakeVideoCodec(kDefaultRedPlType, kRedCodecName));
+ codecs.push_back(MakeRtxCodec(kDefaultRtxRedPlType, kDefaultRedPlType));
+ codecs.push_back(MakeVideoCodec(kDefaultUlpfecType, kUlpfecCodecName));
return codecs;
}
@@ -1729,7 +1738,6 @@
first_receive_ssrc_(kSsrcUnset),
receiver_report_ssrc_(kSsrcUnset),
num_unsignalled_recv_channels_(0),
- send_rtx_type_(-1),
send_red_type_(-1),
send_fec_type_(-1),
sending_(false),
@@ -1819,7 +1827,6 @@
std::vector<webrtc::VideoCodec> send_codecs;
VideoCodec checked_codec;
VideoCodec dummy_current; // Will be ignored by CanSendCodec.
- std::map<int, int> primary_rtx_pt_mapping;
bool nack_enabled = nack_enabled_;
bool remb_enabled = remb_enabled_;
for (std::vector<VideoCodec>::const_iterator iter = codecs.begin();
@@ -1832,7 +1839,7 @@
int rtx_type = iter->id;
int rtx_primary_type = -1;
if (iter->GetParam(kCodecParamAssociatedPayloadType, &rtx_primary_type)) {
- primary_rtx_pt_mapping[rtx_primary_type] = rtx_type;
+ send_rtx_apt_types_[rtx_type] = rtx_primary_type;
}
} else if (engine()->CanSendCodec(*iter, dummy_current, &checked_codec)) {
webrtc::VideoCodec wcodec;
@@ -1897,14 +1904,6 @@
// Select the first matched codec.
webrtc::VideoCodec& codec(send_codecs[0]);
- // Set RTX payload type if primary now active. This value will be used in
- // SetSendCodec.
- std::map<int, int>::const_iterator rtx_it =
- primary_rtx_pt_mapping.find(static_cast<int>(codec.plType));
- if (rtx_it != primary_rtx_pt_mapping.end()) {
- send_rtx_type_ = rtx_it->second;
- }
-
if (BitrateIsSet(codec.minBitrate) && BitrateIsSet(codec.maxBitrate) &&
codec.minBitrate > codec.maxBitrate) {
// TODO(pthatcher): This behavior contradicts other behavior in
@@ -3831,8 +3830,11 @@
<< vie_codec.codecSpecific.VP8.keyFrameInterval;
}
- if (send_rtx_type_ != -1) {
- LOG(LS_INFO) << "RTX payload type: " << send_rtx_type_;
+ std::map<int, int>::const_iterator it;
+ for (it = send_rtx_apt_types_.begin(); it != send_rtx_apt_types_.end();
+ ++it) {
+ LOG(LS_INFO) << "RTX payload type: " << it->first
+ << ", associated payload type:" << it->second;
}
LogSimulcastSubstreams(vie_codec);
@@ -3850,7 +3852,6 @@
it != receive_codecs_.end(); ++it) {
pt_to_codec[it->plType] = &(*it);
}
- bool rtx_registered = false;
for (std::vector<webrtc::VideoCodec>::iterator it = receive_codecs_.begin();
it != receive_codecs_.end(); ++it) {
if (it->codecType == webrtc::kVideoCodecRED) {
@@ -3861,11 +3862,6 @@
// If this is an RTX codec we have to verify that it is associated with
// a valid video codec which we have RTX support for.
if (_stricmp(it->plName, kRtxCodecName) == 0) {
- // WebRTC only supports one RTX codec at a time.
- if (rtx_registered) {
- LOG(LS_ERROR) << "Only one RTX codec at a time is supported.";
- return false;
- }
std::map<int, int>::iterator apt_it = associated_payload_types_.find(
it->plType);
bool valid_apt = false;
@@ -3880,11 +3876,10 @@
return false;
}
if (engine()->vie()->rtp()->SetRtxReceivePayloadType(
- channel_id, it->plType) != 0) {
+ channel_id, it->plType, apt_it->second) != 0) {
LOG_RTCERR2(SetRtxReceivePayloadType, channel_id, it->plType);
return false;
}
- rtx_registered = true;
continue;
}
if (engine()->vie()->codec()->SetReceiveCodec(channel_id, *it) != 0) {
@@ -4020,11 +4015,14 @@
// NOTE: SetRtxSendPayloadType must be called after all SSRCs are
// configured. Otherwise ssrc's configured after this point will use
// the primary PT for RTX.
- if (send_rtx_type_ != -1 &&
- engine()->vie()->rtp()->SetRtxSendPayloadType(channel_id,
- send_rtx_type_) != 0) {
- LOG_RTCERR2(SetRtxSendPayloadType, channel_id, send_rtx_type_);
- return false;
+ std::map<int, int>::const_iterator it;
+ for (it = send_rtx_apt_types_.begin(); it != send_rtx_apt_types_.end();
+ ++it) {
+ if (engine()->vie()->rtp()->SetRtxSendPayloadType(channel_id, it->first,
+ it->second) != 0) {
+ LOG_RTCERR3(SetRtxSendPayloadType, channel_id, it->first, it->second);
+ return false;
+ }
}
send_channel->set_send_params(send_params);
diff --git a/talk/media/webrtc/webrtcvideoengine.h b/talk/media/webrtc/webrtcvideoengine.h
index 78a10e0..85d4611 100644
--- a/talk/media/webrtc/webrtcvideoengine.h
+++ b/talk/media/webrtc/webrtcvideoengine.h
@@ -511,7 +511,8 @@
// Global send side state.
SendChannelMap send_channels_;
rtc::scoped_ptr<webrtc::VideoCodec> send_codec_;
- int send_rtx_type_;
+ // A map from RTX payload types to their associated payload types.
+ std::map<int, int> send_rtx_apt_types_;
int send_red_type_;
int send_fec_type_;
bool sending_;
diff --git a/talk/media/webrtc/webrtcvideoengine2.cc b/talk/media/webrtc/webrtcvideoengine2.cc
index d066eb9..0239c89 100644
--- a/talk/media/webrtc/webrtcvideoengine2.cc
+++ b/talk/media/webrtc/webrtcvideoengine2.cc
@@ -121,6 +121,15 @@
}
output->red_payload_type = other.red_payload_type;
}
+ if (other.rtx_payload_type != -1) {
+ if (output->rtx_payload_type != -1 &&
+ output->rtx_payload_type != other.rtx_payload_type) {
+ LOG(LS_WARNING) << "Conflict merging rtx_payload_type configs: "
+ << output->rtx_payload_type << " and "
+ << other.rtx_payload_type;
+ }
+ output->rtx_payload_type = other.rtx_payload_type;
+ }
}
} // namespace
@@ -2070,6 +2079,7 @@
return codec == other.codec &&
fec.ulpfec_payload_type == other.fec.ulpfec_payload_type &&
fec.red_payload_type == other.fec.red_payload_type &&
+ fec.rtx_payload_type == other.fec.rtx_payload_type &&
rtx_payload_type == other.rtx_payload_type;
}
@@ -2142,17 +2152,24 @@
LOG(LS_ERROR) << "RTX mapped to payload not in codec list.";
return std::vector<VideoCodecSettings>();
}
- if (payload_codec_type[it->first] != VideoCodec::CODEC_VIDEO) {
- LOG(LS_ERROR) << "RTX not mapped to regular video codec.";
+ if (payload_codec_type[it->first] != VideoCodec::CODEC_VIDEO &&
+ payload_codec_type[it->first] != VideoCodec::CODEC_RED) {
+ LOG(LS_ERROR) << "RTX not mapped to regular video codec or RED codec.";
return std::vector<VideoCodecSettings>();
}
+
+ if (it->first == fec_settings.red_payload_type) {
+ fec_settings.rtx_payload_type = it->second;
+ }
}
// TODO(pbos): Write tests that figure out that I have not verified that RTX
// codecs aren't mapped to bogus payloads.
for (size_t i = 0; i < video_codecs.size(); ++i) {
video_codecs[i].fec = fec_settings;
- if (rtx_mapping[video_codecs[i].codec.id] != 0) {
+ if (rtx_mapping[video_codecs[i].codec.id] != 0 &&
+ rtx_mapping[video_codecs[i].codec.id] !=
+ fec_settings.red_payload_type) {
video_codecs[i].rtx_payload_type = rtx_mapping[video_codecs[i].codec.id];
}
}
diff --git a/talk/media/webrtc/webrtcvideoengine2.h b/talk/media/webrtc/webrtcvideoengine2.h
index 2318971..52428d3 100644
--- a/talk/media/webrtc/webrtcvideoengine2.h
+++ b/talk/media/webrtc/webrtcvideoengine2.h
@@ -285,7 +285,6 @@
struct VideoCodecSettings {
VideoCodecSettings();
-
bool operator ==(const VideoCodecSettings& other) const;
VideoCodec codec;
diff --git a/talk/media/webrtc/webrtcvideoengine2_unittest.cc b/talk/media/webrtc/webrtcvideoengine2_unittest.cc
index 93660a5..7ceabca 100644
--- a/talk/media/webrtc/webrtcvideoengine2_unittest.cc
+++ b/talk/media/webrtc/webrtcvideoengine2_unittest.cc
@@ -34,6 +34,7 @@
#include "talk/media/webrtc/fakewebrtcvideoengine.h"
#include "talk/media/webrtc/simulcast.h"
#include "talk/media/webrtc/webrtcvideochannelfactory.h"
+#include "talk/media/webrtc/webrtcvideoengine.h"
#include "talk/media/webrtc/webrtcvideoengine2.h"
#include "talk/media/webrtc/webrtcvideoengine2_unittest.h"
#include "talk/media/webrtc/webrtcvoiceengine.h"
@@ -73,6 +74,19 @@
cricket::kRtcpFbParamCcm, cricket::kRtcpFbCcmParamFir)));
}
+void VerifySendStreamHasRtxTypes(const webrtc::VideoSendStream::Config& config,
+ const std::map<int, int>& rtx_types) {
+ std::map<int, int>::const_iterator it;
+ it = rtx_types.find(config.encoder_settings.payload_type);
+ EXPECT_TRUE(it != rtx_types.end() &&
+ it->second == config.rtp.rtx.payload_type);
+
+ if (config.rtp.fec.rtx_payload_type != -1) {
+ it = rtx_types.find(config.rtp.fec.red_payload_type);
+ EXPECT_TRUE(it != rtx_types.end() &&
+ it->second == config.rtp.fec.rtx_payload_type);
+ }
+}
} // namespace
namespace cricket {
@@ -349,7 +363,11 @@
} else if (engine_codecs[i].name == "ulpfec") {
default_ulpfec_codec_ = engine_codecs[i];
} else if (engine_codecs[i].name == "rtx") {
- default_rtx_codec_ = engine_codecs[i];
+ int associated_payload_type;
+ if (engine_codecs[i].GetParam(kCodecParamAssociatedPayloadType,
+ &associated_payload_type)) {
+ default_apt_rtx_types_[associated_payload_type] = engine_codecs[i].id;
+ }
} else if (!codec_set) {
default_codec_ = engine_codecs[i];
codec_set = true;
@@ -388,7 +406,7 @@
VideoCodec default_codec_;
VideoCodec default_red_codec_;
VideoCodec default_ulpfec_codec_;
- VideoCodec default_rtx_codec_;
+ std::map<int, int> default_apt_rtx_types_;
};
TEST_F(WebRtcVideoEngine2Test, ConfiguresAvSyncForFirstReceiveChannel) {
@@ -431,7 +449,7 @@
TEST_F(WebRtcVideoEngine2Test, FindCodec) {
const std::vector<cricket::VideoCodec>& c = engine_.codecs();
- EXPECT_EQ(4U, c.size());
+ EXPECT_EQ(cricket::DefaultVideoCodecList().size(), c.size());
cricket::VideoCodec vp8(104, "VP8", 320, 200, 30, 0);
EXPECT_TRUE(engine_.FindCodec(vp8));
@@ -1583,8 +1601,7 @@
EXPECT_EQ(1u, config.rtp.rtx.ssrcs.size());
EXPECT_EQ(kRtxSsrcs1[0], config.rtp.rtx.ssrcs[0]);
- EXPECT_EQ(static_cast<int>(default_rtx_codec_.id),
- config.rtp.rtx.payload_type);
+ VerifySendStreamHasRtxTypes(config, default_apt_rtx_types_);
// TODO(juberti): Check RTCP, PLI, TMMBR.
}
diff --git a/talk/media/webrtc/webrtcvideoengine_unittest.cc b/talk/media/webrtc/webrtcvideoengine_unittest.cc
index 24e9af2..93560a9 100644
--- a/talk/media/webrtc/webrtcvideoengine_unittest.cc
+++ b/talk/media/webrtc/webrtcvideoengine_unittest.cc
@@ -38,6 +38,8 @@
#include "talk/media/webrtc/webrtcvideoframe.h"
#include "talk/media/webrtc/webrtcvoiceengine.h"
#include "talk/session/media/mediasession.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
#include "webrtc/base/fakecpumonitor.h"
#include "webrtc/base/gunit.h"
#include "webrtc/base/logging.h"
@@ -754,7 +756,8 @@
EXPECT_FALSE(vie_.ReceiveCodecRegistered(channel_num, wcodec));
// The RTX payload type should have been set.
- EXPECT_EQ(rtx_codec.id, vie_.GetRtxRecvPayloadType(channel_num));
+ EXPECT_THAT(vie_.GetRtxRecvPayloadType(channel_num),
+ ::testing::ElementsAre(rtx_codec.id));
}
// Test that RTX packets are routed to the default video channel if
@@ -2079,7 +2082,8 @@
codecs.push_back(rtx_codec);
EXPECT_TRUE(channel_->SetSendCodecs(codecs));
- EXPECT_EQ(96, vie_.GetRtxSendPayloadType(channel_num));
+ EXPECT_THAT(vie_.GetRtxSendPayloadType(channel_num),
+ ::testing::ElementsAre(96));
cricket::StreamParams params =
cricket::StreamParams::CreateLegacy(kSsrcs1[0]);
@@ -2117,7 +2121,8 @@
// The first matched codec should be set, i.e., H.264.
- EXPECT_EQ(96, vie_.GetRtxSendPayloadType(channel_num));
+ EXPECT_THAT(vie_.GetRtxSendPayloadType(channel_num),
+ ::testing::ElementsAre(96, 97));
cricket::StreamParams params =
cricket::StreamParams::CreateLegacy(kSsrcs1[0]);
@@ -2154,7 +2159,8 @@
codecs.push_back(rtx_codec);
EXPECT_TRUE(channel_->SetRecvCodecs(codecs));
- EXPECT_EQ(96, vie_.GetRtxRecvPayloadType(channel_num));
+ EXPECT_THAT(vie_.GetRtxRecvPayloadType(channel_num),
+ ::testing::ElementsAre(96));
cricket::StreamParams params =
cricket::StreamParams::CreateLegacy(kSsrcs1[0]);
@@ -2189,17 +2195,21 @@
cricket::VideoCodec rtx_codec2(96, "rtx", 0, 0, 0, 0);
rtx_codec2.SetParam("apt", kVP8Codec.id);
codecs.push_back(kVP8Codec);
- codecs.push_back(rtx_codec);
- // Should fail since WebRTC only supports one RTX codec at a time.
- EXPECT_FALSE(channel_->SetRecvCodecs(codecs));
+ codecs.push_back(rtx_codec2);
+ // Now WebRTC supports setting multiple RTX codecs at a time.
+ EXPECT_TRUE(channel_->SetRecvCodecs(codecs));
+ EXPECT_THAT(vie_.GetRtxRecvPayloadType(channel_num),
+ ::testing::ElementsAre(96, 97));
codecs.pop_back();
-
// One RTX codec should be fine.
EXPECT_TRUE(channel_->SetRecvCodecs(codecs));
- // The RTX payload type should have been set.
- EXPECT_EQ(rtx_codec.id, vie_.GetRtxRecvPayloadType(channel_num));
+ // TODO(changbin): The Rtx key can still be found from the Rtx-Apt map
+ // if the new codec list doesn't assign it with a new value.
+ // Should pass a map to SetRtxRecvPayloadType in future.
+ EXPECT_THAT(vie_.GetRtxRecvPayloadType(channel_num),
+ ::testing::ElementsAre(96, 97));
}
#endif
@@ -2249,7 +2259,7 @@
TEST_F(WebRtcVideoEngineTest, FindCodec) {
// We should not need to init engine in order to get codecs.
const std::vector<cricket::VideoCodec>& c = engine_.codecs();
- EXPECT_EQ(4U, c.size());
+ EXPECT_EQ(cricket::DefaultVideoCodecList().size(), c.size());
cricket::VideoCodec vp8(104, "VP8", 320, 200, 30, 0);
EXPECT_TRUE(engine_.FindCodec(vp8));
@@ -2296,7 +2306,7 @@
std::vector<cricket::VideoCodec>::const_iterator it;
bool apt_checked = false;
for (it = engine_.codecs().begin(); it != engine_.codecs().end(); ++it) {
- if (_stricmp(cricket::kRtxCodecName, it->name.c_str()) && it->id != 96) {
+ if (_stricmp(cricket::kRtxCodecName, it->name.c_str()) || it->id != 96) {
continue;
}
int apt;
@@ -3202,7 +3212,8 @@
EXPECT_TRUE(channel_->SetSendCodecs(codec_list));
// RTX payload type should now be set.
- EXPECT_EQ(96, vie_.GetRtxSendPayloadType(channel_num));
+ EXPECT_THAT(vie_.GetRtxSendPayloadType(channel_num),
+ ::testing::ElementsAre(96));
// Verify all SSRCs are set after SetSendCodecs.
EXPECT_EQ(3, vie_.GetNumSsrcs(channel_num));
diff --git a/webrtc/config.cc b/webrtc/config.cc
index 357f636..a8cb523 100644
--- a/webrtc/config.cc
+++ b/webrtc/config.cc
@@ -17,6 +17,7 @@
std::stringstream ss;
ss << "{ulpfec_payload_type: " << ulpfec_payload_type;
ss << ", red_payload_type: " << red_payload_type;
+ ss << ", rtx_payload_type: " << rtx_payload_type;
ss << '}';
return ss.str();
}
diff --git a/webrtc/config.h b/webrtc/config.h
index cd5a23f..f5a5144 100644
--- a/webrtc/config.h
+++ b/webrtc/config.h
@@ -54,13 +54,17 @@
// Settings for forward error correction, see RFC 5109 for details. Set the
// payload types to '-1' to disable.
struct FecConfig {
- FecConfig() : ulpfec_payload_type(-1), red_payload_type(-1) {}
+ FecConfig()
+ : ulpfec_payload_type(-1), red_payload_type(-1), rtx_payload_type(-1) {}
std::string ToString() const;
// Payload type used for ULPFEC packets.
int ulpfec_payload_type;
// Payload type used for RED packets.
int red_payload_type;
+
+ // Rtx payload type for RED payload.
+ int rtx_payload_type;
};
// RTP header extension to use for the video stream, see RFC 5285.
diff --git a/webrtc/modules/rtp_rtcp/interface/rtp_payload_registry.h b/webrtc/modules/rtp_rtcp/interface/rtp_payload_registry.h
index f58eaea..e73bac3 100644
--- a/webrtc/modules/rtp_rtcp/interface/rtp_payload_registry.h
+++ b/webrtc/modules/rtp_rtcp/interface/rtp_payload_registry.h
@@ -79,7 +79,7 @@
bool GetRtxSsrc(uint32_t* ssrc) const;
- void SetRtxPayloadType(int payload_type);
+ void SetRtxPayloadType(int payload_type, int associated_payload_type);
bool IsRtx(const RTPHeader& header) const;
@@ -158,7 +158,8 @@
int8_t last_received_payload_type_;
int8_t last_received_media_payload_type_;
bool rtx_;
- int8_t payload_type_rtx_;
+ // Mapping rtx_apt_types_[rtx] = apt.
+ std::map<int, int> rtx_apt_types_;
uint32_t ssrc_rtx_;
};
diff --git a/webrtc/modules/rtp_rtcp/interface/rtp_rtcp.h b/webrtc/modules/rtp_rtcp/interface/rtp_rtcp.h
index 6b9a554..f1466ae 100644
--- a/webrtc/modules/rtp_rtcp/interface/rtp_rtcp.h
+++ b/webrtc/modules/rtp_rtcp/interface/rtp_rtcp.h
@@ -228,7 +228,8 @@
// 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;
+ virtual void SetRtxSendPayloadType(int payload_type,
+ int associated_payload_type) = 0;
/*
* Get status of sending RTX (RFC 4588) on a specific SSRC.
diff --git a/webrtc/modules/rtp_rtcp/mocks/mock_rtp_rtcp.h b/webrtc/modules/rtp_rtcp/mocks/mock_rtp_rtcp.h
index 31fade4..7c81715 100644
--- a/webrtc/modules/rtp_rtcp/mocks/mock_rtp_rtcp.h
+++ b/webrtc/modules/rtp_rtcp/mocks/mock_rtp_rtcp.h
@@ -101,8 +101,7 @@
void(int* modes, uint32_t* ssrc, int* payload_type));
MOCK_METHOD1(SetRtxSsrc,
void(uint32_t));
- MOCK_METHOD1(SetRtxSendPayloadType,
- void(int));
+ MOCK_METHOD2(SetRtxSendPayloadType, void(int, 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 bfe0af0..ad553ac 100644
--- a/webrtc/modules/rtp_rtcp/source/nack_rtx_unittest.cc
+++ b/webrtc/modules/rtp_rtcp/source/nack_rtx_unittest.cc
@@ -32,6 +32,8 @@
const uint32_t kTestNumberOfPackets = 1350;
const int kTestNumberOfRtxPackets = 149;
const int kNumFrames = 30;
+const int kPayloadType = 123;
+const int kRtxPayloadType = 98;
class VerifyingRtxReceiver : public NullRtpData
{
@@ -206,15 +208,17 @@
VideoCodec video_codec;
memset(&video_codec, 0, sizeof(video_codec));
- video_codec.plType = 123;
+ video_codec.plType = kPayloadType;
memcpy(video_codec.plName, "I420", 5);
EXPECT_EQ(0, rtp_rtcp_module_->RegisterSendPayload(video_codec));
+ rtp_rtcp_module_->SetRtxSendPayloadType(kRtxPayloadType, kPayloadType);
EXPECT_EQ(0, rtp_receiver_->RegisterReceivePayload(video_codec.plName,
video_codec.plType,
90000,
0,
video_codec.maxBitrate));
+ rtp_payload_registry_.SetRtxPayloadType(kRtxPayloadType, kPayloadType);
for (size_t n = 0; n < payload_data_length; n++) {
payload_data[n] = n % 10;
@@ -265,12 +269,9 @@
uint32_t timestamp = 3000;
uint16_t nack_list[kVideoNackListSize];
for (int frame = 0; frame < kNumFrames; ++frame) {
- EXPECT_EQ(0, rtp_rtcp_module_->SendOutgoingData(webrtc::kVideoFrameDelta,
- 123,
- timestamp,
- timestamp / 90,
- payload_data,
- payload_data_length));
+ EXPECT_EQ(0, rtp_rtcp_module_->SendOutgoingData(
+ webrtc::kVideoFrameDelta, kPayloadType, timestamp,
+ timestamp / 90, payload_data, payload_data_length));
int length = BuildNackList(nack_list);
if (length > 0)
rtp_rtcp_module_->SendNACK(nack_list, length);
@@ -313,12 +314,9 @@
// Send 30 frames which at the default size is roughly what we need to get
// enough packets.
for (int frame = 0; frame < kNumFrames; ++frame) {
- EXPECT_EQ(0, rtp_rtcp_module_->SendOutgoingData(webrtc::kVideoFrameDelta,
- 123,
- timestamp,
- timestamp / 90,
- payload_data,
- payload_data_length));
+ EXPECT_EQ(0, rtp_rtcp_module_->SendOutgoingData(
+ webrtc::kVideoFrameDelta, kPayloadType, timestamp,
+ timestamp / 90, payload_data, payload_data_length));
// Prepare next frame.
timestamp += 3000;
fake_clock.AdvanceTimeMilliseconds(33);
diff --git a/webrtc/modules/rtp_rtcp/source/rtp_payload_registry.cc b/webrtc/modules/rtp_rtcp/source/rtp_payload_registry.cc
index 727a4d3..18aeb11 100644
--- a/webrtc/modules/rtp_rtcp/source/rtp_payload_registry.cc
+++ b/webrtc/modules/rtp_rtcp/source/rtp_payload_registry.cc
@@ -24,7 +24,6 @@
last_received_payload_type_(-1),
last_received_media_payload_type_(-1),
rtx_(false),
- payload_type_rtx_(-1),
ssrc_rtx_(0) {}
RTPPayloadRegistry::~RTPPayloadRegistry() {
@@ -264,19 +263,25 @@
RtpUtility::AssignUWord32ToBuffer(*restored_packet + 8, original_ssrc);
CriticalSectionScoped cs(crit_sect_.get());
+ if (!rtx_)
+ return true;
- if (payload_type_rtx_ != -1) {
- if (header.payloadType == payload_type_rtx_ &&
- incoming_payload_type_ != -1) {
- (*restored_packet)[1] = static_cast<uint8_t>(incoming_payload_type_);
- if (header.markerBit) {
- (*restored_packet)[1] |= kRtpMarkerBitMask; // Marker bit is set.
- }
- } else {
- LOG(LS_WARNING) << "Incorrect RTX configuration, dropping packet.";
- return false;
- }
+ if (rtx_apt_types_.empty()) {
+ LOG(LS_WARNING) << "No RTX is set, dropping packet.";
+ return false;
}
+ std::map<int, int>::const_iterator it =
+ rtx_apt_types_.find(header.payloadType);
+ if (it != rtx_apt_types_.end()) {
+ (*restored_packet)[1] = static_cast<uint8_t>(it->second);
+ if (header.markerBit) {
+ (*restored_packet)[1] |= kRtpMarkerBitMask; // Marker bit is set.
+ }
+ } else {
+ LOG(LS_WARNING) << "Incorrect RTX configuration, dropping packet.";
+ return false;
+ }
+
return true;
}
@@ -292,10 +297,12 @@
return rtx_;
}
-void RTPPayloadRegistry::SetRtxPayloadType(int payload_type) {
+void RTPPayloadRegistry::SetRtxPayloadType(int payload_type,
+ int associated_payload_type) {
CriticalSectionScoped cs(crit_sect_.get());
assert(payload_type >= 0);
- payload_type_rtx_ = payload_type;
+ assert(associated_payload_type >= 0);
+ rtx_apt_types_[payload_type] = associated_payload_type;
rtx_ = true;
}
diff --git a/webrtc/modules/rtp_rtcp/source/rtp_rtcp_impl.cc b/webrtc/modules/rtp_rtcp/source/rtp_rtcp_impl.cc
index 4dd74ce..15286cb 100644
--- a/webrtc/modules/rtp_rtcp/source/rtp_rtcp_impl.cc
+++ b/webrtc/modules/rtp_rtcp/source/rtp_rtcp_impl.cc
@@ -257,8 +257,9 @@
rtp_sender_.SetRtxSsrc(ssrc);
}
-void ModuleRtpRtcpImpl::SetRtxSendPayloadType(int payload_type) {
- rtp_sender_.SetRtxPayloadType(payload_type);
+void ModuleRtpRtcpImpl::SetRtxSendPayloadType(int payload_type,
+ int associated_payload_type) {
+ rtp_sender_.SetRtxPayloadType(payload_type, associated_payload_type);
}
int32_t ModuleRtpRtcpImpl::IncomingRtcpPacket(
diff --git a/webrtc/modules/rtp_rtcp/source/rtp_rtcp_impl.h b/webrtc/modules/rtp_rtcp/source/rtp_rtcp_impl.h
index ec06783..6e0e907 100644
--- a/webrtc/modules/rtp_rtcp/source/rtp_rtcp_impl.h
+++ b/webrtc/modules/rtp_rtcp/source/rtp_rtcp_impl.h
@@ -94,7 +94,8 @@
virtual void SetRtxSsrc(uint32_t ssrc) OVERRIDE;
- virtual void SetRtxSendPayloadType(int payload_type) OVERRIDE;
+ virtual void SetRtxSendPayloadType(int payload_type,
+ int associated_payload_type) OVERRIDE;
// Sends kRtcpByeCode when going from true to false.
virtual int32_t SetSendingStatus(bool sending) OVERRIDE;
diff --git a/webrtc/modules/rtp_rtcp/source/rtp_rtcp_impl_unittest.cc b/webrtc/modules/rtp_rtcp/source/rtp_rtcp_impl_unittest.cc
index 3f9e95f..726d6f1 100644
--- a/webrtc/modules/rtp_rtcp/source/rtp_rtcp_impl_unittest.cc
+++ b/webrtc/modules/rtp_rtcp/source/rtp_rtcp_impl_unittest.cc
@@ -691,7 +691,7 @@
// as otherwise the timestmap used for BWE will be broken.
senders_[i]->RegisterSendRtpHeaderExtension(kRtpExtensionAbsoluteSendTime,
1);
- senders_[i]->SetRtxSendPayloadType(96);
+ senders_[i]->SetRtxSendPayloadType(96, 100);
senders_[i]->SetRtxSsrc(kSenderRtxSsrc + i);
senders_[i]->SetRTXSendStatus(kRtxRetransmitted);
}
@@ -716,7 +716,7 @@
TEST_F(RtpSendingTest, DISABLED_RoundRobinPaddingRtxRedundantPayloads) {
for (int i = 1; i < codec_.numberOfSimulcastStreams + 1; ++i) {
- senders_[i]->SetRtxSendPayloadType(96);
+ senders_[i]->SetRtxSendPayloadType(96, 100);
senders_[i]->SetRtxSsrc(kSenderRtxSsrc + i);
senders_[i]->SetRTXSendStatus(kRtxRetransmitted | kRtxRedundantPayloads);
senders_[i]->SetStorePacketsStatus(true, 100);
diff --git a/webrtc/modules/rtp_rtcp/source/rtp_sender.cc b/webrtc/modules/rtp_rtcp/source/rtp_sender.cc
index a1810f2..42df579 100644
--- a/webrtc/modules/rtp_rtcp/source/rtp_sender.cc
+++ b/webrtc/modules/rtp_rtcp/source/rtp_sender.cc
@@ -147,7 +147,6 @@
last_packet_marker_bit_(false),
csrcs_(),
rtx_(kRtxOff),
- payload_type_rtx_(-1),
target_bitrate_critsect_(CriticalSectionWrapper::CreateCriticalSection()),
target_bitrate_(0) {
memset(nack_byte_count_times_, 0, sizeof(nack_byte_count_times_));
@@ -403,12 +402,17 @@
CriticalSectionScoped cs(send_critsect_);
*mode = rtx_;
*ssrc = ssrc_rtx_;
- *payload_type = payload_type_rtx_;
+
+ std::map<int, int>::const_iterator it = apt_rtx_types_.find(payload_type_);
+ *payload_type = (it == apt_rtx_types_.end()) ? -1 : it->second;
}
-void RTPSender::SetRtxPayloadType(int payload_type) {
+void RTPSender::SetRtxPayloadType(int payload_type,
+ int associated_payload_type) {
CriticalSectionScoped cs(send_critsect_);
- payload_type_rtx_ = payload_type;
+ assert(payload_type >= 0);
+ assert(associated_payload_type >= 0);
+ apt_rtx_types_[associated_payload_type] = payload_type;
}
int32_t RTPSender::CheckPayloadType(int8_t payload_type,
@@ -610,8 +614,14 @@
ssrc = ssrc_rtx_;
sequence_number = sequence_number_rtx_;
++sequence_number_rtx_;
- payload_type = ((rtx_ & kRtxRedundantPayloads) > 0) ? payload_type_rtx_
- : payload_type_;
+
+ if (apt_rtx_types_.empty())
+ return 0;
+ std::map<int, int>::const_iterator it =
+ apt_rtx_types_.find(payload_type_);
+ payload_type = it != apt_rtx_types_.end()
+ ? it->second
+ : apt_rtx_types_.begin()->second;
over_rtx = true;
}
}
@@ -1660,9 +1670,10 @@
// Add original RTP header.
memcpy(data_buffer_rtx, buffer, rtp_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_);
+ std::map<int, int>::const_iterator it =
+ apt_rtx_types_.find(rtp_header.payloadType);
+ if (it != apt_rtx_types_.end()) {
+ data_buffer_rtx[1] = static_cast<uint8_t>(it->second);
if (rtp_header.markerBit)
data_buffer_rtx[1] |= kRtpMarkerBitMask;
}
diff --git a/webrtc/modules/rtp_rtcp/source/rtp_sender.h b/webrtc/modules/rtp_rtcp/source/rtp_sender.h
index 2703fea..c807a5b 100644
--- a/webrtc/modules/rtp_rtcp/source/rtp_sender.h
+++ b/webrtc/modules/rtp_rtcp/source/rtp_sender.h
@@ -191,7 +191,7 @@
uint32_t RtxSsrc() const;
void SetRtxSsrc(uint32_t ssrc);
- void SetRtxPayloadType(int payloadType);
+ void SetRtxPayloadType(int payloadType, int associated_payload_type);
// Functions wrapping RTPSenderInterface.
virtual int32_t BuildRTPheader(
@@ -391,7 +391,8 @@
std::vector<uint32_t> csrcs_ GUARDED_BY(send_critsect_);
int rtx_ GUARDED_BY(send_critsect_);
uint32_t ssrc_rtx_ GUARDED_BY(send_critsect_);
- int payload_type_rtx_ GUARDED_BY(send_critsect_);
+ // Mapping apt_rtx_types_[apt] = rtx.
+ std::map<int, int> apt_rtx_types_ GUARDED_BY(send_critsect_);
// Note: Don't access this variable directly, always go through
// SetTargetBitrateKbps or GetTargetBitrateKbps. Also remember
diff --git a/webrtc/modules/rtp_rtcp/source/rtp_sender_unittest.cc b/webrtc/modules/rtp_rtcp/source/rtp_sender_unittest.cc
index 3946c44..0a95807 100644
--- a/webrtc/modules/rtp_rtcp/source/rtp_sender_unittest.cc
+++ b/webrtc/modules/rtp_rtcp/source/rtp_sender_unittest.cc
@@ -30,6 +30,7 @@
const int kTransmissionTimeOffsetExtensionId = 1;
const int kAbsoluteSendTimeExtensionId = 14;
const int kPayload = 100;
+const int kRtxPayload = 98;
const uint32_t kTimestamp = 10;
const uint16_t kSeqNum = 33;
const int kTimeOffset = 22222;
@@ -654,6 +655,7 @@
rtp_sender_.reset(new RTPSender(0, false, &fake_clock_, &transport, NULL,
&mock_paced_sender_, NULL, NULL, NULL));
rtp_sender_->SetSequenceNumber(kSeqNum);
+ rtp_sender_->SetRtxPayloadType(kRtxPayload, kPayload);
// Make all packets go through the pacer.
EXPECT_CALL(mock_paced_sender_,
SendPacket(PacedSender::kNormalPriority, _, _, _, _, _)).
@@ -1123,7 +1125,7 @@
const uint8_t kPayloadType = 127;
rtp_sender_->SetSSRC(1234);
rtp_sender_->SetRtxSsrc(4321);
- rtp_sender_->SetRtxPayloadType(kPayloadType - 1);
+ rtp_sender_->SetRtxPayloadType(kPayloadType - 1, kPayloadType);
rtp_sender_->SetRTXStatus(kRtxRetransmitted | kRtxRedundantPayloads);
ASSERT_EQ(
diff --git a/webrtc/modules/rtp_rtcp/test/testAPI/test_api.cc b/webrtc/modules/rtp_rtcp/test/testAPI/test_api.cc
index ccc8cf2..f8b6011 100644
--- a/webrtc/modules/rtp_rtcp/test/testAPI/test_api.cc
+++ b/webrtc/modules/rtp_rtcp/test/testAPI/test_api.cc
@@ -106,33 +106,31 @@
unsigned int ssrc = 0;
int rtx_mode = kRtxOff;
const int kRtxPayloadType = 119;
- int payload_type = -1;
+ const int kPayloadType = 100;
module->SetRTXSendStatus(kRtxRetransmitted);
- module->SetRtxSendPayloadType(kRtxPayloadType);
+ module->SetRtxSendPayloadType(kRtxPayloadType, kPayloadType);
module->SetRtxSsrc(1);
+ int payload_type;
module->RTXSendStatus(&rtx_mode, &ssrc, &payload_type);
EXPECT_EQ(kRtxRetransmitted, rtx_mode);
EXPECT_EQ(1u, ssrc);
- EXPECT_EQ(kRtxPayloadType, payload_type);
rtx_mode = kRtxOff;
module->SetRTXSendStatus(kRtxOff);
- payload_type = -1;
- module->SetRtxSendPayloadType(kRtxPayloadType);
+ module->SetRtxSendPayloadType(kRtxPayloadType, kPayloadType);
module->RTXSendStatus(&rtx_mode, &ssrc, &payload_type);
EXPECT_EQ(kRtxOff, rtx_mode);
- 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);
}
TEST_F(RtpRtcpAPITest, RtxReceiver) {
const uint32_t kRtxSsrc = 1;
const int kRtxPayloadType = 119;
+ const int kPayloadType = 100;
EXPECT_FALSE(rtp_payload_registry_->RtxEnabled());
rtp_payload_registry_->SetRtxSsrc(kRtxSsrc);
- rtp_payload_registry_->SetRtxPayloadType(kRtxPayloadType);
+ rtp_payload_registry_->SetRtxPayloadType(kRtxPayloadType, kPayloadType);
EXPECT_TRUE(rtp_payload_registry_->RtxEnabled());
RTPHeader rtx_header;
rtx_header.ssrc = kRtxSsrc;
diff --git a/webrtc/test/call_test.cc b/webrtc/test/call_test.cc
index 126c716..dbd514e 100644
--- a/webrtc/test/call_test.cc
+++ b/webrtc/test/call_test.cc
@@ -151,6 +151,7 @@
const uint8_t CallTest::kFakeSendPayloadType = 125;
const uint8_t CallTest::kSendRtxPayloadType = 98;
const uint8_t CallTest::kRedPayloadType = 118;
+const uint8_t CallTest::kRtxRedPayloadType = 99;
const uint8_t CallTest::kUlpfecPayloadType = 119;
const uint32_t CallTest::kSendRtxSsrcs[kNumSsrcs] = {0xBADCAFD, 0xBADCAFE,
0xBADCAFF};
diff --git a/webrtc/test/call_test.h b/webrtc/test/call_test.h
index b9a091b..1e01733 100644
--- a/webrtc/test/call_test.h
+++ b/webrtc/test/call_test.h
@@ -37,6 +37,7 @@
static const uint8_t kSendRtxPayloadType;
static const uint8_t kFakeSendPayloadType;
static const uint8_t kRedPayloadType;
+ static const uint8_t kRtxRedPayloadType;
static const uint8_t kUlpfecPayloadType;
static const uint32_t kSendRtxSsrcs[kNumSsrcs];
static const uint32_t kSendSsrcs[kNumSsrcs];
diff --git a/webrtc/video/end_to_end_tests.cc b/webrtc/video/end_to_end_tests.cc
index f820554..65d9568 100644
--- a/webrtc/video/end_to_end_tests.cc
+++ b/webrtc/video/end_to_end_tests.cc
@@ -69,7 +69,7 @@
}
};
- void DecodesRetransmittedFrame(bool retransmit_over_rtx);
+ void DecodesRetransmittedFrame(bool use_rtx, bool use_red);
void ReceivesPliAndRecovers(int rtp_history_ms);
void RespectsRtcpMode(newapi::RtcpMode rtcp_mode);
void TestXrReceiverReferenceTimeReport(bool enable_rrtr);
@@ -538,16 +538,16 @@
// This test drops second RTP packet with a marker bit set, makes sure it's
// retransmitted and renders. Retransmission SSRCs are also checked.
-void EndToEndTest::DecodesRetransmittedFrame(bool retransmit_over_rtx) {
+void EndToEndTest::DecodesRetransmittedFrame(bool use_rtx, bool use_red) {
static const int kDroppedFrameNumber = 2;
class RetransmissionObserver : public test::EndToEndTest,
public I420FrameCallback {
public:
- explicit RetransmissionObserver(bool expect_rtx)
+ explicit RetransmissionObserver(bool use_rtx, bool use_red)
: EndToEndTest(kDefaultTimeoutMs),
- retransmission_ssrc_(expect_rtx ? kSendRtxSsrcs[0] : kSendSsrcs[0]),
- retransmission_payload_type_(expect_rtx ? kSendRtxPayloadType
- : kFakeSendPayloadType),
+ payload_type_(GetPayloadType(false, use_red)),
+ retransmission_ssrc_(use_rtx ? kSendRtxSsrcs[0] : kSendSsrcs[0]),
+ retransmission_payload_type_(GetPayloadType(use_rtx, use_red)),
marker_bits_observed_(0),
retransmitted_timestamp_(0),
frame_retransmitted_(false) {}
@@ -565,7 +565,7 @@
}
EXPECT_EQ(kSendSsrcs[0], header.ssrc);
- EXPECT_EQ(kFakeSendPayloadType, header.payloadType);
+ EXPECT_EQ(payload_type_, header.payloadType);
// Found the second frame's final packet, drop this and expect a
// retransmission.
@@ -592,13 +592,25 @@
send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
(*receive_configs)[0].pre_render_callback = this;
(*receive_configs)[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
+
+ if (payload_type_ == kRedPayloadType) {
+ send_config->rtp.fec.ulpfec_payload_type = kUlpfecPayloadType;
+ send_config->rtp.fec.red_payload_type = kRedPayloadType;
+ (*receive_configs)[0].rtp.fec.red_payload_type = kRedPayloadType;
+ (*receive_configs)[0].rtp.fec.ulpfec_payload_type = kUlpfecPayloadType;
+ }
+
if (retransmission_ssrc_ == kSendRtxSsrcs[0]) {
send_config->rtp.rtx.ssrcs.push_back(kSendRtxSsrcs[0]);
send_config->rtp.rtx.payload_type = kSendRtxPayloadType;
- (*receive_configs)[0].rtp.rtx[kSendRtxPayloadType].ssrc =
+ (*receive_configs)[0].rtp.rtx[kFakeSendPayloadType].ssrc =
kSendRtxSsrcs[0];
- (*receive_configs)[0].rtp.rtx[kSendRtxPayloadType].payload_type =
+ (*receive_configs)[0].rtp.rtx[kFakeSendPayloadType].payload_type =
kSendRtxPayloadType;
+ if (payload_type_ == kRedPayloadType) {
+ send_config->rtp.fec.rtx_payload_type = kRtxRedPayloadType;
+ (*receive_configs)[0].rtp.fec.rtx_payload_type = kRtxRedPayloadType;
+ }
}
}
@@ -607,22 +619,36 @@
<< "Timed out while waiting for retransmission to render.";
}
+ int GetPayloadType(bool use_rtx, bool use_red) {
+ return use_red ? (use_rtx ? kRtxRedPayloadType : kRedPayloadType)
+ : (use_rtx ? kSendRtxPayloadType : kFakeSendPayloadType);
+ }
+
+ const int payload_type_;
const uint32_t retransmission_ssrc_;
const int retransmission_payload_type_;
int marker_bits_observed_;
uint32_t retransmitted_timestamp_;
bool frame_retransmitted_;
- } test(retransmit_over_rtx);
+ } test(use_rtx, use_red);
RunBaseTest(&test);
}
TEST_F(EndToEndTest, DecodesRetransmittedFrame) {
- DecodesRetransmittedFrame(false);
+ DecodesRetransmittedFrame(false, false);
}
TEST_F(EndToEndTest, DecodesRetransmittedFrameOverRtx) {
- DecodesRetransmittedFrame(true);
+ DecodesRetransmittedFrame(true, false);
+}
+
+TEST_F(EndToEndTest, DecodesRetransmittedFrameByRed) {
+ DecodesRetransmittedFrame(false, true);
+}
+
+TEST_F(EndToEndTest, DecodesRetransmittedFrameByRedOverRtx) {
+ DecodesRetransmittedFrame(true, true);
}
TEST_F(EndToEndTest, UsesFrameCallbacks) {
@@ -2268,5 +2294,4 @@
call->DestroyVideoReceiveStream(receive_stream);
}
}
-
} // namespace webrtc
diff --git a/webrtc/video/loopback.cc b/webrtc/video/loopback.cc
index a1ebed1..52cfaa3 100644
--- a/webrtc/video/loopback.cc
+++ b/webrtc/video/loopback.cc
@@ -103,7 +103,8 @@
static const uint32_t kSendRtxSsrc = 0x654322;
static const uint32_t kReceiverLocalSsrc = 0x123456;
-static const uint8_t kRtxPayloadType = 96;
+static const uint8_t kRtxVideoPayloadType = 96;
+static const uint8_t kVideoPayloadType = 124;
void Loopback() {
scoped_ptr<test::TraceToStderr> trace_to_stderr_;
@@ -137,7 +138,7 @@
VideoSendStream::Config send_config;
send_config.rtp.ssrcs.push_back(kSendSsrc);
send_config.rtp.rtx.ssrcs.push_back(kSendRtxSsrc);
- send_config.rtp.rtx.payload_type = kRtxPayloadType;
+ send_config.rtp.rtx.payload_type = kRtxVideoPayloadType;
send_config.rtp.nack.rtp_history_ms = 1000;
send_config.rtp.extensions.push_back(
RtpExtension(RtpExtension::kAbsSendTime, kAbsSendTimeExtensionId));
@@ -155,7 +156,7 @@
}
send_config.encoder_settings.encoder = encoder.get();
send_config.encoder_settings.payload_name = flags::Codec();
- send_config.encoder_settings.payload_type = 124;
+ send_config.encoder_settings.payload_type = kVideoPayloadType;
VideoEncoderConfig encoder_config;
encoder_config.streams = test::CreateVideoStreams(1);
VideoStream* stream = &encoder_config.streams[0];
@@ -183,8 +184,8 @@
receive_config.rtp.remote_ssrc = send_config.rtp.ssrcs[0];
receive_config.rtp.local_ssrc = kReceiverLocalSsrc;
receive_config.rtp.nack.rtp_history_ms = 1000;
- receive_config.rtp.rtx[kRtxPayloadType].ssrc = kSendRtxSsrc;
- receive_config.rtp.rtx[kRtxPayloadType].payload_type = kRtxPayloadType;
+ receive_config.rtp.rtx[kVideoPayloadType].ssrc = kSendRtxSsrc;
+ receive_config.rtp.rtx[kVideoPayloadType].payload_type = kRtxVideoPayloadType;
receive_config.rtp.extensions.push_back(
RtpExtension(RtpExtension::kAbsSendTime, kAbsSendTimeExtensionId));
receive_config.renderer = loopback_video.get();
diff --git a/webrtc/video/rampup_tests.cc b/webrtc/video/rampup_tests.cc
index 4b26d05..b3f0522 100644
--- a/webrtc/video/rampup_tests.cc
+++ b/webrtc/video/rampup_tests.cc
@@ -76,6 +76,10 @@
remote_bitrate_estimator_.reset(
rbe_factory->Create(this, clock, control_type,
kRemoteBitrateEstimatorMinBitrateBps));
+ payload_registry_->SetRtxPayloadType(RampUpTest::kSendRtxPayloadType,
+ RampUpTest::kFakeSendPayloadType);
+ payload_registry_->SetRtxPayloadType(RampUpTest::kRtxRedPayloadType,
+ RampUpTest::kRedPayloadType);
}
void StreamObserver::set_expected_bitrate_bps(
@@ -118,7 +122,6 @@
RTPHeader header;
EXPECT_TRUE(rtp_parser_->Parse(packet, length, &header));
receive_stats_->IncomingPacket(header, length, false);
- payload_registry_->SetIncomingPayloadType(header);
remote_bitrate_estimator_->IncomingPacket(
clock_->TimeInMilliseconds(), length - 12, header);
if (remote_bitrate_estimator_->TimeUntilNextProcess() <= 0) {
@@ -136,11 +139,9 @@
uint8_t restored_packet[kMaxPacketSize];
uint8_t* restored_packet_ptr = restored_packet;
size_t restored_length = length;
- payload_registry_->RestoreOriginalPacket(&restored_packet_ptr,
- packet,
- &restored_length,
- rtx_media_ssrcs_[header.ssrc],
- header);
+ EXPECT_TRUE(payload_registry_->RestoreOriginalPacket(
+ &restored_packet_ptr, packet, &restored_length,
+ rtx_media_ssrcs_[header.ssrc], header));
length = restored_length;
EXPECT_TRUE(rtp_parser_->Parse(
restored_packet, static_cast<int>(length), &header));
@@ -366,10 +367,11 @@
return test_done_->Wait(test::CallTest::kLongTimeoutMs);
}
-void RampUpTest::RunRampUpTest(bool rtx,
- size_t num_streams,
+void RampUpTest::RunRampUpTest(size_t num_streams,
unsigned int start_bitrate_bps,
- const std::string& extension_type) {
+ const std::string& extension_type,
+ bool rtx,
+ bool red) {
std::vector<uint32_t> ssrcs(GenerateSsrcs(num_streams, 100));
std::vector<uint32_t> rtx_ssrcs(GenerateSsrcs(num_streams, 200));
StreamObserver::SsrcMap rtx_ssrc_map;
@@ -422,6 +424,11 @@
send_config_.rtp.rtx.payload_type = kSendRtxPayloadType;
send_config_.rtp.rtx.ssrcs = rtx_ssrcs;
}
+ if (red) {
+ send_config_.rtp.fec.ulpfec_payload_type = kUlpfecPayloadType;
+ send_config_.rtp.fec.red_payload_type = kRedPayloadType;
+ send_config_.rtp.fec.rtx_payload_type = kRtxRedPayloadType;
+ }
if (num_streams == 1) {
// For single stream rampup until 1mbps
@@ -448,7 +455,9 @@
DestroyStreams();
}
-void RampUpTest::RunRampUpDownUpTest(size_t number_of_streams, bool rtx) {
+void RampUpTest::RunRampUpDownUpTest(size_t number_of_streams,
+ bool rtx,
+ bool red) {
test::DirectTransport receiver_transport;
LowRateStreamObserver stream_observer(
&receiver_transport, Clock::GetRealTimeClock(), number_of_streams, rtx);
@@ -467,6 +476,11 @@
send_config_.rtp.rtx.payload_type = kSendRtxPayloadType;
send_config_.rtp.rtx.ssrcs = GenerateSsrcs(number_of_streams, 200);
}
+ if (red) {
+ send_config_.rtp.fec.ulpfec_payload_type = kUlpfecPayloadType;
+ send_config_.rtp.fec.red_payload_type = kRedPayloadType;
+ send_config_.rtp.fec.rtx_payload_type = kRtxRedPayloadType;
+ }
CreateStreams();
stream_observer.SetSendStream(send_stream_);
@@ -482,43 +496,68 @@
}
TEST_F(RampUpTest, SingleStream) {
- RunRampUpTest(false, 1, 0, RtpExtension::kTOffset);
+ RunRampUpTest(1, 0, RtpExtension::kTOffset, false, false);
}
TEST_F(RampUpTest, Simulcast) {
- RunRampUpTest(false, 3, 0, RtpExtension::kTOffset);
+ RunRampUpTest(3, 0, RtpExtension::kTOffset, false, false);
}
TEST_F(RampUpTest, SimulcastWithRtx) {
- RunRampUpTest(true, 3, 0, RtpExtension::kTOffset);
+ RunRampUpTest(3, 0, RtpExtension::kTOffset, true, false);
+}
+
+TEST_F(RampUpTest, SimulcastByRedWithRtx) {
+ RunRampUpTest(3, 0, RtpExtension::kTOffset, true, true);
}
TEST_F(RampUpTest, SingleStreamWithHighStartBitrate) {
- RunRampUpTest(false, 1, 0.9 * kSingleStreamTargetBps, RtpExtension::kTOffset);
+ RunRampUpTest(1, 0.9 * kSingleStreamTargetBps, RtpExtension::kTOffset, false,
+ false);
}
-TEST_F(RampUpTest, UpDownUpOneStream) { RunRampUpDownUpTest(1, false); }
+TEST_F(RampUpTest, UpDownUpOneStream) {
+ RunRampUpDownUpTest(1, false, false);
+}
-TEST_F(RampUpTest, UpDownUpThreeStreams) { RunRampUpDownUpTest(3, false); }
+TEST_F(RampUpTest, UpDownUpThreeStreams) {
+ RunRampUpDownUpTest(3, false, false);
+}
-TEST_F(RampUpTest, UpDownUpOneStreamRtx) { RunRampUpDownUpTest(1, true); }
+TEST_F(RampUpTest, UpDownUpOneStreamRtx) {
+ RunRampUpDownUpTest(1, true, false);
+}
-TEST_F(RampUpTest, UpDownUpThreeStreamsRtx) { RunRampUpDownUpTest(3, true); }
+TEST_F(RampUpTest, UpDownUpThreeStreamsRtx) {
+ RunRampUpDownUpTest(3, true, false);
+}
+
+TEST_F(RampUpTest, UpDownUpOneStreamByRedRtx) {
+ RunRampUpDownUpTest(1, true, true);
+}
+
+TEST_F(RampUpTest, UpDownUpThreeStreamsByRedRtx) {
+ RunRampUpDownUpTest(3, true, true);
+}
TEST_F(RampUpTest, AbsSendTimeSingleStream) {
- RunRampUpTest(false, 1, 0, RtpExtension::kAbsSendTime);
+ RunRampUpTest(1, 0, RtpExtension::kAbsSendTime, false, false);
}
TEST_F(RampUpTest, AbsSendTimeSimulcast) {
- RunRampUpTest(false, 3, 0, RtpExtension::kAbsSendTime);
+ RunRampUpTest(3, 0, RtpExtension::kAbsSendTime, false, false);
}
TEST_F(RampUpTest, AbsSendTimeSimulcastWithRtx) {
- RunRampUpTest(true, 3, 0, RtpExtension::kAbsSendTime);
+ RunRampUpTest(3, 0, RtpExtension::kAbsSendTime, true, false);
+}
+
+TEST_F(RampUpTest, AbsSendTimeSimulcastByRedWithRtx) {
+ RunRampUpTest(3, 0, RtpExtension::kAbsSendTime, true, true);
}
TEST_F(RampUpTest, AbsSendTimeSingleStreamWithHighStartBitrate) {
- RunRampUpTest(false, 1, 0.9 * kSingleStreamTargetBps,
- RtpExtension::kAbsSendTime);
+ RunRampUpTest(1, 0.9 * kSingleStreamTargetBps, RtpExtension::kAbsSendTime,
+ false, false);
}
} // namespace webrtc
diff --git a/webrtc/video/rampup_tests.h b/webrtc/video/rampup_tests.h
index e506cd4..b09de9b 100644
--- a/webrtc/video/rampup_tests.h
+++ b/webrtc/video/rampup_tests.h
@@ -148,12 +148,13 @@
class RampUpTest : public test::CallTest {
protected:
- void RunRampUpTest(bool rtx,
- size_t num_streams,
+ void RunRampUpTest(size_t num_streams,
unsigned int start_bitrate_bps,
- const std::string& extension_type);
+ const std::string& extension_type,
+ bool rtx,
+ bool red);
- void RunRampUpDownUpTest(size_t number_of_streams, bool rtx);
+ void RunRampUpDownUpTest(size_t number_of_streams, bool rtx, bool red);
};
} // namespace webrtc
#endif // WEBRTC_VIDEO_RAMPUP_TESTS_H_
diff --git a/webrtc/video/video_receive_stream.cc b/webrtc/video/video_receive_stream.cc
index 73f6e7c..9c4a687 100644
--- a/webrtc/video/video_receive_stream.cc
+++ b/webrtc/video/video_receive_stream.cc
@@ -92,12 +92,13 @@
rtp_rtcp_->SetLocalSSRC(channel_, config_.rtp.local_ssrc);
// TODO(pbos): Support multiple RTX, per video payload.
Config::Rtp::RtxMap::const_iterator it = config_.rtp.rtx.begin();
- if (it != config_.rtp.rtx.end()) {
+ for (; it != config_.rtp.rtx.end(); ++it) {
assert(it->second.ssrc != 0);
assert(it->second.payload_type != 0);
rtp_rtcp_->SetRemoteSSRCType(channel_, kViEStreamTypeRtx, it->second.ssrc);
- rtp_rtcp_->SetRtxReceivePayloadType(channel_, it->second.payload_type);
+ rtp_rtcp_->SetRtxReceivePayloadType(channel_, it->second.payload_type,
+ it->first);
}
rtp_rtcp_->SetRembStatus(channel_, false, config_.rtp.remb);
@@ -146,6 +147,11 @@
LOG(LS_ERROR) << "Could not set RED codec. This shouldn't happen.";
abort();
}
+ if (config_.rtp.fec.rtx_payload_type != -1) {
+ rtp_rtcp_->SetRtxReceivePayloadType(channel_,
+ config_.rtp.fec.rtx_payload_type,
+ config_.rtp.fec.red_payload_type);
+ }
}
stats_proxy_.reset(
diff --git a/webrtc/video/video_send_stream.cc b/webrtc/video/video_send_stream.cc
index b8ef4d3..f531f11 100644
--- a/webrtc/video/video_send_stream.cc
+++ b/webrtc/video/video_send_stream.cc
@@ -49,7 +49,6 @@
ss << "}, {";
}
ss << '}';
-
ss << ", payload_type: " << payload_type;
ss << '}';
return ss.str();
@@ -173,6 +172,11 @@
static_cast<unsigned char>(config_.rtp.fec.red_payload_type),
static_cast<unsigned char>(config_.rtp.fec.ulpfec_payload_type));
}
+ if (config_.rtp.fec.rtx_payload_type != -1) {
+ rtp_rtcp_->SetRtxSendPayloadType(channel_,
+ config_.rtp.fec.rtx_payload_type,
+ config_.rtp.fec.red_payload_type);
+ }
} else {
rtp_rtcp_->SetNACKStatus(channel_, config_.rtp.nack.rtp_history_ms > 0);
}
@@ -475,7 +479,8 @@
}
assert(config_.rtp.rtx.payload_type >= 0);
- rtp_rtcp_->SetRtxSendPayloadType(channel_, config_.rtp.rtx.payload_type);
+ rtp_rtcp_->SetRtxSendPayloadType(channel_, config_.rtp.rtx.payload_type,
+ config_.encoder_settings.payload_type);
}
std::map<uint32_t, RtpState> VideoSendStream::GetRtpStates() const {
diff --git a/webrtc/video_engine/include/vie_rtp_rtcp.h b/webrtc/video_engine/include/vie_rtp_rtcp.h
index 103a196..2c53475 100644
--- a/webrtc/video_engine/include/vie_rtp_rtcp.h
+++ b/webrtc/video_engine/include/vie_rtp_rtcp.h
@@ -114,10 +114,13 @@
// 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;
+ const uint8_t payload_type,
+ const uint8_t associated_payload_type) = 0;
- virtual int SetRtxReceivePayloadType(const int video_channel,
- const uint8_t payload_type) = 0;
+ virtual int SetRtxReceivePayloadType(
+ const int video_channel,
+ const uint8_t payload_type,
+ const uint8_t associated_payload_type) = 0;
// This function enables manual initialization of the sequence number. The
// start sequence number is normally a random number.
diff --git a/webrtc/video_engine/test/auto_test/source/vie_autotest_loopback.cc b/webrtc/video_engine/test/auto_test/source/vie_autotest_loopback.cc
index 4711122..ce4b71f 100644
--- a/webrtc/video_engine/test/auto_test/source/vie_autotest_loopback.cc
+++ b/webrtc/video_engine/test/auto_test/source/vie_autotest_loopback.cc
@@ -40,6 +40,7 @@
const uint32_t kSsrc = 0x01234567;
const uint32_t kRtxSsrc = 0x01234568;
const int kRtxPayloadType = 98;
+const int kPayloadType = 100;
#define VCM_RED_PAYLOAD_TYPE 96
#define VCM_ULPFEC_PAYLOAD_TYPE 97
@@ -244,14 +245,15 @@
return -1;
}
- error = ptrViERtpRtcp->SetRtxSendPayloadType(videoChannel, kRtxPayloadType);
+ error = ptrViERtpRtcp->SetRtxSendPayloadType(videoChannel, kRtxPayloadType,
+ kPayloadType);
if (error == -1) {
printf("ERROR in ViERTP_RTCP::SetRtxSendPayloadType\n");
return -1;
}
- error = ptrViERtpRtcp->SetRtxReceivePayloadType(videoChannel,
- kRtxPayloadType);
+ error = ptrViERtpRtcp->SetRtxReceivePayloadType(
+ videoChannel, kRtxPayloadType, kPayloadType);
if (error == -1) {
printf("ERROR in ViERTP_RTCP::SetRtxReceivePayloadType\n");
return -1;
diff --git a/webrtc/video_engine/test/auto_test/source/vie_autotest_rtp_rtcp.cc b/webrtc/video_engine/test/auto_test/source/vie_autotest_rtp_rtcp.cc
index 923fe41..ae63558 100644
--- a/webrtc/video_engine/test/auto_test/source/vie_autotest_rtp_rtcp.cc
+++ b/webrtc/video_engine/test/auto_test/source/vie_autotest_rtp_rtcp.cc
@@ -172,14 +172,15 @@
myTransport.ClearStats();
const uint8_t kRtxPayloadType = 96;
+ const uint8_t kPayloadType = 100;
// Temporarily disable pacing.
EXPECT_EQ(0, ViE.rtp_rtcp->SetTransmissionSmoothingStatus(
tbChannel.videoChannel, false));
EXPECT_EQ(0, ViE.rtp_rtcp->SetNACKStatus(tbChannel.videoChannel, true));
- EXPECT_EQ(0, ViE.rtp_rtcp->SetRtxSendPayloadType(tbChannel.videoChannel,
- kRtxPayloadType));
- EXPECT_EQ(0, ViE.rtp_rtcp->SetRtxReceivePayloadType(tbChannel.videoChannel,
- kRtxPayloadType));
+ EXPECT_EQ(0, ViE.rtp_rtcp->SetRtxSendPayloadType(
+ tbChannel.videoChannel, kRtxPayloadType, kPayloadType));
+ EXPECT_EQ(0, ViE.rtp_rtcp->SetRtxReceivePayloadType(
+ tbChannel.videoChannel, kRtxPayloadType, kPayloadType));
EXPECT_EQ(0, ViE.rtp_rtcp->SetLocalSSRC(tbChannel.videoChannel, 1234,
webrtc::kViEStreamTypeRtx, 0));
EXPECT_EQ(0, ViE.rtp_rtcp->SetRemoteSSRCType(tbChannel.videoChannel,
diff --git a/webrtc/video_engine/vie_channel.cc b/webrtc/video_engine/vie_channel.cc
index 79ebe70..eb28bd0 100644
--- a/webrtc/video_engine/vie_channel.cc
+++ b/webrtc/video_engine/vie_channel.cc
@@ -899,11 +899,12 @@
return 0;
}
-int ViEChannel::SetRtxSendPayloadType(int payload_type) {
- rtp_rtcp_->SetRtxSendPayloadType(payload_type);
+int ViEChannel::SetRtxSendPayloadType(int payload_type,
+ int associated_payload_type) {
+ rtp_rtcp_->SetRtxSendPayloadType(payload_type, associated_payload_type);
for (std::list<RtpRtcp*>::iterator it = simulcast_rtp_rtcp_.begin();
it != simulcast_rtp_rtcp_.end(); it++) {
- (*it)->SetRtxSendPayloadType(payload_type);
+ (*it)->SetRtxSendPayloadType(payload_type, associated_payload_type);
}
SetRtxSendStatus(true);
return 0;
@@ -920,8 +921,9 @@
}
}
-void ViEChannel::SetRtxReceivePayloadType(int payload_type) {
- vie_receiver_.SetRtxPayloadType(payload_type);
+void ViEChannel::SetRtxReceivePayloadType(int payload_type,
+ int associated_payload_type) {
+ vie_receiver_.SetRtxPayloadType(payload_type, associated_payload_type);
}
int32_t ViEChannel::SetStartSequenceNumber(uint16_t sequence_number) {
diff --git a/webrtc/video_engine/vie_channel.h b/webrtc/video_engine/vie_channel.h
index 7a46d1f..0096c70 100644
--- a/webrtc/video_engine/vie_channel.h
+++ b/webrtc/video_engine/vie_channel.h
@@ -145,8 +145,8 @@
// Gets the CSRC for the incoming stream.
int32_t GetRemoteCSRC(uint32_t CSRCs[kRtpCsrcSize]);
- int SetRtxSendPayloadType(int payload_type);
- void SetRtxReceivePayloadType(int payload_type);
+ int SetRtxSendPayloadType(int payload_type, int associated_payload_type);
+ void SetRtxReceivePayloadType(int payload_type, int associated_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_receiver.cc b/webrtc/video_engine/vie_receiver.cc
index 6dec985..048eecd 100644
--- a/webrtc/video_engine/vie_receiver.cc
+++ b/webrtc/video_engine/vie_receiver.cc
@@ -102,8 +102,10 @@
rtp_receiver_->SetNACKStatus(enable ? kNackRtcp : kNackOff);
}
-void ViEReceiver::SetRtxPayloadType(int payload_type) {
- rtp_payload_registry_->SetRtxPayloadType(payload_type);
+void ViEReceiver::SetRtxPayloadType(int payload_type,
+ int associated_payload_type) {
+ rtp_payload_registry_->SetRtxPayloadType(payload_type,
+ associated_payload_type);
}
void ViEReceiver::SetRtxSsrc(uint32_t ssrc) {
diff --git a/webrtc/video_engine/vie_receiver.h b/webrtc/video_engine/vie_receiver.h
index 39a85e4..aaeba17 100644
--- a/webrtc/video_engine/vie_receiver.h
+++ b/webrtc/video_engine/vie_receiver.h
@@ -47,7 +47,7 @@
bool RegisterPayload(const VideoCodec& video_codec);
void SetNackStatus(bool enable, int max_nack_reordering_threshold);
- void SetRtxPayloadType(int payload_type);
+ void SetRtxPayloadType(int payload_type, int associated_payload_type);
void SetRtxSsrc(uint32_t ssrc);
bool GetRtxSsrc(uint32_t* ssrc) const;
diff --git a/webrtc/video_engine/vie_rtp_rtcp_impl.cc b/webrtc/video_engine/vie_rtp_rtcp_impl.cc
index ae21307..354e1d6 100644
--- a/webrtc/video_engine/vie_rtp_rtcp_impl.cc
+++ b/webrtc/video_engine/vie_rtp_rtcp_impl.cc
@@ -191,8 +191,10 @@
return 0;
}
-int ViERTP_RTCPImpl::SetRtxSendPayloadType(const int video_channel,
- const uint8_t payload_type) {
+int ViERTP_RTCPImpl::SetRtxSendPayloadType(
+ const int video_channel,
+ const uint8_t payload_type,
+ const uint8_t associated_payload_type) {
LOG_F(LS_INFO) << "channel: " << video_channel
<< " payload_type: " << static_cast<int>(payload_type);
ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
@@ -201,14 +203,17 @@
shared_data_->SetLastError(kViERtpRtcpInvalidChannelId);
return -1;
}
- if (vie_channel->SetRtxSendPayloadType(payload_type) != 0) {
+ if (vie_channel->SetRtxSendPayloadType(payload_type,
+ associated_payload_type) != 0) {
return -1;
}
return 0;
}
-int ViERTP_RTCPImpl::SetRtxReceivePayloadType(const int video_channel,
- const uint8_t payload_type) {
+int ViERTP_RTCPImpl::SetRtxReceivePayloadType(
+ const int video_channel,
+ const uint8_t payload_type,
+ const uint8_t associated_payload_type) {
LOG_F(LS_INFO) << "channel: " << video_channel
<< " payload_type: " << static_cast<int>(payload_type);
ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
@@ -217,7 +222,7 @@
shared_data_->SetLastError(kViERtpRtcpInvalidChannelId);
return -1;
}
- vie_channel->SetRtxReceivePayloadType(payload_type);
+ vie_channel->SetRtxReceivePayloadType(payload_type, associated_payload_type);
return 0;
}
diff --git a/webrtc/video_engine/vie_rtp_rtcp_impl.h b/webrtc/video_engine/vie_rtp_rtcp_impl.h
index 8e9f097..7374d1a 100644
--- a/webrtc/video_engine/vie_rtp_rtcp_impl.h
+++ b/webrtc/video_engine/vie_rtp_rtcp_impl.h
@@ -40,9 +40,11 @@
virtual int GetRemoteCSRCs(const int video_channel,
unsigned int CSRCs[kRtpCsrcSize]) const;
virtual int SetRtxSendPayloadType(const int video_channel,
- const uint8_t payload_type);
+ const uint8_t payload_type,
+ const uint8_t associated_payload_type);
virtual int SetRtxReceivePayloadType(const int video_channel,
- const uint8_t payload_type);
+ const uint8_t payload_type,
+ const uint8_t associated_payload_type);
virtual int SetStartSequenceNumber(const int video_channel,
uint16_t sequence_number);
virtual void SetRtpStateForSsrc(int video_channel,