Revert of Adding support for Unified Plan offer/answer negotiation. (patchset #9 id:500001 of https://codereview.webrtc.org/2991693002/ )
Reason for revert:
BUG=webrtc:8108: breaks Clang build.
Original issue's description:
> Adding support for Unified Plan offer/answer negotiation to the mediasession layer.
>
> This layer takes in a simplified "options" struct and the current local description,
> and generates a new offer/answer. Previously the options struct assumed there would
> only be one media description per media type (audio/video), but it now supports
> N number of audio/video descriptions.
>
> The |add_legacy_stream| options is removed from the mediasession.cc/.h
> in this CL.
>
> The next step is to add the ability for PeerConnection/WebRtcSession to create
> "options" to represent multiple RtpTransceivers, and apply the Unified Plan
> descriptions correctly. Right now, only Plan B descriptions will be
> generated in unit tests.
>
> BUG=chromium:465349
>
> Review-Url: https://codereview.webrtc.org/2991693002
> Cr-Commit-Position: refs/heads/master@{#19343}
> Committed: https://chromium.googlesource.com/external/webrtc/+/a77e6bbd30276bdc5b30f2cbc1e92ca181ae76f0
TBR=deadbeef@webrtc.org,zhihuang@webrtc.org
# Not skipping CQ checks because original CL landed more than 1 days ago.
BUG=chromium:465349
Review-Url: https://codereview.webrtc.org/3001083002
Cr-Commit-Position: refs/heads/master@{#19384}
diff --git a/webrtc/pc/mediasession.cc b/webrtc/pc/mediasession.cc
index 4d4744a..de8f72c 100644
--- a/webrtc/pc/mediasession.cc
+++ b/webrtc/pc/mediasession.cc
@@ -188,14 +188,11 @@
return true;
}
-const CryptoParamsVec* GetCryptos(const ContentInfo* content) {
- if (!content) {
- return nullptr;
+const CryptoParamsVec* GetCryptos(const MediaContentDescription* media) {
+ if (!media) {
+ return NULL;
}
-
- RTC_DCHECK(IsMediaContent(content));
- return &(static_cast<const MediaContentDescription*>(content->description)
- ->cryptos());
+ return &media->cryptos();
}
bool FindMatchingCrypto(const CryptoParamsVec& cryptos,
@@ -431,15 +428,15 @@
private:
};
-// Adds a StreamParams for each SenderOptions in |sender_options| to
-// content_description.
+// Adds a StreamParams for each Stream in Streams with media type
+// media_type to content_description.
// |current_params| - All currently known StreamParams of any media type.
template <class C>
-static bool AddStreamParams(
- const std::vector<SenderOptions>& sender_options,
- const std::string& rtcp_cname,
- StreamParamsVec* current_streams,
- MediaContentDescriptionImpl<C>* content_description) {
+static bool AddStreamParams(MediaType media_type,
+ const MediaSessionOptions& options,
+ StreamParamsVec* current_streams,
+ MediaContentDescriptionImpl<C>* content_description,
+ const bool add_legacy_stream) {
// SCTP streams are not negotiated using SDP/ContentDescriptions.
if (IsSctp(content_description->protocol())) {
return true;
@@ -448,26 +445,44 @@
const bool include_rtx_streams =
ContainsRtxCodec(content_description->codecs());
+ const MediaSessionOptions::Streams& streams = options.streams;
+ if (streams.empty() && add_legacy_stream) {
+ // TODO(perkj): Remove this legacy stream when all apps use StreamParams.
+ std::vector<uint32_t> ssrcs;
+ int num_ssrcs = include_rtx_streams ? 2 : 1;
+ GenerateSsrcs(*current_streams, num_ssrcs, &ssrcs);
+ if (include_rtx_streams) {
+ content_description->AddLegacyStream(ssrcs[0], ssrcs[1]);
+ content_description->set_multistream(true);
+ } else {
+ content_description->AddLegacyStream(ssrcs[0]);
+ }
+ return true;
+ }
const bool include_flexfec_stream =
ContainsFlexfecCodec(content_description->codecs());
- for (const SenderOptions& sender : sender_options) {
+ MediaSessionOptions::Streams::const_iterator stream_it;
+ for (stream_it = streams.begin();
+ stream_it != streams.end(); ++stream_it) {
+ if (stream_it->type != media_type)
+ continue; // Wrong media type.
+
+ StreamParams* param = GetStreamByIds(*current_streams, "", stream_it->id);
// groupid is empty for StreamParams generated using
// MediaSessionDescriptionFactory.
- StreamParams* param =
- GetStreamByIds(*current_streams, "" /*group_id*/, sender.track_id);
if (!param) {
- // This is a new sender.
+ // This is a new stream.
std::vector<uint32_t> ssrcs;
- GenerateSsrcs(*current_streams, sender.num_sim_layers, &ssrcs);
+ GenerateSsrcs(*current_streams, stream_it->num_sim_layers, &ssrcs);
StreamParams stream_param;
- stream_param.id = sender.track_id;
+ stream_param.id = stream_it->id;
// Add the generated ssrc.
for (size_t i = 0; i < ssrcs.size(); ++i) {
stream_param.ssrcs.push_back(ssrcs[i]);
}
- if (sender.num_sim_layers > 1) {
+ if (stream_it->num_sim_layers > 1) {
SsrcGroup group(kSimSsrcGroupSemantics, stream_param.ssrcs);
stream_param.ssrc_groups.push_back(group);
}
@@ -497,8 +512,8 @@
<< "media streams however, so no FlexFEC SSRC will be generated.";
}
}
- stream_param.cname = rtcp_cname;
- stream_param.sync_label = sender.stream_id;
+ stream_param.cname = options.rtcp_cname;
+ stream_param.sync_label = stream_it->sync_label;
content_description->AddStream(stream_param);
// Store the new StreamParams in current_streams.
@@ -508,7 +523,7 @@
// Use existing generated SSRCs/groups, but update the sync_label if
// necessary. This may be needed if a MediaStreamTrack was moved from one
// MediaStream to another.
- param->sync_label = sender.stream_id;
+ param->sync_label = stream_it->sync_label;
content_description->AddStream(*param);
}
}
@@ -720,34 +735,46 @@
return STR_CASE_CMP(codec.name.c_str(), kFlexfecCodecName) == 0;
}
-// Create a media content to be offered for the given |sender_options|,
-// according to the given options.rtcp_mux, session_options.is_muc, codecs,
-// secure_transport, crypto, and current_streams. If we don't currently have
-// 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 TransportOptions GetTransportOptions(const MediaSessionOptions& options,
+ const std::string& content_name) {
+ TransportOptions transport_options;
+ auto it = options.transport_options.find(content_name);
+ if (it != options.transport_options.end()) {
+ transport_options = it->second;
+ }
+ transport_options.enable_ice_renomination = options.enable_ice_renomination;
+ return transport_options;
+}
+
+// Create a media content to be offered in a session-initiate,
+// according to the given options.rtcp_mux, options.is_muc,
+// options.streams, codecs, secure_transport, crypto, and streams. If we don't
+// currently have crypto (in current_cryptos) and it is enabled (in
+// secure_policy), crypto is created (according to crypto_suites). If
+// add_legacy_stream is true, and current_streams is empty, a legacy
+// stream is created. The created content is added to the offer.
template <class C>
static bool CreateMediaContentOffer(
- const std::vector<SenderOptions>& sender_options,
- const MediaSessionOptions& session_options,
+ const MediaSessionOptions& 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,
+ bool add_legacy_stream,
StreamParamsVec* current_streams,
MediaContentDescriptionImpl<C>* offer) {
offer->AddCodecs(codecs);
- offer->set_rtcp_mux(session_options.rtcp_mux_enabled);
+ offer->set_rtcp_mux(options.rtcp_mux_enabled);
if (offer->type() == cricket::MEDIA_TYPE_VIDEO) {
offer->set_rtcp_reduced_size(true);
}
- offer->set_multistream(session_options.is_muc);
+ offer->set_multistream(options.is_muc);
offer->set_rtp_header_extensions(rtp_extensions);
- if (!AddStreamParams(sender_options, session_options.rtcp_cname,
- current_streams, offer)) {
+ if (!AddStreamParams(offer->type(), options, current_streams, offer,
+ add_legacy_stream)) {
return false;
}
@@ -855,42 +882,15 @@
return false;
}
-// Find the codec in |codec_list| that |rtx_codec| is associated with.
-template <class C>
-static const C* GetAssociatedCodec(const std::vector<C>& codec_list,
- const C& rtx_codec) {
- std::string associated_pt_str;
- if (!rtx_codec.GetParam(kCodecParamAssociatedPayloadType,
- &associated_pt_str)) {
- LOG(LS_WARNING) << "RTX codec " << rtx_codec.name
- << " is missing an associated payload type.";
- return nullptr;
- }
-
- int associated_pt;
- if (!rtc::FromString(associated_pt_str, &associated_pt)) {
- LOG(LS_WARNING) << "Couldn't convert payload type " << associated_pt_str
- << " of RTX codec " << rtx_codec.name << " to an integer.";
- return nullptr;
- }
-
- // Find the associated reference codec for the reference RTX codec.
- const C* associated_codec = FindCodecById(codec_list, associated_pt);
- if (!associated_codec) {
- LOG(LS_WARNING) << "Couldn't find associated codec with payload type "
- << associated_pt << " for RTX codec " << rtx_codec.name
- << ".";
- }
- return associated_codec;
-}
-
-// Adds all codecs from |reference_codecs| to |offered_codecs| that don't
+// Adds all codecs from |reference_codecs| to |offered_codecs| that dont'
// already exist in |offered_codecs| and ensure the payload types don't
// collide.
template <class C>
-static void MergeCodecs(const std::vector<C>& reference_codecs,
- std::vector<C>* offered_codecs,
- UsedPayloadTypes* used_pltypes) {
+static void FindCodecsToOffer(
+ const std::vector<C>& reference_codecs,
+ std::vector<C>* offered_codecs,
+ UsedPayloadTypes* used_pltypes) {
+
// Add all new codecs that are not RTX codecs.
for (const C& reference_codec : reference_codecs) {
if (!IsRtxCodec(reference_codec) &&
@@ -908,11 +908,33 @@
!FindMatchingCodec<C>(reference_codecs, *offered_codecs,
reference_codec, nullptr)) {
C rtx_codec = reference_codec;
- const C* associated_codec =
- GetAssociatedCodec(reference_codecs, rtx_codec);
- if (!associated_codec) {
+
+ std::string associated_pt_str;
+ if (!rtx_codec.GetParam(kCodecParamAssociatedPayloadType,
+ &associated_pt_str)) {
+ LOG(LS_WARNING) << "RTX codec " << rtx_codec.name
+ << " is missing an associated payload type.";
continue;
}
+
+ int associated_pt;
+ if (!rtc::FromString(associated_pt_str, &associated_pt)) {
+ LOG(LS_WARNING) << "Couldn't convert payload type " << associated_pt_str
+ << " of RTX codec " << rtx_codec.name
+ << " to an integer.";
+ continue;
+ }
+
+ // Find the associated reference codec for the reference RTX codec.
+ const C* associated_codec =
+ FindCodecById(reference_codecs, associated_pt);
+ if (!associated_codec) {
+ LOG(LS_WARNING) << "Couldn't find associated codec with payload type "
+ << associated_pt << " for RTX codec " << rtx_codec.name
+ << ".";
+ continue;
+ }
+
// Find a codec in the offered list that matches the reference codec.
// Its payload type may be different than the reference codec.
C matching_codec;
@@ -931,22 +953,6 @@
}
}
-static bool FindByUriAndEncryption(const RtpHeaderExtensions& extensions,
- const webrtc::RtpExtension& ext_to_match,
- webrtc::RtpExtension* found_extension) {
- for (RtpHeaderExtensions::const_iterator it = extensions.begin();
- it != extensions.end(); ++it) {
- // We assume that all URIs are given in a canonical format.
- if (it->uri == ext_to_match.uri && it->encrypt == ext_to_match.encrypt) {
- if (found_extension) {
- *found_extension = *it;
- }
- return true;
- }
- }
- return false;
-}
-
static bool FindByUri(const RtpHeaderExtensions& extensions,
const webrtc::RtpExtension& ext_to_match,
webrtc::RtpExtension* found_extension) {
@@ -990,41 +996,50 @@
return false;
}
-// Adds all extensions from |reference_extensions| to |offered_extensions| that
-// don't already exist in |offered_extensions| and ensure the IDs don't
-// collide. If an extension is added, it's also added to |regular_extensions| or
-// |encrypted_extensions|, and if the extension is in |regular_extensions| or
-// |encrypted_extensions|, its ID is marked as used in |used_ids|.
-// |offered_extensions| is for either audio or video while |regular_extensions|
-// and |encrypted_extensions| are used for both audio and video. There could be
-// overlap between audio extensions and video extensions.
-static void MergeRtpHdrExts(const RtpHeaderExtensions& reference_extensions,
- RtpHeaderExtensions* offered_extensions,
- RtpHeaderExtensions* regular_extensions,
- RtpHeaderExtensions* encrypted_extensions,
- UsedRtpHeaderExtensionIds* used_ids) {
- for (auto reference_extension : reference_extensions) {
- if (!FindByUriAndEncryption(*offered_extensions, reference_extension,
- nullptr)) {
- webrtc::RtpExtension existing;
- if (reference_extension.encrypt) {
- if (FindByUriAndEncryption(*encrypted_extensions, reference_extension,
- &existing)) {
- offered_extensions->push_back(existing);
- } else {
- used_ids->FindAndSetIdUsed(&reference_extension);
- encrypted_extensions->push_back(reference_extension);
- offered_extensions->push_back(reference_extension);
- }
+// Iterates through |offered_extensions|, adding each one to
+// |regular_extensions| (or |encrypted_extensions| if encrypted) and |used_ids|,
+// and resolving ID conflicts.
+// If an offered extension has the same URI as one in |regular_extensions| or
+// |encrypted_extensions|, it will re-use the same ID and won't be treated as
+// a conflict.
+static void FindAndSetRtpHdrExtUsed(RtpHeaderExtensions* offered_extensions,
+ RtpHeaderExtensions* regular_extensions,
+ RtpHeaderExtensions* encrypted_extensions,
+ UsedRtpHeaderExtensionIds* used_ids) {
+ for (auto& extension : *offered_extensions) {
+ webrtc::RtpExtension existing;
+ if ((extension.encrypt &&
+ FindByUri(*encrypted_extensions, extension, &existing)) ||
+ (!extension.encrypt &&
+ FindByUri(*regular_extensions, extension, &existing))) {
+ extension.id = existing.id;
+ } else {
+ used_ids->FindAndSetIdUsed(&extension);
+ if (extension.encrypt) {
+ encrypted_extensions->push_back(extension);
} else {
- if (FindByUriAndEncryption(*regular_extensions, reference_extension,
- &existing)) {
- offered_extensions->push_back(existing);
- } else {
- used_ids->FindAndSetIdUsed(&reference_extension);
- regular_extensions->push_back(reference_extension);
- offered_extensions->push_back(reference_extension);
- }
+ regular_extensions->push_back(extension);
+ }
+ }
+ }
+}
+
+// Adds |reference_extensions| to |offered_extensions|, while updating
+// |all_extensions| and |used_ids|.
+static void FindRtpHdrExtsToOffer(
+ const RtpHeaderExtensions& reference_extensions,
+ RtpHeaderExtensions* offered_extensions,
+ RtpHeaderExtensions* all_extensions,
+ UsedRtpHeaderExtensionIds* used_ids) {
+ for (auto reference_extension : reference_extensions) {
+ if (!FindByUri(*offered_extensions, reference_extension, NULL)) {
+ webrtc::RtpExtension existing;
+ if (FindByUri(*all_extensions, reference_extension, &existing)) {
+ offered_extensions->push_back(existing);
+ } else {
+ used_ids->FindAndSetIdUsed(&reference_extension);
+ all_extensions->push_back(reference_extension);
+ offered_extensions->push_back(reference_extension);
}
}
}
@@ -1088,24 +1103,26 @@
}
}
-// 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
-// current_cryptos) and it is enabled (in secure_policy), crypto is created
-// (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.
+// Create a media content to be answered in a session-accept,
+// according to the given options.rtcp_mux, options.streams, codecs,
+// crypto, and streams. If we don't currently have crypto (in
+// current_cryptos) and it is enabled (in secure_policy), crypto is
+// created (according to crypto_suites). If add_legacy_stream is
+// true, and current_streams is empty, a legacy stream is created.
+// The codecs, rtcp_mux, and crypto are all negotiated with the offer
+// from the incoming session-initiate. If the negotiation fails, this
+// method returns false. The created content is added to the offer.
template <class C>
static bool CreateMediaContentAnswer(
const MediaContentDescriptionImpl<C>* offer,
- const MediaDescriptionOptions& media_description_options,
- const MediaSessionOptions& session_options,
+ const MediaSessionOptions& options,
const std::vector<C>& local_codecs,
const SecurePolicy& sdes_policy,
const CryptoParamsVec* current_cryptos,
const RtpHeaderExtensions& local_rtp_extenstions,
bool enable_encrypted_rtp_header_extensions,
StreamParamsVec* current_streams,
+ bool add_legacy_stream,
bool bundle_enabled,
MediaContentDescriptionImpl<C>* answer) {
std::vector<C> negotiated_codecs;
@@ -1119,15 +1136,14 @@
&negotiated_rtp_extensions);
answer->set_rtp_header_extensions(negotiated_rtp_extensions);
- answer->set_rtcp_mux(session_options.rtcp_mux_enabled && offer->rtcp_mux());
+ answer->set_rtcp_mux(options.rtcp_mux_enabled && offer->rtcp_mux());
if (answer->type() == cricket::MEDIA_TYPE_VIDEO) {
answer->set_rtcp_reduced_size(offer->rtcp_reduced_size());
}
if (sdes_policy != SEC_DISABLED) {
CryptoParams crypto;
- if (SelectCrypto(offer, bundle_enabled, session_options.crypto_options,
- &crypto)) {
+ if (SelectCrypto(offer, bundle_enabled, options.crypto_options, &crypto)) {
if (current_cryptos) {
FindMatchingCrypto(*current_cryptos, crypto, &crypto);
}
@@ -1139,17 +1155,29 @@
return false;
}
- if (!AddStreamParams(media_description_options.sender_options,
- session_options.rtcp_cname, current_streams, answer)) {
+ if (!AddStreamParams(answer->type(), options, current_streams, answer,
+ add_legacy_stream)) {
return false; // Something went seriously wrong.
}
+ // Make sure the answer media content direction is per default set as
+ // described in RFC3264 section 6.1.
+ const bool is_data = !IsRtpProtocol(answer->protocol());
+ const bool has_send_streams = !answer->streams().empty();
+ const bool wants_send = has_send_streams || is_data;
+ const bool recv_audio =
+ answer->type() == cricket::MEDIA_TYPE_AUDIO && options.recv_audio;
+ const bool recv_video =
+ answer->type() == cricket::MEDIA_TYPE_VIDEO && options.recv_video;
+ const bool recv_data =
+ answer->type() == cricket::MEDIA_TYPE_DATA;
+ const bool wants_receive = recv_audio || recv_video || recv_data;
+
auto offer_rtd =
RtpTransceiverDirection::FromMediaContentDirection(offer->direction());
-
- answer->set_direction(NegotiateRtpTransceiverDirection(
- offer_rtd, media_description_options.direction)
- .ToMediaContentDirection());
+ auto wants_rtd = RtpTransceiverDirection(wants_send, wants_receive);
+ answer->set_direction(NegotiateRtpTransceiverDirection(offer_rtd, wants_rtd)
+ .ToMediaContentDirection());
return true;
}
@@ -1211,20 +1239,23 @@
}
// Gets the current DTLS state from the transport description.
-static bool IsDtlsActive(const ContentInfo* content,
- const SessionDescription* current_description) {
- if (!content) {
+static bool IsDtlsActive(
+ const std::string& content_name,
+ const SessionDescription* current_description) {
+ if (!current_description)
return false;
- }
- size_t msection_index = content - ¤t_description->contents()[0];
-
- if (current_description->transport_infos().size() <= msection_index) {
+ const ContentInfo* content =
+ current_description->GetContentByName(content_name);
+ if (!content)
return false;
- }
- return current_description->transport_infos()[msection_index]
- .description.secure();
+ const TransportDescription* current_tdesc =
+ GetTransportDescription(content_name, current_description);
+ if (!current_tdesc)
+ return false;
+
+ return current_tdesc->secure();
}
std::string MediaContentDirectionToString(MediaContentDirection direction) {
@@ -1250,54 +1281,75 @@
return dir_str;
}
-void MediaDescriptionOptions::AddAudioSender(const std::string& track_id,
- const std::string& stream_id) {
- RTC_DCHECK(type == MEDIA_TYPE_AUDIO);
- AddSenderInternal(track_id, stream_id, 1);
+void MediaSessionOptions::AddSendStream(MediaType type,
+ const std::string& id,
+ const std::string& sync_label) {
+ AddSendStreamInternal(type, id, sync_label, 1);
}
-void MediaDescriptionOptions::AddVideoSender(const std::string& track_id,
- const std::string& stream_id,
- int num_sim_layers) {
- RTC_DCHECK(type == MEDIA_TYPE_VIDEO);
- AddSenderInternal(track_id, stream_id, num_sim_layers);
+void MediaSessionOptions::AddSendVideoStream(
+ const std::string& id,
+ const std::string& sync_label,
+ int num_sim_layers) {
+ AddSendStreamInternal(MEDIA_TYPE_VIDEO, id, sync_label, num_sim_layers);
}
-void MediaDescriptionOptions::AddRtpDataChannel(const std::string& track_id,
- const std::string& stream_id) {
- RTC_DCHECK(type == MEDIA_TYPE_DATA);
- AddSenderInternal(track_id, stream_id, 1);
+void MediaSessionOptions::AddSendStreamInternal(
+ MediaType type,
+ const std::string& id,
+ const std::string& sync_label,
+ int num_sim_layers) {
+ streams.push_back(Stream(type, id, sync_label, num_sim_layers));
+
+ // If we haven't already set the data_channel_type, and we add a
+ // stream, we assume it's an RTP data stream.
+ if (type == MEDIA_TYPE_DATA && data_channel_type == DCT_NONE)
+ data_channel_type = DCT_RTP;
}
-void MediaDescriptionOptions::AddSenderInternal(const std::string& track_id,
- const std::string& stream_id,
- int num_sim_layers) {
- sender_options.push_back(SenderOptions{track_id, stream_id, num_sim_layers});
+void MediaSessionOptions::RemoveSendStream(MediaType type,
+ const std::string& id) {
+ Streams::iterator stream_it = streams.begin();
+ for (; stream_it != streams.end(); ++stream_it) {
+ if (stream_it->type == type && stream_it->id == id) {
+ streams.erase(stream_it);
+ return;
+ }
+ }
+ RTC_NOTREACHED();
}
-bool MediaSessionOptions::HasMediaDescription(MediaType type) const {
- return std::find_if(media_description_options.begin(),
- media_description_options.end(),
- [type](const MediaDescriptionOptions& t) {
- return t.type == type;
- }) != media_description_options.end();
+bool MediaSessionOptions::HasSendMediaStream(MediaType type) const {
+ Streams::const_iterator stream_it = streams.begin();
+ for (; stream_it != streams.end(); ++stream_it) {
+ if (stream_it->type == type) {
+ return true;
+ }
+ }
+ return false;
}
MediaSessionDescriptionFactory::MediaSessionDescriptionFactory(
const TransportDescriptionFactory* transport_desc_factory)
- : transport_desc_factory_(transport_desc_factory) {}
+ : secure_(SEC_DISABLED),
+ add_legacy_(true),
+ transport_desc_factory_(transport_desc_factory) {
+}
MediaSessionDescriptionFactory::MediaSessionDescriptionFactory(
ChannelManager* channel_manager,
const TransportDescriptionFactory* transport_desc_factory)
- : transport_desc_factory_(transport_desc_factory) {
+ : secure_(SEC_DISABLED),
+ add_legacy_(true),
+ transport_desc_factory_(transport_desc_factory) {
channel_manager->GetSupportedAudioSendCodecs(&audio_send_codecs_);
channel_manager->GetSupportedAudioReceiveCodecs(&audio_recv_codecs_);
channel_manager->GetSupportedAudioRtpHeaderExtensions(&audio_rtp_extensions_);
channel_manager->GetSupportedVideoCodecs(&video_codecs_);
channel_manager->GetSupportedVideoRtpHeaderExtensions(&video_rtp_extensions_);
channel_manager->GetSupportedDataCodecs(&data_codecs_);
- ComputeAudioCodecsIntersectionAndUnion();
+ NegotiateCodecs(audio_recv_codecs_, audio_send_codecs_,
+ &audio_sendrecv_codecs_);
}
const AudioCodecs& MediaSessionDescriptionFactory::audio_sendrecv_codecs()
@@ -1317,114 +1369,129 @@
const AudioCodecs& send_codecs, const AudioCodecs& recv_codecs) {
audio_send_codecs_ = send_codecs;
audio_recv_codecs_ = recv_codecs;
- ComputeAudioCodecsIntersectionAndUnion();
+ audio_sendrecv_codecs_.clear();
+ // Use NegotiateCodecs to merge our codec lists, since the operation is
+ // essentially the same. Put send_codecs as the offered_codecs, which is the
+ // order we'd like to follow. The reasoning is that encoding is usually more
+ // expensive than decoding, and prioritizing a codec in the send list probably
+ // means it's a codec we can handle efficiently.
+ NegotiateCodecs(recv_codecs, send_codecs, &audio_sendrecv_codecs_);
}
SessionDescription* MediaSessionDescriptionFactory::CreateOffer(
- const MediaSessionOptions& session_options,
+ const MediaSessionOptions& options,
const SessionDescription* current_description) const {
std::unique_ptr<SessionDescription> offer(new SessionDescription());
StreamParamsVec current_streams;
GetCurrentStreamParams(current_description, ¤t_streams);
- AudioCodecs offer_audio_codecs;
- VideoCodecs offer_video_codecs;
- DataCodecs offer_data_codecs;
- GetCodecsForOffer(current_description, &offer_audio_codecs,
- &offer_video_codecs, &offer_data_codecs);
+ const bool wants_send =
+ options.HasSendMediaStream(MEDIA_TYPE_AUDIO) || add_legacy_;
+ const AudioCodecs& supported_audio_codecs =
+ GetAudioCodecsForOffer({wants_send, options.recv_audio});
- if (!session_options.vad_enabled) {
+ AudioCodecs audio_codecs;
+ VideoCodecs video_codecs;
+ DataCodecs data_codecs;
+ GetCodecsToOffer(current_description, supported_audio_codecs,
+ video_codecs_, data_codecs_,
+ &audio_codecs, &video_codecs, &data_codecs);
+
+ if (!options.vad_enabled) {
// If application doesn't want CN codecs in offer.
- StripCNCodecs(&offer_audio_codecs);
+ StripCNCodecs(&audio_codecs);
}
- FilterDataCodecs(&offer_data_codecs,
- session_options.data_channel_type == DCT_SCTP);
RtpHeaderExtensions audio_rtp_extensions;
RtpHeaderExtensions video_rtp_extensions;
GetRtpHdrExtsToOffer(current_description, &audio_rtp_extensions,
&video_rtp_extensions);
- // Must have options for each existing section.
+ bool audio_added = false;
+ bool video_added = false;
+ bool data_added = false;
+
+ // Iterate through the contents of |current_description| to maintain the order
+ // of the m-lines in the new offer.
if (current_description) {
- RTC_DCHECK(current_description->contents().size() <=
- session_options.media_description_options.size());
+ ContentInfos::const_iterator it = current_description->contents().begin();
+ for (; it != current_description->contents().end(); ++it) {
+ if (IsMediaContentOfType(&*it, MEDIA_TYPE_AUDIO)) {
+ if (!AddAudioContentForOffer(options, current_description,
+ audio_rtp_extensions, audio_codecs,
+ ¤t_streams, offer.get())) {
+ return NULL;
+ }
+ audio_added = true;
+ } else if (IsMediaContentOfType(&*it, MEDIA_TYPE_VIDEO)) {
+ if (!AddVideoContentForOffer(options, current_description,
+ video_rtp_extensions, video_codecs,
+ ¤t_streams, offer.get())) {
+ return NULL;
+ }
+ video_added = true;
+ } else if (IsMediaContentOfType(&*it, MEDIA_TYPE_DATA)) {
+ MediaSessionOptions options_copy(options);
+ if (IsSctp(static_cast<const MediaContentDescription*>(it->description)
+ ->protocol())) {
+ options_copy.data_channel_type = DCT_SCTP;
+ }
+ if (!AddDataContentForOffer(options_copy, current_description,
+ &data_codecs, ¤t_streams,
+ offer.get())) {
+ return NULL;
+ }
+ data_added = true;
+ } else {
+ RTC_NOTREACHED();
+ }
+ }
}
- // Iterate through the media description options, matching with existing media
- // descriptions in |current_description|.
- int msection_index = 0;
- for (const MediaDescriptionOptions& media_description_options :
- session_options.media_description_options) {
- const ContentInfo* current_content = nullptr;
- if (current_description &&
- msection_index <
- static_cast<int>(current_description->contents().size())) {
- current_content = ¤t_description->contents()[msection_index];
- // Media type must match.
- RTC_DCHECK(IsMediaContentOfType(current_content,
- media_description_options.type));
- }
- switch (media_description_options.type) {
- case MEDIA_TYPE_AUDIO:
- if (!AddAudioContentForOffer(media_description_options, session_options,
- current_content, current_description,
- audio_rtp_extensions, offer_audio_codecs,
- ¤t_streams, offer.get())) {
- return nullptr;
- }
- break;
- case MEDIA_TYPE_VIDEO:
- if (!AddVideoContentForOffer(media_description_options, session_options,
- current_content, current_description,
- video_rtp_extensions, offer_video_codecs,
- ¤t_streams, offer.get())) {
- return nullptr;
- }
- break;
- case MEDIA_TYPE_DATA:
- if (!AddDataContentForOffer(media_description_options, session_options,
- current_content, current_description,
- offer_data_codecs, ¤t_streams,
- offer.get())) {
- return nullptr;
- }
- break;
- default:
- RTC_NOTREACHED();
- }
- ++msection_index;
+ // Append contents that are not in |current_description|.
+ if (!audio_added && options.has_audio() &&
+ !AddAudioContentForOffer(options, current_description,
+ audio_rtp_extensions, audio_codecs,
+ ¤t_streams, offer.get())) {
+ return NULL;
+ }
+ if (!video_added && options.has_video() &&
+ !AddVideoContentForOffer(options, current_description,
+ video_rtp_extensions, video_codecs,
+ ¤t_streams, offer.get())) {
+ return NULL;
+ }
+ if (!data_added && options.has_data() &&
+ !AddDataContentForOffer(options, current_description, &data_codecs,
+ ¤t_streams, offer.get())) {
+ return NULL;
}
// Bundle the contents together, if we've been asked to do so, and update any
// parameters that need to be tweaked for BUNDLE.
- if (session_options.bundle_enabled && offer->contents().size() > 0u) {
+ if (options.bundle_enabled) {
ContentGroup offer_bundle(GROUP_TYPE_BUNDLE);
- for (const ContentInfo& content : offer->contents()) {
- // TODO(deadbeef): There are conditions that make bundling two media
- // descriptions together illegal. For example, they use the same payload
- // type to represent different codecs, or same IDs for different header
- // extensions. We need to detect this and not try to bundle those media
- // descriptions together.
- offer_bundle.AddContentName(content.name);
+ for (ContentInfos::const_iterator content = offer->contents().begin();
+ content != offer->contents().end(); ++content) {
+ offer_bundle.AddContentName(content->name);
}
offer->AddGroup(offer_bundle);
if (!UpdateTransportInfoForBundle(offer_bundle, offer.get())) {
LOG(LS_ERROR) << "CreateOffer failed to UpdateTransportInfoForBundle.";
- return nullptr;
+ return NULL;
}
if (!UpdateCryptoParamsForBundle(offer_bundle, offer.get())) {
LOG(LS_ERROR) << "CreateOffer failed to UpdateCryptoParamsForBundle.";
- return nullptr;
+ return NULL;
}
}
+
return offer.release();
}
SessionDescription* MediaSessionDescriptionFactory::CreateAnswer(
- const SessionDescription* offer,
- const MediaSessionOptions& session_options,
+ const SessionDescription* offer, const MediaSessionOptions& options,
const SessionDescription* current_description) const {
if (!offer) {
return nullptr;
@@ -1444,81 +1511,32 @@
// Transport info shared by the bundle group.
std::unique_ptr<TransportInfo> bundle_transport;
- // Get list of all possible codecs that respects existing payload type
- // mappings and uses a single payload type space.
- //
- // Note that these lists may be further filtered for each m= section; this
- // step is done just to establish the payload type mappings shared by all
- // sections.
- AudioCodecs answer_audio_codecs;
- VideoCodecs answer_video_codecs;
- DataCodecs answer_data_codecs;
- GetCodecsForAnswer(current_description, offer, &answer_audio_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_data_codecs,
- session_options.data_channel_type == DCT_SCTP);
-
- // Must have options for exactly as many sections as in the offer.
- RTC_DCHECK(offer->contents().size() ==
- session_options.media_description_options.size());
- // Iterate through the media description options, matching with existing
- // media descriptions in |current_description|.
- int msection_index = 0;
- for (const MediaDescriptionOptions& media_description_options :
- session_options.media_description_options) {
- const ContentInfo* offer_content = &offer->contents()[msection_index];
- // Media types and MIDs must match between the remote offer and the
- // MediaDescriptionOptions.
- RTC_DCHECK(
- IsMediaContentOfType(offer_content, media_description_options.type));
- RTC_DCHECK(media_description_options.mid == offer_content->name);
- const ContentInfo* current_content = nullptr;
- if (current_description &&
- msection_index <
- static_cast<int>(current_description->contents().size())) {
- current_content = ¤t_description->contents()[msection_index];
+ ContentInfos::const_iterator it = offer->contents().begin();
+ for (; it != offer->contents().end(); ++it) {
+ if (IsMediaContentOfType(&*it, MEDIA_TYPE_AUDIO)) {
+ if (!AddAudioContentForAnswer(offer, options, current_description,
+ bundle_transport.get(), ¤t_streams,
+ answer.get())) {
+ return NULL;
+ }
+ } else if (IsMediaContentOfType(&*it, MEDIA_TYPE_VIDEO)) {
+ if (!AddVideoContentForAnswer(offer, options, current_description,
+ bundle_transport.get(), ¤t_streams,
+ answer.get())) {
+ return NULL;
+ }
+ } else {
+ RTC_DCHECK(IsMediaContentOfType(&*it, MEDIA_TYPE_DATA));
+ if (!AddDataContentForAnswer(offer, options, current_description,
+ bundle_transport.get(), ¤t_streams,
+ answer.get())) {
+ return NULL;
+ }
}
- switch (media_description_options.type) {
- case MEDIA_TYPE_AUDIO:
- if (!AddAudioContentForAnswer(
- media_description_options, session_options, offer_content,
- offer, current_content, current_description,
- bundle_transport.get(), answer_audio_codecs, ¤t_streams,
- answer.get())) {
- return nullptr;
- }
- break;
- case MEDIA_TYPE_VIDEO:
- if (!AddVideoContentForAnswer(
- media_description_options, session_options, offer_content,
- offer, current_content, current_description,
- bundle_transport.get(), answer_video_codecs, ¤t_streams,
- answer.get())) {
- return nullptr;
- }
- break;
- case MEDIA_TYPE_DATA:
- if (!AddDataContentForAnswer(media_description_options, session_options,
- offer_content, offer, current_content,
- current_description,
- bundle_transport.get(), answer_data_codecs,
- ¤t_streams, answer.get())) {
- return nullptr;
- }
- break;
- default:
- RTC_NOTREACHED();
- }
- ++msection_index;
// See if we can add the newly generated m= section to the BUNDLE group in
// the answer.
ContentInfo& added = answer->contents().back();
- if (!added.rejected && session_options.bundle_enabled && offer_bundle &&
+ if (!added.rejected && options.bundle_enabled && offer_bundle &&
offer_bundle->HasContentName(added.name)) {
answer_bundle.AddContentName(added.name);
bundle_transport.reset(
@@ -1578,37 +1596,11 @@
}
}
-void MergeCodecsFromDescription(const SessionDescription* description,
- AudioCodecs* audio_codecs,
- VideoCodecs* video_codecs,
- DataCodecs* data_codecs,
- UsedPayloadTypes* used_pltypes) {
- RTC_DCHECK(description);
- for (const ContentInfo& content : description->contents()) {
- if (IsMediaContentOfType(&content, MEDIA_TYPE_AUDIO)) {
- const AudioContentDescription* audio =
- static_cast<AudioContentDescription*>(content.description);
- MergeCodecs<AudioCodec>(audio->codecs(), audio_codecs, used_pltypes);
- } else if (IsMediaContentOfType(&content, MEDIA_TYPE_VIDEO)) {
- const VideoContentDescription* video =
- static_cast<VideoContentDescription*>(content.description);
- MergeCodecs<VideoCodec>(video->codecs(), video_codecs, used_pltypes);
- } else if (IsMediaContentOfType(&content, MEDIA_TYPE_DATA)) {
- const DataContentDescription* data =
- static_cast<DataContentDescription*>(content.description);
- MergeCodecs<DataCodec>(data->codecs(), data_codecs, used_pltypes);
- }
- }
-}
-
-// Getting codecs for an offer involves these steps:
-//
-// 1. Construct payload type -> codec mappings for current description.
-// 2. Add any reference codecs that weren't already present
-// 3. For each individual media description (m= section), filter codecs based
-// on the directional attribute (happens in another method).
-void MediaSessionDescriptionFactory::GetCodecsForOffer(
+void MediaSessionDescriptionFactory::GetCodecsToOffer(
const SessionDescription* current_description,
+ const AudioCodecs& supported_audio_codecs,
+ const VideoCodecs& supported_video_codecs,
+ const DataCodecs& supported_data_codecs,
AudioCodecs* audio_codecs,
VideoCodecs* video_codecs,
DataCodecs* data_codecs) const {
@@ -1617,150 +1609,87 @@
video_codecs->clear();
data_codecs->clear();
+
// 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.
+ // is used.
+ // Add them to |used_pltypes| so the payloadtype is not reused if a new media
+ // type is added.
if (current_description) {
- MergeCodecsFromDescription(current_description, audio_codecs, video_codecs,
- data_codecs, &used_pltypes);
+ const AudioContentDescription* audio =
+ GetFirstAudioContentDescription(current_description);
+ if (audio) {
+ *audio_codecs = audio->codecs();
+ used_pltypes.FindAndSetIdUsed<AudioCodec>(audio_codecs);
+ }
+ const VideoContentDescription* video =
+ GetFirstVideoContentDescription(current_description);
+ if (video) {
+ *video_codecs = video->codecs();
+ used_pltypes.FindAndSetIdUsed<VideoCodec>(video_codecs);
+ }
+ const DataContentDescription* data =
+ GetFirstDataContentDescription(current_description);
+ if (data) {
+ *data_codecs = data->codecs();
+ used_pltypes.FindAndSetIdUsed<DataCodec>(data_codecs);
+ }
}
// Add our codecs that are not in |current_description|.
- MergeCodecs<AudioCodec>(all_audio_codecs_, audio_codecs, &used_pltypes);
- MergeCodecs<VideoCodec>(video_codecs_, video_codecs, &used_pltypes);
- MergeCodecs<DataCodec>(data_codecs_, data_codecs, &used_pltypes);
-}
-
-// Getting codecs for an answer involves these steps:
-//
-// 1. Construct payload type -> codec mappings for current description.
-// 2. Add any codecs from the offer that weren't already present.
-// 3. Add any remaining codecs that weren't already present.
-// 4. For each individual media description (m= section), filter codecs based
-// on the directional attribute (happens in another method).
-void MediaSessionDescriptionFactory::GetCodecsForAnswer(
- const SessionDescription* current_description,
- const SessionDescription* remote_offer,
- AudioCodecs* audio_codecs,
- VideoCodecs* video_codecs,
- DataCodecs* data_codecs) const {
- UsedPayloadTypes used_pltypes;
- audio_codecs->clear();
- video_codecs->clear();
- data_codecs->clear();
-
- // 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.
- if (current_description) {
- MergeCodecsFromDescription(current_description, audio_codecs, 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;
- DataCodecs filtered_offered_data_codecs;
- for (const ContentInfo& content : remote_offer->contents()) {
- if (IsMediaContentOfType(&content, MEDIA_TYPE_AUDIO)) {
- const AudioContentDescription* audio =
- static_cast<AudioContentDescription*>(content.description);
- for (const AudioCodec& offered_audio_codec : audio->codecs()) {
- if (!FindMatchingCodec<AudioCodec>(audio->codecs(),
- filtered_offered_audio_codecs,
- offered_audio_codec, nullptr) &&
- FindMatchingCodec<AudioCodec>(audio->codecs(), all_audio_codecs_,
- offered_audio_codec, nullptr)) {
- filtered_offered_audio_codecs.push_back(offered_audio_codec);
- }
- }
- } else if (IsMediaContentOfType(&content, MEDIA_TYPE_VIDEO)) {
- const VideoContentDescription* video =
- static_cast<VideoContentDescription*>(content.description);
- for (const VideoCodec& offered_video_codec : video->codecs()) {
- if (!FindMatchingCodec<VideoCodec>(video->codecs(),
- filtered_offered_video_codecs,
- offered_video_codec, nullptr) &&
- FindMatchingCodec<VideoCodec>(video->codecs(), video_codecs_,
- offered_video_codec, nullptr)) {
- filtered_offered_video_codecs.push_back(offered_video_codec);
- }
- }
- } else if (IsMediaContentOfType(&content, MEDIA_TYPE_DATA)) {
- const DataContentDescription* data =
- static_cast<DataContentDescription*>(content.description);
- 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);
- }
- }
- }
- }
-
- // Add codecs that are not in |current_description| but were in
- // |remote_offer|.
- MergeCodecs<AudioCodec>(filtered_offered_audio_codecs, audio_codecs,
- &used_pltypes);
- MergeCodecs<VideoCodec>(filtered_offered_video_codecs, video_codecs,
- &used_pltypes);
- MergeCodecs<DataCodec>(filtered_offered_data_codecs, data_codecs,
- &used_pltypes);
+ FindCodecsToOffer<AudioCodec>(supported_audio_codecs, audio_codecs,
+ &used_pltypes);
+ FindCodecsToOffer<VideoCodec>(supported_video_codecs, video_codecs,
+ &used_pltypes);
+ FindCodecsToOffer<DataCodec>(supported_data_codecs, data_codecs,
+ &used_pltypes);
}
void MediaSessionDescriptionFactory::GetRtpHdrExtsToOffer(
const SessionDescription* current_description,
- RtpHeaderExtensions* offer_audio_extensions,
- RtpHeaderExtensions* offer_video_extensions) const {
+ RtpHeaderExtensions* audio_extensions,
+ RtpHeaderExtensions* video_extensions) const {
// All header extensions allocated from the same range to avoid potential
// issues when using BUNDLE.
UsedRtpHeaderExtensionIds used_ids;
RtpHeaderExtensions all_regular_extensions;
RtpHeaderExtensions all_encrypted_extensions;
- offer_audio_extensions->clear();
- offer_video_extensions->clear();
+ audio_extensions->clear();
+ video_extensions->clear();
// First - get all extensions from the current description if the media type
// is used.
// Add them to |used_ids| so the local ids are not reused if a new media
// type is added.
if (current_description) {
- for (const ContentInfo& content : current_description->contents()) {
- if (IsMediaContentOfType(&content, MEDIA_TYPE_AUDIO)) {
- const AudioContentDescription* audio =
- static_cast<const AudioContentDescription*>(content.description);
- MergeRtpHdrExts(audio->rtp_header_extensions(), offer_audio_extensions,
- &all_regular_extensions, &all_encrypted_extensions,
- &used_ids);
- } else if (IsMediaContentOfType(&content, MEDIA_TYPE_VIDEO)) {
- const VideoContentDescription* video =
- static_cast<const VideoContentDescription*>(content.description);
- MergeRtpHdrExts(video->rtp_header_extensions(), offer_video_extensions,
- &all_regular_extensions, &all_encrypted_extensions,
- &used_ids);
- }
+ const AudioContentDescription* audio =
+ GetFirstAudioContentDescription(current_description);
+ if (audio) {
+ *audio_extensions = audio->rtp_header_extensions();
+ FindAndSetRtpHdrExtUsed(audio_extensions, &all_regular_extensions,
+ &all_encrypted_extensions, &used_ids);
+ }
+ const VideoContentDescription* video =
+ GetFirstVideoContentDescription(current_description);
+ if (video) {
+ *video_extensions = video->rtp_header_extensions();
+ FindAndSetRtpHdrExtUsed(video_extensions, &all_regular_extensions,
+ &all_encrypted_extensions, &used_ids);
}
}
// Add our default RTP header extensions that are not in
// |current_description|.
- MergeRtpHdrExts(audio_rtp_header_extensions(), offer_audio_extensions,
- &all_regular_extensions, &all_encrypted_extensions,
- &used_ids);
- MergeRtpHdrExts(video_rtp_header_extensions(), offer_video_extensions,
- &all_regular_extensions, &all_encrypted_extensions,
- &used_ids);
-
+ FindRtpHdrExtsToOffer(audio_rtp_header_extensions(), audio_extensions,
+ &all_regular_extensions, &used_ids);
+ FindRtpHdrExtsToOffer(video_rtp_header_extensions(), video_extensions,
+ &all_regular_extensions, &used_ids);
// TODO(jbauch): Support adding encrypted header extensions to existing
// sessions.
if (enable_encrypted_rtp_header_extensions_ && !current_description) {
- AddEncryptedVersionsOfHdrExts(offer_audio_extensions,
- &all_encrypted_extensions, &used_ids);
- AddEncryptedVersionsOfHdrExts(offer_video_extensions,
- &all_encrypted_extensions, &used_ids);
+ AddEncryptedVersionsOfHdrExts(audio_extensions, &all_encrypted_extensions,
+ &used_ids);
+ AddEncryptedVersionsOfHdrExts(video_extensions, &all_encrypted_extensions,
+ &used_ids);
}
}
@@ -1814,71 +1743,35 @@
return true;
}
-// |audio_codecs| = set of all possible codecs that can be used, with correct
-// payload type mappings
-//
-// |supported_audio_codecs| = set of codecs that are supported for the direction
-// of this m= section
-//
-// acd->codecs() = set of previously negotiated codecs for this m= section
-//
-// The payload types should come from audio_codecs, but the order should come
-// from acd->codecs() and then supported_codecs, to ensure that re-offers don't
-// change existing codec priority, and that new codecs are added with the right
-// priority.
bool MediaSessionDescriptionFactory::AddAudioContentForOffer(
- const MediaDescriptionOptions& media_description_options,
- const MediaSessionOptions& session_options,
- const ContentInfo* current_content,
+ const MediaSessionOptions& options,
const SessionDescription* current_description,
const RtpHeaderExtensions& audio_rtp_extensions,
const AudioCodecs& audio_codecs,
StreamParamsVec* current_streams,
SessionDescription* desc) const {
- // Filter audio_codecs (which includes all codecs, with correctly remapped
- // payload types) based on transceiver direction.
- const AudioCodecs& supported_audio_codecs =
- GetAudioCodecsForOffer(media_description_options.direction);
-
- AudioCodecs filtered_codecs;
- // Add the codecs from current content if exists.
- if (current_content) {
- RTC_DCHECK(IsMediaContentOfType(current_content, MEDIA_TYPE_AUDIO));
- const AudioContentDescription* acd =
- static_cast<const AudioContentDescription*>(
- current_content->description);
- for (const AudioCodec& codec : acd->codecs()) {
- if (FindMatchingCodec<AudioCodec>(supported_audio_codecs, audio_codecs,
- codec, nullptr)) {
- filtered_codecs.push_back(codec);
- }
- }
- }
- // Add other supported audio codecs.
- AudioCodec found_codec;
- for (const AudioCodec& codec : supported_audio_codecs) {
- if (FindMatchingCodec<AudioCodec>(supported_audio_codecs, audio_codecs,
- codec, &found_codec) &&
- !FindMatchingCodec<AudioCodec>(supported_audio_codecs, filtered_codecs,
- codec, nullptr)) {
- // Use the |found_codec| from |audio_codecs| because it has the correctly
- // mapped payload type.
- filtered_codecs.push_back(found_codec);
- }
- }
+ const ContentInfo* current_audio_content =
+ GetFirstAudioContent(current_description);
+ std::string content_name =
+ current_audio_content ? current_audio_content->name : CN_AUDIO;
cricket::SecurePolicy sdes_policy =
- IsDtlsActive(current_content, current_description) ? cricket::SEC_DISABLED
- : secure();
+ IsDtlsActive(content_name, current_description) ? cricket::SEC_DISABLED
+ : secure();
std::unique_ptr<AudioContentDescription> audio(new AudioContentDescription());
std::vector<std::string> crypto_suites;
- GetSupportedAudioSdesCryptoSuiteNames(session_options.crypto_options,
- &crypto_suites);
+ GetSupportedAudioSdesCryptoSuiteNames(options.crypto_options, &crypto_suites);
if (!CreateMediaContentOffer(
- media_description_options.sender_options, session_options,
- filtered_codecs, sdes_policy, GetCryptos(current_content),
- crypto_suites, audio_rtp_extensions, current_streams, audio.get())) {
+ options,
+ audio_codecs,
+ sdes_policy,
+ GetCryptos(GetFirstAudioContentDescription(current_description)),
+ crypto_suites,
+ audio_rtp_extensions,
+ add_legacy_,
+ current_streams,
+ audio.get())) {
return false;
}
audio->set_lang(lang_);
@@ -1886,13 +1779,13 @@
bool secure_transport = (transport_desc_factory_->secure() != SEC_DISABLED);
SetMediaProtocol(secure_transport, audio.get());
- audio->set_direction(
- media_description_options.direction.ToMediaContentDirection());
+ auto offer_rtd =
+ RtpTransceiverDirection(!audio->streams().empty(), options.recv_audio);
+ audio->set_direction(offer_rtd.ToMediaContentDirection());
- desc->AddContent(media_description_options.mid, NS_JINGLE_RTP,
- media_description_options.stopped, audio.release());
- if (!AddTransportOffer(media_description_options.mid,
- media_description_options.transport_options,
+ desc->AddContent(content_name, NS_JINGLE_RTP, audio.release());
+ if (!AddTransportOffer(content_name,
+ GetTransportOptions(options, content_name),
current_description, desc)) {
return false;
}
@@ -1901,98 +1794,87 @@
}
bool MediaSessionDescriptionFactory::AddVideoContentForOffer(
- const MediaDescriptionOptions& media_description_options,
- const MediaSessionOptions& session_options,
- const ContentInfo* current_content,
+ const MediaSessionOptions& options,
const SessionDescription* current_description,
const RtpHeaderExtensions& video_rtp_extensions,
const VideoCodecs& video_codecs,
StreamParamsVec* current_streams,
SessionDescription* desc) const {
+ const ContentInfo* current_video_content =
+ GetFirstVideoContent(current_description);
+ std::string content_name =
+ current_video_content ? current_video_content->name : CN_VIDEO;
+
cricket::SecurePolicy sdes_policy =
- IsDtlsActive(current_content, current_description) ? cricket::SEC_DISABLED
- : secure();
+ IsDtlsActive(content_name, current_description) ? cricket::SEC_DISABLED
+ : secure();
std::unique_ptr<VideoContentDescription> video(new VideoContentDescription());
std::vector<std::string> crypto_suites;
- GetSupportedVideoSdesCryptoSuiteNames(session_options.crypto_options,
- &crypto_suites);
-
- VideoCodecs filtered_codecs;
- // Add the codecs from current content if exists.
- if (current_content) {
- RTC_DCHECK(IsMediaContentOfType(current_content, MEDIA_TYPE_VIDEO));
- const VideoContentDescription* vcd =
- static_cast<const VideoContentDescription*>(
- current_content->description);
- for (const VideoCodec& codec : vcd->codecs()) {
- if (FindMatchingCodec<VideoCodec>(video_codecs_, video_codecs, codec,
- nullptr)) {
- filtered_codecs.push_back(codec);
- }
- }
- }
- // Add other supported video codecs.
- VideoCodec found_codec;
- for (const VideoCodec& codec : video_codecs_) {
- if (FindMatchingCodec<VideoCodec>(video_codecs_, video_codecs, codec,
- &found_codec) &&
- !FindMatchingCodec<VideoCodec>(video_codecs_, filtered_codecs, codec,
- nullptr)) {
- // Use the |found_codec| from |video_codecs| because it has the correctly
- // mapped payload type.
- filtered_codecs.push_back(found_codec);
- }
- }
-
+ GetSupportedVideoSdesCryptoSuiteNames(options.crypto_options, &crypto_suites);
if (!CreateMediaContentOffer(
- media_description_options.sender_options, session_options,
- filtered_codecs, sdes_policy, GetCryptos(current_content),
- crypto_suites, video_rtp_extensions, current_streams, video.get())) {
+ options,
+ video_codecs,
+ sdes_policy,
+ GetCryptos(GetFirstVideoContentDescription(current_description)),
+ crypto_suites,
+ video_rtp_extensions,
+ add_legacy_,
+ current_streams,
+ video.get())) {
return false;
}
- video->set_bandwidth(kAutoBandwidth);
+ video->set_bandwidth(options.video_bandwidth);
bool secure_transport = (transport_desc_factory_->secure() != SEC_DISABLED);
SetMediaProtocol(secure_transport, video.get());
- video->set_direction(
- media_description_options.direction.ToMediaContentDirection());
+ if (!video->streams().empty()) {
+ if (options.recv_video) {
+ video->set_direction(MD_SENDRECV);
+ } else {
+ video->set_direction(MD_SENDONLY);
+ }
+ } else {
+ if (options.recv_video) {
+ video->set_direction(MD_RECVONLY);
+ } else {
+ video->set_direction(MD_INACTIVE);
+ }
+ }
- desc->AddContent(media_description_options.mid, NS_JINGLE_RTP,
- media_description_options.stopped, video.release());
- if (!AddTransportOffer(media_description_options.mid,
- media_description_options.transport_options,
+ desc->AddContent(content_name, NS_JINGLE_RTP, video.release());
+ if (!AddTransportOffer(content_name,
+ GetTransportOptions(options, content_name),
current_description, desc)) {
return false;
}
+
return true;
}
bool MediaSessionDescriptionFactory::AddDataContentForOffer(
- const MediaDescriptionOptions& media_description_options,
- const MediaSessionOptions& session_options,
- const ContentInfo* current_content,
+ const MediaSessionOptions& options,
const SessionDescription* current_description,
- const DataCodecs& data_codecs,
+ DataCodecs* data_codecs,
StreamParamsVec* current_streams,
SessionDescription* desc) 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.
- if (session_options.data_channel_type == DCT_NONE && current_content) {
- is_sctp = (static_cast<const DataContentDescription*>(
- current_content->description)
- ->protocol() == kMediaProtocolSctp);
- }
+ bool is_sctp = (options.data_channel_type == DCT_SCTP);
+
+ FilterDataCodecs(data_codecs, is_sctp);
+
+ const ContentInfo* current_data_content =
+ GetFirstDataContent(current_description);
+ std::string content_name =
+ current_data_content ? current_data_content->name : CN_DATA;
cricket::SecurePolicy sdes_policy =
- IsDtlsActive(current_content, current_description) ? cricket::SEC_DISABLED
- : secure();
+ IsDtlsActive(content_name, current_description) ? cricket::SEC_DISABLED
+ : secure();
std::vector<std::string> crypto_suites;
if (is_sctp) {
// SDES doesn't make sense for SCTP, so we disable it, and we only
@@ -2008,279 +1890,227 @@
data->set_protocol(
secure_transport ? kMediaProtocolDtlsSctp : kMediaProtocolSctp);
} else {
- GetSupportedDataSdesCryptoSuiteNames(session_options.crypto_options,
+ GetSupportedDataSdesCryptoSuiteNames(options.crypto_options,
&crypto_suites);
}
- // Even SCTP uses a "codec".
if (!CreateMediaContentOffer(
- media_description_options.sender_options, session_options,
- data_codecs, sdes_policy, GetCryptos(current_content), crypto_suites,
- RtpHeaderExtensions(), current_streams, data.get())) {
+ options,
+ *data_codecs,
+ sdes_policy,
+ GetCryptos(GetFirstDataContentDescription(current_description)),
+ crypto_suites,
+ RtpHeaderExtensions(),
+ add_legacy_,
+ current_streams,
+ data.get())) {
return false;
}
if (is_sctp) {
- desc->AddContent(media_description_options.mid, NS_JINGLE_DRAFT_SCTP,
- data.release());
+ desc->AddContent(content_name, NS_JINGLE_DRAFT_SCTP, data.release());
} else {
- data->set_bandwidth(kDataMaxBandwidth);
+ data->set_bandwidth(options.data_bandwidth);
SetMediaProtocol(secure_transport, data.get());
- desc->AddContent(media_description_options.mid, NS_JINGLE_RTP,
- media_description_options.stopped, data.release());
+ desc->AddContent(content_name, NS_JINGLE_RTP, data.release());
}
- if (!AddTransportOffer(media_description_options.mid,
- media_description_options.transport_options,
+ if (!AddTransportOffer(content_name,
+ GetTransportOptions(options, content_name),
current_description, desc)) {
return false;
}
return true;
}
-// |audio_codecs| = set of all possible codecs that can be used, with correct
-// payload type mappings
-//
-// |supported_audio_codecs| = set of codecs that are supported for the direction
-// of this m= section
-//
-// acd->codecs() = set of previously negotiated codecs for this m= section
-//
-// The payload types should come from audio_codecs, but the order should come
-// from acd->codecs() and then supported_codecs, to ensure that re-offers don't
-// change existing codec priority, and that new codecs are added with the right
-// priority.
bool MediaSessionDescriptionFactory::AddAudioContentForAnswer(
- const MediaDescriptionOptions& media_description_options,
- const MediaSessionOptions& session_options,
- const ContentInfo* offer_content,
- const SessionDescription* offer_description,
- const ContentInfo* current_content,
+ const SessionDescription* offer,
+ const MediaSessionOptions& options,
const SessionDescription* current_description,
const TransportInfo* bundle_transport,
- const AudioCodecs& audio_codecs,
StreamParamsVec* current_streams,
SessionDescription* answer) const {
- const AudioContentDescription* offer_audio_description =
- static_cast<const AudioContentDescription*>(offer_content->description);
+ const ContentInfo* audio_content = GetFirstAudioContent(offer);
+ const AudioContentDescription* offer_audio =
+ static_cast<const AudioContentDescription*>(audio_content->description);
std::unique_ptr<TransportDescription> audio_transport(
- CreateTransportAnswer(media_description_options.mid, offer_description,
- media_description_options.transport_options,
+ CreateTransportAnswer(audio_content->name, offer,
+ GetTransportOptions(options, audio_content->name),
current_description, bundle_transport != nullptr));
if (!audio_transport) {
return false;
}
- // Pick codecs based on the requested communications direction in the offer
- // and the selected direction in the answer.
- // Note these will be filtered one final time in CreateMediaContentAnswer.
- auto wants_rtd = media_description_options.direction;
- auto offer_rtd = RtpTransceiverDirection::FromMediaContentDirection(
- offer_audio_description->direction());
+ // Pick codecs based on the requested communications direction in the offer.
+ const bool wants_send =
+ options.HasSendMediaStream(MEDIA_TYPE_AUDIO) || add_legacy_;
+ auto wants_rtd = RtpTransceiverDirection(wants_send, options.recv_audio);
+ auto offer_rtd =
+ RtpTransceiverDirection::FromMediaContentDirection(
+ offer_audio->direction());
auto answer_rtd = NegotiateRtpTransceiverDirection(offer_rtd, wants_rtd);
- AudioCodecs supported_audio_codecs =
- GetAudioCodecsForAnswer(offer_rtd, answer_rtd);
-
- AudioCodecs filtered_codecs;
- // Add the codecs from current content if exists.
- if (current_content) {
- RTC_DCHECK(IsMediaContentOfType(current_content, MEDIA_TYPE_AUDIO));
- const AudioContentDescription* acd =
- static_cast<const AudioContentDescription*>(
- current_content->description);
- for (const AudioCodec& codec : acd->codecs()) {
- if (FindMatchingCodec<AudioCodec>(supported_audio_codecs, audio_codecs,
- codec, nullptr)) {
- filtered_codecs.push_back(codec);
- }
- }
- }
- // Add other supported audio codecs.
- AudioCodec found_codec;
- for (const AudioCodec& codec : supported_audio_codecs) {
- if (FindMatchingCodec<AudioCodec>(supported_audio_codecs, audio_codecs,
- codec, &found_codec) &&
- !FindMatchingCodec<AudioCodec>(supported_audio_codecs, filtered_codecs,
- codec, nullptr)) {
- // Use the |found_codec| from |audio_codecs| because it has the correctly
- // mapped payload type.
- filtered_codecs.push_back(found_codec);
- }
+ AudioCodecs audio_codecs = GetAudioCodecsForAnswer(offer_rtd, answer_rtd);
+ if (!options.vad_enabled) {
+ StripCNCodecs(&audio_codecs);
}
- bool bundle_enabled = offer_description->HasGroup(GROUP_TYPE_BUNDLE) &&
- session_options.bundle_enabled;
+ bool bundle_enabled =
+ offer->HasGroup(GROUP_TYPE_BUNDLE) && options.bundle_enabled;
std::unique_ptr<AudioContentDescription> audio_answer(
new AudioContentDescription());
// Do not require or create SDES cryptos if DTLS is used.
cricket::SecurePolicy sdes_policy =
audio_transport->secure() ? cricket::SEC_DISABLED : secure();
if (!CreateMediaContentAnswer(
- offer_audio_description, media_description_options, session_options,
- filtered_codecs, sdes_policy, GetCryptos(current_content),
- audio_rtp_extensions_, enable_encrypted_rtp_header_extensions_,
- current_streams, bundle_enabled, audio_answer.get())) {
+ offer_audio,
+ options,
+ audio_codecs,
+ sdes_policy,
+ GetCryptos(GetFirstAudioContentDescription(current_description)),
+ audio_rtp_extensions_,
+ enable_encrypted_rtp_header_extensions_,
+ current_streams,
+ add_legacy_,
+ bundle_enabled,
+ audio_answer.get())) {
return false; // Fails the session setup.
}
bool secure = bundle_transport ? bundle_transport->description.secure()
: audio_transport->secure();
- bool rejected = media_description_options.stopped ||
- offer_content->rejected ||
+ bool rejected = !options.has_audio() || audio_content->rejected ||
!IsMediaProtocolSupported(MEDIA_TYPE_AUDIO,
audio_answer->protocol(), secure);
if (!rejected) {
- AddTransportAnswer(media_description_options.mid, *(audio_transport.get()),
- answer);
+ AddTransportAnswer(audio_content->name, *(audio_transport.get()), answer);
} else {
- LOG(LS_INFO) << "Audio m= section '" << media_description_options.mid
- << "' being rejected in answer.";
+ // RFC 3264
+ // The answer MUST contain the same number of m-lines as the offer.
+ LOG(LS_INFO) << "Audio is not supported in the answer.";
}
- answer->AddContent(media_description_options.mid, offer_content->type,
- rejected, audio_answer.release());
+ answer->AddContent(audio_content->name, audio_content->type, rejected,
+ audio_answer.release());
return true;
}
bool MediaSessionDescriptionFactory::AddVideoContentForAnswer(
- const MediaDescriptionOptions& media_description_options,
- const MediaSessionOptions& session_options,
- const ContentInfo* offer_content,
- const SessionDescription* offer_description,
- const ContentInfo* current_content,
+ const SessionDescription* offer,
+ const MediaSessionOptions& options,
const SessionDescription* current_description,
const TransportInfo* bundle_transport,
- const VideoCodecs& video_codecs,
StreamParamsVec* current_streams,
SessionDescription* answer) const {
- const VideoContentDescription* offer_video_description =
- static_cast<const VideoContentDescription*>(offer_content->description);
-
+ const ContentInfo* video_content = GetFirstVideoContent(offer);
std::unique_ptr<TransportDescription> video_transport(
- CreateTransportAnswer(media_description_options.mid, offer_description,
- media_description_options.transport_options,
+ CreateTransportAnswer(video_content->name, offer,
+ GetTransportOptions(options, video_content->name),
current_description, bundle_transport != nullptr));
if (!video_transport) {
return false;
}
- VideoCodecs filtered_codecs;
- // Add the codecs from current content if exists.
- if (current_content) {
- RTC_DCHECK(IsMediaContentOfType(current_content, MEDIA_TYPE_VIDEO));
- const VideoContentDescription* vcd =
- static_cast<const VideoContentDescription*>(
- current_content->description);
- for (const VideoCodec& codec : vcd->codecs()) {
- if (FindMatchingCodec<VideoCodec>(video_codecs_, video_codecs, codec,
- nullptr)) {
- filtered_codecs.push_back(codec);
- }
- }
- }
- // Add other supported video codecs.
- VideoCodec found_codec;
- for (const VideoCodec& codec : video_codecs_) {
- if (FindMatchingCodec<VideoCodec>(video_codecs_, video_codecs, codec,
- &found_codec) &&
- !FindMatchingCodec<VideoCodec>(video_codecs_, filtered_codecs, codec,
- nullptr)) {
- // Use the |found_codec| from |video_codecs| because it has the correctly
- // mapped payload type.
- filtered_codecs.push_back(found_codec);
- }
- }
-
- bool bundle_enabled = offer_description->HasGroup(GROUP_TYPE_BUNDLE) &&
- session_options.bundle_enabled;
-
std::unique_ptr<VideoContentDescription> video_answer(
new VideoContentDescription());
// Do not require or create SDES cryptos if DTLS is used.
cricket::SecurePolicy sdes_policy =
video_transport->secure() ? cricket::SEC_DISABLED : secure();
+ bool bundle_enabled =
+ offer->HasGroup(GROUP_TYPE_BUNDLE) && options.bundle_enabled;
if (!CreateMediaContentAnswer(
- offer_video_description, media_description_options, session_options,
- filtered_codecs, sdes_policy, GetCryptos(current_content),
- video_rtp_extensions_, enable_encrypted_rtp_header_extensions_,
- current_streams, bundle_enabled, video_answer.get())) {
- return false; // Failed the sessin setup.
+ static_cast<const VideoContentDescription*>(
+ video_content->description),
+ options,
+ video_codecs_,
+ sdes_policy,
+ GetCryptos(GetFirstVideoContentDescription(current_description)),
+ video_rtp_extensions_,
+ enable_encrypted_rtp_header_extensions_,
+ current_streams,
+ add_legacy_,
+ bundle_enabled,
+ video_answer.get())) {
+ return false;
}
bool secure = bundle_transport ? bundle_transport->description.secure()
: video_transport->secure();
- bool rejected = media_description_options.stopped ||
- offer_content->rejected ||
+ bool rejected = !options.has_video() || video_content->rejected ||
!IsMediaProtocolSupported(MEDIA_TYPE_VIDEO,
video_answer->protocol(), secure);
if (!rejected) {
- if (!AddTransportAnswer(media_description_options.mid,
- *(video_transport.get()), answer)) {
+ if (!AddTransportAnswer(video_content->name, *(video_transport.get()),
+ answer)) {
return false;
}
- video_answer->set_bandwidth(kAutoBandwidth);
+ video_answer->set_bandwidth(options.video_bandwidth);
} else {
- LOG(LS_INFO) << "Video m= section '" << media_description_options.mid
- << "' being rejected in answer.";
+ // RFC 3264
+ // The answer MUST contain the same number of m-lines as the offer.
+ LOG(LS_INFO) << "Video is not supported in the answer.";
}
- answer->AddContent(media_description_options.mid, offer_content->type,
- rejected, video_answer.release());
+ answer->AddContent(video_content->name, video_content->type, rejected,
+ video_answer.release());
return true;
}
bool MediaSessionDescriptionFactory::AddDataContentForAnswer(
- const MediaDescriptionOptions& media_description_options,
- const MediaSessionOptions& session_options,
- const ContentInfo* offer_content,
- const SessionDescription* offer_description,
- const ContentInfo* current_content,
+ const SessionDescription* offer,
+ const MediaSessionOptions& options,
const SessionDescription* current_description,
const TransportInfo* bundle_transport,
- const DataCodecs& data_codecs,
StreamParamsVec* current_streams,
SessionDescription* answer) const {
+ const ContentInfo* data_content = GetFirstDataContent(offer);
std::unique_ptr<TransportDescription> data_transport(
- CreateTransportAnswer(media_description_options.mid, offer_description,
- media_description_options.transport_options,
+ CreateTransportAnswer(data_content->name, offer,
+ GetTransportOptions(options, data_content->name),
current_description, bundle_transport != nullptr));
if (!data_transport) {
return false;
}
+ bool is_sctp = (options.data_channel_type == DCT_SCTP);
+ std::vector<DataCodec> data_codecs(data_codecs_);
+ FilterDataCodecs(&data_codecs, is_sctp);
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;
+ bool bundle_enabled =
+ offer->HasGroup(GROUP_TYPE_BUNDLE) && options.bundle_enabled;
if (!CreateMediaContentAnswer(
static_cast<const DataContentDescription*>(
- offer_content->description),
- media_description_options, session_options, data_codecs, sdes_policy,
- GetCryptos(current_content), RtpHeaderExtensions(),
- enable_encrypted_rtp_header_extensions_, current_streams,
- bundle_enabled, data_answer.get())) {
+ data_content->description),
+ options,
+ data_codecs_,
+ sdes_policy,
+ GetCryptos(GetFirstDataContentDescription(current_description)),
+ RtpHeaderExtensions(),
+ enable_encrypted_rtp_header_extensions_,
+ current_streams,
+ add_legacy_,
+ bundle_enabled,
+ data_answer.get())) {
return false; // Fails the session setup.
}
// Respond with sctpmap if the offer uses sctpmap.
const DataContentDescription* offer_data_description =
- static_cast<const DataContentDescription*>(offer_content->description);
+ static_cast<const DataContentDescription*>(data_content->description);
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();
- bool rejected = session_options.data_channel_type == DCT_NONE ||
- media_description_options.stopped ||
- offer_content->rejected ||
+ bool rejected = !options.has_data() || data_content->rejected ||
!IsMediaProtocolSupported(MEDIA_TYPE_DATA,
data_answer->protocol(), secure);
if (!rejected) {
- data_answer->set_bandwidth(kDataMaxBandwidth);
- if (!AddTransportAnswer(media_description_options.mid,
- *(data_transport.get()), answer)) {
+ data_answer->set_bandwidth(options.data_bandwidth);
+ if (!AddTransportAnswer(data_content->name, *(data_transport.get()),
+ answer)) {
return false;
}
} else {
@@ -2288,39 +2118,11 @@
// The answer MUST contain the same number of m-lines as the offer.
LOG(LS_INFO) << "Data is not supported in the answer.";
}
- answer->AddContent(media_description_options.mid, offer_content->type,
- rejected, data_answer.release());
+ answer->AddContent(data_content->name, data_content->type, rejected,
+ data_answer.release());
return true;
}
-void MediaSessionDescriptionFactory::ComputeAudioCodecsIntersectionAndUnion() {
- audio_sendrecv_codecs_.clear();
- all_audio_codecs_.clear();
- // Compute the audio codecs union.
- for (const AudioCodec& send : audio_send_codecs_) {
- all_audio_codecs_.push_back(send);
- if (!FindMatchingCodec<AudioCodec>(audio_send_codecs_, audio_recv_codecs_,
- send, nullptr)) {
- // It doesn't make sense to have an RTX codec we support sending but not
- // receiving.
- RTC_DCHECK(!IsRtxCodec(send));
- }
- }
- for (const AudioCodec& recv : audio_recv_codecs_) {
- if (!FindMatchingCodec<AudioCodec>(audio_recv_codecs_, audio_send_codecs_,
- recv, nullptr)) {
- all_audio_codecs_.push_back(recv);
- }
- }
- // Use NegotiateCodecs to merge our codec lists, since the operation is
- // essentially the same. Put send_codecs as the offered_codecs, which is the
- // order we'd like to follow. The reasoning is that encoding is usually more
- // expensive than decoding, and prioritizing a codec in the send list probably
- // means it's a codec we can handle efficiently.
- NegotiateCodecs(audio_recv_codecs_, audio_send_codecs_,
- &audio_sendrecv_codecs_);
-}
-
bool IsMediaContent(const ContentInfo* content) {
return (content &&
(content->type == NS_JINGLE_RTP ||
diff --git a/webrtc/pc/mediasession.h b/webrtc/pc/mediasession.h
index 35bd444..596bd18 100644
--- a/webrtc/pc/mediasession.h
+++ b/webrtc/pc/mediasession.h
@@ -102,72 +102,83 @@
NegotiateRtpTransceiverDirection(RtpTransceiverDirection offer,
RtpTransceiverDirection wants);
-// Options for an RtpSender contained with an media description/"m=" section.
-struct SenderOptions {
- std::string track_id;
- std::string stream_id;
- int num_sim_layers;
-};
-
-// Options for an individual media description/"m=" section.
-struct MediaDescriptionOptions {
- MediaDescriptionOptions(MediaType type,
- const std::string& mid,
- RtpTransceiverDirection direction,
- bool stopped)
- : type(type), mid(mid), direction(direction), stopped(stopped) {}
-
- // TODO(deadbeef): When we don't support Plan B, there will only be one
- // sender per media description and this can be simplified.
- void AddAudioSender(const std::string& track_id,
- const std::string& stream_id);
- void AddVideoSender(const std::string& track_id,
- const std::string& stream_id,
- int num_sim_layers);
-
- // Internally just uses sender_options.
- void AddRtpDataChannel(const std::string& track_id,
- const std::string& stream_id);
-
- MediaType type;
- std::string mid;
- RtpTransceiverDirection direction;
- bool stopped;
- TransportOptions transport_options;
- // Note: There's no equivalent "RtpReceiverOptions" because only send
- // stream information goes in the local descriptions.
- std::vector<SenderOptions> sender_options;
-
- private:
- // Doesn't DCHECK on |type|.
- void AddSenderInternal(const std::string& track_id,
- const std::string& stream_id,
- int num_sim_layers);
-};
-
-// Provides a mechanism for describing how m= sections should be generated.
-// The m= section with index X will use media_description_options[X]. There
-// must be an option for each existing section if creating an answer, or a
-// subsequent offer.
struct MediaSessionOptions {
- MediaSessionOptions() {}
+ MediaSessionOptions()
+ : recv_audio(true),
+ recv_video(false),
+ data_channel_type(DCT_NONE),
+ is_muc(false),
+ vad_enabled(true), // When disabled, removes all CN codecs from SDP.
+ rtcp_mux_enabled(true),
+ bundle_enabled(false),
+ video_bandwidth(kAutoBandwidth),
+ data_bandwidth(kDataMaxBandwidth),
+ rtcp_cname(kDefaultRtcpCname) {}
- bool has_audio() const { return HasMediaDescription(MEDIA_TYPE_AUDIO); }
- bool has_video() const { return HasMediaDescription(MEDIA_TYPE_VIDEO); }
- bool has_data() const { return HasMediaDescription(MEDIA_TYPE_DATA); }
+ bool has_audio() const {
+ return recv_audio || HasSendMediaStream(MEDIA_TYPE_AUDIO);
+ }
+ bool has_video() const {
+ return recv_video || HasSendMediaStream(MEDIA_TYPE_VIDEO);
+ }
+ bool has_data() const { return data_channel_type != DCT_NONE; }
- bool HasMediaDescription(MediaType type) const;
+ // Add a stream with MediaType type and id.
+ // All streams with the same sync_label will get the same CNAME.
+ // All ids must be unique.
+ void AddSendStream(MediaType type,
+ const std::string& id,
+ const std::string& sync_label);
+ void AddSendVideoStream(const std::string& id,
+ const std::string& sync_label,
+ int num_sim_layers);
+ void RemoveSendStream(MediaType type, const std::string& id);
- DataChannelType data_channel_type = DCT_NONE;
- bool is_muc = false;
- bool vad_enabled = true; // When disabled, removes all CN codecs from SDP.
- bool rtcp_mux_enabled = true;
- bool bundle_enabled = false;
- std::string rtcp_cname = kDefaultRtcpCname;
+
+ // Helper function.
+ void AddSendStreamInternal(MediaType type,
+ const std::string& id,
+ const std::string& sync_label,
+ int num_sim_layers);
+
+ bool HasSendMediaStream(MediaType type) const;
+
+ // TODO(deadbeef): Put all the audio/video/data-specific options into a map
+ // structure (content name -> options).
+ // MediaSessionDescriptionFactory assumes there will never be more than one
+ // audio/video/data content, but this will change with unified plan.
+ bool recv_audio;
+ bool recv_video;
+ DataChannelType data_channel_type;
+ bool is_muc;
+ bool vad_enabled;
+ bool rtcp_mux_enabled;
+ bool bundle_enabled;
+ // bps. -1 == auto.
+ int video_bandwidth;
+ int data_bandwidth;
+ bool enable_ice_renomination = false;
+ // content name ("mid") => options.
+ std::map<std::string, TransportOptions> transport_options;
+ std::string rtcp_cname;
rtc::CryptoOptions crypto_options;
- // List of media description options in the same order that the media
- // descriptions will be generated.
- std::vector<MediaDescriptionOptions> media_description_options;
+
+ struct Stream {
+ Stream(MediaType type,
+ const std::string& id,
+ const std::string& sync_label,
+ int num_sim_layers)
+ : type(type), id(id), sync_label(sync_label),
+ num_sim_layers(num_sim_layers) {
+ }
+ MediaType type;
+ std::string id;
+ std::string sync_label;
+ int num_sim_layers;
+ };
+
+ typedef std::vector<Stream> Streams;
+ Streams streams;
};
// "content" (as used in XEP-0166) descriptions for voice and video.
@@ -266,6 +277,7 @@
streams_.push_back(sp);
}
// Sets the CNAME of all StreamParams if it have not been set.
+ // This can be used to set the CNAME of legacy streams.
void SetCnameIfEmpty(const std::string& cname) {
for (cricket::StreamParamsVec::iterator it = streams_.begin();
it != streams_.end(); ++it) {
@@ -457,6 +469,11 @@
void set_data_codecs(const DataCodecs& codecs) { data_codecs_ = codecs; }
SecurePolicy secure() const { return secure_; }
void set_secure(SecurePolicy s) { secure_ = s; }
+ // Decides if a StreamParams shall be added to the audio and video media
+ // content in SessionDescription when CreateOffer and CreateAnswer is called
+ // even if |options| don't include a Stream. This is needed to support legacy
+ // applications. |add_legacy_| is true per default.
+ void set_add_legacy_streams(bool add_legacy) { add_legacy_ = add_legacy; }
void set_enable_encrypted_rtp_header_extensions(bool enable) {
enable_encrypted_rtp_header_extensions_ = enable;
@@ -476,15 +493,13 @@
const AudioCodecs& GetAudioCodecsForAnswer(
const RtpTransceiverDirection& offer,
const RtpTransceiverDirection& answer) const;
- void GetCodecsForOffer(const SessionDescription* current_description,
- AudioCodecs* audio_codecs,
- VideoCodecs* video_codecs,
- DataCodecs* data_codecs) const;
- void GetCodecsForAnswer(const SessionDescription* current_description,
- const SessionDescription* remote_offer,
- AudioCodecs* audio_codecs,
- VideoCodecs* video_codecs,
- DataCodecs* data_codecs) const;
+ void GetCodecsToOffer(const SessionDescription* current_description,
+ const AudioCodecs& supported_audio_codecs,
+ const VideoCodecs& supported_video_codecs,
+ const DataCodecs& supported_data_codecs,
+ AudioCodecs* audio_codecs,
+ VideoCodecs* video_codecs,
+ DataCodecs* data_codecs) const;
void GetRtpHdrExtsToOffer(const SessionDescription* current_description,
RtpHeaderExtensions* audio_extensions,
RtpHeaderExtensions* video_extensions) const;
@@ -511,9 +526,7 @@
// error.
bool AddAudioContentForOffer(
- const MediaDescriptionOptions& media_description_options,
- const MediaSessionOptions& session_options,
- const ContentInfo* current_content,
+ const MediaSessionOptions& options,
const SessionDescription* current_description,
const RtpHeaderExtensions& audio_rtp_extensions,
const AudioCodecs& audio_codecs,
@@ -521,9 +534,7 @@
SessionDescription* desc) const;
bool AddVideoContentForOffer(
- const MediaDescriptionOptions& media_description_options,
- const MediaSessionOptions& session_options,
- const ContentInfo* current_content,
+ const MediaSessionOptions& options,
const SessionDescription* current_description,
const RtpHeaderExtensions& video_rtp_extensions,
const VideoCodecs& video_codecs,
@@ -531,66 +542,43 @@
SessionDescription* desc) const;
bool AddDataContentForOffer(
- const MediaDescriptionOptions& media_description_options,
- const MediaSessionOptions& session_options,
- const ContentInfo* current_content,
+ const MediaSessionOptions& options,
const SessionDescription* current_description,
- const DataCodecs& data_codecs,
+ DataCodecs* data_codecs,
StreamParamsVec* current_streams,
SessionDescription* desc) const;
- bool AddAudioContentForAnswer(
- const MediaDescriptionOptions& media_description_options,
- const MediaSessionOptions& session_options,
- const ContentInfo* offer_content,
- const SessionDescription* offer_description,
- const ContentInfo* current_content,
- const SessionDescription* current_description,
- const TransportInfo* bundle_transport,
- const AudioCodecs& audio_codecs,
- StreamParamsVec* current_streams,
- SessionDescription* answer) const;
+ bool AddAudioContentForAnswer(const SessionDescription* offer,
+ const MediaSessionOptions& options,
+ const SessionDescription* current_description,
+ const TransportInfo* bundle_transport,
+ StreamParamsVec* current_streams,
+ SessionDescription* answer) const;
- bool AddVideoContentForAnswer(
- const MediaDescriptionOptions& media_description_options,
- const MediaSessionOptions& session_options,
- const ContentInfo* offer_content,
- const SessionDescription* offer_description,
- const ContentInfo* current_content,
- const SessionDescription* current_description,
- const TransportInfo* bundle_transport,
- const VideoCodecs& video_codecs,
- StreamParamsVec* current_streams,
- SessionDescription* answer) const;
+ bool AddVideoContentForAnswer(const SessionDescription* offer,
+ const MediaSessionOptions& options,
+ const SessionDescription* current_description,
+ const TransportInfo* bundle_transport,
+ StreamParamsVec* current_streams,
+ SessionDescription* answer) const;
- bool AddDataContentForAnswer(
- const MediaDescriptionOptions& media_description_options,
- const MediaSessionOptions& session_options,
- const ContentInfo* offer_content,
- const SessionDescription* offer_description,
- const ContentInfo* current_content,
- const SessionDescription* current_description,
- const TransportInfo* bundle_transport,
- const DataCodecs& data_codecs,
- StreamParamsVec* current_streams,
- SessionDescription* answer) const;
-
- void ComputeAudioCodecsIntersectionAndUnion();
+ bool AddDataContentForAnswer(const SessionDescription* offer,
+ const MediaSessionOptions& options,
+ const SessionDescription* current_description,
+ const TransportInfo* bundle_transport,
+ StreamParamsVec* current_streams,
+ SessionDescription* answer) const;
AudioCodecs audio_send_codecs_;
AudioCodecs audio_recv_codecs_;
- // Intersection of send and recv.
AudioCodecs audio_sendrecv_codecs_;
- // Union of send and recv.
- AudioCodecs all_audio_codecs_;
RtpHeaderExtensions audio_rtp_extensions_;
VideoCodecs video_codecs_;
RtpHeaderExtensions video_rtp_extensions_;
DataCodecs data_codecs_;
+ SecurePolicy secure_;
+ bool add_legacy_;
bool enable_encrypted_rtp_header_extensions_ = false;
- // TODO(zhihuang): Rename secure_ to sdec_policy_; rename the related getter
- // and setter.
- SecurePolicy secure_ = SEC_DISABLED;
std::string lang_;
const TransportDescriptionFactory* transport_desc_factory_;
};
diff --git a/webrtc/pc/mediasession_unittest.cc b/webrtc/pc/mediasession_unittest.cc
index f87dda1..ae8d139 100644
--- a/webrtc/pc/mediasession_unittest.cc
+++ b/webrtc/pc/mediasession_unittest.cc
@@ -34,7 +34,6 @@
using cricket::MediaContentDescription;
using cricket::MediaSessionDescriptionFactory;
using cricket::MediaContentDirection;
-using cricket::MediaDescriptionOptions;
using cricket::MediaSessionOptions;
using cricket::MediaType;
using cricket::SessionDescription;
@@ -66,7 +65,6 @@
using cricket::SEC_DISABLED;
using cricket::SEC_ENABLED;
using cricket::SEC_REQUIRED;
-using cricket::RtpTransceiverDirection;
using rtc::CS_AES_CM_128_HMAC_SHA1_32;
using rtc::CS_AES_CM_128_HMAC_SHA1_80;
using rtc::CS_AEAD_AES_128_GCM;
@@ -95,9 +93,6 @@
static const VideoCodec kVideoCodecs1[] = {VideoCodec(96, "H264-SVC"),
VideoCodec(97, "H264")};
-static const VideoCodec kVideoCodecs1Reverse[] = {VideoCodec(97, "H264"),
- VideoCodec(96, "H264-SVC")};
-
static const VideoCodec kVideoCodecs2[] = {VideoCodec(126, "H264"),
VideoCodec(127, "H263")};
@@ -213,11 +208,6 @@
"TCP/TLS/RTP/SAVPF", "TCP/TLS/RTP/SAVP", "UDP/TLS/RTP/SAVPF",
"UDP/TLS/RTP/SAVP"};
-// These constants are used to make the code using "AddMediaSection" more
-// readable.
-static constexpr bool kStopped = true;
-static constexpr bool kActive = false;
-
static bool IsMediaContentOfType(const ContentInfo* content,
MediaType media_type) {
const MediaContentDescription* mdesc =
@@ -247,95 +237,11 @@
return codec_names;
}
-// This is used for test only. MIDs are not the identification of the
-// MediaDescriptionOptions since some end points may not support MID and the SDP
-// may not contain 'mid'.
-std::vector<MediaDescriptionOptions>::iterator FindFirstMediaDescriptionByMid(
- const std::string& mid,
- MediaSessionOptions* opts) {
- return std::find_if(
- opts->media_description_options.begin(),
- opts->media_description_options.end(),
- [mid](const MediaDescriptionOptions& t) { return t.mid == mid; });
-}
-
-// Add a media section to the |session_options|.
-static void AddMediaSection(MediaType type,
- const std::string& mid,
- MediaContentDirection direction,
- bool stopped,
- MediaSessionOptions* opts) {
- opts->media_description_options.push_back(MediaDescriptionOptions(
- type, mid,
- cricket::RtpTransceiverDirection::FromMediaContentDirection(direction),
- stopped));
-}
-
-static void AddAudioVideoSections(MediaContentDirection direction,
- MediaSessionOptions* opts) {
- AddMediaSection(MEDIA_TYPE_AUDIO, "audio", direction, kActive, opts);
- AddMediaSection(MEDIA_TYPE_VIDEO, "video", direction, kActive, opts);
-}
-
-static void AddDataSection(cricket::DataChannelType dct,
- MediaContentDirection direction,
- MediaSessionOptions* opts) {
- opts->data_channel_type = dct;
- AddMediaSection(MEDIA_TYPE_DATA, "data", direction, kActive, opts);
-}
-
-static void AttachSenderToMediaSection(const std::string& mid,
- MediaType type,
- const std::string& track_id,
- const std::string& stream_id,
- int num_sim_layer,
- MediaSessionOptions* session_options) {
- auto it = FindFirstMediaDescriptionByMid(mid, session_options);
- switch (type) {
- case MEDIA_TYPE_AUDIO:
- it->AddAudioSender(track_id, stream_id);
- break;
- case MEDIA_TYPE_VIDEO:
- it->AddVideoSender(track_id, stream_id, num_sim_layer);
- break;
- case MEDIA_TYPE_DATA:
- it->AddRtpDataChannel(track_id, stream_id);
- break;
- default:
- RTC_NOTREACHED();
- }
-}
-
-static void DetachSenderFromMediaSection(const std::string& mid,
- const std::string& track_id,
- MediaSessionOptions* session_options) {
- auto it = FindFirstMediaDescriptionByMid(mid, session_options);
- auto sender_it = it->sender_options.begin();
- for (; sender_it != it->sender_options.end(); ++sender_it) {
- if (sender_it->track_id == track_id) {
- it->sender_options.erase(sender_it);
- return;
- }
- }
- RTC_NOTREACHED();
-}
-
-// Helper function used to create a default MediaSessionOptions for Plan B SDP.
-// (https://tools.ietf.org/html/draft-uberti-rtcweb-plan-00).
-static MediaSessionOptions CreatePlanBMediaSessionOptions() {
- MediaSessionOptions session_options;
- AddMediaSection(MEDIA_TYPE_AUDIO, "audio", cricket::MD_RECVONLY, kActive,
- &session_options);
- return session_options;
-}
-
-// TODO(zhihuang): Most of these tests were written while MediaSessionOptions
-// was designed for Plan B SDP, where only one audio "m=" section and one video
-// "m=" section could be generated, and ordering couldn't be controlled. Many of
-// these tests may be obsolete as a result, and should be refactored or removed.
class MediaSessionDescriptionFactoryTest : public testing::Test {
public:
- MediaSessionDescriptionFactoryTest() : f1_(&tdf1_), f2_(&tdf2_) {
+ MediaSessionDescriptionFactoryTest()
+ : f1_(&tdf1_),
+ f2_(&tdf2_) {
f1_.set_audio_codecs(MAKE_VECTOR(kAudioCodecs1),
MAKE_VECTOR(kAudioCodecs1));
f1_.set_video_codecs(MAKE_VECTOR(kVideoCodecs1));
@@ -399,8 +305,7 @@
return iter != ice_options.end();
}
- void TestTransportInfo(bool offer,
- MediaSessionOptions& options,
+ void TestTransportInfo(bool offer, const MediaSessionOptions& options,
bool has_current_desc) {
const std::string current_audio_ufrag = "current_audio_ufrag";
const std::string current_audio_pwd = "current_audio_pwd";
@@ -445,11 +350,7 @@
EXPECT_EQ(static_cast<size_t>(cricket::ICE_PWD_LENGTH),
ti_audio->description.ice_pwd.size());
}
- auto media_desc_options_it =
- FindFirstMediaDescriptionByMid("audio", &options);
- EXPECT_EQ(
- media_desc_options_it->transport_options.enable_ice_renomination,
- GetIceRenomination(ti_audio));
+ EXPECT_EQ(options.enable_ice_renomination, GetIceRenomination(ti_audio));
} else {
EXPECT_TRUE(ti_audio == NULL);
@@ -473,11 +374,7 @@
ti_video->description.ice_pwd.size());
}
}
- auto media_desc_options_it =
- FindFirstMediaDescriptionByMid("video", &options);
- EXPECT_EQ(
- media_desc_options_it->transport_options.enable_ice_renomination,
- GetIceRenomination(ti_video));
+ EXPECT_EQ(options.enable_ice_renomination, GetIceRenomination(ti_video));
} else {
EXPECT_TRUE(ti_video == NULL);
}
@@ -500,11 +397,7 @@
ti_data->description.ice_pwd.size());
}
}
- auto media_desc_options_it =
- FindFirstMediaDescriptionByMid("data", &options);
- EXPECT_EQ(
- media_desc_options_it->transport_options.enable_ice_renomination,
- GetIceRenomination(ti_data));
+ EXPECT_EQ(options.enable_ice_renomination, GetIceRenomination(ti_data));
} else {
EXPECT_TRUE(ti_video == NULL);
@@ -514,8 +407,9 @@
void TestCryptoWithBundle(bool offer) {
f1_.set_secure(SEC_ENABLED);
MediaSessionOptions options;
- AddAudioVideoSections(cricket::MD_RECVONLY, &options);
- AddDataSection(cricket::DCT_RTP, cricket::MD_RECVONLY, &options);
+ options.recv_audio = true;
+ options.recv_video = true;
+ options.data_channel_type = cricket::DCT_RTP;
std::unique_ptr<SessionDescription> ref_desc;
std::unique_ptr<SessionDescription> desc;
if (offer) {
@@ -561,25 +455,27 @@
// This test that the audio and video media direction is set to
// |expected_direction_in_answer| in an answer if the offer direction is set
- // to |direction_in_offer| and the answer is willing to both send and receive.
+ // to |direction_in_offer|.
void TestMediaDirectionInAnswer(
cricket::MediaContentDirection direction_in_offer,
cricket::MediaContentDirection expected_direction_in_answer) {
- MediaSessionOptions offer_opts;
- AddAudioVideoSections(direction_in_offer, &offer_opts);
-
- std::unique_ptr<SessionDescription> offer(
- f1_.CreateOffer(offer_opts, NULL));
+ MediaSessionOptions opts;
+ opts.recv_video = true;
+ std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
ASSERT_TRUE(offer.get() != NULL);
ContentInfo* ac_offer = offer->GetContentByName("audio");
ASSERT_TRUE(ac_offer != NULL);
+ AudioContentDescription* acd_offer =
+ static_cast<AudioContentDescription*>(ac_offer->description);
+ acd_offer->set_direction(direction_in_offer);
ContentInfo* vc_offer = offer->GetContentByName("video");
ASSERT_TRUE(vc_offer != NULL);
+ VideoContentDescription* vcd_offer =
+ static_cast<VideoContentDescription*>(vc_offer->description);
+ vcd_offer->set_direction(direction_in_offer);
- MediaSessionOptions answer_opts;
- AddAudioVideoSections(cricket::MD_SENDRECV, &answer_opts);
std::unique_ptr<SessionDescription> answer(
- f2_.CreateAnswer(offer.get(), answer_opts, NULL));
+ f2_.CreateAnswer(offer.get(), opts, NULL));
const AudioContentDescription* acd_answer =
GetFirstAudioContentDescription(answer.get());
EXPECT_EQ(expected_direction_in_answer, acd_answer->direction());
@@ -603,13 +499,11 @@
void TestVideoGcmCipher(bool gcm_offer, bool gcm_answer) {
MediaSessionOptions offer_opts;
- AddAudioVideoSections(cricket::MD_RECVONLY, &offer_opts);
+ offer_opts.recv_video = true;
offer_opts.crypto_options.enable_gcm_crypto_suites = gcm_offer;
-
MediaSessionOptions answer_opts;
- AddAudioVideoSections(cricket::MD_RECVONLY, &answer_opts);
+ answer_opts.recv_video = true;
answer_opts.crypto_options.enable_gcm_crypto_suites = gcm_answer;
-
f1_.set_secure(SEC_ENABLED);
f2_.set_secure(SEC_ENABLED);
std::unique_ptr<SessionDescription> offer(
@@ -630,7 +524,7 @@
EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
EXPECT_EQ(MAKE_VECTOR(kAudioCodecsAnswer), acd->codecs());
EXPECT_EQ(kAutoBandwidth, acd->bandwidth()); // negotiated auto bw
- EXPECT_EQ(0U, acd->first_ssrc()); // no sender is attached
+ EXPECT_NE(0U, acd->first_ssrc()); // a random nonzero ssrc
EXPECT_TRUE(acd->rtcp_mux()); // negotiated rtcp-mux
if (gcm_offer && gcm_answer) {
ASSERT_CRYPTO(acd, 1U, CS_AEAD_AES_256_GCM);
@@ -639,7 +533,7 @@
}
EXPECT_EQ(MEDIA_TYPE_VIDEO, vcd->type());
EXPECT_EQ(MAKE_VECTOR(kVideoCodecsAnswer), vcd->codecs());
- EXPECT_EQ(0U, vcd->first_ssrc()); // no sender is attached
+ EXPECT_NE(0U, vcd->first_ssrc()); // a random nonzero ssrc
EXPECT_TRUE(vcd->rtcp_mux()); // negotiated rtcp-mux
if (gcm_offer && gcm_answer) {
ASSERT_CRYPTO(vcd, 1U, CS_AEAD_AES_256_GCM);
@@ -660,7 +554,7 @@
TEST_F(MediaSessionDescriptionFactoryTest, TestCreateAudioOffer) {
f1_.set_secure(SEC_ENABLED);
std::unique_ptr<SessionDescription> offer(
- f1_.CreateOffer(CreatePlanBMediaSessionOptions(), NULL));
+ f1_.CreateOffer(MediaSessionOptions(), NULL));
ASSERT_TRUE(offer.get() != NULL);
const ContentInfo* ac = offer->GetContentByName("audio");
const ContentInfo* vc = offer->GetContentByName("video");
@@ -671,7 +565,7 @@
static_cast<const AudioContentDescription*>(ac->description);
EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
EXPECT_EQ(f1_.audio_sendrecv_codecs(), acd->codecs());
- EXPECT_EQ(0U, acd->first_ssrc()); // no sender is attached.
+ EXPECT_NE(0U, acd->first_ssrc()); // a random nonzero ssrc
EXPECT_EQ(kAutoBandwidth, acd->bandwidth()); // default bandwidth (auto)
EXPECT_TRUE(acd->rtcp_mux()); // rtcp-mux defaults on
ASSERT_CRYPTO(acd, 2U, CS_AES_CM_128_HMAC_SHA1_32);
@@ -681,7 +575,7 @@
// Create a typical video offer, and ensure it matches what we expect.
TEST_F(MediaSessionDescriptionFactoryTest, TestCreateVideoOffer) {
MediaSessionOptions opts;
- AddAudioVideoSections(cricket::MD_RECVONLY, &opts);
+ opts.recv_video = true;
f1_.set_secure(SEC_ENABLED);
std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
ASSERT_TRUE(offer.get() != NULL);
@@ -697,14 +591,14 @@
static_cast<const VideoContentDescription*>(vc->description);
EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
EXPECT_EQ(f1_.audio_sendrecv_codecs(), acd->codecs());
- EXPECT_EQ(0U, acd->first_ssrc()); // no sender is attached
+ EXPECT_NE(0U, acd->first_ssrc()); // a random nonzero ssrc
EXPECT_EQ(kAutoBandwidth, acd->bandwidth()); // default bandwidth (auto)
EXPECT_TRUE(acd->rtcp_mux()); // rtcp-mux defaults on
ASSERT_CRYPTO(acd, 2U, CS_AES_CM_128_HMAC_SHA1_32);
EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), acd->protocol());
EXPECT_EQ(MEDIA_TYPE_VIDEO, vcd->type());
EXPECT_EQ(f1_.video_codecs(), vcd->codecs());
- EXPECT_EQ(0U, vcd->first_ssrc()); // no sender is attached
+ EXPECT_NE(0U, vcd->first_ssrc()); // a random nonzero ssrc
EXPECT_EQ(kAutoBandwidth, vcd->bandwidth()); // default bandwidth (auto)
EXPECT_TRUE(vcd->rtcp_mux()); // rtcp-mux defaults on
ASSERT_CRYPTO(vcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
@@ -722,8 +616,9 @@
ASSERT_EQ(offered_video_codec.id, offered_data_codec.id);
MediaSessionOptions opts;
- AddAudioVideoSections(cricket::MD_RECVONLY, &opts);
- AddDataSection(cricket::DCT_RTP, cricket::MD_RECVONLY, &opts);
+ opts.recv_audio = true;
+ opts.recv_video = true;
+ opts.data_channel_type = cricket::DCT_RTP;
opts.bundle_enabled = true;
std::unique_ptr<SessionDescription> offer(f2_.CreateOffer(opts, NULL));
const VideoContentDescription* vcd =
@@ -743,17 +638,15 @@
EXPECT_EQ(dcd->codecs()[0].name, offered_data_codec.name);
}
-// Test creating an updated offer with bundle, audio, video and data
+// Test creating an updated offer with with bundle, audio, video and data
// after an audio only session has been negotiated.
TEST_F(MediaSessionDescriptionFactoryTest,
TestCreateUpdatedVideoOfferWithBundle) {
f1_.set_secure(SEC_ENABLED);
f2_.set_secure(SEC_ENABLED);
MediaSessionOptions opts;
- AddMediaSection(MEDIA_TYPE_AUDIO, "audio", cricket::MD_RECVONLY, kActive,
- &opts);
- AddMediaSection(MEDIA_TYPE_VIDEO, "video", cricket::MD_INACTIVE, kStopped,
- &opts);
+ opts.recv_audio = true;
+ opts.recv_video = false;
opts.data_channel_type = cricket::DCT_NONE;
opts.bundle_enabled = true;
std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
@@ -761,8 +654,9 @@
f2_.CreateAnswer(offer.get(), opts, NULL));
MediaSessionOptions updated_opts;
- AddAudioVideoSections(cricket::MD_RECVONLY, &updated_opts);
- AddDataSection(cricket::DCT_RTP, cricket::MD_RECVONLY, &updated_opts);
+ updated_opts.recv_audio = true;
+ updated_opts.recv_video = true;
+ updated_opts.data_channel_type = cricket::DCT_RTP;
updated_opts.bundle_enabled = true;
std::unique_ptr<SessionDescription> updated_offer(
f1_.CreateOffer(updated_opts, answer.get()));
@@ -788,8 +682,7 @@
// Create a RTP data offer, and ensure it matches what we expect.
TEST_F(MediaSessionDescriptionFactoryTest, TestCreateRtpDataOffer) {
MediaSessionOptions opts;
- AddAudioVideoSections(cricket::MD_RECVONLY, &opts);
- AddDataSection(cricket::DCT_RTP, cricket::MD_RECVONLY, &opts);
+ opts.data_channel_type = cricket::DCT_RTP;
f1_.set_secure(SEC_ENABLED);
std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
ASSERT_TRUE(offer.get() != NULL);
@@ -805,14 +698,14 @@
static_cast<const DataContentDescription*>(dc->description);
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.
+ EXPECT_NE(0U, acd->first_ssrc()); // a random nonzero ssrc
EXPECT_EQ(kAutoBandwidth, acd->bandwidth()); // default bandwidth (auto)
EXPECT_TRUE(acd->rtcp_mux()); // rtcp-mux defaults on
ASSERT_CRYPTO(acd, 2U, CS_AES_CM_128_HMAC_SHA1_32);
EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), acd->protocol());
EXPECT_EQ(MEDIA_TYPE_DATA, dcd->type());
EXPECT_EQ(f1_.data_codecs(), dcd->codecs());
- EXPECT_EQ(0U, dcd->first_ssrc()); // no sender is attached.
+ EXPECT_NE(0U, dcd->first_ssrc()); // a random nonzero ssrc
EXPECT_EQ(cricket::kDataMaxBandwidth,
dcd->bandwidth()); // default bandwidth (auto)
EXPECT_TRUE(dcd->rtcp_mux()); // rtcp-mux defaults on
@@ -823,8 +716,9 @@
// Create an SCTP data offer with bundle without error.
TEST_F(MediaSessionDescriptionFactoryTest, TestCreateSctpDataOffer) {
MediaSessionOptions opts;
+ opts.recv_audio = false;
opts.bundle_enabled = true;
- AddDataSection(cricket::DCT_SCTP, cricket::MD_SENDRECV, &opts);
+ opts.data_channel_type = cricket::DCT_SCTP;
f1_.set_secure(SEC_ENABLED);
std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
EXPECT_TRUE(offer.get() != NULL);
@@ -834,8 +728,9 @@
// Test creating an sctp data channel from an already generated offer.
TEST_F(MediaSessionDescriptionFactoryTest, TestCreateImplicitSctpDataOffer) {
MediaSessionOptions opts;
+ opts.recv_audio = false;
opts.bundle_enabled = true;
- AddDataSection(cricket::DCT_SCTP, cricket::MD_SENDRECV, &opts);
+ opts.data_channel_type = cricket::DCT_SCTP;
f1_.set_secure(SEC_ENABLED);
std::unique_ptr<SessionDescription> offer1(f1_.CreateOffer(opts, NULL));
ASSERT_TRUE(offer1.get() != NULL);
@@ -861,7 +756,8 @@
TEST_F(MediaSessionDescriptionFactoryTest,
TestCreateOfferWithoutLegacyStreams) {
MediaSessionOptions opts;
- AddAudioVideoSections(cricket::MD_RECVONLY, &opts);
+ opts.recv_video = true;
+ f1_.set_add_legacy_streams(false);
std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
ASSERT_TRUE(offer.get() != NULL);
const ContentInfo* ac = offer->GetContentByName("audio");
@@ -879,14 +775,13 @@
// Creates an audio+video sendonly offer.
TEST_F(MediaSessionDescriptionFactoryTest, TestCreateSendOnlyOffer) {
- MediaSessionOptions opts;
- AddAudioVideoSections(cricket::MD_SENDONLY, &opts);
- AttachSenderToMediaSection("video", MEDIA_TYPE_VIDEO, kVideoTrack1,
- kMediaStream1, 1, &opts);
- AttachSenderToMediaSection("audio", MEDIA_TYPE_AUDIO, kAudioTrack1,
- kMediaStream1, 1, &opts);
+ MediaSessionOptions options;
+ options.recv_audio = false;
+ options.recv_video = false;
+ options.AddSendStream(MEDIA_TYPE_VIDEO, kVideoTrack1, kMediaStream1);
+ options.AddSendStream(MEDIA_TYPE_AUDIO, kAudioTrack1, kMediaStream1);
- std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
+ std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(options, NULL));
ASSERT_TRUE(offer.get() != NULL);
EXPECT_EQ(2u, offer->contents().size());
EXPECT_TRUE(IsMediaContentOfType(&offer->contents()[0], MEDIA_TYPE_AUDIO));
@@ -900,15 +795,16 @@
// SessionDescription is preserved in the new SessionDescription.
TEST_F(MediaSessionDescriptionFactoryTest, TestCreateOfferContentOrder) {
MediaSessionOptions opts;
- AddDataSection(cricket::DCT_SCTP, cricket::MD_SENDRECV, &opts);
+ opts.recv_audio = false;
+ opts.recv_video = false;
+ opts.data_channel_type = cricket::DCT_SCTP;
std::unique_ptr<SessionDescription> offer1(f1_.CreateOffer(opts, NULL));
ASSERT_TRUE(offer1.get() != NULL);
EXPECT_EQ(1u, offer1->contents().size());
EXPECT_TRUE(IsMediaContentOfType(&offer1->contents()[0], MEDIA_TYPE_DATA));
- AddMediaSection(MEDIA_TYPE_VIDEO, "video", cricket::MD_RECVONLY, kActive,
- &opts);
+ opts.recv_video = true;
std::unique_ptr<SessionDescription> offer2(
f1_.CreateOffer(opts, offer1.get()));
ASSERT_TRUE(offer2.get() != NULL);
@@ -916,8 +812,7 @@
EXPECT_TRUE(IsMediaContentOfType(&offer2->contents()[0], MEDIA_TYPE_DATA));
EXPECT_TRUE(IsMediaContentOfType(&offer2->contents()[1], MEDIA_TYPE_VIDEO));
- AddMediaSection(MEDIA_TYPE_AUDIO, "audio", cricket::MD_RECVONLY, kActive,
- &opts);
+ opts.recv_audio = true;
std::unique_ptr<SessionDescription> offer3(
f1_.CreateOffer(opts, offer2.get()));
ASSERT_TRUE(offer3.get() != NULL);
@@ -925,6 +820,15 @@
EXPECT_TRUE(IsMediaContentOfType(&offer3->contents()[0], MEDIA_TYPE_DATA));
EXPECT_TRUE(IsMediaContentOfType(&offer3->contents()[1], MEDIA_TYPE_VIDEO));
EXPECT_TRUE(IsMediaContentOfType(&offer3->contents()[2], MEDIA_TYPE_AUDIO));
+
+ // Verifies the default order is audio-video-data, so that the previous checks
+ // didn't pass by accident.
+ std::unique_ptr<SessionDescription> offer4(f1_.CreateOffer(opts, NULL));
+ ASSERT_TRUE(offer4.get() != NULL);
+ EXPECT_EQ(3u, offer4->contents().size());
+ EXPECT_TRUE(IsMediaContentOfType(&offer4->contents()[0], MEDIA_TYPE_AUDIO));
+ EXPECT_TRUE(IsMediaContentOfType(&offer4->contents()[1], MEDIA_TYPE_VIDEO));
+ EXPECT_TRUE(IsMediaContentOfType(&offer4->contents()[2], MEDIA_TYPE_DATA));
}
// Create a typical audio answer, and ensure it matches what we expect.
@@ -932,10 +836,10 @@
f1_.set_secure(SEC_ENABLED);
f2_.set_secure(SEC_ENABLED);
std::unique_ptr<SessionDescription> offer(
- f1_.CreateOffer(CreatePlanBMediaSessionOptions(), NULL));
+ f1_.CreateOffer(MediaSessionOptions(), NULL));
ASSERT_TRUE(offer.get() != NULL);
std::unique_ptr<SessionDescription> answer(
- f2_.CreateAnswer(offer.get(), CreatePlanBMediaSessionOptions(), NULL));
+ f2_.CreateAnswer(offer.get(), MediaSessionOptions(), NULL));
const ContentInfo* ac = answer->GetContentByName("audio");
const ContentInfo* vc = answer->GetContentByName("video");
ASSERT_TRUE(ac != NULL);
@@ -945,7 +849,7 @@
static_cast<const AudioContentDescription*>(ac->description);
EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
EXPECT_EQ(MAKE_VECTOR(kAudioCodecsAnswer), acd->codecs());
- EXPECT_EQ(0U, acd->first_ssrc()); // no sender is attached
+ EXPECT_NE(0U, acd->first_ssrc()); // a random nonzero ssrc
EXPECT_EQ(kAutoBandwidth, acd->bandwidth()); // negotiated auto bw
EXPECT_TRUE(acd->rtcp_mux()); // negotiated rtcp-mux
ASSERT_CRYPTO(acd, 1U, CS_AES_CM_128_HMAC_SHA1_32);
@@ -957,12 +861,13 @@
TEST_F(MediaSessionDescriptionFactoryTest, TestCreateAudioAnswerGcm) {
f1_.set_secure(SEC_ENABLED);
f2_.set_secure(SEC_ENABLED);
- MediaSessionOptions opts = CreatePlanBMediaSessionOptions();
- opts.crypto_options.enable_gcm_crypto_suites = true;
- std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
+ MediaSessionOptions options;
+ options.crypto_options.enable_gcm_crypto_suites = true;
+ std::unique_ptr<SessionDescription> offer(
+ f1_.CreateOffer(options, NULL));
ASSERT_TRUE(offer.get() != NULL);
std::unique_ptr<SessionDescription> answer(
- f2_.CreateAnswer(offer.get(), opts, NULL));
+ f2_.CreateAnswer(offer.get(), options, NULL));
const ContentInfo* ac = answer->GetContentByName("audio");
const ContentInfo* vc = answer->GetContentByName("video");
ASSERT_TRUE(ac != NULL);
@@ -972,7 +877,7 @@
static_cast<const AudioContentDescription*>(ac->description);
EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
EXPECT_EQ(MAKE_VECTOR(kAudioCodecsAnswer), acd->codecs());
- EXPECT_EQ(0U, acd->first_ssrc()); // no sender is attached
+ EXPECT_NE(0U, acd->first_ssrc()); // a random nonzero ssrc
EXPECT_EQ(kAutoBandwidth, acd->bandwidth()); // negotiated auto bw
EXPECT_TRUE(acd->rtcp_mux()); // negotiated rtcp-mux
ASSERT_CRYPTO(acd, 1U, CS_AEAD_AES_256_GCM);
@@ -982,7 +887,7 @@
// Create a typical video answer, and ensure it matches what we expect.
TEST_F(MediaSessionDescriptionFactoryTest, TestCreateVideoAnswer) {
MediaSessionOptions opts;
- AddAudioVideoSections(cricket::MD_RECVONLY, &opts);
+ opts.recv_video = true;
f1_.set_secure(SEC_ENABLED);
f2_.set_secure(SEC_ENABLED);
std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
@@ -1002,12 +907,12 @@
EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
EXPECT_EQ(MAKE_VECTOR(kAudioCodecsAnswer), acd->codecs());
EXPECT_EQ(kAutoBandwidth, acd->bandwidth()); // negotiated auto bw
- EXPECT_EQ(0U, acd->first_ssrc()); // no sender is attached
+ EXPECT_NE(0U, acd->first_ssrc()); // a random nonzero ssrc
EXPECT_TRUE(acd->rtcp_mux()); // negotiated rtcp-mux
ASSERT_CRYPTO(acd, 1U, CS_AES_CM_128_HMAC_SHA1_32);
EXPECT_EQ(MEDIA_TYPE_VIDEO, vcd->type());
EXPECT_EQ(MAKE_VECTOR(kVideoCodecsAnswer), vcd->codecs());
- EXPECT_EQ(0U, vcd->first_ssrc()); // no sender is attached
+ EXPECT_NE(0U, vcd->first_ssrc()); // a random nonzero ssrc
EXPECT_TRUE(vcd->rtcp_mux()); // negotiated rtcp-mux
ASSERT_CRYPTO(vcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), vcd->protocol());
@@ -1032,8 +937,8 @@
}
TEST_F(MediaSessionDescriptionFactoryTest, TestCreateDataAnswer) {
- MediaSessionOptions opts = CreatePlanBMediaSessionOptions();
- AddDataSection(cricket::DCT_RTP, cricket::MD_RECVONLY, &opts);
+ MediaSessionOptions opts;
+ opts.data_channel_type = cricket::DCT_RTP;
f1_.set_secure(SEC_ENABLED);
f2_.set_secure(SEC_ENABLED);
std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
@@ -1053,20 +958,20 @@
EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
EXPECT_EQ(MAKE_VECTOR(kAudioCodecsAnswer), acd->codecs());
EXPECT_EQ(kAutoBandwidth, acd->bandwidth()); // negotiated auto bw
- EXPECT_EQ(0U, acd->first_ssrc()); // no sender is attached
+ EXPECT_NE(0U, acd->first_ssrc()); // a random nonzero ssrc
EXPECT_TRUE(acd->rtcp_mux()); // negotiated rtcp-mux
ASSERT_CRYPTO(acd, 1U, CS_AES_CM_128_HMAC_SHA1_32);
EXPECT_EQ(MEDIA_TYPE_DATA, dcd->type());
EXPECT_EQ(MAKE_VECTOR(kDataCodecsAnswer), dcd->codecs());
- EXPECT_EQ(0U, dcd->first_ssrc()); // no sender is attached
+ EXPECT_NE(0U, dcd->first_ssrc()); // a random nonzero ssrc
EXPECT_TRUE(dcd->rtcp_mux()); // negotiated rtcp-mux
ASSERT_CRYPTO(dcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), dcd->protocol());
}
TEST_F(MediaSessionDescriptionFactoryTest, TestCreateDataAnswerGcm) {
- MediaSessionOptions opts = CreatePlanBMediaSessionOptions();
- AddDataSection(cricket::DCT_RTP, cricket::MD_RECVONLY, &opts);
+ MediaSessionOptions opts;
+ opts.data_channel_type = cricket::DCT_RTP;
opts.crypto_options.enable_gcm_crypto_suites = true;
f1_.set_secure(SEC_ENABLED);
f2_.set_secure(SEC_ENABLED);
@@ -1087,12 +992,12 @@
EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
EXPECT_EQ(MAKE_VECTOR(kAudioCodecsAnswer), acd->codecs());
EXPECT_EQ(kAutoBandwidth, acd->bandwidth()); // negotiated auto bw
- EXPECT_EQ(0U, acd->first_ssrc()); // no sender is attached
+ EXPECT_NE(0U, acd->first_ssrc()); // a random nonzero ssrc
EXPECT_TRUE(acd->rtcp_mux()); // negotiated rtcp-mux
ASSERT_CRYPTO(acd, 1U, CS_AEAD_AES_256_GCM);
EXPECT_EQ(MEDIA_TYPE_DATA, dcd->type());
EXPECT_EQ(MAKE_VECTOR(kDataCodecsAnswer), dcd->codecs());
- EXPECT_EQ(0U, dcd->first_ssrc()); // no sender is attached
+ EXPECT_NE(0U, dcd->first_ssrc()); // a random nonzero ssrc
EXPECT_TRUE(dcd->rtcp_mux()); // negotiated rtcp-mux
ASSERT_CRYPTO(dcd, 1U, CS_AEAD_AES_256_GCM);
EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), dcd->protocol());
@@ -1102,7 +1007,7 @@
// The answer's use_sctpmap flag should match the offer's.
TEST_F(MediaSessionDescriptionFactoryTest, TestCreateDataAnswerUsesSctpmap) {
MediaSessionOptions opts;
- AddDataSection(cricket::DCT_SCTP, cricket::MD_SENDRECV, &opts);
+ opts.data_channel_type = cricket::DCT_SCTP;
std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
ASSERT_TRUE(offer.get() != NULL);
ContentInfo* dc_offer = offer->GetContentByName("data");
@@ -1123,7 +1028,7 @@
// The answer's use_sctpmap flag should match the offer's.
TEST_F(MediaSessionDescriptionFactoryTest, TestCreateDataAnswerWithoutSctpmap) {
MediaSessionOptions opts;
- AddDataSection(cricket::DCT_SCTP, cricket::MD_SENDRECV, &opts);
+ opts.data_channel_type = cricket::DCT_SCTP;
std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
ASSERT_TRUE(offer.get() != NULL);
ContentInfo* dc_offer = offer->GetContentByName("data");
@@ -1153,7 +1058,7 @@
tdf2_.set_secure(SEC_ENABLED);
MediaSessionOptions opts;
- AddDataSection(cricket::DCT_SCTP, cricket::MD_SENDRECV, &opts);
+ opts.data_channel_type = cricket::DCT_SCTP;
std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, nullptr));
ASSERT_TRUE(offer.get() != nullptr);
ContentInfo* dc_offer = offer->GetContentByName("data");
@@ -1182,20 +1087,19 @@
MediaSessionOptions opts;
// Creates a data only offer.
- AddDataSection(cricket::DCT_SCTP, cricket::MD_SENDRECV, &opts);
+ opts.recv_audio = false;
+ opts.data_channel_type = cricket::DCT_SCTP;
std::unique_ptr<SessionDescription> offer1(f1_.CreateOffer(opts, NULL));
ASSERT_TRUE(offer1.get() != NULL);
// Appends audio to the offer.
- AddMediaSection(MEDIA_TYPE_AUDIO, "audio", cricket::MD_RECVONLY, kActive,
- &opts);
+ opts.recv_audio = true;
std::unique_ptr<SessionDescription> offer2(
f1_.CreateOffer(opts, offer1.get()));
ASSERT_TRUE(offer2.get() != NULL);
// Appends video to the offer.
- AddMediaSection(MEDIA_TYPE_VIDEO, "video", cricket::MD_RECVONLY, kActive,
- &opts);
+ opts.recv_video = true;
std::unique_ptr<SessionDescription> offer3(
f1_.CreateOffer(opts, offer2.get()));
ASSERT_TRUE(offer3.get() != NULL);
@@ -1240,7 +1144,8 @@
TEST_F(MediaSessionDescriptionFactoryTest,
CreateDataAnswerToOfferWithUnknownProtocol) {
MediaSessionOptions opts;
- AddDataSection(cricket::DCT_RTP, cricket::MD_RECVONLY, &opts);
+ opts.data_channel_type = cricket::DCT_RTP;
+ opts.recv_audio = false;
f1_.set_secure(SEC_ENABLED);
f2_.set_secure(SEC_ENABLED);
std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
@@ -1266,7 +1171,7 @@
// Test that the media protocol is RTP/AVPF if DTLS and SDES are disabled.
TEST_F(MediaSessionDescriptionFactoryTest, AudioOfferAnswerWithCryptoDisabled) {
- MediaSessionOptions opts = CreatePlanBMediaSessionOptions();
+ MediaSessionOptions opts;
f1_.set_secure(SEC_DISABLED);
f2_.set_secure(SEC_DISABLED);
tdf1_.set_secure(SEC_DISABLED);
@@ -1295,7 +1200,8 @@
// matches what we expect.
TEST_F(MediaSessionDescriptionFactoryTest, TestOfferAnswerWithRtpExtensions) {
MediaSessionOptions opts;
- AddAudioVideoSections(cricket::MD_RECVONLY, &opts);
+ opts.recv_video = true;
+
f1_.set_audio_rtp_header_extensions(MAKE_VECTOR(kAudioRtpExtension1));
f1_.set_video_rtp_header_extensions(MAKE_VECTOR(kVideoRtpExtension1));
f2_.set_audio_rtp_header_extensions(MAKE_VECTOR(kAudioRtpExtension2));
@@ -1323,7 +1229,7 @@
TEST_F(MediaSessionDescriptionFactoryTest,
TestOfferAnswerWithEncryptedRtpExtensionsBoth) {
MediaSessionOptions opts;
- AddAudioVideoSections(cricket::MD_RECVONLY, &opts);
+ opts.recv_video = true;
f1_.set_enable_encrypted_rtp_header_extensions(true);
f2_.set_enable_encrypted_rtp_header_extensions(true);
@@ -1359,7 +1265,7 @@
TEST_F(MediaSessionDescriptionFactoryTest,
TestOfferAnswerWithEncryptedRtpExtensionsOffer) {
MediaSessionOptions opts;
- AddAudioVideoSections(cricket::MD_RECVONLY, &opts);
+ opts.recv_video = true;
f1_.set_enable_encrypted_rtp_header_extensions(true);
@@ -1394,7 +1300,7 @@
TEST_F(MediaSessionDescriptionFactoryTest,
TestOfferAnswerWithEncryptedRtpExtensionsAnswer) {
MediaSessionOptions opts;
- AddAudioVideoSections(cricket::MD_RECVONLY, &opts);
+ opts.recv_video = true;
f2_.set_enable_encrypted_rtp_header_extensions(true);
@@ -1430,8 +1336,10 @@
TEST_F(MediaSessionDescriptionFactoryTest,
TestCreateAnswerWithoutLegacyStreams) {
MediaSessionOptions opts;
- AddAudioVideoSections(cricket::MD_RECVONLY, &opts);
- AddDataSection(cricket::DCT_RTP, cricket::MD_RECVONLY, &opts);
+ opts.recv_video = true;
+ opts.data_channel_type = cricket::DCT_RTP;
+ f1_.set_add_legacy_streams(false);
+ f2_.set_add_legacy_streams(false);
std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
ASSERT_TRUE(offer.get() != NULL);
std::unique_ptr<SessionDescription> answer(
@@ -1455,8 +1363,8 @@
TEST_F(MediaSessionDescriptionFactoryTest, TestPartial) {
MediaSessionOptions opts;
- AddAudioVideoSections(cricket::MD_RECVONLY, &opts);
- AddDataSection(cricket::DCT_RTP, cricket::MD_RECVONLY, &opts);
+ opts.recv_video = true;
+ opts.data_channel_type = cricket::DCT_RTP;
f1_.set_secure(SEC_ENABLED);
std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
ASSERT_TRUE(offer.get() != NULL);
@@ -1492,18 +1400,18 @@
// Create a typical video answer, and ensure it matches what we expect.
TEST_F(MediaSessionDescriptionFactoryTest, TestCreateVideoAnswerRtcpMux) {
MediaSessionOptions offer_opts;
- AddAudioVideoSections(cricket::MD_SENDRECV, &offer_opts);
- AddDataSection(cricket::DCT_RTP, cricket::MD_SENDRECV, &offer_opts);
-
MediaSessionOptions answer_opts;
- AddAudioVideoSections(cricket::MD_SENDRECV, &answer_opts);
- AddDataSection(cricket::DCT_RTP, cricket::MD_SENDRECV, &answer_opts);
+ answer_opts.recv_video = true;
+ offer_opts.recv_video = true;
+ answer_opts.data_channel_type = cricket::DCT_RTP;
+ offer_opts.data_channel_type = cricket::DCT_RTP;
std::unique_ptr<SessionDescription> offer;
std::unique_ptr<SessionDescription> answer;
offer_opts.rtcp_mux_enabled = true;
answer_opts.rtcp_mux_enabled = true;
+
offer.reset(f1_.CreateOffer(offer_opts, NULL));
answer.reset(f2_.CreateAnswer(offer.get(), answer_opts, NULL));
ASSERT_TRUE(NULL != GetFirstAudioContentDescription(offer.get()));
@@ -1521,6 +1429,7 @@
offer_opts.rtcp_mux_enabled = true;
answer_opts.rtcp_mux_enabled = false;
+
offer.reset(f1_.CreateOffer(offer_opts, NULL));
answer.reset(f2_.CreateAnswer(offer.get(), answer_opts, NULL));
ASSERT_TRUE(NULL != GetFirstAudioContentDescription(offer.get()));
@@ -1538,6 +1447,7 @@
offer_opts.rtcp_mux_enabled = false;
answer_opts.rtcp_mux_enabled = true;
+
offer.reset(f1_.CreateOffer(offer_opts, NULL));
answer.reset(f2_.CreateAnswer(offer.get(), answer_opts, NULL));
ASSERT_TRUE(NULL != GetFirstAudioContentDescription(offer.get()));
@@ -1555,6 +1465,7 @@
offer_opts.rtcp_mux_enabled = false;
answer_opts.rtcp_mux_enabled = false;
+
offer.reset(f1_.CreateOffer(offer_opts, NULL));
answer.reset(f2_.CreateAnswer(offer.get(), answer_opts, NULL));
ASSERT_TRUE(NULL != GetFirstAudioContentDescription(offer.get()));
@@ -1574,16 +1485,11 @@
// Create an audio-only answer to a video offer.
TEST_F(MediaSessionDescriptionFactoryTest, TestCreateAudioAnswerToVideo) {
MediaSessionOptions opts;
- AddMediaSection(MEDIA_TYPE_AUDIO, "audio", cricket::MD_RECVONLY, kActive,
- &opts);
- AddMediaSection(MEDIA_TYPE_VIDEO, "video", cricket::MD_RECVONLY, kActive,
- &opts);
+ opts.recv_video = true;
std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
ASSERT_TRUE(offer.get() != NULL);
-
- opts.media_description_options[1].stopped = true;
std::unique_ptr<SessionDescription> answer(
- f2_.CreateAnswer(offer.get(), opts, NULL));
+ f2_.CreateAnswer(offer.get(), MediaSessionOptions(), NULL));
const ContentInfo* ac = answer->GetContentByName("audio");
const ContentInfo* vc = answer->GetContentByName("video");
ASSERT_TRUE(ac != NULL);
@@ -1594,16 +1500,12 @@
// Create an audio-only answer to an offer with data.
TEST_F(MediaSessionDescriptionFactoryTest, TestCreateNoDataAnswerToDataOffer) {
- MediaSessionOptions opts = CreatePlanBMediaSessionOptions();
+ MediaSessionOptions opts;
opts.data_channel_type = cricket::DCT_RTP;
- AddMediaSection(MEDIA_TYPE_DATA, "data", cricket::MD_RECVONLY, kActive,
- &opts);
std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
ASSERT_TRUE(offer.get() != NULL);
-
- opts.media_description_options[1].stopped = true;
std::unique_ptr<SessionDescription> answer(
- f2_.CreateAnswer(offer.get(), opts, NULL));
+ f2_.CreateAnswer(offer.get(), MediaSessionOptions(), NULL));
const ContentInfo* ac = answer->GetContentByName("audio");
const ContentInfo* dc = answer->GetContentByName("data");
ASSERT_TRUE(ac != NULL);
@@ -1616,8 +1518,8 @@
TEST_F(MediaSessionDescriptionFactoryTest,
CreateAnswerToOfferWithRejectedMedia) {
MediaSessionOptions opts;
- AddAudioVideoSections(cricket::MD_RECVONLY, &opts);
- AddDataSection(cricket::DCT_RTP, cricket::MD_RECVONLY, &opts);
+ opts.recv_video = true;
+ opts.data_channel_type = cricket::DCT_RTP;
std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
ASSERT_TRUE(offer.get() != NULL);
ContentInfo* ac = offer->GetContentByName("audio");
@@ -1650,19 +1552,12 @@
// adding a new video track and replaces one of the audio tracks.
TEST_F(MediaSessionDescriptionFactoryTest, TestCreateMultiStreamVideoOffer) {
MediaSessionOptions opts;
- AddAudioVideoSections(cricket::MD_SENDRECV, &opts);
- AttachSenderToMediaSection("video", MEDIA_TYPE_VIDEO, kVideoTrack1,
- kMediaStream1, 1, &opts);
- AttachSenderToMediaSection("audio", MEDIA_TYPE_AUDIO, kAudioTrack1,
- kMediaStream1, 1, &opts);
- AttachSenderToMediaSection("audio", MEDIA_TYPE_AUDIO, kAudioTrack2,
- kMediaStream1, 1, &opts);
-
- AddDataSection(cricket::DCT_RTP, cricket::MD_SENDRECV, &opts);
- AttachSenderToMediaSection("data", MEDIA_TYPE_DATA, kDataTrack1,
- kMediaStream1, 1, &opts);
- AttachSenderToMediaSection("data", MEDIA_TYPE_DATA, kDataTrack2,
- kMediaStream1, 1, &opts);
+ opts.AddSendStream(MEDIA_TYPE_VIDEO, kVideoTrack1, kMediaStream1);
+ opts.AddSendStream(MEDIA_TYPE_AUDIO, kAudioTrack1, kMediaStream1);
+ opts.AddSendStream(MEDIA_TYPE_AUDIO, kAudioTrack2, kMediaStream1);
+ opts.data_channel_type = cricket::DCT_RTP;
+ opts.AddSendStream(MEDIA_TYPE_DATA, kDataTrack1, kMediaStream1);
+ opts.AddSendStream(MEDIA_TYPE_DATA, kDataTrack2, kMediaStream1);
f1_.set_secure(SEC_ENABLED);
std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
@@ -1727,16 +1622,14 @@
EXPECT_TRUE(dcd->rtcp_mux()); // rtcp-mux defaults on
ASSERT_CRYPTO(dcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
+
// Update the offer. Add a new video track that is not synched to the
// other tracks and replace audio track 2 with audio track 3.
- AttachSenderToMediaSection("video", MEDIA_TYPE_VIDEO, kVideoTrack2,
- kMediaStream2, 1, &opts);
- DetachSenderFromMediaSection("audio", kAudioTrack2, &opts);
- AttachSenderToMediaSection("audio", MEDIA_TYPE_AUDIO, kAudioTrack3,
- kMediaStream1, 1, &opts);
- DetachSenderFromMediaSection("data", kDataTrack2, &opts);
- AttachSenderToMediaSection("data", MEDIA_TYPE_DATA, kDataTrack3,
- kMediaStream1, 1, &opts);
+ opts.AddSendStream(MEDIA_TYPE_VIDEO, kVideoTrack2, kMediaStream2);
+ opts.RemoveSendStream(MEDIA_TYPE_AUDIO, kAudioTrack2);
+ opts.AddSendStream(MEDIA_TYPE_AUDIO, kAudioTrack3, kMediaStream1);
+ opts.RemoveSendStream(MEDIA_TYPE_DATA, kDataTrack2);
+ opts.AddSendStream(MEDIA_TYPE_DATA, kDataTrack3, kMediaStream1);
std::unique_ptr<SessionDescription> updated_offer(
f1_.CreateOffer(opts, offer.get()));
@@ -1798,13 +1691,8 @@
// Create an offer with simulcast video stream.
TEST_F(MediaSessionDescriptionFactoryTest, TestCreateSimulcastVideoOffer) {
MediaSessionOptions opts;
- AddMediaSection(MEDIA_TYPE_AUDIO, "audio", cricket::MD_RECVONLY, kActive,
- &opts);
- AddMediaSection(MEDIA_TYPE_VIDEO, "video", cricket::MD_SENDRECV, kActive,
- &opts);
const int num_sim_layers = 3;
- AttachSenderToMediaSection("video", MEDIA_TYPE_VIDEO, kVideoTrack1,
- kMediaStream1, num_sim_layers, &opts);
+ opts.AddSendVideoStream(kVideoTrack1, kMediaStream1, num_sim_layers);
std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
ASSERT_TRUE(offer.get() != NULL);
@@ -1830,39 +1718,22 @@
// adding a new video track and removes one of the audio tracks.
TEST_F(MediaSessionDescriptionFactoryTest, TestCreateMultiStreamVideoAnswer) {
MediaSessionOptions offer_opts;
- AddMediaSection(MEDIA_TYPE_AUDIO, "audio", cricket::MD_RECVONLY, kActive,
- &offer_opts);
- AddMediaSection(MEDIA_TYPE_VIDEO, "video", cricket::MD_RECVONLY, kActive,
- &offer_opts);
+ offer_opts.recv_video = true;
offer_opts.data_channel_type = cricket::DCT_RTP;
- AddMediaSection(MEDIA_TYPE_DATA, "data", cricket::MD_RECVONLY, kActive,
- &offer_opts);
f1_.set_secure(SEC_ENABLED);
f2_.set_secure(SEC_ENABLED);
std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(offer_opts, NULL));
- MediaSessionOptions answer_opts;
- AddMediaSection(MEDIA_TYPE_AUDIO, "audio", cricket::MD_SENDRECV, kActive,
- &answer_opts);
- AddMediaSection(MEDIA_TYPE_VIDEO, "video", cricket::MD_SENDRECV, kActive,
- &answer_opts);
- AttachSenderToMediaSection("video", MEDIA_TYPE_VIDEO, kVideoTrack1,
- kMediaStream1, 1, &answer_opts);
- AttachSenderToMediaSection("audio", MEDIA_TYPE_AUDIO, kAudioTrack1,
- kMediaStream1, 1, &answer_opts);
- AttachSenderToMediaSection("audio", MEDIA_TYPE_AUDIO, kAudioTrack2,
- kMediaStream1, 1, &answer_opts);
-
- AddMediaSection(MEDIA_TYPE_DATA, "data", cricket::MD_SENDRECV, kActive,
- &answer_opts);
- AttachSenderToMediaSection("data", MEDIA_TYPE_DATA, kDataTrack1,
- kMediaStream1, 1, &answer_opts);
- AttachSenderToMediaSection("data", MEDIA_TYPE_DATA, kDataTrack2,
- kMediaStream1, 1, &answer_opts);
- answer_opts.data_channel_type = cricket::DCT_RTP;
+ MediaSessionOptions opts;
+ opts.AddSendStream(MEDIA_TYPE_VIDEO, kVideoTrack1, kMediaStream1);
+ opts.AddSendStream(MEDIA_TYPE_AUDIO, kAudioTrack1, kMediaStream1);
+ opts.AddSendStream(MEDIA_TYPE_AUDIO, kAudioTrack2, kMediaStream1);
+ opts.data_channel_type = cricket::DCT_RTP;
+ opts.AddSendStream(MEDIA_TYPE_DATA, kDataTrack1, kMediaStream1);
+ opts.AddSendStream(MEDIA_TYPE_DATA, kDataTrack2, kMediaStream1);
std::unique_ptr<SessionDescription> answer(
- f2_.CreateAnswer(offer.get(), answer_opts, NULL));
+ f2_.CreateAnswer(offer.get(), opts, NULL));
ASSERT_TRUE(answer.get() != NULL);
const ContentInfo* ac = answer->GetContentByName("audio");
@@ -1926,12 +1797,11 @@
// Update the answer. Add a new video track that is not synched to the
// other tracks and remove 1 audio track.
- AttachSenderToMediaSection("video", MEDIA_TYPE_VIDEO, kVideoTrack2,
- kMediaStream2, 1, &answer_opts);
- DetachSenderFromMediaSection("audio", kAudioTrack2, &answer_opts);
- DetachSenderFromMediaSection("data", kDataTrack2, &answer_opts);
+ opts.AddSendStream(MEDIA_TYPE_VIDEO, kVideoTrack2, kMediaStream2);
+ opts.RemoveSendStream(MEDIA_TYPE_AUDIO, kAudioTrack2);
+ opts.RemoveSendStream(MEDIA_TYPE_DATA, kDataTrack2);
std::unique_ptr<SessionDescription> updated_answer(
- f2_.CreateAnswer(offer.get(), answer_opts, answer.get()));
+ f2_.CreateAnswer(offer.get(), opts, answer.get()));
ASSERT_TRUE(updated_answer.get() != NULL);
ac = updated_answer->GetContentByName("audio");
@@ -1983,7 +1853,8 @@
TEST_F(MediaSessionDescriptionFactoryTest,
RespondentCreatesOfferAfterCreatingAnswer) {
MediaSessionOptions opts;
- AddAudioVideoSections(cricket::MD_RECVONLY, &opts);
+ opts.recv_audio = true;
+ opts.recv_video = true;
std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
std::unique_ptr<SessionDescription> answer(
@@ -2034,8 +1905,8 @@
TEST_F(MediaSessionDescriptionFactoryTest,
RespondentCreatesOfferAfterCreatingAnswerWithRtx) {
MediaSessionOptions opts;
- AddMediaSection(MEDIA_TYPE_VIDEO, "video", cricket::MD_RECVONLY, kActive,
- &opts);
+ opts.recv_video = true;
+ opts.recv_audio = false;
std::vector<VideoCodec> f1_codecs = MAKE_VECTOR(kVideoCodecs1);
// This creates rtx for H264 with the payload type |f1_| uses.
AddRtxCodec(VideoCodec::CreateRtxCodec(126, kVideoCodecs1[1].id), &f1_codecs);
@@ -2087,8 +1958,8 @@
f1_.set_video_codecs(f1_codecs);
MediaSessionOptions opts;
- AddMediaSection(MEDIA_TYPE_AUDIO, "audio", cricket::MD_RECVONLY, kActive,
- &opts);
+ opts.recv_audio = true;
+ opts.recv_video = false;
std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
std::unique_ptr<SessionDescription> answer(
@@ -2101,8 +1972,8 @@
// Now - let |f2_| add video with RTX and let the payload type the RTX codec
// reference be the same as an audio codec that was negotiated in the
// first offer/answer exchange.
- opts.media_description_options.clear();
- AddAudioVideoSections(cricket::MD_RECVONLY, &opts);
+ opts.recv_audio = true;
+ opts.recv_video = true;
std::vector<VideoCodec> f2_codecs = MAKE_VECTOR(kVideoCodecs2);
int used_pl_type = acd->codecs()[0].id;
@@ -2139,7 +2010,8 @@
TEST_F(MediaSessionDescriptionFactoryTest,
RespondentCreatesOfferWithRtxAfterCreatingAnswerWithoutRtx) {
MediaSessionOptions opts;
- AddAudioVideoSections(cricket::MD_RECVONLY, &opts);
+ opts.recv_video = true;
+ opts.recv_audio = true;
std::vector<VideoCodec> f2_codecs = MAKE_VECTOR(kVideoCodecs2);
// This creates rtx for H264 with the payload type |f2_| uses.
@@ -2177,8 +2049,8 @@
// Test that RTX is ignored when there is no associated payload type parameter.
TEST_F(MediaSessionDescriptionFactoryTest, RtxWithoutApt) {
MediaSessionOptions opts;
- AddMediaSection(MEDIA_TYPE_VIDEO, "video", cricket::MD_RECVONLY, kActive,
- &opts);
+ opts.recv_video = true;
+ opts.recv_audio = false;
std::vector<VideoCodec> f1_codecs = MAKE_VECTOR(kVideoCodecs1);
// This creates RTX without associated payload type parameter.
AddRtxCodec(VideoCodec(126, cricket::kRtxCodecName), &f1_codecs);
@@ -2221,8 +2093,8 @@
// type doesn't match the local value.
TEST_F(MediaSessionDescriptionFactoryTest, FilterOutRtxIfAptDoesntMatch) {
MediaSessionOptions opts;
- AddMediaSection(MEDIA_TYPE_VIDEO, "video", cricket::MD_RECVONLY, kActive,
- &opts);
+ opts.recv_video = true;
+ opts.recv_audio = false;
std::vector<VideoCodec> f1_codecs = MAKE_VECTOR(kVideoCodecs1);
// This creates RTX for H264 in sender.
AddRtxCodec(VideoCodec::CreateRtxCodec(126, kVideoCodecs1[1].id), &f1_codecs);
@@ -2251,8 +2123,8 @@
TEST_F(MediaSessionDescriptionFactoryTest,
FilterOutUnsupportedRtxWhenCreatingAnswer) {
MediaSessionOptions opts;
- AddMediaSection(MEDIA_TYPE_VIDEO, "video", cricket::MD_RECVONLY, kActive,
- &opts);
+ opts.recv_video = true;
+ opts.recv_audio = false;
std::vector<VideoCodec> f1_codecs = MAKE_VECTOR(kVideoCodecs1);
// This creates RTX for H264-SVC in sender.
AddRtxCodec(VideoCodec::CreateRtxCodec(125, kVideoCodecs1[0].id), &f1_codecs);
@@ -2286,8 +2158,8 @@
// to add another.
TEST_F(MediaSessionDescriptionFactoryTest, AddSecondRtxInNewOffer) {
MediaSessionOptions opts;
- AddMediaSection(MEDIA_TYPE_VIDEO, "video", cricket::MD_RECVONLY, kActive,
- &opts);
+ opts.recv_video = true;
+ opts.recv_audio = false;
std::vector<VideoCodec> f1_codecs = MAKE_VECTOR(kVideoCodecs1);
// This creates RTX for H264 for the offerer.
AddRtxCodec(VideoCodec::CreateRtxCodec(126, kVideoCodecs1[1].id), &f1_codecs);
@@ -2321,11 +2193,11 @@
// generated for each simulcast ssrc and correctly grouped.
TEST_F(MediaSessionDescriptionFactoryTest, SimSsrcsGenerateMultipleRtxSsrcs) {
MediaSessionOptions opts;
- AddMediaSection(MEDIA_TYPE_VIDEO, "video", cricket::MD_SENDRECV, kActive,
- &opts);
+ opts.recv_video = true;
+ opts.recv_audio = false;
+
// Add simulcast streams.
- AttachSenderToMediaSection("video", MEDIA_TYPE_VIDEO, "stream1",
- "stream1label", 3, &opts);
+ opts.AddSendVideoStream("stream1", "stream1label", 3);
// Use a single real codec, and then add RTX for it.
std::vector<VideoCodec> f1_codecs;
@@ -2362,11 +2234,11 @@
// together with a FEC-FR grouping.
TEST_F(MediaSessionDescriptionFactoryTest, GenerateFlexfecSsrc) {
MediaSessionOptions opts;
- AddMediaSection(MEDIA_TYPE_VIDEO, "video", cricket::MD_SENDRECV, kActive,
- &opts);
+ opts.recv_video = true;
+ opts.recv_audio = false;
+
// Add single stream.
- AttachSenderToMediaSection("video", MEDIA_TYPE_VIDEO, "stream1",
- "stream1label", 1, &opts);
+ opts.AddSendVideoStream("stream1", "stream1label", 1);
// Use a single real codec, and then add FlexFEC for it.
std::vector<VideoCodec> f1_codecs;
@@ -2402,11 +2274,11 @@
// multiple FlexfecSenders, or through multistream protection.
TEST_F(MediaSessionDescriptionFactoryTest, SimSsrcsGenerateNoFlexfecSsrcs) {
MediaSessionOptions opts;
- AddMediaSection(MEDIA_TYPE_VIDEO, "video", cricket::MD_SENDRECV, kActive,
- &opts);
+ opts.recv_video = true;
+ opts.recv_audio = false;
+
// Add simulcast streams.
- AttachSenderToMediaSection("video", MEDIA_TYPE_VIDEO, "stream1",
- "stream1label", 3, &opts);
+ opts.AddSendVideoStream("stream1", "stream1label", 3);
// Use a single real codec, and then add FlexFEC for it.
std::vector<VideoCodec> f1_codecs;
@@ -2446,7 +2318,8 @@
TEST_F(MediaSessionDescriptionFactoryTest,
RespondentCreatesOfferAfterCreatingAnswerWithRtpExtensions) {
MediaSessionOptions opts;
- AddAudioVideoSections(cricket::MD_RECVONLY, &opts);
+ opts.recv_audio = true;
+ opts.recv_video = true;
f1_.set_audio_rtp_header_extensions(MAKE_VECTOR(kAudioRtpExtension1));
f1_.set_video_rtp_header_extensions(MAKE_VECTOR(kVideoRtpExtension1));
@@ -2500,7 +2373,8 @@
// updated offer (this was previously a bug).
TEST_F(MediaSessionDescriptionFactoryTest, RtpExtensionIdReused) {
MediaSessionOptions opts;
- AddAudioVideoSections(cricket::MD_RECVONLY, &opts);
+ opts.recv_audio = true;
+ opts.recv_video = true;
f1_.set_audio_rtp_header_extensions(MAKE_VECTOR(kAudioRtpExtension3));
f1_.set_video_rtp_header_extensions(MAKE_VECTOR(kVideoRtpExtension3));
@@ -2535,7 +2409,8 @@
// Same as "RtpExtensionIdReused" above for encrypted RTP extensions.
TEST_F(MediaSessionDescriptionFactoryTest, RtpExtensionIdReusedEncrypted) {
MediaSessionOptions opts;
- AddAudioVideoSections(cricket::MD_RECVONLY, &opts);
+ opts.recv_audio = true;
+ opts.recv_video = true;
f1_.set_enable_encrypted_rtp_header_extensions(true);
f2_.set_enable_encrypted_rtp_header_extensions(true);
@@ -2611,47 +2486,45 @@
// ensure the TransportInfo in the SessionDescription matches what we expect.
TEST_F(MediaSessionDescriptionFactoryTest, TestTransportInfoOfferAudio) {
MediaSessionOptions options;
- AddMediaSection(MEDIA_TYPE_AUDIO, "audio", cricket::MD_RECVONLY, kActive,
- &options);
+ options.recv_audio = true;
TestTransportInfo(true, options, false);
}
TEST_F(MediaSessionDescriptionFactoryTest,
TestTransportInfoOfferIceRenomination) {
MediaSessionOptions options;
- AddMediaSection(MEDIA_TYPE_AUDIO, "audio", cricket::MD_RECVONLY, kActive,
- &options);
- options.media_description_options[0]
- .transport_options.enable_ice_renomination = true;
+ options.enable_ice_renomination = true;
TestTransportInfo(true, options, false);
}
TEST_F(MediaSessionDescriptionFactoryTest, TestTransportInfoOfferAudioCurrent) {
MediaSessionOptions options;
- AddMediaSection(MEDIA_TYPE_AUDIO, "audio", cricket::MD_RECVONLY, kActive,
- &options);
+ options.recv_audio = true;
TestTransportInfo(true, options, true);
}
TEST_F(MediaSessionDescriptionFactoryTest, TestTransportInfoOfferMultimedia) {
MediaSessionOptions options;
- AddAudioVideoSections(cricket::MD_RECVONLY, &options);
- AddDataSection(cricket::DCT_RTP, cricket::MD_RECVONLY, &options);
+ options.recv_audio = true;
+ options.recv_video = true;
+ options.data_channel_type = cricket::DCT_RTP;
TestTransportInfo(true, options, false);
}
TEST_F(MediaSessionDescriptionFactoryTest,
TestTransportInfoOfferMultimediaCurrent) {
MediaSessionOptions options;
- AddAudioVideoSections(cricket::MD_RECVONLY, &options);
- AddDataSection(cricket::DCT_RTP, cricket::MD_RECVONLY, &options);
+ options.recv_audio = true;
+ options.recv_video = true;
+ options.data_channel_type = cricket::DCT_RTP;
TestTransportInfo(true, options, true);
}
TEST_F(MediaSessionDescriptionFactoryTest, TestTransportInfoOfferBundle) {
MediaSessionOptions options;
- AddAudioVideoSections(cricket::MD_RECVONLY, &options);
- AddDataSection(cricket::DCT_RTP, cricket::MD_RECVONLY, &options);
+ options.recv_audio = true;
+ options.recv_video = true;
+ options.data_channel_type = cricket::DCT_RTP;
options.bundle_enabled = true;
TestTransportInfo(true, options, false);
}
@@ -2659,56 +2532,55 @@
TEST_F(MediaSessionDescriptionFactoryTest,
TestTransportInfoOfferBundleCurrent) {
MediaSessionOptions options;
- AddAudioVideoSections(cricket::MD_RECVONLY, &options);
- AddDataSection(cricket::DCT_RTP, cricket::MD_RECVONLY, &options);
+ options.recv_audio = true;
+ options.recv_video = true;
+ options.data_channel_type = cricket::DCT_RTP;
options.bundle_enabled = true;
TestTransportInfo(true, options, true);
}
TEST_F(MediaSessionDescriptionFactoryTest, TestTransportInfoAnswerAudio) {
MediaSessionOptions options;
- AddMediaSection(MEDIA_TYPE_AUDIO, "audio", cricket::MD_RECVONLY, kActive,
- &options);
+ options.recv_audio = true;
TestTransportInfo(false, options, false);
}
TEST_F(MediaSessionDescriptionFactoryTest,
TestTransportInfoAnswerIceRenomination) {
MediaSessionOptions options;
- AddMediaSection(MEDIA_TYPE_AUDIO, "audio", cricket::MD_RECVONLY, kActive,
- &options);
- options.media_description_options[0]
- .transport_options.enable_ice_renomination = true;
+ options.enable_ice_renomination = true;
TestTransportInfo(false, options, false);
}
TEST_F(MediaSessionDescriptionFactoryTest,
TestTransportInfoAnswerAudioCurrent) {
MediaSessionOptions options;
- AddMediaSection(MEDIA_TYPE_AUDIO, "audio", cricket::MD_RECVONLY, kActive,
- &options);
+ options.recv_audio = true;
TestTransportInfo(false, options, true);
}
TEST_F(MediaSessionDescriptionFactoryTest, TestTransportInfoAnswerMultimedia) {
MediaSessionOptions options;
- AddAudioVideoSections(cricket::MD_RECVONLY, &options);
- AddDataSection(cricket::DCT_RTP, cricket::MD_RECVONLY, &options);
+ options.recv_audio = true;
+ options.recv_video = true;
+ options.data_channel_type = cricket::DCT_RTP;
TestTransportInfo(false, options, false);
}
TEST_F(MediaSessionDescriptionFactoryTest,
TestTransportInfoAnswerMultimediaCurrent) {
MediaSessionOptions options;
- AddAudioVideoSections(cricket::MD_RECVONLY, &options);
- AddDataSection(cricket::DCT_RTP, cricket::MD_RECVONLY, &options);
+ options.recv_audio = true;
+ options.recv_video = true;
+ options.data_channel_type = cricket::DCT_RTP;
TestTransportInfo(false, options, true);
}
TEST_F(MediaSessionDescriptionFactoryTest, TestTransportInfoAnswerBundle) {
MediaSessionOptions options;
- AddAudioVideoSections(cricket::MD_RECVONLY, &options);
- AddDataSection(cricket::DCT_RTP, cricket::MD_RECVONLY, &options);
+ options.recv_audio = true;
+ options.recv_video = true;
+ options.data_channel_type = cricket::DCT_RTP;
options.bundle_enabled = true;
TestTransportInfo(false, options, false);
}
@@ -2716,8 +2588,9 @@
TEST_F(MediaSessionDescriptionFactoryTest,
TestTransportInfoAnswerBundleCurrent) {
MediaSessionOptions options;
- AddAudioVideoSections(cricket::MD_RECVONLY, &options);
- AddDataSection(cricket::DCT_RTP, cricket::MD_RECVONLY, &options);
+ options.recv_audio = true;
+ options.recv_video = true;
+ options.data_channel_type = cricket::DCT_RTP;
options.bundle_enabled = true;
TestTransportInfo(false, options, true);
}
@@ -2744,7 +2617,7 @@
tdf2_.set_secure(SEC_DISABLED);
std::unique_ptr<SessionDescription> offer(
- f1_.CreateOffer(CreatePlanBMediaSessionOptions(), NULL));
+ f1_.CreateOffer(MediaSessionOptions(), NULL));
ASSERT_TRUE(offer.get() != NULL);
ContentInfo* offer_content = offer->GetContentByName("audio");
ASSERT_TRUE(offer_content != NULL);
@@ -2753,7 +2626,7 @@
offer_audio_desc->set_protocol(cricket::kMediaProtocolDtlsSavpf);
std::unique_ptr<SessionDescription> answer(
- f2_.CreateAnswer(offer.get(), CreatePlanBMediaSessionOptions(), NULL));
+ f2_.CreateAnswer(offer.get(), MediaSessionOptions(), NULL));
ASSERT_TRUE(answer != NULL);
ContentInfo* answer_content = answer->GetContentByName("audio");
ASSERT_TRUE(answer_content != NULL);
@@ -2770,7 +2643,7 @@
tdf2_.set_secure(SEC_ENABLED);
std::unique_ptr<SessionDescription> offer(
- f1_.CreateOffer(CreatePlanBMediaSessionOptions(), NULL));
+ f1_.CreateOffer(MediaSessionOptions(), NULL));
ASSERT_TRUE(offer.get() != NULL);
ContentInfo* offer_content = offer->GetContentByName("audio");
ASSERT_TRUE(offer_content != NULL);
@@ -2779,7 +2652,7 @@
offer_audio_desc->set_protocol(cricket::kMediaProtocolDtlsSavpf);
std::unique_ptr<SessionDescription> answer(
- f2_.CreateAnswer(offer.get(), CreatePlanBMediaSessionOptions(), NULL));
+ f2_.CreateAnswer(offer.get(), MediaSessionOptions(), NULL));
ASSERT_TRUE(answer != NULL);
const ContentInfo* answer_content = answer->GetContentByName("audio");
@@ -2800,7 +2673,8 @@
tdf1_.set_secure(SEC_ENABLED);
tdf2_.set_secure(SEC_DISABLED);
MediaSessionOptions options;
- AddAudioVideoSections(cricket::MD_RECVONLY, &options);
+ options.recv_audio = true;
+ options.recv_video = true;
std::unique_ptr<SessionDescription> offer, answer;
const cricket::MediaContentDescription* audio_media_desc;
const cricket::MediaContentDescription* video_media_desc;
@@ -2896,7 +2770,7 @@
// Test that an answer can't be created if cryptos are required but the offer is
// unsecure.
TEST_F(MediaSessionDescriptionFactoryTest, TestSecureAnswerToUnsecureOffer) {
- MediaSessionOptions options = CreatePlanBMediaSessionOptions();
+ MediaSessionOptions options;
f1_.set_secure(SEC_DISABLED);
tdf1_.set_secure(SEC_DISABLED);
f2_.set_secure(SEC_REQUIRED);
@@ -2917,8 +2791,9 @@
tdf1_.set_secure(SEC_ENABLED);
tdf2_.set_secure(SEC_ENABLED);
MediaSessionOptions options;
- AddAudioVideoSections(cricket::MD_RECVONLY, &options);
- AddDataSection(cricket::DCT_RTP, cricket::MD_RECVONLY, &options);
+ options.recv_audio = true;
+ options.recv_video = true;
+ options.data_channel_type = cricket::DCT_RTP;
std::unique_ptr<SessionDescription> offer, answer;
@@ -2965,7 +2840,8 @@
// offer or answer.
TEST_F(MediaSessionDescriptionFactoryTest, TestVADEnableOption) {
MediaSessionOptions options;
- AddAudioVideoSections(cricket::MD_RECVONLY, &options);
+ options.recv_audio = true;
+ options.recv_video = true;
std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(options, NULL));
ASSERT_TRUE(offer.get() != NULL);
const ContentInfo* audio_content = offer->GetContentByName("audio");
@@ -2983,21 +2859,22 @@
EXPECT_TRUE(VerifyNoCNCodecs(audio_content));
}
-// Test that the generated MIDs match the existing offer.
-TEST_F(MediaSessionDescriptionFactoryTest, TestMIDsMatchesExistingOffer) {
+// Test that the content name ("mid" in SDP) is unchanged when creating a
+// new offer.
+TEST_F(MediaSessionDescriptionFactoryTest,
+ TestContentNameNotChangedInSubsequentOffers) {
MediaSessionOptions opts;
- AddMediaSection(MEDIA_TYPE_AUDIO, "audio_modified", cricket::MD_RECVONLY,
- kActive, &opts);
- AddMediaSection(MEDIA_TYPE_VIDEO, "video_modified", cricket::MD_RECVONLY,
- kActive, &opts);
+ opts.recv_audio = true;
+ opts.recv_video = true;
opts.data_channel_type = cricket::DCT_SCTP;
- AddMediaSection(MEDIA_TYPE_DATA, "data_modified", cricket::MD_SENDRECV,
- kActive, &opts);
- // Create offer.
+ // Create offer and modify the default content names.
std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, nullptr));
+ for (ContentInfo& content : offer->contents()) {
+ content.name.append("_modified");
+ }
+
std::unique_ptr<SessionDescription> updated_offer(
f1_.CreateOffer(opts, offer.get()));
-
const ContentInfo* audio_content = GetFirstAudioContent(updated_offer.get());
const ContentInfo* video_content = GetFirstVideoContent(updated_offer.get());
const ContentInfo* data_content = GetFirstDataContent(updated_offer.get());
@@ -3009,340 +2886,6 @@
EXPECT_EQ("data_modified", data_content->name);
}
-// The following tests verify that the unified plan SDP is supported.
-// Test that we can create an offer with multiple media sections of same media
-// type.
-TEST_F(MediaSessionDescriptionFactoryTest,
- CreateOfferWithMultipleAVMediaSections) {
- MediaSessionOptions opts;
- AddMediaSection(MEDIA_TYPE_AUDIO, "audio_1", cricket::MD_SENDRECV, kActive,
- &opts);
- AttachSenderToMediaSection("audio_1", MEDIA_TYPE_AUDIO, kAudioTrack1,
- kMediaStream1, 1, &opts);
-
- AddMediaSection(MEDIA_TYPE_VIDEO, "video_1", cricket::MD_SENDRECV, kActive,
- &opts);
- AttachSenderToMediaSection("video_1", MEDIA_TYPE_VIDEO, kVideoTrack1,
- kMediaStream1, 1, &opts);
-
- AddMediaSection(MEDIA_TYPE_AUDIO, "audio_2", cricket::MD_SENDRECV, kActive,
- &opts);
- AttachSenderToMediaSection("audio_2", MEDIA_TYPE_AUDIO, kAudioTrack2,
- kMediaStream2, 1, &opts);
-
- AddMediaSection(MEDIA_TYPE_VIDEO, "video_2", cricket::MD_SENDRECV, kActive,
- &opts);
- AttachSenderToMediaSection("video_2", MEDIA_TYPE_VIDEO, kVideoTrack2,
- kMediaStream2, 1, &opts);
- std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, nullptr));
- ASSERT_TRUE(offer);
-
- ASSERT_EQ(4u, offer->contents().size());
- EXPECT_FALSE(offer->contents()[0].rejected);
- const AudioContentDescription* acd =
- static_cast<const AudioContentDescription*>(
- offer->contents()[0].description);
- ASSERT_EQ(1u, acd->streams().size());
- EXPECT_EQ(kAudioTrack1, acd->streams()[0].id);
- EXPECT_EQ(cricket::MD_SENDRECV, acd->direction());
-
- EXPECT_FALSE(offer->contents()[1].rejected);
- const VideoContentDescription* vcd =
- static_cast<const VideoContentDescription*>(
- offer->contents()[1].description);
- ASSERT_EQ(1u, vcd->streams().size());
- EXPECT_EQ(kVideoTrack1, vcd->streams()[0].id);
- EXPECT_EQ(cricket::MD_SENDRECV, vcd->direction());
-
- EXPECT_FALSE(offer->contents()[2].rejected);
- acd = static_cast<const AudioContentDescription*>(
- offer->contents()[2].description);
- ASSERT_EQ(1u, acd->streams().size());
- EXPECT_EQ(kAudioTrack2, acd->streams()[0].id);
- EXPECT_EQ(cricket::MD_SENDRECV, acd->direction());
-
- EXPECT_FALSE(offer->contents()[3].rejected);
- vcd = static_cast<const VideoContentDescription*>(
- offer->contents()[3].description);
- ASSERT_EQ(1u, vcd->streams().size());
- EXPECT_EQ(kVideoTrack2, vcd->streams()[0].id);
- EXPECT_EQ(cricket::MD_SENDRECV, vcd->direction());
-}
-
-// Test that we can create an answer with multiple media sections of same media
-// type.
-TEST_F(MediaSessionDescriptionFactoryTest,
- CreateAnswerWithMultipleAVMediaSections) {
- MediaSessionOptions opts;
- AddMediaSection(MEDIA_TYPE_AUDIO, "audio_1", cricket::MD_SENDRECV, kActive,
- &opts);
- AttachSenderToMediaSection("audio_1", MEDIA_TYPE_AUDIO, kAudioTrack1,
- kMediaStream1, 1, &opts);
-
- AddMediaSection(MEDIA_TYPE_VIDEO, "video_1", cricket::MD_SENDRECV, kActive,
- &opts);
- AttachSenderToMediaSection("video_1", MEDIA_TYPE_VIDEO, kVideoTrack1,
- kMediaStream1, 1, &opts);
-
- AddMediaSection(MEDIA_TYPE_AUDIO, "audio_2", cricket::MD_SENDRECV, kActive,
- &opts);
- AttachSenderToMediaSection("audio_2", MEDIA_TYPE_AUDIO, kAudioTrack2,
- kMediaStream2, 1, &opts);
-
- AddMediaSection(MEDIA_TYPE_VIDEO, "video_2", cricket::MD_SENDRECV, kActive,
- &opts);
- AttachSenderToMediaSection("video_2", MEDIA_TYPE_VIDEO, kVideoTrack2,
- kMediaStream2, 1, &opts);
-
- std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, nullptr));
- ASSERT_TRUE(offer);
- std::unique_ptr<SessionDescription> answer(
- f2_.CreateAnswer(offer.get(), opts, nullptr));
-
- ASSERT_EQ(4u, answer->contents().size());
- EXPECT_FALSE(answer->contents()[0].rejected);
- const AudioContentDescription* acd =
- static_cast<const AudioContentDescription*>(
- answer->contents()[0].description);
- ASSERT_EQ(1u, acd->streams().size());
- EXPECT_EQ(kAudioTrack1, acd->streams()[0].id);
- EXPECT_EQ(cricket::MD_SENDRECV, acd->direction());
-
- EXPECT_FALSE(answer->contents()[1].rejected);
- const VideoContentDescription* vcd =
- static_cast<const VideoContentDescription*>(
- answer->contents()[1].description);
- ASSERT_EQ(1u, vcd->streams().size());
- EXPECT_EQ(kVideoTrack1, vcd->streams()[0].id);
- EXPECT_EQ(cricket::MD_SENDRECV, vcd->direction());
-
- EXPECT_FALSE(answer->contents()[2].rejected);
- acd = static_cast<const AudioContentDescription*>(
- answer->contents()[2].description);
- ASSERT_EQ(1u, acd->streams().size());
- EXPECT_EQ(kAudioTrack2, acd->streams()[0].id);
- EXPECT_EQ(cricket::MD_SENDRECV, acd->direction());
-
- EXPECT_FALSE(answer->contents()[3].rejected);
- vcd = static_cast<const VideoContentDescription*>(
- answer->contents()[3].description);
- ASSERT_EQ(1u, vcd->streams().size());
- EXPECT_EQ(kVideoTrack2, vcd->streams()[0].id);
- EXPECT_EQ(cricket::MD_SENDRECV, vcd->direction());
-}
-
-// Test that the media section will be rejected in offer if the corresponding
-// MediaDescriptionOptions is stopped by the offerer.
-TEST_F(MediaSessionDescriptionFactoryTest,
- CreateOfferWithMediaSectionStoppedByOfferer) {
- // Create an offer with two audio sections and one of them is stopped.
- MediaSessionOptions offer_opts;
- AddMediaSection(MEDIA_TYPE_AUDIO, "audio1", cricket::MD_SENDRECV, kActive,
- &offer_opts);
- AddMediaSection(MEDIA_TYPE_AUDIO, "audio2", cricket::MD_INACTIVE, kStopped,
- &offer_opts);
- std::unique_ptr<SessionDescription> offer(
- f1_.CreateOffer(offer_opts, nullptr));
- ASSERT_TRUE(offer);
- ASSERT_EQ(2u, offer->contents().size());
- EXPECT_FALSE(offer->contents()[0].rejected);
- EXPECT_TRUE(offer->contents()[1].rejected);
-}
-
-// Test that the media section will be rejected in answer if the corresponding
-// MediaDescriptionOptions is stopped by the offerer.
-TEST_F(MediaSessionDescriptionFactoryTest,
- CreateAnswerWithMediaSectionStoppedByOfferer) {
- // Create an offer with two audio sections and one of them is stopped.
- MediaSessionOptions offer_opts;
- AddMediaSection(MEDIA_TYPE_AUDIO, "audio1", cricket::MD_SENDRECV, kActive,
- &offer_opts);
- AddMediaSection(MEDIA_TYPE_AUDIO, "audio2", cricket::MD_INACTIVE, kStopped,
- &offer_opts);
- std::unique_ptr<SessionDescription> offer(
- f1_.CreateOffer(offer_opts, nullptr));
- ASSERT_TRUE(offer);
- ASSERT_EQ(2u, offer->contents().size());
- EXPECT_FALSE(offer->contents()[0].rejected);
- EXPECT_TRUE(offer->contents()[1].rejected);
-
- // Create an answer based on the offer.
- MediaSessionOptions answer_opts;
- AddMediaSection(MEDIA_TYPE_AUDIO, "audio1", cricket::MD_SENDRECV, kActive,
- &answer_opts);
- AddMediaSection(MEDIA_TYPE_AUDIO, "audio2", cricket::MD_SENDRECV, kActive,
- &answer_opts);
- std::unique_ptr<SessionDescription> answer(
- f2_.CreateAnswer(offer.get(), answer_opts, nullptr));
- ASSERT_EQ(2u, answer->contents().size());
- EXPECT_FALSE(answer->contents()[0].rejected);
- EXPECT_TRUE(answer->contents()[1].rejected);
-}
-
-// Test that the media section will be rejected in answer if the corresponding
-// MediaDescriptionOptions is stopped by the answerer.
-TEST_F(MediaSessionDescriptionFactoryTest,
- CreateAnswerWithMediaSectionRejectedByAnswerer) {
- // Create an offer with two audio sections.
- MediaSessionOptions offer_opts;
- AddMediaSection(MEDIA_TYPE_AUDIO, "audio1", cricket::MD_SENDRECV, kActive,
- &offer_opts);
- AddMediaSection(MEDIA_TYPE_AUDIO, "audio2", cricket::MD_SENDRECV, kActive,
- &offer_opts);
- std::unique_ptr<SessionDescription> offer(
- f1_.CreateOffer(offer_opts, nullptr));
- ASSERT_TRUE(offer);
- ASSERT_EQ(2u, offer->contents().size());
- ASSERT_FALSE(offer->contents()[0].rejected);
- ASSERT_FALSE(offer->contents()[1].rejected);
-
- // The answerer rejects one of the audio sections.
- MediaSessionOptions answer_opts;
- AddMediaSection(MEDIA_TYPE_AUDIO, "audio1", cricket::MD_SENDRECV, kActive,
- &answer_opts);
- AddMediaSection(MEDIA_TYPE_AUDIO, "audio2", cricket::MD_INACTIVE, kStopped,
- &answer_opts);
- std::unique_ptr<SessionDescription> answer(
- f2_.CreateAnswer(offer.get(), answer_opts, nullptr));
- ASSERT_EQ(2u, answer->contents().size());
- EXPECT_FALSE(answer->contents()[0].rejected);
- EXPECT_TRUE(answer->contents()[1].rejected);
-}
-
-// Test the generated media sections has the same order of the
-// corresponding MediaDescriptionOptions.
-TEST_F(MediaSessionDescriptionFactoryTest,
- CreateOfferRespectsMediaDescriptionOptionsOrder) {
- MediaSessionOptions opts;
- // This tests put video section first because normally audio comes first by
- // default.
- AddMediaSection(MEDIA_TYPE_VIDEO, "video", cricket::MD_SENDRECV, kActive,
- &opts);
- AddMediaSection(MEDIA_TYPE_AUDIO, "audio", cricket::MD_SENDRECV, kActive,
- &opts);
- std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, nullptr));
-
- ASSERT_TRUE(offer);
- ASSERT_EQ(2u, offer->contents().size());
- EXPECT_EQ("video", offer->contents()[0].name);
- EXPECT_EQ("audio", offer->contents()[1].name);
-}
-
-// Test that different media sections using the same codec have same payload
-// type.
-TEST_F(MediaSessionDescriptionFactoryTest,
- PayloadTypesSharedByMediaSectionsOfSameType) {
- MediaSessionOptions opts;
- AddMediaSection(MEDIA_TYPE_VIDEO, "video1", cricket::MD_SENDRECV, kActive,
- &opts);
- AddMediaSection(MEDIA_TYPE_VIDEO, "video2", cricket::MD_SENDRECV, kActive,
- &opts);
- // Create an offer with two video sections using same codecs.
- std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, nullptr));
- ASSERT_TRUE(offer);
- ASSERT_EQ(2u, offer->contents().size());
- const VideoContentDescription* vcd1 =
- static_cast<const VideoContentDescription*>(
- offer->contents()[0].description);
- const VideoContentDescription* vcd2 =
- static_cast<const VideoContentDescription*>(
- offer->contents()[1].description);
- EXPECT_EQ(vcd1->codecs().size(), vcd2->codecs().size());
- ASSERT_EQ(2u, vcd1->codecs().size());
- EXPECT_EQ(vcd1->codecs()[0].name, vcd2->codecs()[0].name);
- EXPECT_EQ(vcd1->codecs()[0].id, vcd2->codecs()[0].id);
- EXPECT_EQ(vcd1->codecs()[1].name, vcd2->codecs()[1].name);
- EXPECT_EQ(vcd1->codecs()[1].id, vcd2->codecs()[1].id);
-
- // Create answer and negotiate the codecs.
- std::unique_ptr<SessionDescription> answer(
- f2_.CreateAnswer(offer.get(), opts, nullptr));
- ASSERT_TRUE(answer);
- ASSERT_EQ(2u, answer->contents().size());
- vcd1 = static_cast<const VideoContentDescription*>(
- answer->contents()[0].description);
- vcd2 = static_cast<const VideoContentDescription*>(
- answer->contents()[1].description);
- EXPECT_EQ(vcd1->codecs().size(), vcd2->codecs().size());
- ASSERT_EQ(1u, vcd1->codecs().size());
- EXPECT_EQ(vcd1->codecs()[0].name, vcd2->codecs()[0].name);
- EXPECT_EQ(vcd1->codecs()[0].id, vcd2->codecs()[0].id);
-}
-
-// Test that the codec preference order per media section is respected in
-// subsequent offer.
-TEST_F(MediaSessionDescriptionFactoryTest,
- CreateOfferRespectsCodecPreferenceOrder) {
- MediaSessionOptions opts;
- AddMediaSection(MEDIA_TYPE_VIDEO, "video1", cricket::MD_SENDRECV, kActive,
- &opts);
- AddMediaSection(MEDIA_TYPE_VIDEO, "video2", cricket::MD_SENDRECV, kActive,
- &opts);
- // Create an offer with two video sections using same codecs.
- std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, nullptr));
- ASSERT_TRUE(offer);
- ASSERT_EQ(2u, offer->contents().size());
- VideoContentDescription* vcd1 =
- static_cast<VideoContentDescription*>(offer->contents()[0].description);
- const VideoContentDescription* vcd2 =
- static_cast<const VideoContentDescription*>(
- offer->contents()[1].description);
- auto video_codecs = MAKE_VECTOR(kVideoCodecs1);
- EXPECT_EQ(video_codecs, vcd1->codecs());
- EXPECT_EQ(video_codecs, vcd2->codecs());
-
- // Change the codec preference of the first video section and create a
- // follow-up offer.
- auto video_codecs_reverse = MAKE_VECTOR(kVideoCodecs1Reverse);
- vcd1->set_codecs(video_codecs_reverse);
- std::unique_ptr<SessionDescription> updated_offer(
- f1_.CreateOffer(opts, offer.get()));
- vcd1 = static_cast<VideoContentDescription*>(
- updated_offer->contents()[0].description);
- vcd2 = static_cast<const VideoContentDescription*>(
- updated_offer->contents()[1].description);
- // The video codec preference order should be respected.
- EXPECT_EQ(video_codecs_reverse, vcd1->codecs());
- EXPECT_EQ(video_codecs, vcd2->codecs());
-}
-
-// Test that the codec preference order per media section is respected in
-// the answer.
-TEST_F(MediaSessionDescriptionFactoryTest,
- CreateAnswerRespectsCodecPreferenceOrder) {
- MediaSessionOptions opts;
- AddMediaSection(MEDIA_TYPE_VIDEO, "video1", cricket::MD_SENDRECV, kActive,
- &opts);
- AddMediaSection(MEDIA_TYPE_VIDEO, "video2", cricket::MD_SENDRECV, kActive,
- &opts);
- // Create an offer with two video sections using same codecs.
- std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, nullptr));
- ASSERT_TRUE(offer);
- ASSERT_EQ(2u, offer->contents().size());
- VideoContentDescription* vcd1 =
- static_cast<VideoContentDescription*>(offer->contents()[0].description);
- const VideoContentDescription* vcd2 =
- static_cast<const VideoContentDescription*>(
- offer->contents()[1].description);
- auto video_codecs = MAKE_VECTOR(kVideoCodecs1);
- EXPECT_EQ(video_codecs, vcd1->codecs());
- EXPECT_EQ(video_codecs, vcd2->codecs());
-
- // Change the codec preference of the first video section and create an
- // answer.
- auto video_codecs_reverse = MAKE_VECTOR(kVideoCodecs1Reverse);
- vcd1->set_codecs(video_codecs_reverse);
- std::unique_ptr<SessionDescription> answer(
- f1_.CreateAnswer(offer.get(), opts, nullptr));
- vcd1 =
- static_cast<VideoContentDescription*>(answer->contents()[0].description);
- vcd2 = static_cast<const VideoContentDescription*>(
- answer->contents()[1].description);
- // The video codec preference order should be respected.
- EXPECT_EQ(video_codecs_reverse, vcd1->codecs());
- EXPECT_EQ(video_codecs, vcd2->codecs());
-}
-
class MediaProtocolTest : public ::testing::TestWithParam<const char*> {
public:
MediaProtocolTest() : f1_(&tdf1_), f2_(&tdf2_) {
@@ -3373,7 +2916,7 @@
TEST_P(MediaProtocolTest, TestAudioVideoAcceptance) {
MediaSessionOptions opts;
- AddAudioVideoSections(cricket::MD_RECVONLY, &opts);
+ opts.recv_video = true;
std::unique_ptr<SessionDescription> offer(f1_.CreateOffer(opts, nullptr));
ASSERT_TRUE(offer.get() != nullptr);
// Set the protocol for all the contents.
@@ -3433,47 +2976,32 @@
// Test proper merge
sf.set_audio_codecs(send_codecs, recv_codecs);
- EXPECT_EQ(send_codecs, sf.audio_send_codecs());
- EXPECT_EQ(recv_codecs, sf.audio_recv_codecs());
- EXPECT_EQ(sendrecv_codecs, sf.audio_sendrecv_codecs());
+ EXPECT_TRUE(sf.audio_send_codecs() == send_codecs);
+ EXPECT_TRUE(sf.audio_recv_codecs() == recv_codecs);
+ EXPECT_TRUE(sf.audio_sendrecv_codecs() == sendrecv_codecs);
// Test empty send codecs list
sf.set_audio_codecs(no_codecs, recv_codecs);
- EXPECT_EQ(no_codecs, sf.audio_send_codecs());
- EXPECT_EQ(recv_codecs, sf.audio_recv_codecs());
- EXPECT_EQ(no_codecs, sf.audio_sendrecv_codecs());
+ EXPECT_TRUE(sf.audio_send_codecs() == no_codecs);
+ EXPECT_TRUE(sf.audio_recv_codecs() == recv_codecs);
+ EXPECT_TRUE(sf.audio_sendrecv_codecs() == no_codecs);
// Test empty recv codecs list
sf.set_audio_codecs(send_codecs, no_codecs);
- EXPECT_EQ(send_codecs, sf.audio_send_codecs());
- EXPECT_EQ(no_codecs, sf.audio_recv_codecs());
- EXPECT_EQ(no_codecs, sf.audio_sendrecv_codecs());
+ EXPECT_TRUE(sf.audio_send_codecs() == send_codecs);
+ EXPECT_TRUE(sf.audio_recv_codecs() == no_codecs);
+ EXPECT_TRUE(sf.audio_sendrecv_codecs() == no_codecs);
// Test all empty codec lists
sf.set_audio_codecs(no_codecs, no_codecs);
- EXPECT_EQ(no_codecs, sf.audio_send_codecs());
- EXPECT_EQ(no_codecs, sf.audio_recv_codecs());
- EXPECT_EQ(no_codecs, sf.audio_sendrecv_codecs());
+ EXPECT_TRUE(sf.audio_send_codecs() == no_codecs);
+ EXPECT_TRUE(sf.audio_recv_codecs() == no_codecs);
+ EXPECT_TRUE(sf.audio_sendrecv_codecs() == no_codecs);
}
namespace {
-// Compare the two vectors of codecs ignoring the payload type.
-template <class Codec>
-bool CodecsMatch(const std::vector<Codec>& codecs1,
- const std::vector<Codec>& codecs2) {
- if (codecs1.size() != codecs2.size()) {
- return false;
- }
-
- for (size_t i = 0; i < codecs1.size(); ++i) {
- if (!codecs1[i].Matches(codecs2[i])) {
- return false;
- }
- }
- return true;
-}
-
-void TestAudioCodecsOffer(MediaContentDirection direction) {
+void TestAudioCodecsOffer(MediaContentDirection direction,
+ bool add_legacy_stream) {
TransportDescriptionFactory tdf;
MediaSessionDescriptionFactory sf(&tdf);
const std::vector<AudioCodec> send_codecs = MAKE_VECTOR(kAudioCodecs1);
@@ -3481,56 +3009,57 @@
const std::vector<AudioCodec> sendrecv_codecs =
MAKE_VECTOR(kAudioCodecsAnswer);
sf.set_audio_codecs(send_codecs, recv_codecs);
+ sf.set_add_legacy_streams(add_legacy_stream);
MediaSessionOptions opts;
- AddMediaSection(MEDIA_TYPE_AUDIO, "audio", direction, kActive, &opts);
-
- if (RtpTransceiverDirection::FromMediaContentDirection(direction).send) {
- AttachSenderToMediaSection("audio", MEDIA_TYPE_AUDIO, kAudioTrack1,
- kMediaStream1, 1, &opts);
- }
+ opts.recv_audio = (direction == cricket::MD_RECVONLY ||
+ direction == cricket::MD_SENDRECV);
+ opts.recv_video = false;
+ if (direction == cricket::MD_SENDONLY || direction == cricket::MD_SENDRECV)
+ opts.AddSendStream(MEDIA_TYPE_AUDIO, kAudioTrack1, kMediaStream1);
std::unique_ptr<SessionDescription> offer(sf.CreateOffer(opts, NULL));
ASSERT_TRUE(offer.get() != NULL);
const ContentInfo* ac = offer->GetContentByName("audio");
// If the factory didn't add any audio content to the offer, we cannot check
- // that the codecs put in are right. This happens when we neither want to
- // send nor receive audio. The checks are still in place if at some point
- // we'd instead create an inactive stream.
+ // that the codecs put in are right. This happens when we neither want to send
+ // nor receive audio. The checks are still in place if at some point we'd
+ // instead create an inactive stream.
if (ac) {
AudioContentDescription* acd =
static_cast<AudioContentDescription*>(ac->description);
- // sendrecv and inactive should both present lists as if the channel was
- // to be used for sending and receiving. Inactive essentially means it
- // might eventually be used anything, but we don't know more at this
- // moment.
+ // sendrecv and inactive should both present lists as if the channel was to
+ // be used for sending and receiving. Inactive essentially means it might
+ // eventually be used anything, but we don't know more at this moment.
if (acd->direction() == cricket::MD_SENDONLY) {
- EXPECT_TRUE(CodecsMatch<AudioCodec>(send_codecs, acd->codecs()));
+ EXPECT_TRUE(acd->codecs() == send_codecs);
} else if (acd->direction() == cricket::MD_RECVONLY) {
- EXPECT_TRUE(CodecsMatch<AudioCodec>(recv_codecs, acd->codecs()));
+ EXPECT_TRUE(acd->codecs() == recv_codecs);
} else {
- EXPECT_TRUE(CodecsMatch<AudioCodec>(sendrecv_codecs, acd->codecs()));
+ EXPECT_TRUE(acd->codecs() == sendrecv_codecs);
}
}
}
static const AudioCodec kOfferAnswerCodecs[] = {
- AudioCodec(0, "codec0", 16000, -1, 1),
- AudioCodec(1, "codec1", 8000, 13300, 1),
- AudioCodec(2, "codec2", 8000, 64000, 1),
- AudioCodec(3, "codec3", 8000, 64000, 1),
- AudioCodec(4, "codec4", 8000, 0, 2),
- AudioCodec(5, "codec5", 32000, 0, 1),
- AudioCodec(6, "codec6", 48000, 0, 1)};
+ AudioCodec(0, "codec0", 16000, -1, 1),
+ AudioCodec(1, "codec1", 8000, 13300, 1),
+ AudioCodec(2, "codec2", 8000, 64000, 1),
+ AudioCodec(3, "codec3", 8000, 64000, 1),
+ AudioCodec(4, "codec4", 8000, 0, 2),
+ AudioCodec(5, "codec5", 32000, 0, 1),
+ AudioCodec(6, "codec6", 48000, 0, 1)
+};
-/* The codecs groups below are chosen as per the matrix below. The objective
- * is to have different sets of codecs in the inputs, to get unique sets of
- * codecs after negotiation, depending on offer and answer communication
- * directions. One-way directions in the offer should either result in the
- * opposite direction in the answer, or an inactive answer. Regardless, the
- * choice of codecs should be as if the answer contained the opposite
- * direction. Inactive offers should be treated as sendrecv/sendrecv.
+
+/* The codecs groups below are chosen as per the matrix below. The objective is
+ * to have different sets of codecs in the inputs, to get unique sets of codecs
+ * after negotiation, depending on offer and answer communication directions.
+ * One-way directions in the offer should either result in the opposite
+ * direction in the answer, or an inactive answer. Regardless, the choice of
+ * codecs should be as if the answer contained the opposite direction.
+ * Inactive offers should be treated as sendrecv/sendrecv.
*
* | Offer | Answer | Result
* codec|send recv sr | send recv sr | s/r r/s sr/s sr/r sr/sr
@@ -3543,18 +3072,18 @@
* 6 | x x x | x x x | x x x x x
*/
// Codecs used by offerer in the AudioCodecsAnswerTest
-static const int kOfferSendCodecs[] = {0, 1, 3, 5, 6};
-static const int kOfferRecvCodecs[] = {1, 2, 3, 4, 6};
+static const int kOfferSendCodecs[] = { 0, 1, 3, 5, 6 };
+static const int kOfferRecvCodecs[] = { 1, 2, 3, 4, 6 };
// Codecs used in the answerer in the AudioCodecsAnswerTest. The order is
// jumbled to catch the answer not following the order in the offer.
-static const int kAnswerSendCodecs[] = {6, 5, 2, 3, 4};
-static const int kAnswerRecvCodecs[] = {6, 5, 4, 1, 0};
+static const int kAnswerSendCodecs[] = { 6, 5, 2, 3, 4 };
+static const int kAnswerRecvCodecs[] = { 6, 5, 4, 1, 0 };
// The resulting sets of codecs in the answer in the AudioCodecsAnswerTest
-static const int kResultSend_RecvCodecs[] = {0, 1, 5, 6};
-static const int kResultRecv_SendCodecs[] = {2, 3, 4, 6};
-static const int kResultSendrecv_SendCodecs[] = {3, 6};
-static const int kResultSendrecv_RecvCodecs[] = {1, 6};
-static const int kResultSendrecv_SendrecvCodecs[] = {6};
+static const int kResultSend_RecvCodecs[] = { 0, 1, 5, 6 };
+static const int kResultRecv_SendCodecs[] = { 2, 3, 4, 6 };
+static const int kResultSendrecv_SendCodecs[] = { 3, 6 };
+static const int kResultSendrecv_RecvCodecs[] = { 1, 6 };
+static const int kResultSendrecv_SendrecvCodecs[] = { 6 };
template <typename T, int IDXS>
std::vector<T> VectorFromIndices(const T* array, const int (&indices)[IDXS]) {
@@ -3580,14 +3109,17 @@
VectorFromIndices(kOfferAnswerCodecs, kAnswerSendCodecs),
VectorFromIndices(kOfferAnswerCodecs, kAnswerRecvCodecs));
+ // Never add a legacy stream to offer - we want to control the offer
+ // parameters exactly.
+ offer_factory.set_add_legacy_streams(false);
+ answer_factory.set_add_legacy_streams(add_legacy_stream);
MediaSessionOptions offer_opts;
- AddMediaSection(MEDIA_TYPE_AUDIO, "audio", offer_direction, kActive,
- &offer_opts);
-
- if (RtpTransceiverDirection::FromMediaContentDirection(offer_direction)
- .send) {
- AttachSenderToMediaSection("audio", MEDIA_TYPE_AUDIO, kAudioTrack1,
- kMediaStream1, 1, &offer_opts);
+ offer_opts.recv_audio = (offer_direction == cricket::MD_RECVONLY ||
+ offer_direction == cricket::MD_SENDRECV);
+ offer_opts.recv_video = false;
+ if (offer_direction == cricket::MD_SENDONLY ||
+ offer_direction == cricket::MD_SENDRECV) {
+ offer_opts.AddSendStream(MEDIA_TYPE_AUDIO, kAudioTrack1, kMediaStream1);
}
std::unique_ptr<SessionDescription> offer(
@@ -3595,27 +3127,27 @@
ASSERT_TRUE(offer.get() != NULL);
MediaSessionOptions answer_opts;
- AddMediaSection(MEDIA_TYPE_AUDIO, "audio", answer_direction, kActive,
- &answer_opts);
-
- if (RtpTransceiverDirection::FromMediaContentDirection(answer_direction)
- .send) {
- AttachSenderToMediaSection("audio", MEDIA_TYPE_AUDIO, kAudioTrack1,
- kMediaStream1, 1, &answer_opts);
+ answer_opts.recv_audio = (answer_direction == cricket::MD_RECVONLY ||
+ answer_direction == cricket::MD_SENDRECV);
+ answer_opts.recv_video = false;
+ if (answer_direction == cricket::MD_SENDONLY ||
+ answer_direction == cricket::MD_SENDRECV) {
+ answer_opts.AddSendStream(MEDIA_TYPE_AUDIO, kAudioTrack1, kMediaStream1);
}
std::unique_ptr<SessionDescription> answer(
answer_factory.CreateAnswer(offer.get(), answer_opts, NULL));
const ContentInfo* ac = answer->GetContentByName("audio");
- // If the factory didn't add any audio content to the answer, we cannot
- // check that the codecs put in are right. This happens when we neither want
- // to send nor receive audio. The checks are still in place if at some point
- // we'd instead create an inactive stream.
+ // If the factory didn't add any audio content to the answer, we cannot check
+ // that the codecs put in are right. This happens when we neither want to send
+ // nor receive audio. The checks are still in place if at some point we'd
+ // instead create an inactive stream.
if (ac) {
const AudioContentDescription* acd =
static_cast<const AudioContentDescription*>(ac->description);
EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
+
std::vector<AudioCodec> target_codecs;
// For offers with sendrecv or inactive, we should never reply with more
// codecs than offered, with these codec sets.
@@ -3625,20 +3157,20 @@
kResultSendrecv_SendrecvCodecs);
break;
case cricket::MD_SENDONLY:
- target_codecs =
- VectorFromIndices(kOfferAnswerCodecs, kResultSend_RecvCodecs);
+ target_codecs = VectorFromIndices(kOfferAnswerCodecs,
+ kResultSend_RecvCodecs);
break;
case cricket::MD_RECVONLY:
- target_codecs =
- VectorFromIndices(kOfferAnswerCodecs, kResultRecv_SendCodecs);
+ target_codecs = VectorFromIndices(kOfferAnswerCodecs,
+ kResultRecv_SendCodecs);
break;
case cricket::MD_SENDRECV:
if (acd->direction() == cricket::MD_SENDONLY) {
- target_codecs =
- VectorFromIndices(kOfferAnswerCodecs, kResultSendrecv_SendCodecs);
+ target_codecs = VectorFromIndices(kOfferAnswerCodecs,
+ kResultSendrecv_SendCodecs);
} else if (acd->direction() == cricket::MD_RECVONLY) {
- target_codecs =
- VectorFromIndices(kOfferAnswerCodecs, kResultSendrecv_RecvCodecs);
+ target_codecs = VectorFromIndices(kOfferAnswerCodecs,
+ kResultSendrecv_RecvCodecs);
} else {
target_codecs = VectorFromIndices(kOfferAnswerCodecs,
kResultSendrecv_SendrecvCodecs);
@@ -3646,7 +3178,7 @@
break;
}
- auto format_codecs = [](const std::vector<AudioCodec>& codecs) {
+ auto format_codecs = [] (const std::vector<AudioCodec>& codecs) {
std::stringstream os;
bool first = true;
os << "{";
@@ -3667,31 +3199,36 @@
<< "; got: " << MediaContentDirectionToString(acd->direction());
} else {
EXPECT_EQ(offer_direction, cricket::MD_INACTIVE)
- << "Only inactive offers are allowed to not generate any audio "
- "content";
+ << "Only inactive offers are allowed to not generate any audio content";
}
}
} // namespace
class AudioCodecsOfferTest
- : public ::testing::TestWithParam<MediaContentDirection> {};
+ : public ::testing::TestWithParam<::testing::tuple<MediaContentDirection,
+ bool>> {
+};
TEST_P(AudioCodecsOfferTest, TestCodecsInOffer) {
- TestAudioCodecsOffer(GetParam());
+ TestAudioCodecsOffer(::testing::get<0>(GetParam()),
+ ::testing::get<1>(GetParam()));
}
INSTANTIATE_TEST_CASE_P(MediaSessionDescriptionFactoryTest,
AudioCodecsOfferTest,
- ::testing::Values(cricket::MD_SENDONLY,
- cricket::MD_RECVONLY,
- cricket::MD_SENDRECV,
- cricket::MD_INACTIVE));
+ ::testing::Combine(
+ ::testing::Values(cricket::MD_SENDONLY,
+ cricket::MD_RECVONLY,
+ cricket::MD_SENDRECV,
+ cricket::MD_INACTIVE),
+ ::testing::Bool()));
class AudioCodecsAnswerTest
: public ::testing::TestWithParam<::testing::tuple<MediaContentDirection,
MediaContentDirection,
- bool>> {};
+ bool>> {
+};
TEST_P(AudioCodecsAnswerTest, TestCodecsInAnswer) {
TestAudioCodecsAnswer(::testing::get<0>(GetParam()),
@@ -3699,15 +3236,15 @@
::testing::get<2>(GetParam()));
}
-INSTANTIATE_TEST_CASE_P(
- MediaSessionDescriptionFactoryTest,
- AudioCodecsAnswerTest,
- ::testing::Combine(::testing::Values(cricket::MD_SENDONLY,
- cricket::MD_RECVONLY,
- cricket::MD_SENDRECV,
- cricket::MD_INACTIVE),
- ::testing::Values(cricket::MD_SENDONLY,
- cricket::MD_RECVONLY,
- cricket::MD_SENDRECV,
- cricket::MD_INACTIVE),
- ::testing::Bool()));
+INSTANTIATE_TEST_CASE_P(MediaSessionDescriptionFactoryTest,
+ AudioCodecsAnswerTest,
+ ::testing::Combine(
+ ::testing::Values(cricket::MD_SENDONLY,
+ cricket::MD_RECVONLY,
+ cricket::MD_SENDRECV,
+ cricket::MD_INACTIVE),
+ ::testing::Values(cricket::MD_SENDONLY,
+ cricket::MD_RECVONLY,
+ cricket::MD_SENDRECV,
+ cricket::MD_INACTIVE),
+ ::testing::Bool()));
diff --git a/webrtc/pc/peerconnection.cc b/webrtc/pc/peerconnection.cc
index d975ed9..3af5667 100644
--- a/webrtc/pc/peerconnection.cc
+++ b/webrtc/pc/peerconnection.cc
@@ -133,45 +133,32 @@
(value <= Options::kMaxOfferToReceiveMedia);
}
-// Add options to |[audio/video]_media_description_options| from |senders|.
-void AddRtpSenderOptions(
+// Add the stream and RTP data channel info to |session_options|.
+void AddSendStreams(
+ cricket::MediaSessionOptions* session_options,
const std::vector<rtc::scoped_refptr<
RtpSenderProxyWithInternal<RtpSenderInternal>>>& senders,
- cricket::MediaDescriptionOptions* audio_media_description_options,
- cricket::MediaDescriptionOptions* video_media_description_options) {
- for (const auto& sender : senders) {
- if (sender->media_type() == cricket::MEDIA_TYPE_AUDIO) {
- if (audio_media_description_options) {
- audio_media_description_options->AddAudioSender(
- sender->id(), sender->internal()->stream_id());
- }
- } else {
- RTC_DCHECK(sender->media_type() == cricket::MEDIA_TYPE_VIDEO);
- if (video_media_description_options) {
- video_media_description_options->AddVideoSender(
- sender->id(), sender->internal()->stream_id(), 1);
- }
- }
- }
-}
-
-// Add options to |session_options| from |rtp_data_channels|.
-void AddRtpDataChannelOptions(
const std::map<std::string, rtc::scoped_refptr<DataChannel>>&
- rtp_data_channels,
- cricket::MediaDescriptionOptions* data_media_description_options) {
- if (!data_media_description_options) {
- return;
+ rtp_data_channels) {
+ session_options->streams.clear();
+ for (const auto& sender : senders) {
+ session_options->AddSendStream(sender->media_type(), sender->id(),
+ sender->internal()->stream_id());
}
+
// Check for data channels.
for (const auto& kv : rtp_data_channels) {
const DataChannel* channel = kv.second;
if (channel->state() == DataChannel::kConnecting ||
channel->state() == DataChannel::kOpen) {
- // Legacy RTP data channels are signaled with the track/stream ID set to
- // the data channel's label.
- data_media_description_options->AddRtpDataChannel(channel->label(),
- channel->label());
+ // |streamid| and |sync_label| are both set to the DataChannel label
+ // here so they can be signaled the same way as MediaStreams and Tracks.
+ // For MediaStreams, the sync_label is the MediaStream label and the
+ // track label is the same as |streamid|.
+ const std::string& streamid = channel->label();
+ const std::string& sync_label = channel->label();
+ session_options->AddSendStream(cricket::MEDIA_TYPE_DATA, streamid,
+ sync_label);
}
}
}
@@ -327,62 +314,92 @@
return cname;
}
-bool ValidateOfferAnswerOptions(
- const PeerConnectionInterface::RTCOfferAnswerOptions& rtc_options) {
- return IsValidOfferToReceiveMedia(rtc_options.offer_to_receive_audio) &&
- IsValidOfferToReceiveMedia(rtc_options.offer_to_receive_video);
-}
-
-// From |rtc_options|, fill parts of |session_options| shared by all generated
-// m= sections (in other words, nothing that involves a map/array).
-void ExtractSharedMediaSessionOptions(
+bool ExtractMediaSessionOptions(
const PeerConnectionInterface::RTCOfferAnswerOptions& rtc_options,
+ bool is_offer,
cricket::MediaSessionOptions* session_options) {
- session_options->vad_enabled = rtc_options.voice_activity_detection;
- session_options->bundle_enabled = rtc_options.use_rtp_mux;
-}
-
-bool ConvertConstraintsToOfferAnswerOptions(
- const MediaConstraintsInterface* constraints,
- PeerConnectionInterface::RTCOfferAnswerOptions* offer_answer_options) {
- if (!constraints) {
- return true;
+ typedef PeerConnectionInterface::RTCOfferAnswerOptions RTCOfferAnswerOptions;
+ if (!IsValidOfferToReceiveMedia(rtc_options.offer_to_receive_audio) ||
+ !IsValidOfferToReceiveMedia(rtc_options.offer_to_receive_video)) {
+ return false;
}
+ // If constraints don't prevent us, we always accept video.
+ if (rtc_options.offer_to_receive_audio != RTCOfferAnswerOptions::kUndefined) {
+ session_options->recv_audio = (rtc_options.offer_to_receive_audio > 0);
+ } else {
+ session_options->recv_audio = true;
+ }
+ // For offers, we only offer video if we have it or it's forced by options.
+ // For answers, we will always accept video (if offered).
+ if (rtc_options.offer_to_receive_video != RTCOfferAnswerOptions::kUndefined) {
+ session_options->recv_video = (rtc_options.offer_to_receive_video > 0);
+ } else if (is_offer) {
+ session_options->recv_video = false;
+ } else {
+ session_options->recv_video = true;
+ }
+
+ session_options->vad_enabled = rtc_options.voice_activity_detection;
+ session_options->bundle_enabled = rtc_options.use_rtp_mux;
+ for (auto& kv : session_options->transport_options) {
+ kv.second.ice_restart = rtc_options.ice_restart;
+ }
+
+ return true;
+}
+
+bool ParseConstraintsForAnswer(const MediaConstraintsInterface* constraints,
+ cricket::MediaSessionOptions* session_options) {
bool value = false;
size_t mandatory_constraints_satisfied = 0;
- if (FindConstraint(constraints,
- MediaConstraintsInterface::kOfferToReceiveAudio, &value,
- &mandatory_constraints_satisfied)) {
- offer_answer_options->offer_to_receive_audio =
- value ? PeerConnectionInterface::RTCOfferAnswerOptions::
- kOfferToReceiveMediaTrue
- : 0;
+ // kOfferToReceiveAudio defaults to true according to spec.
+ if (!FindConstraint(constraints,
+ MediaConstraintsInterface::kOfferToReceiveAudio, &value,
+ &mandatory_constraints_satisfied) ||
+ value) {
+ session_options->recv_audio = true;
}
- if (FindConstraint(constraints,
- MediaConstraintsInterface::kOfferToReceiveVideo, &value,
- &mandatory_constraints_satisfied)) {
- offer_answer_options->offer_to_receive_video =
- value ? PeerConnectionInterface::RTCOfferAnswerOptions::
- kOfferToReceiveMediaTrue
- : 0;
+ // kOfferToReceiveVideo defaults to false according to spec. But
+ // if it is an answer and video is offered, we should still accept video
+ // per default.
+ value = false;
+ if (!FindConstraint(constraints,
+ MediaConstraintsInterface::kOfferToReceiveVideo, &value,
+ &mandatory_constraints_satisfied) ||
+ value) {
+ session_options->recv_video = true;
}
+
if (FindConstraint(constraints,
MediaConstraintsInterface::kVoiceActivityDetection, &value,
&mandatory_constraints_satisfied)) {
- offer_answer_options->voice_activity_detection = value;
- }
- if (FindConstraint(constraints, MediaConstraintsInterface::kUseRtpMux, &value,
- &mandatory_constraints_satisfied)) {
- offer_answer_options->use_rtp_mux = value;
- }
- if (FindConstraint(constraints, MediaConstraintsInterface::kIceRestart,
- &value, &mandatory_constraints_satisfied)) {
- offer_answer_options->ice_restart = value;
+ session_options->vad_enabled = value;
}
+ if (FindConstraint(constraints, MediaConstraintsInterface::kUseRtpMux, &value,
+ &mandatory_constraints_satisfied)) {
+ session_options->bundle_enabled = value;
+ } else {
+ // kUseRtpMux defaults to true according to spec.
+ session_options->bundle_enabled = true;
+ }
+
+ bool ice_restart = false;
+ if (FindConstraint(constraints, MediaConstraintsInterface::kIceRestart,
+ &value, &mandatory_constraints_satisfied)) {
+ // kIceRestart defaults to false according to spec.
+ ice_restart = true;
+ }
+ for (auto& kv : session_options->transport_options) {
+ kv.second.ice_restart = ice_restart;
+ }
+
+ if (!constraints) {
+ return true;
+ }
return mandatory_constraints_satisfied == constraints->GetMandatory().size();
}
@@ -825,17 +842,49 @@
LOG(LS_ERROR) << "CreateOffer - observer is NULL.";
return;
}
- PeerConnectionInterface::RTCOfferAnswerOptions offer_answer_options;
- // Always create an offer even if |ConvertConstraintsToOfferAnswerOptions|
- // returns false for now. Because |ConvertConstraintsToOfferAnswerOptions|
- // compares the mandatory fields parsed with the mandatory fields added in the
- // |constraints| and some downstream applications might create offers with
- // mandatory fields which would not be parsed in the helper method. For
- // example, in Chromium/remoting, |kEnableDtlsSrtp| is added to the
- // |constraints| as a mandatory field but it is not parsed.
- ConvertConstraintsToOfferAnswerOptions(constraints, &offer_answer_options);
+ RTCOfferAnswerOptions options;
- CreateOffer(observer, offer_answer_options);
+ bool value;
+ size_t mandatory_constraints = 0;
+
+ if (FindConstraint(constraints,
+ MediaConstraintsInterface::kOfferToReceiveAudio,
+ &value,
+ &mandatory_constraints)) {
+ options.offer_to_receive_audio =
+ value ? RTCOfferAnswerOptions::kOfferToReceiveMediaTrue : 0;
+ }
+
+ if (FindConstraint(constraints,
+ MediaConstraintsInterface::kOfferToReceiveVideo,
+ &value,
+ &mandatory_constraints)) {
+ options.offer_to_receive_video =
+ value ? RTCOfferAnswerOptions::kOfferToReceiveMediaTrue : 0;
+ }
+
+ if (FindConstraint(constraints,
+ MediaConstraintsInterface::kVoiceActivityDetection,
+ &value,
+ &mandatory_constraints)) {
+ options.voice_activity_detection = value;
+ }
+
+ if (FindConstraint(constraints,
+ MediaConstraintsInterface::kIceRestart,
+ &value,
+ &mandatory_constraints)) {
+ options.ice_restart = value;
+ }
+
+ if (FindConstraint(constraints,
+ MediaConstraintsInterface::kUseRtpMux,
+ &value,
+ &mandatory_constraints)) {
+ options.use_rtp_mux = value;
+ }
+
+ CreateOffer(observer, options);
}
void PeerConnection::CreateOffer(CreateSessionDescriptionObserver* observer,
@@ -846,15 +895,14 @@
return;
}
- if (!ValidateOfferAnswerOptions(options)) {
+ cricket::MediaSessionOptions session_options;
+ if (!GetOptionsForOffer(options, &session_options)) {
std::string error = "CreateOffer called with invalid options.";
LOG(LS_ERROR) << error;
PostCreateSessionDescriptionFailure(observer, error);
return;
}
- cricket::MediaSessionOptions session_options;
- GetOptionsForOffer(options, &session_options);
session_->CreateOffer(observer, options, session_options);
}
@@ -867,26 +915,14 @@
return;
}
- if (!session_->remote_description() ||
- session_->remote_description()->type() !=
- SessionDescriptionInterface::kOffer) {
- std::string error = "CreateAnswer called without remote offer.";
- LOG(LS_ERROR) << error;
- PostCreateSessionDescriptionFailure(observer, error);
- return;
- }
-
- PeerConnectionInterface::RTCOfferAnswerOptions offer_answer_options;
- if (!ConvertConstraintsToOfferAnswerOptions(constraints,
- &offer_answer_options)) {
+ cricket::MediaSessionOptions session_options;
+ if (!GetOptionsForAnswer(constraints, &session_options)) {
std::string error = "CreateAnswer called with invalid constraints.";
LOG(LS_ERROR) << error;
PostCreateSessionDescriptionFailure(observer, error);
return;
}
- cricket::MediaSessionOptions session_options;
- GetOptionsForAnswer(offer_answer_options, &session_options);
session_->CreateAnswer(observer, session_options);
}
@@ -899,7 +935,12 @@
}
cricket::MediaSessionOptions session_options;
- GetOptionsForAnswer(options, &session_options);
+ if (!GetOptionsForAnswer(options, &session_options)) {
+ std::string error = "CreateAnswer called with invalid options.";
+ LOG(LS_ERROR) << error;
+ PostCreateSessionDescriptionFailure(observer, error);
+ return;
+ }
session_->CreateAnswer(observer, session_options);
}
@@ -1657,242 +1698,121 @@
MSG_CREATE_SESSIONDESCRIPTION_FAILED, msg);
}
-void PeerConnection::GetOptionsForOffer(
+bool PeerConnection::GetOptionsForOffer(
const PeerConnectionInterface::RTCOfferAnswerOptions& rtc_options,
cricket::MediaSessionOptions* session_options) {
- ExtractSharedMediaSessionOptions(rtc_options, session_options);
-
- // Figure out transceiver directional preferences.
- bool send_audio = HasRtpSender(cricket::MEDIA_TYPE_AUDIO);
- bool send_video = HasRtpSender(cricket::MEDIA_TYPE_VIDEO);
-
- // By default, generate sendrecv/recvonly m= sections.
- bool recv_audio = true;
- bool recv_video = true;
-
- // By default, only offer a new m= section if we have media to send with it.
- bool offer_new_audio_description = send_audio;
- bool offer_new_video_description = send_video;
- bool offer_new_data_description = HasDataChannels();
-
- // The "offer_to_receive_X" options allow those defaults to be overridden.
- if (rtc_options.offer_to_receive_audio != RTCOfferAnswerOptions::kUndefined) {
- recv_audio = (rtc_options.offer_to_receive_audio > 0);
- offer_new_audio_description =
- offer_new_audio_description || (rtc_options.offer_to_receive_audio > 0);
- }
- if (rtc_options.offer_to_receive_video != RTCOfferAnswerOptions::kUndefined) {
- recv_video = (rtc_options.offer_to_receive_video > 0);
- offer_new_video_description =
- offer_new_video_description || (rtc_options.offer_to_receive_video > 0);
- }
-
- int audio_index = -1;
- int video_index = -1;
- int data_index = -1;
- // If a current description exists, generate m= sections in the same order,
- // using the first audio/video/data section that appears and rejecting
- // extraneous ones.
+ // TODO(deadbeef): Once we have transceivers, enumerate them here instead of
+ // ContentInfos.
if (session_->local_description()) {
- GenerateMediaDescriptionOptions(
- session_->local_description(),
- cricket::RtpTransceiverDirection(send_audio, recv_audio),
- cricket::RtpTransceiverDirection(send_video, recv_video), &audio_index,
- &video_index, &data_index, session_options);
+ for (const cricket::ContentInfo& content :
+ session_->local_description()->description()->contents()) {
+ session_options->transport_options[content.name] =
+ cricket::TransportOptions();
+ }
+ }
+ session_options->enable_ice_renomination =
+ configuration_.enable_ice_renomination;
+
+ if (!ExtractMediaSessionOptions(rtc_options, true, session_options)) {
+ return false;
}
- // Add audio/video/data m= sections to the end if needed.
- if (audio_index == -1 && offer_new_audio_description) {
- session_options->media_description_options.push_back(
- cricket::MediaDescriptionOptions(
- cricket::MEDIA_TYPE_AUDIO, cricket::CN_AUDIO,
- cricket::RtpTransceiverDirection(send_audio, recv_audio), false));
- audio_index = session_options->media_description_options.size() - 1;
+ AddSendStreams(session_options, senders_, rtp_data_channels_);
+ // Offer to receive audio/video if the constraint is not set and there are
+ // send streams, or we're currently receiving.
+ if (rtc_options.offer_to_receive_audio == RTCOfferAnswerOptions::kUndefined) {
+ session_options->recv_audio =
+ session_options->HasSendMediaStream(cricket::MEDIA_TYPE_AUDIO) ||
+ !remote_audio_tracks_.empty();
}
- if (video_index == -1 && offer_new_video_description) {
- session_options->media_description_options.push_back(
- cricket::MediaDescriptionOptions(
- cricket::MEDIA_TYPE_VIDEO, cricket::CN_VIDEO,
- cricket::RtpTransceiverDirection(send_video, recv_video), false));
- video_index = session_options->media_description_options.size() - 1;
+ if (rtc_options.offer_to_receive_video == RTCOfferAnswerOptions::kUndefined) {
+ session_options->recv_video =
+ session_options->HasSendMediaStream(cricket::MEDIA_TYPE_VIDEO) ||
+ !remote_video_tracks_.empty();
}
- if (data_index == -1 && offer_new_data_description) {
- session_options->media_description_options.push_back(
- cricket::MediaDescriptionOptions(
- cricket::MEDIA_TYPE_DATA, cricket::CN_DATA,
- cricket::RtpTransceiverDirection(true, true), false));
- data_index = session_options->media_description_options.size() - 1;
- }
-
- cricket::MediaDescriptionOptions* audio_media_description_options =
- audio_index == -1
- ? nullptr
- : &session_options->media_description_options[audio_index];
- cricket::MediaDescriptionOptions* video_media_description_options =
- video_index == -1
- ? nullptr
- : &session_options->media_description_options[video_index];
- cricket::MediaDescriptionOptions* data_media_description_options =
- data_index == -1
- ? nullptr
- : &session_options->media_description_options[data_index];
-
- // Apply ICE restart flag and renomination flag.
- for (auto& options : session_options->media_description_options) {
- options.transport_options.ice_restart = rtc_options.ice_restart;
- options.transport_options.enable_ice_renomination =
- configuration_.enable_ice_renomination;
- }
-
- AddRtpSenderOptions(senders_, audio_media_description_options,
- video_media_description_options);
- AddRtpDataChannelOptions(rtp_data_channels_, data_media_description_options);
// Intentionally unset the data channel type for RTP data channel with the
// second condition. Otherwise the RTP data channels would be successfully
// negotiated by default and the unit tests in WebRtcDataBrowserTest will fail
// when building with chromium. We want to leave RTP data channels broken, so
// people won't try to use them.
- if (!rtp_data_channels_.empty() ||
- session_->data_channel_type() != cricket::DCT_RTP) {
+ if (HasDataChannels() && session_->data_channel_type() != cricket::DCT_RTP) {
session_options->data_channel_type = session_->data_channel_type();
}
+ session_options->bundle_enabled =
+ session_options->bundle_enabled &&
+ (session_options->has_audio() || session_options->has_video() ||
+ session_options->has_data());
+
session_options->rtcp_cname = rtcp_cname_;
session_options->crypto_options = factory_->options().crypto_options;
+ return true;
}
-void PeerConnection::GetOptionsForAnswer(
- const RTCOfferAnswerOptions& rtc_options,
+void PeerConnection::InitializeOptionsForAnswer(
cricket::MediaSessionOptions* session_options) {
- ExtractSharedMediaSessionOptions(rtc_options, session_options);
+ session_options->recv_audio = false;
+ session_options->recv_video = false;
+ session_options->enable_ice_renomination =
+ configuration_.enable_ice_renomination;
+}
- // Figure out transceiver directional preferences.
- bool send_audio = HasRtpSender(cricket::MEDIA_TYPE_AUDIO);
- bool send_video = HasRtpSender(cricket::MEDIA_TYPE_VIDEO);
-
- // By default, generate sendrecv/recvonly m= sections. The direction is also
- // restricted by the direction in the offer.
- bool recv_audio = true;
- bool recv_video = true;
-
- // The "offer_to_receive_X" options allow those defaults to be overridden.
- if (rtc_options.offer_to_receive_audio != RTCOfferAnswerOptions::kUndefined) {
- recv_audio = (rtc_options.offer_to_receive_audio > 0);
+void PeerConnection::FinishOptionsForAnswer(
+ cricket::MediaSessionOptions* session_options) {
+ // TODO(deadbeef): Once we have transceivers, enumerate them here instead of
+ // ContentInfos.
+ if (session_->remote_description()) {
+ // Initialize the transport_options map.
+ for (const cricket::ContentInfo& content :
+ session_->remote_description()->description()->contents()) {
+ session_options->transport_options[content.name] =
+ cricket::TransportOptions();
+ }
}
- if (rtc_options.offer_to_receive_video != RTCOfferAnswerOptions::kUndefined) {
- recv_video = (rtc_options.offer_to_receive_video > 0);
- }
-
- int audio_index = -1;
- int video_index = -1;
- int data_index = -1;
- // There should be a pending remote description that's an offer...
- RTC_DCHECK(session_->remote_description());
- RTC_DCHECK(session_->remote_description()->type() ==
- SessionDescriptionInterface::kOffer);
- // Generate m= sections that match those in the offer.
- // Note that mediasession.cc will handle intersection our preferred direction
- // with the offered direction.
- GenerateMediaDescriptionOptions(
- session_->remote_description(),
- cricket::RtpTransceiverDirection(send_audio, recv_audio),
- cricket::RtpTransceiverDirection(send_video, recv_video), &audio_index,
- &video_index, &data_index, session_options);
-
- cricket::MediaDescriptionOptions* audio_media_description_options =
- audio_index == -1
- ? nullptr
- : &session_options->media_description_options[audio_index];
- cricket::MediaDescriptionOptions* video_media_description_options =
- video_index == -1
- ? nullptr
- : &session_options->media_description_options[video_index];
- cricket::MediaDescriptionOptions* data_media_description_options =
- data_index == -1
- ? nullptr
- : &session_options->media_description_options[data_index];
-
- // Apply ICE renomination flag.
- for (auto& options : session_options->media_description_options) {
- options.transport_options.enable_ice_renomination =
- configuration_.enable_ice_renomination;
- }
-
- AddRtpSenderOptions(senders_, audio_media_description_options,
- video_media_description_options);
- AddRtpDataChannelOptions(rtp_data_channels_, data_media_description_options);
-
+ AddSendStreams(session_options, senders_, rtp_data_channels_);
+ // RTP data channel is handled in MediaSessionOptions::AddStream. SCTP streams
+ // are not signaled in the SDP so does not go through that path and must be
+ // handled here.
// Intentionally unset the data channel type for RTP data channel. Otherwise
// the RTP data channels would be successfully negotiated by default and the
// unit tests in WebRtcDataBrowserTest will fail when building with chromium.
// We want to leave RTP data channels broken, so people won't try to use them.
- if (!rtp_data_channels_.empty() ||
- session_->data_channel_type() != cricket::DCT_RTP) {
+ if (session_->data_channel_type() != cricket::DCT_RTP) {
session_options->data_channel_type = session_->data_channel_type();
}
+ session_options->bundle_enabled =
+ session_options->bundle_enabled &&
+ (session_options->has_audio() || session_options->has_video() ||
+ session_options->has_data());
- session_options->rtcp_cname = rtcp_cname_;
session_options->crypto_options = factory_->options().crypto_options;
}
-void PeerConnection::GenerateMediaDescriptionOptions(
- const SessionDescriptionInterface* session_desc,
- cricket::RtpTransceiverDirection audio_direction,
- cricket::RtpTransceiverDirection video_direction,
- int* audio_index,
- int* video_index,
- int* data_index,
+bool PeerConnection::GetOptionsForAnswer(
+ const MediaConstraintsInterface* constraints,
cricket::MediaSessionOptions* session_options) {
- for (const cricket::ContentInfo& content :
- session_desc->description()->contents()) {
- if (IsAudioContent(&content)) {
- // If we already have an audio m= section, reject this extra one.
- if (*audio_index != -1) {
- session_options->media_description_options.push_back(
- cricket::MediaDescriptionOptions(
- cricket::MEDIA_TYPE_AUDIO, content.name,
- cricket::RtpTransceiverDirection(false, false), true));
- } else {
- session_options->media_description_options.push_back(
- cricket::MediaDescriptionOptions(
- cricket::MEDIA_TYPE_AUDIO, content.name, audio_direction,
- !audio_direction.send && !audio_direction.recv));
- *audio_index = session_options->media_description_options.size() - 1;
- }
- } else if (IsVideoContent(&content)) {
- // If we already have an video m= section, reject this extra one.
- if (*video_index != -1) {
- session_options->media_description_options.push_back(
- cricket::MediaDescriptionOptions(
- cricket::MEDIA_TYPE_VIDEO, content.name,
- cricket::RtpTransceiverDirection(false, false), true));
- } else {
- session_options->media_description_options.push_back(
- cricket::MediaDescriptionOptions(
- cricket::MEDIA_TYPE_VIDEO, content.name, video_direction,
- !video_direction.send && !video_direction.recv));
- *video_index = session_options->media_description_options.size() - 1;
- }
- } else {
- RTC_DCHECK(IsDataContent(&content));
- // If we already have an data m= section, reject this extra one.
- if (*data_index != -1) {
- session_options->media_description_options.push_back(
- cricket::MediaDescriptionOptions(
- cricket::MEDIA_TYPE_DATA, content.name,
- cricket::RtpTransceiverDirection(false, false), true));
- } else {
- session_options->media_description_options.push_back(
- cricket::MediaDescriptionOptions(
- cricket::MEDIA_TYPE_DATA, content.name,
- // Direction for data sections is meaningless, but legacy
- // endpoints might expect sendrecv.
- cricket::RtpTransceiverDirection(true, true), false));
- *data_index = session_options->media_description_options.size() - 1;
- }
- }
+ InitializeOptionsForAnswer(session_options);
+ if (!ParseConstraintsForAnswer(constraints, session_options)) {
+ return false;
}
+ session_options->rtcp_cname = rtcp_cname_;
+
+ FinishOptionsForAnswer(session_options);
+ return true;
+}
+
+bool PeerConnection::GetOptionsForAnswer(
+ const RTCOfferAnswerOptions& options,
+ cricket::MediaSessionOptions* session_options) {
+ InitializeOptionsForAnswer(session_options);
+ if (!ExtractMediaSessionOptions(options, false, session_options)) {
+ return false;
+ }
+ session_options->rtcp_cname = rtcp_cname_;
+
+ FinishOptionsForAnswer(session_options);
+ return true;
}
void PeerConnection::RemoveTracks(cricket::MediaType media_type) {
@@ -2365,15 +2285,6 @@
observer_->OnDataChannel(std::move(proxy_channel));
}
-bool PeerConnection::HasRtpSender(cricket::MediaType type) const {
- return std::find_if(
- senders_.begin(), senders_.end(),
- [type](const rtc::scoped_refptr<
- RtpSenderProxyWithInternal<RtpSenderInternal>>& sender) {
- return sender->media_type() == type;
- }) != senders_.end();
-}
-
RtpSenderInternal* PeerConnection::FindSenderById(const std::string& id) {
auto it = std::find_if(
senders_.begin(), senders_.end(),
diff --git a/webrtc/pc/peerconnection.h b/webrtc/pc/peerconnection.h
index 48e9628..f8b6a54 100644
--- a/webrtc/pc/peerconnection.h
+++ b/webrtc/pc/peerconnection.h
@@ -32,12 +32,28 @@
class VideoRtpReceiver;
class RtcEventLog;
-// TODO(zhihuang): Remove this declaration when the WebRtcSession tests don't
-// need it.
-void ExtractSharedMediaSessionOptions(
+// Populates |session_options| from |rtc_options|, and returns true if options
+// are valid.
+// |session_options|->transport_options map entries must exist in order for
+// them to be populated from |rtc_options|.
+bool ExtractMediaSessionOptions(
const PeerConnectionInterface::RTCOfferAnswerOptions& rtc_options,
+ bool is_offer,
cricket::MediaSessionOptions* session_options);
+// Populates |session_options| from |constraints|, and returns true if all
+// mandatory constraints are satisfied.
+// Assumes that |session_options|->transport_options map entries exist.
+// Will also set defaults if corresponding constraints are not present:
+// recv_audio=true, recv_video=true, bundle_enabled=true.
+// Other fields will be left with existing values.
+//
+// Deprecated. Will be removed once callers that use constraints are gone.
+// TODO(hta): Remove when callers are gone.
+// https://bugs.chromium.org/p/webrtc/issues/detail?id=5617
+bool ParseConstraintsForAnswer(const MediaConstraintsInterface* constraints,
+ cricket::MediaSessionOptions* session_options);
+
// PeerConnection implements the PeerConnectionInterface interface.
// It uses WebRtcSession to implement the PeerConnection functionality.
class PeerConnection : public PeerConnectionInterface,
@@ -228,24 +244,26 @@
// Returns a MediaSessionOptions struct with options decided by |options|,
// the local MediaStreams and DataChannels.
- void GetOptionsForOffer(
+ virtual bool GetOptionsForOffer(
const PeerConnectionInterface::RTCOfferAnswerOptions& rtc_options,
cricket::MediaSessionOptions* session_options);
// Returns a MediaSessionOptions struct with options decided by
// |constraints|, the local MediaStreams and DataChannels.
- void GetOptionsForAnswer(const RTCOfferAnswerOptions& options,
- cricket::MediaSessionOptions* session_options);
+ // Deprecated, use version without constraints.
+ virtual bool GetOptionsForAnswer(
+ const MediaConstraintsInterface* constraints,
+ cricket::MediaSessionOptions* session_options);
+ virtual bool GetOptionsForAnswer(
+ const RTCOfferAnswerOptions& options,
+ cricket::MediaSessionOptions* session_options);
- // Generates MediaDescriptionOptions for the |session_opts| based on existing
- // local description or remote description.
- void GenerateMediaDescriptionOptions(
- const SessionDescriptionInterface* session_desc,
- cricket::RtpTransceiverDirection audio_direction,
- cricket::RtpTransceiverDirection video_direction,
- int* audio_index,
- int* video_index,
- int* data_index,
+ void InitializeOptionsForAnswer(
+ cricket::MediaSessionOptions* session_options);
+
+ // Helper function for options processing.
+ // Deprecated.
+ virtual void FinishOptionsForAnswer(
cricket::MediaSessionOptions* session_options);
// Remove all local and remote tracks of type |media_type|.
@@ -343,7 +361,6 @@
void OnDataChannelOpenMessage(const std::string& label,
const InternalDataChannelInit& config);
- bool HasRtpSender(cricket::MediaType type) const;
RtpSenderInternal* FindSenderById(const std::string& id);
std::vector<rtc::scoped_refptr<
diff --git a/webrtc/pc/peerconnectioninterface_unittest.cc b/webrtc/pc/peerconnectioninterface_unittest.cc
index 892615a..0e52c20 100644
--- a/webrtc/pc/peerconnectioninterface_unittest.cc
+++ b/webrtc/pc/peerconnectioninterface_unittest.cc
@@ -1184,57 +1184,6 @@
return audio_desc->streams()[0].cname;
}
- std::unique_ptr<SessionDescriptionInterface> CreateOfferWithOptions(
- const RTCOfferAnswerOptions& offer_answer_options) {
- RTC_DCHECK(pc_);
- rtc::scoped_refptr<MockCreateSessionDescriptionObserver> observer(
- new rtc::RefCountedObject<MockCreateSessionDescriptionObserver>());
- pc_->CreateOffer(observer, offer_answer_options);
- EXPECT_EQ_WAIT(true, observer->called(), kTimeout);
- return observer->MoveDescription();
- }
-
- void CreateOfferWithOptionsAsRemoteDescription(
- std::unique_ptr<SessionDescriptionInterface>* desc,
- const RTCOfferAnswerOptions& offer_answer_options) {
- *desc = CreateOfferWithOptions(offer_answer_options);
- ASSERT_TRUE(desc != nullptr);
- std::string sdp;
- EXPECT_TRUE((*desc)->ToString(&sdp));
- SessionDescriptionInterface* remote_offer =
- webrtc::CreateSessionDescription(SessionDescriptionInterface::kOffer,
- sdp, NULL);
- EXPECT_TRUE(DoSetRemoteDescription(remote_offer));
- EXPECT_EQ(PeerConnectionInterface::kHaveRemoteOffer, observer_.state_);
- }
-
- void CreateOfferWithOptionsAsLocalDescription(
- std::unique_ptr<SessionDescriptionInterface>* desc,
- const RTCOfferAnswerOptions& offer_answer_options) {
- *desc = CreateOfferWithOptions(offer_answer_options);
- ASSERT_TRUE(desc != nullptr);
- std::string sdp;
- EXPECT_TRUE((*desc)->ToString(&sdp));
- SessionDescriptionInterface* new_offer = webrtc::CreateSessionDescription(
- SessionDescriptionInterface::kOffer, sdp, NULL);
-
- EXPECT_TRUE(DoSetLocalDescription(new_offer));
- EXPECT_EQ(PeerConnectionInterface::kHaveLocalOffer, observer_.state_);
- }
-
- bool HasCNCodecs(const cricket::ContentInfo* content) {
- const cricket::ContentDescription* description = content->description;
- RTC_DCHECK(description);
- const cricket::AudioContentDescription* audio_content_desc =
- static_cast<const cricket::AudioContentDescription*>(description);
- RTC_DCHECK(audio_content_desc);
- for (size_t i = 0; i < audio_content_desc->codecs().size(); ++i) {
- if (audio_content_desc->codecs()[i].name == "CN")
- return true;
- }
- return false;
- }
-
std::unique_ptr<rtc::VirtualSocketServer> vss_;
rtc::AutoSocketServerThread main_;
cricket::FakePortAllocator* port_allocator_ = nullptr;
@@ -3545,224 +3494,6 @@
EXPECT_TRUE(pc_->SetBitrate(bitrate).ok());
}
-// The following tests verify that the offer can be created correctly.
-TEST_F(PeerConnectionInterfaceTest,
- CreateOfferFailsWithInvalidOfferToReceiveAudio) {
- RTCOfferAnswerOptions rtc_options;
-
- // Setting offer_to_receive_audio to a value lower than kUndefined or greater
- // than kMaxOfferToReceiveMedia should be treated as invalid.
- rtc_options.offer_to_receive_audio = RTCOfferAnswerOptions::kUndefined - 1;
- CreatePeerConnection();
- EXPECT_FALSE(CreateOfferWithOptions(rtc_options));
-
- rtc_options.offer_to_receive_audio =
- RTCOfferAnswerOptions::kMaxOfferToReceiveMedia + 1;
- EXPECT_FALSE(CreateOfferWithOptions(rtc_options));
-}
-
-TEST_F(PeerConnectionInterfaceTest,
- CreateOfferFailsWithInvalidOfferToReceiveVideo) {
- RTCOfferAnswerOptions rtc_options;
-
- // Setting offer_to_receive_video to a value lower than kUndefined or greater
- // than kMaxOfferToReceiveMedia should be treated as invalid.
- rtc_options.offer_to_receive_video = RTCOfferAnswerOptions::kUndefined - 1;
- CreatePeerConnection();
- EXPECT_FALSE(CreateOfferWithOptions(rtc_options));
-
- rtc_options.offer_to_receive_video =
- RTCOfferAnswerOptions::kMaxOfferToReceiveMedia + 1;
- EXPECT_FALSE(CreateOfferWithOptions(rtc_options));
-}
-
-// Test that the audio and video content will be added to an offer if both
-// |offer_to_receive_audio| and |offer_to_receive_video| options are 1.
-TEST_F(PeerConnectionInterfaceTest, CreateOfferWithAudioVideoOptions) {
- RTCOfferAnswerOptions rtc_options;
- rtc_options.offer_to_receive_audio = 1;
- rtc_options.offer_to_receive_video = 1;
-
- std::unique_ptr<SessionDescriptionInterface> offer;
- CreatePeerConnection();
- offer = CreateOfferWithOptions(rtc_options);
- ASSERT_TRUE(offer);
- EXPECT_NE(nullptr, GetFirstAudioContent(offer->description()));
- EXPECT_NE(nullptr, GetFirstVideoContent(offer->description()));
-}
-
-// Test that only audio content will be added to the offer if only
-// |offer_to_receive_audio| options is 1.
-TEST_F(PeerConnectionInterfaceTest, CreateOfferWithAudioOnlyOptions) {
- RTCOfferAnswerOptions rtc_options;
- rtc_options.offer_to_receive_audio = 1;
- rtc_options.offer_to_receive_video = 0;
-
- std::unique_ptr<SessionDescriptionInterface> offer;
- CreatePeerConnection();
- offer = CreateOfferWithOptions(rtc_options);
- ASSERT_TRUE(offer);
- EXPECT_NE(nullptr, GetFirstAudioContent(offer->description()));
- EXPECT_EQ(nullptr, GetFirstVideoContent(offer->description()));
-}
-
-// Test that only video content will be added if only |offer_to_receive_video|
-// options is 1.
-TEST_F(PeerConnectionInterfaceTest, CreateOfferWithVideoOnlyOptions) {
- RTCOfferAnswerOptions rtc_options;
- rtc_options.offer_to_receive_audio = 0;
- rtc_options.offer_to_receive_video = 1;
-
- std::unique_ptr<SessionDescriptionInterface> offer;
- CreatePeerConnection();
- offer = CreateOfferWithOptions(rtc_options);
- ASSERT_TRUE(offer);
- EXPECT_EQ(nullptr, GetFirstAudioContent(offer->description()));
- EXPECT_NE(nullptr, GetFirstVideoContent(offer->description()));
-}
-
-// Test that if |voice_activity_detection| is false, no CN codec is added to the
-// offer.
-TEST_F(PeerConnectionInterfaceTest, CreateOfferWithVADOptions) {
- RTCOfferAnswerOptions rtc_options;
- rtc_options.offer_to_receive_audio = 1;
- rtc_options.offer_to_receive_video = 0;
-
- std::unique_ptr<SessionDescriptionInterface> offer;
- CreatePeerConnection();
- offer = CreateOfferWithOptions(rtc_options);
- ASSERT_TRUE(offer);
- const cricket::ContentInfo* audio_content =
- offer->description()->GetContentByName(cricket::CN_AUDIO);
- ASSERT_TRUE(audio_content);
- // |voice_activity_detection| is true by default.
- EXPECT_TRUE(HasCNCodecs(audio_content));
-
- rtc_options.voice_activity_detection = false;
- CreatePeerConnection();
- offer = CreateOfferWithOptions(rtc_options);
- ASSERT_TRUE(offer);
- audio_content = offer->description()->GetContentByName(cricket::CN_AUDIO);
- ASSERT_TRUE(audio_content);
- EXPECT_FALSE(HasCNCodecs(audio_content));
-}
-
-// Test that no media content will be added to the offer if using default
-// RTCOfferAnswerOptions.
-TEST_F(PeerConnectionInterfaceTest, CreateOfferWithDefaultOfferAnswerOptions) {
- RTCOfferAnswerOptions rtc_options;
-
- std::unique_ptr<SessionDescriptionInterface> offer;
- CreatePeerConnection();
- offer = CreateOfferWithOptions(rtc_options);
- ASSERT_TRUE(offer);
- EXPECT_EQ(nullptr, GetFirstAudioContent(offer->description()));
- EXPECT_EQ(nullptr, GetFirstVideoContent(offer->description()));
-}
-
-// Test that if |ice_restart| is true, the ufrag/pwd will change, otherwise
-// ufrag/pwd will be the same in the new offer.
-TEST_F(PeerConnectionInterfaceTest, CreateOfferWithIceRestart) {
- RTCOfferAnswerOptions rtc_options;
- rtc_options.ice_restart = false;
- rtc_options.offer_to_receive_audio = 1;
-
- std::unique_ptr<SessionDescriptionInterface> offer;
- CreatePeerConnection();
- CreateOfferWithOptionsAsLocalDescription(&offer, rtc_options);
- auto ufrag1 = offer->description()
- ->GetTransportInfoByName(cricket::CN_AUDIO)
- ->description.ice_ufrag;
- auto pwd1 = offer->description()
- ->GetTransportInfoByName(cricket::CN_AUDIO)
- ->description.ice_pwd;
-
- // |ice_restart| is false, the ufrag/pwd shouldn't change.
- CreateOfferWithOptionsAsLocalDescription(&offer, rtc_options);
- auto ufrag2 = offer->description()
- ->GetTransportInfoByName(cricket::CN_AUDIO)
- ->description.ice_ufrag;
- auto pwd2 = offer->description()
- ->GetTransportInfoByName(cricket::CN_AUDIO)
- ->description.ice_pwd;
-
- // |ice_restart| is true, the ufrag/pwd should change.
- rtc_options.ice_restart = true;
- CreateOfferWithOptionsAsLocalDescription(&offer, rtc_options);
- auto ufrag3 = offer->description()
- ->GetTransportInfoByName(cricket::CN_AUDIO)
- ->description.ice_ufrag;
- auto pwd3 = offer->description()
- ->GetTransportInfoByName(cricket::CN_AUDIO)
- ->description.ice_pwd;
-
- EXPECT_EQ(ufrag1, ufrag2);
- EXPECT_EQ(pwd1, pwd2);
- EXPECT_NE(ufrag2, ufrag3);
- EXPECT_NE(pwd2, pwd3);
-}
-
-// Test that if |use_rtp_mux| is true, the bundling will be enabled in the
-// offer; if it is false, there won't be any bundle group in the offer.
-TEST_F(PeerConnectionInterfaceTest, CreateOfferWithRtpMux) {
- RTCOfferAnswerOptions rtc_options;
- rtc_options.offer_to_receive_audio = 1;
- rtc_options.offer_to_receive_video = 1;
-
- std::unique_ptr<SessionDescriptionInterface> offer;
- CreatePeerConnection();
-
- rtc_options.use_rtp_mux = true;
- offer = CreateOfferWithOptions(rtc_options);
- ASSERT_TRUE(offer);
- EXPECT_NE(nullptr, GetFirstAudioContent(offer->description()));
- EXPECT_NE(nullptr, GetFirstVideoContent(offer->description()));
- EXPECT_TRUE(offer->description()->HasGroup(cricket::GROUP_TYPE_BUNDLE));
-
- rtc_options.use_rtp_mux = false;
- offer = CreateOfferWithOptions(rtc_options);
- ASSERT_TRUE(offer);
- EXPECT_NE(nullptr, GetFirstAudioContent(offer->description()));
- EXPECT_NE(nullptr, GetFirstVideoContent(offer->description()));
- EXPECT_FALSE(offer->description()->HasGroup(cricket::GROUP_TYPE_BUNDLE));
-}
-
-// If SetMandatoryReceiveAudio(false) and SetMandatoryReceiveVideo(false) are
-// called for the answer constraints, but an audio and a video section were
-// offered, there will still be an audio and a video section in the answer.
-TEST_F(PeerConnectionInterfaceTest,
- RejectAudioAndVideoInAnswerWithConstraints) {
- // Offer both audio and video.
- RTCOfferAnswerOptions rtc_offer_options;
- rtc_offer_options.offer_to_receive_audio = 1;
- rtc_offer_options.offer_to_receive_video = 1;
-
- CreatePeerConnection();
- std::unique_ptr<SessionDescriptionInterface> offer;
- CreateOfferWithOptionsAsRemoteDescription(&offer, rtc_offer_options);
- EXPECT_NE(nullptr, GetFirstAudioContent(offer->description()));
- EXPECT_NE(nullptr, GetFirstVideoContent(offer->description()));
-
- // Since an offer has been created with both audio and video,
- // Answers will contain the media types that exist in the offer regardless of
- // the value of |answer_options.has_audio| and |answer_options.has_video|.
- FakeConstraints answer_c;
- // Reject both audio and video.
- answer_c.SetMandatoryReceiveAudio(false);
- answer_c.SetMandatoryReceiveVideo(false);
-
- std::unique_ptr<SessionDescriptionInterface> answer;
- ASSERT_TRUE(DoCreateAnswer(&answer, &answer_c));
- const cricket::ContentInfo* audio_content =
- GetFirstAudioContent(answer->description());
- const cricket::ContentInfo* video_content =
- GetFirstVideoContent(answer->description());
- ASSERT_NE(nullptr, audio_content);
- ASSERT_NE(nullptr, video_content);
- EXPECT_TRUE(audio_content->rejected);
- EXPECT_TRUE(video_content->rejected);
-}
-
class PeerConnectionMediaConfigTest : public testing::Test {
protected:
void SetUp() override {
@@ -3771,7 +3502,8 @@
}
const cricket::MediaConfig TestCreatePeerConnection(
const PeerConnectionInterface::RTCConfiguration& config,
- const MediaConstraintsInterface* constraints) {
+ const MediaConstraintsInterface *constraints) {
+
rtc::scoped_refptr<PeerConnectionInterface> pc(pcf_->CreatePeerConnection(
config, constraints, nullptr, nullptr, &observer_));
EXPECT_TRUE(pc.get());
@@ -3853,6 +3585,177 @@
EXPECT_TRUE(media_config.video.suspend_below_min_bitrate);
}
+// The following tests verify that session options are created correctly.
+// TODO(deadbeef): Convert these tests to be more end-to-end. Instead of
+// "verify options are converted correctly", should be "pass options into
+// CreateOffer and verify the correct offer is produced."
+
+TEST(CreateSessionOptionsTest, GetOptionsForOfferWithInvalidAudioOption) {
+ RTCOfferAnswerOptions rtc_options;
+ rtc_options.offer_to_receive_audio = RTCOfferAnswerOptions::kUndefined - 1;
+
+ cricket::MediaSessionOptions options;
+ EXPECT_FALSE(ExtractMediaSessionOptions(rtc_options, true, &options));
+
+ rtc_options.offer_to_receive_audio =
+ RTCOfferAnswerOptions::kMaxOfferToReceiveMedia + 1;
+ EXPECT_FALSE(ExtractMediaSessionOptions(rtc_options, true, &options));
+}
+
+TEST(CreateSessionOptionsTest, GetOptionsForOfferWithInvalidVideoOption) {
+ RTCOfferAnswerOptions rtc_options;
+ rtc_options.offer_to_receive_video = RTCOfferAnswerOptions::kUndefined - 1;
+
+ cricket::MediaSessionOptions options;
+ EXPECT_FALSE(ExtractMediaSessionOptions(rtc_options, true, &options));
+
+ rtc_options.offer_to_receive_video =
+ RTCOfferAnswerOptions::kMaxOfferToReceiveMedia + 1;
+ EXPECT_FALSE(ExtractMediaSessionOptions(rtc_options, true, &options));
+}
+
+// Test that a MediaSessionOptions is created for an offer if
+// OfferToReceiveAudio and OfferToReceiveVideo options are set.
+TEST(CreateSessionOptionsTest, GetMediaSessionOptionsForOfferWithAudioVideo) {
+ RTCOfferAnswerOptions rtc_options;
+ rtc_options.offer_to_receive_audio = 1;
+ rtc_options.offer_to_receive_video = 1;
+
+ cricket::MediaSessionOptions options;
+ EXPECT_TRUE(ExtractMediaSessionOptions(rtc_options, true, &options));
+ EXPECT_TRUE(options.has_audio());
+ EXPECT_TRUE(options.has_video());
+ EXPECT_TRUE(options.bundle_enabled);
+}
+
+// Test that a correct MediaSessionOptions is created for an offer if
+// OfferToReceiveAudio is set.
+TEST(CreateSessionOptionsTest, GetMediaSessionOptionsForOfferWithAudio) {
+ RTCOfferAnswerOptions rtc_options;
+ rtc_options.offer_to_receive_audio = 1;
+
+ cricket::MediaSessionOptions options;
+ EXPECT_TRUE(ExtractMediaSessionOptions(rtc_options, true, &options));
+ EXPECT_TRUE(options.has_audio());
+ EXPECT_FALSE(options.has_video());
+ EXPECT_TRUE(options.bundle_enabled);
+}
+
+// Test that a correct MediaSessionOptions is created for an offer if
+// the default OfferOptions are used.
+TEST(CreateSessionOptionsTest, GetDefaultMediaSessionOptionsForOffer) {
+ RTCOfferAnswerOptions rtc_options;
+
+ cricket::MediaSessionOptions options;
+ options.transport_options["audio"] = cricket::TransportOptions();
+ options.transport_options["video"] = cricket::TransportOptions();
+ EXPECT_TRUE(ExtractMediaSessionOptions(rtc_options, true, &options));
+ EXPECT_TRUE(options.has_audio());
+ EXPECT_FALSE(options.has_video());
+ EXPECT_TRUE(options.bundle_enabled);
+ EXPECT_TRUE(options.vad_enabled);
+ EXPECT_FALSE(options.transport_options["audio"].ice_restart);
+ EXPECT_FALSE(options.transport_options["video"].ice_restart);
+}
+
+// Test that a correct MediaSessionOptions is created for an offer if
+// OfferToReceiveVideo is set.
+TEST(CreateSessionOptionsTest, GetMediaSessionOptionsForOfferWithVideo) {
+ RTCOfferAnswerOptions rtc_options;
+ rtc_options.offer_to_receive_audio = 0;
+ rtc_options.offer_to_receive_video = 1;
+
+ cricket::MediaSessionOptions options;
+ EXPECT_TRUE(ExtractMediaSessionOptions(rtc_options, true, &options));
+ EXPECT_FALSE(options.has_audio());
+ EXPECT_TRUE(options.has_video());
+ EXPECT_TRUE(options.bundle_enabled);
+}
+
+// Test that a correct MediaSessionOptions is created for an offer if
+// UseRtpMux is set to false.
+TEST(CreateSessionOptionsTest,
+ GetMediaSessionOptionsForOfferWithBundleDisabled) {
+ RTCOfferAnswerOptions rtc_options;
+ rtc_options.offer_to_receive_audio = 1;
+ rtc_options.offer_to_receive_video = 1;
+ rtc_options.use_rtp_mux = false;
+
+ cricket::MediaSessionOptions options;
+ EXPECT_TRUE(ExtractMediaSessionOptions(rtc_options, true, &options));
+ EXPECT_TRUE(options.has_audio());
+ EXPECT_TRUE(options.has_video());
+ EXPECT_FALSE(options.bundle_enabled);
+}
+
+// Test that a correct MediaSessionOptions is created to restart ice if
+// IceRestart is set. It also tests that subsequent MediaSessionOptions don't
+// have |audio_transport_options.ice_restart| etc. set.
+TEST(CreateSessionOptionsTest, GetMediaSessionOptionsForOfferWithIceRestart) {
+ RTCOfferAnswerOptions rtc_options;
+ rtc_options.ice_restart = true;
+
+ cricket::MediaSessionOptions options;
+ options.transport_options["audio"] = cricket::TransportOptions();
+ options.transport_options["video"] = cricket::TransportOptions();
+ EXPECT_TRUE(ExtractMediaSessionOptions(rtc_options, true, &options));
+ EXPECT_TRUE(options.transport_options["audio"].ice_restart);
+ EXPECT_TRUE(options.transport_options["video"].ice_restart);
+
+ rtc_options = RTCOfferAnswerOptions();
+ EXPECT_TRUE(ExtractMediaSessionOptions(rtc_options, true, &options));
+ EXPECT_FALSE(options.transport_options["audio"].ice_restart);
+ EXPECT_FALSE(options.transport_options["video"].ice_restart);
+}
+
+// Test that the MediaConstraints in an answer don't affect if audio and video
+// is offered in an offer but that if kOfferToReceiveAudio or
+// kOfferToReceiveVideo constraints are true in an offer, the media type will be
+// included in subsequent answers.
+TEST(CreateSessionOptionsTest, MediaConstraintsInAnswer) {
+ FakeConstraints answer_c;
+ answer_c.SetMandatoryReceiveAudio(true);
+ answer_c.SetMandatoryReceiveVideo(true);
+
+ cricket::MediaSessionOptions answer_options;
+ EXPECT_TRUE(ParseConstraintsForAnswer(&answer_c, &answer_options));
+ EXPECT_TRUE(answer_options.has_audio());
+ EXPECT_TRUE(answer_options.has_video());
+
+ RTCOfferAnswerOptions rtc_offer_options;
+
+ cricket::MediaSessionOptions offer_options;
+ EXPECT_TRUE(
+ ExtractMediaSessionOptions(rtc_offer_options, false, &offer_options));
+ EXPECT_TRUE(offer_options.has_audio());
+ EXPECT_TRUE(offer_options.has_video());
+
+ RTCOfferAnswerOptions updated_rtc_offer_options;
+ updated_rtc_offer_options.offer_to_receive_audio = 1;
+ updated_rtc_offer_options.offer_to_receive_video = 1;
+
+ cricket::MediaSessionOptions updated_offer_options;
+ EXPECT_TRUE(ExtractMediaSessionOptions(updated_rtc_offer_options, false,
+ &updated_offer_options));
+ EXPECT_TRUE(updated_offer_options.has_audio());
+ EXPECT_TRUE(updated_offer_options.has_video());
+
+ // Since an offer has been created with both audio and video, subsequent
+ // offers and answers should contain both audio and video.
+ // Answers will only contain the media types that exist in the offer
+ // regardless of the value of |updated_answer_options.has_audio| and
+ // |updated_answer_options.has_video|.
+ FakeConstraints updated_answer_c;
+ answer_c.SetMandatoryReceiveAudio(false);
+ answer_c.SetMandatoryReceiveVideo(false);
+
+ cricket::MediaSessionOptions updated_answer_options;
+ EXPECT_TRUE(
+ ParseConstraintsForAnswer(&updated_answer_c, &updated_answer_options));
+ EXPECT_TRUE(updated_answer_options.has_audio());
+ EXPECT_TRUE(updated_answer_options.has_video());
+}
+
// Tests a few random fields being different.
TEST(RTCConfigurationTest, ComparisonOperators) {
PeerConnectionInterface::RTCConfiguration a;
diff --git a/webrtc/pc/webrtcsession_unittest.cc b/webrtc/pc/webrtcsession_unittest.cc
index bb1c877..f6d334e 100644
--- a/webrtc/pc/webrtcsession_unittest.cc
+++ b/webrtc/pc/webrtcsession_unittest.cc
@@ -143,9 +143,6 @@
static const char kVideoTrack2[] = "video2";
static const char kAudioTrack2[] = "audio2";
-static constexpr bool kStopped = true;
-static constexpr bool kActive = false;
-
enum RTCCertificateGenerationMethod { ALREADY_GENERATED, DTLS_IDENTITY_STORE };
class MockIceObserver : public webrtc::IceObserver {
@@ -401,6 +398,7 @@
allocator_->set_flags(cricket::PORTALLOCATOR_DISABLE_TCP |
cricket::PORTALLOCATOR_DISABLE_RELAY);
EXPECT_TRUE(channel_manager_->Init());
+ desc_factory_->set_add_legacy_streams(false);
allocator_->set_step_delay(cricket::kMinimumStepDelay);
}
@@ -509,215 +507,107 @@
InitWithCryptoOptions(crypto_options);
}
- // The following convenience functions can be applied for both local side and
- // remote side. The flags can be overwritten for different use cases.
void SendAudioVideoStream1() {
send_stream_1_ = true;
send_stream_2_ = false;
- local_send_audio_ = true;
- local_send_video_ = true;
- remote_send_audio_ = true;
- remote_send_video_ = true;
+ send_audio_ = true;
+ send_video_ = true;
}
void SendAudioVideoStream2() {
send_stream_1_ = false;
send_stream_2_ = true;
- local_send_audio_ = true;
- local_send_video_ = true;
- remote_send_audio_ = true;
- remote_send_video_ = true;
+ send_audio_ = true;
+ send_video_ = true;
}
void SendAudioVideoStream1And2() {
send_stream_1_ = true;
send_stream_2_ = true;
- local_send_audio_ = true;
- local_send_video_ = true;
- remote_send_audio_ = true;
- remote_send_video_ = true;
+ send_audio_ = true;
+ send_video_ = true;
}
void SendNothing() {
send_stream_1_ = false;
send_stream_2_ = false;
- local_send_audio_ = false;
- local_send_video_ = false;
- remote_send_audio_ = false;
- remote_send_video_ = false;
+ send_audio_ = false;
+ send_video_ = false;
}
void SendAudioOnlyStream2() {
send_stream_1_ = false;
send_stream_2_ = true;
- local_send_audio_ = true;
- local_send_video_ = false;
- remote_send_audio_ = true;
- remote_send_video_ = false;
+ send_audio_ = true;
+ send_video_ = false;
}
void SendVideoOnlyStream2() {
send_stream_1_ = false;
send_stream_2_ = true;
- local_send_audio_ = false;
- local_send_video_ = true;
- remote_send_audio_ = false;
- remote_send_video_ = true;
+ send_audio_ = false;
+ send_video_ = true;
}
- // Helper function used to add a specific media section to the
- // |session_options|.
- void AddMediaSection(cricket::MediaType type,
- const std::string& mid,
- cricket::MediaContentDirection direction,
- bool stopped,
- cricket::MediaSessionOptions* opts) {
- opts->media_description_options.push_back(cricket::MediaDescriptionOptions(
- type, mid,
- cricket::RtpTransceiverDirection::FromMediaContentDirection(direction),
- stopped));
- }
-
- // Add the media sections to the options from |offered_media_sections_| when
- // creating an answer or a new offer.
- // This duplicates a lot of logic from PeerConnection but this can be fixed
- // when PeerConnection and WebRtcSession are merged.
- void AddExistingMediaSectionsAndSendersToOptions(
- cricket::MediaSessionOptions* session_options,
- bool send_audio,
- bool recv_audio,
- bool send_video,
- bool recv_video) {
- int num_sim_layer = 1;
- for (auto media_description_options : offered_media_sections_) {
- if (media_description_options.type == cricket::MEDIA_TYPE_AUDIO) {
- bool stopped = !send_audio && !recv_audio;
- auto media_desc_options = cricket::MediaDescriptionOptions(
- cricket::MEDIA_TYPE_AUDIO, media_description_options.mid,
- cricket::RtpTransceiverDirection(send_audio, recv_audio), stopped);
- if (send_stream_1_ && send_audio) {
- media_desc_options.AddAudioSender(kAudioTrack1, kStream1);
- }
- if (send_stream_2_ && send_audio) {
- media_desc_options.AddAudioSender(kAudioTrack2, kStream2);
- }
- session_options->media_description_options.push_back(
- media_desc_options);
- } else if (media_description_options.type == cricket::MEDIA_TYPE_VIDEO) {
- bool stopped = !send_video && !recv_video;
- auto media_desc_options = cricket::MediaDescriptionOptions(
- cricket::MEDIA_TYPE_VIDEO, media_description_options.mid,
- cricket::RtpTransceiverDirection(send_video, recv_video), stopped);
- if (send_stream_1_ && send_video) {
- media_desc_options.AddVideoSender(kVideoTrack1, kStream1,
- num_sim_layer);
- }
- if (send_stream_2_ && send_video) {
- media_desc_options.AddVideoSender(kVideoTrack2, kStream2,
- num_sim_layer);
- }
- session_options->media_description_options.push_back(
- media_desc_options);
- } else if (media_description_options.type == cricket::MEDIA_TYPE_DATA) {
- session_options->media_description_options.push_back(
- cricket::MediaDescriptionOptions(
- cricket::MEDIA_TYPE_DATA, media_description_options.mid,
- // Direction for data sections is meaningless, but legacy
- // endpoints might expect sendrecv.
- cricket::RtpTransceiverDirection(true, true), false));
- } else {
- RTC_NOTREACHED();
- }
+ void AddStreamsToOptions(cricket::MediaSessionOptions* session_options) {
+ if (send_stream_1_ && send_audio_) {
+ session_options->AddSendStream(cricket::MEDIA_TYPE_AUDIO, kAudioTrack1,
+ kStream1);
}
- }
-
- // Add the existing media sections first and then add new media sections if
- // needed.
- void AddMediaSectionsAndSendersToOptions(
- cricket::MediaSessionOptions* session_options,
- bool send_audio,
- bool recv_audio,
- bool send_video,
- bool recv_video) {
- AddExistingMediaSectionsAndSendersToOptions(
- session_options, send_audio, recv_audio, send_video, recv_video);
-
- if (!session_options->has_audio() && (send_audio || recv_audio)) {
- cricket::MediaDescriptionOptions media_desc_options =
- cricket::MediaDescriptionOptions(
- cricket::MEDIA_TYPE_AUDIO, cricket::CN_AUDIO,
- cricket::RtpTransceiverDirection(send_audio, recv_audio),
- kActive);
- if (send_stream_1_ && send_audio) {
- media_desc_options.AddAudioSender(kAudioTrack1, kStream1);
- }
- if (send_stream_2_ && send_audio) {
- media_desc_options.AddAudioSender(kAudioTrack2, kStream2);
- }
- session_options->media_description_options.push_back(media_desc_options);
- offered_media_sections_.push_back(media_desc_options);
+ if (send_stream_1_ && send_video_) {
+ session_options->AddSendStream(cricket::MEDIA_TYPE_VIDEO, kVideoTrack1,
+ kStream1);
}
-
- if (!session_options->has_video() && (send_video || recv_video)) {
- cricket::MediaDescriptionOptions media_desc_options =
- cricket::MediaDescriptionOptions(
- cricket::MEDIA_TYPE_VIDEO, cricket::CN_VIDEO,
- cricket::RtpTransceiverDirection(send_video, recv_video),
- kActive);
- int num_sim_layer = 1;
- if (send_stream_1_ && send_video) {
- media_desc_options.AddVideoSender(kVideoTrack1, kStream1,
- num_sim_layer);
- }
- if (send_stream_2_ && send_video) {
- media_desc_options.AddVideoSender(kVideoTrack2, kStream2,
- num_sim_layer);
- }
- session_options->media_description_options.push_back(media_desc_options);
- offered_media_sections_.push_back(media_desc_options);
+ if (send_stream_2_ && send_audio_) {
+ session_options->AddSendStream(cricket::MEDIA_TYPE_AUDIO, kAudioTrack2,
+ kStream2);
}
-
- if (!session_options->has_data() &&
- (data_channel_ ||
- session_options->data_channel_type != cricket::DCT_NONE)) {
- cricket::MediaDescriptionOptions media_desc_options =
- cricket::MediaDescriptionOptions(
- cricket::MEDIA_TYPE_DATA, cricket::CN_DATA,
- cricket::RtpTransceiverDirection(true, true), kActive);
- if (session_options->data_channel_type == cricket::DCT_RTP) {
- media_desc_options.AddRtpDataChannel(data_channel_->label(),
- data_channel_->label());
- }
- session_options->media_description_options.push_back(media_desc_options);
- offered_media_sections_.push_back(media_desc_options);
+ if (send_stream_2_ && send_video_) {
+ session_options->AddSendStream(cricket::MEDIA_TYPE_VIDEO, kVideoTrack2,
+ kStream2);
+ }
+ if (data_channel_ && session_->data_channel_type() == cricket::DCT_RTP) {
+ session_options->AddSendStream(cricket::MEDIA_TYPE_DATA,
+ data_channel_->label(),
+ data_channel_->label());
}
}
void GetOptionsForOffer(
const PeerConnectionInterface::RTCOfferAnswerOptions& rtc_options,
cricket::MediaSessionOptions* session_options) {
- ExtractSharedMediaSessionOptions(rtc_options, session_options);
+ ASSERT_TRUE(ExtractMediaSessionOptions(rtc_options, true, session_options));
- // |recv_X| is true by default if |offer_to_receive_X| is undefined.
- bool recv_audio = rtc_options.offer_to_receive_audio != 0;
- bool recv_video = rtc_options.offer_to_receive_video != 0;
-
- AddMediaSectionsAndSendersToOptions(session_options, local_send_audio_,
- recv_audio, local_send_video_,
- recv_video);
+ AddStreamsToOptions(session_options);
+ if (rtc_options.offer_to_receive_audio ==
+ RTCOfferAnswerOptions::kUndefined) {
+ session_options->recv_audio =
+ session_options->HasSendMediaStream(cricket::MEDIA_TYPE_AUDIO);
+ }
+ if (rtc_options.offer_to_receive_video ==
+ RTCOfferAnswerOptions::kUndefined) {
+ session_options->recv_video =
+ session_options->HasSendMediaStream(cricket::MEDIA_TYPE_VIDEO);
+ }
session_options->bundle_enabled =
session_options->bundle_enabled &&
(session_options->has_audio() || session_options->has_video() ||
session_options->has_data());
+ if (session_->data_channel_type() == cricket::DCT_SCTP && data_channel_) {
+ session_options->data_channel_type = cricket::DCT_SCTP;
+ } else if (session_->data_channel_type() == cricket::DCT_QUIC) {
+ session_options->data_channel_type = cricket::DCT_QUIC;
+ }
+
session_options->crypto_options = crypto_options_;
}
void GetOptionsForAnswer(cricket::MediaSessionOptions* session_options) {
- AddExistingMediaSectionsAndSendersToOptions(
- session_options, local_send_audio_, local_recv_audio_,
- local_send_video_, local_recv_video_);
+ // ParseConstraintsForAnswer is used to set some defaults.
+ ASSERT_TRUE(webrtc::ParseConstraintsForAnswer(nullptr, session_options));
+ AddStreamsToOptions(session_options);
session_options->bundle_enabled =
session_options->bundle_enabled &&
(session_options->has_audio() || session_options->has_video() ||
@@ -730,50 +620,6 @@
session_options->crypto_options = crypto_options_;
}
- void GetOptionsForRemoteAnswer(
- cricket::MediaSessionOptions* session_options) {
- bool recv_audio = local_send_audio_ || remote_recv_audio_;
- bool recv_video = local_send_video_ || remote_recv_video_;
- bool send_audio = false;
- bool send_video = false;
-
- AddExistingMediaSectionsAndSendersToOptions(
- session_options, send_audio, recv_audio, send_video, recv_video);
-
- session_options->bundle_enabled =
- session_options->bundle_enabled &&
- (session_options->has_audio() || session_options->has_video() ||
- session_options->has_data());
-
- if (session_->data_channel_type() != cricket::DCT_RTP) {
- session_options->data_channel_type = session_->data_channel_type();
- }
-
- session_options->crypto_options = crypto_options_;
- }
-
- void GetOptionsForAudioOnlyRemoteOffer(
- cricket::MediaSessionOptions* session_options) {
- remote_recv_audio_ = true;
- remote_recv_video_ = false;
- GetOptionsForRemoteOffer(session_options);
- }
-
- void GetOptionsForRemoteOffer(cricket::MediaSessionOptions* session_options) {
- AddMediaSectionsAndSendersToOptions(session_options, remote_send_audio_,
- remote_recv_audio_, remote_send_video_,
- remote_recv_video_);
- session_options->bundle_enabled =
- (session_options->has_audio() || session_options->has_video() ||
- session_options->has_data());
-
- if (session_->data_channel_type() != cricket::DCT_RTP) {
- session_options->data_channel_type = session_->data_channel_type();
- }
-
- session_options->crypto_options = crypto_options_;
- }
-
// Creates a local offer and applies it. Starts ICE.
// Call SendAudioVideoStreamX() before this function
// to decide which streams to create.
@@ -789,6 +635,7 @@
PeerConnectionInterface::RTCOfferAnswerOptions options;
options.offer_to_receive_audio =
RTCOfferAnswerOptions::kOfferToReceiveMediaTrue;
+
return CreateOffer(options);
}
@@ -811,6 +658,9 @@
= new WebRtcSessionCreateSDPObserverForTest();
cricket::MediaSessionOptions session_options = options;
GetOptionsForAnswer(&session_options);
+ // Overwrite recv_audio and recv_video with passed-in values.
+ session_options.recv_video = options.recv_video;
+ session_options.recv_audio = options.recv_audio;
session_->CreateAnswer(observer, session_options);
EXPECT_TRUE_WAIT(
observer->state() != WebRtcSessionCreateSDPObserverForTest::kInit,
@@ -820,7 +670,8 @@
SessionDescriptionInterface* CreateAnswer() {
cricket::MediaSessionOptions options;
- options.bundle_enabled = true;
+ options.recv_video = true;
+ options.recv_audio = true;
return CreateAnswer(options);
}
@@ -938,7 +789,7 @@
void VerifyAnswerFromNonCryptoOffer() {
// Create an SDP without Crypto.
cricket::MediaSessionOptions options;
- GetOptionsForRemoteOffer(&options);
+ options.recv_video = true;
JsepSessionDescription* offer(
CreateRemoteOffer(options, cricket::SEC_DISABLED));
ASSERT_TRUE(offer != NULL);
@@ -952,7 +803,7 @@
void VerifyAnswerFromCryptoOffer() {
cricket::MediaSessionOptions options;
- GetOptionsForRemoteOffer(&options);
+ options.recv_video = true;
options.bundle_enabled = true;
std::unique_ptr<JsepSessionDescription> offer(
CreateRemoteOffer(options, cricket::SEC_REQUIRED));
@@ -1075,7 +926,7 @@
SetLocalDescriptionWithoutError(answer);
}
void SetLocalDescriptionWithoutError(SessionDescriptionInterface* desc) {
- ASSERT_TRUE(session_->SetLocalDescription(desc, nullptr));
+ EXPECT_TRUE(session_->SetLocalDescription(desc, NULL));
session_->MaybeStartGathering();
}
void SetLocalDescriptionExpectState(SessionDescriptionInterface* desc,
@@ -1104,7 +955,7 @@
expected_error, desc);
}
void SetRemoteDescriptionWithoutError(SessionDescriptionInterface* desc) {
- ASSERT_TRUE(session_->SetRemoteDescription(desc, nullptr));
+ EXPECT_TRUE(session_->SetRemoteDescription(desc, NULL));
}
void SetRemoteDescriptionExpectState(SessionDescriptionInterface* desc,
WebRtcSession::State expected_state) {
@@ -1141,26 +992,21 @@
SessionDescriptionInterface** nocrypto_answer) {
// Create a SDP without Crypto.
cricket::MediaSessionOptions options;
- GetOptionsForRemoteOffer(&options);
+ options.recv_video = true;
options.bundle_enabled = true;
*offer = CreateRemoteOffer(options, cricket::SEC_ENABLED);
ASSERT_TRUE(*offer != NULL);
VerifyCryptoParams((*offer)->description());
- cricket::MediaSessionOptions answer_options;
- GetOptionsForRemoteAnswer(&answer_options);
- *nocrypto_answer =
- CreateRemoteAnswer(*offer, answer_options, cricket::SEC_DISABLED);
+ *nocrypto_answer = CreateRemoteAnswer(*offer, options,
+ cricket::SEC_DISABLED);
EXPECT_TRUE(*nocrypto_answer != NULL);
}
void CreateDtlsOfferAndNonDtlsAnswer(SessionDescriptionInterface** offer,
SessionDescriptionInterface** nodtls_answer) {
cricket::MediaSessionOptions options;
- AddMediaSection(cricket::MEDIA_TYPE_AUDIO, cricket::CN_AUDIO,
- cricket::MD_RECVONLY, kActive, &options);
- AddMediaSection(cricket::MEDIA_TYPE_VIDEO, cricket::CN_VIDEO,
- cricket::MD_RECVONLY, kActive, &options);
+ options.recv_video = true;
options.bundle_enabled = true;
std::unique_ptr<SessionDescriptionInterface> temp_offer(
@@ -1222,7 +1068,8 @@
const char* sctp_stream_name, int new_port,
cricket::MediaSessionOptions options) {
options.data_channel_type = cricket::DCT_SCTP;
- GetOptionsForRemoteOffer(&options);
+ options.AddSendStream(cricket::MEDIA_TYPE_DATA, "datachannel",
+ sctp_stream_name);
return ChangeSDPSctpPort(new_port, CreateRemoteOffer(options));
}
@@ -1250,7 +1097,7 @@
// before this function to decide which streams to create.
JsepSessionDescription* CreateRemoteOffer() {
cricket::MediaSessionOptions options;
- GetOptionsForRemoteOffer(&options);
+ GetOptionsForAnswer(&options);
return CreateRemoteOffer(options, session_->remote_description());
}
@@ -1285,7 +1132,6 @@
const SessionDescriptionInterface* offer) {
cricket::MediaSessionOptions options;
GetOptionsForAnswer(&options);
- options.bundle_enabled = true;
return CreateRemoteAnswer(offer, options, cricket::SEC_REQUIRED);
}
@@ -1609,7 +1455,6 @@
SetFactoryDtlsSrtp();
if (type == CreateSessionDescriptionRequest::kAnswer) {
cricket::MediaSessionOptions options;
- GetOptionsForRemoteOffer(&options);
std::unique_ptr<JsepSessionDescription> offer(
CreateRemoteOffer(options, cricket::SEC_DISABLED));
ASSERT_TRUE(offer.get() != NULL);
@@ -1617,19 +1462,16 @@
}
PeerConnectionInterface::RTCOfferAnswerOptions options;
- cricket::MediaSessionOptions offer_session_options;
- cricket::MediaSessionOptions answer_session_options;
- GetOptionsForOffer(options, &offer_session_options);
- GetOptionsForAnswer(&answer_session_options);
+ cricket::MediaSessionOptions session_options;
const int kNumber = 3;
rtc::scoped_refptr<WebRtcSessionCreateSDPObserverForTest>
observers[kNumber];
for (int i = 0; i < kNumber; ++i) {
observers[i] = new WebRtcSessionCreateSDPObserverForTest();
if (type == CreateSessionDescriptionRequest::kOffer) {
- session_->CreateOffer(observers[i], options, offer_session_options);
+ session_->CreateOffer(observers[i], options, session_options);
} else {
- session_->CreateAnswer(observers[i], answer_session_options);
+ session_->CreateAnswer(observers[i], session_options);
}
}
@@ -1687,15 +1529,8 @@
// The following flags affect options created for CreateOffer/CreateAnswer.
bool send_stream_1_ = false;
bool send_stream_2_ = false;
- bool local_send_audio_ = false;
- bool local_send_video_ = false;
- bool local_recv_audio_ = true;
- bool local_recv_video_ = true;
- bool remote_send_audio_ = false;
- bool remote_send_video_ = false;
- bool remote_recv_audio_ = true;
- bool remote_recv_video_ = true;
- std::vector<cricket::MediaDescriptionOptions> offered_media_sections_;
+ bool send_audio_ = false;
+ bool send_video_ = false;
rtc::scoped_refptr<DataChannel> data_channel_;
// Last values received from data channel creation signal.
std::string last_data_channel_label_;
@@ -1935,7 +1770,7 @@
TEST_F(WebRtcSessionTest, TestSetNonSdesOfferWhenSdesOn) {
Init();
cricket::MediaSessionOptions options;
- GetOptionsForRemoteOffer(&options);
+ options.recv_video = true;
JsepSessionDescription* offer = CreateRemoteOffer(
options, cricket::SEC_DISABLED);
ASSERT_TRUE(offer != NULL);
@@ -1981,7 +1816,7 @@
InitWithDtls(GetParam());
SetFactoryDtlsSrtp();
cricket::MediaSessionOptions options;
- GetOptionsForRemoteOffer(&options);
+ options.recv_video = true;
JsepSessionDescription* offer =
CreateRemoteOffer(options, cricket::SEC_DISABLED);
ASSERT_TRUE(offer != NULL);
@@ -2020,7 +1855,7 @@
SetLocalDescriptionWithoutError(offer);
cricket::MediaSessionOptions options;
- GetOptionsForAnswer(&options);
+ options.recv_video = true;
JsepSessionDescription* answer =
CreateRemoteAnswer(offer, options, cricket::SEC_DISABLED);
ASSERT_TRUE(answer != NULL);
@@ -2036,7 +1871,7 @@
TEST_P(WebRtcSessionTest, TestReceiveNonDtlsOfferWhenDtlsOn) {
InitWithDtls(GetParam());
cricket::MediaSessionOptions options;
- GetOptionsForRemoteOffer(&options);
+ options.recv_video = true;
options.bundle_enabled = true;
JsepSessionDescription* offer = CreateRemoteOffer(
options, cricket::SEC_REQUIRED);
@@ -2074,16 +1909,12 @@
TEST_P(WebRtcSessionTest, TestSetRemoteNonDtlsAnswerWhenDtlsOn) {
InitWithDtls(GetParam());
SessionDescriptionInterface* offer = CreateOffer();
- cricket::MediaSessionOptions offer_options;
- GetOptionsForRemoteOffer(&offer_options);
-
+ cricket::MediaSessionOptions options;
+ options.recv_video = true;
std::unique_ptr<SessionDescriptionInterface> temp_offer(
- CreateRemoteOffer(offer_options, cricket::SEC_ENABLED));
-
- cricket::MediaSessionOptions answer_options;
- GetOptionsForAnswer(&answer_options);
- JsepSessionDescription* answer = CreateRemoteAnswer(
- temp_offer.get(), answer_options, cricket::SEC_ENABLED);
+ CreateRemoteOffer(options, cricket::SEC_ENABLED));
+ JsepSessionDescription* answer =
+ CreateRemoteAnswer(temp_offer.get(), options, cricket::SEC_ENABLED);
// SetRemoteDescription and SetLocalDescription will take the ownership of
// the offer and answer.
@@ -2110,7 +1941,7 @@
SetLocalDescriptionWithoutError(offer);
cricket::MediaSessionOptions options;
- GetOptionsForAnswer(&options);
+ options.recv_video = true;
JsepSessionDescription* answer =
CreateRemoteAnswer(offer, options, cricket::SEC_DISABLED);
ASSERT_TRUE(answer != NULL);
@@ -2128,7 +1959,7 @@
InitWithDtls(GetParam());
cricket::MediaSessionOptions options;
- GetOptionsForRemoteOffer(&options);
+ options.recv_video = true;
JsepSessionDescription* offer =
CreateRemoteOffer(options, cricket::SEC_DISABLED);
ASSERT_TRUE(offer != NULL);
@@ -2161,7 +1992,7 @@
SetLocalDescriptionWithoutError(offer);
cricket::MediaSessionOptions options;
- GetOptionsForAnswer(&options);
+ options.recv_video = true;
// First, negotiate different SSL roles.
SessionDescriptionInterface* answer =
@@ -2183,9 +2014,7 @@
session_->remote_description());
SetRemoteDescriptionWithoutError(offer);
- cricket::MediaSessionOptions answer_options;
- answer_options.bundle_enabled = true;
- answer = CreateAnswer(answer_options);
+ answer = CreateAnswer();
audio_transport_info = answer->description()->GetTransportInfoByName("audio");
EXPECT_EQ(cricket::CONNECTIONROLE_PASSIVE,
audio_transport_info->description.connection_role);
@@ -2202,7 +2031,7 @@
kSessionVersion,
session_->remote_description());
SetRemoteDescriptionWithoutError(offer);
- answer = CreateAnswer(answer_options);
+ answer = CreateAnswer();
audio_transport_info = answer->description()->GetTransportInfoByName("audio");
EXPECT_EQ(cricket::CONNECTIONROLE_PASSIVE,
audio_transport_info->description.connection_role);
@@ -2563,7 +2392,6 @@
std::unique_ptr<SessionDescriptionInterface> local_offer(CreateOffer());
- ASSERT_TRUE(local_offer);
ASSERT_TRUE(local_offer->candidates(kMediaContentIndex0) != NULL);
EXPECT_LT(0u, local_offer->candidates(kMediaContentIndex0)->count());
@@ -2589,27 +2417,42 @@
// present in SDP.
std::string sdp;
EXPECT_TRUE(offer->ToString(&sdp));
+ const std::string kAudioMid = "a=mid:audio";
+ const std::string kAudioMidReplaceStr = "a=mid:audio_content_name";
+ const std::string kVideoMid = "a=mid:video";
+ const std::string kVideoMidReplaceStr = "a=mid:video_content_name";
+
+ // Replacing |audio| with |audio_content_name|.
+ rtc::replace_substrs(kAudioMid.c_str(), kAudioMid.length(),
+ kAudioMidReplaceStr.c_str(),
+ kAudioMidReplaceStr.length(),
+ &sdp);
+ // Replacing |video| with |video_content_name|.
+ rtc::replace_substrs(kVideoMid.c_str(), kVideoMid.length(),
+ kVideoMidReplaceStr.c_str(),
+ kVideoMidReplaceStr.length(),
+ &sdp);
SessionDescriptionInterface* modified_offer =
CreateSessionDescription(JsepSessionDescription::kOffer, sdp, NULL);
SetRemoteDescriptionWithoutError(modified_offer);
- cricket::MediaSessionOptions answer_options;
- answer_options.bundle_enabled = false;
- SessionDescriptionInterface* answer = CreateAnswer(answer_options);
+ SessionDescriptionInterface* answer = CreateAnswer();
SetLocalDescriptionWithoutError(answer);
rtc::PacketTransportInternal* voice_transport_channel =
session_->voice_rtp_transport_channel();
EXPECT_TRUE(voice_transport_channel != NULL);
EXPECT_EQ(voice_transport_channel->debug_name(),
- "audio " + std::to_string(cricket::ICE_CANDIDATE_COMPONENT_RTP));
+ "audio_content_name " +
+ std::to_string(cricket::ICE_CANDIDATE_COMPONENT_RTP));
rtc::PacketTransportInternal* video_transport_channel =
session_->video_rtp_transport_channel();
ASSERT_TRUE(video_transport_channel != NULL);
EXPECT_EQ(video_transport_channel->debug_name(),
- "video " + std::to_string(cricket::ICE_CANDIDATE_COMPONENT_RTP));
+ "video_content_name " +
+ std::to_string(cricket::ICE_CANDIDATE_COMPONENT_RTP));
EXPECT_TRUE((video_channel_ = media_engine_->GetVideoChannel(0)) != NULL);
EXPECT_TRUE((voice_channel_ = media_engine_->GetVoiceChannel(0)) != NULL);
}
@@ -2623,17 +2466,9 @@
ASSERT_TRUE(offer != NULL);
const cricket::ContentInfo* content =
cricket::GetFirstAudioContent(offer->description());
- ASSERT_TRUE(content != NULL);
- EXPECT_EQ(
- cricket::MD_RECVONLY,
- static_cast<const cricket::AudioContentDescription*>(content->description)
- ->direction());
+ EXPECT_TRUE(content != NULL);
content = cricket::GetFirstVideoContent(offer->description());
- ASSERT_TRUE(content != NULL);
- EXPECT_EQ(
- cricket::MD_RECVONLY,
- static_cast<const cricket::VideoContentDescription*>(content->description)
- ->direction());
+ EXPECT_TRUE(content == NULL);
}
// Test that an offer contains the correct media content descriptions based on
@@ -2646,34 +2481,17 @@
const cricket::ContentInfo* content =
cricket::GetFirstAudioContent(offer->description());
- ASSERT_TRUE(content != NULL);
- EXPECT_EQ(
- cricket::MD_SENDRECV,
- static_cast<const cricket::AudioContentDescription*>(content->description)
- ->direction());
+ EXPECT_TRUE(content != NULL);
content = cricket::GetFirstVideoContent(offer->description());
- ASSERT_TRUE(content != NULL);
- EXPECT_EQ(
- cricket::MD_RECVONLY,
- static_cast<const cricket::VideoContentDescription*>(content->description)
- ->direction());
+ EXPECT_TRUE(content == NULL);
// Test Audio / Video offer.
SendAudioVideoStream1();
offer.reset(CreateOffer());
content = cricket::GetFirstAudioContent(offer->description());
- ASSERT_TRUE(content != NULL);
- EXPECT_EQ(
- cricket::MD_SENDRECV,
- static_cast<const cricket::AudioContentDescription*>(content->description)
- ->direction());
-
+ EXPECT_TRUE(content != NULL);
content = cricket::GetFirstVideoContent(offer->description());
- ASSERT_TRUE(content != NULL);
- EXPECT_EQ(
- cricket::MD_SENDRECV,
- static_cast<const cricket::VideoContentDescription*>(content->description)
- ->direction());
+ EXPECT_TRUE(content != NULL);
}
// Test that an offer contains no media content descriptions if
@@ -2701,7 +2519,6 @@
PeerConnectionInterface::RTCOfferAnswerOptions options;
options.offer_to_receive_audio =
RTCOfferAnswerOptions::kOfferToReceiveMediaTrue;
- options.offer_to_receive_video = 0;
std::unique_ptr<SessionDescriptionInterface> offer(CreateOffer(options));
@@ -2736,8 +2553,6 @@
// removed.
options.offer_to_receive_audio = 0;
options.offer_to_receive_video = 0;
- // Remove the media sections added in previous offer.
- offered_media_sections_.clear();
offer.reset(CreateOffer(options));
content = cricket::GetFirstAudioContent(offer->description());
@@ -2781,7 +2596,6 @@
Init();
// Create a remote offer with audio only.
cricket::MediaSessionOptions options;
- GetOptionsForAudioOnlyRemoteOffer(&options);
std::unique_ptr<JsepSessionDescription> offer(CreateRemoteOffer(options));
ASSERT_TRUE(cricket::GetFirstVideoContent(offer->description()) == NULL);
@@ -2826,10 +2640,8 @@
SetRemoteDescriptionWithoutError(offer.release());
cricket::MediaSessionOptions session_options;
- remote_send_audio_ = false;
- remote_send_video_ = false;
- local_recv_audio_ = false;
- local_recv_video_ = false;
+ session_options.recv_audio = false;
+ session_options.recv_video = false;
std::unique_ptr<SessionDescriptionInterface> answer(
CreateAnswer(session_options));
@@ -2852,6 +2664,9 @@
SetRemoteDescriptionWithoutError(offer.release());
cricket::MediaSessionOptions options;
+ options.recv_audio = false;
+ options.recv_video = false;
+
// Test with a stream with tracks.
SendAudioVideoStream1();
std::unique_ptr<SessionDescriptionInterface> answer(CreateAnswer(options));
@@ -2911,11 +2726,6 @@
SessionDescriptionInterface* offer = CreateOffer();
cricket::MediaSessionOptions options;
- AddMediaSection(cricket::MEDIA_TYPE_AUDIO, cricket::CN_AUDIO,
- cricket::MD_RECVONLY, kActive, &options);
- AddMediaSection(cricket::MEDIA_TYPE_VIDEO, cricket::CN_VIDEO,
- cricket::MD_INACTIVE, kStopped, &options);
- local_recv_video_ = false;
SessionDescriptionInterface* answer = CreateRemoteAnswer(offer, options);
// SetLocalDescription and SetRemoteDescriptions takes ownership of offer
@@ -2926,7 +2736,7 @@
video_channel_ = media_engine_->GetVideoChannel(0);
voice_channel_ = media_engine_->GetVoiceChannel(0);
- ASSERT_TRUE(video_channel_ == nullptr);
+ ASSERT_TRUE(video_channel_ == NULL);
ASSERT_EQ(0u, voice_channel_->recv_streams().size());
ASSERT_EQ(1u, voice_channel_->send_streams().size());
@@ -2934,14 +2744,13 @@
// Let the remote end update the session descriptions, with Audio and Video.
SendAudioVideoStream2();
- local_recv_video_ = true;
CreateAndSetRemoteOfferAndLocalAnswer();
video_channel_ = media_engine_->GetVideoChannel(0);
voice_channel_ = media_engine_->GetVoiceChannel(0);
- ASSERT_TRUE(video_channel_ != nullptr);
- ASSERT_TRUE(voice_channel_ != nullptr);
+ ASSERT_TRUE(video_channel_ != NULL);
+ ASSERT_TRUE(voice_channel_ != NULL);
ASSERT_EQ(1u, video_channel_->recv_streams().size());
ASSERT_EQ(1u, video_channel_->send_streams().size());
@@ -2953,17 +2762,10 @@
EXPECT_EQ(kAudioTrack2, voice_channel_->send_streams()[0].id);
// Change session back to audio only.
- // The remote side doesn't send and recv video.
SendAudioOnlyStream2();
- remote_recv_video_ = false;
CreateAndSetRemoteOfferAndLocalAnswer();
- video_channel_ = media_engine_->GetVideoChannel(0);
- voice_channel_ = media_engine_->GetVoiceChannel(0);
-
- // The audio is expected to be rejected.
- EXPECT_TRUE(video_channel_ == nullptr);
-
+ EXPECT_EQ(0u, video_channel_->recv_streams().size());
ASSERT_EQ(1u, voice_channel_->recv_streams().size());
EXPECT_EQ(kAudioTrack2, voice_channel_->recv_streams()[0].id);
ASSERT_EQ(1u, voice_channel_->send_streams().size());
@@ -2980,13 +2782,10 @@
SessionDescriptionInterface* offer = CreateOffer();
cricket::MediaSessionOptions options;
- AddMediaSection(cricket::MEDIA_TYPE_AUDIO, cricket::CN_AUDIO,
- cricket::MD_INACTIVE, kStopped, &options);
- AddMediaSection(cricket::MEDIA_TYPE_VIDEO, cricket::CN_VIDEO,
- cricket::MD_RECVONLY, kActive, &options);
- local_recv_audio_ = false;
- SessionDescriptionInterface* answer =
- CreateRemoteAnswer(offer, options, cricket::SEC_ENABLED);
+ options.recv_audio = false;
+ options.recv_video = true;
+ SessionDescriptionInterface* answer = CreateRemoteAnswer(
+ offer, options, cricket::SEC_ENABLED);
// SetLocalDescription and SetRemoteDescriptions takes ownership of offer
// and answer.
@@ -3005,41 +2804,23 @@
// Update the session descriptions, with Audio and Video.
SendAudioVideoStream2();
- local_recv_audio_ = true;
- SessionDescriptionInterface* offer2 = CreateRemoteOffer();
- SetRemoteDescriptionWithoutError(offer2);
- cricket::MediaSessionOptions answer_options;
- // Disable the bundling here. If the media is bundled on audio
- // transport, then we can't reject the audio because switching the bundled
- // transport is not currently supported.
- // (https://bugs.chromium.org/p/webrtc/issues/detail?id=6704)
- answer_options.bundle_enabled = false;
- SessionDescriptionInterface* answer2 = CreateAnswer(answer_options);
- SetLocalDescriptionWithoutError(answer2);
+ CreateAndSetRemoteOfferAndLocalAnswer();
voice_channel_ = media_engine_->GetVoiceChannel(0);
-
ASSERT_TRUE(voice_channel_ != NULL);
+
ASSERT_EQ(1u, voice_channel_->recv_streams().size());
ASSERT_EQ(1u, voice_channel_->send_streams().size());
EXPECT_EQ(kAudioTrack2, voice_channel_->recv_streams()[0].id);
EXPECT_EQ(kAudioTrack2, voice_channel_->send_streams()[0].id);
// Change session back to video only.
- // The remote side doesn't send and recv audio.
SendVideoOnlyStream2();
- remote_recv_audio_ = false;
- SessionDescriptionInterface* offer3 = CreateRemoteOffer();
- SetRemoteDescriptionWithoutError(offer3);
- SessionDescriptionInterface* answer3 = CreateAnswer(answer_options);
- SetLocalDescriptionWithoutError(answer3);
+ CreateAndSetRemoteOfferAndLocalAnswer();
video_channel_ = media_engine_->GetVideoChannel(0);
voice_channel_ = media_engine_->GetVoiceChannel(0);
- // The video is expected to be rejected.
- EXPECT_TRUE(voice_channel_ == nullptr);
-
ASSERT_EQ(1u, video_channel_->recv_streams().size());
EXPECT_EQ(kVideoTrack2, video_channel_->recv_streams()[0].id);
ASSERT_EQ(1u, video_channel_->send_streams().size());
@@ -3244,16 +3025,13 @@
InitWithBundlePolicy(PeerConnectionInterface::kBundlePolicyBalanced);
SendAudioVideoStream1();
- cricket::MediaSessionOptions offer_options;
- GetOptionsForRemoteOffer(&offer_options);
- offer_options.bundle_enabled = true;
+ PeerConnectionInterface::RTCOfferAnswerOptions options;
+ options.use_rtp_mux = true;
- SessionDescriptionInterface* offer = CreateRemoteOffer(offer_options);
+ SessionDescriptionInterface* offer = CreateRemoteOffer();
SetRemoteDescriptionWithoutError(offer);
- cricket::MediaSessionOptions answer_options;
- answer_options.bundle_enabled = true;
- SessionDescriptionInterface* answer = CreateAnswer(answer_options);
+ SessionDescriptionInterface* answer = CreateAnswer();
SetLocalDescriptionWithoutError(answer);
EXPECT_EQ(session_->voice_rtp_transport_channel(),
@@ -3418,11 +3196,10 @@
EXPECT_EQ(session_->voice_rtp_transport_channel(),
session_->video_rtp_transport_channel());
- SendVideoOnlyStream2();
- local_send_audio_ = false;
- remote_recv_audio_ = false;
+ SendAudioVideoStream2();
cricket::MediaSessionOptions recv_options;
- GetOptionsForRemoteAnswer(&recv_options);
+ recv_options.recv_audio = false;
+ recv_options.recv_video = true;
SessionDescriptionInterface* answer =
CreateRemoteAnswer(session_->local_description(), recv_options);
SetRemoteDescriptionWithoutError(answer);
@@ -3509,10 +3286,10 @@
InitWithBundlePolicy(PeerConnectionInterface::kBundlePolicyMaxCompat);
SendAudioVideoStream1();
- PeerConnectionInterface::RTCOfferAnswerOptions rtc_options;
- rtc_options.use_rtp_mux = true;
+ PeerConnectionInterface::RTCOfferAnswerOptions options;
+ options.use_rtp_mux = true;
- SessionDescriptionInterface* offer = CreateOffer(rtc_options);
+ SessionDescriptionInterface* offer = CreateOffer(options);
SetLocalDescriptionWithoutError(offer);
EXPECT_NE(session_->voice_rtp_transport_channel(),
@@ -3868,7 +3645,7 @@
TEST_F(WebRtcSessionTest, TestCreateAnswerWithNewUfragAndPassword) {
Init();
cricket::MediaSessionOptions options;
- GetOptionsForRemoteOffer(&options);
+ options.recv_video = true;
std::unique_ptr<JsepSessionDescription> offer(CreateRemoteOffer(options));
SetRemoteDescriptionWithoutError(offer.release());
@@ -3877,10 +3654,10 @@
SetLocalDescriptionWithoutError(answer.release());
// Receive an offer with new ufrag and password.
- for (size_t i = 0; i < options.media_description_options.size(); ++i) {
- options.media_description_options[i].transport_options.ice_restart = true;
+ for (const cricket::ContentInfo& content :
+ session_->local_description()->description()->contents()) {
+ options.transport_options[content.name].ice_restart = true;
}
-
std::unique_ptr<JsepSessionDescription> updated_offer1(
CreateRemoteOffer(options, session_->remote_description()));
SetRemoteDescriptionWithoutError(updated_offer1.release());
@@ -3908,7 +3685,8 @@
TEST_F(WebRtcSessionTest, TestOfferChangingOnlyUfragOrPassword) {
Init();
cricket::MediaSessionOptions options;
- GetOptionsForRemoteOffer(&options);
+ options.recv_audio = true;
+ options.recv_video = true;
// Create an offer with audio and video.
std::unique_ptr<JsepSessionDescription> offer(CreateRemoteOffer(options));
SetIceUfragPwd(offer.get(), "original_ufrag", "original_password12345");
@@ -3948,7 +3726,7 @@
TEST_F(WebRtcSessionTest, TestCreateAnswerWithOldUfragAndPassword) {
Init();
cricket::MediaSessionOptions options;
- GetOptionsForRemoteOffer(&options);
+ options.recv_video = true;
std::unique_ptr<JsepSessionDescription> offer(CreateRemoteOffer(options));
SetRemoteDescriptionWithoutError(offer.release());
@@ -3975,7 +3753,8 @@
TEST_F(WebRtcSessionTest, TestCreateAnswerWithNewAndOldUfragAndPassword) {
Init();
cricket::MediaSessionOptions options;
- GetOptionsForRemoteOffer(&options);
+ options.recv_video = true;
+ options.recv_audio = true;
options.bundle_enabled = false;
std::unique_ptr<JsepSessionDescription> offer(CreateRemoteOffer(options));
@@ -4107,9 +3886,9 @@
// Create answer that finishes BUNDLE negotiation, which means everything
// should be bundled on the first transport (audio).
cricket::MediaSessionOptions answer_options;
+ answer_options.recv_video = true;
answer_options.bundle_enabled = true;
answer_options.data_channel_type = cricket::DCT_SCTP;
- GetOptionsForAnswer(&answer_options);
SetRemoteDescriptionWithoutError(CreateRemoteAnswer(
session_->local_description(), answer_options, cricket::SEC_DISABLED));
ASSERT_TRUE(session_->sctp_content_name());
@@ -4133,7 +3912,6 @@
// Create remote offer with SCTP.
cricket::MediaSessionOptions options;
options.data_channel_type = cricket::DCT_SCTP;
- GetOptionsForRemoteOffer(&options);
JsepSessionDescription* offer =
CreateRemoteOffer(options, cricket::SEC_DISABLED);
SetRemoteDescriptionWithoutError(offer);
@@ -4277,7 +4055,7 @@
SetFactoryDtlsSrtp();
cricket::MediaSessionOptions options;
- GetOptionsForRemoteOffer(&options);
+ options.recv_video = true;
std::unique_ptr<JsepSessionDescription> offer(
CreateRemoteOffer(options, cricket::SEC_DISABLED));
ASSERT_TRUE(offer.get() != NULL);
@@ -4351,7 +4129,6 @@
Init();
// Create a remote offer with secured transport disabled.
cricket::MediaSessionOptions options;
- GetOptionsForRemoteOffer(&options);
JsepSessionDescription* offer(CreateRemoteOffer(
options, cricket::SEC_DISABLED));
// Adds a DTLS fingerprint to the remote offer.
@@ -4395,7 +4172,7 @@
SetRemoteDescriptionWithoutError(answer);
cricket::MediaSessionOptions options;
- GetOptionsForRemoteOffer(&options);
+ options.recv_video = true;
offer = CreateRemoteOffer(options, cricket::SEC_DISABLED);
cricket::Candidate candidate1;
@@ -4424,7 +4201,7 @@
SetRemoteDescriptionWithoutError(answer);
cricket::MediaSessionOptions options;
- GetOptionsForRemoteOffer(&options);
+ options.recv_video = true;
offer = CreateRemoteOffer(options, cricket::SEC_DISABLED);
SetRemoteDescriptionWithoutError(offer);
@@ -4449,7 +4226,8 @@
ASSERT_TRUE(offer->description());
SetLocalDescriptionWithoutError(offer);
cricket::MediaSessionOptions options;
- GetOptionsForAnswer(&options);
+ options.recv_audio = true;
+ options.recv_video = true;
SessionDescriptionInterface* answer =
CreateRemoteAnswer(offer, options, cricket::SEC_DISABLED);
ASSERT_TRUE(answer);
@@ -4462,8 +4240,7 @@
// by local side.
TEST_F(WebRtcSessionTest, TestRtxRemovedByCreateAnswer) {
Init();
- // Send video only to match the |kSdpWithRtx|.
- SendVideoOnlyStream2();
+ SendAudioVideoStream1();
std::string offer_sdp(kSdpWithRtx);
SessionDescriptionInterface* offer =
@@ -4474,11 +4251,6 @@
EXPECT_TRUE(ContainsVideoCodecWithName(offer, "rtx"));
SetRemoteDescriptionWithoutError(offer);
- // |offered_media_sections_| is used when creating answer.
- offered_media_sections_.push_back(cricket::MediaDescriptionOptions(
- cricket::MEDIA_TYPE_VIDEO, cricket::CN_VIDEO,
- cricket::RtpTransceiverDirection(true, true), false));
- // Don't create media section for audio in the answer.
SessionDescriptionInterface* answer = CreateAnswer();
// Answer SDP does not contain the RTX codec.
EXPECT_FALSE(ContainsVideoCodecWithName(answer, "rtx"));
@@ -4544,7 +4316,8 @@
options.offer_to_receive_audio =
RTCOfferAnswerOptions::kOfferToReceiveMediaTrue;
cricket::MediaSessionOptions session_options;
- GetOptionsForOffer(options, &session_options);
+ session_options.recv_audio = true;
+
for (auto& o : observers) {
o = new WebRtcSessionCreateSDPObserverForTest();
session_->CreateOffer(o, options, session_options);
diff --git a/webrtc/pc/webrtcsessiondescriptionfactory.cc b/webrtc/pc/webrtcsessiondescriptionfactory.cc
index beb8d1e..8eccd65 100644
--- a/webrtc/pc/webrtcsessiondescriptionfactory.cc
+++ b/webrtc/pc/webrtcsessiondescriptionfactory.cc
@@ -30,30 +30,24 @@
static const uint64_t kInitSessionVersion = 2;
-static bool CompareSenderOptions(const cricket::SenderOptions& sender1,
- const cricket::SenderOptions& sender2) {
- return sender1.track_id < sender2.track_id;
+static bool CompareStream(const MediaSessionOptions::Stream& stream1,
+ const MediaSessionOptions::Stream& stream2) {
+ return stream1.id < stream2.id;
}
-static bool SameId(const cricket::SenderOptions& sender1,
- const cricket::SenderOptions& sender2) {
- return sender1.track_id == sender2.track_id;
+static bool SameId(const MediaSessionOptions::Stream& stream1,
+ const MediaSessionOptions::Stream& stream2) {
+ return stream1.id == stream2.id;
}
-// Check that each sender has a unique ID.
-static bool ValidMediaSessionOptions(
- const cricket::MediaSessionOptions& session_options) {
- std::vector<cricket::SenderOptions> sorted_senders;
- for (const cricket::MediaDescriptionOptions& media_description_options :
- session_options.media_description_options) {
- sorted_senders.insert(sorted_senders.end(),
- media_description_options.sender_options.begin(),
- media_description_options.sender_options.end());
- }
- std::sort(sorted_senders.begin(), sorted_senders.end(), CompareSenderOptions);
- std::vector<cricket::SenderOptions>::iterator it =
- std::adjacent_find(sorted_senders.begin(), sorted_senders.end(), SameId);
- return it == sorted_senders.end();
+// Checks if each Stream within the |streams| has unique id.
+static bool ValidStreams(const MediaSessionOptions::Streams& streams) {
+ MediaSessionOptions::Streams sorted_streams = streams;
+ std::sort(sorted_streams.begin(), sorted_streams.end(), CompareStream);
+ MediaSessionOptions::Streams::iterator it =
+ std::adjacent_find(sorted_streams.begin(), sorted_streams.end(),
+ SameId);
+ return it == sorted_streams.end();
}
enum {
@@ -134,6 +128,7 @@
session_id_(session_id),
certificate_request_state_(CERTIFICATE_NOT_NEEDED) {
RTC_DCHECK(signaling_thread_);
+ session_desc_factory_.set_add_legacy_streams(false);
bool dtls_enabled = cert_generator_ || certificate;
// SRTP-SDES is disabled if DTLS is on.
SetSdesPolicy(dtls_enabled ? cricket::SEC_DISABLED : cricket::SEC_REQUIRED);
@@ -242,8 +237,8 @@
return;
}
- if (!ValidMediaSessionOptions(session_options)) {
- error += " called with invalid session options";
+ if (!ValidStreams(session_options.streams)) {
+ error += " called with invalid media streams.";
LOG(LS_ERROR) << error;
PostCreateSessionDescriptionFailed(observer, error);
return;
@@ -284,8 +279,8 @@
return;
}
- if (!ValidMediaSessionOptions(session_options)) {
- error += " called with invalid session options.";
+ if (!ValidStreams(session_options.streams)) {
+ error += " called with invalid media streams.";
LOG(LS_ERROR) << error;
PostCreateSessionDescriptionFailed(observer, error);
return;
@@ -345,12 +340,13 @@
void WebRtcSessionDescriptionFactory::InternalCreateOffer(
CreateSessionDescriptionRequest request) {
if (session_->local_description()) {
- // If the needs-ice-restart flag is set as described by JSEP, we should
- // generate an offer with a new ufrag/password to trigger an ICE restart.
- for (cricket::MediaDescriptionOptions& options :
- request.options.media_description_options) {
- if (session_->NeedsIceRestart(options.mid)) {
- options.transport_options.ice_restart = true;
+ for (const cricket::TransportInfo& transport :
+ session_->local_description()->description()->transport_infos()) {
+ // If the needs-ice-restart flag is set as described by JSEP, we should
+ // generate an offer with a new ufrag/password to trigger an ICE restart.
+ if (session_->NeedsIceRestart(transport.content_name)) {
+ request.options.transport_options[transport.content_name].ice_restart =
+ true;
}
}
}
@@ -379,11 +375,13 @@
return;
}
if (session_->local_description()) {
- for (const cricket::MediaDescriptionOptions& options :
- request.options.media_description_options) {
- if (!options.transport_options.ice_restart) {
+ for (const cricket::ContentInfo& content :
+ session_->local_description()->description()->contents()) {
+ // Include all local ICE candidates in the SessionDescription unless
+ // an ICE restart was requested.
+ if (!request.options.transport_options[content.name].ice_restart) {
CopyCandidatesFromSessionDescription(session_->local_description(),
- options.mid, offer);
+ content.name, offer);
}
}
}
@@ -393,18 +391,18 @@
void WebRtcSessionDescriptionFactory::InternalCreateAnswer(
CreateSessionDescriptionRequest request) {
if (session_->remote_description()) {
- for (cricket::MediaDescriptionOptions& options :
- request.options.media_description_options) {
+ for (const cricket::ContentInfo& content :
+ session_->remote_description()->description()->contents()) {
// According to http://tools.ietf.org/html/rfc5245#section-9.2.1.1
// an answer should also contain new ICE ufrag and password if an offer
// has been received with new ufrag and password.
- options.transport_options.ice_restart =
- session_->IceRestartPending(options.mid);
+ request.options.transport_options[content.name].ice_restart =
+ session_->IceRestartPending(content.name);
// We should pass the current SSL role to the transport description
// factory, if there is already an existing ongoing session.
rtc::SSLRole ssl_role;
- if (session_->GetSslRole(options.mid, &ssl_role)) {
- options.transport_options.prefer_passive_role =
+ if (session_->GetSslRole(content.name, &ssl_role)) {
+ request.options.transport_options[content.name].prefer_passive_role =
(rtc::SSL_SERVER == ssl_role);
}
}
@@ -435,13 +433,13 @@
return;
}
if (session_->local_description()) {
- // Include all local ICE candidates in the SessionDescription unless
- // the remote peer has requested an ICE restart.
- for (const cricket::MediaDescriptionOptions& options :
- request.options.media_description_options) {
- if (!options.transport_options.ice_restart) {
+ for (const cricket::ContentInfo& content :
+ session_->local_description()->description()->contents()) {
+ // Include all local ICE candidates in the SessionDescription unless
+ // the remote peer has requested an ICE restart.
+ if (!request.options.transport_options[content.name].ice_restart) {
CopyCandidatesFromSessionDescription(session_->local_description(),
- options.mid, answer);
+ content.name, answer);
}
}
}