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 
     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