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

Side by Side Diff: media/audio/audio_input_device.cc

Issue 2901333002: Revert "Stop source and fire MediaStreamTrack ended event if missing audio input callbacks are dete… (Closed)
Patch Set: Created 3 years, 6 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 unified diff | Download patch
« no previous file with comments | « media/audio/audio_input_device.h ('k') | tools/metrics/histograms/enums.xml » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "media/audio/audio_input_device.h" 5 #include "media/audio/audio_input_device.h"
6 6
7 #include <stdint.h> 7 #include <stdint.h>
8 #include <utility> 8 #include <utility>
9 9
10 #include "base/bind.h" 10 #include "base/bind.h"
11 #include "base/callback_forward.h"
12 #include "base/macros.h" 11 #include "base/macros.h"
13 #include "base/metrics/histogram_macros.h"
14 #include "base/strings/stringprintf.h" 12 #include "base/strings/stringprintf.h"
15 #include "base/threading/thread_restrictions.h" 13 #include "base/threading/thread_restrictions.h"
14 #include "base/time/time.h"
16 #include "build/build_config.h" 15 #include "build/build_config.h"
17 #include "media/audio/audio_manager_base.h" 16 #include "media/audio/audio_manager_base.h"
18 #include "media/base/audio_bus.h" 17 #include "media/base/audio_bus.h"
19 18
20 namespace media { 19 namespace media {
21 20
22 namespace {
23
24 // The number of shared memory buffer segments indicated to browser process 21 // The number of shared memory buffer segments indicated to browser process
25 // in order to avoid data overwriting. This number can be any positive number, 22 // in order to avoid data overwriting. This number can be any positive number,
26 // dependent how fast the renderer process can pick up captured data from 23 // dependent how fast the renderer process can pick up captured data from
27 // shared memory. 24 // shared memory.
28 const int kRequestedSharedMemoryCount = 10; 25 static const int kRequestedSharedMemoryCount = 10;
29
30 // The number of seconds with missing callbacks before we report a capture
31 // error. The value is based on that the Mac audio implementation can defer
32 // start for 5 seconds when resuming after standby, and has a startup success
33 // check 5 seconds after actually starting, where stats is logged. We must allow
34 // enough time for this. See AUAudioInputStream::CheckInputStartupSuccess().
35 const int kMissingCallbacksTimeBeforeErrorSeconds = 12;
36
37 // The interval for checking missing callbacks.
38 const int kCheckMissingCallbacksIntervalSeconds = 5;
39
40 // How often AudioInputDevice::AudioThreadCallback informs that it has gotten
41 // data from the source.
42 const int kGotDataCallbackIntervalSeconds = 1;
43
44 } // namespace
45 26
46 // Takes care of invoking the capture callback on the audio thread. 27 // Takes care of invoking the capture callback on the audio thread.
47 // An instance of this class is created for each capture stream in 28 // An instance of this class is created for each capture stream in
48 // OnLowLatencyCreated(). 29 // OnLowLatencyCreated().
49 class AudioInputDevice::AudioThreadCallback 30 class AudioInputDevice::AudioThreadCallback
50 : public AudioDeviceThread::Callback { 31 : public AudioDeviceThread::Callback {
51 public: 32 public:
52 AudioThreadCallback(const AudioParameters& audio_parameters, 33 AudioThreadCallback(const AudioParameters& audio_parameters,
53 base::SharedMemoryHandle memory, 34 base::SharedMemoryHandle memory,
54 int memory_length, 35 int memory_length,
55 int total_segments, 36 int total_segments,
56 CaptureCallback* capture_callback, 37 CaptureCallback* capture_callback);
57 base::RepeatingClosure got_data_callback);
58 ~AudioThreadCallback() override; 38 ~AudioThreadCallback() override;
59 39
60 void MapSharedMemory() override; 40 void MapSharedMemory() override;
61 41
62 // Called whenever we receive notifications about pending data. 42 // Called whenever we receive notifications about pending data.
63 void Process(uint32_t pending_data) override; 43 void Process(uint32_t pending_data) override;
64 44
65 private: 45 private:
66 const double bytes_per_ms_; 46 const double bytes_per_ms_;
67 int current_segment_id_; 47 int current_segment_id_;
68 uint32_t last_buffer_id_; 48 uint32_t last_buffer_id_;
69 std::vector<std::unique_ptr<media::AudioBus>> audio_buses_; 49 std::vector<std::unique_ptr<media::AudioBus>> audio_buses_;
70 CaptureCallback* capture_callback_; 50 CaptureCallback* capture_callback_;
71 51
72 // Used for informing AudioInputDevice that we have gotten data, i.e. the
73 // stream is alive. |got_data_callback_| is run every
74 // |got_data_callback_interval_in_frames_| frames, calculated from
75 // kGotDataCallbackIntervalSeconds.
76 const int got_data_callback_interval_in_frames_;
77 int frames_since_last_got_data_callback_;
78 base::RepeatingClosure got_data_callback_;
79
80 DISALLOW_COPY_AND_ASSIGN(AudioThreadCallback); 52 DISALLOW_COPY_AND_ASSIGN(AudioThreadCallback);
81 }; 53 };
82 54
83 AudioInputDevice::AudioInputDevice( 55 AudioInputDevice::AudioInputDevice(
84 std::unique_ptr<AudioInputIPC> ipc, 56 std::unique_ptr<AudioInputIPC> ipc,
85 const scoped_refptr<base::SingleThreadTaskRunner>& io_task_runner) 57 const scoped_refptr<base::SingleThreadTaskRunner>& io_task_runner)
86 : ScopedTaskRunnerObserver(io_task_runner), 58 : ScopedTaskRunnerObserver(io_task_runner),
87 callback_(NULL), 59 callback_(NULL),
88 ipc_(std::move(ipc)), 60 ipc_(std::move(ipc)),
89 state_(IDLE), 61 state_(IDLE),
90 session_id_(0), 62 session_id_(0),
91 agc_is_enabled_(false), 63 agc_is_enabled_(false),
92 stopping_hack_(false), 64 stopping_hack_(false) {
93 missing_callbacks_detected_(false) {
94 CHECK(ipc_); 65 CHECK(ipc_);
95 66
96 // The correctness of the code depends on the relative values assigned in the 67 // The correctness of the code depends on the relative values assigned in the
97 // State enum. 68 // State enum.
98 static_assert(IPC_CLOSED < IDLE, "invalid enum value assignment 0"); 69 static_assert(IPC_CLOSED < IDLE, "invalid enum value assignment 0");
99 static_assert(IDLE < CREATING_STREAM, "invalid enum value assignment 1"); 70 static_assert(IDLE < CREATING_STREAM, "invalid enum value assignment 1");
100 static_assert(CREATING_STREAM < RECORDING, "invalid enum value assignment 2"); 71 static_assert(CREATING_STREAM < RECORDING, "invalid enum value assignment 2");
101 } 72 }
102 73
103 void AudioInputDevice::Initialize(const AudioParameters& params, 74 void AudioInputDevice::Initialize(const AudioParameters& params,
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
168 base::AutoLock auto_lock(audio_thread_lock_); 139 base::AutoLock auto_lock(audio_thread_lock_);
169 // TODO(miu): See TODO in OnStreamCreated method for AudioOutputDevice. 140 // TODO(miu): See TODO in OnStreamCreated method for AudioOutputDevice.
170 // Interface changes need to be made; likely, after AudioInputDevice is merged 141 // Interface changes need to be made; likely, after AudioInputDevice is merged
171 // into AudioOutputDevice (http://crbug.com/179597). 142 // into AudioOutputDevice (http://crbug.com/179597).
172 if (stopping_hack_) 143 if (stopping_hack_)
173 return; 144 return;
174 145
175 DCHECK(!audio_callback_); 146 DCHECK(!audio_callback_);
176 DCHECK(!audio_thread_); 147 DCHECK(!audio_thread_);
177 audio_callback_.reset(new AudioInputDevice::AudioThreadCallback( 148 audio_callback_.reset(new AudioInputDevice::AudioThreadCallback(
178 audio_parameters_, handle, length, total_segments, callback_, 149 audio_parameters_, handle, length, total_segments, callback_));
179 base::BindRepeating(&AudioInputDevice::SetLastCallbackTimeToNow, this)));
180 audio_thread_.reset(new AudioDeviceThread(audio_callback_.get(), 150 audio_thread_.reset(new AudioDeviceThread(audio_callback_.get(),
181 socket_handle, "AudioInputDevice")); 151 socket_handle, "AudioInputDevice"));
182 152
183 state_ = RECORDING; 153 state_ = RECORDING;
184 ipc_->RecordStream(); 154 ipc_->RecordStream();
185
186 // Start detecting missing callbacks.
187 SetLastCallbackTimeToNowOnIOThread();
188 check_alive_timer_.Start(
189 FROM_HERE,
190 base::TimeDelta::FromSeconds(kCheckMissingCallbacksIntervalSeconds), this,
191 &AudioInputDevice::CheckIfInputStreamIsAlive);
192 DCHECK(check_alive_timer_.IsRunning());
193 } 155 }
194 156
195 void AudioInputDevice::OnError() { 157 void AudioInputDevice::OnError() {
196 DCHECK(task_runner()->BelongsToCurrentThread()); 158 DCHECK(task_runner()->BelongsToCurrentThread());
197 159
198 // Do nothing if the stream has been closed. 160 // Do nothing if the stream has been closed.
199 if (state_ < CREATING_STREAM) 161 if (state_ < CREATING_STREAM)
200 return; 162 return;
201 163
202 DLOG(WARNING) << "AudioInputDevice::OnStateChanged(ERROR)"; 164 DLOG(WARNING) << "AudioInputDevice::OnStateChanged(ERROR)";
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
253 } 215 }
254 216
255 state_ = CREATING_STREAM; 217 state_ = CREATING_STREAM;
256 ipc_->CreateStream(this, session_id_, audio_parameters_, 218 ipc_->CreateStream(this, session_id_, audio_parameters_,
257 agc_is_enabled_, kRequestedSharedMemoryCount); 219 agc_is_enabled_, kRequestedSharedMemoryCount);
258 } 220 }
259 221
260 void AudioInputDevice::ShutDownOnIOThread() { 222 void AudioInputDevice::ShutDownOnIOThread() {
261 DCHECK(task_runner()->BelongsToCurrentThread()); 223 DCHECK(task_runner()->BelongsToCurrentThread());
262 224
263 check_alive_timer_.Stop();
264
265 UMA_HISTOGRAM_BOOLEAN("Media.Audio.Capture.DetectedMissingCallbacks",
266 missing_callbacks_detected_);
267 missing_callbacks_detected_ = false;
268
269 // Close the stream, if we haven't already. 225 // Close the stream, if we haven't already.
270 if (state_ >= CREATING_STREAM) { 226 if (state_ >= CREATING_STREAM) {
271 ipc_->CloseStream(); 227 ipc_->CloseStream();
272 state_ = IDLE; 228 state_ = IDLE;
273 agc_is_enabled_ = false; 229 agc_is_enabled_ = false;
274 } 230 }
275 231
276 // We can run into an issue where ShutDownOnIOThread is called right after 232 // We can run into an issue where ShutDownOnIOThread is called right after
277 // OnStreamCreated is called in cases where Start/Stop are called before we 233 // OnStreamCreated is called in cases where Start/Stop are called before we
278 // get the OnStreamCreated callback. To handle that corner case, we call 234 // get the OnStreamCreated callback. To handle that corner case, we call
(...skipping 26 matching lines...) Expand all
305 // We simply store the new AGC setting here. This value will be used when 261 // We simply store the new AGC setting here. This value will be used when
306 // a new stream is initialized and by GetAutomaticGainControl(). 262 // a new stream is initialized and by GetAutomaticGainControl().
307 agc_is_enabled_ = enabled; 263 agc_is_enabled_ = enabled;
308 } 264 }
309 265
310 void AudioInputDevice::WillDestroyCurrentMessageLoop() { 266 void AudioInputDevice::WillDestroyCurrentMessageLoop() {
311 LOG(ERROR) << "IO loop going away before the input device has been stopped"; 267 LOG(ERROR) << "IO loop going away before the input device has been stopped";
312 ShutDownOnIOThread(); 268 ShutDownOnIOThread();
313 } 269 }
314 270
315 void AudioInputDevice::CheckIfInputStreamIsAlive() {
316 DCHECK(task_runner()->BelongsToCurrentThread());
317 if (base::TimeTicks::Now() - last_callback_time_ >
318 base::TimeDelta::FromSeconds(kMissingCallbacksTimeBeforeErrorSeconds)) {
319 callback_->OnCaptureError("No audio received from audio capture device.");
320 missing_callbacks_detected_ = true;
321 }
322 }
323
324 void AudioInputDevice::SetLastCallbackTimeToNow() {
325 task_runner()->PostTask(
326 FROM_HERE,
327 base::Bind(&AudioInputDevice::SetLastCallbackTimeToNowOnIOThread, this));
328 }
329
330 void AudioInputDevice::SetLastCallbackTimeToNowOnIOThread() {
331 last_callback_time_ = base::TimeTicks::Now();
332 }
333
334 // AudioInputDevice::AudioThreadCallback 271 // AudioInputDevice::AudioThreadCallback
335 AudioInputDevice::AudioThreadCallback::AudioThreadCallback( 272 AudioInputDevice::AudioThreadCallback::AudioThreadCallback(
336 const AudioParameters& audio_parameters, 273 const AudioParameters& audio_parameters,
337 base::SharedMemoryHandle memory, 274 base::SharedMemoryHandle memory,
338 int memory_length, 275 int memory_length,
339 int total_segments, 276 int total_segments,
340 CaptureCallback* capture_callback, 277 CaptureCallback* capture_callback)
341 base::RepeatingClosure got_data_callback_)
342 : AudioDeviceThread::Callback(audio_parameters, 278 : AudioDeviceThread::Callback(audio_parameters,
343 memory, 279 memory,
344 memory_length, 280 memory_length,
345 total_segments), 281 total_segments),
346 bytes_per_ms_(static_cast<double>(audio_parameters.GetBytesPerSecond()) / 282 bytes_per_ms_(static_cast<double>(audio_parameters.GetBytesPerSecond()) /
347 base::Time::kMillisecondsPerSecond), 283 base::Time::kMillisecondsPerSecond),
348 current_segment_id_(0), 284 current_segment_id_(0),
349 last_buffer_id_(UINT32_MAX), 285 last_buffer_id_(UINT32_MAX),
350 capture_callback_(capture_callback), 286 capture_callback_(capture_callback) {}
351 got_data_callback_interval_in_frames_(kGotDataCallbackIntervalSeconds *
352 audio_parameters.sample_rate()),
353 frames_since_last_got_data_callback_(0),
354 got_data_callback_(std::move(got_data_callback_)) {}
355 287
356 AudioInputDevice::AudioThreadCallback::~AudioThreadCallback() { 288 AudioInputDevice::AudioThreadCallback::~AudioThreadCallback() {
357 } 289 }
358 290
359 void AudioInputDevice::AudioThreadCallback::MapSharedMemory() { 291 void AudioInputDevice::AudioThreadCallback::MapSharedMemory() {
360 shared_memory_.Map(memory_length_); 292 shared_memory_.Map(memory_length_);
361 293
362 // Create vector of audio buses by wrapping existing blocks of memory. 294 // Create vector of audio buses by wrapping existing blocks of memory.
363 uint8_t* ptr = static_cast<uint8_t*>(shared_memory_.memory()); 295 uint8_t* ptr = static_cast<uint8_t*>(shared_memory_.memory());
364 for (int i = 0; i < total_segments_; ++i) { 296 for (int i = 0; i < total_segments_; ++i) {
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
402 "Segment id not matching. Remote = %u. Local = %d.", 334 "Segment id not matching. Remote = %u. Local = %d.",
403 pending_data, current_segment_id_); 335 pending_data, current_segment_id_);
404 LOG(ERROR) << message; 336 LOG(ERROR) << message;
405 capture_callback_->OnCaptureError(message); 337 capture_callback_->OnCaptureError(message);
406 } 338 }
407 last_buffer_id_ = buffer->params.id; 339 last_buffer_id_ = buffer->params.id;
408 340
409 // Use pre-allocated audio bus wrapping existing block of shared memory. 341 // Use pre-allocated audio bus wrapping existing block of shared memory.
410 media::AudioBus* audio_bus = audio_buses_[current_segment_id_].get(); 342 media::AudioBus* audio_bus = audio_buses_[current_segment_id_].get();
411 343
412 // Regularly inform that we have gotten data.
413 frames_since_last_got_data_callback_ += audio_bus->frames();
414 if (frames_since_last_got_data_callback_ >=
415 got_data_callback_interval_in_frames_) {
416 got_data_callback_.Run();
417 frames_since_last_got_data_callback_ = 0;
418 }
419
420 // Deliver captured data to the client in floating point format and update 344 // Deliver captured data to the client in floating point format and update
421 // the audio delay measurement. 345 // the audio delay measurement.
422 capture_callback_->Capture( 346 capture_callback_->Capture(
423 audio_bus, 347 audio_bus,
424 buffer->params.hardware_delay_bytes / bytes_per_ms_, // Delay in ms 348 buffer->params.hardware_delay_bytes / bytes_per_ms_, // Delay in ms
425 buffer->params.volume, buffer->params.key_pressed); 349 buffer->params.volume, buffer->params.key_pressed);
426 350
427 if (++current_segment_id_ >= total_segments_) 351 if (++current_segment_id_ >= total_segments_)
428 current_segment_id_ = 0; 352 current_segment_id_ = 0;
429 } 353 }
430 354
431 } // namespace media 355 } // namespace media
OLDNEW
« no previous file with comments | « media/audio/audio_input_device.h ('k') | tools/metrics/histograms/enums.xml » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698