web_engine_audio_output_device.h 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  1. // Copyright 2020 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. #ifndef FUCHSIA_WEB_WEBENGINE_RENDERER_WEB_ENGINE_AUDIO_OUTPUT_DEVICE_H_
  5. #define FUCHSIA_WEB_WEBENGINE_RENDERER_WEB_ENGINE_AUDIO_OUTPUT_DEVICE_H_
  6. #include <fuchsia/media/cpp/fidl.h>
  7. #include <memory>
  8. #include <vector>
  9. #include "base/memory/ref_counted.h"
  10. #include "base/memory/shared_memory_mapping.h"
  11. #include "base/synchronization/lock.h"
  12. #include "base/time/time.h"
  13. #include "base/timer/timer.h"
  14. #include "fuchsia_web/webengine/web_engine_export.h"
  15. #include "media/base/audio_renderer_sink.h"
  16. namespace base {
  17. class SingleThreadTaskRunner;
  18. class WritableSharedMemoryMapping;
  19. } // namespace base
  20. // AudioRendererSink implementation for WebEngine. It sends audio to
  21. // AudioConsumer provided by the OS. Unlike AudioOutputDevice this class sends
  22. // to the system directly from the renderer process. All work is performed on
  23. // the TaskRunner passed to Create(). It must be an IO thread to allow FIDL
  24. // usage. AudioRendererSink can be used on a different thread.
  25. class WEB_ENGINE_EXPORT WebEngineAudioOutputDevice
  26. : public media::AudioRendererSink {
  27. public:
  28. static scoped_refptr<WebEngineAudioOutputDevice> Create(
  29. fidl::InterfaceHandle<fuchsia::media::AudioConsumer>
  30. audio_consumer_handle,
  31. scoped_refptr<base::SingleThreadTaskRunner> task_runner);
  32. // Same as above, but creates a WebEngineAudioOutputDevice that runs on the
  33. // default audio thread.
  34. static scoped_refptr<WebEngineAudioOutputDevice> CreateOnDefaultThread(
  35. fidl::InterfaceHandle<fuchsia::media::AudioConsumer>
  36. audio_consumer_handle);
  37. // AudioRendererSink implementation.
  38. void Initialize(const media::AudioParameters& params,
  39. RenderCallback* callback) override;
  40. void Start() override;
  41. void Stop() override;
  42. void Pause() override;
  43. void Play() override;
  44. void Flush() override;
  45. bool SetVolume(double volume) override;
  46. media::OutputDeviceInfo GetOutputDeviceInfo() override;
  47. void GetOutputDeviceInfoAsync(OutputDeviceInfoCB info_cb) override;
  48. bool IsOptimizedForHardwareParameters() override;
  49. bool CurrentThreadIsRenderingThread() override;
  50. private:
  51. friend class WebEngineAudioOutputDeviceTest;
  52. explicit WebEngineAudioOutputDevice(
  53. scoped_refptr<base::SingleThreadTaskRunner> task_runner);
  54. ~WebEngineAudioOutputDevice() override;
  55. void BindAudioConsumerOnAudioThread(
  56. fidl::InterfaceHandle<fuchsia::media::AudioConsumer>
  57. audio_consumer_handle);
  58. // AudioRendererSink handlers for the audio thread.
  59. void InitializeOnAudioThread(const media::AudioParameters& params);
  60. void StartOnAudioThread();
  61. void StopOnAudioThread();
  62. void PauseOnAudioThread();
  63. void PlayOnAudioThread();
  64. void FlushOnAudioThread();
  65. void SetVolumeOnAudioThread(double volume);
  66. // Initializes |stream_sink_|.
  67. void CreateStreamSink();
  68. // Sends current volume to |volume_control_|.
  69. void UpdateVolume();
  70. // Polls current |audio_consumer_| status.
  71. void WatchAudioConsumerStatus();
  72. // Callback for AudioConsumer::WatchStatus().
  73. void OnAudioConsumerStatusChanged(fuchsia::media::AudioConsumerStatus status);
  74. // Schedules next PumpSamples() to pump next audio packet.
  75. void SchedulePumpSamples();
  76. // Pumps a single packet to AudioConsumer and calls SchedulePumpSamples() to
  77. // pump the next packet.
  78. void PumpSamples(base::TimeTicks playback_time);
  79. // Callback for StreamSink::SendPacket().
  80. void OnStreamSendDone(size_t buffer_index);
  81. // Reports an error and shuts down the AudioConsumer connection.
  82. void ReportError();
  83. // Task runner used for all activity. Normally this is the audio thread owned
  84. // by FuchsiaAudioDeviceFactory. All AudioRendererSink methods are called on
  85. // another thread (normally the main renderer thread on which this object is
  86. // created).
  87. scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
  88. fuchsia::media::AudioConsumerPtr audio_consumer_;
  89. fuchsia::media::StreamSinkPtr stream_sink_;
  90. fuchsia::media::audio::VolumeControlPtr volume_control_;
  91. media::AudioParameters params_;
  92. // Lock used to control access to |callback_|.
  93. base::Lock callback_lock_;
  94. // Callback passed to Initialize(). It's set on the main thread (that calls
  95. // Initialize() and Stop()), but used on the audio thread (which corresponds
  96. // to the |task_runner_|). This is necessary because AudioRendererSink must
  97. // guarantee that the callback is not called after Stop(). |callback_lock_| is
  98. // used to synchronize access to the |callback_|.
  99. RenderCallback* callback_ GUARDED_BY(callback_lock_) = nullptr;
  100. // Mapped memory for buffers shared with |stream_sink_|.
  101. std::vector<base::WritableSharedMemoryMapping> stream_sink_buffers_;
  102. // Indices of unused buffers in |stream_sink_buffers_|.
  103. std::vector<size_t> available_buffers_indices_;
  104. float volume_ = 1.0;
  105. // Current position in the stream in samples since the stream was started.
  106. size_t media_pos_frames_ = 0;
  107. // Current minimum lead time returned by the |audio_consumer_|.
  108. base::TimeDelta min_lead_time_;
  109. // Current timeline parameters provided by the |audio_consumer_| in the last
  110. // AudioConsumerStatus. See
  111. // https://fuchsia.dev/reference/fidl/fuchsia.media#TimelineFunction for
  112. // details on how these parameters are used. |timeline_reference_time_| is set
  113. // to null value when there is no presentation timeline (i.e. playback isn't
  114. // active).
  115. base::TimeTicks timeline_reference_time_;
  116. base::TimeDelta timeline_subject_time_;
  117. uint32_t timeline_reference_delta_;
  118. uint32_t timeline_subject_delta_;
  119. // Set to true between DoPause() and DoPlay(). AudioConsumer implementations
  120. // should drop |presentation_timeline| when the stream is paused, but the
  121. // state is updated asynchronously. This flag is used to avoid sending packets
  122. // until the state is updated.
  123. bool paused_ = false;
  124. // Timer for PumpSamples().
  125. base::OneShotTimer pump_samples_timer_;
  126. // AudioBus used in PumpSamples(). Stored here to avoid re-allocating it for
  127. // every packet.
  128. std::unique_ptr<media::AudioBus> audio_bus_;
  129. };
  130. #endif // FUCHSIA_WEB_WEBENGINE_RENDERER_WEB_ENGINE_AUDIO_OUTPUT_DEVICE_H_