diff options
author | zijiehe <zijiehe@chromium.org> | 2016-03-10 12:49:24 -0800 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2016-03-10 20:50:46 +0000 |
commit | 3ba26c009b0b2583562b695c426391f71b626f33 (patch) | |
tree | 7e29b9337dfac028031ed88df4465e9124d0807a /remoting | |
parent | c0cecb3e3d9551c8a80937fc9a37c94712d40275 (diff) | |
download | chromium_src-3ba26c009b0b2583562b695c426391f71b626f33.zip chromium_src-3ba26c009b0b2583562b695c426391f71b626f33.tar.gz chromium_src-3ba26c009b0b2583562b695c426391f71b626f33.tar.bz2 |
Add volume control for windows host
BUG=276753
Review URL: https://codereview.chromium.org/1753663002
Cr-Commit-Position: refs/heads/master@{#380458}
Diffstat (limited to 'remoting')
-rw-r--r-- | remoting/host/audio_capturer_win.cc | 87 | ||||
-rw-r--r-- | remoting/host/audio_capturer_win.h | 11 |
2 files changed, 86 insertions, 12 deletions
diff --git a/remoting/host/audio_capturer_win.cc b/remoting/host/audio_capturer_win.cc index 8c90113..86fd959 100644 --- a/remoting/host/audio_capturer_win.cc +++ b/remoting/host/audio_capturer_win.cc @@ -54,6 +54,7 @@ bool AudioCapturerWin::Start(const PacketCapturedCallback& callback) { DCHECK(!audio_capture_client_.get()); DCHECK(!audio_client_.get()); DCHECK(!mm_device_.get()); + DCHECK(!audio_volume_.get()); DCHECK(static_cast<PWAVEFORMATEX>(wave_format_ex_) == nullptr); DCHECK(thread_checker_.CalledOnValidThread()); @@ -193,6 +194,15 @@ bool AudioCapturerWin::Start(const PacketCapturedCallback& callback) { return false; } + // Initialize ISimpleAudioVolume. + // TODO(zijiehe): Do we need to control per process volume? + hr = audio_client_->GetService(__uuidof(ISimpleAudioVolume), + audio_volume_.ReceiveVoid()); + if (FAILED(hr)) { + LOG(ERROR) << "Failed to get an ISimpleAudioVolume. Error " << hr; + return false; + } + silence_detector_.Reset(sampling_rate_, kChannels); // Start capturing. @@ -203,6 +213,70 @@ bool AudioCapturerWin::Start(const PacketCapturedCallback& callback) { return true; } +float AudioCapturerWin::GetAudioLevel() { + BOOL mute; + HRESULT hr = audio_volume_->GetMute(&mute); + if (FAILED(hr)) { + return 1; + } + if (mute) { + return 0; + } + + float level; + hr = audio_volume_->GetMasterVolume(&level); + if (FAILED(hr) || level > 1) { + return 1; + } + if (level < 0) { + return 0; + } + return level; +} + +void AudioCapturerWin::ProcessSamples(uint8_t* data, + size_t frames, + int32_t flags) { + if (frames == 0) { + return; + } + + if ((flags & AUDCLNT_BUFFERFLAGS_SILENT) == 0) { + return; + } + + int16_t* samples = reinterpret_cast<int16_t*>(data); + static_assert(sizeof(samples[0]) == kBytesPerSample, + "expect 16 bits per sample"); + size_t sample_count = frames * kChannels; + if (silence_detector_.IsSilence(samples, sample_count)) { + return; + } + + float level = GetAudioLevel(); + if (level == 0) { + return; + } + + if (level < 1) { + // Windows API does not provide volume adjusted audio sample as Linux does. + // So we need to manually append volume signal to the samples. + int32_t level_int = static_cast<int32_t>(level * 65536); + for (size_t i = 0; i < sample_count; i++) { + samples[i] = (static_cast<int32_t>(samples[i]) * level_int) >> 16; + } + } + + scoped_ptr<AudioPacket> packet(new AudioPacket()); + packet->add_data(data, frames * wave_format_ex_->nBlockAlign); + packet->set_encoding(AudioPacket::ENCODING_RAW); + packet->set_sampling_rate(sampling_rate_); + packet->set_bytes_per_sample(AudioPacket::BYTES_PER_SAMPLE_2); + packet->set_channels(AudioPacket::CHANNELS_STEREO); + + callback_.Run(std::move(packet)); +} + void AudioCapturerWin::DoCapture() { DCHECK(AudioCapturer::IsValidSampleRate(sampling_rate_)); DCHECK(thread_checker_.CalledOnValidThread()); @@ -227,18 +301,7 @@ void AudioCapturerWin::DoCapture() { if (FAILED(hr)) break; - if ((flags & AUDCLNT_BUFFERFLAGS_SILENT) == 0 && - !silence_detector_.IsSilence(reinterpret_cast<const int16_t*>(data), - frames * kChannels)) { - scoped_ptr<AudioPacket> packet(new AudioPacket()); - packet->add_data(data, frames * wave_format_ex_->nBlockAlign); - packet->set_encoding(AudioPacket::ENCODING_RAW); - packet->set_sampling_rate(sampling_rate_); - packet->set_bytes_per_sample(AudioPacket::BYTES_PER_SAMPLE_2); - packet->set_channels(AudioPacket::CHANNELS_STEREO); - - callback_.Run(std::move(packet)); - } + ProcessSamples(data, frames, flags); hr = audio_capture_client_->ReleaseBuffer(frames); if (FAILED(hr)) diff --git a/remoting/host/audio_capturer_win.h b/remoting/host/audio_capturer_win.h index de3c7953..11070be 100644 --- a/remoting/host/audio_capturer_win.h +++ b/remoting/host/audio_capturer_win.h @@ -33,6 +33,16 @@ class AudioCapturerWin : public AudioCapturer { // to the network. void DoCapture(); + // Returns current volume setting of the host, in range [0.0, 1.0]. If the + // audio has been muted, this function returns 0. If Windows API returns error + // (such as audio device has been disabled or unpluged), this function ignores + // host volume setting, and returns 1.0. + float GetAudioLevel(); + + // Processes a series of samples, and executes callback if the packet is + // qualified to be sent to client. + void ProcessSamples(uint8_t* data, size_t frames, int32_t flags); + PacketCapturedCallback callback_; AudioPacket::SamplingRate sampling_rate_; @@ -46,6 +56,7 @@ class AudioCapturerWin : public AudioCapturer { base::win::ScopedComPtr<IAudioCaptureClient> audio_capture_client_; base::win::ScopedComPtr<IAudioClient> audio_client_; base::win::ScopedComPtr<IMMDevice> mm_device_; + base::win::ScopedComPtr<ISimpleAudioVolume> audio_volume_; HRESULT last_capture_error_; |