Index: webrtc/video/rtp_stream_receiver.cc |
diff --git a/webrtc/video/rtp_stream_receiver.cc b/webrtc/video/rtp_stream_receiver.cc |
index ac1caa6a3f4fbe3f1f38ec786fcf64b43c8f5def..4d5402f7d9df61879d4f318a575c9654200dc99d 100644 |
--- a/webrtc/video/rtp_stream_receiver.cc |
+++ b/webrtc/video/rtp_stream_receiver.cc |
@@ -29,6 +29,7 @@ |
#include "webrtc/system_wrappers/include/timestamp_extrapolator.h" |
#include "webrtc/system_wrappers/include/trace.h" |
#include "webrtc/video/receive_statistics_proxy.h" |
+#include "webrtc/video/vie_remb.h" |
namespace webrtc { |
@@ -76,12 +77,17 @@ RtpStreamReceiver::RtpStreamReceiver( |
RtcpRttStats* rtt_stats, |
PacedSender* paced_sender, |
PacketRouter* packet_router, |
+ VieRemb* remb, |
const VideoReceiveStream::Config& config, |
- ReceiveStatisticsProxy* receive_stats_proxy) |
+ ReceiveStatisticsProxy* receive_stats_proxy, |
+ ProcessThread* process_thread) |
: clock_(Clock::GetRealTimeClock()), |
+ config_(config), |
video_receiver_(video_receiver), |
remote_bitrate_estimator_(remote_bitrate_estimator), |
packet_router_(packet_router), |
+ remb_(remb), |
+ process_thread_(process_thread), |
ntp_estimator_(clock_), |
rtp_payload_registry_(RTPPayloadStrategy::CreateStrategy(false)), |
rtp_header_parser_(RtpHeaderParser::Create()), |
@@ -108,8 +114,23 @@ RtpStreamReceiver::RtpStreamReceiver( |
RTC_DCHECK(config.rtp.rtcp_mode != RtcpMode::kOff) |
<< "A stream should not be configured with RTCP disabled. This value is " |
"reserved for internal usage."; |
+ RTC_DCHECK(config_.rtp.remote_ssrc != 0); |
+ // TODO(pbos): What's an appropriate local_ssrc for receive-only streams? |
+ RTC_DCHECK(config_.rtp.local_ssrc != 0); |
+ RTC_DCHECK(config_.rtp.remote_ssrc != config_.rtp.local_ssrc); |
+ |
rtp_rtcp_->SetRTCPStatus(config.rtp.rtcp_mode); |
+ rtp_rtcp_->SetSSRC(config.rtp.local_ssrc); |
rtp_rtcp_->SetKeyFrameRequestMethod(kKeyFrameReqPliRtcp); |
+ if (config.rtp.remb) { |
+ rtp_rtcp_->SetREMBStatus(true); |
+ remb_->AddReceiveChannel(rtp_rtcp_.get()); |
+ } |
+ |
+ for (size_t i = 0; i < config.rtp.extensions.size(); ++i) { |
+ EnableReceiveRtpHeaderExtension(config.rtp.extensions[i].name, |
+ config.rtp.extensions[i].id); |
+ } |
static const int kMaxPacketAgeToNack = 450; |
NACKMethod nack_method = |
@@ -118,28 +139,65 @@ RtpStreamReceiver::RtpStreamReceiver( |
? kMaxPacketAgeToNack : kDefaultMaxReorderingThreshold; |
rtp_receiver_->SetNACKStatus(nack_method); |
rtp_receive_statistics_->SetMaxReorderingThreshold(max_reordering_threshold); |
+ |
+ // TODO(pbos): Support multiple RTX, per video payload. |
+ for (const auto& kv : config_.rtp.rtx) { |
+ RTC_DCHECK(kv.second.ssrc != 0); |
+ RTC_DCHECK(kv.second.payload_type != 0); |
+ |
+ rtp_payload_registry_.SetRtxSsrc(kv.second.ssrc); |
+ rtp_payload_registry_.SetRtxPayloadType(kv.second.payload_type, |
+ kv.first); |
+ } |
+ |
+ // If set to true, the RTX payload type mapping supplied in |
+ // |SetRtxPayloadType| will be used when restoring RTX packets. Without it, |
+ // RTX packets will always be restored to the last non-RTX packet payload type |
+ // received. |
+ // TODO(holmer): When Chrome no longer depends on this being false by default, |
+ // always use the mapping and remove this whole codepath. |
+ rtp_payload_registry_.set_use_rtx_payload_mapping_on_restore( |
+ config_.rtp.use_rtx_payload_mapping_on_restore); |
+ |
+ if (IsFecEnabled()) { |
+ VideoCodec ulpfec_codec = {}; |
+ ulpfec_codec.codecType = kVideoCodecULPFEC; |
+ strncpy(ulpfec_codec.plName, "ulpfec", sizeof(ulpfec_codec.plName)); |
+ ulpfec_codec.plType = config_.rtp.fec.ulpfec_payload_type; |
+ RTC_CHECK(SetReceiveCodec(ulpfec_codec)); |
+ |
+ VideoCodec red_codec = {}; |
+ red_codec.codecType = kVideoCodecRED; |
+ strncpy(red_codec.plName, "red", sizeof(red_codec.plName)); |
+ red_codec.plType = config_.rtp.fec.red_payload_type; |
+ RTC_CHECK(SetReceiveCodec(red_codec)); |
+ if (config_.rtp.fec.red_rtx_payload_type != -1) { |
+ rtp_payload_registry_.SetRtxPayloadType( |
+ config_.rtp.fec.red_rtx_payload_type, |
+ config_.rtp.fec.red_payload_type); |
+ } |
+ } |
+ |
+ if (config.rtp.rtcp_xr.receiver_reference_time_report) |
+ rtp_rtcp_->SetRtcpXrRrtrStatus(true); |
+ |
+ // Stats callback for CNAME changes. |
+ rtp_rtcp_->RegisterRtcpStatisticsCallback(receive_stats_proxy); |
+ |
+ process_thread_->RegisterModule(rtp_receive_statistics_.get()); |
+ process_thread_->RegisterModule(rtp_rtcp_.get()); |
} |
RtpStreamReceiver::~RtpStreamReceiver() { |
+ process_thread_->DeRegisterModule(rtp_receive_statistics_.get()); |
+ process_thread_->DeRegisterModule(rtp_rtcp_.get()); |
+ |
packet_router_->RemoveRtpModule(rtp_rtcp_.get()); |
+ rtp_rtcp_->SetREMBStatus(false); |
+ remb_->RemoveReceiveChannel(rtp_rtcp_.get()); |
UpdateHistograms(); |
} |
-void RtpStreamReceiver::UpdateHistograms() { |
- FecPacketCounter counter = fec_receiver_->GetPacketCounter(); |
- if (counter.num_packets > 0) { |
- RTC_LOGGED_HISTOGRAM_PERCENTAGE( |
- "WebRTC.Video.ReceivedFecPacketsInPercent", |
- static_cast<int>(counter.num_fec_packets * 100 / counter.num_packets)); |
- } |
- if (counter.num_fec_packets > 0) { |
- RTC_LOGGED_HISTOGRAM_PERCENTAGE( |
- "WebRTC.Video.RecoveredMediaPacketsInPercentOfFec", |
- static_cast<int>(counter.num_recovered_packets * 100 / |
- counter.num_fec_packets)); |
- } |
-} |
- |
bool RtpStreamReceiver::SetReceiveCodec(const VideoCodec& video_codec) { |
int8_t old_pltype = -1; |
if (rtp_payload_registry_.ReceivePayloadType( |
@@ -153,28 +211,6 @@ bool RtpStreamReceiver::SetReceiveCodec(const VideoCodec& video_codec) { |
0, 0) == 0; |
} |
-void RtpStreamReceiver::SetRtxPayloadType(int payload_type, |
- int associated_payload_type) { |
- rtp_payload_registry_.SetRtxPayloadType(payload_type, |
- associated_payload_type); |
-} |
- |
-void RtpStreamReceiver::SetUseRtxPayloadMappingOnRestore(bool val) { |
- rtp_payload_registry_.set_use_rtx_payload_mapping_on_restore(val); |
-} |
- |
-void RtpStreamReceiver::SetRtxSsrc(uint32_t ssrc) { |
- rtp_payload_registry_.SetRtxSsrc(ssrc); |
-} |
- |
-bool RtpStreamReceiver::GetRtxSsrc(uint32_t* ssrc) const { |
- return rtp_payload_registry_.GetRtxSsrc(ssrc); |
-} |
- |
-bool RtpStreamReceiver::IsFecEnabled() const { |
- return rtp_payload_registry_.ulpfec_payload_type() > -1; |
-} |
- |
uint32_t RtpStreamReceiver::GetRemoteSsrc() const { |
return rtp_receiver_->SSRC(); |
} |
@@ -187,13 +223,6 @@ RtpReceiver* RtpStreamReceiver::GetRtpReceiver() const { |
return rtp_receiver_.get(); |
} |
-void RtpStreamReceiver::EnableReceiveRtpHeaderExtension( |
- const std::string& extension, int id) { |
- RTC_DCHECK(RtpExtension::IsSupportedForVideo(extension)); |
- RTC_CHECK(rtp_header_parser_->RegisterRtpHeaderExtension( |
- StringToRtpExtensionType(extension), id)); |
-} |
- |
int32_t RtpStreamReceiver::OnReceivedPayloadData( |
const uint8_t* payload_data, |
const size_t payload_size, |
@@ -304,6 +333,20 @@ int32_t RtpStreamReceiver::SliceLossIndicationRequest( |
static_cast<uint8_t>(picture_id)); |
} |
+bool RtpStreamReceiver::IsFecEnabled() const { |
+ return config_.rtp.fec.red_payload_type != -1 && |
+ config_.rtp.fec.ulpfec_payload_type != -1; |
+} |
+ |
+bool RtpStreamReceiver::IsRetransmissionsEnabled() const { |
+ return config_.rtp.nack.rtp_history_ms > 0; |
+} |
+ |
+void RtpStreamReceiver::RequestPacketRetransmit( |
+ const std::vector<uint16_t>& sequence_numbers) { |
+ rtp_rtcp_->SendNack(sequence_numbers); |
+} |
+ |
int32_t RtpStreamReceiver::ResendPackets(const uint16_t* sequence_numbers, |
uint16_t length) { |
return rtp_rtcp_->SendNACK(sequence_numbers, length); |
@@ -432,6 +475,11 @@ bool RtpStreamReceiver::DeliverRtcp(const uint8_t* rtcp_packet, |
return true; |
} |
+void RtpStreamReceiver::SignalNetworkState(NetworkState state) { |
+ rtp_rtcp_->SetRTCPStatus(state == kNetworkUp ? config_.rtp.rtcp_mode |
+ : RtcpMode::kOff); |
+} |
+ |
void RtpStreamReceiver::StartReceive() { |
rtc::CritScope lock(&receive_cs_); |
receiving_ = true; |
@@ -442,10 +490,6 @@ void RtpStreamReceiver::StopReceive() { |
receiving_ = false; |
} |
-ReceiveStatistics* RtpStreamReceiver::GetReceiveStatistics() const { |
- return rtp_receive_statistics_.get(); |
-} |
- |
bool RtpStreamReceiver::IsPacketInOrder(const RTPHeader& header) const { |
StreamStatistician* statistician = |
rtp_receive_statistics_->GetStatistician(header.ssrc); |
@@ -469,4 +513,30 @@ bool RtpStreamReceiver::IsPacketRetransmitted(const RTPHeader& header, |
return !in_order && |
statistician->IsRetransmitOfOldPacket(header, min_rtt); |
} |
+ |
+void RtpStreamReceiver::UpdateHistograms() { |
+ FecPacketCounter counter = fec_receiver_->GetPacketCounter(); |
+ if (counter.num_packets > 0) { |
+ RTC_LOGGED_HISTOGRAM_PERCENTAGE( |
+ "WebRTC.Video.ReceivedFecPacketsInPercent", |
+ static_cast<int>(counter.num_fec_packets * 100 / counter.num_packets)); |
+ } |
+ if (counter.num_fec_packets > 0) { |
+ RTC_LOGGED_HISTOGRAM_PERCENTAGE( |
+ "WebRTC.Video.RecoveredMediaPacketsInPercentOfFec", |
+ static_cast<int>(counter.num_recovered_packets * 100 / |
+ counter.num_fec_packets)); |
+ } |
+} |
+ |
+void RtpStreamReceiver::EnableReceiveRtpHeaderExtension( |
+ const std::string& extension, int id) { |
+ // One-byte-extension local identifiers are in the range 1-14 inclusive. |
+ RTC_DCHECK_GE(id, 1); |
+ RTC_DCHECK_LE(id, 14); |
+ RTC_DCHECK(RtpExtension::IsSupportedForVideo(extension)); |
+ RTC_CHECK(rtp_header_parser_->RegisterRtpHeaderExtension( |
+ StringToRtpExtensionType(extension), id)); |
+} |
+ |
} // namespace webrtc |