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

Unified Diff: media/audio/mac/audio_low_latency_input_mac.cc

Issue 2896423003: Remove Mac input audio restart mechanism and reduce time until startup success check. (Closed)
Patch Set: Created 3 years, 7 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/mac/audio_low_latency_input_mac.h ('k') | tools/metrics/histograms/histograms.xml » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: media/audio/mac/audio_low_latency_input_mac.cc
diff --git a/media/audio/mac/audio_low_latency_input_mac.cc b/media/audio/mac/audio_low_latency_input_mac.cc
index 15640a57ca94816cdef601122bef988982cf6150..f0dc947ce779c5011879411c30146d3f96879eb7 100644
--- a/media/audio/mac/audio_low_latency_input_mac.cc
+++ b/media/audio/mac/audio_low_latency_input_mac.cc
@@ -29,32 +29,11 @@ const int kNumberOfBlocksBufferInFifo = 2;
// The stream will be stopped as soon as this time limit is passed.
const int kMaxErrorTimeoutInSeconds = 1;
-// A repeating timer is created and started in Start() and it triggers calls
-// to CheckIfInputStreamIsAlive() where we do periodic checks to see if the
-// input data callback sequence is active or not. If the stream seems dead,
-// up to |kMaxNumberOfRestartAttempts| restart attempts tries to bring the
-// stream back to life.
-const int kCheckInputIsAliveTimeInSeconds = 5;
-
-// Number of restart indications required to actually trigger a restart
-// attempt.
-const int kNumberOfIndicationsToTriggerRestart = 1;
-
-// Max number of times we try to restart a stream when it has been categorized
-// as dead. Note that we can do many restarts during an audio session and this
-// limitation is per detected problem. Once a restart has succeeded, a new
-// sequence of |kMaxNumberOfRestartAttempts| number of restart attempts can be
-// done.
-const int kMaxNumberOfRestartAttempts = 1;
-
// A one-shot timer is created and started in Start() and it triggers
// CheckInputStartupSuccess() after this amount of time. UMA stats marked
// Media.Audio.InputStartupSuccessMac is then updated where true is added
-// if input callbacks have started, and false otherwise. Note that the value
-// is larger than |kCheckInputIsAliveTimeInSeconds| to ensure that at least one
-// restart attempt can be done before storing the result.
-const int kInputCallbackStartTimeoutInSeconds =
- kCheckInputIsAliveTimeInSeconds + 3;
+// if input callbacks have started, and false otherwise.
+const int kInputCallbackStartTimeoutInSeconds = 5;
// Returns true if the format flags in |format_flags| has the "non-interleaved"
// flag (kAudioFormatFlagIsNonInterleaved) cleared (set to 0).
@@ -255,6 +234,7 @@ AUAudioInputStream::AUAudioInputStream(
fifo_(input_params.channels(),
number_of_frames_,
kNumberOfBlocksBufferInFifo),
+ got_input_callback_(false),
input_callback_is_active_(false),
start_was_deferred_(false),
buffer_size_was_changed_(false),
@@ -265,9 +245,6 @@ AUAudioInputStream::AUAudioInputStream(
total_lost_frames_(0),
largest_glitch_frames_(0),
glitches_detected_(0),
- number_of_restart_indications_(0),
- number_of_restart_attempts_(0),
- total_number_of_restart_attempts_(0),
log_callback_(log_callback),
weak_factory_(this) {
DCHECK(manager_);
@@ -543,7 +520,6 @@ void AUAudioInputStream::Start(AudioInputCallback* callback) {
sink_ = callback;
last_success_time_ = base::TimeTicks::Now();
- last_callback_time_ = base::TimeTicks::Now();
audio_unit_render_has_worked_ = false;
StartAgc();
OSStatus result = AudioOutputUnitStart(audio_unit_);
@@ -565,14 +541,6 @@ void AUAudioInputStream::Start(AudioInputCallback* callback) {
base::TimeDelta::FromSeconds(kInputCallbackStartTimeoutInSeconds), this,
&AUAudioInputStream::CheckInputStartupSuccess);
DCHECK(input_callback_timer_->IsRunning());
-
- // Also create and start a timer that provides periodic callbacks used to
- // monitor if the input stream is alive or not.
- check_alive_timer_.reset(new base::RepeatingTimer());
- check_alive_timer_->Start(
- FROM_HERE, base::TimeDelta::FromSeconds(kCheckInputIsAliveTimeInSeconds),
- this, &AUAudioInputStream::CheckIfInputStreamIsAlive);
- DCHECK(check_alive_timer_->IsRunning());
}
void AUAudioInputStream::Stop() {
@@ -580,10 +548,6 @@ void AUAudioInputStream::Stop() {
deferred_start_cb_.Cancel();
DVLOG(1) << "Stop";
StopAgc();
- if (check_alive_timer_ != nullptr) {
- check_alive_timer_->Stop();
- check_alive_timer_.reset();
- }
if (input_callback_timer_ != nullptr) {
input_callback_timer_->Stop();
input_callback_timer_.reset();
@@ -611,18 +575,23 @@ void AUAudioInputStream::Stop() {
sink_ = nullptr;
fifo_.Clear();
io_buffer_frame_size_ = 0;
+ got_input_callback_ = false;
}
void AUAudioInputStream::Close() {
DCHECK(thread_checker_.CalledOnValidThread());
DVLOG(1) << "Close";
+
// It is valid to call Close() before calling open or Start().
// It is also valid to call Close() after Start() has been called.
Stop();
+
// Uninitialize and dispose the audio unit.
CloseAudioUnit();
+
// Disable the listener for device property changes.
DeRegisterDeviceChangeListener();
+
// Add more UMA stats but only if AGC was activated, i.e. for e.g. WebRTC
// audio input streams.
if (GetAutomaticGainControl()) {
@@ -640,13 +609,8 @@ void AUAudioInputStream::Close() {
// only when input audio fails to start.
UMA_HISTOGRAM_BOOLEAN("Media.Audio.InputBufferSizeWasChangedAudioWorkedMac",
buffer_size_was_changed_);
- // Logs the total number of times RestartAudio() has been called.
- DVLOG(1) << "Total number of restart attempts: "
- << total_number_of_restart_attempts_;
- UMA_HISTOGRAM_COUNTS_1000("Media.Audio.InputRestartAttemptsMac",
- total_number_of_restart_attempts_);
- // TODO(henrika): possibly add more values here...
}
+
// Inform the audio manager that we have been closed. This will cause our
// destruction.
manager_->ReleaseInputStream(this);
@@ -818,20 +782,12 @@ OSStatus AUAudioInputStream::OnDataIsAvailable(
UInt32 bus_number,
UInt32 number_of_frames) {
TRACE_EVENT0("audio", "AUAudioInputStream::OnDataIsAvailable");
- // Update |last_callback_time_| on the main browser thread. Its value is used
- // by CheckIfInputStreamIsAlive() to detect if the stream is dead or alive.
- manager_->GetTaskRunner()->PostTask(
- FROM_HERE,
- base::Bind(&AUAudioInputStream::UpdateDataCallbackTimeOnMainThread,
- weak_factory_.GetWeakPtr(), base::TimeTicks::Now()));
- // Indicate that input callbacks have started on the internal AUHAL IO
- // thread. The |input_callback_is_active_| member is read from the creating
- // thread when a timer fires once and set to false in Stop() on the same
- // thread. It means that this thread is the only writer of
- // |input_callback_is_active_| once the tread starts and it should therefore
- // be safe to modify.
- SetInputCallbackIsActive(true);
+ // Indicate that input callbacks have started.
+ if (!got_input_callback_) {
+ got_input_callback_ = true;
+ SetInputCallbackIsActive(true);
+ }
// Update the |mDataByteSize| value in the audio_buffer_list() since
// |number_of_frames| can be changed on the fly.
@@ -1227,72 +1183,6 @@ void AUAudioInputStream::CheckInputStartupSuccess() {
}
}
-void AUAudioInputStream::UpdateDataCallbackTimeOnMainThread(
- base::TimeTicks now_tick) {
- DCHECK(thread_checker_.CalledOnValidThread());
- last_callback_time_ = now_tick;
-}
-
-void AUAudioInputStream::CheckIfInputStreamIsAlive() {
- DCHECK(thread_checker_.CalledOnValidThread());
- // Avoid checking stream state if we are suspended.
- if (manager_->IsSuspending())
- return;
- // Restrict usage of the restart mechanism to "AGC streams" only.
- // TODO(henrika): if the restart scheme works well, we might include it
- // for all types of input streams.
- if (!GetAutomaticGainControl())
- return;
-
- // Clear this counter here when audio is active instead of in Start(),
- // otherwise it would be cleared at each restart attempt and that would break
- // the current design where only a certain number of restart attempts is
- // allowed.
- if (GetInputCallbackIsActive())
- number_of_restart_attempts_ = 0;
-
- // Measure time since last callback. |last_callback_time_| is set the first
- // time in Start() and then updated in each data callback, hence if
- // |time_since_last_callback| is large (>1) and growing for each check, the
- // callback sequence has stopped. A typical value under normal/working
- // conditions is a few milliseconds.
- base::TimeDelta time_since_last_callback =
- base::TimeTicks::Now() - last_callback_time_;
- DVLOG(2) << "time since last callback: "
- << time_since_last_callback.InSecondsF();
-
- // Increase a counter if it has been too long since the last data callback.
- // A non-zero value of this counter is a strong indication of a "dead" input
- // stream. Reset the same counter if the stream is alive.
- if (time_since_last_callback.InSecondsF() >
- 0.5 * kCheckInputIsAliveTimeInSeconds) {
- ++number_of_restart_indications_;
- } else {
- number_of_restart_indications_ = 0;
- }
-
- // Restart the audio stream if two conditions are met. First, the number of
- // restart indicators must be larger than a threshold, and secondly, only a
- // fixed number of restart attempts is allowed.
- // Note that, the threshold is different depending on if the stream is seen
- // as dead directly at the first call to Start() (i.e. it has never started)
- // or if the stream has started OK at least once but then stopped for some
- // reason (e.g by placing the device in sleep mode). One restart indication
- // is sufficient for the first case (threshold is zero), while a larger value
- // (threshold > 0) is required for the second case to avoid false alarms when
- // e.g. resuming from a suspended state.
- const size_t restart_threshold =
- GetInputCallbackIsActive() ? kNumberOfIndicationsToTriggerRestart : 0;
- if (number_of_restart_indications_ > restart_threshold &&
- number_of_restart_attempts_ < kMaxNumberOfRestartAttempts) {
- SetInputCallbackIsActive(false);
- ++total_number_of_restart_attempts_;
- ++number_of_restart_attempts_;
- number_of_restart_indications_ = 0;
- RestartAudio();
- }
-}
-
void AUAudioInputStream::CloseAudioUnit() {
DCHECK(thread_checker_.CalledOnValidThread());
DVLOG(1) << "CloseAudioUnit";
@@ -1307,26 +1197,6 @@ void AUAudioInputStream::CloseAudioUnit() {
audio_unit_ = 0;
}
-void AUAudioInputStream::RestartAudio() {
- DCHECK(thread_checker_.CalledOnValidThread());
- DVLOG(1) << "RestartAudio";
- LOG_IF(ERROR, IsRunning())
- << "Stream is reported dead but actually seems alive";
- if (!audio_unit_)
- return;
-
- // Store the existing callback instance for upcoming call to Start().
- AudioInputCallback* sink = sink_;
- // Do a best-effort attempt to restart the presumably dead input audio stream.
- // TODO(henrika): initial tests shows that the scheme below works well but
- // there might be corner cases that I have missed.
- Stop();
- CloseAudioUnit();
- DeRegisterDeviceChangeListener();
- Open();
- Start(sink);
-}
-
void AUAudioInputStream::AddHistogramsForFailedStartup() {
DCHECK(thread_checker_.CalledOnValidThread());
UMA_HISTOGRAM_BOOLEAN("Media.Audio.InputStartWasDeferredMac",
« no previous file with comments | « media/audio/mac/audio_low_latency_input_mac.h ('k') | tools/metrics/histograms/histograms.xml » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698