diff options
Diffstat (limited to 'third_party/libwebrtc/pc/audio_rtp_receiver.cc')
-rw-r--r-- | third_party/libwebrtc/pc/audio_rtp_receiver.cc | 338 |
1 files changed, 338 insertions, 0 deletions
diff --git a/third_party/libwebrtc/pc/audio_rtp_receiver.cc b/third_party/libwebrtc/pc/audio_rtp_receiver.cc new file mode 100644 index 0000000000..e58b74ec72 --- /dev/null +++ b/third_party/libwebrtc/pc/audio_rtp_receiver.cc @@ -0,0 +1,338 @@ +/* + * Copyright 2019 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. + */ + +#include "pc/audio_rtp_receiver.h" + +#include <stddef.h> + +#include <string> +#include <utility> +#include <vector> + +#include "api/sequence_checker.h" +#include "pc/audio_track.h" +#include "pc/media_stream_track_proxy.h" +#include "rtc_base/checks.h" +#include "rtc_base/location.h" + +namespace webrtc { + +AudioRtpReceiver::AudioRtpReceiver( + rtc::Thread* worker_thread, + std::string receiver_id, + std::vector<std::string> stream_ids, + bool is_unified_plan, + cricket::VoiceMediaChannel* voice_channel /*= nullptr*/) + : AudioRtpReceiver(worker_thread, + receiver_id, + CreateStreamsFromIds(std::move(stream_ids)), + is_unified_plan, + voice_channel) {} + +AudioRtpReceiver::AudioRtpReceiver( + rtc::Thread* worker_thread, + const std::string& receiver_id, + const std::vector<rtc::scoped_refptr<MediaStreamInterface>>& streams, + bool is_unified_plan, + cricket::VoiceMediaChannel* voice_channel /*= nullptr*/) + : worker_thread_(worker_thread), + id_(receiver_id), + source_(rtc::make_ref_counted<RemoteAudioSource>( + worker_thread, + is_unified_plan + ? RemoteAudioSource::OnAudioChannelGoneAction::kSurvive + : RemoteAudioSource::OnAudioChannelGoneAction::kEnd)), + track_(AudioTrackProxyWithInternal<AudioTrack>::Create( + rtc::Thread::Current(), + AudioTrack::Create(receiver_id, source_))), + media_channel_(voice_channel), + cached_track_enabled_(track_->internal()->enabled()), + attachment_id_(GenerateUniqueId()), + worker_thread_safety_(PendingTaskSafetyFlag::CreateDetachedInactive()) { + RTC_DCHECK(worker_thread_); + RTC_DCHECK(track_->GetSource()->remote()); + track_->RegisterObserver(this); + track_->GetSource()->RegisterAudioObserver(this); + SetStreams(streams); +} + +AudioRtpReceiver::~AudioRtpReceiver() { + RTC_DCHECK_RUN_ON(&signaling_thread_checker_); + RTC_DCHECK(!media_channel_); + + track_->GetSource()->UnregisterAudioObserver(this); + track_->UnregisterObserver(this); +} + +void AudioRtpReceiver::OnChanged() { + RTC_DCHECK_RUN_ON(&signaling_thread_checker_); + const bool enabled = track_->internal()->enabled(); + if (cached_track_enabled_ == enabled) + return; + cached_track_enabled_ = enabled; + worker_thread_->PostTask(SafeTask(worker_thread_safety_, [this, enabled]() { + RTC_DCHECK_RUN_ON(worker_thread_); + Reconfigure(enabled); + })); +} + +void AudioRtpReceiver::SetOutputVolume_w(double volume) { + RTC_DCHECK_RUN_ON(worker_thread_); + RTC_DCHECK_GE(volume, 0.0); + RTC_DCHECK_LE(volume, 10.0); + + if (!media_channel_) + return; + + ssrc_ ? media_channel_->SetOutputVolume(*ssrc_, volume) + : media_channel_->SetDefaultOutputVolume(volume); +} + +void AudioRtpReceiver::OnSetVolume(double volume) { + RTC_DCHECK_RUN_ON(&signaling_thread_checker_); + RTC_DCHECK_GE(volume, 0); + RTC_DCHECK_LE(volume, 10); + + bool track_enabled = track_->internal()->enabled(); + worker_thread_->Invoke<void>(RTC_FROM_HERE, [&]() { + RTC_DCHECK_RUN_ON(worker_thread_); + // Update the cached_volume_ even when stopped, to allow clients to set + // the volume before starting/restarting, eg see crbug.com/1272566. + cached_volume_ = volume; + // When the track is disabled, the volume of the source, which is the + // corresponding WebRtc Voice Engine channel will be 0. So we do not + // allow setting the volume to the source when the track is disabled. + if (track_enabled) + SetOutputVolume_w(volume); + }); +} + +rtc::scoped_refptr<DtlsTransportInterface> AudioRtpReceiver::dtls_transport() + const { + RTC_DCHECK_RUN_ON(&signaling_thread_checker_); + return dtls_transport_; +} + +std::vector<std::string> AudioRtpReceiver::stream_ids() const { + RTC_DCHECK_RUN_ON(&signaling_thread_checker_); + std::vector<std::string> stream_ids(streams_.size()); + for (size_t i = 0; i < streams_.size(); ++i) + stream_ids[i] = streams_[i]->id(); + return stream_ids; +} + +std::vector<rtc::scoped_refptr<MediaStreamInterface>> +AudioRtpReceiver::streams() const { + RTC_DCHECK_RUN_ON(&signaling_thread_checker_); + return streams_; +} + +RtpParameters AudioRtpReceiver::GetParameters() const { + RTC_DCHECK_RUN_ON(worker_thread_); + if (!media_channel_) + return RtpParameters(); + return ssrc_ ? media_channel_->GetRtpReceiveParameters(*ssrc_) + : media_channel_->GetDefaultRtpReceiveParameters(); +} + +void AudioRtpReceiver::SetFrameDecryptor( + rtc::scoped_refptr<FrameDecryptorInterface> frame_decryptor) { + RTC_DCHECK_RUN_ON(worker_thread_); + frame_decryptor_ = std::move(frame_decryptor); + // Special Case: Set the frame decryptor to any value on any existing channel. + if (media_channel_ && ssrc_) { + media_channel_->SetFrameDecryptor(*ssrc_, frame_decryptor_); + } +} + +rtc::scoped_refptr<FrameDecryptorInterface> +AudioRtpReceiver::GetFrameDecryptor() const { + RTC_DCHECK_RUN_ON(worker_thread_); + return frame_decryptor_; +} + +void AudioRtpReceiver::Stop() { + RTC_DCHECK_RUN_ON(&signaling_thread_checker_); + source_->SetState(MediaSourceInterface::kEnded); + track_->internal()->set_ended(); +} + +void AudioRtpReceiver::RestartMediaChannel(absl::optional<uint32_t> ssrc) { + RTC_DCHECK_RUN_ON(&signaling_thread_checker_); + bool enabled = track_->internal()->enabled(); + MediaSourceInterface::SourceState state = source_->state(); + worker_thread_->Invoke<void>(RTC_FROM_HERE, [&]() { + RTC_DCHECK_RUN_ON(worker_thread_); + RestartMediaChannel_w(std::move(ssrc), enabled, state); + }); + source_->SetState(MediaSourceInterface::kLive); +} + +void AudioRtpReceiver::RestartMediaChannel_w( + absl::optional<uint32_t> ssrc, + bool track_enabled, + MediaSourceInterface::SourceState state) { + RTC_DCHECK_RUN_ON(worker_thread_); + if (!media_channel_) + return; // Can't restart. + + // Make sure the safety flag is marked as `alive` for cases where the media + // channel was provided via the ctor and not an explicit call to + // SetMediaChannel. + worker_thread_safety_->SetAlive(); + + if (state != MediaSourceInterface::kInitializing) { + if (ssrc_ == ssrc) + return; + source_->Stop(media_channel_, ssrc_); + } + + ssrc_ = std::move(ssrc); + source_->Start(media_channel_, ssrc_); + if (ssrc_) { + media_channel_->SetBaseMinimumPlayoutDelayMs(*ssrc_, delay_.GetMs()); + } + + Reconfigure(track_enabled); +} + +void AudioRtpReceiver::SetupMediaChannel(uint32_t ssrc) { + RTC_DCHECK_RUN_ON(&signaling_thread_checker_); + RestartMediaChannel(ssrc); +} + +void AudioRtpReceiver::SetupUnsignaledMediaChannel() { + RTC_DCHECK_RUN_ON(&signaling_thread_checker_); + RestartMediaChannel(absl::nullopt); +} + +uint32_t AudioRtpReceiver::ssrc() const { + RTC_DCHECK_RUN_ON(worker_thread_); + return ssrc_.value_or(0); +} + +void AudioRtpReceiver::set_stream_ids(std::vector<std::string> stream_ids) { + RTC_DCHECK_RUN_ON(&signaling_thread_checker_); + SetStreams(CreateStreamsFromIds(std::move(stream_ids))); +} + +void AudioRtpReceiver::set_transport( + rtc::scoped_refptr<DtlsTransportInterface> dtls_transport) { + RTC_DCHECK_RUN_ON(&signaling_thread_checker_); + dtls_transport_ = std::move(dtls_transport); +} + +void AudioRtpReceiver::SetStreams( + const std::vector<rtc::scoped_refptr<MediaStreamInterface>>& streams) { + RTC_DCHECK_RUN_ON(&signaling_thread_checker_); + // Remove remote track from any streams that are going away. + for (const auto& existing_stream : streams_) { + bool removed = true; + for (const auto& stream : streams) { + if (existing_stream->id() == stream->id()) { + RTC_DCHECK_EQ(existing_stream.get(), stream.get()); + removed = false; + break; + } + } + if (removed) { + existing_stream->RemoveTrack(audio_track()); + } + } + // Add remote track to any streams that are new. + for (const auto& stream : streams) { + bool added = true; + for (const auto& existing_stream : streams_) { + if (stream->id() == existing_stream->id()) { + RTC_DCHECK_EQ(stream.get(), existing_stream.get()); + added = false; + break; + } + } + if (added) { + stream->AddTrack(audio_track()); + } + } + streams_ = streams; +} + +std::vector<RtpSource> AudioRtpReceiver::GetSources() const { + RTC_DCHECK_RUN_ON(worker_thread_); + if (!media_channel_ || !ssrc_) { + return {}; + } + return media_channel_->GetSources(*ssrc_); +} + +void AudioRtpReceiver::SetDepacketizerToDecoderFrameTransformer( + rtc::scoped_refptr<webrtc::FrameTransformerInterface> frame_transformer) { + RTC_DCHECK_RUN_ON(worker_thread_); + if (media_channel_) { + media_channel_->SetDepacketizerToDecoderFrameTransformer(ssrc_.value_or(0), + frame_transformer); + } + frame_transformer_ = std::move(frame_transformer); +} + +void AudioRtpReceiver::Reconfigure(bool track_enabled) { + RTC_DCHECK_RUN_ON(worker_thread_); + RTC_DCHECK(media_channel_); + + SetOutputVolume_w(track_enabled ? cached_volume_ : 0); + + if (ssrc_ && frame_decryptor_) { + // Reattach the frame decryptor if we were reconfigured. + media_channel_->SetFrameDecryptor(*ssrc_, frame_decryptor_); + } + + if (frame_transformer_) { + media_channel_->SetDepacketizerToDecoderFrameTransformer( + ssrc_.value_or(0), frame_transformer_); + } +} + +void AudioRtpReceiver::SetObserver(RtpReceiverObserverInterface* observer) { + RTC_DCHECK_RUN_ON(&signaling_thread_checker_); + observer_ = observer; + // Deliver any notifications the observer may have missed by being set late. + if (received_first_packet_ && observer_) { + observer_->OnFirstPacketReceived(media_type()); + } +} + +void AudioRtpReceiver::SetJitterBufferMinimumDelay( + absl::optional<double> delay_seconds) { + RTC_DCHECK_RUN_ON(worker_thread_); + delay_.Set(delay_seconds); + if (media_channel_ && ssrc_) + media_channel_->SetBaseMinimumPlayoutDelayMs(*ssrc_, delay_.GetMs()); +} + +void AudioRtpReceiver::SetMediaChannel(cricket::MediaChannel* media_channel) { + RTC_DCHECK_RUN_ON(worker_thread_); + RTC_DCHECK(media_channel == nullptr || + media_channel->media_type() == media_type()); + if (!media_channel && media_channel_) + SetOutputVolume_w(0.0); + + media_channel ? worker_thread_safety_->SetAlive() + : worker_thread_safety_->SetNotAlive(); + media_channel_ = static_cast<cricket::VoiceMediaChannel*>(media_channel); +} + +void AudioRtpReceiver::NotifyFirstPacketReceived() { + RTC_DCHECK_RUN_ON(&signaling_thread_checker_); + if (observer_) { + observer_->OnFirstPacketReceived(media_type()); + } + received_first_packet_ = true; +} + +} // namespace webrtc |