148 lines
5.8 KiB
C++
148 lines
5.8 KiB
C++
/*
|
|
* Copyright (c) 2018 The WebRTC project authors. All Rights Reserved.
|
|
*
|
|
* Use of this source code is governed by a BSD-style license
|
|
* that can be found in the LICENSE file in the root of the source
|
|
* tree. An additional intellectual property rights grant can be found
|
|
* in the file PATENTS. All contributing project authors may
|
|
* be found in the AUTHORS file in the root of the source tree.
|
|
*/
|
|
|
|
#ifndef MODULES_AUDIO_DEVICE_ANDROID_AAUDIO_PLAYER_H_
|
|
#define MODULES_AUDIO_DEVICE_ANDROID_AAUDIO_PLAYER_H_
|
|
|
|
#include <aaudio/AAudio.h>
|
|
|
|
#include <memory>
|
|
|
|
#include "modules/audio_device/android/aaudio_wrapper.h"
|
|
#include "modules/audio_device/include/audio_device_defines.h"
|
|
#include "rtc_base/message_handler.h"
|
|
#include "rtc_base/thread.h"
|
|
#include "rtc_base/thread_annotations.h"
|
|
#include "rtc_base/thread_checker.h"
|
|
|
|
namespace webrtc {
|
|
|
|
class AudioDeviceBuffer;
|
|
class FineAudioBuffer;
|
|
class AudioManager;
|
|
|
|
// Implements low-latency 16-bit mono PCM audio output support for Android
|
|
// using the C based AAudio API.
|
|
//
|
|
// An instance must be created and destroyed on one and the same thread.
|
|
// All public methods must also be called on the same thread. A thread checker
|
|
// will DCHECK if any method is called on an invalid thread. Audio buffers
|
|
// are requested on a dedicated high-priority thread owned by AAudio.
|
|
//
|
|
// The existing design forces the user to call InitPlayout() after StopPlayout()
|
|
// to be able to call StartPlayout() again. This is in line with how the Java-
|
|
// based implementation works.
|
|
//
|
|
// An audio stream can be disconnected, e.g. when an audio device is removed.
|
|
// This implementation will restart the audio stream using the new preferred
|
|
// device if such an event happens.
|
|
//
|
|
// Also supports automatic buffer-size adjustment based on underrun detections
|
|
// where the internal AAudio buffer can be increased when needed. It will
|
|
// reduce the risk of underruns (~glitches) at the expense of an increased
|
|
// latency.
|
|
class AAudioPlayer final : public AAudioObserverInterface,
|
|
public rtc::MessageHandler {
|
|
public:
|
|
explicit AAudioPlayer(AudioManager* audio_manager);
|
|
~AAudioPlayer();
|
|
|
|
int Init();
|
|
int Terminate();
|
|
|
|
int InitPlayout();
|
|
bool PlayoutIsInitialized() const;
|
|
|
|
int StartPlayout();
|
|
int StopPlayout();
|
|
bool Playing() const;
|
|
|
|
void AttachAudioBuffer(AudioDeviceBuffer* audioBuffer);
|
|
|
|
// Not implemented in AAudio.
|
|
int SpeakerVolumeIsAvailable(bool& available); // NOLINT
|
|
int SetSpeakerVolume(uint32_t volume) { return -1; }
|
|
int SpeakerVolume(uint32_t& volume) const { return -1; } // NOLINT
|
|
int MaxSpeakerVolume(uint32_t& maxVolume) const { return -1; } // NOLINT
|
|
int MinSpeakerVolume(uint32_t& minVolume) const { return -1; } // NOLINT
|
|
|
|
protected:
|
|
// AAudioObserverInterface implementation.
|
|
|
|
// For an output stream, this function should render and write |num_frames|
|
|
// of data in the streams current data format to the |audio_data| buffer.
|
|
// Called on a real-time thread owned by AAudio.
|
|
aaudio_data_callback_result_t OnDataCallback(void* audio_data,
|
|
int32_t num_frames) override;
|
|
// AAudio calls this functions if any error occurs on a callback thread.
|
|
// Called on a real-time thread owned by AAudio.
|
|
void OnErrorCallback(aaudio_result_t error) override;
|
|
|
|
// rtc::MessageHandler used for restart messages from the error-callback
|
|
// thread to the main (creating) thread.
|
|
void OnMessage(rtc::Message* msg) override;
|
|
|
|
private:
|
|
// Closes the existing stream and starts a new stream.
|
|
void HandleStreamDisconnected();
|
|
|
|
// Ensures that methods are called from the same thread as this object is
|
|
// created on.
|
|
rtc::ThreadChecker main_thread_checker_;
|
|
|
|
// Stores thread ID in first call to AAudioPlayer::OnDataCallback from a
|
|
// real-time thread owned by AAudio. Detached during construction of this
|
|
// object.
|
|
rtc::ThreadChecker thread_checker_aaudio_;
|
|
|
|
// The thread on which this object is created on.
|
|
rtc::Thread* main_thread_;
|
|
|
|
// Wraps all AAudio resources. Contains an output stream using the default
|
|
// output audio device. Can be accessed on both the main thread and the
|
|
// real-time thread owned by AAudio. See separate AAudio documentation about
|
|
// thread safety.
|
|
AAudioWrapper aaudio_;
|
|
|
|
// FineAudioBuffer takes an AudioDeviceBuffer which delivers audio data
|
|
// in chunks of 10ms. It then allows for this data to be pulled in
|
|
// a finer or coarser granularity. I.e. interacting with this class instead
|
|
// of directly with the AudioDeviceBuffer one can ask for any number of
|
|
// audio data samples.
|
|
// Example: native buffer size can be 192 audio frames at 48kHz sample rate.
|
|
// WebRTC will provide 480 audio frames per 10ms but AAudio asks for 192
|
|
// in each callback (once every 4th ms). This class can then ask for 192 and
|
|
// the FineAudioBuffer will ask WebRTC for new data approximately only every
|
|
// second callback and also cache non-utilized audio.
|
|
std::unique_ptr<FineAudioBuffer> fine_audio_buffer_;
|
|
|
|
// Counts number of detected underrun events reported by AAudio.
|
|
int32_t underrun_count_ = 0;
|
|
|
|
// True only for the first data callback in each audio session.
|
|
bool first_data_callback_ = true;
|
|
|
|
// Raw pointer handle provided to us in AttachAudioBuffer(). Owned by the
|
|
// AudioDeviceModuleImpl class and set by AudioDeviceModule::Create().
|
|
AudioDeviceBuffer* audio_device_buffer_ RTC_GUARDED_BY(main_thread_checker_) =
|
|
nullptr;
|
|
|
|
bool initialized_ RTC_GUARDED_BY(main_thread_checker_) = false;
|
|
bool playing_ RTC_GUARDED_BY(main_thread_checker_) = false;
|
|
|
|
// Estimated latency between writing an audio frame to the output stream and
|
|
// the time that same frame is played out on the output audio device.
|
|
double latency_millis_ RTC_GUARDED_BY(thread_checker_aaudio_) = 0;
|
|
};
|
|
|
|
} // namespace webrtc
|
|
|
|
#endif // MODULES_AUDIO_DEVICE_ANDROID_AAUDIO_PLAYER_H_
|