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

Unified Diff: media/audio/audio_input_controller.cc

Issue 2665163002: Refactor AudioInputController and split stat by stream type. (Closed)
Patch Set: Compile Created 3 years, 10 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
« no previous file with comments | « media/audio/audio_input_controller.h ('k') | media/audio/audio_input_controller_unittest.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: media/audio/audio_input_controller.cc
diff --git a/media/audio/audio_input_controller.cc b/media/audio/audio_input_controller.cc
index 8a969b188a16fd1f57a519bc4223b84796647470..7eef001eed1dcd60fab0f014aa2c411659f1b5e2 100644
--- a/media/audio/audio_input_controller.cc
+++ b/media/audio/audio_input_controller.cc
@@ -19,7 +19,6 @@
#include "base/threading/thread_task_runner_handle.h"
#include "base/time/time.h"
#include "base/trace_event/trace_event.h"
-#include "media/audio/audio_file_writer.h"
#include "media/base/user_input_monitor.h"
namespace media {
@@ -143,8 +142,8 @@ class AudioInputController::AudioCallback
// that get returned to us somehow.
// We should also avoid calling PostTask here since the implementation
// of the debug writer will basically do a PostTask straight away anyway.
- // Might require some modifications to AudioInputDebugWriter though since
- // there are some threading concerns there and AudioInputDebugWriter's
+ // Might require some modifications to AudioFileWriter though since
+ // there are some threading concerns there and AudioFileWriter's
// lifetime guarantees need to be longer than that of associated active
// audio streams.
std::unique_ptr<AudioBus> source_copy =
@@ -198,21 +197,14 @@ AudioInputController::AudioInputController(
SyncWriter* sync_writer,
std::unique_ptr<AudioFileWriter> debug_writer,
UserInputMonitor* user_input_monitor,
- const bool agc_is_enabled)
+ StreamType type)
: creator_task_runner_(base::ThreadTaskRunnerHandle::Get()),
task_runner_(std::move(task_runner)),
handler_(handler),
stream_(nullptr),
sync_writer_(sync_writer),
- max_volume_(0.0),
+ type_(type),
user_input_monitor_(user_input_monitor),
- agc_is_enabled_(agc_is_enabled),
-#if defined(AUDIO_POWER_MONITORING)
- power_measurement_is_enabled_(false),
- log_silence_state_(false),
- silence_state_(SILENCE_STATE_NO_MEASUREMENT),
-#endif
- prev_key_down_count_(0),
debug_writer_(std::move(debug_writer)),
weak_ptr_factory_(this) {
DCHECK(creator_task_runner_.get());
@@ -230,51 +222,11 @@ scoped_refptr<AudioInputController> AudioInputController::Create(
AudioManager* audio_manager,
EventHandler* event_handler,
SyncWriter* sync_writer,
+ UserInputMonitor* user_input_monitor,
+ std::unique_ptr<AudioFileWriter> debug_writer,
const AudioParameters& params,
const std::string& device_id,
- UserInputMonitor* user_input_monitor) {
- DCHECK(audio_manager);
- DCHECK(event_handler);
- DCHECK(sync_writer);
-
- if (!params.IsValid() || (params.channels() > kMaxInputChannels))
- return nullptr;
-
- if (factory_) {
- return factory_->Create(audio_manager->GetTaskRunner(), sync_writer,
- audio_manager, event_handler, params,
- user_input_monitor);
- }
-
- scoped_refptr<AudioInputController> controller(new AudioInputController(
- audio_manager->GetTaskRunner(), event_handler, sync_writer, nullptr,
- user_input_monitor, false));
-
- // Create and open a new audio input stream from the existing
- // audio-device thread.
- if (!controller->task_runner_->PostTask(
- FROM_HERE,
- base::Bind(&AudioInputController::DoCreate,
- controller,
- base::Unretained(audio_manager),
- params,
- device_id))) {
- controller = nullptr;
- }
-
- return controller;
-}
-
-// static
-scoped_refptr<AudioInputController> AudioInputController::CreateLowLatency(
- AudioManager* audio_manager,
- EventHandler* event_handler,
- const AudioParameters& params,
- const std::string& device_id,
- SyncWriter* sync_writer,
- std::unique_ptr<AudioFileWriter> debug_writer,
- UserInputMonitor* user_input_monitor,
- const bool agc_is_enabled) {
+ bool enable_agc) {
DCHECK(audio_manager);
DCHECK(sync_writer);
DCHECK(event_handler);
@@ -285,24 +237,21 @@ scoped_refptr<AudioInputController> AudioInputController::CreateLowLatency(
if (factory_) {
return factory_->Create(audio_manager->GetTaskRunner(), sync_writer,
audio_manager, event_handler, params,
- user_input_monitor);
+ user_input_monitor, ParamsToStreamType(params));
}
// Create the AudioInputController object and ensure that it runs on
// the audio-manager thread.
scoped_refptr<AudioInputController> controller(new AudioInputController(
audio_manager->GetTaskRunner(), event_handler, sync_writer,
- std::move(debug_writer), user_input_monitor, agc_is_enabled));
+ std::move(debug_writer), user_input_monitor, ParamsToStreamType(params)));
// Create and open a new audio input stream from the existing
// audio-device thread. Use the provided audio-input device.
if (!controller->task_runner_->PostTask(
- FROM_HERE,
- base::Bind(&AudioInputController::DoCreateForLowLatency,
- controller,
- base::Unretained(audio_manager),
- params,
- device_id))) {
+ FROM_HERE, base::Bind(&AudioInputController::DoCreate, controller,
+ base::Unretained(audio_manager), params,
+ device_id, enable_agc))) {
controller = nullptr;
}
@@ -322,20 +271,21 @@ scoped_refptr<AudioInputController> AudioInputController::CreateForStream(
DCHECK(event_handler);
if (factory_) {
- return factory_->Create(
- task_runner, sync_writer, AudioManager::Get(), event_handler,
- AudioParameters::UnavailableDeviceParams(), user_input_monitor);
+ return factory_->Create(task_runner, sync_writer, AudioManager::Get(),
+ event_handler,
+ AudioParameters::UnavailableDeviceParams(),
+ user_input_monitor, VIRTUAL);
}
// Create the AudioInputController object and ensure that it runs on
// the audio-manager thread.
scoped_refptr<AudioInputController> controller(new AudioInputController(
task_runner, event_handler, sync_writer, std::move(debug_writer),
- user_input_monitor, false));
+ user_input_monitor, VIRTUAL));
if (!controller->task_runner_->PostTask(
FROM_HERE, base::Bind(&AudioInputController::DoCreateForStream,
- controller, stream, false))) {
+ controller, stream, /*enable_agc*/ false))) {
controller = nullptr;
}
@@ -364,80 +314,57 @@ void AudioInputController::SetVolume(double volume) {
void AudioInputController::DoCreate(AudioManager* audio_manager,
const AudioParameters& params,
- const std::string& device_id) {
+ const std::string& device_id,
+ bool enable_agc) {
DCHECK(task_runner_->BelongsToCurrentThread());
DCHECK(!stream_);
SCOPED_UMA_HISTOGRAM_TIMER("Media.AudioInputController.CreateTime");
handler_->OnLog(this, "AIC::DoCreate");
#if defined(AUDIO_POWER_MONITORING)
- // Disable power monitoring for streams that run without AGC enabled to
- // avoid adding logs and UMA for non-WebRTC clients.
- power_measurement_is_enabled_ = agc_is_enabled_;
+ // We only do power measurements for UMA stats for low latency streams, and
+ // only if agc is requested, to avoid adding logs and UMA for non-WebRTC
+ // clients.
+ power_measurement_is_enabled_ = (type_ == LOW_LATENCY && enable_agc);
last_audio_level_log_time_ = base::TimeTicks::Now();
- silence_state_ = SILENCE_STATE_NO_MEASUREMENT;
#endif
// MakeAudioInputStream might fail and return nullptr. If so,
// DoCreateForStream will handle and report it.
auto* stream = audio_manager->MakeAudioInputStream(
params, device_id, base::Bind(&AudioInputController::LogMessage, this));
- DoCreateForStream(stream,
- params.format() == AudioParameters::AUDIO_PCM_LOW_LATENCY);
-}
-
-void AudioInputController::DoCreateForLowLatency(AudioManager* audio_manager,
- const AudioParameters& params,
- const std::string& device_id) {
- DCHECK(task_runner_->BelongsToCurrentThread());
-
-#if defined(AUDIO_POWER_MONITORING)
- // We only log silence state UMA stats for low latency mode and if we use a
- // real device.
- if (params.format() != AudioParameters::AUDIO_FAKE)
- log_silence_state_ = true;
-#endif
-
- // Set the low latency timer to non-null. It'll be reset when capture starts.
- low_latency_create_time_ = base::TimeTicks::Now();
- DoCreate(audio_manager, params, device_id);
+ DoCreateForStream(stream, enable_agc);
}
void AudioInputController::DoCreateForStream(
AudioInputStream* stream_to_control,
- bool low_latency) {
+ bool enable_agc) {
DCHECK(task_runner_->BelongsToCurrentThread());
DCHECK(!stream_);
if (!stream_to_control) {
- LogCaptureStartupResult(
- low_latency ? CAPTURE_STARTUP_CREATE_LOW_LATENCY_STREAM_FAILED
- : CAPTURE_STARTUP_CREATE_STREAM_FAILED);
+ LogCaptureStartupResult(CAPTURE_STARTUP_CREATE_STREAM_FAILED);
handler_->OnError(this, STREAM_CREATE_ERROR);
return;
}
if (!stream_to_control->Open()) {
stream_to_control->Close();
- LogCaptureStartupResult(low_latency
- ? CAPTURE_STARTUP_OPEN_LOW_LATENCY_STREAM_FAILED
- : CAPTURE_STARTUP_OPEN_STREAM_FAILED);
+ LogCaptureStartupResult(CAPTURE_STARTUP_OPEN_STREAM_FAILED);
handler_->OnError(this, STREAM_OPEN_ERROR);
return;
}
- // Set AGC state using mode in |agc_is_enabled_| which can only be enabled in
- // CreateLowLatency().
#if defined(AUDIO_POWER_MONITORING)
bool agc_is_supported =
- stream_to_control->SetAutomaticGainControl(agc_is_enabled_);
+ stream_to_control->SetAutomaticGainControl(enable_agc);
// Disable power measurements on platforms that does not support AGC at a
// lower level. AGC can fail on platforms where we don't support the
// functionality to modify the input volume slider. One such example is
// Windows XP.
power_measurement_is_enabled_ &= agc_is_supported;
#else
- stream_to_control->SetAutomaticGainControl(agc_is_enabled_);
+ stream_to_control->SetAutomaticGainControl(enable_agc);
#endif
// Finally, keep the stream pointer around, update the state and notify.
@@ -459,8 +386,7 @@ void AudioInputController::DoRecord() {
prev_key_down_count_ = user_input_monitor_->GetKeyPressCount();
}
- if (!low_latency_create_time_.is_null())
- low_latency_create_time_ = base::TimeTicks::Now();
+ stream_create_time_ = base::TimeTicks::Now();
audio_callback_.reset(new AudioCallback(this));
stream_->Start(audio_callback_.get());
@@ -477,21 +403,20 @@ void AudioInputController::DoClose() {
if (audio_callback_) {
stream_->Stop();
- if (!low_latency_create_time_.is_null()) {
- // Since the usage pattern of getUserMedia commonly is that a stream
- // (and accompanied audio track) is created and immediately closed or
- // discarded, we collect stats separately for short lived audio streams
- // (500ms or less) that we did not receive a callback for, as
- // 'stopped early' and 'never got data'.
- const base::TimeDelta duration =
- base::TimeTicks::Now() - low_latency_create_time_;
- LogCaptureStartupResult(audio_callback_->received_callback()
- ? CAPTURE_STARTUP_OK
- : (duration.InMilliseconds() < 500
- ? CAPTURE_STARTUP_STOPPED_EARLY
- : CAPTURE_STARTUP_NEVER_GOT_DATA));
- UMA_HISTOGRAM_BOOLEAN("Media.Audio.Capture.CallbackError",
- audio_callback_->error_during_callback());
+ // Sometimes a stream (and accompanying audio track) is created and
+ // immediately closed or discarded. In this case they are registered as
+ // 'stopped early' rather than 'never got data'.
+ const base::TimeDelta duration =
+ base::TimeTicks::Now() - stream_create_time_;
+ CaptureStartupResult capture_startup_result =
+ audio_callback_->received_callback()
+ ? CAPTURE_STARTUP_OK
+ : (duration.InMilliseconds() < 500
+ ? CAPTURE_STARTUP_STOPPED_EARLY
+ : CAPTURE_STARTUP_NEVER_GOT_DATA);
+ LogCaptureStartupResult(capture_startup_result);
+ LogCallbackError();
+ if (type_ == LOW_LATENCY) {
if (audio_callback_->received_callback()) {
// Log the total duration (since DoCreate) and update the histogram.
UMA_HISTOGRAM_LONG_TIMES("Media.InputStreamDuration", duration);
@@ -499,6 +424,9 @@ void AudioInputController::DoClose() {
"AIC::DoClose: stream duration=%" PRId64 " seconds",
duration.InSeconds());
handler_->OnLog(this, log_string);
+ } else {
+ UMA_HISTOGRAM_LONG_TIMES("Media.InputStreamDurationWithoutCallback",
+ duration);
}
}
@@ -515,9 +443,8 @@ void AudioInputController::DoClose() {
#if defined(AUDIO_POWER_MONITORING)
// Send UMA stats if enabled.
- if (log_silence_state_)
+ if (power_measurement_is_enabled_)
LogSilenceState(silence_state_);
- log_silence_state_ = false;
#endif
if (debug_writer_)
@@ -640,8 +567,42 @@ void AudioInputController::LogSilenceState(SilenceState value) {
void AudioInputController::LogCaptureStartupResult(
CaptureStartupResult result) {
- UMA_HISTOGRAM_ENUMERATION("Media.AudioInputControllerCaptureStartupSuccess",
- result, CAPTURE_STARTUP_RESULT_MAX + 1);
+ switch (type_) {
+ case LOW_LATENCY:
+ UMA_HISTOGRAM_ENUMERATION("Media.LowLatencyAudioCaptureStartupSuccess",
+ result, CAPTURE_STARTUP_RESULT_MAX + 1);
+ break;
+ case HIGH_LATENCY:
+ UMA_HISTOGRAM_ENUMERATION("Media.HighLatencyAudioCaptureStartupSuccess",
+ result, CAPTURE_STARTUP_RESULT_MAX + 1);
+ break;
+ case VIRTUAL:
+ UMA_HISTOGRAM_ENUMERATION("Media.VirtualAudioCaptureStartupSuccess",
+ result, CAPTURE_STARTUP_RESULT_MAX + 1);
+ break;
+ default:
+ break;
+ }
+}
+
+void AudioInputController::LogCallbackError() {
+ bool error_during_callback = audio_callback_->error_during_callback();
+ switch (type_) {
+ case LOW_LATENCY:
+ UMA_HISTOGRAM_BOOLEAN("Media.Audio.Capture.LowLatencyCallbackError",
+ error_during_callback);
+ break;
+ case HIGH_LATENCY:
+ UMA_HISTOGRAM_BOOLEAN("Media.Audio.Capture.HighLatencyCallbackError",
+ error_during_callback);
+ break;
+ case VIRTUAL:
+ UMA_HISTOGRAM_BOOLEAN("Media.Audio.Capture.VirtualCallbackError",
+ error_during_callback);
+ break;
+ default:
+ break;
+ }
}
void AudioInputController::DoEnableDebugRecording(
@@ -710,4 +671,19 @@ bool AudioInputController::CheckAudioPower(const AudioBus* source,
#endif
}
+// static
+AudioInputController::StreamType AudioInputController::ParamsToStreamType(
+ const AudioParameters& params) {
+ switch (params.format()) {
+ case AudioParameters::Format::AUDIO_PCM_LINEAR:
+ return AudioInputController::StreamType::HIGH_LATENCY;
+ case AudioParameters::Format::AUDIO_PCM_LOW_LATENCY:
+ return AudioInputController::StreamType::LOW_LATENCY;
+ default:
+ // Currently, the remaining supported type is fake. Reconsider if other
+ // formats become supported.
+ return AudioInputController::StreamType::FAKE;
+ }
+}
+
} // namespace media
« no previous file with comments | « media/audio/audio_input_controller.h ('k') | media/audio/audio_input_controller_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698