/* * Copyright 2017 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/rtptransceiver.h" #include #include "pc/rtpmediautils.h" namespace webrtc { RtpTransceiver::RtpTransceiver(cricket::MediaType media_type) : unified_plan_(false), media_type_(media_type) { RTC_DCHECK(media_type == cricket::MEDIA_TYPE_AUDIO || media_type == cricket::MEDIA_TYPE_VIDEO); } RtpTransceiver::RtpTransceiver( rtc::scoped_refptr> sender, rtc::scoped_refptr> receiver) : unified_plan_(true), media_type_(sender->media_type()) { RTC_DCHECK(media_type_ == cricket::MEDIA_TYPE_AUDIO || media_type_ == cricket::MEDIA_TYPE_VIDEO); RTC_DCHECK_EQ(sender->media_type(), receiver->media_type()); senders_.push_back(sender); receivers_.push_back(receiver); } RtpTransceiver::~RtpTransceiver() { Stop(); } void RtpTransceiver::SetChannel(cricket::BaseChannel* channel) { if (channel) { RTC_DCHECK_EQ(media_type(), channel->media_type()); } if (channel_) { channel_->SignalFirstPacketReceived.disconnect(this); } channel_ = channel; if (channel_) { channel_->SignalFirstPacketReceived.connect( this, &RtpTransceiver::OnFirstPacketReceived); } for (auto sender : senders_) { if (media_type() == cricket::MEDIA_TYPE_AUDIO) { auto* voice_channel = static_cast(channel); sender->internal()->SetVoiceMediaChannel( voice_channel ? voice_channel->media_channel() : nullptr); } else { auto* video_channel = static_cast(channel); sender->internal()->SetVideoMediaChannel( video_channel ? video_channel->media_channel() : nullptr); } } for (auto receiver : receivers_) { if (!channel) { receiver->internal()->Stop(); } if (media_type() == cricket::MEDIA_TYPE_AUDIO) { auto* voice_channel = static_cast(channel); receiver->internal()->SetVoiceMediaChannel( voice_channel ? voice_channel->media_channel() : nullptr); } else { auto* video_channel = static_cast(channel); receiver->internal()->SetVideoMediaChannel( video_channel ? video_channel->media_channel() : nullptr); } } } void RtpTransceiver::AddSender( rtc::scoped_refptr> sender) { RTC_DCHECK(!unified_plan_); RTC_DCHECK(sender); RTC_DCHECK_EQ(media_type(), sender->media_type()); RTC_DCHECK(std::find(senders_.begin(), senders_.end(), sender) == senders_.end()); senders_.push_back(sender); } bool RtpTransceiver::RemoveSender(RtpSenderInterface* sender) { RTC_DCHECK(!unified_plan_); if (sender) { RTC_DCHECK_EQ(media_type(), sender->media_type()); } auto it = std::find(senders_.begin(), senders_.end(), sender); if (it == senders_.end()) { return false; } (*it)->internal()->Stop(); senders_.erase(it); return true; } void RtpTransceiver::AddReceiver( rtc::scoped_refptr> receiver) { RTC_DCHECK(!unified_plan_); RTC_DCHECK(receiver); RTC_DCHECK_EQ(media_type(), receiver->media_type()); RTC_DCHECK(std::find(receivers_.begin(), receivers_.end(), receiver) == receivers_.end()); receivers_.push_back(receiver); } bool RtpTransceiver::RemoveReceiver(RtpReceiverInterface* receiver) { RTC_DCHECK(!unified_plan_); if (receiver) { RTC_DCHECK_EQ(media_type(), receiver->media_type()); } auto it = std::find(receivers_.begin(), receivers_.end(), receiver); if (it == receivers_.end()) { return false; } (*it)->internal()->Stop(); receivers_.erase(it); return true; } rtc::scoped_refptr RtpTransceiver::sender_internal() const { RTC_DCHECK(unified_plan_); RTC_CHECK_EQ(1u, senders_.size()); return senders_[0]->internal(); } rtc::scoped_refptr RtpTransceiver::receiver_internal() const { RTC_DCHECK(unified_plan_); RTC_CHECK_EQ(1u, receivers_.size()); return receivers_[0]->internal(); } cricket::MediaType RtpTransceiver::media_type() const { return media_type_; } absl::optional RtpTransceiver::mid() const { return mid_; } void RtpTransceiver::OnFirstPacketReceived(cricket::BaseChannel* channel) { for (auto receiver : receivers_) { receiver->internal()->NotifyFirstPacketReceived(); } } rtc::scoped_refptr RtpTransceiver::sender() const { RTC_DCHECK(unified_plan_); RTC_CHECK_EQ(1u, senders_.size()); return senders_[0]; } rtc::scoped_refptr RtpTransceiver::receiver() const { RTC_DCHECK(unified_plan_); RTC_CHECK_EQ(1u, receivers_.size()); return receivers_[0]; } void RtpTransceiver::set_current_direction(RtpTransceiverDirection direction) { RTC_LOG(LS_INFO) << "Changing transceiver (MID=" << mid_.value_or("") << ") current direction from " << (current_direction_ ? RtpTransceiverDirectionToString( *current_direction_) : "") << " to " << RtpTransceiverDirectionToString(direction) << "."; current_direction_ = direction; if (RtpTransceiverDirectionHasSend(*current_direction_)) { has_ever_been_used_to_send_ = true; } } void RtpTransceiver::set_fired_direction(RtpTransceiverDirection direction) { fired_direction_ = direction; } bool RtpTransceiver::stopped() const { return stopped_; } RtpTransceiverDirection RtpTransceiver::direction() const { return direction_; } void RtpTransceiver::SetDirection(RtpTransceiverDirection new_direction) { if (stopped()) { return; } if (new_direction == direction_) { return; } direction_ = new_direction; SignalNegotiationNeeded(); } absl::optional RtpTransceiver::current_direction() const { return current_direction_; } absl::optional RtpTransceiver::fired_direction() const { return fired_direction_; } void RtpTransceiver::Stop() { for (auto sender : senders_) { sender->internal()->Stop(); } for (auto receiver : receivers_) { receiver->internal()->Stop(); } stopped_ = true; current_direction_ = absl::nullopt; } void RtpTransceiver::SetCodecPreferences( rtc::ArrayView codecs) { // TODO(steveanton): Implement this. RTC_NOTREACHED() << "Not implemented"; } } // namespace webrtc