summaryrefslogtreecommitdiffstats
path: root/dom/media/webrtc/jsep/JsepTrack.h
diff options
context:
space:
mode:
Diffstat (limited to 'dom/media/webrtc/jsep/JsepTrack.h')
-rw-r--r--dom/media/webrtc/jsep/JsepTrack.h305
1 files changed, 305 insertions, 0 deletions
diff --git a/dom/media/webrtc/jsep/JsepTrack.h b/dom/media/webrtc/jsep/JsepTrack.h
new file mode 100644
index 0000000000..70583ccb71
--- /dev/null
+++ b/dom/media/webrtc/jsep/JsepTrack.h
@@ -0,0 +1,305 @@
+/* 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/. */
+
+#ifndef _JSEPTRACK_H_
+#define _JSEPTRACK_H_
+
+#include <functional>
+#include <algorithm>
+#include <string>
+#include <map>
+#include <set>
+#include <vector>
+
+#include <mozilla/UniquePtr.h>
+#include "mozilla/Preferences.h"
+#include "nsError.h"
+
+#include "jsep/JsepTrackEncoding.h"
+#include "jsep/SsrcGenerator.h"
+#include "sdp/Sdp.h"
+#include "sdp/SdpAttribute.h"
+#include "sdp/SdpMediaSection.h"
+#include "libwebrtcglue/RtpRtcpConfig.h"
+namespace mozilla {
+
+class JsepTrackNegotiatedDetails {
+ public:
+ JsepTrackNegotiatedDetails()
+ : mTias(0), mRtpRtcpConf(webrtc::RtcpMode::kCompound) {}
+
+ JsepTrackNegotiatedDetails(const JsepTrackNegotiatedDetails& orig)
+ : mExtmap(orig.mExtmap),
+ mUniquePayloadTypes(orig.mUniquePayloadTypes),
+ mTias(orig.mTias),
+ mRtpRtcpConf(orig.mRtpRtcpConf) {
+ for (const auto& encoding : orig.mEncodings) {
+ mEncodings.emplace_back(new JsepTrackEncoding(*encoding));
+ }
+ }
+
+ size_t GetEncodingCount() const { return mEncodings.size(); }
+
+ const JsepTrackEncoding& GetEncoding(size_t index) const {
+ MOZ_RELEASE_ASSERT(index < mEncodings.size());
+ return *mEncodings[index];
+ }
+
+ void TruncateEncodings(size_t aSize) {
+ if (mEncodings.size() < aSize) {
+ MOZ_ASSERT(false);
+ return;
+ }
+ mEncodings.resize(aSize);
+ }
+
+ const SdpExtmapAttributeList::Extmap* GetExt(
+ const std::string& ext_name) const {
+ auto it = mExtmap.find(ext_name);
+ if (it != mExtmap.end()) {
+ return &it->second;
+ }
+ return nullptr;
+ }
+
+ void ForEachRTPHeaderExtension(
+ const std::function<void(const SdpExtmapAttributeList::Extmap& extmap)>&
+ fn) const {
+ for (auto entry : mExtmap) {
+ fn(entry.second);
+ }
+ }
+
+ std::vector<uint8_t> GetUniquePayloadTypes() const {
+ return mUniquePayloadTypes;
+ }
+
+ uint32_t GetTias() const { return mTias; }
+
+ RtpRtcpConfig GetRtpRtcpConfig() const { return mRtpRtcpConf; }
+
+ private:
+ friend class JsepTrack;
+
+ std::map<std::string, SdpExtmapAttributeList::Extmap> mExtmap;
+ std::vector<uint8_t> mUniquePayloadTypes;
+ std::vector<UniquePtr<JsepTrackEncoding>> mEncodings;
+ uint32_t mTias; // bits per second
+ RtpRtcpConfig mRtpRtcpConf;
+};
+
+class JsepTrack {
+ public:
+ JsepTrack(mozilla::SdpMediaSection::MediaType type, sdp::Direction direction)
+ : mType(type),
+ mDirection(direction),
+ mActive(false),
+ mRemoteSetSendBit(false) {}
+
+ virtual ~JsepTrack() {}
+
+ void UpdateStreamIds(const std::vector<std::string>& streamIds) {
+ mStreamIds = streamIds;
+ }
+
+ void SetTrackId(const std::string& aTrackId) { mTrackId = aTrackId; }
+
+ void ClearStreamIds() { mStreamIds.clear(); }
+
+ void RecvTrackSetRemote(const Sdp& aSdp, const SdpMediaSection& aMsection);
+ void RecvTrackSetLocal(const SdpMediaSection& aMsection);
+
+ // This is called whenever a remote description is set; we do not wait for
+ // offer/answer to complete, since there's nothing to actually negotiate here.
+ void SendTrackSetRemote(SsrcGenerator& aSsrcGenerator,
+ const SdpMediaSection& aRemoteMsection);
+
+ JsepTrack(const JsepTrack& orig) { *this = orig; }
+
+ JsepTrack(JsepTrack&& orig) = default;
+ JsepTrack& operator=(JsepTrack&& rhs) = default;
+
+ JsepTrack& operator=(const JsepTrack& rhs) {
+ if (this != &rhs) {
+ mType = rhs.mType;
+ mStreamIds = rhs.mStreamIds;
+ mTrackId = rhs.mTrackId;
+ mCNAME = rhs.mCNAME;
+ mDirection = rhs.mDirection;
+ mRids = rhs.mRids;
+ mSsrcs = rhs.mSsrcs;
+ mSsrcToRtxSsrc = rhs.mSsrcToRtxSsrc;
+ mActive = rhs.mActive;
+ mRemoteSetSendBit = rhs.mRemoteSetSendBit;
+ mReceptive = rhs.mReceptive;
+ mMaxEncodings = rhs.mMaxEncodings;
+ mInHaveRemote = rhs.mInHaveRemote;
+ mRtxIsAllowed = rhs.mRtxIsAllowed;
+
+ mPrototypeCodecs.clear();
+ for (const auto& codec : rhs.mPrototypeCodecs) {
+ mPrototypeCodecs.emplace_back(codec->Clone());
+ }
+ if (rhs.mNegotiatedDetails) {
+ mNegotiatedDetails.reset(
+ new JsepTrackNegotiatedDetails(*rhs.mNegotiatedDetails));
+ }
+ }
+ return *this;
+ }
+
+ virtual mozilla::SdpMediaSection::MediaType GetMediaType() const {
+ return mType;
+ }
+
+ virtual const std::vector<std::string>& GetStreamIds() const {
+ return mStreamIds;
+ }
+
+ virtual const std::string& GetCNAME() const { return mCNAME; }
+
+ virtual void SetCNAME(const std::string& cname) { mCNAME = cname; }
+
+ virtual sdp::Direction GetDirection() const { return mDirection; }
+
+ virtual const std::vector<uint32_t>& GetSsrcs() const { return mSsrcs; }
+
+ virtual std::vector<uint32_t> GetRtxSsrcs() const {
+ std::vector<uint32_t> result;
+ if (mRtxIsAllowed &&
+ Preferences::GetBool("media.peerconnection.video.use_rtx", false)) {
+ std::for_each(
+ mSsrcToRtxSsrc.begin(), mSsrcToRtxSsrc.end(),
+ [&result](const auto& pair) { result.push_back(pair.second); });
+ }
+ return result;
+ }
+
+ virtual void EnsureSsrcs(SsrcGenerator& ssrcGenerator, size_t aNumber);
+
+ bool GetActive() const { return mActive; }
+
+ void SetActive(bool active) { mActive = active; }
+
+ bool GetRemoteSetSendBit() const { return mRemoteSetSendBit; }
+ bool GetReceptive() const { return mReceptive; }
+
+ virtual void PopulateCodecs(
+ const std::vector<UniquePtr<JsepCodecDescription>>& prototype);
+
+ template <class UnaryFunction>
+ void ForEachCodec(UnaryFunction func) {
+ std::for_each(mPrototypeCodecs.begin(), mPrototypeCodecs.end(), func);
+ }
+
+ template <class BinaryPredicate>
+ void SortCodecs(BinaryPredicate sorter) {
+ std::stable_sort(mPrototypeCodecs.begin(), mPrototypeCodecs.end(), sorter);
+ }
+
+ // These two are non-const because this is where ssrcs are chosen.
+ virtual void AddToOffer(SsrcGenerator& ssrcGenerator, SdpMediaSection* offer);
+ virtual void AddToAnswer(const SdpMediaSection& offer,
+ SsrcGenerator& ssrcGenerator,
+ SdpMediaSection* answer);
+
+ virtual nsresult Negotiate(const SdpMediaSection& answer,
+ const SdpMediaSection& remote,
+ const SdpMediaSection& local);
+ static void SetUniquePayloadTypes(std::vector<JsepTrack*>& tracks);
+ virtual void GetNegotiatedPayloadTypes(
+ std::vector<uint16_t>* payloadTypes) const;
+
+ // This will be set when negotiation is carried out.
+ virtual const JsepTrackNegotiatedDetails* GetNegotiatedDetails() const {
+ if (mNegotiatedDetails) {
+ return mNegotiatedDetails.get();
+ }
+ return nullptr;
+ }
+
+ virtual JsepTrackNegotiatedDetails* GetNegotiatedDetails() {
+ if (mNegotiatedDetails) {
+ return mNegotiatedDetails.get();
+ }
+ return nullptr;
+ }
+
+ virtual void ClearNegotiatedDetails() { mNegotiatedDetails.reset(); }
+
+ void SetRids(const std::vector<std::string>& aRids);
+ void ClearRids() { mRids.clear(); }
+ const std::vector<std::string>& GetRids() const { return mRids; }
+
+ void AddToMsection(const std::vector<std::string>& aRids,
+ sdp::Direction direction, SsrcGenerator& ssrcGenerator,
+ bool rtxEnabled, SdpMediaSection* msection);
+
+ // See Bug 1642419, this can be removed when all sites are working with RTX.
+ void SetRtxIsAllowed(bool aRtxIsAllowed) { mRtxIsAllowed = aRtxIsAllowed; }
+
+ void SetMaxEncodings(size_t aMax);
+ bool IsInHaveRemote() const { return mInHaveRemote; }
+
+ private:
+ std::vector<UniquePtr<JsepCodecDescription>> GetCodecClones() const;
+ static void EnsureNoDuplicatePayloadTypes(
+ std::vector<UniquePtr<JsepCodecDescription>>* codecs);
+ static void GetPayloadTypes(
+ const std::vector<UniquePtr<JsepCodecDescription>>& codecs,
+ std::vector<uint16_t>* pts);
+ void AddToMsection(const std::vector<UniquePtr<JsepCodecDescription>>& codecs,
+ SdpMediaSection* msection) const;
+ void GetRids(const SdpMediaSection& msection, sdp::Direction direction,
+ std::vector<SdpRidAttributeList::Rid>* rids) const;
+ void CreateEncodings(
+ const SdpMediaSection& remote,
+ const std::vector<UniquePtr<JsepCodecDescription>>& negotiatedCodecs,
+ JsepTrackNegotiatedDetails* details);
+
+ virtual std::vector<UniquePtr<JsepCodecDescription>> NegotiateCodecs(
+ const SdpMediaSection& remote, bool remoteIsOffer,
+ Maybe<const SdpMediaSection&> local);
+
+ void UpdateSsrcs(SsrcGenerator& ssrcGenerator, size_t encodings);
+ void PruneSsrcs(size_t aNumSsrcs);
+ bool IsRtxEnabled(
+ const std::vector<UniquePtr<JsepCodecDescription>>& codecs) const;
+
+ mozilla::SdpMediaSection::MediaType mType;
+ // These are the ids that everyone outside of JsepSession care about
+ std::vector<std::string> mStreamIds;
+ std::string mTrackId;
+ std::string mCNAME;
+ sdp::Direction mDirection;
+ std::vector<UniquePtr<JsepCodecDescription>> mPrototypeCodecs;
+ // List of rids. May be initially populated from JS, or from a remote SDP.
+ // Can be updated by remote SDP. If no negotiation has taken place at all,
+ // this will be empty. If negotiation has taken place, but no simulcast
+ // attr was negotiated, this will contain the empty string as a single
+ // element. If a simulcast attribute was negotiated, this will contain the
+ // negotiated rids.
+ std::vector<std::string> mRids;
+ UniquePtr<JsepTrackNegotiatedDetails> mNegotiatedDetails;
+ std::vector<uint32_t> mSsrcs;
+ std::map<uint32_t, uint32_t> mSsrcToRtxSsrc;
+ bool mActive;
+ bool mRemoteSetSendBit;
+ // This is used to drive RTCRtpTransceiver.[[Receptive]]. Basically, this
+ // denotes whether we are prepared to receive RTP. When we apply a local
+ // description with the recv bit set, this is set to true, even if we have
+ // not seen the remote description yet. If we apply either a local or remote
+ // description without the recv bit set (from our perspective), this is set
+ // to false.
+ bool mReceptive = false;
+ size_t mMaxEncodings = 3;
+ bool mInHaveRemote = false;
+
+ // See Bug 1642419, this can be removed when all sites are working with RTX.
+ bool mRtxIsAllowed = true;
+};
+
+} // namespace mozilla
+
+#endif