OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "content/renderer/media/webrtc_local_audio_track.h" | 5 #include "content/renderer/media/webrtc_local_audio_track.h" |
6 | 6 |
7 #include "content/renderer/media/webaudio_capturer_source.h" | 7 #include "content/renderer/media/webaudio_capturer_source.h" |
8 #include "content/renderer/media/webrtc_audio_capturer.h" | 8 #include "content/renderer/media/webrtc_audio_capturer.h" |
9 #include "content/renderer/media/webrtc_audio_capturer_sink_owner.h" | 9 #include "content/renderer/media/webrtc_audio_capturer_sink_owner.h" |
10 #include "content/renderer/media/webrtc_local_audio_source_provider.h" | 10 #include "content/renderer/media/webrtc_local_audio_source_provider.h" |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
45 value) { | 45 value) { |
46 return true; | 46 return true; |
47 } | 47 } |
48 } | 48 } |
49 | 49 |
50 return false; | 50 return false; |
51 } | 51 } |
52 | 52 |
53 } // namespace. | 53 } // namespace. |
54 | 54 |
55 // This is a temporary audio buffer with parameters used to send data to | |
56 // callbacks. | |
57 class WebRtcLocalAudioTrack::ConfiguredBuffer : | |
58 public base::RefCounted<WebRtcLocalAudioTrack::ConfiguredBuffer> { | |
59 public: | |
60 ConfiguredBuffer() : sink_buffer_size_(0) {} | |
61 | |
62 void Initialize(const media::AudioParameters& params) { | |
63 DCHECK(params.IsValid()); | |
64 params_ = params; | |
65 | |
66 // Use 10ms as the sink buffer size since that is the native packet size | |
67 // WebRtc is running on. | |
68 sink_buffer_size_ = params.sample_rate() / 100; | |
69 audio_wrapper_ = | |
70 media::AudioBus::Create(params.channels(), sink_buffer_size_); | |
71 buffer_.reset(new int16[sink_buffer_size_ * params.channels()]); | |
72 | |
73 // The size of the FIFO should be at least twice of the source buffer size | |
74 // or twice of the sink buffer size. | |
75 int buffer_size = std::max( | |
76 kMaxNumberOfBuffersInFifo * params.frames_per_buffer(), | |
77 kMaxNumberOfBuffersInFifo * sink_buffer_size_); | |
78 fifo_.reset(new media::AudioFifo(params.channels(), buffer_size)); | |
79 } | |
80 | |
81 void Push(media::AudioBus* audio_source) { | |
82 DCHECK(fifo_->frames() + audio_source->frames() <= fifo_->max_frames()); | |
83 fifo_->Push(audio_source); | |
84 } | |
85 | |
86 bool Consume() { | |
87 if (fifo_->frames() < audio_wrapper_->frames()) | |
88 return false; | |
89 | |
90 fifo_->Consume(audio_wrapper_.get(), 0, audio_wrapper_->frames()); | |
91 audio_wrapper_->ToInterleaved(audio_wrapper_->frames(), | |
92 params_.bits_per_sample() / 8, | |
93 buffer()); | |
94 return true; | |
95 } | |
96 | |
97 int16* buffer() const { return buffer_.get(); } | |
98 const media::AudioParameters& params() const { return params_; } | |
99 int sink_buffer_size() const { return sink_buffer_size_; } | |
100 | |
101 private: | |
102 ~ConfiguredBuffer() {} | |
103 friend class base::RefCounted<WebRtcLocalAudioTrack::ConfiguredBuffer>; | |
104 | |
105 media::AudioParameters params_; | |
106 scoped_ptr<media::AudioBus> audio_wrapper_; | |
107 scoped_ptr<media::AudioFifo> fifo_; | |
108 scoped_ptr<int16[]> buffer_; | |
109 int sink_buffer_size_; | |
110 }; | |
111 | |
112 scoped_refptr<WebRtcLocalAudioTrack> WebRtcLocalAudioTrack::Create( | 55 scoped_refptr<WebRtcLocalAudioTrack> WebRtcLocalAudioTrack::Create( |
113 const std::string& id, | 56 const std::string& id, |
114 const scoped_refptr<WebRtcAudioCapturer>& capturer, | 57 const scoped_refptr<WebRtcAudioCapturer>& capturer, |
115 WebAudioCapturerSource* webaudio_source, | 58 WebAudioCapturerSource* webaudio_source, |
116 webrtc::AudioSourceInterface* track_source, | 59 webrtc::AudioSourceInterface* track_source, |
117 const webrtc::MediaConstraintsInterface* constraints) { | 60 const webrtc::MediaConstraintsInterface* constraints) { |
118 talk_base::RefCountedObject<WebRtcLocalAudioTrack>* track = | 61 talk_base::RefCountedObject<WebRtcLocalAudioTrack>* track = |
119 new talk_base::RefCountedObject<WebRtcLocalAudioTrack>( | 62 new talk_base::RefCountedObject<WebRtcLocalAudioTrack>( |
120 id, capturer, webaudio_source, track_source, constraints); | 63 id, capturer, webaudio_source, track_source, constraints); |
121 return track; | 64 return track; |
(...skipping 14 matching lines...) Expand all Loading... |
136 DVLOG(1) << "WebRtcLocalAudioTrack::WebRtcLocalAudioTrack()"; | 79 DVLOG(1) << "WebRtcLocalAudioTrack::WebRtcLocalAudioTrack()"; |
137 } | 80 } |
138 | 81 |
139 WebRtcLocalAudioTrack::~WebRtcLocalAudioTrack() { | 82 WebRtcLocalAudioTrack::~WebRtcLocalAudioTrack() { |
140 DCHECK(thread_checker_.CalledOnValidThread()); | 83 DCHECK(thread_checker_.CalledOnValidThread()); |
141 DVLOG(1) << "WebRtcLocalAudioTrack::~WebRtcLocalAudioTrack()"; | 84 DVLOG(1) << "WebRtcLocalAudioTrack::~WebRtcLocalAudioTrack()"; |
142 // Users might not call Stop() on the track. | 85 // Users might not call Stop() on the track. |
143 Stop(); | 86 Stop(); |
144 } | 87 } |
145 | 88 |
146 void WebRtcLocalAudioTrack::Capture(media::AudioBus* audio_source, | 89 void WebRtcLocalAudioTrack::Capture(const int16* audio_data, |
147 int audio_delay_milliseconds, | 90 int sample_rate, |
148 int volume, | 91 int number_of_channels, |
149 bool key_pressed) { | 92 int number_of_frames) { |
150 scoped_refptr<WebRtcAudioCapturer> capturer; | 93 DCHECK(number_of_frames == (sample_rate / 100)); |
| 94 |
151 std::vector<int> voe_channels; | 95 std::vector<int> voe_channels; |
152 int sample_rate = 0; | |
153 int number_of_channels = 0; | |
154 int number_of_frames = 0; | |
155 SinkList sinks; | 96 SinkList sinks; |
156 bool is_webaudio_source = false; | |
157 scoped_refptr<ConfiguredBuffer> current_buffer; | |
158 { | 97 { |
159 base::AutoLock auto_lock(lock_); | 98 base::AutoLock auto_lock(lock_); |
160 capturer = capturer_; | |
161 voe_channels = voe_channels_; | 99 voe_channels = voe_channels_; |
162 current_buffer = buffer_; | |
163 sample_rate = current_buffer->params().sample_rate(); | |
164 number_of_channels = current_buffer->params().channels(); | |
165 number_of_frames = current_buffer->sink_buffer_size(); | |
166 sinks = sinks_; | 100 sinks = sinks_; |
167 is_webaudio_source = (webaudio_source_.get() != NULL); | |
168 } | 101 } |
169 | 102 |
170 // Push the data to the fifo. | 103 // Feed the data to the sinks. |
171 current_buffer->Push(audio_source); | 104 // TODO (jiayl): we should not pass the real audio data down if the track is |
172 | 105 // disabled. This is currently done so to feed input to WebRTC typing |
173 // When the source is WebAudio, turn off the audio processing if the delay | 106 // detection and should be changed when audio processing is moved from |
174 // value is 0 even though the constraint is set to true. In such case, it | 107 // WebRTC to the track. |
175 // indicates the data is not from microphone. | 108 for (SinkList::const_iterator it = sinks.begin(); it != sinks.end(); ++it) { |
176 // TODO(xians): remove the flag when supporting one APM per audio track. | 109 (*it)->CaptureData(voe_channels, |
177 // See crbug/264611 for details. | 110 audio_data, |
178 bool need_audio_processing = need_audio_processing_; | 111 sample_rate, |
179 if (is_webaudio_source && need_audio_processing) | 112 number_of_channels, |
180 need_audio_processing = (audio_delay_milliseconds != 0); | 113 number_of_frames); |
181 | |
182 int current_volume = volume; | |
183 while (current_buffer->Consume()) { | |
184 // Feed the data to the sinks. | |
185 // TODO (jiayl): we should not pass the real audio data down if the track is | |
186 // disabled. This is currently done so to feed input to WebRTC typing | |
187 // detection and should be changed when audio processing is moved from | |
188 // WebRTC to the track. | |
189 for (SinkList::const_iterator it = sinks.begin(); it != sinks.end(); ++it) { | |
190 int new_volume = (*it)->CaptureData(voe_channels, | |
191 current_buffer->buffer(), | |
192 sample_rate, | |
193 number_of_channels, | |
194 number_of_frames, | |
195 audio_delay_milliseconds, | |
196 current_volume, | |
197 need_audio_processing, | |
198 key_pressed); | |
199 if (new_volume != 0 && capturer.get()) { | |
200 // Feed the new volume to WebRtc while changing the volume on the | |
201 // browser. | |
202 capturer->SetVolume(new_volume); | |
203 current_volume = new_volume; | |
204 } | |
205 } | |
206 } | 114 } |
207 } | 115 } |
208 | 116 |
209 void WebRtcLocalAudioTrack::SetCaptureFormat( | 117 void WebRtcLocalAudioTrack::SetCaptureFormat( |
210 const media::AudioParameters& params) { | 118 const media::AudioParameters& params) { |
211 if (!params.IsValid()) | 119 if (!params.IsValid()) |
212 return; | 120 return; |
213 | 121 |
214 scoped_refptr<ConfiguredBuffer> new_buffer(new ConfiguredBuffer()); | |
215 new_buffer->Initialize(params); | |
216 | |
217 SinkList sinks; | 122 SinkList sinks; |
218 { | 123 { |
219 base::AutoLock auto_lock(lock_); | 124 base::AutoLock auto_lock(lock_); |
220 buffer_ = new_buffer; | 125 params_ = params; |
221 sinks = sinks_; | 126 sinks = sinks_; |
222 } | 127 } |
223 | 128 |
224 // Update all the existing sinks with the new format. | 129 // Update all the existing sinks with the new format. |
225 for (SinkList::const_iterator it = sinks.begin(); | 130 for (SinkList::const_iterator it = sinks.begin(); |
226 it != sinks.end(); ++it) { | 131 it != sinks.end(); ++it) { |
227 (*it)->SetCaptureFormat(params); | 132 (*it)->SetCaptureFormat(params); |
228 } | 133 } |
229 } | 134 } |
230 | 135 |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
262 } | 167 } |
263 | 168 |
264 std::string WebRtcLocalAudioTrack::kind() const { | 169 std::string WebRtcLocalAudioTrack::kind() const { |
265 return kAudioTrackKind; | 170 return kAudioTrackKind; |
266 } | 171 } |
267 | 172 |
268 void WebRtcLocalAudioTrack::AddSink(WebRtcAudioCapturerSink* sink) { | 173 void WebRtcLocalAudioTrack::AddSink(WebRtcAudioCapturerSink* sink) { |
269 DCHECK(thread_checker_.CalledOnValidThread()); | 174 DCHECK(thread_checker_.CalledOnValidThread()); |
270 DVLOG(1) << "WebRtcLocalAudioTrack::AddSink()"; | 175 DVLOG(1) << "WebRtcLocalAudioTrack::AddSink()"; |
271 base::AutoLock auto_lock(lock_); | 176 base::AutoLock auto_lock(lock_); |
272 if (buffer_.get()) | 177 |
273 sink->SetCaptureFormat(buffer_->params()); | 178 sink->SetCaptureFormat(params_); |
274 | 179 |
275 // Verify that |sink| is not already added to the list. | 180 // Verify that |sink| is not already added to the list. |
276 DCHECK(std::find_if( | 181 DCHECK(std::find_if( |
277 sinks_.begin(), sinks_.end(), | 182 sinks_.begin(), sinks_.end(), |
278 WebRtcAudioCapturerSinkOwner::WrapsSink(sink)) == sinks_.end()); | 183 WebRtcAudioCapturerSinkOwner::WrapsSink(sink)) == sinks_.end()); |
279 | 184 |
280 // Create (and add to the list) a new WebRtcAudioCapturerSinkOwner which owns | 185 // Create (and add to the list) a new WebRtcAudioCapturerSinkOwner which owns |
281 // the |sink| and delagates all calls to the WebRtcAudioCapturerSink | 186 // the |sink| and delagates all calls to the WebRtcAudioCapturerSink |
282 // interface. | 187 // interface. |
283 sinks_.push_back(new WebRtcAudioCapturerSinkOwner(sink)); | 188 sinks_.push_back(new WebRtcAudioCapturerSinkOwner(sink)); |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
346 sinks = sinks_; | 251 sinks = sinks_; |
347 webaudio_source_ = NULL; | 252 webaudio_source_ = NULL; |
348 capturer_ = NULL; | 253 capturer_ = NULL; |
349 } | 254 } |
350 | 255 |
351 for (SinkList::const_iterator it = sinks.begin(); it != sinks.end(); ++it) | 256 for (SinkList::const_iterator it = sinks.begin(); it != sinks.end(); ++it) |
352 (*it)->Reset(); | 257 (*it)->Reset(); |
353 } | 258 } |
354 | 259 |
355 } // namespace content | 260 } // namespace content |
OLD | NEW |