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