Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 


Quelle  RsdparsaSdpAttributeList.cpp   Sprache: C

 
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
 * You can obtain one at http://mozilla.org/MPL/2.0/. */


#include "SdpAttribute.h"
#include "nsCRT.h"

#include "sdp/RsdparsaSdpAttributeList.h"
#include "sdp/RsdparsaSdpInc.h"
#include "sdp/RsdparsaSdpGlue.h"

#include <ostream>
#include "mozilla/Assertions.h"

#include <limits>

namespace mozilla {

MOZ_RUNINIT const std::string RsdparsaSdpAttributeList::kEmptyString = "";

RsdparsaSdpAttributeList::~RsdparsaSdpAttributeList() {
  for (size_t i = 0; i < kNumAttributeTypes; ++i) {
    delete mAttributes[i];
  }
}

bool RsdparsaSdpAttributeList::HasAttribute(AttributeType type,
                                            bool sessionFallback) const {
  return !!GetAttribute(type, sessionFallback);
}

const SdpAttribute* RsdparsaSdpAttributeList::GetAttribute(
    AttributeType type, bool sessionFallback) const {
  const SdpAttribute* value = mAttributes[static_cast<size_t>(type)];
  // Only do fallback when the attribute can appear at both the media and
  // session level
  if (!value && !AtSessionLevel() && sessionFallback &&
      SdpAttribute::IsAllowedAtSessionLevel(type) &&
      SdpAttribute::IsAllowedAtMediaLevel(type)) {
    return mSessionAttributes->GetAttribute(type, false);
  }
  return value;
}

void RsdparsaSdpAttributeList::RemoveAttribute(AttributeType type) {
  delete mAttributes[static_cast<size_t>(type)];
  mAttributes[static_cast<size_t>(type)] = nullptr;
}

void RsdparsaSdpAttributeList::Clear() {
  for (size_t i = 0; i < kNumAttributeTypes; ++i) {
    RemoveAttribute(static_cast<AttributeType>(i));
  }
}

uint32_t RsdparsaSdpAttributeList::Count() const {
  uint32_t count = 0;
  for (size_t i = 0; i < kNumAttributeTypes; ++i) {
    if (mAttributes[i]) {
      count++;
    }
  }
  return count;
}

void RsdparsaSdpAttributeList::SetAttribute(SdpAttribute* attr) {
  if (!IsAllowedHere(attr->GetType())) {
    MOZ_ASSERT(false"This type of attribute is not allowed here");
    delete attr;
    return;
  }
  RemoveAttribute(attr->GetType());
  mAttributes[attr->GetType()] = attr;
}

const std::vector<std::string>& RsdparsaSdpAttributeList::GetCandidate() const {
  if (!HasAttribute(SdpAttribute::kCandidateAttribute)) {
    MOZ_CRASH();
  }

  return static_cast<const SdpMultiStringAttribute*>(
             GetAttribute(SdpAttribute::kCandidateAttribute))
      ->mValues;
}

const SdpConnectionAttribute& RsdparsaSdpAttributeList::GetConnection() const {
  if (!HasAttribute(SdpAttribute::kConnectionAttribute)) {
    MOZ_CRASH();
  }

  return *static_cast<const SdpConnectionAttribute*>(
      GetAttribute(SdpAttribute::kConnectionAttribute));
}

SdpDirectionAttribute::Direction RsdparsaSdpAttributeList::GetDirection()
    const {
  if (!HasAttribute(SdpAttribute::kDirectionAttribute)) {
    MOZ_CRASH();
  }

  const SdpAttribute* attr = GetAttribute(SdpAttribute::kDirectionAttribute);
  return static_cast<const SdpDirectionAttribute*>(attr)->mValue;
}

const SdpDtlsMessageAttribute& RsdparsaSdpAttributeList::GetDtlsMessage()
    const {
  if (!HasAttribute(SdpAttribute::kDtlsMessageAttribute)) {
    MOZ_CRASH();
  }
  const SdpAttribute* attr = GetAttribute(SdpAttribute::kDtlsMessageAttribute);
  return *static_cast<const SdpDtlsMessageAttribute*>(attr);
}

const SdpExtmapAttributeList& RsdparsaSdpAttributeList::GetExtmap() const {
  if (!HasAttribute(SdpAttribute::kExtmapAttribute)) {
    MOZ_CRASH();
  }

  return *static_cast<const SdpExtmapAttributeList*>(
      GetAttribute(SdpAttribute::kExtmapAttribute));
}

const SdpFingerprintAttributeList& RsdparsaSdpAttributeList::GetFingerprint()
    const {
  if (!HasAttribute(SdpAttribute::kFingerprintAttribute)) {
    MOZ_CRASH();
  }
  const SdpAttribute* attr = GetAttribute(SdpAttribute::kFingerprintAttribute);
  return *static_cast<const SdpFingerprintAttributeList*>(attr);
}

const SdpFmtpAttributeList& RsdparsaSdpAttributeList::GetFmtp() const {
  if (!HasAttribute(SdpAttribute::kFmtpAttribute)) {
    MOZ_CRASH();
  }

  return *static_cast<const SdpFmtpAttributeList*>(
      GetAttribute(SdpAttribute::kFmtpAttribute));
}

const SdpGroupAttributeList& RsdparsaSdpAttributeList::GetGroup() const {
  if (!HasAttribute(SdpAttribute::kGroupAttribute)) {
    MOZ_CRASH();
  }

  return *static_cast<const SdpGroupAttributeList*>(
      GetAttribute(SdpAttribute::kGroupAttribute));
}

const SdpOptionsAttribute& RsdparsaSdpAttributeList::GetIceOptions() const {
  if (!HasAttribute(SdpAttribute::kIceOptionsAttribute)) {
    MOZ_CRASH();
  }

  const SdpAttribute* attr = GetAttribute(SdpAttribute::kIceOptionsAttribute);
  return *static_cast<const SdpOptionsAttribute*>(attr);
}

const std::string& RsdparsaSdpAttributeList::GetIcePwd() const {
  if (!HasAttribute(SdpAttribute::kIcePwdAttribute)) {
    return kEmptyString;
  }
  const SdpAttribute* attr = GetAttribute(SdpAttribute::kIcePwdAttribute);
  return static_cast<const SdpStringAttribute*>(attr)->mValue;
}

const std::string& RsdparsaSdpAttributeList::GetIceUfrag() const {
  if (!HasAttribute(SdpAttribute::kIceUfragAttribute)) {
    return kEmptyString;
  }
  const SdpAttribute* attr = GetAttribute(SdpAttribute::kIceUfragAttribute);
  return static_cast<const SdpStringAttribute*>(attr)->mValue;
}

const std::string& RsdparsaSdpAttributeList::GetIdentity() const {
  if (!HasAttribute(SdpAttribute::kIdentityAttribute)) {
    return kEmptyString;
  }
  const SdpAttribute* attr = GetAttribute(SdpAttribute::kIdentityAttribute);
  return static_cast<const SdpStringAttribute*>(attr)->mValue;
}

const SdpImageattrAttributeList& RsdparsaSdpAttributeList::GetImageattr()
    const {
  if (!HasAttribute(SdpAttribute::kImageattrAttribute)) {
    MOZ_CRASH();
  }
  const SdpAttribute* attr = GetAttribute(SdpAttribute::kImageattrAttribute);
  return *static_cast<const SdpImageattrAttributeList*>(attr);
}

const SdpSimulcastAttribute& RsdparsaSdpAttributeList::GetSimulcast() const {
  if (!HasAttribute(SdpAttribute::kSimulcastAttribute)) {
    MOZ_CRASH();
  }
  const SdpAttribute* attr = GetAttribute(SdpAttribute::kSimulcastAttribute);
  return *static_cast<const SdpSimulcastAttribute*>(attr);
}

const std::string& RsdparsaSdpAttributeList::GetLabel() const {
  if (!HasAttribute(SdpAttribute::kLabelAttribute)) {
    return kEmptyString;
  }
  const SdpAttribute* attr = GetAttribute(SdpAttribute::kLabelAttribute);
  return static_cast<const SdpStringAttribute*>(attr)->mValue;
}

uint32_t RsdparsaSdpAttributeList::GetMaxptime() const {
  if (!HasAttribute(SdpAttribute::kMaxptimeAttribute)) {
    MOZ_CRASH();
  }
  const SdpAttribute* attr = GetAttribute(SdpAttribute::kMaxptimeAttribute);
  return static_cast<const SdpNumberAttribute*>(attr)->mValue;
}

const std::string& RsdparsaSdpAttributeList::GetMid() const {
  if (!HasAttribute(SdpAttribute::kMidAttribute)) {
    return kEmptyString;
  }
  const SdpAttribute* attr = GetAttribute(SdpAttribute::kMidAttribute);
  return static_cast<const SdpStringAttribute*>(attr)->mValue;
}

const SdpMsidAttributeList& RsdparsaSdpAttributeList::GetMsid() const {
  if (!HasAttribute(SdpAttribute::kMsidAttribute)) {
    MOZ_CRASH();
  }
  const SdpAttribute* attr = GetAttribute(SdpAttribute::kMsidAttribute);
  return *static_cast<const SdpMsidAttributeList*>(attr);
}

const SdpMsidSemanticAttributeList& RsdparsaSdpAttributeList::GetMsidSemantic()
    const {
  if (!HasAttribute(SdpAttribute::kMsidSemanticAttribute)) {
    MOZ_CRASH();
  }
  const SdpAttribute* attr = GetAttribute(SdpAttribute::kMsidSemanticAttribute);
  return *static_cast<const SdpMsidSemanticAttributeList*>(attr);
}

const SdpRidAttributeList& RsdparsaSdpAttributeList::GetRid() const {
  if (!HasAttribute(SdpAttribute::kRidAttribute)) {
    MOZ_CRASH();
  }
  const SdpAttribute* attr = GetAttribute(SdpAttribute::kRidAttribute);
  return *static_cast<const SdpRidAttributeList*>(attr);
}

uint32_t RsdparsaSdpAttributeList::GetPtime() const {
  if (!HasAttribute(SdpAttribute::kPtimeAttribute)) {
    MOZ_CRASH();
  }
  const SdpAttribute* attr = GetAttribute(SdpAttribute::kPtimeAttribute);
  return static_cast<const SdpNumberAttribute*>(attr)->mValue;
}

const SdpRtcpAttribute& RsdparsaSdpAttributeList::GetRtcp() const {
  if (!HasAttribute(SdpAttribute::kRtcpAttribute)) {
    MOZ_CRASH();
  }
  const SdpAttribute* attr = GetAttribute(SdpAttribute::kRtcpAttribute);
  return *static_cast<const SdpRtcpAttribute*>(attr);
}

const SdpRtcpFbAttributeList& RsdparsaSdpAttributeList::GetRtcpFb() const {
  if (!HasAttribute(SdpAttribute::kRtcpFbAttribute)) {
    MOZ_CRASH();
  }
  const SdpAttribute* attr = GetAttribute(SdpAttribute::kRtcpFbAttribute);
  return *static_cast<const SdpRtcpFbAttributeList*>(attr);
}

const SdpRemoteCandidatesAttribute&
RsdparsaSdpAttributeList::GetRemoteCandidates() const {
  MOZ_CRASH("Not yet implemented");
}

const SdpRtpmapAttributeList& RsdparsaSdpAttributeList::GetRtpmap() const {
  if (!HasAttribute(SdpAttribute::kRtpmapAttribute)) {
    MOZ_CRASH();
  }
  const SdpAttribute* attr = GetAttribute(SdpAttribute::kRtpmapAttribute);
  return *static_cast<const SdpRtpmapAttributeList*>(attr);
}

const SdpSctpmapAttributeList& RsdparsaSdpAttributeList::GetSctpmap() const {
  if (!HasAttribute(SdpAttribute::kSctpmapAttribute)) {
    MOZ_CRASH();
  }
  const SdpAttribute* attr = GetAttribute(SdpAttribute::kSctpmapAttribute);
  return *static_cast<const SdpSctpmapAttributeList*>(attr);
}

uint32_t RsdparsaSdpAttributeList::GetSctpPort() const {
  if (!HasAttribute(SdpAttribute::kSctpPortAttribute)) {
    MOZ_CRASH();
  }

  const SdpAttribute* attr = GetAttribute(SdpAttribute::kSctpPortAttribute);
  return static_cast<const SdpNumberAttribute*>(attr)->mValue;
}

uint32_t RsdparsaSdpAttributeList::GetMaxMessageSize() const {
  if (!HasAttribute(SdpAttribute::kMaxMessageSizeAttribute)) {
    MOZ_CRASH();
  }

  const SdpAttribute* attr =
      GetAttribute(SdpAttribute::kMaxMessageSizeAttribute);
  return static_cast<const SdpNumberAttribute*>(attr)->mValue;
}

const SdpSetupAttribute& RsdparsaSdpAttributeList::GetSetup() const {
  if (!HasAttribute(SdpAttribute::kSetupAttribute)) {
    MOZ_CRASH();
  }
  const SdpAttribute* attr = GetAttribute(SdpAttribute::kSetupAttribute);
  return *static_cast<const SdpSetupAttribute*>(attr);
}

const SdpSsrcAttributeList& RsdparsaSdpAttributeList::GetSsrc() const {
  if (!HasAttribute(SdpAttribute::kSsrcAttribute)) {
    MOZ_CRASH();
  }
  const SdpAttribute* attr = GetAttribute(SdpAttribute::kSsrcAttribute);
  return *static_cast<const SdpSsrcAttributeList*>(attr);
}

const SdpSsrcGroupAttributeList& RsdparsaSdpAttributeList::GetSsrcGroup()
    const {
  if (!HasAttribute(SdpAttribute::kSsrcGroupAttribute)) {
    MOZ_CRASH();
  }
  const SdpAttribute* attr = GetAttribute(SdpAttribute::kSsrcGroupAttribute);
  return *static_cast<const SdpSsrcGroupAttributeList*>(attr);
}

void RsdparsaSdpAttributeList::LoadAttribute(RustAttributeList* attributeList,
                                             AttributeType type) {
  if (!mAttributes[type]) {
    switch (type) {
      case SdpAttribute::kIceUfragAttribute:
        LoadIceUfrag(attributeList);
        return;
      case SdpAttribute::kIcePwdAttribute:
        LoadIcePwd(attributeList);
        return;
      case SdpAttribute::kIceOptionsAttribute:
        LoadIceOptions(attributeList);
        return;
      case SdpAttribute::kDtlsMessageAttribute:
        LoadDtlsMessage(attributeList);
        return;
      case SdpAttribute::kFingerprintAttribute:
        LoadFingerprint(attributeList);
        return;
      case SdpAttribute::kIdentityAttribute:
        LoadIdentity(attributeList);
        return;
      case SdpAttribute::kSetupAttribute:
        LoadSetup(attributeList);
        return;
      case SdpAttribute::kSsrcAttribute:
        LoadSsrc(attributeList);
        return;
      case SdpAttribute::kRtpmapAttribute:
        LoadRtpmap(attributeList);
        return;
      case SdpAttribute::kFmtpAttribute:
        LoadFmtp(attributeList);
        return;
      case SdpAttribute::kPtimeAttribute:
        LoadPtime(attributeList);
        return;
      case SdpAttribute::kIceLiteAttribute:
      case SdpAttribute::kRtcpMuxAttribute:
      case SdpAttribute::kRtcpRsizeAttribute:
      case SdpAttribute::kBundleOnlyAttribute:
      case SdpAttribute::kEndOfCandidatesAttribute:
        LoadFlags(attributeList);
        return;
      case SdpAttribute::kMaxMessageSizeAttribute:
        LoadMaxMessageSize(attributeList);
        return;
      case SdpAttribute::kMidAttribute:
        LoadMid(attributeList);
        return;
      case SdpAttribute::kMsidAttribute:
        LoadMsid(attributeList);
        return;
      case SdpAttribute::kMsidSemanticAttribute:
        LoadMsidSemantics(attributeList);
        return;
      case SdpAttribute::kGroupAttribute:
        LoadGroup(attributeList);
        return;
      case SdpAttribute::kRtcpAttribute:
        LoadRtcp(attributeList);
        return;
      case SdpAttribute::kRtcpFbAttribute:
        LoadRtcpFb(attributeList);
        return;
      case SdpAttribute::kImageattrAttribute:
        LoadImageattr(attributeList);
        return;
      case SdpAttribute::kSctpmapAttribute:
        LoadSctpmaps(attributeList);
        return;
      case SdpAttribute::kDirectionAttribute:
        LoadDirection(attributeList);
        return;
      case SdpAttribute::kRemoteCandidatesAttribute:
        LoadRemoteCandidates(attributeList);
        return;
      case SdpAttribute::kRidAttribute:
        LoadRids(attributeList);
        return;
      case SdpAttribute::kSctpPortAttribute:
        LoadSctpPort(attributeList);
        return;
      case SdpAttribute::kExtmapAttribute:
        LoadExtmap(attributeList);
        return;
      case SdpAttribute::kSimulcastAttribute:
        LoadSimulcast(attributeList);
        return;
      case SdpAttribute::kMaxptimeAttribute:
        LoadMaxPtime(attributeList);
        return;
      case SdpAttribute::kCandidateAttribute:
        LoadCandidate(attributeList);
        return;
      case SdpAttribute::kSsrcGroupAttribute:
        LoadSsrcGroup(attributeList);
        return;
      case SdpAttribute::kConnectionAttribute:
      case SdpAttribute::kIceMismatchAttribute:
      case SdpAttribute::kLabelAttribute:
        // These attributes are unused
        return;
    }
  }
}

void RsdparsaSdpAttributeList::LoadAll(RustAttributeList* attributeList) {
  for (int i = SdpAttribute::kFirstAttribute; i <= SdpAttribute::kLastAttribute;
       i++) {
    LoadAttribute(attributeList, static_cast<SdpAttribute::AttributeType>(i));
  }
}

void RsdparsaSdpAttributeList::LoadIceUfrag(RustAttributeList* attributeList) {
  StringView ufragStr;
  nsresult nr = sdp_get_iceufrag(attributeList, &ufragStr);
  if (NS_SUCCEEDED(nr)) {
    std::string iceufrag = convertStringView(ufragStr);
    SetAttribute(
        new SdpStringAttribute(SdpAttribute::kIceUfragAttribute, iceufrag));
  }
}

void RsdparsaSdpAttributeList::LoadIcePwd(RustAttributeList* attributeList) {
  StringView pwdStr;
  nsresult nr = sdp_get_icepwd(attributeList, &pwdStr);
  if (NS_SUCCEEDED(nr)) {
    std::string icePwd = convertStringView(pwdStr);
    SetAttribute(
        new SdpStringAttribute(SdpAttribute::kIcePwdAttribute, icePwd));
  }
}

void RsdparsaSdpAttributeList::LoadIdentity(RustAttributeList* attributeList) {
  StringView identityStr;
  nsresult nr = sdp_get_identity(attributeList, &identityStr);
  if (NS_SUCCEEDED(nr)) {
    std::string identity = convertStringView(identityStr);
    SetAttribute(
        new SdpStringAttribute(SdpAttribute::kIdentityAttribute, identity));
  }
}

void RsdparsaSdpAttributeList::LoadIceOptions(
    RustAttributeList* attributeList) {
  StringVec* options;
  nsresult nr = sdp_get_iceoptions(attributeList, &options);
  if (NS_SUCCEEDED(nr)) {
    std::vector<std::string> optionsVec;
    auto optionsAttr =
        MakeUnique<SdpOptionsAttribute>(SdpAttribute::kIceOptionsAttribute);
    for (size_t i = 0; i < string_vec_len(options); i++) {
      StringView optionStr;
      string_vec_get_view(options, i, &optionStr);
      optionsAttr->PushEntry(convertStringView(optionStr));
    }
    SetAttribute(optionsAttr.release());
  }
}

void RsdparsaSdpAttributeList::LoadFingerprint(
    RustAttributeList* attributeList) {
  size_t nFp = sdp_get_fingerprint_count(attributeList);
  if (nFp == 0) {
    return;
  }
  auto rustFingerprints = MakeUnique<RustSdpAttributeFingerprint[]>(nFp);
  sdp_get_fingerprints(attributeList, nFp, rustFingerprints.get());
  auto fingerprints = MakeUnique<SdpFingerprintAttributeList>();
  for (size_t i = 0; i < nFp; i++) {
    const RustSdpAttributeFingerprint& fingerprint = rustFingerprints[i];
    std::string algorithm;
    switch (fingerprint.hashAlgorithm) {
      case RustSdpAttributeFingerprintHashAlgorithm::kSha1:
        algorithm = "sha-1";
        break;
      case RustSdpAttributeFingerprintHashAlgorithm::kSha224:
        algorithm = "sha-224";
        break;
      case RustSdpAttributeFingerprintHashAlgorithm::kSha256:
        algorithm = "sha-256";
        break;
      case RustSdpAttributeFingerprintHashAlgorithm::kSha384:
        algorithm = "sha-384";
        break;
      case RustSdpAttributeFingerprintHashAlgorithm::kSha512:
        algorithm = "sha-512";
        break;
    }

    std::vector<uint8_t> fingerprintBytes =
        convertU8Vec(fingerprint.fingerprint);

    fingerprints->PushEntry(algorithm, fingerprintBytes);
  }
  SetAttribute(fingerprints.release());
}

void RsdparsaSdpAttributeList::LoadDtlsMessage(
    RustAttributeList* attributeList) {
  RustSdpAttributeDtlsMessage rustDtlsMessage;
  nsresult nr = sdp_get_dtls_message(attributeList, &rustDtlsMessage);
  if (NS_SUCCEEDED(nr)) {
    SdpDtlsMessageAttribute::Role role;
    if (rustDtlsMessage.role == RustSdpAttributeDtlsMessageType::kClient) {
      role = SdpDtlsMessageAttribute::kClient;
    } else {
      role = SdpDtlsMessageAttribute::kServer;
    }

    std::string value = convertStringView(rustDtlsMessage.value);

    SetAttribute(new SdpDtlsMessageAttribute(role, value));
  }
}

void RsdparsaSdpAttributeList::LoadSetup(RustAttributeList* attributeList) {
  RustSdpSetup rustSetup;
  nsresult nr = sdp_get_setup(attributeList, &rustSetup);
  if (NS_SUCCEEDED(nr)) {
    SdpSetupAttribute::Role setupEnum;
    switch (rustSetup) {
      case RustSdpSetup::kRustActive:
        setupEnum = SdpSetupAttribute::kActive;
        break;
      case RustSdpSetup::kRustActpass:
        setupEnum = SdpSetupAttribute::kActpass;
        break;
      case RustSdpSetup::kRustHoldconn:
        setupEnum = SdpSetupAttribute::kHoldconn;
        break;
      case RustSdpSetup::kRustPassive:
        setupEnum = SdpSetupAttribute::kPassive;
        break;
    }
    SetAttribute(new SdpSetupAttribute(setupEnum));
  }
}

void RsdparsaSdpAttributeList::LoadSsrc(RustAttributeList* attributeList) {
  size_t numSsrc = sdp_get_ssrc_count(attributeList);
  if (numSsrc == 0) {
    return;
  }
  auto rustSsrcs = MakeUnique<RustSdpAttributeSsrc[]>(numSsrc);
  sdp_get_ssrcs(attributeList, numSsrc, rustSsrcs.get());
  auto ssrcs = MakeUnique<SdpSsrcAttributeList>();
  for (size_t i = 0; i < numSsrc; i++) {
    RustSdpAttributeSsrc& ssrc = rustSsrcs[i];
    std::string attribute = convertStringView(ssrc.attribute);
    std::string value = convertStringView(ssrc.value);
    if (value.length() == 0) {
      ssrcs->PushEntry(ssrc.id, attribute);
    } else {
      ssrcs->PushEntry(ssrc.id, attribute + ":" + value);
    }
  }
  SetAttribute(ssrcs.release());
}

void RsdparsaSdpAttributeList::LoadSsrcGroup(RustAttributeList* attributeList) {
  size_t numSsrcGroups = sdp_get_ssrc_group_count(attributeList);
  if (numSsrcGroups == 0) {
    return;
  }
  auto rustSsrcGroups = MakeUnique<RustSdpAttributeSsrcGroup[]>(numSsrcGroups);
  sdp_get_ssrc_groups(attributeList, numSsrcGroups, rustSsrcGroups.get());
  auto ssrcGroups = MakeUnique<SdpSsrcGroupAttributeList>();
  for (size_t i = 0; i < numSsrcGroups; i++) {
    RustSdpAttributeSsrcGroup& ssrcGroup = rustSsrcGroups[i];
    SdpSsrcGroupAttributeList::Semantics semantic;
    switch (ssrcGroup.semantic) {
      case RustSdpAttributeSsrcGroupSemantic ::kRustDup:
        semantic = SdpSsrcGroupAttributeList::kDup;
        break;
      case RustSdpAttributeSsrcGroupSemantic ::kRustFec:
        semantic = SdpSsrcGroupAttributeList::kFec;
        break;
      case RustSdpAttributeSsrcGroupSemantic ::kRustFecFr:
        semantic = SdpSsrcGroupAttributeList::kFecFr;
        break;
      case RustSdpAttributeSsrcGroupSemantic ::kRustFid:
        semantic = SdpSsrcGroupAttributeList::kFid;
        break;
      case RustSdpAttributeSsrcGroupSemantic ::kRustSim:
        semantic = SdpSsrcGroupAttributeList::kSim;
        break;
    }
    std::vector<uint32_t> ssrcs;
    for (size_t i = 0; i < ssrc_vec_len(ssrcGroup.ssrcs); ++i) {
      uint32_t ssrc;
      ssrc_vec_get_id(ssrcGroup.ssrcs, i, &ssrc);
      ssrcs.push_back(ssrc);
    }
    ssrcGroups->PushEntry(semantic, ssrcs);
  }
  SetAttribute(ssrcGroups.release());
}

struct FmtDefaults {
  uint32_t minimumChannels = 0;
};

std::tuple<SdpRtpmapAttributeList::CodecType, FmtDefaults> strToCodecType(
    const std::string& name) {
  auto codec = SdpRtpmapAttributeList::kOtherCodec;
  FmtDefaults defaults = {0};  // This is tracked to match SIPCC behavior only
  if (!nsCRT::strcasecmp(name.c_str(), "opus")) {
    codec = SdpRtpmapAttributeList::kOpus;
    defaults = {0};
  } else if (!nsCRT::strcasecmp(name.c_str(), "G722")) {
    codec = SdpRtpmapAttributeList::kG722;
    defaults = {1};
  } else if (!nsCRT::strcasecmp(name.c_str(), "PCMU")) {
    codec = SdpRtpmapAttributeList::kPCMU;
    defaults = {1};
  } else if (!nsCRT::strcasecmp(name.c_str(), "PCMA")) {
    codec = SdpRtpmapAttributeList::kPCMA;
    defaults = {1};
  } else if (!nsCRT::strcasecmp(name.c_str(), "VP8")) {
    codec = SdpRtpmapAttributeList::kVP8;
    defaults = {0};
  } else if (!nsCRT::strcasecmp(name.c_str(), "VP9")) {
    codec = SdpRtpmapAttributeList::kVP9;
    defaults = {0};
  } else if (!nsCRT::strcasecmp(name.c_str(), "iLBC")) {
    codec = SdpRtpmapAttributeList::kiLBC;
    defaults = {1};
  } else if (!nsCRT::strcasecmp(name.c_str(), "iSAC")) {
    codec = SdpRtpmapAttributeList::kiSAC;
    defaults = {1};
  } else if (!nsCRT::strcasecmp(name.c_str(), "H264")) {
    codec = SdpRtpmapAttributeList::kH264;
    defaults = {0};
  } else if (!nsCRT::strcasecmp(name.c_str(), "red")) {
    codec = SdpRtpmapAttributeList::kRed;
    defaults = {0};
  } else if (!nsCRT::strcasecmp(name.c_str(), "ulpfec")) {
    codec = SdpRtpmapAttributeList::kUlpfec;
    defaults = {0};
  } else if (!nsCRT::strcasecmp(name.c_str(), "telephone-event")) {
    codec = SdpRtpmapAttributeList::kTelephoneEvent;
    defaults = {1};
  } else if (!nsCRT::strcasecmp(name.c_str(), "rtx")) {
    codec = SdpRtpmapAttributeList::kRtx;
    defaults = {0};
  }
  return std::make_tuple(codec, defaults);
}

void RsdparsaSdpAttributeList::LoadRtpmap(RustAttributeList* attributeList) {
  size_t numRtpmap = sdp_get_rtpmap_count(attributeList);
  if (numRtpmap == 0) {
    return;
  }
  auto rustRtpmaps = MakeUnique<RustSdpAttributeRtpmap[]>(numRtpmap);
  sdp_get_rtpmaps(attributeList, numRtpmap, rustRtpmaps.get());
  auto rtpmapList = MakeUnique<SdpRtpmapAttributeList>();
  for (size_t i = 0; i < numRtpmap; i++) {
    RustSdpAttributeRtpmap& rtpmap = rustRtpmaps[i];
    std::string payloadType = std::to_string(rtpmap.payloadType);
    std::string name = convertStringView(rtpmap.codecName);
    auto [codec, defaults] = strToCodecType(name);
    uint32_t channels = rtpmap.channels;
    if (channels == 0) {
      channels = defaults.minimumChannels;
    }
    rtpmapList->PushEntry(payloadType, codec, name, rtpmap.frequency, channels);
  }
  SetAttribute(rtpmapList.release());
}

void RsdparsaSdpAttributeList::LoadFmtp(RustAttributeList* attributeList) {
  size_t numFmtp = sdp_get_fmtp_count(attributeList);
  if (numFmtp == 0) {
    return;
  }
  auto rustFmtps = MakeUnique<RustSdpAttributeFmtp[]>(numFmtp);
  size_t numValidFmtp = sdp_get_fmtp(attributeList, numFmtp, rustFmtps.get());
  auto fmtpList = MakeUnique<SdpFmtpAttributeList>();
  for (size_t i = 0; i < numValidFmtp; i++) {
    const RustSdpAttributeFmtp& fmtp = rustFmtps[i];
    uint8_t payloadType = fmtp.payloadType;
    std::string codecName = convertStringView(fmtp.codecName);
    const RustSdpAttributeFmtpParameters& rustFmtpParameters = fmtp.parameters;

    UniquePtr<SdpFmtpAttributeList::Parameters> fmtpParameters;

    // use the upper case version of the codec name
    std::transform(codecName.begin(), codecName.end(), codecName.begin(),
                   ::toupper);

    if (codecName == "H264") {
      SdpFmtpAttributeList::H264Parameters h264Parameters;

      h264Parameters.packetization_mode = rustFmtpParameters.packetization_mode;
      h264Parameters.level_asymmetry_allowed =
          rustFmtpParameters.level_asymmetry_allowed;
      h264Parameters.profile_level_id = rustFmtpParameters.profile_level_id;
      h264Parameters.max_mbps = rustFmtpParameters.max_mbps;
      h264Parameters.max_fs = rustFmtpParameters.max_fs;
      h264Parameters.max_cpb = rustFmtpParameters.max_cpb;
      h264Parameters.max_dpb = rustFmtpParameters.max_dpb;
      h264Parameters.max_br = rustFmtpParameters.max_br;

      // TODO(bug 1466859): Support sprop-parameter-sets

      fmtpParameters.reset(
          new SdpFmtpAttributeList::H264Parameters(std::move(h264Parameters)));
    } else if (codecName == "OPUS") {
      SdpFmtpAttributeList::OpusParameters opusParameters;

      opusParameters.maxplaybackrate = rustFmtpParameters.maxplaybackrate;
      opusParameters.maxAverageBitrate = rustFmtpParameters.maxaveragebitrate;
      opusParameters.useDTX = rustFmtpParameters.usedtx;
      opusParameters.stereo = rustFmtpParameters.stereo;
      opusParameters.useInBandFec = rustFmtpParameters.useinbandfec;
      opusParameters.frameSizeMs = rustFmtpParameters.ptime;
      opusParameters.minFrameSizeMs = rustFmtpParameters.minptime;
      opusParameters.maxFrameSizeMs = rustFmtpParameters.maxptime;
      opusParameters.useCbr = rustFmtpParameters.cbr;

      fmtpParameters.reset(
          new SdpFmtpAttributeList::OpusParameters(std::move(opusParameters)));
    } else if ((codecName == "VP8") || (codecName == "VP9")) {
      SdpFmtpAttributeList::VP8Parameters vp8Parameters(
          codecName == "VP8" ? SdpRtpmapAttributeList::kVP8
                             : SdpRtpmapAttributeList::kVP9);

      vp8Parameters.max_fs = rustFmtpParameters.max_fs;
      vp8Parameters.max_fr = rustFmtpParameters.max_fr;

      fmtpParameters.reset(
          new SdpFmtpAttributeList::VP8Parameters(std::move(vp8Parameters)));
    } else if (codecName == "TELEPHONE-EVENT") {
      SdpFmtpAttributeList::TelephoneEventParameters telephoneEventParameters;

      telephoneEventParameters.dtmfTones =
          convertStringView(rustFmtpParameters.dtmf_tones);

      fmtpParameters.reset(new SdpFmtpAttributeList::TelephoneEventParameters(
          std::move(telephoneEventParameters)));
    } else if (codecName == "RED") {
      SdpFmtpAttributeList::RedParameters redParameters;

      redParameters.encodings = convertU8Vec(rustFmtpParameters.encodings);

      fmtpParameters.reset(
          new SdpFmtpAttributeList::RedParameters(std::move(redParameters)));
    } else if (codecName == "RTX") {
      SdpFmtpAttributeList::RtxParameters rtxParameters;

      rtxParameters.apt = rustFmtpParameters.rtx.apt;
      if (rustFmtpParameters.rtx.has_rtx_time) {
        rtxParameters.rtx_time = Some(rustFmtpParameters.rtx.rtx_time);
      }

      fmtpParameters.reset(
          new SdpFmtpAttributeList::RtxParameters(rtxParameters));
    } else if (codecName == "AV1") {
      SdpFmtpAttributeList::Av1Parameters av1Parameters;

      av1Parameters.profile = rustFmtpParameters.av1.has_profile
                                  ? Some(rustFmtpParameters.av1.profile)
                                  : Nothing();
      av1Parameters.levelIdx = rustFmtpParameters.av1.has_level_idx
                                   ? Some(rustFmtpParameters.av1.level_idx)
                                   : Nothing();
      av1Parameters.tier = rustFmtpParameters.av1.has_tier
                               ? Some(rustFmtpParameters.av1.tier)
                               : Nothing();
      fmtpParameters.reset(
          new SdpFmtpAttributeList::Av1Parameters(av1Parameters));

    } else {
      // The parameter set is unknown so skip it
      continue;
    }
    fmtpList->PushEntry(std::to_string(payloadType), *fmtpParameters);
  }
  SetAttribute(fmtpList.release());
}

void RsdparsaSdpAttributeList::LoadPtime(RustAttributeList* attributeList) {
  int64_t ptime = sdp_get_ptime(attributeList);
  if (ptime >= 0) {
    SetAttribute(new SdpNumberAttribute(SdpAttribute::kPtimeAttribute,
                                        static_cast<uint32_t>(ptime)));
  }
}

void RsdparsaSdpAttributeList::LoadFlags(RustAttributeList* attributeList) {
  RustSdpAttributeFlags flags = sdp_get_attribute_flags(attributeList);
  if (flags.iceLite) {
    SetAttribute(new SdpFlagAttribute(SdpAttribute::kIceLiteAttribute));
  }
  if (flags.rtcpMux) {
    SetAttribute(new SdpFlagAttribute(SdpAttribute::kRtcpMuxAttribute));
  }
  if (flags.rtcpRsize) {
    SetAttribute(new SdpFlagAttribute(SdpAttribute::kRtcpRsizeAttribute));
  }
  if (flags.bundleOnly) {
    SetAttribute(new SdpFlagAttribute(SdpAttribute::kBundleOnlyAttribute));
  }
  if (flags.endOfCandidates) {
    SetAttribute(new SdpFlagAttribute(SdpAttribute::kEndOfCandidatesAttribute));
  }
}

void RsdparsaSdpAttributeList::LoadMaxMessageSize(
    RustAttributeList* attributeList) {
  int64_t max_msg_size = sdp_get_max_msg_size(attributeList);
  if (max_msg_size >= 0) {
    SetAttribute(new SdpNumberAttribute(SdpAttribute::kMaxMessageSizeAttribute,
                                        static_cast<uint32_t>(max_msg_size)));
  }
}

void RsdparsaSdpAttributeList::LoadMid(RustAttributeList* attributeList) {
  StringView rustMid;
  if (NS_SUCCEEDED(sdp_get_mid(attributeList, &rustMid))) {
    std::string mid = convertStringView(rustMid);
    SetAttribute(new SdpStringAttribute(SdpAttribute::kMidAttribute, mid));
  }
}

void RsdparsaSdpAttributeList::LoadMsid(RustAttributeList* attributeList) {
  size_t numMsid = sdp_get_msid_count(attributeList);
  if (numMsid == 0) {
    return;
  }
  auto rustMsid = MakeUnique<RustSdpAttributeMsid[]>(numMsid);
  sdp_get_msids(attributeList, numMsid, rustMsid.get());
  auto msids = MakeUnique<SdpMsidAttributeList>();
  for (size_t i = 0; i < numMsid; i++) {
    RustSdpAttributeMsid& msid = rustMsid[i];
    std::string id = convertStringView(msid.id);
    std::string appdata = convertStringView(msid.appdata);
    msids->PushEntry(id, appdata);
  }
  SetAttribute(msids.release());
}

void RsdparsaSdpAttributeList::LoadMsidSemantics(
    RustAttributeList* attributeList) {
  size_t numMsidSemantic = sdp_get_msid_semantic_count(attributeList);
  if (numMsidSemantic == 0) {
    return;
  }
  auto rustMsidSemantics =
      MakeUnique<RustSdpAttributeMsidSemantic[]>(numMsidSemantic);
  sdp_get_msid_semantics(attributeList, numMsidSemantic,
                         rustMsidSemantics.get());
  auto msidSemantics = MakeUnique<SdpMsidSemanticAttributeList>();
  for (size_t i = 0; i < numMsidSemantic; i++) {
    RustSdpAttributeMsidSemantic& rustMsidSemantic = rustMsidSemantics[i];
    std::string semantic = convertStringView(rustMsidSemantic.semantic);
    std::vector<std::string> msids = convertStringVec(rustMsidSemantic.msids);
    msidSemantics->PushEntry(semantic, msids);
  }
  SetAttribute(msidSemantics.release());
}

void RsdparsaSdpAttributeList::LoadGroup(RustAttributeList* attributeList) {
  size_t numGroup = sdp_get_group_count(attributeList);
  if (numGroup == 0) {
    return;
  }
  auto rustGroups = MakeUnique<RustSdpAttributeGroup[]>(numGroup);
  sdp_get_groups(attributeList, numGroup, rustGroups.get());
  auto groups = MakeUnique<SdpGroupAttributeList>();
  for (size_t i = 0; i < numGroup; i++) {
    RustSdpAttributeGroup& group = rustGroups[i];
    SdpGroupAttributeList::Semantics semantic;
    switch (group.semantic) {
      case RustSdpAttributeGroupSemantic ::kRustLipSynchronization:
        semantic = SdpGroupAttributeList::kLs;
        break;
      case RustSdpAttributeGroupSemantic ::kRustFlowIdentification:
        semantic = SdpGroupAttributeList::kFid;
        break;
      case RustSdpAttributeGroupSemantic ::kRustSingleReservationFlow:
        semantic = SdpGroupAttributeList::kSrf;
        break;
      case RustSdpAttributeGroupSemantic ::kRustAlternateNetworkAddressType:
        semantic = SdpGroupAttributeList::kAnat;
        break;
      case RustSdpAttributeGroupSemantic ::kRustForwardErrorCorrection:
        semantic = SdpGroupAttributeList::kFec;
        break;
      case RustSdpAttributeGroupSemantic ::kRustDecodingDependency:
        semantic = SdpGroupAttributeList::kDdp;
        break;
      case RustSdpAttributeGroupSemantic ::kRustBundle:
        semantic = SdpGroupAttributeList::kBundle;
        break;
    }
    std::vector<std::string> tags = convertStringVec(group.tags);
    groups->PushEntry(semantic, tags);
  }
  SetAttribute(groups.release());
}

void RsdparsaSdpAttributeList::LoadRtcp(RustAttributeList* attributeList) {
  RustSdpAttributeRtcp rtcp;
  if (NS_SUCCEEDED(sdp_get_rtcp(attributeList, &rtcp))) {
    if (rtcp.has_address) {
      auto address = convertExplicitlyTypedAddress(&rtcp.unicastAddr);
      SetAttribute(new SdpRtcpAttribute(rtcp.port, sdp::kInternet,
                                        address.first, address.second));
    } else {
      SetAttribute(new SdpRtcpAttribute(rtcp.port));
    }
  }
}

void RsdparsaSdpAttributeList::LoadRtcpFb(RustAttributeList* attributeList) {
  auto rtcpfbsCount = sdp_get_rtcpfb_count(attributeList);
  if (!rtcpfbsCount) {
    return;
  }

  auto rustRtcpfbs = MakeUnique<RustSdpAttributeRtcpFb[]>(rtcpfbsCount);
  sdp_get_rtcpfbs(attributeList, rtcpfbsCount, rustRtcpfbs.get());

  auto rtcpfbList = MakeUnique<SdpRtcpFbAttributeList>();
  for (size_t i = 0; i < rtcpfbsCount; i++) {
    RustSdpAttributeRtcpFb& rtcpfb = rustRtcpfbs[i];
    uint32_t payloadTypeU32 = rtcpfb.payloadType;

    std::stringstream ss;
    if (payloadTypeU32 == std::numeric_limits<uint32_t>::max()) {
      ss << "*";
    } else {
      ss << payloadTypeU32;
    }

    uint32_t feedbackType = rtcpfb.feedbackType;
    std::string parameter = convertStringView(rtcpfb.parameter);
    std::string extra = convertStringView(rtcpfb.extra);

    rtcpfbList->PushEntry(
        ss.str(), static_cast<SdpRtcpFbAttributeList::Type>(feedbackType),
        parameter, extra);
  }

  SetAttribute(rtcpfbList.release());
}

SdpSimulcastAttribute::Versions LoadSimulcastVersions(
    const RustSdpAttributeSimulcastVersionVec* rustVersionList) {
  size_t rustVersionCount = sdp_simulcast_get_version_count(rustVersionList);
  auto rustVersionArray =
      MakeUnique<RustSdpAttributeSimulcastVersion[]>(rustVersionCount);
  sdp_simulcast_get_versions(rustVersionList, rustVersionCount,
                             rustVersionArray.get());

  SdpSimulcastAttribute::Versions versions;

  for (size_t i = 0; i < rustVersionCount; i++) {
    const RustSdpAttributeSimulcastVersion& rustVersion = rustVersionArray[i];
    size_t rustIdCount = sdp_simulcast_get_ids_count(rustVersion.ids);
    if (!rustIdCount) {
      continue;
    }

    SdpSimulcastAttribute::Version version;
    auto rustIdArray = MakeUnique<RustSdpAttributeSimulcastId[]>(rustIdCount);
    sdp_simulcast_get_ids(rustVersion.ids, rustIdCount, rustIdArray.get());

    for (size_t j = 0; j < rustIdCount; j++) {
      const RustSdpAttributeSimulcastId& rustId = rustIdArray[j];
      std::string id = convertStringView(rustId.id);
      // TODO: Bug 1225877. Added support for 'paused'-state
      version.choices.push_back(
          SdpSimulcastAttribute::Encoding(id, rustId.paused));
    }

    versions.push_back(version);
  }

  return versions;
}

void RsdparsaSdpAttributeList::LoadSimulcast(RustAttributeList* attributeList) {
  RustSdpAttributeSimulcast rustSimulcast;
  if (NS_SUCCEEDED(sdp_get_simulcast(attributeList, &rustSimulcast))) {
    auto simulcast = MakeUnique<SdpSimulcastAttribute>();

    simulcast->sendVersions = LoadSimulcastVersions(rustSimulcast.send);
    simulcast->recvVersions = LoadSimulcastVersions(rustSimulcast.recv);

    SetAttribute(simulcast.release());
  }
}

SdpImageattrAttributeList::XYRange LoadImageattrXYRange(
    const RustSdpAttributeImageAttrXYRange& rustXYRange) {
  SdpImageattrAttributeList::XYRange xyRange;

  if (!rustXYRange.discrete_values) {
    xyRange.min = rustXYRange.min;
    xyRange.max = rustXYRange.max;
    xyRange.step = rustXYRange.step;

  } else {
    xyRange.discreteValues = convertU32Vec(rustXYRange.discrete_values);
  }

  return xyRange;
}

std::vector<SdpImageattrAttributeList::Set> LoadImageattrSets(
    const RustSdpAttributeImageAttrSetVec* rustSets) {
  std::vector<SdpImageattrAttributeList::Set> sets;

  size_t rustSetCount = sdp_imageattr_get_set_count(rustSets);
  if (!rustSetCount) {
    return sets;
  }

  auto rustSetArray = MakeUnique<RustSdpAttributeImageAttrSet[]>(rustSetCount);
  sdp_imageattr_get_sets(rustSets, rustSetCount, rustSetArray.get());

  for (size_t i = 0; i < rustSetCount; i++) {
    const RustSdpAttributeImageAttrSet& rustSet = rustSetArray[i];
    SdpImageattrAttributeList::Set set;

    set.xRange = LoadImageattrXYRange(rustSet.x);
    set.yRange = LoadImageattrXYRange(rustSet.y);

    if (rustSet.has_sar) {
      if (!rustSet.sar.discrete_values) {
        set.sRange.min = rustSet.sar.min;
        set.sRange.max = rustSet.sar.max;
      } else {
        set.sRange.discreteValues = convertF32Vec(rustSet.sar.discrete_values);
      }
    }

    if (rustSet.has_par) {
      set.pRange.min = rustSet.par.min;
      set.pRange.max = rustSet.par.max;
    }

    set.qValue = rustSet.q;

    sets.push_back(set);
  }

  return sets;
}

void RsdparsaSdpAttributeList::LoadImageattr(RustAttributeList* attributeList) {
  size_t numImageattrs = sdp_get_imageattr_count(attributeList);
  if (numImageattrs == 0) {
    return;
  }
  auto rustImageattrs = MakeUnique<RustSdpAttributeImageAttr[]>(numImageattrs);
  sdp_get_imageattrs(attributeList, numImageattrs, rustImageattrs.get());
  auto imageattrList = MakeUnique<SdpImageattrAttributeList>();
  for (size_t i = 0; i < numImageattrs; i++) {
    const RustSdpAttributeImageAttr& rustImageAttr = rustImageattrs[i];

    SdpImageattrAttributeList::Imageattr imageAttr;

    if (rustImageAttr.payloadType != std::numeric_limits<uint32_t>::max()) {
      imageAttr.pt = Some(rustImageAttr.payloadType);
    }

    if (rustImageAttr.send.sets) {
      imageAttr.sendSets = LoadImageattrSets(rustImageAttr.send.sets);
    } else {
      imageAttr.sendAll = true;
    }

    if (rustImageAttr.recv.sets) {
      imageAttr.recvSets = LoadImageattrSets(rustImageAttr.recv.sets);
    } else {
      imageAttr.recvAll = true;
    }

    imageattrList->mImageattrs.push_back(imageAttr);
  }
  SetAttribute(imageattrList.release());
}

void RsdparsaSdpAttributeList::LoadSctpmaps(RustAttributeList* attributeList) {
  size_t numSctpmaps = sdp_get_sctpmap_count(attributeList);
  if (numSctpmaps == 0) {
    return;
  }
  auto rustSctpmaps = MakeUnique<RustSdpAttributeSctpmap[]>(numSctpmaps);
  sdp_get_sctpmaps(attributeList, numSctpmaps, rustSctpmaps.get());
  auto sctpmapList = MakeUnique<SdpSctpmapAttributeList>();
  for (size_t i = 0; i < numSctpmaps; i++) {
    RustSdpAttributeSctpmap& sctpmap = rustSctpmaps[i];
    sctpmapList->PushEntry(std::to_string(sctpmap.port), "webrtc-datachannel",
                           sctpmap.channels);
  }
  SetAttribute(sctpmapList.release());
}

void RsdparsaSdpAttributeList::LoadDirection(RustAttributeList* attributeList) {
  SdpDirectionAttribute::Direction dir;
  RustDirection rustDir = sdp_get_direction(attributeList);
  switch (rustDir) {
    case RustDirection::kRustRecvonly:
      dir = SdpDirectionAttribute::kRecvonly;
      break;
    case RustDirection::kRustSendonly:
      dir = SdpDirectionAttribute::kSendonly;
      break;
    case RustDirection::kRustSendrecv:
      dir = SdpDirectionAttribute::kSendrecv;
      break;
    case RustDirection::kRustInactive:
      dir = SdpDirectionAttribute::kInactive;
      break;
  }
  SetAttribute(new SdpDirectionAttribute(dir));
}

void RsdparsaSdpAttributeList::LoadRemoteCandidates(
    RustAttributeList* attributeList) {
  size_t nC = sdp_get_remote_candidate_count(attributeList);
  if (nC == 0) {
    return;
  }
  auto rustCandidates = MakeUnique<RustSdpAttributeRemoteCandidate[]>(nC);
  sdp_get_remote_candidates(attributeList, nC, rustCandidates.get());
  std::vector<SdpRemoteCandidatesAttribute::Candidate> candidates;
  for (size_t i = 0; i < nC; i++) {
    RustSdpAttributeRemoteCandidate& rustCandidate = rustCandidates[i];
    SdpRemoteCandidatesAttribute::Candidate candidate;
    candidate.port = rustCandidate.port;
    candidate.id = std::to_string(rustCandidate.component);
    candidate.address = convertAddress(&rustCandidate.address);
    candidates.push_back(candidate);
  }
  SdpRemoteCandidatesAttribute* candidatesList;
  candidatesList = new SdpRemoteCandidatesAttribute(candidates);
  SetAttribute(candidatesList);
}

void RsdparsaSdpAttributeList::LoadRids(RustAttributeList* attributeList) {
  size_t numRids = sdp_get_rid_count(attributeList);
  if (numRids == 0) {
    return;
  }

  auto rustRids = MakeUnique<RustSdpAttributeRid[]>(numRids);
  sdp_get_rids(attributeList, numRids, rustRids.get());

  auto ridList = MakeUnique<SdpRidAttributeList>();
  for (size_t i = 0; i < numRids; i++) {
    const RustSdpAttributeRid& rid = rustRids[i];

    std::string id = convertStringView(rid.id);
    auto direction = static_cast<sdp::Direction>(rid.direction);
    std::vector<uint16_t> formats = convertU16Vec(rid.formats);

    EncodingConstraints parameters;
    parameters.maxWidth = rid.params.max_width;
    parameters.maxHeight = rid.params.max_height;
    // Right now, we treat max-fps=0 and the absence of max-fps as no limit.
    // We will eventually want to treat max-fps=0 as 0 frames per second, and
    // the absence of max-fps as no limit (bug 1762632).
    if (rid.params.max_fps) {
      parameters.maxFps = Some(rid.params.max_fps);
    }
    parameters.maxFs = rid.params.max_fs;
    parameters.maxBr = rid.params.max_br;
    parameters.maxPps = rid.params.max_pps;

    std::vector<std::string> depends = convertStringVec(rid.depends);

    ridList->PushEntry(id, direction, formats, parameters, depends);
  }

  SetAttribute(ridList.release());
}

void RsdparsaSdpAttributeList::LoadSctpPort(RustAttributeList* attributeList) {
  int64_t port = sdp_get_sctp_port(attributeList);
  if (port >= 0) {
    SetAttribute(new SdpNumberAttribute(SdpAttribute::kSctpPortAttribute,
                                        static_cast<uint32_t>(port)));
  }
}

void RsdparsaSdpAttributeList::LoadExtmap(RustAttributeList* attributeList) {
  size_t numExtmap = sdp_get_extmap_count(attributeList);
  if (numExtmap == 0) {
    return;
  }
  auto rustExtmaps = MakeUnique<RustSdpAttributeExtmap[]>(numExtmap);
  sdp_get_extmaps(attributeList, numExtmap, rustExtmaps.get());
  auto extmaps = MakeUnique<SdpExtmapAttributeList>();
  for (size_t i = 0; i < numExtmap; i++) {
    RustSdpAttributeExtmap& rustExtmap = rustExtmaps[i];
    std::string name = convertStringView(rustExtmap.url);
    SdpDirectionAttribute::Direction direction;
    bool directionSpecified = rustExtmap.direction_specified;
    switch (rustExtmap.direction) {
      case RustDirection::kRustRecvonly:
        direction = SdpDirectionAttribute::kRecvonly;
        break;
      case RustDirection::kRustSendonly:
        direction = SdpDirectionAttribute::kSendonly;
        break;
      case RustDirection::kRustSendrecv:
        direction = SdpDirectionAttribute::kSendrecv;
        break;
      case RustDirection::kRustInactive:
        direction = SdpDirectionAttribute::kInactive;
        break;
    }
    std::string extensionAttributes;
    extensionAttributes = convertStringView(rustExtmap.extensionAttributes);
    extmaps->PushEntry((uint16_t)rustExtmap.id, direction, directionSpecified,
                       name, extensionAttributes);
  }
  SetAttribute(extmaps.release());
}

void RsdparsaSdpAttributeList::LoadMaxPtime(RustAttributeList* attributeList) {
  uint64_t maxPtime = 0;
  nsresult nr = sdp_get_maxptime(attributeList, &maxPtime);
  if (NS_SUCCEEDED(nr)) {
    SetAttribute(
        new SdpNumberAttribute(SdpAttribute::kMaxptimeAttribute, maxPtime));
  }
}

void RsdparsaSdpAttributeList::LoadCandidate(RustAttributeList* attributeList) {
  size_t candidatesCount = sdp_get_candidate_count(attributeList);
  if (!candidatesCount) {
    return;
  }

  StringVec* rustCandidatesStrings;
  sdp_get_candidates(attributeList, candidatesCount, &rustCandidatesStrings);

  std::vector<std::string> candidatesStrings =
      convertStringVec(rustCandidatesStrings);
  free_boxed_string_vec(rustCandidatesStrings);

  auto candidates =
      MakeUnique<SdpMultiStringAttribute>(SdpAttribute::kCandidateAttribute);
  candidates->mValues = candidatesStrings;

  SetAttribute(candidates.release());
}

bool RsdparsaSdpAttributeList::IsAllowedHere(SdpAttribute::AttributeType type) {
  if (AtSessionLevel() && !SdpAttribute::IsAllowedAtSessionLevel(type)) {
    return false;
  }

  if (!AtSessionLevel() && !SdpAttribute::IsAllowedAtMediaLevel(type)) {
    return false;
  }

  return true;
}

void RsdparsaSdpAttributeList::Serialize(std::ostream& os) const {
  for (size_t i = 0; i < kNumAttributeTypes; ++i) {
    if (mAttributes[i]) {
      os << *mAttributes[i];
    }
  }
}

}  // namespace mozilla

Messung V0.5
C=100 H=90 G=95

¤ Dauer der Verarbeitung: 0.18 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Produkte
     Quellcodebibliothek

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....

Besucherstatistik

Besucherstatistik

Monitoring

Montastic status badge