| /* | |
| * Copyright 2015 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. | |
| */ | |
| // This file contains classes that implement RtpSenderInterface. | |
| // An RtpSender associates a MediaStreamTrackInterface with an underlying | |
| // transport (provided by AudioProviderInterface/VideoProviderInterface) | |
| #ifndef PC_RTP_SENDER_H_ | |
| #define PC_RTP_SENDER_H_ | |
| #include <stddef.h> | |
| #include <stdint.h> | |
| #include <memory> | |
| #include <optional> | |
| #include <string> | |
| #include <vector> | |
| #include "absl/functional/any_invocable.h" | |
| #include "absl/strings/string_view.h" | |
| #include "api/crypto/frame_encryptor_interface.h" | |
| #include "api/dtls_transport_interface.h" | |
| #include "api/dtmf_sender_interface.h" | |
| #include "api/environment/environment.h" | |
| #include "api/frame_transformer_interface.h" | |
| #include "api/media_stream_interface.h" | |
| #include "api/media_types.h" | |
| #include "api/rtc_error.h" | |
| #include "api/rtp_parameters.h" | |
| #include "api/rtp_sender_interface.h" | |
| #include "api/scoped_refptr.h" | |
| #include "api/sequence_checker.h" | |
| #include "api/task_queue/pending_task_safety_flag.h" | |
| #include "api/task_queue/task_queue_base.h" | |
| #include "api/video_codecs/video_encoder_factory.h" | |
| #include "media/base/audio_source.h" | |
| #include "media/base/codec.h" | |
| #include "media/base/media_channel.h" | |
| #include "pc/dtmf_sender.h" | |
| #include "pc/legacy_stats_collector_interface.h" | |
| #include "rtc_base/synchronization/mutex.h" | |
| #include "rtc_base/thread.h" | |
| #include "rtc_base/thread_annotations.h" | |
| namespace webrtc { | |
| bool UnimplementedRtpParameterHasValue(const RtpParameters& parameters); | |
| // Internal interface used by PeerConnection. | |
| class RtpSenderInternal : public RtpSenderInterface { | |
| public: | |
| // Sets the underlying MediaEngine channel associated with this RtpSender. | |
| // A VoiceMediaChannel should be used for audio RtpSenders and | |
| // a VideoMediaChannel should be used for video RtpSenders. | |
| // Must call SetMediaChannel(nullptr) before the media channel is destroyed. | |
| virtual void SetMediaChannel(MediaSendChannelInterface* media_channel) = 0; | |
| // Used to set the SSRC of the sender, once a local description has been set. | |
| // If `ssrc` is 0, this indiates that the sender should disconnect from the | |
| // underlying transport (this occurs if the sender isn't seen in a local | |
| // description). | |
| virtual void SetSsrc(uint32_t ssrc) = 0; | |
| virtual void set_stream_ids(const std::vector<std::string>& stream_ids) = 0; | |
| virtual void set_init_send_encodings( | |
| const std::vector<RtpEncodingParameters>& init_send_encodings) = 0; | |
| virtual void set_transport( | |
| scoped_refptr<DtlsTransportInterface> dtls_transport) = 0; | |
| virtual void Stop() = 0; | |
| // Cleans up the state on the signaling thread, as `Stop()` does, but does | |
| // not perform the worker thread cleanup directly. Instead, returns a task | |
| // that the caller must invoke on the worker thread to perform that work. | |
| // Note that if no worker thread needs to be done, the retuned task will be | |
| // empty. | |
| virtual absl::AnyInvocable<void() &&> DetachTrackAndGetStopTask() = 0; | |
| // `GetParameters` and `SetParameters` operate with a transactional model. | |
| // Allow access to get/set parameters without invalidating transaction id. | |
| virtual RtpParameters GetParametersInternal(bool may_use_cache, | |
| bool with_all_layers) const = 0; | |
| virtual RTCError SetParametersInternal(const RtpParameters& parameters, | |
| SetParametersCallback, | |
| bool blocking) = 0; | |
| virtual void SetCachedParameters(std::optional<RtpParameters> parameters) = 0; | |
| // GetParameters and SetParameters will remove deactivated simulcast layers | |
| // and restore them on SetParameters. This is probably a Bad Idea, but we | |
| // do not know who depends on this behavior | |
| virtual RtpParameters GetParametersInternalWithAllLayers() const = 0; | |
| virtual RTCError SetParametersInternalWithAllLayers( | |
| const RtpParameters& parameters) = 0; | |
| // Returns an ID that changes every time SetTrack() is called, but | |
| // otherwise remains constant. Used to generate IDs for stats. | |
| // The special value zero means that no track is attached. | |
| virtual int AttachmentId() const = 0; | |
| // Disables the layers identified by the specified RIDs. | |
| // If the specified list is empty, this is a no-op. | |
| virtual RTCError DisableEncodingLayers( | |
| const std::vector<std::string>& rid) = 0; | |
| // Used by the owning transceiver to inform the sender on the currently | |
| // selected codecs. | |
| virtual void SetSendCodecs(std::vector<Codec> send_codecs) = 0; | |
| virtual std::vector<Codec> GetSendCodecs() const = 0; | |
| virtual void NotifyFirstPacketSent() = 0; | |
| }; | |
| // Shared implementation for RtpSenderInternal interface. | |
| class RtpSenderBase : public RtpSenderInternal, public ObserverInterface { | |
| public: | |
| class SetStreamsObserver { | |
| public: | |
| virtual ~SetStreamsObserver() = default; | |
| virtual void OnSetStreams() = 0; | |
| }; | |
| ~RtpSenderBase() override; | |
| // Sets the underlying MediaEngine channel associated with this RtpSender. | |
| // A VoiceMediaChannel should be used for audio RtpSenders and | |
| // a VideoMediaChannel should be used for video RtpSenders. | |
| // Must call SetMediaChannel(nullptr) before the media channel is destroyed. | |
| void SetMediaChannel(MediaSendChannelInterface* media_channel) override; | |
| bool SetTrack(MediaStreamTrackInterface* track) override; | |
| scoped_refptr<MediaStreamTrackInterface> track() const override { | |
| RTC_DCHECK_RUN_ON(signaling_thread_); | |
| return track_; | |
| } | |
| MediaType media_type() const final { return media_type_; } | |
| RtpParameters GetParameters() const override; | |
| RTCError SetParameters(const RtpParameters& parameters) override; | |
| void SetParametersAsync(const RtpParameters& parameters, | |
| SetParametersCallback callback) override; | |
| // `GetParameters` and `SetParameters` operate with a transactional model. | |
| // Allow access to get/set parameters without invalidating transaction id. | |
| RtpParameters GetParametersInternal( | |
| bool may_use_cache = true, | |
| bool with_all_layers = false) const override; | |
| RTCError SetParametersInternal(const RtpParameters& parameters, | |
| SetParametersCallback callback = nullptr, | |
| bool blocking = true) override; | |
| void SetCachedParameters(std::optional<RtpParameters> parameters) override; | |
| RTCError CheckSetParameters(const RtpParameters& parameters); | |
| RtpParameters GetParametersInternalWithAllLayers() const override; | |
| RTCError SetParametersInternalWithAllLayers( | |
| const RtpParameters& parameters) override; | |
| std::optional<RTCError> ValidateAndMaybeUpdateInitParameters( | |
| const RtpParameters& parameters) RTC_RUN_ON(signaling_thread_); | |
| // Used to set the SSRC of the sender, once a local description has been set. | |
| // If `ssrc` is 0, this indiates that the sender should disconnect from the | |
| // underlying transport (this occurs if the sender isn't seen in a local | |
| // description). | |
| void SetSsrc(uint32_t ssrc) override; | |
| uint32_t ssrc() const override { | |
| RTC_DCHECK_RUN_ON(signaling_thread_); | |
| return ssrc_; | |
| } | |
| std::vector<std::string> stream_ids() const override { | |
| RTC_DCHECK_RUN_ON(signaling_thread_); | |
| return stream_ids_; | |
| } | |
| // Set stream ids, eliminating duplicates in the process. | |
| void set_stream_ids(const std::vector<std::string>& stream_ids) override; | |
| void SetStreams(const std::vector<std::string>& stream_ids) override; | |
| std::string id() const override { return id_; } | |
| void set_init_send_encodings( | |
| const std::vector<RtpEncodingParameters>& init_send_encodings) override { | |
| init_parameters_.encodings = init_send_encodings; | |
| } | |
| std::vector<RtpEncodingParameters> init_send_encodings() const override { | |
| RTC_DCHECK_RUN_ON(signaling_thread_); | |
| return init_parameters_.encodings; | |
| } | |
| void set_transport( | |
| scoped_refptr<DtlsTransportInterface> dtls_transport) override { | |
| dtls_transport_ = dtls_transport; | |
| } | |
| scoped_refptr<DtlsTransportInterface> dtls_transport() const override { | |
| RTC_DCHECK_RUN_ON(signaling_thread_); | |
| return dtls_transport_; | |
| } | |
| void SetFrameEncryptor( | |
| scoped_refptr<FrameEncryptorInterface> frame_encryptor) override; | |
| scoped_refptr<FrameEncryptorInterface> GetFrameEncryptor() const override { | |
| return frame_encryptor_; | |
| } | |
| void Stop() override; | |
| absl::AnyInvocable<void() &&> DetachTrackAndGetStopTask() override; | |
| // Returns an ID that changes every time SetTrack() is called, but | |
| // otherwise remains constant. Used to generate IDs for stats. | |
| // The special value zero means that no track is attached. | |
| int AttachmentId() const override { return attachment_id_; } | |
| // Disables the layers identified by the specified RIDs. | |
| // If the specified list is empty, this is a no-op. | |
| RTCError DisableEncodingLayers(const std::vector<std::string>& rid) override; | |
| void SetFrameTransformer( | |
| scoped_refptr<FrameTransformerInterface> frame_transformer) override; | |
| void SetEncoderSelector( | |
| std::unique_ptr<VideoEncoderFactory::EncoderSelectorInterface> | |
| encoder_selector) override; | |
| void SetEncoderSelectorOnChannel(); | |
| void SetSendCodecs(std::vector<Codec> send_codecs) override { | |
| send_codecs_ = send_codecs; | |
| } | |
| std::vector<Codec> GetSendCodecs() const override { return send_codecs_; } | |
| void NotifyFirstPacketSent() override; | |
| void SetObserver(RtpSenderObserverInterface* observer) override; | |
| protected: | |
| void InvalidateCache() { | |
| RTC_DCHECK_RUN_ON(signaling_thread_); | |
| cached_parameters_.reset(); | |
| } | |
| // Called by the media channel when parameters change autonomously on the | |
| // worker thread (e.g., encoder fallback). | |
| void OnParametersChanged(); | |
| // If `set_streams_observer` is not null, it is invoked when SetStreams() | |
| // is called. `set_streams_observer` is not owned by this object. If not | |
| // null, it must be valid at least until this sender becomes stopped. | |
| RtpSenderBase(const Environment& env, | |
| Thread* signaling_thread, | |
| Thread* worker_thread, | |
| absl::string_view id, | |
| MediaType media_type, | |
| SetStreamsObserver* set_streams_observer, | |
| MediaSendChannelInterface* media_channel); | |
| // TODO(bugs.webrtc.org/8694): Since SSRC == 0 is technically valid, figure | |
| // out some other way to test if we have a valid SSRC. | |
| bool can_send_track() const RTC_RUN_ON(signaling_thread_) { | |
| return track_ && ssrc_; | |
| } | |
| virtual std::string track_kind() const = 0; | |
| // Enable sending on the media channel. | |
| virtual void SetSend() = 0; | |
| // Disable sending on the media channel. | |
| virtual void ClearSend() = 0; | |
| virtual void ClearSend_w(uint32_t ssrc) RTC_RUN_ON(worker_thread_) = 0; | |
| // Template method pattern to allow subclasses to add custom behavior for | |
| // when tracks are attached, detached, and for adding tracks to statistics. | |
| virtual void AttachTrack() RTC_RUN_ON(signaling_thread_) {} | |
| virtual void DetachTrack() RTC_RUN_ON(signaling_thread_) {} | |
| virtual void AddTrackToStats() RTC_RUN_ON(signaling_thread_) {} | |
| virtual void RemoveTrackFromStats() RTC_RUN_ON(signaling_thread_) {} | |
| // Special case for downstream code that calls into this code with a | |
| // configuration where the signaling, worker and network threads are all | |
| // configured to be the same thread. | |
| RTCError SetParametersInternalWorkaround(const RtpParameters& parameters); | |
| const Environment env_; | |
| TaskQueueBase* const signaling_thread_; | |
| Thread* const worker_thread_; | |
| // TODO(tommi): The type for ssrc_ should be `std::optional<uint32_t>` | |
| // since 0 is a legal SSRC value. | |
| uint32_t ssrc_ RTC_GUARDED_BY(signaling_thread_) = 0; | |
| bool stopped_ RTC_GUARDED_BY(signaling_thread_) = false; | |
| int attachment_id_ = 0; | |
| const std::string id_; | |
| const MediaType media_type_; | |
| std::vector<std::string> stream_ids_; | |
| RtpParameters init_parameters_; | |
| mutable std::optional<RtpParameters> cached_parameters_ | |
| RTC_GUARDED_BY(signaling_thread_); | |
| std::vector<Codec> send_codecs_; | |
| // TODO(tommi): Several member variables in this class (ssrc_, stopped_, etc) | |
| // are accessed from more than one thread without a guard or lock. Internally | |
| // there are also several Invoke()s that we could remove since the upstream | |
| // code may already be performing several operations on the worker thread. Add | |
| // RTC_GUARDED_BY(worker_thread_). | |
| MediaSendChannelInterface* media_channel_ RTC_GUARDED_BY(worker_thread_) = | |
| nullptr; | |
| // Apply RTC_GUARDED_BY(signaling_thread_) when not accessed from worker. | |
| scoped_refptr<MediaStreamTrackInterface> track_; | |
| scoped_refptr<DtlsTransportInterface> dtls_transport_; | |
| // Apply RTC_GUARDED_BY(worker_thread_) when no longer accessed from unknown | |
| // threads. Alternatively make const. | |
| scoped_refptr<FrameEncryptorInterface> frame_encryptor_; | |
| // `last_transaction_id_` is used to verify that `SetParameters` is receiving | |
| // the parameters object that was last returned from `GetParameters`. | |
| // As such, it is used for internal verification and is not observable by the | |
| // the client. It is marked as mutable to enable `GetParameters` to be a | |
| // const method. | |
| mutable std::optional<std::string> last_transaction_id_ | |
| RTC_GUARDED_BY(signaling_thread_); | |
| std::vector<std::string> disabled_rids_; | |
| SetStreamsObserver* const set_streams_observer_ = nullptr; | |
| RtpSenderObserverInterface* observer_ RTC_GUARDED_BY(signaling_thread_) = | |
| nullptr; | |
| bool sent_first_packet_ = false; | |
| scoped_refptr<FrameTransformerInterface> frame_transformer_; | |
| // Guard with RTC_GUARDED_BY(worker_thread_) after refactoring. | |
| std::unique_ptr<VideoEncoderFactory::EncoderSelectorInterface> | |
| encoder_selector_; | |
| scoped_refptr<PendingTaskSafetyFlag> worker_safety_; | |
| ScopedTaskSafety signaling_safety_; | |
| }; | |
| // LocalAudioSinkAdapter receives data callback as a sink to the local | |
| // AudioTrack, and passes the data to the sink of AudioSource. | |
| class LocalAudioSinkAdapter : public AudioTrackSinkInterface, | |
| public AudioSource { | |
| public: | |
| LocalAudioSinkAdapter(); | |
| ~LocalAudioSinkAdapter() override; | |
| private: | |
| // AudioSinkInterface implementation. | |
| void OnData(const void* audio_data, | |
| int bits_per_sample, | |
| int sample_rate, | |
| size_t number_of_channels, | |
| size_t number_of_frames, | |
| std::optional<int64_t> absolute_capture_timestamp_ms) override; | |
| // AudioSinkInterface implementation. | |
| void OnData(const void* audio_data, | |
| int bits_per_sample, | |
| int sample_rate, | |
| size_t number_of_channels, | |
| size_t number_of_frames) override { | |
| OnData(audio_data, bits_per_sample, sample_rate, number_of_channels, | |
| number_of_frames, | |
| /*absolute_capture_timestamp_ms=*/std::nullopt); | |
| } | |
| // AudioSinkInterface implementation. | |
| int NumPreferredChannels() const override { return num_preferred_channels_; } | |
| // webrtc::AudioSource implementation. | |
| void SetSink(AudioSource::Sink* sink) override; | |
| AudioSource::Sink* sink_; | |
| // Critical section protecting `sink_`. | |
| Mutex lock_; | |
| int num_preferred_channels_ = -1; | |
| }; | |
| class AudioRtpSender : public DtmfProviderInterface, public RtpSenderBase { | |
| public: | |
| // Construct an RtpSender for audio with the given sender ID. | |
| // The sender is initialized with no track to send and no associated streams. | |
| // StatsCollector provided so that Add/RemoveLocalAudioTrack can be called | |
| // at the appropriate times. | |
| // If `set_streams_observer` is not null, it is invoked when SetStreams() | |
| // is called. `set_streams_observer` is not owned by this object. If not | |
| // null, it must be valid at least until this sender becomes stopped. | |
| static scoped_refptr<AudioRtpSender> Create( | |
| const Environment& env, | |
| Thread* signaling_thread, | |
| Thread* worker_thread, | |
| absl::string_view id, | |
| LegacyStatsCollectorInterface* stats, | |
| SetStreamsObserver* set_streams_observer, | |
| MediaSendChannelInterface* media_channel); | |
| ~AudioRtpSender() override; | |
| // DtmfSenderProvider implementation. | |
| bool CanInsertDtmf() override; | |
| bool InsertDtmf(int code, int duration) override; | |
| // ObserverInterface implementation. | |
| void OnChanged() override; | |
| std::string track_kind() const override { | |
| return MediaStreamTrackInterface::kAudioKind; | |
| } | |
| scoped_refptr<DtmfSenderInterface> GetDtmfSender() const override; | |
| RTCError GenerateKeyFrame(const std::vector<std::string>& rids) override; | |
| protected: | |
| AudioRtpSender(const Environment& env, | |
| Thread* signaling_thread, | |
| Thread* worker_thread, | |
| absl::string_view id, | |
| LegacyStatsCollectorInterface* legacy_stats, | |
| SetStreamsObserver* set_streams_observer, | |
| MediaSendChannelInterface* media_channel); | |
| void SetSend() override; | |
| void ClearSend() override; | |
| void ClearSend_w(uint32_t ssrc) RTC_RUN_ON(worker_thread_) override; | |
| // Hooks to allow custom logic when tracks are attached and detached. | |
| void AttachTrack() RTC_RUN_ON(signaling_thread_) override; | |
| void DetachTrack() RTC_RUN_ON(signaling_thread_) override; | |
| void AddTrackToStats() RTC_RUN_ON(signaling_thread_) override; | |
| void RemoveTrackFromStats() RTC_RUN_ON(signaling_thread_) override; | |
| private: | |
| VoiceMediaSendChannelInterface* voice_media_channel() | |
| RTC_RUN_ON(worker_thread_) { | |
| return media_channel_->AsVoiceSendChannel(); | |
| } | |
| scoped_refptr<AudioTrackInterface> audio_track() const | |
| RTC_RUN_ON(signaling_thread_) { | |
| return scoped_refptr<AudioTrackInterface>( | |
| static_cast<AudioTrackInterface*>(track_.get())); | |
| } | |
| LegacyStatsCollectorInterface* const legacy_stats_ = nullptr; | |
| const scoped_refptr<DtmfSender> dtmf_sender_; | |
| const scoped_refptr<DtmfSenderInterface> dtmf_sender_proxy_; | |
| bool cached_track_enabled_ = false; | |
| // Used to pass the data callback from the `track_` to the other end of | |
| // webrtc::AudioSource. | |
| const std::unique_ptr<LocalAudioSinkAdapter> sink_adapter_; | |
| }; | |
| class VideoRtpSender : public RtpSenderBase { | |
| public: | |
| // Construct an RtpSender for video with the given sender ID. | |
| // The sender is initialized with no track to send and no associated streams. | |
| // If `set_streams_observer` is not null, it is invoked when SetStreams() | |
| // is called. `set_streams_observer` is not owned by this object. If not | |
| // null, it must be valid at least until this sender becomes stopped. | |
| static scoped_refptr<VideoRtpSender> Create( | |
| const Environment& env, | |
| Thread* signaling_thread, | |
| Thread* worker_thread, | |
| absl::string_view id, | |
| SetStreamsObserver* set_streams_observer, | |
| MediaSendChannelInterface* media_channel); | |
| ~VideoRtpSender() override; | |
| // ObserverInterface implementation | |
| void OnChanged() override; | |
| std::string track_kind() const override { | |
| return MediaStreamTrackInterface::kVideoKind; | |
| } | |
| scoped_refptr<DtmfSenderInterface> GetDtmfSender() const override; | |
| RTCError GenerateKeyFrame(const std::vector<std::string>& rids) override; | |
| protected: | |
| VideoRtpSender(const Environment& env, | |
| Thread* signaling_thread, | |
| Thread* worker_thread, | |
| absl::string_view id, | |
| SetStreamsObserver* set_streams_observer, | |
| MediaSendChannelInterface* media_channel); | |
| void SetSend() override; | |
| void ClearSend() override; | |
| void ClearSend_w(uint32_t ssrc) RTC_RUN_ON(worker_thread_) override; | |
| // Hook to allow custom logic when tracks are attached. | |
| void AttachTrack() RTC_RUN_ON(signaling_thread_) override; | |
| private: | |
| VideoMediaSendChannelInterface* video_media_channel() | |
| RTC_RUN_ON(worker_thread_) { | |
| return media_channel_->AsVideoSendChannel(); | |
| } | |
| scoped_refptr<VideoTrackInterface> video_track() const | |
| RTC_RUN_ON(signaling_thread_) { | |
| return scoped_refptr<VideoTrackInterface>( | |
| static_cast<VideoTrackInterface*>(track_.get())); | |
| } | |
| VideoTrackInterface::ContentHint cached_track_content_hint_ = | |
| VideoTrackInterface::ContentHint::kNone; | |
| }; | |
| } // namespace webrtc | |
| #endif // PC_RTP_SENDER_H_ |