| Index: content/renderer/media/webaudio_media_stream_source.cc
|
| diff --git a/content/renderer/media/webaudio_media_stream_source.cc b/content/renderer/media/webaudio_media_stream_source.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..efdd7ed8364a269276d318e5f8bf1c9553fd855e
|
| --- /dev/null
|
| +++ b/content/renderer/media/webaudio_media_stream_source.cc
|
| @@ -0,0 +1,109 @@
|
| +// Copyright (c) 2016 The Chromium Authors. All rights reserved.
|
| +// Use of this source code is governed by a BSD-style license that can be
|
| +// found in the LICENSE file.
|
| +
|
| +#include "content/renderer/media/webaudio_media_stream_source.h"
|
| +
|
| +#include "base/bind.h"
|
| +#include "base/bind_helpers.h"
|
| +#include "base/logging.h"
|
| +
|
| +namespace content {
|
| +
|
| +WebAudioMediaStreamSource::WebAudioMediaStreamSource(
|
| + const blink::WebMediaStreamSource& blink_source)
|
| + : MediaStreamAudioSource(false /* is_remote */),
|
| + blink_source_(blink_source),
|
| + is_started_(false),
|
| + rechunker_(base::TimeDelta::FromMilliseconds(10),
|
| + base::Bind(&WebAudioMediaStreamSource::DeliverRechunkedAudio,
|
| + base::Unretained(this))) {
|
| + DVLOG(1) << "WebAudioMediaStreamSource::WebAudioMediaStreamSource()";
|
| +}
|
| +
|
| +WebAudioMediaStreamSource::~WebAudioMediaStreamSource() {
|
| + DVLOG(1) << "WebAudioMediaStreamSource::~WebAudioMediaStreamSource()";
|
| + // Superclass will call StopSource() just in case.
|
| +}
|
| +
|
| +void WebAudioMediaStreamSource::setFormat(
|
| + size_t number_of_channels, float sample_rate) {
|
| + VLOG(1) << "WebAudio media stream source changed format to: channels="
|
| + << number_of_channels << ", sample_rate=" << sample_rate;
|
| +
|
| + rechunker_.SetSampleRate(sample_rate);
|
| + if (!wrapper_bus_ ||
|
| + wrapper_bus_->channels() != static_cast<int>(number_of_channels)) {
|
| + wrapper_bus_ = media::AudioBus::CreateWrapper(number_of_channels);
|
| + }
|
| +
|
| + // If the channel count is greater than 8, use discrete layout. However,
|
| + // anything beyond 8 is ignored by some audio tracks/sinks.
|
| + const media::ChannelLayout channel_layout =
|
| + number_of_channels > 8 ? media::CHANNEL_LAYOUT_DISCRETE
|
| + : media::GuessChannelLayout(number_of_channels);
|
| +
|
| + MediaStreamAudioSource::SetFormat(media::AudioParameters(
|
| + media::AudioParameters::AUDIO_PCM_LOW_LATENCY,
|
| + channel_layout,
|
| + sample_rate,
|
| + 16, // Legacy parameter (data is always in 32-bit float format).
|
| + rechunker_.output_frames()));
|
| +}
|
| +
|
| +void WebAudioMediaStreamSource::consumeAudio(
|
| + const blink::WebVector<const float*>& audio_data,
|
| + size_t number_of_frames) {
|
| + // TODO(miu): Plumbing is needed to determine the actual capture timestamp
|
| + // of the audio, instead of just snapshotting TimeTicks::Now(), for proper
|
| + // audio/video sync. http://crbug.com/335335
|
| + base::TimeTicks reference_time = base::TimeTicks::Now();
|
| +
|
| + wrapper_bus_->set_frames(number_of_frames);
|
| + DCHECK_EQ(wrapper_bus_->channels(), static_cast<int>(audio_data.size()));
|
| + for (size_t i = 0; i < audio_data.size(); ++i)
|
| + wrapper_bus_->SetChannelData(i, const_cast<float*>(audio_data[i]));
|
| +
|
| + rechunker_.Push(*wrapper_bus_, reference_time - base::TimeTicks());
|
| +}
|
| +
|
| +void WebAudioMediaStreamSource::DeliverRechunkedAudio(
|
| + const media::AudioBus& audio_bus,
|
| + base::TimeDelta reference_timestamp) {
|
| + MediaStreamAudioSource::DeliverDataToTracks(
|
| + audio_bus, reference_timestamp + base::TimeTicks());
|
| +}
|
| +
|
| +void WebAudioMediaStreamSource::DoStopSource() {
|
| + DCHECK(thread_checker_.CalledOnValidThread());
|
| + if (is_stopped_)
|
| + return;
|
| + if (is_started_) {
|
| + if (!blink_source_.isNull()) {
|
| + blink_source_.removeAudioConsumer(this);
|
| + blink_source_.reset();
|
| + VLOG(1) << "Stopped WebAudio media stream source. Final audio "
|
| + "parameters={"
|
| + << GetAudioParameters().AsHumanReadableString() << "}.";
|
| + }
|
| + }
|
| + is_stopped_ = true;
|
| +}
|
| +
|
| +bool WebAudioMediaStreamSource::EnsureSourceIsStarted() {
|
| + DCHECK(thread_checker_.CalledOnValidThread());
|
| + if (is_stopped_)
|
| + return false;
|
| + if (is_started_)
|
| + return true;
|
| + if (blink_source_.isNull() || !blink_source_.requiresAudioConsumer()) {
|
| + StopSource();
|
| + return false;
|
| + }
|
| + VLOG(1) << "Starting WebAudio media stream source.";
|
| + blink_source_.addAudioConsumer(this);
|
| + is_started_ = true;
|
| + return true;
|
| +}
|
| +
|
| +} // namespace content
|
|
|