1 /*
2  *  Copyright 2004 The WebRTC project authors. All Rights Reserved.
3  *
4  *  Use of this source code is governed by a BSD-style license
5  *  that can be found in the LICENSE file in the root of the source
6  *  tree. An additional intellectual property rights grant can be found
7  *  in the file PATENTS.  All contributing project authors may
8  *  be found in the AUTHORS file in the root of the source tree.
9  */
10 
11 // Types and classes used in media session descriptions.
12 
13 #ifndef WEBRTC_PC_MEDIASESSION_H_
14 #define WEBRTC_PC_MEDIASESSION_H_
15 
16 #include <algorithm>
17 #include <map>
18 #include <string>
19 #include <vector>
20 
21 #include "webrtc/media/base/codec.h"
22 #include "webrtc/media/base/cryptoparams.h"
23 #include "webrtc/media/base/mediachannel.h"
24 #include "webrtc/media/base/mediaconstants.h"
25 #include "webrtc/media/base/mediaengine.h"  // For DataChannelType
26 #include "webrtc/media/base/streamparams.h"
27 #include "webrtc/p2p/base/sessiondescription.h"
28 #include "webrtc/p2p/base/jseptransport.h"
29 #include "webrtc/p2p/base/transportdescriptionfactory.h"
30 
31 namespace cricket {
32 
33 class ChannelManager;
34 typedef std::vector<AudioCodec> AudioCodecs;
35 typedef std::vector<VideoCodec> VideoCodecs;
36 typedef std::vector<DataCodec> DataCodecs;
37 typedef std::vector<CryptoParams> CryptoParamsVec;
38 typedef std::vector<webrtc::RtpExtension> RtpHeaderExtensions;
39 
40 enum MediaType {
41   MEDIA_TYPE_AUDIO,
42   MEDIA_TYPE_VIDEO,
43   MEDIA_TYPE_DATA
44 };
45 
46 std::string MediaTypeToString(MediaType type);
47 
48 enum MediaContentDirection {
49   MD_INACTIVE,
50   MD_SENDONLY,
51   MD_RECVONLY,
52   MD_SENDRECV
53 };
54 
55 std::string MediaContentDirectionToString(MediaContentDirection direction);
56 
57 enum CryptoType {
58   CT_NONE,
59   CT_SDES,
60   CT_DTLS
61 };
62 
63 // RTC4585 RTP/AVPF
64 extern const char kMediaProtocolAvpf[];
65 // RFC5124 RTP/SAVPF
66 extern const char kMediaProtocolSavpf[];
67 
68 extern const char kMediaProtocolDtlsSavpf[];
69 
70 extern const char kMediaProtocolRtpPrefix[];
71 
72 extern const char kMediaProtocolSctp[];
73 extern const char kMediaProtocolDtlsSctp[];
74 extern const char kMediaProtocolUdpDtlsSctp[];
75 extern const char kMediaProtocolTcpDtlsSctp[];
76 
77 // Options to control how session descriptions are generated.
78 const int kAutoBandwidth = -1;
79 const int kBufferedModeDisabled = 0;
80 
81 // Default RTCP CNAME for unit tests.
82 const char kDefaultRtcpCname[] = "DefaultRtcpCname";
83 
84 struct RtpTransceiverDirection {
85   bool send;
86   bool recv;
87 
RtpTransceiverDirectionRtpTransceiverDirection88   RtpTransceiverDirection(bool send, bool recv) : send(send), recv(recv) {}
89 
90   bool operator==(const RtpTransceiverDirection& o) const {
91     return send == o.send && recv == o.recv;
92   }
93 
94   bool operator!=(const RtpTransceiverDirection& o) const {
95     return !(*this == o);
96   }
97 
98   static RtpTransceiverDirection FromMediaContentDirection(
99       MediaContentDirection md);
100 
101   MediaContentDirection ToMediaContentDirection() const;
102 };
103 
104 RtpTransceiverDirection
105 NegotiateRtpTransceiverDirection(RtpTransceiverDirection offer,
106                                  RtpTransceiverDirection wants);
107 
108 struct MediaSessionOptions {
MediaSessionOptionsMediaSessionOptions109   MediaSessionOptions()
110       : recv_audio(true),
111         recv_video(false),
112         data_channel_type(DCT_NONE),
113         is_muc(false),
114         vad_enabled(true),  // When disabled, removes all CN codecs from SDP.
115         rtcp_mux_enabled(true),
116         bundle_enabled(false),
117         video_bandwidth(kAutoBandwidth),
118         data_bandwidth(kDataMaxBandwidth),
119         rtcp_cname(kDefaultRtcpCname) {}
120 
has_audioMediaSessionOptions121   bool has_audio() const {
122     return recv_audio || HasSendMediaStream(MEDIA_TYPE_AUDIO);
123   }
has_videoMediaSessionOptions124   bool has_video() const {
125     return recv_video || HasSendMediaStream(MEDIA_TYPE_VIDEO);
126   }
has_dataMediaSessionOptions127   bool has_data() const { return data_channel_type != DCT_NONE; }
128 
129   // Add a stream with MediaType type and id.
130   // All streams with the same sync_label will get the same CNAME.
131   // All ids must be unique.
132   void AddSendStream(MediaType type,
133                  const std::string& id,
134                  const std::string& sync_label);
135   void AddSendVideoStream(const std::string& id,
136                       const std::string& sync_label,
137                       int num_sim_layers);
138   void RemoveSendStream(MediaType type, const std::string& id);
139 
140 
141   // Helper function.
142   void AddSendStreamInternal(MediaType type,
143                          const std::string& id,
144                          const std::string& sync_label,
145                          int num_sim_layers);
146 
147   bool HasSendMediaStream(MediaType type) const;
148 
149   // TODO(deadbeef): Put all the audio/video/data-specific options into a map
150   // structure (content name -> options).
151   // MediaSessionDescriptionFactory assumes there will never be more than one
152   // audio/video/data content, but this will change with unified plan.
153   bool recv_audio;
154   bool recv_video;
155   DataChannelType data_channel_type;
156   bool is_muc;
157   bool vad_enabled;
158   bool rtcp_mux_enabled;
159   bool bundle_enabled;
160   // bps. -1 == auto.
161   int video_bandwidth;
162   int data_bandwidth;
163   bool enable_ice_renomination = false;
164   // content name ("mid") => options.
165   std::map<std::string, TransportOptions> transport_options;
166   std::string rtcp_cname;
167   rtc::CryptoOptions crypto_options;
168 
169   struct Stream {
StreamMediaSessionOptions::Stream170     Stream(MediaType type,
171            const std::string& id,
172            const std::string& sync_label,
173            int num_sim_layers)
174         : type(type), id(id), sync_label(sync_label),
175           num_sim_layers(num_sim_layers) {
176     }
177     MediaType type;
178     std::string id;
179     std::string sync_label;
180     int num_sim_layers;
181   };
182 
183   typedef std::vector<Stream> Streams;
184   Streams streams;
185 };
186 
187 // "content" (as used in XEP-0166) descriptions for voice and video.
188 class MediaContentDescription : public ContentDescription {
189  public:
MediaContentDescription()190   MediaContentDescription() {}
191 
192   virtual MediaType type() const = 0;
193   virtual bool has_codecs() const = 0;
194 
195   // |protocol| is the expected media transport protocol, such as RTP/AVPF,
196   // RTP/SAVPF or SCTP/DTLS.
protocol()197   std::string protocol() const { return protocol_; }
set_protocol(const std::string & protocol)198   void set_protocol(const std::string& protocol) { protocol_ = protocol; }
199 
direction()200   MediaContentDirection direction() const { return direction_; }
set_direction(MediaContentDirection direction)201   void set_direction(MediaContentDirection direction) {
202     direction_ = direction;
203   }
204 
rtcp_mux()205   bool rtcp_mux() const { return rtcp_mux_; }
set_rtcp_mux(bool mux)206   void set_rtcp_mux(bool mux) { rtcp_mux_ = mux; }
207 
rtcp_reduced_size()208   bool rtcp_reduced_size() const { return rtcp_reduced_size_; }
set_rtcp_reduced_size(bool reduced_size)209   void set_rtcp_reduced_size(bool reduced_size) {
210     rtcp_reduced_size_ = reduced_size;
211   }
212 
bandwidth()213   int bandwidth() const { return bandwidth_; }
set_bandwidth(int bandwidth)214   void set_bandwidth(int bandwidth) { bandwidth_ = bandwidth; }
215 
cryptos()216   const std::vector<CryptoParams>& cryptos() const { return cryptos_; }
AddCrypto(const CryptoParams & params)217   void AddCrypto(const CryptoParams& params) {
218     cryptos_.push_back(params);
219   }
set_cryptos(const std::vector<CryptoParams> & cryptos)220   void set_cryptos(const std::vector<CryptoParams>& cryptos) {
221     cryptos_ = cryptos;
222   }
223 
crypto_required()224   CryptoType crypto_required() const { return crypto_required_; }
set_crypto_required(CryptoType type)225   void set_crypto_required(CryptoType type) {
226     crypto_required_ = type;
227   }
228 
rtp_header_extensions()229   const RtpHeaderExtensions& rtp_header_extensions() const {
230     return rtp_header_extensions_;
231   }
set_rtp_header_extensions(const RtpHeaderExtensions & extensions)232   void set_rtp_header_extensions(const RtpHeaderExtensions& extensions) {
233     rtp_header_extensions_ = extensions;
234     rtp_header_extensions_set_ = true;
235   }
AddRtpHeaderExtension(const webrtc::RtpExtension & ext)236   void AddRtpHeaderExtension(const webrtc::RtpExtension& ext) {
237     rtp_header_extensions_.push_back(ext);
238     rtp_header_extensions_set_ = true;
239   }
AddRtpHeaderExtension(const cricket::RtpHeaderExtension & ext)240   void AddRtpHeaderExtension(const cricket::RtpHeaderExtension& ext) {
241     webrtc::RtpExtension webrtc_extension;
242     webrtc_extension.uri = ext.uri;
243     webrtc_extension.id = ext.id;
244     rtp_header_extensions_.push_back(webrtc_extension);
245     rtp_header_extensions_set_ = true;
246   }
ClearRtpHeaderExtensions()247   void ClearRtpHeaderExtensions() {
248     rtp_header_extensions_.clear();
249     rtp_header_extensions_set_ = true;
250   }
251   // We can't always tell if an empty list of header extensions is
252   // because the other side doesn't support them, or just isn't hooked up to
253   // signal them. For now we assume an empty list means no signaling, but
254   // provide the ClearRtpHeaderExtensions method to allow "no support" to be
255   // clearly indicated (i.e. when derived from other information).
rtp_header_extensions_set()256   bool rtp_header_extensions_set() const {
257     return rtp_header_extensions_set_;
258   }
259   // True iff the client supports multiple streams.
set_multistream(bool multistream)260   void set_multistream(bool multistream) { multistream_ = multistream; }
multistream()261   bool multistream() const { return multistream_; }
streams()262   const StreamParamsVec& streams() const {
263     return streams_;
264   }
265   // TODO(pthatcher): Remove this by giving mediamessage.cc access
266   // to MediaContentDescription
mutable_streams()267   StreamParamsVec& mutable_streams() {
268     return streams_;
269   }
AddStream(const StreamParams & stream)270   void AddStream(const StreamParams& stream) {
271     streams_.push_back(stream);
272   }
273   // Legacy streams have an ssrc, but nothing else.
AddLegacyStream(uint32_t ssrc)274   void AddLegacyStream(uint32_t ssrc) {
275     streams_.push_back(StreamParams::CreateLegacy(ssrc));
276   }
AddLegacyStream(uint32_t ssrc,uint32_t fid_ssrc)277   void AddLegacyStream(uint32_t ssrc, uint32_t fid_ssrc) {
278     StreamParams sp = StreamParams::CreateLegacy(ssrc);
279     sp.AddFidSsrc(ssrc, fid_ssrc);
280     streams_.push_back(sp);
281   }
282   // Sets the CNAME of all StreamParams if it have not been set.
283   // This can be used to set the CNAME of legacy streams.
SetCnameIfEmpty(const std::string & cname)284   void SetCnameIfEmpty(const std::string& cname) {
285     for (cricket::StreamParamsVec::iterator it = streams_.begin();
286          it != streams_.end(); ++it) {
287       if (it->cname.empty())
288         it->cname = cname;
289     }
290   }
first_ssrc()291   uint32_t first_ssrc() const {
292     if (streams_.empty()) {
293       return 0;
294     }
295     return streams_[0].first_ssrc();
296   }
has_ssrcs()297   bool has_ssrcs() const {
298     if (streams_.empty()) {
299       return false;
300     }
301     return streams_[0].has_ssrcs();
302   }
303 
set_conference_mode(bool enable)304   void set_conference_mode(bool enable) { conference_mode_ = enable; }
conference_mode()305   bool conference_mode() const { return conference_mode_; }
306 
set_partial(bool partial)307   void set_partial(bool partial) { partial_ = partial; }
partial()308   bool partial() const { return partial_;  }
309 
set_buffered_mode_latency(int latency)310   void set_buffered_mode_latency(int latency) {
311     buffered_mode_latency_ = latency;
312   }
buffered_mode_latency()313   int buffered_mode_latency() const { return buffered_mode_latency_; }
314 
315  protected:
316   bool rtcp_mux_ = false;
317   bool rtcp_reduced_size_ = false;
318   int bandwidth_ = kAutoBandwidth;
319   std::string protocol_;
320   std::vector<CryptoParams> cryptos_;
321   CryptoType crypto_required_ = CT_NONE;
322   std::vector<webrtc::RtpExtension> rtp_header_extensions_;
323   bool rtp_header_extensions_set_ = false;
324   bool multistream_ = false;
325   StreamParamsVec streams_;
326   bool conference_mode_ = false;
327   bool partial_ = false;
328   int buffered_mode_latency_ = kBufferedModeDisabled;
329   MediaContentDirection direction_ = MD_SENDRECV;
330 };
331 
332 template <class C>
333 class MediaContentDescriptionImpl : public MediaContentDescription {
334  public:
335   typedef C CodecType;
336 
337   // Codecs should be in preference order (most preferred codec first).
codecs()338   const std::vector<C>& codecs() const { return codecs_; }
set_codecs(const std::vector<C> & codecs)339   void set_codecs(const std::vector<C>& codecs) { codecs_ = codecs; }
has_codecs()340   virtual bool has_codecs() const { return !codecs_.empty(); }
HasCodec(int id)341   bool HasCodec(int id) {
342     bool found = false;
343     for (typename std::vector<C>::iterator iter = codecs_.begin();
344          iter != codecs_.end(); ++iter) {
345       if (iter->id == id) {
346         found = true;
347         break;
348       }
349     }
350     return found;
351   }
AddCodec(const C & codec)352   void AddCodec(const C& codec) {
353     codecs_.push_back(codec);
354   }
AddOrReplaceCodec(const C & codec)355   void AddOrReplaceCodec(const C& codec) {
356     for (typename std::vector<C>::iterator iter = codecs_.begin();
357          iter != codecs_.end(); ++iter) {
358       if (iter->id == codec.id) {
359         *iter = codec;
360         return;
361       }
362     }
363     AddCodec(codec);
364   }
AddCodecs(const std::vector<C> & codecs)365   void AddCodecs(const std::vector<C>& codecs) {
366     typename std::vector<C>::const_iterator codec;
367     for (codec = codecs.begin(); codec != codecs.end(); ++codec) {
368       AddCodec(*codec);
369     }
370   }
371 
372  private:
373   std::vector<C> codecs_;
374 };
375 
376 class AudioContentDescription : public MediaContentDescriptionImpl<AudioCodec> {
377  public:
AudioContentDescription()378   AudioContentDescription() :
379       agc_minus_10db_(false) {}
380 
Copy()381   virtual ContentDescription* Copy() const {
382     return new AudioContentDescription(*this);
383   }
type()384   virtual MediaType type() const { return MEDIA_TYPE_AUDIO; }
385 
lang()386   const std::string &lang() const { return lang_; }
set_lang(const std::string & lang)387   void set_lang(const std::string &lang) { lang_ = lang; }
388 
agc_minus_10db()389   bool agc_minus_10db() const { return agc_minus_10db_; }
set_agc_minus_10db(bool enable)390   void set_agc_minus_10db(bool enable) {
391     agc_minus_10db_ = enable;
392   }
393 
394  private:
395   bool agc_minus_10db_;
396 
397  private:
398   std::string lang_;
399 };
400 
401 class VideoContentDescription : public MediaContentDescriptionImpl<VideoCodec> {
402  public:
Copy()403   virtual ContentDescription* Copy() const {
404     return new VideoContentDescription(*this);
405   }
type()406   virtual MediaType type() const { return MEDIA_TYPE_VIDEO; }
407 };
408 
409 class DataContentDescription : public MediaContentDescriptionImpl<DataCodec> {
410  public:
Copy()411   virtual ContentDescription* Copy() const {
412     return new DataContentDescription(*this);
413   }
type()414   virtual MediaType type() const { return MEDIA_TYPE_DATA; }
415 };
416 
417 // Creates media session descriptions according to the supplied codecs and
418 // other fields, as well as the supplied per-call options.
419 // When creating answers, performs the appropriate negotiation
420 // of the various fields to determine the proper result.
421 class MediaSessionDescriptionFactory {
422  public:
423   // Default ctor; use methods below to set configuration.
424   // The TransportDescriptionFactory is not owned by MediaSessionDescFactory,
425   // so it must be kept alive by the user of this class.
426   explicit MediaSessionDescriptionFactory(
427       const TransportDescriptionFactory* factory);
428   // This helper automatically sets up the factory to get its configuration
429   // from the specified ChannelManager.
430   MediaSessionDescriptionFactory(ChannelManager* cmanager,
431                                  const TransportDescriptionFactory* factory);
432 
433   const AudioCodecs& audio_sendrecv_codecs() const;
434   const AudioCodecs& audio_send_codecs() const;
435   const AudioCodecs& audio_recv_codecs() const;
436   void set_audio_codecs(const AudioCodecs& send_codecs,
437                         const AudioCodecs& recv_codecs);
set_audio_rtp_header_extensions(const RtpHeaderExtensions & extensions)438   void set_audio_rtp_header_extensions(const RtpHeaderExtensions& extensions) {
439     audio_rtp_extensions_ = extensions;
440   }
audio_rtp_header_extensions()441   const RtpHeaderExtensions& audio_rtp_header_extensions() const {
442     return audio_rtp_extensions_;
443   }
video_codecs()444   const VideoCodecs& video_codecs() const { return video_codecs_; }
set_video_codecs(const VideoCodecs & codecs)445   void set_video_codecs(const VideoCodecs& codecs) { video_codecs_ = codecs; }
set_video_rtp_header_extensions(const RtpHeaderExtensions & extensions)446   void set_video_rtp_header_extensions(const RtpHeaderExtensions& extensions) {
447     video_rtp_extensions_ = extensions;
448   }
video_rtp_header_extensions()449   const RtpHeaderExtensions& video_rtp_header_extensions() const {
450     return video_rtp_extensions_;
451   }
data_codecs()452   const DataCodecs& data_codecs() const { return data_codecs_; }
set_data_codecs(const DataCodecs & codecs)453   void set_data_codecs(const DataCodecs& codecs) { data_codecs_ = codecs; }
secure()454   SecurePolicy secure() const { return secure_; }
set_secure(SecurePolicy s)455   void set_secure(SecurePolicy s) { secure_ = s; }
456   // Decides if a StreamParams shall be added to the audio and video media
457   // content in SessionDescription when CreateOffer and CreateAnswer is called
458   // even if |options| don't include a Stream. This is needed to support legacy
459   // applications. |add_legacy_| is true per default.
set_add_legacy_streams(bool add_legacy)460   void set_add_legacy_streams(bool add_legacy) { add_legacy_ = add_legacy; }
461 
462   SessionDescription* CreateOffer(
463       const MediaSessionOptions& options,
464       const SessionDescription* current_description) const;
465   SessionDescription* CreateAnswer(
466         const SessionDescription* offer,
467         const MediaSessionOptions& options,
468         const SessionDescription* current_description) const;
469 
470  private:
471   const AudioCodecs& GetAudioCodecsForOffer(
472       const RtpTransceiverDirection& direction) const;
473   const AudioCodecs& GetAudioCodecsForAnswer(
474       const RtpTransceiverDirection& offer,
475       const RtpTransceiverDirection& answer) const;
476   void GetCodecsToOffer(const SessionDescription* current_description,
477                         const AudioCodecs& supported_audio_codecs,
478                         const VideoCodecs& supported_video_codecs,
479                         const DataCodecs& supported_data_codecs,
480                         AudioCodecs* audio_codecs,
481                         VideoCodecs* video_codecs,
482                         DataCodecs* data_codecs) const;
483   void GetRtpHdrExtsToOffer(const SessionDescription* current_description,
484                             RtpHeaderExtensions* audio_extensions,
485                             RtpHeaderExtensions* video_extensions) const;
486   bool AddTransportOffer(
487       const std::string& content_name,
488       const TransportOptions& transport_options,
489       const SessionDescription* current_desc,
490       SessionDescription* offer) const;
491 
492   TransportDescription* CreateTransportAnswer(
493       const std::string& content_name,
494       const SessionDescription* offer_desc,
495       const TransportOptions& transport_options,
496       const SessionDescription* current_desc) const;
497 
498   bool AddTransportAnswer(
499       const std::string& content_name,
500       const TransportDescription& transport_desc,
501       SessionDescription* answer_desc) const;
502 
503   // Helpers for adding media contents to the SessionDescription. Returns true
504   // it succeeds or the media content is not needed, or false if there is any
505   // error.
506 
507   bool AddAudioContentForOffer(
508       const MediaSessionOptions& options,
509       const SessionDescription* current_description,
510       const RtpHeaderExtensions& audio_rtp_extensions,
511       const AudioCodecs& audio_codecs,
512       StreamParamsVec* current_streams,
513       SessionDescription* desc) const;
514 
515   bool AddVideoContentForOffer(
516       const MediaSessionOptions& options,
517       const SessionDescription* current_description,
518       const RtpHeaderExtensions& video_rtp_extensions,
519       const VideoCodecs& video_codecs,
520       StreamParamsVec* current_streams,
521       SessionDescription* desc) const;
522 
523   bool AddDataContentForOffer(
524       const MediaSessionOptions& options,
525       const SessionDescription* current_description,
526       DataCodecs* data_codecs,
527       StreamParamsVec* current_streams,
528       SessionDescription* desc) const;
529 
530   bool AddAudioContentForAnswer(
531       const SessionDescription* offer,
532       const MediaSessionOptions& options,
533       const SessionDescription* current_description,
534       StreamParamsVec* current_streams,
535       SessionDescription* answer) const;
536 
537   bool AddVideoContentForAnswer(
538       const SessionDescription* offer,
539       const MediaSessionOptions& options,
540       const SessionDescription* current_description,
541       StreamParamsVec* current_streams,
542       SessionDescription* answer) const;
543 
544   bool AddDataContentForAnswer(
545       const SessionDescription* offer,
546       const MediaSessionOptions& options,
547       const SessionDescription* current_description,
548       StreamParamsVec* current_streams,
549       SessionDescription* answer) const;
550 
551   AudioCodecs audio_send_codecs_;
552   AudioCodecs audio_recv_codecs_;
553   AudioCodecs audio_sendrecv_codecs_;
554   RtpHeaderExtensions audio_rtp_extensions_;
555   VideoCodecs video_codecs_;
556   RtpHeaderExtensions video_rtp_extensions_;
557   DataCodecs data_codecs_;
558   SecurePolicy secure_;
559   bool add_legacy_;
560   std::string lang_;
561   const TransportDescriptionFactory* transport_desc_factory_;
562 };
563 
564 // Convenience functions.
565 bool IsMediaContent(const ContentInfo* content);
566 bool IsAudioContent(const ContentInfo* content);
567 bool IsVideoContent(const ContentInfo* content);
568 bool IsDataContent(const ContentInfo* content);
569 const ContentInfo* GetFirstMediaContent(const ContentInfos& contents,
570                                         MediaType media_type);
571 const ContentInfo* GetFirstAudioContent(const ContentInfos& contents);
572 const ContentInfo* GetFirstVideoContent(const ContentInfos& contents);
573 const ContentInfo* GetFirstDataContent(const ContentInfos& contents);
574 const ContentInfo* GetFirstAudioContent(const SessionDescription* sdesc);
575 const ContentInfo* GetFirstVideoContent(const SessionDescription* sdesc);
576 const ContentInfo* GetFirstDataContent(const SessionDescription* sdesc);
577 const AudioContentDescription* GetFirstAudioContentDescription(
578     const SessionDescription* sdesc);
579 const VideoContentDescription* GetFirstVideoContentDescription(
580     const SessionDescription* sdesc);
581 const DataContentDescription* GetFirstDataContentDescription(
582     const SessionDescription* sdesc);
583 // Non-const versions of the above functions.
584 // Useful when modifying an existing description.
585 ContentInfo* GetFirstMediaContent(ContentInfos& contents, MediaType media_type);
586 ContentInfo* GetFirstAudioContent(ContentInfos& contents);
587 ContentInfo* GetFirstVideoContent(ContentInfos& contents);
588 ContentInfo* GetFirstDataContent(ContentInfos& contents);
589 ContentInfo* GetFirstAudioContent(SessionDescription* sdesc);
590 ContentInfo* GetFirstVideoContent(SessionDescription* sdesc);
591 ContentInfo* GetFirstDataContent(SessionDescription* sdesc);
592 AudioContentDescription* GetFirstAudioContentDescription(
593     SessionDescription* sdesc);
594 VideoContentDescription* GetFirstVideoContentDescription(
595     SessionDescription* sdesc);
596 DataContentDescription* GetFirstDataContentDescription(
597     SessionDescription* sdesc);
598 
599 void GetSupportedAudioCryptoSuites(const rtc::CryptoOptions& crypto_options,
600     std::vector<int>* crypto_suites);
601 void GetSupportedVideoCryptoSuites(const rtc::CryptoOptions& crypto_options,
602     std::vector<int>* crypto_suites);
603 void GetSupportedDataCryptoSuites(const rtc::CryptoOptions& crypto_options,
604     std::vector<int>* crypto_suites);
605 void GetDefaultSrtpCryptoSuites(const rtc::CryptoOptions& crypto_options,
606     std::vector<int>* crypto_suites);
607 void GetSupportedAudioCryptoSuiteNames(const rtc::CryptoOptions& crypto_options,
608     std::vector<std::string>* crypto_suite_names);
609 void GetSupportedVideoCryptoSuiteNames(const rtc::CryptoOptions& crypto_options,
610     std::vector<std::string>* crypto_suite_names);
611 void GetSupportedDataCryptoSuiteNames(const rtc::CryptoOptions& crypto_options,
612     std::vector<std::string>* crypto_suite_names);
613 void GetDefaultSrtpCryptoSuiteNames(const rtc::CryptoOptions& crypto_options,
614     std::vector<std::string>* crypto_suite_names);
615 
616 }  // namespace cricket
617 
618 #endif  // WEBRTC_PC_MEDIASESSION_H_
619