tor-browser

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

MediaConduitInterface.h (17134B)


      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 MEDIA_CONDUIT_ABSTRACTION_
      6 #define MEDIA_CONDUIT_ABSTRACTION_
      7 
      8 #include <functional>
      9 #include <map>
     10 #include <vector>
     11 
     12 #include "CodecConfig.h"
     13 #include "ImageContainer.h"
     14 #include "MediaConduitControl.h"
     15 #include "MediaConduitErrors.h"
     16 #include "PerformanceRecorder.h"
     17 #include "WebrtcVideoCodecFactory.h"
     18 #include "jsapi/RTCStatsReport.h"
     19 #include "mozilla/MozPromise.h"
     20 #include "mozilla/dom/RTCRtpSourcesBinding.h"
     21 #include "mozilla/media/MediaUtils.h"
     22 #include "nsTArray.h"
     23 #include "transport/mediapacket.h"
     24 
     25 // libwebrtc includes
     26 #include "api/audio/audio_frame.h"
     27 #include "api/call/transport.h"
     28 #include "api/media_stream_interface.h"
     29 #include "api/rtp_headers.h"
     30 #include "api/rtp_parameters.h"
     31 #include "api/transport/rtp/rtp_source.h"
     32 #include "api/video/video_frame_buffer.h"
     33 #include "call/audio_receive_stream.h"
     34 #include "call/audio_send_stream.h"
     35 #include "call/call_basic_stats.h"
     36 #include "call/video_receive_stream.h"
     37 #include "call/video_send_stream.h"
     38 #include "rtc_base/copy_on_write_buffer.h"
     39 
     40 namespace webrtc {
     41 class RtpPacketReceived;
     42 class VideoFrame;
     43 }  // namespace webrtc
     44 
     45 namespace mozilla {
     46 namespace dom {
     47 struct RTCRtpSourceEntry;
     48 }
     49 
     50 enum class MediaSessionConduitLocalDirection : int { kSend, kRecv };
     51 
     52 class VideoSessionConduit;
     53 class AudioSessionConduit;
     54 class WebrtcCallWrapper;
     55 class FrameTransformerProxy;
     56 
     57 /**
     58 * 1. Abstract renderer for video data
     59 * 2. This class acts as abstract interface between the video-engine and
     60 *    video-engine agnostic renderer implementation.
     61 * 3. Concrete implementation of this interface is responsible for
     62 *    processing and/or rendering the obtained raw video frame to appropriate
     63 *    output , say, <video>
     64 */
     65 class VideoRenderer {
     66 protected:
     67  virtual ~VideoRenderer() {}
     68 
     69 public:
     70  /**
     71   * Callback Function reporting decoded frame for processing.
     72   * @param video_frame: reference to decoded video frame
     73   * NOTE: If decoded video frame is passed through buffer , it is the
     74   * responsibility of the concrete implementations of this class to own copy
     75   * of the frame if needed for time longer than scope of this callback.
     76   * Such implementations should be quick in processing the frames and return
     77   * immediately.
     78   */
     79  virtual void RenderVideoFrame(const webrtc::VideoFrame& video_frame) = 0;
     80 
     81  NS_INLINE_DECL_THREADSAFE_REFCOUNTING(VideoRenderer)
     82 };
     83 
     84 /**
     85 * Generic Interface for representing Audio/Video Session
     86 * MediaSession conduit is identified by 2 main components
     87 * 1. Attached Transport Interface (through events) for inbound and outbound RTP
     88 *    transport
     89 * 2. Attached Renderer Interface for rendering media data off the network
     90 * This class hides specifics of Media-Engine implementation from the consumers
     91 * of this interface.
     92 * Also provides codec configuration API for the media sent and recevied
     93 */
     94 class MediaSessionConduit {
     95 protected:
     96  virtual ~MediaSessionConduit() {}
     97 
     98 public:
     99  enum Type { AUDIO, VIDEO };
    100  enum class PacketType { RTP, RTCP };
    101 
    102  static std::string LocalDirectionToString(
    103      const MediaSessionConduitLocalDirection aDirection) {
    104    return aDirection == MediaSessionConduitLocalDirection::kSend ? "send"
    105                                                                  : "receive";
    106  }
    107 
    108  virtual Type type() const = 0;
    109 
    110  // Call thread only
    111  virtual Maybe<int> ActiveSendPayloadType() const = 0;
    112  virtual Maybe<int> ActiveRecvPayloadType() const = 0;
    113 
    114  // Whether transport is currently sending and receiving packets
    115  virtual void SetTransportActive(bool aActive) = 0;
    116 
    117  // Sending packets
    118  virtual MediaEventSourceExc<MediaPacket>& SenderRtpSendEvent() = 0;
    119  virtual MediaEventSourceExc<MediaPacket>& SenderRtcpSendEvent() = 0;
    120  virtual MediaEventSourceExc<MediaPacket>& ReceiverRtcpSendEvent() = 0;
    121 
    122  // Receiving RTP packets
    123  virtual void ConnectReceiverRtpEvent(
    124      MediaEventSourceExc<webrtc::RtpPacketReceived, webrtc::RTPHeader>&
    125          aEvent) = 0;
    126 
    127  virtual void ConnectReceiverRtcpEvent(
    128      MediaEventSourceExc<webrtc::CopyOnWriteBuffer>& aEvent) = 0;
    129 
    130  virtual void ConnectSenderRtcpEvent(
    131      MediaEventSourceExc<webrtc::CopyOnWriteBuffer>& aEvent) = 0;
    132 
    133  // Sts thread only.
    134  virtual Maybe<uint16_t> RtpSendBaseSeqFor(uint32_t aSsrc) const = 0;
    135 
    136  // Any thread.
    137  virtual const dom::RTCStatsTimestampMaker& GetTimestampMaker() const = 0;
    138 
    139  virtual Ssrcs GetLocalSSRCs() const = 0;
    140 
    141  virtual Maybe<Ssrc> GetRemoteSSRC() const = 0;
    142  virtual void UnsetRemoteSSRC(Ssrc aSsrc) = 0;
    143 
    144  virtual void DisableSsrcChanges() = 0;
    145 
    146  virtual bool HasCodecPluginID(uint64_t aPluginID) const = 0;
    147 
    148  // Stuff for driving mute/unmute events
    149  virtual MediaEventSource<void>& RtcpByeEvent() = 0;
    150  virtual MediaEventSource<void>& RtcpTimeoutEvent() = 0;
    151  virtual MediaEventSource<void>& RtpPacketEvent() = 0;
    152 
    153  virtual bool SendRtp(const uint8_t* aData, size_t aLength,
    154                       const webrtc::PacketOptions& aOptions) = 0;
    155  virtual bool SendSenderRtcp(const uint8_t* aData, size_t aLength) = 0;
    156  virtual bool SendReceiverRtcp(const uint8_t* aData, size_t aLength) = 0;
    157 
    158  virtual void DeliverPacket(webrtc::CopyOnWriteBuffer packet,
    159                             PacketType type) = 0;
    160 
    161  virtual RefPtr<GenericPromise> Shutdown() = 0;
    162  // Call thread only. Is set at the end of Shutdown()
    163  virtual bool IsShutdown() const = 0;
    164 
    165  virtual Maybe<RefPtr<AudioSessionConduit>> AsAudioSessionConduit() = 0;
    166  virtual Maybe<RefPtr<VideoSessionConduit>> AsVideoSessionConduit() = 0;
    167 
    168  virtual Maybe<webrtc::CallBasicStats> GetCallStats() const = 0;
    169 
    170  NS_INLINE_DECL_THREADSAFE_REFCOUNTING(MediaSessionConduit)
    171 
    172  void GetRtpSources(nsTArray<dom::RTCRtpSourceEntry>& outSources) const;
    173 
    174  virtual void SetJitterBufferTarget(DOMHighResTimeStamp aTargetMs) = 0;
    175 
    176  // test-only: inserts fake CSRCs and audio level data.
    177  // NB: fake data is only valid during the current main thread task.
    178  void InsertAudioLevelForContributingSource(const uint32_t aCsrcSource,
    179                                             const int64_t aTimestamp,
    180                                             const uint32_t aRtpTimestamp,
    181                                             const bool aHasAudioLevel,
    182                                             const uint8_t aAudioLevel);
    183 
    184 protected:
    185  virtual const std::vector<webrtc::RtpSource>& GetUpstreamRtpSources()
    186      const = 0;
    187 
    188 private:
    189  void UpdateRtpSources(const std::vector<webrtc::RtpSource>& aSources) const;
    190 
    191  // Marks the cache as having been updated in the current task, and keeps it
    192  // stable until the current task is finished.
    193  void OnSourcesUpdated() const;
    194 
    195  // Accessed only on main thread. This exists for a couple of reasons:
    196  // 1. The webrtc spec says that source stats are updated using a queued task;
    197  //    libwebrtc's internal representation of these stats is updated without
    198  //    any task queueing, which means we need a mainthread-only cache.
    199  // 2. libwebrtc uses its own clock that is not consistent with the one we
    200  // need to use for stats (the so-called JS timestamps), which means we need
    201  // to adjust the timestamps.  Since timestamp adjustment is inexact and will
    202  // not necessarily yield exactly the same result if performed again later, we
    203  // need to avoid performing it more than once for each entry, which means we
    204  // need to remember both the JS timestamp (in dom::RTCRtpSourceEntry) and the
    205  // libwebrtc timestamp (in SourceKey::mLibwebrtcTimestampMs).
    206  class SourceKey {
    207   public:
    208    explicit SourceKey(const webrtc::RtpSource& aSource)
    209        : SourceKey(aSource.timestamp().ms(), aSource.source_id()) {}
    210 
    211    SourceKey(uint32_t aTimestamp, uint32_t aSrc)
    212        : mLibwebrtcTimestampMs(aTimestamp), mSrc(aSrc) {}
    213 
    214    // TODO: Once we support = default for this in our toolchain, do so
    215    auto operator>(const SourceKey& aRhs) const {
    216      if (mLibwebrtcTimestampMs == aRhs.mLibwebrtcTimestampMs) {
    217        return mSrc > aRhs.mSrc;
    218      }
    219      return mLibwebrtcTimestampMs > aRhs.mLibwebrtcTimestampMs;
    220    }
    221 
    222   private:
    223    uint32_t mLibwebrtcTimestampMs;
    224    uint32_t mSrc;
    225  };
    226  mutable std::map<SourceKey, dom::RTCRtpSourceEntry, std::greater<SourceKey>>
    227      mSourcesCache;
    228  // Accessed only on main thread. A flag saying whether mSourcesCache needs
    229  // updating. Ensures that get*Sources() appear stable from javascript
    230  // throughout a main thread task, even though we don't follow the spec to the
    231  // letter (dispatch a task to update the sources).
    232  mutable bool mSourcesUpdateNeeded = true;
    233 };
    234 
    235 class WebrtcSendTransport : public webrtc::Transport {
    236  // WeakRef to the owning conduit
    237  MediaSessionConduit* mConduit;
    238 
    239 public:
    240  explicit WebrtcSendTransport(MediaSessionConduit* aConduit)
    241      : mConduit(aConduit) {}
    242  bool SendRtp(webrtc::ArrayView<const uint8_t> aPacket,
    243               const webrtc::PacketOptions& aOptions) {
    244    return mConduit->SendRtp(aPacket.data(), aPacket.size(), aOptions);
    245  }
    246  bool SendRtcp(webrtc::ArrayView<const uint8_t> aPacket,
    247                const webrtc::PacketOptions& aOptions) {
    248    return mConduit->SendSenderRtcp(aPacket.data(), aPacket.size());
    249  }
    250 };
    251 
    252 class WebrtcReceiveTransport : public webrtc::Transport {
    253  // WeakRef to the owning conduit
    254  MediaSessionConduit* mConduit;
    255 
    256 public:
    257  explicit WebrtcReceiveTransport(MediaSessionConduit* aConduit)
    258      : mConduit(aConduit) {}
    259  bool SendRtp(webrtc::ArrayView<const uint8_t> aPacket,
    260               const webrtc::PacketOptions& aOptions) {
    261    MOZ_CRASH("Unexpected RTP packet");
    262  }
    263  bool SendRtcp(webrtc::ArrayView<const uint8_t> aPacket,
    264                const webrtc::PacketOptions& aOptions) {
    265    return mConduit->SendReceiverRtcp(aPacket.data(), aPacket.size());
    266  }
    267 };
    268 
    269 // Abstract base classes for external encoder/decoder.
    270 
    271 // Interface to help signal PluginIDs
    272 class CodecPluginID {
    273 public:
    274  virtual MediaEventSource<uint64_t>* InitPluginEvent() { return nullptr; }
    275  virtual MediaEventSource<uint64_t>* ReleasePluginEvent() { return nullptr; }
    276  virtual ~CodecPluginID() {}
    277 };
    278 
    279 class VideoEncoder : public CodecPluginID {
    280 public:
    281  virtual ~VideoEncoder() {}
    282 };
    283 
    284 class VideoDecoder : public CodecPluginID {
    285 public:
    286  virtual ~VideoDecoder() {}
    287 };
    288 
    289 /**
    290 * MediaSessionConduit for video
    291 * Refer to the comments on MediaSessionConduit above for overall
    292 * information
    293 */
    294 class VideoSessionConduit : public MediaSessionConduit {
    295 public:
    296  struct Options {
    297    bool mVideoLatencyTestEnable = false;
    298    // All in bps.
    299    int mMinBitrate = 0;
    300    int mStartBitrate = 0;
    301    int mPrefMaxBitrate = 0;
    302    int mMinBitrateEstimate = 0;
    303    bool mDenoising = false;
    304    bool mLockScaling = false;
    305    uint8_t mSpatialLayers = 1;
    306    uint8_t mTemporalLayers = 1;
    307  };
    308 
    309  /**
    310   * Factory function to create and initialize a Video Conduit Session
    311   * @param  webrtc::Call instance shared by paired audio and video
    312   *         media conduits
    313   * @param  aOptions are a number of options, typically from prefs, used to
    314   *         configure the created VideoConduit.
    315   * @param  aPCHandle is a string representing the RTCPeerConnection that is
    316   *         creating this VideoConduit. This is used when reporting GMP plugin
    317   *         crashes.
    318   * @result Concrete VideoSessionConduitObject or nullptr in the case
    319   *         of failure
    320   */
    321  static RefPtr<VideoSessionConduit> Create(
    322      RefPtr<WebrtcCallWrapper> aCall,
    323      nsCOMPtr<nsISerialEventTarget> aStsThread, Options aOptions,
    324      std::string aPCHandle, const TrackingId& aRecvTrackingId);
    325 
    326  enum FrameRequestType {
    327    FrameRequestNone,
    328    FrameRequestFir,
    329    FrameRequestPli,
    330    FrameRequestUnknown
    331  };
    332 
    333  VideoSessionConduit()
    334      : mFrameRequestMethod(FrameRequestNone),
    335        mUsingNackBasic(false),
    336        mUsingTmmbr(false),
    337        mUsingFEC(false) {}
    338 
    339  virtual ~VideoSessionConduit() {}
    340 
    341  Type type() const override { return VIDEO; }
    342 
    343  Maybe<RefPtr<AudioSessionConduit>> AsAudioSessionConduit() override {
    344    return Nothing();
    345  }
    346 
    347  Maybe<RefPtr<VideoSessionConduit>> AsVideoSessionConduit() override {
    348    return Some(RefPtr<VideoSessionConduit>(this));
    349  }
    350 
    351  /**
    352   * Hooks up mControl Mirrors with aControl Canonicals, and sets up
    353   * mWatchManager to react on Mirror changes.
    354   */
    355  virtual void InitControl(VideoConduitControlInterface* aControl) = 0;
    356 
    357  /**
    358   * Function to attach Renderer end-point of the Media-Video conduit.
    359   * @param aRenderer : Reference to the concrete Video renderer implementation
    360   * Note: Multiple invocations of this API shall remove an existing renderer
    361   * and attaches the new to the Conduit.
    362   */
    363  virtual MediaConduitErrorCode AttachRenderer(
    364      RefPtr<mozilla::VideoRenderer> aRenderer) = 0;
    365  virtual void DetachRenderer() = 0;
    366 
    367  virtual void SetTrackSource(webrtc::VideoTrackSourceInterface* aSource) = 0;
    368 
    369  /**
    370   * These methods allow unit tests to double-check that the
    371   * rtcp-fb settings are as expected.
    372   */
    373  FrameRequestType FrameRequestMethod() const { return mFrameRequestMethod; }
    374 
    375  bool UsingNackBasic() const { return mUsingNackBasic; }
    376 
    377  bool UsingTmmbr() const { return mUsingTmmbr; }
    378 
    379  bool UsingFEC() const { return mUsingFEC; }
    380 
    381  virtual bool LockScaling() const = 0;
    382 
    383  virtual Maybe<webrtc::VideoReceiveStreamInterface::Stats> GetReceiverStats()
    384      const = 0;
    385  virtual Maybe<webrtc::VideoSendStream::Stats> GetSenderStats() const = 0;
    386 
    387  virtual void CollectTelemetryData() = 0;
    388 
    389  virtual bool AddFrameHistory(
    390      dom::Sequence<dom::RTCVideoFrameHistoryInternal>* outHistories) const = 0;
    391 
    392  virtual Maybe<Ssrc> GetAssociatedLocalRtxSSRC(Ssrc aSsrc) const = 0;
    393 
    394  virtual Maybe<gfx::IntSize> GetLastResolution() const = 0;
    395  virtual AbstractCanonical<Maybe<gfx::IntSize>>* CanonicalReceivingSize() = 0;
    396 
    397  virtual void RequestKeyFrame(FrameTransformerProxy* aProxy) = 0;
    398  virtual void GenerateKeyFrame(const Maybe<std::string>& aRid,
    399                                FrameTransformerProxy* aProxy) = 0;
    400 
    401 protected:
    402  /* RTCP feedback settings, for unit testing purposes */
    403  FrameRequestType mFrameRequestMethod;
    404  bool mUsingNackBasic;
    405  bool mUsingTmmbr;
    406  bool mUsingFEC;
    407 };
    408 
    409 /**
    410 * MediaSessionConduit for audio
    411 * Refer to the comments on MediaSessionConduit above for overall
    412 * information
    413 */
    414 class AudioSessionConduit : public MediaSessionConduit {
    415 public:
    416  /**
    417   * Factory function to create and initialize an Audio Conduit Session
    418   * @param  webrtc::Call instance shared by paired audio and video
    419   *         media conduits
    420   * @result Concrete AudioSessionConduitObject or nullptr in the case
    421   *         of failure
    422   */
    423  static RefPtr<AudioSessionConduit> Create(
    424      RefPtr<WebrtcCallWrapper> aCall,
    425      nsCOMPtr<nsISerialEventTarget> aStsThread);
    426 
    427  virtual ~AudioSessionConduit() {}
    428 
    429  Type type() const override { return AUDIO; }
    430 
    431  Maybe<RefPtr<AudioSessionConduit>> AsAudioSessionConduit() override {
    432    return Some(this);
    433  }
    434 
    435  Maybe<RefPtr<VideoSessionConduit>> AsVideoSessionConduit() override {
    436    return Nothing();
    437  }
    438 
    439  /**
    440   * Hooks up mControl Mirrors with aControl Canonicals, and sets up
    441   * mWatchManager to react on Mirror changes.
    442   */
    443  virtual void InitControl(AudioConduitControlInterface* aControl) = 0;
    444 
    445  /**
    446   * Function to deliver externally captured audio sample for encoding and
    447   * transport
    448   * @param frame [in]: AudioFrame in upstream's format for forwarding to the
    449   *                    send stream. Ownership is passed along.
    450   * NOTE: ConfigureSendMediaCodec() SHOULD be called before this function can
    451   * be invoked. This ensures the inserted audio-samples can be transmitted by
    452   * the conduit.
    453   */
    454  virtual MediaConduitErrorCode SendAudioFrame(
    455      std::unique_ptr<webrtc::AudioFrame> frame) = 0;
    456 
    457  /**
    458   * Function to grab a decoded audio-sample from the media engine for
    459   * rendering / playout of length 10 milliseconds.
    460   *
    461   * @param samplingFreqHz [in]: Frequency of the sampling for playback in
    462   *                             Hertz (16000, 32000,..)
    463   * @param frame [in/out]: Pointer to an AudioFrame to which audio data will be
    464   *                        copied
    465   * NOTE: This function should be invoked every 10 milliseconds for the best
    466   *       performance
    467   * NOTE: ConfigureRecvMediaCodec() SHOULD be called before this function can
    468   *       be invoked
    469   * This ensures the decoded samples are ready for reading and playout is
    470   * enabled.
    471   */
    472  virtual MediaConduitErrorCode GetAudioFrame(int32_t samplingFreqHz,
    473                                              webrtc::AudioFrame* frame) = 0;
    474 
    475  /**
    476   * Checks if given sampling frequency is supported
    477   * @param freq: Sampling rate (in Hz) to check
    478   */
    479  virtual bool IsSamplingFreqSupported(int freq) const = 0;
    480 
    481  virtual Maybe<webrtc::AudioReceiveStreamInterface::Stats> GetReceiverStats()
    482      const = 0;
    483  virtual Maybe<webrtc::AudioSendStream::Stats> GetSenderStats() const = 0;
    484 };
    485 }  // namespace mozilla
    486 #endif