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/. */
6 #include "MediaTrackGraph.h"
7 #include "MediaTrackListener.h"
8 #include "mozilla/MathAlgorithms.h"
9 #include "mozilla/Unused.h"
11 #include "AudioSegment.h"
12 #include "mozilla/Logging.h"
13 #include "mozilla/Attributes.h"
14 #include "AudioCaptureTrack.h"
15 #include "ImageContainer.h"
16 #include "AudioNodeEngine.h"
17 #include "AudioNodeTrack.h"
18 #include "AudioNodeExternalInputTrack.h"
19 #include "webaudio/MediaStreamAudioDestinationNode.h"
21 #include "DOMMediaStream.h"
23 using namespace mozilla::layers
;
24 using namespace mozilla::dom
;
25 using namespace mozilla::gfx
;
29 // We are mixing to mono until PeerConnection can accept stereo
30 static const uint32_t MONO
= 1;
32 AudioCaptureTrack::AudioCaptureTrack(TrackRate aRate
)
33 : ProcessedMediaTrack(aRate
, MediaSegment::AUDIO
, new AudioSegment()),
35 MOZ_ASSERT(NS_IsMainThread());
36 MOZ_COUNT_CTOR(AudioCaptureTrack
);
39 AudioCaptureTrack::~AudioCaptureTrack() { MOZ_COUNT_DTOR(AudioCaptureTrack
); }
41 void AudioCaptureTrack::Start() {
42 QueueControlMessageWithNoShutdown(
43 [self
= RefPtr
{this}, this] { mStarted
= true; });
46 void AudioCaptureTrack::ProcessInput(GraphTime aFrom
, GraphTime aTo
,
52 uint32_t inputCount
= mInputs
.Length();
58 // If the captured track is connected back to a object on the page (be it an
59 // HTMLMediaElement with a track as source, or an AudioContext), a cycle
60 // situation occur. This can work if it's an AudioContext with at least one
61 // DelayNode, but the MTG will mute the whole cycle otherwise.
62 if (InMutedCycle() || inputCount
== 0) {
63 GetData
<AudioSegment
>()->AppendNullData(aTo
- aFrom
);
65 // We mix down all the tracks of all inputs, to a stereo track. Everything
66 // is {up,down}-mixed to stereo.
69 for (uint32_t i
= 0; i
< inputCount
; i
++) {
70 MediaTrack
* s
= mInputs
[i
]->GetSource();
71 AudioSegment
* inputSegment
= s
->GetData
<AudioSegment
>();
72 TrackTime inputStart
= s
->GraphTimeToTrackTimeWithBlocking(aFrom
);
73 TrackTime inputEnd
= s
->GraphTimeToTrackTimeWithBlocking(aTo
);
75 if (s
->Ended() && inputSegment
->GetDuration() <= inputStart
) {
76 toMix
.AppendNullData(aTo
- aFrom
);
78 toMix
.AppendSlice(*inputSegment
, inputStart
, inputEnd
);
79 // Care for tracks blocked in the [aTo, aFrom] range.
80 if (inputEnd
- inputStart
< aTo
- aFrom
) {
81 toMix
.AppendNullData((aTo
- aFrom
) - (inputEnd
- inputStart
));
84 toMix
.Mix(mMixer
, MONO
, Graph()->GraphRate());
86 AudioChunk
* mixed
= mMixer
.MixedChunk();
87 MOZ_ASSERT(mixed
->ChannelCount() == MONO
);
88 // Now we have mixed data, simply append it.
89 GetData
<AudioSegment
>()->AppendAndConsumeChunk(std::move(*mixed
));
93 uint32_t AudioCaptureTrack::NumberOfChannels() const {
94 return GetData
<AudioSegment
>()->MaxChannelCount();
97 } // namespace mozilla