1 /* 2 * libjingle 3 * Copyright 2004 Google Inc. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are met: 7 * 8 * 1. Redistributions of source code must retain the above copyright notice, 9 * this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright notice, 11 * this list of conditions and the following disclaimer in the documentation 12 * and/or other materials provided with the distribution. 13 * 3. The name of the author may not be used to endorse or promote products 14 * derived from this software without specific prior written permission. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 18 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 19 * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 20 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 21 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 22 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 23 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 24 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 25 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 */ 27 28 // Types and classes used in media session descriptions. 29 30 #ifndef TALK_SESSION_MEDIA_MEDIASESSION_H_ 31 #define TALK_SESSION_MEDIA_MEDIASESSION_H_ 32 33 #include <string> 34 #include <vector> 35 #include <algorithm> 36 37 #include "talk/base/scoped_ptr.h" 38 #include "talk/media/base/codec.h" 39 #include "talk/media/base/constants.h" 40 #include "talk/media/base/cryptoparams.h" 41 #include "talk/media/base/mediachannel.h" 42 #include "talk/media/base/mediaengine.h" // For DataChannelType 43 #include "talk/media/base/streamparams.h" 44 #include "talk/p2p/base/sessiondescription.h" 45 #include "talk/p2p/base/transport.h" 46 #include "talk/p2p/base/transportdescriptionfactory.h" 47 48 namespace cricket { 49 50 class ChannelManager; 51 typedef std::vector<AudioCodec> AudioCodecs; 52 typedef std::vector<VideoCodec> VideoCodecs; 53 typedef std::vector<DataCodec> DataCodecs; 54 typedef std::vector<CryptoParams> CryptoParamsVec; 55 typedef std::vector<RtpHeaderExtension> RtpHeaderExtensions; 56 57 // TODO(juberti): Replace SecureMediaPolicy with SecurePolicy everywhere. 58 typedef SecurePolicy SecureMediaPolicy; 59 60 enum MediaType { 61 MEDIA_TYPE_AUDIO, 62 MEDIA_TYPE_VIDEO, 63 MEDIA_TYPE_DATA 64 }; 65 66 enum MediaContentDirection { 67 MD_INACTIVE, 68 MD_SENDONLY, 69 MD_RECVONLY, 70 MD_SENDRECV 71 }; 72 73 // RTC4585 RTP/AVPF 74 extern const char kMediaProtocolAvpf[]; 75 // RFC5124 RTP/SAVPF 76 extern const char kMediaProtocolSavpf[]; 77 78 extern const char kMediaProtocolRtpPrefix[]; 79 80 extern const char kMediaProtocolSctp[]; 81 extern const char kMediaProtocolDtlsSctp[]; 82 83 // Options to control how session descriptions are generated. 84 const int kAutoBandwidth = -1; 85 const int kBufferedModeDisabled = 0; 86 87 struct MediaSessionOptions { 88 MediaSessionOptions() : 89 has_audio(true), // Audio enabled by default. 90 has_video(false), 91 data_channel_type(DCT_NONE), 92 is_muc(false), 93 vad_enabled(true), // When disabled, removes all CN codecs from SDP. 94 rtcp_mux_enabled(true), 95 bundle_enabled(false), 96 video_bandwidth(kAutoBandwidth), 97 data_bandwidth(kDataMaxBandwidth) { 98 } 99 100 bool has_data() const { return data_channel_type != DCT_NONE; } 101 102 // Add a stream with MediaType type and id. 103 // All streams with the same sync_label will get the same CNAME. 104 // All ids must be unique. 105 void AddStream(MediaType type, 106 const std::string& id, 107 const std::string& sync_label); 108 void AddVideoStream(const std::string& id, 109 const std::string& sync_label, 110 int num_sim_layers); 111 void RemoveStream(MediaType type, const std::string& id); 112 113 114 // Helper function. 115 void AddStreamInternal(MediaType type, 116 const std::string& id, 117 const std::string& sync_label, 118 int num_sim_layers); 119 120 bool has_audio; 121 bool has_video; 122 DataChannelType data_channel_type; 123 bool is_muc; 124 bool vad_enabled; 125 bool rtcp_mux_enabled; 126 bool bundle_enabled; 127 // bps. -1 == auto. 128 int video_bandwidth; 129 int data_bandwidth; 130 TransportOptions transport_options; 131 132 struct Stream { 133 Stream(MediaType type, 134 const std::string& id, 135 const std::string& sync_label, 136 int num_sim_layers) 137 : type(type), id(id), sync_label(sync_label), 138 num_sim_layers(num_sim_layers) { 139 } 140 MediaType type; 141 std::string id; 142 std::string sync_label; 143 int num_sim_layers; 144 }; 145 146 typedef std::vector<Stream> Streams; 147 Streams streams; 148 }; 149 150 // "content" (as used in XEP-0166) descriptions for voice and video. 151 class MediaContentDescription : public ContentDescription { 152 public: 153 MediaContentDescription() 154 : rtcp_mux_(false), 155 bandwidth_(kAutoBandwidth), 156 crypto_required_(false), 157 rtp_header_extensions_set_(false), 158 multistream_(false), 159 conference_mode_(false), 160 partial_(false), 161 buffered_mode_latency_(kBufferedModeDisabled), 162 direction_(MD_SENDRECV) { 163 } 164 165 virtual MediaType type() const = 0; 166 virtual bool has_codecs() const = 0; 167 168 // |protocol| is the expected media transport protocol, such as RTP/AVPF, 169 // RTP/SAVPF or SCTP/DTLS. 170 std::string protocol() const { return protocol_; } 171 void set_protocol(const std::string& protocol) { protocol_ = protocol; } 172 173 MediaContentDirection direction() const { return direction_; } 174 void set_direction(MediaContentDirection direction) { 175 direction_ = direction; 176 } 177 178 bool rtcp_mux() const { return rtcp_mux_; } 179 void set_rtcp_mux(bool mux) { rtcp_mux_ = mux; } 180 181 int bandwidth() const { return bandwidth_; } 182 void set_bandwidth(int bandwidth) { bandwidth_ = bandwidth; } 183 184 const std::vector<CryptoParams>& cryptos() const { return cryptos_; } 185 void AddCrypto(const CryptoParams& params) { 186 cryptos_.push_back(params); 187 } 188 void set_cryptos(const std::vector<CryptoParams>& cryptos) { 189 cryptos_ = cryptos; 190 } 191 bool crypto_required() const { return crypto_required_; } 192 void set_crypto_required(bool crypto) { 193 crypto_required_ = crypto; 194 } 195 196 const RtpHeaderExtensions& rtp_header_extensions() const { 197 return rtp_header_extensions_; 198 } 199 void set_rtp_header_extensions(const RtpHeaderExtensions& extensions) { 200 rtp_header_extensions_ = extensions; 201 rtp_header_extensions_set_ = true; 202 } 203 void AddRtpHeaderExtension(const RtpHeaderExtension& ext) { 204 rtp_header_extensions_.push_back(ext); 205 rtp_header_extensions_set_ = true; 206 } 207 void ClearRtpHeaderExtensions() { 208 rtp_header_extensions_.clear(); 209 rtp_header_extensions_set_ = true; 210 } 211 // We can't always tell if an empty list of header extensions is 212 // because the other side doesn't support them, or just isn't hooked up to 213 // signal them. For now we assume an empty list means no signaling, but 214 // provide the ClearRtpHeaderExtensions method to allow "no support" to be 215 // clearly indicated (i.e. when derived from other information). 216 bool rtp_header_extensions_set() const { 217 return rtp_header_extensions_set_; 218 } 219 // True iff the client supports multiple streams. 220 void set_multistream(bool multistream) { multistream_ = multistream; } 221 bool multistream() const { return multistream_; } 222 const StreamParamsVec& streams() const { 223 return streams_; 224 } 225 // TODO(pthatcher): Remove this by giving mediamessage.cc access 226 // to MediaContentDescription 227 StreamParamsVec& mutable_streams() { 228 return streams_; 229 } 230 void AddStream(const StreamParams& stream) { 231 streams_.push_back(stream); 232 } 233 // Legacy streams have an ssrc, but nothing else. 234 void AddLegacyStream(uint32 ssrc) { 235 streams_.push_back(StreamParams::CreateLegacy(ssrc)); 236 } 237 void AddLegacyStream(uint32 ssrc, uint32 fid_ssrc) { 238 StreamParams sp = StreamParams::CreateLegacy(ssrc); 239 sp.AddFidSsrc(ssrc, fid_ssrc); 240 streams_.push_back(sp); 241 } 242 // Sets the CNAME of all StreamParams if it have not been set. 243 // This can be used to set the CNAME of legacy streams. 244 void SetCnameIfEmpty(const std::string& cname) { 245 for (cricket::StreamParamsVec::iterator it = streams_.begin(); 246 it != streams_.end(); ++it) { 247 if (it->cname.empty()) 248 it->cname = cname; 249 } 250 } 251 uint32 first_ssrc() const { 252 if (streams_.empty()) { 253 return 0; 254 } 255 return streams_[0].first_ssrc(); 256 } 257 bool has_ssrcs() const { 258 if (streams_.empty()) { 259 return false; 260 } 261 return streams_[0].has_ssrcs(); 262 } 263 264 void set_conference_mode(bool enable) { conference_mode_ = enable; } 265 bool conference_mode() const { return conference_mode_; } 266 267 void set_partial(bool partial) { partial_ = partial; } 268 bool partial() const { return partial_; } 269 270 void set_buffered_mode_latency(int latency) { 271 buffered_mode_latency_ = latency; 272 } 273 int buffered_mode_latency() const { return buffered_mode_latency_; } 274 275 protected: 276 bool rtcp_mux_; 277 int bandwidth_; 278 std::string protocol_; 279 std::vector<CryptoParams> cryptos_; 280 bool crypto_required_; 281 std::vector<RtpHeaderExtension> rtp_header_extensions_; 282 bool rtp_header_extensions_set_; 283 bool multistream_; 284 StreamParamsVec streams_; 285 bool conference_mode_; 286 bool partial_; 287 int buffered_mode_latency_; 288 MediaContentDirection direction_; 289 }; 290 291 template <class C> 292 class MediaContentDescriptionImpl : public MediaContentDescription { 293 public: 294 struct PreferenceSort { 295 bool operator()(C a, C b) { return a.preference > b.preference; } 296 }; 297 298 const std::vector<C>& codecs() const { return codecs_; } 299 void set_codecs(const std::vector<C>& codecs) { codecs_ = codecs; } 300 virtual bool has_codecs() const { return !codecs_.empty(); } 301 bool HasCodec(int id) { 302 bool found = false; 303 for (typename std::vector<C>::iterator iter = codecs_.begin(); 304 iter != codecs_.end(); ++iter) { 305 if (iter->id == id) { 306 found = true; 307 break; 308 } 309 } 310 return found; 311 } 312 void AddCodec(const C& codec) { 313 codecs_.push_back(codec); 314 } 315 void AddCodecs(const std::vector<C>& codecs) { 316 typename std::vector<C>::const_iterator codec; 317 for (codec = codecs.begin(); codec != codecs.end(); ++codec) { 318 AddCodec(*codec); 319 } 320 } 321 void SortCodecs() { 322 std::sort(codecs_.begin(), codecs_.end(), PreferenceSort()); 323 } 324 325 private: 326 std::vector<C> codecs_; 327 }; 328 329 class AudioContentDescription : public MediaContentDescriptionImpl<AudioCodec> { 330 public: 331 AudioContentDescription() : 332 agc_minus_10db_(false) {} 333 334 virtual ContentDescription* Copy() const { 335 return new AudioContentDescription(*this); 336 } 337 virtual MediaType type() const { return MEDIA_TYPE_AUDIO; } 338 339 const std::string &lang() const { return lang_; } 340 void set_lang(const std::string &lang) { lang_ = lang; } 341 342 bool agc_minus_10db() const { return agc_minus_10db_; } 343 void set_agc_minus_10db(bool enable) { 344 agc_minus_10db_ = enable; 345 } 346 347 private: 348 bool agc_minus_10db_; 349 350 private: 351 std::string lang_; 352 }; 353 354 class VideoContentDescription : public MediaContentDescriptionImpl<VideoCodec> { 355 public: 356 virtual ContentDescription* Copy() const { 357 return new VideoContentDescription(*this); 358 } 359 virtual MediaType type() const { return MEDIA_TYPE_VIDEO; } 360 }; 361 362 class DataContentDescription : public MediaContentDescriptionImpl<DataCodec> { 363 public: 364 virtual ContentDescription* Copy() const { 365 return new DataContentDescription(*this); 366 } 367 virtual MediaType type() const { return MEDIA_TYPE_DATA; } 368 }; 369 370 // Creates media session descriptions according to the supplied codecs and 371 // other fields, as well as the supplied per-call options. 372 // When creating answers, performs the appropriate negotiation 373 // of the various fields to determine the proper result. 374 class MediaSessionDescriptionFactory { 375 public: 376 // Default ctor; use methods below to set configuration. 377 // The TransportDescriptionFactory is not owned by MediaSessionDescFactory, 378 // so it must be kept alive by the user of this class. 379 explicit MediaSessionDescriptionFactory( 380 const TransportDescriptionFactory* factory); 381 // This helper automatically sets up the factory to get its configuration 382 // from the specified ChannelManager. 383 MediaSessionDescriptionFactory(ChannelManager* cmanager, 384 const TransportDescriptionFactory* factory); 385 386 const AudioCodecs& audio_codecs() const { return audio_codecs_; } 387 void set_audio_codecs(const AudioCodecs& codecs) { audio_codecs_ = codecs; } 388 void set_audio_rtp_header_extensions(const RtpHeaderExtensions& extensions) { 389 audio_rtp_extensions_ = extensions; 390 } 391 const RtpHeaderExtensions& audio_rtp_header_extensions() const { 392 return audio_rtp_extensions_; 393 } 394 const VideoCodecs& video_codecs() const { return video_codecs_; } 395 void set_video_codecs(const VideoCodecs& codecs) { video_codecs_ = codecs; } 396 void set_video_rtp_header_extensions(const RtpHeaderExtensions& extensions) { 397 video_rtp_extensions_ = extensions; 398 } 399 const RtpHeaderExtensions& video_rtp_header_extensions() const { 400 return video_rtp_extensions_; 401 } 402 const DataCodecs& data_codecs() const { return data_codecs_; } 403 void set_data_codecs(const DataCodecs& codecs) { data_codecs_ = codecs; } 404 SecurePolicy secure() const { return secure_; } 405 void set_secure(SecurePolicy s) { secure_ = s; } 406 // Decides if a StreamParams shall be added to the audio and video media 407 // content in SessionDescription when CreateOffer and CreateAnswer is called 408 // even if |options| don't include a Stream. This is needed to support legacy 409 // applications. |add_legacy_| is true per default. 410 void set_add_legacy_streams(bool add_legacy) { add_legacy_ = add_legacy; } 411 412 SessionDescription* CreateOffer( 413 const MediaSessionOptions& options, 414 const SessionDescription* current_description) const; 415 SessionDescription* CreateAnswer( 416 const SessionDescription* offer, 417 const MediaSessionOptions& options, 418 const SessionDescription* current_description) const; 419 420 private: 421 void GetCodecsToOffer(const SessionDescription* current_description, 422 AudioCodecs* audio_codecs, 423 VideoCodecs* video_codecs, 424 DataCodecs* data_codecs) const; 425 void GetRtpHdrExtsToOffer(const SessionDescription* current_description, 426 RtpHeaderExtensions* audio_extensions, 427 RtpHeaderExtensions* video_extensions) const; 428 bool AddTransportOffer( 429 const std::string& content_name, 430 const TransportOptions& transport_options, 431 const SessionDescription* current_desc, 432 SessionDescription* offer) const; 433 434 TransportDescription* CreateTransportAnswer( 435 const std::string& content_name, 436 const SessionDescription* offer_desc, 437 const TransportOptions& transport_options, 438 const SessionDescription* current_desc) const; 439 440 bool AddTransportAnswer( 441 const std::string& content_name, 442 const TransportDescription& transport_desc, 443 SessionDescription* answer_desc) const; 444 445 AudioCodecs audio_codecs_; 446 RtpHeaderExtensions audio_rtp_extensions_; 447 VideoCodecs video_codecs_; 448 RtpHeaderExtensions video_rtp_extensions_; 449 DataCodecs data_codecs_; 450 SecurePolicy secure_; 451 bool add_legacy_; 452 std::string lang_; 453 const TransportDescriptionFactory* transport_desc_factory_; 454 }; 455 456 // Convenience functions. 457 bool IsMediaContent(const ContentInfo* content); 458 bool IsAudioContent(const ContentInfo* content); 459 bool IsVideoContent(const ContentInfo* content); 460 bool IsDataContent(const ContentInfo* content); 461 const ContentInfo* GetFirstAudioContent(const ContentInfos& contents); 462 const ContentInfo* GetFirstVideoContent(const ContentInfos& contents); 463 const ContentInfo* GetFirstDataContent(const ContentInfos& contents); 464 const ContentInfo* GetFirstAudioContent(const SessionDescription* sdesc); 465 const ContentInfo* GetFirstVideoContent(const SessionDescription* sdesc); 466 const ContentInfo* GetFirstDataContent(const SessionDescription* sdesc); 467 const AudioContentDescription* GetFirstAudioContentDescription( 468 const SessionDescription* sdesc); 469 const VideoContentDescription* GetFirstVideoContentDescription( 470 const SessionDescription* sdesc); 471 const DataContentDescription* GetFirstDataContentDescription( 472 const SessionDescription* sdesc); 473 bool GetStreamBySsrc( 474 const SessionDescription* sdesc, MediaType media_type, 475 uint32 ssrc, StreamParams* stream_out); 476 bool GetStreamByIds( 477 const SessionDescription* sdesc, MediaType media_type, 478 const std::string& groupid, const std::string& id, 479 StreamParams* stream_out); 480 481 // Functions for translating media candidate names. 482 483 // For converting between media ICE component and G-ICE channel 484 // names. For example: 485 // "rtp" <=> 1 486 // "rtcp" <=> 2 487 // "video_rtp" <=> 1 488 // "video_rtcp" <=> 2 489 // Will not convert in the general case of arbitrary channel names, 490 // but is useful for cases where we have candidates for media 491 // channels. 492 // returns false if there is no mapping. 493 bool GetMediaChannelNameFromComponent( 494 int component, cricket::MediaType media_type, std::string* channel_name); 495 bool GetMediaComponentFromChannelName( 496 const std::string& channel_name, int* component); 497 bool GetMediaTypeFromChannelName( 498 const std::string& channel_name, cricket::MediaType* media_type); 499 500 void GetSupportedAudioCryptoSuites(std::vector<std::string>* crypto_suites); 501 void GetSupportedVideoCryptoSuites(std::vector<std::string>* crypto_suites); 502 void GetSupportedDataCryptoSuites(std::vector<std::string>* crypto_suites); 503 void GetSupportedDefaultCryptoSuites(std::vector<std::string>* crypto_suites); 504 } // namespace cricket 505 506 #endif // TALK_SESSION_MEDIA_MEDIASESSION_H_ 507