codec.h (9308B)
1 /* 2 * Copyright (c) 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 #ifndef MEDIA_BASE_CODEC_H_ 12 #define MEDIA_BASE_CODEC_H_ 13 14 #include <cstddef> 15 #include <optional> 16 #include <string> 17 #include <vector> 18 19 #include "absl/container/inlined_vector.h" 20 #include "absl/strings/str_format.h" 21 #include "absl/strings/string_view.h" 22 #include "api/audio_codecs/audio_format.h" 23 #include "api/rtp_parameters.h" 24 #include "api/video_codecs/scalability_mode.h" 25 #include "api/video_codecs/sdp_video_format.h" 26 #include "media/base/media_constants.h" 27 #include "rtc_base/system/rtc_export.h" 28 29 namespace webrtc { 30 31 class FeedbackParam { 32 public: 33 FeedbackParam() = default; 34 FeedbackParam(absl::string_view id, const std::string& param) 35 : id_(id), param_(param) {} 36 explicit FeedbackParam(absl::string_view id) 37 : id_(id), param_(kParamValueEmpty) {} 38 39 bool operator==(const FeedbackParam& other) const; 40 bool operator!=(const FeedbackParam& c) const { return !(*this == c); } 41 42 const std::string& id() const { return id_; } 43 const std::string& param() const { return param_; } 44 45 private: 46 std::string id_; // e.g. "nack", "ccm" 47 std::string param_; // e.g. "", "rpsi", "fir" 48 }; 49 50 class FeedbackParams { 51 public: 52 FeedbackParams(); 53 ~FeedbackParams(); 54 bool operator==(const FeedbackParams& other) const; 55 bool operator!=(const FeedbackParams& c) const { return !(*this == c); } 56 57 bool Has(const FeedbackParam& param) const; 58 void Add(const FeedbackParam& param); 59 bool Remove(const FeedbackParam& param); 60 61 void Intersect(const FeedbackParams& from); 62 63 const std::vector<FeedbackParam>& params() const { return params_; } 64 65 private: 66 bool HasDuplicateEntries() const; 67 68 std::vector<FeedbackParam> params_; 69 }; 70 constexpr int kDefaultVideoClockRateHz = 90'000; 71 constexpr int kDefaultAudioClockRateHz = 8'000; 72 73 struct RTC_EXPORT Codec { 74 enum class Type { 75 kAudio, 76 kVideo, 77 }; 78 79 enum class ResiliencyType { 80 kNone, 81 kRed, 82 kUlpfec, 83 kFlexfec, 84 kRtx, 85 }; 86 // Value of "id" if it's not explicitly set. Exposed for tests. 87 static const int kIdNotSet = -1; 88 89 Type type; 90 int id; 91 std::string name; 92 int clockrate; 93 94 // Audio only 95 // Can be used to override the target bitrate in the encoder. 96 // TODO(orphis): Remove in favor of alternative APIs 97 int bitrate; 98 size_t channels; 99 100 // Video only 101 std::optional<std::string> packetization; 102 absl::InlinedVector<ScalabilityMode, kScalabilityModeCount> scalability_modes; 103 104 // H.265 only 105 std::optional<std::string> tx_mode; 106 107 // Non key-value parameters such as the telephone-event "0‐15" are 108 // represented using an empty string as key, i.e. {"": "0-15"}. 109 // The equivalent of fmtp in SDP. 110 CodecParameterMap params; 111 // The equivalent of rtcp-fb in SDP. 112 FeedbackParams feedback_params; 113 114 Codec(const Codec& c); 115 Codec(Codec&& c); 116 117 virtual ~Codec(); 118 119 // Indicates if this codec is compatible with the specified codec by 120 // checking the assigned id and profile values for the relevant video codecs. 121 // The rules for this comparison, in particular the parameters are 122 // codec-specific as described in RFC 3264 6.1: 123 // https://www.rfc-editor.org/rfc/rfc3264#section-6.1 124 // For H.264, packetization modes will be compared. 125 // If H.265 is enabled, TxModes will be compared. 126 // H.264 (and H.265, if enabled) levels are not compared. 127 // In all other cases, parameters do not need to match. 128 // This is used in SDP offer/answer codec matching. 129 bool Matches(const Codec& codec) const; 130 131 // This is an exact match similar to what is described in 132 // https://w3c.github.io/webrtc-pc/#dfn-codec-match 133 // with two differences: 134 // - rtx which is included in capabilities without the apt parameter 135 // so number of channels, clock rate or the equality of the parameters 136 // are not compared. 137 // - parameters is compared element-wise, not as a string comparison. 138 // This method should only be used to compare input on our end to something we 139 // generated, done e.g. by setCodecPreferences or setParameters. 140 bool MatchesRtpCodec(const RtpCodec& capability) const; 141 142 // Find the parameter for `key` and write the value to `out`. 143 bool GetParam(const std::string& key, std::string* out) const; 144 bool GetParam(const std::string& key, int* out) const; 145 146 void SetParam(const std::string& key, const std::string& value); 147 void SetParam(const std::string& key, int value); 148 149 // It is safe to input a non-existent parameter. 150 // Returns true if the parameter existed, false if it did not exist. 151 bool RemoveParam(const std::string& key); 152 153 bool HasFeedbackParam(const FeedbackParam& param) const; 154 void AddFeedbackParam(const FeedbackParam& param); 155 156 // Filter `this` feedbacks params such that only those shared by both `this` 157 // and `other` are kept. 158 void IntersectFeedbackParams(const Codec& other); 159 160 virtual RtpCodecParameters ToCodecParameters() const; 161 162 // The codec represent an actual media codec, and not a resiliency codec. 163 bool IsMediaCodec() const; 164 // The codec represent a resiliency codec such as RED, RTX or FEC variants. 165 bool IsResiliencyCodec() const; 166 ResiliencyType GetResiliencyType() const; 167 168 // Validates a VideoCodec's payload type, dimensions and bitrates etc. If they 169 // don't make sense (such as max < min bitrate), and error is logged and 170 // ValidateCodecFormat returns false. 171 bool ValidateCodecFormat() const; 172 173 std::string ToString() const; 174 175 // Default constructor, for initialization. 176 Codec() : Codec(Type::kAudio, kIdNotSet, "", kDefaultAudioClockRateHz) {} 177 Codec& operator=(const Codec& c); 178 Codec& operator=(Codec&& c); 179 180 bool operator==(const Codec& c) const; 181 182 bool operator!=(const Codec& c) const { return !(*this == c); } 183 184 template <typename Sink> 185 friend void AbslStringify(Sink& sink, const Codec& c) { 186 absl::Format(&sink, "[%d:", c.id); 187 switch (c.type) { 188 case Codec::Type::kAudio: 189 sink.Append("audio/"); 190 break; 191 case Codec::Type::kVideo: 192 sink.Append("video/"); 193 } 194 absl::Format(&sink, "%s/%d/%d", c.name, c.clockrate, c.channels); 195 if (c.packetization) { 196 absl::Format(&sink, ",packetization=%s", *c.packetization); 197 } 198 for (auto param : c.params) { 199 sink.Append(";"); 200 sink.Append(param.first); 201 sink.Append("="); 202 sink.Append(param.second); 203 } 204 sink.Append("]"); 205 } 206 207 protected: 208 // Creates an empty codec. 209 explicit Codec(Type type); 210 // Creates a codec with the given parameters. 211 Codec(Type type, int id, const std::string& name, int clockrate); 212 Codec(Type type, 213 int id, 214 const std::string& name, 215 int clockrate, 216 size_t channels); 217 218 explicit Codec(const SdpAudioFormat& c); 219 explicit Codec(const SdpVideoFormat& c); 220 221 friend Codec CreateAudioCodec(int id, 222 const std::string& name, 223 int clockrate, 224 size_t channels); 225 friend Codec CreateAudioCodec(const SdpAudioFormat& c); 226 friend Codec CreateAudioRtxCodec(int rtx_payload_type, 227 int associated_payload_type); 228 friend Codec CreateVideoCodec(int id, const std::string& name); 229 friend Codec CreateVideoCodec(const SdpVideoFormat& c); 230 friend Codec CreateVideoRtxCodec(int rtx_payload_type, 231 int associated_payload_type); 232 }; 233 234 using Codecs = std::vector<Codec>; 235 236 Codec CreateAudioCodec(int id, 237 const std::string& name, 238 int clockrate, 239 size_t channels); 240 Codec CreateAudioCodec(const SdpAudioFormat& c); 241 Codec CreateAudioRtxCodec(int rtx_payload_type, int associated_payload_type); 242 Codec CreateVideoCodec(const std::string& name); 243 Codec CreateVideoCodec(int id, const std::string& name); 244 Codec CreateVideoCodec(const SdpVideoFormat& c); 245 Codec CreateVideoCodec(int id, const SdpVideoFormat& sdp); 246 Codec CreateVideoRtxCodec(int rtx_payload_type, int associated_payload_type); 247 248 // Get the codec setting associated with `payload_type`. If there 249 // is no codec associated with that payload type it returns nullptr. 250 const Codec* FindCodecById(const std::vector<Codec>& codecs, int payload_type); 251 252 bool HasLntf(const Codec& codec); 253 bool HasNack(const Codec& codec); 254 bool HasRemb(const Codec& codec); 255 bool HasRrtr(const Codec& codec); 256 257 // Returns the first codec in `supported_codecs` that matches `codec`, or 258 // nullptr if no codec matches. 259 const Codec* FindMatchingVideoCodec(const std::vector<Codec>& supported_codecs, 260 const Codec& codec); 261 262 // Returns all codecs in `supported_codecs` that matches `codec`. 263 std::vector<const Codec*> FindAllMatchingCodecs( 264 const std::vector<Codec>& supported_codecs, 265 const Codec& codec); 266 267 RTC_EXPORT void AddH264ConstrainedBaselineProfileToSupportedFormats( 268 std::vector<SdpVideoFormat>* supported_formats); 269 } // namespace webrtc 270 271 272 #endif // MEDIA_BASE_CODEC_H_