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

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

Issue 2903153004: [Chromoting] Implement down mixing in AudioPump (Closed)
Patch Set: Resolve review comments Created 3 years, 6 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
« no previous file with comments | « remoting/host/audio_capturer_win.h ('k') | remoting/proto/audio.proto » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 // Chooses a similar and supported channel configuration. |channels| represents
43 // the selected channels. It can be nullptr.
44 void ChooseChannels(WORD* channel_count, DWORD* channels) {
45 // We supports mono to 7.1.
46 if (*channel_count >= 1 && *channel_count <= 8) {
47 return;
48 }
49
50 *channel_count = remoting::AudioPacket::CHANNELS_STEREO;
51 if (channels) {
52 *channels = SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT;
53 }
54 }
55
42 } // namespace 56 } // namespace
43 57
44 namespace remoting { 58 namespace remoting {
45 59
46 AudioCapturerWin::AudioCapturerWin() 60 AudioCapturerWin::AudioCapturerWin()
47 : sampling_rate_(AudioPacket::SAMPLING_RATE_INVALID), 61 : sampling_rate_(AudioPacket::SAMPLING_RATE_INVALID),
48 volume_filter_(kSilenceThreshold), 62 volume_filter_(kSilenceThreshold),
49 last_capture_error_(S_OK) { 63 last_capture_error_(S_OK) {
50 thread_checker_.DetachFromThread(); 64 thread_checker_.DetachFromThread();
51 } 65 }
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after
156 // Intentional fall-through. 170 // Intentional fall-through.
157 case WAVE_FORMAT_PCM: 171 case WAVE_FORMAT_PCM:
158 if (!AudioCapturer::IsValidSampleRate(wave_format_ex_->nSamplesPerSec)) { 172 if (!AudioCapturer::IsValidSampleRate(wave_format_ex_->nSamplesPerSec)) {
159 LOG(ERROR) << "Host sampling rate is neither 44.1 kHz nor 48 kHz."; 173 LOG(ERROR) << "Host sampling rate is neither 44.1 kHz nor 48 kHz.";
160 return false; 174 return false;
161 } 175 }
162 sampling_rate_ = static_cast<AudioPacket::SamplingRate>( 176 sampling_rate_ = static_cast<AudioPacket::SamplingRate>(
163 wave_format_ex_->nSamplesPerSec); 177 wave_format_ex_->nSamplesPerSec);
164 178
165 wave_format_ex_->wFormatTag = WAVE_FORMAT_PCM; 179 wave_format_ex_->wFormatTag = WAVE_FORMAT_PCM;
166 wave_format_ex_->nChannels = kChannels; 180 ChooseChannels(&wave_format_ex_->nChannels, nullptr);
167 wave_format_ex_->wBitsPerSample = kBitsPerSample; 181 wave_format_ex_->wBitsPerSample = kBitsPerSample;
168 wave_format_ex_->nBlockAlign = kChannels * kBytesPerSample; 182 wave_format_ex_->nBlockAlign =
183 wave_format_ex_->nChannels * kBytesPerSample;
169 wave_format_ex_->nAvgBytesPerSec = 184 wave_format_ex_->nAvgBytesPerSec =
170 sampling_rate_ * kChannels * kBytesPerSample; 185 sampling_rate_ * wave_format_ex_->nChannels * kBytesPerSample;
171 break; 186 break;
172 case WAVE_FORMAT_EXTENSIBLE: { 187 case WAVE_FORMAT_EXTENSIBLE: {
173 PWAVEFORMATEXTENSIBLE wave_format_extensible = 188 PWAVEFORMATEXTENSIBLE wave_format_extensible =
174 reinterpret_cast<WAVEFORMATEXTENSIBLE*>( 189 reinterpret_cast<WAVEFORMATEXTENSIBLE*>(
175 static_cast<WAVEFORMATEX*>(wave_format_ex_)); 190 static_cast<WAVEFORMATEX*>(wave_format_ex_));
176 if (IsEqualGUID(KSDATAFORMAT_SUBTYPE_IEEE_FLOAT, 191 if (IsEqualGUID(KSDATAFORMAT_SUBTYPE_IEEE_FLOAT,
177 wave_format_extensible->SubFormat)) { 192 wave_format_extensible->SubFormat)) {
178 if (!AudioCapturer::IsValidSampleRate( 193 if (!AudioCapturer::IsValidSampleRate(
179 wave_format_extensible->Format.nSamplesPerSec)) { 194 wave_format_extensible->Format.nSamplesPerSec)) {
180 LOG(ERROR) << "Host sampling rate is neither 44.1 kHz nor 48 kHz."; 195 LOG(ERROR) << "Host sampling rate is neither 44.1 kHz nor 48 kHz.";
181 return false; 196 return false;
182 } 197 }
183 sampling_rate_ = static_cast<AudioPacket::SamplingRate>( 198 sampling_rate_ = static_cast<AudioPacket::SamplingRate>(
184 wave_format_extensible->Format.nSamplesPerSec); 199 wave_format_extensible->Format.nSamplesPerSec);
185 200
186 wave_format_extensible->SubFormat = KSDATAFORMAT_SUBTYPE_PCM; 201 wave_format_extensible->SubFormat = KSDATAFORMAT_SUBTYPE_PCM;
187 wave_format_extensible->Samples.wValidBitsPerSample = kBitsPerSample; 202 wave_format_extensible->Samples.wValidBitsPerSample = kBitsPerSample;
188 203
189 wave_format_extensible->Format.nChannels = kChannels; 204 ChooseChannels(&wave_format_extensible->Format.nChannels,
205 &wave_format_extensible->dwChannelMask);
190 wave_format_extensible->Format.nSamplesPerSec = sampling_rate_; 206 wave_format_extensible->Format.nSamplesPerSec = sampling_rate_;
191 wave_format_extensible->Format.wBitsPerSample = kBitsPerSample; 207 wave_format_extensible->Format.wBitsPerSample = kBitsPerSample;
192 wave_format_extensible->Format.nBlockAlign = 208 wave_format_extensible->Format.nBlockAlign =
193 kChannels * kBytesPerSample; 209 wave_format_extensible->Format.nChannels * kBytesPerSample;
194 wave_format_extensible->Format.nAvgBytesPerSec = 210 wave_format_extensible->Format.nAvgBytesPerSec =
195 sampling_rate_ * kChannels * kBytesPerSample; 211 sampling_rate_ * wave_format_extensible->Format.nChannels *
212 kBytesPerSample;
196 } else { 213 } else {
197 LOG(ERROR) << "Failed to force 16-bit samples"; 214 LOG(ERROR) << "Failed to force 16-bit samples";
198 return false; 215 return false;
199 } 216 }
200 break; 217 break;
201 } 218 }
202 default: 219 default:
203 LOG(ERROR) << "Failed to force 16-bit PCM"; 220 LOG(ERROR) << "Failed to force 16-bit PCM";
204 return false; 221 return false;
205 } 222 }
(...skipping 20 matching lines...) Expand all
226 } 243 }
227 244
228 // Start the IAudioClient. 245 // Start the IAudioClient.
229 hr = audio_client_->Start(); 246 hr = audio_client_->Start();
230 if (FAILED(hr)) { 247 if (FAILED(hr)) {
231 LOG(ERROR) << "Failed to start IAudioClient. Error " << hr; 248 LOG(ERROR) << "Failed to start IAudioClient. Error " << hr;
232 return false; 249 return false;
233 } 250 }
234 251
235 volume_filter_.ActivateBy(mm_device_.Get()); 252 volume_filter_.ActivateBy(mm_device_.Get());
236 volume_filter_.Initialize(sampling_rate_, kChannels); 253 volume_filter_.Initialize(sampling_rate_, wave_format_ex_->nChannels);
237 254
238 return true; 255 return true;
239 } 256 }
240 257
241 bool AudioCapturerWin::is_initialized() const { 258 bool AudioCapturerWin::is_initialized() const {
242 // All Com components should be initialized / deinitialized together. 259 // All Com components should be initialized / deinitialized together.
243 return !!audio_client_; 260 return !!audio_client_;
244 } 261 }
245 262
246 void AudioCapturerWin::DoCapture() { 263 void AudioCapturerWin::DoCapture() {
(...skipping 26 matching lines...) Expand all
273 nullptr); 290 nullptr);
274 if (FAILED(hr)) 291 if (FAILED(hr))
275 break; 292 break;
276 293
277 if (volume_filter_.Apply(reinterpret_cast<int16_t*>(data), frames)) { 294 if (volume_filter_.Apply(reinterpret_cast<int16_t*>(data), frames)) {
278 std::unique_ptr<AudioPacket> packet(new AudioPacket()); 295 std::unique_ptr<AudioPacket> packet(new AudioPacket());
279 packet->add_data(data, frames * wave_format_ex_->nBlockAlign); 296 packet->add_data(data, frames * wave_format_ex_->nBlockAlign);
280 packet->set_encoding(AudioPacket::ENCODING_RAW); 297 packet->set_encoding(AudioPacket::ENCODING_RAW);
281 packet->set_sampling_rate(sampling_rate_); 298 packet->set_sampling_rate(sampling_rate_);
282 packet->set_bytes_per_sample(AudioPacket::BYTES_PER_SAMPLE_2); 299 packet->set_bytes_per_sample(AudioPacket::BYTES_PER_SAMPLE_2);
283 packet->set_channels(AudioPacket::CHANNELS_STEREO); 300 packet->set_channels(static_cast<AudioPacket::Channels>(
Sergey Ulanov 2017/06/05 18:03:19 I think this would be the right place to add a com
Hzj_jie 2017/06/06 03:21:43 Done.
301 wave_format_ex_->nChannels));
284 302
285 callback_.Run(std::move(packet)); 303 callback_.Run(std::move(packet));
286 } 304 }
287 305
288 hr = audio_capture_client_->ReleaseBuffer(frames); 306 hr = audio_capture_client_->ReleaseBuffer(frames);
289 if (FAILED(hr)) 307 if (FAILED(hr))
290 break; 308 break;
291 } 309 }
292 310
293 // There is nothing to capture if the audio endpoint device has been unplugged 311 // There is nothing to capture if the audio endpoint device has been unplugged
(...skipping 11 matching lines...) Expand all
305 323
306 bool AudioCapturer::IsSupported() { 324 bool AudioCapturer::IsSupported() {
307 return true; 325 return true;
308 } 326 }
309 327
310 std::unique_ptr<AudioCapturer> AudioCapturer::Create() { 328 std::unique_ptr<AudioCapturer> AudioCapturer::Create() {
311 return base::WrapUnique(new AudioCapturerWin()); 329 return base::WrapUnique(new AudioCapturerWin());
312 } 330 }
313 331
314 } // namespace remoting 332 } // namespace remoting
OLDNEW
« no previous file with comments | « remoting/host/audio_capturer_win.h ('k') | remoting/proto/audio.proto » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698