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 {
MediaSessionOptionsMediaSessionOptions97   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 
has_audioMediaSessionOptions109   bool has_audio() const {
110     return recv_audio || HasSendMediaStream(MEDIA_TYPE_AUDIO);
111   }
has_videoMediaSessionOptions112   bool has_video() const {
113     return recv_video || HasSendMediaStream(MEDIA_TYPE_VIDEO);
114   }
has_dataMediaSessionOptions115   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 {
StreamMediaSessionOptions::Stream156     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:
MediaContentDescription()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.
protocol()183   std::string protocol() const { return protocol_; }
set_protocol(const std::string & protocol)184   void set_protocol(const std::string& protocol) { protocol_ = protocol; }
185 
direction()186   MediaContentDirection direction() const { return direction_; }
set_direction(MediaContentDirection direction)187   void set_direction(MediaContentDirection direction) {
188     direction_ = direction;
189   }
190 
rtcp_mux()191   bool rtcp_mux() const { return rtcp_mux_; }
set_rtcp_mux(bool mux)192   void set_rtcp_mux(bool mux) { rtcp_mux_ = mux; }
193 
rtcp_reduced_size()194   bool rtcp_reduced_size() const { return rtcp_reduced_size_; }
set_rtcp_reduced_size(bool reduced_size)195   void set_rtcp_reduced_size(bool reduced_size) {
196     rtcp_reduced_size_ = reduced_size;
197   }
198 
bandwidth()199   int bandwidth() const { return bandwidth_; }
set_bandwidth(int bandwidth)200   void set_bandwidth(int bandwidth) { bandwidth_ = bandwidth; }
201 
cryptos()202   const std::vector<CryptoParams>& cryptos() const { return cryptos_; }
AddCrypto(const CryptoParams & params)203   void AddCrypto(const CryptoParams& params) {
204     cryptos_.push_back(params);
205   }
set_cryptos(const std::vector<CryptoParams> & cryptos)206   void set_cryptos(const std::vector<CryptoParams>& cryptos) {
207     cryptos_ = cryptos;
208   }
209 
crypto_required()210   CryptoType crypto_required() const { return crypto_required_; }
set_crypto_required(CryptoType type)211   void set_crypto_required(CryptoType type) {
212     crypto_required_ = type;
213   }
214 
rtp_header_extensions()215   const RtpHeaderExtensions& rtp_header_extensions() const {
216     return rtp_header_extensions_;
217   }
set_rtp_header_extensions(const RtpHeaderExtensions & extensions)218   void set_rtp_header_extensions(const RtpHeaderExtensions& extensions) {
219     rtp_header_extensions_ = extensions;
220     rtp_header_extensions_set_ = true;
221   }
AddRtpHeaderExtension(const RtpHeaderExtension & ext)222   void AddRtpHeaderExtension(const RtpHeaderExtension& ext) {
223     rtp_header_extensions_.push_back(ext);
224     rtp_header_extensions_set_ = true;
225   }
ClearRtpHeaderExtensions()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).
rtp_header_extensions_set()235   bool rtp_header_extensions_set() const {
236     return rtp_header_extensions_set_;
237   }
238   // True iff the client supports multiple streams.
set_multistream(bool multistream)239   void set_multistream(bool multistream) { multistream_ = multistream; }
multistream()240   bool multistream() const { return multistream_; }
streams()241   const StreamParamsVec& streams() const {
242     return streams_;
243   }
244   // TODO(pthatcher): Remove this by giving mediamessage.cc access
245   // to MediaContentDescription
mutable_streams()246   StreamParamsVec& mutable_streams() {
247     return streams_;
248   }
AddStream(const StreamParams & stream)249   void AddStream(const StreamParams& stream) {
250     streams_.push_back(stream);
251   }
252   // Legacy streams have an ssrc, but nothing else.
AddLegacyStream(uint32_t ssrc)253   void AddLegacyStream(uint32_t ssrc) {
254     streams_.push_back(StreamParams::CreateLegacy(ssrc));
255   }
AddLegacyStream(uint32_t ssrc,uint32_t fid_ssrc)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.
SetCnameIfEmpty(const std::string & cname)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   }
first_ssrc()270   uint32_t first_ssrc() const {
271     if (streams_.empty()) {
272       return 0;
273     }
274     return streams_[0].first_ssrc();
275   }
has_ssrcs()276   bool has_ssrcs() const {
277     if (streams_.empty()) {
278       return false;
279     }
280     return streams_[0].has_ssrcs();
281   }
282 
set_conference_mode(bool enable)283   void set_conference_mode(bool enable) { conference_mode_ = enable; }
conference_mode()284   bool conference_mode() const { return conference_mode_; }
285 
set_partial(bool partial)286   void set_partial(bool partial) { partial_ = partial; }
partial()287   bool partial() const { return partial_;  }
288 
set_buffered_mode_latency(int latency)289   void set_buffered_mode_latency(int latency) {
290     buffered_mode_latency_ = latency;
291   }
buffered_mode_latency()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 {
operatorPreferenceSort315     bool operator()(C a, C b) { return a.preference > b.preference; }
316   };
317 
codecs()318   const std::vector<C>& codecs() const { return codecs_; }
set_codecs(const std::vector<C> & codecs)319   void set_codecs(const std::vector<C>& codecs) { codecs_ = codecs; }
has_codecs()320   virtual bool has_codecs() const { return !codecs_.empty(); }
HasCodec(int id)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   }
AddCodec(const C & codec)332   void AddCodec(const C& codec) {
333     codecs_.push_back(codec);
334   }
AddOrReplaceCodec(const C & codec)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   }
AddCodecs(const std::vector<C> & codecs)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   }
SortCodecs()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:
AudioContentDescription()361   AudioContentDescription() :
362       agc_minus_10db_(false) {}
363 
Copy()364   virtual ContentDescription* Copy() const {
365     return new AudioContentDescription(*this);
366   }
type()367   virtual MediaType type() const { return MEDIA_TYPE_AUDIO; }
368 
lang()369   const std::string &lang() const { return lang_; }
set_lang(const std::string & lang)370   void set_lang(const std::string &lang) { lang_ = lang; }
371 
agc_minus_10db()372   bool agc_minus_10db() const { return agc_minus_10db_; }
set_agc_minus_10db(bool enable)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:
Copy()386   virtual ContentDescription* Copy() const {
387     return new VideoContentDescription(*this);
388   }
type()389   virtual MediaType type() const { return MEDIA_TYPE_VIDEO; }
390 };
391 
392 class DataContentDescription : public MediaContentDescriptionImpl<DataCodec> {
393  public:
Copy()394   virtual ContentDescription* Copy() const {
395     return new DataContentDescription(*this);
396   }
type()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 
audio_codecs()416   const AudioCodecs& audio_codecs() const { return audio_codecs_; }
set_audio_codecs(const AudioCodecs & codecs)417   void set_audio_codecs(const AudioCodecs& codecs) { audio_codecs_ = codecs; }
set_audio_rtp_header_extensions(const RtpHeaderExtensions & extensions)418   void set_audio_rtp_header_extensions(const RtpHeaderExtensions& extensions) {
419     audio_rtp_extensions_ = extensions;
420   }
audio_rtp_header_extensions()421   const RtpHeaderExtensions& audio_rtp_header_extensions() const {
422     return audio_rtp_extensions_;
423   }
video_codecs()424   const VideoCodecs& video_codecs() const { return video_codecs_; }
set_video_codecs(const VideoCodecs & codecs)425   void set_video_codecs(const VideoCodecs& codecs) { video_codecs_ = codecs; }
set_video_rtp_header_extensions(const RtpHeaderExtensions & extensions)426   void set_video_rtp_header_extensions(const RtpHeaderExtensions& extensions) {
427     video_rtp_extensions_ = extensions;
428   }
video_rtp_header_extensions()429   const RtpHeaderExtensions& video_rtp_header_extensions() const {
430     return video_rtp_extensions_;
431   }
data_codecs()432   const DataCodecs& data_codecs() const { return data_codecs_; }
set_data_codecs(const DataCodecs & codecs)433   void set_data_codecs(const DataCodecs& codecs) { data_codecs_ = codecs; }
secure()434   SecurePolicy secure() const { return secure_; }
set_secure(SecurePolicy s)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.
set_add_legacy_streams(bool add_legacy)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