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