123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165 |
- // Copyright 2020 The Chromium Authors. All rights reserved.
- // Use of this source code is governed by a BSD-style license that can be
- // found in the LICENSE file.
- #ifndef FUCHSIA_WEB_WEBENGINE_RENDERER_WEB_ENGINE_AUDIO_OUTPUT_DEVICE_H_
- #define FUCHSIA_WEB_WEBENGINE_RENDERER_WEB_ENGINE_AUDIO_OUTPUT_DEVICE_H_
- #include <fuchsia/media/cpp/fidl.h>
- #include <memory>
- #include <vector>
- #include "base/memory/ref_counted.h"
- #include "base/memory/shared_memory_mapping.h"
- #include "base/synchronization/lock.h"
- #include "base/time/time.h"
- #include "base/timer/timer.h"
- #include "fuchsia_web/webengine/web_engine_export.h"
- #include "media/base/audio_renderer_sink.h"
- namespace base {
- class SingleThreadTaskRunner;
- class WritableSharedMemoryMapping;
- } // namespace base
- // AudioRendererSink implementation for WebEngine. It sends audio to
- // AudioConsumer provided by the OS. Unlike AudioOutputDevice this class sends
- // to the system directly from the renderer process. All work is performed on
- // the TaskRunner passed to Create(). It must be an IO thread to allow FIDL
- // usage. AudioRendererSink can be used on a different thread.
- class WEB_ENGINE_EXPORT WebEngineAudioOutputDevice
- : public media::AudioRendererSink {
- public:
- static scoped_refptr<WebEngineAudioOutputDevice> Create(
- fidl::InterfaceHandle<fuchsia::media::AudioConsumer>
- audio_consumer_handle,
- scoped_refptr<base::SingleThreadTaskRunner> task_runner);
- // Same as above, but creates a WebEngineAudioOutputDevice that runs on the
- // default audio thread.
- static scoped_refptr<WebEngineAudioOutputDevice> CreateOnDefaultThread(
- fidl::InterfaceHandle<fuchsia::media::AudioConsumer>
- audio_consumer_handle);
- // AudioRendererSink implementation.
- void Initialize(const media::AudioParameters& params,
- RenderCallback* callback) override;
- void Start() override;
- void Stop() override;
- void Pause() override;
- void Play() override;
- void Flush() override;
- bool SetVolume(double volume) override;
- media::OutputDeviceInfo GetOutputDeviceInfo() override;
- void GetOutputDeviceInfoAsync(OutputDeviceInfoCB info_cb) override;
- bool IsOptimizedForHardwareParameters() override;
- bool CurrentThreadIsRenderingThread() override;
- private:
- friend class WebEngineAudioOutputDeviceTest;
- explicit WebEngineAudioOutputDevice(
- scoped_refptr<base::SingleThreadTaskRunner> task_runner);
- ~WebEngineAudioOutputDevice() override;
- void BindAudioConsumerOnAudioThread(
- fidl::InterfaceHandle<fuchsia::media::AudioConsumer>
- audio_consumer_handle);
- // AudioRendererSink handlers for the audio thread.
- void InitializeOnAudioThread(const media::AudioParameters& params);
- void StartOnAudioThread();
- void StopOnAudioThread();
- void PauseOnAudioThread();
- void PlayOnAudioThread();
- void FlushOnAudioThread();
- void SetVolumeOnAudioThread(double volume);
- // Initializes |stream_sink_|.
- void CreateStreamSink();
- // Sends current volume to |volume_control_|.
- void UpdateVolume();
- // Polls current |audio_consumer_| status.
- void WatchAudioConsumerStatus();
- // Callback for AudioConsumer::WatchStatus().
- void OnAudioConsumerStatusChanged(fuchsia::media::AudioConsumerStatus status);
- // Schedules next PumpSamples() to pump next audio packet.
- void SchedulePumpSamples();
- // Pumps a single packet to AudioConsumer and calls SchedulePumpSamples() to
- // pump the next packet.
- void PumpSamples(base::TimeTicks playback_time);
- // Callback for StreamSink::SendPacket().
- void OnStreamSendDone(size_t buffer_index);
- // Reports an error and shuts down the AudioConsumer connection.
- void ReportError();
- // Task runner used for all activity. Normally this is the audio thread owned
- // by FuchsiaAudioDeviceFactory. All AudioRendererSink methods are called on
- // another thread (normally the main renderer thread on which this object is
- // created).
- scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
- fuchsia::media::AudioConsumerPtr audio_consumer_;
- fuchsia::media::StreamSinkPtr stream_sink_;
- fuchsia::media::audio::VolumeControlPtr volume_control_;
- media::AudioParameters params_;
- // Lock used to control access to |callback_|.
- base::Lock callback_lock_;
- // Callback passed to Initialize(). It's set on the main thread (that calls
- // Initialize() and Stop()), but used on the audio thread (which corresponds
- // to the |task_runner_|). This is necessary because AudioRendererSink must
- // guarantee that the callback is not called after Stop(). |callback_lock_| is
- // used to synchronize access to the |callback_|.
- RenderCallback* callback_ GUARDED_BY(callback_lock_) = nullptr;
- // Mapped memory for buffers shared with |stream_sink_|.
- std::vector<base::WritableSharedMemoryMapping> stream_sink_buffers_;
- // Indices of unused buffers in |stream_sink_buffers_|.
- std::vector<size_t> available_buffers_indices_;
- float volume_ = 1.0;
- // Current position in the stream in samples since the stream was started.
- size_t media_pos_frames_ = 0;
- // Current minimum lead time returned by the |audio_consumer_|.
- base::TimeDelta min_lead_time_;
- // Current timeline parameters provided by the |audio_consumer_| in the last
- // AudioConsumerStatus. See
- // https://fuchsia.dev/reference/fidl/fuchsia.media#TimelineFunction for
- // details on how these parameters are used. |timeline_reference_time_| is set
- // to null value when there is no presentation timeline (i.e. playback isn't
- // active).
- base::TimeTicks timeline_reference_time_;
- base::TimeDelta timeline_subject_time_;
- uint32_t timeline_reference_delta_;
- uint32_t timeline_subject_delta_;
- // Set to true between DoPause() and DoPlay(). AudioConsumer implementations
- // should drop |presentation_timeline| when the stream is paused, but the
- // state is updated asynchronously. This flag is used to avoid sending packets
- // until the state is updated.
- bool paused_ = false;
- // Timer for PumpSamples().
- base::OneShotTimer pump_samples_timer_;
- // AudioBus used in PumpSamples(). Stored here to avoid re-allocating it for
- // every packet.
- std::unique_ptr<media::AudioBus> audio_bus_;
- };
- #endif // FUCHSIA_WEB_WEBENGINE_RENDERER_WEB_ENGINE_AUDIO_OUTPUT_DEVICE_H_
|