tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

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