1 // Copyright (c) 2012 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/webaudio_capturer_source.h"
7 #include "base/logging.h"
8 #include "base/time/time.h"
9 #include "content/renderer/media/webrtc_audio_capturer.h"
10 #include "content/renderer/media/webrtc_local_audio_track.h"
12 using media::AudioBus
;
13 using media::AudioFifo
;
14 using media::AudioParameters
;
15 using media::ChannelLayout
;
16 using media::CHANNEL_LAYOUT_MONO
;
17 using media::CHANNEL_LAYOUT_STEREO
;
19 static const int kMaxNumberOfBuffersInFifo
= 5;
23 WebAudioCapturerSource::WebAudioCapturerSource()
26 audio_format_changed_(false) {
29 WebAudioCapturerSource::~WebAudioCapturerSource() {
32 void WebAudioCapturerSource::setFormat(
33 size_t number_of_channels
, float sample_rate
) {
34 DCHECK(thread_checker_
.CalledOnValidThread());
35 DVLOG(1) << "WebAudioCapturerSource::setFormat(sample_rate="
36 << sample_rate
<< ")";
37 if (number_of_channels
> 2) {
38 // TODO(xians): Handle more than just the mono and stereo cases.
39 LOG(WARNING
) << "WebAudioCapturerSource::setFormat() : unhandled format.";
43 ChannelLayout channel_layout
=
44 number_of_channels
== 1 ? CHANNEL_LAYOUT_MONO
: CHANNEL_LAYOUT_STEREO
;
46 base::AutoLock
auto_lock(lock_
);
47 // Set the format used by this WebAudioCapturerSource. We are using 10ms data
48 // as buffer size since that is the native buffer size of WebRtc packet
50 params_
.Reset(media::AudioParameters::AUDIO_PCM_LOW_LATENCY
,
51 channel_layout
, number_of_channels
, 0, sample_rate
, 16,
53 audio_format_changed_
= true;
55 wrapper_bus_
= AudioBus::CreateWrapper(params_
.channels());
56 capture_bus_
= AudioBus::Create(params_
);
58 new int16
[params_
.frames_per_buffer() * params_
.channels()]);
59 fifo_
.reset(new AudioFifo(
61 kMaxNumberOfBuffersInFifo
* params_
.frames_per_buffer()));
64 void WebAudioCapturerSource::Start(
65 WebRtcLocalAudioTrack
* track
, WebRtcAudioCapturer
* capturer
) {
66 DCHECK(thread_checker_
.CalledOnValidThread());
68 base::AutoLock
auto_lock(lock_
);
73 void WebAudioCapturerSource::Stop() {
74 DCHECK(thread_checker_
.CalledOnValidThread());
75 base::AutoLock
auto_lock(lock_
);
80 void WebAudioCapturerSource::consumeAudio(
81 const blink::WebVector
<const float*>& audio_data
,
82 size_t number_of_frames
) {
83 base::AutoLock
auto_lock(lock_
);
87 // Update the downstream client if the audio format has been changed.
88 if (audio_format_changed_
) {
89 track_
->OnSetFormat(params_
);
90 audio_format_changed_
= false;
93 wrapper_bus_
->set_frames(number_of_frames
);
95 // Make sure WebKit is honoring what it told us up front
96 // about the channels.
97 DCHECK_EQ(params_
.channels(), static_cast<int>(audio_data
.size()));
99 for (size_t i
= 0; i
< audio_data
.size(); ++i
)
100 wrapper_bus_
->SetChannelData(i
, const_cast<float*>(audio_data
[i
]));
102 // Handle mismatch between WebAudio buffer-size and WebRTC.
103 int available
= fifo_
->max_frames() - fifo_
->frames();
104 if (available
< static_cast<int>(number_of_frames
)) {
105 NOTREACHED() << "WebAudioCapturerSource::Consume() : FIFO overrun.";
109 fifo_
->Push(wrapper_bus_
.get());
110 int capture_frames
= params_
.frames_per_buffer();
111 base::TimeDelta delay
;
113 bool key_pressed
= false;
115 capturer_
->GetAudioProcessingParams(&delay
, &volume
, &key_pressed
);
118 // Turn off audio processing if the delay value is 0, since in such case,
119 // it indicates the data is not from microphone.
120 // TODO(xians): remove the flag when supporting one APM per audio track.
121 // See crbug/264611 for details.
122 bool need_audio_processing
= (delay
.InMilliseconds() != 0);
123 while (fifo_
->frames() >= capture_frames
) {
124 fifo_
->Consume(capture_bus_
.get(), 0, capture_frames
);
125 // TODO(xians): Avoid this interleave/deinterleave operation.
126 capture_bus_
->ToInterleaved(capture_bus_
->frames(),
127 params_
.bits_per_sample() / 8,
129 track_
->Capture(audio_data_
.get(), delay
, volume
, key_pressed
,
130 need_audio_processing
);
134 } // namespace content