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