Roll src/third_party/WebKit eac3800:0237a66 (svn 202606:202607)
[chromium-blink-merge.git] / content / renderer / media / webrtc_local_audio_source_provider.cc
blobb6ec56eff0cdd62c80e3d9ae39d258f9aad38648
1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "content/renderer/media/webrtc_local_audio_source_provider.h"
7 #include "base/logging.h"
8 #include "content/renderer/render_thread_impl.h"
9 #include "media/audio/audio_parameters.h"
10 #include "media/base/audio_fifo.h"
11 #include "media/base/audio_hardware_config.h"
12 #include "third_party/WebKit/public/platform/WebAudioSourceProviderClient.h"
14 using blink::WebVector;
16 namespace content {
18 static const size_t kMaxNumberOfBuffers = 10;
20 // Size of the buffer that WebAudio processes each time, it is the same value
21 // as AudioNode::ProcessingSizeInFrames in WebKit.
22 // static
23 const size_t WebRtcLocalAudioSourceProvider::kWebAudioRenderBufferSize = 128;
25 WebRtcLocalAudioSourceProvider::WebRtcLocalAudioSourceProvider(
26 const blink::WebMediaStreamTrack& track)
27 : is_enabled_(false),
28 track_(track),
29 track_stopped_(false) {
30 // Get the native audio output hardware sample-rate for the sink.
31 // We need to check if RenderThreadImpl is valid here since the unittests
32 // do not have one and they will inject their own |sink_params_| for testing.
33 if (RenderThreadImpl::current()) {
34 media::AudioHardwareConfig* hardware_config =
35 RenderThreadImpl::current()->GetAudioHardwareConfig();
36 int sample_rate = hardware_config->GetOutputSampleRate();
37 sink_params_.Reset(media::AudioParameters::AUDIO_PCM_LOW_LATENCY,
38 media::CHANNEL_LAYOUT_STEREO, sample_rate, 16,
39 kWebAudioRenderBufferSize);
42 // Connect the source provider to the track as a sink.
43 MediaStreamAudioSink::AddToAudioTrack(this, track_);
46 WebRtcLocalAudioSourceProvider::~WebRtcLocalAudioSourceProvider() {
47 if (audio_converter_.get())
48 audio_converter_->RemoveInput(this);
50 // If the track is still active, it is necessary to notify the track before
51 // the source provider goes away.
52 if (!track_stopped_)
53 MediaStreamAudioSink::RemoveFromAudioTrack(this, track_);
56 void WebRtcLocalAudioSourceProvider::OnSetFormat(
57 const media::AudioParameters& params) {
58 // We need detach the thread here because it will be a new capture thread
59 // calling OnSetFormat() and OnData() if the source is restarted.
60 capture_thread_checker_.DetachFromThread();
61 DCHECK(capture_thread_checker_.CalledOnValidThread());
62 DCHECK(params.IsValid());
63 DCHECK(sink_params_.IsValid());
65 base::AutoLock auto_lock(lock_);
66 source_params_ = params;
67 // Create the audio converter with |disable_fifo| as false so that the
68 // converter will request source_params.frames_per_buffer() each time.
69 // This will not increase the complexity as there is only one client to
70 // the converter.
71 audio_converter_.reset(
72 new media::AudioConverter(params, sink_params_, false));
73 audio_converter_->AddInput(this);
74 fifo_.reset(new media::AudioFifo(
75 params.channels(),
76 kMaxNumberOfBuffers * params.frames_per_buffer()));
79 void WebRtcLocalAudioSourceProvider::OnReadyStateChanged(
80 blink::WebMediaStreamSource::ReadyState state) {
81 if (state == blink::WebMediaStreamSource::ReadyStateEnded)
82 track_stopped_ = true;
85 void WebRtcLocalAudioSourceProvider::OnData(
86 const media::AudioBus& audio_bus,
87 base::TimeTicks estimated_capture_time) {
88 DCHECK(capture_thread_checker_.CalledOnValidThread());
89 DCHECK_EQ(audio_bus.channels(), source_params_.channels());
90 DCHECK_EQ(audio_bus.frames(), source_params_.frames_per_buffer());
91 DCHECK(!estimated_capture_time.is_null());
93 base::AutoLock auto_lock(lock_);
94 if (!is_enabled_)
95 return;
97 DCHECK(fifo_.get());
99 if (fifo_->frames() + audio_bus.frames() <= fifo_->max_frames()) {
100 fifo_->Push(&audio_bus);
101 } else {
102 // This can happen if the data in FIFO is too slowly consumed or
103 // WebAudio stops consuming data.
104 DVLOG(3) << "Local source provicer FIFO is full" << fifo_->frames();
108 void WebRtcLocalAudioSourceProvider::setClient(
109 blink::WebAudioSourceProviderClient* client) {
110 NOTREACHED();
113 void WebRtcLocalAudioSourceProvider::provideInput(
114 const WebVector<float*>& audio_data, size_t number_of_frames) {
115 DCHECK_EQ(number_of_frames, kWebAudioRenderBufferSize);
116 if (!output_wrapper_ ||
117 static_cast<size_t>(output_wrapper_->channels()) != audio_data.size()) {
118 output_wrapper_ = media::AudioBus::CreateWrapper(audio_data.size());
121 output_wrapper_->set_frames(number_of_frames);
122 for (size_t i = 0; i < audio_data.size(); ++i)
123 output_wrapper_->SetChannelData(i, audio_data[i]);
125 base::AutoLock auto_lock(lock_);
126 if (!audio_converter_)
127 return;
129 is_enabled_ = true;
130 audio_converter_->Convert(output_wrapper_.get());
133 double WebRtcLocalAudioSourceProvider::ProvideInput(
134 media::AudioBus* audio_bus, base::TimeDelta buffer_delay) {
135 if (fifo_->frames() >= audio_bus->frames()) {
136 fifo_->Consume(audio_bus, 0, audio_bus->frames());
137 } else {
138 audio_bus->Zero();
139 DVLOG(1) << "WARNING: Underrun, FIFO has data " << fifo_->frames()
140 << " samples but " << audio_bus->frames()
141 << " samples are needed";
144 return 1.0;
147 void WebRtcLocalAudioSourceProvider::SetSinkParamsForTesting(
148 const media::AudioParameters& sink_params) {
149 sink_params_ = sink_params;
152 } // namespace content