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 #ifndef TALK_MEDIA_BASE_CODEC_H_
29 #define TALK_MEDIA_BASE_CODEC_H_
30 
31 #include <map>
32 #include <set>
33 #include <string>
34 #include <vector>
35 
36 #include "talk/media/base/constants.h"
37 
38 namespace cricket {
39 
40 typedef std::map<std::string, std::string> CodecParameterMap;
41 
42 extern const int kMaxPayloadId;
43 
44 class FeedbackParam {
45  public:
FeedbackParam(const std::string & id,const std::string & param)46   FeedbackParam(const std::string& id, const std::string& param)
47       : id_(id),
48         param_(param) {
49   }
FeedbackParam(const std::string & id)50   explicit FeedbackParam(const std::string& id)
51       : id_(id),
52         param_(kParamValueEmpty) {
53   }
54   bool operator==(const FeedbackParam& other) const;
55 
id()56   const std::string& id() const { return id_; }
param()57   const std::string& param() const { return param_; }
58 
59  private:
60   std::string id_;  // e.g. "nack", "ccm"
61   std::string param_;  // e.g. "", "rpsi", "fir"
62 };
63 
64 class FeedbackParams {
65  public:
66   bool operator==(const FeedbackParams& other) const;
67 
68   bool Has(const FeedbackParam& param) const;
69   void Add(const FeedbackParam& param);
70 
71   void Intersect(const FeedbackParams& from);
72 
params()73   const std::vector<FeedbackParam>& params() const { return params_; }
74  private:
75   bool HasDuplicateEntries() const;
76 
77   std::vector<FeedbackParam> params_;
78 };
79 
80 struct Codec {
81   int id;
82   std::string name;
83   int clockrate;
84   int preference;
85   CodecParameterMap params;
86   FeedbackParams feedback_params;
87 
88   // Creates a codec with the given parameters.
89   Codec(int id, const std::string& name, int clockrate, int preference);
90   // Creates an empty codec.
91   Codec();
92   Codec(const Codec& c);
93   ~Codec();
94 
95   // Indicates if this codec is compatible with the specified codec.
96   bool Matches(const Codec& codec) const;
97 
98   // Find the parameter for |name| and write the value to |out|.
99   bool GetParam(const std::string& name, std::string* out) const;
100   bool GetParam(const std::string& name, int* out) const;
101 
102   void SetParam(const std::string& name, const std::string& value);
103   void SetParam(const std::string& name, int value);
104 
105   // It is safe to input a non-existent parameter.
106   // Returns true if the parameter existed, false if it did not exist.
107   bool RemoveParam(const std::string& name);
108 
109   bool HasFeedbackParam(const FeedbackParam& param) const;
110   void AddFeedbackParam(const FeedbackParam& param);
111 
PreferableCodec112   static bool Preferable(const Codec& first, const Codec& other) {
113     return first.preference > other.preference;
114   }
115 
116   // Filter |this| feedbacks params such that only those shared by both |this|
117   // and |other| are kept.
118   void IntersectFeedbackParams(const Codec& other);
119 
120   Codec& operator=(const Codec& c);
121 
122   bool operator==(const Codec& c) const;
123 
124   bool operator!=(const Codec& c) const {
125     return !(*this == c);
126   }
127 };
128 
129 struct AudioCodec : public Codec {
130   int bitrate;
131   size_t channels;
132 
133   // Creates a codec with the given parameters.
134   AudioCodec(int id,
135              const std::string& name,
136              int clockrate,
137              int bitrate,
138              size_t channels,
139              int preference);
140   // Creates an empty codec.
141   AudioCodec();
142   AudioCodec(const AudioCodec& c);
143   ~AudioCodec() = default;
144 
145   // Indicates if this codec is compatible with the specified codec.
146   bool Matches(const AudioCodec& codec) const;
147 
PreferableAudioCodec148   static bool Preferable(const AudioCodec& first, const AudioCodec& other) {
149     return first.preference > other.preference;
150   }
151 
152   std::string ToString() const;
153 
154   AudioCodec& operator=(const AudioCodec& c);
155 
156   bool operator==(const AudioCodec& c) const;
157 
158   bool operator!=(const AudioCodec& c) const {
159     return !(*this == c);
160   }
161 };
162 
163 struct VideoCodec : public Codec {
164   int width;
165   int height;
166   int framerate;
167 
168   // Creates a codec with the given parameters.
169   VideoCodec(int id,
170              const std::string& name,
171              int width,
172              int height,
173              int framerate,
174              int preference);
175   VideoCodec(int id, const std::string& name);
176   // Creates an empty codec.
177   VideoCodec();
178   VideoCodec(const VideoCodec& c);
179   ~VideoCodec() = default;
180 
PreferableVideoCodec181   static bool Preferable(const VideoCodec& first, const VideoCodec& other) {
182     return first.preference > other.preference;
183   }
184 
185   std::string ToString() const;
186 
187   VideoCodec& operator=(const VideoCodec& c);
188 
189   bool operator==(const VideoCodec& c) const;
190 
191   bool operator!=(const VideoCodec& c) const {
192     return !(*this == c);
193   }
194 
195   static VideoCodec CreateRtxCodec(int rtx_payload_type,
196                                    int associated_payload_type);
197 
198   enum CodecType {
199     CODEC_VIDEO,
200     CODEC_RED,
201     CODEC_ULPFEC,
202     CODEC_RTX,
203   };
204 
205   CodecType GetCodecType() const;
206   // Validates a VideoCodec's payload type, dimensions and bitrates etc. If they
207   // don't make sense (such as max < min bitrate), and error is logged and
208   // ValidateCodecFormat returns false.
209   bool ValidateCodecFormat() const;
210 };
211 
212 struct DataCodec : public Codec {
213   DataCodec(int id, const std::string& name, int preference);
214   DataCodec();
215   DataCodec(const DataCodec& c);
216 
217   DataCodec& operator=(const DataCodec& c);
218 
219   std::string ToString() const;
220 };
221 
222 // Get the codec setting associated with |payload_type|. If there
223 // is no codec associated with that payload type it returns false.
224 template <class Codec>
FindCodecById(const std::vector<Codec> & codecs,int payload_type,Codec * codec_out)225 bool FindCodecById(const std::vector<Codec>& codecs,
226                    int payload_type,
227                    Codec* codec_out) {
228   for (const auto& codec : codecs) {
229     if (codec.id == payload_type) {
230       *codec_out = codec;
231       return true;
232     }
233   }
234   return false;
235 }
236 
237 bool CodecNamesEq(const std::string& name1, const std::string& name2);
238 bool HasNack(const VideoCodec& codec);
239 bool HasRemb(const VideoCodec& codec);
240 bool HasTransportCc(const VideoCodec& codec);
241 
242 }  // namespace cricket
243 
244 #endif  // TALK_MEDIA_BASE_CODEC_H_
245