diff options
Diffstat (limited to 'dom/media/webrtc/sdp/RsdparsaSdpMediaSection.cpp')
-rw-r--r-- | dom/media/webrtc/sdp/RsdparsaSdpMediaSection.cpp | 253 |
1 files changed, 253 insertions, 0 deletions
diff --git a/dom/media/webrtc/sdp/RsdparsaSdpMediaSection.cpp b/dom/media/webrtc/sdp/RsdparsaSdpMediaSection.cpp new file mode 100644 index 0000000000..25084db2ad --- /dev/null +++ b/dom/media/webrtc/sdp/RsdparsaSdpMediaSection.cpp @@ -0,0 +1,253 @@ +/* -*- 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 "sdp/SdpMediaSection.h" +#include "sdp/RsdparsaSdpMediaSection.h" + +#include "sdp/RsdparsaSdpGlue.h" +#include "sdp/RsdparsaSdpInc.h" + +#include <ostream> + +#ifdef CRLF +# undef CRLF +#endif +#define CRLF "\r\n" + +namespace mozilla { + +RsdparsaSdpMediaSection::RsdparsaSdpMediaSection( + size_t level, RsdparsaSessionHandle session, + const RustMediaSection* const section, + const RsdparsaSdpAttributeList* sessionLevel) + : SdpMediaSection(level), mSession(std::move(session)), mSection(section) { + switch (sdp_rust_get_media_type(section)) { + case RustSdpMediaValue::kRustAudio: + mMediaType = kAudio; + break; + case RustSdpMediaValue::kRustVideo: + mMediaType = kVideo; + break; + case RustSdpMediaValue::kRustApplication: + mMediaType = kApplication; + break; + } + + RsdparsaSessionHandle attributeSession(sdp_new_reference(mSession.get())); + mAttributeList.reset(new RsdparsaSdpAttributeList(std::move(attributeSession), + section, sessionLevel)); + + LoadFormats(); + LoadConnection(); +} + +unsigned int RsdparsaSdpMediaSection::GetPort() const { + return sdp_get_media_port(mSection); +} + +void RsdparsaSdpMediaSection::SetPort(unsigned int port) { + sdp_set_media_port(mSection, port); +} + +unsigned int RsdparsaSdpMediaSection::GetPortCount() const { + return sdp_get_media_port_count(mSection); +} + +SdpMediaSection::Protocol RsdparsaSdpMediaSection::GetProtocol() const { + switch (sdp_get_media_protocol(mSection)) { + case RustSdpProtocolValue::kRustRtpSavpf: + return kRtpSavpf; + case RustSdpProtocolValue::kRustUdpTlsRtpSavp: + return kUdpTlsRtpSavp; + case RustSdpProtocolValue::kRustTcpDtlsRtpSavp: + return kTcpDtlsRtpSavp; + case RustSdpProtocolValue::kRustUdpTlsRtpSavpf: + return kUdpTlsRtpSavpf; + case RustSdpProtocolValue::kRustTcpDtlsRtpSavpf: + return kTcpDtlsRtpSavpf; + case RustSdpProtocolValue::kRustDtlsSctp: + return kDtlsSctp; + case RustSdpProtocolValue::kRustUdpDtlsSctp: + return kUdpDtlsSctp; + case RustSdpProtocolValue::kRustTcpDtlsSctp: + return kTcpDtlsSctp; + case RustSdpProtocolValue::kRustRtpAvp: + return kRtpAvp; + case RustSdpProtocolValue::kRustRtpAvpf: + return kRtpAvpf; + case RustSdpProtocolValue::kRustRtpSavp: + return kRtpSavp; + } + MOZ_CRASH("invalid media protocol"); +} + +const SdpConnection& RsdparsaSdpMediaSection::GetConnection() const { + MOZ_ASSERT(mConnection); + return *mConnection; +} + +SdpConnection& RsdparsaSdpMediaSection::GetConnection() { + MOZ_ASSERT(mConnection); + return *mConnection; +} + +uint32_t RsdparsaSdpMediaSection::GetBandwidth(const std::string& type) const { + return sdp_get_media_bandwidth(mSection, type.c_str()); +} + +const std::vector<std::string>& RsdparsaSdpMediaSection::GetFormats() const { + return mFormats; +} + +const SdpAttributeList& RsdparsaSdpMediaSection::GetAttributeList() const { + return *mAttributeList; +} + +SdpAttributeList& RsdparsaSdpMediaSection::GetAttributeList() { + return *mAttributeList; +} + +SdpDirectionAttribute RsdparsaSdpMediaSection::GetDirectionAttribute() const { + return SdpDirectionAttribute(mAttributeList->GetDirection()); +} + +void RsdparsaSdpMediaSection::AddCodec(const std::string& pt, + const std::string& name, + uint32_t clockrate, uint16_t channels) { + StringView rustName{name.c_str(), name.size()}; + + // call the rust interface + auto nr = sdp_media_add_codec(mSection, std::stoul(pt), rustName, clockrate, + channels); + + if (NS_SUCCEEDED(nr)) { + // If the rust call was successful, adjust the shadow C++ structures + mFormats.push_back(pt); + + // Add a rtpmap in mAttributeList + SdpRtpmapAttributeList* rtpmap = new SdpRtpmapAttributeList(); + if (mAttributeList->HasAttribute(SdpAttribute::kRtpmapAttribute)) { + const SdpRtpmapAttributeList& old = mAttributeList->GetRtpmap(); + for (auto it = old.mRtpmaps.begin(); it != old.mRtpmaps.end(); ++it) { + rtpmap->mRtpmaps.push_back(*it); + } + } + + SdpRtpmapAttributeList::CodecType codec = + SdpRtpmapAttributeList::kOtherCodec; + if (name == "opus") { + codec = SdpRtpmapAttributeList::kOpus; + } else if (name == "VP8") { + codec = SdpRtpmapAttributeList::kVP8; + } else if (name == "VP9") { + codec = SdpRtpmapAttributeList::kVP9; + } else if (name == "H264") { + codec = SdpRtpmapAttributeList::kH264; + } + + rtpmap->PushEntry(pt, codec, name, clockrate, channels); + mAttributeList->SetAttribute(rtpmap); + } +} + +void RsdparsaSdpMediaSection::ClearCodecs() { + // Clear the codecs in rust + sdp_media_clear_codecs(mSection); + + mFormats.clear(); + mAttributeList->RemoveAttribute(SdpAttribute::kRtpmapAttribute); + mAttributeList->RemoveAttribute(SdpAttribute::kFmtpAttribute); + mAttributeList->RemoveAttribute(SdpAttribute::kSctpmapAttribute); + mAttributeList->RemoveAttribute(SdpAttribute::kRtcpFbAttribute); +} + +void RsdparsaSdpMediaSection::AddDataChannel(const std::string& name, + uint16_t port, uint16_t streams, + uint32_t message_size) { + StringView rustName{name.c_str(), name.size()}; + auto nr = sdp_media_add_datachannel(mSection, rustName, port, streams, + message_size); + if (NS_SUCCEEDED(nr)) { + // Update the formats + mFormats.clear(); + LoadFormats(); + + // Update the attribute list + RsdparsaSessionHandle sessHandle(sdp_new_reference(mSession.get())); + auto sessAttributes = mAttributeList->mSessionAttributes; + mAttributeList.reset(new RsdparsaSdpAttributeList( + std::move(sessHandle), mSection, sessAttributes)); + } +} + +void RsdparsaSdpMediaSection::Serialize(std::ostream& os) const { + os << "m=" << mMediaType << " " << GetPort(); + if (GetPortCount()) { + os << "/" << GetPortCount(); + } + os << " " << GetProtocol(); + for (auto i = mFormats.begin(); i != mFormats.end(); ++i) { + os << " " << (*i); + } + os << CRLF; + + // We dont do i= + + if (mConnection) { + os << *mConnection; + } + + BandwidthVec* bwVec = sdp_get_media_bandwidth_vec(mSection); + char* bwString = sdp_serialize_bandwidth(bwVec); + if (bwString) { + os << bwString; + sdp_free_string(bwString); + } + + // We dont do k= because they're evil + + os << *mAttributeList; +} + +void RsdparsaSdpMediaSection::LoadFormats() { + RustSdpFormatType formatType = sdp_get_format_type(mSection); + if (formatType == RustSdpFormatType::kRustIntegers) { + U32Vec* vec = sdp_get_format_u32_vec(mSection); + size_t len = u32_vec_len(vec); + for (size_t i = 0; i < len; i++) { + uint32_t val; + u32_vec_get(vec, i, &val); + mFormats.push_back(std::to_string(val)); + } + } else { + StringVec* vec = sdp_get_format_string_vec(mSection); + mFormats = convertStringVec(vec); + } +} + +UniquePtr<SdpConnection> convertRustConnection(RustSdpConnection conn) { + auto address = convertExplicitlyTypedAddress(&conn.addr); + return MakeUnique<SdpConnection>(address.first, address.second, conn.ttl, + conn.amount); +} + +void RsdparsaSdpMediaSection::LoadConnection() { + RustSdpConnection conn; + nsresult nr; + if (sdp_media_has_connection(mSection)) { + nr = sdp_get_media_connection(mSection, &conn); + if (NS_SUCCEEDED(nr)) { + mConnection = convertRustConnection(conn); + } + } else if (sdp_session_has_connection(mSession.get())) { + nr = sdp_get_session_connection(mSession.get(), &conn); + if (NS_SUCCEEDED(nr)) { + mConnection = convertRustConnection(conn); + } + } +} + +} // namespace mozilla |