| /* |
| ** |
| ** 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 |