flexfec_receive_stream_impl.cc (6322B)
1 /* 2 * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. 3 * 4 * Use of this source code is governed by a BSD-style license 5 * that can be found in the LICENSE file in the root of the source 6 * tree. An additional intellectual property rights grant can be found 7 * in the file PATENTS. All contributing project authors may 8 * be found in the AUTHORS file in the root of the source tree. 9 */ 10 11 #include "call/flexfec_receive_stream_impl.h" 12 13 #include <cstddef> 14 #include <cstdint> 15 #include <memory> 16 #include <string> 17 18 #include "api/array_view.h" 19 #include "api/environment/environment.h" 20 #include "api/sequence_checker.h" 21 #include "call/flexfec_receive_stream.h" 22 #include "call/rtp_stream_receiver_controller_interface.h" 23 #include "modules/rtp_rtcp/include/flexfec_receiver.h" 24 #include "modules/rtp_rtcp/source/rtp_packet_received.h" 25 #include "rtc_base/checks.h" 26 #include "rtc_base/logging.h" 27 #include "rtc_base/strings/string_builder.h" 28 29 namespace webrtc { 30 31 std::string FlexfecReceiveStream::Config::ToString() const { 32 char buf[1024]; 33 SimpleStringBuilder ss(buf); 34 ss << "{payload_type: " << payload_type; 35 ss << ", remote_ssrc: " << rtp.remote_ssrc; 36 ss << ", local_ssrc: " << rtp.local_ssrc; 37 ss << ", protected_media_ssrcs: ["; 38 size_t i = 0; 39 for (; i + 1 < protected_media_ssrcs.size(); ++i) 40 ss << protected_media_ssrcs[i] << ", "; 41 if (!protected_media_ssrcs.empty()) 42 ss << protected_media_ssrcs[i]; 43 ss << "}"; 44 return ss.str(); 45 } 46 47 bool FlexfecReceiveStream::Config::IsCompleteAndEnabled() const { 48 // Check if FlexFEC is enabled. 49 if (payload_type < 0) 50 return false; 51 // Do we have the necessary SSRC information? 52 if (rtp.remote_ssrc == 0) 53 return false; 54 // TODO(brandtr): Update this check when we support multistream protection. 55 if (protected_media_ssrcs.size() != 1u) 56 return false; 57 return true; 58 } 59 60 namespace { 61 62 // TODO(brandtr): Update this function when we support multistream protection. 63 std::unique_ptr<FlexfecReceiver> MaybeCreateFlexfecReceiver( 64 Clock* clock, 65 const FlexfecReceiveStream::Config& config, 66 RecoveredPacketReceiver* recovered_packet_receiver) { 67 if (config.payload_type < 0) { 68 RTC_LOG(LS_WARNING) 69 << "Invalid FlexFEC payload type given. " 70 "This FlexfecReceiveStream will therefore be useless."; 71 return nullptr; 72 } 73 RTC_DCHECK_GE(config.payload_type, 0); 74 RTC_DCHECK_LE(config.payload_type, 127); 75 if (config.rtp.remote_ssrc == 0) { 76 RTC_LOG(LS_WARNING) 77 << "Invalid FlexFEC SSRC given. " 78 "This FlexfecReceiveStream will therefore be useless."; 79 return nullptr; 80 } 81 if (config.protected_media_ssrcs.empty()) { 82 RTC_LOG(LS_WARNING) 83 << "No protected media SSRC supplied. " 84 "This FlexfecReceiveStream will therefore be useless."; 85 return nullptr; 86 } 87 88 if (config.protected_media_ssrcs.size() > 1) { 89 RTC_LOG(LS_WARNING) 90 << "The supplied FlexfecConfig contained multiple protected " 91 "media streams, but our implementation currently only " 92 "supports protecting a single media stream. " 93 "To avoid confusion, disabling FlexFEC completely."; 94 return nullptr; 95 } 96 RTC_DCHECK_EQ(1U, config.protected_media_ssrcs.size()); 97 return std::unique_ptr<FlexfecReceiver>(new FlexfecReceiver( 98 clock, config.rtp.remote_ssrc, config.protected_media_ssrcs[0], 99 recovered_packet_receiver)); 100 } 101 102 } // namespace 103 104 FlexfecReceiveStreamImpl::FlexfecReceiveStreamImpl( 105 const Environment& env, 106 Config config, 107 RecoveredPacketReceiver* recovered_packet_receiver, 108 RtcpRttStats* rtt_stats) 109 : remote_ssrc_(config.rtp.remote_ssrc), 110 payload_type_(config.payload_type), 111 receiver_(MaybeCreateFlexfecReceiver(&env.clock(), 112 config, 113 recovered_packet_receiver)), 114 rtp_receive_statistics_(ReceiveStatistics::Create(&env.clock())), 115 rtp_rtcp_(env, 116 {.audio = false, 117 .receiver_only = true, 118 .receive_statistics = rtp_receive_statistics_.get(), 119 .outgoing_transport = config.rtcp_send_transport, 120 .rtt_stats = rtt_stats, 121 .local_media_ssrc = config.rtp.local_ssrc}) { 122 RTC_LOG(LS_INFO) << "FlexfecReceiveStreamImpl: " << config.ToString(); 123 RTC_DCHECK_GE(payload_type_, -1); 124 125 packet_sequence_checker_.Detach(); 126 127 // RTCP reporting. 128 rtp_rtcp_.SetRTCPStatus(config.rtcp_mode); 129 } 130 131 FlexfecReceiveStreamImpl::~FlexfecReceiveStreamImpl() { 132 RTC_DLOG(LS_INFO) << "~FlexfecReceiveStreamImpl: ssrc: " << remote_ssrc_; 133 } 134 135 void FlexfecReceiveStreamImpl::RegisterWithTransport( 136 RtpStreamReceiverControllerInterface* receiver_controller) { 137 RTC_DCHECK_RUN_ON(&packet_sequence_checker_); 138 RTC_DCHECK(!rtp_stream_receiver_); 139 140 if (!receiver_) 141 return; 142 143 // TODO(nisse): OnRtpPacket in this class delegates all real work to 144 // `receiver_`. So maybe we don't need to implement RtpPacketSinkInterface 145 // here at all, we'd then delete the OnRtpPacket method and instead register 146 // `receiver_` as the RtpPacketSinkInterface for this stream. 147 rtp_stream_receiver_ = 148 receiver_controller->CreateReceiver(remote_ssrc(), this); 149 } 150 151 void FlexfecReceiveStreamImpl::UnregisterFromTransport() { 152 RTC_DCHECK_RUN_ON(&packet_sequence_checker_); 153 rtp_stream_receiver_.reset(); 154 } 155 156 void FlexfecReceiveStreamImpl::OnRtpPacket(const RtpPacketReceived& packet) { 157 RTC_DCHECK_RUN_ON(&packet_sequence_checker_); 158 if (!receiver_) 159 return; 160 161 receiver_->OnRtpPacket(packet); 162 163 // Do not report media packets in the RTCP RRs generated by `rtp_rtcp_`. 164 if (packet.Ssrc() == remote_ssrc()) { 165 rtp_receive_statistics_->OnRtpPacket(packet); 166 } 167 } 168 169 void FlexfecReceiveStreamImpl::SetPayloadType(int payload_type) { 170 RTC_DCHECK_RUN_ON(&packet_sequence_checker_); 171 RTC_DCHECK_GE(payload_type, -1); 172 payload_type_ = payload_type; 173 } 174 175 int FlexfecReceiveStreamImpl::payload_type() const { 176 RTC_DCHECK_RUN_ON(&packet_sequence_checker_); 177 return payload_type_; 178 } 179 180 void FlexfecReceiveStreamImpl::SetLocalSsrc(uint32_t local_ssrc) { 181 RTC_DCHECK_RUN_ON(&packet_sequence_checker_); 182 if (local_ssrc == rtp_rtcp_.local_media_ssrc()) 183 return; 184 185 rtp_rtcp_.SetLocalSsrc(local_ssrc); 186 } 187 188 } // namespace webrtc