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