Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(31)

Side by Side Diff: remoting/host/audio_capturer_win.cc

Issue 2903153004: [Chromoting] Implement down mixing in AudioPump (Closed)
Patch Set: Created 3 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 "remoting/host/audio_capturer_win.h" 5 #include "remoting/host/audio_capturer_win.h"
6 6
7 #include <avrt.h> 7 #include <avrt.h>
8 #include <mmreg.h> 8 #include <mmreg.h>
9 #include <mmsystem.h> 9 #include <mmsystem.h>
10 #include <objbase.h> 10 #include <objbase.h>
11 #include <stdint.h> 11 #include <stdint.h>
12 #include <stdlib.h> 12 #include <stdlib.h>
13 #include <windows.h> 13 #include <windows.h>
14 14
15 #include <algorithm> 15 #include <algorithm>
16 #include <utility> 16 #include <utility>
17 17
18 #include "base/logging.h" 18 #include "base/logging.h"
19 #include "base/memory/ptr_util.h" 19 #include "base/memory/ptr_util.h"
20 #include "base/synchronization/lock.h" 20 #include "base/synchronization/lock.h"
21 #include "remoting/host/win/default_audio_device_change_detector.h" 21 #include "remoting/host/win/default_audio_device_change_detector.h"
22 22
23 namespace { 23 namespace {
24 const int kChannels = 2;
25 const int kBytesPerSample = 2; 24 const int kBytesPerSample = 2;
26 const int kBitsPerSample = kBytesPerSample * 8; 25 const int kBitsPerSample = kBytesPerSample * 8;
27 // Conversion factor from 100ns to 1ms. 26 // Conversion factor from 100ns to 1ms.
28 const int k100nsPerMillisecond = 10000; 27 const int k100nsPerMillisecond = 10000;
29 28
30 // Tolerance for catching packets of silence. If all samples have absolute 29 // Tolerance for catching packets of silence. If all samples have absolute
31 // value less than this threshold, the packet will be counted as a packet of 30 // value less than this threshold, the packet will be counted as a packet of
32 // silence. A value of 2 was chosen, because Windows can give samples of 1 and 31 // silence. A value of 2 was chosen, because Windows can give samples of 1 and
33 // -1, even when no audio is playing. 32 // -1, even when no audio is playing.
34 const int kSilenceThreshold = 2; 33 const int kSilenceThreshold = 2;
35 34
36 // Lower bound for timer intervals, in milliseconds. 35 // Lower bound for timer intervals, in milliseconds.
37 const int kMinTimerInterval = 30; 36 const int kMinTimerInterval = 30;
38 37
39 // Upper bound for the timer precision error, in milliseconds. 38 // Upper bound for the timer precision error, in milliseconds.
40 // Timers are supposed to be accurate to 20ms, so we use 30ms to be safe. 39 // Timers are supposed to be accurate to 20ms, so we use 30ms to be safe.
41 const int kMaxExpectedTimerLag = 30; 40 const int kMaxExpectedTimerLag = 30;
41
42 int ChooseChannels(int channel_count) {
joedow 2017/05/26 16:01:50 This function doesn't choose a channel, it convert
Hzj_jie 2017/05/26 20:08:03 Before this change, we always select stereo. But t
Sergey Ulanov 2017/05/26 22:24:45 If I understand correctly this function defines ch
Hzj_jie 2017/05/28 20:58:58 IMO, it's still worthy to have a shot: it won't wa
Sergey Ulanov 2017/06/05 18:03:19 I still don't think this is necessary. The problem
Hzj_jie 2017/06/06 03:21:42 Then I would prefer to rewrite the wave_format_ex_
chcunningham 2017/06/09 19:25:28 This is fine for this CL, but we have seen more th
Hzj_jie 2017/06/09 21:33:47 IMO, a long-term solution is to migrate to AudioIn
43 using remoting::AudioPacket;
44 // The condition should match AudioPacket::Channels enum in audio.proto.
45 if (channel_count == AudioPacket::CHANNELS_MONO ||
46 channel_count == AudioPacket::CHANNELS_STEREO ||
47 channel_count == AudioPacket::CHANNELS_5_1 ||
48 channel_count == AudioPacket::CHANNELS_6_1 ||
49 channel_count == AudioPacket::CHANNELS_7_1) {
50 return channel_count;
51 }
52 return AudioPacket::CHANNELS_STEREO;
53 }
54
42 } // namespace 55 } // namespace
43 56
44 namespace remoting { 57 namespace remoting {
45 58
46 AudioCapturerWin::AudioCapturerWin() 59 AudioCapturerWin::AudioCapturerWin()
47 : sampling_rate_(AudioPacket::SAMPLING_RATE_INVALID), 60 : sampling_rate_(AudioPacket::SAMPLING_RATE_INVALID),
48 volume_filter_(kSilenceThreshold), 61 volume_filter_(kSilenceThreshold),
49 last_capture_error_(S_OK) { 62 last_capture_error_(S_OK) {
50 thread_checker_.DetachFromThread(); 63 thread_checker_.DetachFromThread();
51 } 64 }
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after
156 // Intentional fall-through. 169 // Intentional fall-through.
157 case WAVE_FORMAT_PCM: 170 case WAVE_FORMAT_PCM:
158 if (!AudioCapturer::IsValidSampleRate(wave_format_ex_->nSamplesPerSec)) { 171 if (!AudioCapturer::IsValidSampleRate(wave_format_ex_->nSamplesPerSec)) {
159 LOG(ERROR) << "Host sampling rate is neither 44.1 kHz nor 48 kHz."; 172 LOG(ERROR) << "Host sampling rate is neither 44.1 kHz nor 48 kHz.";
160 return false; 173 return false;
161 } 174 }
162 sampling_rate_ = static_cast<AudioPacket::SamplingRate>( 175 sampling_rate_ = static_cast<AudioPacket::SamplingRate>(
163 wave_format_ex_->nSamplesPerSec); 176 wave_format_ex_->nSamplesPerSec);
164 177
165 wave_format_ex_->wFormatTag = WAVE_FORMAT_PCM; 178 wave_format_ex_->wFormatTag = WAVE_FORMAT_PCM;
166 wave_format_ex_->nChannels = kChannels; 179 wave_format_ex_->nChannels = ChooseChannels(wave_format_ex_->nChannels);
167 wave_format_ex_->wBitsPerSample = kBitsPerSample; 180 wave_format_ex_->wBitsPerSample = kBitsPerSample;
168 wave_format_ex_->nBlockAlign = kChannels * kBytesPerSample; 181 wave_format_ex_->nBlockAlign =
182 wave_format_ex_->nChannels * kBytesPerSample;
169 wave_format_ex_->nAvgBytesPerSec = 183 wave_format_ex_->nAvgBytesPerSec =
170 sampling_rate_ * kChannels * kBytesPerSample; 184 sampling_rate_ * wave_format_ex_->nChannels * kBytesPerSample;
171 break; 185 break;
172 case WAVE_FORMAT_EXTENSIBLE: { 186 case WAVE_FORMAT_EXTENSIBLE: {
173 PWAVEFORMATEXTENSIBLE wave_format_extensible = 187 PWAVEFORMATEXTENSIBLE wave_format_extensible =
174 reinterpret_cast<WAVEFORMATEXTENSIBLE*>( 188 reinterpret_cast<WAVEFORMATEXTENSIBLE*>(
175 static_cast<WAVEFORMATEX*>(wave_format_ex_)); 189 static_cast<WAVEFORMATEX*>(wave_format_ex_));
176 if (IsEqualGUID(KSDATAFORMAT_SUBTYPE_IEEE_FLOAT, 190 if (IsEqualGUID(KSDATAFORMAT_SUBTYPE_IEEE_FLOAT,
177 wave_format_extensible->SubFormat)) { 191 wave_format_extensible->SubFormat)) {
178 if (!AudioCapturer::IsValidSampleRate( 192 if (!AudioCapturer::IsValidSampleRate(
179 wave_format_extensible->Format.nSamplesPerSec)) { 193 wave_format_extensible->Format.nSamplesPerSec)) {
180 LOG(ERROR) << "Host sampling rate is neither 44.1 kHz nor 48 kHz."; 194 LOG(ERROR) << "Host sampling rate is neither 44.1 kHz nor 48 kHz.";
181 return false; 195 return false;
182 } 196 }
183 sampling_rate_ = static_cast<AudioPacket::SamplingRate>( 197 sampling_rate_ = static_cast<AudioPacket::SamplingRate>(
184 wave_format_extensible->Format.nSamplesPerSec); 198 wave_format_extensible->Format.nSamplesPerSec);
185 199
186 wave_format_extensible->SubFormat = KSDATAFORMAT_SUBTYPE_PCM; 200 wave_format_extensible->SubFormat = KSDATAFORMAT_SUBTYPE_PCM;
187 wave_format_extensible->Samples.wValidBitsPerSample = kBitsPerSample; 201 wave_format_extensible->Samples.wValidBitsPerSample = kBitsPerSample;
188 202
189 wave_format_extensible->Format.nChannels = kChannels; 203 wave_format_extensible->Format.nChannels =
204 ChooseChannels(wave_format_extensible->Format.nChannels);
Sergey Ulanov 2017/05/26 22:24:45 If you change number of channels here then you pro
Hzj_jie 2017/05/28 20:58:59 According to MSDN, https://social.msdn.microsoft.c
Sergey Ulanov 2017/05/30 19:18:19 My point was that, if the API will never downmix t
Hzj_jie 2017/05/31 00:12:08 Got you. I will update both nChannels and dwChanne
Sergey Ulanov 2017/05/31 00:44:43 Is this useful given that we know that windows wil
Hzj_jie 2017/05/31 02:49:28 Trying to initialize in stereo does not really was
Sergey Ulanov 2017/06/05 18:03:19 I don't think it can cause any problems. It's reas
Hzj_jie 2017/06/06 03:21:42 Done.
190 wave_format_extensible->Format.nSamplesPerSec = sampling_rate_; 205 wave_format_extensible->Format.nSamplesPerSec = sampling_rate_;
191 wave_format_extensible->Format.wBitsPerSample = kBitsPerSample; 206 wave_format_extensible->Format.wBitsPerSample = kBitsPerSample;
192 wave_format_extensible->Format.nBlockAlign = 207 wave_format_extensible->Format.nBlockAlign =
193 kChannels * kBytesPerSample; 208 wave_format_extensible->Format.nChannels * kBytesPerSample;
194 wave_format_extensible->Format.nAvgBytesPerSec = 209 wave_format_extensible->Format.nAvgBytesPerSec =
195 sampling_rate_ * kChannels * kBytesPerSample; 210 sampling_rate_ * wave_format_extensible->Format.nChannels *
211 kBytesPerSample;
196 } else { 212 } else {
197 LOG(ERROR) << "Failed to force 16-bit samples"; 213 LOG(ERROR) << "Failed to force 16-bit samples";
198 return false; 214 return false;
199 } 215 }
200 break; 216 break;
201 } 217 }
202 default: 218 default:
203 LOG(ERROR) << "Failed to force 16-bit PCM"; 219 LOG(ERROR) << "Failed to force 16-bit PCM";
204 return false; 220 return false;
205 } 221 }
(...skipping 20 matching lines...) Expand all
226 } 242 }
227 243
228 // Start the IAudioClient. 244 // Start the IAudioClient.
229 hr = audio_client_->Start(); 245 hr = audio_client_->Start();
230 if (FAILED(hr)) { 246 if (FAILED(hr)) {
231 LOG(ERROR) << "Failed to start IAudioClient. Error " << hr; 247 LOG(ERROR) << "Failed to start IAudioClient. Error " << hr;
232 return false; 248 return false;
233 } 249 }
234 250
235 volume_filter_.ActivateBy(mm_device_.Get()); 251 volume_filter_.ActivateBy(mm_device_.Get());
236 volume_filter_.Initialize(sampling_rate_, kChannels); 252 volume_filter_.Initialize(sampling_rate_, wave_format_ex_->nChannels);
237 253
238 return true; 254 return true;
239 } 255 }
240 256
241 bool AudioCapturerWin::is_initialized() const { 257 bool AudioCapturerWin::is_initialized() const {
242 // All Com components should be initialized / deinitialized together. 258 // All Com components should be initialized / deinitialized together.
243 return !!audio_client_; 259 return !!audio_client_;
244 } 260 }
245 261
246 void AudioCapturerWin::DoCapture() { 262 void AudioCapturerWin::DoCapture() {
(...skipping 26 matching lines...) Expand all
273 nullptr); 289 nullptr);
274 if (FAILED(hr)) 290 if (FAILED(hr))
275 break; 291 break;
276 292
277 if (volume_filter_.Apply(reinterpret_cast<int16_t*>(data), frames)) { 293 if (volume_filter_.Apply(reinterpret_cast<int16_t*>(data), frames)) {
278 std::unique_ptr<AudioPacket> packet(new AudioPacket()); 294 std::unique_ptr<AudioPacket> packet(new AudioPacket());
279 packet->add_data(data, frames * wave_format_ex_->nBlockAlign); 295 packet->add_data(data, frames * wave_format_ex_->nBlockAlign);
280 packet->set_encoding(AudioPacket::ENCODING_RAW); 296 packet->set_encoding(AudioPacket::ENCODING_RAW);
281 packet->set_sampling_rate(sampling_rate_); 297 packet->set_sampling_rate(sampling_rate_);
282 packet->set_bytes_per_sample(AudioPacket::BYTES_PER_SAMPLE_2); 298 packet->set_bytes_per_sample(AudioPacket::BYTES_PER_SAMPLE_2);
283 packet->set_channels(AudioPacket::CHANNELS_STEREO); 299 packet->set_channels(static_cast<AudioPacket::Channels>(
300 wave_format_ex_->nChannels));
284 301
285 callback_.Run(std::move(packet)); 302 callback_.Run(std::move(packet));
286 } 303 }
287 304
288 hr = audio_capture_client_->ReleaseBuffer(frames); 305 hr = audio_capture_client_->ReleaseBuffer(frames);
289 if (FAILED(hr)) 306 if (FAILED(hr))
290 break; 307 break;
291 } 308 }
292 309
293 // There is nothing to capture if the audio endpoint device has been unplugged 310 // There is nothing to capture if the audio endpoint device has been unplugged
(...skipping 11 matching lines...) Expand all
305 322
306 bool AudioCapturer::IsSupported() { 323 bool AudioCapturer::IsSupported() {
307 return true; 324 return true;
308 } 325 }
309 326
310 std::unique_ptr<AudioCapturer> AudioCapturer::Create() { 327 std::unique_ptr<AudioCapturer> AudioCapturer::Create() {
311 return base::WrapUnique(new AudioCapturerWin()); 328 return base::WrapUnique(new AudioCapturerWin());
312 } 329 }
313 330
314 } // namespace remoting 331 } // namespace remoting
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698