/* ** ** 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/LinearTransform.h> #include <utils/String16.h> #include <utils/String8.h> #include <utils/threads.h> #include <utils/Vector.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