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