JsepTrack.h (12402B)
1 /* This Source Code Form is subject to the terms of the Mozilla Public 2 * License, v. 2.0. If a copy of the MPL was not distributed with this file, 3 * You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 5 #ifndef _JSEPTRACK_H_ 6 #define _JSEPTRACK_H_ 7 8 #include <mozilla/UniquePtr.h> 9 10 #include <algorithm> 11 #include <functional> 12 #include <map> 13 #include <string> 14 #include <vector> 15 16 #include "jsep/JsepTrackEncoding.h" 17 #include "jsep/SsrcGenerator.h" 18 #include "libwebrtcglue/RtpRtcpConfig.h" 19 #include "mozilla/Preferences.h" 20 #include "nsError.h" 21 #include "sdp/Sdp.h" 22 #include "sdp/SdpAttribute.h" 23 #include "sdp/SdpMediaSection.h" 24 namespace mozilla { 25 26 class JsepTrackNegotiatedDetails { 27 public: 28 JsepTrackNegotiatedDetails() 29 : mTias(0), mRtpRtcpConf(webrtc::RtcpMode::kCompound, true) {} 30 31 JsepTrackNegotiatedDetails(const JsepTrackNegotiatedDetails& orig) 32 : mExtmap(orig.mExtmap), 33 mTias(orig.mTias), 34 mRtpRtcpConf(orig.mRtpRtcpConf) { 35 for (const auto& encoding : orig.mEncodings) { 36 mEncodings.emplace_back(new JsepTrackEncoding(*encoding)); 37 } 38 } 39 40 size_t GetEncodingCount() const { return mEncodings.size(); } 41 42 const JsepTrackEncoding& GetEncoding(size_t index) const { 43 MOZ_RELEASE_ASSERT(index < mEncodings.size()); 44 return *mEncodings[index]; 45 } 46 47 void TruncateEncodings(size_t aSize) { 48 if (mEncodings.size() < aSize) { 49 MOZ_ASSERT(false); 50 return; 51 } 52 mEncodings.resize(aSize); 53 } 54 55 const SdpExtmapAttributeList::Extmap* GetExt( 56 const std::string& ext_name) const { 57 auto it = mExtmap.find(ext_name); 58 if (it != mExtmap.end()) { 59 return &it->second; 60 } 61 return nullptr; 62 } 63 64 void ForEachRTPHeaderExtension( 65 const std::function<void(const SdpExtmapAttributeList::Extmap& extmap)>& 66 fn) const { 67 for (const auto& entry : mExtmap) { 68 fn(entry.second); 69 } 70 } 71 72 uint32_t GetTias() const { return mTias; } 73 74 RtpRtcpConfig GetRtpRtcpConfig() const { return mRtpRtcpConf; } 75 76 private: 77 friend class JsepTrack; 78 79 std::map<std::string, SdpExtmapAttributeList::Extmap> mExtmap; 80 std::vector<UniquePtr<JsepTrackEncoding>> mEncodings; 81 uint32_t mTias; // bits per second 82 RtpRtcpConfig mRtpRtcpConf; 83 }; 84 85 class JsepTrack { 86 public: 87 JsepTrack(mozilla::SdpMediaSection::MediaType type, sdp::Direction direction) 88 : mType(type), 89 mDirection(direction), 90 mActive(false), 91 mRemoteSetSendBit(false) {} 92 93 virtual ~JsepTrack() {} 94 95 void UpdateStreamIds(const std::vector<std::string>& streamIds) { 96 mStreamIds = streamIds; 97 } 98 99 void SetTrackId(const std::string& aTrackId) { mTrackId = aTrackId; } 100 101 void ClearStreamIds() { mStreamIds.clear(); } 102 103 void RecvTrackSetRemote(const Sdp& aSdp, const SdpMediaSection& aMsection); 104 void RecvTrackSetLocal(const SdpMediaSection& aMsection); 105 106 // This is called whenever a remote description is set; we do not wait for 107 // offer/answer to complete, since there's nothing to actually negotiate here. 108 void SendTrackSetRemote(SsrcGenerator& aSsrcGenerator, 109 const SdpMediaSection& aRemoteMsection); 110 111 JsepTrack(const JsepTrack& orig) { *this = orig; } 112 113 JsepTrack(JsepTrack&& orig) = default; 114 JsepTrack& operator=(JsepTrack&& rhs) = default; 115 116 JsepTrack& operator=(const JsepTrack& rhs) { 117 if (this != &rhs) { 118 mType = rhs.mType; 119 mStreamIds = rhs.mStreamIds; 120 mTrackId = rhs.mTrackId; 121 mCNAME = rhs.mCNAME; 122 mDirection = rhs.mDirection; 123 mRids = rhs.mRids; 124 mSsrcs = rhs.mSsrcs; 125 mSsrcToRtxSsrc = rhs.mSsrcToRtxSsrc; 126 mActive = rhs.mActive; 127 mRemoteSetSendBit = rhs.mRemoteSetSendBit; 128 mReceptive = rhs.mReceptive; 129 mMaxEncodings = rhs.mMaxEncodings; 130 mInHaveRemote = rhs.mInHaveRemote; 131 mRtxIsAllowed = rhs.mRtxIsAllowed; 132 mUsePreferredCodecsOrder = rhs.mUsePreferredCodecsOrder; 133 mFecCodec = rhs.mFecCodec; 134 mAudioPreferredCodec = rhs.mAudioPreferredCodec; 135 mVideoPreferredCodec = rhs.mVideoPreferredCodec; 136 mUniqueReceivePayloadTypes = rhs.mUniqueReceivePayloadTypes; 137 mReceivePayloadTypes = rhs.mReceivePayloadTypes; 138 mOtherReceivePayloadTypes = rhs.mOtherReceivePayloadTypes; 139 140 mPrototypeCodecs.clear(); 141 for (const auto& codec : rhs.mPrototypeCodecs) { 142 mPrototypeCodecs.emplace_back(codec->Clone()); 143 } 144 if (rhs.mNegotiatedDetails) { 145 mNegotiatedDetails.reset( 146 new JsepTrackNegotiatedDetails(*rhs.mNegotiatedDetails)); 147 } 148 } 149 return *this; 150 } 151 152 virtual mozilla::SdpMediaSection::MediaType GetMediaType() const { 153 return mType; 154 } 155 156 virtual const std::vector<std::string>& GetStreamIds() const { 157 return mStreamIds; 158 } 159 160 virtual const std::string& GetCNAME() const { return mCNAME; } 161 162 virtual void SetCNAME(const std::string& cname) { mCNAME = cname; } 163 164 virtual sdp::Direction GetDirection() const { return mDirection; } 165 166 virtual const std::vector<uint32_t>& GetSsrcs() const { return mSsrcs; } 167 168 virtual std::vector<uint32_t> GetRtxSsrcs() const { 169 std::vector<uint32_t> result; 170 if (mRtxIsAllowed && 171 Preferences::GetBool("media.peerconnection.video.use_rtx", false) && 172 !mSsrcToRtxSsrc.empty()) { 173 MOZ_ASSERT(mSsrcToRtxSsrc.size() == mSsrcs.size()); 174 for (const auto ssrc : mSsrcs) { 175 auto it = mSsrcToRtxSsrc.find(ssrc); 176 MOZ_ASSERT(it != mSsrcToRtxSsrc.end()); 177 result.push_back(it->second); 178 } 179 } 180 return result; 181 } 182 183 virtual void EnsureSsrcs(SsrcGenerator& ssrcGenerator, size_t aNumber); 184 185 bool GetActive() const { return mActive; } 186 187 void SetActive(bool active) { mActive = active; } 188 189 bool GetRemoteSetSendBit() const { return mRemoteSetSendBit; } 190 bool GetReceptive() const { return mReceptive; } 191 192 void PopulatePreferredCodecs( 193 const std::vector<UniquePtr<JsepCodecDescription>>& aPreferredCodecs, 194 bool aUsePreferredCodecsOrder); 195 196 virtual void PopulateCodecs( 197 const std::vector<UniquePtr<JsepCodecDescription>>& prototype, 198 bool aUsePreferredCodecsOrder = false); 199 200 template <class UnaryFunction> 201 void ForEachCodec(UnaryFunction func) { 202 std::for_each(mPrototypeCodecs.begin(), mPrototypeCodecs.end(), func); 203 } 204 205 template <class BinaryPredicate> 206 void SortCodecs(BinaryPredicate sorter) { 207 std::stable_sort(mPrototypeCodecs.begin(), mPrototypeCodecs.end(), sorter); 208 } 209 210 // These two are non-const because this is where ssrcs are chosen. 211 virtual void AddToOffer(SsrcGenerator& ssrcGenerator, SdpMediaSection* offer); 212 virtual void AddToAnswer(const SdpMediaSection& offer, 213 SsrcGenerator& ssrcGenerator, 214 SdpMediaSection* answer); 215 216 virtual nsresult Negotiate(const SdpMediaSection& answer, 217 const SdpMediaSection& remote, 218 const SdpMediaSection& local); 219 static void SetReceivePayloadTypes(std::vector<JsepTrack*>& tracks, 220 bool localOffer = false); 221 virtual void GetNegotiatedPayloadTypes( 222 std::vector<uint16_t>* payloadTypes) const; 223 224 // This will be set when negotiation is carried out. 225 virtual const JsepTrackNegotiatedDetails* GetNegotiatedDetails() const { 226 if (mNegotiatedDetails) { 227 return mNegotiatedDetails.get(); 228 } 229 return nullptr; 230 } 231 232 virtual JsepTrackNegotiatedDetails* GetNegotiatedDetails() { 233 if (mNegotiatedDetails) { 234 return mNegotiatedDetails.get(); 235 } 236 return nullptr; 237 } 238 239 virtual void ClearNegotiatedDetails() { mNegotiatedDetails.reset(); } 240 241 void SetRids(const std::vector<std::string>& aRids); 242 void ClearRids() { mRids.clear(); } 243 const std::vector<std::string>& GetRids() const { return mRids; } 244 245 void AddToMsection(const std::vector<std::string>& aRids, 246 sdp::Direction direction, SsrcGenerator& ssrcGenerator, 247 bool rtxEnabled, SdpMediaSection* msection); 248 249 // See Bug 1642419, this can be removed when all sites are working with RTX. 250 void SetRtxIsAllowed(bool aRtxIsAllowed) { mRtxIsAllowed = aRtxIsAllowed; } 251 252 void SetMaxEncodings(size_t aMax); 253 bool IsInHaveRemote() const { return mInHaveRemote; } 254 255 const std::string& GetFecCodecName() const { return mFecCodec; } 256 const std::string& GetAudioPreferredCodec() const { 257 return mAudioPreferredCodec; 258 } 259 const std::string& GetVideoPreferredCodec() const { 260 return mVideoPreferredCodec; 261 } 262 263 void ResetReceivePayloadTypes() { 264 mUniqueReceivePayloadTypes.clear(); 265 mOtherReceivePayloadTypes.clear(); 266 } 267 268 const std::vector<uint8_t>& GetUniqueReceivePayloadTypes() const { 269 return mUniqueReceivePayloadTypes; 270 } 271 272 const std::vector<uint8_t>& GetOtherReceivePayloadTypes() const { 273 return mOtherReceivePayloadTypes; 274 } 275 276 private: 277 std::vector<UniquePtr<JsepCodecDescription>> GetCodecClones() const; 278 static void EnsureNoDuplicatePayloadTypes( 279 std::vector<UniquePtr<JsepCodecDescription>>* codecs); 280 static void GetPayloadTypes( 281 const std::vector<UniquePtr<JsepCodecDescription>>& codecs, 282 std::vector<uint16_t>* pts); 283 void AddToMsection(const std::vector<UniquePtr<JsepCodecDescription>>& codecs, 284 SdpMediaSection* msection) const; 285 void GetRids(const SdpMediaSection& msection, sdp::Direction direction, 286 std::vector<SdpRidAttributeList::Rid>* rids) const; 287 void CreateEncodings( 288 const SdpMediaSection& remote, 289 const std::vector<UniquePtr<JsepCodecDescription>>& negotiatedCodecs, 290 JsepTrackNegotiatedDetails* details); 291 // Identifies codecs we want to store for logging purposes. 292 void MaybeStoreCodecToLog(const std::string& codec, 293 SdpMediaSection::MediaType type); 294 virtual std::vector<UniquePtr<JsepCodecDescription>> NegotiateCodecs( 295 const SdpMediaSection& remote, bool remoteIsOffer, 296 Maybe<const SdpMediaSection&> local); 297 298 void UpdateSsrcs(SsrcGenerator& ssrcGenerator, size_t encodings); 299 void PruneSsrcs(size_t aNumSsrcs); 300 bool IsRtxEnabled( 301 const std::vector<UniquePtr<JsepCodecDescription>>& codecs) const; 302 303 mozilla::SdpMediaSection::MediaType mType; 304 // These are the ids that everyone outside of JsepSession care about 305 std::vector<std::string> mStreamIds; 306 std::string mTrackId; 307 std::string mCNAME; 308 sdp::Direction mDirection; 309 std::vector<UniquePtr<JsepCodecDescription>> mPrototypeCodecs; 310 // List of rids. May be initially populated from JS, or from a remote SDP. 311 // Can be updated by remote SDP. If no negotiation has taken place at all, 312 // this will be empty. If negotiation has taken place, but no simulcast 313 // attr was negotiated, this will contain the empty string as a single 314 // element. If a simulcast attribute was negotiated, this will contain the 315 // negotiated rids. 316 std::vector<std::string> mRids; 317 UniquePtr<JsepTrackNegotiatedDetails> mNegotiatedDetails; 318 // Storage of mSsrcs and mSsrcToRtxSsrc could be improved, see Bug 1990364 319 std::vector<uint32_t> mSsrcs; 320 std::map<uint32_t, uint32_t> mSsrcToRtxSsrc; 321 bool mActive; 322 bool mRemoteSetSendBit; 323 // This is used to drive RTCRtpTransceiver.[[Receptive]]. Basically, this 324 // denotes whether we are prepared to receive RTP. When we apply a local 325 // description with the recv bit set, this is set to true, even if we have 326 // not seen the remote description yet. If we apply either a local or remote 327 // description without the recv bit set (from our perspective), this is set 328 // to false. 329 bool mReceptive = false; 330 size_t mMaxEncodings = 3; 331 bool mInHaveRemote = false; 332 333 // See Bug 1642419, this can be removed when all sites are working with RTX. 334 bool mRtxIsAllowed = true; 335 336 // Used with setCodecPreferences to determine if an answer created should 337 // match the order of preferred codecs. 338 bool mUsePreferredCodecsOrder = false; 339 340 // Codec names for logging 341 std::string mFecCodec; 342 std::string mAudioPreferredCodec; 343 std::string mVideoPreferredCodec; 344 345 // Only the unique PTs we are willing to receive, not necessarily all PTs. 346 // Used for matching SSRC to PT as only unique PTs support for this. 347 std::vector<uint8_t> mUniqueReceivePayloadTypes; 348 std::vector<uint16_t> mReceivePayloadTypes; 349 // Payload types that are registered to some track but not us. 350 std::vector<uint8_t> mOtherReceivePayloadTypes; 351 }; 352 353 } // namespace mozilla 354 355 #endif