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

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

Issue 1897953003: Unmute Tab Audio For Desktop Share (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Nit Fix Created 4 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
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_output_controller.h" 5 #include "media/audio/audio_output_controller.h"
6 6
7 #include <stdint.h> 7 #include <stdint.h>
8 8
9 #include <limits> 9 #include <limits>
10 10
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
43 ignore_errors_during_stop_close_(false) { 43 ignore_errors_during_stop_close_(false) {
44 DCHECK(audio_manager); 44 DCHECK(audio_manager);
45 DCHECK(handler_); 45 DCHECK(handler_);
46 DCHECK(sync_reader_); 46 DCHECK(sync_reader_);
47 DCHECK(message_loop_.get()); 47 DCHECK(message_loop_.get());
48 } 48 }
49 49
50 AudioOutputController::~AudioOutputController() { 50 AudioOutputController::~AudioOutputController() {
51 CHECK_EQ(kClosed, state_); 51 CHECK_EQ(kClosed, state_);
52 CHECK_EQ(nullptr, stream_); 52 CHECK_EQ(nullptr, stream_);
53 CHECK(duplication_targets_.empty());
53 } 54 }
54 55
55 // static 56 // static
56 scoped_refptr<AudioOutputController> AudioOutputController::Create( 57 scoped_refptr<AudioOutputController> AudioOutputController::Create(
57 AudioManager* audio_manager, 58 AudioManager* audio_manager,
58 EventHandler* event_handler, 59 EventHandler* event_handler,
59 const AudioParameters& params, 60 const AudioParameters& params,
60 const std::string& output_device_id, 61 const std::string& output_device_id,
61 SyncReader* sync_reader) { 62 SyncReader* sync_reader) {
62 CHECK(audio_manager); 63 CHECK(audio_manager);
(...skipping 239 matching lines...) Expand 10 before | Expand all | Expand 10 after
302 // thread starts, its safe to compare and then increment. 303 // thread starts, its safe to compare and then increment.
303 if (base::AtomicRefCountIsZero(&on_more_io_data_called_)) 304 if (base::AtomicRefCountIsZero(&on_more_io_data_called_))
304 base::AtomicRefCountInc(&on_more_io_data_called_); 305 base::AtomicRefCountInc(&on_more_io_data_called_);
305 306
306 sync_reader_->Read(dest); 307 sync_reader_->Read(dest);
307 308
308 const int frames = dest->frames(); 309 const int frames = dest->frames();
309 sync_reader_->UpdatePendingBytes( 310 sync_reader_->UpdatePendingBytes(
310 total_bytes_delay + frames * params_.GetBytesPerFrame(), frames_skipped); 311 total_bytes_delay + frames * params_.GetBytesPerFrame(), frames_skipped);
311 312
313 bool need_to_duplicate = false;
314 {
315 base::AutoLock lock(duplication_targets_lock_);
316 need_to_duplicate = !duplication_targets_.empty();
317 }
318 if (need_to_duplicate) {
319 const base::TimeTicks reference_time =
320 base::TimeTicks::Now() +
321 base::TimeDelta::FromMicroseconds(base::Time::kMicrosecondsPerSecond *
322 total_bytes_delay /
DaleCurtis 2016/06/01 20:58:07 These are integer values and will lose precision.
qiangchen 2016/06/01 21:43:15 Really necessary? I think multiplication is before
DaleCurtis 2016/06/01 21:52:09 It depends on how you use these timestamps, but it
qiangchen 2016/06/01 23:11:13 Acknowledged.
323 params_.GetBytesPerSecond());
324 std::unique_ptr<AudioBus> copy(AudioBus::Create(params_));
325 dest->CopyTo(copy.get());
326 message_loop_->PostTask(
327 FROM_HERE,
328 base::Bind(&AudioOutputController::BroadcastDataToDuplicationTargets,
329 this, base::Passed(&copy), reference_time));
330 }
331
312 if (will_monitor_audio_levels()) 332 if (will_monitor_audio_levels())
313 power_monitor_.Scan(*dest, frames); 333 power_monitor_.Scan(*dest, frames);
314 334
315 return frames; 335 return frames;
316 } 336 }
317 337
338 void AudioOutputController::BroadcastDataToDuplicationTargets(
339 std::unique_ptr<AudioBus> audio_bus,
340 base::TimeTicks reference_time) {
341 DCHECK(message_loop_->BelongsToCurrentThread());
342 if (state_ != kPlaying || duplication_targets_.empty())
343 return;
344
345 // Note: Do not need to acquire lock since this is running on the same thread
346 // as where the set is modified.
347 for (auto target = std::next(duplication_targets_.begin(), 1);
DaleCurtis 2016/06/01 20:58:07 How come you need std::next here? Does for (auto a
qiangchen 2016/06/01 21:43:15 This loop skips the first target. The statement af
DaleCurtis 2016/06/01 21:52:58 Up to you, but it seems like this would be clearer
qiangchen 2016/06/01 23:11:13 Not that simple. Without using this technique, fo
348 target != duplication_targets_.end(); ++target) {
349 std::unique_ptr<AudioBus> copy(AudioBus::Create(params_));
350 audio_bus->CopyTo(copy.get());
351 (*target)->OnData(std::move(copy), reference_time);
352 }
353
354 (*duplication_targets_.begin())->OnData(std::move(audio_bus), reference_time);
DaleCurtis 2016/06/01 20:58:07 This looks like it broadcasts twice?
qiangchen 2016/06/01 21:43:15 Explained above.
355 }
356
318 void AudioOutputController::OnError(AudioOutputStream* stream) { 357 void AudioOutputController::OnError(AudioOutputStream* stream) {
319 { 358 {
320 base::AutoLock auto_lock(error_lock_); 359 base::AutoLock auto_lock(error_lock_);
321 if (ignore_errors_during_stop_close_) 360 if (ignore_errors_during_stop_close_)
322 return; 361 return;
323 } 362 }
324 363
325 // Handle error on the audio controller thread. 364 // Handle error on the audio controller thread.
326 message_loop_->PostTask(FROM_HERE, base::Bind( 365 message_loop_->PostTask(FROM_HERE, base::Bind(
327 &AudioOutputController::DoReportError, this)); 366 &AudioOutputController::DoReportError, this));
328 } 367 }
329 368
330 void AudioOutputController::DoStopCloseAndClearStream() { 369 void AudioOutputController::DoStopCloseAndClearStream() {
331 DCHECK(message_loop_->BelongsToCurrentThread()); 370 DCHECK(message_loop_->BelongsToCurrentThread());
332 371
333 // Allow calling unconditionally and bail if we don't have a stream_ to close. 372 // Allow calling unconditionally and bail if we don't have a stream_ to close.
334 if (stream_) { 373 if (stream_) {
335 { 374 {
336 base::AutoLock auto_lock(error_lock_); 375 base::AutoLock auto_lock(error_lock_);
337 ignore_errors_during_stop_close_ = true; 376 ignore_errors_during_stop_close_ = true;
338 } 377 }
339 378
340 // De-register from state change callbacks if stream_ was created via 379 // De-register from state change callbacks if stream_ was created via
341 // AudioManager. 380 // AudioManager.
342 if (stream_ != diverting_to_stream_) 381 if (stream_ != diverting_to_stream_)
343 audio_manager_->RemoveOutputDeviceChangeListener(this); 382 audio_manager_->RemoveOutputDeviceChangeListener(this);
344 383
345 StopStream(); 384 StopStream();
346 stream_->Close(); 385 stream_->Close();
386
347 if (stream_ == diverting_to_stream_) 387 if (stream_ == diverting_to_stream_)
348 diverting_to_stream_ = NULL; 388 diverting_to_stream_ = NULL;
349 stream_ = NULL; 389 stream_ = NULL;
350 390
351 // Since the stream is no longer running, no lock is necessary. 391 // Since the stream is no longer running, no lock is necessary.
352 ignore_errors_during_stop_close_ = false; 392 ignore_errors_during_stop_close_ = false;
353 } 393 }
354 394
355 state_ = kEmpty; 395 state_ = kEmpty;
356 } 396 }
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
393 message_loop_->PostTask( 433 message_loop_->PostTask(
394 FROM_HERE, 434 FROM_HERE,
395 base::Bind(&AudioOutputController::DoStartDiverting, this, to_stream)); 435 base::Bind(&AudioOutputController::DoStartDiverting, this, to_stream));
396 } 436 }
397 437
398 void AudioOutputController::StopDiverting() { 438 void AudioOutputController::StopDiverting() {
399 message_loop_->PostTask( 439 message_loop_->PostTask(
400 FROM_HERE, base::Bind(&AudioOutputController::DoStopDiverting, this)); 440 FROM_HERE, base::Bind(&AudioOutputController::DoStopDiverting, this));
401 } 441 }
402 442
443 void AudioOutputController::StartDuplicating(AudioPushSink* sink) {
444 message_loop_->PostTask(
445 FROM_HERE,
446 base::Bind(&AudioOutputController::DoStartDuplicating, this, sink));
447 }
448
449 void AudioOutputController::StopDuplicating(AudioPushSink* sink) {
450 message_loop_->PostTask(
451 FROM_HERE,
452 base::Bind(&AudioOutputController::DoStopDuplicating, this, sink));
453 }
454
403 void AudioOutputController::DoStartDiverting(AudioOutputStream* to_stream) { 455 void AudioOutputController::DoStartDiverting(AudioOutputStream* to_stream) {
404 DCHECK(message_loop_->BelongsToCurrentThread()); 456 DCHECK(message_loop_->BelongsToCurrentThread());
405 457
406 if (state_ == kClosed) 458 if (state_ == kClosed)
407 return; 459 return;
408 460
409 DCHECK(!diverting_to_stream_); 461 DCHECK(!diverting_to_stream_);
410 diverting_to_stream_ = to_stream; 462 diverting_to_stream_ = to_stream;
411 // Note: OnDeviceChange() will engage the "re-create" process, which will 463 // Note: OnDeviceChange() will engage the "re-create" process, which will
412 // detect and use the alternate AudioOutputStream rather than create a new one 464 // detect and use the alternate AudioOutputStream rather than create a new one
413 // via AudioManager. 465 // via AudioManager.
414 OnDeviceChange(); 466 OnDeviceChange();
415 } 467 }
416 468
417 void AudioOutputController::DoStopDiverting() { 469 void AudioOutputController::DoStopDiverting() {
418 DCHECK(message_loop_->BelongsToCurrentThread()); 470 DCHECK(message_loop_->BelongsToCurrentThread());
419 471
420 if (state_ == kClosed) 472 if (state_ == kClosed)
421 return; 473 return;
422 474
423 // Note: OnDeviceChange() will cause the existing stream (the consumer of the 475 // Note: OnDeviceChange() will cause the existing stream (the consumer of the
424 // diverted audio data) to be closed, and diverting_to_stream_ will be set 476 // diverted audio data) to be closed, and diverting_to_stream_ will be set
425 // back to NULL. 477 // back to NULL.
426 OnDeviceChange(); 478 OnDeviceChange();
427 DCHECK(!diverting_to_stream_); 479 DCHECK(!diverting_to_stream_);
428 } 480 }
429 481
482 void AudioOutputController::DoStartDuplicating(AudioPushSink* to_stream) {
483 DCHECK(message_loop_->BelongsToCurrentThread());
484 if (state_ == kClosed)
485 return;
486
487 base::AutoLock lock(duplication_targets_lock_);
488 duplication_targets_.insert(to_stream);
489 }
490
491 void AudioOutputController::DoStopDuplicating(AudioPushSink* to_stream) {
492 DCHECK(message_loop_->BelongsToCurrentThread());
493 to_stream->Close();
494
495 base::AutoLock lock(duplication_targets_lock_);
496 duplication_targets_.erase(to_stream);
497 }
498
430 std::pair<float, bool> AudioOutputController::ReadCurrentPowerAndClip() { 499 std::pair<float, bool> AudioOutputController::ReadCurrentPowerAndClip() {
431 DCHECK(will_monitor_audio_levels()); 500 DCHECK(will_monitor_audio_levels());
432 return power_monitor_.ReadCurrentPowerAndClip(); 501 return power_monitor_.ReadCurrentPowerAndClip();
433 } 502 }
434 503
435 void AudioOutputController::WedgeCheck() { 504 void AudioOutputController::WedgeCheck() {
436 DCHECK(message_loop_->BelongsToCurrentThread()); 505 DCHECK(message_loop_->BelongsToCurrentThread());
437 506
438 // If we should be playing and we haven't, that's a wedge. 507 // If we should be playing and we haven't, that's a wedge.
439 if (state_ == kPlaying) { 508 if (state_ == kPlaying) {
440 UMA_HISTOGRAM_BOOLEAN("Media.AudioOutputControllerPlaybackStartupSuccess", 509 UMA_HISTOGRAM_BOOLEAN("Media.AudioOutputControllerPlaybackStartupSuccess",
441 base::AtomicRefCountIsOne(&on_more_io_data_called_)); 510 base::AtomicRefCountIsOne(&on_more_io_data_called_));
442 } 511 }
443 } 512 }
444 513
445 } // namespace media 514 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698