webrtc/pc/media_session.h
Bjorn A Mellem 8e1343aeda Add an alt-protocol to SDP to indicate which m= sections use a plugin transport.
The plugin transport parameters (a=x-opaque: lines) relate to how to create and
set up a plugin transport.  When SDP bundle is used, the x-opaque line needs to
be copied into the bundled m= section.  This means x-opaque can appear on a
section even if the offerer does not intend to use the transport for the media
described by that section.  Consequently, the answerer cannot currently tell
whether the caller is offering an alternate transport for media, data, or both.

This change adds an a=x-alt-protocol: line to SDP.  The value following this
line matches the <protocol> part of the x-opaque:<protocol>:<params> line.
However, alt-protocol is not bundled--it only ever applies to the m= section
that contains the line.  This allows the offerer to express which m= sections
should actually use an alternate transport, even in the case of bundle.

Note that this is still limited by the available configuration options:
datagram transport can be used for media (audio + video) and/or data.  It is
still not possible to use it for audio but not video, or vice versa.

PeerConnection places an alt-protocol line in each media (audio/video) m=
section if it is configured to use a datagram transport for media.  It places
an alt-protocol line in each data m= section if it is configured to use a
datagram transport for data channels.  PeerConnection leaves alt-protocol in
media (audio/video) m= sections of the answer if it is configured to use a
datagram transport for media, and in data m= sections of the answer if it is
configured to use a datagram transport for data channels.

JsepTransport now negotiates use of the datagram transport independently for
media and data channels.  It only uses it for media if the m= sections for
bundled audio/video have an alt-protocol line matching the x-opaque protocol,
and only uses it for data channels if a bundled m= section for data has an
alt-protocol line matching the x-opaque protocol.

Bug: webrtc:9719
Change-Id: I773e4fc10c57d815afcd76a2a74da38dd0c52b3b
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/154763
Reviewed-by: Steve Anton <steveanton@webrtc.org>
Reviewed-by: Seth Hampson <shampson@webrtc.org>
Commit-Queue: Bjorn Mellem <mellem@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#29351}
2019-09-30 23:10:34 +00:00

410 lines
17 KiB
C++

