diff options
author | Lorry Tar Creator <lorry-tar-importer@lorry> | 2017-06-27 06:07:23 +0000 |
---|---|---|
committer | Lorry Tar Creator <lorry-tar-importer@lorry> | 2017-06-27 06:07:23 +0000 |
commit | 1bf1084f2b10c3b47fd1a588d85d21ed0eb41d0c (patch) | |
tree | 46dcd36c86e7fbc6e5df36deb463b33e9967a6f7 /Source/WebCore/Modules/webaudio/MediaStreamAudioSourceNode.cpp | |
parent | 32761a6cee1d0dee366b885b7b9c777e67885688 (diff) | |
download | WebKitGtk-tarball-master.tar.gz |
webkitgtk-2.16.5HEADwebkitgtk-2.16.5master
Diffstat (limited to 'Source/WebCore/Modules/webaudio/MediaStreamAudioSourceNode.cpp')
-rw-r--r-- | Source/WebCore/Modules/webaudio/MediaStreamAudioSourceNode.cpp | 95 |
1 files changed, 56 insertions, 39 deletions
diff --git a/Source/WebCore/Modules/webaudio/MediaStreamAudioSourceNode.cpp b/Source/WebCore/Modules/webaudio/MediaStreamAudioSourceNode.cpp index 867212e51..f640a6826 100644 --- a/Source/WebCore/Modules/webaudio/MediaStreamAudioSourceNode.cpp +++ b/Source/WebCore/Modules/webaudio/MediaStreamAudioSourceNode.cpp @@ -35,18 +35,21 @@ namespace WebCore { -PassRefPtr<MediaStreamAudioSourceNode> MediaStreamAudioSourceNode::create(AudioContext* context, MediaStream* mediaStream, MediaStreamTrack* audioTrack, AudioSourceProvider* audioSourceProvider) +Ref<MediaStreamAudioSourceNode> MediaStreamAudioSourceNode::create(AudioContext& context, MediaStream& mediaStream, MediaStreamTrack& audioTrack) { - return adoptRef(new MediaStreamAudioSourceNode(context, mediaStream, audioTrack, audioSourceProvider)); + return adoptRef(*new MediaStreamAudioSourceNode(context, mediaStream, audioTrack)); } -MediaStreamAudioSourceNode::MediaStreamAudioSourceNode(AudioContext* context, MediaStream* mediaStream, MediaStreamTrack* audioTrack, AudioSourceProvider* audioSourceProvider) - : AudioNode(context, context->sampleRate()) +MediaStreamAudioSourceNode::MediaStreamAudioSourceNode(AudioContext& context, MediaStream& mediaStream, MediaStreamTrack& audioTrack) + : AudioNode(context, context.sampleRate()) , m_mediaStream(mediaStream) , m_audioTrack(audioTrack) - , m_audioSourceProvider(audioSourceProvider) - , m_sourceNumberOfChannels(0) { + AudioSourceProvider* audioSourceProvider = m_audioTrack->audioSourceProvider(); + ASSERT(audioSourceProvider); + + audioSourceProvider->setClient(this); + // Default to stereo. This could change depending on the format of the MediaStream's audio track. addOutput(std::make_unique<AudioNodeOutput>(this, 2)); @@ -57,45 +60,56 @@ MediaStreamAudioSourceNode::MediaStreamAudioSourceNode(AudioContext* context, Me MediaStreamAudioSourceNode::~MediaStreamAudioSourceNode() { + AudioSourceProvider* audioSourceProvider = m_audioTrack->audioSourceProvider(); + ASSERT(audioSourceProvider); + audioSourceProvider->setClient(nullptr); uninitialize(); } void MediaStreamAudioSourceNode::setFormat(size_t numberOfChannels, float sourceSampleRate) { - if (numberOfChannels != m_sourceNumberOfChannels || sourceSampleRate != sampleRate()) { - // The sample-rate must be equal to the context's sample-rate. - if (!numberOfChannels || numberOfChannels > AudioContext::maxNumberOfChannels() || sourceSampleRate != sampleRate()) { - // process() will generate silence for these uninitialized values. - LOG(Media, "MediaStreamAudioSourceNode::setFormat(%u, %f) - unhandled format change", static_cast<unsigned>(numberOfChannels), sourceSampleRate); - m_sourceNumberOfChannels = 0; - return; - } - - // Synchronize with process(). - std::lock_guard<std::mutex> lock(m_processMutex); - - m_sourceNumberOfChannels = numberOfChannels; - - { - // The context must be locked when changing the number of output channels. - AudioContext::AutoLocker contextLocker(*context()); - - // Do any necesssary re-configuration to the output's number of channels. - output(0)->setNumberOfChannels(numberOfChannels); - } + float sampleRate = this->sampleRate(); + if (numberOfChannels == m_sourceNumberOfChannels && sourceSampleRate == sampleRate) + return; + + // The sample-rate must be equal to the context's sample-rate. + if (!numberOfChannels || numberOfChannels > AudioContext::maxNumberOfChannels() || sourceSampleRate != sampleRate) { + // process() will generate silence for these uninitialized values. + LOG(Media, "MediaStreamAudioSourceNode::setFormat(%u, %f) - unhandled format change", static_cast<unsigned>(numberOfChannels), sourceSampleRate); + m_sourceNumberOfChannels = 0; + return; + } + + // Synchronize with process(). + std::lock_guard<Lock> lock(m_processMutex); + + m_sourceNumberOfChannels = numberOfChannels; + m_sourceSampleRate = sourceSampleRate; + + if (sourceSampleRate == sampleRate) + m_multiChannelResampler = nullptr; + else { + double scaleFactor = sourceSampleRate / sampleRate; + m_multiChannelResampler = std::make_unique<MultiChannelResampler>(scaleFactor, numberOfChannels); + } + + m_sourceNumberOfChannels = numberOfChannels; + + { + // The context must be locked when changing the number of output channels. + AudioContext::AutoLocker contextLocker(context()); + + // Do any necesssary re-configuration to the output's number of channels. + output(0)->setNumberOfChannels(numberOfChannels); } } void MediaStreamAudioSourceNode::process(size_t numberOfFrames) { AudioBus* outputBus = output(0)->bus(); + AudioSourceProvider* provider = m_audioTrack->audioSourceProvider(); - if (!audioSourceProvider()) { - outputBus->zero(); - return; - } - - if (!mediaStream() || m_sourceNumberOfChannels != outputBus->numberOfChannels()) { + if (!mediaStream() || !m_sourceNumberOfChannels || !m_sourceSampleRate || !provider) { outputBus->zero(); return; } @@ -103,18 +117,21 @@ void MediaStreamAudioSourceNode::process(size_t numberOfFrames) // Use std::try_to_lock to avoid contention in the real-time audio thread. // If we fail to acquire the lock then the MediaStream must be in the middle of // a format change, so we output silence in this case. - std::unique_lock<std::mutex> lock(m_processMutex, std::try_to_lock); + std::unique_lock<Lock> lock(m_processMutex, std::try_to_lock); if (!lock.owns_lock()) { // We failed to acquire the lock. outputBus->zero(); return; } - audioSourceProvider()->provideInput(outputBus, numberOfFrames); -} - -void MediaStreamAudioSourceNode::reset() -{ + if (m_multiChannelResampler.get()) { + ASSERT(m_sourceSampleRate != sampleRate()); + m_multiChannelResampler->process(provider, outputBus, numberOfFrames); + } else { + // Bypass the resampler completely if the source is at the context's sample-rate. + ASSERT(m_sourceSampleRate == sampleRate()); + provider->provideInput(outputBus, numberOfFrames); + } } } // namespace WebCore |