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

Unified Diff: content/browser/renderer_host/media/audio_input_device_manager.cc

Issue 2763383002: Switching AudioInputDeviceManager from using AudioManager interface to AudioSystem one. (Closed)
Patch Set: Created 3 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: content/browser/renderer_host/media/audio_input_device_manager.cc
diff --git a/content/browser/renderer_host/media/audio_input_device_manager.cc b/content/browser/renderer_host/media/audio_input_device_manager.cc
index 4ad35755240e59932c8d60e8e8998c3eca558254..9aea4b3d4d8bb6e2d1049e21c9c5da1d0b48edb6 100644
--- a/content/browser/renderer_host/media/audio_input_device_manager.cc
+++ b/content/browser/renderer_host/media/audio_input_device_manager.cc
@@ -8,13 +8,15 @@
#include "base/bind.h"
#include "base/command_line.h"
+#include "base/memory/ptr_util.h"
#include "base/metrics/histogram_macros.h"
#include "build/build_config.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/common/media_stream_request.h"
#include "media/audio/audio_input_ipc.h"
-#include "media/audio/audio_manager_base.h"
+#include "media/audio/audio_system.h"
#include "media/base/audio_parameters.h"
+#include "media/base/bind_to_current_loop.h"
#include "media/base/channel_layout.h"
#include "media/base/media_switches.h"
@@ -29,20 +31,199 @@ const int AudioInputDeviceManager::kFakeOpenSessionId = 1;
namespace {
// Starting id for the first capture session.
const int kFirstSessionId = AudioInputDeviceManager::kFakeOpenSessionId + 1;
+
+// The object of this class lives on AudioSystem thread and at each given
+// moment is owned by a callback it posted to that thread.
+class DeviceOpener {
+ public:
+ using OnOpenedCallback = base::Callback<void(const StreamDeviceInfo&)>;
+
+ ~DeviceOpener();
+
+ // Wwill reply with |on_opened_cb| on the thread Open() is called on.
Max Morin 2017/03/22 17:46:24 Typo Wwill
+ static void Open(media::AudioSystem* audio_system,
+ const MediaStreamDevice& device,
+ int session_id,
+ OnOpenedCallback on_opened_cb);
+
+ protected:
+ DeviceOpener(media::AudioSystem* audio_system,
+ const MediaStreamDevice& device,
+ int session_id,
+ OnOpenedCallback on_opened_cb);
+
+ private:
+ void DoOpen(std::unique_ptr<DeviceOpener> owned_this);
+ void OpenWithMatchedOutputId(std::unique_ptr<DeviceOpener> owned_this,
+ const std::string& matched_output_id);
+ void OpenWithInputParams(std::unique_ptr<DeviceOpener> owned_this,
+ const media::AudioParameters& params);
+ void OpenWithOutputParams(std::unique_ptr<DeviceOpener> owned_this,
+ const media::AudioParameters& params);
+ void ReplyOpened();
+
+ base::WeakPtr<media::AudioSystem> audio_system_;
+ base::TimeTicks start_time_;
+ OnOpenedCallback on_opened_cb_;
+ StreamDeviceInfo info_;
+
+ DISALLOW_COPY_AND_ASSIGN(DeviceOpener);
+};
+
+DeviceOpener::DeviceOpener(media::AudioSystem* audio_system,
+ const MediaStreamDevice& device,
+ int session_id,
+ OnOpenedCallback on_opened_cb)
+ : audio_system_(audio_system->GetWeakPtr()),
+ on_opened_cb_(std::move(on_opened_cb)),
+ info_(device.type, device.name, device.id, 0, 0, 0) {
+ info_.session_id = session_id;
+}
+
+DeviceOpener::~DeviceOpener() {
+ if (!audio_system_)
+ return;
+ DCHECK(audio_system_->GetTaskRunner()->BelongsToCurrentThread());
+
+ // Do not ReplyOpened() here, since destructor may be called on message
+ // loop destruction before callback runs.
+
+ DCHECK(start_time_ == base::TimeTicks() ||
+ (base::TimeTicks::Now() - start_time_).InSeconds() < 30)
+ << "DeviceOpener hang";
+}
+
+// static
+void DeviceOpener::Open(media::AudioSystem* audio_system,
+ const MediaStreamDevice& device,
+ int session_id,
+ OnOpenedCallback on_opened_cb) {
+ DCHECK(audio_system);
+
+ std::unique_ptr<DeviceOpener> opener(
+ new DeviceOpener(audio_system, device, session_id,
+ media::BindToCurrentLoop(on_opened_cb)));
+
+ audio_system->GetTaskRunner()->PostTask(
+ FROM_HERE,
+ base::Bind(&DeviceOpener::DoOpen, base::Unretained(opener.get()),
+ base::Passed(&opener)));
+}
+
+void DeviceOpener::DoOpen(std::unique_ptr<DeviceOpener> owned_this) {
+ if (!audio_system_)
+ return;
+ DCHECK(audio_system_->GetTaskRunner()->BelongsToCurrentThread());
+
+ start_time_ = base::TimeTicks::Now();
+
+ audio_system_->GetAssociatedOutputDeviceID(
+ info_.device.id,
+ base::Bind(&DeviceOpener::OpenWithMatchedOutputId, base::Unretained(this),
+ base::Passed(&owned_this)));
+}
+
+void DeviceOpener::OpenWithMatchedOutputId(
+ std::unique_ptr<DeviceOpener> owned_this,
+ const std::string& matched_output_id) {
+ if (!audio_system_)
+ return;
+ DCHECK(audio_system_->GetTaskRunner()->BelongsToCurrentThread());
+
+ info_.device.matched_output_device_id = matched_output_id;
+
+ if (!base::CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kUseFakeDeviceForMediaStream)) {
+ audio_system_->GetInputStreamParameters(
+ info_.device.id,
+ base::Bind(&DeviceOpener::OpenWithInputParams, base::Unretained(this),
+ base::Passed(&owned_this)));
+ return;
+ }
+
+ // Don't need to query the hardware information if using fake device.
+ info_.device.input.sample_rate = 44100;
+ info_.device.input.channel_layout = media::CHANNEL_LAYOUT_STEREO;
+ if (!info_.device.matched_output_device_id.empty()) {
+ info_.device.matched_output.sample_rate = 44100;
+ info_.device.matched_output.channel_layout = media::CHANNEL_LAYOUT_STEREO;
+ }
+ ReplyOpened();
+}
+
+void DeviceOpener::OpenWithInputParams(std::unique_ptr<DeviceOpener> owned_this,
+ const media::AudioParameters& params) {
+ if (!audio_system_)
+ return;
+ DCHECK(audio_system_->GetTaskRunner()->BelongsToCurrentThread());
+
+ // TODO(tommi): As is, we hit this code path when device.type is
+ // MEDIA_TAB_AUDIO_CAPTURE and the device id is not a device that
+ // the AudioManager can know about. This currently does not fail because
+ // the implementation of GetInputStreamParameters returns valid parameters
+ // by default for invalid devices. That behavior is problematic because it
+ // causes other parts of the code to attempt to open truly invalid or
+ // missing devices and falling back on alternate devices (and likely fail
+ // twice in a row). Tab audio capture should not pass through here and
+ // GetInputStreamParameters should return invalid parameters for invalid
+ // devices.
+
+ // Get the preferred sample rate and channel configuration for the
+ // audio device.
+ info_.device.input.sample_rate = params.sample_rate();
+ info_.device.input.channel_layout = params.channel_layout();
+ info_.device.input.frames_per_buffer = params.frames_per_buffer();
+ info_.device.input.effects = params.effects();
+ info_.device.input.mic_positions = params.mic_positions();
+
+ if (info_.device.matched_output_device_id.empty()) {
+ ReplyOpened();
+ return;
+ }
+
+ audio_system_->GetOutputStreamParameters(
+ info_.device.matched_output_device_id,
+ base::Bind(&DeviceOpener::OpenWithOutputParams, base::Unretained(this),
+ base::Passed(&owned_this)));
+}
+
+void DeviceOpener::OpenWithOutputParams(
+ std::unique_ptr<DeviceOpener> owned_this,
+ const media::AudioParameters& params) {
+ if (!audio_system_)
+ return;
+ DCHECK(audio_system_->GetTaskRunner()->BelongsToCurrentThread());
+
+ info_.device.matched_output.sample_rate = params.sample_rate();
+ info_.device.matched_output.channel_layout = params.channel_layout();
+ info_.device.matched_output.frames_per_buffer = params.frames_per_buffer();
+ ReplyOpened();
}
+void DeviceOpener::ReplyOpened() {
+ if (!audio_system_)
+ return;
+ DCHECK(audio_system_->GetTaskRunner()->BelongsToCurrentThread());
+
+ DCHECK(start_time_ > base::TimeTicks());
+ UMA_HISTOGRAM_TIMES("Media.AudioInputDeviceManager.OpenOnDeviceThreadTime",
o1ka 2017/03/22 17:09:33 TODO: Make sure UMA meaning is unchanged. Add UMA
+ base::TimeTicks::Now() - start_time_);
+ std::move(on_opened_cb_).Run(info_);
+ start_time_ = base::TimeTicks();
+}
+
+} // namespace
+
AudioInputDeviceManager::AudioInputDeviceManager(
- media::AudioManager* audio_manager)
+ media::AudioSystem* audio_system)
: next_capture_session_id_(kFirstSessionId),
#if defined(OS_CHROMEOS)
keyboard_mic_streams_count_(0),
#endif
- audio_manager_(audio_manager),
- device_task_runner_(audio_manager_->GetTaskRunner()) {
+ audio_system_(audio_system) {
}
-AudioInputDeviceManager::~AudioInputDeviceManager() {
-}
+AudioInputDeviceManager::~AudioInputDeviceManager() {}
const StreamDeviceInfo* AudioInputDeviceManager::GetOpenedDeviceInfoById(
int session_id) {
@@ -58,7 +239,6 @@ void AudioInputDeviceManager::RegisterListener(
MediaStreamProviderListener* listener) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
DCHECK(listener);
- DCHECK(device_task_runner_);
listeners_.AddObserver(listener);
}
@@ -73,10 +253,9 @@ int AudioInputDeviceManager::Open(const MediaStreamDevice& device) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
// Generate a new id for this device.
int session_id = next_capture_session_id_++;
- device_task_runner_->PostTask(
- FROM_HERE,
- base::Bind(&AudioInputDeviceManager::OpenOnDeviceThread,
- this, session_id, device));
+ DeviceOpener::Open(
+ audio_system_, device, session_id,
+ base::Bind(&AudioInputDeviceManager::OpenedOnIOThread, this, session_id));
return session_id;
}
@@ -135,72 +314,6 @@ void AudioInputDeviceManager::UnregisterKeyboardMicStream() {
}
#endif
-void AudioInputDeviceManager::OpenOnDeviceThread(
- int session_id,
- const MediaStreamDevice& device) {
- SCOPED_UMA_HISTOGRAM_TIMER(
- "Media.AudioInputDeviceManager.OpenOnDeviceThreadTime");
- DCHECK(IsOnDeviceThread());
-
- StreamDeviceInfo out(device.type, device.name, device.id, 0, 0, 0);
- out.session_id = session_id;
-
- MediaStreamDevice::AudioDeviceParameters& input_params = out.device.input;
-
- // Add preferred output device information if a matching output device
- // exists.
- out.device.matched_output_device_id =
- audio_manager_->GetAssociatedOutputDeviceID(device.id);
-
- if (base::CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kUseFakeDeviceForMediaStream)) {
- // Don't need to query the hardware information if using fake device.
- input_params.sample_rate = 44100;
- input_params.channel_layout = media::CHANNEL_LAYOUT_STEREO;
- if (!out.device.matched_output_device_id.empty()) {
- out.device.matched_output.sample_rate = 44100;
- out.device.matched_output.channel_layout = media::CHANNEL_LAYOUT_STEREO;
- }
- } else {
- // TODO(tommi): As is, we hit this code path when device.type is
- // MEDIA_TAB_AUDIO_CAPTURE and the device id is not a device that
- // the AudioManager can know about. This currently does not fail because
- // the implementation of GetInputStreamParameters returns valid parameters
- // by default for invalid devices. That behavior is problematic because it
- // causes other parts of the code to attempt to open truly invalid or
- // missing devices and falling back on alternate devices (and likely fail
- // twice in a row). Tab audio capture should not pass through here and
- // GetInputStreamParameters should return invalid parameters for invalid
- // devices.
-
- // Get the preferred sample rate and channel configuration for the
- // audio device.
- media::AudioParameters params =
- audio_manager_->GetInputStreamParameters(device.id);
- input_params.sample_rate = params.sample_rate();
- input_params.channel_layout = params.channel_layout();
- input_params.frames_per_buffer = params.frames_per_buffer();
- input_params.effects = params.effects();
- input_params.mic_positions = params.mic_positions();
- if (!out.device.matched_output_device_id.empty()) {
- params = audio_manager_->GetOutputStreamParameters(
- out.device.matched_output_device_id);
- MediaStreamDevice::AudioDeviceParameters& matched_output_params =
- out.device.matched_output;
- matched_output_params.sample_rate = params.sample_rate();
- matched_output_params.channel_layout = params.channel_layout();
- matched_output_params.frames_per_buffer = params.frames_per_buffer();
- }
- }
-
- // Return the |session_id| through the listener by posting a task on
- // IO thread since MediaStreamManager handles the callback asynchronously.
- BrowserThread::PostTask(BrowserThread::IO,
- FROM_HERE,
- base::Bind(&AudioInputDeviceManager::OpenedOnIOThread,
- this, session_id, out));
-}
-
void AudioInputDeviceManager::OpenedOnIOThread(int session_id,
const StreamDeviceInfo& info) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
@@ -220,10 +333,6 @@ void AudioInputDeviceManager::ClosedOnIOThread(MediaStreamType stream_type,
listener.Closed(stream_type, session_id);
}
-bool AudioInputDeviceManager::IsOnDeviceThread() const {
- return device_task_runner_->BelongsToCurrentThread();
-}
-
AudioInputDeviceManager::StreamDeviceList::iterator
AudioInputDeviceManager::GetDevice(int session_id) {
for (StreamDeviceList::iterator i(devices_.begin()); i != devices_.end();
@@ -243,5 +352,4 @@ void AudioInputDeviceManager::SetKeyboardMicStreamActiveOnUIThread(
}
#endif
-
} // namespace content

Powered by Google App Engine
This is Rietveld 408576698