1 /* -*- Mode: C++; tab-width: 2; 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 #ifndef MOZILLA_CROSS_GRAPH_TRACK_H_
7 #define MOZILLA_CROSS_GRAPH_TRACK_H_
8 
9 #include "AudioDriftCorrection.h"
10 #include "AudioSegment.h"
11 #include "ForwardedInputTrack.h"
12 #include "mozilla/SPSCQueue.h"
13 #include "mozilla/UniquePtr.h"
14 
15 namespace mozilla {
16 class CrossGraphReceiver;
17 }
18 
19 namespace mozilla::dom {
20 class AudioStreamTrack;
21 }
22 
23 namespace mozilla {
24 
25 /**
26  * See MediaTrackGraph::CreateCrossGraphTransmitter()
27  */
28 class CrossGraphTransmitter : public ProcessedMediaTrack {
29  public:
30   CrossGraphTransmitter(TrackRate aSampleRate,
31                         RefPtr<CrossGraphReceiver> aReceiver);
AsCrossGraphTransmitter()32   CrossGraphTransmitter* AsCrossGraphTransmitter() override { return this; }
33 
NumberOfChannels()34   uint32_t NumberOfChannels() const override {
35     MOZ_CRASH("CrossGraphTransmitter has no segment. It cannot be played out.");
36   }
37   void ProcessInput(GraphTime aFrom, GraphTime aTo, uint32_t aFlags) override;
38 
39  private:
40   const RefPtr<CrossGraphReceiver> mReceiver;
41 };
42 
43 /**
44  * See MediaTrackGraph::CreateCrossGraphReceiver()
45  */
46 class CrossGraphReceiver : public ProcessedMediaTrack {
47  public:
48   CrossGraphReceiver(TrackRate aSampleRate, TrackRate aTransmitterRate);
AsCrossGraphReceiver()49   CrossGraphReceiver* AsCrossGraphReceiver() override { return this; }
50 
51   uint32_t NumberOfChannels() const override;
52   void ProcessInput(GraphTime aFrom, GraphTime aTo, uint32_t aFlags) override;
53 
54   int EnqueueAudio(AudioChunk& aChunk);
55 
56  private:
57   SPSCQueue<AudioChunk> mCrossThreadFIFO{30};
58   // Indicates that tre CrossGraphTransmitter has started sending frames. It
59   // is false untill the point, transmitter has sent the first valid frame.
60   // Accessed in GraphThread only.
61   bool mTransmitterHasStarted = false;
62   // Correct the drift between transmitter and receiver. Reciever (this class)
63   // is considered as the master clock.
64   // Accessed in GraphThread only.
65   AudioDriftCorrection mDriftCorrection;
66 };
67 
68 class CrossGraphPort final {
69  public:
70   static UniquePtr<CrossGraphPort> Connect(
71       const RefPtr<dom::AudioStreamTrack>& aStreamTrack,
72       MediaTrackGraph* aPartnerGraph);
73   static UniquePtr<CrossGraphPort> Connect(
74       const RefPtr<dom::AudioStreamTrack>& aStreamTrack, AudioDeviceInfo* aSink,
75       nsPIDOMWindowInner* aWindow);
76   ~CrossGraphPort() = default;
77 
78   void AddAudioOutput(void* aKey);
79   void RemoveAudioOutput(void* aKey);
80   void SetAudioOutputVolume(void* aKey, float aVolume);
81   void Destroy();
82 
83   RefPtr<GenericPromise> EnsureConnected();
84 
85   const RefPtr<CrossGraphTransmitter> mTransmitter;
86   const RefPtr<CrossGraphReceiver> mReceiver;
87 
88  private:
CrossGraphPort(RefPtr<MediaInputPort> aTransmitterPort,RefPtr<CrossGraphTransmitter> aTransmitter,RefPtr<CrossGraphReceiver> aReceiver)89   explicit CrossGraphPort(RefPtr<MediaInputPort> aTransmitterPort,
90                           RefPtr<CrossGraphTransmitter> aTransmitter,
91                           RefPtr<CrossGraphReceiver> aReceiver)
92       : mTransmitter(std::move(aTransmitter)),
93         mReceiver(std::move(aReceiver)),
94         mTransmitterPort(std::move(aTransmitterPort)) {
95     MOZ_ASSERT(mTransmitter);
96     MOZ_ASSERT(mReceiver);
97     MOZ_ASSERT(mTransmitterPort);
98   }
99 
100   // The port that connects the input track to the transmitter.
101   const RefPtr<MediaInputPort> mTransmitterPort;
102 };
103 
104 }  // namespace mozilla
105 
106 #endif /* MOZILLA_CROSS_GRAPH_TRACK_H_ */
107