Backed out changeset 06f41c22f3a6 (bug 1888460) for causing linux xpcshell failures...
[gecko.git] / dom / media / AudioCaptureTrack.cpp
blob0a7aaccb5c4f042ea0c1ff16e39f52ccabbae00c
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"
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);
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,
47 uint32_t aFlags) {
48 if (!mStarted) {
49 return;
52 uint32_t inputCount = mInputs.Length();
54 if (mEnded) {
55 return;
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);
64 } else {
65 // We mix down all the tracks of all inputs, to a stereo track. Everything
66 // is {up,down}-mixed to stereo.
67 mMixer.StartMixing();
68 AudioSegment output;
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);
74 AudioSegment toMix;
75 if (s->Ended() && inputSegment->GetDuration() <= inputStart) {
76 toMix.AppendNullData(aTo - aFrom);
77 } else {
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