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 
AudioOutput(const char * alsa_name,enum pcm_format alsa_pcm_format)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 
~AudioOutput()69 AudioOutput::~AudioOutput() {
70     cleanupResources();
71     delete[] mStagingBuf;
72 }
73 
initCheck()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 
setupInternal()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 
primeOutput(bool hasActiveOutputs)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 
adjustDelay(int32_t nFrames)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 
pushSilence(uint32_t nFrames)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 
stageChunk(const uint8_t * chunkData,uint8_t * sbuf,uint32_t inBytesPerSample,uint32_t nSamples)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 
cleanupResources()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 
openPCMDevice()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 
getNextWriteTimestamp(int64_t * timestamp,bool * discon)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 
getLastNextWriteTSValid() const322 bool AudioOutput::getLastNextWriteTSValid() const {
323     return mLastNextWriteTimeValid;
324 }
325 
getLastNextWriteTS() const326 int64_t AudioOutput::getLastNextWriteTS() const {
327     return mLastNextWriteTime;
328 }
329 
getExternalDelay_uSec() const330 uint32_t AudioOutput::getExternalDelay_uSec() const {
331     return mExternalDelayUSec;
332 }
333 
setExternalDelay_uSec(uint32_t delay_usec)334 void AudioOutput::setExternalDelay_uSec(uint32_t delay_usec) {
335     mExternalDelayUSec = delay_usec;
336 }
337 
reset()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 
getDMAStartData(int64_t * dma_start_time,int64_t * frames_queued_to_driver)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 
processOneChunk(const uint8_t * data,size_t len,bool hasActiveOutputs)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 
convert_16PCM_to_24PCM(const void * input,void * output,int ipbytes)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 
doPCMWrite(const uint8_t * data,size_t len)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 
setVolume(float vol)492 void AudioOutput::setVolume(float vol) {
493     Mutex::Autolock _l(mVolumeLock);
494     if (mVolume != vol) {
495         mVolume = vol;
496         mVolParamsDirty = true;
497     }
498 }
499 
setMute(bool mute)500 void AudioOutput::setMute(bool mute) {
501     Mutex::Autolock _l(mVolumeLock);
502     if (mMute != mute) {
503         mMute = mute;
504         mVolParamsDirty = true;
505     }
506 }
507 
setOutputIsFixed(bool fixed)508 void AudioOutput::setOutputIsFixed(bool fixed) {
509     Mutex::Autolock _l(mVolumeLock);
510     if (mOutputFixed != fixed) {
511         mOutputFixed = fixed;
512         mVolParamsDirty = true;
513     }
514 }
515 
setFixedOutputLevel(float level)516 void AudioOutput::setFixedOutputLevel(float level) {
517     Mutex::Autolock _l(mVolumeLock);
518     if (mFixedLvl != level) {
519         mFixedLvl = level;
520         mVolParamsDirty = true;
521     }
522 }
523 
getHardwareTimestamp(size_t * pAvail,struct timespec * pTimestamp)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