chromium/third_party/webrtc/pc/webrtc_sdp.cc

/*
 *  Copyright 2011 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

#include "pc/webrtc_sdp.h"

#include <ctype.h>
#include <limits.h>

#include <algorithm>
#include <cstddef>
#include <cstdint>
#include <map>
#include <memory>
#include <set>
#include <string>
#include <type_traits>
#include <unordered_map>
#include <utility>
#include <vector>

#include "absl/algorithm/container.h"
#include "absl/strings/ascii.h"
#include "absl/strings/match.h"
#include "api/candidate.h"
#include "api/jsep_ice_candidate.h"
#include "api/jsep_session_description.h"
#include "api/media_types.h"
// for RtpExtension
#include "absl/strings/string_view.h"
#include "absl/types/optional.h"
#include "api/rtc_error.h"
#include "api/rtp_parameters.h"
#include "api/rtp_transceiver_direction.h"
#include "media/base/codec.h"
#include "media/base/media_constants.h"
#include "media/base/rid_description.h"
#include "media/base/rtp_utils.h"
#include "media/base/stream_params.h"
#include "media/sctp/sctp_transport_internal.h"
#include "p2p/base/candidate_pair_interface.h"
#include "p2p/base/ice_transport_internal.h"
#include "p2p/base/p2p_constants.h"
#include "p2p/base/port.h"
#include "p2p/base/port_interface.h"
#include "p2p/base/transport_description.h"
#include "p2p/base/transport_info.h"
#include "pc/media_protocol_names.h"
#include "pc/media_session.h"
#include "pc/session_description.h"
#include "pc/simulcast_description.h"
#include "pc/simulcast_sdp_serializer.h"
#include "rtc_base/arraysize.h"
#include "rtc_base/checks.h"
#include "rtc_base/crypto_random.h"
#include "rtc_base/ip_address.h"
#include "rtc_base/logging.h"
#include "rtc_base/net_helper.h"
#include "rtc_base/network_constants.h"
#include "rtc_base/socket_address.h"
#include "rtc_base/ssl_fingerprint.h"
#include "rtc_base/string_encode.h"
#include "rtc_base/string_utils.h"
#include "rtc_base/strings/string_builder.h"

AudioContentDescription;
Candidate;
Candidates;
ContentInfo;
ICE_CANDIDATE_COMPONENT_RTCP;
ICE_CANDIDATE_COMPONENT_RTP;
kApplicationSpecificBandwidth;
kCodecParamMaxPTime;
kCodecParamMinPTime;
kCodecParamPTime;
kTransportSpecificBandwidth;
MediaContentDescription;
MediaProtocolType;
MediaType;
RidDescription;
RtpHeaderExtensions;
SctpDataContentDescription;
SimulcastDescription;
SimulcastLayer;
SimulcastLayerList;
SsrcGroup;
StreamParams;
StreamParamsVec;
TransportDescription;
TransportInfo;
UnsupportedContentDescription;
VideoContentDescription;
SocketAddress;

// TODO(deadbeef): Switch to using anonymous namespace rather than declaring
// everything "static".
namespace webrtc {

// Line type
// RFC 4566
// An SDP session description consists of a number of lines of text of
// the form:
// <type>=<value>
// where <type> MUST be exactly one case-significant character.

// Check if passed character is a "token-char" from RFC 4566.
// https://datatracker.ietf.org/doc/html/rfc4566#section-9
//    token-char =          %x21 / %x23-27 / %x2A-2B / %x2D-2E / %x30-39
//                         / %x41-5A / %x5E-7E
bool IsTokenChar(char ch) {}
static const int kLinePrefixLength =;  // Length of <type>=
static const char kLineTypeVersion =;
static const char kLineTypeOrigin =;
static const char kLineTypeSessionName =;
static const char kLineTypeSessionInfo =;
static const char kLineTypeSessionUri =;
static const char kLineTypeSessionEmail =;
static const char kLineTypeSessionPhone =;
static const char kLineTypeSessionBandwidth =;
static const char kLineTypeTiming =;
static const char kLineTypeRepeatTimes =;
static const char kLineTypeTimeZone =;
static const char kLineTypeEncryptionKey =;
static const char kLineTypeMedia =;
static const char kLineTypeConnection =;
static const char kLineTypeAttributes =;

// Attributes
static const char kAttributeGroup[] =;
static const char kAttributeMid[] =;
static const char kAttributeMsid[] =;
static const char kAttributeBundleOnly[] =;
static const char kAttributeRtcpMux[] =;
static const char kAttributeRtcpReducedSize[] =;
static const char kAttributeSsrc[] =;
static const char kSsrcAttributeCname[] =;
static const char kAttributeExtmapAllowMixed[] =;
static const char kAttributeExtmap[] =;
// draft-alvestrand-mmusic-msid-01
// a=msid-semantic: WMS
// This is a legacy field supported only for Plan B semantics.
static const char kAttributeMsidSemantics[] =;
static const char kMediaStreamSemantic[] =;
static const char kSsrcAttributeMsid[] =;
static const char kDefaultMsid[] =;
static const char kNoStreamMsid[] =;
static const char kAttributeSsrcGroup[] =;
static const char kAttributeCandidate[] =;
static const char kAttributeCandidateTyp[] =;
static const char kAttributeCandidateRaddr[] =;
static const char kAttributeCandidateRport[] =;
static const char kAttributeCandidateUfrag[] =;
static const char kAttributeCandidatePwd[] =;
static const char kAttributeCandidateGeneration[] =;
static const char kAttributeCandidateNetworkId[] =;
static const char kAttributeCandidateNetworkCost[] =;
static const char kAttributeFingerprint[] =;
static const char kAttributeSetup[] =;
static const char kAttributeFmtp[] =;
static const char kAttributeRtpmap[] =;
static const char kAttributeSctpmap[] =;
static const char kAttributeRtcp[] =;
static const char kAttributeIceUfrag[] =;
static const char kAttributeIcePwd[] =;
static const char kAttributeIceLite[] =;
static const char kAttributeIceOption[] =;
static const char kAttributeSendOnly[] =;
static const char kAttributeRecvOnly[] =;
static const char kAttributeRtcpFb[] =;
static const char kAttributeSendRecv[] =;
static const char kAttributeInactive[] =;
// draft-ietf-mmusic-sctp-sdp-26
// a=sctp-port, a=max-message-size
static const char kAttributeSctpPort[] =;
static const char kAttributeMaxMessageSize[] =;
static const int kDefaultSctpMaxMessageSize =;
// draft-ietf-mmusic-sdp-simulcast-13
// a=simulcast
static const char kAttributeSimulcast[] =;
// draft-ietf-mmusic-rid-15
// a=rid
static const char kAttributeRid[] =;
static const char kAttributePacketization[] =;

// Experimental flags
static const char kAttributeXGoogleFlag[] =;
static const char kValueConference[] =;

static const char kAttributeRtcpRemoteEstimate[] =;

// Candidate
static const char kCandidateHost[] =;
static const char kCandidateSrflx[] =;
static const char kCandidatePrflx[] =;
static const char kCandidateRelay[] =;
static const char kTcpCandidateType[] =;

// rtc::StringBuilder doesn't have a << overload for chars, while rtc::split and
// rtc::tokenize_first both take a char delimiter. To handle both cases these
// constants come in pairs of a chars and length-one strings.
static const char kSdpDelimiterEqual[] =;
static const char kSdpDelimiterEqualChar =;
static const char kSdpDelimiterSpace[] =;
static const char kSdpDelimiterSpaceChar =;
static const char kSdpDelimiterColon[] =;
static const char kSdpDelimiterColonChar =;
static const char kSdpDelimiterSemicolon[] =;
static const char kSdpDelimiterSemicolonChar =;
static const char kSdpDelimiterSlashChar =;
static const char kNewLineChar =;
static const char kReturnChar =;
static const char kLineBreak[] =;

// TODO(deadbeef): Generate the Session and Time description
// instead of hardcoding.
static const char kSessionVersion[] =;
// RFC 4566
static const char kSessionOriginUsername[] =;
static const char kSessionOriginSessionId[] =;
static const char kSessionOriginSessionVersion[] =;
static const char kSessionOriginNettype[] =;
static const char kSessionOriginAddrtype[] =;
static const char kSessionOriginAddress[] =;
static const char kSessionName[] =;
static const char kTimeDescription[] =;
static const char kAttrGroup[] =;
static const char kConnectionNettype[] =;
static const char kConnectionIpv4Addrtype[] =;
static const char kConnectionIpv6Addrtype[] =;
static const char kMediaTypeVideo[] =;
static const char kMediaTypeAudio[] =;
static const char kMediaTypeData[] =;
static const char kMediaPortRejected[] =;
// draft-ietf-mmusic-trickle-ice-01
// When no candidates have been gathered, set the connection
// address to IP6 ::.
// TODO(perkj): FF can not parse IP6 ::. See http://crbug/430333
// Use IPV4 per default.
static const char kDummyAddress[] =;
static const char kDummyPort[] =;

static const char kDefaultSctpmapProtocol[] =;

// RTP payload type is in the 0-127 range. Use -1 to indicate "all" payload
// types.
const int kWildcardPayloadType =;

// Maximum number of channels allowed.
static const size_t kMaxNumberOfChannels =;

struct SsrcInfo {};
SsrcInfoVec;
SsrcGroupVec;

static void BuildMediaDescription(const ContentInfo* content_info,
                                  const TransportInfo* transport_info,
                                  const cricket::MediaType media_type,
                                  const std::vector<Candidate>& candidates,
                                  int msid_signaling,
                                  std::string* message);
static void BuildMediaLine(const cricket::MediaType media_type,
                           const ContentInfo* content_info,
                           const MediaContentDescription* media_desc,
                           std::string* message);
static void BuildRtpContentAttributes(const MediaContentDescription* media_desc,
                                      const cricket::MediaType media_type,
                                      int msid_signaling,
                                      std::string* message);
static void BuildRtpHeaderExtensions(const RtpHeaderExtensions& extensions,
                                     std::string* message);
static void BuildRtpmap(const MediaContentDescription* media_desc,
                        const cricket::MediaType media_type,
                        std::string* message);
static void BuildCandidate(const std::vector<Candidate>& candidates,
                           bool include_ufrag,
                           std::string* message);
static void BuildIceUfragPwd(const TransportInfo* transport_info,
                             std::string* message);
static void BuildDtlsFingerprintSetup(const TransportInfo* transport_info,
                                      std::string* message);
static void BuildIceOptions(const std::vector<std::string>& transport_options,
                            std::string* message);
static bool ParseSessionDescription(absl::string_view message,
                                    size_t* pos,
                                    std::string* session_id,
                                    std::string* session_version,
                                    TransportDescription* session_td,
                                    RtpHeaderExtensions* session_extmaps,
                                    rtc::SocketAddress* connection_addr,
                                    cricket::SessionDescription* desc,
                                    SdpParseError* error);
static bool ParseMediaDescription(
    absl::string_view message,
    const TransportDescription& session_td,
    const RtpHeaderExtensions& session_extmaps,
    size_t* pos,
    const rtc::SocketAddress& session_connection_addr,
    cricket::SessionDescription* desc,
    std::vector<std::unique_ptr<JsepIceCandidate>>* candidates,
    SdpParseError* error);
static bool ParseContent(
    absl::string_view message,
    const cricket::MediaType media_type,
    int mline_index,
    absl::string_view protocol,
    const std::vector<int>& payload_types,
    size_t* pos,
    std::string* content_name,
    bool* bundle_only,
    int* msid_signaling,
    MediaContentDescription* media_desc,
    TransportDescription* transport,
    std::vector<std::unique_ptr<JsepIceCandidate>>* candidates,
    SdpParseError* error);
static bool ParseGroupAttribute(absl::string_view line,
                                cricket::SessionDescription* desc,
                                SdpParseError* error);
static bool ParseSsrcAttribute(absl::string_view line,
                               SsrcInfoVec* ssrc_infos,
                               int* msid_signaling,
                               SdpParseError* error);
static bool ParseSsrcGroupAttribute(absl::string_view line,
                                    SsrcGroupVec* ssrc_groups,
                                    SdpParseError* error);
static bool ParseRtpmapAttribute(absl::string_view line,
                                 const cricket::MediaType media_type,
                                 const std::vector<int>& payload_types,
                                 MediaContentDescription* media_desc,
                                 SdpParseError* error);
static bool ParseFmtpAttributes(absl::string_view line,
                                const cricket::MediaType media_type,
                                MediaContentDescription* media_desc,
                                SdpParseError* error);
static bool ParseFmtpParam(absl::string_view line,
                           std::string* parameter,
                           std::string* value,
                           SdpParseError* error);
static bool ParsePacketizationAttribute(absl::string_view line,
                                        const cricket::MediaType media_type,
                                        MediaContentDescription* media_desc,
                                        SdpParseError* error);
static bool ParseRtcpFbAttribute(absl::string_view line,
                                 const cricket::MediaType media_type,
                                 MediaContentDescription* media_desc,
                                 SdpParseError* error);
static bool ParseIceOptions(absl::string_view line,
                            std::vector<std::string>* transport_options,
                            SdpParseError* error);
static bool ParseExtmap(absl::string_view line,
                        RtpExtension* extmap,
                        SdpParseError* error);
static bool ParseFingerprintAttribute(
    absl::string_view line,
    std::unique_ptr<rtc::SSLFingerprint>* fingerprint,
    SdpParseError* error);
static bool ParseDtlsSetup(absl::string_view line,
                           cricket::ConnectionRole* role,
                           SdpParseError* error);
static bool ParseMsidAttribute(absl::string_view line,
                               std::vector<std::string>* stream_ids,
                               std::string* track_id,
                               SdpParseError* error);

static void RemoveInvalidRidDescriptions(const std::vector<int>& payload_types,
                                         std::vector<RidDescription>* rids);

static SimulcastLayerList RemoveRidsFromSimulcastLayerList(
    const std::set<std::string>& to_remove,
    const SimulcastLayerList& layers);

static void RemoveInvalidRidsFromSimulcast(
    const std::vector<RidDescription>& rids,
    SimulcastDescription* simulcast);

// Helper functions

// Below ParseFailed*** functions output the line that caused the parsing
// failure and the detailed reason (`description`) of the failure to `error`.
// The functions always return false so that they can be used directly in the
// following way when error happens:
// "return ParseFailed***(...);"

// The line starting at `line_start` of `message` is the failing line.
// The reason for the failure should be provided in the `description`.
// An example of a description could be "unknown character".
static bool ParseFailed(absl::string_view message,
                        size_t line_start,
                        std::string description,
                        SdpParseError* error) {}

// `line` is the failing line. The reason for the failure should be
// provided in the `description`.
static bool ParseFailed(absl::string_view line,
                        std::string description,
                        SdpParseError* error) {}

// Parses failure where the failing SDP line isn't know or there are multiple
// failing lines.
static bool ParseFailed(std::string description, SdpParseError* error) {}

// `line` is the failing line. The failure is due to the fact that `line`
// doesn't have `expected_fields` fields.
static bool ParseFailedExpectFieldNum(absl::string_view line,
                                      int expected_fields,
                                      SdpParseError* error) {}

// `line` is the failing line. The failure is due to the fact that `line` has
// less than `expected_min_fields` fields.
static bool ParseFailedExpectMinFieldNum(absl::string_view line,
                                         int expected_min_fields,
                                         SdpParseError* error) {}

// `line` is the failing line. The failure is due to the fact that it failed to
// get the value of `attribute`.
static bool ParseFailedGetValue(absl::string_view line,
                                absl::string_view attribute,
                                SdpParseError* error) {}

// The line starting at `line_start` of `message` is the failing line. The
// failure is due to the line type (e.g. the "m" part of the "m-line")
// not matching what is expected. The expected line type should be
// provided as `line_type`.
static bool ParseFailedExpectLine(absl::string_view message,
                                  size_t line_start,
                                  const char line_type,
                                  absl::string_view line_value,
                                  SdpParseError* error) {}

static bool AddLine(absl::string_view line, std::string* message) {}

// Trim return character, if any.
static absl::string_view TrimReturnChar(absl::string_view line) {}

// Gets line of `message` starting at `pos`, and checks overall SDP syntax. On
// success, advances `pos` to the next line.
static absl::optional<absl::string_view> GetLine(absl::string_view message,
                                                 size_t* pos) {}

// Init `os` to "`type`=`value`".
static void InitLine(const char type,
                     absl::string_view value,
                     rtc::StringBuilder* os) {}

// Init `os` to "a=`attribute`".
static void InitAttrLine(absl::string_view attribute, rtc::StringBuilder* os) {}

// Writes a SDP attribute line based on `attribute` and `value` to `message`.
static void AddAttributeLine(absl::string_view attribute,
                             int value,
                             std::string* message) {}

static bool IsLineType(absl::string_view message,
                       const char type,
                       size_t line_start) {}

static bool IsLineType(absl::string_view line, const char type) {}

static absl::optional<absl::string_view>
GetLineWithType(absl::string_view message, size_t* pos, const char type) {}

static bool HasAttribute(absl::string_view line, absl::string_view attribute) {}

static bool AddSsrcLine(uint32_t ssrc_id,
                        absl::string_view attribute,
                        absl::string_view value,
                        std::string* message) {}

// Get value only from <attribute>:<value>.
static bool GetValue(absl::string_view message,
                     absl::string_view attribute,
                     std::string* value,
                     SdpParseError* error) {}

// Get a single [token] from <attribute>:<token>
static bool GetSingleTokenValue(absl::string_view message,
                                absl::string_view attribute,
                                std::string* value,
                                SdpParseError* error) {}

static bool CaseInsensitiveFind(std::string str1, std::string str2) {}

template <class T>
static bool GetValueFromString(absl::string_view line,
                               absl::string_view s,
                               T* t,
                               SdpParseError* error) {}

static bool GetPayloadTypeFromString(absl::string_view line,
                                     absl::string_view s,
                                     int* payload_type,
                                     SdpParseError* error) {}

// Creates a StreamParams track in the case when no SSRC lines are signaled.
// This is a track that does not contain SSRCs and only contains
// stream_ids/track_id if it's signaled with a=msid lines.
void CreateTrackWithNoSsrcs(const std::vector<std::string>& msid_stream_ids,
                            absl::string_view msid_track_id,
                            const std::vector<RidDescription>& rids,
                            StreamParamsVec* tracks) {}

// Creates the StreamParams tracks, for the case when SSRC lines are signaled.
// `msid_stream_ids` and `msid_track_id` represent the stream/track ID from the
// "a=msid" attribute, if it exists. They are empty if the attribute does not
// exist. We prioritize getting stream_ids/track_ids signaled in a=msid lines.
void CreateTracksFromSsrcInfos(const SsrcInfoVec& ssrc_infos,
                               const std::vector<std::string>& msid_stream_ids,
                               absl::string_view msid_track_id,
                               StreamParamsVec* tracks,
                               int msid_signaling) {}

void GetMediaStreamIds(const ContentInfo* content,
                       std::set<std::string>* labels) {}

// Get ip and port of the default destination from the `candidates` with the
// given value of `component_id`. The default candidate should be the one most
// likely to work, typically IPv4 relay.
// RFC 5245
// The value of `component_id` currently supported are 1 (RTP) and 2 (RTCP).
// TODO(deadbeef): Decide the default destination in webrtcsession and
// pass it down via SessionDescription.
static void GetDefaultDestination(const std::vector<Candidate>& candidates,
                                  int component_id,
                                  std::string* port,
                                  std::string* ip,
                                  std::string* addr_type) {}

// Gets "a=rtcp" line if found default RTCP candidate from `candidates`.
static std::string GetRtcpLine(const std::vector<Candidate>& candidates) {}

// Get candidates according to the mline index from SessionDescriptionInterface.
static void GetCandidatesByMindex(const SessionDescriptionInterface& desci,
                                  int mline_index,
                                  std::vector<Candidate>* candidates) {}

static bool IsValidPort(int port) {}

std::string SdpSerialize(const JsepSessionDescription& jdesc) {}

// Serializes the passed in IceCandidateInterface to a SDP string.
// candidate - The candidate to be serialized.
std::string SdpSerializeCandidate(const IceCandidateInterface& candidate) {}

// Serializes a cricket Candidate.
std::string SdpSerializeCandidate(const cricket::Candidate& candidate) {}

bool SdpDeserialize(absl::string_view message,
                    JsepSessionDescription* jdesc,
                    SdpParseError* error) {}

bool SdpDeserializeCandidate(absl::string_view message,
                             JsepIceCandidate* jcandidate,
                             SdpParseError* error) {}

bool SdpDeserializeCandidate(absl::string_view transport_name,
                             absl::string_view message,
                             cricket::Candidate* candidate,
                             SdpParseError* error) {}

bool ParseCandidate(absl::string_view message,
                    Candidate* candidate,
                    SdpParseError* error,
                    bool is_raw) {}

bool ParseIceOptions(absl::string_view line,
                     std::vector<std::string>* transport_options,
                     SdpParseError* error) {}

bool ParseSctpPort(absl::string_view line,
                   int* sctp_port,
                   SdpParseError* error) {}

bool ParseSctpMaxMessageSize(absl::string_view line,
                             int* max_message_size,
                             SdpParseError* error) {}

bool ParseExtmap(absl::string_view line,
                 RtpExtension* extmap,
                 SdpParseError* error) {}

static void BuildSctpContentAttributes(
    std::string* message,
    const cricket::SctpDataContentDescription* data_desc) {}

void BuildIceUfragPwd(const TransportInfo* transport_info,
                      std::string* message) {}

void BuildDtlsFingerprintSetup(const TransportInfo* transport_info,
                               std::string* message) {}

void BuildMediaLine(const cricket::MediaType media_type,
                    const ContentInfo* content_info,
                    const MediaContentDescription* media_desc,
                    std::string* message) {}

void BuildMediaDescription(const ContentInfo* content_info,
                           const TransportInfo* transport_info,
                           const cricket::MediaType media_type,
                           const std::vector<Candidate>& candidates,
                           int msid_signaling,
                           std::string* message) {}

void BuildRtpContentAttributes(const MediaContentDescription* media_desc,
                               const cricket::MediaType media_type,
                               int msid_signaling,
                               std::string* message) {}

void BuildRtpHeaderExtensions(const RtpHeaderExtensions& extensions,
                              std::string* message) {}

void WriteFmtpHeader(int payload_type, rtc::StringBuilder* os) {}

void WritePacketizationHeader(int payload_type, rtc::StringBuilder* os) {}

void WriteRtcpFbHeader(int payload_type, rtc::StringBuilder* os) {}

void WriteFmtpParameter(absl::string_view parameter_name,
                        absl::string_view parameter_value,
                        rtc::StringBuilder* os) {}

bool IsFmtpParam(absl::string_view name) {}

bool WriteFmtpParameters(const webrtc::CodecParameterMap& parameters,
                         rtc::StringBuilder* os) {}

void AddFmtpLine(const cricket::Codec& codec, std::string* message) {}

void AddPacketizationLine(const cricket::Codec& codec, std::string* message) {}

void AddRtcpFbLines(const cricket::Codec& codec, std::string* message) {}

bool GetMinValue(const std::vector<int>& values, int* value) {}

bool GetParameter(const std::string& name,
                  const webrtc::CodecParameterMap& params,
                  int* value) {}

void BuildRtpmap(const MediaContentDescription* media_desc,
                 const cricket::MediaType media_type,
                 std::string* message) {}

void BuildCandidate(const std::vector<Candidate>& candidates,
                    bool include_ufrag,
                    std::string* message) {}

void BuildIceOptions(const std::vector<std::string>& transport_options,
                     std::string* message) {}

bool ParseConnectionData(absl::string_view line,
                         rtc::SocketAddress* addr,
                         SdpParseError* error) {}

bool ParseSessionDescription(absl::string_view message,
                             size_t* pos,
                             std::string* session_id,
                             std::string* session_version,
                             TransportDescription* session_td,
                             RtpHeaderExtensions* session_extmaps,
                             rtc::SocketAddress* connection_addr,
                             cricket::SessionDescription* desc,
                             SdpParseError* error) {}

bool ParseGroupAttribute(absl::string_view line,
                         cricket::SessionDescription* desc,
                         SdpParseError* error) {}

static bool ParseFingerprintAttribute(
    absl::string_view line,
    std::unique_ptr<rtc::SSLFingerprint>* fingerprint,
    SdpParseError* error) {}

static bool ParseDtlsSetup(absl::string_view line,
                           cricket::ConnectionRole* role_ptr,
                           SdpParseError* error) {}

static bool ParseMsidAttribute(absl::string_view line,
                               std::vector<std::string>* stream_ids,
                               std::string* track_id,
                               SdpParseError* error) {}

static void RemoveInvalidRidDescriptions(const std::vector<int>& payload_types,
                                         std::vector<RidDescription>* rids) {}

// Create a new list (because SimulcastLayerList is immutable) without any
// layers that have a rid in the to_remove list.
// If a group of alternatives is empty after removing layers, the group should
// be removed altogether.
static SimulcastLayerList RemoveRidsFromSimulcastLayerList(
    const std::set<std::string>& to_remove,
    const SimulcastLayerList& layers) {}

// Will remove Simulcast Layers if:
// 1. They appear in both send and receive directions.
// 2. They do not appear in the list of `valid_rids`.
static void RemoveInvalidRidsFromSimulcast(
    const std::vector<RidDescription>& valid_rids,
    SimulcastDescription* simulcast) {}

// RFC 3551
//  PT   encoding    media type  clock rate   channels
//                      name                    (Hz)
//  0    PCMU        A            8,000       1
//  1    reserved    A
//  2    reserved    A
//  3    GSM         A            8,000       1
//  4    G723        A            8,000       1
//  5    DVI4        A            8,000       1
//  6    DVI4        A           16,000       1
//  7    LPC         A            8,000       1
//  8    PCMA        A            8,000       1
//  9    G722        A            8,000       1
//  10   L16         A           44,100       2
//  11   L16         A           44,100       1
//  12   QCELP       A            8,000       1
//  13   CN          A            8,000       1
//  14   MPA         A           90,000       (see text)
//  15   G728        A            8,000       1
//  16   DVI4        A           11,025       1
//  17   DVI4        A           22,050       1
//  18   G729        A            8,000       1
struct StaticPayloadAudioCodec {};
static const StaticPayloadAudioCodec kStaticPayloadAudioCodecs[] =;

void MaybeCreateStaticPayloadAudioCodecs(const std::vector<int>& fmts,
                                         MediaContentDescription* media_desc) {}

static void BackfillCodecParameters(std::vector<cricket::Codec>& codecs) {}

static std::unique_ptr<MediaContentDescription> ParseContentDescription(
    absl::string_view message,
    const cricket::MediaType media_type,
    int mline_index,
    absl::string_view protocol,
    const std::vector<int>& payload_types,
    size_t* pos,
    std::string* content_name,
    bool* bundle_only,
    int* msid_signaling,
    TransportDescription* transport,
    std::vector<std::unique_ptr<JsepIceCandidate>>* candidates,
    SdpParseError* error) {}

bool HasDuplicateMsidLines(cricket::SessionDescription* desc) {}

bool ParseMediaDescription(
    absl::string_view message,
    const TransportDescription& session_td,
    const RtpHeaderExtensions& session_extmaps,
    size_t* pos,
    const rtc::SocketAddress& session_connection_addr,
    cricket::SessionDescription* desc,
    std::vector<std::unique_ptr<JsepIceCandidate>>* candidates,
    SdpParseError* error) {}

void AddParameters(const webrtc::CodecParameterMap& parameters,
                   cricket::Codec* codec) {}

void AddFeedbackParameter(const cricket::FeedbackParam& feedback_param,
                          cricket::Codec* codec) {}

void AddFeedbackParameters(const cricket::FeedbackParams& feedback_params,
                           cricket::Codec* codec) {}

// Gets the current codec setting associated with `payload_type`. If there
// is no Codec associated with that payload type it returns an empty codec
// with that payload type.
cricket::Codec GetCodecWithPayloadType(
    cricket::MediaType type,
    const std::vector<cricket::Codec>& codecs,
    int payload_type) {}

// Updates or creates a new codec entry in the media description.
void AddOrReplaceCodec(MediaContentDescription* content_desc,
                       const cricket::Codec& codec) {}

// Adds or updates existing codec corresponding to `payload_type` according
// to `parameters`.
void UpdateCodec(MediaContentDescription* content_desc,
                 int payload_type,
                 const webrtc::CodecParameterMap& parameters) {}

// Adds or updates existing codec corresponding to `payload_type` according
// to `feedback_param`.
void UpdateCodec(MediaContentDescription* content_desc,
                 int payload_type,
                 const cricket::FeedbackParam& feedback_param) {}

// Adds or updates existing video codec corresponding to `payload_type`
// according to `packetization`.
void UpdateVideoCodecPacketization(MediaContentDescription* desc,
                                   int payload_type,
                                   absl::string_view packetization) {}

absl::optional<cricket::Codec> PopWildcardCodec(
    std::vector<cricket::Codec>* codecs) {}

void UpdateFromWildcardCodecs(cricket::MediaContentDescription* desc) {}

void AddAudioAttribute(const std::string& name,
                       absl::string_view value,
                       MediaContentDescription* desc) {}

bool ParseContent(absl::string_view message,
                  const cricket::MediaType media_type,
                  int mline_index,
                  absl::string_view protocol,
                  const std::vector<int>& payload_types,
                  size_t* pos,
                  std::string* content_name,
                  bool* bundle_only,
                  int* msid_signaling,
                  MediaContentDescription* media_desc,
                  TransportDescription* transport,
                  std::vector<std::unique_ptr<JsepIceCandidate>>* candidates,
                  SdpParseError* error) {}

bool ParseSsrcAttribute(absl::string_view line,
                        SsrcInfoVec* ssrc_infos,
                        int* msid_signaling,
                        SdpParseError* error) {}

bool ParseSsrcGroupAttribute(absl::string_view line,
                             SsrcGroupVec* ssrc_groups,
                             SdpParseError* error) {}

// Updates or creates a new codec entry in the audio description with according
// to `name`, `clockrate`, `bitrate`, and `channels`.
void UpdateCodec(int payload_type,
                 absl::string_view name,
                 int clockrate,
                 int bitrate,
                 size_t channels,
                 MediaContentDescription* desc) {}

// Updates or creates a new codec entry in the video description according to
// `name`, `width`, `height`, and `framerate`.
void UpdateCodec(int payload_type,
                 absl::string_view name,
                 MediaContentDescription* desc) {}

bool ParseRtpmapAttribute(absl::string_view line,
                          const cricket::MediaType media_type,
                          const std::vector<int>& payload_types,
                          MediaContentDescription* media_desc,
                          SdpParseError* error) {}

bool ParseFmtpParam(absl::string_view line,
                    std::string* parameter,
                    std::string* value,
                    SdpParseError* error) {}

bool ParseFmtpParameterSet(absl::string_view line_params,
                           webrtc::CodecParameterMap& codec_params,
                           SdpParseError* error) {}

bool ParseFmtpAttributes(absl::string_view line,
                         const cricket::MediaType media_type,
                         MediaContentDescription* media_desc,
                         SdpParseError* error) {}

bool ParsePacketizationAttribute(absl::string_view line,
                                 const cricket::MediaType media_type,
                                 MediaContentDescription* media_desc,
                                 SdpParseError* error) {}

bool ParseRtcpFbAttribute(absl::string_view line,
                          const cricket::MediaType media_type,
                          MediaContentDescription* media_desc,
                          SdpParseError* error) {}

}  // namespace webrtc