summaryrefslogtreecommitdiffstats
path: root/dom/media/webrtc/sdp/RsdparsaSdpMediaSection.cpp
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--dom/media/webrtc/sdp/RsdparsaSdpMediaSection.cpp253
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