blob: 7d77212bbe64eed8938ace0f930891ddc827908a [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.
#ifndef CONTENT_RENDERER_MEDIA_AUDIO_RENDERER_MIXER_MANAGER_H_
#define CONTENT_RENDERER_MEDIA_AUDIO_RENDERER_MIXER_MANAGER_H_
#include <bitset>
#include <map>
#include <memory>
#include <string>
#include "base/macros.h"
#include "base/synchronization/lock.h"
#include "content/common/content_export.h"
#include "media/audio/audio_device_description.h"
#include "media/base/audio_latency.h"
#include "media/base/audio_parameters.h"
#include "media/base/audio_renderer_mixer_pool.h"
#include "media/base/output_device_info.h"
#include "url/origin.h"
namespace media {
class AudioRendererMixer;
class AudioRendererMixerInput;
class AudioRendererSink;
}
namespace content {
class AudioRendererSinkCache;
// Manages sharing of an AudioRendererMixer among AudioRendererMixerInputs based
// on their AudioParameters configuration. Inputs with the same AudioParameters
// configuration will share a mixer while a new AudioRendererMixer will be
// lazily created if one with the exact AudioParameters does not exist. When an
// AudioRendererMixer is returned by AudioRendererMixerInput, it will be deleted
// if its only other reference is held by AudioRendererMixerManager.
//
// There should only be one instance of AudioRendererMixerManager per render
// thread.
//
// TODO(dalecurtis): Right now we require AudioParameters to be an exact match
// when we should be able to ignore bits per channel since we're only dealing
// with floats. However, bits per channel is currently used to interleave the
// audio data by AudioOutputDevice::AudioThreadCallback::Process for consumption
// via the shared memory. See http://crbug.com/114700.
class CONTENT_EXPORT AudioRendererMixerManager
: public media::AudioRendererMixerPool {
public:
~AudioRendererMixerManager() final;
static std::unique_ptr<AudioRendererMixerManager> Create();
// Creates an AudioRendererMixerInput with the proper callbacks necessary to
// retrieve an AudioRendererMixer instance from AudioRendererMixerManager.
// |source_render_frame_id| refers to the RenderFrame containing the entity
// rendering the audio. Caller must ensure AudioRendererMixerManager outlives
// the returned input. |device_id|, |session_id| and |security_origin|
// identify the output device to use. If |device_id| is empty and |session_id|
// is nonzero, output device associated with the opened input device
// designated by |session_id| is used. Otherwise, |session_id| is ignored.
media::AudioRendererMixerInput* CreateInput(
int source_render_frame_id,
int session_id,
const std::string& device_id,
const url::Origin& security_origin,
media::AudioLatency::LatencyType latency);
// AudioRendererMixerPool implementation.
media::AudioRendererMixer* GetMixer(
int source_render_frame_id,
const media::AudioParameters& input_params,
media::AudioLatency::LatencyType latency,
const std::string& device_id,
const url::Origin& security_origin,
media::OutputDeviceStatus* device_status) final;
void ReturnMixer(media::AudioRendererMixer* mixer) final;
media::OutputDeviceInfo GetOutputDeviceInfo(
int source_render_frame_id,
int session_id,
const std::string& device_id,
const url::Origin& security_origin) final;
protected:
explicit AudioRendererMixerManager(
std::unique_ptr<AudioRendererSinkCache> sink_cache);
private:
friend class AudioRendererMixerManagerTest;
// Define a key so that only those AudioRendererMixerInputs from the same
// RenderView, AudioParameters and output device can be mixed together.
struct MixerKey {
MixerKey(int source_render_frame_id,
const media::AudioParameters& params,
media::AudioLatency::LatencyType latency,
const std::string& device_id,
const url::Origin& security_origin);
MixerKey(const MixerKey& other);
int source_render_frame_id;
media::AudioParameters params;
media::AudioLatency::LatencyType latency;
std::string device_id;
url::Origin security_origin;
};
// Custom compare operator for the AudioRendererMixerMap. Allows reuse of
// mixers where only irrelevant keys mismatch; e.g., effects, bits per sample.
struct MixerKeyCompare {
bool operator()(const MixerKey& a, const MixerKey& b) const {
if (a.source_render_frame_id != b.source_render_frame_id)
return a.source_render_frame_id < b.source_render_frame_id;
if (a.params.channels() != b.params.channels())
return a.params.channels() < b.params.channels();
if (a.latency != b.latency)
return a.latency < b.latency;
// TODO(olka) add buffer duration comparison for LATENCY_EXACT_MS when
// adding support for it.
DCHECK_NE(media::AudioLatency::LATENCY_EXACT_MS, a.latency);
// Ignore effects(), bits_per_sample(), format(), and frames_per_buffer(),
// these parameters do not affect mixer reuse. All AudioRendererMixer
// units disable FIFO, so frames_per_buffer() can be safely ignored.
if (a.params.channel_layout() != b.params.channel_layout())
return a.params.channel_layout() < b.params.channel_layout();
if (media::AudioDeviceDescription::IsDefaultDevice(a.device_id) &&
media::AudioDeviceDescription::IsDefaultDevice(b.device_id)) {
// Both device IDs represent the same default device => do not compare
// them; the default device is always authorized => ignoring security
// origin.
return false;
}
if (a.device_id != b.device_id)
return a.device_id < b.device_id;
return a.security_origin < b.security_origin;
}
};
// Map of MixerKey to <AudioRendererMixer, Count>. Count allows
// AudioRendererMixerManager to keep track explicitly (v.s. RefCounted which
// is implicit) of the number of outstanding AudioRendererMixers.
struct AudioRendererMixerReference {
media::AudioRendererMixer* mixer;
int ref_count;
// Mixer sink pointer, to remove a sink from cache upon mixer destruction.
const media::AudioRendererSink* sink_ptr;
};
using AudioRendererMixerMap =
std::map<MixerKey, AudioRendererMixerReference, MixerKeyCompare>;
// Active mixers.
AudioRendererMixerMap mixers_;
base::Lock mixers_lock_;
// Mixer sink cache.
const std::unique_ptr<AudioRendererSinkCache> sink_cache_;
// Map of the output latencies encountered throughout mixer manager lifetime.
// Used for UMA histogram logging.
std::bitset<media::AudioLatency::LATENCY_COUNT> latency_map_;
DISALLOW_COPY_AND_ASSIGN(AudioRendererMixerManager);
};
} // namespace content
#endif // CONTENT_RENDERER_MEDIA_AUDIO_RENDERER_MIXER_MANAGER_H_