MediaPipeline.h (17086B)
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* This Source Code Form is subject to the terms of the Mozilla Public 3 * License, v. 2.0. If a copy of the MPL was not distributed with this file, 4 * You can obtain one at http://mozilla.org/MPL/2.0/. */ 5 6 // Original author: ekr@rtfm.com 7 8 #ifndef mediapipeline_h__ 9 #define mediapipeline_h__ 10 11 #include <map> 12 13 #include "AudioPacketizer.h" 14 #include "MediaEventSource.h" 15 #include "MediaPipelineFilter.h" 16 #include "MediaSegment.h" 17 #include "PerformanceRecorder.h" 18 #include "PrincipalChangeObserver.h" 19 #include "jsapi/PacketDumper.h" 20 #include "libwebrtcglue/MediaConduitControl.h" 21 #include "mozilla/Atomics.h" 22 #include "mozilla/ReentrantMonitor.h" 23 #include "mozilla/StateMirroring.h" 24 #include "rtc_base/copy_on_write_buffer.h" 25 #include "transport/mediapacket.h" 26 #include "transport/runnable_utils.h" 27 #include "transport/sigslot.h" 28 #include "transport/transportlayer.h" // For TransportLayer::State 29 30 // Should come from MediaEngine.h, but that's a pain to include here 31 // because of the MOZILLA_EXTERNAL_LINKAGE stuff. 32 #define WEBRTC_MAX_SAMPLE_RATE 48000 33 34 class nsIPrincipal; 35 36 namespace webrtc { 37 struct RTPHeader; 38 class RtpHeaderExtensionMap; 39 class RtpPacketReceived; 40 } // namespace webrtc 41 42 namespace mozilla { 43 class AudioProxyThread; 44 class MediaInputPort; 45 class MediaPipelineFilter; 46 class MediaTransportHandler; 47 class PeerIdentity; 48 class ProcessedMediaTrack; 49 class SourceMediaTrack; 50 class VideoFrameConverter; 51 class MediaSessionConduit; 52 class AudioSessionConduit; 53 class VideoSessionConduit; 54 55 namespace dom { 56 class MediaStreamTrack; 57 struct RTCRTPContributingSourceStats; 58 class RTCStatsTimestampMaker; 59 } // namespace dom 60 61 struct MediaPipelineReceiveControlInterface { 62 virtual Canonical<bool>& CanonicalReceiving() = 0; 63 }; 64 65 struct MediaPipelineTransmitControlInterface { 66 virtual Canonical<bool>& CanonicalTransmitting() = 0; 67 }; 68 69 // A class that represents the pipeline of audio and video 70 // The dataflow looks like: 71 // 72 // TRANSMIT 73 // CaptureDevice -> stream -> [us] -> conduit -> [us] -> transport -> network 74 // 75 // RECEIVE 76 // network -> transport -> [us] -> conduit -> [us] -> stream -> Playout 77 // 78 // The boxes labeled [us] are just bridge logic implemented in this class 79 // 80 // We have to deal with a number of threads: 81 // 82 // GSM: 83 // * Assembles the pipeline 84 // SocketTransportService 85 // * Receives notification that ICE and DTLS have completed 86 // * Processes incoming network data and passes it to the conduit 87 // * Processes outgoing RTP and RTCP 88 // MediaTrackGraph 89 // * Receives outgoing data from the MediaTrackGraph 90 // * Receives pull requests for more data from the 91 // MediaTrackGraph 92 // One or another GIPS threads 93 // * Receives RTCP messages to send to the other side 94 // * Processes video frames GIPS wants to render 95 // 96 // For a transmitting conduit, "output" is RTP and "input" is RTCP. 97 // For a receiving conduit, "input" is RTP and "output" is RTCP. 98 // 99 100 class MediaPipeline : public sigslot::has_slots<> { 101 public: 102 enum class DirectionType { TRANSMIT, RECEIVE }; 103 MediaPipeline(const std::string& aPc, 104 RefPtr<MediaTransportHandler> aTransportHandler, 105 DirectionType aDirection, RefPtr<AbstractThread> aCallThread, 106 RefPtr<nsISerialEventTarget> aStsThread, 107 RefPtr<MediaSessionConduit> aConduit); 108 109 void SetLevel(size_t aLevel) { mLevel = aLevel; } 110 111 // Main thread shutdown. 112 virtual void Shutdown(); 113 114 void UpdateTransport_m(const std::string& aTransportId, 115 UniquePtr<MediaPipelineFilter>&& aFilter, 116 bool aSignalingStable); 117 118 void UpdateTransport_s(const std::string& aTransportId, 119 UniquePtr<MediaPipelineFilter>&& aFilter, 120 bool aSignalingStable); 121 122 void UpdateActive(); 123 virtual DirectionType Direction() const { return mDirection; } 124 size_t Level() const { return mLevel; } 125 virtual bool IsVideo() const = 0; 126 127 class RtpCSRCStats { 128 public: 129 // Gets an expiration time for CRC info given a reference time, 130 // this reference time would normally be the time of calling. 131 // This value can then be used to check if a RtpCSRCStats 132 // has expired via Expired(...) 133 static DOMHighResTimeStamp GetExpiryFromTime( 134 const DOMHighResTimeStamp aTime); 135 136 RtpCSRCStats(const uint32_t aCsrc, const DOMHighResTimeStamp aTime); 137 ~RtpCSRCStats() = default; 138 // Initialize a webidl representation suitable for adding to a report. 139 // This assumes that the webidl object is empty. 140 // @param aWebidlObj the webidl binding object to popluate 141 // @param aInboundRtpStreamId the associated RTCInboundRTPStreamStats.id 142 void GetWebidlInstance(dom::RTCRTPContributingSourceStats& aWebidlObj, 143 const nsString& aInboundRtpStreamId) const; 144 void SetTimestamp(const DOMHighResTimeStamp aTime) { mTimestamp = aTime; } 145 // Check if the RtpCSRCStats has expired, checks against a 146 // given expiration time. 147 bool Expired(const DOMHighResTimeStamp aExpiry) const { 148 return mTimestamp < aExpiry; 149 } 150 151 private: 152 static const double constexpr EXPIRY_TIME_MILLISECONDS = 10 * 1000; 153 const uint32_t mCsrc; 154 DOMHighResTimeStamp mTimestamp; 155 }; 156 157 // Gets the gathered contributing source stats for the last expiration period. 158 // @param aId the stream id to use for populating inboundRtpStreamId field 159 // @param aArr the array to append the stats objects to 160 void GetContributingSourceStats( 161 const nsString& aInboundRtpStreamId, 162 FallibleTArray<dom::RTCRTPContributingSourceStats>& aArr) const; 163 164 int32_t RtpPacketsSent() const { return mRtpPacketsSent; } 165 int64_t RtpBytesSent() const { return mRtpBytesSent; } 166 int32_t RtcpPacketsSent() const { return mRtcpPacketsSent; } 167 int32_t RtpPacketsReceived() const { return mRtpPacketsReceived; } 168 int64_t RtpBytesReceived() const { return mRtpBytesReceived; } 169 170 const dom::RTCStatsTimestampMaker& GetTimestampMaker() const; 171 172 // Thread counting 173 NS_INLINE_DECL_THREADSAFE_REFCOUNTING(MediaPipeline) 174 175 protected: 176 virtual ~MediaPipeline(); 177 178 // The transport is ready 179 virtual void TransportReady_s() {} 180 181 void IncrementRtpPacketsSent(const MediaPacket& aPacket); 182 void IncrementRtcpPacketsSent(); 183 void IncrementRtpPacketsReceived(int aBytes); 184 185 virtual void SendPacket(MediaPacket&& packet); 186 187 // Process slots on transports 188 void RtpStateChange(const std::string& aTransportId, TransportLayer::State); 189 void RtcpStateChange(const std::string& aTransportId, TransportLayer::State); 190 virtual void CheckTransportStates(); 191 void PacketReceived(std::string& aTransportId, MediaPacket& packet); 192 void RtpPacketReceived(std::string& aTransportId, MediaPacket& packet); 193 void RtcpPacketReceived(std::string& aTransportId, MediaPacket& packet); 194 void AlpnNegotiated(const std::string& aAlpn, bool aPrivacyRequested); 195 196 void EncryptedPacketSending(const std::string& aTransportId, 197 const MediaPacket& aPacket); 198 199 void SetDescription_s(const std::string& description); 200 201 public: 202 const RefPtr<MediaSessionConduit> mConduit; 203 const DirectionType mDirection; 204 205 // Pointers to the threads we need. Initialized at creation 206 // and used all over the place. 207 const RefPtr<AbstractThread> mCallThread; 208 const RefPtr<nsISerialEventTarget> mStsThread; 209 210 protected: 211 // True if we should be actively transmitting or receiving data. Main thread 212 // only. 213 Mirror<bool> mActive; 214 // Variant of mActive, manually mirrored to the STS thread. 215 bool mActiveSts; 216 Atomic<size_t> mLevel; 217 std::string mTransportId; 218 const RefPtr<MediaTransportHandler> mTransportHandler; 219 220 TransportLayer::State mRtpState = TransportLayer::TS_NONE; 221 TransportLayer::State mRtcpState = TransportLayer::TS_NONE; 222 bool mSignalsConnected = false; 223 224 // Only safe to access from STS thread. 225 int32_t mRtpPacketsSent; 226 int32_t mRtcpPacketsSent; 227 int32_t mRtpPacketsReceived; 228 int64_t mRtpBytesSent; 229 int64_t mRtpBytesReceived; 230 231 // Only safe to access from STS thread. 232 std::map<uint32_t, RtpCSRCStats> mCsrcStats; 233 234 // Written in c'tor. Read on STS and main thread. 235 const std::string mPc; 236 237 // String describing this MediaPipeline for logging purposes. Only safe to 238 // access from STS thread. 239 std::string mDescription; 240 241 // Written in c'tor, all following accesses are on the STS thread. 242 UniquePtr<MediaPipelineFilter> mFilter; 243 const UniquePtr<webrtc::RtpHeaderExtensionMap> mRtpHeaderExtensionMap; 244 245 RefPtr<PacketDumper> mPacketDumper; 246 247 MediaEventProducerExc<webrtc::RtpPacketReceived, webrtc::RTPHeader> 248 mRtpReceiveEvent; 249 MediaEventProducerExc<webrtc::CopyOnWriteBuffer> mRtcpReceiveEvent; 250 251 MediaEventListener mRtpSendEventListener; 252 MediaEventListener mSenderRtcpSendEventListener; 253 MediaEventListener mReceiverRtcpSendEventListener; 254 MediaEventListener mRtpPacketReceivedListener; 255 MediaEventListener mStateChangeListener; 256 MediaEventListener mRtcpStateChangeListener; 257 MediaEventListener mEncryptedSendingListener; 258 MediaEventListener mAlpnNegotiatedListener; 259 260 private: 261 bool IsRtp(const unsigned char* aData, size_t aLen) const; 262 // Must be called on the STS thread. Must be called after Shutdown(). 263 void DetachTransport_s(); 264 }; 265 266 // A specialization of pipeline for reading from an input device 267 // and transmitting to the network. 268 class MediaPipelineTransmit 269 : public MediaPipeline, 270 public dom::PrincipalChangeObserver<dom::MediaStreamTrack> { 271 private: 272 // Set aRtcpTransport to nullptr to use rtcp-mux 273 MediaPipelineTransmit(const std::string& aPc, 274 RefPtr<MediaTransportHandler> aTransportHandler, 275 RefPtr<AbstractThread> aCallThread, 276 RefPtr<nsISerialEventTarget> aStsThread, bool aIsVideo, 277 RefPtr<MediaSessionConduit> aConduit); 278 279 void RegisterListener(); 280 281 public: 282 static already_AddRefed<MediaPipelineTransmit> Create( 283 const std::string& aPc, RefPtr<MediaTransportHandler> aTransportHandler, 284 RefPtr<AbstractThread> aCallThread, 285 RefPtr<nsISerialEventTarget> aStsThread, bool aIsVideo, 286 RefPtr<MediaSessionConduit> aConduit); 287 288 void InitControl(MediaPipelineTransmitControlInterface* aControl); 289 290 void Shutdown() override; 291 292 bool Transmitting() const; 293 294 // written and used from MainThread 295 bool IsVideo() const override; 296 297 // When the principal of the domtrack changes, it calls through to here 298 // so that we can determine whether to enable track transmission. 299 // In cases where the peer isn't yet identified, we disable the pipeline (not 300 // the stream, that would potentially affect others), so that it sends 301 // black/silence. Once the peer is identified, re-enable those streams. 302 virtual void UpdateSinkIdentity(nsIPrincipal* aPrincipal, 303 const PeerIdentity* aSinkIdentity); 304 305 // for monitoring changes in track ownership 306 void PrincipalChanged(dom::MediaStreamTrack* aTrack) override; 307 308 // Override MediaPipeline::TransportReady_s. 309 void TransportReady_s() override; 310 311 // Replace a track with a different one. 312 nsresult SetTrack(const RefPtr<dom::MediaStreamTrack>& aDomTrack); 313 314 // Used to correlate stats 315 RefPtr<dom::MediaStreamTrack> GetTrack() const; 316 317 // For test use only. This allows a send track to be set without a 318 // corresponding dom track. 319 void SetSendTrackOverride(const RefPtr<ProcessedMediaTrack>& aSendTrack); 320 321 // Separate classes to allow ref counting 322 class PipelineListener; 323 class VideoFrameFeeder; 324 325 protected: 326 ~MediaPipelineTransmit(); 327 328 // Updates mDescription (async) with information about the track we are 329 // transmitting. 330 std::string GenerateDescription() const; 331 332 // Sets up mSendPort and mSendTrack to feed mConduit if we are transmitting 333 // and have a dom track but no send track. Main thread only. 334 void UpdateSendState(); 335 336 private: 337 WatchManager<MediaPipelineTransmit> mWatchManager; 338 const bool mIsVideo; 339 const RefPtr<PipelineListener> mListener; 340 RefPtr<AudioProxyThread> mAudioProcessing; 341 RefPtr<VideoFrameConverter> mConverter; 342 MediaEventListener mFrameListener; 343 Watchable<RefPtr<dom::MediaStreamTrack>> mDomTrack; 344 // Input port connecting mDomTrack's MediaTrack to mSendTrack. 345 RefPtr<MediaInputPort> mSendPort; 346 // The source track of the mSendTrack. Main thread only. 347 RefPtr<ProcessedMediaTrack> mSendPortSource; 348 // True if a parameter affecting mDescription has changed. To avoid updating 349 // the description unnecessarily. Main thread only. 350 bool mDescriptionInvalidated = true; 351 // Set true once we trigger the async removal of mSendTrack. Set false once 352 // the async removal is done. Main thread only. 353 bool mUnsettingSendTrack = false; 354 // MediaTrack that we send over the network. This allows changing mDomTrack. 355 // Because changing mSendTrack is async and can be racy (when changing from a 356 // track in one graph to a track in another graph), it is set very strictly. 357 // If mSendTrack is null it can be set by UpdateSendState(). 358 // If it is non-null it can only be set to null, and only by the 359 // RemoveListener MozPromise handler, as seen in UpdateSendState. 360 RefPtr<ProcessedMediaTrack> mSendTrack; 361 // When this is set and we are active, this track will be used as mSendTrack. 362 // Allows unittests to insert a send track without requiring a dom track or a 363 // graph. Main thread only. 364 Watchable<RefPtr<ProcessedMediaTrack>> mSendTrackOverride; 365 // True when mSendTrack is set, not destroyed and mActive is true. mListener 366 // is attached to mSendTrack when this is true. Main thread only. 367 bool mTransmitting = false; 368 }; 369 370 // A specialization of pipeline for reading from the network and 371 // rendering media. 372 class MediaPipelineReceive : public MediaPipeline { 373 public: 374 // Set aRtcpTransport to nullptr to use rtcp-mux 375 MediaPipelineReceive(const std::string& aPc, 376 RefPtr<MediaTransportHandler> aTransportHandler, 377 RefPtr<AbstractThread> aCallThread, 378 RefPtr<nsISerialEventTarget> aStsThread, 379 RefPtr<MediaSessionConduit> aConduit); 380 381 void InitControl(MediaPipelineReceiveControlInterface* aControl); 382 383 // Called when ALPN is negotiated and is requesting privacy, so receive 384 // pipelines do not enter data into the graph under a content principal. 385 virtual void OnPrivacyRequested_s() = 0; 386 387 // Called after privacy has been requested, with the updated private 388 // principal. 389 virtual void SetPrivatePrincipal(PrincipalHandle aHandle) = 0; 390 391 void Shutdown() override; 392 393 protected: 394 ~MediaPipelineReceive(); 395 396 virtual void UpdateListener() = 0; 397 398 private: 399 WatchManager<MediaPipelineReceive> mWatchManager; 400 }; 401 402 // A specialization of pipeline for reading from the network and 403 // rendering audio. 404 class MediaPipelineReceiveAudio : public MediaPipelineReceive { 405 public: 406 MediaPipelineReceiveAudio(const std::string& aPc, 407 RefPtr<MediaTransportHandler> aTransportHandler, 408 RefPtr<AbstractThread> aCallThread, 409 RefPtr<nsISerialEventTarget> aStsThread, 410 RefPtr<AudioSessionConduit> aConduit, 411 RefPtr<SourceMediaTrack> aSource, 412 TrackingId aTrackingId, 413 PrincipalHandle aPrincipalHandle, 414 PrincipalPrivacy aPrivacy); 415 416 void Shutdown() override; 417 418 bool IsVideo() const override { return false; } 419 420 void OnPrivacyRequested_s() override; 421 void SetPrivatePrincipal(PrincipalHandle aHandle) override; 422 423 private: 424 void UpdateListener() override; 425 426 // Separate class to allow ref counting 427 class PipelineListener; 428 429 const RefPtr<PipelineListener> mListener; 430 }; 431 432 // A specialization of pipeline for reading from the network and 433 // rendering video. 434 class MediaPipelineReceiveVideo : public MediaPipelineReceive { 435 public: 436 MediaPipelineReceiveVideo(const std::string& aPc, 437 RefPtr<MediaTransportHandler> aTransportHandler, 438 RefPtr<AbstractThread> aCallThread, 439 RefPtr<nsISerialEventTarget> aStsThread, 440 RefPtr<VideoSessionConduit> aConduit, 441 RefPtr<SourceMediaTrack> aSource, 442 TrackingId aTrackingId, 443 PrincipalHandle aPrincipalHandle, 444 PrincipalPrivacy aPrivacy); 445 446 void Shutdown() override; 447 448 bool IsVideo() const override { return true; } 449 450 void OnPrivacyRequested_s() override; 451 void SetPrivatePrincipal(PrincipalHandle aHandle) override; 452 453 private: 454 void UpdateListener() override; 455 456 class PipelineRenderer; 457 friend class PipelineRenderer; 458 459 // Separate class to allow ref counting 460 class PipelineListener; 461 462 const RefPtr<PipelineRenderer> mRenderer; 463 const RefPtr<PipelineListener> mListener; 464 }; 465 466 } // namespace mozilla 467 #endif