blob: 0e8e82984a9df5005fa6ecb64d1062df2a0b1050 [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 MEDIA_AUDIO_WIN_AUDIO_UNIFIED_WIN_H_
#define MEDIA_AUDIO_WIN_AUDIO_UNIFIED_WIN_H_
#include <Audioclient.h>
#include <MMDeviceAPI.h>
#include <string>
#include "base/compiler_specific.h"
#include "base/gtest_prod_util.h"
#include "base/threading/platform_thread.h"
#include "base/threading/simple_thread.h"
#include "base/win/scoped_co_mem.h"
#include "base/win/scoped_comptr.h"
#include "base/win/scoped_handle.h"
#include "media/audio/audio_io.h"
#include "media/audio/audio_parameters.h"
#include "media/base/media_export.h"
namespace media {
class AudioManagerWin;
// Implementation of AudioOutputStream for Windows using the Core Audio API
// where both capturing and rendering takes place on the same thread to enable
// audio I/O.
//
// The user should also ensure that audio I/O is supported by calling
// HasUnifiedDefaultIO().
//
// Implementation notes:
//
// - Certain conditions must be fulfilled to support audio I/O:
// o Both capture and render side must use the same sample rate.
// o Both capture and render side must use the same channel count.
// o Both capture and render side must use the same channel configuration.
// o See HasUnifiedDefaultIO() for more details.
//
// TODO(henrika):
//
// - Add support for exclusive mode.
// - Add multi-channel support.
// - Add support for non-matching sample rates.
//
class MEDIA_EXPORT WASAPIUnifiedStream
: public AudioOutputStream,
public base::DelegateSimpleThread::Delegate {
public:
// The ctor takes all the usual parameters, plus |manager| which is the
// the audio manager who is creating this object.
WASAPIUnifiedStream(AudioManagerWin* manager,
const AudioParameters& params);
// The dtor is typically called by the AudioManager only and it is usually
// triggered by calling AudioOutputStream::Close().
virtual ~WASAPIUnifiedStream();
// Implementation of AudioOutputStream.
virtual bool Open() OVERRIDE;
virtual void Start(AudioSourceCallback* callback) OVERRIDE;
virtual void Stop() OVERRIDE;
virtual void Close() OVERRIDE;
virtual void SetVolume(double volume) OVERRIDE;
virtual void GetVolume(double* volume) OVERRIDE;
// Returns true if all conditions to support audio IO are fulfilled.
// Input and output sides of the Audio Engine must use the same native
// device period (requires e.g. identical sample rates) and have the same
// channel count.
static bool HasUnifiedDefaultIO();
bool started() const {
return audio_io_thread_.get() != NULL;
}
private:
// DelegateSimpleThread::Delegate implementation.
virtual void Run() OVERRIDE;
// Issues the OnError() callback to the |source_|.
void HandleError(HRESULT err);
// Stops and joins the audio thread in case of an error.
void StopAndJoinThread(HRESULT err);
// Converts unique endpoint ID to user-friendly device name.
std::string GetDeviceName(LPCWSTR device_id) const;
// Returns the number of channels the audio engine uses for its internal
// processing/mixing of shared-mode streams for the default endpoint device.
int endpoint_channel_count() { return format_.Format.nChannels; }
// Contains the thread ID of the creating thread.
base::PlatformThreadId creating_thread_id_;
// Our creator, the audio manager needs to be notified when we close.
AudioManagerWin* manager_;
// The sharing mode for the streams.
// Valid values are AUDCLNT_SHAREMODE_SHARED and AUDCLNT_SHAREMODE_EXCLUSIVE
// where AUDCLNT_SHAREMODE_SHARED is the default.
AUDCLNT_SHAREMODE share_mode_;
// Rendering and capturing is driven by this thread (no message loop).
// All OnMoreIOData() callbacks will be called from this thread.
scoped_ptr<base::DelegateSimpleThread> audio_io_thread_;
// Contains the desired audio format which is set up at construction.
// Extended PCM waveform format structure based on WAVEFORMATEXTENSIBLE.
// Use this for multiple channel and hi-resolution PCM data.
WAVEFORMATPCMEX format_;
// True when successfully opened.
bool opened_;
// Size in bytes of each audio frame (4 bytes for 16-bit stereo PCM).
size_t frame_size_;
// Size in audio frames of each audio packet where an audio packet
// is defined as the block of data which the source is expected to deliver
// in each OnMoreIOData() callback.
size_t packet_size_frames_;
// Length of the audio endpoint buffer.
size_t endpoint_render_buffer_size_frames_;
size_t endpoint_capture_buffer_size_frames_;
// Counts the number of audio frames written to the endpoint buffer.
uint64 num_written_frames_;
// Time stamp for last delay measurement.
base::TimeTicks last_delay_sample_time_;
// Contains the total (sum of render and capture) delay in milliseconds.
double total_delay_ms_;
// Pointer to the client that will deliver audio samples to be played out.
AudioSourceCallback* source_;
// IMMDevice interfaces which represents audio endpoint devices.
base::win::ScopedComPtr<IMMDevice> endpoint_render_device_;
base::win::ScopedComPtr<IMMDevice> endpoint_capture_device_;
// IAudioClient interfaces which enables a client to create and initialize
// an audio stream between an audio application and the audio engine.
base::win::ScopedComPtr<IAudioClient> audio_output_client_;
base::win::ScopedComPtr<IAudioClient> audio_input_client_;
// IAudioRenderClient interfaces enables a client to write output
// data to a rendering endpoint buffer.
base::win::ScopedComPtr<IAudioRenderClient> audio_render_client_;
// IAudioCaptureClient interfaces enables a client to read input
// data from a capturing endpoint buffer.
base::win::ScopedComPtr<IAudioCaptureClient> audio_capture_client_;
// The audio engine will signal this event each time a buffer has been
// recorded.
base::win::ScopedHandle capture_event_;
// This event will be signaled when streaming shall stop.
base::win::ScopedHandle stop_streaming_event_;
// Container for retrieving data from AudioSourceCallback::OnMoreIOData().
scoped_ptr<AudioBus> render_bus_;
// Container for sending data to AudioSourceCallback::OnMoreIOData().
scoped_ptr<AudioBus> capture_bus_;
DISALLOW_COPY_AND_ASSIGN(WASAPIUnifiedStream);
};
} // namespace media
#endif // MEDIA_AUDIO_WIN_AUDIO_UNIFIED_WIN_H_