• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
AudioOutput(const char * alsa_name,enum pcm_format alsa_pcm_format)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 
~AudioOutput()78 AudioOutput::~AudioOutput() {
79     cleanupResources();
80     free(mStagingBuf);
81     free(mSilenceBuf);
82 }
83 
initCheck()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 
setupInternal()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 
primeOutput(bool hasActiveOutputs)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 
adjustDelay(int32_t nFrames)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 
pushSilence(uint32_t nFrames)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 
cleanupResources()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 
openPCMDevice()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 
getNextWriteTimestamp(int64_t * timestamp,bool * discon)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 
getLastNextWriteTSValid() const317 bool AudioOutput::getLastNextWriteTSValid() const {
318     return mLastNextWriteTimeValid;
319 }
320 
getLastNextWriteTS() const321 int64_t AudioOutput::getLastNextWriteTS() const {
322     return mLastNextWriteTime;
323 }
324 
getExternalDelay_uSec() const325 uint32_t AudioOutput::getExternalDelay_uSec() const {
326     return mExternalDelayUSec;
327 }
328 
setExternalDelay_uSec(uint32_t delay_usec)329 void AudioOutput::setExternalDelay_uSec(uint32_t delay_usec) {
330     mExternalDelayUSec = delay_usec;
331 }
332 
reset()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 
getDMAStartData(int64_t * dma_start_time,int64_t * frames_queued_to_driver)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 
processOneChunk(const uint8_t * data,size_t len,bool hasActiveOutputs,audio_format_t format)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 
doPCMWrite(const uint8_t * data,size_t len,audio_format_t format)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 
setVolume(float vol)481 void AudioOutput::setVolume(float vol) {
482     Mutex::Autolock _l(mVolumeLock);
483     if (mVolume != vol) {
484         mVolume = vol;
485         mVolParamsDirty = true;
486     }
487 }
488 
setMute(bool mute)489 void AudioOutput::setMute(bool mute) {
490     Mutex::Autolock _l(mVolumeLock);
491     if (mMute != mute) {
492         mMute = mute;
493         mVolParamsDirty = true;
494     }
495 }
496 
setOutputIsFixed(bool fixed)497 void AudioOutput::setOutputIsFixed(bool fixed) {
498     Mutex::Autolock _l(mVolumeLock);
499     if (mOutputFixed != fixed) {
500         mOutputFixed = fixed;
501         mVolParamsDirty = true;
502     }
503 }
504 
setFixedOutputLevel(float level)505 void AudioOutput::setFixedOutputLevel(float level) {
506     Mutex::Autolock _l(mVolumeLock);
507     if (mFixedLvl != level) {
508         mFixedLvl = level;
509         mVolParamsDirty = true;
510     }
511 }
512 
getHardwareTimestamp(size_t * pAvail,struct timespec * pTimestamp)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