This source file includes following definitions.
- track_stopped_
- OnSetFormat
- OnReadyStateChanged
- OnData
- setClient
- provideInput
- ProvideInput
- SetSinkParamsForTesting
#include "content/renderer/media/webrtc_local_audio_source_provider.h"
#include "base/logging.h"
#include "content/renderer/render_thread_impl.h"
#include "media/audio/audio_parameters.h"
#include "media/base/audio_fifo.h"
#include "media/base/audio_hardware_config.h"
#include "third_party/WebKit/public/platform/WebAudioSourceProviderClient.h"
using blink::WebVector;
namespace content {
static const size_t kMaxNumberOfBuffers = 10;
const size_t WebRtcLocalAudioSourceProvider::kWebAudioRenderBufferSize = 128;
WebRtcLocalAudioSourceProvider::WebRtcLocalAudioSourceProvider(
const blink::WebMediaStreamTrack& track)
: is_enabled_(false),
track_(track),
track_stopped_(false) {
if (RenderThreadImpl::current()) {
media::AudioHardwareConfig* hardware_config =
RenderThreadImpl::current()->GetAudioHardwareConfig();
int sample_rate = hardware_config->GetOutputSampleRate();
sink_params_.Reset(
media::AudioParameters::AUDIO_PCM_LOW_LATENCY,
media::CHANNEL_LAYOUT_STEREO, 2, 0, sample_rate, 16,
kWebAudioRenderBufferSize);
}
MediaStreamAudioSink::AddToAudioTrack(this, track_);
}
WebRtcLocalAudioSourceProvider::~WebRtcLocalAudioSourceProvider() {
if (audio_converter_.get())
audio_converter_->RemoveInput(this);
if (!track_stopped_)
MediaStreamAudioSink::RemoveFromAudioTrack(this, track_);
}
void WebRtcLocalAudioSourceProvider::OnSetFormat(
const media::AudioParameters& params) {
capture_thread_checker_.DetachFromThread();
DCHECK(capture_thread_checker_.CalledOnValidThread());
DCHECK(params.IsValid());
DCHECK(sink_params_.IsValid());
base::AutoLock auto_lock(lock_);
source_params_ = params;
audio_converter_.reset(
new media::AudioConverter(params, sink_params_, false));
audio_converter_->AddInput(this);
fifo_.reset(new media::AudioFifo(
params.channels(),
kMaxNumberOfBuffers * params.frames_per_buffer()));
input_bus_ = media::AudioBus::Create(params.channels(),
params.frames_per_buffer());
}
void WebRtcLocalAudioSourceProvider::OnReadyStateChanged(
blink::WebMediaStreamSource::ReadyState state) {
if (state == blink::WebMediaStreamSource::ReadyStateEnded)
track_stopped_ = true;
}
void WebRtcLocalAudioSourceProvider::OnData(
const int16* audio_data,
int sample_rate,
int number_of_channels,
int number_of_frames) {
DCHECK(capture_thread_checker_.CalledOnValidThread());
base::AutoLock auto_lock(lock_);
if (!is_enabled_)
return;
DCHECK(fifo_.get());
DCHECK(input_bus_->frames() == number_of_frames);
DCHECK(input_bus_->channels() == number_of_channels);
input_bus_->FromInterleaved(audio_data, number_of_frames, 2);
if (fifo_->frames() + number_of_frames <= fifo_->max_frames()) {
fifo_->Push(input_bus_.get());
} else {
DVLOG(3) << "Local source provicer FIFO is full" << fifo_->frames();
}
}
void WebRtcLocalAudioSourceProvider::setClient(
blink::WebAudioSourceProviderClient* client) {
NOTREACHED();
}
void WebRtcLocalAudioSourceProvider::provideInput(
const WebVector<float*>& audio_data, size_t number_of_frames) {
DCHECK_EQ(number_of_frames, kWebAudioRenderBufferSize);
if (!output_wrapper_ ||
static_cast<size_t>(output_wrapper_->channels()) != audio_data.size()) {
output_wrapper_ = media::AudioBus::CreateWrapper(audio_data.size());
}
output_wrapper_->set_frames(number_of_frames);
for (size_t i = 0; i < audio_data.size(); ++i)
output_wrapper_->SetChannelData(i, audio_data[i]);
base::AutoLock auto_lock(lock_);
if (!audio_converter_)
return;
is_enabled_ = true;
audio_converter_->Convert(output_wrapper_.get());
}
double WebRtcLocalAudioSourceProvider::ProvideInput(
media::AudioBus* audio_bus, base::TimeDelta buffer_delay) {
if (fifo_->frames() >= audio_bus->frames()) {
fifo_->Consume(audio_bus, 0, audio_bus->frames());
} else {
audio_bus->Zero();
DVLOG(1) << "WARNING: Underrun, FIFO has data " << fifo_->frames()
<< " samples but " << audio_bus->frames()
<< " samples are needed";
}
return 1.0;
}
void WebRtcLocalAudioSourceProvider::SetSinkParamsForTesting(
const media::AudioParameters& sink_params) {
sink_params_ = sink_params;
}
}