• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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