blob: bb4122a83f427996eb3ec66cbc3ebe0a7b94aa4e [file] [log] [blame]
brandtr76648da2016-10-20 11:54:481/*
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
Mirko Bonadei92ea95e2017-09-15 04:47:3111#include "call/flexfec_receive_stream_impl.h"
brandtr76648da2016-10-20 11:54:4812
Yves Gerey3e707812018-11-28 15:47:4913#include <stddef.h>
Jonas Olssona4d87372019-07-05 17:08:3314
Yves Gerey3e707812018-11-28 15:47:4915#include <cstdint>
Harald Alvestrand93c9aa12024-09-02 20:55:5216#include <memory>
brandtrfa5a3682017-01-17 09:33:5417#include <string>
brandtrb29e6522016-12-21 14:37:1818
Yves Gerey3e707812018-11-28 15:47:4919#include "api/array_view.h"
Danil Chapovalov4e41db22024-08-30 13:10:2020#include "api/environment/environment.h"
Harald Alvestrand93c9aa12024-09-02 20:55:5221#include "api/sequence_checker.h"
22#include "call/flexfec_receive_stream.h"
Mirko Bonadei92ea95e2017-09-15 04:47:3123#include "call/rtp_stream_receiver_controller_interface.h"
24#include "modules/rtp_rtcp/include/flexfec_receiver.h"
Mirko Bonadei92ea95e2017-09-15 04:47:3125#include "modules/rtp_rtcp/source/rtp_packet_received.h"
Mirko Bonadei92ea95e2017-09-15 04:47:3126#include "rtc_base/checks.h"
Mirko Bonadei92ea95e2017-09-15 04:47:3127#include "rtc_base/logging.h"
Jonas Olsson0a713b62018-04-04 13:49:3228#include "rtc_base/strings/string_builder.h"
brandtr76648da2016-10-20 11:54:4829
30namespace webrtc {
31
brandtr1cfbd602016-12-08 12:17:5332std::string FlexfecReceiveStream::Config::ToString() const {
Jonas Olsson0a713b62018-04-04 13:49:3233 char buf[1024];
34 rtc::SimpleStringBuilder ss(buf);
brandtr1cfbd602016-12-08 12:17:5335 ss << "{payload_type: " << payload_type;
Tommi1c1f5402021-06-14 08:54:2036 ss << ", remote_ssrc: " << rtp.remote_ssrc;
37 ss << ", local_ssrc: " << rtp.local_ssrc;
brandtr1cfbd602016-12-08 12:17:5338 ss << ", protected_media_ssrcs: [";
39 size_t i = 0;
40 for (; i + 1 < protected_media_ssrcs.size(); ++i)
41 ss << protected_media_ssrcs[i] << ", ";
42 if (!protected_media_ssrcs.empty())
43 ss << protected_media_ssrcs[i];
Per K217b3842023-01-30 15:04:0144 ss << "}";
brandtr1cfbd602016-12-08 12:17:5345 return ss.str();
46}
47
brandtr8313a6f2017-01-13 15:41:1948bool FlexfecReceiveStream::Config::IsCompleteAndEnabled() const {
49 // Check if FlexFEC is enabled.
50 if (payload_type < 0)
51 return false;
52 // Do we have the necessary SSRC information?
Tommi1c1f5402021-06-14 08:54:2053 if (rtp.remote_ssrc == 0)
brandtr8313a6f2017-01-13 15:41:1954 return false;
55 // TODO(brandtr): Update this check when we support multistream protection.
56 if (protected_media_ssrcs.size() != 1u)
57 return false;
58 return true;
59}
60
brandtr76648da2016-10-20 11:54:4861namespace {
62
63// TODO(brandtr): Update this function when we support multistream protection.
brandtr43c31e72016-11-15 13:26:4564std::unique_ptr<FlexfecReceiver> MaybeCreateFlexfecReceiver(
Sebastian Jansson8026d602019-03-04 18:39:0165 Clock* clock,
brandtr43c31e72016-11-15 13:26:4566 const FlexfecReceiveStream::Config& config,
brandtrb29e6522016-12-21 14:37:1867 RecoveredPacketReceiver* recovered_packet_receiver) {
brandtr1cfbd602016-12-08 12:17:5368 if (config.payload_type < 0) {
Mirko Bonadei675513b2017-11-09 10:09:2569 RTC_LOG(LS_WARNING)
70 << "Invalid FlexFEC payload type given. "
Jonas Olssonb2b20312020-01-14 11:11:3171 "This FlexfecReceiveStream will therefore be useless.";
brandtr76648da2016-10-20 11:54:4872 return nullptr;
brandtr43c31e72016-11-15 13:26:4573 }
brandtr1cfbd602016-12-08 12:17:5374 RTC_DCHECK_GE(config.payload_type, 0);
75 RTC_DCHECK_LE(config.payload_type, 127);
Tommi1c1f5402021-06-14 08:54:2076 if (config.rtp.remote_ssrc == 0) {
Mirko Bonadei675513b2017-11-09 10:09:2577 RTC_LOG(LS_WARNING)
78 << "Invalid FlexFEC SSRC given. "
Jonas Olssonb2b20312020-01-14 11:11:3179 "This FlexfecReceiveStream will therefore be useless.";
brandtr43c31e72016-11-15 13:26:4580 return nullptr;
81 }
82 if (config.protected_media_ssrcs.empty()) {
Mirko Bonadei675513b2017-11-09 10:09:2583 RTC_LOG(LS_WARNING)
84 << "No protected media SSRC supplied. "
Jonas Olssonb2b20312020-01-14 11:11:3185 "This FlexfecReceiveStream will therefore be useless.";
brandtr43c31e72016-11-15 13:26:4586 return nullptr;
87 }
88
89 if (config.protected_media_ssrcs.size() > 1) {
Mirko Bonadei675513b2017-11-09 10:09:2590 RTC_LOG(LS_WARNING)
brandtr76648da2016-10-20 11:54:4891 << "The supplied FlexfecConfig contained multiple protected "
92 "media streams, but our implementation currently only "
brandtr43c31e72016-11-15 13:26:4593 "supports protecting a single media stream. "
94 "To avoid confusion, disabling FlexFEC completely.";
95 return nullptr;
brandtr76648da2016-10-20 11:54:4896 }
brandtr43c31e72016-11-15 13:26:4597 RTC_DCHECK_EQ(1U, config.protected_media_ssrcs.size());
Sebastian Jansson8026d602019-03-04 18:39:0198 return std::unique_ptr<FlexfecReceiver>(new FlexfecReceiver(
Tommi1c1f5402021-06-14 08:54:2099 clock, config.rtp.remote_ssrc, config.protected_media_ssrcs[0],
Sebastian Jansson8026d602019-03-04 18:39:01100 recovered_packet_receiver));
brandtr76648da2016-10-20 11:54:48101}
102
103} // namespace
104
brandtr7250b392016-12-19 09:13:46105FlexfecReceiveStreamImpl::FlexfecReceiveStreamImpl(
Danil Chapovalov4e41db22024-08-30 13:10:20106 const Environment& env,
Tommicf4ed152022-05-09 20:46:57107 Config config,
brandtrfa5a3682017-01-17 09:33:54108 RecoveredPacketReceiver* recovered_packet_receiver,
Markus Handelleb61b7f2021-06-22 08:46:48109 RtcpRttStats* rtt_stats)
Per K217b3842023-01-30 15:04:01110 : remote_ssrc_(config.rtp.remote_ssrc),
Tommi43b15c32022-07-28 07:24:52111 payload_type_(config.payload_type),
Danil Chapovalov4e41db22024-08-30 13:10:20112 receiver_(MaybeCreateFlexfecReceiver(&env.clock(),
113 config,
114 recovered_packet_receiver)),
115 rtp_receive_statistics_(ReceiveStatistics::Create(&env.clock())),
116 rtp_rtcp_(env,
117 {.audio = false,
118 .receiver_only = true,
119 .receive_statistics = rtp_receive_statistics_.get(),
120 .outgoing_transport = config.rtcp_send_transport,
121 .rtt_stats = rtt_stats,
122 .local_media_ssrc = config.rtp.local_ssrc}) {
Tommifc2c24e2022-05-25 18:54:24123 RTC_LOG(LS_INFO) << "FlexfecReceiveStreamImpl: " << config.ToString();
Tommi43b15c32022-07-28 07:24:52124 RTC_DCHECK_GE(payload_type_, -1);
brandtrfa5a3682017-01-17 09:33:54125
Tommi90738dd2021-05-31 15:36:47126 packet_sequence_checker_.Detach();
Tommi0377bab2021-05-31 12:26:05127
brandtrfa5a3682017-01-17 09:33:54128 // RTCP reporting.
Danil Chapovalov4e41db22024-08-30 13:10:20129 rtp_rtcp_.SetRTCPStatus(config.rtcp_mode);
brandtr76648da2016-10-20 11:54:48130}
131
brandtr7250b392016-12-19 09:13:46132FlexfecReceiveStreamImpl::~FlexfecReceiveStreamImpl() {
Tommifc2c24e2022-05-25 18:54:24133 RTC_DLOG(LS_INFO) << "~FlexfecReceiveStreamImpl: ssrc: " << remote_ssrc_;
brandtr76648da2016-10-20 11:54:48134}
135
Tommi0377bab2021-05-31 12:26:05136void FlexfecReceiveStreamImpl::RegisterWithTransport(
137 RtpStreamReceiverControllerInterface* receiver_controller) {
Tommi90738dd2021-05-31 15:36:47138 RTC_DCHECK_RUN_ON(&packet_sequence_checker_);
Tommi0377bab2021-05-31 12:26:05139 RTC_DCHECK(!rtp_stream_receiver_);
140
141 if (!receiver_)
142 return;
143
144 // TODO(nisse): OnRtpPacket in this class delegates all real work to
145 // `receiver_`. So maybe we don't need to implement RtpPacketSinkInterface
146 // here at all, we'd then delete the OnRtpPacket method and instead register
147 // `receiver_` as the RtpPacketSinkInterface for this stream.
148 rtp_stream_receiver_ =
Tommicf4ed152022-05-09 20:46:57149 receiver_controller->CreateReceiver(remote_ssrc(), this);
Tommi0377bab2021-05-31 12:26:05150}
151
152void FlexfecReceiveStreamImpl::UnregisterFromTransport() {
Tommi90738dd2021-05-31 15:36:47153 RTC_DCHECK_RUN_ON(&packet_sequence_checker_);
Tommi0377bab2021-05-31 12:26:05154 rtp_stream_receiver_.reset();
155}
156
nisse5c29a7a2017-02-16 14:52:32157void FlexfecReceiveStreamImpl::OnRtpPacket(const RtpPacketReceived& packet) {
Tommi1f38a382021-09-08 08:44:50158 RTC_DCHECK_RUN_ON(&packet_sequence_checker_);
brandtr76648da2016-10-20 11:54:48159 if (!receiver_)
nisse5c29a7a2017-02-16 14:52:32160 return;
brandtrfa5a3682017-01-17 09:33:54161
nisse5c29a7a2017-02-16 14:52:32162 receiver_->OnRtpPacket(packet);
brandtrfa5a3682017-01-17 09:33:54163
Artem Titovea240272021-07-26 10:40:21164 // Do not report media packets in the RTCP RRs generated by `rtp_rtcp_`.
Tommicf4ed152022-05-09 20:46:57165 if (packet.Ssrc() == remote_ssrc()) {
Niels Möller1f3206c2018-09-14 06:26:32166 rtp_receive_statistics_->OnRtpPacket(packet);
brandtrfa5a3682017-01-17 09:33:54167 }
brandtr76648da2016-10-20 11:54:48168}
169
Tommi43b15c32022-07-28 07:24:52170void FlexfecReceiveStreamImpl::SetPayloadType(int payload_type) {
171 RTC_DCHECK_RUN_ON(&packet_sequence_checker_);
172 RTC_DCHECK_GE(payload_type, -1);
173 payload_type_ = payload_type;
174}
175
176int FlexfecReceiveStreamImpl::payload_type() const {
177 RTC_DCHECK_RUN_ON(&packet_sequence_checker_);
178 return payload_type_;
179}
180
Tommi1331c182022-05-17 08:13:52181void FlexfecReceiveStreamImpl::SetLocalSsrc(uint32_t local_ssrc) {
182 RTC_DCHECK_RUN_ON(&packet_sequence_checker_);
Danil Chapovalov4e41db22024-08-30 13:10:20183 if (local_ssrc == rtp_rtcp_.local_media_ssrc())
Tommi1331c182022-05-17 08:13:52184 return;
185
Danil Chapovalov4e41db22024-08-30 13:10:20186 rtp_rtcp_.SetLocalSsrc(local_ssrc);
Tommi1331c182022-05-17 08:13:52187}
188
brandtr76648da2016-10-20 11:54:48189} // namespace webrtc