diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 19:33:14 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 19:33:14 +0000 |
commit | 36d22d82aa202bb199967e9512281e9a53db42c9 (patch) | |
tree | 105e8c98ddea1c1e4784a60a5a6410fa416be2de /third_party/libwebrtc/pc/channel.h | |
parent | Initial commit. (diff) | |
download | firefox-esr-36d22d82aa202bb199967e9512281e9a53db42c9.tar.xz firefox-esr-36d22d82aa202bb199967e9512281e9a53db42c9.zip |
Adding upstream version 115.7.0esr.upstream/115.7.0esrupstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to '')
-rw-r--r-- | third_party/libwebrtc/pc/channel.h | 491 |
1 files changed, 491 insertions, 0 deletions
diff --git a/third_party/libwebrtc/pc/channel.h b/third_party/libwebrtc/pc/channel.h new file mode 100644 index 0000000000..b3020e377c --- /dev/null +++ b/third_party/libwebrtc/pc/channel.h @@ -0,0 +1,491 @@ +/* + * Copyright 2004 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef PC_CHANNEL_H_ +#define PC_CHANNEL_H_ + +#include <stdint.h> + +#include <functional> +#include <memory> +#include <string> +#include <utility> +#include <vector> + +#include "absl/strings/string_view.h" +#include "absl/types/optional.h" +#include "api/crypto/crypto_options.h" +#include "api/jsep.h" +#include "api/media_types.h" +#include "api/rtp_parameters.h" +#include "api/rtp_transceiver_direction.h" +#include "api/scoped_refptr.h" +#include "api/sequence_checker.h" +#include "api/task_queue/pending_task_safety_flag.h" +#include "call/rtp_demuxer.h" +#include "call/rtp_packet_sink_interface.h" +#include "media/base/media_channel.h" +#include "media/base/media_channel_impl.h" +#include "media/base/stream_params.h" +#include "modules/rtp_rtcp/source/rtp_packet_received.h" +#include "pc/channel_interface.h" +#include "pc/rtp_transport_internal.h" +#include "pc/session_description.h" +#include "rtc_base/async_packet_socket.h" +#include "rtc_base/checks.h" +#include "rtc_base/containers/flat_set.h" +#include "rtc_base/copy_on_write_buffer.h" +#include "rtc_base/network/sent_packet.h" +#include "rtc_base/network_route.h" +#include "rtc_base/socket.h" +#include "rtc_base/third_party/sigslot/sigslot.h" +#include "rtc_base/thread.h" +#include "rtc_base/thread_annotations.h" +#include "rtc_base/unique_id_generator.h" + +namespace cricket { + +// BaseChannel contains logic common to voice and video, including enable, +// marshaling calls to a worker and network threads, and connection and media +// monitors. +// +// BaseChannel assumes signaling and other threads are allowed to make +// synchronous calls to the worker thread, the worker thread makes synchronous +// calls only to the network thread, and the network thread can't be blocked by +// other threads. +// All methods with _n suffix must be called on network thread, +// methods with _w suffix on worker thread +// and methods with _s suffix on signaling thread. +// Network and worker threads may be the same thread. +// +class VideoChannel; +class VoiceChannel; + +class BaseChannel : public ChannelInterface, + // TODO(tommi): Remove has_slots inheritance. + public sigslot::has_slots<>, + // TODO(tommi): Consider implementing these interfaces + // via composition. + public MediaChannelNetworkInterface, + public webrtc::RtpPacketSinkInterface { + public: + // If `srtp_required` is true, the channel will not send or receive any + // RTP/RTCP packets without using SRTP (either using SDES or DTLS-SRTP). + // The BaseChannel does not own the UniqueRandomIdGenerator so it is the + // responsibility of the user to ensure it outlives this object. + // TODO(zhihuang:) Create a BaseChannel::Config struct for the parameter lists + // which will make it easier to change the constructor. + BaseChannel(rtc::Thread* worker_thread, + rtc::Thread* network_thread, + rtc::Thread* signaling_thread, + std::unique_ptr<MediaChannel> media_channel, + absl::string_view mid, + bool srtp_required, + webrtc::CryptoOptions crypto_options, + rtc::UniqueRandomIdGenerator* ssrc_generator); + virtual ~BaseChannel(); + + rtc::Thread* worker_thread() const { return worker_thread_; } + rtc::Thread* network_thread() const { return network_thread_; } + const std::string& mid() const override { return demuxer_criteria_.mid(); } + // TODO(deadbeef): This is redundant; remove this. + absl::string_view transport_name() const override { + RTC_DCHECK_RUN_ON(network_thread()); + if (rtp_transport_) + return rtp_transport_->transport_name(); + return ""; + } + + // This function returns true if using SRTP (DTLS-based keying or SDES). + bool srtp_active() const { + RTC_DCHECK_RUN_ON(network_thread()); + return rtp_transport_ && rtp_transport_->IsSrtpActive(); + } + + // Set an RTP level transport which could be an RtpTransport without + // encryption, an SrtpTransport for SDES or a DtlsSrtpTransport for DTLS-SRTP. + // This can be called from any thread and it hops to the network thread + // internally. It would replace the `SetTransports` and its variants. + bool SetRtpTransport(webrtc::RtpTransportInternal* rtp_transport) override; + + webrtc::RtpTransportInternal* rtp_transport() const { + RTC_DCHECK_RUN_ON(network_thread()); + return rtp_transport_; + } + + // Channel control + bool SetLocalContent(const MediaContentDescription* content, + webrtc::SdpType type, + std::string& error_desc) override; + bool SetRemoteContent(const MediaContentDescription* content, + webrtc::SdpType type, + std::string& error_desc) override; + // Controls whether this channel will receive packets on the basis of + // matching payload type alone. This is needed for legacy endpoints that + // don't signal SSRCs or use MID/RID, but doesn't make sense if there is + // more than channel of specific media type, As that creates an ambiguity. + // + // This method will also remove any existing streams that were bound to this + // channel on the basis of payload type, since one of these streams might + // actually belong to a new channel. See: crbug.com/webrtc/11477 + bool SetPayloadTypeDemuxingEnabled(bool enabled) override; + + void Enable(bool enable) override; + + const std::vector<StreamParams>& local_streams() const override { + return local_streams_; + } + const std::vector<StreamParams>& remote_streams() const override { + return remote_streams_; + } + + // Used for latency measurements. + void SetFirstPacketReceivedCallback(std::function<void()> callback) override; + + // From RtpTransport - public for testing only + void OnTransportReadyToSend(bool ready); + + // Only public for unit tests. Otherwise, consider protected. + int SetOption(SocketType type, rtc::Socket::Option o, int val) override; + + // RtpPacketSinkInterface overrides. + void OnRtpPacket(const webrtc::RtpPacketReceived& packet) override; + + MediaChannel* media_channel() override { return media_channel_.get(); } + + VideoMediaSendChannelInterface* video_media_send_channel() override { + RTC_CHECK(false) << "Attempt to fetch video channel from non-video"; + return nullptr; + } + VoiceMediaSendChannelInterface* voice_media_send_channel() override { + RTC_CHECK(false) << "Attempt to fetch voice channel from non-voice"; + return nullptr; + } + VideoMediaReceiveChannelInterface* video_media_receive_channel() override { + RTC_CHECK(false) << "Attempt to fetch video channel from non-video"; + return nullptr; + } + VoiceMediaReceiveChannelInterface* voice_media_receive_channel() override { + RTC_CHECK(false) << "Attempt to fetch voice channel from non-voice"; + return nullptr; + } + + protected: + void set_local_content_direction(webrtc::RtpTransceiverDirection direction) + RTC_RUN_ON(worker_thread()) { + local_content_direction_ = direction; + } + + webrtc::RtpTransceiverDirection local_content_direction() const + RTC_RUN_ON(worker_thread()) { + return local_content_direction_; + } + + void set_remote_content_direction(webrtc::RtpTransceiverDirection direction) + RTC_RUN_ON(worker_thread()) { + remote_content_direction_ = direction; + } + + webrtc::RtpTransceiverDirection remote_content_direction() const + RTC_RUN_ON(worker_thread()) { + return remote_content_direction_; + } + + webrtc::RtpExtension::Filter extensions_filter() const { + return extensions_filter_; + } + + bool network_initialized() RTC_RUN_ON(network_thread()) { + return media_channel_->HasNetworkInterface(); + } + + bool enabled() const RTC_RUN_ON(worker_thread()) { return enabled_; } + rtc::Thread* signaling_thread() const { return signaling_thread_; } + + // Call to verify that: + // * The required content description directions have been set. + // * The channel is enabled. + // * The SRTP filter is active if it's needed. + // * The transport has been writable before, meaning it should be at least + // possible to succeed in sending a packet. + // + // When any of these properties change, UpdateMediaSendRecvState_w should be + // called. + bool IsReadyToSendMedia_w() const RTC_RUN_ON(worker_thread()); + + // NetworkInterface implementation, called by MediaEngine + bool SendPacket(rtc::CopyOnWriteBuffer* packet, + const rtc::PacketOptions& options) override; + bool SendRtcp(rtc::CopyOnWriteBuffer* packet, + const rtc::PacketOptions& options) override; + + // From RtpTransportInternal + void OnWritableState(bool writable); + + void OnNetworkRouteChanged(absl::optional<rtc::NetworkRoute> network_route); + + bool SendPacket(bool rtcp, + rtc::CopyOnWriteBuffer* packet, + const rtc::PacketOptions& options); + + void EnableMedia_w() RTC_RUN_ON(worker_thread()); + void DisableMedia_w() RTC_RUN_ON(worker_thread()); + + // Performs actions if the RTP/RTCP writable state changed. This should + // be called whenever a channel's writable state changes or when RTCP muxing + // becomes active/inactive. + void UpdateWritableState_n() RTC_RUN_ON(network_thread()); + void ChannelWritable_n() RTC_RUN_ON(network_thread()); + void ChannelNotWritable_n() RTC_RUN_ON(network_thread()); + + bool SetPayloadTypeDemuxingEnabled_w(bool enabled) + RTC_RUN_ON(worker_thread()); + + // Should be called whenever the conditions for + // IsReadyToReceiveMedia/IsReadyToSendMedia are satisfied (or unsatisfied). + // Updates the send/recv state of the media channel. + virtual void UpdateMediaSendRecvState_w() RTC_RUN_ON(worker_thread()) = 0; + + bool UpdateLocalStreams_w(const std::vector<StreamParams>& streams, + webrtc::SdpType type, + std::string& error_desc) + RTC_RUN_ON(worker_thread()); + bool UpdateRemoteStreams_w(const MediaContentDescription* content, + webrtc::SdpType type, + std::string& error_desc) + RTC_RUN_ON(worker_thread()); + virtual bool SetLocalContent_w(const MediaContentDescription* content, + webrtc::SdpType type, + std::string& error_desc) + RTC_RUN_ON(worker_thread()) = 0; + virtual bool SetRemoteContent_w(const MediaContentDescription* content, + webrtc::SdpType type, + std::string& error_desc) + RTC_RUN_ON(worker_thread()) = 0; + + // Returns a list of RTP header extensions where any extension URI is unique. + // Encrypted extensions will be either preferred or discarded, depending on + // the current crypto_options_. + RtpHeaderExtensions GetDeduplicatedRtpHeaderExtensions( + const RtpHeaderExtensions& extensions); + + // Add `payload_type` to `demuxer_criteria_` if payload type demuxing is + // enabled. + // Returns true if the demuxer payload type changed and a re-registration + // is needed. + bool MaybeAddHandledPayloadType(int payload_type) RTC_RUN_ON(worker_thread()); + + // Returns true if the demuxer payload type criteria was non-empty before + // clearing. + bool ClearHandledPayloadTypes() RTC_RUN_ON(worker_thread()); + + // Hops to the network thread to update the transport if an update is + // requested. If `update_demuxer` is false and `extensions` is not set, the + // function simply returns. If either of these is set, the function updates + // the transport with either or both of the demuxer criteria and the supplied + // rtp header extensions. + // Returns `true` if either an update wasn't needed or one was successfully + // applied. If the return value is `false`, then updating the demuxer criteria + // failed, which needs to be treated as an error. + bool MaybeUpdateDemuxerAndRtpExtensions_w( + bool update_demuxer, + absl::optional<RtpHeaderExtensions> extensions, + std::string& error_desc) RTC_RUN_ON(worker_thread()); + + bool RegisterRtpDemuxerSink_w() RTC_RUN_ON(worker_thread()); + + // Return description of media channel to facilitate logging + std::string ToString() const; + + private: + bool ConnectToRtpTransport_n() RTC_RUN_ON(network_thread()); + void DisconnectFromRtpTransport_n() RTC_RUN_ON(network_thread()); + void SignalSentPacket_n(const rtc::SentPacket& sent_packet); + + rtc::Thread* const worker_thread_; + rtc::Thread* const network_thread_; + rtc::Thread* const signaling_thread_; + rtc::scoped_refptr<webrtc::PendingTaskSafetyFlag> alive_; + + std::function<void()> on_first_packet_received_ + RTC_GUARDED_BY(network_thread()); + + webrtc::RtpTransportInternal* rtp_transport_ + RTC_GUARDED_BY(network_thread()) = nullptr; + + std::vector<std::pair<rtc::Socket::Option, int> > socket_options_ + RTC_GUARDED_BY(network_thread()); + std::vector<std::pair<rtc::Socket::Option, int> > rtcp_socket_options_ + RTC_GUARDED_BY(network_thread()); + bool writable_ RTC_GUARDED_BY(network_thread()) = false; + bool was_ever_writable_n_ RTC_GUARDED_BY(network_thread()) = false; + bool was_ever_writable_ RTC_GUARDED_BY(worker_thread()) = false; + const bool srtp_required_ = true; + + // Set to either kPreferEncryptedExtension or kDiscardEncryptedExtension + // based on the supplied CryptoOptions. + const webrtc::RtpExtension::Filter extensions_filter_; + + // MediaChannel related members that should be accessed from the worker + // thread. + const std::unique_ptr<MediaChannel> media_channel_; + // Currently the `enabled_` flag is accessed from the signaling thread as + // well, but it can be changed only when signaling thread does a synchronous + // call to the worker thread, so it should be safe. + bool enabled_ RTC_GUARDED_BY(worker_thread()) = false; + bool enabled_s_ RTC_GUARDED_BY(signaling_thread()) = false; + bool payload_type_demuxing_enabled_ RTC_GUARDED_BY(worker_thread()) = true; + std::vector<StreamParams> local_streams_ RTC_GUARDED_BY(worker_thread()); + std::vector<StreamParams> remote_streams_ RTC_GUARDED_BY(worker_thread()); + webrtc::RtpTransceiverDirection local_content_direction_ RTC_GUARDED_BY( + worker_thread()) = webrtc::RtpTransceiverDirection::kInactive; + webrtc::RtpTransceiverDirection remote_content_direction_ RTC_GUARDED_BY( + worker_thread()) = webrtc::RtpTransceiverDirection::kInactive; + + // Cached list of payload types, used if payload type demuxing is re-enabled. + webrtc::flat_set<uint8_t> payload_types_ RTC_GUARDED_BY(worker_thread()); + // A stored copy of the rtp header extensions as applied to the transport. + RtpHeaderExtensions rtp_header_extensions_ RTC_GUARDED_BY(worker_thread()); + // TODO(bugs.webrtc.org/12239): Modified on worker thread, accessed + // on network thread in RegisterRtpDemuxerSink_n (called from Init_w) + webrtc::RtpDemuxerCriteria demuxer_criteria_; + // This generator is used to generate SSRCs for local streams. + // This is needed in cases where SSRCs are not negotiated or set explicitly + // like in Simulcast. + // This object is not owned by the channel so it must outlive it. + rtc::UniqueRandomIdGenerator* const ssrc_generator_; +}; + +// VoiceChannel is a specialization that adds support for early media, DTMF, +// and input/output level monitoring. +class VoiceChannel : public BaseChannel { + public: + VoiceChannel(rtc::Thread* worker_thread, + rtc::Thread* network_thread, + rtc::Thread* signaling_thread, + std::unique_ptr<VoiceMediaChannel> channel, + absl::string_view mid, + bool srtp_required, + webrtc::CryptoOptions crypto_options, + rtc::UniqueRandomIdGenerator* ssrc_generator); + ~VoiceChannel(); + + VideoChannel* AsVideoChannel() override { + RTC_CHECK_NOTREACHED(); + return nullptr; + } + VoiceChannel* AsVoiceChannel() override { return this; } + + VoiceMediaSendChannelInterface* media_send_channel() override { + return &send_channel_; + } + + VoiceMediaSendChannelInterface* voice_media_send_channel() override { + return &send_channel_; + } + + VoiceMediaReceiveChannelInterface* media_receive_channel() override { + return &receive_channel_; + } + + VoiceMediaReceiveChannelInterface* voice_media_receive_channel() override { + return &receive_channel_; + } + + cricket::MediaType media_type() const override { + return cricket::MEDIA_TYPE_AUDIO; + } + + private: + // overrides from BaseChannel + void UpdateMediaSendRecvState_w() RTC_RUN_ON(worker_thread()) override; + bool SetLocalContent_w(const MediaContentDescription* content, + webrtc::SdpType type, + std::string& error_desc) + RTC_RUN_ON(worker_thread()) override; + bool SetRemoteContent_w(const MediaContentDescription* content, + webrtc::SdpType type, + std::string& error_desc) + RTC_RUN_ON(worker_thread()) override; + + VoiceMediaSendChannel send_channel_ RTC_GUARDED_BY(worker_thread()); + VoiceMediaReceiveChannel receive_channel_ RTC_GUARDED_BY(worker_thread()); + // Last AudioSendParameters sent down to the media_channel() via + // SetSendParameters. + AudioSendParameters last_send_params_ RTC_GUARDED_BY(worker_thread()); + // Last AudioRecvParameters sent down to the media_channel() via + // SetRecvParameters. + AudioRecvParameters last_recv_params_ RTC_GUARDED_BY(worker_thread()); +}; + +// VideoChannel is a specialization for video. +class VideoChannel : public BaseChannel { + public: + VideoChannel(rtc::Thread* worker_thread, + rtc::Thread* network_thread, + rtc::Thread* signaling_thread, + std::unique_ptr<VideoMediaChannel> media_channel, + absl::string_view mid, + bool srtp_required, + webrtc::CryptoOptions crypto_options, + rtc::UniqueRandomIdGenerator* ssrc_generator); + ~VideoChannel(); + + VideoChannel* AsVideoChannel() override { return this; } + VoiceChannel* AsVoiceChannel() override { + RTC_CHECK_NOTREACHED(); + return nullptr; + } + + VideoMediaSendChannelInterface* media_send_channel() override { + return &send_channel_; + } + + VideoMediaSendChannelInterface* video_media_send_channel() override { + return &send_channel_; + } + + VideoMediaReceiveChannelInterface* media_receive_channel() override { + return &receive_channel_; + } + + VideoMediaReceiveChannelInterface* video_media_receive_channel() override { + return &receive_channel_; + } + + cricket::MediaType media_type() const override { + return cricket::MEDIA_TYPE_VIDEO; + } + + private: + // overrides from BaseChannel + void UpdateMediaSendRecvState_w() RTC_RUN_ON(worker_thread()) override; + bool SetLocalContent_w(const MediaContentDescription* content, + webrtc::SdpType type, + std::string& error_desc) + RTC_RUN_ON(worker_thread()) override; + bool SetRemoteContent_w(const MediaContentDescription* content, + webrtc::SdpType type, + std::string& error_desc) + RTC_RUN_ON(worker_thread()) override; + + VideoMediaSendChannel send_channel_ RTC_GUARDED_BY(worker_thread()); + VideoMediaReceiveChannel receive_channel_ RTC_GUARDED_BY(worker_thread()); + // Last VideoSendParameters sent down to the media_channel() via + // SetSendParameters. + VideoSendParameters last_send_params_ RTC_GUARDED_BY(worker_thread()); + // Last VideoRecvParameters sent down to the media_channel() via + // SetRecvParameters. + VideoRecvParameters last_recv_params_ RTC_GUARDED_BY(worker_thread()); +}; + +} // namespace cricket + +#endif // PC_CHANNEL_H_ |