diff options
author | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2018-12-10 16:19:40 +0100 |
---|---|---|
committer | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2018-12-10 16:01:50 +0000 |
commit | 51f6c2793adab2d864b3d2b360000ef8db1d3e92 (patch) | |
tree | 835b3b4446b012c75e80177cef9fbe6972cc7dbe /chromium/media/audio | |
parent | 6036726eb981b6c4b42047513b9d3f4ac865daac (diff) | |
download | qtwebengine-chromium-51f6c2793adab2d864b3d2b360000ef8db1d3e92.tar.gz |
BASELINE: Update Chromium to 71.0.3578.93
Change-Id: I6a32086c33670e1b033f8b10e6bf1fd4da1d105d
Reviewed-by: Alexandru Croitor <alexandru.croitor@qt.io>
Diffstat (limited to 'chromium/media/audio')
38 files changed, 368 insertions, 1061 deletions
diff --git a/chromium/media/audio/BUILD.gn b/chromium/media/audio/BUILD.gn index 6b7eccaf55c..38e7bb1d7f4 100644 --- a/chromium/media/audio/BUILD.gn +++ b/chromium/media/audio/BUILD.gn @@ -231,13 +231,9 @@ source_set("audio") { ] libs += [ - "dmoguids.lib", "dxguid.lib", - "msdmo.lib", "setupapi.lib", - "strmiids.lib", "winmm.lib", - "wmcodecdspuuid.lib", ] } @@ -323,7 +319,7 @@ source_set("audio") { "fuchsia/audio_output_stream_fuchsia.cc", "fuchsia/audio_output_stream_fuchsia.h", ] - deps += [ "//third_party/fuchsia-sdk:media" ] + deps += [ "//third_party/fuchsia-sdk/sdk:media" ] } configs += [ "//build/config/compiler:no_size_t_to_int_warning" ] diff --git a/chromium/media/audio/audio_features.cc b/chromium/media/audio/audio_features.cc index f5b297bf195..7bcb922fbff 100644 --- a/chromium/media/audio/audio_features.cc +++ b/chromium/media/audio/audio_features.cc @@ -11,6 +11,8 @@ namespace features { // Default disabled (crbug.com/554168). const base::Feature kEnumerateAudioDevices{"EnumerateAudioDevices", base::FEATURE_ENABLED_BY_DEFAULT}; +const base::Feature kCrOSSystemAEC{"CrOSSystemAEC", + base::FEATURE_ENABLED_BY_DEFAULT}; #endif #if defined(OS_WIN) diff --git a/chromium/media/audio/audio_features.h b/chromium/media/audio/audio_features.h index ae3c12d4161..4995e46e21d 100644 --- a/chromium/media/audio/audio_features.h +++ b/chromium/media/audio/audio_features.h @@ -13,6 +13,7 @@ namespace features { #if defined(OS_CHROMEOS) MEDIA_EXPORT extern const base::Feature kEnumerateAudioDevices; +MEDIA_EXPORT extern const base::Feature kCrOSSystemAEC; #endif #if defined(OS_WIN) diff --git a/chromium/media/audio/audio_manager.cc b/chromium/media/audio/audio_manager.cc index ee635709921..d016814a65a 100644 --- a/chromium/media/audio/audio_manager.cc +++ b/chromium/media/audio/audio_manager.cc @@ -71,8 +71,8 @@ class AudioManagerHelper : public base::PowerObserver { base::Bind(&AudioManagerHelper::UpdateLastAudioThreadTimeTick, base::Unretained(this))); monitor_task_runner_->PostTask( - FROM_HERE, base::Bind(&AudioManagerHelper::RecordAudioThreadStatus, - base::Unretained(this))); + FROM_HERE, base::BindOnce(&AudioManagerHelper::RecordAudioThreadStatus, + base::Unretained(this))); } bool IsAudioThreadHung() { @@ -130,8 +130,9 @@ class AudioManagerHelper : public base::PowerObserver { base::AutoUnlock unlock(hang_lock_); monitor_task_runner_->PostTask( - FROM_HERE, base::Bind(&AudioManagerHelper::RecordAudioThreadStatus, - base::Unretained(this))); + FROM_HERE, + base::BindOnce(&AudioManagerHelper::RecordAudioThreadStatus, + base::Unretained(this))); } } @@ -172,8 +173,9 @@ class AudioManagerHelper : public base::PowerObserver { // Don't hold the lock while posting the next task. monitor_task_runner_->PostDelayedTask( - FROM_HERE, base::Bind(&AudioManagerHelper::RecordAudioThreadStatus, - base::Unretained(this)), + FROM_HERE, + base::BindOnce(&AudioManagerHelper::RecordAudioThreadStatus, + base::Unretained(this)), max_hung_task_time_); } @@ -342,8 +344,8 @@ bool AudioManager::Shutdown() { ShutdownOnAudioThread(); } else { audio_thread_->GetTaskRunner()->PostTask( - FROM_HERE, base::Bind(&AudioManager::ShutdownOnAudioThread, - base::Unretained(this))); + FROM_HERE, base::BindOnce(&AudioManager::ShutdownOnAudioThread, + base::Unretained(this))); } audio_thread_->Stop(); shutdown_ = true; diff --git a/chromium/media/audio/audio_manager_base.cc b/chromium/media/audio/audio_manager_base.cc index bf77eef9114..44f7667d1fb 100644 --- a/chromium/media/audio/audio_manager_base.cc +++ b/chromium/media/audio/audio_manager_base.cc @@ -583,8 +583,8 @@ void AudioManagerBase::InitializeDebugRecording() { // AudioManager is deleted on the audio thread, so it's safe to post // unretained. GetTaskRunner()->PostTask( - FROM_HERE, base::Bind(&AudioManagerBase::InitializeDebugRecording, - base::Unretained(this))); + FROM_HERE, base::BindOnce(&AudioManagerBase::InitializeDebugRecording, + base::Unretained(this))); return; } diff --git a/chromium/media/audio/audio_manager_unittest.cc b/chromium/media/audio/audio_manager_unittest.cc index 9cfbb127f2c..6271c1fb890 100644 --- a/chromium/media/audio/audio_manager_unittest.cc +++ b/chromium/media/audio/audio_manager_unittest.cc @@ -10,6 +10,7 @@ #include <vector> #include "base/bind.h" +#include "base/command_line.h" #include "base/environment.h" #include "base/logging.h" #include "base/run_loop.h" @@ -17,6 +18,7 @@ #include "base/strings/string_number_conversions.h" #include "base/strings/string_util.h" #include "base/synchronization/waitable_event.h" +#include "base/sys_info.h" #include "base/test/test_message_loop.h" #include "base/threading/thread_task_runner_handle.h" #include "build/build_config.h" @@ -54,6 +56,7 @@ #if defined(USE_CRAS) #include "chromeos/audio/audio_devices_pref_handler_stub.h" #include "chromeos/audio/cras_audio_handler.h" +#include "chromeos/dbus/dbus_switches.h" #include "chromeos/dbus/dbus_thread_manager.h" #include "chromeos/dbus/fake_cras_audio_client.h" #include "media/audio/cras/audio_manager_cras.h" @@ -264,6 +267,12 @@ class AudioManagerTest : public ::testing::Test { } void SetUpCrasAudioHandlerWithTestingNodes(const AudioNodeList& audio_nodes) { + if (base::SysInfo::IsRunningOnChromeOS()) { + // Ensure a FakeCrasAudioClient is created, even on a real device or VM. + base::CommandLine::ForCurrentProcess()->AppendSwitch( + chromeos::switches::kDbusStub); + } + chromeos::DBusThreadManager::Initialize(); audio_client_ = static_cast<chromeos::FakeCrasAudioClient*>( chromeos::DBusThreadManager::Get()->GetCrasAudioClient()); @@ -285,7 +294,7 @@ class AudioManagerTest : public ::testing::Test { const AudioDeviceDescriptions& device_descriptions) { DVLOG(2) << "Got " << device_descriptions.size() << " audio devices."; if (!device_descriptions.empty()) { - AudioDeviceDescriptions::const_iterator it = device_descriptions.begin(); + auto it = device_descriptions.begin(); // The first device in the list should always be the default device. EXPECT_EQ(std::string(AudioDeviceDescription::kDefaultDeviceId), diff --git a/chromium/media/audio/audio_output_controller.cc b/chromium/media/audio/audio_output_controller.cc index e017324bdce..508c57133e8 100644 --- a/chromium/media/audio/audio_output_controller.cc +++ b/chromium/media/audio/audio_output_controller.cc @@ -96,6 +96,7 @@ AudioOutputController::AudioOutputController( params_(params), handler_(handler), task_runner_(audio_manager->GetTaskRunner()), + construction_time_(base::TimeTicks::Now()), output_device_id_(output_device_id), stream_(NULL), diverting_to_stream_(NULL), @@ -118,6 +119,8 @@ AudioOutputController::~AudioOutputController() { CHECK_EQ(kClosed, state_); CHECK_EQ(nullptr, stream_); CHECK(duplication_targets_.empty()); + UMA_HISTOGRAM_LONG_TIMES("Media.AudioOutputController.LifeTime", + base::TimeTicks::Now() - construction_time_); } // static @@ -579,10 +582,7 @@ void AudioOutputController::DoStartDiverting(AudioOutputStream* to_stream) { DCHECK(!diverting_to_stream_); diverting_to_stream_ = to_stream; - // Note: OnDeviceChange() will engage the "re-create" process, which will - // detect and use the alternate AudioOutputStream rather than create a new one - // via AudioManager. - OnDeviceChange(); + DoStartOrStopDivertingInternal(); } void AudioOutputController::DoStopDiverting() { @@ -591,13 +591,43 @@ void AudioOutputController::DoStopDiverting() { if (state_ == kClosed) return; - // Note: OnDeviceChange() will cause the existing stream (the consumer of the - // diverted audio data) to be closed, and diverting_to_stream_ will be set - // back to NULL. - OnDeviceChange(); + DoStartOrStopDivertingInternal(); DCHECK(!diverting_to_stream_); } +void AudioOutputController::DoStartOrStopDivertingInternal() { + TRACE_EVENT0("audio", + "AudioOutputController::DoStartOrStopDivertingInternal"); + + handler_->OnLog(base::StringPrintf( + "AOC::DoStartOrStopDivertingInternal() will %s diverting", + (stream_ == diverting_to_stream_) ? "stop" : "start")); + + // Re-create the stream: First, shut down an existing stream (if any), then + // attempt to open either: a) the |diverting_to_stream_|, or b) a normal + // stream from the AudioManager. If that fails, error-out the controller. + // Otherwise, set the volume and restore playback if the prior stream was + // playing. + const bool restore_playback = (state_ == kPlaying); + DoStopCloseAndClearStream(); // Calls RemoveOutputDeviceChangeListener(). + DCHECK_EQ(kEmpty, state_); + stream_ = diverting_to_stream_ ? diverting_to_stream_ + : audio_manager_->MakeAudioOutputStreamProxy( + params_, output_device_id_); + if (!stream_ || !stream_->Open()) { + DoStopCloseAndClearStream(); + state_ = kError; + handler_->OnControllerError(); + return; + } + if (stream_ != diverting_to_stream_) + audio_manager_->AddOutputDeviceChangeListener(this); + stream_->SetVolume(volume_); + state_ = kCreated; + if (restore_playback) + DoPlay(); +} + void AudioOutputController::DoStartDuplicating(AudioPushSink* to_stream) { DCHECK(task_runner_->BelongsToCurrentThread()); if (state_ == kClosed) diff --git a/chromium/media/audio/audio_output_controller.h b/chromium/media/audio/audio_output_controller.h index 8c8afe5f335..b3721f17ec7 100644 --- a/chromium/media/audio/audio_output_controller.h +++ b/chromium/media/audio/audio_output_controller.h @@ -260,6 +260,11 @@ class MEDIA_EXPORT AudioOutputController // Helper method that stops, closes, and NULLs |*stream_|. void DoStopCloseAndClearStream(); + // Equivalent to OnDeviceChange(), but without any UMA events recorded. This + // is necessary for proper apples-to-apples comparison with the new Audio + // Service code paths. http://crbug.com/866455 + void DoStartOrStopDivertingInternal(); + // Send audio data to each duplication target. void BroadcastDataToDuplicationTargets(std::unique_ptr<AudioBus> audio_bus, base::TimeTicks reference_time); @@ -276,6 +281,10 @@ class MEDIA_EXPORT AudioOutputController // The message loop of audio manager thread that this object runs on. const scoped_refptr<base::SingleThreadTaskRunner> task_runner_; + // Time when the controller is constructed. Used to record its lifetime on + // destruction. + const base::TimeTicks construction_time_; + // Specifies the device id of the output device to open or empty for the // default output device. std::string output_device_id_; diff --git a/chromium/media/audio/audio_output_dispatcher_impl.cc b/chromium/media/audio/audio_output_dispatcher_impl.cc index c955993370c..932be8196d7 100644 --- a/chromium/media/audio/audio_output_dispatcher_impl.cc +++ b/chromium/media/audio/audio_output_dispatcher_impl.cc @@ -101,7 +101,7 @@ bool AudioOutputDispatcherImpl::StartStream( void AudioOutputDispatcherImpl::StopStream(AudioOutputProxy* stream_proxy) { DCHECK(audio_manager()->GetTaskRunner()->BelongsToCurrentThread()); - AudioStreamMap::iterator it = proxy_to_physical_map_.find(stream_proxy); + auto it = proxy_to_physical_map_.find(stream_proxy); DCHECK(it != proxy_to_physical_map_.end()); StopPhysicalStream(it->second); proxy_to_physical_map_.erase(it); @@ -111,7 +111,7 @@ void AudioOutputDispatcherImpl::StopStream(AudioOutputProxy* stream_proxy) { void AudioOutputDispatcherImpl::StreamVolumeSet(AudioOutputProxy* stream_proxy, double volume) { DCHECK(audio_manager()->GetTaskRunner()->BelongsToCurrentThread()); - AudioStreamMap::iterator it = proxy_to_physical_map_.find(stream_proxy); + auto it = proxy_to_physical_map_.find(stream_proxy); if (it != proxy_to_physical_map_.end()) { AudioOutputStream* physical_stream = it->second; physical_stream->SetVolume(volume); diff --git a/chromium/media/audio/audio_output_resampler.cc b/chromium/media/audio/audio_output_resampler.cc index 5c0f5f447c9..67aa3b75b13 100644 --- a/chromium/media/audio/audio_output_resampler.cc +++ b/chromium/media/audio/audio_output_resampler.cc @@ -106,9 +106,8 @@ static void RecordStats(const AudioParameters& output_params) { UMA_HISTOGRAM_ENUMERATION( "Media.HardwareAudioSamplesPerSecond", asr, kAudioSampleRateMax + 1); } else { - UMA_HISTOGRAM_COUNTS( - "Media.HardwareAudioSamplesPerSecondUnexpected", - output_params.sample_rate()); + UMA_HISTOGRAM_COUNTS_1M("Media.HardwareAudioSamplesPerSecondUnexpected", + output_params.sample_rate()); } } @@ -128,7 +127,7 @@ static void RecordFallbackStats(const AudioParameters& output_params) { "Media.FallbackHardwareAudioSamplesPerSecond", asr, kAudioSampleRateMax + 1); } else { - UMA_HISTOGRAM_COUNTS( + UMA_HISTOGRAM_COUNTS_1M( "Media.FallbackHardwareAudioSamplesPerSecondUnexpected", output_params.sample_rate()); } @@ -410,7 +409,7 @@ bool AudioOutputResampler::StartStream( DCHECK(dispatcher_); OnMoreDataConverter* resampler_callback = nullptr; - CallbackMap::iterator it = callbacks_.find(stream_proxy); + auto it = callbacks_.find(stream_proxy); if (it == callbacks_.end()) { // If a register callback has been given, register and pass the returned // recoder to the converter. Data is fed to same recorder for the lifetime @@ -441,7 +440,7 @@ void AudioOutputResampler::StreamVolumeSet(AudioOutputProxy* stream_proxy, void AudioOutputResampler::StopStream(AudioOutputProxy* stream_proxy) { DCHECK(audio_manager()->GetTaskRunner()->BelongsToCurrentThread()); - CallbackMap::iterator it = callbacks_.find(stream_proxy); + auto it = callbacks_.find(stream_proxy); DCHECK(it != callbacks_.end()); StopStreamInternal(*it); } diff --git a/chromium/media/audio/audio_output_stream_sink.cc b/chromium/media/audio/audio_output_stream_sink.cc index b6d8eddea08..2ff001236cf 100644 --- a/chromium/media/audio/audio_output_stream_sink.cc +++ b/chromium/media/audio/audio_output_stream_sink.cc @@ -43,20 +43,21 @@ void AudioOutputStreamSink::Start() { } started_ = true; audio_task_runner_->PostTask( - FROM_HERE, base::Bind(&AudioOutputStreamSink::DoStart, this, params_)); + FROM_HERE, + base::BindOnce(&AudioOutputStreamSink::DoStart, this, params_)); } void AudioOutputStreamSink::Stop() { ClearCallback(); started_ = false; audio_task_runner_->PostTask( - FROM_HERE, base::Bind(&AudioOutputStreamSink::DoStop, this)); + FROM_HERE, base::BindOnce(&AudioOutputStreamSink::DoStop, this)); } void AudioOutputStreamSink::Pause() { ClearCallback(); audio_task_runner_->PostTask( - FROM_HERE, base::Bind(&AudioOutputStreamSink::DoPause, this)); + FROM_HERE, base::BindOnce(&AudioOutputStreamSink::DoPause, this)); } void AudioOutputStreamSink::Play() { @@ -65,12 +66,13 @@ void AudioOutputStreamSink::Play() { active_render_callback_ = render_callback_; } audio_task_runner_->PostTask( - FROM_HERE, base::Bind(&AudioOutputStreamSink::DoPlay, this)); + FROM_HERE, base::BindOnce(&AudioOutputStreamSink::DoPlay, this)); } bool AudioOutputStreamSink::SetVolume(double volume) { audio_task_runner_->PostTask( - FROM_HERE, base::Bind(&AudioOutputStreamSink::DoSetVolume, this, volume)); + FROM_HERE, + base::BindOnce(&AudioOutputStreamSink::DoSetVolume, this, volume)); return true; } diff --git a/chromium/media/audio/cras/audio_manager_cras.cc b/chromium/media/audio/cras/audio_manager_cras.cc index e84164d9748..eedca3280f1 100644 --- a/chromium/media/audio/cras/audio_manager_cras.cc +++ b/chromium/media/audio/cras/audio_manager_cras.cc @@ -186,9 +186,14 @@ AudioParameters AudioManagerCras::GetInputStreamParameters( if (HasKeyboardMic(devices)) params.set_effects(AudioParameters::KEYBOARD_MIC); - if (GetSystemAecSupportedPerBoard()) - params.set_effects(params.effects() | - AudioParameters::EXPERIMENTAL_ECHO_CANCELLER); + // Allow experimentation with system echo cancellation with all devices, + // but enable it by default on devices that actually support it. + params.set_effects(params.effects() | + AudioParameters::EXPERIMENTAL_ECHO_CANCELLER); + if (base::FeatureList::IsEnabled(features::kCrOSSystemAEC) && + GetSystemAecSupportedPerBoard()) { + params.set_effects(params.effects() | AudioParameters::ECHO_CANCELLER); + } return params; } diff --git a/chromium/media/audio/fuchsia/audio_output_stream_fuchsia.cc b/chromium/media/audio/fuchsia/audio_output_stream_fuchsia.cc index 63d7cd25ca6..db239da750d 100644 --- a/chromium/media/audio/fuchsia/audio_output_stream_fuchsia.cc +++ b/chromium/media/audio/fuchsia/audio_output_stream_fuchsia.cc @@ -13,9 +13,9 @@ namespace media { -// Current AudioOut implementation allows only one buffer with id=0. +// Current AudioRenderer implementation allows only one buffer with id=0. // TODO(sergeyu): Replace with an incrementing buffer id once AddPayloadBuffer() -// and RemovePayloadBuffer() are implemented properly in AudioOut. +// and RemovePayloadBuffer() are implemented properly in AudioRenderer. const uint32_t kBufferId = 0; AudioOutputStreamFuchsia::AudioOutputStreamFuchsia( @@ -27,36 +27,36 @@ AudioOutputStreamFuchsia::AudioOutputStreamFuchsia( AudioOutputStreamFuchsia::~AudioOutputStreamFuchsia() { // Close() must be called first. - DCHECK(!audio_out_); + DCHECK(!audio_renderer_); } bool AudioOutputStreamFuchsia::Open() { - DCHECK(!audio_out_); + DCHECK(!audio_renderer_); - // Connect |audio_out_| to the audio service. + // Connect |audio_renderer_| to the audio service. fuchsia::media::AudioPtr audio_server = base::fuchsia::ComponentContext::GetDefault() ->ConnectToService<fuchsia::media::Audio>(); - audio_server->CreateAudioOut(audio_out_.NewRequest()); - audio_out_.set_error_handler( + audio_server->CreateAudioRenderer(audio_renderer_.NewRequest()); + audio_renderer_.set_error_handler( fit::bind_member(this, &AudioOutputStreamFuchsia::OnRendererError)); - // Inform the |audio_out_| of the format required by the caller. + // Inform the |audio_renderer_| of the format required by the caller. fuchsia::media::AudioStreamType format; format.sample_format = fuchsia::media::AudioSampleFormat::FLOAT; format.channels = parameters_.channels(); format.frames_per_second = parameters_.sample_rate(); - audio_out_->SetPcmStreamType(std::move(format)); + audio_renderer_->SetPcmStreamType(std::move(format)); // Use number of samples to specify media position. - audio_out_->SetPtsUnits(parameters_.sample_rate(), 1); + audio_renderer_->SetPtsUnits(parameters_.sample_rate(), 1); // Setup OnMinLeadTimeChanged event listener. This event is used to get // |min_lead_time_|, which indicates how far ahead audio samples need to be // sent to the renderer. - audio_out_.events().OnMinLeadTimeChanged = + audio_renderer_.events().OnMinLeadTimeChanged = fit::bind_member(this, &AudioOutputStreamFuchsia::OnMinLeadTimeChanged); - audio_out_->EnableMinLeadTimeEvents(true); + audio_renderer_->EnableMinLeadTimeEvents(true); // The renderer may fail initialization asynchronously, which is handled in // OnRendererError(). @@ -75,7 +75,8 @@ void AudioOutputStreamFuchsia::Start(AudioSourceCallback* callback) { void AudioOutputStreamFuchsia::Stop() { callback_ = nullptr; reference_time_ = base::TimeTicks(); - audio_out_->PauseNoReply(); + audio_renderer_->PauseNoReply(); + audio_renderer_->DiscardAllPacketsNoReply(); timer_.Stop(); } @@ -90,7 +91,7 @@ void AudioOutputStreamFuchsia::GetVolume(double* volume) { void AudioOutputStreamFuchsia::Close() { Stop(); - audio_out_.Unbind(); + audio_renderer_.Unbind(); // Signal to the manager that we're closed and can be removed. This should be // the last call in the function as it deletes |this|. @@ -124,7 +125,7 @@ bool AudioOutputStreamFuchsia::InitializePayloadBuffer() { } payload_buffer_pos_ = 0; - audio_out_->AddPayloadBuffer( + audio_renderer_->AddPayloadBuffer( kBufferId, zx::vmo(payload_buffer_.handle().Duplicate().GetHandle())); return true; @@ -145,7 +146,7 @@ void AudioOutputStreamFuchsia::OnMinLeadTimeChanged(int64_t min_lead_time) { } void AudioOutputStreamFuchsia::OnRendererError() { - LOG(WARNING) << "AudioOut has failed."; + LOG(WARNING) << "AudioRenderer has failed."; ReportError(); } @@ -157,7 +158,7 @@ void AudioOutputStreamFuchsia::ReportError() { } void AudioOutputStreamFuchsia::PumpSamples() { - DCHECK(audio_out_); + DCHECK(audio_renderer_); // Allocate payload buffer if necessary. if (!payload_buffer_.mapped_size() && !InitializePayloadBuffer()) { @@ -182,47 +183,42 @@ void AudioOutputStreamFuchsia::PumpSamples() { delay = stream_time - now; } + // Start playback if the stream was previously stopped. + if (reference_time_.is_null()) { + stream_position_samples_ = 0; + reference_time_ = now + min_lead_time_; + audio_renderer_->PlayNoReply(reference_time_.ToZxTime(), + stream_position_samples_); + } + + // Request more samples from |callback_|. int frames_filled = callback_->OnMoreData(delay, now, 0, audio_bus_.get()); DCHECK_EQ(frames_filled, audio_bus_->frames()); audio_bus_->Scale(volume_); + // Save samples to the |payload_buffer_|. size_t packet_size = parameters_.GetBytesPerBuffer(kSampleFormatF32); DCHECK_LE(payload_buffer_pos_ + packet_size, payload_buffer_.mapped_size()); - audio_bus_->ToInterleaved<media::Float32SampleTypeTraits>( audio_bus_->frames(), reinterpret_cast<float*>(static_cast<uint8_t*>(payload_buffer_.memory()) + payload_buffer_pos_)); + // Send a new packet. fuchsia::media::StreamPacket packet; packet.pts = stream_position_samples_; packet.payload_buffer_id = kBufferId; packet.payload_offset = payload_buffer_pos_; packet.payload_size = packet_size; packet.flags = 0; - - audio_out_->SendPacketNoReply(std::move(packet)); + audio_renderer_->SendPacketNoReply(std::move(packet)); stream_position_samples_ += frames_filled; payload_buffer_pos_ = (payload_buffer_pos_ + packet_size) % payload_buffer_.mapped_size(); - if (reference_time_.is_null()) { - audio_out_->Play( - fuchsia::media::NO_TIMESTAMP, stream_position_samples_ - frames_filled, - [this](int64_t reference_time, int64_t media_time) { - if (!callback_) - return; - - reference_time_ = base::TimeTicks::FromZxTime(reference_time); - stream_position_samples_ = media_time; - - SchedulePumpSamples(base::TimeTicks::Now()); - }); - } else { - SchedulePumpSamples(now); - } + SchedulePumpSamples(now); } void AudioOutputStreamFuchsia::SchedulePumpSamples(base::TimeTicks now) { diff --git a/chromium/media/audio/fuchsia/audio_output_stream_fuchsia.h b/chromium/media/audio/fuchsia/audio_output_stream_fuchsia.h index da710f0d765..9c1837a84a3 100644 --- a/chromium/media/audio/fuchsia/audio_output_stream_fuchsia.h +++ b/chromium/media/audio/fuchsia/audio_output_stream_fuchsia.h @@ -61,7 +61,7 @@ class AudioOutputStreamFuchsia : public AudioOutputStream { AudioManagerFuchsia* manager_; AudioParameters parameters_; - fuchsia::media::AudioOutPtr audio_out_; + fuchsia::media::AudioRendererPtr audio_renderer_; // |audio_bus_| is used only in PumpSamples(). It is kept here to avoid // reallocating the memory every time. diff --git a/chromium/media/audio/mac/audio_auhal_mac.cc b/chromium/media/audio/mac/audio_auhal_mac.cc index 03e2639c662..cd89860527e 100644 --- a/chromium/media/audio/mac/audio_auhal_mac.cc +++ b/chromium/media/audio/mac/audio_auhal_mac.cc @@ -401,8 +401,8 @@ void AUHALStream::ReportAndResetStats() { return; // No stats gathered to report. // A value of 0 indicates that we got the buffer size we asked for. - UMA_HISTOGRAM_COUNTS("Media.Audio.Render.FramesRequested", - number_of_frames_requested_); + UMA_HISTOGRAM_COUNTS_1M("Media.Audio.Render.FramesRequested", + number_of_frames_requested_); // Even if there aren't any glitches, we want to record it to get a feel for // how often we get no glitches vs the alternative. UMA_HISTOGRAM_CUSTOM_COUNTS("Media.Audio.Render.Glitches", glitches_detected_, @@ -418,11 +418,12 @@ void AUHALStream::ReportAndResetStats() { log_callback_.Run(log_message); if (glitches_detected_ != 0) { - UMA_HISTOGRAM_COUNTS("Media.Audio.Render.LostFramesInMs", lost_frames_ms); + UMA_HISTOGRAM_COUNTS_1M("Media.Audio.Render.LostFramesInMs", + lost_frames_ms); auto largest_glitch_ms = (largest_glitch_frames_ * 1000) / params_.sample_rate(); - UMA_HISTOGRAM_COUNTS("Media.Audio.Render.LargestGlitchMs", - largest_glitch_ms); + UMA_HISTOGRAM_COUNTS_1M("Media.Audio.Render.LargestGlitchMs", + largest_glitch_ms); DLOG(WARNING) << log_message; } diff --git a/chromium/media/audio/mac/audio_device_listener_mac_unittest.cc b/chromium/media/audio/mac/audio_device_listener_mac_unittest.cc index 94700767341..cd73209bd07 100644 --- a/chromium/media/audio/mac/audio_device_listener_mac_unittest.cc +++ b/chromium/media/audio/mac/audio_device_listener_mac_unittest.cc @@ -26,8 +26,9 @@ class AudioDeviceListenerMacTest : public testing::Test { // It's important to create the device listener from the message loop in // order to ensure we don't end up with unbalanced TaskObserver calls. message_loop_.task_runner()->PostTask( - FROM_HERE, base::Bind(&AudioDeviceListenerMacTest::CreateDeviceListener, - base::Unretained(this))); + FROM_HERE, + base::BindOnce(&AudioDeviceListenerMacTest::CreateDeviceListener, + base::Unretained(this))); base::RunLoop().RunUntilIdle(); } diff --git a/chromium/media/audio/mac/audio_low_latency_input_mac.cc b/chromium/media/audio/mac/audio_low_latency_input_mac.cc index c0579e95374..b7bcfa7b01d 100644 --- a/chromium/media/audio/mac/audio_low_latency_input_mac.cc +++ b/chromium/media/audio/mac/audio_low_latency_input_mac.cc @@ -16,6 +16,7 @@ #include "base/mac/mac_logging.h" #include "base/mac/mac_util.h" #include "base/mac/scoped_cftyperef.h" +#include "base/mac/scoped_mach_port.h" #include "base/metrics/histogram_functions.h" #include "base/metrics/histogram_macros.h" #include "base/strings/strcat.h" @@ -124,13 +125,12 @@ static OSStatus GetInputDeviceStreamFormat( // Returns the number of physical processors on the device. static int NumberOfPhysicalProcessors() { - mach_port_t mach_host = mach_host_self(); + base::mac::ScopedMachSendRight mach_host(mach_host_self()); host_basic_info hbi = {}; mach_msg_type_number_t info_count = HOST_BASIC_INFO_COUNT; kern_return_t kr = - host_info(mach_host, HOST_BASIC_INFO, reinterpret_cast<host_info_t>(&hbi), - &info_count); - mach_port_deallocate(mach_task_self(), mach_host); + host_info(mach_host.get(), HOST_BASIC_INFO, + reinterpret_cast<host_info_t>(&hbi), &info_count); int n_physical_cores = 0; if (kr != KERN_SUCCESS) { @@ -148,11 +148,11 @@ static int NumberOfPhysicalProcessors() { // as expected. static void AddSystemInfoToUMA() { // Number of logical processors/cores on the current machine. - UMA_HISTOGRAM_COUNTS("Media.Audio.LogicalProcessorsMac", - base::SysInfo::NumberOfProcessors()); + UMA_HISTOGRAM_COUNTS_1M("Media.Audio.LogicalProcessorsMac", + base::SysInfo::NumberOfProcessors()); // Number of physical processors/cores on the current machine. - UMA_HISTOGRAM_COUNTS("Media.Audio.PhysicalProcessorsMac", - NumberOfPhysicalProcessors()); + UMA_HISTOGRAM_COUNTS_1M("Media.Audio.PhysicalProcessorsMac", + NumberOfPhysicalProcessors()); DVLOG(1) << "logical processors: " << base::SysInfo::NumberOfProcessors(); DVLOG(1) << "physical processors: " << NumberOfPhysicalProcessors(); } @@ -1418,7 +1418,7 @@ void AUAudioInputStream::ReportAndResetStats() { number_of_frames_provided_); // Even if there aren't any glitches, we want to record it to get a feel for // how often we get no glitches vs the alternative. - UMA_HISTOGRAM_COUNTS("Media.Audio.Capture.Glitches", glitches_detected_); + UMA_HISTOGRAM_COUNTS_1M("Media.Audio.Capture.Glitches", glitches_detected_); auto lost_frames_ms = (total_lost_frames_ * 1000) / format_.mSampleRate; std::string log_message = base::StringPrintf( diff --git a/chromium/media/audio/mac/audio_manager_mac.cc b/chromium/media/audio/mac/audio_manager_mac.cc index 74dd21d45b4..31f593c5908 100644 --- a/chromium/media/audio/mac/audio_manager_mac.cc +++ b/chromium/media/audio/mac/audio_manager_mac.cc @@ -515,8 +515,8 @@ AudioManagerMac::AudioManagerMac(std::unique_ptr<AudioThread> audio_thread, // PostTask since AudioManager creation may be on the startup path and this // may be slow. GetTaskRunner()->PostTask( - FROM_HERE, base::Bind(&AudioManagerMac::InitializeOnAudioThread, - weak_ptr_factory_.GetWeakPtr())); + FROM_HERE, base::BindOnce(&AudioManagerMac::InitializeOnAudioThread, + weak_ptr_factory_.GetWeakPtr())); } AudioManagerMac::~AudioManagerMac() = default; diff --git a/chromium/media/audio/mock_audio_manager.cc b/chromium/media/audio/mock_audio_manager.cc index 9f0686f71b6..d8b9e149191 100644 --- a/chromium/media/audio/mock_audio_manager.cc +++ b/chromium/media/audio/mock_audio_manager.cc @@ -35,7 +35,7 @@ bool MockAudioManager::HasAudioInputDevices() { void MockAudioManager::GetAudioInputDeviceDescriptions( AudioDeviceDescriptions* device_descriptions) { DCHECK(GetTaskRunner()->BelongsToCurrentThread()); - if (get_input_device_descriptions_cb_.is_null()) + if (!get_input_device_descriptions_cb_) return; get_input_device_descriptions_cb_.Run(device_descriptions); } @@ -43,7 +43,7 @@ void MockAudioManager::GetAudioInputDeviceDescriptions( void MockAudioManager::GetAudioOutputDeviceDescriptions( AudioDeviceDescriptions* device_descriptions) { DCHECK(GetTaskRunner()->BelongsToCurrentThread()); - if (get_output_device_descriptions_cb_.is_null()) + if (!get_output_device_descriptions_cb_) return; get_output_device_descriptions_cb_.Run(device_descriptions); } @@ -58,20 +58,16 @@ media::AudioOutputStream* MockAudioManager::MakeAudioOutputStream( media::AudioOutputStream* MockAudioManager::MakeAudioOutputStreamProxy( const media::AudioParameters& params, const std::string& device_id) { - if (make_output_stream_cb_) { - return make_output_stream_cb_.Run(params, device_id); - } - return nullptr; + return make_output_stream_cb_ ? make_output_stream_cb_.Run(params, device_id) + : nullptr; } media::AudioInputStream* MockAudioManager::MakeAudioInputStream( const media::AudioParameters& params, const std::string& device_id, const LogCallback& log_callback) { - if (make_input_stream_cb_) { - return make_input_stream_cb_.Run(params, device_id); - } - return nullptr; + return make_input_stream_cb_ ? make_input_stream_cb_.Run(params, device_id) + : nullptr; } void MockAudioManager::AddOutputDeviceChangeListener( @@ -102,9 +98,9 @@ AudioParameters MockAudioManager::GetInputStreamParameters( std::string MockAudioManager::GetAssociatedOutputDeviceID( const std::string& input_device_id) { DCHECK(GetTaskRunner()->BelongsToCurrentThread()); - return get_associated_output_device_id_cb_.is_null() - ? std::string() - : get_associated_output_device_id_cb_.Run(input_device_id); + return get_associated_output_device_id_cb_ + ? get_associated_output_device_id_cb_.Run(input_device_id) + : std::string(); } std::string MockAudioManager::GetDefaultInputDeviceID() { diff --git a/chromium/media/audio/pulse/audio_manager_pulse.cc b/chromium/media/audio/pulse/audio_manager_pulse.cc index 6696198658e..3700506781f 100644 --- a/chromium/media/audio/pulse/audio_manager_pulse.cc +++ b/chromium/media/audio/pulse/audio_manager_pulse.cc @@ -160,12 +160,11 @@ AudioInputStream* AudioManagerPulse::MakeLowLatencyInputStream( } std::string AudioManagerPulse::GetDefaultInputDeviceID() { -#if defined(OS_CHROMEOS) + // Do not use the real default input device since it is a fallback + // device rather than a default device. Using the default input device + // reported by Pulse Audio prevents, for example, input redirection + // using the PULSE_SOURCE environment variable. return AudioManagerBase::GetDefaultInputDeviceID(); -#else - return pulse::GetRealDefaultDeviceId(input_mainloop_, input_context_, - pulse::RequestType::INPUT); -#endif } std::string AudioManagerPulse::GetDefaultOutputDeviceID() { @@ -184,15 +183,13 @@ std::string AudioManagerPulse::GetAssociatedOutputDeviceID( DCHECK(AudioManager::Get()->GetTaskRunner()->BelongsToCurrentThread()); DCHECK(input_mainloop_); DCHECK(input_context_); - std::string input = - (input_device_id == AudioDeviceDescription::kDefaultDeviceId) - ? pulse::GetRealDefaultDeviceId(input_mainloop_, input_context_, - pulse::RequestType::INPUT) - : input_device_id; + + if (input_device_id == AudioDeviceDescription::kDefaultDeviceId) + return std::string(); std::string input_bus = - pulse::GetBusOfInput(input_mainloop_, input_context_, input); - return input_bus.empty() ? "" + pulse::GetBusOfInput(input_mainloop_, input_context_, input_device_id); + return input_bus.empty() ? std::string() : pulse::GetOutputCorrespondingTo( input_mainloop_, input_context_, input_bus); #endif diff --git a/chromium/media/audio/sounds/audio_stream_handler.cc b/chromium/media/audio/sounds/audio_stream_handler.cc index 90ff6a089e8..ff975c42f11 100644 --- a/chromium/media/audio/sounds/audio_stream_handler.cc +++ b/chromium/media/audio/sounds/audio_stream_handler.cc @@ -198,8 +198,8 @@ AudioStreamHandler::~AudioStreamHandler() { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); if (IsInitialized()) { AudioManager::Get()->GetTaskRunner()->PostTask( - FROM_HERE, base::Bind(&AudioStreamContainer::Stop, - base::Unretained(stream_.get()))); + FROM_HERE, base::BindOnce(&AudioStreamContainer::Stop, + base::Unretained(stream_.get()))); AudioManager::Get()->GetTaskRunner()->DeleteSoon(FROM_HERE, stream_.release()); } diff --git a/chromium/media/audio/sounds/audio_stream_handler_unittest.cc b/chromium/media/audio/sounds/audio_stream_handler_unittest.cc index b71edb6a16e..79073fe7df4 100644 --- a/chromium/media/audio/sounds/audio_stream_handler_unittest.cc +++ b/chromium/media/audio/sounds/audio_stream_handler_unittest.cc @@ -99,12 +99,14 @@ TEST_F(AudioStreamHandlerTest, ConsecutivePlayRequests) { ASSERT_TRUE(audio_stream_handler()->Play()); base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( - FROM_HERE, base::Bind(base::IgnoreResult(&AudioStreamHandler::Play), - base::Unretained(audio_stream_handler())), + FROM_HERE, + base::BindOnce(base::IgnoreResult(&AudioStreamHandler::Play), + base::Unretained(audio_stream_handler())), base::TimeDelta::FromSeconds(1)); base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( - FROM_HERE, base::Bind(&AudioStreamHandler::Stop, - base::Unretained(audio_stream_handler())), + FROM_HERE, + base::BindOnce(&AudioStreamHandler::Stop, + base::Unretained(audio_stream_handler())), base::TimeDelta::FromSeconds(2)); run_loop.Run(); diff --git a/chromium/media/audio/virtual_audio_input_stream.cc b/chromium/media/audio/virtual_audio_input_stream.cc index 660fb6692a4..7c8ca14b820 100644 --- a/chromium/media/audio/virtual_audio_input_stream.cc +++ b/chromium/media/audio/virtual_audio_input_stream.cc @@ -41,8 +41,7 @@ VirtualAudioInputStream::~VirtualAudioInputStream() { // output streams be removed before VirtualAudioInputStream is destroyed. DCHECK_EQ(0, num_attached_output_streams_); - for (AudioConvertersMap::iterator it = converters_.begin(); - it != converters_.end(); ++it) { + for (auto it = converters_.begin(); it != converters_.end(); ++it) { delete it->second; } } @@ -72,7 +71,7 @@ void VirtualAudioInputStream::AddInputProvider( base::AutoLock scoped_lock(converter_network_lock_); - AudioConvertersMap::iterator converter = converters_.find(params); + auto converter = converters_.find(params); if (converter == converters_.end()) { std::pair<AudioConvertersMap::iterator, bool> result = converters_.insert(std::make_pair( @@ -122,7 +121,7 @@ void VirtualAudioInputStream::Close() { // If a non-null AfterCloseCallback was provided to the constructor, invoke it // here. The callback is moved to a stack-local first since |this| could be // destroyed during Run(). - if (!after_close_cb_.is_null()) { + if (after_close_cb_) { const AfterCloseCallback cb = after_close_cb_; after_close_cb_.Reset(); cb.Run(this); diff --git a/chromium/media/audio/virtual_audio_input_stream_unittest.cc b/chromium/media/audio/virtual_audio_input_stream_unittest.cc index 63d3fc6ee1d..fc9a7d027d2 100644 --- a/chromium/media/audio/virtual_audio_input_stream_unittest.cc +++ b/chromium/media/audio/virtual_audio_input_stream_unittest.cc @@ -253,10 +253,10 @@ class VirtualAudioInputStreamTest : public testing::TestWithParam<bool> { DISALLOW_COPY_AND_ASSIGN(VirtualAudioInputStreamTest); }; -#define RUN_ON_AUDIO_THREAD(method) \ - audio_task_runner()->PostTask( \ - FROM_HERE, base::Bind(&VirtualAudioInputStreamTest::method, \ - base::Unretained(this))) +#define RUN_ON_AUDIO_THREAD(method) \ + audio_task_runner()->PostTask( \ + FROM_HERE, base::BindOnce(&VirtualAudioInputStreamTest::method, \ + base::Unretained(this))) TEST_P(VirtualAudioInputStreamTest, CreateAndClose) { RUN_ON_AUDIO_THREAD(Create); diff --git a/chromium/media/audio/virtual_audio_output_stream.cc b/chromium/media/audio/virtual_audio_output_stream.cc index e7e5255c68e..a7ba1dec76f 100644 --- a/chromium/media/audio/virtual_audio_output_stream.cc +++ b/chromium/media/audio/virtual_audio_output_stream.cc @@ -58,7 +58,7 @@ void VirtualAudioOutputStream::Close() { // If a non-null AfterCloseCallback was provided to the constructor, invoke it // here. The callback is moved to a stack-local first since |this| could be // destroyed during Run(). - if (!after_close_cb_.is_null()) { + if (after_close_cb_) { const AfterCloseCallback cb = after_close_cb_; after_close_cb_.Reset(); cb.Run(this); diff --git a/chromium/media/audio/virtual_audio_output_stream_unittest.cc b/chromium/media/audio/virtual_audio_output_stream_unittest.cc index 569e2387850..320b789c896 100644 --- a/chromium/media/audio/virtual_audio_output_stream_unittest.cc +++ b/chromium/media/audio/virtual_audio_output_stream_unittest.cc @@ -69,8 +69,8 @@ class VirtualAudioOutputStreamTest : public testing::Test { base::WaitableEvent done(base::WaitableEvent::ResetPolicy::AUTOMATIC, base::WaitableEvent::InitialState::NOT_SIGNALED); audio_task_runner()->PostTask( - FROM_HERE, base::Bind(&base::WaitableEvent::Signal, - base::Unretained(&done))); + FROM_HERE, + base::BindOnce(&base::WaitableEvent::Signal, base::Unretained(&done))); done.Wait(); } @@ -87,9 +87,9 @@ TEST_F(VirtualAudioOutputStreamTest, StartStopStartStop) { MockVirtualAudioInputStream* const input_stream = new MockVirtualAudioInputStream(audio_task_runner()); audio_task_runner()->PostTask( - FROM_HERE, base::Bind( - base::IgnoreResult(&MockVirtualAudioInputStream::Open), - base::Unretained(input_stream))); + FROM_HERE, + base::BindOnce(base::IgnoreResult(&MockVirtualAudioInputStream::Open), + base::Unretained(input_stream))); VirtualAudioOutputStream* const output_stream = new VirtualAudioOutputStream( kParams, @@ -101,25 +101,25 @@ TEST_F(VirtualAudioOutputStreamTest, StartStopStartStop) { .Times(kCycles); audio_task_runner()->PostTask( - FROM_HERE, base::Bind(base::IgnoreResult(&VirtualAudioOutputStream::Open), - base::Unretained(output_stream))); + FROM_HERE, + base::BindOnce(base::IgnoreResult(&VirtualAudioOutputStream::Open), + base::Unretained(output_stream))); SineWaveAudioSource source(CHANNEL_LAYOUT_STEREO, 200.0, 128); for (int i = 0; i < kCycles; ++i) { audio_task_runner()->PostTask( - FROM_HERE, base::Bind(&VirtualAudioOutputStream::Start, - base::Unretained(output_stream), - &source)); + FROM_HERE, base::BindOnce(&VirtualAudioOutputStream::Start, + base::Unretained(output_stream), &source)); audio_task_runner()->PostTask( - FROM_HERE, base::Bind(&VirtualAudioOutputStream::Stop, - base::Unretained(output_stream))); + FROM_HERE, base::BindOnce(&VirtualAudioOutputStream::Stop, + base::Unretained(output_stream))); } audio_task_runner()->PostTask( - FROM_HERE, base::Bind(&VirtualAudioOutputStream::Close, - base::Unretained(output_stream))); + FROM_HERE, base::BindOnce(&VirtualAudioOutputStream::Close, + base::Unretained(output_stream))); audio_task_runner()->PostTask( - FROM_HERE, base::Bind(&MockVirtualAudioInputStream::Close, - base::Unretained(input_stream))); + FROM_HERE, base::BindOnce(&MockVirtualAudioInputStream::Close, + base::Unretained(input_stream))); SyncWithAudioThread(); } diff --git a/chromium/media/audio/virtual_audio_sink.cc b/chromium/media/audio/virtual_audio_sink.cc index 41b306627bb..9db8da49924 100644 --- a/chromium/media/audio/virtual_audio_sink.cc +++ b/chromium/media/audio/virtual_audio_sink.cc @@ -44,9 +44,8 @@ VirtualAudioSink::~VirtualAudioSink() = default; void VirtualAudioSink::Close() { target_->RemoveInputProvider(this, params_); - const AfterCloseCallback& cb = base::ResetAndReturn(&after_close_callback_); - if (!cb.is_null()) - cb.Run(this); + if (after_close_callback_) + std::move(after_close_callback_).Run(this); } void VirtualAudioSink::OnData(std::unique_ptr<AudioBus> source, diff --git a/chromium/media/audio/win/audio_device_listener_win.cc b/chromium/media/audio/win/audio_device_listener_win.cc index e39eb06b2b4..f147e454a3d 100644 --- a/chromium/media/audio/win/audio_device_listener_win.cc +++ b/chromium/media/audio/win/audio_device_listener_win.cc @@ -8,7 +8,7 @@ #include "base/logging.h" #include "base/strings/utf_string_conversions.h" -#include "base/system_monitor/system_monitor.h" +#include "base/system/system_monitor.h" #include "base/time/default_tick_clock.h" #include "base/win/scoped_co_mem.h" #include "base/win/windows_version.h" diff --git a/chromium/media/audio/win/audio_low_latency_input_win.cc b/chromium/media/audio/win/audio_low_latency_input_win.cc index ccf5652cbef..90b12155255 100644 --- a/chromium/media/audio/win/audio_low_latency_input_win.cc +++ b/chromium/media/audio/win/audio_low_latency_input_win.cc @@ -4,11 +4,7 @@ #include "media/audio/win/audio_low_latency_input_win.h" -#include <audiopolicy.h> -#include <mediaobj.h> #include <objbase.h> -#include <uuids.h> -#include <wmcodecdsp.h> #include <algorithm> #include <cmath> @@ -70,125 +66,18 @@ bool IsSupportedFormatForConversion(const WAVEFORMATEX& format) { return true; } -// Returns the index of the device in the device collection, or -1 for the -// default device, as used by the voice processing DMO. -base::Optional<WORD> GetAudioDeviceCollectionIndexFromId( - const std::string& device_id, - const EDataFlow data_flow) { - // The default device is specified with -1. - if (AudioDeviceDescription::IsDefaultDevice(device_id)) - return -1; - - WORD device_index = -1; - HRESULT hr = E_FAIL; - // The default communications does not have an index itself, so we need to - // find the index for the underlying device. - if (AudioDeviceDescription::IsCommunicationsDevice(device_id)) { - const std::string communications_id = - (data_flow == eCapture) - ? CoreAudioUtil::GetCommunicationsInputDeviceID() - : CoreAudioUtil::GetCommunicationsOutputDeviceID(); - hr = CoreAudioUtil::GetDeviceCollectionIndex(communications_id, data_flow, - &device_index); - } else { - // Otherwise, just look for the device_id directly. - hr = CoreAudioUtil::GetDeviceCollectionIndex(device_id, data_flow, - &device_index); - } - - if (FAILED(hr) || hr == S_FALSE) - return base::nullopt; - - return device_index; -} - -// Implementation of IMediaBuffer, as required for -// IMediaObject::ProcessOutput(). After consuming data provided by -// ProcessOutput(), call SetLength() to update the buffer availability. -// Example implementation: -// http://msdn.microsoft.com/en-us/library/dd376684(v=vs.85).aspx -class MediaBufferImpl : public IMediaBuffer { - public: - explicit MediaBufferImpl(DWORD max_length) - : data_(new BYTE[max_length]), max_length_(max_length) {} - - // IMediaBuffer implementation. - STDMETHOD(GetBufferAndLength)(BYTE** buffer, DWORD* length) { - if (!buffer || !length) - return E_POINTER; - - *buffer = data_.get(); - *length = length_; - return S_OK; - } - - STDMETHOD(GetMaxLength)(DWORD* max_length) { - if (!max_length) - return E_POINTER; - - *max_length = max_length_; - return S_OK; - } - - STDMETHOD(SetLength)(DWORD length) { - if (length > max_length_) - return E_INVALIDARG; - - length_ = length; - return S_OK; - } - - // IUnknown implementation. - STDMETHOD_(ULONG, AddRef)() { return InterlockedIncrement(&ref_count_); } - - STDMETHOD(QueryInterface)(REFIID riid, void** object) { - if (!object) - return E_POINTER; - if (riid != IID_IMediaBuffer && riid != IID_IUnknown) - return E_NOINTERFACE; - - *object = static_cast<IMediaBuffer*>(this); - AddRef(); - return S_OK; - } - - STDMETHOD_(ULONG, Release)() { - LONG ref_count = InterlockedDecrement(&ref_count_); - if (ref_count == 0) - delete this; - - return ref_count; - } - - private: - virtual ~MediaBufferImpl() {} - - std::unique_ptr<BYTE[]> data_; - DWORD length_ = 0; - const DWORD max_length_; - LONG ref_count_ = 0; -}; - } // namespace WASAPIAudioInputStream::WASAPIAudioInputStream( AudioManagerWin* manager, const AudioParameters& params, const std::string& device_id, - const AudioManager::LogCallback& log_callback, - AudioManagerBase::VoiceProcessingMode voice_processing_mode) - : manager_(manager), - device_id_(device_id), - output_device_id_for_aec_(AudioDeviceDescription::kDefaultDeviceId), - log_callback_(log_callback), - use_voice_processing_(voice_processing_mode == - AudioManagerBase::VoiceProcessingMode::kEnabled) { + const AudioManager::LogCallback& log_callback) + : manager_(manager), device_id_(device_id), log_callback_(log_callback) { DCHECK(manager_); DCHECK(!device_id_.empty()); DCHECK(!log_callback_.is_null()); - DVLOG_IF(1, use_voice_processing_) << "Using Windows voice capture DSP DMO."; - // Load the Avrt DLL if not already loaded. Required to support MMCSS. bool avrt_init = avrt::Initialize(); DCHECK(avrt_init) << "Failed to load the Avrt.dll"; @@ -255,16 +144,6 @@ bool WASAPIAudioInputStream::Open() { return false; } - // If voice processing is enabled, initialize the DMO that is used for it. The - // remainder of the function initializes an audio capture client (the normal - // case). Either the DMO or the capture client is used. - // TODO(grunell): Refactor out the audio capture client initialization to its - // own function. - if (use_voice_processing_) { - opened_ = InitializeDmo(); - return opened_; - } - // Obtain an IAudioClient interface which enables us to create and initialize // an audio stream between an audio application and the audio engine. hr = endpoint_device_->Activate(__uuidof(IAudioClient), CLSCTX_INPROC_SERVER, @@ -312,27 +191,17 @@ void WASAPIAudioInputStream::Start(AudioInputCallback* callback) { if (started_) return; - // TODO(grunell): Refactor the |use_voice_processing_| conditions in this - // function to clean up the code. - if (use_voice_processing_) { - // Pre-fill render buffer with silence. - if (!CoreAudioUtil::FillRenderEndpointBufferWithSilence( - audio_client_for_render_.Get(), audio_render_client_.Get())) { - DLOG(WARNING) << "Failed to pre-fill render buffer with silence."; - } - } else { - if (device_id_ == AudioDeviceDescription::kLoopbackWithMuteDeviceId && - system_audio_volume_) { - BOOL muted = false; - system_audio_volume_->GetMute(&muted); - - // If the system audio is muted at the time of capturing, then no need to - // mute it again, and later we do not unmute system audio when stopping - // capturing. - if (!muted) { - system_audio_volume_->SetMute(true, NULL); - mute_done_ = true; - } + if (device_id_ == AudioDeviceDescription::kLoopbackWithMuteDeviceId && + system_audio_volume_) { + BOOL muted = false; + system_audio_volume_->GetMute(&muted); + + // If the system audio is muted at the time of capturing, then no need to + // mute it again, and later we do not unmute system audio when stopping + // capturing. + if (!muted) { + system_audio_volume_->SetMute(true, NULL); + mute_done_ = true; } } @@ -351,31 +220,21 @@ void WASAPIAudioInputStream::Start(AudioInputCallback* callback) { base::SimpleThread::Options(base::ThreadPriority::REALTIME_AUDIO))); capture_thread_->Start(); - HRESULT hr = E_FAIL; - if (use_voice_processing_) { - hr = audio_client_for_render_->Start(); - if (FAILED(hr)) { - DLOG(ERROR) << "Failed to start output streaming: " << std::hex << hr - << ", proceeding without rendering."; - } - } else { - // Start streaming data between the endpoint buffer and the audio engine. - hr = audio_client_->Start(); - if (FAILED(hr)) { - DLOG(ERROR) << "Failed to start input streaming."; + // Start streaming data between the endpoint buffer and the audio engine. + HRESULT hr = audio_client_->Start(); + if (FAILED(hr)) { + DLOG(ERROR) << "Failed to start input streaming."; + log_callback_.Run(base::StringPrintf( + "WASAPIAIS::Start: Failed to start audio client, hresult = %#lx", hr)); + } + + if (SUCCEEDED(hr) && audio_render_client_for_loopback_.Get()) { + hr = audio_render_client_for_loopback_->Start(); + if (FAILED(hr)) log_callback_.Run(base::StringPrintf( - "WASAPIAIS::Start: Failed to start audio client, hresult = %#lx", + "WASAPIAIS::Start: Failed to start render client for loopback, " + "hresult = %#lx", hr)); - } - - if (SUCCEEDED(hr) && audio_render_client_for_loopback_.Get()) { - hr = audio_render_client_for_loopback_->Start(); - if (FAILED(hr)) - log_callback_.Run(base::StringPrintf( - "WASAPIAIS::Start: Failed to start render client for loopback, " - "hresult = %#lx", - hr)); - } } started_ = SUCCEEDED(hr); @@ -406,21 +265,10 @@ void WASAPIAudioInputStream::Stop() { SetEvent(stop_capture_event_.Get()); } - // TODO(grunell): Refactor the |use_voice_processing_| conditions in this - // function to clean up the code. - if (use_voice_processing_) { - // Stop the render audio streaming. The input streaming needs no explicit - // stopping. - HRESULT hr = audio_client_for_render_->Stop(); - if (FAILED(hr)) { - DLOG(ERROR) << "Failed to stop output streaming."; - } - } else { - // Stop the input audio streaming. - HRESULT hr = audio_client_->Stop(); - if (FAILED(hr)) { - DLOG(ERROR) << "Failed to stop input streaming."; - } + // Stop the input audio streaming. + HRESULT hr = audio_client_->Stop(); + if (FAILED(hr)) { + LOG(ERROR) << "Failed to stop input streaming."; } // Wait until the thread completes and perform cleanup. @@ -430,12 +278,6 @@ void WASAPIAudioInputStream::Stop() { capture_thread_.reset(); } - if (use_voice_processing_) { - HRESULT hr = voice_capture_dmo_->FreeStreamingResources(); - if (FAILED(hr)) - DLOG(ERROR) << "Failed to free dmo resources."; - } - started_ = false; sink_ = NULL; } @@ -524,58 +366,7 @@ bool WASAPIAudioInputStream::IsMuted() { void WASAPIAudioInputStream::SetOutputDeviceForAec( const std::string& output_device_id) { - if (!use_voice_processing_) - return; - - if (output_device_id == output_device_id_for_aec_) - return; - - output_device_id_for_aec_ = output_device_id; - - if (opened_) { - // Set devices. - Microsoft::WRL::ComPtr<IPropertyStore> ps; - HRESULT hr = voice_capture_dmo_->QueryInterface(IID_IPropertyStore, &ps); - if (FAILED(hr) || !ps) { - log_callback_.Run( - base::StringPrintf("WASAPIAIS:SetOutputDeviceForAec: Getting DMO " - "property store failed.")); - return; - } - - if (!SetDmoDevices(ps.Get())) { - log_callback_.Run( - "WASAPIAIS:SetOutputDeviceForAec: Setting device indices failed."); - return; - } - } - - if (started_) { - DCHECK(opened_); - // Recreate the dummy render client on the new output. - HRESULT hr = audio_client_for_render_->Stop(); - if (FAILED(hr)) { - DLOG(ERROR) << "Failed to stop output streaming."; - } - - CreateDummyRenderClientsForDmo(); - - if (!CoreAudioUtil::FillRenderEndpointBufferWithSilence( - audio_client_for_render_.Get(), audio_render_client_.Get())) { - DLOG(WARNING) << "Failed to pre-fill render buffer with silence."; - } - - hr = audio_client_for_render_->Start(); - if (FAILED(hr)) { - DLOG(ERROR) << "Failed to start output streaming: " << std::hex << hr - << ", proceeding without rendering."; - } - } - - log_callback_.Run(base::StringPrintf( - "WASAPIAIS:SetOutputDeviceForAec: Successfully updated AEC output " - "device to %s", - output_device_id.c_str())); + // Not supported. Do nothing. } void WASAPIAudioInputStream::Run() { @@ -619,70 +410,43 @@ void WASAPIAudioInputStream::Run() { DVLOG(1) << "AudioBlockFifo buffer count: " << buffers_required; - bool success = - use_voice_processing_ ? RunWithDmo() : RunWithAudioCaptureClient(); - - if (!success) { - // TODO(henrika): perhaps it worth improving the cleanup here by e.g. - // stopping the audio client, joining the thread etc.? - NOTREACHED() << "WASAPI capturing failed with error code " - << GetLastError(); - } - - // Disable MMCSS. - if (mm_task && !avrt::AvRevertMmThreadCharacteristics(mm_task)) { - PLOG(WARNING) << "Failed to disable MMCSS"; - } - - fifo_.reset(); -} - -bool WASAPIAudioInputStream::RunWithAudioCaptureClient() { + bool recording = true; + bool error = false; HANDLE wait_array[2] = {stop_capture_event_.Get(), audio_samples_ready_event_.Get()}; - while (true) { + while (recording && !error) { // Wait for a close-down event or a new capture event. DWORD wait_result = WaitForMultipleObjects(2, wait_array, FALSE, INFINITE); switch (wait_result) { case WAIT_OBJECT_0 + 0: // |stop_capture_event_| has been set. - return true; + recording = false; + break; case WAIT_OBJECT_0 + 1: // |audio_samples_ready_event_| has been set. PullCaptureDataAndPushToSink(); break; case WAIT_FAILED: default: - return false; + error = true; + break; } } - return false; -} + if (recording && error) { + // TODO(henrika): perhaps it worth improving the cleanup here by e.g. + // stopping the audio client, joining the thread etc.? + NOTREACHED() << "WASAPI capturing failed with error code " + << GetLastError(); + } -bool WASAPIAudioInputStream::RunWithDmo() { - while (true) { - // Poll every 5 ms, or wake up on capture stop signal. - DWORD wait_result = WaitForSingleObject(stop_capture_event_.Get(), 5); - switch (wait_result) { - case WAIT_OBJECT_0: - // |stop_capture_event_| has been set. - return true; - case WAIT_TIMEOUT: - PullDmoCaptureDataAndPushToSink(); - if (!CoreAudioUtil::FillRenderEndpointBufferWithSilence( - audio_client_for_render_.Get(), audio_render_client_.Get())) { - DLOG(WARNING) << "Failed to fill render buffer with silence."; - } - break; - case WAIT_FAILED: - default: - return false; - } + // Disable MMCSS. + if (mm_task && !avrt::AvRevertMmThreadCharacteristics(mm_task)) { + PLOG(WARNING) << "Failed to disable MMCSS"; } - return false; + fifo_.reset(); } void WASAPIAudioInputStream::PullCaptureDataAndPushToSink() { @@ -813,106 +577,6 @@ void WASAPIAudioInputStream::PullCaptureDataAndPushToSink() { } // while (true) } -void WASAPIAudioInputStream::PullDmoCaptureDataAndPushToSink() { - TRACE_EVENT1("audio", - "WASAPIAudioInputStream::PullDmoCaptureDataAndPushToSink", - "sample rate", input_format_.nSamplesPerSec); - - // Pull data from the capture endpoint buffer until it's empty or an error - // occurs. - while (true) { - DWORD status = 0; - DMO_OUTPUT_DATA_BUFFER data_buffer = {0}; - data_buffer.pBuffer = media_buffer_.Get(); - - // Get processed capture data from the DMO. - HRESULT hr = - voice_capture_dmo_->ProcessOutput(0, // dwFlags - 1, // cOutputBufferCount - &data_buffer, - &status); // Must be ignored. - if (FAILED(hr)) { - DLOG(ERROR) << "DMO ProcessOutput failed, hr = 0x" << std::hex << hr; - break; - } - - BYTE* data; - ULONG data_length = 0; - // Get a pointer to the data buffer. This should be valid until the next - // call to ProcessOutput. - hr = media_buffer_->GetBufferAndLength(&data, &data_length); - if (FAILED(hr)) { - DLOG(ERROR) << "Could not get buffer, hr = 0x" << std::hex << hr; - break; - } - - if (data_length > 0) { - const int samples_produced = data_length / frame_size_bytes_; - - base::TimeTicks capture_time; - if (data_buffer.dwStatus & DMO_OUTPUT_DATA_BUFFERF_TIME && - data_buffer.rtTimestamp > 0) { - // See conversion notes on |capture_time_100ns| in - // PullCaptureDataAndPushToSink(). - capture_time += - base::TimeDelta::FromMicroseconds(data_buffer.rtTimestamp / 10.0); - } else { - // We may not get the timestamp from ProcessOutput(), fall back on - // current timestamp. - capture_time = base::TimeTicks::Now(); - } - - // Adjust |capture_time| for the FIFO before pushing. - capture_time -= AudioTimestampHelper::FramesToTime( - fifo_->GetAvailableFrames(), input_format_.nSamplesPerSec); - - fifo_->Push(data, samples_produced, input_format_.wBitsPerSample / 8); - - // Reset length to indicate buffer availability. - hr = media_buffer_->SetLength(0); - if (FAILED(hr)) - DLOG(ERROR) << "Could not reset length, hr = 0x" << std::hex << hr; - - // Get a cached AGC volume level which is updated once every second on the - // audio manager thread. Note that, |volume| is also updated each time - // SetVolume() is called through IPC by the render-side AGC. - double volume = 0.0; - GetAgcVolume(&volume); - - while (fifo_->available_blocks()) { - if (converter_) { - if (imperfect_buffer_size_conversion_ && - fifo_->available_blocks() == 1) { - // Special case. We need to buffer up more audio before we can - // convert or else we'll suffer an underrun. - // TODO(grunell): Verify this is really true. - break; - } - converter_->Convert(convert_bus_.get()); - sink_->OnData(convert_bus_.get(), capture_time, volume); - - // Move the capture time forward for each vended block. - capture_time += AudioTimestampHelper::FramesToTime( - convert_bus_->frames(), output_format_.nSamplesPerSec); - } else { - sink_->OnData(fifo_->Consume(), capture_time, volume); - - // Move the capture time forward for each vended block. - capture_time += AudioTimestampHelper::FramesToTime( - packet_size_frames_, input_format_.nSamplesPerSec); - } - } - } // if (data_length > 0) - - if (!(data_buffer.dwStatus & DMO_OUTPUT_DATA_BUFFERF_INCOMPLETE)) { - // The DMO cannot currently produce more data. This is the normal case; - // otherwise it means the DMO had more than 10 ms of data available and - // ProcessOutput should be called again. - break; - } - } // while (true) -} - void WASAPIAudioInputStream::HandleError(HRESULT err) { NOTREACHED() << "Error code: " << err; if (sink_) @@ -1334,223 +998,6 @@ void WASAPIAudioInputStream::MaybeReportFormatRelatedInitError( FormatRelatedInitError::kCount); } -bool WASAPIAudioInputStream::InitializeDmo() { - HRESULT hr = ::CoCreateInstance(CLSID_CWMAudioAEC, NULL, CLSCTX_INPROC_SERVER, - IID_IMediaObject, &voice_capture_dmo_); - if (FAILED(hr)) { - DLOG(ERROR) << "Creating DMO failed."; - return false; - } - - if (!SetDmoProperties()) - return false; - - if (!SetDmoFormat()) - return false; - - hr = voice_capture_dmo_->AllocateStreamingResources(); - if (FAILED(hr)) { - DLOG(ERROR) << "Allocating DMO resources failed."; - return false; - } - - SetupConverterAndStoreFormatInfo(); - - media_buffer_ = - new MediaBufferImpl(endpoint_buffer_size_frames_ * frame_size_bytes_); - - if (!CreateDummyRenderClientsForDmo()) - return false; - - // Get volume interface. - Microsoft::WRL::ComPtr<IAudioSessionManager> audio_session_manager; - hr = endpoint_device_->Activate(__uuidof(IAudioSessionManager), - CLSCTX_INPROC_SERVER, NULL, - &audio_session_manager); - if (FAILED(hr)) { - DLOG(ERROR) << "Obtaining audio session manager failed."; - return false; - } - hr = audio_session_manager->GetSimpleAudioVolume( - NULL, // AudioSessionGuid. NULL for default session. - FALSE, // CrossProcessSession. - &simple_audio_volume_); - if (FAILED(hr)) { - DLOG(ERROR) << "Obtaining audio volume interface failed."; - return false; - } - - return true; -} - -bool WASAPIAudioInputStream::SetDmoProperties() { - Microsoft::WRL::ComPtr<IPropertyStore> ps; - HRESULT hr = voice_capture_dmo_->QueryInterface(IID_IPropertyStore, &ps); - if (FAILED(hr) || !ps) { - DLOG(ERROR) << "Getting DMO property store failed."; - return false; - } - - // Set devices. - if (!SetDmoDevices(ps.Get())) { - DLOG(ERROR) << "Setting device indices failed."; - return false; - } - - // Set DMO mode to AEC only. - if (FAILED(CoreAudioUtil::SetVtI4Property( - ps.Get(), MFPKEY_WMAAECMA_SYSTEM_MODE, SINGLE_CHANNEL_AEC))) { - DLOG(ERROR) << "Setting DMO system mode failed."; - return false; - } - - // Enable the feature mode. This lets us override the default processing - // settings below. - if (FAILED(CoreAudioUtil::SetBoolProperty( - ps.Get(), MFPKEY_WMAAECMA_FEATURE_MODE, VARIANT_TRUE))) { - DLOG(ERROR) << "Setting DMO feature mode failed."; - return false; - } - - // Disable analog AGC (default enabled). - if (FAILED(CoreAudioUtil::SetBoolProperty( - ps.Get(), MFPKEY_WMAAECMA_MIC_GAIN_BOUNDER, VARIANT_FALSE))) { - DLOG(ERROR) << "Setting DMO mic gain bounder failed."; - return false; - } - - // Disable noise suppression (default enabled). - if (FAILED(CoreAudioUtil::SetVtI4Property(ps.Get(), MFPKEY_WMAAECMA_FEATR_NS, - 0))) { - DLOG(ERROR) << "Disabling DMO NS failed."; - return false; - } - - return true; -} - -bool WASAPIAudioInputStream::SetDmoFormat() { - DMO_MEDIA_TYPE mt; // Media type. - mt.majortype = MEDIATYPE_Audio; - mt.subtype = MEDIASUBTYPE_PCM; - mt.lSampleSize = 0; - mt.bFixedSizeSamples = TRUE; - mt.bTemporalCompression = FALSE; - mt.formattype = FORMAT_WaveFormatEx; - - HRESULT hr = MoInitMediaType(&mt, sizeof(WAVEFORMATEX)); - if (FAILED(hr)) { - DLOG(ERROR) << "Init media type for DMO failed."; - return false; - } - - WAVEFORMATEX* dmo_output_format = - reinterpret_cast<WAVEFORMATEX*>(mt.pbFormat); - dmo_output_format->wFormatTag = WAVE_FORMAT_PCM; - dmo_output_format->nChannels = 1; - dmo_output_format->nSamplesPerSec = 16000; - dmo_output_format->nAvgBytesPerSec = 32000; - dmo_output_format->nBlockAlign = 2; - dmo_output_format->wBitsPerSample = 16; - dmo_output_format->cbSize = 0; - - DCHECK(IsSupportedFormatForConversion(*dmo_output_format)); - - // Store the format used. - input_format_.wFormatTag = dmo_output_format->wFormatTag; - input_format_.nChannels = dmo_output_format->nChannels; - input_format_.nSamplesPerSec = dmo_output_format->nSamplesPerSec; - input_format_.wBitsPerSample = dmo_output_format->wBitsPerSample; - input_format_.nBlockAlign = dmo_output_format->nBlockAlign; - input_format_.nAvgBytesPerSec = dmo_output_format->nAvgBytesPerSec; - input_format_.cbSize = dmo_output_format->cbSize; - - hr = voice_capture_dmo_->SetOutputType(0, &mt, 0); - MoFreeMediaType(&mt); - if (FAILED(hr)) { - DLOG(ERROR) << "Setting DMO output type failed."; - return false; - } - - // We use 10 ms buffer size for the DMO. - endpoint_buffer_size_frames_ = input_format_.nSamplesPerSec / 100; - - return true; -} - -bool WASAPIAudioInputStream::SetDmoDevices(IPropertyStore* ps) { - // Look up the input device's index. - const base::Optional<WORD> input_device_index = - GetAudioDeviceCollectionIndexFromId(device_id_, eCapture); - - if (!input_device_index) { - log_callback_.Run( - base::StringPrintf("WASAPIAIS:SetDmoDevices: Could not " - "resolve input device index for %s", - device_id_.c_str())); - return false; - } - - // Look up the output device's index. - const base::Optional<WORD> output_device_index = - GetAudioDeviceCollectionIndexFromId(output_device_id_for_aec_, eRender); - if (!output_device_index) { - log_callback_.Run( - base::StringPrintf("WASAPIAIS:SetDmoDevices: Could not " - "resolve output device index for %s", - output_device_id_for_aec_.c_str())); - return false; - } - - // The DEVICE_INDEXES property packs the input and output indices into the - // upper and lower halves of a LONG. - LONG device_index_value = - (static_cast<ULONG>(*output_device_index) << 16) + - (static_cast<ULONG>(*input_device_index) & 0x0000ffff); - return !FAILED(CoreAudioUtil::SetVtI4Property( - ps, MFPKEY_WMAAECMA_DEVICE_INDEXES, device_index_value)); -} - -bool WASAPIAudioInputStream::CreateDummyRenderClientsForDmo() { - Microsoft::WRL::ComPtr<IAudioClient> audio_client(CoreAudioUtil::CreateClient( - output_device_id_for_aec_, eRender, eConsole)); - if (!audio_client.Get()) { - DLOG(ERROR) << "Failed to create audio client for dummy rendering for DMO."; - return false; - } - - WAVEFORMATPCMEX mix_format; - HRESULT hr = - CoreAudioUtil::GetSharedModeMixFormat(audio_client.Get(), &mix_format); - if (FAILED(hr)) { - DLOG(ERROR) << "Failed to get mix format."; - return false; - } - - hr = audio_client->Initialize(AUDCLNT_SHAREMODE_SHARED, - 0, // Stream flags - 0, // Buffer duration - 0, // Device period - reinterpret_cast<WAVEFORMATEX*>(&mix_format), - NULL); - if (FAILED(hr)) { - DLOG(ERROR) << "Failed to initalize audio client for rendering."; - return false; - } - - Microsoft::WRL::ComPtr<IAudioRenderClient> audio_render_client = - CoreAudioUtil::CreateRenderClient(audio_client.Get()); - if (!audio_render_client.Get()) { - DLOG(ERROR) << "Failed to create audio render client."; - return false; - } - - audio_client_for_render_ = audio_client; - audio_render_client_ = audio_render_client; - - return true; -} - double WASAPIAudioInputStream::ProvideInput(AudioBus* audio_bus, uint32_t frames_delayed) { fifo_->Consume()->CopyTo(audio_bus); @@ -1594,12 +1041,13 @@ void WASAPIAudioInputStream::ReportDelayStatsAndUpdateGlitchCount( } void WASAPIAudioInputStream::ReportAndResetGlitchStats() { - UMA_HISTOGRAM_COUNTS("Media.Audio.Capture.Glitches", total_glitches_); - UMA_HISTOGRAM_COUNTS("Media.Audio.Capture.Win.DevicePositionLessThanExpected", - total_device_position_less_than_expected_); - UMA_HISTOGRAM_COUNTS("Media.Audio.Capture.Win.Discontinuities", - total_discontinuities_); - UMA_HISTOGRAM_COUNTS( + UMA_HISTOGRAM_COUNTS_1M("Media.Audio.Capture.Glitches", total_glitches_); + UMA_HISTOGRAM_COUNTS_1M( + "Media.Audio.Capture.Win.DevicePositionLessThanExpected", + total_device_position_less_than_expected_); + UMA_HISTOGRAM_COUNTS_1M("Media.Audio.Capture.Win.Discontinuities", + total_discontinuities_); + UMA_HISTOGRAM_COUNTS_1M( "Media.Audio.Capture.Win.ConcurrentGlitchAndDiscontinuities", total_concurrent_glitch_and_discontinuities_); diff --git a/chromium/media/audio/win/audio_low_latency_input_win.h b/chromium/media/audio/win/audio_low_latency_input_win.h index 938bba7cef9..ee8307dfaee 100644 --- a/chromium/media/audio/win/audio_low_latency_input_win.h +++ b/chromium/media/audio/win/audio_low_latency_input_win.h @@ -58,7 +58,6 @@ #include <Audioclient.h> #include <MMDeviceAPI.h> -#include <dmo.h> #include <endpointvolume.h> #include <stddef.h> #include <stdint.h> @@ -94,12 +93,10 @@ class MEDIA_EXPORT WASAPIAudioInputStream public: // The ctor takes all the usual parameters, plus |manager| which is the // the audio manager who is creating this object. - WASAPIAudioInputStream( - AudioManagerWin* manager, - const AudioParameters& params, - const std::string& device_id, - const AudioManager::LogCallback& log_callback, - AudioManagerBase::VoiceProcessingMode voice_processing_mode); + WASAPIAudioInputStream(AudioManagerWin* manager, + const AudioParameters& params, + const std::string& device_id, + const AudioManager::LogCallback& log_callback); // The dtor is typically called by the AudioManager only and it is usually // triggered by calling AudioInputStream::Close(). @@ -119,27 +116,16 @@ class MEDIA_EXPORT WASAPIAudioInputStream bool started() const { return started_; } private: - // DelegateSimpleThread::Delegate implementation. Calls either - // RunWithAudioCaptureClient() or RunWithDmo(). + // DelegateSimpleThread::Delegate implementation. void Run() override; - // Waits for an event that the audio capture client has data ready. - bool RunWithAudioCaptureClient(); - - // Polls the DMO (voice processing component) for data every 5 ms. - bool RunWithDmo(); - - // Pulls capture data from the audio capture client and pushes it to the sink. + // Pulls capture data from the endpoint device and pushes it to the sink. void PullCaptureDataAndPushToSink(); - // Pulls capture data from the DMO and pushes it to the sink. - void PullDmoCaptureDataAndPushToSink(); - // Issues the OnError() callback to the |sink_|. void HandleError(HRESULT err); - // The Open() method is divided into these sub methods when not using the - // voice processing DMO. + // The Open() method is divided into these sub methods. HRESULT SetCaptureDevice(); HRESULT GetAudioEngineStreamFormat(); // Returns whether the desired format is supported or not and writes the @@ -155,15 +141,6 @@ class MEDIA_EXPORT WASAPIAudioInputStream // the format. void MaybeReportFormatRelatedInitError(HRESULT hr) const; - // The Open() method is divided into these sub methods when using the voice - // processing DMO. In addition, SetupConverterAndStoreFormatInfo() above is - // also called. - bool InitializeDmo(); - bool SetDmoProperties(); - bool SetDmoFormat(); - bool SetDmoDevices(IPropertyStore* ps); - bool CreateDummyRenderClientsForDmo(); - // AudioConverter::InputCallback implementation. double ProvideInput(AudioBus* audio_bus, uint32_t frames_delayed) override; @@ -215,10 +192,10 @@ class MEDIA_EXPORT WASAPIAudioInputStream WAVEFORMATEX output_format_; // Contains the audio format we get data from the audio engine in. Set to - // |output_format_| at construction and might be changed to a close match - // if the audio engine doesn't support the originally set format, or to the - // format the voice capture DMO outputs if it's used. Note that this is also - // the format after the fifo, i.e. the input format to the converter if any. + // |output_format_| at construction and might be changed to a close match if + // the audio engine doesn't support the originally set format. Note that this + // is also the format after the fifo, i.e. the input format to the converter + // if any. WAVEFORMATEX input_format_; bool opened_ = false; @@ -237,8 +214,7 @@ class MEDIA_EXPORT WASAPIAudioInputStream // converter. size_t packet_size_bytes_ = 0; - // Length of the audio endpoint buffer, or the buffer size used for the DMO. - // That is, the buffer size before the fifo. + // Length of the audio endpoint buffer, i.e. the buffer size before the fifo. uint32_t endpoint_buffer_size_frames_ = 0; // Contains the unique name of the selected endpoint device. @@ -246,10 +222,6 @@ class MEDIA_EXPORT WASAPIAudioInputStream // device role and is not a valid ID as such. std::string device_id_; - // Contains the unique name of the output device from which to cancel echo, in - // case voice processing is enabled, i.e. |use_voice_processing_| is true. - std::string output_device_id_for_aec_; - // Pointer to the object that will receive the recorded audio samples. AudioInputCallback* sink_ = nullptr; @@ -325,22 +297,6 @@ class MEDIA_EXPORT WASAPIAudioInputStream UINT64 total_lost_frames_ = 0; UINT64 largest_glitch_frames_ = 0; - // Indicates if the voice processing DMO should be used. - bool use_voice_processing_ = false; - - // The voice processing DMO and its data buffer. - Microsoft::WRL::ComPtr<IMediaObject> voice_capture_dmo_; - Microsoft::WRL::ComPtr<IMediaBuffer> media_buffer_; - - // Dummy rendering when using the DMO. The DMO requires audio rendering to the - // device it's set up to use, otherwise it won't produce any capture audio - // data. Normally, when the DMO is used there's a render stream, but it's not - // guaranteed so we need to support the lack of it. We do this by always - // opening a render client and rendering silence to it when the DMO is - // running. - Microsoft::WRL::ComPtr<IAudioClient> audio_client_for_render_; - Microsoft::WRL::ComPtr<IAudioRenderClient> audio_render_client_; - SEQUENCE_CHECKER(sequence_checker_); DISALLOW_COPY_AND_ASSIGN(WASAPIAudioInputStream); diff --git a/chromium/media/audio/win/audio_low_latency_input_win_unittest.cc b/chromium/media/audio/win/audio_low_latency_input_win_unittest.cc index 27b0f65fbf8..13cf3734ed2 100644 --- a/chromium/media/audio/win/audio_low_latency_input_win_unittest.cc +++ b/chromium/media/audio/win/audio_low_latency_input_win_unittest.cc @@ -170,16 +170,11 @@ static bool HasCoreAudioAndInputDevices(AudioManager* audio_man) { // also allows the user to modify the default settings. class AudioInputStreamWrapper { public: - explicit AudioInputStreamWrapper(AudioManager* audio_manager, - bool use_voice_processing) + explicit AudioInputStreamWrapper(AudioManager* audio_manager) : audio_man_(audio_manager) { EXPECT_TRUE(SUCCEEDED(CoreAudioUtil::GetPreferredAudioParameters( AudioDeviceDescription::kDefaultDeviceId, false, &default_params_))); EXPECT_EQ(format(), AudioParameters::AUDIO_PCM_LOW_LATENCY); - if (use_voice_processing) { - default_params_.set_effects(default_params_.effects() | - AudioParameters::ECHO_CANCELLER); - } frames_per_buffer_ = default_params_.frames_per_buffer(); } @@ -227,9 +222,8 @@ class AudioInputStreamWrapper { // Convenience method which creates a default AudioInputStream object. static AudioInputStream* CreateDefaultAudioInputStream( - AudioManager* audio_manager, - bool use_voice_processing) { - AudioInputStreamWrapper aisw(audio_manager, use_voice_processing); + AudioManager* audio_manager) { + AudioInputStreamWrapper aisw(audio_manager); AudioInputStream* ais = aisw.Create(); return ais; } @@ -264,9 +258,7 @@ class ScopedAudioInputStream { DISALLOW_COPY_AND_ASSIGN(ScopedAudioInputStream); }; -// The test class. The boolean parameter specifies if voice processing should be -// used. -class WinAudioInputTest : public ::testing::TestWithParam<bool> { +class WinAudioInputTest : public ::testing::Test { public: WinAudioInputTest() { audio_manager_ = @@ -300,28 +292,57 @@ TEST_F(WinAudioInputTest, WASAPIAudioInputStreamHardwareSampleRate) { } } +// Test effects. +TEST_F(WinAudioInputTest, WASAPIAudioInputStreamEffects) { + AudioDeviceInfoAccessorForTests device_info_accessor(audio_manager_.get()); + ABORT_AUDIO_TEST_IF_NOT(device_info_accessor.HasAudioInputDevices() && + device_info_accessor.HasAudioOutputDevices() && + CoreAudioUtil::IsSupported()); + + // Retrieve a list of all available input devices. + media::AudioDeviceDescriptions device_descriptions; + device_info_accessor.GetAudioInputDeviceDescriptions(&device_descriptions); + + // No device should have any effects. + for (const auto& device : device_descriptions) { + AudioParameters params = + device_info_accessor.GetInputStreamParameters(device.unique_id); + EXPECT_EQ(params.effects(), AudioParameters::NO_EFFECTS); + } + + // The two loopback devices are not included in the device description list + // above. They should also have no effects. + AudioParameters params = device_info_accessor.GetInputStreamParameters( + AudioDeviceDescription::kLoopbackInputDeviceId); + EXPECT_EQ(params.effects(), AudioParameters::NO_EFFECTS); + + params = device_info_accessor.GetInputStreamParameters( + AudioDeviceDescription::kLoopbackWithMuteDeviceId); + EXPECT_EQ(params.effects(), AudioParameters::NO_EFFECTS); +} + // Test Create(), Close() calling sequence. -TEST_P(WinAudioInputTest, WASAPIAudioInputStreamCreateAndClose) { +TEST_F(WinAudioInputTest, WASAPIAudioInputStreamCreateAndClose) { ABORT_AUDIO_TEST_IF_NOT(HasCoreAudioAndInputDevices(audio_manager_.get())); ScopedAudioInputStream ais( - CreateDefaultAudioInputStream(audio_manager_.get(), GetParam())); + CreateDefaultAudioInputStream(audio_manager_.get())); ais.Close(); } // Test Open(), Close() calling sequence. -TEST_P(WinAudioInputTest, WASAPIAudioInputStreamOpenAndClose) { +TEST_F(WinAudioInputTest, WASAPIAudioInputStreamOpenAndClose) { ABORT_AUDIO_TEST_IF_NOT(HasCoreAudioAndInputDevices(audio_manager_.get())); ScopedAudioInputStream ais( - CreateDefaultAudioInputStream(audio_manager_.get(), GetParam())); + CreateDefaultAudioInputStream(audio_manager_.get())); EXPECT_TRUE(ais->Open()); ais.Close(); } // Test Open(), Start(), Close() calling sequence. -TEST_P(WinAudioInputTest, WASAPIAudioInputStreamOpenStartAndClose) { +TEST_F(WinAudioInputTest, WASAPIAudioInputStreamOpenStartAndClose) { ABORT_AUDIO_TEST_IF_NOT(HasCoreAudioAndInputDevices(audio_manager_.get())); ScopedAudioInputStream ais( - CreateDefaultAudioInputStream(audio_manager_.get(), GetParam())); + CreateDefaultAudioInputStream(audio_manager_.get())); EXPECT_TRUE(ais->Open()); MockAudioInputCallback sink; ais->Start(&sink); @@ -329,10 +350,10 @@ TEST_P(WinAudioInputTest, WASAPIAudioInputStreamOpenStartAndClose) { } // Test Open(), Start(), Stop(), Close() calling sequence. -TEST_P(WinAudioInputTest, WASAPIAudioInputStreamOpenStartStopAndClose) { +TEST_F(WinAudioInputTest, WASAPIAudioInputStreamOpenStartStopAndClose) { ABORT_AUDIO_TEST_IF_NOT(HasCoreAudioAndInputDevices(audio_manager_.get())); ScopedAudioInputStream ais( - CreateDefaultAudioInputStream(audio_manager_.get(), GetParam())); + CreateDefaultAudioInputStream(audio_manager_.get())); EXPECT_TRUE(ais->Open()); MockAudioInputCallback sink; ais->Start(&sink); @@ -341,10 +362,10 @@ TEST_P(WinAudioInputTest, WASAPIAudioInputStreamOpenStartStopAndClose) { } // Test some additional calling sequences. -TEST_P(WinAudioInputTest, WASAPIAudioInputStreamMiscCallingSequences) { +TEST_F(WinAudioInputTest, WASAPIAudioInputStreamMiscCallingSequences) { ABORT_AUDIO_TEST_IF_NOT(HasCoreAudioAndInputDevices(audio_manager_.get())); ScopedAudioInputStream ais( - CreateDefaultAudioInputStream(audio_manager_.get(), GetParam())); + CreateDefaultAudioInputStream(audio_manager_.get())); // Open(), Open() should fail the second time. EXPECT_TRUE(ais->Open()); @@ -366,7 +387,7 @@ TEST_P(WinAudioInputTest, WASAPIAudioInputStreamMiscCallingSequences) { ais.Close(); } -TEST_P(WinAudioInputTest, WASAPIAudioInputStreamTestPacketSizes) { +TEST_F(WinAudioInputTest, WASAPIAudioInputStreamTestPacketSizes) { ABORT_AUDIO_TEST_IF_NOT(HasCoreAudioAndInputDevices(audio_manager_.get())); int count = 0; @@ -375,7 +396,7 @@ TEST_P(WinAudioInputTest, WASAPIAudioInputStreamTestPacketSizes) { // Create default WASAPI input stream which records in stereo using // the shared mixing rate. The default buffer size is 10ms. - AudioInputStreamWrapper aisw(audio_manager_.get(), GetParam()); + AudioInputStreamWrapper aisw(audio_manager_.get()); ScopedAudioInputStream ais(aisw.Create()); EXPECT_TRUE(ais->Open()); @@ -449,13 +470,13 @@ TEST_P(WinAudioInputTest, WASAPIAudioInputStreamTestPacketSizes) { } // Test that we can capture a stream in loopback. -TEST_P(WinAudioInputTest, WASAPIAudioInputStreamLoopback) { +TEST_F(WinAudioInputTest, WASAPIAudioInputStreamLoopback) { AudioDeviceInfoAccessorForTests device_info_accessor(audio_manager_.get()); ABORT_AUDIO_TEST_IF_NOT(device_info_accessor.HasAudioOutputDevices() && CoreAudioUtil::IsSupported()); AudioParameters params = device_info_accessor.GetInputStreamParameters( AudioDeviceDescription::kLoopbackInputDeviceId); - EXPECT_EQ(params.effects(), 0); + EXPECT_EQ(params.effects(), AudioParameters::NO_EFFECTS); AudioParameters output_params = device_info_accessor.GetOutputStreamParameters(std::string()); @@ -483,7 +504,7 @@ TEST_P(WinAudioInputTest, WASAPIAudioInputStreamLoopback) { // To include disabled tests in test execution, just invoke the test program // with --gtest_also_run_disabled_tests or set the GTEST_ALSO_RUN_DISABLED_TESTS // environment variable to a value greater than 0. -TEST_P(WinAudioInputTest, DISABLED_WASAPIAudioInputStreamRecordToFile) { +TEST_F(WinAudioInputTest, DISABLED_WASAPIAudioInputStreamRecordToFile) { ABORT_AUDIO_TEST_IF_NOT(HasCoreAudioAndInputDevices(audio_manager_.get())); // Name of the output PCM file containing captured data. The output file @@ -491,7 +512,7 @@ TEST_P(WinAudioInputTest, DISABLED_WASAPIAudioInputStreamRecordToFile) { // Example of full name: \src\build\Debug\out_stereo_10sec.pcm. const char* file_name = "out_10sec.pcm"; - AudioInputStreamWrapper aisw(audio_manager_.get(), GetParam()); + AudioInputStreamWrapper aisw(audio_manager_.get()); ScopedAudioInputStream ais(aisw.Create()); ASSERT_TRUE(ais->Open()); @@ -505,7 +526,7 @@ TEST_P(WinAudioInputTest, DISABLED_WASAPIAudioInputStreamRecordToFile) { ais.Close(); } -TEST_P(WinAudioInputTest, DISABLED_WASAPIAudioInputStreamResampleToFile) { +TEST_F(WinAudioInputTest, DISABLED_WASAPIAudioInputStreamResampleToFile) { ABORT_AUDIO_TEST_IF_NOT(HasCoreAudioAndInputDevices(audio_manager_.get())); // This is basically the same test as WASAPIAudioInputStreamRecordToFile @@ -540,8 +561,6 @@ TEST_P(WinAudioInputTest, DISABLED_WASAPIAudioInputStreamResampleToFile) { // Otherwise (e.g. 44.1kHz, 22.05kHz etc) we convert to 48kHz. const int hw_sample_rate = params.sample_rate(); params.Reset(params.format(), test.layout, test.rate, test.frames); - if (GetParam()) - params.set_effects(params.effects() | AudioParameters::ECHO_CANCELLER); std::string file_name(base::StringPrintf( "resampled_10sec_%i_to_%i_%s.pcm", hw_sample_rate, params.sample_rate(), @@ -565,8 +584,4 @@ TEST_P(WinAudioInputTest, DISABLED_WASAPIAudioInputStreamResampleToFile) { } } -INSTANTIATE_TEST_CASE_P(/* Intentially left empty */, - WinAudioInputTest, - ::testing::Bool()); - } // namespace media diff --git a/chromium/media/audio/win/audio_manager_win.cc b/chromium/media/audio/win/audio_manager_win.cc index d61781b625a..0d982488b62 100644 --- a/chromium/media/audio/win/audio_manager_win.cc +++ b/chromium/media/audio/win/audio_manager_win.cc @@ -23,7 +23,6 @@ #include "base/strings/string_number_conversions.h" #include "base/win/windows_version.h" #include "media/audio/audio_device_description.h" -#include "media/audio/audio_features.h" #include "media/audio/audio_io.h" #include "media/audio/win/audio_device_listener_win.h" #include "media/audio/win/audio_low_latency_input_win.h" @@ -107,8 +106,8 @@ AudioManagerWin::AudioManagerWin(std::unique_ptr<AudioThread> audio_thread, // audio thread. Unretained is safe since we join the audio thread before // destructing |this|. GetTaskRunner()->PostTask( - FROM_HERE, base::Bind(&AudioManagerWin::InitializeOnAudioThread, - base::Unretained(this))); + FROM_HERE, base::BindOnce(&AudioManagerWin::InitializeOnAudioThread, + base::Unretained(this))); } AudioManagerWin::~AudioManagerWin() = default; @@ -187,9 +186,6 @@ AudioParameters AudioManagerWin::GetInputStreamParameters( if (user_buffer_size) parameters.set_frames_per_buffer(user_buffer_size); - parameters.set_effects(parameters.effects() | - AudioParameters::EXPERIMENTAL_ECHO_CANCELLER); - return parameters; } @@ -260,14 +256,7 @@ AudioInputStream* AudioManagerWin::MakeLowLatencyInputStream( const LogCallback& log_callback) { // Used for both AUDIO_PCM_LOW_LATENCY and AUDIO_PCM_LINEAR. DVLOG(1) << "MakeLowLatencyInputStream: " << device_id; - - VoiceProcessingMode voice_processing_mode = - params.effects() & AudioParameters::ECHO_CANCELLER - ? VoiceProcessingMode::kEnabled - : VoiceProcessingMode::kDisabled; - - return new WASAPIAudioInputStream(this, params, device_id, log_callback, - voice_processing_mode); + return new WASAPIAudioInputStream(this, params, device_id, log_callback); } std::string AudioManagerWin::GetDefaultInputDeviceID() { diff --git a/chromium/media/audio/win/audio_output_win_unittest.cc b/chromium/media/audio/win/audio_output_win_unittest.cc index 73ea9caf58b..dc261937b36 100644 --- a/chromium/media/audio/win/audio_output_win_unittest.cc +++ b/chromium/media/audio/win/audio_output_win_unittest.cc @@ -189,43 +189,6 @@ TEST_F(WinAudioTest, PCMWaveStreamGetAndClose) { oas->Close(); } -// Test that can it be cannot be created with invalid parameters. -TEST_F(WinAudioTest, SanityOnMakeParams) { - ABORT_AUDIO_TEST_IF_NOT(audio_manager_device_info_->HasAudioOutputDevices()); - - AudioParameters::Format fmt = AudioParameters::AUDIO_PCM_LINEAR; - EXPECT_TRUE(NULL == - audio_manager_->MakeAudioOutputStream( - AudioParameters(fmt, CHANNEL_LAYOUT_UNSUPPORTED, 8000, 256), - std::string(), AudioManager::LogCallback())); - EXPECT_TRUE(NULL == - audio_manager_->MakeAudioOutputStream( - AudioParameters(fmt, CHANNEL_LAYOUT_MONO, 1024 * 1024, 256), - std::string(), AudioManager::LogCallback())); - EXPECT_TRUE(NULL == audio_manager_->MakeAudioOutputStream( - AudioParameters(fmt, CHANNEL_LAYOUT_STEREO, 0, 256), - std::string(), AudioManager::LogCallback())); - EXPECT_TRUE(NULL == - audio_manager_->MakeAudioOutputStream( - AudioParameters(fmt, CHANNEL_LAYOUT_UNSUPPORTED, 8000, 256), - std::string(), AudioManager::LogCallback())); - EXPECT_TRUE(NULL == - audio_manager_->MakeAudioOutputStream( - AudioParameters(fmt, CHANNEL_LAYOUT_STEREO, -8000, 256), - std::string(), AudioManager::LogCallback())); - EXPECT_TRUE(NULL == audio_manager_->MakeAudioOutputStream( - AudioParameters(fmt, CHANNEL_LAYOUT_MONO, 8000, -100), - std::string(), AudioManager::LogCallback())); - EXPECT_TRUE(NULL == audio_manager_->MakeAudioOutputStream( - AudioParameters(fmt, CHANNEL_LAYOUT_MONO, 8000, 0), - std::string(), AudioManager::LogCallback())); - EXPECT_TRUE(NULL == - audio_manager_->MakeAudioOutputStream( - AudioParameters(fmt, CHANNEL_LAYOUT_MONO, 8000, - media::limits::kMaxSamplesPerPacket + 1), - std::string(), AudioManager::LogCallback())); -} - // Test that it can be opened and closed. TEST_F(WinAudioTest, PCMWaveStreamOpenAndClose) { ABORT_AUDIO_TEST_IF_NOT(audio_manager_device_info_->HasAudioOutputDevices()); @@ -239,19 +202,6 @@ TEST_F(WinAudioTest, PCMWaveStreamOpenAndClose) { oas->Close(); } -// Test that it has a maximum packet size. -TEST_F(WinAudioTest, PCMWaveStreamOpenLimit) { - ABORT_AUDIO_TEST_IF_NOT(audio_manager_device_info_->HasAudioOutputDevices()); - - AudioOutputStream* oas = audio_manager_->MakeAudioOutputStream( - AudioParameters(AudioParameters::AUDIO_PCM_LINEAR, CHANNEL_LAYOUT_STEREO, - 8000, 1024 * 1024 * 1024), - std::string(), AudioManager::LogCallback()); - EXPECT_TRUE(NULL == oas); - if (oas) - oas->Close(); -} - // Test potential deadlock situation if the source is slow or blocks for some // time. The actual EXPECT_GT are mostly meaningless and the real test is that // the test completes in reasonable time. diff --git a/chromium/media/audio/win/core_audio_util_win.cc b/chromium/media/audio/win/core_audio_util_win.cc index 59869e9a879..fc681c8ac9d 100644 --- a/chromium/media/audio/win/core_audio_util_win.cc +++ b/chromium/media/audio/win/core_audio_util_win.cc @@ -180,15 +180,6 @@ std::ostream& operator<<(std::ostream& os, const WAVEFORMATPCMEX& format) { return os; } -bool LoadAudiosesDll() { - static const wchar_t* const kAudiosesDLL = - L"%WINDIR%\\system32\\audioses.dll"; - - wchar_t path[MAX_PATH] = {0}; - ExpandEnvironmentStringsW(kAudiosesDLL, path, arraysize(path)); - return (LoadLibraryExW(path, NULL, LOAD_WITH_ALTERED_SEARCH_PATH) != NULL); -} - std::string GetDeviceID(IMMDevice* device) { ScopedCoMem<WCHAR> device_id_com; std::string device_id; @@ -286,18 +277,7 @@ bool IsSupportedInternal() { return false; } - // The audio core APIs are implemented in the Mmdevapi.dll and - // Audioses.dll system components. Dependency Walker shows that it is - // enough to verify possibility to load the Audioses DLL since it depends - // on Mmdevapi.dll. See http://crbug.com/166397 why this extra step is - // required to guarantee Core Audio support. - if (!LoadAudiosesDll()) - return false; - - // Being able to load the Audioses.dll does not seem to be sufficient for - // all devices to guarantee Core Audio support. To be 100%, we also verify - // that it is possible to a create the IMMDeviceEnumerator interface. If - // this works as well we should be home free. + // Verify that it is possible to a create the IMMDeviceEnumerator interface. ComPtr<IMMDeviceEnumerator> device_enumerator = CreateDeviceEnumeratorInternal(false, base::BindRepeating(&LogUMAEmptyCb)); @@ -922,71 +902,4 @@ bool CoreAudioUtil::FillRenderEndpointBufferWithSilence( return true; } -HRESULT CoreAudioUtil::GetDeviceCollectionIndex(const std::string& device_id, - EDataFlow data_flow, - WORD* index) { - ComPtr<IMMDeviceEnumerator> enumerator = CreateDeviceEnumerator(); - if (!enumerator.Get()) { - DLOG(ERROR) << "Failed to create device enumerator."; - return E_FAIL; - } - - ComPtr<IMMDeviceCollection> device_collection; - HRESULT hr = enumerator->EnumAudioEndpoints(data_flow, DEVICE_STATE_ACTIVE, - &device_collection); - if (FAILED(hr)) { - DLOG(ERROR) << "Failed to get device collection."; - return hr; - } - - UINT number_of_devices = 0; - hr = device_collection->GetCount(&number_of_devices); - if (FAILED(hr)) { - DLOG(ERROR) << "Failed to get device collection count."; - return hr; - } - - ComPtr<IMMDevice> device; - for (WORD i = 0; i < number_of_devices; ++i) { - hr = device_collection->Item(i, &device); - if (FAILED(hr)) { - DLOG(WARNING) << "Failed to get device."; - continue; - } - ScopedCoMem<WCHAR> current_device_id; - hr = device->GetId(¤t_device_id); - if (FAILED(hr)) { - DLOG(WARNING) << "Failed to get device id."; - continue; - } - if (base::UTF16ToUTF8(current_device_id.get()) == device_id) { - *index = i; - return S_OK; - } - } - - DVLOG(1) << "No matching device found."; - return S_FALSE; -} - -HRESULT CoreAudioUtil::SetBoolProperty(IPropertyStore* property_store, - REFPROPERTYKEY key, - VARIANT_BOOL value) { - base::win::ScopedPropVariant pv; - PROPVARIANT* pv_ptr = pv.Receive(); - pv_ptr->vt = VT_BOOL; - pv_ptr->boolVal = value; - return property_store->SetValue(key, pv.get()); -} - -HRESULT CoreAudioUtil::SetVtI4Property(IPropertyStore* property_store, - REFPROPERTYKEY key, - LONG value) { - base::win::ScopedPropVariant pv; - PROPVARIANT* pv_ptr = pv.Receive(); - pv_ptr->vt = VT_I4; - pv_ptr->lVal = value; - return property_store->SetValue(key, pv.get()); -} - } // namespace media diff --git a/chromium/media/audio/win/core_audio_util_win.h b/chromium/media/audio/win/core_audio_util_win.h index 6a2b0dabb65..8a3174b36df 100644 --- a/chromium/media/audio/win/core_audio_util_win.h +++ b/chromium/media/audio/win/core_audio_util_win.h @@ -207,23 +207,6 @@ class MEDIA_EXPORT CoreAudioUtil { static bool FillRenderEndpointBufferWithSilence( IAudioClient* client, IAudioRenderClient* render_client); - // Gets the device collection index for the device specified by |device_id|. - // If the device is found in the device collection, the index is written to - // |*index| and S_OK is returned. If the device is not found, S_FALSE is - // returned and |*index| is left unchanged. In case of an error, the error - // result is returned and |*index| is left unchanged. - static HRESULT GetDeviceCollectionIndex(const std::string& device_id, - EDataFlow data_flow, - WORD* index); - - // Sets the property identified by |key| to |value| in |*property_store|. - static HRESULT SetBoolProperty(IPropertyStore* property_store, - REFPROPERTYKEY key, - VARIANT_BOOL value); - static HRESULT SetVtI4Property(IPropertyStore* property_store, - REFPROPERTYKEY key, - LONG value); - private: CoreAudioUtil() {} ~CoreAudioUtil() {} diff --git a/chromium/media/audio/win/device_enumeration_win.cc b/chromium/media/audio/win/device_enumeration_win.cc index 3a3a04dfc82..e23128e9d4f 100644 --- a/chromium/media/audio/win/device_enumeration_win.cc +++ b/chromium/media/audio/win/device_enumeration_win.cc @@ -89,12 +89,12 @@ static bool GetDeviceNamesWinImpl(EDataFlow data_flow, device.device_name = base::WideToUTF8(friendly_name.get().pwszVal); } - // Append VID/PID to USB devices. + // Append suffix to USB and Bluetooth devices. std::string controller_id = CoreAudioUtil::GetAudioControllerID( audio_device.Get(), enumerator.Get()); - std::string vid_pid_suffix = GetUsbVidPidSuffixWin(controller_id); - if (!vid_pid_suffix.empty()) - device.device_name += vid_pid_suffix; + std::string suffix = GetDeviceSuffixWin(controller_id); + if (!suffix.empty()) + device.device_name += suffix; } // Add combination of user-friendly and unique name to the output list. @@ -165,14 +165,19 @@ bool GetOutputDeviceNamesWinXP(AudioDeviceNames* device_names) { waveOutGetDevCapsW>(device_names); } -std::string GetUsbVidPidSuffixWin(const std::string& controller_id) { - std::string vid_pid; +std::string GetDeviceSuffixWin(const std::string& controller_id) { + std::string suffix; if (controller_id.size() >= 21 && controller_id.substr(0, 8) == "USB\\VID_" && controller_id.substr(12, 5) == "&PID_") { - vid_pid = " (" + base::ToLowerASCII(controller_id.substr(8, 4)) + ":" + - base::ToLowerASCII(controller_id.substr(17, 4)) + ")"; + suffix = " (" + base::ToLowerASCII(controller_id.substr(8, 4)) + ":" + + base::ToLowerASCII(controller_id.substr(17, 4)) + ")"; + } else if ((controller_id.size() >= 22 && + controller_id.substr(0, 22) == "BTHHFENUM\\BthHFPAudio\\") || + (controller_id.size() >= 8 && + controller_id.substr(0, 8) == "BTHENUM\\")) { + suffix = " (Bluetooth)"; } - return vid_pid; + return suffix; } } // namespace media diff --git a/chromium/media/audio/win/device_enumeration_win.h b/chromium/media/audio/win/device_enumeration_win.h index e7443a4b0f7..25c162b96ea 100644 --- a/chromium/media/audio/win/device_enumeration_win.h +++ b/chromium/media/audio/win/device_enumeration_win.h @@ -30,15 +30,17 @@ bool GetOutputDeviceNamesWin(media::AudioDeviceNames* device_names); // - unique_id: "Microphone (Realtek High Defini" (same as friendly name). bool GetOutputDeviceNamesWinXP(media::AudioDeviceNames* device_names); -// Given a string |controller_id| with the controller ID of a USB device, -// returns a string containing the device's VID and PID. -// The format of the string is " (vid:pid)", with vid and pid being 4-character -// lowercase hexadecimal numbers. This string is intended to be appended to a -// device-name string without any further formatting. -// If |controller_id| does not refer to a USB device, this function returns an -// empty string. -MEDIA_EXPORT std::string GetUsbVidPidSuffixWin( - const std::string& controller_id); +// Given a string |controller_id| with the controller ID of an audio device, +// returns a string containing extra information about the device. +// If the device is a USB device, the format of the returned string is +// " (vid:pid)", with vid and pid being 4-character lowercase hexadecimal +// numbers. +// If the device is a Bluetooth device, the returned string is " (Bluetooth)". +// This string is intended to be appended to a device-name string without any +// further formatting. +// If |controller_id| does not refer to a USB or Bluetooth device, this +// function returns an empty string. +MEDIA_EXPORT std::string GetDeviceSuffixWin(const std::string& controller_id); } // namespace media diff --git a/chromium/media/audio/win/device_enumeration_win_unittest.cc b/chromium/media/audio/win/device_enumeration_win_unittest.cc index 8f13727645a..0585df46e4b 100644 --- a/chromium/media/audio/win/device_enumeration_win_unittest.cc +++ b/chromium/media/audio/win/device_enumeration_win_unittest.cc @@ -8,38 +8,38 @@ namespace media { -TEST(DeviceEnumerationWin, GetUsbVidPidSuffix) { +TEST(DeviceEnumerationWin, GetDeviceSuffix) { // Some real-world USB devices EXPECT_EQ( - GetUsbVidPidSuffixWin("USB\\VID_046D&PID_09A6&MI_02\\6&318d810e&1&0002"), + GetDeviceSuffixWin("USB\\VID_046D&PID_09A6&MI_02\\6&318d810e&1&0002"), " (046d:09a6)"); - EXPECT_EQ(GetUsbVidPidSuffixWin("USB\\VID_8087&PID_07DC&REV_0001"), + EXPECT_EQ(GetDeviceSuffixWin("USB\\VID_8087&PID_07DC&REV_0001"), " (8087:07dc)"); - EXPECT_EQ(GetUsbVidPidSuffixWin("USB\\VID_0403&PID_6010"), " (0403:6010)"); + EXPECT_EQ(GetDeviceSuffixWin("USB\\VID_0403&PID_6010"), " (0403:6010)"); - // Some real-world non-USB devices - EXPECT_TRUE( - GetUsbVidPidSuffixWin("BTHHFENUM\\BthHFPAudio\\8&39e29755&0&97").empty()); - EXPECT_TRUE(GetUsbVidPidSuffixWin("BTHENUM\\{0000110b-0000-1000-8000-" - "00805f9b34fb}_LOCALMFG&0002\\7&25f92e87&0&" - "70886B900BB0_C00000000") + // Some real-world Bluetooth devices + EXPECT_EQ(GetDeviceSuffixWin("BTHHFENUM\\BthHFPAudio\\8&39e29755&0&97"), + " (Bluetooth)"); + EXPECT_EQ(GetDeviceSuffixWin("BTHENUM\\{0000110b-0000-1000-8000-" + "00805f9b34fb}_LOCALMFG&0002\\7&25f92e87&0&" + "70886B900BB0_C00000000"), + " (Bluetooth)"); + + // Other real-world devices + EXPECT_TRUE(GetDeviceSuffixWin("INTELAUDIO\\FUNC_01&VEN_8086&DEV_280B&SUBSYS_" + "80860101&REV_1000\\4&c083774&0&0201") + .empty()); + EXPECT_TRUE(GetDeviceSuffixWin("INTELAUDIO\\FUNC_01&VEN_10EC&DEV_0298&SUBSYS_" + "102807BF&REV_1001\\4&c083774&0&0001") .empty()); EXPECT_TRUE( - GetUsbVidPidSuffixWin("INTELAUDIO\\FUNC_01&VEN_8086&DEV_280B&SUBSYS_" - "80860101&REV_1000\\4&c083774&0&0201") - .empty()); - EXPECT_TRUE( - GetUsbVidPidSuffixWin("INTELAUDIO\\FUNC_01&VEN_10EC&DEV_0298&SUBSYS_" - "102807BF&REV_1001\\4&c083774&0&0001") + GetDeviceSuffixWin("PCI\\VEN_1000&DEV_0001&SUBSYS_00000000&REV_02\\1&08") .empty()); - EXPECT_TRUE(GetUsbVidPidSuffixWin( - "PCI\\VEN_1000&DEV_0001&SUBSYS_00000000&REV_02\\1&08") - .empty()); // Other input strings. - EXPECT_TRUE(GetUsbVidPidSuffixWin(std::string()).empty()); - EXPECT_TRUE(GetUsbVidPidSuffixWin(" ").empty()); - EXPECT_TRUE(GetUsbVidPidSuffixWin("USBVID_1234&PID1234").empty()); + EXPECT_TRUE(GetDeviceSuffixWin(std::string()).empty()); + EXPECT_TRUE(GetDeviceSuffixWin(" ").empty()); + EXPECT_TRUE(GetDeviceSuffixWin("USBVID_1234&PID1234").empty()); } } // namespace media |