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 <algorithm>
     34 #include <string>
     35 #include <vector>
     36 
     37 #include "talk/media/base/codec.h"
     38 #include "talk/media/base/constants.h"
     39 #include "talk/media/base/cryptoparams.h"
     40 #include "talk/media/base/mediachannel.h"
     41 #include "talk/media/base/mediaengine.h"  // For DataChannelType
     42 #include "talk/media/base/streamparams.h"
     43 #include "talk/p2p/base/sessiondescription.h"
     44 #include "talk/p2p/base/transport.h"
     45 #include "talk/p2p/base/transportdescriptionfactory.h"
     46 #include "webrtc/base/scoped_ptr.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   // Helpers for adding media contents to the SessionDescription. Returns true
    464   // it succeeds or the media content is not needed, or false if there is any
    465   // error.
    466 
    467   bool AddAudioContentForOffer(
    468       const MediaSessionOptions& options,
    469       const SessionDescription* current_description,
    470       const RtpHeaderExtensions& audio_rtp_extensions,
    471       const AudioCodecs& audio_codecs,
    472       StreamParamsVec* current_streams,
    473       SessionDescription* desc) const;
    474 
    475   bool AddVideoContentForOffer(
    476       const MediaSessionOptions& options,
    477       const SessionDescription* current_description,
    478       const RtpHeaderExtensions& video_rtp_extensions,
    479       const VideoCodecs& video_codecs,
    480       StreamParamsVec* current_streams,
    481       SessionDescription* desc) const;
    482 
    483   bool AddDataContentForOffer(
    484       const MediaSessionOptions& options,
    485       const SessionDescription* current_description,
    486       DataCodecs* data_codecs,
    487       StreamParamsVec* current_streams,
    488       SessionDescription* desc) const;
    489 
    490   bool AddAudioContentForAnswer(
    491       const SessionDescription* offer,
    492       const MediaSessionOptions& options,
    493       const SessionDescription* current_description,
    494       StreamParamsVec* current_streams,
    495       SessionDescription* answer) const;
    496 
    497   bool AddVideoContentForAnswer(
    498       const SessionDescription* offer,
    499       const MediaSessionOptions& options,
    500       const SessionDescription* current_description,
    501       StreamParamsVec* current_streams,
    502       SessionDescription* answer) const;
    503 
    504   bool AddDataContentForAnswer(
    505       const SessionDescription* offer,
    506       const MediaSessionOptions& options,
    507       const SessionDescription* current_description,
    508       StreamParamsVec* current_streams,
    509       SessionDescription* answer) const;
    510 
    511   AudioCodecs audio_codecs_;
    512   RtpHeaderExtensions audio_rtp_extensions_;
    513   VideoCodecs video_codecs_;
    514   RtpHeaderExtensions video_rtp_extensions_;
    515   DataCodecs data_codecs_;
    516   SecurePolicy secure_;
    517   bool add_legacy_;
    518   std::string lang_;
    519   const TransportDescriptionFactory* transport_desc_factory_;
    520 };
    521 
    522 // Convenience functions.
    523 bool IsMediaContent(const ContentInfo* content);
    524 bool IsAudioContent(const ContentInfo* content);
    525 bool IsVideoContent(const ContentInfo* content);
    526 bool IsDataContent(const ContentInfo* content);
    527 const ContentInfo* GetFirstAudioContent(const ContentInfos& contents);
    528 const ContentInfo* GetFirstVideoContent(const ContentInfos& contents);
    529 const ContentInfo* GetFirstDataContent(const ContentInfos& contents);
    530 const ContentInfo* GetFirstAudioContent(const SessionDescription* sdesc);
    531 const ContentInfo* GetFirstVideoContent(const SessionDescription* sdesc);
    532 const ContentInfo* GetFirstDataContent(const SessionDescription* sdesc);
    533 const AudioContentDescription* GetFirstAudioContentDescription(
    534     const SessionDescription* sdesc);
    535 const VideoContentDescription* GetFirstVideoContentDescription(
    536     const SessionDescription* sdesc);
    537 const DataContentDescription* GetFirstDataContentDescription(
    538     const SessionDescription* sdesc);
    539 bool GetStreamBySsrc(
    540     const SessionDescription* sdesc, MediaType media_type,
    541     uint32 ssrc, StreamParams* stream_out);
    542 bool GetStreamByIds(
    543     const SessionDescription* sdesc, MediaType media_type,
    544     const std::string& groupid, const std::string& id,
    545     StreamParams* stream_out);
    546 
    547 // Functions for translating media candidate names.
    548 
    549 // For converting between media ICE component and G-ICE channel
    550 // names.  For example:
    551 // "rtp" <=> 1
    552 // "rtcp" <=> 2
    553 // "video_rtp" <=> 1
    554 // "video_rtcp" <=> 2
    555 // Will not convert in the general case of arbitrary channel names,
    556 // but is useful for cases where we have candidates for media
    557 // channels.
    558 // returns false if there is no mapping.
    559 bool GetMediaChannelNameFromComponent(
    560     int component, cricket::MediaType media_type, std::string* channel_name);
    561 bool GetMediaComponentFromChannelName(
    562     const std::string& channel_name, int* component);
    563 bool GetMediaTypeFromChannelName(
    564     const std::string& channel_name, cricket::MediaType* media_type);
    565 
    566 void GetSupportedAudioCryptoSuites(std::vector<std::string>* crypto_suites);
    567 void GetSupportedVideoCryptoSuites(std::vector<std::string>* crypto_suites);
    568 void GetSupportedDataCryptoSuites(std::vector<std::string>* crypto_suites);
    569 void GetSupportedDefaultCryptoSuites(std::vector<std::string>* crypto_suites);
    570 }  // namespace cricket
    571 
    572 #endif  // TALK_SESSION_MEDIA_MEDIASESSION_H_
    573