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
38namespace cricket {
39
40typedef std::map<std::string, std::string> CodecParameterMap;
41
42extern const int kMaxPayloadId;
43
44class FeedbackParam {
45 public:
46  FeedbackParam(const std::string& id, const std::string& param)
47      : id_(id),
48        param_(param) {
49  }
50  explicit FeedbackParam(const std::string& id)
51      : id_(id),
52        param_(kParamValueEmpty) {
53  }
54  bool operator==(const FeedbackParam& other) const;
55
56  const std::string& id() const { return id_; }
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
64class 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
73  const std::vector<FeedbackParam>& params() const { return params_; }
74 private:
75  bool HasDuplicateEntries() const;
76
77  std::vector<FeedbackParam> params_;
78};
79
80struct 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      : id(id),
91        name(name),
92        clockrate(clockrate),
93        preference(preference) {
94  }
95
96  // Creates an empty codec.
97  Codec() : id(0), clockrate(0), preference(0) {}
98
99  // Indicates if this codec is compatible with the specified codec.
100  bool Matches(const Codec& codec) const;
101
102  // Find the parameter for |name| and write the value to |out|.
103  bool GetParam(const std::string& name, std::string* out) const;
104  bool GetParam(const std::string& name, int* out) const;
105
106  void SetParam(const std::string& name, const std::string& value);
107  void SetParam(const std::string& name, int value);
108
109  // It is safe to input a non-existent parameter.
110  // Returns true if the parameter existed, false if it did not exist.
111  bool RemoveParam(const std::string& name);
112
113  bool HasFeedbackParam(const FeedbackParam& param) const;
114  void AddFeedbackParam(const FeedbackParam& param);
115
116  static bool Preferable(const Codec& first, const Codec& other) {
117    return first.preference > other.preference;
118  }
119
120  // Filter |this| feedbacks params such that only those shared by both |this|
121  // and |other| are kept.
122  void IntersectFeedbackParams(const Codec& other);
123
124  Codec& operator=(const Codec& c) {
125    this->id = c.id;  // id is reserved in objective-c
126    name = c.name;
127    clockrate = c.clockrate;
128    preference = c.preference;
129    params = c.params;
130    feedback_params = c.feedback_params;
131    return *this;
132  }
133
134  bool operator==(const Codec& c) const {
135    return this->id == c.id &&  // id is reserved in objective-c
136        name == c.name &&
137        clockrate == c.clockrate &&
138        preference == c.preference &&
139        params == c.params &&
140        feedback_params == c.feedback_params;
141  }
142
143  bool operator!=(const Codec& c) const {
144    return !(*this == c);
145  }
146};
147
148struct AudioCodec : public Codec {
149  int bitrate;
150  int channels;
151
152  // Creates a codec with the given parameters.
153  AudioCodec(int pt, const std::string& nm, int cr, int br, int cs, int pr)
154      : Codec(pt, nm, cr, pr),
155        bitrate(br),
156        channels(cs) {
157  }
158
159  // Creates an empty codec.
160  AudioCodec() : Codec(), bitrate(0), channels(0) {}
161
162  // Indicates if this codec is compatible with the specified codec.
163  bool Matches(const AudioCodec& codec) const;
164
165  static bool Preferable(const AudioCodec& first, const AudioCodec& other) {
166    return first.preference > other.preference;
167  }
168
169  std::string ToString() const;
170
171  AudioCodec& operator=(const AudioCodec& c) {
172    this->id = c.id;  // id is reserved in objective-c
173    name = c.name;
174    clockrate = c.clockrate;
175    bitrate = c.bitrate;
176    channels = c.channels;
177    preference =  c.preference;
178    params = c.params;
179    feedback_params = c.feedback_params;
180    return *this;
181  }
182
183  bool operator==(const AudioCodec& c) const {
184    return this->id == c.id &&  // id is reserved in objective-c
185           name == c.name &&
186           clockrate == c.clockrate &&
187           bitrate == c.bitrate &&
188           channels == c.channels &&
189           preference == c.preference &&
190           params == c.params &&
191           feedback_params == c.feedback_params;
192  }
193
194  bool operator!=(const AudioCodec& c) const {
195    return !(*this == c);
196  }
197};
198
199struct VideoCodec : public Codec {
200  int width;
201  int height;
202  int framerate;
203
204  // Creates a codec with the given parameters.
205  VideoCodec(int pt, const std::string& nm, int w, int h, int fr, int pr)
206      : Codec(pt, nm, kVideoCodecClockrate, pr),
207        width(w),
208        height(h),
209        framerate(fr) {
210  }
211
212  // Creates an empty codec.
213  VideoCodec()
214      : Codec(),
215        width(0),
216        height(0),
217        framerate(0) {
218    clockrate = kVideoCodecClockrate;
219  }
220
221  static bool Preferable(const VideoCodec& first, const VideoCodec& other) {
222    return first.preference > other.preference;
223  }
224
225  std::string ToString() const;
226
227  VideoCodec& operator=(const VideoCodec& c) {
228    this->id = c.id;  // id is reserved in objective-c
229    name = c.name;
230    clockrate = c.clockrate;
231    width = c.width;
232    height = c.height;
233    framerate = c.framerate;
234    preference =  c.preference;
235    params = c.params;
236    feedback_params = c.feedback_params;
237    return *this;
238  }
239
240  bool operator==(const VideoCodec& c) const {
241    return this->id == c.id &&  // id is reserved in objective-c
242           name == c.name &&
243           clockrate == c.clockrate &&
244           width == c.width &&
245           height == c.height &&
246           framerate == c.framerate &&
247           preference == c.preference &&
248           params == c.params &&
249           feedback_params == c.feedback_params;
250  }
251
252  bool operator!=(const VideoCodec& c) const {
253    return !(*this == c);
254  }
255
256  static VideoCodec CreateRtxCodec(int rtx_payload_type,
257                                   int associated_payload_type);
258
259  enum CodecType {
260    CODEC_VIDEO,
261    CODEC_RED,
262    CODEC_ULPFEC,
263    CODEC_RTX,
264  };
265
266  CodecType GetCodecType() const;
267  // Validates a VideoCodec's payload type, dimensions and bitrates etc. If they
268  // don't make sense (such as max < min bitrate), and error is logged and
269  // ValidateCodecFormat returns false.
270  bool ValidateCodecFormat() const;
271};
272
273struct DataCodec : public Codec {
274  DataCodec(int id, const std::string& name, int preference)
275      : Codec(id, name, kDataCodecClockrate, preference) {
276  }
277
278  DataCodec() : Codec() {
279    clockrate = kDataCodecClockrate;
280  }
281
282  std::string ToString() const;
283};
284
285struct VideoEncoderConfig {
286  static const int kDefaultMaxThreads = -1;
287  static const int kDefaultCpuProfile = -1;
288
289  VideoEncoderConfig()
290      : max_codec(),
291        num_threads(kDefaultMaxThreads),
292        cpu_profile(kDefaultCpuProfile) {
293  }
294
295  VideoEncoderConfig(const VideoCodec& c)
296      : max_codec(c),
297        num_threads(kDefaultMaxThreads),
298        cpu_profile(kDefaultCpuProfile) {
299  }
300
301  VideoEncoderConfig(const VideoCodec& c, int t, int p)
302      : max_codec(c),
303        num_threads(t),
304        cpu_profile(p) {
305  }
306
307  VideoEncoderConfig& operator=(const VideoEncoderConfig& config) {
308    max_codec = config.max_codec;
309    num_threads = config.num_threads;
310    cpu_profile = config.cpu_profile;
311    return *this;
312  }
313
314  bool operator==(const VideoEncoderConfig& config) const {
315    return max_codec == config.max_codec &&
316           num_threads == config.num_threads &&
317           cpu_profile == config.cpu_profile;
318  }
319
320  bool operator!=(const VideoEncoderConfig& config) const {
321    return !(*this == config);
322  }
323
324  VideoCodec max_codec;
325  int num_threads;
326  int cpu_profile;
327};
328
329}  // namespace cricket
330
331#endif  // TALK_MEDIA_BASE_CODEC_H_
332