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 <stddef.h>
14
15 #include <cstdint>
16 #include <string>
17 #include <vector>
18
19 #include "api/array_view.h"
20 #include "api/call/transport.h"
21 #include "api/rtp_parameters.h"
22 #include "call/rtp_stream_receiver_controller_interface.h"
23 #include "modules/rtp_rtcp/include/flexfec_receiver.h"
24 #include "modules/rtp_rtcp/include/receive_statistics.h"
25 #include "modules/rtp_rtcp/source/rtp_packet_received.h"
26 #include "modules/utility/include/process_thread.h"
27 #include "rtc_base/checks.h"
28 #include "rtc_base/location.h"
29 #include "rtc_base/logging.h"
30 #include "rtc_base/strings/string_builder.h"
31 #include "system_wrappers/include/clock.h"
32
33 namespace webrtc {
34
ToString(int64_t time_ms) const35 std::string FlexfecReceiveStream::Stats::ToString(int64_t time_ms) const {
36 char buf[1024];
37 rtc::SimpleStringBuilder ss(buf);
38 ss << "FlexfecReceiveStream stats: " << time_ms
39 << ", {flexfec_bitrate_bps: " << flexfec_bitrate_bps << "}";
40 return ss.str();
41 }
42
ToString() const43 std::string FlexfecReceiveStream::Config::ToString() const {
44 char buf[1024];
45 rtc::SimpleStringBuilder ss(buf);
46 ss << "{payload_type: " << payload_type;
47 ss << ", remote_ssrc: " << remote_ssrc;
48 ss << ", local_ssrc: " << local_ssrc;
49 ss << ", protected_media_ssrcs: [";
50 size_t i = 0;
51 for (; i + 1 < protected_media_ssrcs.size(); ++i)
52 ss << protected_media_ssrcs[i] << ", ";
53 if (!protected_media_ssrcs.empty())
54 ss << protected_media_ssrcs[i];
55 ss << "], transport_cc: " << (transport_cc ? "on" : "off");
56 ss << ", rtp_header_extensions: [";
57 i = 0;
58 for (; i + 1 < rtp_header_extensions.size(); ++i)
59 ss << rtp_header_extensions[i].ToString() << ", ";
60 if (!rtp_header_extensions.empty())
61 ss << rtp_header_extensions[i].ToString();
62 ss << "]}";
63 return ss.str();
64 }
65
IsCompleteAndEnabled() const66 bool FlexfecReceiveStream::Config::IsCompleteAndEnabled() const {
67 // Check if FlexFEC is enabled.
68 if (payload_type < 0)
69 return false;
70 // Do we have the necessary SSRC information?
71 if (remote_ssrc == 0)
72 return false;
73 // TODO(brandtr): Update this check when we support multistream protection.
74 if (protected_media_ssrcs.size() != 1u)
75 return false;
76 return true;
77 }
78
79 namespace {
80
81 // TODO(brandtr): Update this function when we support multistream protection.
MaybeCreateFlexfecReceiver(Clock * clock,const FlexfecReceiveStream::Config & config,RecoveredPacketReceiver * recovered_packet_receiver)82 std::unique_ptr<FlexfecReceiver> MaybeCreateFlexfecReceiver(
83 Clock* clock,
84 const FlexfecReceiveStream::Config& config,
85 RecoveredPacketReceiver* recovered_packet_receiver) {
86 if (config.payload_type < 0) {
87 RTC_LOG(LS_WARNING)
88 << "Invalid FlexFEC payload type given. "
89 "This FlexfecReceiveStream will therefore be useless.";
90 return nullptr;
91 }
92 RTC_DCHECK_GE(config.payload_type, 0);
93 RTC_DCHECK_LE(config.payload_type, 127);
94 if (config.remote_ssrc == 0) {
95 RTC_LOG(LS_WARNING)
96 << "Invalid FlexFEC SSRC given. "
97 "This FlexfecReceiveStream will therefore be useless.";
98 return nullptr;
99 }
100 if (config.protected_media_ssrcs.empty()) {
101 RTC_LOG(LS_WARNING)
102 << "No protected media SSRC supplied. "
103 "This FlexfecReceiveStream will therefore be useless.";
104 return nullptr;
105 }
106
107 if (config.protected_media_ssrcs.size() > 1) {
108 RTC_LOG(LS_WARNING)
109 << "The supplied FlexfecConfig contained multiple protected "
110 "media streams, but our implementation currently only "
111 "supports protecting a single media stream. "
112 "To avoid confusion, disabling FlexFEC completely.";
113 return nullptr;
114 }
115 RTC_DCHECK_EQ(1U, config.protected_media_ssrcs.size());
116 return std::unique_ptr<FlexfecReceiver>(new FlexfecReceiver(
117 clock, config.remote_ssrc, config.protected_media_ssrcs[0],
118 recovered_packet_receiver));
119 }
120
CreateRtpRtcpModule(Clock * clock,ReceiveStatistics * receive_statistics,const FlexfecReceiveStreamImpl::Config & config,RtcpRttStats * rtt_stats)121 std::unique_ptr<ModuleRtpRtcpImpl2> CreateRtpRtcpModule(
122 Clock* clock,
123 ReceiveStatistics* receive_statistics,
124 const FlexfecReceiveStreamImpl::Config& config,
125 RtcpRttStats* rtt_stats) {
126 RtpRtcpInterface::Configuration configuration;
127 configuration.audio = false;
128 configuration.receiver_only = true;
129 configuration.clock = clock;
130 configuration.receive_statistics = receive_statistics;
131 configuration.outgoing_transport = config.rtcp_send_transport;
132 configuration.rtt_stats = rtt_stats;
133 configuration.local_media_ssrc = config.local_ssrc;
134 return ModuleRtpRtcpImpl2::Create(configuration);
135 }
136
137 } // namespace
138
FlexfecReceiveStreamImpl(Clock * clock,RtpStreamReceiverControllerInterface * receiver_controller,const Config & config,RecoveredPacketReceiver * recovered_packet_receiver,RtcpRttStats * rtt_stats,ProcessThread * process_thread)139 FlexfecReceiveStreamImpl::FlexfecReceiveStreamImpl(
140 Clock* clock,
141 RtpStreamReceiverControllerInterface* receiver_controller,
142 const Config& config,
143 RecoveredPacketReceiver* recovered_packet_receiver,
144 RtcpRttStats* rtt_stats,
145 ProcessThread* process_thread)
146 : config_(config),
147 receiver_(MaybeCreateFlexfecReceiver(clock,
148 config_,
149 recovered_packet_receiver)),
150 rtp_receive_statistics_(ReceiveStatistics::Create(clock)),
151 rtp_rtcp_(CreateRtpRtcpModule(clock,
152 rtp_receive_statistics_.get(),
153 config_,
154 rtt_stats)),
155 process_thread_(process_thread) {
156 RTC_LOG(LS_INFO) << "FlexfecReceiveStreamImpl: " << config_.ToString();
157
158 // RTCP reporting.
159 rtp_rtcp_->SetRTCPStatus(config_.rtcp_mode);
160 process_thread_->RegisterModule(rtp_rtcp_.get(), RTC_FROM_HERE);
161
162 // Register with transport.
163 // TODO(nisse): OnRtpPacket in this class delegates all real work to
164 // |receiver_|. So maybe we don't need to implement RtpPacketSinkInterface
165 // here at all, we'd then delete the OnRtpPacket method and instead register
166 // |receiver_| as the RtpPacketSinkInterface for this stream.
167 // TODO(nisse): Passing |this| from the constructor to the RtpDemuxer, before
168 // the object is fully initialized, is risky. But it works in this case
169 // because locking in our caller, Call::CreateFlexfecReceiveStream, ensures
170 // that the demuxer doesn't call OnRtpPacket before this object is fully
171 // constructed. Registering |receiver_| instead of |this| would solve this
172 // problem too.
173 rtp_stream_receiver_ =
174 receiver_controller->CreateReceiver(config_.remote_ssrc, this);
175 }
176
~FlexfecReceiveStreamImpl()177 FlexfecReceiveStreamImpl::~FlexfecReceiveStreamImpl() {
178 RTC_LOG(LS_INFO) << "~FlexfecReceiveStreamImpl: " << config_.ToString();
179 process_thread_->DeRegisterModule(rtp_rtcp_.get());
180 }
181
OnRtpPacket(const RtpPacketReceived & packet)182 void FlexfecReceiveStreamImpl::OnRtpPacket(const RtpPacketReceived& packet) {
183 if (!receiver_)
184 return;
185
186 receiver_->OnRtpPacket(packet);
187
188 // Do not report media packets in the RTCP RRs generated by |rtp_rtcp_|.
189 if (packet.Ssrc() == config_.remote_ssrc) {
190 rtp_receive_statistics_->OnRtpPacket(packet);
191 }
192 }
193
194 // TODO(brandtr): Implement this member function when we have designed the
195 // stats for FlexFEC.
GetStats() const196 FlexfecReceiveStreamImpl::Stats FlexfecReceiveStreamImpl::GetStats() const {
197 return FlexfecReceiveStream::Stats();
198 }
199
GetConfig() const200 const FlexfecReceiveStream::Config& FlexfecReceiveStreamImpl::GetConfig()
201 const {
202 return config_;
203 }
204
205 } // namespace webrtc
206