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 183e8b92e93b5b49633e0452fb2cd5f6e3149667cePhil Burk#define LOG_TAG "AudioHAL_AudioStreamOut" 19ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen 202b895ba03ec99ccccb05f67e297e91e31c128ce2Phil Burk#include <inttypes.h> 21ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen#include <utils/Log.h> 22ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen 23ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen#include "AudioHardwareOutput.h" 24ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen#include "AudioStreamOut.h" 25ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen 26ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen// Set to 1 to print timestamp data in CSV format. 27ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen#ifndef HAL_PRINT_TIMESTAMP_CSV 28ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen#define HAL_PRINT_TIMESTAMP_CSV 0 29ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen#endif 30ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen 31ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen//#define VERY_VERBOSE_LOGGING 32ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen#ifdef VERY_VERBOSE_LOGGING 33ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen#define ALOGVV ALOGV 34ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen#else 35ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen#define ALOGVV(a...) do { } while(0) 36ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen#endif 37ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen 38ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chennamespace android { 39ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen 40c3ed98f08d4380cc03d2e9f33cf7cf9300a6fb69Phil BurkAudioStreamOut::AudioStreamOut(AudioHardwareOutput& owner, bool mcOut, bool isIec958NonAudio) 41c73381fd51ed430361c5f3c8b6f43b425802b3c7Phil Burk : mRenderPosition(0) 422b895ba03ec99ccccb05f67e297e91e31c128ce2Phil Burk , mFramesPresented(0) 432b895ba03ec99ccccb05f67e297e91e31c128ce2Phil Burk , mLastPresentationPosition(0) 442b895ba03ec99ccccb05f67e297e91e31c128ce2Phil Burk , mLastPresentationValid(false) 45ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen , mOwnerHAL(owner) 46ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen , mFramesWritten(0) 47ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen , mTgtDevices(0) 48ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen , mAudioFlingerTgtDevices(0) 49ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen , mIsMCOutput(mcOut) 50282f06dc6d099dbb010cf9acf0bcb9bdee43fb8dRajat S Gupta , mInStandby(false) 51c3ed98f08d4380cc03d2e9f33cf7cf9300a6fb69Phil Burk , mIsIec958NonAudio(isIec958NonAudio) 52184227b9dc0cf61a6d7dcb8bc123e3e28a1bdd99Phil Burk , mReportedAvailFail(false) 53ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen{ 54ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen assert(mLocalClock.initCheck()); 55ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen 56ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen mPhysOutputs.setCapacity(3); 57ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen 583f7f6417bffb56e1111f528d2c065f01b35d2310Phil Burk // Set some reasonable defaults for these. All of this should eventually 59ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // be overwritten by a specific audio flinger configuration, but it does not 60ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // hurt to have something here by default. 61ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen mInputSampleRate = 48000; 62ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen mInputChanMask = AUDIO_CHANNEL_OUT_STEREO; 63ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen mInputFormat = AUDIO_FORMAT_PCM_16_BIT; 643f7f6417bffb56e1111f528d2c065f01b35d2310Phil Burk mInputNominalChunksInFlight = 4; // pcm_open() fails if not 4! 65ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen updateInputNums(); 66ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen 67ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen mThrottleValid = false; 68ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen 69ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen memset(&mUSecToLocalTime, 0, sizeof(mUSecToLocalTime)); 70ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen mUSecToLocalTime.a_to_b_numer = mLocalClock.getLocalFreq(); 71ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen mUSecToLocalTime.a_to_b_denom = 1000000; 72ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen LinearTransform::reduce(&mUSecToLocalTime.a_to_b_numer, 73ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen &mUSecToLocalTime.a_to_b_denom); 74ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen} 75ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen 76ae089528c7e3a8107be65657e52276dd068c1039Mike J. ChenAudioStreamOut::~AudioStreamOut() 77ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen{ 78ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen releaseAllOutputs(); 79ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen} 80ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen 81ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chenstatus_t AudioStreamOut::set( 82ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen audio_format_t *pFormat, 83ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen uint32_t *pChannels, 84ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen uint32_t *pRate) 85ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen{ 862b895ba03ec99ccccb05f67e297e91e31c128ce2Phil Burk Mutex::Autolock _l(mRoutingLock); 87ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen audio_format_t lFormat = pFormat ? *pFormat : AUDIO_FORMAT_DEFAULT; 88ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen uint32_t lChannels = pChannels ? *pChannels : 0; 89ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen uint32_t lRate = pRate ? *pRate : 0; 90ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen 91ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // fix up defaults 92ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen if (lFormat == AUDIO_FORMAT_DEFAULT) lFormat = format(); 93ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen if (lChannels == 0) lChannels = chanMask(); 94ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen if (lRate == 0) lRate = sampleRate(); 95ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen 96ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen if (pFormat) *pFormat = lFormat; 97ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen if (pChannels) *pChannels = lChannels; 98ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen if (pRate) *pRate = lRate; 99ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen 100078fc72542351e9b997ec87ab2cd4ea44bc05489Phil Burk if (!audio_has_proportional_frames(lFormat)) { 1019dc03cf9edf04867a6242e1b89868e54212af0b0Phil Burk ALOGW("set: format 0x%08X needs to be wrapped in SPDIF data burst", lFormat); 1029dc03cf9edf04867a6242e1b89868e54212af0b0Phil Burk return BAD_VALUE; 1039dc03cf9edf04867a6242e1b89868e54212af0b0Phil Burk } 104ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen 1059dc03cf9edf04867a6242e1b89868e54212af0b0Phil Burk if (!mIsMCOutput) { 106ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // If this is the primary stream out, then demand our defaults. 107d55a8c2d46cc1ddce61154862e087d39b52b993bAndy Hung if ((lFormat != AUDIO_FORMAT_PCM_16_BIT && lFormat != AUDIO_FORMAT_PCM_8_24_BIT) || 108ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen (lChannels != chanMask()) || 109d55a8c2d46cc1ddce61154862e087d39b52b993bAndy Hung (lRate != sampleRate())) { 110d55a8c2d46cc1ddce61154862e087d39b52b993bAndy Hung ALOGW("set: parameters incompatible with defaults"); 111ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen return BAD_VALUE; 112d55a8c2d46cc1ddce61154862e087d39b52b993bAndy Hung } 113ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen } else { 114ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // Else check to see if our HDMI sink supports this format before proceeding. 115d55a8c2d46cc1ddce61154862e087d39b52b993bAndy Hung if (!mOwnerHAL.getHDMIAudioCaps().supportsFormat( 1163109327f8a93439fe191643cd428ed3f0c279308Phil Burk lFormat, lRate, audio_channel_count_from_out_mask(lChannels), 1173109327f8a93439fe191643cd428ed3f0c279308Phil Burk mIsIec958NonAudio)) { 118d55a8c2d46cc1ddce61154862e087d39b52b993bAndy Hung ALOGW("set: parameters incompatible with hdmi capabilities"); 119ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen return BAD_VALUE; 120d55a8c2d46cc1ddce61154862e087d39b52b993bAndy Hung } 121ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen } 122ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen 123ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen mInputFormat = lFormat; 124ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen mInputChanMask = lChannels; 125ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen mInputSampleRate = lRate; 1269dc03cf9edf04867a6242e1b89868e54212af0b0Phil Burk ALOGI("AudioStreamOut::set: rate = %u, format = 0x%08X\n", lRate, lFormat); 127ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen updateInputNums(); 128ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen 129ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen return NO_ERROR; 130ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen} 131ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen 132ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chenvoid AudioStreamOut::setTgtDevices(uint32_t tgtDevices) 133ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen{ 134ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen Mutex::Autolock _l(mRoutingLock); 135ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen if (mTgtDevices != tgtDevices) { 136ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen mTgtDevices = tgtDevices; 137ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen } 138ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen} 139ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen 1403e8b92e93b5b49633e0452fb2cd5f6e3149667cePhil Burkstatus_t AudioStreamOut::standbyHardware() 141ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen{ 142ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen releaseAllOutputs(); 143282f06dc6d099dbb010cf9acf0bcb9bdee43fb8dRajat S Gupta mOwnerHAL.standbyStatusUpdate(true, mIsMCOutput); 144282f06dc6d099dbb010cf9acf0bcb9bdee43fb8dRajat S Gupta mInStandby = true; 145ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen return NO_ERROR; 146ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen} 147ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen 1483e8b92e93b5b49633e0452fb2cd5f6e3149667cePhil Burkstatus_t AudioStreamOut::standby() 1493e8b92e93b5b49633e0452fb2cd5f6e3149667cePhil Burk{ 15001b3691f20a8e5c6112f7174f3d119d8425b896bPhil Burk ALOGI("standby: =========================="); 151c73381fd51ed430361c5f3c8b6f43b425802b3c7Phil Burk mRenderPosition = 0; 1522b895ba03ec99ccccb05f67e297e91e31c128ce2Phil Burk mLastPresentationValid = false; 153c73381fd51ed430361c5f3c8b6f43b425802b3c7Phil Burk // Don't reset the presentation position. 1543e8b92e93b5b49633e0452fb2cd5f6e3149667cePhil Burk return standbyHardware(); 1553e8b92e93b5b49633e0452fb2cd5f6e3149667cePhil Burk} 1563e8b92e93b5b49633e0452fb2cd5f6e3149667cePhil Burk 157ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chenvoid AudioStreamOut::releaseAllOutputs() { 158ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen Mutex::Autolock _l(mRoutingLock); 159ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen ALOGI("releaseAllOutputs: releasing %d mPhysOutputs", mPhysOutputs.size()); 160ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen AudioOutputList::iterator I; 161ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen for (I = mPhysOutputs.begin(); I != mPhysOutputs.end(); ++I) 162ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen mOwnerHAL.releaseOutput(*this, *I); 163ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen 164ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen mPhysOutputs.clear(); 165ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen} 166ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen 1673e8b92e93b5b49633e0452fb2cd5f6e3149667cePhil Burkstatus_t AudioStreamOut::pause() 1683e8b92e93b5b49633e0452fb2cd5f6e3149667cePhil Burk{ 16901b3691f20a8e5c6112f7174f3d119d8425b896bPhil Burk ALOGI("pause: =========================="); 1702b895ba03ec99ccccb05f67e297e91e31c128ce2Phil Burk mLastPresentationValid = false; 1713e8b92e93b5b49633e0452fb2cd5f6e3149667cePhil Burk return standbyHardware(); 1723e8b92e93b5b49633e0452fb2cd5f6e3149667cePhil Burk} 1733e8b92e93b5b49633e0452fb2cd5f6e3149667cePhil Burk 1743e8b92e93b5b49633e0452fb2cd5f6e3149667cePhil Burkstatus_t AudioStreamOut::resume() 1753e8b92e93b5b49633e0452fb2cd5f6e3149667cePhil Burk{ 17601b3691f20a8e5c6112f7174f3d119d8425b896bPhil Burk ALOGI("resume: =========================="); 1773e8b92e93b5b49633e0452fb2cd5f6e3149667cePhil Burk return NO_ERROR; 1783e8b92e93b5b49633e0452fb2cd5f6e3149667cePhil Burk} 1793e8b92e93b5b49633e0452fb2cd5f6e3149667cePhil Burk 1803e8b92e93b5b49633e0452fb2cd5f6e3149667cePhil Burkstatus_t AudioStreamOut::flush() 1813e8b92e93b5b49633e0452fb2cd5f6e3149667cePhil Burk{ 18201b3691f20a8e5c6112f7174f3d119d8425b896bPhil Burk ALOGI("flush: =========================="); 183c73381fd51ed430361c5f3c8b6f43b425802b3c7Phil Burk mRenderPosition = 0; 1842b895ba03ec99ccccb05f67e297e91e31c128ce2Phil Burk mFramesPresented = 0; 1852b895ba03ec99ccccb05f67e297e91e31c128ce2Phil Burk Mutex::Autolock _l(mPresentationLock); 1862b895ba03ec99ccccb05f67e297e91e31c128ce2Phil Burk mLastPresentationPosition = 0; 1872b895ba03ec99ccccb05f67e297e91e31c128ce2Phil Burk mLastPresentationValid = false; 1883e8b92e93b5b49633e0452fb2cd5f6e3149667cePhil Burk return NO_ERROR; 1893e8b92e93b5b49633e0452fb2cd5f6e3149667cePhil Burk} 1903e8b92e93b5b49633e0452fb2cd5f6e3149667cePhil Burk 191ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chenvoid AudioStreamOut::updateInputNums() 192ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen{ 193ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen assert(mLocalClock.initCheck()); 194ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen 195ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen mInputChanCount = audio_channel_count_from_out_mask(mInputChanMask); 196ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen 1972b895ba03ec99ccccb05f67e297e91e31c128ce2Phil Burk // 512 is good for AC3 and DTS passthrough. 1983f7f6417bffb56e1111f528d2c065f01b35d2310Phil Burk mInputChunkFrames = 512 * ((outputSampleRate() + 48000 - 1) / 48000); 1993f7f6417bffb56e1111f528d2c065f01b35d2310Phil Burk 2002b895ba03ec99ccccb05f67e297e91e31c128ce2Phil Burk ALOGV("updateInputNums: chunk size %u from output rate %u\n", 201ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen mInputChunkFrames, outputSampleRate()); 202ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen 203c54f78610f4db840c24119b89533f1fd6d30d217Andy Hung mInputFrameSize = mInputChanCount * audio_bytes_per_sample(mInputFormat); 204c54f78610f4db840c24119b89533f1fd6d30d217Andy Hung 205ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // Buffer size is just the frame size multiplied by the number of 206ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // frames per chunk. 207c54f78610f4db840c24119b89533f1fd6d30d217Andy Hung mInputBufSize = mInputChunkFrames * mInputFrameSize; 208ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen 209ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // The nominal latency is just the duration of a chunk * the number of 210ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // chunks we nominally keep in flight at any given point in time. 211ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen mInputNominalLatencyUSec = static_cast<uint32_t>((( 212ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen static_cast<uint64_t>(mInputChunkFrames) 213ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen * 1000000 * mInputNominalChunksInFlight) 214ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen / mInputSampleRate)); 215ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen 216ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen memset(&mLocalTimeToFrames, 0, sizeof(mLocalTimeToFrames)); 217ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen mLocalTimeToFrames.a_to_b_numer = mInputSampleRate; 218ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen mLocalTimeToFrames.a_to_b_denom = mLocalClock.getLocalFreq(); 219ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen LinearTransform::reduce( 220ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen &mLocalTimeToFrames.a_to_b_numer, 221ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen &mLocalTimeToFrames.a_to_b_denom); 222ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen} 223ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen 224ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chenvoid AudioStreamOut::finishedWriteOp(size_t framesWritten, 225ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen bool needThrottle) 226ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen{ 227ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen assert(mLocalClock.initCheck()); 228ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen 229ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen int64_t now = mLocalClock.getLocalTime(); 230ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen 231ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen if (!mThrottleValid || !needThrottle) { 232ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen mThrottleValid = true; 233ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen mWriteStartLT = now; 234ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen mFramesWritten = 0; 235ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen } 236ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen 2379dc03cf9edf04867a6242e1b89868e54212af0b0Phil Burk mFramesWritten += framesWritten; 2382b895ba03ec99ccccb05f67e297e91e31c128ce2Phil Burk mFramesPresented += framesWritten; 239c73381fd51ed430361c5f3c8b6f43b425802b3c7Phil Burk mRenderPosition += framesWritten; 240ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen 241ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen if (needThrottle) { 242ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen int64_t deltaLT; 243ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen mLocalTimeToFrames.doReverseTransform(mFramesWritten, &deltaLT); 244ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen deltaLT += mWriteStartLT; 245ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen deltaLT -= now; 246ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen 247ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen int64_t deltaUSec; 248ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen mUSecToLocalTime.doReverseTransform(deltaLT, &deltaUSec); 249ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen 250ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen if (deltaUSec > 0) { 251ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen useconds_t sleep_time; 252ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen 253ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // We should never be a full second ahead of schedule; sanity check 254ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // our throttle time and cap the max sleep time at 1 second. 255821688ed8ee498455d39b6b7d5d853c16f74ae98Phil Burk if (deltaUSec > 1000000) { 2562b895ba03ec99ccccb05f67e297e91e31c128ce2Phil Burk ALOGW("throttle time clipped! deltaLT = %" PRIi64 " deltaUSec = %" PRIi64, 257821688ed8ee498455d39b6b7d5d853c16f74ae98Phil Burk deltaLT, deltaUSec); 258ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen sleep_time = 1000000; 259821688ed8ee498455d39b6b7d5d853c16f74ae98Phil Burk } else { 260ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen sleep_time = static_cast<useconds_t>(deltaUSec); 261821688ed8ee498455d39b6b7d5d853c16f74ae98Phil Burk } 262ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen usleep(sleep_time); 263ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen } 264ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen } 265ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen} 266ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen 267ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chenstatic const String8 keyRouting(AudioParameter::keyRouting); 268ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chenstatic const String8 keySupSampleRates("sup_sampling_rates"); 269ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chenstatic const String8 keySupFormats("sup_formats"); 270ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chenstatic const String8 keySupChannels("sup_channels"); 271ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chenstatus_t AudioStreamOut::setParameters(__unused struct audio_stream *stream, const char *kvpairs) 272ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen{ 273ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen AudioParameter param = AudioParameter(String8(kvpairs)); 274ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen String8 key = String8(AudioParameter::keyRouting); 275ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen int tmpInt; 276ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen 277ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen if (param.getInt(key, tmpInt) == NO_ERROR) { 278ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // The audio HAL handles routing to physical devices entirely 279ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // internally and mostly ignores what audio flinger tells it to do. JiC 280ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // there is something (now or in the future) in audio flinger which 281ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // cares about the routing value in a call to getParameters, we hang on 282ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // to the last routing value set by audio flinger so we can at least be 283ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // consistent when we lie to the upper levels about doing what they told 284ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // us to do. 285ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen mAudioFlingerTgtDevices = static_cast<uint32_t>(tmpInt); 286ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen } 287ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen 288ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen return NO_ERROR; 289ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen} 290ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen 291ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chenchar* AudioStreamOut::getParameters(const char* k) 292ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen{ 293ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen AudioParameter param = AudioParameter(String8(k)); 294ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen String8 value; 295ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen 296ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen if (param.get(keyRouting, value) == NO_ERROR) { 297ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen param.addInt(keyRouting, (int)mAudioFlingerTgtDevices); 298ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen } 299ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen 300ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen HDMIAudioCaps& hdmiCaps = mOwnerHAL.getHDMIAudioCaps(); 301ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen 302ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen if (param.get(keySupSampleRates, value) == NO_ERROR) { 303ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen if (mIsMCOutput) { 304ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen hdmiCaps.getRatesForAF(value); 305ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen param.add(keySupSampleRates, value); 306ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen } else { 307ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen param.add(keySupSampleRates, String8("48000")); 308ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen } 309ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen } 310ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen 311ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen if (param.get(keySupFormats, value) == NO_ERROR) { 312ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen if (mIsMCOutput) { 313ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen hdmiCaps.getFmtsForAF(value); 314ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen param.add(keySupFormats, value); 315ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen } else { 316d55a8c2d46cc1ddce61154862e087d39b52b993bAndy Hung param.add(keySupFormats, String8("AUDIO_FORMAT_PCM_16_BIT|AUDIO_FORMAT_PCM_8_24_BIT")); 317ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen } 318ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen } 319ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen 320ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen if (param.get(keySupChannels, value) == NO_ERROR) { 321ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen if (mIsMCOutput) { 3223ea12695eb0674e1f62c2afa585a047d4c81676bEric Laurent hdmiCaps.getChannelMasksForAF(value); 323ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen param.add(keySupChannels, value); 324ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen } else { 325ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen param.add(keySupChannels, String8("AUDIO_CHANNEL_OUT_STEREO")); 326ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen } 327ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen } 328ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen 329ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen return strdup(param.toString().string()); 330ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen} 331ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen 332ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chenuint32_t AudioStreamOut::outputSampleRate() const 333ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen{ 3349dc03cf9edf04867a6242e1b89868e54212af0b0Phil Burk return mInputSampleRate; 335ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen} 336ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen 337ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chenuint32_t AudioStreamOut::latency() const { 338ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen uint32_t uSecLatency = mInputNominalLatencyUSec; 339ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen uint32_t vcompDelay = mOwnerHAL.getVideoDelayCompUsec(); 340ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen 341ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen if (uSecLatency < vcompDelay) 342ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen return 0; 343ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen 344ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen return ((uSecLatency - vcompDelay) / 1000); 345ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen} 346ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen 347ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen// Used to implement get_presentation_position() for Audio HAL. 348ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen// According to the prototype in audio.h, the frame count should not get 349ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen// reset on standby(). 350ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chenstatus_t AudioStreamOut::getPresentationPosition(uint64_t *frames, 351ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen struct timespec *timestamp) 352ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen{ 3532b895ba03ec99ccccb05f67e297e91e31c128ce2Phil Burk status_t result = -ENODEV; 3542b895ba03ec99ccccb05f67e297e91e31c128ce2Phil Burk // If we cannot get a lock then try to return a cached position and timestamp. 3552b895ba03ec99ccccb05f67e297e91e31c128ce2Phil Burk // It is better to return an old timestamp then to wait for a fresh one. 3562b895ba03ec99ccccb05f67e297e91e31c128ce2Phil Burk if (mRoutingLock.tryLock() != OK) { 3572b895ba03ec99ccccb05f67e297e91e31c128ce2Phil Burk // We failed to get the lock. It is probably held by a blocked write(). 3582b895ba03ec99ccccb05f67e297e91e31c128ce2Phil Burk if (mLastPresentationValid) { 3592b895ba03ec99ccccb05f67e297e91e31c128ce2Phil Burk // Use cached position. 3602b895ba03ec99ccccb05f67e297e91e31c128ce2Phil Burk // Use mutex because this cluster of variables may be getting 3612b895ba03ec99ccccb05f67e297e91e31c128ce2Phil Burk // updated by the write thread. 3622b895ba03ec99ccccb05f67e297e91e31c128ce2Phil Burk Mutex::Autolock _l(mPresentationLock); 3632b895ba03ec99ccccb05f67e297e91e31c128ce2Phil Burk *frames = mLastPresentationPosition; 3642b895ba03ec99ccccb05f67e297e91e31c128ce2Phil Burk *timestamp = mLastPresentationTime; 3652b895ba03ec99ccccb05f67e297e91e31c128ce2Phil Burk result = NO_ERROR; 3662b895ba03ec99ccccb05f67e297e91e31c128ce2Phil Burk } 3672b895ba03ec99ccccb05f67e297e91e31c128ce2Phil Burk return result; 3682b895ba03ec99ccccb05f67e297e91e31c128ce2Phil Burk } 3692b895ba03ec99ccccb05f67e297e91e31c128ce2Phil Burk 3702b895ba03ec99ccccb05f67e297e91e31c128ce2Phil Burk // Lock succeeded so it is safe to call this. 3712b895ba03ec99ccccb05f67e297e91e31c128ce2Phil Burk result = getPresentationPosition_l(frames, timestamp); 3722b895ba03ec99ccccb05f67e297e91e31c128ce2Phil Burk 3732b895ba03ec99ccccb05f67e297e91e31c128ce2Phil Burk mRoutingLock.unlock(); 3742b895ba03ec99ccccb05f67e297e91e31c128ce2Phil Burk return result; 3752b895ba03ec99ccccb05f67e297e91e31c128ce2Phil Burk} 3762b895ba03ec99ccccb05f67e297e91e31c128ce2Phil Burk 3772b895ba03ec99ccccb05f67e297e91e31c128ce2Phil Burk// Used to implement get_presentation_position() for Audio HAL. 3782b895ba03ec99ccccb05f67e297e91e31c128ce2Phil Burk// According to the prototype in audio.h, the frame count should not get 3792b895ba03ec99ccccb05f67e297e91e31c128ce2Phil Burk// reset on standby(). 3802b895ba03ec99ccccb05f67e297e91e31c128ce2Phil Burk// mRoutingLock should be locked before calling this method. 3812b895ba03ec99ccccb05f67e297e91e31c128ce2Phil Burkstatus_t AudioStreamOut::getPresentationPosition_l(uint64_t *frames, 3822b895ba03ec99ccccb05f67e297e91e31c128ce2Phil Burk struct timespec *timestamp) 3832b895ba03ec99ccccb05f67e297e91e31c128ce2Phil Burk{ 384ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen status_t result = -ENODEV; 385ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // The presentation timestamp should be the same for all devices. 386ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // Also Molly only has one output device at the moment. 387ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // So just use the first one in the list. 388ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen if (!mPhysOutputs.isEmpty()) { 389ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen unsigned int avail = 0; 390ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen sp<AudioOutput> audioOutput = mPhysOutputs.itemAt(0); 391f82ef78124519a9173937dcaa6b0961bb1e1044ePhil Burk if (audioOutput->getHardwareTimestamp(&avail, timestamp) == OK) { 392f82ef78124519a9173937dcaa6b0961bb1e1044ePhil Burk 393f82ef78124519a9173937dcaa6b0961bb1e1044ePhil Burk int64_t framesInDriverBuffer = (int64_t)audioOutput->getKernelBufferSize() - (int64_t)avail; 394f82ef78124519a9173937dcaa6b0961bb1e1044ePhil Burk if (framesInDriverBuffer >= 0) { 395f82ef78124519a9173937dcaa6b0961bb1e1044ePhil Burk // FIXME av sync fudge factor 396f82ef78124519a9173937dcaa6b0961bb1e1044ePhil Burk // Use a fudge factor to account for hidden buffering in the 397f82ef78124519a9173937dcaa6b0961bb1e1044ePhil Burk // HDMI output path. This is a hack until we can determine the 398f82ef78124519a9173937dcaa6b0961bb1e1044ePhil Burk // actual buffer sizes. 399f82ef78124519a9173937dcaa6b0961bb1e1044ePhil Burk // Increasing kFudgeMSec will move the audio earlier in 400f82ef78124519a9173937dcaa6b0961bb1e1044ePhil Burk // relation to the video. 401f82ef78124519a9173937dcaa6b0961bb1e1044ePhil Burk const int kFudgeMSec = 50; 402f82ef78124519a9173937dcaa6b0961bb1e1044ePhil Burk int fudgeFrames = kFudgeMSec * sampleRate() / 1000; 403f82ef78124519a9173937dcaa6b0961bb1e1044ePhil Burk int64_t pendingFrames = framesInDriverBuffer + fudgeFrames; 404f82ef78124519a9173937dcaa6b0961bb1e1044ePhil Burk 405f82ef78124519a9173937dcaa6b0961bb1e1044ePhil Burk int64_t signedFrames = mFramesPresented - pendingFrames; 406f82ef78124519a9173937dcaa6b0961bb1e1044ePhil Burk if (signedFrames < 0) { 407f82ef78124519a9173937dcaa6b0961bb1e1044ePhil Burk ALOGV("getPresentationPosition: playing silent preroll" 408f82ef78124519a9173937dcaa6b0961bb1e1044ePhil Burk ", mFramesPresented = %" PRIu64 ", pendingFrames = %" PRIi64, 409f82ef78124519a9173937dcaa6b0961bb1e1044ePhil Burk mFramesPresented, pendingFrames); 410f82ef78124519a9173937dcaa6b0961bb1e1044ePhil Burk } else { 411f82ef78124519a9173937dcaa6b0961bb1e1044ePhil Burk #if HAL_PRINT_TIMESTAMP_CSV 412f82ef78124519a9173937dcaa6b0961bb1e1044ePhil Burk // Print comma separated values for spreadsheet analysis. 413f82ef78124519a9173937dcaa6b0961bb1e1044ePhil Burk uint64_t nanos = (((uint64_t)timestamp->tv_sec) * 1000000000L) 414f82ef78124519a9173937dcaa6b0961bb1e1044ePhil Burk + timestamp->tv_nsec; 415f82ef78124519a9173937dcaa6b0961bb1e1044ePhil Burk ALOGI("getPresentationPosition, %" PRIu64 ", %4u, %" PRIi64 ", %" PRIu64, 416f82ef78124519a9173937dcaa6b0961bb1e1044ePhil Burk mFramesPresented, avail, signedFrames, nanos); 417f82ef78124519a9173937dcaa6b0961bb1e1044ePhil Burk #endif 418f82ef78124519a9173937dcaa6b0961bb1e1044ePhil Burk uint64_t unsignedFrames = (uint64_t) signedFrames; 419f82ef78124519a9173937dcaa6b0961bb1e1044ePhil Burk 420f82ef78124519a9173937dcaa6b0961bb1e1044ePhil Burk { 421f82ef78124519a9173937dcaa6b0961bb1e1044ePhil Burk Mutex::Autolock _l(mPresentationLock); 422f82ef78124519a9173937dcaa6b0961bb1e1044ePhil Burk // Check for retrograde timestamps. 423f82ef78124519a9173937dcaa6b0961bb1e1044ePhil Burk if (unsignedFrames < mLastPresentationPosition) { 424f82ef78124519a9173937dcaa6b0961bb1e1044ePhil Burk ALOGW("getPresentationPosition: RETROGRADE timestamp, diff = %" PRId64, 425f82ef78124519a9173937dcaa6b0961bb1e1044ePhil Burk (int64_t)(unsignedFrames - mLastPresentationPosition)); 426f82ef78124519a9173937dcaa6b0961bb1e1044ePhil Burk if (mLastPresentationValid) { 427f82ef78124519a9173937dcaa6b0961bb1e1044ePhil Burk // Use previous presentation position and time. 428f82ef78124519a9173937dcaa6b0961bb1e1044ePhil Burk *timestamp = mLastPresentationTime; 429f82ef78124519a9173937dcaa6b0961bb1e1044ePhil Burk *frames = mLastPresentationPosition; 430f82ef78124519a9173937dcaa6b0961bb1e1044ePhil Burk result = NO_ERROR; 431f82ef78124519a9173937dcaa6b0961bb1e1044ePhil Burk } 432f82ef78124519a9173937dcaa6b0961bb1e1044ePhil Burk // else return error 433f82ef78124519a9173937dcaa6b0961bb1e1044ePhil Burk } else { 434f82ef78124519a9173937dcaa6b0961bb1e1044ePhil Burk *frames = unsignedFrames; 435f82ef78124519a9173937dcaa6b0961bb1e1044ePhil Burk // Save cached data that we can use when the HAL is locked. 436f82ef78124519a9173937dcaa6b0961bb1e1044ePhil Burk mLastPresentationPosition = unsignedFrames; 437f82ef78124519a9173937dcaa6b0961bb1e1044ePhil Burk mLastPresentationTime = *timestamp; 4382b895ba03ec99ccccb05f67e297e91e31c128ce2Phil Burk result = NO_ERROR; 4392b895ba03ec99ccccb05f67e297e91e31c128ce2Phil Burk } 4403f7f6417bffb56e1111f528d2c065f01b35d2310Phil Burk } 441ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen } 442f82ef78124519a9173937dcaa6b0961bb1e1044ePhil Burk } else { 443f82ef78124519a9173937dcaa6b0961bb1e1044ePhil Burk ALOGE("getPresentationPosition: avail too large = %u", avail); 444ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen } 445f82ef78124519a9173937dcaa6b0961bb1e1044ePhil Burk mReportedAvailFail = false; 446ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen } else { 447184227b9dc0cf61a6d7dcb8bc123e3e28a1bdd99Phil Burk ALOGW_IF(!mReportedAvailFail, 448184227b9dc0cf61a6d7dcb8bc123e3e28a1bdd99Phil Burk "getPresentationPosition: getHardwareTimestamp returned non-zero"); 449184227b9dc0cf61a6d7dcb8bc123e3e28a1bdd99Phil Burk mReportedAvailFail = true; 450ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen } 451ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen } else { 452b7d477723e64b7526106641de168788e59152617Andre Eisenbach ALOGVV("getPresentationPosition: no physical outputs! This HAL is inactive!"); 453ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen } 4542b895ba03ec99ccccb05f67e297e91e31c128ce2Phil Burk mLastPresentationValid = result == NO_ERROR; 455ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen return result; 456ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen} 457ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen 458ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chenstatus_t AudioStreamOut::getRenderPosition(__unused uint32_t *dspFrames) 459ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen{ 460e78fa3676f07529a565b6b073d8c63d14f8c383aPhil Burk if (dspFrames == NULL) { 461e78fa3676f07529a565b6b073d8c63d14f8c383aPhil Burk return -EINVAL; 462e78fa3676f07529a565b6b073d8c63d14f8c383aPhil Burk } 463c73381fd51ed430361c5f3c8b6f43b425802b3c7Phil Burk *dspFrames = (uint32_t) mRenderPosition; 464e78fa3676f07529a565b6b073d8c63d14f8c383aPhil Burk return NO_ERROR; 465ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen} 466ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen 467ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chenvoid AudioStreamOut::updateTargetOutputs() 468ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen{ 469ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen Mutex::Autolock _l(mRoutingLock); 470ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen AudioOutputList::iterator I; 471ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen uint32_t cur_outputs = 0; 472ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen 473ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen for (I = mPhysOutputs.begin(); I != mPhysOutputs.end(); ++I) 474ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen cur_outputs |= (*I)->devMask(); 475ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen 476ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen if (cur_outputs == mTgtDevices) 477ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen return; 478ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen 479ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen uint32_t outputsToObtain = mTgtDevices & ~cur_outputs; 480ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen uint32_t outputsToRelease = cur_outputs & ~mTgtDevices; 481ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen 482ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // Start by releasing any outputs we should no longer have back to the HAL. 483ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen if (outputsToRelease) { 484ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen 485ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen I = mPhysOutputs.begin(); 486ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen while (I != mPhysOutputs.end()) { 487ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen if (!(outputsToRelease & (*I)->devMask())) { 488ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen ++I; 489ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen continue; 490ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen } 491ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen 492ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen outputsToRelease &= ~((*I)->devMask()); 493ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen mOwnerHAL.releaseOutput(*this, *I); 494ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen I = mPhysOutputs.erase(I); 495ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen } 496ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen } 497ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen 498ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen if (outputsToRelease) { 499ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen ALOGW("Bookkeeping error! Still have outputs to release (%08x), but" 500ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen " none of them appear to be in the mPhysOutputs list!", 501ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen outputsToRelease); 502ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen } 503ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen 504ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // Now attempt to obtain any outputs we should be using, but are not 505ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // currently. 506ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen if (outputsToObtain) { 507ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen uint32_t mask; 508ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen 509ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // Buffer configuration may need updating now that we have decoded 510ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // the start of a stream. For example, EAC3, needs 4X sampleRate. 511ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen updateInputNums(); 512ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen 513ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen for (mask = 0x1; outputsToObtain; mask <<= 1) { 514ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen if (!(mask & outputsToObtain)) 515ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen continue; 516ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen 517ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen sp<AudioOutput> newOutput; 518ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen status_t res; 519ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen 520ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen res = mOwnerHAL.obtainOutput(*this, mask, &newOutput); 521ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen outputsToObtain &= ~mask; 522ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen 523ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen if (OK != res) { 524ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // If we get an error back from obtain output, it means that 525ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // something went really wrong at a lower level (probably failed 526ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // to open the driver). We should not try to obtain this output 527ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // again, at least until the next routing change. 528ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen ALOGW("Failed to obtain output %08x for %s audio stream out." 529ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen " (res %d)", mask, getName(), res); 530ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen mTgtDevices &= ~mask; 531ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen continue; 532ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen } 533ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen 534ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen if (newOutput != NULL) { 535ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // If we actually got an output, go ahead and add it to our list 536ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // of physical outputs. The rest of the system will handle 5373f7f6417bffb56e1111f528d2c065f01b35d2310Phil Burk // starting it up. If we didn't get an output, but also got no 538ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // error code, it just means that the output is currently busy 539ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // and should become available soon. 540ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen ALOGI("updateTargetOutputs: adding output back to mPhysOutputs"); 541ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen mPhysOutputs.push_back(newOutput); 542ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen } 543ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen } 544ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen } 545ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen} 546ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen 547ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chenvoid AudioStreamOut::adjustOutputs(int64_t maxTime) 548ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen{ 549821688ed8ee498455d39b6b7d5d853c16f74ae98Phil Burk int64_t a_zero_original = mLocalTimeToFrames.a_zero; 550821688ed8ee498455d39b6b7d5d853c16f74ae98Phil Burk int64_t b_zero_original = mLocalTimeToFrames.b_zero; 551ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen AudioOutputList::iterator I; 552ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen 553ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // Check to see if any outputs are active and see what their buffer levels 554ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // are. 555ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen for (I = mPhysOutputs.begin(); I != mPhysOutputs.end(); ++I) { 556ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen if ((*I)->getState() == AudioOutput::DMA_START) { 557ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen int64_t lastWriteTS = (*I)->getLastNextWriteTS(); 558ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen int64_t padAmt; 559ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen 560ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen mLocalTimeToFrames.a_zero = lastWriteTS; 561ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen mLocalTimeToFrames.b_zero = 0; 562ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen if (mLocalTimeToFrames.doForwardTransform(maxTime, 563ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen &padAmt)) { 564ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen (*I)->adjustDelay(((int32_t)padAmt)); 565ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen } 566ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen } 567ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen } 568821688ed8ee498455d39b6b7d5d853c16f74ae98Phil Burk // Restore original offset so that the sleep time calculation for 569821688ed8ee498455d39b6b7d5d853c16f74ae98Phil Burk // throttling is not broken in finishedWriteOp(). 570821688ed8ee498455d39b6b7d5d853c16f74ae98Phil Burk mLocalTimeToFrames.a_zero = a_zero_original; 571821688ed8ee498455d39b6b7d5d853c16f74ae98Phil Burk mLocalTimeToFrames.b_zero = b_zero_original; 572ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen} 573ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen 574ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chenssize_t AudioStreamOut::write(const void* buffer, size_t bytes) 575ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen{ 576ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen uint8_t *data = (uint8_t *)buffer; 577ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen ALOGVV("AudioStreamOut::write_l(%u) 0x%02X, 0x%02X, 0x%02X, 0x%02X," 578ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen " 0x%02X, 0x%02X, 0x%02X, 0x%02X," 579ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen " 0x%02X, 0x%02X, 0x%02X, 0x%02X," 580ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen " 0x%02X, 0x%02X, 0x%02X, 0x%02X", 581ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen bytes, data[0], data[1], data[2], data[3], 582ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen data[4], data[5], data[6], data[7], 583ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen data[8], data[9], data[10], data[11], 584ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen data[12], data[13], data[14], data[15] 585ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen ); 586282f06dc6d099dbb010cf9acf0bcb9bdee43fb8dRajat S Gupta 587ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // 5882b895ba03ec99ccccb05f67e297e91e31c128ce2Phil Burk // Note that 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). 595282f06dc6d099dbb010cf9acf0bcb9bdee43fb8dRajat S Gupta 596282f06dc6d099dbb010cf9acf0bcb9bdee43fb8dRajat S Gupta // If the stream is in standby, then the first write should bring it out 597282f06dc6d099dbb010cf9acf0bcb9bdee43fb8dRajat S Gupta // of standby 598282f06dc6d099dbb010cf9acf0bcb9bdee43fb8dRajat S Gupta if (mInStandby) { 599282f06dc6d099dbb010cf9acf0bcb9bdee43fb8dRajat S Gupta mOwnerHAL.standbyStatusUpdate(false, mIsMCOutput); 600282f06dc6d099dbb010cf9acf0bcb9bdee43fb8dRajat S Gupta mInStandby = false; 601282f06dc6d099dbb010cf9acf0bcb9bdee43fb8dRajat S Gupta } 602282f06dc6d099dbb010cf9acf0bcb9bdee43fb8dRajat S Gupta 6032b895ba03ec99ccccb05f67e297e91e31c128ce2Phil Burk updateTargetOutputs(); // locks mRoutingLock 604ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen 605ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // If any of our outputs is in the PRIMED state when ::write is called, it 606ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // means one of two things. First, it could be that the DMA output really 607ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // has not started yet. This is odd, but certainly not impossible. The 608ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // other possibility is that AudioFlinger is in its silence-pushing mode and 609ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // is not calling getNextWriteTimestamp. After an output is primed, its in 6103e8b92e93b5b49633e0452fb2cd5f6e3149667cePhil Burk // GNWTS where the amount of padding to compensate for different DMA start 611ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // times is taken into account. Go ahead and force a call to GNWTS, just to 612ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // be certain that we have checked recently and are not stuck in silence 613ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // fill mode. Failure to do this will cause the AudioOutput state machine 614ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // to eventually give up on DMA starting and reset the output over and over 615ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // again (spamming the log and producing general confusion). 616ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // 617ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // While we are in the process of checking our various output states, check 618ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // to see if any outputs have made it to the ACTIVE state. Pass this 619ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // information along to the call to processOneChunk. If any of our outputs 620ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // are waiting to be primed while other outputs have made it to steady 621ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // state, we need to change our priming behavior slightly. Instead of 622ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // filling an output's buffer completely, we want to fill it to slightly 623ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // less than full and let the adjustDelay mechanism take care of the rest. 624ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // 625ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // Failure to do this during steady state operation will almost certainly 626ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // lead to the new output being over-filled relative to the other outputs 627ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // causing it to be slightly out of sync. 628ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen AudioOutputList::iterator I; 629ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen bool checkDMAStart = false; 630ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen bool hasActiveOutputs = false; 6312b895ba03ec99ccccb05f67e297e91e31c128ce2Phil Burk { 6322b895ba03ec99ccccb05f67e297e91e31c128ce2Phil Burk Mutex::Autolock _l(mRoutingLock); 6332b895ba03ec99ccccb05f67e297e91e31c128ce2Phil Burk for (I = mPhysOutputs.begin(); I != mPhysOutputs.end(); ++I) { 6342b895ba03ec99ccccb05f67e297e91e31c128ce2Phil Burk if (AudioOutput::PRIMED == (*I)->getState()) 6352b895ba03ec99ccccb05f67e297e91e31c128ce2Phil Burk checkDMAStart = true; 6362b895ba03ec99ccccb05f67e297e91e31c128ce2Phil Burk 6372b895ba03ec99ccccb05f67e297e91e31c128ce2Phil Burk if ((*I)->getState() == AudioOutput::ACTIVE) 6382b895ba03ec99ccccb05f67e297e91e31c128ce2Phil Burk hasActiveOutputs = true; 6392b895ba03ec99ccccb05f67e297e91e31c128ce2Phil Burk } 640ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen } 641ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen if (checkDMAStart) { 642ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen int64_t junk; 643ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen getNextWriteTimestamp_internal(&junk); 644ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen } 645ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen 646ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // We always call processOneChunk on the outputs, as it is the 647ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // tick for their state machines. 6482b895ba03ec99ccccb05f67e297e91e31c128ce2Phil Burk { 6492b895ba03ec99ccccb05f67e297e91e31c128ce2Phil Burk Mutex::Autolock _l(mRoutingLock); 6502b895ba03ec99ccccb05f67e297e91e31c128ce2Phil Burk for (I = mPhysOutputs.begin(); I != mPhysOutputs.end(); ++I) { 6512b895ba03ec99ccccb05f67e297e91e31c128ce2Phil Burk (*I)->processOneChunk((uint8_t *)buffer, bytes, hasActiveOutputs, mInputFormat); 6522b895ba03ec99ccccb05f67e297e91e31c128ce2Phil Burk } 653ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen 6542b895ba03ec99ccccb05f67e297e91e31c128ce2Phil Burk // If we don't actually have any physical outputs to write to, just sleep 6552b895ba03ec99ccccb05f67e297e91e31c128ce2Phil Burk // for the proper amount of time in order to simulate the throttle that writing 6562b895ba03ec99ccccb05f67e297e91e31c128ce2Phil Burk // to the hardware would impose. 6572b895ba03ec99ccccb05f67e297e91e31c128ce2Phil Burk uint32_t framesWritten = bytes / mInputFrameSize; 6582b895ba03ec99ccccb05f67e297e91e31c128ce2Phil Burk finishedWriteOp(framesWritten, (0 == mPhysOutputs.size())); 6592b895ba03ec99ccccb05f67e297e91e31c128ce2Phil Burk } 660ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen 6612b895ba03ec99ccccb05f67e297e91e31c128ce2Phil Burk // Load presentation position cache because we will normally be locked when it is called. 6622b895ba03ec99ccccb05f67e297e91e31c128ce2Phil Burk { 6632b895ba03ec99ccccb05f67e297e91e31c128ce2Phil Burk Mutex::Autolock _l(mRoutingLock); 6642b895ba03ec99ccccb05f67e297e91e31c128ce2Phil Burk uint64_t frames; 6652b895ba03ec99ccccb05f67e297e91e31c128ce2Phil Burk struct timespec timestamp; 6662b895ba03ec99ccccb05f67e297e91e31c128ce2Phil Burk getPresentationPosition_l(&frames, ×tamp); 6672b895ba03ec99ccccb05f67e297e91e31c128ce2Phil Burk } 668ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen return static_cast<ssize_t>(bytes); 669ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen} 670ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen 671ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chenstatus_t AudioStreamOut::getNextWriteTimestamp(int64_t *timestamp) 672ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen{ 673ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen return getNextWriteTimestamp_internal(timestamp); 674ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen} 675ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen 676ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chenstatus_t AudioStreamOut::getNextWriteTimestamp_internal( 677ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen int64_t *timestamp) 678ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen{ 679ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen int64_t max_time = LLONG_MIN; 680ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen bool max_time_valid = false; 681ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen bool need_adjust = false; 682ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen 683ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // Across all of our physical outputs, figure out the max time when 684ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // a write operation will hit the speakers. Assume that if an 685ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // output cannot answer the question, its because it has never 686ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // started or because it has recently underflowed and needs to be 687ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // restarted. If this is the case, we will need to prime the 688ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // pipeline with a chunk's worth of data before proceeding. 689ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // If any of the outputs indicate a discontinuity (meaning that the 690ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // DMA start time was valid and is now invalid, or was and is valid 691ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // but was different from before; almost certainly caused by a low 692ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // level underfow), then just stop now. We will need to reset and 693ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // re-prime all of the outputs in order to make certain that the 694ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // lead-times on all of the outputs match. 695ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen 696ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen AudioOutputList::iterator I; 697ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen bool discon = false; 698ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen 699ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // Find the largest next write timestamp. The goal is to make EVERY 700ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // output have the same value, but we also need this to pass back 701ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // up the layers. 702ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen for (I = mPhysOutputs.begin(); I != mPhysOutputs.end(); ++I) { 703ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen int64_t tmp; 704ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen if (OK == (*I)->getNextWriteTimestamp(&tmp, &discon)) { 705ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen if (!max_time_valid || (max_time < tmp)) { 706ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen max_time = tmp; 707ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen max_time_valid = true; 708ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen } 709ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen } 710ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen } 711ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen 712ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // Check the state of each output and determine if we need to align them. 713ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // Make sure to do this after we have called each outputs' 714ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // getNextWriteTimestamp as the transition from PRIMED to DMA_START happens 715ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // there. 716ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen for (I = mPhysOutputs.begin(); I != mPhysOutputs.end(); ++I) { 717ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen if ((*I)->getState() == AudioOutput::DMA_START) { 718ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen need_adjust = true; 719ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen break; 720ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen } 721ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen } 722ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen 723ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // At this point, if we still have not found at least one output 724ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // who knows when their data is going to hit the speakers, then we 725ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // just can't answer the getNextWriteTimestamp question and we 726ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // should give up. 727ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen if (!max_time_valid) { 728ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen return INVALID_OPERATION; 729ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen } 730ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen 731ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // Stuff silence into the non-aligned outputs so that the effective 732ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // timestamp is the same for all the outputs. 733ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen if (need_adjust) 734ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen adjustOutputs(max_time); 735ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen 736ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // We are done. The time at which the next written audio should 737ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // hit the speakers is just max_time plus the maximum amt of delay 738ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen // compensation in the system. 739ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen *timestamp = max_time; 740ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen return OK; 741ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen} 742ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen 743ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen#define DUMP(a...) \ 744ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen snprintf(buffer, SIZE, a); \ 745ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen buffer[SIZE - 1] = 0; \ 746ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen result.append(buffer); 747ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen#define B2STR(b) b ? "true" : "false" 748ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen 749ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chenstatus_t AudioStreamOut::dump(int fd) 750ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen{ 751ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen const size_t SIZE = 256; 752ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen char buffer[SIZE]; 753ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen String8 result; 754ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen DUMP("\n%s AudioStreamOut::dump\n", getName()); 755ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen DUMP("\tsample rate : %d\n", sampleRate()); 756ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen DUMP("\tbuffer size : %d\n", bufferSize()); 757ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen DUMP("\tchannel mask : 0x%04x\n", chanMask()); 758ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen DUMP("\tformat : %d\n", format()); 759ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen DUMP("\tdevice mask : 0x%04x\n", mTgtDevices); 760282f06dc6d099dbb010cf9acf0bcb9bdee43fb8dRajat S Gupta DUMP("\tIn standby : %s\n", mInStandby? "yes" : "no"); 761ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen 762ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen mRoutingLock.lock(); 763ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen AudioOutputList outSnapshot(mPhysOutputs); 764ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen mRoutingLock.unlock(); 765ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen 766ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen AudioOutputList::iterator I; 767ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen for (I = outSnapshot.begin(); I != outSnapshot.end(); ++I) 768ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen (*I)->dump(result); 769ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen 770ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen ::write(fd, result.string(), result.size()); 771ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen 772ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen return NO_ERROR; 773ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen} 774ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen 775ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen#undef B2STR 776ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen#undef DUMP 777ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen 778ae089528c7e3a8107be65657e52276dd068c1039Mike J. Chen} // android 779