tor-browser

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

RTCRtpScriptTransformer.h (7523B)


      1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
      2 /* vim: set ts=2 et sw=2 tw=80: */
      3 /* This Source Code Form is subject to the terms of the Mozilla Public
      4 * License, v. 2.0. If a copy of the MPL was not distributed with this
      5 * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
      6 
      7 #ifndef MOZILLA_DOM_MEDIA_WEBRTC_JSAPI_RTCRTPSCRIPTTRANSFORMER_H_
      8 #define MOZILLA_DOM_MEDIA_WEBRTC_JSAPI_RTCRTPSCRIPTTRANSFORMER_H_
      9 
     10 #include <memory>
     11 
     12 #include "js/RootingAPI.h"
     13 #include "mozilla/Maybe.h"
     14 #include "mozilla/RefPtr.h"
     15 #include "mozilla/dom/ReadableStream.h"
     16 #include "mozilla/dom/WritableStream.h"
     17 #include "nsCOMArray.h"
     18 #include "nsCycleCollectionParticipant.h"
     19 #include "nsISupports.h"
     20 #include "nsTArray.h"
     21 #include "nsTHashSet.h"
     22 #include "nsWrapperCache.h"
     23 
     24 class nsPIDOMWindowInner;
     25 
     26 namespace webrtc {
     27 class TransformableFrameInterface;
     28 }
     29 
     30 namespace mozilla {
     31 class FrameTransformerProxy;
     32 
     33 namespace dom {
     34 class Worker;
     35 class WorkerPrivate;
     36 
     37 // Dirt simple source for ReadableStream that accepts nsISupports
     38 // Might be suitable to move someplace else, with some polish.
     39 class nsISupportsStreamSource final : public UnderlyingSourceAlgorithmsWrapper {
     40 public:
     41  nsISupportsStreamSource();
     42  nsISupportsStreamSource(const nsISupportsStreamSource&) = delete;
     43  nsISupportsStreamSource(nsISupportsStreamSource&&) = delete;
     44  nsISupportsStreamSource& operator=(const nsISupportsStreamSource&) = delete;
     45  nsISupportsStreamSource& operator=(nsISupportsStreamSource&&) = delete;
     46 
     47  NS_DECL_ISUPPORTS_INHERITED
     48  NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(nsISupportsStreamSource,
     49                                           UnderlyingSourceAlgorithmsWrapper)
     50 
     51  void Init(ReadableStream* aStream);
     52 
     53  void Enqueue(nsISupports* aThing);
     54 
     55  // From UnderlyingSourceAlgorithmsWrapper
     56  already_AddRefed<Promise> PullCallbackImpl(
     57      JSContext* aCx, ReadableStreamControllerBase& aController,
     58      ErrorResult& aRv) override;
     59 
     60  void EnqueueOneThingFromQueue(JSContext* aCx);
     61 
     62 private:
     63  virtual ~nsISupportsStreamSource();
     64 
     65  // Calls ReadableStream::EnqueueNative, which is MOZ_CAN_RUN_SCRIPT.
     66  MOZ_CAN_RUN_SCRIPT_BOUNDARY void EnqueueToStream(JSContext* aCx,
     67                                                   nsISupports* aThing);
     68 
     69  RefPtr<ReadableStream> mStream;
     70  RefPtr<Promise> mThingQueuedPromise;
     71  // mozilla::Queue is not cycle-collector friendly :(
     72  nsCOMArray<nsISupports> mQueue;
     73 };
     74 
     75 class RTCRtpScriptTransformer;
     76 
     77 class WritableStreamRTCFrameSink final
     78    : public UnderlyingSinkAlgorithmsWrapper {
     79 public:
     80  explicit WritableStreamRTCFrameSink(RTCRtpScriptTransformer* aTransformer);
     81  WritableStreamRTCFrameSink(const WritableStreamRTCFrameSink&) = delete;
     82  WritableStreamRTCFrameSink(WritableStreamRTCFrameSink&&) = delete;
     83  WritableStreamRTCFrameSink& operator=(const WritableStreamRTCFrameSink&) =
     84      delete;
     85  WritableStreamRTCFrameSink& operator=(WritableStreamRTCFrameSink&&) = delete;
     86 
     87  NS_DECL_ISUPPORTS_INHERITED
     88  NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(WritableStreamRTCFrameSink,
     89                                           UnderlyingSinkAlgorithmsWrapper)
     90 
     91  already_AddRefed<Promise> WriteCallbackImpl(
     92      JSContext* aCx, JS::Handle<JS::Value> aChunk,
     93      WritableStreamDefaultController& aController,
     94      ErrorResult& aError) override;
     95 
     96 private:
     97  virtual ~WritableStreamRTCFrameSink();
     98  RefPtr<RTCRtpScriptTransformer> mTransformer;
     99 };
    100 
    101 class RTCEncodedFrameBase;
    102 
    103 // Here's the basic flow. All of this happens on the worker thread.
    104 // 0. We register with a FrameTransformerProxy.
    105 // 1. That FrameTransformerProxy dispatches webrtc::TransformableFrameInterface
    106 //    to us (from either the encoder/depacketizer thread), via our
    107 //    TransformFrame method.
    108 // 2. We wrap these frames in RTCEncodedAudio/VideoFrame, and feed them to
    109 //    mReadableSource, which queues them.
    110 // 3. mReadableSource.PullCallbackImpl consumes that queue, and feeds the
    111 //    frames to mReadable.
    112 // 4. JS worker code consumes from mReadable, does whatever transformation it
    113 //    wants, then writes the frames to mWritable.
    114 // 5. mWritableSink.WriteCallback passes those frames to us.
    115 // 6. We unwrap the webrtc::TransformableFrameInterface from these frames.
    116 // 7. We pass these unwrapped frames back to the FrameTransformerProxy.
    117 //    (FrameTransformerProxy handles any dispatching/synchronization necessary)
    118 // 8. Eventually, that FrameTransformerProxy calls NotifyReleased (possibly at
    119 //    our prompting).
    120 class RTCRtpScriptTransformer final : public nsISupports,
    121                                      public nsWrapperCache {
    122 public:
    123  explicit RTCRtpScriptTransformer(nsIGlobalObject* aGlobal);
    124 
    125  MOZ_CAN_RUN_SCRIPT_BOUNDARY nsresult Init(JSContext* aCx,
    126                                            JS::Handle<JS::Value> aOptions,
    127                                            WorkerPrivate* aWorkerPrivate,
    128                                            FrameTransformerProxy* aProxy);
    129 
    130  void NotifyReleased();
    131 
    132  void TransformFrame(
    133      std::unique_ptr<webrtc::TransformableFrameInterface> aFrame);
    134  already_AddRefed<Promise> OnTransformedFrame(RTCEncodedFrameBase* aFrame,
    135                                               ErrorResult& aError);
    136 
    137  // nsISupports
    138  NS_DECL_CYCLE_COLLECTING_ISUPPORTS
    139  NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(RTCRtpScriptTransformer)
    140 
    141  JSObject* WrapObject(JSContext* aCx,
    142                       JS::Handle<JSObject*> aGivenProto) override;
    143 
    144  nsIGlobalObject* GetParentObject() const { return mGlobal; }
    145 
    146  // WebIDL Interface
    147  already_AddRefed<mozilla::dom::ReadableStream> Readable() const {
    148    return do_AddRef(mReadable);
    149  }
    150  already_AddRefed<mozilla::dom::WritableStream> Writable() const {
    151    return do_AddRef(mWritable);
    152  }
    153 
    154  void GetOptions(JSContext* aCx, JS::MutableHandle<JS::Value> aVal,
    155                  ErrorResult& aError);
    156 
    157  already_AddRefed<Promise> GenerateKeyFrame(const Optional<nsAString>& aRid);
    158  void GenerateKeyFrameError(const Maybe<std::string>& aRid,
    159                             const CopyableErrorResult& aResult);
    160  already_AddRefed<Promise> SendKeyFrameRequest();
    161  void KeyFrameRequestDone();
    162 
    163  // Public to ease implementation of cycle collection functions
    164  using GenerateKeyFramePromises =
    165      nsTHashMap<nsCStringHashKey, nsTArray<RefPtr<Promise>>>;
    166 
    167 private:
    168  virtual ~RTCRtpScriptTransformer();
    169  void RejectPendingPromises();
    170  // empty string means no rid
    171  void ResolveGenerateKeyFramePromises(const std::string& aRid,
    172                                       uint64_t aTimestamp);
    173 
    174  nsCOMPtr<nsIGlobalObject> mGlobal;
    175 
    176  RefPtr<FrameTransformerProxy> mProxy;
    177  RefPtr<nsISupportsStreamSource> mReadableSource;
    178  RefPtr<ReadableStream> mReadable;
    179  RefPtr<WritableStream> mWritable;
    180  RefPtr<WritableStreamRTCFrameSink> mWritableSink;
    181 
    182  JS::Heap<JS::Value> mOptions;
    183  uint64_t mLastEnqueuedFrameCounter = 0;
    184  uint64_t mLastReceivedFrameCounter = 0;
    185  nsTArray<RefPtr<Promise>> mKeyFrameRequestPromises;
    186  // Contains the promise returned for each call to GenerateKeyFrame(rid), in
    187  // the order in which it was called, keyed by the rid (empty string if not
    188  // passed). If there is already a promise in here for a given rid, we do not
    189  // ask the FrameTransformerProxy again, and just bulk resolve/reject.
    190  GenerateKeyFramePromises mGenerateKeyFramePromises;
    191  Maybe<bool> mVideo;
    192  RefPtr<StrongWorkerRef> mWorkerRef;
    193 };
    194 
    195 }  // namespace dom
    196 }  // namespace mozilla
    197 
    198 #endif  // MOZILLA_DOM_MEDIA_WEBRTC_JSAPI_RTCRTPSCRIPTTRANSFORMER_H_