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, &timestamp);
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