Use the PayloadType class rather than uint8_t in Codec class Also replace "int" with "PayloadType" in a number of interfaces, and make appropriate adjustments. This is one step towards controlling the issuing and consumption of PayloadType values. Bug: webrtc:360058654 Change-Id: I146bc4e3e9966b98864277eee6f52b75ba10d89a Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/460021 Commit-Queue: Harald Alvestrand <hta@webrtc.org> Reviewed-by: Henrik Boström <hbos@webrtc.org> Cr-Commit-Position: refs/heads/main@{#47286}
diff --git a/api/BUILD.gn b/api/BUILD.gn index 5e0e0f4..3555ec0 100644 --- a/api/BUILD.gn +++ b/api/BUILD.gn
@@ -340,6 +340,7 @@ ] deps = [ ":candidate", + ":payload_type", ":ref_count", ":rtc_error", ":rtp_parameters",
diff --git a/api/payload_type.h b/api/payload_type.h index 9d4a443..dc40b1f 100644 --- a/api/payload_type.h +++ b/api/payload_type.h
@@ -11,31 +11,64 @@ #ifndef API_PAYLOAD_TYPE_H_ #define API_PAYLOAD_TYPE_H_ -#include <cstdint> +#include <optional> #include "absl/strings/str_format.h" #include "rtc_base/strong_alias.h" namespace webrtc { -class PayloadType : public StrongAlias<class PayloadTypeTag, uint8_t> { +class PayloadType : public StrongAlias<class PayloadTypeTag, int> { public: + // The default constructor makes a NotSet. + PayloadType() : StrongAlias(-1) {} // Non-explicit conversions from and to ints are to be deprecated and // removed once calling code is upgraded. - PayloadType(uint8_t pt) { value_ = pt; } // NOLINT: explicit - constexpr operator uint8_t() const& { return value_; } // NOLINT: Explicit - static bool IsValid(PayloadType id, bool rtcp_mux) { + constexpr PayloadType(int pt) : StrongAlias(pt) { // NOLINT: explicit + // The number of tests that use invalid values is high enough that + // this DCHECK can't be deployed yet. + // Also, allow -1 as argument as a temporary measure. Those calls should + // eventually be replaced with PayloadType::NotSet() values. + // Intended check: + // RTC_DCHECK(pt >= -1 && pt <= 127) << "Payload type " << pt << " is + // invalid"; + } + + constexpr operator int() const& { return value(); } // NOLINT: explicit + + // Factory function to create a value if you need to check for + // values in the valid range. + static std::optional<PayloadType> Create(int pt) { + if (pt < 0 || pt > 127) { + return std::nullopt; + } + return PayloadType(pt); + } + // Factory function for the NotSet value. This should be the only way + // to create a value outside the valid range. + static constexpr PayloadType NotSet() { return PayloadType(Internal{}, -1); } + bool Valid(bool rtcp_mux = false) { // A payload type is a 7-bit value in the RTP header, so max = 127. // If RTCP multiplexing is used, the numbers from 64 to 95 are reserved // for RTCP packets. - if (rtcp_mux && (id > 63 && id < 96)) { + if (rtcp_mux && (value() > 63 && value() < 96)) { return false; } - return id >= 0 && id <= 127; + return value() >= 0 && value() <= 127; } + // Older interface to validity check. + static bool IsValid(PayloadType id, bool rtcp_mux) { + return id.Valid(rtcp_mux); + } + bool IsSet() { return value() >= 0; } + + private: + class Internal {}; + // Allow -1 for "NotSet" + explicit constexpr PayloadType(Internal tag, int pt) : StrongAlias(pt) {} template <typename Sink> friend void AbslStringify(Sink& sink, const PayloadType pt) { - absl::Format(&sink, "%d", pt.value_); + absl::Format(&sink, "%d", pt.value()); } };
diff --git a/api/webrtc_sdp.cc b/api/webrtc_sdp.cc index aab9251..67eee80 100644 --- a/api/webrtc_sdp.cc +++ b/api/webrtc_sdp.cc
@@ -33,6 +33,7 @@ #include "api/candidate.h" #include "api/jsep.h" #include "api/media_types.h" +#include "api/payload_type.h" #include "api/rtc_error.h" #include "api/rtp_parameters.h" #include "api/rtp_transceiver_direction.h" @@ -192,7 +193,7 @@ // RTP payload type is in the 0-127 range. Use -1 to indicate "all" payload // types. -const int kWildcardPayloadType = -1; +constexpr PayloadType kWildcardPayloadType = PayloadType::NotSet(); // Check if passed character is a "token-char" from RFC 4566. // https://datatracker.ietf.org/doc/html/rfc4566#section-9 @@ -1013,7 +1014,7 @@ return true; } -void WriteFmtpHeader(int payload_type, StringBuilder* os) { +void WriteFmtpHeader(PayloadType payload_type, StringBuilder* os) { // fmtp header: a=fmtp:`payload_type` <parameters> // Add a=fmtp InitAttrLine(kAttributeFmtp, os); @@ -1021,7 +1022,7 @@ *os << kSdpDelimiterColon << payload_type; } -void WritePacketizationHeader(int payload_type, StringBuilder* os) { +void WritePacketizationHeader(PayloadType payload_type, StringBuilder* os) { // packetization header: a=packetization:`payload_type` <packetization_format> // Add a=packetization InitAttrLine(kAttributePacketization, os); @@ -1029,7 +1030,7 @@ *os << kSdpDelimiterColon << payload_type; } -void WriteRtcpFbHeader(int payload_type, StringBuilder* os) { +void WriteRtcpFbHeader(PayloadType payload_type, StringBuilder* os) { // rtcp-fb header: a=rtcp-fb:`payload_type` // <parameters>/<ccm <ccm_parameters>> // Add a=rtcp-fb @@ -2035,7 +2036,7 @@ // with that payload type. Codec GetCodecWithPayloadType(MediaType type, const std::vector<Codec>& codecs, - int payload_type) { + PayloadType payload_type) { const Codec* codec = FindCodecById(codecs, payload_type); if (codec) return *codec; @@ -2050,7 +2051,7 @@ // Adds or updates existing codec corresponding to `payload_type` according // to `parameters`. void UpdateCodec(MediaContentDescription* content_desc, - int payload_type, + PayloadType payload_type, const CodecParameterMap& parameters) { // Codec might already have been populated (from rtpmap). Codec new_codec = GetCodecWithPayloadType( @@ -2062,7 +2063,7 @@ // Adds or updates existing codec corresponding to `payload_type` according // to `feedback_param`. void UpdateCodec(MediaContentDescription* content_desc, - int payload_type, + PayloadType payload_type, const FeedbackParam& feedback_param) { // Codec might already have been populated (from rtpmap). Codec new_codec = GetCodecWithPayloadType( @@ -2098,11 +2099,12 @@ return false; } - int payload_type = 0; - if (!GetPayloadTypeFromString(line_payload, payload_type_str, &payload_type, + int pt_int = 0; + if (!GetPayloadTypeFromString(line_payload, payload_type_str, &pt_int, error)) { return false; } + PayloadType payload_type = PayloadType(pt_int); // Parse out format specific parameters. CodecParameterMap codec_params; @@ -2224,7 +2226,7 @@ // Updates or creates a new codec entry in the audio description with according // to `name`, `clockrate`, `bitrate`, and `channels`. -void UpdateCodec(int payload_type, +void UpdateCodec(PayloadType payload_type, absl::string_view name, int clockrate, int bitrate, @@ -2243,7 +2245,7 @@ // Updates or creates a new codec entry in the video description according to // `name`, `width`, `height`, and `framerate`. -void UpdateCodec(int payload_type, +void UpdateCodec(PayloadType payload_type, absl::string_view name, MediaContentDescription* desc) { // Codec may already be populated with (only) optional parameters @@ -2358,7 +2360,7 @@ // Adds or updates existing video codec corresponding to `payload_type` // according to `packetization`. void UpdateVideoCodecPacketization(MediaContentDescription* desc, - int payload_type, + PayloadType payload_type, absl::string_view packetization) { if (packetization != kPacketizationParamRaw) { // Ignore unsupported packetization attribute. @@ -2389,11 +2391,11 @@ &payload_type_string, error)) { return false; } - int payload_type; - if (!GetPayloadTypeFromString(line, payload_type_string, &payload_type, - error)) { + int pt_int; + if (!GetPayloadTypeFromString(line, payload_type_string, &pt_int, error)) { return false; } + PayloadType payload_type = PayloadType(pt_int); absl::string_view packetization = packetization_fields[1]; UpdateVideoCodecPacketization(media_desc, payload_type, packetization); return true; @@ -2416,12 +2418,13 @@ error)) { return false; } - int payload_type = kWildcardPayloadType; + PayloadType payload_type = kWildcardPayloadType; if (payload_type_string != "*") { - if (!GetPayloadTypeFromString(line, payload_type_string, &payload_type, - error)) { + int pt_int; + if (!GetPayloadTypeFromString(line, payload_type_string, &pt_int, error)) { return false; } + payload_type = PayloadType(pt_int); } absl::string_view id = rtcp_fb_fields[1]; std::string param = "";
diff --git a/call/BUILD.gn b/call/BUILD.gn index 232c66a..b116163 100644 --- a/call/BUILD.gn +++ b/call/BUILD.gn
@@ -530,6 +530,7 @@ "../api:mock_audio_mixer", "../api:mock_frame_transformer", "../api:mock_video_codec_factory", + "../api:payload_type", "../api:rtp_headers", "../api:rtp_parameters", "../api:scoped_refptr",
diff --git a/call/payload_type_picker_unittest.cc b/call/payload_type_picker_unittest.cc index 46e0de7..562bb2c 100644 --- a/call/payload_type_picker_unittest.cc +++ b/call/payload_type_picker_unittest.cc
@@ -13,6 +13,7 @@ #include <string> #include "absl/strings/str_cat.h" +#include "api/payload_type.h" #include "api/video_codecs/sdp_video_format.h" #include "call/payload_type.h" #include "media/base/codec.h" @@ -96,7 +97,6 @@ PayloadTypeRecorder recorder(picker); const PayloadType a_payload_type(123); const PayloadType b_payload_type(124); - const PayloadType not_a_payload_type(44); Codec a_codec = CreateVideoCodec(0, "vp8");
diff --git a/media/BUILD.gn b/media/BUILD.gn index e292762..15c2cf9 100644 --- a/media/BUILD.gn +++ b/media/BUILD.gn
@@ -356,6 +356,7 @@ "../rtc_base:stringutils", "../rtc_base/network:sent_packet", "../video/config:encoder_config", + "//third_party/abseil-cpp/absl/container:flat_hash_map", "//third_party/abseil-cpp/absl/functional:any_invocable", "//third_party/abseil-cpp/absl/strings", "//third_party/abseil-cpp/absl/strings:string_view", @@ -374,6 +375,7 @@ ] deps = [ ":media_constants", + "../api:payload_type", "../api:rtp_parameters", "../api/audio_codecs:audio_codecs_api", "../api/video_codecs:scalability_mode", @@ -400,6 +402,7 @@ deps = [ ":codec", ":media_constants", + "../api:payload_type", "../api:rtc_error", "../rtc_base:checks", "../rtc_base:logging", @@ -970,6 +973,7 @@ "../api:mock_video_codec_factory", "../api:mock_video_decoder", "../api:mock_video_encoder", + "../api:payload_type", "../api:priority", "../api:ref_count", "../api:rtc_error",
diff --git a/media/base/codec.cc b/media/base/codec.cc index 8379f99..535fcd8 100644 --- a/media/base/codec.cc +++ b/media/base/codec.cc
@@ -22,6 +22,7 @@ #include "absl/strings/str_cat.h" #include "api/audio_codecs/audio_format.h" #include "api/media_types.h" +#include "api/payload_type.h" #include "api/rtp_parameters.h" #include "api/video_codecs/h264_profile_level_id.h" #include "api/video_codecs/sdp_video_format.h" @@ -97,10 +98,10 @@ return false; } -Codec::Codec(Type type, int id, const std::string& name, int clockrate) +Codec::Codec(Type type, PayloadType id, const std::string& name, int clockrate) : Codec(type, id, name, clockrate, 0) {} Codec::Codec(Type type, - int id, + PayloadType id, const std::string& name, int clockrate, size_t channels) @@ -115,18 +116,22 @@ Codec::Codec(Type type) : Codec(type, - kIdNotSet, + PayloadType::NotSet(), "", type == Type::kVideo ? kDefaultVideoClockRateHz : kDefaultAudioClockRateHz) {} Codec::Codec(const SdpAudioFormat& c) - : Codec(Type::kAudio, kIdNotSet, c.name, c.clockrate_hz, c.num_channels) { + : Codec(Type::kAudio, + PayloadType::NotSet(), + c.name, + c.clockrate_hz, + c.num_channels) { params = c.parameters; } Codec::Codec(const SdpVideoFormat& c) - : Codec(Type::kVideo, kIdNotSet, c.name, kVideoCodecClockrate) { + : Codec(Type::kVideo, PayloadType::NotSet(), c.name, kVideoCodecClockrate) { params = c.parameters; scalability_modes = c.scalability_modes; } @@ -290,20 +295,25 @@ return sb.str(); } -Codec CreateAudioRtxCodec(int rtx_payload_type, int associated_payload_type) { +Codec CreateAudioRtxCodec(PayloadType rtx_payload_type, + PayloadType associated_payload_type) { Codec rtx_codec = CreateAudioCodec(rtx_payload_type, kRtxCodecName, kDefaultAudioClockRateHz, 1); - rtx_codec.SetParam(kCodecParamAssociatedPayloadType, associated_payload_type); + rtx_codec.SetParam(kCodecParamAssociatedPayloadType, + associated_payload_type.value()); return rtx_codec; } -Codec CreateVideoRtxCodec(int rtx_payload_type, int associated_payload_type) { +Codec CreateVideoRtxCodec(PayloadType rtx_payload_type, + PayloadType associated_payload_type) { Codec rtx_codec = CreateVideoCodec(rtx_payload_type, kRtxCodecName); - rtx_codec.SetParam(kCodecParamAssociatedPayloadType, associated_payload_type); + rtx_codec.SetParam(kCodecParamAssociatedPayloadType, + associated_payload_type.value()); return rtx_codec; } -const Codec* FindCodecById(const std::vector<Codec>& codecs, int payload_type) { +const Codec* FindCodecById(const std::vector<Codec>& codecs, + PayloadType payload_type) { for (const auto& codec : codecs) { if (codec.id == payload_type) return &codec; @@ -395,7 +405,7 @@ } } -Codec CreateAudioCodec(int id, +Codec CreateAudioCodec(PayloadType id, const std::string& name, int clockrate, size_t channels) { @@ -407,10 +417,10 @@ } Codec CreateVideoCodec(const std::string& name) { - return CreateVideoCodec(Codec::kIdNotSet, name); + return CreateVideoCodec(PayloadType::NotSet(), name); } -Codec CreateVideoCodec(int id, const std::string& name) { +Codec CreateVideoCodec(PayloadType id, const std::string& name) { Codec c(Codec::Type::kVideo, id, name, kVideoCodecClockrate); if (absl::EqualsIgnoreCase(kH264CodecName, name)) { // This default is set for all H.264 codecs created because @@ -426,7 +436,7 @@ return Codec(c); } -Codec CreateVideoCodec(int id, const SdpVideoFormat& sdp) { +Codec CreateVideoCodec(PayloadType id, const SdpVideoFormat& sdp) { Codec c = CreateVideoCodec(sdp); c.id = id; return c;
diff --git a/media/base/codec.h b/media/base/codec.h index bc970c5..5f19744 100644 --- a/media/base/codec.h +++ b/media/base/codec.h
@@ -20,6 +20,7 @@ #include "absl/strings/str_format.h" #include "absl/strings/string_view.h" #include "api/audio_codecs/audio_format.h" +#include "api/payload_type.h" #include "api/rtp_parameters.h" #include "api/video_codecs/scalability_mode.h" #include "api/video_codecs/sdp_video_format.h" @@ -87,7 +88,7 @@ static const int kIdNotSet = -1; Type type; - int id; + PayloadType id; std::string name; int clockrate; @@ -173,7 +174,11 @@ std::string ToString() const; // Default constructor, for initialization. - Codec() : Codec(Type::kAudio, kIdNotSet, "", kDefaultAudioClockRateHz) {} + Codec() + : Codec(Type::kAudio, + PayloadType::NotSet(), + "", + kDefaultAudioClockRateHz) {} Codec& operator=(const Codec& c); Codec& operator=(Codec&& c); @@ -183,7 +188,7 @@ template <typename Sink> friend void AbslStringify(Sink& sink, const Codec& c) { - absl::Format(&sink, "[%d:", c.id); + absl::Format(&sink, "[%v:", c.id); switch (c.type) { case Codec::Type::kAudio: sink.Append("audio/"); @@ -208,9 +213,9 @@ // Creates an empty codec. explicit Codec(Type type); // Creates a codec with the given parameters. - Codec(Type type, int id, const std::string& name, int clockrate); + Codec(Type type, PayloadType id, const std::string& name, int clockrate); Codec(Type type, - int id, + PayloadType id, const std::string& name, int clockrate, size_t channels); @@ -218,36 +223,38 @@ explicit Codec(const SdpAudioFormat& c); explicit Codec(const SdpVideoFormat& c); - friend Codec CreateAudioCodec(int id, + friend Codec CreateAudioCodec(PayloadType id, const std::string& name, int clockrate, size_t channels); friend Codec CreateAudioCodec(const SdpAudioFormat& c); - friend Codec CreateAudioRtxCodec(int rtx_payload_type, - int associated_payload_type); - friend Codec CreateVideoCodec(int id, const std::string& name); + friend Codec CreateAudioRtxCodec(PayloadType rtx_payload_type, + PayloadType associated_payload_type); + friend Codec CreateVideoCodec(PayloadType id, const std::string& name); friend Codec CreateVideoCodec(const SdpVideoFormat& c); - friend Codec CreateVideoRtxCodec(int rtx_payload_type, - int associated_payload_type); + friend Codec CreateVideoCodec(PayloadType id, const SdpVideoFormat& sdp); }; using Codecs = std::vector<Codec>; -Codec CreateAudioCodec(int id, +Codec CreateAudioCodec(PayloadType id, const std::string& name, int clockrate, size_t channels); Codec CreateAudioCodec(const SdpAudioFormat& c); -Codec CreateAudioRtxCodec(int rtx_payload_type, int associated_payload_type); +Codec CreateAudioRtxCodec(PayloadType rtx_payload_type, + PayloadType associated_payload_type); Codec CreateVideoCodec(const std::string& name); -Codec CreateVideoCodec(int id, const std::string& name); +Codec CreateVideoCodec(PayloadType id, const std::string& name); Codec CreateVideoCodec(const SdpVideoFormat& c); -Codec CreateVideoCodec(int id, const SdpVideoFormat& sdp); -Codec CreateVideoRtxCodec(int rtx_payload_type, int associated_payload_type); +Codec CreateVideoCodec(PayloadType id, const SdpVideoFormat& sdp); +Codec CreateVideoRtxCodec(PayloadType rtx_payload_type, + PayloadType associated_payload_type); // Get the codec setting associated with `payload_type`. If there // is no codec associated with that payload type it returns nullptr. -const Codec* FindCodecById(const std::vector<Codec>& codecs, int payload_type); +const Codec* FindCodecById(const std::vector<Codec>& codecs, + PayloadType payload_type); bool HasLntf(const Codec& codec); bool HasNack(const Codec& codec);
diff --git a/media/base/codec_comparators.cc b/media/base/codec_comparators.cc index 942e3a2..3b4b198 100644 --- a/media/base/codec_comparators.cc +++ b/media/base/codec_comparators.cc
@@ -11,6 +11,7 @@ #include <algorithm> #include <cstddef> +#include <cstdint> #include <optional> #include <string> #include <vector> @@ -20,6 +21,7 @@ #include "absl/strings/match.h" #include "absl/strings/string_view.h" #include "api/media_types.h" +#include "api/payload_type.h" #include "api/rtp_parameters.h" #include "api/video_codecs/av1_profile.h" #include "api/video_codecs/h264_profile_level_id.h" @@ -119,9 +121,9 @@ } bool ReferencedCodecsMatch(const std::vector<Codec>& codecs1, - const int codec1_id, + const PayloadType codec1_id, const std::vector<Codec>& codecs2, - const int codec2_id) { + const PayloadType codec2_id) { const Codec* codec1 = FindCodecById(codecs1, codec1_id); const Codec* codec2 = FindCodecById(codecs2, codec2_id); return codec1 != nullptr && codec2 != nullptr && codec1->Matches(*codec2); @@ -130,21 +132,25 @@ bool MatchesWithReferenceAttributesAndComparator( const Codec& codec_to_match, const Codec& potential_match, - absl::AnyInvocable<bool(int, int)> reference_comparator) { + absl::AnyInvocable<bool(PayloadType, PayloadType)> reference_comparator) { if (!MatchesWithCodecRules(codec_to_match, potential_match)) { return false; } Codec::ResiliencyType resiliency_type = codec_to_match.GetResiliencyType(); if (resiliency_type == Codec::ResiliencyType::kRtx) { - int apt_value_1 = 0; - int apt_value_2 = 0; + int apt_value_1_int = 0; + int apt_value_2_int = 0; if (!codec_to_match.GetParam(kCodecParamAssociatedPayloadType, - &apt_value_1) || + &apt_value_1_int) || !potential_match.GetParam(kCodecParamAssociatedPayloadType, - &apt_value_2)) { + &apt_value_2_int)) { RTC_LOG(LS_WARNING) << "RTX missing associated payload type."; return false; } + PayloadType apt_value_1 = + PayloadType(static_cast<uint8_t>(apt_value_1_int)); + PayloadType apt_value_2 = + PayloadType(static_cast<uint8_t>(apt_value_2_int)); if (reference_comparator(apt_value_1, apt_value_2)) { return true; } @@ -196,8 +202,8 @@ // codecs has an unassigned payload type or they have the same ID. if (codec_to_match.type == Codec::Type::kAudio && codec_to_match.name == kRedCodecName && - (codec_to_match.id == Codec::kIdNotSet || - potential_match.id == Codec::kIdNotSet || + (codec_to_match.id == PayloadType::NotSet() || + potential_match.id == PayloadType::NotSet() || codec_to_match.id == potential_match.id)) { return true; } @@ -297,7 +303,8 @@ bool matches_id; if ((is_id_in_dynamic_range && is_codec_id_in_dynamic_range) || - left_codec.id == Codec::kIdNotSet || right_codec.id == Codec::kIdNotSet) { + left_codec.id == PayloadType::NotSet() || + right_codec.id == PayloadType::NotSet()) { matches_id = absl::EqualsIgnoreCase(left_codec.name, right_codec.name); } else { matches_id = (left_codec.id == right_codec.id); @@ -330,7 +337,7 @@ bool MatchesWithReferenceAttributes(const Codec& codec1, const Codec& codec2) { return MatchesWithReferenceAttributesAndComparator( - codec1, codec2, [](int a, int b) { return a == b; }); + codec1, codec2, [](PayloadType a, PayloadType b) { return a == b; }); } // Finds a codec in `codecs2` that matches `codec_to_match`, which is @@ -348,7 +355,7 @@ for (const Codec& potential_match : codecs2) { if (MatchesWithReferenceAttributesAndComparator( codec_to_match, potential_match, - [&codecs1, &codecs2](int a, int b) { + [&codecs1, &codecs2](PayloadType a, PayloadType b) { return ReferencedCodecsMatch(codecs1, a, codecs2, b); })) { return potential_match;
diff --git a/media/base/codec_list.cc b/media/base/codec_list.cc index 4be60c4..a293244 100644 --- a/media/base/codec_list.cc +++ b/media/base/codec_list.cc
@@ -14,6 +14,7 @@ #include <map> #include <vector> +#include "api/payload_type.h" #include "api/rtc_error.h" #include "media/base/codec.h" #include "media/base/media_constants.h" @@ -32,8 +33,8 @@ // that there are no duplicates. for (size_t i = 0; i < codecs.size(); i++) { const Codec& codec = codecs[i]; - if (codec.id != Codec::kIdNotSet) { - auto [it, success] = pt_to_index.insert({codec.id, i}); + if (codec.id != PayloadType::NotSet()) { + auto [it, success] = pt_to_index.insert({codec.id, static_cast<int>(i)}); if (!success) { RTC_LOG(LS_ERROR) << "Duplicate payload type in codec list, " << codec << " and " << codecs[it->second] @@ -56,7 +57,7 @@ // TODO: https://issues.webrtc.org/384756622 - reject codec earlier and // enable check. RTC_DCHECK(apt_it != codec.params.end()); Until that is // fixed: - if (codec.id == Codec::kIdNotSet) { + if (codec.id == PayloadType::NotSet()) { // Should not have an apt parameter. if (apt_it != codec.params.end()) { RTC_LOG(LS_WARNING) << "Surprising condition: RTX codec without " @@ -77,7 +78,7 @@ return LOG_ERROR(RTCError(RTCErrorType::INVALID_PARAMETER) << "Non-numeric argument to rtx apt parameter"); } - if (codec.id != Codec::kIdNotSet && + if (codec.id != PayloadType::NotSet() && pt_to_index.count(associated_pt) != 1) { RTC_LOG(LS_WARNING) << "Surprising condition: RTX codec APT not found: " << codec
diff --git a/media/base/media_channel.h b/media/base/media_channel.h index cdc1928..7075694 100644 --- a/media/base/media_channel.h +++ b/media/base/media_channel.h
@@ -22,6 +22,7 @@ #include <utility> #include <vector> +#include "absl/container/flat_hash_map.h" #include "absl/functional/any_invocable.h" #include "absl/strings/str_cat.h" #include "absl/strings/string_view.h" @@ -705,7 +706,8 @@ }; // Maps from payload type to `RtpCodecParameters`. -typedef std::map<int, RtpCodecParameters> RtpCodecParametersMap; +typedef absl::flat_hash_map<decltype(Codec::id), RtpCodecParameters> + RtpCodecParametersMap; // Stats returned from VoiceMediaSendChannel.GetStats() struct VoiceMediaSendInfo {
diff --git a/media/engine/webrtc_video_engine.cc b/media/engine/webrtc_video_engine.cc index 91f2c9b..6b3e0b5 100644 --- a/media/engine/webrtc_video_engine.cc +++ b/media/engine/webrtc_video_engine.cc
@@ -1715,13 +1715,13 @@ // we can omit the codec information for those here and only insert the // primary codec that is being used to send here. video_media_info->send_codecs.insert(std::make_pair( - send_codec()->codec.id, send_codec()->codec.ToCodecParameters())); + send_codec()->codec.id.value(), send_codec()->codec.ToCodecParameters())); for (const auto& it : send_codecs_) { auto codec_param_it = video_media_info->send_codecs.find(it.codec.id); if (codec_param_it == video_media_info->send_codecs.end()) { video_media_info->send_codecs.insert( - std::make_pair(it.codec.id, it.codec.ToCodecParameters())); + std::make_pair(it.codec.id.value(), it.codec.ToCodecParameters())); } } } @@ -2472,7 +2472,8 @@ VideoSenderInfo common_info; if (parameters_.codec_settings) { common_info.codec_name = parameters_.codec_settings->codec.name; - common_info.codec_payload_type = parameters_.codec_settings->codec.id; + common_info.codec_payload_type = + parameters_.codec_settings->codec.id.value(); } // If SVC is used, one stream is configured but multiple encodings exist. This // is not spec-compliant, but it is how we've implemented SVC so this affects @@ -3223,7 +3224,7 @@ *receiver.codec_payload_type == c.id; }); if (codec != recv_params_.codecs.end()) { - video_media_info->receive_codecs.insert( + video_media_info->receive_codecs.emplace( std::make_pair(codec->id, codec->ToCodecParameters())); } }
diff --git a/media/engine/webrtc_video_engine_unittest.cc b/media/engine/webrtc_video_engine_unittest.cc index 3685544..c9de2e5 100644 --- a/media/engine/webrtc_video_engine_unittest.cc +++ b/media/engine/webrtc_video_engine_unittest.cc
@@ -36,6 +36,7 @@ #include "api/field_trials.h" #include "api/make_ref_counted.h" #include "api/media_types.h" +#include "api/payload_type.h" #include "api/priority.h" #include "api/rtc_error.h" #include "api/rtp_headers.h" @@ -5626,7 +5627,7 @@ VideoReceiverParameters parameters; parameters.codecs.push_back(GetEngineCodec("VP8")); parameters.codecs.push_back(GetEngineCodec("VP8")); - parameters.codecs[1].id += 1; + parameters.codecs[1].id = PayloadType(parameters.codecs[1].id + 1); EXPECT_TRUE(receive_channel_->SetReceiverParameters(parameters)); }
diff --git a/media/engine/webrtc_voice_engine.cc b/media/engine/webrtc_voice_engine.cc index c8bda98..a3c8c98 100644 --- a/media/engine/webrtc_voice_engine.cc +++ b/media/engine/webrtc_voice_engine.cc
@@ -50,6 +50,7 @@ #include "api/frame_transformer_interface.h" #include "api/make_ref_counted.h" #include "api/media_types.h" +#include "api/payload_type.h" #include "api/priority.h" #include "api/rtc_error.h" #include "api/rtp_headers.h" @@ -1431,7 +1432,7 @@ const std::vector<Codec>& codecs, std::optional<Codec> preferred_codec) { RTC_DCHECK_RUN_ON(worker_thread_); - dtmf_payload_type_ = std::nullopt; + dtmf_payload_type_ = PayloadType::NotSet(); dtmf_payload_freq_ = -1; // Validate supplied codecs list. @@ -1453,7 +1454,8 @@ for (const Codec& codec : codecs) { if (IsCodec(codec, kDtmfCodecName)) { dtmf_codecs.push_back(codec); - if (!dtmf_payload_type_ || codec.clockrate < dtmf_payload_freq_) { + if ((dtmf_payload_type_ == PayloadType::NotSet()) || + codec.clockrate < dtmf_payload_freq_) { dtmf_payload_type_ = codec.id; dtmf_payload_freq_ = codec.clockrate; } @@ -1513,7 +1515,7 @@ RTC_LOG(LS_WARNING) << "CN frequency " << cn_codec.clockrate << " not supported."; } else { - send_codec_spec->cng_payload_type = cn_codec.id; + send_codec_spec->cng_payload_type = cn_codec.id.value(); } break; } @@ -1537,7 +1539,7 @@ const Codec& red_codec = codecs[i]; if (IsCodec(red_codec, kRedCodecName) && CheckRedParameters(red_codec, *send_codec_spec)) { - send_codec_spec->red_payload_type = red_codec.id; + send_codec_spec->red_payload_type = red_codec.id.value(); break; } } @@ -1698,7 +1700,7 @@ bool WebRtcVoiceSendChannel::CanInsertDtmf() { RTC_DCHECK_RUN_ON(worker_thread_); - return dtmf_payload_type_.has_value() && send_; + return (dtmf_payload_type_ != PayloadType::NotSet()) && send_; } void WebRtcVoiceSendChannel::SetFrameEncryptor( @@ -1884,7 +1886,7 @@ }); if (codec != send_codecs_.end()) { voice_media_info->send_codecs.insert( - std::make_pair(codec->id, codec->ToCodecParameters())); + std::make_pair(codec->id.value(), codec->ToCodecParameters())); } } } @@ -2772,7 +2774,7 @@ }); if (codec != recv_codecs_.end()) { voice_media_info->receive_codecs.insert( - std::make_pair(codec->id, codec->ToCodecParameters())); + std::make_pair(codec->id.value(), codec->ToCodecParameters())); } } }
diff --git a/media/engine/webrtc_voice_engine.h b/media/engine/webrtc_voice_engine.h index 97907fd..c38a47f 100644 --- a/media/engine/webrtc_voice_engine.h +++ b/media/engine/webrtc_voice_engine.h
@@ -39,6 +39,7 @@ #include "api/field_trials_view.h" #include "api/frame_transformer_interface.h" #include "api/media_types.h" +#include "api/payload_type.h" #include "api/rtc_error.h" #include "api/rtp_headers.h" #include "api/rtp_parameters.h" @@ -280,7 +281,7 @@ int max_send_bitrate_bps_ RTC_GUARDED_BY(worker_thread_) = 0; AudioOptions options_ RTC_GUARDED_BY(worker_thread_); - std::optional<int> dtmf_payload_type_ RTC_GUARDED_BY(worker_thread_); + PayloadType dtmf_payload_type_ RTC_GUARDED_BY(worker_thread_); int dtmf_payload_freq_ RTC_GUARDED_BY(worker_thread_) = -1; bool enable_non_sender_rtt_ RTC_GUARDED_BY(worker_thread_) = false; bool send_ RTC_GUARDED_BY(worker_thread_) = false;
diff --git a/media/engine/webrtc_voice_engine_unittest.cc b/media/engine/webrtc_voice_engine_unittest.cc index 8195403..526a6cb 100644 --- a/media/engine/webrtc_voice_engine_unittest.cc +++ b/media/engine/webrtc_voice_engine_unittest.cc
@@ -38,6 +38,7 @@ #include "api/field_trials.h" #include "api/make_ref_counted.h" #include "api/media_types.h" +#include "api/payload_type.h" #include "api/priority.h" #include "api/ref_count.h" #include "api/rtc_error.h" @@ -1110,7 +1111,7 @@ parameters.codecs.push_back(kOpusCodec); EXPECT_TRUE(receive_channel_->SetReceiverParameters(parameters)); - ++parameters.codecs[0].id; + parameters.codecs[0].id = PayloadType(parameters.codecs[0].id + 1); EXPECT_TRUE(receive_channel_->SetReceiverParameters(parameters)); }
diff --git a/pc/BUILD.gn b/pc/BUILD.gn index 1f19fdc..a903e35 100644 --- a/pc/BUILD.gn +++ b/pc/BUILD.gn
@@ -105,6 +105,7 @@ "//third_party/abseil-cpp/absl/algorithm:container", "//third_party/abseil-cpp/absl/cleanup", "//third_party/abseil-cpp/absl/functional:any_invocable", + "//third_party/abseil-cpp/absl/strings:str_format", "//third_party/abseil-cpp/absl/strings:string_view", ] } @@ -1228,6 +1229,7 @@ ":jsep_transport_collection", ":session_description", "../api:jsep", + "../api:payload_type", "../api:peer_connection_interface", "../api:rtc_error", "../call:payload_type", @@ -1235,6 +1237,7 @@ "../media:codec", "../rtc_base:checks", "../rtc_base:event_tracer", + "../rtc_base:logging", "../rtc_base:threading", "//third_party/abseil-cpp/absl/strings:string_view", ] @@ -1390,6 +1393,7 @@ deps = [ ":session_description", ":simulcast_description", + "../api:payload_type", "../api:rtc_error", "../api:rtp_parameters", "../media:codec", @@ -2268,6 +2272,7 @@ "../api:make_ref_counted", "../api:media_stream_interface", "../api:mock_datagram_connection_observer", + "../api:payload_type", "../api:peer_connection_interface", "../api:priority", "../api:rtc_error", @@ -2625,6 +2630,7 @@ "../api:mock_encoder_selector", "../api:mock_packet_socket_factory", "../api:mock_video_track", + "../api:payload_type", "../api:peer_connection_interface", "../api:priority", "../api:ref_count",
diff --git a/pc/channel.cc b/pc/channel.cc index 1774778..610f507 100644 --- a/pc/channel.cc +++ b/pc/channel.cc
@@ -21,6 +21,7 @@ #include "absl/algorithm/container.h" #include "absl/cleanup/cleanup.h" #include "absl/functional/any_invocable.h" +#include "absl/strings/str_format.h" #include "absl/strings/string_view.h" #include "api/crypto/crypto_options.h" #include "api/jsep.h" @@ -156,9 +157,9 @@ // Note: this writes into old_params codec.packetization = std::nullopt; } else if (!has_matching_packetization) { - std::string error_desc = StringFormat( + std::string error_desc = absl::StrFormat( "Failed to set local answer due to incompatible codec " - "packetization for pt='%d' specified.", + "packetization for pt='%v' specified.", codec.id); return RTCError(RTCErrorType::INTERNAL_ERROR, error_desc); }
diff --git a/pc/codec_vendor.cc b/pc/codec_vendor.cc index 2adc3a6..cb9f65c 100644 --- a/pc/codec_vendor.cc +++ b/pc/codec_vendor.cc
@@ -563,7 +563,7 @@ RTC_DCHECK_DISALLOW_THREAD_BLOCKING_CALLS(); int codec_payload_type = Codec::kIdNotSet; for (Codec& codec : codecs) { - if (codec.id == Codec::kIdNotSet) { + if (codec.id == PayloadType::NotSet()) { // Add payload types to codecs, if needed // This should only happen if WebRTC-PayloadTypesInTransport field trial // is enabled. @@ -577,7 +577,7 @@ // record first Opus codec id if (absl::EqualsIgnoreCase(codec.name, kOpusCodecName) && codec_payload_type == Codec::kIdNotSet) { - codec_payload_type = codec.id; + codec_payload_type = codec.id.value(); } } if (codec_payload_type != Codec::kIdNotSet) {
diff --git a/pc/codec_vendor_unittest.cc b/pc/codec_vendor_unittest.cc index d8f88f6..76b4cbe 100644 --- a/pc/codec_vendor_unittest.cc +++ b/pc/codec_vendor_unittest.cc
@@ -18,6 +18,7 @@ #include "api/environment/environment_factory.h" #include "api/field_trials.h" #include "api/media_types.h" +#include "api/payload_type.h" #include "api/rtc_error.h" #include "api/rtp_transceiver_direction.h" #include "api/test/rtc_error_matchers.h" @@ -194,7 +195,7 @@ MediaDescriptionOptions options(MediaType::VIDEO, "mid", RtpTransceiverDirection::kSendOnly, false); options.codec_preferences = { - ToRtpCodecCapability(CreateVideoCodec(-1, "vp9")), + ToRtpCodecCapability(CreateVideoCodec(PayloadType::NotSet(), "vp9")), }; FakePayloadTypeSuggester pt_suggester;
diff --git a/pc/rtp_parameters_conversion.cc b/pc/rtp_parameters_conversion.cc index 63d50d2..ca19b21 100644 --- a/pc/rtp_parameters_conversion.cc +++ b/pc/rtp_parameters_conversion.cc
@@ -81,7 +81,7 @@ codec.kind = cricket_codec.type == Codec::Type::kAudio ? MediaType::AUDIO : MediaType::VIDEO; codec.clock_rate.emplace(cricket_codec.clockrate); - codec.preferred_payload_type.emplace(cricket_codec.id); + codec.preferred_payload_type.emplace(cricket_codec.id.value()); for (const FeedbackParam& cricket_feedback : cricket_codec.feedback_params.params()) { std::optional<RtcpFeedback> feedback = ToRtcpFeedback(cricket_feedback);
diff --git a/pc/sdp_payload_type_suggester.cc b/pc/sdp_payload_type_suggester.cc index acaca73..2386864 100644 --- a/pc/sdp_payload_type_suggester.cc +++ b/pc/sdp_payload_type_suggester.cc
@@ -16,12 +16,14 @@ #include "absl/strings/string_view.h" #include "api/jsep.h" +#include "api/payload_type.h" #include "api/rtc_error.h" #include "call/payload_type.h" #include "call/payload_type_picker.h" #include "media/base/codec.h" #include "pc/session_description.h" #include "rtc_base/checks.h" +#include "rtc_base/logging.h" #include "rtc_base/thread.h" #include "rtc_base/trace_event.h" @@ -45,6 +47,8 @@ RTCErrorOr<PayloadType> remote_result = remote_recorder.LookupPayloadType(codec); if (remote_result.ok()) { + RTC_LOG(LS_INFO) << "SuggestPayloadType: Found remote mapping for " << codec + << " to PT " << remote_result.value(); RTCErrorOr<Codec> local_codec = local_recorder.LookupCodec(remote_result.value()); if (!local_codec.ok()) { @@ -55,6 +59,9 @@ } // If we get here, PT is already in use, possibly for something else. // Fall through to SuggestMapping. + } else { + RTC_LOG(LS_INFO) << "SuggestPayloadType: FAILED to find remote mapping for " + << codec; } return payload_type_picker_.SuggestMapping(codec, &local_recorder); }
diff --git a/pc/sdp_payload_type_suggester_unittest.cc b/pc/sdp_payload_type_suggester_unittest.cc index d543d1b..1610822 100644 --- a/pc/sdp_payload_type_suggester_unittest.cc +++ b/pc/sdp_payload_type_suggester_unittest.cc
@@ -16,9 +16,9 @@ #include "absl/strings/string_view.h" #include "api/jsep.h" +#include "api/payload_type.h" #include "api/peer_connection_interface.h" #include "api/rtc_error.h" -#include "call/payload_type.h" #include "media/base/codec.h" #include "media/base/media_constants.h" #include "pc/session_description.h" @@ -48,7 +48,8 @@ }; TEST_F(SdpPayloadTypeSuggesterTest, SuggestPayloadTypeBasic) { - Codec pcmu_codec = CreateAudioCodec(-1, kPcmuCodecName, 8000, 1); + Codec pcmu_codec = + CreateAudioCodec(PayloadType::NotSet(), kPcmuCodecName, 8000, 1); RTCErrorOr<PayloadType> pcmu_pt = suggester_.SuggestPayloadType("mid", pcmu_codec); ASSERT_TRUE(pcmu_pt.ok()); @@ -63,7 +64,8 @@ offer->contents()[0].media_description()->set_codecs({remote_lyra_codec}); EXPECT_TRUE( suggester_.Update(offer.get(), /* local= */ false, SdpType::kOffer).ok()); - Codec local_lyra_codec = CreateAudioCodec(-1, "lyra", 8000, 1); + Codec local_lyra_codec = + CreateAudioCodec(PayloadType::NotSet(), "lyra", 8000, 1); RTCErrorOr<PayloadType> lyra_pt = suggester_.SuggestPayloadType(kAudioMid1, local_lyra_codec); ASSERT_TRUE(lyra_pt.ok()); @@ -81,12 +83,14 @@ EXPECT_TRUE( suggester_.Update(offer.get(), /* local= */ false, SdpType::kOffer).ok()); // Check that we get the Opus codec back with the remote PT - Codec local_opus_codec = CreateAudioCodec(-1, "opus", 48000, 2); + Codec local_opus_codec = + CreateAudioCodec(PayloadType::NotSet(), "opus", 48000, 2); RTCErrorOr<PayloadType> local_opus_pt = suggester_.SuggestPayloadType(kAudioMid1, local_opus_codec); EXPECT_EQ(local_opus_pt.value(), remote_opus_pt); // Check that we don't get 110 allocated for DTMF, since it's in use for opus - Codec local_other_codec = CreateAudioCodec(-1, kDtmfCodecName, 48000, 1); + Codec local_other_codec = + CreateAudioCodec(PayloadType::NotSet(), kDtmfCodecName, 48000, 1); RTCErrorOr<PayloadType> other_pt = suggester_.SuggestPayloadType(kAudioMid1, local_other_codec); ASSERT_TRUE(other_pt.ok());
diff --git a/pc/simulcast_sdp_serializer.cc b/pc/simulcast_sdp_serializer.cc index 9f35399..68aea17 100644 --- a/pc/simulcast_sdp_serializer.cc +++ b/pc/simulcast_sdp_serializer.cc
@@ -19,6 +19,7 @@ #include "absl/algorithm/container.h" #include "absl/strings/string_view.h" +#include "api/payload_type.h" #include "api/rtc_error.h" #include "api/rtp_parameters.h" #include "media/base/codec.h" @@ -302,7 +303,7 @@ if (it == media_desc.codecs().end()) { break; } - if (it->id == Codec::kIdNotSet) { + if (it->id == PayloadType::NotSet()) { RTC_DCHECK_NOTREACHED(); break; }
diff --git a/rtc_base/strong_alias.h b/rtc_base/strong_alias.h index 548253d..8071a7e 100644 --- a/rtc_base/strong_alias.h +++ b/rtc_base/strong_alias.h
@@ -68,6 +68,13 @@ protected: UnderlyingType value_; + + private: + // Helper function for using abseil hash types. + template <typename H> + friend H AbslHashValue(H h, const StrongAlias& st) { + return H::combine(std::move(h), st.value_); + } }; } // namespace webrtc