Prevent channels being set on stopped transceiver.
Fixing bug that allows a channel to be set on a stopped transceiver.
This CL contains the following refactoring:
1. Extracted ChannelInterface from BaseChannel
2. Unified SetXxxMediaChannel (Voice, Video) into SetMediaChannel
Bug: webrtc:9932
Change-Id: I2fbf00c823b7848ad4f2acb6e80b1b58ac45ee38
Reviewed-on: https://webrtc-review.googlesource.com/c/110564
Reviewed-by: Seth Hampson <shampson@webrtc.org>
Reviewed-by: Steve Anton <steveanton@webrtc.org>
Commit-Queue: Amit Hilbuch <amithi@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#25641}
diff --git a/media/base/mediachannel.cc b/media/base/mediachannel.cc
index a5dadd2..0634b2e 100644
--- a/media/base/mediachannel.cc
+++ b/media/base/mediachannel.cc
@@ -87,6 +87,10 @@
return params;
}
+cricket::MediaType VoiceMediaChannel::media_type() const {
+ return cricket::MediaType::MEDIA_TYPE_AUDIO;
+}
+
VideoSendParameters::VideoSendParameters() = default;
VideoSendParameters::~VideoSendParameters() = default;
@@ -96,11 +100,19 @@
return params;
}
+cricket::MediaType VideoMediaChannel::media_type() const {
+ return cricket::MediaType::MEDIA_TYPE_VIDEO;
+}
+
DataMediaChannel::DataMediaChannel() = default;
DataMediaChannel::DataMediaChannel(const MediaConfig& config)
: MediaChannel(config) {}
DataMediaChannel::~DataMediaChannel() = default;
+cricket::MediaType DataMediaChannel::media_type() const {
+ return cricket::MediaType::MEDIA_TYPE_DATA;
+}
+
bool DataMediaChannel::GetStats(DataMediaInfo* info) {
return true;
}
diff --git a/media/base/mediachannel.h b/media/base/mediachannel.h
index 69c7b00..108ae26 100644
--- a/media/base/mediachannel.h
+++ b/media/base/mediachannel.h
@@ -184,6 +184,8 @@
MediaChannel();
~MediaChannel() override;
+ virtual cricket::MediaType media_type() const = 0;
+
// Sets the abstract interface class for sending RTP/RTCP data and
// interface for media transport (experimental). If media transport is
// provided, it should be used instead of RTP/RTCP.
@@ -700,6 +702,8 @@
explicit VoiceMediaChannel(const MediaConfig& config)
: MediaChannel(config) {}
~VoiceMediaChannel() override {}
+
+ cricket::MediaType media_type() const override;
virtual bool SetSendParameters(const AudioSendParameters& params) = 0;
virtual bool SetRecvParameters(const AudioRecvParameters& params) = 0;
virtual webrtc::RtpParameters GetRtpSendParameters(uint32_t ssrc) const = 0;
@@ -772,6 +776,7 @@
: MediaChannel(config) {}
~VideoMediaChannel() override {}
+ cricket::MediaType media_type() const override;
virtual bool SetSendParameters(const VideoSendParameters& params) = 0;
virtual bool SetRecvParameters(const VideoRecvParameters& params) = 0;
virtual webrtc::RtpParameters GetRtpSendParameters(uint32_t ssrc) const = 0;
@@ -883,6 +888,7 @@
explicit DataMediaChannel(const MediaConfig& config);
~DataMediaChannel() override;
+ cricket::MediaType media_type() const override;
virtual bool SetSendParameters(const DataSendParameters& params) = 0;
virtual bool SetRecvParameters(const DataRecvParameters& params) = 0;
diff --git a/pc/BUILD.gn b/pc/BUILD.gn
index 97045ba..4be6052 100644
--- a/pc/BUILD.gn
+++ b/pc/BUILD.gn
@@ -31,6 +31,7 @@
sources = [
"channel.cc",
"channel.h",
+ "channelinterface.h",
"channelmanager.cc",
"channelmanager.h",
"dtlssrtptransport.cc",
@@ -380,6 +381,7 @@
"test/fakevideotrackrenderer.h",
"test/fakevideotracksource.h",
"test/framegeneratorcapturervideotracksource.h",
+ "test/mock_channelinterface.h",
"test/mock_datachannel.h",
"test/mock_rtpreceiverinternal.h",
"test/mock_rtpsenderinternal.h",
@@ -460,6 +462,7 @@
"rtpmediautils_unittest.cc",
"rtpparametersconversion_unittest.cc",
"rtpsenderreceiver_unittest.cc",
+ "rtptransceiver_unittest.cc",
"sctputils_unittest.cc",
"statscollector_unittest.cc",
"test/fakeaudiocapturemodule_unittest.cc",
diff --git a/pc/channel.cc b/pc/channel.cc
index 50fa567..0f857cd 100644
--- a/pc/channel.cc
+++ b/pc/channel.cc
@@ -702,7 +702,7 @@
break;
}
case MSG_FIRSTPACKETRECEIVED: {
- SignalFirstPacketReceived(this);
+ SignalFirstPacketReceived_(this);
break;
}
}
diff --git a/pc/channel.h b/pc/channel.h
index 65d6480..5644bb4 100644
--- a/pc/channel.h
+++ b/pc/channel.h
@@ -29,6 +29,7 @@
#include "media/base/streamparams.h"
#include "p2p/base/dtlstransportinternal.h"
#include "p2p/base/packettransportinternal.h"
+#include "pc/channelinterface.h"
#include "pc/dtlssrtptransport.h"
#include "pc/mediasession.h"
#include "pc/rtptransport.h"
@@ -48,7 +49,6 @@
namespace cricket {
struct CryptoParams;
-class MediaContentDescription;
// BaseChannel contains logic common to voice and video, including enable,
// marshaling calls to a worker and network threads, and connection and media
@@ -68,7 +68,8 @@
// vtable, and the media channel's thread using BaseChannel as the
// NetworkInterface.
-class BaseChannel : public rtc::MessageHandler,
+class BaseChannel : public ChannelInterface,
+ public rtc::MessageHandler,
public sigslot::has_slots<>,
public MediaChannel::NetworkInterface,
public webrtc::RtpPacketSinkInterface {
@@ -94,10 +95,10 @@
rtc::Thread* worker_thread() const { return worker_thread_; }
rtc::Thread* network_thread() const { return network_thread_; }
- const std::string& content_name() const { return content_name_; }
+ const std::string& content_name() const override { return content_name_; }
// TODO(deadbeef): This is redundant; remove this.
- const std::string& transport_name() const { return transport_name_; }
- bool enabled() const { return enabled_; }
+ const std::string& transport_name() const override { return transport_name_; }
+ bool enabled() const override { return enabled_; }
// This function returns true if using SRTP (DTLS-based keying or SDES).
bool srtp_active() const {
@@ -110,17 +111,17 @@
// 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);
+ bool SetRtpTransport(webrtc::RtpTransportInternal* rtp_transport) override;
// Channel control
bool SetLocalContent(const MediaContentDescription* content,
webrtc::SdpType type,
- std::string* error_desc);
+ std::string* error_desc) override;
bool SetRemoteContent(const MediaContentDescription* content,
webrtc::SdpType type,
- std::string* error_desc);
+ std::string* error_desc) override;
- bool Enable(bool enable);
+ bool Enable(bool enable) override;
// TODO(zhihuang): These methods are used for testing and can be removed.
bool AddRecvStream(const StreamParams& sp);
@@ -140,7 +141,9 @@
void SignalDtlsSrtpSetupFailure_s(bool rtcp);
// Used for latency measurements.
- sigslot::signal1<BaseChannel*> SignalFirstPacketReceived;
+ sigslot::signal1<ChannelInterface*>& SignalFirstPacketReceived() override {
+ return SignalFirstPacketReceived_;
+ }
// Forward SignalSentPacket to worker thread.
sigslot::signal1<const rtc::SentPacket&> SignalSentPacket;
@@ -176,8 +179,6 @@
int SetOption(SocketType type, rtc::Socket::Option o, int val) override;
int SetOption_n(SocketType type, rtc::Socket::Option o, int val);
- virtual cricket::MediaType media_type() = 0;
-
// RtpPacketSinkInterface overrides.
void OnRtpPacket(const webrtc::RtpPacketReceived& packet) override;
@@ -187,9 +188,9 @@
transport_name_ = transport_name;
}
- protected:
- virtual MediaChannel* media_channel() const { return media_channel_.get(); }
+ MediaChannel* media_channel() const override { return media_channel_.get(); }
+ protected:
bool was_ever_writable() const { return was_ever_writable_; }
void set_local_content_direction(webrtc::RtpTransceiverDirection direction) {
local_content_direction_ = direction;
@@ -306,6 +307,7 @@
rtc::Thread* const network_thread_;
rtc::Thread* const signaling_thread_;
rtc::AsyncInvoker invoker_;
+ sigslot::signal1<ChannelInterface*> SignalFirstPacketReceived_;
const std::string content_name_;
@@ -363,7 +365,9 @@
return static_cast<VoiceMediaChannel*>(BaseChannel::media_channel());
}
- cricket::MediaType media_type() override { return cricket::MEDIA_TYPE_AUDIO; }
+ cricket::MediaType media_type() const override {
+ return cricket::MEDIA_TYPE_AUDIO;
+ }
private:
// overrides from BaseChannel
@@ -402,7 +406,9 @@
void FillBitrateInfo(BandwidthEstimationInfo* bwe_info);
- cricket::MediaType media_type() override { return cricket::MEDIA_TYPE_VIDEO; }
+ cricket::MediaType media_type() const override {
+ return cricket::MEDIA_TYPE_VIDEO;
+ }
private:
// overrides from BaseChannel
@@ -454,7 +460,9 @@
// That occurs when the channel is enabled, the transport is writable,
// both local and remote descriptions are set, and the channel is unblocked.
sigslot::signal1<bool> SignalReadyToSendData;
- cricket::MediaType media_type() override { return cricket::MEDIA_TYPE_DATA; }
+ cricket::MediaType media_type() const override {
+ return cricket::MEDIA_TYPE_DATA;
+ }
protected:
// downcasts a MediaChannel.
diff --git a/pc/channelinterface.h b/pc/channelinterface.h
new file mode 100644
index 0000000..8e4109a
--- /dev/null
+++ b/pc/channelinterface.h
@@ -0,0 +1,68 @@
+/*
+ * Copyright 2018 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_CHANNELINTERFACE_H_
+#define PC_CHANNELINTERFACE_H_
+
+#include <string>
+
+#include "api/jsep.h"
+#include "api/mediatypes.h"
+#include "media/base/mediachannel.h"
+#include "pc/rtptransportinternal.h"
+
+namespace cricket {
+
+class MediaContentDescription;
+
+// ChannelInterface contains methods common to voice, video and data channels.
+// As more methods are added to BaseChannel, they should be included in the
+// interface as well.
+class ChannelInterface {
+ public:
+ virtual cricket::MediaType media_type() const = 0;
+
+ virtual MediaChannel* media_channel() const = 0;
+
+ // TODO(deadbeef): This is redundant; remove this.
+ virtual const std::string& transport_name() const = 0;
+
+ virtual const std::string& content_name() const = 0;
+
+ virtual bool enabled() const = 0;
+
+ // Enables or disables this channel
+ virtual bool Enable(bool enable) = 0;
+
+ // Used for latency measurements.
+ virtual sigslot::signal1<ChannelInterface*>& SignalFirstPacketReceived() = 0;
+
+ // Channel control
+ virtual bool SetLocalContent(const MediaContentDescription* content,
+ webrtc::SdpType type,
+ std::string* error_desc) = 0;
+ virtual bool SetRemoteContent(const MediaContentDescription* content,
+ webrtc::SdpType type,
+ std::string* error_desc) = 0;
+
+ // Set an RTP level transport.
+ // Some examples:
+ // * An RtpTransport without encryption.
+ // * An SrtpTransport for SDES.
+ // * A DtlsSrtpTransport for DTLS-SRTP.
+ virtual bool SetRtpTransport(webrtc::RtpTransportInternal* rtp_transport) = 0;
+
+ protected:
+ virtual ~ChannelInterface() = default;
+};
+
+} // namespace cricket
+
+#endif // PC_CHANNELINTERFACE_H_
diff --git a/pc/peerconnection.cc b/pc/peerconnection.cc
index 3fa5ca5..47ecb4e 100644
--- a/pc/peerconnection.cc
+++ b/pc/peerconnection.cc
@@ -1253,7 +1253,7 @@
auto new_sender =
CreateSender(media_type, track->id(), track, adjusted_stream_ids, {});
if (track->kind() == MediaStreamTrackInterface::kAudioKind) {
- new_sender->internal()->SetVoiceMediaChannel(voice_media_channel());
+ new_sender->internal()->SetMediaChannel(voice_media_channel());
GetAudioTransceiver()->internal()->AddSender(new_sender);
const RtpSenderInfo* sender_info =
FindSenderInfo(local_audio_sender_infos_,
@@ -1263,7 +1263,7 @@
}
} else {
RTC_DCHECK_EQ(MediaStreamTrackInterface::kVideoKind, track->kind());
- new_sender->internal()->SetVideoMediaChannel(video_media_channel());
+ new_sender->internal()->SetMediaChannel(video_media_channel());
GetVideoTransceiver()->internal()->AddSender(new_sender);
const RtpSenderInfo* sender_info =
FindSenderInfo(local_video_sender_infos_,
@@ -1593,14 +1593,14 @@
if (kind == MediaStreamTrackInterface::kAudioKind) {
auto* audio_sender = new AudioRtpSender(
worker_thread(), rtc::CreateRandomUuid(), stats_.get());
- audio_sender->SetVoiceMediaChannel(voice_media_channel());
+ audio_sender->SetMediaChannel(voice_media_channel());
new_sender = RtpSenderProxyWithInternal<RtpSenderInternal>::Create(
signaling_thread(), audio_sender);
GetAudioTransceiver()->internal()->AddSender(new_sender);
} else if (kind == MediaStreamTrackInterface::kVideoKind) {
auto* video_sender =
new VideoRtpSender(worker_thread(), rtc::CreateRandomUuid());
- video_sender->SetVideoMediaChannel(video_media_channel());
+ video_sender->SetMediaChannel(video_media_channel());
new_sender = RtpSenderProxyWithInternal<RtpSenderInternal>::Create(
signaling_thread(), video_sender);
GetVideoTransceiver()->internal()->AddSender(new_sender);
@@ -2736,11 +2736,11 @@
const cricket::ContentGroup* bundle_group) {
RTC_DCHECK(IsUnifiedPlan());
RTC_DCHECK(transceiver);
- cricket::BaseChannel* channel = transceiver->internal()->channel();
+ cricket::ChannelInterface* channel = transceiver->internal()->channel();
if (content.rejected) {
if (channel) {
transceiver->internal()->SetChannel(nullptr);
- DestroyBaseChannel(channel);
+ DestroyChannelInterface(channel);
}
} else {
if (!channel) {
@@ -3482,7 +3482,7 @@
// the constructor taking stream IDs instead.
auto* audio_receiver = new AudioRtpReceiver(
worker_thread(), remote_sender_info.sender_id, streams);
- audio_receiver->SetVoiceMediaChannel(voice_media_channel());
+ audio_receiver->SetMediaChannel(voice_media_channel());
audio_receiver->SetupMediaChannel(remote_sender_info.first_ssrc);
auto receiver = RtpReceiverProxyWithInternal<RtpReceiverInternal>::Create(
signaling_thread(), audio_receiver);
@@ -3500,7 +3500,7 @@
// the constructor taking stream IDs instead.
auto* video_receiver = new VideoRtpReceiver(
worker_thread(), remote_sender_info.sender_id, streams);
- video_receiver->SetVideoMediaChannel(video_media_channel());
+ video_receiver->SetMediaChannel(video_media_channel());
video_receiver->SetupMediaChannel(remote_sender_info.first_ssrc);
auto receiver = RtpReceiverProxyWithInternal<RtpReceiverInternal>::Create(
signaling_thread(), video_receiver);
@@ -3543,7 +3543,7 @@
// Normal case; we've never seen this track before.
auto new_sender = CreateSender(cricket::MEDIA_TYPE_AUDIO, track->id(), track,
{stream->id()}, {});
- new_sender->internal()->SetVoiceMediaChannel(voice_media_channel());
+ new_sender->internal()->SetMediaChannel(voice_media_channel());
GetAudioTransceiver()->internal()->AddSender(new_sender);
// If the sender has already been configured in SDP, we call SetSsrc,
// which will connect the sender to the underlying transport. This can
@@ -3588,7 +3588,7 @@
// Normal case; we've never seen this track before.
auto new_sender = CreateSender(cricket::MEDIA_TYPE_VIDEO, track->id(), track,
{stream->id()}, {});
- new_sender->internal()->SetVideoMediaChannel(video_media_channel());
+ new_sender->internal()->SetMediaChannel(video_media_channel());
GetVideoTransceiver()->internal()->AddSender(new_sender);
const RtpSenderInfo* sender_info =
FindSenderInfo(local_video_sender_infos_, stream->id(), track->id());
@@ -4966,10 +4966,10 @@
}
}
-cricket::BaseChannel* PeerConnection::GetChannel(
+cricket::ChannelInterface* PeerConnection::GetChannel(
const std::string& content_name) {
for (auto transceiver : transceivers_) {
- cricket::BaseChannel* channel = transceiver->internal()->channel();
+ cricket::ChannelInterface* channel = transceiver->internal()->channel();
if (channel && channel->content_name() == content_name) {
return channel;
}
@@ -5086,7 +5086,7 @@
for (auto transceiver : transceivers_) {
const ContentInfo* content_info =
FindMediaSectionForTransceiver(transceiver, sdesc);
- cricket::BaseChannel* channel = transceiver->internal()->channel();
+ cricket::ChannelInterface* channel = transceiver->internal()->channel();
if (!channel || !content_info || content_info->rejected) {
continue;
}
@@ -5421,7 +5421,7 @@
const {
std::map<std::string, std::string> transport_names_by_mid;
for (auto transceiver : transceivers_) {
- cricket::BaseChannel* channel = transceiver->internal()->channel();
+ cricket::ChannelInterface* channel = transceiver->internal()->channel();
if (channel) {
transport_names_by_mid[channel->content_name()] =
channel->transport_name();
@@ -5598,7 +5598,7 @@
void PeerConnection::EnableSending() {
for (auto transceiver : transceivers_) {
- cricket::BaseChannel* channel = transceiver->internal()->channel();
+ cricket::ChannelInterface* channel = transceiver->internal()->channel();
if (channel && !channel->enabled()) {
channel->Enable(true);
}
@@ -6484,7 +6484,7 @@
const std::string PeerConnection::GetTransportName(
const std::string& content_name) {
- cricket::BaseChannel* channel = GetChannel(content_name);
+ cricket::ChannelInterface* channel = GetChannel(content_name);
if (channel) {
return channel->transport_name();
}
@@ -6503,17 +6503,17 @@
transceiver) {
RTC_DCHECK(transceiver);
- cricket::BaseChannel* channel = transceiver->internal()->channel();
+ cricket::ChannelInterface* channel = transceiver->internal()->channel();
if (channel) {
transceiver->internal()->SetChannel(nullptr);
- DestroyBaseChannel(channel);
+ DestroyChannelInterface(channel);
}
}
void PeerConnection::DestroyDataChannel() {
if (rtp_data_channel_) {
OnDataChannelDestroyed();
- DestroyBaseChannel(rtp_data_channel_);
+ DestroyChannelInterface(rtp_data_channel_);
rtp_data_channel_ = nullptr;
}
@@ -6538,7 +6538,8 @@
}
}
-void PeerConnection::DestroyBaseChannel(cricket::BaseChannel* channel) {
+void PeerConnection::DestroyChannelInterface(
+ cricket::ChannelInterface* channel) {
RTC_DCHECK(channel);
switch (channel->media_type()) {
case cricket::MEDIA_TYPE_AUDIO:
diff --git a/pc/peerconnection.h b/pc/peerconnection.h
index fe4d777..b5ae9d2 100644
--- a/pc/peerconnection.h
+++ b/pc/peerconnection.h
@@ -719,7 +719,7 @@
SessionError session_error() const { return session_error_; }
const std::string& session_error_desc() const { return session_error_desc_; }
- cricket::BaseChannel* GetChannel(const std::string& content_name);
+ cricket::ChannelInterface* GetChannel(const std::string& content_name);
// Get current SSL role used by SCTP's underlying transport.
bool GetSctpSslRole(rtc::SSLRole* role);
@@ -922,9 +922,9 @@
// Destroys the RTP data channel and/or the SCTP data channel and clears it.
void DestroyDataChannel();
- // Destroys the given BaseChannel. The channel cannot be accessed after this
- // method is called.
- void DestroyBaseChannel(cricket::BaseChannel* channel);
+ // Destroys the given ChannelInterface.
+ // The channel cannot be accessed after this method is called.
+ void DestroyChannelInterface(cricket::ChannelInterface* channel);
// JsepTransportController::Observer override.
//
diff --git a/pc/peerconnection_ice_unittest.cc b/pc/peerconnection_ice_unittest.cc
index 8fde875..e015abf 100644
--- a/pc/peerconnection_ice_unittest.cc
+++ b/pc/peerconnection_ice_unittest.cc
@@ -212,7 +212,12 @@
PeerConnection* pc = static_cast<PeerConnection*>(pc_proxy->internal());
for (auto transceiver : pc->GetTransceiversInternal()) {
if (transceiver->media_type() == cricket::MEDIA_TYPE_AUDIO) {
- cricket::BaseChannel* channel = transceiver->internal()->channel();
+ // TODO(amithi): This test seems to be using a method that should not
+ // be public |rtp_packet_transport|. Because the test is not mocking
+ // the channels or transceiver, workaround will be to |static_cast|
+ // the channel until the method is rewritten.
+ cricket::BaseChannel* channel = static_cast<cricket::BaseChannel*>(
+ transceiver->internal()->channel());
if (channel) {
auto dtls_transport = static_cast<cricket::DtlsTransportInternal*>(
channel->rtp_packet_transport());
diff --git a/pc/rtcstatscollector.cc b/pc/rtcstatscollector.cc
index 32e0b65..871cff9 100644
--- a/pc/rtcstatscollector.cc
+++ b/pc/rtcstatscollector.cc
@@ -1426,7 +1426,7 @@
stats.transceiver = transceiver->internal();
stats.media_type = media_type;
- cricket::BaseChannel* channel = transceiver->internal()->channel();
+ cricket::ChannelInterface* channel = transceiver->internal()->channel();
if (!channel) {
// The remaining fields require a BaseChannel.
continue;
diff --git a/pc/rtpreceiver.cc b/pc/rtpreceiver.cc
index acea930..1916a73 100644
--- a/pc/rtpreceiver.cc
+++ b/pc/rtpreceiver.cc
@@ -268,9 +268,10 @@
}
}
-void AudioRtpReceiver::SetVoiceMediaChannel(
- cricket::VoiceMediaChannel* voice_media_channel) {
- media_channel_ = voice_media_channel;
+void AudioRtpReceiver::SetMediaChannel(cricket::MediaChannel* media_channel) {
+ RTC_DCHECK(media_channel == nullptr ||
+ media_channel->media_type() == media_type());
+ media_channel_ = static_cast<cricket::VoiceMediaChannel*>(media_channel);
}
void AudioRtpReceiver::NotifyFirstPacketReceived() {
@@ -443,9 +444,10 @@
}
}
-void VideoRtpReceiver::SetVideoMediaChannel(
- cricket::VideoMediaChannel* video_media_channel) {
- media_channel_ = video_media_channel;
+void VideoRtpReceiver::SetMediaChannel(cricket::MediaChannel* media_channel) {
+ RTC_DCHECK(media_channel == nullptr ||
+ media_channel->media_type() == media_type());
+ media_channel_ = static_cast<cricket::VideoMediaChannel*>(media_channel);
}
void VideoRtpReceiver::NotifyFirstPacketReceived() {
diff --git a/pc/rtpreceiver.h b/pc/rtpreceiver.h
index 85be8c2..06331a6 100644
--- a/pc/rtpreceiver.h
+++ b/pc/rtpreceiver.h
@@ -34,14 +34,10 @@
virtual void Stop() = 0;
// Sets the underlying MediaEngine channel associated with this RtpSender.
- // SetVoiceMediaChannel should be used for audio RtpSenders and
- // SetVideoMediaChannel should be used for video RtpSenders. Must call the
- // appropriate SetXxxMediaChannel(nullptr) before the media channel is
- // destroyed.
- virtual void SetVoiceMediaChannel(
- cricket::VoiceMediaChannel* voice_media_channel) = 0;
- virtual void SetVideoMediaChannel(
- cricket::VideoMediaChannel* video_media_channel) = 0;
+ // 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(cricket::MediaChannel* media_channel) = 0;
// Configures the RtpReceiver with the underlying media channel, with the
// given SSRC as the stream identifier. If |ssrc| is 0, the receiver will
@@ -130,13 +126,8 @@
void SetStreams(const std::vector<rtc::scoped_refptr<MediaStreamInterface>>&
streams) override;
void SetObserver(RtpReceiverObserverInterface* observer) override;
- void SetVoiceMediaChannel(
- cricket::VoiceMediaChannel* voice_media_channel) override;
- void SetVideoMediaChannel(
- cricket::VideoMediaChannel* video_media_channel) override {
- RTC_NOTREACHED();
- }
+ void SetMediaChannel(cricket::MediaChannel* media_channel) override;
std::vector<RtpSource> GetSources() const override;
int AttachmentId() const override { return attachment_id_; }
@@ -217,13 +208,7 @@
void SetObserver(RtpReceiverObserverInterface* observer) override;
- void SetVoiceMediaChannel(
- cricket::VoiceMediaChannel* voice_media_channel) override {
- RTC_NOTREACHED();
- }
-
- void SetVideoMediaChannel(
- cricket::VideoMediaChannel* video_media_channel) override;
+ void SetMediaChannel(cricket::MediaChannel* media_channel) override;
int AttachmentId() const override { return attachment_id_; }
diff --git a/pc/rtpsender.cc b/pc/rtpsender.cc
index abd1748..76fdca6 100644
--- a/pc/rtpsender.cc
+++ b/pc/rtpsender.cc
@@ -386,9 +386,10 @@
stopped_ = true;
}
-void AudioRtpSender::SetVoiceMediaChannel(
- cricket::VoiceMediaChannel* voice_media_channel) {
- media_channel_ = voice_media_channel;
+void AudioRtpSender::SetMediaChannel(cricket::MediaChannel* media_channel) {
+ RTC_DCHECK(media_channel == nullptr ||
+ media_channel->media_type() == media_type());
+ media_channel_ = static_cast<cricket::VoiceMediaChannel*>(media_channel);
}
void AudioRtpSender::SetAudioSend() {
@@ -629,9 +630,10 @@
stopped_ = true;
}
-void VideoRtpSender::SetVideoMediaChannel(
- cricket::VideoMediaChannel* video_media_channel) {
- media_channel_ = video_media_channel;
+void VideoRtpSender::SetMediaChannel(cricket::MediaChannel* media_channel) {
+ RTC_DCHECK(media_channel == nullptr ||
+ media_channel->media_type() == media_type());
+ media_channel_ = static_cast<cricket::VideoMediaChannel*>(media_channel);
}
void VideoRtpSender::SetVideoSend() {
diff --git a/pc/rtpsender.h b/pc/rtpsender.h
index 2a8289f..07fae6b 100644
--- a/pc/rtpsender.h
+++ b/pc/rtpsender.h
@@ -36,14 +36,10 @@
class RtpSenderInternal : public RtpSenderInterface {
public:
// Sets the underlying MediaEngine channel associated with this RtpSender.
- // SetVoiceMediaChannel should be used for audio RtpSenders and
- // SetVideoMediaChannel should be used for video RtpSenders. Must call the
- // appropriate SetXxxMediaChannel(nullptr) before the media channel is
- // destroyed.
- virtual void SetVoiceMediaChannel(
- cricket::VoiceMediaChannel* voice_media_channel) = 0;
- virtual void SetVideoMediaChannel(
- cricket::VideoMediaChannel* video_media_channel) = 0;
+ // 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(cricket::MediaChannel* 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
@@ -156,13 +152,7 @@
int AttachmentId() const override { return attachment_id_; }
- void SetVoiceMediaChannel(
- cricket::VoiceMediaChannel* voice_media_channel) override;
-
- void SetVideoMediaChannel(
- cricket::VideoMediaChannel* video_media_channel) override {
- RTC_NOTREACHED();
- }
+ void SetMediaChannel(cricket::MediaChannel* media_channel) override;
private:
// TODO(nisse): Since SSRC == 0 is technically valid, figure out
@@ -253,13 +243,7 @@
void Stop() override;
int AttachmentId() const override { return attachment_id_; }
- void SetVoiceMediaChannel(
- cricket::VoiceMediaChannel* voice_media_channel) override {
- RTC_NOTREACHED();
- }
-
- void SetVideoMediaChannel(
- cricket::VideoMediaChannel* video_media_channel) override;
+ void SetMediaChannel(cricket::MediaChannel* media_channel) override;
private:
bool can_send_track() const { return track_ && ssrc_; }
diff --git a/pc/rtpsenderreceiver_unittest.cc b/pc/rtpsenderreceiver_unittest.cc
index fa42615..b5a513b 100644
--- a/pc/rtpsenderreceiver_unittest.cc
+++ b/pc/rtpsenderreceiver_unittest.cc
@@ -154,7 +154,7 @@
new AudioRtpSender(worker_thread_, audio_track_->id(), nullptr);
ASSERT_TRUE(audio_rtp_sender_->SetTrack(audio_track_));
audio_rtp_sender_->set_stream_ids({local_stream_->id()});
- audio_rtp_sender_->SetVoiceMediaChannel(voice_media_channel_);
+ audio_rtp_sender_->SetMediaChannel(voice_media_channel_);
audio_rtp_sender_->SetSsrc(kAudioSsrc);
audio_rtp_sender_->GetOnDestroyedSignal()->connect(
this, &RtpSenderReceiverTest::OnAudioSenderDestroyed);
@@ -163,7 +163,7 @@
void CreateAudioRtpSenderWithNoTrack() {
audio_rtp_sender_ = new AudioRtpSender(worker_thread_, /*id=*/"", nullptr);
- audio_rtp_sender_->SetVoiceMediaChannel(voice_media_channel_);
+ audio_rtp_sender_->SetMediaChannel(voice_media_channel_);
}
void OnAudioSenderDestroyed() { audio_sender_destroyed_signal_fired_ = true; }
@@ -191,13 +191,13 @@
video_rtp_sender_ = new VideoRtpSender(worker_thread_, video_track_->id());
ASSERT_TRUE(video_rtp_sender_->SetTrack(video_track_));
video_rtp_sender_->set_stream_ids({local_stream_->id()});
- video_rtp_sender_->SetVideoMediaChannel(video_media_channel_);
+ video_rtp_sender_->SetMediaChannel(video_media_channel_);
video_rtp_sender_->SetSsrc(ssrc);
VerifyVideoChannelInput(ssrc);
}
void CreateVideoRtpSenderWithNoTrack() {
video_rtp_sender_ = new VideoRtpSender(worker_thread_, /*id=*/"");
- video_rtp_sender_->SetVideoMediaChannel(video_media_channel_);
+ video_rtp_sender_->SetMediaChannel(video_media_channel_);
}
void DestroyAudioRtpSender() {
@@ -214,7 +214,7 @@
std::vector<rtc::scoped_refptr<MediaStreamInterface>> streams = {}) {
audio_rtp_receiver_ = new AudioRtpReceiver(
rtc::Thread::Current(), kAudioTrackId, std::move(streams));
- audio_rtp_receiver_->SetVoiceMediaChannel(voice_media_channel_);
+ audio_rtp_receiver_->SetMediaChannel(voice_media_channel_);
audio_rtp_receiver_->SetupMediaChannel(kAudioSsrc);
audio_track_ = audio_rtp_receiver_->audio_track();
VerifyVoiceChannelOutput();
@@ -224,7 +224,7 @@
std::vector<rtc::scoped_refptr<MediaStreamInterface>> streams = {}) {
video_rtp_receiver_ = new VideoRtpReceiver(
rtc::Thread::Current(), kVideoTrackId, std::move(streams));
- video_rtp_receiver_->SetVideoMediaChannel(video_media_channel_);
+ video_rtp_receiver_->SetMediaChannel(video_media_channel_);
video_rtp_receiver_->SetupMediaChannel(kVideoSsrc);
video_track_ = video_rtp_receiver_->video_track();
VerifyVideoChannelOutput();
@@ -664,7 +664,7 @@
cricket::StreamParams stream_params =
cricket::CreateSimStreamParams("cname", ssrcs);
voice_media_channel_->AddSendStream(stream_params);
- audio_rtp_sender_->SetVoiceMediaChannel(voice_media_channel_);
+ audio_rtp_sender_->SetMediaChannel(voice_media_channel_);
audio_rtp_sender_->SetSsrc(1);
params = audio_rtp_sender_->GetParameters();
@@ -903,7 +903,7 @@
cricket::StreamParams stream_params =
cricket::CreateSimStreamParams("cname", ssrcs);
video_media_channel_->AddSendStream(stream_params);
- video_rtp_sender_->SetVideoMediaChannel(video_media_channel_);
+ video_rtp_sender_->SetMediaChannel(video_media_channel_);
video_rtp_sender_->SetSsrc(kVideoSsrcSimulcast);
params = video_rtp_sender_->GetParameters();
@@ -938,7 +938,7 @@
cricket::StreamParams stream_params =
cricket::CreateSimStreamParams("cname", ssrcs);
video_media_channel_->AddSendStream(stream_params);
- video_rtp_sender_->SetVideoMediaChannel(video_media_channel_);
+ video_rtp_sender_->SetMediaChannel(video_media_channel_);
video_rtp_sender_->SetSsrc(kVideoSsrcSimulcast);
params = video_rtp_sender_->GetParameters();
@@ -1332,7 +1332,7 @@
video_rtp_sender_ = new VideoRtpSender(worker_thread_, video_track_->id());
ASSERT_TRUE(video_rtp_sender_->SetTrack(video_track_));
video_rtp_sender_->set_stream_ids({local_stream_->id()});
- video_rtp_sender_->SetVideoMediaChannel(video_media_channel_);
+ video_rtp_sender_->SetMediaChannel(video_media_channel_);
video_track_->set_enabled(true);
// Sender is not ready to send (no SSRC) so no option should have been set.
diff --git a/pc/rtptransceiver.cc b/pc/rtptransceiver.cc
index 0fe8ea6..8b56b8b 100644
--- a/pc/rtptransceiver.cc
+++ b/pc/rtptransceiver.cc
@@ -38,52 +38,45 @@
Stop();
}
-void RtpTransceiver::SetChannel(cricket::BaseChannel* channel) {
+void RtpTransceiver::SetChannel(cricket::ChannelInterface* channel) {
+ // Cannot set a non-null channel on a stopped transceiver.
+ if (stopped_ && channel) {
+ return;
+ }
+
if (channel) {
RTC_DCHECK_EQ(media_type(), channel->media_type());
}
if (channel_) {
- channel_->SignalFirstPacketReceived.disconnect(this);
+ channel_->SignalFirstPacketReceived().disconnect(this);
}
channel_ = channel;
if (channel_) {
- channel_->SignalFirstPacketReceived.connect(
+ channel_->SignalFirstPacketReceived().connect(
this, &RtpTransceiver::OnFirstPacketReceived);
}
for (auto sender : senders_) {
- if (media_type() == cricket::MEDIA_TYPE_AUDIO) {
- auto* voice_channel = static_cast<cricket::VoiceChannel*>(channel);
- sender->internal()->SetVoiceMediaChannel(
- voice_channel ? voice_channel->media_channel() : nullptr);
- } else {
- auto* video_channel = static_cast<cricket::VideoChannel*>(channel);
- sender->internal()->SetVideoMediaChannel(
- video_channel ? video_channel->media_channel() : nullptr);
- }
+ sender->internal()->SetMediaChannel(channel_ ? channel_->media_channel()
+ : nullptr);
}
for (auto receiver : receivers_) {
- if (!channel) {
+ if (!channel_) {
receiver->internal()->Stop();
}
- if (media_type() == cricket::MEDIA_TYPE_AUDIO) {
- auto* voice_channel = static_cast<cricket::VoiceChannel*>(channel);
- receiver->internal()->SetVoiceMediaChannel(
- voice_channel ? voice_channel->media_channel() : nullptr);
- } else {
- auto* video_channel = static_cast<cricket::VideoChannel*>(channel);
- receiver->internal()->SetVideoMediaChannel(
- video_channel ? video_channel->media_channel() : nullptr);
- }
+
+ receiver->internal()->SetMediaChannel(channel_ ? channel_->media_channel()
+ : nullptr);
}
}
void RtpTransceiver::AddSender(
rtc::scoped_refptr<RtpSenderProxyWithInternal<RtpSenderInternal>> sender) {
+ RTC_DCHECK(!stopped_);
RTC_DCHECK(!unified_plan_);
RTC_DCHECK(sender);
RTC_DCHECK_EQ(media_type(), sender->media_type());
@@ -109,6 +102,7 @@
void RtpTransceiver::AddReceiver(
rtc::scoped_refptr<RtpReceiverProxyWithInternal<RtpReceiverInternal>>
receiver) {
+ RTC_DCHECK(!stopped_);
RTC_DCHECK(!unified_plan_);
RTC_DCHECK(receiver);
RTC_DCHECK_EQ(media_type(), receiver->media_type());
@@ -152,7 +146,7 @@
return mid_;
}
-void RtpTransceiver::OnFirstPacketReceived(cricket::BaseChannel* channel) {
+void RtpTransceiver::OnFirstPacketReceived(cricket::ChannelInterface*) {
for (auto receiver : receivers_) {
receiver->internal()->NotifyFirstPacketReceived();
}
diff --git a/pc/rtptransceiver.h b/pc/rtptransceiver.h
index 3e0d433..07db196 100644
--- a/pc/rtptransceiver.h
+++ b/pc/rtptransceiver.h
@@ -70,11 +70,11 @@
// Returns the Voice/VideoChannel set for this transceiver. May be null if
// the transceiver is not in the currently set local/remote description.
- cricket::BaseChannel* channel() const { return channel_; }
+ cricket::ChannelInterface* channel() const { return channel_; }
// Sets the Voice/VideoChannel. The caller must pass in the correct channel
// implementation based on the type of the transceiver.
- void SetChannel(cricket::BaseChannel* channel);
+ void SetChannel(cricket::ChannelInterface* channel);
// Adds an RtpSender of the appropriate type to be owned by this transceiver.
// Must not be null.
@@ -177,7 +177,7 @@
void SetCodecPreferences(rtc::ArrayView<RtpCodecCapability> codecs) override;
private:
- void OnFirstPacketReceived(cricket::BaseChannel* channel);
+ void OnFirstPacketReceived(cricket::ChannelInterface* channel);
const bool unified_plan_;
const cricket::MediaType media_type_;
@@ -196,7 +196,7 @@
bool created_by_addtrack_ = false;
bool has_ever_been_used_to_send_ = false;
- cricket::BaseChannel* channel_ = nullptr;
+ cricket::ChannelInterface* channel_ = nullptr;
};
BEGIN_SIGNALING_PROXY_MAP(RtpTransceiver)
diff --git a/pc/rtptransceiver_unittest.cc b/pc/rtptransceiver_unittest.cc
new file mode 100644
index 0000000..b57d212
--- /dev/null
+++ b/pc/rtptransceiver_unittest.cc
@@ -0,0 +1,71 @@
+/*
+ * Copyright 2018 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 tests for |RtpTransceiver|.
+
+#include "pc/rtptransceiver.h"
+#include "rtc_base/gunit.h"
+#include "test/gmock.h"
+#include "test/mock_channelinterface.h"
+
+using ::testing::Return;
+using ::testing::ReturnRef;
+
+namespace webrtc {
+
+// Checks that a channel cannot be set on a stopped |RtpTransceiver|.
+TEST(RtpTransceiverTest, CannotSetChannelOnStoppedTransceiver) {
+ RtpTransceiver transceiver(cricket::MediaType::MEDIA_TYPE_AUDIO);
+ cricket::MockChannelInterface channel1;
+ sigslot::signal1<cricket::ChannelInterface*> signal;
+ EXPECT_CALL(channel1, media_type())
+ .WillRepeatedly(Return(cricket::MediaType::MEDIA_TYPE_AUDIO));
+ EXPECT_CALL(channel1, SignalFirstPacketReceived())
+ .WillRepeatedly(ReturnRef(signal));
+
+ transceiver.SetChannel(&channel1);
+ EXPECT_EQ(&channel1, transceiver.channel());
+
+ // Stop the transceiver.
+ transceiver.Stop();
+ EXPECT_EQ(&channel1, transceiver.channel());
+
+ cricket::MockChannelInterface channel2;
+ EXPECT_CALL(channel2, media_type())
+ .WillRepeatedly(Return(cricket::MediaType::MEDIA_TYPE_AUDIO));
+
+ // Channel can no longer be set, so this call should be a no-op.
+ transceiver.SetChannel(&channel2);
+ EXPECT_EQ(&channel1, transceiver.channel());
+}
+
+// Checks that a channel can be unset on a stopped |RtpTransceiver|
+TEST(RtpTransceiverTest, CanUnsetChannelOnStoppedTransceiver) {
+ RtpTransceiver transceiver(cricket::MediaType::MEDIA_TYPE_VIDEO);
+ cricket::MockChannelInterface channel;
+ sigslot::signal1<cricket::ChannelInterface*> signal;
+ EXPECT_CALL(channel, media_type())
+ .WillRepeatedly(Return(cricket::MediaType::MEDIA_TYPE_VIDEO));
+ EXPECT_CALL(channel, SignalFirstPacketReceived())
+ .WillRepeatedly(ReturnRef(signal));
+
+ transceiver.SetChannel(&channel);
+ EXPECT_EQ(&channel, transceiver.channel());
+
+ // Stop the transceiver.
+ transceiver.Stop();
+ EXPECT_EQ(&channel, transceiver.channel());
+
+ // Set the channel to |nullptr|.
+ transceiver.SetChannel(nullptr);
+ EXPECT_EQ(nullptr, transceiver.channel());
+}
+
+} // namespace webrtc
diff --git a/pc/test/mock_channelinterface.h b/pc/test/mock_channelinterface.h
new file mode 100644
index 0000000..4c32a8f
--- /dev/null
+++ b/pc/test/mock_channelinterface.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2018 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_TEST_MOCK_CHANNELINTERFACE_H_
+#define PC_TEST_MOCK_CHANNELINTERFACE_H_
+
+#include <string>
+
+#include "pc/channelinterface.h"
+#include "test/gmock.h"
+
+namespace cricket {
+
+// Mock class for BaseChannel.
+// Use this class in unit tests to avoid dependecy on a specific
+// implementation of BaseChannel.
+class MockChannelInterface : public cricket::ChannelInterface {
+ public:
+ MOCK_CONST_METHOD0(media_type, cricket::MediaType());
+ MOCK_CONST_METHOD0(media_channel, MediaChannel*());
+ MOCK_CONST_METHOD0(transport_name, const std::string&());
+ MOCK_CONST_METHOD0(content_name, const std::string&());
+ MOCK_CONST_METHOD0(enabled, bool());
+ MOCK_METHOD1(Enable, bool(bool));
+ MOCK_METHOD0(SignalFirstPacketReceived,
+ sigslot::signal1<ChannelInterface*>&());
+ MOCK_METHOD3(SetLocalContent,
+ bool(const cricket::MediaContentDescription*,
+ webrtc::SdpType,
+ std::string*));
+ MOCK_METHOD3(SetRemoteContent,
+ bool(const cricket::MediaContentDescription*,
+ webrtc::SdpType,
+ std::string*));
+ MOCK_METHOD1(SetRtpTransport, bool(webrtc::RtpTransportInternal*));
+};
+
+} // namespace cricket
+
+#endif // PC_TEST_MOCK_CHANNELINTERFACE_H_
diff --git a/pc/test/mock_rtpreceiverinternal.h b/pc/test/mock_rtpreceiverinternal.h
index 850d5a9..84b0d71 100644
--- a/pc/test/mock_rtpreceiverinternal.h
+++ b/pc/test/mock_rtpreceiverinternal.h
@@ -41,8 +41,7 @@
// RtpReceiverInternal methods.
MOCK_METHOD0(Stop, void());
- MOCK_METHOD1(SetVoiceMediaChannel, void(cricket::VoiceMediaChannel*));
- MOCK_METHOD1(SetVideoMediaChannel, void(cricket::VideoMediaChannel*));
+ MOCK_METHOD1(SetMediaChannel, void(cricket::MediaChannel*));
MOCK_METHOD1(SetupMediaChannel, void(uint32_t));
MOCK_CONST_METHOD0(ssrc, uint32_t());
MOCK_METHOD0(NotifyFirstPacketReceived, void());
diff --git a/pc/test/mock_rtpsenderinternal.h b/pc/test/mock_rtpsenderinternal.h
index 5e14f7a..dd4f694 100644
--- a/pc/test/mock_rtpsenderinternal.h
+++ b/pc/test/mock_rtpsenderinternal.h
@@ -39,8 +39,7 @@
rtc::scoped_refptr<FrameEncryptorInterface>());
// RtpSenderInternal methods.
- MOCK_METHOD1(SetVoiceMediaChannel, void(cricket::VoiceMediaChannel*));
- MOCK_METHOD1(SetVideoMediaChannel, void(cricket::VideoMediaChannel*));
+ MOCK_METHOD1(SetMediaChannel, void(cricket::MediaChannel*));
MOCK_METHOD1(SetSsrc, void(uint32_t));
MOCK_METHOD1(set_stream_ids, void(const std::vector<std::string>&));
MOCK_METHOD1(set_init_send_encodings,