Revert "Version 2 "Refactoring DataContentDescription class""

This reverts commit 14b2758726879d21671a21291dfed8fb4fd5c21c.

Reason for revert: Internal import failed.

Original change's description:
> Version 2 "Refactoring DataContentDescription class"
> 
> (substantial changes since version 1)
> 
> This CL splits the cricket::DataContentDescription class into
> two classes: cricket::RtpDataContentDescription (used for RTP data)
> and cricket::SctpDataContentDescription (used for SCTP only).
> 
> SctpDataContentDescription no longer inherits from
> MediaContentDescriptionImpl, and no longer contains "codecs".
> 
> Due to usage of internal interfaces by consumers, shimming the old
> DataContentDescription API is needed.
> 
> A new cricket::DataContentDescription class is defined, which is
> a shim over RtpDataContentDescription and SctpDataContentDescription.
> It exposes as little functionality as possible, but supports the
> concerned consumer's usage
> 
> Design document:
> https://docs.google.com/document/d/1H5LfQxJA2ikMWTQ8FZ3_GAmaXM7knfVQWiSz6ph8VQ0/edit#
> 
> Version 1 reviewed-on: https://webrtc-review.googlesource.com/c/src/+/132700
> 
> Bug: webrtc:10358
> Change-Id: Icf95fb7308244d6f2ebfdb403aaffc544e358580
> Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/133900
> Commit-Queue: Harald Alvestrand <hta@webrtc.org>
> Reviewed-by: Steve Anton <steveanton@webrtc.org>
> Cr-Commit-Position: refs/heads/master@{#27853}

TBR=danilchap@webrtc.org,steveanton@webrtc.org,kwiberg@webrtc.org,hbos@webrtc.org,hta@webrtc.org,shampson@webrtc.org

Change-Id: Ibc16ba14c1cbf50345a9b79151b79df140482539
No-Presubmit: true
No-Tree-Checks: true
No-Try: true
Bug: webrtc:10358
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/135280
Reviewed-by: Harald Alvestrand <hta@webrtc.org>
Commit-Queue: Harald Alvestrand <hta@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#27855}
This commit is contained in:
Harald Alvestrand 2019-05-05 19:00:00 +00:00 committed by Commit Bot
parent 4b831ac127
commit 141c0ad8ab
21 changed files with 492 additions and 1350 deletions

View File

@ -334,22 +334,22 @@ bool VideoCodec::ValidateCodecFormat() const {
return true;
}
RtpDataCodec::RtpDataCodec(int id, const std::string& name)
DataCodec::DataCodec(int id, const std::string& name)
: Codec(id, name, kDataCodecClockrate) {}
RtpDataCodec::RtpDataCodec() : Codec() {
DataCodec::DataCodec() : Codec() {
clockrate = kDataCodecClockrate;
}
RtpDataCodec::RtpDataCodec(const RtpDataCodec& c) = default;
RtpDataCodec::RtpDataCodec(RtpDataCodec&& c) = default;
RtpDataCodec& RtpDataCodec::operator=(const RtpDataCodec& c) = default;
RtpDataCodec& RtpDataCodec::operator=(RtpDataCodec&& c) = default;
DataCodec::DataCodec(const DataCodec& c) = default;
DataCodec::DataCodec(DataCodec&& c) = default;
DataCodec& DataCodec::operator=(const DataCodec& c) = default;
DataCodec& DataCodec::operator=(DataCodec&& c) = default;
std::string RtpDataCodec::ToString() const {
std::string DataCodec::ToString() const {
char buf[256];
rtc::SimpleStringBuilder sb(buf);
sb << "RtpDataCodec[" << id << ":" << name << "]";
sb << "DataCodec[" << id << ":" << name << "]";
return sb.str();
}

View File

@ -192,23 +192,19 @@ struct RTC_EXPORT VideoCodec : public Codec {
void SetDefaultParameters();
};
struct RtpDataCodec : public Codec {
RtpDataCodec(int id, const std::string& name);
RtpDataCodec();
RtpDataCodec(const RtpDataCodec& c);
RtpDataCodec(RtpDataCodec&& c);
~RtpDataCodec() override = default;
struct DataCodec : public Codec {
DataCodec(int id, const std::string& name);
DataCodec();
DataCodec(const DataCodec& c);
DataCodec(DataCodec&& c);
~DataCodec() override = default;
RtpDataCodec& operator=(const RtpDataCodec& c);
RtpDataCodec& operator=(RtpDataCodec&& c);
DataCodec& operator=(const DataCodec& c);
DataCodec& operator=(DataCodec&& c);
std::string ToString() const;
};
// For backwards compatibility
// TODO(bugs.webrtc.org/10597): Remove when no longer needed.
typedef RtpDataCodec DataCodec;
// Get the codec setting associated with |payload_type|. If there
// is no codec associated with that payload type it returns nullptr.
template <class Codec>

View File

@ -16,7 +16,6 @@
#include <string>
#include <vector>
#include "media/base/codec.h"
#include "media/base/media_channel.h"
#include "media/base/media_constants.h"
#include "media/base/media_engine.h"
@ -27,6 +26,8 @@ class DataRateLimiter;
namespace cricket {
struct DataCodec;
class RtpDataEngine : public DataEngineInterface {
public:
RtpDataEngine();

View File

@ -72,7 +72,6 @@ rtc_static_library("rtc_pc_base") {
]
deps = [
":media_protocol_names",
"../api:array_view",
"../api:audio_options_api",
"../api:call_api",
@ -122,13 +121,6 @@ rtc_source_set("rtc_pc") {
]
}
rtc_source_set("media_protocol_names") {
sources = [
"media_protocol_names.cc",
"media_protocol_names.h",
]
}
rtc_static_library("peerconnection") {
visibility = [ "*" ]
cflags = []

View File

@ -1143,7 +1143,7 @@ bool RtpDataChannel::SendData(const SendDataParams& params,
}
bool RtpDataChannel::CheckDataChannelTypeFromContent(
const RtpDataContentDescription* content,
const DataContentDescription* content,
std::string* error_desc) {
bool is_sctp = ((content->protocol() == kMediaProtocolSctp) ||
(content->protocol() == kMediaProtocolDtlsSctp));
@ -1169,7 +1169,7 @@ bool RtpDataChannel::SetLocalContent_w(const MediaContentDescription* content,
return false;
}
const RtpDataContentDescription* data = content->as_rtp_data();
const DataContentDescription* data = content->as_data();
if (!CheckDataChannelTypeFromContent(data, error_desc)) {
return false;
@ -1223,12 +1223,7 @@ bool RtpDataChannel::SetRemoteContent_w(const MediaContentDescription* content,
return false;
}
const RtpDataContentDescription* data = content->as_rtp_data();
if (!data) {
RTC_LOG(LS_INFO) << "Accepting and ignoring non-RTP content description";
return true;
}
const DataContentDescription* data = content->as_data();
// If the remote data doesn't have codecs, it must be empty, so ignore it.
if (!data->has_codecs()) {

View File

@ -518,7 +518,7 @@ class RtpDataChannel : public BaseChannel {
// overrides from BaseChannel
// Checks that data channel type is RTP.
bool CheckDataChannelTypeFromContent(const RtpDataContentDescription* content,
bool CheckDataChannelTypeFromContent(const DataContentDescription* content,
std::string* error_desc);
bool SetLocalContent_w(const MediaContentDescription* content,
webrtc::SdpType type,

View File

@ -94,8 +94,8 @@ class VideoTraits : public Traits<cricket::VideoChannel,
class DataTraits : public Traits<cricket::RtpDataChannel,
cricket::FakeDataMediaChannel,
cricket::RtpDataContentDescription,
cricket::RtpDataCodec,
cricket::DataContentDescription,
cricket::DataCodec,
cricket::DataMediaInfo,
cricket::DataOptions> {};
@ -2308,15 +2308,15 @@ void ChannelTest<DataTraits>::CreateContent(
int flags,
const cricket::AudioCodec& audio_codec,
const cricket::VideoCodec& video_codec,
cricket::RtpDataContentDescription* data) {
cricket::DataContentDescription* data) {
data->AddCodec(kGoogleDataCodec);
data->set_rtcp_mux((flags & RTCP_MUX) != 0);
}
template <>
void ChannelTest<DataTraits>::CopyContent(
const cricket::RtpDataContentDescription& source,
cricket::RtpDataContentDescription* data) {
const cricket::DataContentDescription& source,
cricket::DataContentDescription* data) {
*data = source;
}
@ -2330,7 +2330,7 @@ template <>
void ChannelTest<DataTraits>::AddLegacyStreamInContent(
uint32_t ssrc,
int flags,
cricket::RtpDataContentDescription* data) {
cricket::DataContentDescription* data) {
data->AddLegacyStream(ssrc);
}

View File

@ -175,9 +175,8 @@ class JsepTransportControllerTest : public JsepTransportController::Observer,
cricket::IceMode ice_mode,
cricket::ConnectionRole conn_role,
rtc::scoped_refptr<rtc::RTCCertificate> cert) {
RTC_CHECK(protocol_type == cricket::MediaProtocolType::kSctp);
std::unique_ptr<cricket::SctpDataContentDescription> data(
new cricket::SctpDataContentDescription());
std::unique_ptr<cricket::DataContentDescription> data(
new cricket::DataContentDescription());
data->set_rtcp_mux(true);
description->AddContent(mid, protocol_type,
/*rejected=*/false, data.release());

View File

@ -1,41 +0,0 @@
/*
* 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/media_protocol_names.h"
namespace cricket {
const char kMediaProtocolRtpPrefix[] = "RTP/";
const char kMediaProtocolSctp[] = "SCTP";
const char kMediaProtocolDtlsSctp[] = "DTLS/SCTP";
const char kMediaProtocolUdpDtlsSctp[] = "UDP/DTLS/SCTP";
const char kMediaProtocolTcpDtlsSctp[] = "TCP/DTLS/SCTP";
bool IsDtlsSctp(const std::string& protocol) {
return protocol == kMediaProtocolDtlsSctp ||
protocol == kMediaProtocolUdpDtlsSctp ||
protocol == kMediaProtocolTcpDtlsSctp;
}
bool IsPlainSctp(const std::string& protocol) {
return protocol == kMediaProtocolSctp;
}
bool IsRtpProtocol(const std::string& protocol) {
return protocol.empty() ||
(protocol.find(cricket::kMediaProtocolRtpPrefix) != std::string::npos);
}
bool IsSctpProtocol(const std::string& protocol) {
return IsPlainSctp(protocol) || IsDtlsSctp(protocol);
}
} // namespace cricket

View File

@ -1,35 +0,0 @@
/*
* 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.
*/
#ifndef PC_MEDIA_PROTOCOL_NAMES_H_
#define PC_MEDIA_PROTOCOL_NAMES_H_
#include <string>
namespace cricket {
// Names or name prefixes of protocols as defined by SDP specifications.
extern const char kMediaProtocolRtpPrefix[];
extern const char kMediaProtocolSctp[];
extern const char kMediaProtocolDtlsSctp[];
extern const char kMediaProtocolUdpDtlsSctp[];
extern const char kMediaProtocolTcpDtlsSctp[];
bool IsDtlsSctp(const std::string& protocol);
bool IsPlainSctp(const std::string& protocol);
// Returns true if the given media section protocol indicates use of RTP.
bool IsRtpProtocol(const std::string& protocol);
// Returns true if the given media section protocol indicates use of SCTP.
bool IsSctpProtocol(const std::string& protocol);
} // namespace cricket
#endif // PC_MEDIA_PROTOCOL_NAMES_H_

View File

@ -27,7 +27,6 @@
#include "media/base/media_constants.h"
#include "p2p/base/p2p_constants.h"
#include "pc/channel_manager.h"
#include "pc/media_protocol_names.h"
#include "pc/rtp_media_utils.h"
#include "pc/srtp_filter.h"
#include "rtc_base/checks.h"
@ -69,6 +68,13 @@ const char kMediaProtocolDtlsSavpf[] = "UDP/TLS/RTP/SAVPF";
// but we tolerate "RTP/SAVPF" in offers we receive, for compatibility.
const char kMediaProtocolSavpf[] = "RTP/SAVPF";
const char kMediaProtocolRtpPrefix[] = "RTP/";
const char kMediaProtocolSctp[] = "SCTP";
const char kMediaProtocolDtlsSctp[] = "DTLS/SCTP";
const char kMediaProtocolUdpDtlsSctp[] = "UDP/DTLS/SCTP";
const char kMediaProtocolTcpDtlsSctp[] = "TCP/DTLS/SCTP";
// Note that the below functions support some protocol strings purely for
// legacy compatibility, as required by JSEP in Section 5.1.2, Profile Names
// and Interoperability.
@ -85,6 +91,20 @@ static bool IsPlainRtp(const std::string& protocol) {
protocol == "RTP/SAVP" || protocol == "RTP/AVP";
}
static bool IsDtlsSctp(const std::string& protocol) {
return protocol == kMediaProtocolDtlsSctp ||
protocol == kMediaProtocolUdpDtlsSctp ||
protocol == kMediaProtocolTcpDtlsSctp;
}
static bool IsPlainSctp(const std::string& protocol) {
return protocol == kMediaProtocolSctp;
}
static bool IsSctp(const std::string& protocol) {
return IsPlainSctp(protocol) || IsDtlsSctp(protocol);
}
static RtpTransceiverDirection NegotiateRtpTransceiverDirection(
RtpTransceiverDirection offer,
RtpTransceiverDirection wants) {
@ -469,7 +489,7 @@ static bool AddStreamParams(
StreamParamsVec* current_streams,
MediaContentDescriptionImpl<C>* content_description) {
// SCTP streams are not negotiated using SDP/ContentDescriptions.
if (IsSctpProtocol(content_description->protocol())) {
if (IsSctp(content_description->protocol())) {
return true;
}
@ -588,6 +608,11 @@ static void PruneCryptos(const CryptoParamsVec& filter,
target_cryptos->end());
}
bool IsRtpProtocol(const std::string& protocol) {
return protocol.empty() ||
(protocol.find(cricket::kMediaProtocolRtpPrefix) != std::string::npos);
}
static bool IsRtpContent(SessionDescription* sdesc,
const std::string& content_name) {
bool is_rtp = false;
@ -716,22 +741,32 @@ static bool IsFlexfecCodec(const C& codec) {
// crypto (in current_cryptos) and it is enabled (in secure_policy), crypto is
// created (according to crypto_suites). The created content is added to the
// offer.
static bool CreateContentOffer(
template <class C>
static bool CreateMediaContentOffer(
const MediaDescriptionOptions& media_description_options,
const MediaSessionOptions& session_options,
const std::vector<C>& codecs,
const SecurePolicy& secure_policy,
const CryptoParamsVec* current_cryptos,
const std::vector<std::string>& crypto_suites,
const RtpHeaderExtensions& rtp_extensions,
UniqueRandomIdGenerator* ssrc_generator,
StreamParamsVec* current_streams,
MediaContentDescription* offer) {
MediaContentDescriptionImpl<C>* offer) {
offer->AddCodecs(codecs);
offer->set_rtcp_mux(session_options.rtcp_mux_enabled);
if (offer->type() == cricket::MEDIA_TYPE_VIDEO) {
offer->set_rtcp_reduced_size(true);
}
offer->set_rtp_header_extensions(rtp_extensions);
if (!AddStreamParams(media_description_options.sender_options,
session_options.rtcp_cname, ssrc_generator,
current_streams, offer)) {
return false;
}
AddSimulcastToMediaDescription(media_description_options, offer);
if (secure_policy != SEC_DISABLED) {
@ -750,30 +785,6 @@ static bool CreateContentOffer(
}
return true;
}
template <class C>
static bool CreateMediaContentOffer(
const MediaDescriptionOptions& media_description_options,
const MediaSessionOptions& session_options,
const std::vector<C>& codecs,
const SecurePolicy& secure_policy,
const CryptoParamsVec* current_cryptos,
const std::vector<std::string>& crypto_suites,
const RtpHeaderExtensions& rtp_extensions,
UniqueRandomIdGenerator* ssrc_generator,
StreamParamsVec* current_streams,
MediaContentDescriptionImpl<C>* offer) {
offer->AddCodecs(codecs);
if (!AddStreamParams(media_description_options.sender_options,
session_options.rtcp_cname, ssrc_generator,
current_streams, offer)) {
return false;
}
return CreateContentOffer(media_description_options, session_options,
secure_policy, current_cryptos, crypto_suites,
rtp_extensions, ssrc_generator, current_streams,
offer);
}
template <class C>
static bool ReferencedCodecsMatch(const std::vector<C>& codecs1,
@ -1175,28 +1186,6 @@ static void StripCNCodecs(AudioCodecs* audio_codecs) {
audio_codecs->end());
}
template <class C>
static bool SetCodecsInAnswer(
const MediaContentDescriptionImpl<C>* offer,
const std::vector<C>& local_codecs,
const MediaDescriptionOptions& media_description_options,
const MediaSessionOptions& session_options,
UniqueRandomIdGenerator* ssrc_generator,
StreamParamsVec* current_streams,
MediaContentDescriptionImpl<C>* answer) {
std::vector<C> negotiated_codecs;
NegotiateCodecs(local_codecs, offer->codecs(), &negotiated_codecs,
media_description_options.codec_preferences.empty());
answer->AddCodecs(negotiated_codecs);
answer->set_protocol(offer->protocol());
if (!AddStreamParams(media_description_options.sender_options,
session_options.rtcp_cname, ssrc_generator,
current_streams, answer)) {
return false; // Something went seriously wrong.
}
return true;
}
// Create a media content to be answered for the given |sender_options|
// according to the given session_options.rtcp_mux, session_options.streams,
// codecs, crypto, and current_streams. If we don't currently have crypto (in
@ -1204,10 +1193,12 @@ static bool SetCodecsInAnswer(
// (according to crypto_suites). The codecs, rtcp_mux, and crypto are all
// negotiated with the offer. If the negotiation fails, this method returns
// false. The created content is added to the offer.
template <class C>
static bool CreateMediaContentAnswer(
const MediaContentDescription* offer,
const MediaContentDescriptionImpl<C>* offer,
const MediaDescriptionOptions& media_description_options,
const MediaSessionOptions& session_options,
const std::vector<C>& local_codecs,
const SecurePolicy& sdes_policy,
const CryptoParamsVec* current_cryptos,
const RtpHeaderExtensions& local_rtp_extenstions,
@ -1215,7 +1206,13 @@ static bool CreateMediaContentAnswer(
bool enable_encrypted_rtp_header_extensions,
StreamParamsVec* current_streams,
bool bundle_enabled,
MediaContentDescription* answer) {
MediaContentDescriptionImpl<C>* answer) {
std::vector<C> negotiated_codecs;
NegotiateCodecs(local_codecs, offer->codecs(), &negotiated_codecs,
media_description_options.codec_preferences.empty());
answer->AddCodecs(negotiated_codecs);
answer->set_protocol(offer->protocol());
answer->set_extmap_allow_mixed_enum(offer->extmap_allow_mixed_enum());
RtpHeaderExtensions negotiated_rtp_extensions;
NegotiateRtpHeaderExtensions(
@ -1243,6 +1240,12 @@ static bool CreateMediaContentAnswer(
return false;
}
if (!AddStreamParams(media_description_options.sender_options,
session_options.rtcp_cname, ssrc_generator,
current_streams, answer)) {
return false; // Something went seriously wrong.
}
AddSimulcastToMediaDescription(media_description_options, answer);
answer->set_direction(NegotiateRtpTransceiverDirection(
@ -1394,7 +1397,7 @@ MediaSessionDescriptionFactory::MediaSessionDescriptionFactory(
channel_manager->GetSupportedAudioRtpHeaderExtensions(&audio_rtp_extensions_);
channel_manager->GetSupportedVideoCodecs(&video_codecs_);
channel_manager->GetSupportedVideoRtpHeaderExtensions(&video_rtp_extensions_);
channel_manager->GetSupportedDataCodecs(&rtp_data_codecs_);
channel_manager->GetSupportedDataCodecs(&data_codecs_);
ComputeAudioCodecsIntersectionAndUnion();
}
@ -1481,15 +1484,15 @@ std::unique_ptr<SessionDescription> MediaSessionDescriptionFactory::CreateOffer(
AudioCodecs offer_audio_codecs;
VideoCodecs offer_video_codecs;
RtpDataCodecs offer_rtp_data_codecs;
DataCodecs offer_data_codecs;
GetCodecsForOffer(current_active_contents, &offer_audio_codecs,
&offer_video_codecs, &offer_rtp_data_codecs);
&offer_video_codecs, &offer_data_codecs);
if (!session_options.vad_enabled) {
// If application doesn't want CN codecs in offer.
StripCNCodecs(&offer_audio_codecs);
}
FilterDataCodecs(&offer_rtp_data_codecs,
FilterDataCodecs(&offer_data_codecs,
session_options.data_channel_type == DCT_SCTP);
RtpHeaderExtensions audio_rtp_extensions;
@ -1533,7 +1536,7 @@ std::unique_ptr<SessionDescription> MediaSessionDescriptionFactory::CreateOffer(
case MEDIA_TYPE_DATA:
if (!AddDataContentForOffer(media_description_options, session_options,
current_content, current_description,
offer_rtp_data_codecs, &current_streams,
offer_data_codecs, &current_streams,
offer.get(), &ice_credentials)) {
return nullptr;
}
@ -1631,15 +1634,15 @@ MediaSessionDescriptionFactory::CreateAnswer(
// sections.
AudioCodecs answer_audio_codecs;
VideoCodecs answer_video_codecs;
RtpDataCodecs answer_rtp_data_codecs;
DataCodecs answer_data_codecs;
GetCodecsForAnswer(current_active_contents, *offer, &answer_audio_codecs,
&answer_video_codecs, &answer_rtp_data_codecs);
&answer_video_codecs, &answer_data_codecs);
if (!session_options.vad_enabled) {
// If application doesn't want CN codecs in answer.
StripCNCodecs(&answer_audio_codecs);
}
FilterDataCodecs(&answer_rtp_data_codecs,
FilterDataCodecs(&answer_data_codecs,
session_options.data_channel_type == DCT_SCTP);
auto answer = absl::make_unique<SessionDescription>();
@ -1692,8 +1695,8 @@ MediaSessionDescriptionFactory::CreateAnswer(
if (!AddDataContentForAnswer(
media_description_options, session_options, offer_content,
offer, current_content, current_description,
bundle_transport.get(), answer_rtp_data_codecs,
&current_streams, answer.get(), &ice_credentials)) {
bundle_transport.get(), answer_data_codecs, &current_streams,
answer.get(), &ice_credentials)) {
return nullptr;
}
break;
@ -1813,7 +1816,7 @@ void MergeCodecsFromDescription(
const std::vector<const ContentInfo*>& current_active_contents,
AudioCodecs* audio_codecs,
VideoCodecs* video_codecs,
RtpDataCodecs* rtp_data_codecs,
DataCodecs* data_codecs,
UsedPayloadTypes* used_pltypes) {
for (const ContentInfo* content : current_active_contents) {
if (IsMediaContentOfType(content, MEDIA_TYPE_AUDIO)) {
@ -1825,13 +1828,9 @@ void MergeCodecsFromDescription(
content->media_description()->as_video();
MergeCodecs<VideoCodec>(video->codecs(), video_codecs, used_pltypes);
} else if (IsMediaContentOfType(content, MEDIA_TYPE_DATA)) {
const RtpDataContentDescription* data =
content->media_description()->as_rtp_data();
if (data) {
// Only relevant for RTP datachannels
MergeCodecs<RtpDataCodec>(data->codecs(), rtp_data_codecs,
used_pltypes);
}
const DataContentDescription* data =
content->media_description()->as_data();
MergeCodecs<DataCodec>(data->codecs(), data_codecs, used_pltypes);
}
}
}
@ -1846,18 +1845,18 @@ void MediaSessionDescriptionFactory::GetCodecsForOffer(
const std::vector<const ContentInfo*>& current_active_contents,
AudioCodecs* audio_codecs,
VideoCodecs* video_codecs,
RtpDataCodecs* rtp_data_codecs) const {
DataCodecs* data_codecs) const {
// First - get all codecs from the current description if the media type
// is used. Add them to |used_pltypes| so the payload type is not reused if a
// new media type is added.
UsedPayloadTypes used_pltypes;
MergeCodecsFromDescription(current_active_contents, audio_codecs,
video_codecs, rtp_data_codecs, &used_pltypes);
video_codecs, data_codecs, &used_pltypes);
// Add our codecs that are not in the current description.
MergeCodecs<AudioCodec>(all_audio_codecs_, audio_codecs, &used_pltypes);
MergeCodecs<VideoCodec>(video_codecs_, video_codecs, &used_pltypes);
MergeCodecs<DataCodec>(rtp_data_codecs_, rtp_data_codecs, &used_pltypes);
MergeCodecs<DataCodec>(data_codecs_, data_codecs, &used_pltypes);
}
// Getting codecs for an answer involves these steps:
@ -1872,18 +1871,18 @@ void MediaSessionDescriptionFactory::GetCodecsForAnswer(
const SessionDescription& remote_offer,
AudioCodecs* audio_codecs,
VideoCodecs* video_codecs,
RtpDataCodecs* rtp_data_codecs) const {
DataCodecs* data_codecs) const {
// First - get all codecs from the current description if the media type
// is used. Add them to |used_pltypes| so the payload type is not reused if a
// new media type is added.
UsedPayloadTypes used_pltypes;
MergeCodecsFromDescription(current_active_contents, audio_codecs,
video_codecs, rtp_data_codecs, &used_pltypes);
video_codecs, data_codecs, &used_pltypes);
// Second - filter out codecs that we don't support at all and should ignore.
AudioCodecs filtered_offered_audio_codecs;
VideoCodecs filtered_offered_video_codecs;
RtpDataCodecs filtered_offered_rtp_data_codecs;
DataCodecs filtered_offered_data_codecs;
for (const ContentInfo& content : remote_offer.contents()) {
if (IsMediaContentOfType(&content, MEDIA_TYPE_AUDIO)) {
const AudioContentDescription* audio =
@ -1910,19 +1909,15 @@ void MediaSessionDescriptionFactory::GetCodecsForAnswer(
}
}
} else if (IsMediaContentOfType(&content, MEDIA_TYPE_DATA)) {
const RtpDataContentDescription* data =
content.media_description()->as_rtp_data();
if (data) {
// RTP data. This part is inactive for SCTP data.
for (const RtpDataCodec& offered_rtp_data_codec : data->codecs()) {
if (!FindMatchingCodec<RtpDataCodec>(
data->codecs(), filtered_offered_rtp_data_codecs,
offered_rtp_data_codec, nullptr) &&
FindMatchingCodec<RtpDataCodec>(data->codecs(), rtp_data_codecs_,
offered_rtp_data_codec,
nullptr)) {
filtered_offered_rtp_data_codecs.push_back(offered_rtp_data_codec);
}
const DataContentDescription* data =
content.media_description()->as_data();
for (const DataCodec& offered_data_codec : data->codecs()) {
if (!FindMatchingCodec<DataCodec>(data->codecs(),
filtered_offered_data_codecs,
offered_data_codec, nullptr) &&
FindMatchingCodec<DataCodec>(data->codecs(), data_codecs_,
offered_data_codec, nullptr)) {
filtered_offered_data_codecs.push_back(offered_data_codec);
}
}
}
@ -1934,7 +1929,7 @@ void MediaSessionDescriptionFactory::GetCodecsForAnswer(
&used_pltypes);
MergeCodecs<VideoCodec>(filtered_offered_video_codecs, video_codecs,
&used_pltypes);
MergeCodecs<DataCodec>(filtered_offered_rtp_data_codecs, rtp_data_codecs,
MergeCodecs<DataCodec>(filtered_offered_data_codecs, data_codecs,
&used_pltypes);
}
@ -2211,101 +2206,18 @@ bool MediaSessionDescriptionFactory::AddVideoContentForOffer(
return true;
}
bool MediaSessionDescriptionFactory::AddSctpDataContentForOffer(
const MediaDescriptionOptions& media_description_options,
const MediaSessionOptions& session_options,
const ContentInfo* current_content,
const SessionDescription* current_description,
StreamParamsVec* current_streams,
SessionDescription* desc,
IceCredentialsIterator* ice_credentials) const {
std::unique_ptr<SctpDataContentDescription> data(
new SctpDataContentDescription());
bool secure_transport = (transport_desc_factory_->secure() != SEC_DISABLED);
cricket::SecurePolicy sdes_policy =
IsDtlsActive(current_content, current_description) ? cricket::SEC_DISABLED
: secure();
std::vector<std::string> crypto_suites;
// SDES doesn't make sense for SCTP, so we disable it, and we only
// get SDES crypto suites for RTP-based data channels.
sdes_policy = cricket::SEC_DISABLED;
// Unlike SetMediaProtocol below, we need to set the protocol
// before we call CreateMediaContentOffer. Otherwise,
// CreateMediaContentOffer won't know this is SCTP and will
// generate SSRCs rather than SIDs.
// TODO(deadbeef): Offer kMediaProtocolUdpDtlsSctp (or TcpDtlsSctp), once
// it's safe to do so. Older versions of webrtc would reject these
// protocols; see https://bugs.chromium.org/p/webrtc/issues/detail?id=7706.
data->set_protocol(secure_transport ? kMediaProtocolDtlsSctp
: kMediaProtocolSctp);
if (!CreateContentOffer(media_description_options, session_options,
sdes_policy, GetCryptos(current_content),
crypto_suites, RtpHeaderExtensions(), ssrc_generator_,
current_streams, data.get())) {
return false;
}
desc->AddContent(media_description_options.mid, MediaProtocolType::kSctp,
data.release());
if (!AddTransportOffer(media_description_options.mid,
media_description_options.transport_options,
current_description, desc, ice_credentials)) {
return false;
}
return true;
}
bool MediaSessionDescriptionFactory::AddRtpDataContentForOffer(
const MediaDescriptionOptions& media_description_options,
const MediaSessionOptions& session_options,
const ContentInfo* current_content,
const SessionDescription* current_description,
const RtpDataCodecs& rtp_data_codecs,
StreamParamsVec* current_streams,
SessionDescription* desc,
IceCredentialsIterator* ice_credentials) const {
std::unique_ptr<RtpDataContentDescription> data(
new RtpDataContentDescription());
bool secure_transport = (transport_desc_factory_->secure() != SEC_DISABLED);
cricket::SecurePolicy sdes_policy =
IsDtlsActive(current_content, current_description) ? cricket::SEC_DISABLED
: secure();
std::vector<std::string> crypto_suites;
GetSupportedDataSdesCryptoSuiteNames(session_options.crypto_options,
&crypto_suites);
if (!CreateMediaContentOffer(media_description_options, session_options,
rtp_data_codecs, sdes_policy,
GetCryptos(current_content), crypto_suites,
RtpHeaderExtensions(), ssrc_generator_,
current_streams, data.get())) {
return false;
}
data->set_bandwidth(kDataMaxBandwidth);
SetMediaProtocol(secure_transport, data.get());
desc->AddContent(media_description_options.mid, MediaProtocolType::kRtp,
media_description_options.stopped, data.release());
if (!AddTransportOffer(media_description_options.mid,
media_description_options.transport_options,
current_description, desc, ice_credentials)) {
return false;
}
return true;
}
bool MediaSessionDescriptionFactory::AddDataContentForOffer(
const MediaDescriptionOptions& media_description_options,
const MediaSessionOptions& session_options,
const ContentInfo* current_content,
const SessionDescription* current_description,
const RtpDataCodecs& rtp_data_codecs,
const DataCodecs& data_codecs,
StreamParamsVec* current_streams,
SessionDescription* desc,
IceCredentialsIterator* ice_credentials) const {
bool secure_transport = (transport_desc_factory_->secure() != SEC_DISABLED);
std::unique_ptr<DataContentDescription> data(new DataContentDescription());
bool is_sctp = (session_options.data_channel_type == DCT_SCTP);
// If the DataChannel type is not specified, use the DataChannel type in
// the current description.
@ -2314,16 +2226,52 @@ bool MediaSessionDescriptionFactory::AddDataContentForOffer(
is_sctp = (current_content->media_description()->protocol() ==
kMediaProtocolSctp);
}
cricket::SecurePolicy sdes_policy =
IsDtlsActive(current_content, current_description) ? cricket::SEC_DISABLED
: secure();
std::vector<std::string> crypto_suites;
if (is_sctp) {
return AddSctpDataContentForOffer(
media_description_options, session_options, current_content,
current_description, current_streams, desc, ice_credentials);
// SDES doesn't make sense for SCTP, so we disable it, and we only
// get SDES crypto suites for RTP-based data channels.
sdes_policy = cricket::SEC_DISABLED;
// Unlike SetMediaProtocol below, we need to set the protocol
// before we call CreateMediaContentOffer. Otherwise,
// CreateMediaContentOffer won't know this is SCTP and will
// generate SSRCs rather than SIDs.
// TODO(deadbeef): Offer kMediaProtocolUdpDtlsSctp (or TcpDtlsSctp), once
// it's safe to do so. Older versions of webrtc would reject these
// protocols; see https://bugs.chromium.org/p/webrtc/issues/detail?id=7706.
data->set_protocol(secure_transport ? kMediaProtocolDtlsSctp
: kMediaProtocolSctp);
} else {
return AddRtpDataContentForOffer(media_description_options, session_options,
current_content, current_description,
rtp_data_codecs, current_streams, desc,
ice_credentials);
GetSupportedDataSdesCryptoSuiteNames(session_options.crypto_options,
&crypto_suites);
}
// Even SCTP uses a "codec".
if (!CreateMediaContentOffer(
media_description_options, session_options, data_codecs, sdes_policy,
GetCryptos(current_content), crypto_suites, RtpHeaderExtensions(),
ssrc_generator_, current_streams, data.get())) {
return false;
}
if (is_sctp) {
desc->AddContent(media_description_options.mid, MediaProtocolType::kSctp,
data.release());
} else {
data->set_bandwidth(kDataMaxBandwidth);
SetMediaProtocol(secure_transport, data.get());
desc->AddContent(media_description_options.mid, MediaProtocolType::kRtp,
media_description_options.stopped, data.release());
}
if (!AddTransportOffer(media_description_options.mid,
media_description_options.transport_options,
current_description, desc, ice_credentials)) {
return false;
}
return true;
}
// |audio_codecs| = set of all possible codecs that can be used, with correct
@ -2411,15 +2359,9 @@ bool MediaSessionDescriptionFactory::AddAudioContentForAnswer(
// Do not require or create SDES cryptos if DTLS is used.
cricket::SecurePolicy sdes_policy =
audio_transport->secure() ? cricket::SEC_DISABLED : secure();
if (!SetCodecsInAnswer(offer_audio_description, filtered_codecs,
media_description_options, session_options,
ssrc_generator_, current_streams,
audio_answer.get())) {
return false;
}
if (!CreateMediaContentAnswer(
offer_audio_description, media_description_options, session_options,
sdes_policy, GetCryptos(current_content),
filtered_codecs, sdes_policy, GetCryptos(current_content),
audio_rtp_header_extensions(), ssrc_generator_,
enable_encrypted_rtp_header_extensions_, current_streams,
bundle_enabled, audio_answer.get())) {
@ -2512,15 +2454,9 @@ bool MediaSessionDescriptionFactory::AddVideoContentForAnswer(
// Do not require or create SDES cryptos if DTLS is used.
cricket::SecurePolicy sdes_policy =
video_transport->secure() ? cricket::SEC_DISABLED : secure();
if (!SetCodecsInAnswer(offer_video_description, filtered_codecs,
media_description_options, session_options,
ssrc_generator_, current_streams,
video_answer.get())) {
return false;
}
if (!CreateMediaContentAnswer(
offer_video_description, media_description_options, session_options,
sdes_policy, GetCryptos(current_content),
filtered_codecs, sdes_policy, GetCryptos(current_content),
video_rtp_header_extensions(), ssrc_generator_,
enable_encrypted_rtp_header_extensions_, current_streams,
bundle_enabled, video_answer.get())) {
@ -2556,7 +2492,7 @@ bool MediaSessionDescriptionFactory::AddDataContentForAnswer(
const ContentInfo* current_content,
const SessionDescription* current_description,
const TransportInfo* bundle_transport,
const RtpDataCodecs& rtp_data_codecs,
const DataCodecs& data_codecs,
StreamParamsVec* current_streams,
SessionDescription* answer,
IceCredentialsIterator* ice_credentials) const {
@ -2568,52 +2504,29 @@ bool MediaSessionDescriptionFactory::AddDataContentForAnswer(
return false;
}
std::unique_ptr<DataContentDescription> data_answer(
new DataContentDescription());
// Do not require or create SDES cryptos if DTLS is used.
cricket::SecurePolicy sdes_policy =
data_transport->secure() ? cricket::SEC_DISABLED : secure();
bool bundle_enabled = offer_description->HasGroup(GROUP_TYPE_BUNDLE) &&
session_options.bundle_enabled;
RTC_CHECK(IsMediaContentOfType(offer_content, MEDIA_TYPE_DATA));
std::unique_ptr<MediaContentDescription> data_answer;
if (offer_content->media_description()->as_sctp()) {
// SCTP data content
data_answer = absl::make_unique<SctpDataContentDescription>();
const SctpDataContentDescription* offer_data_description =
offer_content->media_description()->as_sctp();
// Respond with the offerer's proto, whatever it is.
data_answer->as_sctp()->set_protocol(offer_data_description->protocol());
if (!CreateMediaContentAnswer(
offer_data_description, media_description_options, session_options,
sdes_policy, GetCryptos(current_content), RtpHeaderExtensions(),
ssrc_generator_, enable_encrypted_rtp_header_extensions_,
current_streams, bundle_enabled, data_answer.get())) {
return false; // Fails the session setup.
}
// Respond with sctpmap if the offer uses sctpmap.
bool offer_uses_sctpmap = offer_data_description->use_sctpmap();
data_answer->as_sctp()->set_use_sctpmap(offer_uses_sctpmap);
} else {
// RTP offer
data_answer = absl::make_unique<RtpDataContentDescription>();
const RtpDataContentDescription* offer_data_description =
offer_content->media_description()->as_rtp_data();
RTC_CHECK(offer_data_description);
if (!SetCodecsInAnswer(offer_data_description, rtp_data_codecs,
media_description_options, session_options,
ssrc_generator_, current_streams,
data_answer->as_rtp_data())) {
return false;
}
if (!CreateMediaContentAnswer(
offer_data_description, media_description_options, session_options,
sdes_policy, GetCryptos(current_content), RtpHeaderExtensions(),
ssrc_generator_, enable_encrypted_rtp_header_extensions_,
current_streams, bundle_enabled, data_answer.get())) {
return false; // Fails the session setup.
}
const DataContentDescription* offer_data_description =
offer_content->media_description()->as_data();
if (!CreateMediaContentAnswer(
offer_data_description, media_description_options, session_options,
data_codecs, sdes_policy, GetCryptos(current_content),
RtpHeaderExtensions(), ssrc_generator_,
enable_encrypted_rtp_header_extensions_, current_streams,
bundle_enabled, data_answer.get())) {
return false; // Fails the session setup.
}
// Respond with sctpmap if the offer uses sctpmap.
bool offer_uses_sctpmap = offer_data_description->use_sctpmap();
data_answer->set_use_sctpmap(offer_uses_sctpmap);
bool secure = bundle_transport ? bundle_transport->description.secure()
: data_transport->secure();
@ -2736,35 +2649,20 @@ const MediaContentDescription* GetFirstMediaContentDescription(
const AudioContentDescription* GetFirstAudioContentDescription(
const SessionDescription* sdesc) {
auto desc = GetFirstMediaContentDescription(sdesc, MEDIA_TYPE_AUDIO);
return desc ? desc->as_audio() : nullptr;
return static_cast<const AudioContentDescription*>(
GetFirstMediaContentDescription(sdesc, MEDIA_TYPE_AUDIO));
}
const VideoContentDescription* GetFirstVideoContentDescription(
const SessionDescription* sdesc) {
auto desc = GetFirstMediaContentDescription(sdesc, MEDIA_TYPE_VIDEO);
return desc ? desc->as_video() : nullptr;
return static_cast<const VideoContentDescription*>(
GetFirstMediaContentDescription(sdesc, MEDIA_TYPE_VIDEO));
}
const RtpDataContentDescription* GetFirstRtpDataContentDescription(
const SessionDescription* sdesc) {
auto desc = GetFirstMediaContentDescription(sdesc, MEDIA_TYPE_DATA);
return desc ? desc->as_rtp_data() : nullptr;
}
const SctpDataContentDescription* GetFirstSctpDataContentDescription(
const SessionDescription* sdesc) {
auto desc = GetFirstMediaContentDescription(sdesc, MEDIA_TYPE_DATA);
return desc ? desc->as_sctp() : nullptr;
}
// Returns a shim representing either an SctpDataContentDescription
// or an RtpDataContentDescription, as appropriate.
// TODO(bugs.webrtc.org/10597): Remove together with shim.
const DataContentDescription* GetFirstDataContentDescription(
const SessionDescription* sdesc) {
auto desc = GetFirstMediaContentDescription(sdesc, MEDIA_TYPE_DATA);
return desc ? desc->as_data() : nullptr;
return static_cast<const DataContentDescription*>(
GetFirstMediaContentDescription(sdesc, MEDIA_TYPE_DATA));
}
//
@ -2823,33 +2721,20 @@ MediaContentDescription* GetFirstMediaContentDescription(
AudioContentDescription* GetFirstAudioContentDescription(
SessionDescription* sdesc) {
auto desc = GetFirstMediaContentDescription(sdesc, MEDIA_TYPE_AUDIO);
return desc ? desc->as_audio() : nullptr;
return static_cast<AudioContentDescription*>(
GetFirstMediaContentDescription(sdesc, MEDIA_TYPE_AUDIO));
}
VideoContentDescription* GetFirstVideoContentDescription(
SessionDescription* sdesc) {
auto desc = GetFirstMediaContentDescription(sdesc, MEDIA_TYPE_VIDEO);
return desc ? desc->as_video() : nullptr;
return static_cast<VideoContentDescription*>(
GetFirstMediaContentDescription(sdesc, MEDIA_TYPE_VIDEO));
}
RtpDataContentDescription* GetFirstRtpDataContentDescription(
SessionDescription* sdesc) {
auto desc = GetFirstMediaContentDescription(sdesc, MEDIA_TYPE_DATA);
return desc ? desc->as_rtp_data() : nullptr;
}
SctpDataContentDescription* GetFirstSctpDataContentDescription(
SessionDescription* sdesc) {
auto desc = GetFirstMediaContentDescription(sdesc, MEDIA_TYPE_DATA);
return desc ? desc->as_sctp() : nullptr;
}
// Returns shim
DataContentDescription* GetFirstDataContentDescription(
SessionDescription* sdesc) {
auto desc = GetFirstMediaContentDescription(sdesc, MEDIA_TYPE_DATA);
return desc ? desc->as_data() : nullptr;
return static_cast<DataContentDescription*>(
GetFirstMediaContentDescription(sdesc, MEDIA_TYPE_DATA));
}
} // namespace cricket

View File

@ -24,7 +24,6 @@
#include "p2p/base/ice_credentials_iterator.h"
#include "p2p/base/transport_description_factory.h"
#include "pc/jsep_transport.h"
#include "pc/media_protocol_names.h"
#include "pc/session_description.h"
#include "rtc_base/unique_id_generator.h"
@ -155,10 +154,8 @@ class MediaSessionDescriptionFactory {
video_rtp_extensions_ = extensions;
}
RtpHeaderExtensions video_rtp_header_extensions() const;
const RtpDataCodecs& rtp_data_codecs() const { return rtp_data_codecs_; }
void set_rtp_data_codecs(const RtpDataCodecs& codecs) {
rtp_data_codecs_ = codecs;
}
const DataCodecs& data_codecs() const { return data_codecs_; }
void set_data_codecs(const DataCodecs& codecs) { data_codecs_ = codecs; }
SecurePolicy secure() const { return secure_; }
void set_secure(SecurePolicy s) { secure_ = s; }
@ -188,13 +185,13 @@ class MediaSessionDescriptionFactory {
const std::vector<const ContentInfo*>& current_active_contents,
AudioCodecs* audio_codecs,
VideoCodecs* video_codecs,
RtpDataCodecs* rtp_data_codecs) const;
DataCodecs* data_codecs) const;
void GetCodecsForAnswer(
const std::vector<const ContentInfo*>& current_active_contents,
const SessionDescription& remote_offer,
AudioCodecs* audio_codecs,
VideoCodecs* video_codecs,
RtpDataCodecs* rtp_data_codecs) const;
DataCodecs* data_codecs) const;
void GetRtpHdrExtsToOffer(
const std::vector<const ContentInfo*>& current_active_contents,
RtpHeaderExtensions* audio_extensions,
@ -243,32 +240,12 @@ class MediaSessionDescriptionFactory {
SessionDescription* desc,
IceCredentialsIterator* ice_credentials) const;
bool AddSctpDataContentForOffer(
const MediaDescriptionOptions& media_description_options,
const MediaSessionOptions& session_options,
const ContentInfo* current_content,
const SessionDescription* current_description,
StreamParamsVec* current_streams,
SessionDescription* desc,
IceCredentialsIterator* ice_credentials) const;
bool AddRtpDataContentForOffer(
const MediaDescriptionOptions& media_description_options,
const MediaSessionOptions& session_options,
const ContentInfo* current_content,
const SessionDescription* current_description,
const RtpDataCodecs& rtp_data_codecs,
StreamParamsVec* current_streams,
SessionDescription* desc,
IceCredentialsIterator* ice_credentials) const;
// This function calls either AddRtpDataContentForOffer or
// AddSctpDataContentForOffer depending on protocol.
// The codecs argument is ignored for SCTP.
bool AddDataContentForOffer(
const MediaDescriptionOptions& media_description_options,
const MediaSessionOptions& session_options,
const ContentInfo* current_content,
const SessionDescription* current_description,
const RtpDataCodecs& rtp_data_codecs,
const DataCodecs& data_codecs,
StreamParamsVec* current_streams,
SessionDescription* desc,
IceCredentialsIterator* ice_credentials) const;
@ -307,7 +284,7 @@ class MediaSessionDescriptionFactory {
const ContentInfo* current_content,
const SessionDescription* current_description,
const TransportInfo* bundle_transport,
const RtpDataCodecs& rtp_data_codecs,
const DataCodecs& data_codecs,
StreamParamsVec* current_streams,
SessionDescription* answer,
IceCredentialsIterator* ice_credentials) const;
@ -324,7 +301,7 @@ class MediaSessionDescriptionFactory {
RtpHeaderExtensions audio_rtp_extensions_;
VideoCodecs video_codecs_;
RtpHeaderExtensions video_rtp_extensions_;
RtpDataCodecs rtp_data_codecs_;
DataCodecs data_codecs_;
// This object is not owned by the channel so it must outlive it.
rtc::UniqueRandomIdGenerator* const ssrc_generator_;
bool enable_encrypted_rtp_header_extensions_ = false;
@ -353,11 +330,6 @@ const AudioContentDescription* GetFirstAudioContentDescription(
const SessionDescription* sdesc);
const VideoContentDescription* GetFirstVideoContentDescription(
const SessionDescription* sdesc);
const RtpDataContentDescription* GetFirstRtpDataContentDescription(
const SessionDescription* sdesc);
const SctpDataContentDescription* GetFirstSctpDataContentDescription(
const SessionDescription* sdesc);
// Returns shim. Deprecated - ask for the right protocol instead.
const DataContentDescription* GetFirstDataContentDescription(
const SessionDescription* sdesc);
// Non-const versions of the above functions.
@ -375,10 +347,6 @@ AudioContentDescription* GetFirstAudioContentDescription(
SessionDescription* sdesc);
VideoContentDescription* GetFirstVideoContentDescription(
SessionDescription* sdesc);
RtpDataContentDescription* GetFirstRtpDataContentDescription(
SessionDescription* sdesc);
SctpDataContentDescription* GetFirstSctpDataContentDescription(
SessionDescription* sdesc);
DataContentDescription* GetFirstDataContentDescription(
SessionDescription* sdesc);
@ -402,6 +370,9 @@ void GetSupportedDataSdesCryptoSuiteNames(
const webrtc::CryptoOptions& crypto_options,
std::vector<std::string>* crypto_suite_names);
// Returns true if the given media section protocol indicates use of RTP.
bool IsRtpProtocol(const std::string& protocol);
} // namespace cricket
#endif // PC_MEDIA_SESSION_H_

View File

@ -42,10 +42,12 @@ using cricket::AudioCodec;
using cricket::AudioContentDescription;
using cricket::ContentInfo;
using cricket::CryptoParamsVec;
using cricket::DataCodec;
using cricket::DataContentDescription;
using cricket::GetFirstAudioContent;
using cricket::GetFirstAudioContentDescription;
using cricket::GetFirstDataContent;
using cricket::GetFirstRtpDataContentDescription;
using cricket::GetFirstDataContentDescription;
using cricket::GetFirstVideoContent;
using cricket::GetFirstVideoContentDescription;
using cricket::kAutoBandwidth;
@ -60,9 +62,6 @@ using cricket::MediaSessionOptions;
using cricket::MediaType;
using cricket::RidDescription;
using cricket::RidDirection;
using cricket::RtpDataCodec;
using cricket::RtpDataContentDescription;
using cricket::SctpDataContentDescription;
using cricket::SEC_DISABLED;
using cricket::SEC_ENABLED;
using cricket::SEC_REQUIRED;
@ -127,14 +126,14 @@ static const VideoCodec kVideoCodecs2[] = {VideoCodec(126, "H264"),
static const VideoCodec kVideoCodecsAnswer[] = {VideoCodec(97, "H264")};
static const RtpDataCodec kDataCodecs1[] = {RtpDataCodec(98, "binary-data"),
RtpDataCodec(99, "utf8-text")};
static const DataCodec kDataCodecs1[] = {DataCodec(98, "binary-data"),
DataCodec(99, "utf8-text")};
static const RtpDataCodec kDataCodecs2[] = {RtpDataCodec(126, "binary-data"),
RtpDataCodec(127, "utf8-text")};
static const DataCodec kDataCodecs2[] = {DataCodec(126, "binary-data"),
DataCodec(127, "utf8-text")};
static const RtpDataCodec kDataCodecsAnswer[] = {
RtpDataCodec(98, "binary-data"), RtpDataCodec(99, "utf8-text")};
static const DataCodec kDataCodecsAnswer[] = {DataCodec(98, "binary-data"),
DataCodec(99, "utf8-text")};
static const RtpExtension kAudioRtpExtension1[] = {
RtpExtension("urn:ietf:params:rtp-hdrext:ssrc-audio-level", 8),
@ -413,11 +412,11 @@ class MediaSessionDescriptionFactoryTest : public ::testing::Test {
f1_.set_audio_codecs(MAKE_VECTOR(kAudioCodecs1),
MAKE_VECTOR(kAudioCodecs1));
f1_.set_video_codecs(MAKE_VECTOR(kVideoCodecs1));
f1_.set_rtp_data_codecs(MAKE_VECTOR(kDataCodecs1));
f1_.set_data_codecs(MAKE_VECTOR(kDataCodecs1));
f2_.set_audio_codecs(MAKE_VECTOR(kAudioCodecs2),
MAKE_VECTOR(kAudioCodecs2));
f2_.set_video_codecs(MAKE_VECTOR(kVideoCodecs2));
f2_.set_rtp_data_codecs(MAKE_VECTOR(kDataCodecs2));
f2_.set_data_codecs(MAKE_VECTOR(kDataCodecs2));
tdf1_.set_certificate(rtc::RTCCertificate::Create(
std::unique_ptr<rtc::SSLIdentity>(new rtc::FakeSSLIdentity("id1"))));
tdf2_.set_certificate(rtc::RTCCertificate::Create(
@ -802,7 +801,7 @@ TEST_F(MediaSessionDescriptionFactoryTest, TestCreateVideoOffer) {
TEST_F(MediaSessionDescriptionFactoryTest, TestBundleOfferWithSameCodecPlType) {
const VideoCodec& offered_video_codec = f2_.video_codecs()[0];
const AudioCodec& offered_audio_codec = f2_.audio_sendrecv_codecs()[0];
const RtpDataCodec& offered_data_codec = f2_.rtp_data_codecs()[0];
const DataCodec& offered_data_codec = f2_.data_codecs()[0];
ASSERT_EQ(offered_video_codec.id, offered_audio_codec.id);
ASSERT_EQ(offered_video_codec.id, offered_data_codec.id);
@ -815,8 +814,8 @@ TEST_F(MediaSessionDescriptionFactoryTest, TestBundleOfferWithSameCodecPlType) {
GetFirstVideoContentDescription(offer.get());
const AudioContentDescription* acd =
GetFirstAudioContentDescription(offer.get());
const RtpDataContentDescription* dcd =
GetFirstRtpDataContentDescription(offer.get());
const DataContentDescription* dcd =
GetFirstDataContentDescription(offer.get());
ASSERT_TRUE(NULL != vcd);
ASSERT_TRUE(NULL != acd);
ASSERT_TRUE(NULL != dcd);
@ -859,8 +858,8 @@ TEST_F(MediaSessionDescriptionFactoryTest,
GetFirstAudioContentDescription(updated_offer.get());
const VideoContentDescription* vcd =
GetFirstVideoContentDescription(updated_offer.get());
const RtpDataContentDescription* dcd =
GetFirstRtpDataContentDescription(updated_offer.get());
const DataContentDescription* dcd =
GetFirstDataContentDescription(updated_offer.get());
EXPECT_TRUE(NULL != vcd);
EXPECT_TRUE(NULL != acd);
EXPECT_TRUE(NULL != dcd);
@ -888,7 +887,7 @@ TEST_F(MediaSessionDescriptionFactoryTest, TestCreateRtpDataOffer) {
EXPECT_EQ(MediaProtocolType::kRtp, ac->type);
EXPECT_EQ(MediaProtocolType::kRtp, dc->type);
const AudioContentDescription* acd = ac->media_description()->as_audio();
const RtpDataContentDescription* dcd = dc->media_description()->as_rtp_data();
const DataContentDescription* dcd = dc->media_description()->as_data();
EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
EXPECT_EQ(f1_.audio_sendrecv_codecs(), acd->codecs());
EXPECT_EQ(0U, acd->first_ssrc()); // no sender is attched.
@ -897,7 +896,7 @@ TEST_F(MediaSessionDescriptionFactoryTest, TestCreateRtpDataOffer) {
ASSERT_CRYPTO(acd, 1U, kDefaultSrtpCryptoSuite);
EXPECT_EQ(cricket::kMediaProtocolSavpf, acd->protocol());
EXPECT_EQ(MEDIA_TYPE_DATA, dcd->type());
EXPECT_EQ(f1_.rtp_data_codecs(), dcd->codecs());
EXPECT_EQ(f1_.data_codecs(), dcd->codecs());
EXPECT_EQ(0U, dcd->first_ssrc()); // no sender is attached.
EXPECT_EQ(cricket::kDataMaxBandwidth,
dcd->bandwidth()); // default bandwidth (auto)
@ -1281,7 +1280,7 @@ TEST_F(MediaSessionDescriptionFactoryTest, TestCreateDataAnswer) {
EXPECT_EQ(MediaProtocolType::kRtp, ac->type);
EXPECT_EQ(MediaProtocolType::kRtp, dc->type);
const AudioContentDescription* acd = ac->media_description()->as_audio();
const RtpDataContentDescription* dcd = dc->media_description()->as_rtp_data();
const DataContentDescription* dcd = dc->media_description()->as_data();
EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
EXPECT_THAT(acd->codecs(), ElementsAreArray(kAudioCodecsAnswer));
EXPECT_EQ(kAutoBandwidth, acd->bandwidth()); // negotiated auto bw
@ -1313,7 +1312,7 @@ TEST_F(MediaSessionDescriptionFactoryTest, TestCreateDataAnswerGcm) {
EXPECT_EQ(MediaProtocolType::kRtp, ac->type);
EXPECT_EQ(MediaProtocolType::kRtp, dc->type);
const AudioContentDescription* acd = ac->media_description()->as_audio();
const RtpDataContentDescription* dcd = dc->media_description()->as_rtp_data();
const DataContentDescription* dcd = dc->media_description()->as_data();
EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
EXPECT_THAT(acd->codecs(), ElementsAreArray(kAudioCodecsAnswer));
EXPECT_EQ(kAutoBandwidth, acd->bandwidth()); // negotiated auto bw
@ -1337,16 +1336,15 @@ TEST_F(MediaSessionDescriptionFactoryTest, TestCreateDataAnswerUsesSctpmap) {
ASSERT_TRUE(offer.get() != NULL);
ContentInfo* dc_offer = offer->GetContentByName("data");
ASSERT_TRUE(dc_offer != NULL);
SctpDataContentDescription* dcd_offer =
dc_offer->media_description()->as_sctp();
DataContentDescription* dcd_offer = dc_offer->media_description()->as_data();
EXPECT_TRUE(dcd_offer->use_sctpmap());
std::unique_ptr<SessionDescription> answer =
f2_.CreateAnswer(offer.get(), opts, NULL);
const ContentInfo* dc_answer = answer->GetContentByName("data");
ASSERT_TRUE(dc_answer != NULL);
const SctpDataContentDescription* dcd_answer =
dc_answer->media_description()->as_sctp();
const DataContentDescription* dcd_answer =
dc_answer->media_description()->as_data();
EXPECT_TRUE(dcd_answer->use_sctpmap());
}
@ -1358,16 +1356,15 @@ TEST_F(MediaSessionDescriptionFactoryTest, TestCreateDataAnswerWithoutSctpmap) {
ASSERT_TRUE(offer.get() != NULL);
ContentInfo* dc_offer = offer->GetContentByName("data");
ASSERT_TRUE(dc_offer != NULL);
SctpDataContentDescription* dcd_offer =
dc_offer->media_description()->as_sctp();
DataContentDescription* dcd_offer = dc_offer->media_description()->as_data();
dcd_offer->set_use_sctpmap(false);
std::unique_ptr<SessionDescription> answer =
f2_.CreateAnswer(offer.get(), opts, NULL);
const ContentInfo* dc_answer = answer->GetContentByName("data");
ASSERT_TRUE(dc_answer != NULL);
const SctpDataContentDescription* dcd_answer =
dc_answer->media_description()->as_sctp();
const DataContentDescription* dcd_answer =
dc_answer->media_description()->as_data();
EXPECT_FALSE(dcd_answer->use_sctpmap());
}
@ -1388,9 +1385,7 @@ TEST_F(MediaSessionDescriptionFactoryTest,
ASSERT_TRUE(offer.get() != nullptr);
ContentInfo* dc_offer = offer->GetContentByName("data");
ASSERT_TRUE(dc_offer != nullptr);
SctpDataContentDescription* dcd_offer =
dc_offer->media_description()->as_sctp();
ASSERT_TRUE(dcd_offer);
DataContentDescription* dcd_offer = dc_offer->media_description()->as_data();
std::vector<std::string> protos = {"DTLS/SCTP", "UDP/DTLS/SCTP",
"TCP/DTLS/SCTP"};
@ -1400,8 +1395,8 @@ TEST_F(MediaSessionDescriptionFactoryTest,
f2_.CreateAnswer(offer.get(), opts, nullptr);
const ContentInfo* dc_answer = answer->GetContentByName("data");
ASSERT_TRUE(dc_answer != nullptr);
const SctpDataContentDescription* dcd_answer =
dc_answer->media_description()->as_sctp();
const DataContentDescription* dcd_answer =
dc_answer->media_description()->as_data();
EXPECT_FALSE(dc_answer->rejected);
EXPECT_EQ(proto, dcd_answer->protocol());
}
@ -1483,11 +1478,9 @@ TEST_F(MediaSessionDescriptionFactoryTest,
std::unique_ptr<SessionDescription> offer = f1_.CreateOffer(opts, NULL);
ContentInfo* dc_offer = offer->GetContentByName("data");
ASSERT_TRUE(dc_offer != NULL);
RtpDataContentDescription* dcd_offer =
dc_offer->media_description()->as_rtp_data();
DataContentDescription* dcd_offer = dc_offer->media_description()->as_data();
ASSERT_TRUE(dcd_offer != NULL);
// Offer must be acceptable as an RTP protocol in order to be set.
std::string protocol = "RTP/a weird unknown protocol";
std::string protocol = "a weird unknown protocol";
dcd_offer->set_protocol(protocol);
std::unique_ptr<SessionDescription> answer =
@ -1496,8 +1489,8 @@ TEST_F(MediaSessionDescriptionFactoryTest,
const ContentInfo* dc_answer = answer->GetContentByName("data");
ASSERT_TRUE(dc_answer != NULL);
EXPECT_TRUE(dc_answer->rejected);
const RtpDataContentDescription* dcd_answer =
dc_answer->media_description()->as_rtp_data();
const DataContentDescription* dcd_answer =
dc_answer->media_description()->as_data();
ASSERT_TRUE(dcd_answer != NULL);
EXPECT_EQ(protocol, dcd_answer->protocol());
}
@ -1695,7 +1688,7 @@ TEST_F(MediaSessionDescriptionFactoryTest,
ASSERT_TRUE(vc != NULL);
const AudioContentDescription* acd = ac->media_description()->as_audio();
const VideoContentDescription* vcd = vc->media_description()->as_video();
const RtpDataContentDescription* dcd = dc->media_description()->as_rtp_data();
const DataContentDescription* dcd = dc->media_description()->as_data();
EXPECT_FALSE(acd->has_ssrcs()); // No StreamParams.
EXPECT_FALSE(vcd->has_ssrcs()); // No StreamParams.
@ -1723,16 +1716,16 @@ TEST_F(MediaSessionDescriptionFactoryTest, TestCreateVideoAnswerRtcpMux) {
answer = f2_.CreateAnswer(offer.get(), answer_opts, NULL);
ASSERT_TRUE(NULL != GetFirstAudioContentDescription(offer.get()));
ASSERT_TRUE(NULL != GetFirstVideoContentDescription(offer.get()));
ASSERT_TRUE(NULL != GetFirstRtpDataContentDescription(offer.get()));
ASSERT_TRUE(NULL != GetFirstDataContentDescription(offer.get()));
ASSERT_TRUE(NULL != GetFirstAudioContentDescription(answer.get()));
ASSERT_TRUE(NULL != GetFirstVideoContentDescription(answer.get()));
ASSERT_TRUE(NULL != GetFirstRtpDataContentDescription(answer.get()));
ASSERT_TRUE(NULL != GetFirstDataContentDescription(answer.get()));
EXPECT_TRUE(GetFirstAudioContentDescription(offer.get())->rtcp_mux());
EXPECT_TRUE(GetFirstVideoContentDescription(offer.get())->rtcp_mux());
EXPECT_TRUE(GetFirstRtpDataContentDescription(offer.get())->rtcp_mux());
EXPECT_TRUE(GetFirstDataContentDescription(offer.get())->rtcp_mux());
EXPECT_TRUE(GetFirstAudioContentDescription(answer.get())->rtcp_mux());
EXPECT_TRUE(GetFirstVideoContentDescription(answer.get())->rtcp_mux());
EXPECT_TRUE(GetFirstRtpDataContentDescription(answer.get())->rtcp_mux());
EXPECT_TRUE(GetFirstDataContentDescription(answer.get())->rtcp_mux());
offer_opts.rtcp_mux_enabled = true;
answer_opts.rtcp_mux_enabled = false;
@ -1740,16 +1733,16 @@ TEST_F(MediaSessionDescriptionFactoryTest, TestCreateVideoAnswerRtcpMux) {
answer = f2_.CreateAnswer(offer.get(), answer_opts, NULL);
ASSERT_TRUE(NULL != GetFirstAudioContentDescription(offer.get()));
ASSERT_TRUE(NULL != GetFirstVideoContentDescription(offer.get()));
ASSERT_TRUE(NULL != GetFirstRtpDataContentDescription(offer.get()));
ASSERT_TRUE(NULL != GetFirstDataContentDescription(offer.get()));
ASSERT_TRUE(NULL != GetFirstAudioContentDescription(answer.get()));
ASSERT_TRUE(NULL != GetFirstVideoContentDescription(answer.get()));
ASSERT_TRUE(NULL != GetFirstRtpDataContentDescription(answer.get()));
ASSERT_TRUE(NULL != GetFirstDataContentDescription(answer.get()));
EXPECT_TRUE(GetFirstAudioContentDescription(offer.get())->rtcp_mux());
EXPECT_TRUE(GetFirstVideoContentDescription(offer.get())->rtcp_mux());
EXPECT_TRUE(GetFirstRtpDataContentDescription(offer.get())->rtcp_mux());
EXPECT_TRUE(GetFirstDataContentDescription(offer.get())->rtcp_mux());
EXPECT_FALSE(GetFirstAudioContentDescription(answer.get())->rtcp_mux());
EXPECT_FALSE(GetFirstVideoContentDescription(answer.get())->rtcp_mux());
EXPECT_FALSE(GetFirstRtpDataContentDescription(answer.get())->rtcp_mux());
EXPECT_FALSE(GetFirstDataContentDescription(answer.get())->rtcp_mux());
offer_opts.rtcp_mux_enabled = false;
answer_opts.rtcp_mux_enabled = true;
@ -1757,16 +1750,16 @@ TEST_F(MediaSessionDescriptionFactoryTest, TestCreateVideoAnswerRtcpMux) {
answer = f2_.CreateAnswer(offer.get(), answer_opts, NULL);
ASSERT_TRUE(NULL != GetFirstAudioContentDescription(offer.get()));
ASSERT_TRUE(NULL != GetFirstVideoContentDescription(offer.get()));
ASSERT_TRUE(NULL != GetFirstRtpDataContentDescription(offer.get()));
ASSERT_TRUE(NULL != GetFirstDataContentDescription(offer.get()));
ASSERT_TRUE(NULL != GetFirstAudioContentDescription(answer.get()));
ASSERT_TRUE(NULL != GetFirstVideoContentDescription(answer.get()));
ASSERT_TRUE(NULL != GetFirstRtpDataContentDescription(answer.get()));
ASSERT_TRUE(NULL != GetFirstDataContentDescription(answer.get()));
EXPECT_FALSE(GetFirstAudioContentDescription(offer.get())->rtcp_mux());
EXPECT_FALSE(GetFirstVideoContentDescription(offer.get())->rtcp_mux());
EXPECT_FALSE(GetFirstRtpDataContentDescription(offer.get())->rtcp_mux());
EXPECT_FALSE(GetFirstDataContentDescription(offer.get())->rtcp_mux());
EXPECT_FALSE(GetFirstAudioContentDescription(answer.get())->rtcp_mux());
EXPECT_FALSE(GetFirstVideoContentDescription(answer.get())->rtcp_mux());
EXPECT_FALSE(GetFirstRtpDataContentDescription(answer.get())->rtcp_mux());
EXPECT_FALSE(GetFirstDataContentDescription(answer.get())->rtcp_mux());
offer_opts.rtcp_mux_enabled = false;
answer_opts.rtcp_mux_enabled = false;
@ -1774,16 +1767,16 @@ TEST_F(MediaSessionDescriptionFactoryTest, TestCreateVideoAnswerRtcpMux) {
answer = f2_.CreateAnswer(offer.get(), answer_opts, NULL);
ASSERT_TRUE(NULL != GetFirstAudioContentDescription(offer.get()));
ASSERT_TRUE(NULL != GetFirstVideoContentDescription(offer.get()));
ASSERT_TRUE(NULL != GetFirstRtpDataContentDescription(offer.get()));
ASSERT_TRUE(NULL != GetFirstDataContentDescription(offer.get()));
ASSERT_TRUE(NULL != GetFirstAudioContentDescription(answer.get()));
ASSERT_TRUE(NULL != GetFirstVideoContentDescription(answer.get()));
ASSERT_TRUE(NULL != GetFirstRtpDataContentDescription(answer.get()));
ASSERT_TRUE(NULL != GetFirstDataContentDescription(answer.get()));
EXPECT_FALSE(GetFirstAudioContentDescription(offer.get())->rtcp_mux());
EXPECT_FALSE(GetFirstVideoContentDescription(offer.get())->rtcp_mux());
EXPECT_FALSE(GetFirstRtpDataContentDescription(offer.get())->rtcp_mux());
EXPECT_FALSE(GetFirstDataContentDescription(offer.get())->rtcp_mux());
EXPECT_FALSE(GetFirstAudioContentDescription(answer.get())->rtcp_mux());
EXPECT_FALSE(GetFirstVideoContentDescription(answer.get())->rtcp_mux());
EXPECT_FALSE(GetFirstRtpDataContentDescription(answer.get())->rtcp_mux());
EXPECT_FALSE(GetFirstDataContentDescription(answer.get())->rtcp_mux());
}
// Create an audio-only answer to a video offer.
@ -1955,7 +1948,7 @@ TEST_F(MediaSessionDescriptionFactoryTest, TestCreateMultiStreamVideoOffer) {
ASSERT_TRUE(dc != NULL);
const AudioContentDescription* acd = ac->media_description()->as_audio();
const VideoContentDescription* vcd = vc->media_description()->as_video();
const RtpDataContentDescription* dcd = dc->media_description()->as_rtp_data();
const DataContentDescription* dcd = dc->media_description()->as_data();
EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
EXPECT_EQ(f1_.audio_sendrecv_codecs(), acd->codecs());
@ -1985,7 +1978,7 @@ TEST_F(MediaSessionDescriptionFactoryTest, TestCreateMultiStreamVideoOffer) {
EXPECT_TRUE(vcd->rtcp_mux()); // rtcp-mux defaults on
EXPECT_EQ(MEDIA_TYPE_DATA, dcd->type());
EXPECT_EQ(f1_.rtp_data_codecs(), dcd->codecs());
EXPECT_EQ(f1_.data_codecs(), dcd->codecs());
ASSERT_CRYPTO(dcd, 1U, kDefaultSrtpCryptoSuite);
const StreamParamsVec& data_streams = dcd->streams();
@ -2027,8 +2020,8 @@ TEST_F(MediaSessionDescriptionFactoryTest, TestCreateMultiStreamVideoOffer) {
ac->media_description()->as_audio();
const VideoContentDescription* updated_vcd =
vc->media_description()->as_video();
const RtpDataContentDescription* updated_dcd =
dc->media_description()->as_rtp_data();
const DataContentDescription* updated_dcd =
dc->media_description()->as_data();
EXPECT_EQ(acd->type(), updated_acd->type());
EXPECT_EQ(acd->codecs(), updated_acd->codecs());
@ -2314,7 +2307,7 @@ TEST_F(MediaSessionDescriptionFactoryTest, TestCreateMultiStreamVideoAnswer) {
ASSERT_TRUE(dc != NULL);
const AudioContentDescription* acd = ac->media_description()->as_audio();
const VideoContentDescription* vcd = vc->media_description()->as_video();
const RtpDataContentDescription* dcd = dc->media_description()->as_rtp_data();
const DataContentDescription* dcd = dc->media_description()->as_data();
ASSERT_CRYPTO(acd, 1U, kDefaultSrtpCryptoSuite);
ASSERT_CRYPTO(vcd, 1U, kDefaultSrtpCryptoSuite);
ASSERT_CRYPTO(dcd, 1U, kDefaultSrtpCryptoSuite);
@ -2382,8 +2375,8 @@ TEST_F(MediaSessionDescriptionFactoryTest, TestCreateMultiStreamVideoAnswer) {
ac->media_description()->as_audio();
const VideoContentDescription* updated_vcd =
vc->media_description()->as_video();
const RtpDataContentDescription* updated_dcd =
dc->media_description()->as_rtp_data();
const DataContentDescription* updated_dcd =
dc->media_description()->as_data();
ASSERT_CRYPTO(updated_acd, 1U, kDefaultSrtpCryptoSuite);
EXPECT_TRUE(CompareCryptoParams(acd->cryptos(), updated_acd->cryptos()));
@ -3543,8 +3536,8 @@ TEST_F(MediaSessionDescriptionFactoryTest, TestCryptoOfferDtlsButNotSdes) {
const VideoContentDescription* video_offer =
GetFirstVideoContentDescription(offer.get());
ASSERT_TRUE(video_offer->cryptos().empty());
const RtpDataContentDescription* data_offer =
GetFirstRtpDataContentDescription(offer.get());
const DataContentDescription* data_offer =
GetFirstDataContentDescription(offer.get());
ASSERT_TRUE(data_offer->cryptos().empty());
const cricket::TransportDescription* audio_offer_trans_desc =
@ -4075,11 +4068,11 @@ class MediaProtocolTest : public ::testing::TestWithParam<const char*> {
f1_.set_audio_codecs(MAKE_VECTOR(kAudioCodecs1),
MAKE_VECTOR(kAudioCodecs1));
f1_.set_video_codecs(MAKE_VECTOR(kVideoCodecs1));
f1_.set_rtp_data_codecs(MAKE_VECTOR(kDataCodecs1));
f1_.set_data_codecs(MAKE_VECTOR(kDataCodecs1));
f2_.set_audio_codecs(MAKE_VECTOR(kAudioCodecs2),
MAKE_VECTOR(kAudioCodecs2));
f2_.set_video_codecs(MAKE_VECTOR(kVideoCodecs2));
f2_.set_rtp_data_codecs(MAKE_VECTOR(kDataCodecs2));
f2_.set_data_codecs(MAKE_VECTOR(kDataCodecs2));
f1_.set_secure(SEC_ENABLED);
f2_.set_secure(SEC_ENABLED);
tdf1_.set_certificate(rtc::RTCCertificate::Create(

View File

@ -559,13 +559,24 @@ bool VerifyIceUfragPwdPresent(const SessionDescription* desc) {
// Get the SCTP port out of a SessionDescription.
// Return -1 if not found.
int GetSctpPort(const SessionDescription* session_description) {
const cricket::SctpDataContentDescription* data_desc =
GetFirstSctpDataContentDescription(session_description);
const cricket::DataContentDescription* data_desc =
GetFirstDataContentDescription(session_description);
RTC_DCHECK(data_desc);
if (!data_desc) {
return -1;
}
return data_desc->port();
std::string value;
cricket::DataCodec match_pattern(cricket::kGoogleSctpDataCodecPlType,
cricket::kGoogleSctpDataCodecName);
for (const cricket::DataCodec& codec : data_desc->codecs()) {
if (!codec.Matches(match_pattern)) {
continue;
}
if (codec.GetParam(cricket::kCodecParamPort, &value)) {
return rtc::FromString<int>(value);
}
}
return -1;
}
// Returns true if |new_desc| requests an ICE restart (i.e., new ufrag/pwd).
@ -2412,11 +2423,11 @@ RTCError PeerConnection::ApplyLocalDescription(
const cricket::ContentInfo* data_content =
GetFirstDataContent(local_description()->description());
if (data_content) {
const cricket::RtpDataContentDescription* rtp_data_desc =
data_content->media_description()->as_rtp_data();
// rtp_data_desc will be null if this is an SCTP description.
if (rtp_data_desc) {
UpdateLocalRtpDataChannels(rtp_data_desc->streams());
const cricket::DataContentDescription* data_desc =
data_content->media_description()->as_data();
if (absl::StartsWith(data_desc->protocol(),
cricket::kMediaProtocolRtpPrefix)) {
UpdateLocalRtpDataChannels(data_desc->streams());
}
}
@ -2822,8 +2833,8 @@ RTCError PeerConnection::ApplyRemoteDescription(
GetFirstAudioContentDescription(remote_description()->description());
const cricket::VideoContentDescription* video_desc =
GetFirstVideoContentDescription(remote_description()->description());
const cricket::RtpDataContentDescription* rtp_data_desc =
GetFirstRtpDataContentDescription(remote_description()->description());
const cricket::DataContentDescription* data_desc =
GetFirstDataContentDescription(remote_description()->description());
// Check if the descriptions include streams, just in case the peer supports
// MSID, but doesn't indicate so with "a=msid-semantic".
@ -2876,10 +2887,12 @@ RTCError PeerConnection::ApplyRemoteDescription(
}
}
// If this is an RTP data transport, update the DataChannels with the
// information from the remote peer.
if (rtp_data_desc) {
UpdateRemoteRtpDataChannels(GetActiveStreams(rtp_data_desc));
// Update the DataChannels with the information from the remote peer.
if (data_desc) {
if (absl::StartsWith(data_desc->protocol(),
cricket::kMediaProtocolRtpPrefix)) {
UpdateRemoteRtpDataChannels(GetActiveStreams(data_desc));
}
}
// Iterate new_streams and notify the observer about new MediaStreams.

View File

@ -193,11 +193,14 @@ class PeerConnectionDataChannelBaseTest : public ::testing::Test {
// Changes the SCTP data channel port on the given session description.
void ChangeSctpPortOnDescription(cricket::SessionDescription* desc,
int port) {
cricket::DataCodec sctp_codec(cricket::kGoogleSctpDataCodecPlType,
cricket::kGoogleSctpDataCodecName);
sctp_codec.SetParam(cricket::kCodecParamPort, port);
auto* data_content = cricket::GetFirstDataContent(desc);
RTC_DCHECK(data_content);
auto* data_desc = data_content->media_description()->as_sctp();
RTC_DCHECK(data_desc);
data_desc->set_port(port);
auto* data_desc = data_content->media_description()->as_data();
data_desc->set_codecs({sctp_codec});
}
std::unique_ptr<rtc::VirtualSocketServer> vss_;

View File

@ -3450,8 +3450,8 @@ TEST_P(PeerConnectionIntegrationTest, SctpDataChannelToAudioVideoUpgrade) {
}
static void MakeSpecCompliantSctpOffer(cricket::SessionDescription* desc) {
cricket::SctpDataContentDescription* dcd_offer =
GetFirstSctpDataContentDescription(desc);
cricket::DataContentDescription* dcd_offer =
GetFirstDataContentDescription(desc);
ASSERT_TRUE(dcd_offer);
dcd_offer->set_use_sctpmap(false);
dcd_offer->set_protocol("UDP/DTLS/SCTP");

View File

@ -15,7 +15,6 @@
#include "absl/algorithm/container.h"
#include "absl/memory/memory.h"
#include "pc/media_protocol_names.h"
#include "rtc_base/checks.h"
namespace cricket {
@ -184,24 +183,6 @@ void SessionDescription::AddContent(const std::string& name,
}
void SessionDescription::AddContent(ContentInfo* content) {
// Unwrap the as_data shim layer before using.
auto* description = content->media_description();
bool should_delete = false;
if (description->as_rtp_data()) {
if (description->as_rtp_data() != description) {
content->set_media_description(
description->as_data()->Unshim(&should_delete));
}
}
if (description->as_sctp()) {
if (description->as_sctp() != description) {
content->set_media_description(
description->as_data()->Unshim(&should_delete));
}
}
if (should_delete) {
delete description;
}
if (extmap_allow_mixed()) {
// Mixed support on session level overrides setting on media level.
content->description->set_extmap_allow_mixed_enum(
@ -291,404 +272,4 @@ const ContentGroup* SessionDescription::GetGroupByName(
return NULL;
}
// DataContentDescription shim creation
DataContentDescription* RtpDataContentDescription::as_data() {
if (!shim_) {
shim_.reset(new DataContentDescription(this));
}
return shim_.get();
}
const DataContentDescription* RtpDataContentDescription::as_data() const {
return const_cast<RtpDataContentDescription*>(this)->as_data();
}
DataContentDescription* SctpDataContentDescription::as_data() {
if (!shim_) {
shim_.reset(new DataContentDescription(this));
}
return shim_.get();
}
const DataContentDescription* SctpDataContentDescription::as_data() const {
return const_cast<SctpDataContentDescription*>(this)->as_data();
}
DataContentDescription::DataContentDescription() {
// In this case, we will initialize |owned_description_| as soon as
// we are told what protocol to use via set_protocol or another function
// calling CreateShimTarget.
}
DataContentDescription::DataContentDescription(
SctpDataContentDescription* wrapped)
: real_description_(wrapped) {
// SctpDataContentDescription doesn't contain codecs, but code
// using DataContentDescription expects to see one.
Super::AddCodec(
cricket::DataCodec(kGoogleSctpDataCodecPlType, kGoogleSctpDataCodecName));
}
DataContentDescription::DataContentDescription(
RtpDataContentDescription* wrapped)
: real_description_(wrapped) {}
DataContentDescription::DataContentDescription(
const DataContentDescription* o) {
if (o->real_description_) {
owned_description_ = absl::WrapUnique(o->real_description_->Copy());
real_description_ = owned_description_.get();
}
}
void DataContentDescription::CreateShimTarget(bool is_sctp) {
RTC_LOG(LS_INFO) << "Creating shim target, is_sctp is " << is_sctp;
RTC_CHECK(!owned_description_.get());
if (is_sctp) {
owned_description_ = absl::make_unique<SctpDataContentDescription>();
// Copy all information collected so far, except codecs.
owned_description_->MediaContentDescription::operator=(*this);
} else {
owned_description_ = absl::make_unique<RtpDataContentDescription>();
// Copy all information collected so far, including codecs.
owned_description_->as_rtp_data()
->MediaContentDescriptionImpl<RtpDataCodec>::operator=(*this);
}
real_description_ = owned_description_.get();
}
MediaContentDescription* DataContentDescription::Unshim(bool* should_delete) {
if (owned_description_) {
// Pass ownership to caller, and remove myself.
// Since caller can't know if I was owner or owned, tell them.
MediaContentDescription* to_return = owned_description_.release();
*should_delete = true;
return to_return;
}
// Real object is owner, and presumably referenced from elsewhere.
*should_delete = false;
return real_description_;
}
void DataContentDescription::set_protocol(const std::string& protocol) {
if (real_description_) {
real_description_->set_protocol(protocol);
} else {
CreateShimTarget(IsSctpProtocol(protocol));
}
}
bool DataContentDescription::IsSctp() const {
return (real_description_ && real_description_->as_sctp());
}
void DataContentDescription::EnsureIsRtp() {
RTC_CHECK(real_description_);
RTC_CHECK(real_description_->as_rtp_data());
}
RtpDataContentDescription* DataContentDescription::as_rtp_data() {
if (real_description_) {
return real_description_->as_rtp_data();
}
return nullptr;
}
SctpDataContentDescription* DataContentDescription::as_sctp() {
if (real_description_) {
return real_description_->as_sctp();
}
return nullptr;
}
// Override all methods defined in MediaContentDescription.
bool DataContentDescription::has_codecs() const {
if (!real_description_) {
return Super::has_codecs();
}
return real_description_->has_codecs();
}
std::string DataContentDescription::protocol() const {
if (!real_description_) {
return Super::protocol();
}
return real_description_->protocol();
}
webrtc::RtpTransceiverDirection DataContentDescription::direction() const {
if (!real_description_) {
return Super::direction();
}
return real_description_->direction();
}
void DataContentDescription::set_direction(
webrtc::RtpTransceiverDirection direction) {
if (!real_description_) {
return Super::set_direction(direction);
}
return real_description_->set_direction(direction);
}
bool DataContentDescription::rtcp_mux() const {
if (!real_description_) {
return Super::rtcp_mux();
}
return real_description_->rtcp_mux();
}
void DataContentDescription::set_rtcp_mux(bool mux) {
if (!real_description_) {
Super::set_rtcp_mux(mux);
return;
}
real_description_->set_rtcp_mux(mux);
}
bool DataContentDescription::rtcp_reduced_size() const {
if (!real_description_) {
return Super::rtcp_reduced_size();
}
return real_description_->rtcp_reduced_size();
}
void DataContentDescription::set_rtcp_reduced_size(bool reduced_size) {
if (!real_description_) {
return Super::set_rtcp_reduced_size(reduced_size);
}
return real_description_->set_rtcp_reduced_size(reduced_size);
}
int DataContentDescription::bandwidth() const {
if (!real_description_) {
return Super::bandwidth();
}
return real_description_->bandwidth();
}
void DataContentDescription::set_bandwidth(int bandwidth) {
if (!real_description_) {
return Super::set_bandwidth(bandwidth);
}
return real_description_->set_bandwidth(bandwidth);
}
const std::vector<CryptoParams>& DataContentDescription::cryptos() const {
if (!real_description_) {
return Super::cryptos();
}
return real_description_->cryptos();
}
void DataContentDescription::AddCrypto(const CryptoParams& params) {
if (!real_description_) {
return Super::AddCrypto(params);
}
return real_description_->AddCrypto(params);
}
void DataContentDescription::set_cryptos(
const std::vector<CryptoParams>& cryptos) {
if (!real_description_) {
return Super::set_cryptos(cryptos);
}
return real_description_->set_cryptos(cryptos);
}
const RtpHeaderExtensions& DataContentDescription::rtp_header_extensions()
const {
if (!real_description_) {
return Super::rtp_header_extensions();
}
return real_description_->rtp_header_extensions();
}
void DataContentDescription::set_rtp_header_extensions(
const RtpHeaderExtensions& extensions) {
if (!real_description_) {
return Super::set_rtp_header_extensions(extensions);
}
return real_description_->set_rtp_header_extensions(extensions);
}
void DataContentDescription::AddRtpHeaderExtension(
const webrtc::RtpExtension& ext) {
if (!real_description_) {
return Super::AddRtpHeaderExtension(ext);
}
return real_description_->AddRtpHeaderExtension(ext);
}
void DataContentDescription::AddRtpHeaderExtension(
const cricket::RtpHeaderExtension& ext) {
if (!real_description_) {
return Super::AddRtpHeaderExtension(ext);
}
return real_description_->AddRtpHeaderExtension(ext);
}
void DataContentDescription::ClearRtpHeaderExtensions() {
if (!real_description_) {
return Super::ClearRtpHeaderExtensions();
}
return real_description_->ClearRtpHeaderExtensions();
}
bool DataContentDescription::rtp_header_extensions_set() const {
if (!real_description_) {
return Super::rtp_header_extensions_set();
}
return real_description_->rtp_header_extensions_set();
}
const StreamParamsVec& DataContentDescription::streams() const {
if (!real_description_) {
return Super::streams();
}
return real_description_->streams();
}
StreamParamsVec& DataContentDescription::mutable_streams() {
if (!real_description_) {
return Super::mutable_streams();
}
EnsureIsRtp();
return real_description_->mutable_streams();
}
void DataContentDescription::AddStream(const StreamParams& stream) {
if (!real_description_) {
return Super::AddStream(stream);
}
EnsureIsRtp();
return real_description_->AddStream(stream);
}
void DataContentDescription::SetCnameIfEmpty(const std::string& cname) {
if (!real_description_) {
return Super::SetCnameIfEmpty(cname);
}
return real_description_->SetCnameIfEmpty(cname);
}
uint32_t DataContentDescription::first_ssrc() const {
if (!real_description_) {
return Super::first_ssrc();
}
return real_description_->first_ssrc();
}
bool DataContentDescription::has_ssrcs() const {
if (!real_description_) {
return Super::has_ssrcs();
}
return real_description_->has_ssrcs();
}
void DataContentDescription::set_conference_mode(bool enable) {
if (!real_description_) {
return Super::set_conference_mode(enable);
}
return real_description_->set_conference_mode(enable);
}
bool DataContentDescription::conference_mode() const {
if (!real_description_) {
return Super::conference_mode();
}
return real_description_->conference_mode();
}
void DataContentDescription::set_connection_address(
const rtc::SocketAddress& address) {
if (!real_description_) {
return Super::set_connection_address(address);
}
return real_description_->set_connection_address(address);
}
const rtc::SocketAddress& DataContentDescription::connection_address() const {
if (!real_description_) {
return Super::connection_address();
}
return real_description_->connection_address();
}
void DataContentDescription::set_extmap_allow_mixed_enum(
ExtmapAllowMixed mixed) {
if (!real_description_) {
return Super::set_extmap_allow_mixed_enum(mixed);
}
return real_description_->set_extmap_allow_mixed_enum(mixed);
}
MediaContentDescription::ExtmapAllowMixed
DataContentDescription::extmap_allow_mixed_enum() const {
if (!real_description_) {
return Super::extmap_allow_mixed_enum();
}
return real_description_->extmap_allow_mixed_enum();
}
bool DataContentDescription::HasSimulcast() const {
if (!real_description_) {
return Super::HasSimulcast();
}
return real_description_->HasSimulcast();
}
SimulcastDescription& DataContentDescription::simulcast_description() {
if (!real_description_) {
return Super::simulcast_description();
}
return real_description_->simulcast_description();
}
const SimulcastDescription& DataContentDescription::simulcast_description()
const {
if (!real_description_) {
return Super::simulcast_description();
}
return real_description_->simulcast_description();
}
void DataContentDescription::set_simulcast_description(
const SimulcastDescription& simulcast) {
if (!real_description_) {
return Super::set_simulcast_description(simulcast);
}
return real_description_->set_simulcast_description(simulcast);
}
// Methods defined in MediaContentDescriptionImpl.
// For SCTP, we implement codec handling.
// For RTP, we pass the codecs.
// In the cases where type hasn't been decided yet, we return dummies.
const std::vector<DataCodec>& DataContentDescription::codecs() const {
if (IsSctp() || !real_description_) {
return Super::codecs();
}
return real_description_->as_rtp_data()->codecs();
}
void DataContentDescription::set_codecs(const std::vector<DataCodec>& codecs) {
if (IsSctp() || !real_description_) {
Super::set_codecs(codecs);
} else {
EnsureIsRtp();
real_description_->as_rtp_data()->set_codecs(codecs);
}
}
bool DataContentDescription::HasCodec(int id) {
if (IsSctp() || !real_description_) {
return Super::HasCodec(id);
}
return real_description_->as_rtp_data()->HasCodec(id);
}
void DataContentDescription::AddCodec(const DataCodec& codec) {
if (IsSctp() || !real_description_) {
Super::AddCodec(codec);
} else {
EnsureIsRtp();
real_description_->as_rtp_data()->AddCodec(codec);
}
}
void DataContentDescription::AddOrReplaceCodec(const DataCodec& codec) {
if (IsSctp() || real_description_) {
Super::AddOrReplaceCodec(codec);
} else {
EnsureIsRtp();
real_description_->as_rtp_data()->AddOrReplaceCodec(codec);
}
}
void DataContentDescription::AddCodecs(const std::vector<DataCodec>& codecs) {
if (IsSctp() || !real_description_) {
Super::AddCodecs(codecs);
} else {
EnsureIsRtp();
real_description_->as_rtp_data()->AddCodecs(codecs);
}
}
} // namespace cricket

View File

@ -18,7 +18,6 @@
#include <string>
#include <vector>
#include "absl/memory/memory.h"
#include "api/crypto_params.h"
#include "api/media_types.h"
#include "api/rtp_parameters.h"
@ -27,7 +26,6 @@
#include "media/base/stream_params.h"
#include "p2p/base/transport_description.h"
#include "p2p/base/transport_info.h"
#include "pc/media_protocol_names.h"
#include "pc/simulcast_description.h"
#include "rtc_base/socket_address.h"
@ -35,7 +33,7 @@ namespace cricket {
typedef std::vector<AudioCodec> AudioCodecs;
typedef std::vector<VideoCodec> VideoCodecs;
typedef std::vector<RtpDataCodec> RtpDataCodecs;
typedef std::vector<DataCodec> DataCodecs;
typedef std::vector<CryptoParams> CryptoParamsVec;
typedef std::vector<webrtc::RtpExtension> RtpHeaderExtensions;
@ -46,15 +44,19 @@ extern const char kMediaProtocolSavpf[];
extern const char kMediaProtocolDtlsSavpf[];
extern const char kMediaProtocolRtpPrefix[];
extern const char kMediaProtocolSctp[];
extern const char kMediaProtocolDtlsSctp[];
extern const char kMediaProtocolUdpDtlsSctp[];
extern const char kMediaProtocolTcpDtlsSctp[];
// Options to control how session descriptions are generated.
const int kAutoBandwidth = -1;
class AudioContentDescription;
class VideoContentDescription;
class DataContentDescription;
class RtpDataContentDescription;
class SctpDataContentDescription;
class VideoContentDescription;
// Describes a session description media section. There are subclasses for each
// media type (audio, video, data) that will have additional information.
@ -75,77 +77,61 @@ class MediaContentDescription {
virtual VideoContentDescription* as_video() { return nullptr; }
virtual const VideoContentDescription* as_video() const { return nullptr; }
// Backwards compatible shim: Return a shim object that allows
// callers to ignore the distinction between RtpDataContentDescription
// and SctpDataContentDescription objects.
// Try to cast this media description to a DataContentDescription. Returns
// nullptr if the cast fails.
virtual DataContentDescription* as_data() { return nullptr; }
virtual const DataContentDescription* as_data() const { return nullptr; }
virtual RtpDataContentDescription* as_rtp_data() { return nullptr; }
virtual const RtpDataContentDescription* as_rtp_data() const {
return nullptr;
}
virtual SctpDataContentDescription* as_sctp() { return nullptr; }
virtual const SctpDataContentDescription* as_sctp() const { return nullptr; }
virtual bool has_codecs() const = 0;
virtual MediaContentDescription* Copy() const = 0;
// |protocol| is the expected media transport protocol, such as RTP/AVPF,
// RTP/SAVPF or SCTP/DTLS.
virtual std::string protocol() const { return protocol_; }
virtual void set_protocol(const std::string& protocol) {
protocol_ = protocol;
}
std::string protocol() const { return protocol_; }
void set_protocol(const std::string& protocol) { protocol_ = protocol; }
virtual webrtc::RtpTransceiverDirection direction() const {
return direction_;
}
virtual void set_direction(webrtc::RtpTransceiverDirection direction) {
webrtc::RtpTransceiverDirection direction() const { return direction_; }
void set_direction(webrtc::RtpTransceiverDirection direction) {
direction_ = direction;
}
virtual bool rtcp_mux() const { return rtcp_mux_; }
virtual void set_rtcp_mux(bool mux) { rtcp_mux_ = mux; }
bool rtcp_mux() const { return rtcp_mux_; }
void set_rtcp_mux(bool mux) { rtcp_mux_ = mux; }
virtual bool rtcp_reduced_size() const { return rtcp_reduced_size_; }
virtual void set_rtcp_reduced_size(bool reduced_size) {
bool rtcp_reduced_size() const { return rtcp_reduced_size_; }
void set_rtcp_reduced_size(bool reduced_size) {
rtcp_reduced_size_ = reduced_size;
}
virtual int bandwidth() const { return bandwidth_; }
virtual void set_bandwidth(int bandwidth) { bandwidth_ = bandwidth; }
int bandwidth() const { return bandwidth_; }
void set_bandwidth(int bandwidth) { bandwidth_ = bandwidth; }
virtual const std::vector<CryptoParams>& cryptos() const { return cryptos_; }
virtual void AddCrypto(const CryptoParams& params) {
cryptos_.push_back(params);
}
virtual void set_cryptos(const std::vector<CryptoParams>& cryptos) {
const std::vector<CryptoParams>& cryptos() const { return cryptos_; }
void AddCrypto(const CryptoParams& params) { cryptos_.push_back(params); }
void set_cryptos(const std::vector<CryptoParams>& cryptos) {
cryptos_ = cryptos;
}
virtual const RtpHeaderExtensions& rtp_header_extensions() const {
const RtpHeaderExtensions& rtp_header_extensions() const {
return rtp_header_extensions_;
}
virtual void set_rtp_header_extensions(
const RtpHeaderExtensions& extensions) {
void set_rtp_header_extensions(const RtpHeaderExtensions& extensions) {
rtp_header_extensions_ = extensions;
rtp_header_extensions_set_ = true;
}
virtual void AddRtpHeaderExtension(const webrtc::RtpExtension& ext) {
void AddRtpHeaderExtension(const webrtc::RtpExtension& ext) {
rtp_header_extensions_.push_back(ext);
rtp_header_extensions_set_ = true;
}
virtual void AddRtpHeaderExtension(const cricket::RtpHeaderExtension& ext) {
void AddRtpHeaderExtension(const cricket::RtpHeaderExtension& ext) {
webrtc::RtpExtension webrtc_extension;
webrtc_extension.uri = ext.uri;
webrtc_extension.id = ext.id;
rtp_header_extensions_.push_back(webrtc_extension);
rtp_header_extensions_set_ = true;
}
virtual void ClearRtpHeaderExtensions() {
void ClearRtpHeaderExtensions() {
rtp_header_extensions_.clear();
rtp_header_extensions_set_ = true;
}
@ -154,65 +140,62 @@ class MediaContentDescription {
// signal them. For now we assume an empty list means no signaling, but
// provide the ClearRtpHeaderExtensions method to allow "no support" to be
// clearly indicated (i.e. when derived from other information).
virtual bool rtp_header_extensions_set() const {
return rtp_header_extensions_set_;
}
virtual const StreamParamsVec& streams() const { return send_streams_; }
bool rtp_header_extensions_set() const { return rtp_header_extensions_set_; }
const StreamParamsVec& streams() const { return send_streams_; }
// TODO(pthatcher): Remove this by giving mediamessage.cc access
// to MediaContentDescription
virtual StreamParamsVec& mutable_streams() { return send_streams_; }
virtual void AddStream(const StreamParams& stream) {
StreamParamsVec& mutable_streams() { return send_streams_; }
void AddStream(const StreamParams& stream) {
send_streams_.push_back(stream);
}
// Legacy streams have an ssrc, but nothing else.
void AddLegacyStream(uint32_t ssrc) {
AddStream(StreamParams::CreateLegacy(ssrc));
send_streams_.push_back(StreamParams::CreateLegacy(ssrc));
}
void AddLegacyStream(uint32_t ssrc, uint32_t fid_ssrc) {
StreamParams sp = StreamParams::CreateLegacy(ssrc);
sp.AddFidSsrc(ssrc, fid_ssrc);
AddStream(sp);
send_streams_.push_back(sp);
}
// Sets the CNAME of all StreamParams if it have not been set.
virtual void SetCnameIfEmpty(const std::string& cname) {
void SetCnameIfEmpty(const std::string& cname) {
for (cricket::StreamParamsVec::iterator it = send_streams_.begin();
it != send_streams_.end(); ++it) {
if (it->cname.empty())
it->cname = cname;
}
}
virtual uint32_t first_ssrc() const {
uint32_t first_ssrc() const {
if (send_streams_.empty()) {
return 0;
}
return send_streams_[0].first_ssrc();
}
virtual bool has_ssrcs() const {
bool has_ssrcs() const {
if (send_streams_.empty()) {
return false;
}
return send_streams_[0].has_ssrcs();
}
virtual void set_conference_mode(bool enable) { conference_mode_ = enable; }
virtual bool conference_mode() const { return conference_mode_; }
void set_conference_mode(bool enable) { conference_mode_ = enable; }
bool conference_mode() const { return conference_mode_; }
// https://tools.ietf.org/html/rfc4566#section-5.7
// May be present at the media or session level of SDP. If present at both
// levels, the media-level attribute overwrites the session-level one.
virtual void set_connection_address(const rtc::SocketAddress& address) {
void set_connection_address(const rtc::SocketAddress& address) {
connection_address_ = address;
}
virtual const rtc::SocketAddress& connection_address() const {
const rtc::SocketAddress& connection_address() const {
return connection_address_;
}
// Determines if it's allowed to mix one- and two-byte rtp header extensions
// within the same rtp stream.
enum ExtmapAllowMixed { kNo, kSession, kMedia };
virtual void set_extmap_allow_mixed_enum(
ExtmapAllowMixed new_extmap_allow_mixed) {
void set_extmap_allow_mixed_enum(ExtmapAllowMixed new_extmap_allow_mixed) {
if (new_extmap_allow_mixed == kMedia &&
extmap_allow_mixed_enum_ == kSession) {
// Do not downgrade from session level to media level.
@ -220,12 +203,10 @@ class MediaContentDescription {
}
extmap_allow_mixed_enum_ = new_extmap_allow_mixed;
}
virtual ExtmapAllowMixed extmap_allow_mixed_enum() const {
ExtmapAllowMixed extmap_allow_mixed_enum() const {
return extmap_allow_mixed_enum_;
}
virtual bool extmap_allow_mixed() const {
return extmap_allow_mixed_enum_ != kNo;
}
bool extmap_allow_mixed() const { return extmap_allow_mixed_enum_ != kNo; }
// Simulcast functionality.
virtual bool HasSimulcast() const { return !simulcast_.empty(); }
@ -266,18 +247,13 @@ using ContentDescription = MediaContentDescription;
template <class C>
class MediaContentDescriptionImpl : public MediaContentDescription {
public:
void set_protocol(const std::string& protocol) override {
RTC_DCHECK(IsRtpProtocol(protocol));
protocol_ = protocol;
}
typedef C CodecType;
// Codecs should be in preference order (most preferred codec first).
virtual const std::vector<C>& codecs() const { return codecs_; }
virtual void set_codecs(const std::vector<C>& codecs) { codecs_ = codecs; }
bool has_codecs() const override { return !codecs_.empty(); }
virtual bool HasCodec(int id) {
const std::vector<C>& codecs() const { return codecs_; }
void set_codecs(const std::vector<C>& codecs) { codecs_ = codecs; }
virtual bool has_codecs() const { return !codecs_.empty(); }
bool HasCodec(int id) {
bool found = false;
for (typename std::vector<C>::iterator iter = codecs_.begin();
iter != codecs_.end(); ++iter) {
@ -288,8 +264,8 @@ class MediaContentDescriptionImpl : public MediaContentDescription {
}
return found;
}
virtual void AddCodec(const C& codec) { codecs_.push_back(codec); }
virtual void AddOrReplaceCodec(const C& codec) {
void AddCodec(const C& codec) { codecs_.push_back(codec); }
void AddOrReplaceCodec(const C& codec) {
for (typename std::vector<C>::iterator iter = codecs_.begin();
iter != codecs_.end(); ++iter) {
if (iter->id == codec.id) {
@ -299,7 +275,7 @@ class MediaContentDescriptionImpl : public MediaContentDescription {
}
AddCodec(codec);
}
virtual void AddCodecs(const std::vector<C>& codecs) {
void AddCodecs(const std::vector<C>& codecs) {
typename std::vector<C>::const_iterator codec;
for (codec = codecs.begin(); codec != codecs.end(); ++codec) {
AddCodec(*codec);
@ -332,173 +308,22 @@ class VideoContentDescription : public MediaContentDescriptionImpl<VideoCodec> {
virtual const VideoContentDescription* as_video() const { return this; }
};
// The DataContentDescription is a shim over the RtpDataContentDescription
// and SctpDataContentDescription classes that is used for external callers
// into this internal API.
// It is a templated derivation of MediaContentDescriptionImpl because
// that's what the external caller expects it to be.
// TODO(bugs.webrtc.org/10597): Declare this class obsolete and remove it
// once external callers have been updated.
class DataContentDescription : public MediaContentDescriptionImpl<DataCodec> {
public:
DataContentDescription();
MediaType type() const override { return MEDIA_TYPE_DATA; }
DataContentDescription* as_data() override { return this; }
const DataContentDescription* as_data() const override { return this; }
DataContentDescription() {}
// Override all methods defined in MediaContentDescription.
bool has_codecs() const override;
DataContentDescription* Copy() const override {
return new DataContentDescription(this);
}
std::string protocol() const override;
void set_protocol(const std::string& protocol) override;
webrtc::RtpTransceiverDirection direction() const override;
void set_direction(webrtc::RtpTransceiverDirection direction) override;
bool rtcp_mux() const override;
void set_rtcp_mux(bool mux) override;
bool rtcp_reduced_size() const override;
void set_rtcp_reduced_size(bool) override;
int bandwidth() const override;
void set_bandwidth(int bandwidth) override;
const std::vector<CryptoParams>& cryptos() const override;
void AddCrypto(const CryptoParams& params) override;
void set_cryptos(const std::vector<CryptoParams>& cryptos) override;
const RtpHeaderExtensions& rtp_header_extensions() const override;
void set_rtp_header_extensions(
const RtpHeaderExtensions& extensions) override;
void AddRtpHeaderExtension(const webrtc::RtpExtension& ext) override;
void AddRtpHeaderExtension(const cricket::RtpHeaderExtension& ext) override;
void ClearRtpHeaderExtensions() override;
bool rtp_header_extensions_set() const override;
const StreamParamsVec& streams() const override;
StreamParamsVec& mutable_streams() override;
void AddStream(const StreamParams& stream) override;
void SetCnameIfEmpty(const std::string& cname) override;
uint32_t first_ssrc() const override;
bool has_ssrcs() const override;
void set_conference_mode(bool enable) override;
bool conference_mode() const override;
void set_connection_address(const rtc::SocketAddress& address) override;
const rtc::SocketAddress& connection_address() const override;
void set_extmap_allow_mixed_enum(ExtmapAllowMixed) override;
ExtmapAllowMixed extmap_allow_mixed_enum() const override;
bool HasSimulcast() const override;
SimulcastDescription& simulcast_description() override;
const SimulcastDescription& simulcast_description() const override;
void set_simulcast_description(
const SimulcastDescription& simulcast) override;
// Override all methods defined in MediaContentDescriptionImpl.
const std::vector<CodecType>& codecs() const override;
void set_codecs(const std::vector<CodecType>& codecs) override;
bool HasCodec(int id) override;
void AddCodec(const CodecType& codec) override;
void AddOrReplaceCodec(const CodecType& codec) override;
void AddCodecs(const std::vector<CodecType>& codec) override;
private:
typedef MediaContentDescriptionImpl<DataCodec> Super;
// Friend classes are allowed to create proxies for themselves.
friend class RtpDataContentDescription; // for constructors
friend class SctpDataContentDescription;
friend class SessionDescription; // for Unshim()
// Copy constructor. A copy results in an object that owns its
// real description, which is a copy of the original description
// (whether that was owned or not).
explicit DataContentDescription(const DataContentDescription* o);
explicit DataContentDescription(RtpDataContentDescription*);
explicit DataContentDescription(SctpDataContentDescription*);
// Exposed for internal use - new clients should not use this class.
RtpDataContentDescription* as_rtp_data() override;
SctpDataContentDescription* as_sctp() override;
// Create a shimmed object, owned by the shim.
void CreateShimTarget(bool is_sctp);
// Return the shimmed object, passing ownership if owned, and set
// |should_delete| to true if it was the owner. If |should_delete|
// is true on return, the caller should immediately delete the
// DataContentDescription object.
MediaContentDescription* Unshim(bool* should_delete);
// Returns whether SCTP is in use. False when it's not decided.
bool IsSctp() const;
// Check function for use when caller obviously assumes RTP.
void EnsureIsRtp();
MediaContentDescription* real_description_ = nullptr;
std::unique_ptr<MediaContentDescription> owned_description_;
};
class RtpDataContentDescription
: public MediaContentDescriptionImpl<RtpDataCodec> {
public:
RtpDataContentDescription() {}
RtpDataContentDescription(const RtpDataContentDescription& o)
: MediaContentDescriptionImpl<RtpDataCodec>(o), shim_(nullptr) {}
RtpDataContentDescription& operator=(const RtpDataContentDescription& o) {
this->MediaContentDescriptionImpl<RtpDataCodec>::operator=(o);
// Do not copy the shim.
return *this;
}
RtpDataContentDescription* Copy() const override {
return new RtpDataContentDescription(*this);
}
MediaType type() const override { return MEDIA_TYPE_DATA; }
RtpDataContentDescription* as_rtp_data() override { return this; }
const RtpDataContentDescription* as_rtp_data() const override { return this; }
// Shim support
DataContentDescription* as_data() override;
const DataContentDescription* as_data() const override;
private:
std::unique_ptr<DataContentDescription> shim_;
};
class SctpDataContentDescription : public MediaContentDescription {
public:
SctpDataContentDescription() {}
SctpDataContentDescription(const SctpDataContentDescription& o)
: MediaContentDescription(o),
use_sctpmap_(o.use_sctpmap_),
port_(o.port_),
max_message_size_(o.max_message_size_),
shim_(nullptr) {}
SctpDataContentDescription* Copy() const override {
return new SctpDataContentDescription(*this);
}
MediaType type() const override { return MEDIA_TYPE_DATA; }
SctpDataContentDescription* as_sctp() override { return this; }
const SctpDataContentDescription* as_sctp() const override { return this; }
// Shim support
DataContentDescription* as_data() override;
const DataContentDescription* as_data() const override;
bool has_codecs() const override { return false; }
void set_protocol(const std::string& protocol) override {
RTC_DCHECK(IsSctpProtocol(protocol));
protocol_ = protocol;
virtual DataContentDescription* Copy() const {
return new DataContentDescription(*this);
}
virtual MediaType type() const { return MEDIA_TYPE_DATA; }
virtual DataContentDescription* as_data() { return this; }
virtual const DataContentDescription* as_data() const { return this; }
bool use_sctpmap() const { return use_sctpmap_; }
void set_use_sctpmap(bool enable) { use_sctpmap_ = enable; }
int port() const { return port_; }
void set_port(int port) { port_ = port; }
int max_message_size() const { return max_message_size_; }
void set_max_message_size(int max_message_size) {
max_message_size_ = max_message_size;
}
private:
bool use_sctpmap_ = true; // Note: "true" is no longer conformant.
// Defaults should be constants imported from SCTP. Quick hack.
int port_ = 5000;
int max_message_size_ = 256 * 1024;
std::unique_ptr<DataContentDescription> shim_;
bool use_sctpmap_ = true;
};
// Protocol used for encoding media. This is the "top level" protocol that may

View File

@ -9,7 +9,6 @@
*/
#include "pc/session_description.h"
#include "absl/memory/memory.h"
#include "test/gtest.h"
namespace cricket {
@ -122,69 +121,11 @@ TEST(SessionDescriptionTest, AddContentTransfersExtmapAllowMixedSetting) {
video_desc->extmap_allow_mixed_enum());
// Session level setting overrides media level when new content is added.
MediaContentDescription* data_desc = new RtpDataContentDescription;
MediaContentDescription* data_desc = new DataContentDescription;
data_desc->set_extmap_allow_mixed_enum(MediaContentDescription::kMedia);
session_desc.AddContent("data", MediaProtocolType::kRtp, data_desc);
EXPECT_EQ(MediaContentDescription::kSession,
data_desc->extmap_allow_mixed_enum());
}
TEST(SessionDescriptionTest, DataContentDescriptionCanAddStream) {
auto description = absl::make_unique<DataContentDescription>();
// Adding a stream without setting protocol first should work.
description->AddLegacyStream(1234);
EXPECT_EQ(1UL, description->streams().size());
}
TEST(SessionDescriptionTest, DataContentDescriptionCopyWorks) {
auto description = absl::make_unique<RtpDataContentDescription>();
auto shim_description = description->as_data();
auto shim_copy = shim_description->Copy();
delete shim_copy;
}
TEST(SessionDescriptionTest, DataContentDescriptionCodecsCallableOnNull) {
auto shim_description = absl::make_unique<DataContentDescription>();
auto codec_list = shim_description->codecs();
EXPECT_EQ(0UL, codec_list.size());
}
TEST(SessionDescriptionTest, DataContentDescriptionSctpConferenceMode) {
auto description = absl::make_unique<SctpDataContentDescription>();
auto shim_description = description->as_data();
EXPECT_FALSE(shim_description->conference_mode());
shim_description->set_conference_mode(true);
EXPECT_TRUE(shim_description->conference_mode());
}
TEST(SessionDescriptionTest, DataContentDesriptionInSessionIsUnwrapped) {
auto description = absl::make_unique<DataContentDescription>();
// Create a DTLS object behind the shim.
description->set_protocol(kMediaProtocolUdpDtlsSctp);
SessionDescription session;
session.AddContent("name", MediaProtocolType::kSctp, description.release());
ContentInfo* content = &(session.contents()[0]);
ASSERT_TRUE(content);
ASSERT_TRUE(content->media_description()->type() == MEDIA_TYPE_DATA);
ASSERT_TRUE(content->media_description()->as_sctp());
}
TEST(SessionDescriptionTest,
DataContentDescriptionInfoSurvivesInstantiationAsSctp) {
auto description = absl::make_unique<DataContentDescription>();
description->set_rtcp_mux(true);
description->set_protocol(kMediaProtocolUdpDtlsSctp);
EXPECT_TRUE(description->rtcp_mux());
}
TEST(SessionDescriptionTest,
DataContentDescriptionStreamInfoSurvivesInstantiationAsRtp) {
auto description = absl::make_unique<DataContentDescription>();
StreamParams stream;
description->AddLegacyStream(1234);
EXPECT_EQ(1UL, description->streams().size());
description->set_protocol(kMediaProtocolDtlsSavpf);
EXPECT_EQ(1UL, description->streams().size());
}
} // namespace cricket

View File

@ -54,31 +54,29 @@ using cricket::Candidates;
using cricket::ContentInfo;
using cricket::CryptoParams;
using cricket::DataContentDescription;
using cricket::ICE_CANDIDATE_COMPONENT_RTCP;
using cricket::ICE_CANDIDATE_COMPONENT_RTP;
using cricket::kCodecParamAssociatedPayloadType;
using cricket::kCodecParamMaxAverageBitrate;
using cricket::ICE_CANDIDATE_COMPONENT_RTCP;
using cricket::kCodecParamMaxBitrate;
using cricket::kCodecParamMaxPlaybackRate;
using cricket::kCodecParamMaxPTime;
using cricket::kCodecParamMaxQuantization;
using cricket::kCodecParamMinBitrate;
using cricket::kCodecParamMinPTime;
using cricket::kCodecParamPTime;
using cricket::kCodecParamSctpProtocol;
using cricket::kCodecParamSctpStreams;
using cricket::kCodecParamSPropStereo;
using cricket::kCodecParamStartBitrate;
using cricket::kCodecParamStereo;
using cricket::kCodecParamUseDtx;
using cricket::kCodecParamUseInbandFec;
using cricket::kCodecParamUseDtx;
using cricket::kCodecParamSctpProtocol;
using cricket::kCodecParamSctpStreams;
using cricket::kCodecParamMaxAverageBitrate;
using cricket::kCodecParamMaxPlaybackRate;
using cricket::kCodecParamAssociatedPayloadType;
using cricket::MediaContentDescription;
using cricket::MediaProtocolType;
using cricket::MediaType;
using cricket::RidDescription;
using cricket::RtpDataContentDescription;
using cricket::RtpHeaderExtensions;
using cricket::SctpDataContentDescription;
using cricket::MediaProtocolType;
using cricket::RidDescription;
using cricket::SimulcastDescription;
using cricket::SimulcastLayer;
using cricket::SimulcastLayerList;
@ -1339,6 +1337,8 @@ void BuildMediaDescription(const ContentInfo* content_info,
const MediaContentDescription* media_desc = content_info->media_description();
RTC_DCHECK(media_desc);
int sctp_port = cricket::kSctpDefaultPort;
// RFC 4566
// m=<media> <port> <proto> <fmt>
// fmt is a list of payload type numbers that MAY be used in the session.
@ -1366,19 +1366,25 @@ void BuildMediaDescription(const ContentInfo* content_info,
fmt.append(rtc::ToString(codec.id));
}
} else if (media_type == cricket::MEDIA_TYPE_DATA) {
const DataContentDescription* data_desc = media_desc->as_data();
if (IsDtlsSctp(media_desc->protocol())) {
const cricket::SctpDataContentDescription* data_desc =
media_desc->as_sctp();
fmt.append(" ");
if (data_desc->use_sctpmap()) {
fmt.append(rtc::ToString(data_desc->port()));
for (const cricket::DataCodec& codec : data_desc->codecs()) {
if (absl::EqualsIgnoreCase(codec.name,
cricket::kGoogleSctpDataCodecName) &&
codec.GetParam(cricket::kCodecParamPort, &sctp_port)) {
break;
}
}
fmt.append(rtc::ToString(sctp_port));
} else {
fmt.append(kDefaultSctpmapProtocol);
}
} else {
const RtpDataContentDescription* data_desc = media_desc->as_rtp_data();
for (const cricket::RtpDataCodec& codec : data_desc->codecs()) {
for (const cricket::DataCodec& codec : data_desc->codecs()) {
fmt.append(" ");
fmt.append(rtc::ToString(codec.id));
}
@ -1517,10 +1523,9 @@ void BuildMediaDescription(const ContentInfo* content_info,
AddLine(os.str(), message);
if (IsDtlsSctp(media_desc->protocol())) {
const cricket::SctpDataContentDescription* data_desc =
media_desc->as_sctp();
const DataContentDescription* data_desc = media_desc->as_data();
bool use_sctpmap = data_desc->use_sctpmap();
BuildSctpContentAttributes(message, data_desc->port(), use_sctpmap);
BuildSctpContentAttributes(message, sctp_port, use_sctpmap);
} else if (IsRtp(media_desc->protocol())) {
BuildRtpContentAttributes(media_desc, media_type, msid_signaling, message);
}
@ -1829,6 +1834,43 @@ void AddRtcpFbLines(const T& codec, std::string* message) {
}
}
cricket::DataCodec FindOrMakeSctpDataCodec(DataContentDescription* media_desc) {
for (const auto& codec : media_desc->codecs()) {
if (absl::EqualsIgnoreCase(codec.name, cricket::kGoogleSctpDataCodecName)) {
return codec;
}
}
cricket::DataCodec codec_port(cricket::kGoogleSctpDataCodecPlType,
cricket::kGoogleSctpDataCodecName);
return codec_port;
}
bool AddOrModifySctpDataCodecPort(DataContentDescription* media_desc,
int sctp_port) {
// Add the SCTP Port number as a pseudo-codec "port" parameter
auto codec = FindOrMakeSctpDataCodec(media_desc);
int dummy;
if (codec.GetParam(cricket::kCodecParamPort, &dummy)) {
return false;
}
codec.SetParam(cricket::kCodecParamPort, sctp_port);
media_desc->AddOrReplaceCodec(codec);
return true;
}
bool AddOrModifySctpDataMaxMessageSize(DataContentDescription* media_desc,
int max_message_size) {
// Add the SCTP Max Message Size as a pseudo-parameter to the codec
auto codec = FindOrMakeSctpDataCodec(media_desc);
int dummy;
if (codec.GetParam(cricket::kCodecParamMaxMessageSize, &dummy)) {
return false;
}
codec.SetParam(cricket::kCodecParamMaxMessageSize, max_message_size);
media_desc->AddOrReplaceCodec(codec);
return true;
}
bool GetMinValue(const std::vector<int>& values, int* value) {
if (values.empty()) {
return false;
@ -1918,8 +1960,7 @@ void BuildRtpMap(const MediaContentDescription* media_desc,
AddAttributeLine(kCodecParamPTime, ptime, message);
}
} else if (media_type == cricket::MEDIA_TYPE_DATA) {
for (const cricket::RtpDataCodec& codec :
media_desc->as_rtp_data()->codecs()) {
for (const cricket::DataCodec& codec : media_desc->as_data()->codecs()) {
// RFC 4566
// a=rtpmap:<payload type> <encoding name>/<clock rate>
// [/<encodingparameters>]
@ -2707,36 +2748,24 @@ bool ParseMediaDescription(
payload_types, pos, &content_name, &bundle_only,
&section_msid_signaling, &transport, candidates, error);
} else if (HasAttribute(line, kMediaTypeData)) {
if (IsDtlsSctp(protocol)) {
// The draft-03 format is:
// m=application <port> DTLS/SCTP <sctp-port>...
// use_sctpmap should be false.
// The draft-26 format is:
// m=application <port> UDP/DTLS/SCTP webrtc-datachannel
// use_sctpmap should be false.
auto data_desc = absl::make_unique<SctpDataContentDescription>();
std::unique_ptr<DataContentDescription> data_desc =
ParseContentDescription<DataContentDescription>(
message, cricket::MEDIA_TYPE_DATA, mline_index, protocol,
payload_types, pos, &content_name, &bundle_only,
&section_msid_signaling, &transport, candidates, error);
if (data_desc && IsDtlsSctp(protocol)) {
int p;
if (rtc::FromString(fields[3], &p)) {
data_desc->set_port(p);
if (!AddOrModifySctpDataCodecPort(data_desc.get(), p)) {
return false;
}
} else if (fields[3] == kDefaultSctpmapProtocol) {
data_desc->set_use_sctpmap(false);
}
if (!ParseContent(message, cricket::MEDIA_TYPE_DATA, mline_index,
protocol, payload_types, pos, &content_name,
&bundle_only, &section_msid_signaling,
data_desc.get(), &transport, candidates, error)) {
return false;
}
content = std::move(data_desc);
} else {
// RTP
std::unique_ptr<RtpDataContentDescription> data_desc =
ParseContentDescription<RtpDataContentDescription>(
message, cricket::MEDIA_TYPE_DATA, mline_index, protocol,
payload_types, pos, &content_name, &bundle_only,
&section_msid_signaling, &transport, candidates, error);
content = std::move(data_desc);
}
content = std::move(data_desc);
} else {
RTC_LOG(LS_WARNING) << "Unsupported media type: " << line;
continue;
@ -3109,15 +3138,13 @@ bool ParseContent(const std::string& message,
line, "sctp-port attribute found in non-data media description.",
error);
}
if (media_desc->as_sctp()->use_sctpmap()) {
return ParseFailed(
line, "sctp-port attribute can't be used with sctpmap.", error);
}
int sctp_port;
if (!ParseSctpPort(line, &sctp_port, error)) {
return false;
}
media_desc->as_sctp()->set_port(sctp_port);
if (!AddOrModifySctpDataCodecPort(media_desc->as_data(), sctp_port)) {
return false;
}
} else if (IsDtlsSctp(protocol) &&
HasAttribute(line, kAttributeMaxMessageSize)) {
if (media_type != cricket::MEDIA_TYPE_DATA) {
@ -3130,7 +3157,10 @@ bool ParseContent(const std::string& message,
if (!ParseSctpMaxMessageSize(line, &max_message_size, error)) {
return false;
}
media_desc->as_sctp()->set_max_message_size(max_message_size);
if (!AddOrModifySctpDataMaxMessageSize(media_desc->as_data(),
max_message_size)) {
return false;
}
} else if (IsRtp(protocol)) {
//
// RTP specific attrubtes
@ -3591,8 +3621,8 @@ bool ParseRtpmapAttribute(const std::string& line,
UpdateCodec(payload_type, encoding_name, clock_rate, 0, channels,
audio_desc);
} else if (media_type == cricket::MEDIA_TYPE_DATA) {
RtpDataContentDescription* data_desc = media_desc->as_rtp_data();
data_desc->AddCodec(cricket::RtpDataCodec(payload_type, encoding_name));
DataContentDescription* data_desc = media_desc->as_data();
data_desc->AddCodec(cricket::DataCodec(payload_type, encoding_name));
}
return true;
}

View File

@ -56,6 +56,7 @@ using cricket::ContentGroup;
using cricket::ContentInfo;
using cricket::CryptoParams;
using cricket::DataCodec;
using cricket::DataContentDescription;
using cricket::ICE_CANDIDATE_COMPONENT_RTCP;
using cricket::ICE_CANDIDATE_COMPONENT_RTP;
using cricket::kFecSsrcGroupSemantics;
@ -64,8 +65,6 @@ using cricket::MediaProtocolType;
using cricket::RELAY_PORT_TYPE;
using cricket::RidDescription;
using cricket::RidDirection;
using cricket::RtpDataContentDescription;
using cricket::SctpDataContentDescription;
using cricket::SessionDescription;
using cricket::SimulcastDescription;
using cricket::SimulcastLayer;
@ -276,7 +275,6 @@ static const char kSdpRtpDataChannelString[] =
"a=ssrc:10 mslabel:data_channel\r\n"
"a=ssrc:10 label:data_channeld0\r\n";
// draft-ietf-mmusic-sctp-sdp-03
static const char kSdpSctpDataChannelString[] =
"m=application 9 DTLS/SCTP 5000\r\n"
"c=IN IP4 0.0.0.0\r\n"
@ -1445,17 +1443,10 @@ class WebRtcSdpTest : public ::testing::Test {
simulcast2.receive_layers().size());
}
void CompareRtpDataContentDescription(const RtpDataContentDescription* dcd1,
const RtpDataContentDescription* dcd2) {
CompareMediaContentDescription<RtpDataContentDescription>(dcd1, dcd2);
}
void CompareSctpDataContentDescription(
const SctpDataContentDescription* dcd1,
const SctpDataContentDescription* dcd2) {
void CompareDataContentDescription(const DataContentDescription* dcd1,
const DataContentDescription* dcd2) {
EXPECT_EQ(dcd1->use_sctpmap(), dcd2->use_sctpmap());
EXPECT_EQ(dcd1->port(), dcd2->port());
EXPECT_EQ(dcd1->max_message_size(), dcd2->max_message_size());
CompareMediaContentDescription<DataContentDescription>(dcd1, dcd2);
}
void CompareSessionDescription(const SessionDescription& desc1,
@ -1493,21 +1484,10 @@ class WebRtcSdpTest : public ::testing::Test {
}
ASSERT_EQ(IsDataContent(&c1), IsDataContent(&c2));
if (c1.media_description()->as_sctp()) {
ASSERT_TRUE(c2.media_description()->as_sctp());
const SctpDataContentDescription* scd1 =
c1.media_description()->as_sctp();
const SctpDataContentDescription* scd2 =
c2.media_description()->as_sctp();
CompareSctpDataContentDescription(scd1, scd2);
} else {
if (IsDataContent(&c1)) {
const RtpDataContentDescription* dcd1 =
c1.media_description()->as_rtp_data();
const RtpDataContentDescription* dcd2 =
c2.media_description()->as_rtp_data();
CompareRtpDataContentDescription(dcd1, dcd2);
}
if (IsDataContent(&c1)) {
const DataContentDescription* dcd1 = c1.media_description()->as_data();
const DataContentDescription* dcd2 = c2.media_description()->as_data();
CompareDataContentDescription(dcd1, dcd2);
}
CompareSimulcastDescription(
@ -1780,12 +1760,14 @@ class WebRtcSdpTest : public ::testing::Test {
}
void AddSctpDataChannel(bool use_sctpmap) {
std::unique_ptr<SctpDataContentDescription> data(
new SctpDataContentDescription());
sctp_desc_ = data.get();
sctp_desc_->set_use_sctpmap(use_sctpmap);
sctp_desc_->set_protocol(cricket::kMediaProtocolDtlsSctp);
sctp_desc_->set_port(kDefaultSctpPort);
std::unique_ptr<DataContentDescription> data(new DataContentDescription());
data_desc_ = data.get();
data_desc_->set_use_sctpmap(use_sctpmap);
data_desc_->set_protocol(cricket::kMediaProtocolDtlsSctp);
DataCodec codec(cricket::kGoogleSctpDataCodecPlType,
cricket::kGoogleSctpDataCodecName);
codec.SetParam(cricket::kCodecParamPort, kDefaultSctpPort);
data_desc_->AddCodec(codec);
desc_.AddContent(kDataContentName, MediaProtocolType::kSctp,
data.release());
desc_.AddTransportInfo(TransportInfo(
@ -1793,8 +1775,7 @@ class WebRtcSdpTest : public ::testing::Test {
}
void AddRtpDataChannel() {
std::unique_ptr<RtpDataContentDescription> data(
new RtpDataContentDescription());
std::unique_ptr<DataContentDescription> data(new DataContentDescription());
data_desc_ = data.get();
data_desc_->AddCodec(DataCodec(101, "google-data"));
@ -2062,8 +2043,7 @@ class WebRtcSdpTest : public ::testing::Test {
SessionDescription desc_;
AudioContentDescription* audio_desc_;
VideoContentDescription* video_desc_;
RtpDataContentDescription* data_desc_;
SctpDataContentDescription* sctp_desc_;
DataContentDescription* data_desc_;
Candidates candidates_;
std::unique_ptr<IceCandidateInterface> jcandidate_;
JsepSessionDescription jdesc_;
@ -2235,26 +2215,21 @@ TEST_F(WebRtcSdpTest, SerializeSessionDescriptionWithSctpDataChannel) {
EXPECT_EQ(message, expected_sdp);
}
void MutateJsepSctpPort(JsepSessionDescription* jdesc,
const SessionDescription& desc,
int port) {
// Take our pre-built session description and change the SCTP port.
cricket::SessionDescription* mutant = desc.Copy();
SctpDataContentDescription* dcdesc =
mutant->GetContentDescriptionByName(kDataContentName)->as_sctp();
dcdesc->set_port(port);
// Note: mutant's owned by jdesc now.
ASSERT_TRUE(jdesc->Initialize(mutant, kSessionId, kSessionVersion));
}
TEST_F(WebRtcSdpTest, SerializeWithSctpDataChannelAndNewPort) {
bool use_sctpmap = true;
AddSctpDataChannel(use_sctpmap);
JsepSessionDescription jsep_desc(kDummyType);
MakeDescriptionWithoutCandidates(&jsep_desc);
DataContentDescription* dcdesc =
jsep_desc.description()
->GetContentDescriptionByName(kDataContentName)
->as_data();
const int kNewPort = 1234;
MutateJsepSctpPort(&jsep_desc, desc_, kNewPort);
cricket::DataCodec codec(cricket::kGoogleSctpDataCodecPlType,
cricket::kGoogleSctpDataCodecName);
codec.SetParam(cricket::kCodecParamPort, kNewPort);
dcdesc->AddOrReplaceCodec(codec);
std::string message = webrtc::SdpSerialize(jsep_desc);
@ -2893,12 +2868,14 @@ TEST_F(WebRtcSdpTest, DeserializeSdpWithSctpDataChannelsWithSctpColonPort) {
// Helper function to set the max-message-size parameter in the
// SCTP data codec.
void MutateJsepSctpMaxMessageSize(const SessionDescription& desc,
int new_value,
const std::string& new_value,
JsepSessionDescription* jdesc) {
cricket::SessionDescription* mutant = desc.Copy();
SctpDataContentDescription* dcdesc =
mutant->GetContentDescriptionByName(kDataContentName)->as_sctp();
dcdesc->set_max_message_size(new_value);
DataContentDescription* dcdesc =
mutant->GetContentDescriptionByName(kDataContentName)->as_data();
std::vector<cricket::DataCodec> codecs(dcdesc->codecs());
codecs[0].SetParam(cricket::kCodecParamMaxMessageSize, new_value);
dcdesc->set_codecs(codecs);
jdesc->Initialize(mutant, kSessionId, kSessionVersion);
}
@ -2910,7 +2887,7 @@ TEST_F(WebRtcSdpTest, DeserializeSdpWithSctpDataChannelsWithMaxMessageSize) {
sdp_with_data.append(kSdpSctpDataChannelStringWithSctpColonPort);
sdp_with_data.append("a=max-message-size:12345\r\n");
MutateJsepSctpMaxMessageSize(desc_, 12345, &jdesc);
MutateJsepSctpMaxMessageSize(desc_, "12345", &jdesc);
JsepSessionDescription jdesc_output(kDummyType);
// Verify with DTLS/SCTP.
@ -2960,13 +2937,29 @@ TEST_F(WebRtcSdpTest, DeserializeSdpWithCorruptedSctpDataChannels) {
// No crash is a pass.
}
void MutateJsepSctpPort(JsepSessionDescription* jdesc,
const SessionDescription& desc) {
// take our pre-built session description and change the SCTP port.
std::unique_ptr<cricket::SessionDescription> mutant = desc.Clone();
DataContentDescription* dcdesc =
mutant->GetContentDescriptionByName(kDataContentName)->as_data();
std::vector<cricket::DataCodec> codecs(dcdesc->codecs());
EXPECT_EQ(1U, codecs.size());
EXPECT_EQ(cricket::kGoogleSctpDataCodecPlType, codecs[0].id);
codecs[0].SetParam(cricket::kCodecParamPort, kUnusualSctpPort);
dcdesc->set_codecs(codecs);
ASSERT_TRUE(
jdesc->Initialize(std::move(mutant), kSessionId, kSessionVersion));
}
TEST_F(WebRtcSdpTest, DeserializeSdpWithSctpDataChannelAndUnusualPort) {
bool use_sctpmap = true;
AddSctpDataChannel(use_sctpmap);
// First setup the expected JsepSessionDescription.
JsepSessionDescription jdesc(kDummyType);
MutateJsepSctpPort(&jdesc, desc_, kUnusualSctpPort);
MutateJsepSctpPort(&jdesc, desc_);
// Then get the deserialized JsepSessionDescription.
std::string sdp_with_data = kSdpString;
@ -2986,7 +2979,7 @@ TEST_F(WebRtcSdpTest,
AddSctpDataChannel(use_sctpmap);
JsepSessionDescription jdesc(kDummyType);
MutateJsepSctpPort(&jdesc, desc_, kUnusualSctpPort);
MutateJsepSctpPort(&jdesc, desc_);
// We need to test the deserialized JsepSessionDescription from
// kSdpSctpDataChannelStringWithSctpPort for
@ -3022,7 +3015,7 @@ TEST_F(WebRtcSdpTest, DeserializeSdpWithSctpDataChannelsAndBandwidth) {
bool use_sctpmap = true;
AddSctpDataChannel(use_sctpmap);
JsepSessionDescription jdesc(kDummyType);
SctpDataContentDescription* dcd = GetFirstSctpDataContentDescription(&desc_);
DataContentDescription* dcd = GetFirstDataContentDescription(&desc_);
dcd->set_bandwidth(100 * 1000);
ASSERT_TRUE(jdesc.Initialize(desc_.Clone(), kSessionId, kSessionVersion));