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