no bug - Bumping Firefox l10n changesets r=release a=l10n-bump DONTBUILD CLOSED TREE
[gecko.git] / dom / media / CrossGraphPort.cpp
blob25d3a2b505bb2eefdb8733bb7c95c53c76363265
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/. */
5 #include "CrossGraphPort.h"
7 #include "AudioDeviceInfo.h"
8 #include "AudioStreamTrack.h"
9 #include "MediaTrackGraph.h"
10 #include "mozilla/Logging.h"
11 #include "mozilla/Preferences.h"
13 namespace mozilla {
15 #ifdef LOG
16 # undef LOG
17 #endif
18 #ifdef LOG_TEST
19 # undef LOG_TEST
20 #endif
22 extern LazyLogModule gMediaTrackGraphLog;
23 #define LOG(type, msg) MOZ_LOG(gMediaTrackGraphLog, type, msg)
24 #define LOG_TEST(type) MOZ_LOG_TEST(gMediaTrackGraphLog, type)
26 UniquePtr<CrossGraphPort> CrossGraphPort::Connect(
27 const RefPtr<dom::AudioStreamTrack>& aStreamTrack,
28 MediaTrackGraph* aPartnerGraph) {
29 MOZ_ASSERT(aStreamTrack);
30 MOZ_ASSERT(aPartnerGraph);
31 if (aStreamTrack->Graph() == aPartnerGraph) {
32 // Primary graph the same as partner graph, just remove the existing cross
33 // graph connection
34 return nullptr;
37 RefPtr<CrossGraphReceiver> receiver = aPartnerGraph->CreateCrossGraphReceiver(
38 aStreamTrack->Graph()->GraphRate());
40 RefPtr<CrossGraphTransmitter> transmitter =
41 aStreamTrack->Graph()->CreateCrossGraphTransmitter(receiver);
43 RefPtr<MediaInputPort> port =
44 aStreamTrack->ForwardTrackContentsTo(transmitter);
46 return WrapUnique(new CrossGraphPort(std::move(port), std::move(transmitter),
47 std::move(receiver)));
50 CrossGraphPort::~CrossGraphPort() {
51 mTransmitter->Destroy();
52 mReceiver->Destroy();
53 mTransmitterPort->Destroy();
56 /** CrossGraphTransmitter **/
58 CrossGraphTransmitter::CrossGraphTransmitter(
59 TrackRate aSampleRate, RefPtr<CrossGraphReceiver> aReceiver)
60 : ProcessedMediaTrack(aSampleRate, MediaSegment::AUDIO,
61 nullptr /* aSegment */),
62 mReceiver(std::move(aReceiver)) {}
64 void CrossGraphTransmitter::ProcessInput(GraphTime aFrom, GraphTime aTo,
65 uint32_t aFlags) {
66 MOZ_ASSERT(!mInputs.IsEmpty());
67 MOZ_ASSERT(mDisabledMode == DisabledTrackMode::ENABLED);
69 MediaTrack* input = mInputs[0]->GetSource();
71 if (input->Ended() &&
72 (input->GetEnd() <= input->GraphTimeToTrackTimeWithBlocking(aFrom))) {
73 mEnded = true;
74 return;
77 LOG(LogLevel::Verbose,
78 ("Transmitter (%p) from %" PRId64 ", to %" PRId64 ", ticks %" PRId64 "",
79 this, aFrom, aTo, aTo - aFrom));
81 AudioSegment audio;
82 GraphTime next;
83 for (GraphTime t = aFrom; t < aTo; t = next) {
84 MediaInputPort::InputInterval interval =
85 MediaInputPort::GetNextInputInterval(mInputs[0], t);
86 interval.mEnd = std::min(interval.mEnd, aTo);
88 TrackTime ticks = interval.mEnd - interval.mStart;
89 next = interval.mEnd;
91 if (interval.mStart >= interval.mEnd) {
92 break;
95 if (interval.mInputIsBlocked) {
96 audio.AppendNullData(ticks);
97 } else if (input->IsSuspended()) {
98 audio.AppendNullData(ticks);
99 } else {
100 MOZ_ASSERT(GetEnd() == GraphTimeToTrackTimeWithBlocking(interval.mStart),
101 "Samples missing");
102 TrackTime inputStart =
103 input->GraphTimeToTrackTimeWithBlocking(interval.mStart);
104 TrackTime inputEnd =
105 input->GraphTimeToTrackTimeWithBlocking(interval.mEnd);
106 audio.AppendSlice(*input->GetData(), inputStart, inputEnd);
110 mStartTime = aTo;
112 for (AudioSegment::ChunkIterator iter(audio); !iter.IsEnded(); iter.Next()) {
113 Unused << mReceiver->EnqueueAudio(*iter);
117 /** CrossGraphReceiver **/
119 CrossGraphReceiver::CrossGraphReceiver(TrackRate aSampleRate,
120 TrackRate aTransmitterRate)
121 : ProcessedMediaTrack(aSampleRate, MediaSegment::AUDIO,
122 static_cast<MediaSegment*>(new AudioSegment())),
123 mDriftCorrection(aTransmitterRate, aSampleRate, PRINCIPAL_HANDLE_NONE) {}
125 uint32_t CrossGraphReceiver::NumberOfChannels() const {
126 return GetData<AudioSegment>()->MaxChannelCount();
129 void CrossGraphReceiver::ProcessInput(GraphTime aFrom, GraphTime aTo,
130 uint32_t aFlags) {
131 LOG(LogLevel::Verbose,
132 ("Receiver (%p) mSegment: duration: %" PRId64 ", from %" PRId64
133 ", to %" PRId64 ", ticks %" PRId64 "",
134 this, mSegment->GetDuration(), aFrom, aTo, aTo - aFrom));
136 AudioSegment transmittedAudio;
137 while (mCrossThreadFIFO.AvailableRead()) {
138 AudioChunk chunk;
139 Unused << mCrossThreadFIFO.Dequeue(&chunk, 1);
140 transmittedAudio.AppendAndConsumeChunk(std::move(chunk));
141 mTransmitterHasStarted = true;
144 if (mTransmitterHasStarted) {
145 // If it does not have enough frames the result will be silence.
146 AudioSegment audioCorrected =
147 mDriftCorrection.RequestFrames(transmittedAudio, aTo - aFrom);
148 if (LOG_TEST(LogLevel::Verbose) && audioCorrected.IsNull()) {
149 LOG(LogLevel::Verbose,
150 ("Receiver(%p): Silence has been added, not enough input", this));
152 mSegment->AppendFrom(&audioCorrected);
153 } else {
154 mSegment->AppendNullData(aTo - aFrom);
158 int CrossGraphReceiver::EnqueueAudio(AudioChunk& aChunk) {
159 // This will take place on transmitter graph thread only.
160 return mCrossThreadFIFO.Enqueue(aChunk);
163 } // namespace mozilla