177 lines
5.8 KiB
C++
177 lines
5.8 KiB
C++
/*
|
|
**
|
|
** Copyright 2011, The Android Open Source Project
|
|
**
|
|
** Licensed under the Apache License, Version 2.0 (the "License");
|
|
** you may not use this file except in compliance with the License.
|
|
** You may obtain a copy of the License at
|
|
**
|
|
** http://www.apache.org/licenses/LICENSE-2.0
|
|
**
|
|
** Unless required by applicable law or agreed to in writing, software
|
|
** distributed under the License is distributed on an "AS IS" BASIS,
|
|
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
** See the License for the specific language governing permissions and
|
|
** limitations under the License.
|
|
*/
|
|
|
|
#ifndef ANDROID_AUDIO_OUTPUT_H
|
|
#define ANDROID_AUDIO_OUTPUT_H
|
|
|
|
#include <semaphore.h>
|
|
#include <tinyalsa/asoundlib.h>
|
|
#include <utils/String16.h>
|
|
#include <utils/String8.h>
|
|
#include <utils/threads.h>
|
|
#include <utils/Vector.h>
|
|
|
|
#include "LinearTransform.h"
|
|
|
|
namespace android {
|
|
|
|
class AudioStreamOut;
|
|
|
|
class AudioOutput : public RefBase {
|
|
public:
|
|
|
|
// Audio ouput state machine states.
|
|
enum State {
|
|
// Ouput not yet started or synchronized.
|
|
OUT_OF_SYNC,
|
|
|
|
// Silence primed to output to start DMA.
|
|
PRIMED,
|
|
|
|
// DMA started, ready to align to other inputs.
|
|
DMA_START,
|
|
|
|
// DMA active.
|
|
ACTIVE,
|
|
|
|
// Fatal, unrecoverable error.
|
|
FATAL,
|
|
};
|
|
|
|
AudioOutput(const char* alsa_name,
|
|
enum pcm_format alsa_pcm_format);
|
|
virtual ~AudioOutput();
|
|
|
|
virtual status_t initCheck();
|
|
virtual status_t setupForStream(const AudioStreamOut& stream) = 0;
|
|
|
|
// State machine transition functions.
|
|
State getState() { return mState; };
|
|
bool hasFatalError() { return mState == FATAL; }
|
|
|
|
// Prime data to output device, go to PRIMED state.
|
|
void primeOutput(bool hasActiveOutputs);
|
|
|
|
// Adjust for write timestamp difference, go to ACTIVE state.
|
|
void adjustDelay(int32_t nFrames);
|
|
|
|
// Send one chunk of data to ALSA, if state machine permits. This is called
|
|
// for every chunk sent down, regardless of the state of the output.
|
|
void processOneChunk(const uint8_t* data, size_t len,
|
|
bool hasActiveOutputs, audio_format_t format);
|
|
|
|
status_t getNextWriteTimestamp(int64_t* timestamp,
|
|
bool* discon);
|
|
bool getLastNextWriteTSValid() const;
|
|
int64_t getLastNextWriteTS() const;
|
|
|
|
uint32_t getExternalDelay_uSec() const;
|
|
void setExternalDelay_uSec(uint32_t delay);
|
|
void setDelayComp_uSec(uint32_t delay_usec);
|
|
|
|
void setVolume(float vol);
|
|
void setMute(bool mute);
|
|
void setOutputIsFixed(bool fixed);
|
|
void setFixedOutputLevel(float level);
|
|
|
|
float getVolume() const { return mVolume; }
|
|
bool getMute() const { return mMute; }
|
|
bool getOutputIsFixed() const { return mOutputFixed; }
|
|
float getFixedOutputLevel() const { return mFixedLvl; }
|
|
|
|
int getHardwareTimestamp(unsigned int *pAvail,
|
|
struct timespec *pTimestamp);
|
|
uint32_t getKernelBufferSize() { return mFramesPerChunk * mBufferChunks; }
|
|
|
|
virtual void dump(String8& result) = 0;
|
|
|
|
virtual const char* getOutputName() = 0;
|
|
virtual uint32_t devMask() const = 0;
|
|
|
|
virtual void cleanupResources();
|
|
|
|
static const uint32_t kMaxDelayCompensationMSec;
|
|
static const uint32_t kPrimeTimeoutChunks;
|
|
|
|
protected:
|
|
|
|
void pushSilence(uint32_t nFrames);
|
|
|
|
virtual void openPCMDevice();
|
|
virtual void reset();
|
|
virtual status_t getDMAStartData(int64_t* dma_start_time,
|
|
int64_t* frames_queued_to_driver);
|
|
void doPCMWrite(const uint8_t* data, size_t len, audio_format_t format);
|
|
void setupInternal();
|
|
|
|
// Current state machine state.
|
|
State mState;
|
|
|
|
// Output format
|
|
uint32_t mFramesPerChunk;
|
|
uint32_t mFramesPerSec;
|
|
uint32_t mBufferChunks;
|
|
uint32_t mChannelCnt;
|
|
const char* mALSAName;
|
|
enum pcm_format mALSAFormat;
|
|
|
|
// These numbers are relative to the ALSA output.
|
|
uint32_t mBytesPerSample;
|
|
uint32_t mBytesPerFrame;
|
|
uint32_t mBytesPerChunk;
|
|
size_t mStagingSize;
|
|
void* mStagingBuf;
|
|
size_t mSilenceSize;
|
|
void* mSilenceBuf;
|
|
|
|
// Get next write time stuff.
|
|
bool mLastNextWriteTimeValid;
|
|
int64_t mLastNextWriteTime;
|
|
int64_t mLastDMAStartTime;
|
|
|
|
// External delay compensation.
|
|
uint32_t mMaxDelayCompFrames;
|
|
uint32_t mExternalDelayUSec;
|
|
uint32_t mExternalDelayLocalTicks;
|
|
|
|
LinearTransform mFramesToLocalTime;
|
|
|
|
// ALSA device stuff.
|
|
Mutex mDeviceLock;
|
|
struct pcm* mDevice;
|
|
int mDeviceExtFd;
|
|
int mALSACardID;
|
|
uint64_t mFramesQueuedToDriver;
|
|
uint32_t mPrimeTimeoutChunks;
|
|
|
|
// reduce log spew
|
|
bool mReportedWriteFail;
|
|
|
|
// Volume stuff
|
|
Mutex mVolumeLock;
|
|
float mVolume;
|
|
float mFixedLvl;
|
|
bool mMute;
|
|
bool mOutputFixed;
|
|
bool mVolParamsDirty;
|
|
virtual void applyPendingVolParams() = 0;
|
|
};
|
|
|
|
typedef Vector< sp<AudioOutput> > AudioOutputList;
|
|
|
|
} // namespace android
|
|
#endif // ANDROID_AUDIO_OUTPUT_H
|