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

Unified Diff: media/audio/audio_input_device.cc

Issue 2888383002: Stop source and fire MediaStreamTrack ended event if missing audio input callbacks are detected. (Closed)
Patch Set: Added WebRTC logging in LocalMediaStreamAudioSource::OnCaptureError(). 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/audio_input_device.h ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: media/audio/audio_input_device.cc
diff --git a/media/audio/audio_input_device.cc b/media/audio/audio_input_device.cc
index 3b83deb10e3475b9aee2c1415b73a0e00e7f718a..f5ff9a23a43c4f6068bdac57343c61130c6ec3c8 100644
--- a/media/audio/audio_input_device.cc
+++ b/media/audio/audio_input_device.cc
@@ -8,21 +8,37 @@
#include <utility>
#include "base/bind.h"
+#include "base/callback_forward.h"
#include "base/macros.h"
#include "base/strings/stringprintf.h"
#include "base/threading/thread_restrictions.h"
-#include "base/time/time.h"
#include "build/build_config.h"
#include "media/audio/audio_manager_base.h"
#include "media/base/audio_bus.h"
namespace media {
+namespace {
+
// The number of shared memory buffer segments indicated to browser process
// in order to avoid data overwriting. This number can be any positive number,
// dependent how fast the renderer process can pick up captured data from
// shared memory.
-static const int kRequestedSharedMemoryCount = 10;
+const int kRequestedSharedMemoryCount = 10;
+
+// The number of seconds with missing callbacks before we report an error.
+// The value is based on that the Mac audio implementations (see
+// media/audio/mac/audio_low_latency_input_mac.h/cc) has a restart mechanism
+// that triggers after 10 seconds of missing callbacks, and after that an 8
+// seconds delay before detecting still missing callbacks. We don't want to stop
+// the source before that to allow logging and stats reporting to take place.
+// TODO(grunell): The delay in the Mac implementation could probably be shorter.
+const int kMissingCallbacksTimeBeforeErrorSeconds = 20;
tommi (sloooow) - chröme 2017/05/19 11:00:37 20 seems pretty long. In the comment, can you poi
Henrik Grunell 2017/05/20 08:40:51 Hmm, first of all the 10 seconds is really 10-15 s
+
+// The interval for checking missing callbacks.
+const int kCheckMissingCallbacksIntervalSeconds = 5;
+
+} // namespace
// Takes care of invoking the capture callback on the audio thread.
// An instance of this class is created for each capture stream in
@@ -30,11 +46,16 @@ static const int kRequestedSharedMemoryCount = 10;
class AudioInputDevice::AudioThreadCallback
: public AudioDeviceThread::Callback {
public:
- AudioThreadCallback(const AudioParameters& audio_parameters,
- base::SharedMemoryHandle memory,
- int memory_length,
- int total_segments,
- CaptureCallback* capture_callback);
+ using DataCallbackNotificationCallback =
+ base::RepeatingCallback<void(base::TimeTicks last_callback_time)>;
+
+ AudioThreadCallback(
+ const AudioParameters& audio_parameters,
+ base::SharedMemoryHandle memory,
+ int memory_length,
+ int total_segments,
+ CaptureCallback* capture_callback,
+ DataCallbackNotificationCallback data_callback_notification_callback);
tommi (sloooow) - chröme 2017/05/19 11:00:37 yo dawg, I heard you like callbacks, so...
ossu-chromium 2017/05/19 11:26:48 Yeah, this name... could it be made a bit clearer?
Henrik Grunell 2017/05/20 08:40:51 Haha, yep it's a callback to notify about a callba
ossu-chromium 2017/05/22 11:27:35 Alright, but this seems very wasteful. IIUC, with
Max Morin 2017/05/22 11:44:59 Another idea is to not use TimeTicks and have an a
Henrik Grunell 2017/05/22 15:04:54 That's a nice idea. However, it seems dangerous si
Henrik Grunell 2017/05/22 15:04:54 Agree.
~AudioThreadCallback() override;
void MapSharedMemory() override;
@@ -48,6 +69,7 @@ class AudioInputDevice::AudioThreadCallback
uint32_t last_buffer_id_;
std::vector<std::unique_ptr<media::AudioBus>> audio_buses_;
CaptureCallback* capture_callback_;
+ DataCallbackNotificationCallback data_callback_notification_callback_;
DISALLOW_COPY_AND_ASSIGN(AudioThreadCallback);
};
@@ -146,12 +168,21 @@ void AudioInputDevice::OnStreamCreated(
DCHECK(!audio_callback_);
DCHECK(!audio_thread_);
audio_callback_.reset(new AudioInputDevice::AudioThreadCallback(
- audio_parameters_, handle, length, total_segments, callback_));
+ audio_parameters_, handle, length, total_segments, callback_,
+ base::BindRepeating(&AudioInputDevice::SetLastCallbackTime, this)));
audio_thread_.reset(new AudioDeviceThread(audio_callback_.get(),
socket_handle, "AudioInputDevice"));
state_ = RECORDING;
ipc_->RecordStream();
+
+ // Start detecting missing callbacks.
+ last_callback_time_ = base::TimeTicks::Now();
+ check_alive_timer_.Start(
+ FROM_HERE,
+ base::TimeDelta::FromSeconds(kCheckMissingCallbacksIntervalSeconds), this,
+ &AudioInputDevice::CheckIfInputStreamIsAlive);
+ DCHECK(check_alive_timer_.IsRunning());
}
void AudioInputDevice::OnError() {
@@ -222,6 +253,9 @@ void AudioInputDevice::StartUpOnIOThread() {
void AudioInputDevice::ShutDownOnIOThread() {
DCHECK(task_runner()->BelongsToCurrentThread());
+ check_alive_timer_.Stop();
+ DCHECK(!check_alive_timer_.IsRunning());
+
// Close the stream, if we haven't already.
if (state_ >= CREATING_STREAM) {
ipc_->CloseStream();
@@ -268,13 +302,36 @@ void AudioInputDevice::WillDestroyCurrentMessageLoop() {
ShutDownOnIOThread();
}
+void AudioInputDevice::CheckIfInputStreamIsAlive() {
+ DCHECK(task_runner()->BelongsToCurrentThread());
+ base::TimeDelta time_since_last_callback =
+ base::TimeTicks::Now() - last_callback_time_;
+ if (time_since_last_callback >
+ base::TimeDelta::FromSeconds(kMissingCallbacksTimeBeforeErrorSeconds)) {
+ callback_->OnCaptureError("No audio received from audio capture device.");
ossu-chromium 2017/05/19 11:26:48 Should we also tie this to a UMA stat, like we do
Henrik Grunell 2017/05/20 08:40:51 Thanks for reminding. Yes, we should have that. We
+ }
+}
+
+void AudioInputDevice::SetLastCallbackTime(base::TimeTicks last_callback_time) {
+ task_runner()->PostTask(
+ FROM_HERE, base::Bind(&AudioInputDevice::SetLastCallbackTimeOnIOThread,
+ this, last_callback_time));
+}
+
+void AudioInputDevice::SetLastCallbackTimeOnIOThread(
+ base::TimeTicks last_callback_time) {
+ DCHECK(task_runner()->BelongsToCurrentThread());
+ last_callback_time_ = last_callback_time;
+}
+
// AudioInputDevice::AudioThreadCallback
AudioInputDevice::AudioThreadCallback::AudioThreadCallback(
const AudioParameters& audio_parameters,
base::SharedMemoryHandle memory,
int memory_length,
int total_segments,
- CaptureCallback* capture_callback)
+ CaptureCallback* capture_callback,
+ DataCallbackNotificationCallback data_callback_notification_callback)
: AudioDeviceThread::Callback(audio_parameters,
memory,
memory_length,
@@ -283,7 +340,9 @@ AudioInputDevice::AudioThreadCallback::AudioThreadCallback(
base::Time::kMillisecondsPerSecond),
current_segment_id_(0),
last_buffer_id_(UINT32_MAX),
- capture_callback_(capture_callback) {}
+ capture_callback_(capture_callback),
+ data_callback_notification_callback_(
+ std::move(data_callback_notification_callback)) {}
AudioInputDevice::AudioThreadCallback::~AudioThreadCallback() {
}
@@ -341,6 +400,9 @@ void AudioInputDevice::AudioThreadCallback::Process(uint32_t pending_data) {
// Use pre-allocated audio bus wrapping existing block of shared memory.
media::AudioBus* audio_bus = audio_buses_[current_segment_id_].get();
+ // Inform that we have gotten a callback.
+ data_callback_notification_callback_.Run(base::TimeTicks::Now());
+
// Deliver captured data to the client in floating point format and update
// the audio delay measurement.
capture_callback_->Capture(
« no previous file with comments | « media/audio/audio_input_device.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698