Bug 1839170 - Refactor Snap pulling, Add Firefox Snap Core22 and GNOME 42 SDK symbols...
[gecko.git] / dom / media / AudioCaptureTrack.cpp
blobf30581ee692523deeee61ab8df390a76b9ca4910
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 "MediaTrackGraphImpl.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"
20 #include <algorithm>
21 #include "DOMMediaStream.h"
23 using namespace mozilla::layers;
24 using namespace mozilla::dom;
25 using namespace mozilla::gfx;
27 namespace mozilla {
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()),
34 mStarted(false) {
35 MOZ_ASSERT(NS_IsMainThread());
36 MOZ_COUNT_CTOR(AudioCaptureTrack);
37 mMixer.AddCallback(WrapNotNull(this));
40 AudioCaptureTrack::~AudioCaptureTrack() {
41 MOZ_COUNT_DTOR(AudioCaptureTrack);
42 mMixer.RemoveCallback(this);
45 void AudioCaptureTrack::Start() {
46 class Message : public ControlMessage {
47 public:
48 explicit Message(AudioCaptureTrack* aTrack)
49 : ControlMessage(aTrack), mTrack(aTrack) {}
51 virtual void Run() { mTrack->mStarted = true; }
53 protected:
54 AudioCaptureTrack* mTrack;
56 GraphImpl()->AppendMessage(MakeUnique<Message>(this));
59 void AudioCaptureTrack::ProcessInput(GraphTime aFrom, GraphTime aTo,
60 uint32_t aFlags) {
61 if (!mStarted) {
62 return;
65 uint32_t inputCount = mInputs.Length();
67 if (mEnded) {
68 return;
71 // If the captured track is connected back to a object on the page (be it an
72 // HTMLMediaElement with a track as source, or an AudioContext), a cycle
73 // situation occur. This can work if it's an AudioContext with at least one
74 // DelayNode, but the MTG will mute the whole cycle otherwise.
75 if (InMutedCycle() || inputCount == 0) {
76 GetData<AudioSegment>()->AppendNullData(aTo - aFrom);
77 } else {
78 // We mix down all the tracks of all inputs, to a stereo track. Everything
79 // is {up,down}-mixed to stereo.
80 mMixer.StartMixing();
81 AudioSegment output;
82 for (uint32_t i = 0; i < inputCount; i++) {
83 MediaTrack* s = mInputs[i]->GetSource();
84 AudioSegment* inputSegment = s->GetData<AudioSegment>();
85 TrackTime inputStart = s->GraphTimeToTrackTimeWithBlocking(aFrom);
86 TrackTime inputEnd = s->GraphTimeToTrackTimeWithBlocking(aTo);
87 AudioSegment toMix;
88 if (s->Ended() && inputSegment->GetDuration() <= inputStart) {
89 toMix.AppendNullData(aTo - aFrom);
90 } else {
91 toMix.AppendSlice(*inputSegment, inputStart, inputEnd);
92 // Care for tracks blocked in the [aTo, aFrom] range.
93 if (inputEnd - inputStart < aTo - aFrom) {
94 toMix.AppendNullData((aTo - aFrom) - (inputEnd - inputStart));
97 toMix.Mix(mMixer, MONO, Graph()->GraphRate());
99 // This calls MixerCallback below
100 mMixer.FinishMixing();
104 uint32_t AudioCaptureTrack::NumberOfChannels() const {
105 return GetData<AudioSegment>()->MaxChannelCount();
108 void AudioCaptureTrack::MixerCallback(AudioDataValue* aMixedBuffer,
109 AudioSampleFormat aFormat,
110 uint32_t aChannels, uint32_t aFrames,
111 uint32_t aSampleRate) {
112 AutoTArray<nsTArray<AudioDataValue>, MONO> output;
113 AutoTArray<const AudioDataValue*, MONO> bufferPtrs;
114 output.SetLength(MONO);
115 bufferPtrs.SetLength(MONO);
117 uint32_t written = 0;
118 // We need to copy here, because the mixer will reuse the storage, we should
119 // not hold onto it. Buffers are in planar format.
120 for (uint32_t channel = 0; channel < aChannels; channel++) {
121 AudioDataValue* out = output[channel].AppendElements(aFrames);
122 PodCopy(out, aMixedBuffer + written, aFrames);
123 bufferPtrs[channel] = out;
124 written += aFrames;
126 AudioChunk chunk;
127 chunk.mBuffer =
128 new mozilla::SharedChannelArrayBuffer<AudioDataValue>(std::move(output));
129 chunk.mDuration = aFrames;
130 chunk.mBufferFormat = aFormat;
131 chunk.mChannelData.SetLength(MONO);
132 for (uint32_t channel = 0; channel < aChannels; channel++) {
133 chunk.mChannelData[channel] = bufferPtrs[channel];
136 // Now we have mixed data, simply append it.
137 GetData<AudioSegment>()->AppendAndConsumeChunk(std::move(chunk));
139 } // namespace mozilla