xref: /aosp_15_r20/external/webrtc/media/engine/payload_type_mapper.cc (revision d9f758449e529ab9291ac668be2861e7a55c2422)
1 /*
2  *  Copyright (c) 2016 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 #include "media/engine/payload_type_mapper.h"
12 
13 #include <utility>
14 
15 #include "absl/strings/ascii.h"
16 #include "api/audio_codecs/audio_format.h"
17 #include "media/base/media_constants.h"
18 
19 namespace cricket {
20 
AudioCodecToSdpAudioFormat(const AudioCodec & ac)21 webrtc::SdpAudioFormat AudioCodecToSdpAudioFormat(const AudioCodec& ac) {
22   return webrtc::SdpAudioFormat(ac.name, ac.clockrate, ac.channels, ac.params);
23 }
24 
PayloadTypeMapper()25 PayloadTypeMapper::PayloadTypeMapper()
26     // RFC 3551 reserves payload type numbers in the range 96-127 exclusively
27     // for dynamic assignment. Once those are used up, it is recommended that
28     // payload types unassigned by the RFC are used for dynamic payload type
29     // mapping, before any static payload ids. At this point, we only support
30     // mapping within the exclusive range.
31     : next_unused_payload_type_(96),
32       max_payload_type_(127),
33       mappings_(
34           {// Static payload type assignments according to RFC 3551.
35            {{kPcmuCodecName, 8000, 1}, 0},
36            {{"GSM", 8000, 1}, 3},
37            {{"G723", 8000, 1}, 4},
38            {{"DVI4", 8000, 1}, 5},
39            {{"DVI4", 16000, 1}, 6},
40            {{"LPC", 8000, 1}, 7},
41            {{kPcmaCodecName, 8000, 1}, 8},
42            {{kG722CodecName, 8000, 1}, 9},
43            {{kL16CodecName, 44100, 2}, 10},
44            {{kL16CodecName, 44100, 1}, 11},
45            {{"QCELP", 8000, 1}, 12},
46            {{kCnCodecName, 8000, 1}, 13},
47            // RFC 4566 is a bit ambiguous on the contents of the "encoding
48            // parameters" field, which, for audio, encodes the number of
49            // channels. It is "optional and may be omitted if the number of
50            // channels is one". Does that necessarily imply that an omitted
51            // encoding parameter means one channel?  Since RFC 3551 doesn't
52            // specify a value for this parameter for MPA, I've included both 0
53            // and 1 here, to increase the chances it will be correctly used if
54            // someone implements an MPEG audio encoder/decoder.
55            {{"MPA", 90000, 0}, 14},
56            {{"MPA", 90000, 1}, 14},
57            {{"G728", 8000, 1}, 15},
58            {{"DVI4", 11025, 1}, 16},
59            {{"DVI4", 22050, 1}, 17},
60            {{"G729", 8000, 1}, 18},
61 
62            // Payload type assignments currently used by WebRTC.
63            // Includes data to reduce collisions (and thus reassignments)
64            {{kIlbcCodecName, 8000, 1}, 102},
65            {{kIsacCodecName, 16000, 1}, 103},
66            {{kIsacCodecName, 32000, 1}, 104},
67            {{kCnCodecName, 16000, 1}, 105},
68            {{kCnCodecName, 32000, 1}, 106},
69            {{kOpusCodecName,
70              48000,
71              2,
72              {{kCodecParamMinPTime, "10"},
73               {kCodecParamUseInbandFec, kParamValueTrue}}},
74             111},
75            // RED for opus is assigned in the lower range, starting at the top.
76            // Note that the FMTP refers to the opus payload type.
77            {{kRedCodecName,
78              48000,
79              2,
80              {{kCodecParamNotInNameValueFormat, "111/111"}}},
81             63},
82            // TODO(solenberg): Remove the hard coded 16k,32k,48k DTMF once we
83            // assign payload types dynamically for send side as well.
84            {{kDtmfCodecName, 48000, 1}, 110},
85            {{kDtmfCodecName, 32000, 1}, 112},
86            {{kDtmfCodecName, 16000, 1}, 113},
87            {{kDtmfCodecName, 8000, 1}, 126}}) {
88   // TODO(ossu): Try to keep this as change-proof as possible until we're able
89   // to remove the payload type constants from everywhere in the code.
90   for (const auto& mapping : mappings_) {
91     used_payload_types_.insert(mapping.second);
92   }
93 }
94 
95 PayloadTypeMapper::~PayloadTypeMapper() = default;
96 
GetMappingFor(const webrtc::SdpAudioFormat & format)97 absl::optional<int> PayloadTypeMapper::GetMappingFor(
98     const webrtc::SdpAudioFormat& format) {
99   auto iter = mappings_.find(format);
100   if (iter != mappings_.end())
101     return iter->second;
102 
103   for (; next_unused_payload_type_ <= max_payload_type_;
104        ++next_unused_payload_type_) {
105     int payload_type = next_unused_payload_type_;
106     if (used_payload_types_.find(payload_type) == used_payload_types_.end()) {
107       used_payload_types_.insert(payload_type);
108       mappings_[format] = payload_type;
109       ++next_unused_payload_type_;
110       return payload_type;
111     }
112   }
113 
114   return absl::nullopt;
115 }
116 
FindMappingFor(const webrtc::SdpAudioFormat & format) const117 absl::optional<int> PayloadTypeMapper::FindMappingFor(
118     const webrtc::SdpAudioFormat& format) const {
119   auto iter = mappings_.find(format);
120   if (iter != mappings_.end())
121     return iter->second;
122 
123   return absl::nullopt;
124 }
125 
ToAudioCodec(const webrtc::SdpAudioFormat & format)126 absl::optional<AudioCodec> PayloadTypeMapper::ToAudioCodec(
127     const webrtc::SdpAudioFormat& format) {
128   // TODO(ossu): We can safely set bitrate to zero here, since that field is
129   // not presented in the SDP. It is used to ferry around some target bitrate
130   // values for certain codecs (ISAC and Opus) and in ways it really
131   // shouldn't. It should be removed once we no longer use CodecInsts in the
132   // ACM or NetEq.
133   auto opt_payload_type = GetMappingFor(format);
134   if (opt_payload_type) {
135     AudioCodec codec(*opt_payload_type, format.name, format.clockrate_hz, 0,
136                      format.num_channels);
137     codec.params = format.parameters;
138     return std::move(codec);
139   }
140 
141   return absl::nullopt;
142 }
143 
operator ()(const webrtc::SdpAudioFormat & a,const webrtc::SdpAudioFormat & b) const144 bool PayloadTypeMapper::SdpAudioFormatOrdering::operator()(
145     const webrtc::SdpAudioFormat& a,
146     const webrtc::SdpAudioFormat& b) const {
147   if (a.clockrate_hz == b.clockrate_hz) {
148     if (a.num_channels == b.num_channels) {
149       int name_cmp =
150           absl::AsciiStrToLower(a.name).compare(absl::AsciiStrToLower(b.name));
151       if (name_cmp == 0)
152         return a.parameters < b.parameters;
153       return name_cmp < 0;
154     }
155     return a.num_channels < b.num_channels;
156   }
157   return a.clockrate_hz < b.clockrate_hz;
158 }
159 
160 }  // namespace cricket
161