blob: 0e47c24d9b8b1e27485e81eae227ef72b5624c51 [file] [log] [blame]
// Copyright (c) 2012 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.
// This class is generally not thread safe. Callers should ensure thread safety.
// For instance, the |sink_lock_| in WebAudioSourceProvider synchronizes access
// to this object across the main thread (for WebAudio APIs) and the
// media thread (for HTMLMediaElement APIs).
// The one exception is protection for |volume_| via |volume_lock_|. This lock
// prevents races between SetVolume() (called on any thread) and ProvideInput
// (called on audio device thread). See
#include <string>
#include "base/callback.h"
#include "base/macros.h"
#include "base/synchronization/lock.h"
#include "base/thread_annotations.h"
#include "media/base/audio_converter.h"
#include "media/base/audio_latency.h"
#include "media/base/audio_renderer_sink.h"
namespace media {
class AudioRendererMixerPool;
class AudioRendererMixer;
class MEDIA_EXPORT AudioRendererMixerInput
: public SwitchableAudioRendererSink,
public AudioConverter::InputCallback {
AudioRendererMixerInput(AudioRendererMixerPool* mixer_pool,
int owner_id,
const std::string& device_id,
AudioLatency::LatencyType latency);
// SwitchableAudioRendererSink implementation.
void Start() override;
void Stop() override;
void Play() override;
void Pause() override;
bool SetVolume(double volume) override;
OutputDeviceInfo GetOutputDeviceInfo() override;
void GetOutputDeviceInfoAsync(OutputDeviceInfoCB info_cb) override;
bool IsOptimizedForHardwareParameters() override;
void Initialize(const AudioParameters& params,
AudioRendererSink::RenderCallback* renderer) override;
void SwitchOutputDevice(const std::string& device_id,
OutputDeviceStatusCB callback) override;
// This is expected to be called on the audio rendering thread. The caller
// must ensure that this input has been added to a mixer before calling the
// function, and that it is not removed from the mixer before this function
// returns.
bool CurrentThreadIsRenderingThread() override;
// Called by AudioRendererMixer when an error occurs.
void OnRenderError();
~AudioRendererMixerInput() override;
friend class AudioRendererMixerInputTest;
// Pool to obtain mixers from / return them to.
AudioRendererMixerPool* const mixer_pool_;
// Protect |volume_|, accessed by separate threads in ProvideInput() and
// SetVolume().
base::Lock volume_lock_;
bool started_ = false;
bool playing_ = false;
double volume_ GUARDED_BY(volume_lock_) = 1.0;
scoped_refptr<AudioRendererSink> sink_;
base::Optional<OutputDeviceInfo> device_info_;
// AudioConverter::InputCallback implementation.
double ProvideInput(AudioBus* audio_bus, uint32_t frames_delayed) override;
void OnDeviceInfoReceived(OutputDeviceInfoCB info_cb,
OutputDeviceInfo device_info);
// Method to help handle device changes. Must be static to ensure we can still
// execute the |switch_cb| even if the pipeline is destructed. Restarts (if
// necessary) Start() and Play() state with a new |sink| and |device_info|.
// |switch_cb| is the callback given to the SwitchOutputDevice() call.
// |sink| is a fresh sink which should be used if device info is good.
// |device_info| is the OutputDeviceInfo for |sink| after
// GetOutputDeviceInfoAsync() completes.
void OnDeviceSwitchReady(OutputDeviceStatusCB switch_cb,
scoped_refptr<AudioRendererSink> sink,
OutputDeviceInfo device_info);
// AudioParameters received during Initialize().
AudioParameters params_;
const int owner_id_;
std::string device_id_; // ID of hardware device to use
const AudioLatency::LatencyType latency_;
// AudioRendererMixer obtained from mixer pool during Initialize(),
// guaranteed to live (at least) until it is returned to the pool.
AudioRendererMixer* mixer_ = nullptr;
// Source of audio data which is provided to the mixer.
AudioRendererSink::RenderCallback* callback_ = nullptr;
// SwitchOutputDevice() and GetOutputDeviceInfoAsync() must be mutually
// exclusive when executing; these flags indicate whether one or the other is
// in progress. Each method will use the other method's to defer its action.
bool godia_in_progress_ = false;
bool switch_output_device_in_progress_ = false;
// Set by GetOutputDeviceInfoAsync() if a SwitchOutputDevice() call is in
// progress. GetOutputDeviceInfoAsync() will be invoked again with this value
// once OnDeviceSwitchReady() from the SwitchOutputDevice() call completes.
OutputDeviceInfoCB pending_device_info_cb_;
// Set by SwitchOutputDevice() if a GetOutputDeviceInfoAsync() call is in
// progress. SwitchOutputDevice() will be invoked again with these values once
// the OnDeviceInfoReceived() from the GODIA() call completes.
std::string pending_device_id_;
OutputDeviceStatusCB pending_switch_cb_;
} // namespace media