/*
* Copyright 2004 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
// Types and classes used in media session descriptions.
#ifndef PC_MEDIA_SESSION_H_
#define PC_MEDIA_SESSION_H_
#include <map>
#include <memory>
#include <string>
#include <vector>
#include "api/media_types.h"
#include "media/base/media_constants.h"
#include "media/base/media_engine.h" // For DataChannelType
#include "p2p/base/ice_credentials_iterator.h"
#include "p2p/base/transport_description_factory.h"
#include "pc/jsep_transport.h"
#include "pc/media_protocol_names.h"
#include "pc/session_description.h"
#include "rtc_base/unique_id_generator.h"
namespace cricket {
class ChannelManager;
// Default RTCP CNAME for unit tests.
const char kDefaultRtcpCname[] = "DefaultRtcpCname";
// Options for an RtpSender contained with an media description/"m=" section.
// Note: Spec-compliant Simulcast and legacy simulcast are mutually exclusive.
struct SenderOptions {
std::string track_id;
std::vector<std::string> stream_ids;
// Use RIDs and Simulcast Layers to indicate spec-compliant Simulcast.
std::vector<RidDescription> rids;
SimulcastLayerList simulcast_layers;
// Use |num_sim_layers| to indicate legacy simulcast.
int num_sim_layers;
};
// Options for an individual media description/"m=" section.
struct MediaDescriptionOptions {
MediaDescriptionOptions(MediaType type,
const std::string& mid,
webrtc::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::vector<std::string>& stream_ids);
void AddVideoSender(const std::string& track_id,
const std::vector<std::string>& stream_ids,
const std::vector<RidDescription>& rids,
const SimulcastLayerList& simulcast_layers,
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;
webrtc::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;
std::vector<webrtc::RtpCodecCapability> codec_preferences;
absl::optional<std::string> alt_protocol;
private:
// Doesn't DCHECK on |type|.
void AddSenderInternal(const std::string& track_id,
const std::vector<std::string>& stream_ids,
const std::vector<RidDescription>& rids,
const SimulcastLayerList& simulcast_layers,
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() {}
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 HasMediaDescription(MediaType type) const;
DataChannelType data_channel_type = DCT_NONE;
bool vad_enabled = true; // When disabled, removes all CN codecs from SDP.
bool rtcp_mux_enabled = true;
bool bundle_enabled = false;
bool offer_extmap_allow_mixed = false;
bool raw_packetization_for_video = false;
std::string rtcp_cname = kDefaultRtcpCname;
webrtc::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;
std::vector<IceParameters> pooled_ice_credentials;
// An optional media transport settings.
// In the future we may consider using a vector here, to indicate multiple
// supported transports.
absl::optional<cricket::SessionDescription::MediaTransportSetting>
media_transport_settings;
// Use the draft-ietf-mmusic-sctp-sdp-03 obsolete syntax for SCTP
// datachannels.
// Default is true for backwards compatibility with clients that use
// this internal interface.
bool use_obsolete_sctp_sdp = true;
};
// Creates media session descriptions according to the supplied codecs and
// other fields, as well as the supplied per-call options.
// When creating answers, performs the appropriate negotiation
// of the various fields to determine the proper result.
class MediaSessionDescriptionFactory {
public:
// Simple constructor that does not set any configuration for the factory.
// When using this constructor, the methods below can be used to set the
// configuration.
// The TransportDescriptionFactory and the UniqueRandomIdGenerator are not
// owned by MediaSessionDescriptionFactory, so they must be kept alive by the
// user of this class.
MediaSessionDescriptionFactory(const TransportDescriptionFactory* factory,
rtc::UniqueRandomIdGenerator* ssrc_generator);
// This helper automatically sets up the factory to get its configuration
// from the specified ChannelManager.
MediaSessionDescriptionFactory(ChannelManager* cmanager,
const TransportDescriptionFactory* factory,
rtc::UniqueRandomIdGenerator* ssrc_generator);
const AudioCodecs& audio_sendrecv_codecs() const;
const AudioCodecs& audio_send_codecs() const;
const AudioCodecs& audio_recv_codecs() const;
void set_audio_codecs(const AudioCodecs& send_codecs,
const AudioCodecs& recv_codecs);
void set_audio_rtp_header_extensions(const RtpHeaderExtensions& extensions) {
audio_rtp_extensions_ = extensions;
}
RtpHeaderExtensions audio_rtp_header_extensions() const;
const VideoCodecs& video_codecs() const { return video_codecs_; }
void set_video_codecs(const VideoCodecs& codecs) { video_codecs_ = codecs; }
void set_video_rtp_header_extensions(const RtpHeaderExtensions& extensions) {
video_rtp_extensions_ = extensions;
}
RtpHeaderExtensions video_rtp_header_extensions() const;
const RtpDataCodecs& rtp_data_codecs() const { return rtp_data_codecs_; }
void set_rtp_data_codecs(const RtpDataCodecs& codecs) {
rtp_data_codecs_ = codecs;
}
SecurePolicy secure() const { return secure_; }
void set_secure(SecurePolicy s) { secure_ = s; }
void set_enable_encrypted_rtp_header_extensions(bool enable) {
enable_encrypted_rtp_header_extensions_ = enable;
}
void set_is_unified_plan(bool is_unified_plan) {
is_unified_plan_ = is_unified_plan;
}
std::unique_ptr<SessionDescription> CreateOffer(
const MediaSessionOptions& options,
const SessionDescription* current_description) const;
std::unique_ptr<SessionDescription> CreateAnswer(
const SessionDescription* offer,
const MediaSessionOptions& options,
const SessionDescription* current_description) const;
private:
const AudioCodecs& GetAudioCodecsForOffer(
const webrtc::RtpTransceiverDirection& direction) const;
const AudioCodecs& GetAudioCodecsForAnswer(
const webrtc::RtpTransceiverDirection& offer,
const webrtc::RtpTransceiverDirection& answer) const;
void GetCodecsForOffer(
const std::vector<const ContentInfo*>& current_active_contents,
AudioCodecs* audio_codecs,
VideoCodecs* video_codecs,
RtpDataCodecs* rtp_data_codecs) const;
void GetCodecsForAnswer(
const std::vector<const ContentInfo*>& current_active_contents,
const SessionDescription& remote_offer,
AudioCodecs* audio_codecs,
VideoCodecs* video_codecs,
RtpDataCodecs* rtp_data_codecs) const;
void GetRtpHdrExtsToOffer(
const std::vector<const ContentInfo*>& current_active_contents,
bool extmap_allow_mixed,
RtpHeaderExtensions* audio_extensions,
RtpHeaderExtensions* video_extensions) const;
bool AddTransportOffer(const std::string& content_name,
const TransportOptions& transport_options,
const SessionDescription* current_desc,
SessionDescription* offer,
IceCredentialsIterator* ice_credentials) const;
std::unique_ptr<TransportDescription> CreateTransportAnswer(
const std::string& content_name,
const SessionDescription* offer_desc,
const TransportOptions& transport_options,
const SessionDescription* current_desc,
bool require_transport_attributes,
IceCredentialsIterator* ice_credentials) const;
bool AddTransportAnswer(const std::string& content_name,
const TransportDescription& transport_desc,
SessionDescription* answer_desc) const;
// Helpers for adding media contents to the SessionDescription. Returns true
// it succeeds or the media content is not needed, or false if there is any
// error.
bool AddAudioContentForOffer(
const MediaDescriptionOptions& media_description_options,
const MediaSessionOptions& session_options,
const ContentInfo* current_content,
const SessionDescription* current_description,
const RtpHeaderExtensions& audio_rtp_extensions,
const AudioCodecs& audio_codecs,
StreamParamsVec* current_streams,
SessionDescription* desc,
IceCredentialsIterator* ice_credentials) const;
bool AddVideoContentForOffer(
const MediaDescriptionOptions& media_description_options,
const MediaSessionOptions& session_options,
const ContentInfo* current_content,
const SessionDescription* current_description,
const RtpHeaderExtensions& video_rtp_extensions,
const VideoCodecs& video_codecs,
StreamParamsVec* current_streams,
SessionDescription* desc,
IceCredentialsIterator* ice_credentials) const;
bool AddSctpDataContentForOffer(
const MediaDescriptionOptions& media_description_options,
const MediaSessionOptions& session_options,
const ContentInfo* current_content,
const SessionDescription* current_description,
StreamParamsVec* current_streams,
SessionDescription* desc,
IceCredentialsIterator* ice_credentials) const;
bool AddRtpDataContentForOffer(
const MediaDescriptionOptions& media_description_options,
const MediaSessionOptions& session_options,
const ContentInfo* current_content,
const SessionDescription* current_description,
const RtpDataCodecs& rtp_data_codecs,
StreamParamsVec* current_streams,
SessionDescription* desc,
IceCredentialsIterator* ice_credentials) const;
// This function calls either AddRtpDataContentForOffer or
// AddSctpDataContentForOffer depending on protocol.
// The codecs argument is ignored for SCTP.
bool AddDataContentForOffer(
const MediaDescriptionOptions& media_description_options,
const MediaSessionOptions& session_options,
const ContentInfo* current_content,
const SessionDescription* current_description,
const RtpDataCodecs& rtp_data_codecs,
StreamParamsVec* current_streams,
SessionDescription* desc,
IceCredentialsIterator* ice_credentials) 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,
IceCredentialsIterator* ice_credentials) 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,
IceCredentialsIterator* ice_credentials) 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 RtpDataCodecs& rtp_data_codecs,
StreamParamsVec* current_streams,
SessionDescription* answer,
IceCredentialsIterator* ice_credentials) const;
void ComputeAudioCodecsIntersectionAndUnion();
bool is_unified_plan_ = false;
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_;
RtpDataCodecs rtp_data_codecs_;
// This object is not owned by the channel so it must outlive it.
rtc::UniqueRandomIdGenerator* const ssrc_generator_;
bool enable_encrypted_rtp_header_extensions_ = false;
// TODO(zhihuang): Rename secure_ to sdec_policy_; rename the related getter
// and setter.
SecurePolicy secure_ = SEC_DISABLED;
const TransportDescriptionFactory* transport_desc_factory_;
};
// Convenience functions.
bool IsMediaContent(const ContentInfo* content);
bool IsAudioContent(const ContentInfo* content);
bool IsVideoContent(const ContentInfo* content);
bool IsDataContent(const ContentInfo* content);
const ContentInfo* GetFirstMediaContent(const ContentInfos& contents,
MediaType media_type);
const ContentInfo* GetFirstAudioContent(const ContentInfos& contents);
const ContentInfo* GetFirstVideoContent(const ContentInfos& contents);
const ContentInfo* GetFirstDataContent(const ContentInfos& contents);
const ContentInfo* GetFirstMediaContent(const SessionDescription* sdesc,
MediaType media_type);
const ContentInfo* GetFirstAudioContent(const SessionDescription* sdesc);
const ContentInfo* GetFirstVideoContent(const SessionDescription* sdesc);
const ContentInfo* GetFirstDataContent(const SessionDescription* sdesc);
const AudioContentDescription* GetFirstAudioContentDescription(
const SessionDescription* sdesc);
const VideoContentDescription* GetFirstVideoContentDescription(
const SessionDescription* sdesc);
const RtpDataContentDescription* GetFirstRtpDataContentDescription(
const SessionDescription* sdesc);
const SctpDataContentDescription* GetFirstSctpDataContentDescription(
const SessionDescription* sdesc);
// Non-const versions of the above functions.
// Useful when modifying an existing description.
ContentInfo* GetFirstMediaContent(ContentInfos* contents, MediaType media_type);
ContentInfo* GetFirstAudioContent(ContentInfos* contents);
ContentInfo* GetFirstVideoContent(ContentInfos* contents);
ContentInfo* GetFirstDataContent(ContentInfos* contents);
ContentInfo* GetFirstMediaContent(SessionDescription* sdesc,
MediaType media_type);
ContentInfo* GetFirstAudioContent(SessionDescription* sdesc);
ContentInfo* GetFirstVideoContent(SessionDescription* sdesc);
ContentInfo* GetFirstDataContent(SessionDescription* sdesc);
AudioContentDescription* GetFirstAudioContentDescription(
SessionDescription* sdesc);
VideoContentDescription* GetFirstVideoContentDescription(
SessionDescription* sdesc);
RtpDataContentDescription* GetFirstRtpDataContentDescription(
SessionDescription* sdesc);
SctpDataContentDescription* GetFirstSctpDataContentDescription(
SessionDescription* sdesc);
// Helper functions to return crypto suites used for SDES.
void GetSupportedAudioSdesCryptoSuites(
const webrtc::CryptoOptions& crypto_options,
std::vector<int>* crypto_suites);
void GetSupportedVideoSdesCryptoSuites(
const webrtc::CryptoOptions& crypto_options,
std::vector<int>* crypto_suites);
void GetSupportedDataSdesCryptoSuites(
const webrtc::CryptoOptions& crypto_options,
std::vector<int>* crypto_suites);
void GetSupportedAudioSdesCryptoSuiteNames(
const webrtc::CryptoOptions& crypto_options,
std::vector<std::string>* crypto_suite_names);
void GetSupportedVideoSdesCryptoSuiteNames(
const webrtc::CryptoOptions& crypto_options,
std::vector<std::string>* crypto_suite_names);
void GetSupportedDataSdesCryptoSuiteNames(
const webrtc::CryptoOptions& crypto_options,
std::vector<std::string>* crypto_suite_names);
} // namespace cricket
#endif // PC_MEDIA_SESSION_H_