1062e67a26e0553dd142be622821f493df541f0c6Phil Burk/*
2062e67a26e0553dd142be622821f493df541f0c6Phil Burk**
3062e67a26e0553dd142be622821f493df541f0c6Phil Burk** Copyright 2015, The Android Open Source Project
4062e67a26e0553dd142be622821f493df541f0c6Phil Burk**
5062e67a26e0553dd142be622821f493df541f0c6Phil Burk** Licensed under the Apache License, Version 2.0 (the "License");
6062e67a26e0553dd142be622821f493df541f0c6Phil Burk** you may not use this file except in compliance with the License.
7062e67a26e0553dd142be622821f493df541f0c6Phil Burk** You may obtain a copy of the License at
8062e67a26e0553dd142be622821f493df541f0c6Phil Burk**
9062e67a26e0553dd142be622821f493df541f0c6Phil Burk**     http://www.apache.org/licenses/LICENSE-2.0
10062e67a26e0553dd142be622821f493df541f0c6Phil Burk**
11062e67a26e0553dd142be622821f493df541f0c6Phil Burk** Unless required by applicable law or agreed to in writing, software
12062e67a26e0553dd142be622821f493df541f0c6Phil Burk** distributed under the License is distributed on an "AS IS" BASIS,
13062e67a26e0553dd142be622821f493df541f0c6Phil Burk** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14062e67a26e0553dd142be622821f493df541f0c6Phil Burk** See the License for the specific language governing permissions and
15062e67a26e0553dd142be622821f493df541f0c6Phil Burk** limitations under the License.
16062e67a26e0553dd142be622821f493df541f0c6Phil Burk*/
17062e67a26e0553dd142be622821f493df541f0c6Phil Burk
18062e67a26e0553dd142be622821f493df541f0c6Phil Burk#define LOG_TAG "AudioFlinger"
19062e67a26e0553dd142be622821f493df541f0c6Phil Burk//#define LOG_NDEBUG 0
20062e67a26e0553dd142be622821f493df541f0c6Phil Burk
21a0c91339814f37ea78365afb436c9f3d1f0a0090Mikhail Naganov#include <media/audiohal/DeviceHalInterface.h>
22a0c91339814f37ea78365afb436c9f3d1f0a0090Mikhail Naganov#include <media/audiohal/StreamHalInterface.h>
23cbc8f617c1aebef5d041fa40dcd38a5466690b99Mikhail Naganov#include <system/audio.h>
24062e67a26e0553dd142be622821f493df541f0c6Phil Burk#include <utils/Log.h>
25062e67a26e0553dd142be622821f493df541f0c6Phil Burk
26062e67a26e0553dd142be622821f493df541f0c6Phil Burk#include "AudioHwDevice.h"
27062e67a26e0553dd142be622821f493df541f0c6Phil Burk#include "AudioStreamOut.h"
28062e67a26e0553dd142be622821f493df541f0c6Phil Burk
29062e67a26e0553dd142be622821f493df541f0c6Phil Burknamespace android {
30062e67a26e0553dd142be622821f493df541f0c6Phil Burk
31062e67a26e0553dd142be622821f493df541f0c6Phil Burk// ----------------------------------------------------------------------------
32062e67a26e0553dd142be622821f493df541f0c6Phil BurkAudioStreamOut::AudioStreamOut(AudioHwDevice *dev, audio_output_flags_t flags)
33062e67a26e0553dd142be622821f493df541f0c6Phil Burk        : audioHwDev(dev)
34062e67a26e0553dd142be622821f493df541f0c6Phil Burk        , stream(NULL)
35062e67a26e0553dd142be622821f493df541f0c6Phil Burk        , flags(flags)
3690eea7631b07117e46ae8b84889a2baa3eee7aeaPhil Burk        , mFramesWritten(0)
3790eea7631b07117e46ae8b84889a2baa3eee7aeaPhil Burk        , mFramesWrittenAtStandby(0)
3890eea7631b07117e46ae8b84889a2baa3eee7aeaPhil Burk        , mRenderPosition(0)
3990eea7631b07117e46ae8b84889a2baa3eee7aeaPhil Burk        , mRateMultiplier(1)
40fdb3c07db5d44535eb8c3ec46dc78ad8446c01ebPhil Burk        , mHalFormatHasProportionalFrames(false)
4190eea7631b07117e46ae8b84889a2baa3eee7aeaPhil Burk        , mHalFrameSize(0)
42062e67a26e0553dd142be622821f493df541f0c6Phil Burk{
43062e67a26e0553dd142be622821f493df541f0c6Phil Burk}
44062e67a26e0553dd142be622821f493df541f0c6Phil Burk
451dc98674f701dada94143b4d31b7221c58346c6cMikhail NaganovAudioStreamOut::~AudioStreamOut()
461dc98674f701dada94143b4d31b7221c58346c6cMikhail Naganov{
471dc98674f701dada94143b4d31b7221c58346c6cMikhail Naganov}
481dc98674f701dada94143b4d31b7221c58346c6cMikhail Naganov
49e4f1f63a2c54ee8687ad8cca18df0f6639ad7c81Mikhail Naganovsp<DeviceHalInterface> AudioStreamOut::hwDev() const
50062e67a26e0553dd142be622821f493df541f0c6Phil Burk{
51062e67a26e0553dd142be622821f493df541f0c6Phil Burk    return audioHwDev->hwDevice();
52062e67a26e0553dd142be622821f493df541f0c6Phil Burk}
53062e67a26e0553dd142be622821f493df541f0c6Phil Burk
5490eea7631b07117e46ae8b84889a2baa3eee7aeaPhil Burkstatus_t AudioStreamOut::getRenderPosition(uint64_t *frames)
55062e67a26e0553dd142be622821f493df541f0c6Phil Burk{
561dc98674f701dada94143b4d31b7221c58346c6cMikhail Naganov    if (stream == 0) {
57062e67a26e0553dd142be622821f493df541f0c6Phil Burk        return NO_INIT;
58062e67a26e0553dd142be622821f493df541f0c6Phil Burk    }
5990eea7631b07117e46ae8b84889a2baa3eee7aeaPhil Burk
6090eea7631b07117e46ae8b84889a2baa3eee7aeaPhil Burk    uint32_t halPosition = 0;
611dc98674f701dada94143b4d31b7221c58346c6cMikhail Naganov    status_t status = stream->getRenderPosition(&halPosition);
6290eea7631b07117e46ae8b84889a2baa3eee7aeaPhil Burk    if (status != NO_ERROR) {
6390eea7631b07117e46ae8b84889a2baa3eee7aeaPhil Burk        return status;
6490eea7631b07117e46ae8b84889a2baa3eee7aeaPhil Burk    }
6590eea7631b07117e46ae8b84889a2baa3eee7aeaPhil Burk
6690eea7631b07117e46ae8b84889a2baa3eee7aeaPhil Burk    // Maintain a 64-bit render position using the 32-bit result from the HAL.
6790eea7631b07117e46ae8b84889a2baa3eee7aeaPhil Burk    // This delta calculation relies on the arithmetic overflow behavior
6890eea7631b07117e46ae8b84889a2baa3eee7aeaPhil Burk    // of integers. For example (100 - 0xFFFFFFF0) = 116.
6990eea7631b07117e46ae8b84889a2baa3eee7aeaPhil Burk    uint32_t truncatedPosition = (uint32_t)mRenderPosition;
7090eea7631b07117e46ae8b84889a2baa3eee7aeaPhil Burk    int32_t deltaHalPosition = (int32_t)(halPosition - truncatedPosition);
7190eea7631b07117e46ae8b84889a2baa3eee7aeaPhil Burk    if (deltaHalPosition > 0) {
7290eea7631b07117e46ae8b84889a2baa3eee7aeaPhil Burk        mRenderPosition += deltaHalPosition;
7390eea7631b07117e46ae8b84889a2baa3eee7aeaPhil Burk    }
7490eea7631b07117e46ae8b84889a2baa3eee7aeaPhil Burk    // Scale from HAL sample rate to application rate.
7590eea7631b07117e46ae8b84889a2baa3eee7aeaPhil Burk    *frames = mRenderPosition / mRateMultiplier;
7690eea7631b07117e46ae8b84889a2baa3eee7aeaPhil Burk
7790eea7631b07117e46ae8b84889a2baa3eee7aeaPhil Burk    return status;
7890eea7631b07117e46ae8b84889a2baa3eee7aeaPhil Burk}
7990eea7631b07117e46ae8b84889a2baa3eee7aeaPhil Burk
8090eea7631b07117e46ae8b84889a2baa3eee7aeaPhil Burk// return bottom 32-bits of the render position
8190eea7631b07117e46ae8b84889a2baa3eee7aeaPhil Burkstatus_t AudioStreamOut::getRenderPosition(uint32_t *frames)
8290eea7631b07117e46ae8b84889a2baa3eee7aeaPhil Burk{
8390eea7631b07117e46ae8b84889a2baa3eee7aeaPhil Burk    uint64_t position64 = 0;
8490eea7631b07117e46ae8b84889a2baa3eee7aeaPhil Burk    status_t status = getRenderPosition(&position64);
8590eea7631b07117e46ae8b84889a2baa3eee7aeaPhil Burk    if (status == NO_ERROR) {
8690eea7631b07117e46ae8b84889a2baa3eee7aeaPhil Burk        *frames = (uint32_t)position64;
8790eea7631b07117e46ae8b84889a2baa3eee7aeaPhil Burk    }
8890eea7631b07117e46ae8b84889a2baa3eee7aeaPhil Burk    return status;
89062e67a26e0553dd142be622821f493df541f0c6Phil Burk}
90062e67a26e0553dd142be622821f493df541f0c6Phil Burk
91062e67a26e0553dd142be622821f493df541f0c6Phil Burkstatus_t AudioStreamOut::getPresentationPosition(uint64_t *frames, struct timespec *timestamp)
92062e67a26e0553dd142be622821f493df541f0c6Phil Burk{
931dc98674f701dada94143b4d31b7221c58346c6cMikhail Naganov    if (stream == 0) {
94062e67a26e0553dd142be622821f493df541f0c6Phil Burk        return NO_INIT;
95062e67a26e0553dd142be622821f493df541f0c6Phil Burk    }
9690eea7631b07117e46ae8b84889a2baa3eee7aeaPhil Burk
9790eea7631b07117e46ae8b84889a2baa3eee7aeaPhil Burk    uint64_t halPosition = 0;
981dc98674f701dada94143b4d31b7221c58346c6cMikhail Naganov    status_t status = stream->getPresentationPosition(&halPosition, timestamp);
9990eea7631b07117e46ae8b84889a2baa3eee7aeaPhil Burk    if (status != NO_ERROR) {
10090eea7631b07117e46ae8b84889a2baa3eee7aeaPhil Burk        return status;
10190eea7631b07117e46ae8b84889a2baa3eee7aeaPhil Burk    }
10290eea7631b07117e46ae8b84889a2baa3eee7aeaPhil Burk
10390eea7631b07117e46ae8b84889a2baa3eee7aeaPhil Burk    // Adjust for standby using HAL rate frames.
10490eea7631b07117e46ae8b84889a2baa3eee7aeaPhil Burk    // Only apply this correction if the HAL is getting PCM frames.
105fdb3c07db5d44535eb8c3ec46dc78ad8446c01ebPhil Burk    if (mHalFormatHasProportionalFrames) {
10690eea7631b07117e46ae8b84889a2baa3eee7aeaPhil Burk        uint64_t adjustedPosition = (halPosition <= mFramesWrittenAtStandby) ?
10790eea7631b07117e46ae8b84889a2baa3eee7aeaPhil Burk                0 : (halPosition - mFramesWrittenAtStandby);
10890eea7631b07117e46ae8b84889a2baa3eee7aeaPhil Burk        // Scale from HAL sample rate to application rate.
10990eea7631b07117e46ae8b84889a2baa3eee7aeaPhil Burk        *frames = adjustedPosition / mRateMultiplier;
11090eea7631b07117e46ae8b84889a2baa3eee7aeaPhil Burk    } else {
11190eea7631b07117e46ae8b84889a2baa3eee7aeaPhil Burk        // For offloaded MP3 and other compressed formats.
11290eea7631b07117e46ae8b84889a2baa3eee7aeaPhil Burk        *frames = halPosition;
11390eea7631b07117e46ae8b84889a2baa3eee7aeaPhil Burk    }
11490eea7631b07117e46ae8b84889a2baa3eee7aeaPhil Burk
11590eea7631b07117e46ae8b84889a2baa3eee7aeaPhil Burk    return status;
116062e67a26e0553dd142be622821f493df541f0c6Phil Burk}
117062e67a26e0553dd142be622821f493df541f0c6Phil Burk
118062e67a26e0553dd142be622821f493df541f0c6Phil Burkstatus_t AudioStreamOut::open(
119062e67a26e0553dd142be622821f493df541f0c6Phil Burk        audio_io_handle_t handle,
120062e67a26e0553dd142be622821f493df541f0c6Phil Burk        audio_devices_t devices,
121062e67a26e0553dd142be622821f493df541f0c6Phil Burk        struct audio_config *config,
122062e67a26e0553dd142be622821f493df541f0c6Phil Burk        const char *address)
123062e67a26e0553dd142be622821f493df541f0c6Phil Burk{
1241dc98674f701dada94143b4d31b7221c58346c6cMikhail Naganov    sp<StreamOutHalInterface> outStream;
125fdb3c07db5d44535eb8c3ec46dc78ad8446c01ebPhil Burk
126fdb3c07db5d44535eb8c3ec46dc78ad8446c01ebPhil Burk    audio_output_flags_t customFlags = (config->format == AUDIO_FORMAT_IEC61937)
127fdb3c07db5d44535eb8c3ec46dc78ad8446c01ebPhil Burk                ? (audio_output_flags_t)(flags | AUDIO_OUTPUT_FLAG_IEC958_NONAUDIO)
128fdb3c07db5d44535eb8c3ec46dc78ad8446c01ebPhil Burk                : flags;
129fdb3c07db5d44535eb8c3ec46dc78ad8446c01ebPhil Burk
1301dc98674f701dada94143b4d31b7221c58346c6cMikhail Naganov    int status = hwDev()->openOutputStream(
131062e67a26e0553dd142be622821f493df541f0c6Phil Burk            handle,
132062e67a26e0553dd142be622821f493df541f0c6Phil Burk            devices,
133fdb3c07db5d44535eb8c3ec46dc78ad8446c01ebPhil Burk            customFlags,
134062e67a26e0553dd142be622821f493df541f0c6Phil Burk            config,
135e4f1f63a2c54ee8687ad8cca18df0f6639ad7c81Mikhail Naganov            address,
136e4f1f63a2c54ee8687ad8cca18df0f6639ad7c81Mikhail Naganov            &outStream);
137fdb3c07db5d44535eb8c3ec46dc78ad8446c01ebPhil Burk    ALOGV("AudioStreamOut::open(), HAL returned "
138fdb3c07db5d44535eb8c3ec46dc78ad8446c01ebPhil Burk            " stream %p, sampleRate %d, Format %#x, "
139062e67a26e0553dd142be622821f493df541f0c6Phil Burk            "channelMask %#x, status %d",
1401dc98674f701dada94143b4d31b7221c58346c6cMikhail Naganov            outStream.get(),
141062e67a26e0553dd142be622821f493df541f0c6Phil Burk            config->sample_rate,
142062e67a26e0553dd142be622821f493df541f0c6Phil Burk            config->format,
143062e67a26e0553dd142be622821f493df541f0c6Phil Burk            config->channel_mask,
144062e67a26e0553dd142be622821f493df541f0c6Phil Burk            status);
145062e67a26e0553dd142be622821f493df541f0c6Phil Burk
146fdb3c07db5d44535eb8c3ec46dc78ad8446c01ebPhil Burk    // Some HALs may not recognize AUDIO_FORMAT_IEC61937. But if we declare
147fdb3c07db5d44535eb8c3ec46dc78ad8446c01ebPhil Burk    // it as PCM then it will probably work.
148fdb3c07db5d44535eb8c3ec46dc78ad8446c01ebPhil Burk    if (status != NO_ERROR && config->format == AUDIO_FORMAT_IEC61937) {
149fdb3c07db5d44535eb8c3ec46dc78ad8446c01ebPhil Burk        struct audio_config customConfig = *config;
150fdb3c07db5d44535eb8c3ec46dc78ad8446c01ebPhil Burk        customConfig.format = AUDIO_FORMAT_PCM_16_BIT;
151fdb3c07db5d44535eb8c3ec46dc78ad8446c01ebPhil Burk
1521dc98674f701dada94143b4d31b7221c58346c6cMikhail Naganov        status = hwDev()->openOutputStream(
153fdb3c07db5d44535eb8c3ec46dc78ad8446c01ebPhil Burk                handle,
154fdb3c07db5d44535eb8c3ec46dc78ad8446c01ebPhil Burk                devices,
155fdb3c07db5d44535eb8c3ec46dc78ad8446c01ebPhil Burk                customFlags,
156fdb3c07db5d44535eb8c3ec46dc78ad8446c01ebPhil Burk                &customConfig,
157e4f1f63a2c54ee8687ad8cca18df0f6639ad7c81Mikhail Naganov                address,
158e4f1f63a2c54ee8687ad8cca18df0f6639ad7c81Mikhail Naganov                &outStream);
159fdb3c07db5d44535eb8c3ec46dc78ad8446c01ebPhil Burk        ALOGV("AudioStreamOut::open(), treat IEC61937 as PCM, status = %d", status);
160fdb3c07db5d44535eb8c3ec46dc78ad8446c01ebPhil Burk    }
161fdb3c07db5d44535eb8c3ec46dc78ad8446c01ebPhil Burk
162062e67a26e0553dd142be622821f493df541f0c6Phil Burk    if (status == NO_ERROR) {
163062e67a26e0553dd142be622821f493df541f0c6Phil Burk        stream = outStream;
164fdb3c07db5d44535eb8c3ec46dc78ad8446c01ebPhil Burk        mHalFormatHasProportionalFrames = audio_has_proportional_frames(config->format);
1651dc98674f701dada94143b4d31b7221c58346c6cMikhail Naganov        status = stream->getFrameSize(&mHalFrameSize);
166062e67a26e0553dd142be622821f493df541f0c6Phil Burk    }
167062e67a26e0553dd142be622821f493df541f0c6Phil Burk
168062e67a26e0553dd142be622821f493df541f0c6Phil Burk    return status;
169062e67a26e0553dd142be622821f493df541f0c6Phil Burk}
170062e67a26e0553dd142be622821f493df541f0c6Phil Burk
171ca5e6143740299c877d69e97f7968cd04476d32cPhil Burkaudio_format_t AudioStreamOut::getFormat() const
172062e67a26e0553dd142be622821f493df541f0c6Phil Burk{
1731dc98674f701dada94143b4d31b7221c58346c6cMikhail Naganov    audio_format_t result;
1741dc98674f701dada94143b4d31b7221c58346c6cMikhail Naganov    return stream->getFormat(&result) == OK ? result : AUDIO_FORMAT_INVALID;
175ca5e6143740299c877d69e97f7968cd04476d32cPhil Burk}
176ca5e6143740299c877d69e97f7968cd04476d32cPhil Burk
177ca5e6143740299c877d69e97f7968cd04476d32cPhil Burkuint32_t AudioStreamOut::getSampleRate() const
178ca5e6143740299c877d69e97f7968cd04476d32cPhil Burk{
1791dc98674f701dada94143b4d31b7221c58346c6cMikhail Naganov    uint32_t result;
1801dc98674f701dada94143b4d31b7221c58346c6cMikhail Naganov    return stream->getSampleRate(&result) == OK ? result : 0;
181ca5e6143740299c877d69e97f7968cd04476d32cPhil Burk}
182ca5e6143740299c877d69e97f7968cd04476d32cPhil Burk
183ca5e6143740299c877d69e97f7968cd04476d32cPhil Burkaudio_channel_mask_t AudioStreamOut::getChannelMask() const
184ca5e6143740299c877d69e97f7968cd04476d32cPhil Burk{
1851dc98674f701dada94143b4d31b7221c58346c6cMikhail Naganov    audio_channel_mask_t result;
1861dc98674f701dada94143b4d31b7221c58346c6cMikhail Naganov    return stream->getChannelMask(&result) == OK ? result : AUDIO_CHANNEL_INVALID;
187062e67a26e0553dd142be622821f493df541f0c6Phil Burk}
188062e67a26e0553dd142be622821f493df541f0c6Phil Burk
189062e67a26e0553dd142be622821f493df541f0c6Phil Burkint AudioStreamOut::flush()
190062e67a26e0553dd142be622821f493df541f0c6Phil Burk{
19190eea7631b07117e46ae8b84889a2baa3eee7aeaPhil Burk    mRenderPosition = 0;
19290eea7631b07117e46ae8b84889a2baa3eee7aeaPhil Burk    mFramesWritten = 0;
19390eea7631b07117e46ae8b84889a2baa3eee7aeaPhil Burk    mFramesWrittenAtStandby = 0;
1941dc98674f701dada94143b4d31b7221c58346c6cMikhail Naganov    status_t result = stream->flush();
1951dc98674f701dada94143b4d31b7221c58346c6cMikhail Naganov    return result != INVALID_OPERATION ? result : NO_ERROR;
196062e67a26e0553dd142be622821f493df541f0c6Phil Burk}
197062e67a26e0553dd142be622821f493df541f0c6Phil Burk
198062e67a26e0553dd142be622821f493df541f0c6Phil Burkint AudioStreamOut::standby()
199062e67a26e0553dd142be622821f493df541f0c6Phil Burk{
20090eea7631b07117e46ae8b84889a2baa3eee7aeaPhil Burk    mRenderPosition = 0;
20190eea7631b07117e46ae8b84889a2baa3eee7aeaPhil Burk    mFramesWrittenAtStandby = mFramesWritten;
2021dc98674f701dada94143b4d31b7221c58346c6cMikhail Naganov    return stream->standby();
203062e67a26e0553dd142be622821f493df541f0c6Phil Burk}
204062e67a26e0553dd142be622821f493df541f0c6Phil Burk
20590eea7631b07117e46ae8b84889a2baa3eee7aeaPhil Burkssize_t AudioStreamOut::write(const void *buffer, size_t numBytes)
206062e67a26e0553dd142be622821f493df541f0c6Phil Burk{
2071dc98674f701dada94143b4d31b7221c58346c6cMikhail Naganov    size_t bytesWritten;
2081dc98674f701dada94143b4d31b7221c58346c6cMikhail Naganov    status_t result = stream->write(buffer, numBytes, &bytesWritten);
2091dc98674f701dada94143b4d31b7221c58346c6cMikhail Naganov    if (result == OK && bytesWritten > 0 && mHalFrameSize > 0) {
21090eea7631b07117e46ae8b84889a2baa3eee7aeaPhil Burk        mFramesWritten += bytesWritten / mHalFrameSize;
21190eea7631b07117e46ae8b84889a2baa3eee7aeaPhil Burk    }
2121dc98674f701dada94143b4d31b7221c58346c6cMikhail Naganov    return result == OK ? bytesWritten : result;
213062e67a26e0553dd142be622821f493df541f0c6Phil Burk}
214062e67a26e0553dd142be622821f493df541f0c6Phil Burk
215062e67a26e0553dd142be622821f493df541f0c6Phil Burk} // namespace android
216