Home | History | Annotate | Download | only in libaudio
      1 /*
      2 **
      3 ** Copyright 2011, The Android Open Source Project
      4 **
      5 ** Licensed under the Apache License, Version 2.0 (the "License");
      6 ** you may not use this file except in compliance with the License.
      7 ** You may obtain a copy of the License at
      8 **
      9 **     http://www.apache.org/licenses/LICENSE-2.0
     10 **
     11 ** Unless required by applicable law or agreed to in writing, software
     12 ** distributed under the License is distributed on an "AS IS" BASIS,
     13 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     14 ** See the License for the specific language governing permissions and
     15 ** limitations under the License.
     16 */
     17 
     18 #define LOG_TAG "AudioHAL:AudioOutput"
     19 // #define LOG_NDEBUG 0
     20 
     21 #include <utils/Log.h>
     22 
     23 #include <assert.h>
     24 #include <limits.h>
     25 #include <semaphore.h>
     26 #include <sys/ioctl.h>
     27 
     28 #include <audio_utils/primitives.h>
     29 #include <common_time/local_clock.h>
     30 
     31 #define __DO_FUNCTION_IMPL__
     32 #include "alsa_utils.h"
     33 #undef __DO_FUNCTION_IMPL__
     34 #include "AudioOutput.h"
     35 
     36 // TODO: Consider using system/media/alsa_utils for the future.
     37 
     38 namespace android {
     39 
     40 const uint32_t AudioOutput::kMaxDelayCompensationMSec = 300;
     41 const uint32_t AudioOutput::kPrimeTimeoutChunks = 10; // 100ms
     42 
     43 AudioOutput::AudioOutput(const char* alsa_name,
     44                          enum pcm_format alsa_pcm_format)
     45         : mState(OUT_OF_SYNC)
     46         , mFramesPerChunk(0)
     47         , mFramesPerSec(0)
     48         , mBufferChunks(0)
     49         , mChannelCnt(0)
     50         , mALSAName(alsa_name)
     51         , mALSAFormat(alsa_pcm_format)
     52         , mBytesPerSample(0)
     53         , mBytesPerFrame(0)
     54         , mBytesPerChunk(0)
     55         , mStagingSize(0)
     56         , mStagingBuf(NULL)
     57         , mSilenceSize(0)
     58         , mSilenceBuf(NULL)
     59         , mPrimeTimeoutChunks(0)
     60         , mReportedWriteFail(false)
     61         , mVolume(0.0)
     62         , mFixedLvl(0.0)
     63         , mMute(false)
     64         , mOutputFixed(false)
     65         , mVolParamsDirty(true)
     66 {
     67     mLastNextWriteTimeValid = false;
     68 
     69     mMaxDelayCompFrames = 0;
     70     mExternalDelayUSec = 0;
     71 
     72     mDevice = NULL;
     73     mDeviceExtFd = -1;
     74     mALSACardID = -1;
     75     mFramesQueuedToDriver = 0;
     76 }
     77 
     78 AudioOutput::~AudioOutput() {
     79     cleanupResources();
     80     free(mStagingBuf);
     81     free(mSilenceBuf);
     82 }
     83 
     84 status_t AudioOutput::initCheck() {
     85     if (!mDevice) {
     86         ALOGE("Unable to open PCM device for %s output.", getOutputName());
     87         return NO_INIT;
     88     }
     89     if (!pcm_is_ready(mDevice)) {
     90         ALOGE("PCM device %s is not ready.", getOutputName());
     91         ALOGE("PCM error: %s", pcm_get_error(mDevice));
     92         return NO_INIT;
     93     }
     94 
     95     return OK;
     96 }
     97 
     98 void AudioOutput::setupInternal() {
     99     LocalClock lc;
    100 
    101     mMaxDelayCompFrames = kMaxDelayCompensationMSec * mFramesPerSec / 1000;
    102 
    103     switch (mALSAFormat) {
    104     case PCM_FORMAT_S16_LE:
    105         mBytesPerSample = 2;
    106         break;
    107     case PCM_FORMAT_S24_3LE:
    108         mBytesPerSample = 3;
    109         break;
    110     case PCM_FORMAT_S24_LE: // fall through
    111     case PCM_FORMAT_S32_LE:
    112         mBytesPerSample = 4;
    113         break;
    114     default:
    115         LOG_ALWAYS_FATAL("Unexpected alsa format %d", mALSAFormat);
    116         break;
    117     }
    118 
    119     mBytesPerFrame = mBytesPerSample * mChannelCnt;
    120     mBytesPerChunk = mBytesPerFrame * mFramesPerChunk;
    121 
    122     memset(&mFramesToLocalTime, 0, sizeof(mFramesToLocalTime));
    123     mFramesToLocalTime.a_to_b_numer = lc.getLocalFreq();
    124     mFramesToLocalTime.a_to_b_denom = mFramesPerSec ? mFramesPerSec : 1;
    125     LinearTransform::reduce(
    126             &mFramesToLocalTime.a_to_b_numer,
    127             &mFramesToLocalTime.a_to_b_denom);
    128 
    129     openPCMDevice();
    130 }
    131 
    132 void AudioOutput::primeOutput(bool hasActiveOutputs) {
    133     ALOGI("primeOutput %s", getOutputName());
    134 
    135     if (hasFatalError())
    136         return;
    137 
    138     // See comments in AudioStreamOut::write for the reasons behind the
    139     // different priming levels.
    140     uint32_t primeAmt = mFramesPerChunk * mBufferChunks;
    141     if (hasActiveOutputs)
    142         primeAmt /= 2;
    143 
    144     pushSilence(primeAmt);
    145     mPrimeTimeoutChunks = 0;
    146     mState = PRIMED;
    147 }
    148 
    149 void AudioOutput::adjustDelay(int32_t nFrames) {
    150     if (hasFatalError())
    151         return;
    152 
    153     if (nFrames >= 0) {
    154         ALOGI("adjustDelay %s %d", getOutputName(), nFrames);
    155         pushSilence(nFrames);
    156         mState = ACTIVE;
    157     } else {
    158         ALOGW("adjustDelay %s %d, ignoring negative adjustment",
    159               getOutputName(), nFrames);
    160     }
    161 }
    162 
    163 void AudioOutput::pushSilence(uint32_t nFrames)
    164 {
    165     if (nFrames == 0 || hasFatalError())
    166         return;
    167     // choose 8_24_BIT instead of 16_BIT as it is native to Fugu
    168     const audio_format_t format = AUDIO_FORMAT_PCM_8_24_BIT;
    169     const size_t frameSize = audio_bytes_per_sample(format) * mChannelCnt;
    170     const size_t writeSize = nFrames * frameSize;
    171     if (mSilenceSize < writeSize) {
    172         // for zero initialized memory calloc is much faster than malloc or realloc.
    173         void *sbuf = calloc(nFrames, frameSize);
    174         if (sbuf == NULL) return;
    175         free(mSilenceBuf);
    176         mSilenceBuf = sbuf;
    177         mSilenceSize = writeSize;
    178     }
    179     doPCMWrite((const uint8_t*)mSilenceBuf, writeSize, format);
    180     mFramesQueuedToDriver += nFrames;
    181 }
    182 
    183 void AudioOutput::cleanupResources() {
    184 
    185     Mutex::Autolock _l(mDeviceLock);
    186 
    187     if (NULL != mDevice)
    188         pcm_close(mDevice);
    189 
    190     mDevice = NULL;
    191     mDeviceExtFd = -1;
    192     mALSACardID = -1;
    193 }
    194 
    195 void AudioOutput::openPCMDevice() {
    196 
    197     Mutex::Autolock _l(mDeviceLock);
    198     if (NULL == mDevice) {
    199         struct pcm_config config;
    200         int dev_id = 0;
    201         int retry = 0;
    202         static const int MAX_RETRY_COUNT = 3;
    203 
    204         mALSACardID = find_alsa_card_by_name(mALSAName);
    205         if (mALSACardID < 0)
    206             return;
    207 
    208         memset(&config, 0, sizeof(config));
    209         config.channels        = mChannelCnt;
    210         config.rate            = mFramesPerSec;
    211         config.period_size     = mFramesPerChunk;
    212         config.period_count    = mBufferChunks;
    213         config.format          = mALSAFormat;
    214         // start_threshold is in audio frames. The default behavior
    215         // is to fill period_size*period_count frames before outputing
    216         // audio. Setting to 1 will start the DMA immediately. Our first
    217         // write is a full chunk, so we have 10ms to get back with the next
    218         // chunk before we underflow. This number could be increased if
    219         // problems arise.
    220         config.start_threshold = 1;
    221 
    222         ALOGI("calling pcm_open() for output, mALSACardID = %d, dev_id %d, rate = %u, "
    223             "%d channels, framesPerChunk = %d, alsaFormat = %d",
    224               mALSACardID, dev_id, config.rate, config.channels, config.period_size, config.format);
    225         while (1) {
    226             // Use PCM_MONOTONIC clock for get_presentation_position.
    227             mDevice = pcm_open(mALSACardID, dev_id,
    228                     PCM_OUT | PCM_NORESTART | PCM_MONOTONIC, &config);
    229             if (initCheck() == OK)
    230                 break;
    231             if (retry++ >= MAX_RETRY_COUNT) {
    232                 ALOGI("out of retries, giving up");
    233                 break;
    234             }
    235             /* try again after a delay.  on hotplug, there appears to
    236              * be a race where the pcm device node isn't available on
    237              * first open try.
    238              */
    239             pcm_close(mDevice);
    240             mDevice = NULL;
    241             sleep(1);
    242             ALOGI("retrying pcm_open() after delay");
    243         }
    244         mDeviceExtFd = mDevice
    245                         ? *(reinterpret_cast<int*>(mDevice))
    246                         : -1;
    247         mState = OUT_OF_SYNC;
    248     }
    249 }
    250 
    251 status_t AudioOutput::getNextWriteTimestamp(int64_t* timestamp,
    252                                             bool* discon) {
    253     int64_t  dma_start_time;
    254     int64_t  frames_queued_to_driver;
    255     status_t ret;
    256 
    257     *discon = false;
    258     if (hasFatalError())
    259         return UNKNOWN_ERROR;
    260 
    261     ret = getDMAStartData(&dma_start_time,
    262                           &frames_queued_to_driver);
    263     if (OK != ret) {
    264         if (mLastNextWriteTimeValid) {
    265             if (!hasFatalError())
    266                 ALOGE("Underflow detected for output \"%s\"", getOutputName());
    267             *discon = true;
    268         }
    269 
    270         goto bailout;
    271     }
    272 
    273     if (mLastNextWriteTimeValid && (mLastDMAStartTime != dma_start_time)) {
    274         *discon = true;
    275         ret = UNKNOWN_ERROR;
    276 
    277         ALOGE("Discontinuous DMA start time detected for output \"%s\"."
    278               "DMA start time is %lld, but last DMA start time was %lld.",
    279               getOutputName(), dma_start_time, mLastDMAStartTime);
    280 
    281         goto bailout;
    282     }
    283 
    284     mLastDMAStartTime = dma_start_time;
    285 
    286     mFramesToLocalTime.a_zero = 0;
    287     mFramesToLocalTime.b_zero = dma_start_time;
    288 
    289     if (!mFramesToLocalTime.doForwardTransform(frames_queued_to_driver,
    290                                                timestamp)) {
    291         ALOGE("Overflow when attempting to compute next write time for output"
    292               " \"%s\".  Frames Queued To Driver = %lld, DMA Start Time = %lld",
    293               getOutputName(), frames_queued_to_driver, dma_start_time);
    294         ret = UNKNOWN_ERROR;
    295         goto bailout;
    296     }
    297 
    298     mLastNextWriteTime = *timestamp;
    299     mLastNextWriteTimeValid = true;
    300 
    301     // If we have a valuid timestamp, DMA has started so advance the state.
    302     if (mState == PRIMED)
    303         mState = DMA_START;
    304 
    305     return OK;
    306 
    307 bailout:
    308     mLastNextWriteTimeValid = false;
    309     // If we underflow, reset this output now.
    310     if (mState > PRIMED) {
    311         reset();
    312     }
    313 
    314     return ret;
    315 }
    316 
    317 bool AudioOutput::getLastNextWriteTSValid() const {
    318     return mLastNextWriteTimeValid;
    319 }
    320 
    321 int64_t AudioOutput::getLastNextWriteTS() const {
    322     return mLastNextWriteTime;
    323 }
    324 
    325 uint32_t AudioOutput::getExternalDelay_uSec() const {
    326     return mExternalDelayUSec;
    327 }
    328 
    329 void AudioOutput::setExternalDelay_uSec(uint32_t delay_usec) {
    330     mExternalDelayUSec = delay_usec;
    331 }
    332 
    333 void AudioOutput::reset() {
    334     if (hasFatalError())
    335         return;
    336 
    337     // Flush the driver level.
    338     cleanupResources();
    339     openPCMDevice();
    340     mFramesQueuedToDriver = 0;
    341     mLastNextWriteTimeValid = false;
    342 
    343     if (OK == initCheck()) {
    344         ALOGE("Reset %s", mALSAName);
    345     } else {
    346         ALOGE("Reset for %s failed, device is a zombie pending cleanup.", mALSAName);
    347         cleanupResources();
    348         mState = FATAL;
    349     }
    350 }
    351 
    352 status_t AudioOutput::getDMAStartData(
    353         int64_t* dma_start_time,
    354         int64_t* frames_queued_to_driver) {
    355     int ret;
    356 #if 1 /* not implemented in driver yet, just fake it */
    357     *dma_start_time = mLastDMAStartTime;
    358     ret = 0;
    359 #endif
    360 
    361     // If the get start time ioctl fails with an error of EBADFD, then our
    362     // underlying audio device is in the DISCONNECTED state.  The only reason
    363     // this should happen is that HDMI was unplugged while we were running, and
    364     // the audio driver needed to immediately shut down the driver without
    365     // involving the application level.  We should enter the fatal state, and
    366     // wait until the app level catches up to our view of the world (at which
    367     // point in time we will go through a plug/unplug cycle which should clean
    368     // things up).
    369     if (ret < 0) {
    370         if (EBADFD == errno) {
    371             ALOGI("Failed to ioctl to %s, output is probably disconnected."
    372                   " Going into zombie state to await cleanup.", mALSAName);
    373             cleanupResources();
    374             mState = FATAL;
    375         }
    376 
    377         return UNKNOWN_ERROR;
    378     }
    379 
    380     *frames_queued_to_driver = mFramesQueuedToDriver;
    381     return OK;
    382 }
    383 
    384 void AudioOutput::processOneChunk(const uint8_t* data, size_t len,
    385                                   bool hasActiveOutputs, audio_format_t format) {
    386     switch (mState) {
    387     case OUT_OF_SYNC:
    388         primeOutput(hasActiveOutputs);
    389         break;
    390     case PRIMED:
    391         if (mPrimeTimeoutChunks < kPrimeTimeoutChunks)
    392             mPrimeTimeoutChunks++;
    393         else
    394             // Uh-oh, DMA didn't start. Reset and try again.
    395             reset();
    396 
    397         break;
    398     case DMA_START:
    399         // Don't push data when primed and waiting for buffer alignment.
    400         // We need to align the ALSA buffers first.
    401         break;
    402     case ACTIVE: {
    403         doPCMWrite(data, len, format);
    404         // we use input frame size here (mBytesPerFrame is alsa device frame size)
    405         const size_t frameSize = mChannelCnt * audio_bytes_per_sample(format);
    406         mFramesQueuedToDriver += len / frameSize;
    407         } break;
    408     default:
    409         // Do nothing.
    410         break;
    411     }
    412 
    413 }
    414 
    415 void AudioOutput::doPCMWrite(const uint8_t* data, size_t len, audio_format_t format) {
    416     if (len == 0 || hasFatalError())
    417         return;
    418 
    419     // If write fails with an error of EBADFD, then our underlying audio
    420     // device is in a pretty bad state.  This common cause of this is
    421     // that HDMI was unplugged while we were running, and the audio
    422     // driver needed to immediately shut down the driver without
    423     // involving the application level.  When this happens, the HDMI
    424     // audio device is put into the DISCONNECTED state, and calls to
    425     // write will return EBADFD.
    426 #if 1
    427     /* Intel HDMI appears to be locked at 24bit PCM, but Android
    428      * will send data in the format specified in adev_open_output_stream().
    429      */
    430     LOG_ALWAYS_FATAL_IF(mALSAFormat != PCM_FORMAT_S24_LE,
    431             "Fugu alsa device format(%d) must be PCM_FORMAT_S24_LE", mALSAFormat);
    432 
    433     int err = BAD_VALUE;
    434     switch(format) {
    435     case AUDIO_FORMAT_IEC61937:
    436     case AUDIO_FORMAT_PCM_16_BIT: {
    437         const size_t outputSize = len * 2;
    438         if (outputSize > mStagingSize) {
    439             void *buf = realloc(mStagingBuf, outputSize);
    440             if (buf == NULL) {
    441                 ALOGE("%s: memory allocation for conversion buffer failed", __func__);
    442                 return;
    443             }
    444             mStagingBuf = buf;
    445             mStagingSize = outputSize;
    446         }
    447         memcpy_to_q8_23_from_i16((int32_t*)mStagingBuf, (const int16_t*)data, len >> 1);
    448         err = pcm_write(mDevice, mStagingBuf, outputSize);
    449     } break;
    450     case AUDIO_FORMAT_PCM_8_24_BIT:
    451         err = pcm_write(mDevice, data, len);
    452         break;
    453     default:
    454         LOG_ALWAYS_FATAL("Fugu input format(%#x) should be 16 bit or 8_24 bit pcm", format);
    455         break;
    456     }
    457 
    458 #else
    459 
    460     int err = pcm_write(mDevice, data, len);
    461 #endif
    462     if ((err < 0) && (EBADFD == errno)) {
    463         ALOGI("Failed to write to %s, output is probably disconnected."
    464               " Going into zombie state to await cleanup.", mALSAName);
    465         cleanupResources();
    466         mState = FATAL;
    467     }
    468     else if (err < 0) {
    469         ALOGW_IF(!mReportedWriteFail, "pcm_write failed err %d", err);
    470         mReportedWriteFail = true;
    471     }
    472     else {
    473         mReportedWriteFail = false;
    474 #if 1 /* not implemented in driver yet, just fake it */
    475         LocalClock lc;
    476         mLastDMAStartTime = lc.getLocalTime();
    477 #endif
    478     }
    479 }
    480 
    481 void AudioOutput::setVolume(float vol) {
    482     Mutex::Autolock _l(mVolumeLock);
    483     if (mVolume != vol) {
    484         mVolume = vol;
    485         mVolParamsDirty = true;
    486     }
    487 }
    488 
    489 void AudioOutput::setMute(bool mute) {
    490     Mutex::Autolock _l(mVolumeLock);
    491     if (mMute != mute) {
    492         mMute = mute;
    493         mVolParamsDirty = true;
    494     }
    495 }
    496 
    497 void AudioOutput::setOutputIsFixed(bool fixed) {
    498     Mutex::Autolock _l(mVolumeLock);
    499     if (mOutputFixed != fixed) {
    500         mOutputFixed = fixed;
    501         mVolParamsDirty = true;
    502     }
    503 }
    504 
    505 void AudioOutput::setFixedOutputLevel(float level) {
    506     Mutex::Autolock _l(mVolumeLock);
    507     if (mFixedLvl != level) {
    508         mFixedLvl = level;
    509         mVolParamsDirty = true;
    510     }
    511 }
    512 
    513 int  AudioOutput::getHardwareTimestamp(size_t *pAvail,
    514                             struct timespec *pTimestamp)
    515 {
    516     Mutex::Autolock _l(mDeviceLock);
    517     if (!mDevice) {
    518        ALOGW("pcm device unavailable - reinitialize  timestamp");
    519        return -1;
    520     }
    521     return pcm_get_htimestamp(mDevice, pAvail, pTimestamp);
    522 }
    523 
    524 }  // namespace android
    525