AudioStreamOut.cpp revision e78fa3676f07529a565b6b073d8c63d14f8c383a
1ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen/* 2ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen** 3ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen** Copyright 2012, The Android Open Source Project 4ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen** 5ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen** Licensed under the Apache License, Version 2.0 (the "License"); 6ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen** you may not use this file except in compliance with the License. 7ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen** You may obtain a copy of the License at 8ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen** 9ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen** http://www.apache.org/licenses/LICENSE-2.0 10ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen** 11ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen** Unless required by applicable law or agreed to in writing, software 12ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen** distributed under the License is distributed on an "AS IS" BASIS, 13ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen** See the License for the specific language governing permissions and 15ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen** limitations under the License. 16ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen*/ 17ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen 18ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen#define LOG_TAG "AudioHAL:AudioStreamOut" 19ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen 20ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen#include <utils/Log.h> 21ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen 22ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen#include "AudioHardwareOutput.h" 23ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen#include "AudioStreamOut.h" 24ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen 25ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen// Set to 1 to print timestamp data in CSV format. 26ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen#ifndef HAL_PRINT_TIMESTAMP_CSV 27ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen#define HAL_PRINT_TIMESTAMP_CSV 0 28ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen#endif 29ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen 30ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen//#define VERY_VERBOSE_LOGGING 31ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen#ifdef VERY_VERBOSE_LOGGING 32ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen#define ALOGVV ALOGV 33ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen#else 34ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen#define ALOGVV(a...) do { } while(0) 35ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen#endif 36ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen 37ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chennamespace android { 38ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen 39ae089528c7e3a8107be65657e52276dd068c1039Mike J. ChenAudioStreamOut::AudioStreamOut(AudioHardwareOutput& owner, bool mcOut) 40ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen : mFramesPresented(0) 41e78fa3676f07529a565b6b073d8c63d14f8c383aPhil Burk , mFramesRendered(0) 42ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen , mFramesWrittenRemainder(0) 43ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen , mOwnerHAL(owner) 44ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen , mFramesWritten(0) 45ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen , mTgtDevices(0) 46ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen , mAudioFlingerTgtDevices(0) 47ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen , mIsMCOutput(mcOut) 48ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen , mIsEncoded(false) 49ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen , mSPDIFEncoder(this) 50ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen{ 51ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen assert(mLocalClock.initCheck()); 52ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen 53ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen mPhysOutputs.setCapacity(3); 54ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen 55ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // Set some reasonable defaults for these. All of this should be eventually 56ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // be overwritten by a specific audio flinger configuration, but it does not 57ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // hurt to have something here by default. 58ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen mInputSampleRate = 48000; 59ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen mInputChanMask = AUDIO_CHANNEL_OUT_STEREO; 60ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen mInputFormat = AUDIO_FORMAT_PCM_16_BIT; 61ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen mInputNominalChunksInFlight = 4; 62ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen updateInputNums(); 63ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen 64ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen mThrottleValid = false; 65ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen 66ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen memset(&mUSecToLocalTime, 0, sizeof(mUSecToLocalTime)); 67ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen mUSecToLocalTime.a_to_b_numer = mLocalClock.getLocalFreq(); 68ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen mUSecToLocalTime.a_to_b_denom = 1000000; 69ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen LinearTransform::reduce(&mUSecToLocalTime.a_to_b_numer, 70ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen &mUSecToLocalTime.a_to_b_denom); 71ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen} 72ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen 73ae089528c7e3a8107be65657e52276dd068c1039Mike J. ChenAudioStreamOut::~AudioStreamOut() 74ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen{ 75ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen releaseAllOutputs(); 76ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen} 77ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen 78ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chenstatus_t AudioStreamOut::set( 79ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen audio_format_t *pFormat, 80ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen uint32_t *pChannels, 81ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen uint32_t *pRate) 82ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen{ 83ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen Mutex::Autolock _l(mLock); 84ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen audio_format_t lFormat = pFormat ? *pFormat : AUDIO_FORMAT_DEFAULT; 85ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen uint32_t lChannels = pChannels ? *pChannels : 0; 86ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen uint32_t lRate = pRate ? *pRate : 0; 87ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen 88ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // fix up defaults 89ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen if (lFormat == AUDIO_FORMAT_DEFAULT) lFormat = format(); 90ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen if (lChannels == 0) lChannels = chanMask(); 91ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen if (lRate == 0) lRate = sampleRate(); 92ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen 93ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen if (pFormat) *pFormat = lFormat; 94ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen if (pChannels) *pChannels = lChannels; 95ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen if (pRate) *pRate = lRate; 96ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen 97ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen mIsEncoded = !audio_is_linear_pcm(lFormat); 98ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen 99ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen if (!mIsMCOutput && !mIsEncoded) { 100ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // If this is the primary stream out, then demand our defaults. 101ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen if ((lFormat != format()) || 102ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen (lChannels != chanMask()) || 103ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen (lRate != sampleRate())) 104ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen return BAD_VALUE; 105ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen } else { 106ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // Else check to see if our HDMI sink supports this format before proceeding. 107ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen if (!mOwnerHAL.getHDMIAudioCaps().supportsFormat(lFormat, 108ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen lRate, 109ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen audio_channel_count_from_out_mask(lChannels))) 110ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen return BAD_VALUE; 111ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen } 112ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen 113ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen mInputFormat = lFormat; 114ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen mInputChanMask = lChannels; 115ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen mInputSampleRate = lRate; 116ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen ALOGI("AudioStreamOut::set: lRate = %u, mIsEncoded = %d\n", lRate, mIsEncoded); 117ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen updateInputNums(); 118ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen 119ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen return NO_ERROR; 120ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen} 121ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen 122ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chenvoid AudioStreamOut::setTgtDevices(uint32_t tgtDevices) 123ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen{ 124ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen Mutex::Autolock _l(mRoutingLock); 125ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen if (mTgtDevices != tgtDevices) { 126ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen mTgtDevices = tgtDevices; 127ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen } 128ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen} 129ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen 130ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chenstatus_t AudioStreamOut::standby() 131ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen{ 132e78fa3676f07529a565b6b073d8c63d14f8c383aPhil Burk mFramesRendered = 0; 133ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen releaseAllOutputs(); 134ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen return NO_ERROR; 135ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen} 136ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen 137ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chenvoid AudioStreamOut::releaseAllOutputs() { 138ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen Mutex::Autolock _l(mRoutingLock); 139ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen 140ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen ALOGI("releaseAllOutputs: releasing %d mPhysOutputs", mPhysOutputs.size()); 141ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen AudioOutputList::iterator I; 142ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen for (I = mPhysOutputs.begin(); I != mPhysOutputs.end(); ++I) 143ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen mOwnerHAL.releaseOutput(*this, *I); 144ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen 145ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen mPhysOutputs.clear(); 146ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen} 147ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen 148ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chenvoid AudioStreamOut::updateInputNums() 149ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen{ 150ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen assert(mLocalClock.initCheck()); 151ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen 152ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // mInputBufSize determines how many audio frames AudioFlinger is going to 153ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // mix at a time. We also use the mInputBufSize to determine the ALSA 154ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // period_size, the number of of samples which need to play out (at most) 155ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // before low level ALSA driver code is required to wake up upper levels of 156ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // SW to fill a new buffer. As it turns out, ALSA is going to apply some 157ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // rules and modify the period_size which we pass to it. One of the things 158ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // ALSA seems to do is attempt to round the period_size up to a value which 159ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // will make the period an integral number of 0.5 mSec. This round-up 160ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // behavior can cause the low levels of ALSA to consume more data per period 161ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // than the AudioFlinger mixer has been told to produce. If there are only 162ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // two buffers in flight at any given point in time, this can lead to a 163ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // situation where the pipeline ends up slipping an extra buffer and 164ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // underflowing. There are two approaches to mitigate this, both of which 165ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // are implemented in this HAL... 166ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // 167ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // 1) Try as hard as possible to make certain that the buffer size we choose 168ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // results in a period_size which is not going to get rounded up by ALSA. 169ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // This means that we want a buffer size which at the chosen sample rate 170ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // and frame size will be an integral multiple of 1/2 mSec. 171ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // 2) Increate the number of chunks we keep in flight. If the system slips 172ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // a single period, its only really a problem if there is no data left in 173ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // the pipeline waiting to be played out. The mixer should going to mix 174ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // as fast as possible until the buffer has been topped off. By 175ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // decreasing the buffer size and increasing the number of buffers in 176ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // flight, we increase the number of interrups and mix events per second, 177ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // but buy ourselves some insurance against the negative side effects of 178ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // slipping one buffer in the schedule. We end up using 4 buffers at 179ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // 10mSec, making the total audio latency somewhere between 40 and 50 180ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // mSec, depending on when a sample begins playback relative to 181ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // AudioFlinger's mixing schedule. 182ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // 183ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen mInputChanCount = audio_channel_count_from_out_mask(mInputChanMask); 184ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen 185ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // Picking a chunk duration 10mSec should satisfy #1 for both major families 186ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // of audio sample rates (the 44.1K and 48K families). In the case of 44.1 187ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // (or higher) we will end up with a multiple of 441 frames of audio per 188ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // chunk, while for 48K, we will have a multiple of 480 frames of audio per 189ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // chunk. This will not work well for lower sample rates in the 44.1 family 190ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // (22.05K and 11.025K); it is unlikely that we will ever be configured to 191ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // deliver those rates, and if we ever do, we will need to rely on having 192ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // extra chunks in flight to deal with the jitter problem described above. 193ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen mInputChunkFrames = outputSampleRate() / 100; 194ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen 195ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // FIXME: Currently, audio flinger demands an input buffer size which is a 196ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // multiple of 16 audio frames. Right now, there is no good way to 197ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // reconcile this with ALSA round-up behavior described above when the 198ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // desired sample rate is a member of the 44.1 family. For now, we just 199ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // round up to the nearest multiple of 16 frames and roll the dice, but 200ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // someday it would be good to fix one or the other halves of the problem 201ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // (either ALSA or AudioFlinger) 202ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen mInputChunkFrames = (mInputChunkFrames + 0xF) & ~0xF; 203ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen 204ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen ALOGD("AudioStreamOut::updateInputNums: chunk size %u from output rate %u\n", 205ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen mInputChunkFrames, outputSampleRate()); 206ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen 207ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // Buffer size is just the frame size multiplied by the number of 208ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // frames per chunk. 209ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen mInputBufSize = mInputChunkFrames * getBytesPerOutputFrame(); 210ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen 211ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // The nominal latency is just the duration of a chunk * the number of 212ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // chunks we nominally keep in flight at any given point in time. 213ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen mInputNominalLatencyUSec = static_cast<uint32_t>((( 214ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen static_cast<uint64_t>(mInputChunkFrames) 215ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen * 1000000 * mInputNominalChunksInFlight) 216ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen / mInputSampleRate)); 217ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen 218ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen memset(&mLocalTimeToFrames, 0, sizeof(mLocalTimeToFrames)); 219ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen mLocalTimeToFrames.a_to_b_numer = mInputSampleRate; 220ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen mLocalTimeToFrames.a_to_b_denom = mLocalClock.getLocalFreq(); 221ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen LinearTransform::reduce( 222ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen &mLocalTimeToFrames.a_to_b_numer, 223ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen &mLocalTimeToFrames.a_to_b_denom); 224ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen} 225ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen 226ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chenvoid AudioStreamOut::finishedWriteOp(size_t framesWritten, 227ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen bool needThrottle) 228ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen{ 229ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen assert(mLocalClock.initCheck()); 230ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen 231ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen int64_t now = mLocalClock.getLocalTime(); 232ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen 233ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen if (!mThrottleValid || !needThrottle) { 234ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen mThrottleValid = true; 235ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen mWriteStartLT = now; 236ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen mFramesWritten = 0; 237ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen } 238ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen 239ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen size_t framesWrittenAppRate; 240ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen uint32_t multiplier = getRateMultiplier(); 241ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen if (multiplier != 1) { 242ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // Accumulate round-off error from previous call. 243ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen framesWritten += mFramesWrittenRemainder; 244ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // Scale from device sample rate to application rate. 245ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen framesWrittenAppRate = framesWritten / multiplier; 246ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen ALOGV("finishedWriteOp() framesWrittenAppRate = %d = %d / %d\n", 247ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen framesWrittenAppRate, framesWritten, multiplier); 248ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // Save remainder for next time to prevent error accumulation. 249ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen mFramesWrittenRemainder = framesWritten - (framesWrittenAppRate * multiplier); 250ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen } else { 251ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen framesWrittenAppRate = framesWritten; 252ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen } 253ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen 254ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen mFramesWritten += framesWrittenAppRate; 255ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen mFramesPresented += framesWrittenAppRate; 256e78fa3676f07529a565b6b073d8c63d14f8c383aPhil Burk mFramesRendered += framesWrittenAppRate; 257ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen 258ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen if (needThrottle) { 259ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen int64_t deltaLT; 260ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen mLocalTimeToFrames.doReverseTransform(mFramesWritten, &deltaLT); 261ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen deltaLT += mWriteStartLT; 262ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen deltaLT -= now; 263ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen 264ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen int64_t deltaUSec; 265ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen mUSecToLocalTime.doReverseTransform(deltaLT, &deltaUSec); 266ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen 267ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen if (deltaUSec > 0) { 268ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen useconds_t sleep_time; 269ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen 270ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // We should never be a full second ahead of schedule; sanity check 271ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // our throttle time and cap the max sleep time at 1 second. 272ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen if (deltaUSec > 1000000) 273ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen sleep_time = 1000000; 274ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen else 275ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen sleep_time = static_cast<useconds_t>(deltaUSec); 276ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen 277ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen usleep(sleep_time); 278ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen } 279ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen } 280ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen} 281ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen 282ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chenstatic const String8 keyRouting(AudioParameter::keyRouting); 283ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chenstatic const String8 keySupSampleRates("sup_sampling_rates"); 284ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chenstatic const String8 keySupFormats("sup_formats"); 285ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chenstatic const String8 keySupChannels("sup_channels"); 286ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chenstatus_t AudioStreamOut::setParameters(__unused struct audio_stream *stream, const char *kvpairs) 287ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen{ 288ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen AudioParameter param = AudioParameter(String8(kvpairs)); 289ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen String8 key = String8(AudioParameter::keyRouting); 290ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen int tmpInt; 291ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen 292ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen if (param.getInt(key, tmpInt) == NO_ERROR) { 293ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // The audio HAL handles routing to physical devices entirely 294ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // internally and mostly ignores what audio flinger tells it to do. JiC 295ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // there is something (now or in the future) in audio flinger which 296ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // cares about the routing value in a call to getParameters, we hang on 297ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // to the last routing value set by audio flinger so we can at least be 298ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // consistent when we lie to the upper levels about doing what they told 299ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // us to do. 300ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen mAudioFlingerTgtDevices = static_cast<uint32_t>(tmpInt); 301ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen } 302ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen 303ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen return NO_ERROR; 304ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen} 305ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen 306ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chenchar* AudioStreamOut::getParameters(const char* k) 307ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen{ 308ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen AudioParameter param = AudioParameter(String8(k)); 309ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen String8 value; 310ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen 311ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen if (param.get(keyRouting, value) == NO_ERROR) { 312ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen param.addInt(keyRouting, (int)mAudioFlingerTgtDevices); 313ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen } 314ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen 315ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen HDMIAudioCaps& hdmiCaps = mOwnerHAL.getHDMIAudioCaps(); 316ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen 317ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen if (param.get(keySupSampleRates, value) == NO_ERROR) { 318ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen if (mIsMCOutput) { 319ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen hdmiCaps.getRatesForAF(value); 320ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen param.add(keySupSampleRates, value); 321ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen } else { 322ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen param.add(keySupSampleRates, String8("48000")); 323ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen } 324ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen } 325ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen 326ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen if (param.get(keySupFormats, value) == NO_ERROR) { 327ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen if (mIsMCOutput) { 328ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen hdmiCaps.getFmtsForAF(value); 329ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen param.add(keySupFormats, value); 330ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen } else { 331ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen param.add(keySupFormats, String8("AUDIO_FORMAT_PCM_16_BIT")); 332ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen } 333ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen } 334ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen 335ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen if (param.get(keySupChannels, value) == NO_ERROR) { 336ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen if (mIsMCOutput) { 337fb00fc03145686357e87621e3744579f3829091fEric Laurent hdmiCaps.getChannelMasksForAF(value, false); 338ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen param.add(keySupChannels, value); 339ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen } else { 340ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen param.add(keySupChannels, String8("AUDIO_CHANNEL_OUT_STEREO")); 341ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen } 342ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen } 343ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen 344ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen return strdup(param.toString().string()); 345ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen} 346ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen 347ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chenuint32_t AudioStreamOut::getRateMultiplier() const 348ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen{ 349ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen return (mIsEncoded) ? mSPDIFEncoder.getRateMultiplier() : 1; 350ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen} 351ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen 352ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chenuint32_t AudioStreamOut::outputSampleRate() const 353ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen{ 354ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen return mInputSampleRate * getRateMultiplier(); 355ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen} 356ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen 357ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chenint AudioStreamOut::getBytesPerOutputFrame() 358ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen{ 359ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen return (mIsEncoded) ? mSPDIFEncoder.getBytesPerOutputFrame() 360ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen : (mInputChanCount * sizeof(int16_t)); 361ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen} 362ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen 363ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chenuint32_t AudioStreamOut::latency() const { 364ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen uint32_t uSecLatency = mInputNominalLatencyUSec; 365ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen uint32_t vcompDelay = mOwnerHAL.getVideoDelayCompUsec(); 366ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen 367ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen if (uSecLatency < vcompDelay) 368ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen return 0; 369ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen 370ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen return ((uSecLatency - vcompDelay) / 1000); 371ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen} 372ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen 373ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen// Used to implement get_presentation_position() for Audio HAL. 374ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen// According to the prototype in audio.h, the frame count should not get 375ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen// reset on standby(). 376ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chenstatus_t AudioStreamOut::getPresentationPosition(uint64_t *frames, 377ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen struct timespec *timestamp) 378ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen{ 379ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen Mutex::Autolock _l(mRoutingLock); 380ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen status_t result = -ENODEV; 381ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // The presentation timestamp should be the same for all devices. 382ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // Also Molly only has one output device at the moment. 383ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // So just use the first one in the list. 384ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen if (!mPhysOutputs.isEmpty()) { 385ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen const unsigned int kInsaneAvail = 10 * 48000; 386ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen unsigned int avail = 0; 387ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen sp<AudioOutput> audioOutput = mPhysOutputs.itemAt(0); 388ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen if (audioOutput->getHardwareTimestamp(&avail, timestamp) == 0) { 389ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen if (avail < kInsaneAvail) { 390ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // FIXME av sync fudge factor 391ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // Use a fudge factor to account for hidden buffering in the 392ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // HDMI output path. This is a hack until we can determine the 393ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // actual buffer sizes. 394ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // Increasing kFudgeMSec will move the audio earlier in 395ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // relation to the video. 396ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen const int kFudgeMSec = 40; 397ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen int fudgeFrames = kFudgeMSec * sampleRate() / 1000; 398ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen 399ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // Scale the frames in the driver because it might be running at 400ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // a higher rate for EAC3. 401ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen int64_t framesInDriverBuffer = 402ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen (int64_t)audioOutput->getKernelBufferSize() - (int64_t)avail; 403ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen framesInDriverBuffer = framesInDriverBuffer / getRateMultiplier(); 404ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen 405ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen int64_t pendingFrames = framesInDriverBuffer + fudgeFrames; 406ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen int64_t signedFrames = mFramesPresented - pendingFrames; 407ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen if (pendingFrames < 0) { 408ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen ALOGE("getPresentationPosition: negative pendingFrames = %lld", 409ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen pendingFrames); 410ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen } else if (signedFrames < 0) { 411ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen ALOGI("getPresentationPosition: playing silent preroll" 412ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen ", mFramesPresented = %llu, pendingFrames = %lld", 413ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen mFramesPresented, pendingFrames); 414ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen } else { 415ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen#if HAL_PRINT_TIMESTAMP_CSV 416ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // Print comma separated values for spreadsheet analysis. 417ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen uint64_t nanos = (((uint64_t)timestamp->tv_sec) * 1000000000L) 418ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen + timestamp->tv_nsec; 419ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen ALOGI("getPresentationPosition, %lld, %4u, %lld, %llu", 420ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen mFramesPresented, avail, signedFrames, nanos); 421ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen#endif 422ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen *frames = (uint64_t) signedFrames; 423ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen result = NO_ERROR; 424ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen } 425ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen } else { 426ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen ALOGE("getPresentationPosition: avail too large = %u", avail); 427ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen } 428ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen } else { 429ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen ALOGE("getPresentationPosition: getHardwareTimestamp returned non-zero"); 430ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen } 431ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen } else { 432b7d477723e64b7526106641de168788e59152617Andre Eisenbach ALOGVV("getPresentationPosition: no physical outputs! This HAL is inactive!"); 433ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen } 434ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen return result; 435ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen} 436ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen 437ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chenstatus_t AudioStreamOut::getRenderPosition(__unused uint32_t *dspFrames) 438ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen{ 439e78fa3676f07529a565b6b073d8c63d14f8c383aPhil Burk if (dspFrames == NULL) { 440e78fa3676f07529a565b6b073d8c63d14f8c383aPhil Burk return -EINVAL; 441e78fa3676f07529a565b6b073d8c63d14f8c383aPhil Burk } 442e78fa3676f07529a565b6b073d8c63d14f8c383aPhil Burk if (mPhysOutputs.isEmpty()) { 443e78fa3676f07529a565b6b073d8c63d14f8c383aPhil Burk *dspFrames = 0; 444e78fa3676f07529a565b6b073d8c63d14f8c383aPhil Burk return -ENODEV; 445e78fa3676f07529a565b6b073d8c63d14f8c383aPhil Burk } 446e78fa3676f07529a565b6b073d8c63d14f8c383aPhil Burk *dspFrames = (uint32_t) mFramesRendered; 447e78fa3676f07529a565b6b073d8c63d14f8c383aPhil Burk return NO_ERROR; 448ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen} 449ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen 450ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chenvoid AudioStreamOut::updateTargetOutputs() 451ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen{ 452ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen Mutex::Autolock _l(mRoutingLock); 453ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen 454ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen AudioOutputList::iterator I; 455ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen uint32_t cur_outputs = 0; 456ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen 457ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen for (I = mPhysOutputs.begin(); I != mPhysOutputs.end(); ++I) 458ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen cur_outputs |= (*I)->devMask(); 459ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen 460ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen if (cur_outputs == mTgtDevices) 461ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen return; 462ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen 463ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen uint32_t outputsToObtain = mTgtDevices & ~cur_outputs; 464ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen uint32_t outputsToRelease = cur_outputs & ~mTgtDevices; 465ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen 466ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // Start by releasing any outputs we should no longer have back to the HAL. 467ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen if (outputsToRelease) { 468ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen 469ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen I = mPhysOutputs.begin(); 470ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen while (I != mPhysOutputs.end()) { 471ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen if (!(outputsToRelease & (*I)->devMask())) { 472ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen ++I; 473ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen continue; 474ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen } 475ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen 476ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen outputsToRelease &= ~((*I)->devMask()); 477ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen mOwnerHAL.releaseOutput(*this, *I); 478ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen I = mPhysOutputs.erase(I); 479ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen } 480ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen } 481ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen 482ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen if (outputsToRelease) { 483ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen ALOGW("Bookkeeping error! Still have outputs to release (%08x), but" 484ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen " none of them appear to be in the mPhysOutputs list!", 485ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen outputsToRelease); 486ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen } 487ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen 488ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // Now attempt to obtain any outputs we should be using, but are not 489ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // currently. 490ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen if (outputsToObtain) { 491ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen uint32_t mask; 492ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen 493ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // Buffer configuration may need updating now that we have decoded 494ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // the start of a stream. For example, EAC3, needs 4X sampleRate. 495ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen updateInputNums(); 496ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen 497ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen for (mask = 0x1; outputsToObtain; mask <<= 1) { 498ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen if (!(mask & outputsToObtain)) 499ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen continue; 500ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen 501ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen sp<AudioOutput> newOutput; 502ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen status_t res; 503ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen 504ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen res = mOwnerHAL.obtainOutput(*this, mask, &newOutput); 505ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen outputsToObtain &= ~mask; 506ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen 507ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen if (OK != res) { 508ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // If we get an error back from obtain output, it means that 509ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // something went really wrong at a lower level (probably failed 510ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // to open the driver). We should not try to obtain this output 511ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // again, at least until the next routing change. 512ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen ALOGW("Failed to obtain output %08x for %s audio stream out." 513ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen " (res %d)", mask, getName(), res); 514ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen mTgtDevices &= ~mask; 515ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen continue; 516ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen } 517ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen 518ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen if (newOutput != NULL) { 519ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // If we actually got an output, go ahead and add it to our list 520ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // of physical outputs. The rest of the system will handle 521ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // starting it up. If we didn't get an output, but also go no 522ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // error code, it just means that the output is currently busy 523ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // and should become available soon. 524ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen ALOGI("updateTargetOutputs: adding output back to mPhysOutputs"); 525ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen mPhysOutputs.push_back(newOutput); 526ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen } 527ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen } 528ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen } 529ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen} 530ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen 531ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chenvoid AudioStreamOut::adjustOutputs(int64_t maxTime) 532ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen{ 533ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen AudioOutputList::iterator I; 534ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen 535ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // Check to see if any outputs are active and see what their buffer levels 536ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // are. 537ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen for (I = mPhysOutputs.begin(); I != mPhysOutputs.end(); ++I) { 538ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen if ((*I)->getState() == AudioOutput::DMA_START) { 539ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen int64_t lastWriteTS = (*I)->getLastNextWriteTS(); 540ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen int64_t padAmt; 541ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen 542ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen mLocalTimeToFrames.a_zero = lastWriteTS; 543ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen mLocalTimeToFrames.b_zero = 0; 544ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen if (mLocalTimeToFrames.doForwardTransform(maxTime, 545ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen &padAmt)) { 546ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen (*I)->adjustDelay(((int32_t)padAmt)); 547ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen } 548ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen } 549ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen } 550ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen} 551ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen 552ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chenssize_t AudioStreamOut::write(const void* buffer, size_t bytes) 553ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen{ 554ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen uint8_t *data = (uint8_t *)buffer; 555ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen ALOGVV("AudioStreamOut::write(%u) 0x%02X, 0x%02X, 0x%02X, 0x%02X," 556ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen " 0x%02X, 0x%02X, 0x%02X, 0x%02X," 557ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen " 0x%02X, 0x%02X, 0x%02X, 0x%02X," 558ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen " 0x%02X, 0x%02X, 0x%02X, 0x%02X ====", 559ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen bytes, data[0], data[1], data[2], data[3], 560ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen data[4], data[5], data[6], data[7], 561ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen data[8], data[9], data[10], data[11], 562ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen data[12], data[13], data[14], data[15] 563ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen ); 564ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen if (mIsEncoded) { 565ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen return mSPDIFEncoder.write(buffer, bytes); 566ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen } else { 567ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen return writeInternal(buffer, bytes); 568ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen } 569ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen} 570ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen 571ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chenssize_t AudioStreamOut::writeInternal(const void* buffer, size_t bytes) 572ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen{ 573ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen uint8_t *data = (uint8_t *)buffer; 574ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen ALOGVV("AudioStreamOut::write_l(%u) 0x%02X, 0x%02X, 0x%02X, 0x%02X," 575ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen " 0x%02X, 0x%02X, 0x%02X, 0x%02X," 576ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen " 0x%02X, 0x%02X, 0x%02X, 0x%02X," 577ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen " 0x%02X, 0x%02X, 0x%02X, 0x%02X", 578ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen bytes, data[0], data[1], data[2], data[3], 579ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen data[4], data[5], data[6], data[7], 580ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen data[8], data[9], data[10], data[11], 581ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen data[12], data[13], data[14], data[15] 582ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen ); 583ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // Note: no lock is obtained here. Calls to write and getNextWriteTimestamp 584ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // happen only on the AudioFlinger mixer thread which owns this particular 585ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // output stream, so there is no need to worry that there will be two 586ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // threads in this instance method concurrently. 587ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // 588ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // In addition, only calls to write change the contents of the mPhysOutputs 589ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // collection (during the call to updateTargetOutputs). updateTargetOutputs 590ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // will hold the routing lock during the operation, as should any reader of 591ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // mPhysOutputs, unless the reader is a call to write or 592ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // getNextWriteTimestamp (we know that it is safe for write and gnwt to read 593ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // the collection because the only collection mutator is the same thread 594ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // which calls write and gnwt). 595ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen updateTargetOutputs(); 596ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen 597ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // If any of our outputs is in the PRIMED state when ::write is called, it 598ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // means one of two things. First, it could be that the DMA output really 599ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // has not started yet. This is odd, but certainly not impossible. The 600ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // other possibility is that AudioFlinger is in its silence-pushing mode and 601ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // is not calling getNextWriteTimestamp. After an output is primed, its in 602ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // GNWTS where the amt of padding to compensate for different DMA start 603ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // times is taken into account. Go ahead and force a call to GNWTS, just to 604ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // be certain that we have checked recently and are not stuck in silence 605ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // fill mode. Failure to do this will cause the AudioOutput state machine 606ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // to eventually give up on DMA starting and reset the output over and over 607ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // again (spamming the log and producing general confusion). 608ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // 609ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // While we are in the process of checking our various output states, check 610ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // to see if any outputs have made it to the ACTIVE state. Pass this 611ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // information along to the call to processOneChunk. If any of our outputs 612ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // are waiting to be primed while other outputs have made it to steady 613ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // state, we need to change our priming behavior slightly. Instead of 614ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // filling an output's buffer completely, we want to fill it to slightly 615ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // less than full and let the adjustDelay mechanism take care of the rest. 616ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // 617ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // Failure to do this during steady state operation will almost certainly 618ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // lead to the new output being over-filled relative to the other outputs 619ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // causing it to be slightly out of sync. 620ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen AudioOutputList::iterator I; 621ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen bool checkDMAStart = false; 622ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen bool hasActiveOutputs = false; 623ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen for (I = mPhysOutputs.begin(); I != mPhysOutputs.end(); ++I) { 624ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen if (AudioOutput::PRIMED == (*I)->getState()) 625ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen checkDMAStart = true; 626ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen 627ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen if ((*I)->getState() == AudioOutput::ACTIVE) 628ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen hasActiveOutputs = true; 629ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen } 630ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen 631ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen if (checkDMAStart) { 632ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen int64_t junk; 633ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen getNextWriteTimestamp_internal(&junk); 634ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen } 635ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen 636ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // We always call processOneChunk on the outputs, as it is the 637ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // tick for their state machines. 638ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen for (I = mPhysOutputs.begin(); I != mPhysOutputs.end(); ++I) { 639ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen (*I)->processOneChunk((uint8_t *)buffer, bytes, hasActiveOutputs); 640ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen } 641ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen 642ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // If we don't actually have any physical outputs to write to, just sleep 643ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // for the proper amt of time in order to simulate the throttle that writing 644ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // to the hardware would impose. 645ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen finishedWriteOp(bytes / getBytesPerOutputFrame(), (0 == mPhysOutputs.size())); 646ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen 647ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen return static_cast<ssize_t>(bytes); 648ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen} 649ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen 650ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chenstatus_t AudioStreamOut::getNextWriteTimestamp(int64_t *timestamp) 651ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen{ 652ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen return getNextWriteTimestamp_internal(timestamp); 653ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen} 654ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen 655ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chenstatus_t AudioStreamOut::getNextWriteTimestamp_internal( 656ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen int64_t *timestamp) 657ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen{ 658ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen int64_t max_time = LLONG_MIN; 659ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen bool max_time_valid = false; 660ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen bool need_adjust = false; 661ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen 662ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // Across all of our physical outputs, figure out the max time when 663ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // a write operation will hit the speakers. Assume that if an 664ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // output cannot answer the question, its because it has never 665ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // started or because it has recently underflowed and needs to be 666ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // restarted. If this is the case, we will need to prime the 667ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // pipeline with a chunk's worth of data before proceeding. 668ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // If any of the outputs indicate a discontinuity (meaning that the 669ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // DMA start time was valid and is now invalid, or was and is valid 670ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // but was different from before; almost certainly caused by a low 671ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // level underfow), then just stop now. We will need to reset and 672ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // re-prime all of the outputs in order to make certain that the 673ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // lead-times on all of the outputs match. 674ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen 675ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen AudioOutputList::iterator I; 676ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen bool discon = false; 677ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen 678ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // Find the largest next write timestamp. The goal is to make EVERY 679ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // output have the same value, but we also need this to pass back 680ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // up the layers. 681ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen for (I = mPhysOutputs.begin(); I != mPhysOutputs.end(); ++I) { 682ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen int64_t tmp; 683ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen if (OK == (*I)->getNextWriteTimestamp(&tmp, &discon)) { 684ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen if (!max_time_valid || (max_time < tmp)) { 685ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen max_time = tmp; 686ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen max_time_valid = true; 687ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen } 688ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen } 689ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen } 690ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen 691ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // Check the state of each output and determine if we need to align them. 692ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // Make sure to do this after we have called each outputs' 693ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // getNextWriteTimestamp as the transition from PRIMED to DMA_START happens 694ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // there. 695ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen for (I = mPhysOutputs.begin(); I != mPhysOutputs.end(); ++I) { 696ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen if ((*I)->getState() == AudioOutput::DMA_START) { 697ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen need_adjust = true; 698ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen break; 699ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen } 700ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen } 701ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen 702ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // At this point, if we still have not found at least one output 703ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // who knows when their data is going to hit the speakers, then we 704ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // just can't answer the getNextWriteTimestamp question and we 705ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // should give up. 706ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen if (!max_time_valid) { 707ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen return INVALID_OPERATION; 708ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen } 709ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen 710ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // Stuff silence into the non-aligned outputs so that the effective 711ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // timestamp is the same for all the outputs. 712ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen if (need_adjust) 713ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen adjustOutputs(max_time); 714ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen 715ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // We are done. The time at which the next written audio should 716ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // hit the speakers is just max_time plus the maximum amt of delay 717ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // compensation in the system. 718ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen *timestamp = max_time; 719ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen return OK; 720ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen} 721ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen 722ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen#define DUMP(a...) \ 723ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen snprintf(buffer, SIZE, a); \ 724ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen buffer[SIZE - 1] = 0; \ 725ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen result.append(buffer); 726ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen#define B2STR(b) b ? "true" : "false" 727ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen 728ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chenstatus_t AudioStreamOut::dump(int fd) 729ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen{ 730ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen const size_t SIZE = 256; 731ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen char buffer[SIZE]; 732ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen String8 result; 733ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen DUMP("\n%s AudioStreamOut::dump\n", getName()); 734ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen DUMP("\tsample rate : %d\n", sampleRate()); 735ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen DUMP("\tbuffer size : %d\n", bufferSize()); 736ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen DUMP("\tchannel mask : 0x%04x\n", chanMask()); 737ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen DUMP("\tformat : %d\n", format()); 738ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen DUMP("\tdevice mask : 0x%04x\n", mTgtDevices); 739ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen 740ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen mRoutingLock.lock(); 741ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen AudioOutputList outSnapshot(mPhysOutputs); 742ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen mRoutingLock.unlock(); 743ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen 744ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen AudioOutputList::iterator I; 745ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen for (I = outSnapshot.begin(); I != outSnapshot.end(); ++I) 746ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen (*I)->dump(result); 747ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen 748ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen ::write(fd, result.string(), result.size()); 749ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen 750ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen return NO_ERROR; 751ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen} 752ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen 753ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen#undef B2STR 754ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen#undef DUMP 755ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen 756ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen} // android 757