null_audio_sink.cc 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131
  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
  3. // found in the LICENSE file.
  4. #include "media/audio/null_audio_sink.h"
  5. #include <memory>
  6. #include "base/bind.h"
  7. #include "base/location.h"
  8. #include "base/task/single_thread_task_runner.h"
  9. #include "base/threading/sequenced_task_runner_handle.h"
  10. #include "media/base/audio_hash.h"
  11. #include "media/base/fake_audio_worker.h"
  12. namespace media {
  13. NullAudioSink::NullAudioSink(
  14. const scoped_refptr<base::SingleThreadTaskRunner>& task_runner)
  15. : initialized_(false),
  16. started_(false),
  17. playing_(false),
  18. callback_(nullptr),
  19. task_runner_(task_runner) {}
  20. NullAudioSink::~NullAudioSink() = default;
  21. void NullAudioSink::Initialize(const AudioParameters& params,
  22. RenderCallback* callback) {
  23. DCHECK(!started_);
  24. fake_worker_ = std::make_unique<FakeAudioWorker>(task_runner_, params);
  25. fixed_data_delay_ = FakeAudioWorker::ComputeFakeOutputDelay(params);
  26. audio_bus_ = AudioBus::Create(params);
  27. callback_ = callback;
  28. initialized_ = true;
  29. }
  30. void NullAudioSink::Start() {
  31. DCHECK(task_runner_->BelongsToCurrentThread());
  32. DCHECK(initialized_);
  33. DCHECK(!started_);
  34. started_ = true;
  35. }
  36. void NullAudioSink::Stop() {
  37. DCHECK(task_runner_->BelongsToCurrentThread());
  38. started_ = false;
  39. // Stop may be called at any time, so we have to check before stopping.
  40. if (fake_worker_)
  41. fake_worker_->Stop();
  42. }
  43. void NullAudioSink::Play() {
  44. DCHECK(task_runner_->BelongsToCurrentThread());
  45. DCHECK(started_);
  46. if (playing_)
  47. return;
  48. fake_worker_->Start(
  49. base::BindRepeating(&NullAudioSink::CallRender, base::Unretained(this)));
  50. playing_ = true;
  51. }
  52. void NullAudioSink::Pause() {
  53. DCHECK(task_runner_->BelongsToCurrentThread());
  54. DCHECK(started_);
  55. if (!playing_)
  56. return;
  57. fake_worker_->Stop();
  58. playing_ = false;
  59. }
  60. void NullAudioSink::Flush() {}
  61. bool NullAudioSink::SetVolume(double volume) {
  62. // Audio is always muted.
  63. return volume == 0.0;
  64. }
  65. OutputDeviceInfo NullAudioSink::GetOutputDeviceInfo() {
  66. return OutputDeviceInfo(OUTPUT_DEVICE_STATUS_OK);
  67. }
  68. void NullAudioSink::GetOutputDeviceInfoAsync(OutputDeviceInfoCB info_cb) {
  69. base::SequencedTaskRunnerHandle::Get()->PostTask(
  70. FROM_HERE, base::BindOnce(std::move(info_cb), GetOutputDeviceInfo()));
  71. }
  72. bool NullAudioSink::IsOptimizedForHardwareParameters() {
  73. return false;
  74. }
  75. bool NullAudioSink::CurrentThreadIsRenderingThread() {
  76. return task_runner_->BelongsToCurrentThread();
  77. }
  78. void NullAudioSink::SwitchOutputDevice(const std::string& device_id,
  79. OutputDeviceStatusCB callback) {
  80. std::move(callback).Run(OUTPUT_DEVICE_STATUS_ERROR_INTERNAL);
  81. }
  82. void NullAudioSink::CallRender(base::TimeTicks ideal_time,
  83. base::TimeTicks now) {
  84. DCHECK(task_runner_->BelongsToCurrentThread());
  85. // Since NullAudioSink is only used for cases where a real audio sink was not
  86. // available, provide "idealized" delay-timing arguments. This will drive the
  87. // smoothest playback (since video is sync'ed to audio). See
  88. // content::AudioRendererImpl and media::AudioClock for further details.
  89. int frames_received =
  90. callback_->Render(fixed_data_delay_, ideal_time, 0, audio_bus_.get());
  91. if (!audio_hash_ || frames_received <= 0)
  92. return;
  93. audio_hash_->Update(audio_bus_.get(), frames_received);
  94. }
  95. void NullAudioSink::StartAudioHashForTesting() {
  96. DCHECK(!initialized_);
  97. audio_hash_ = std::make_unique<AudioHash>();
  98. }
  99. std::string NullAudioSink::GetAudioHashForTesting() {
  100. return audio_hash_ ? audio_hash_->ToString() : std::string();
  101. }
  102. } // namespace media