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