#ifndef CONTENT_RENDERER_MEDIA_RENDERER_WEBAUDIODEVICE_IMPL_H_
#define CONTENT_RENDERER_MEDIA_RENDERER_WEBAUDIODEVICE_IMPL_H_
#include <stdint.h>
#include <memory>
#include <string>
#include "base/gtest_prod_util.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/scoped_refptr.h"
#include "base/threading/thread_checker.h"
#include "content/common/content_export.h"
#include "media/base/audio_parameters.h"
#include "media/base/audio_renderer_sink.h"
#include "third_party/blink/public/common/tokens/tokens.h"
#include "third_party/blink/public/platform/web_audio_device.h"
#include "third_party/blink/public/platform/web_audio_latency_hint.h"
#include "third_party/blink/public/platform/web_audio_sink_descriptor.h"
namespace base {
class SingleThreadTaskRunner;
}
namespace media {
class SilentSinkSuspender;
class SpeechRecognitionClient;
}
namespace content {
class CONTENT_EXPORT RendererWebAudioDeviceImpl
: public blink::WebAudioDevice,
public media::AudioRendererSink::RenderCallback {
public:
RendererWebAudioDeviceImpl(const RendererWebAudioDeviceImpl&) = delete;
RendererWebAudioDeviceImpl& operator=(const RendererWebAudioDeviceImpl&) =
delete;
~RendererWebAudioDeviceImpl() override;
static std::unique_ptr<RendererWebAudioDeviceImpl> Create(
const blink::WebAudioSinkDescriptor& sink_descriptor,
int number_of_output_channels,
const blink::WebAudioLatencyHint& latency_hint,
std::optional<float> context_sample_rate,
media::AudioRendererSink::RenderCallback* webaudio_callback);
static int GetOutputBufferSize(const blink::WebAudioLatencyHint& latency_hint,
int resolved_context_sample_rate,
const media::AudioParameters& hardware_params);
void Start() override;
void Stop() override;
void Pause() override;
void Resume() override;
double SampleRate() override;
int FramesPerBuffer() override;
int MaxChannelCount() override;
void SetDetectSilence(bool enable_silence_detection) override;
int Render(base::TimeDelta delay,
base::TimeTicks delay_timestamp,
const media::AudioGlitchInfo& glitch_info,
media::AudioBus* dest) override;
void OnRenderError() override;
void NotifyRenderError();
void SetSilentSinkTaskRunnerForTesting(
scoped_refptr<base::SingleThreadTaskRunner> task_runner);
const media::AudioParameters& get_sink_params_for_testing() {
return current_sink_params_;
}
media::OutputDeviceStatus MaybeCreateSinkAndGetStatus() override;
const media::AudioParameters& GetOriginalSinkParamsForTesting() const {
return original_sink_params_;
}
protected:
using OutputDeviceParamsCallback = base::OnceCallback<media::AudioParameters(
const blink::LocalFrameToken& frame_token,
const std::string& device_id)>;
using CreateSilentSinkCallback =
base::RepeatingCallback<scoped_refptr<media::AudioRendererSink>(
const scoped_refptr<base::SequencedTaskRunner>& task_runner)>;
RendererWebAudioDeviceImpl(
const blink::WebAudioSinkDescriptor& sink_descriptor,
media::ChannelLayoutConfig layout_config,
const blink::WebAudioLatencyHint& latency_hint,
std::optional<float> context_sample_rate,
media::AudioRendererSink::RenderCallback* webaudio_callback,
OutputDeviceParamsCallback device_params_cb,
CreateSilentSinkCallback create_silent_sink_cb);
private:
scoped_refptr<base::SingleThreadTaskRunner> GetSilentSinkTaskRunner();
void SendLogMessage(const std::string& message);
void CreateAudioRendererSink();
media::AudioParameters current_sink_params_;
media::AudioParameters original_sink_params_;
const blink::WebAudioSinkDescriptor sink_descriptor_;
const blink::WebAudioLatencyHint latency_hint_;
const raw_ptr<media::AudioRendererSink::RenderCallback> webaudio_callback_;
base::ThreadChecker thread_checker_;
scoped_refptr<media::AudioRendererSink> sink_;
std::unique_ptr<media::SilentSinkSuspender> silent_sink_suspender_;
blink::LocalFrameToken frame_token_;
scoped_refptr<base::SingleThreadTaskRunner> silent_sink_task_runner_;
scoped_refptr<base::SingleThreadTaskRunner> main_thread_task_runner_;
bool is_rendering_ = false;
CreateSilentSinkCallback create_silent_sink_cb_;
bool is_stopped_ = true;
std::unique_ptr<media::SpeechRecognitionClient> speech_recognition_client_;
base::WeakPtrFactory<RendererWebAudioDeviceImpl> weak_ptr_factory_{this};
FRIEND_TEST_ALL_PREFIXES(RendererWebAudioDeviceImplTest,
CreateSinkAndGetDeviceStatus_HealthyDevice);
FRIEND_TEST_ALL_PREFIXES(RendererWebAudioDeviceImplTest,
CreateSinkAndGetDeviceStatus_ErrorDevice);
FRIEND_TEST_ALL_PREFIXES(RendererWebAudioDeviceImplTest,
CreateSinkAndGetDeviceStatus_SilentSink);
};
}
#endif