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 21062e67a26e0553dd142be622821f493df541f0c6Phil Burk#include <hardware/audio.h> 22062e67a26e0553dd142be622821f493df541f0c6Phil Burk#include <utils/Log.h> 23062e67a26e0553dd142be622821f493df541f0c6Phil Burk 24062e67a26e0553dd142be622821f493df541f0c6Phil Burk#include "AudioHwDevice.h" 25062e67a26e0553dd142be622821f493df541f0c6Phil Burk#include "AudioStreamOut.h" 26062e67a26e0553dd142be622821f493df541f0c6Phil Burk 27062e67a26e0553dd142be622821f493df541f0c6Phil Burknamespace android { 28062e67a26e0553dd142be622821f493df541f0c6Phil Burk 29062e67a26e0553dd142be622821f493df541f0c6Phil Burk// ---------------------------------------------------------------------------- 30062e67a26e0553dd142be622821f493df541f0c6Phil BurkAudioStreamOut::AudioStreamOut(AudioHwDevice *dev, audio_output_flags_t flags) 31062e67a26e0553dd142be622821f493df541f0c6Phil Burk : audioHwDev(dev) 32062e67a26e0553dd142be622821f493df541f0c6Phil Burk , stream(NULL) 33062e67a26e0553dd142be622821f493df541f0c6Phil Burk , flags(flags) 3490eea7631b07117e46ae8b84889a2baa3eee7aeaPhil Burk , mFramesWritten(0) 3590eea7631b07117e46ae8b84889a2baa3eee7aeaPhil Burk , mFramesWrittenAtStandby(0) 3690eea7631b07117e46ae8b84889a2baa3eee7aeaPhil Burk , mRenderPosition(0) 3790eea7631b07117e46ae8b84889a2baa3eee7aeaPhil Burk , mRateMultiplier(1) 38fdb3c07db5d44535eb8c3ec46dc78ad8446c01ebPhil Burk , mHalFormatHasProportionalFrames(false) 3990eea7631b07117e46ae8b84889a2baa3eee7aeaPhil Burk , mHalFrameSize(0) 40062e67a26e0553dd142be622821f493df541f0c6Phil Burk{ 41062e67a26e0553dd142be622821f493df541f0c6Phil Burk} 42062e67a26e0553dd142be622821f493df541f0c6Phil Burk 4390eea7631b07117e46ae8b84889a2baa3eee7aeaPhil Burkaudio_hw_device_t *AudioStreamOut::hwDev() const 44062e67a26e0553dd142be622821f493df541f0c6Phil Burk{ 45062e67a26e0553dd142be622821f493df541f0c6Phil Burk return audioHwDev->hwDevice(); 46062e67a26e0553dd142be622821f493df541f0c6Phil Burk} 47062e67a26e0553dd142be622821f493df541f0c6Phil Burk 4890eea7631b07117e46ae8b84889a2baa3eee7aeaPhil Burkstatus_t AudioStreamOut::getRenderPosition(uint64_t *frames) 49062e67a26e0553dd142be622821f493df541f0c6Phil Burk{ 50062e67a26e0553dd142be622821f493df541f0c6Phil Burk if (stream == NULL) { 51062e67a26e0553dd142be622821f493df541f0c6Phil Burk return NO_INIT; 52062e67a26e0553dd142be622821f493df541f0c6Phil Burk } 5390eea7631b07117e46ae8b84889a2baa3eee7aeaPhil Burk 5490eea7631b07117e46ae8b84889a2baa3eee7aeaPhil Burk uint32_t halPosition = 0; 5590eea7631b07117e46ae8b84889a2baa3eee7aeaPhil Burk status_t status = stream->get_render_position(stream, &halPosition); 5690eea7631b07117e46ae8b84889a2baa3eee7aeaPhil Burk if (status != NO_ERROR) { 5790eea7631b07117e46ae8b84889a2baa3eee7aeaPhil Burk return status; 5890eea7631b07117e46ae8b84889a2baa3eee7aeaPhil Burk } 5990eea7631b07117e46ae8b84889a2baa3eee7aeaPhil Burk 6090eea7631b07117e46ae8b84889a2baa3eee7aeaPhil Burk // Maintain a 64-bit render position using the 32-bit result from the HAL. 6190eea7631b07117e46ae8b84889a2baa3eee7aeaPhil Burk // This delta calculation relies on the arithmetic overflow behavior 6290eea7631b07117e46ae8b84889a2baa3eee7aeaPhil Burk // of integers. For example (100 - 0xFFFFFFF0) = 116. 6390eea7631b07117e46ae8b84889a2baa3eee7aeaPhil Burk uint32_t truncatedPosition = (uint32_t)mRenderPosition; 6490eea7631b07117e46ae8b84889a2baa3eee7aeaPhil Burk int32_t deltaHalPosition = (int32_t)(halPosition - truncatedPosition); 6590eea7631b07117e46ae8b84889a2baa3eee7aeaPhil Burk if (deltaHalPosition > 0) { 6690eea7631b07117e46ae8b84889a2baa3eee7aeaPhil Burk mRenderPosition += deltaHalPosition; 6790eea7631b07117e46ae8b84889a2baa3eee7aeaPhil Burk } 6890eea7631b07117e46ae8b84889a2baa3eee7aeaPhil Burk // Scale from HAL sample rate to application rate. 6990eea7631b07117e46ae8b84889a2baa3eee7aeaPhil Burk *frames = mRenderPosition / mRateMultiplier; 7090eea7631b07117e46ae8b84889a2baa3eee7aeaPhil Burk 7190eea7631b07117e46ae8b84889a2baa3eee7aeaPhil Burk return status; 7290eea7631b07117e46ae8b84889a2baa3eee7aeaPhil Burk} 7390eea7631b07117e46ae8b84889a2baa3eee7aeaPhil Burk 7490eea7631b07117e46ae8b84889a2baa3eee7aeaPhil Burk// return bottom 32-bits of the render position 7590eea7631b07117e46ae8b84889a2baa3eee7aeaPhil Burkstatus_t AudioStreamOut::getRenderPosition(uint32_t *frames) 7690eea7631b07117e46ae8b84889a2baa3eee7aeaPhil Burk{ 7790eea7631b07117e46ae8b84889a2baa3eee7aeaPhil Burk uint64_t position64 = 0; 7890eea7631b07117e46ae8b84889a2baa3eee7aeaPhil Burk status_t status = getRenderPosition(&position64); 7990eea7631b07117e46ae8b84889a2baa3eee7aeaPhil Burk if (status == NO_ERROR) { 8090eea7631b07117e46ae8b84889a2baa3eee7aeaPhil Burk *frames = (uint32_t)position64; 8190eea7631b07117e46ae8b84889a2baa3eee7aeaPhil Burk } 8290eea7631b07117e46ae8b84889a2baa3eee7aeaPhil Burk return status; 83062e67a26e0553dd142be622821f493df541f0c6Phil Burk} 84062e67a26e0553dd142be622821f493df541f0c6Phil Burk 85062e67a26e0553dd142be622821f493df541f0c6Phil Burkstatus_t AudioStreamOut::getPresentationPosition(uint64_t *frames, struct timespec *timestamp) 86062e67a26e0553dd142be622821f493df541f0c6Phil Burk{ 87062e67a26e0553dd142be622821f493df541f0c6Phil Burk if (stream == NULL) { 88062e67a26e0553dd142be622821f493df541f0c6Phil Burk return NO_INIT; 89062e67a26e0553dd142be622821f493df541f0c6Phil Burk } 9090eea7631b07117e46ae8b84889a2baa3eee7aeaPhil Burk 9190eea7631b07117e46ae8b84889a2baa3eee7aeaPhil Burk uint64_t halPosition = 0; 9290eea7631b07117e46ae8b84889a2baa3eee7aeaPhil Burk status_t status = stream->get_presentation_position(stream, &halPosition, timestamp); 9390eea7631b07117e46ae8b84889a2baa3eee7aeaPhil Burk if (status != NO_ERROR) { 9490eea7631b07117e46ae8b84889a2baa3eee7aeaPhil Burk return status; 9590eea7631b07117e46ae8b84889a2baa3eee7aeaPhil Burk } 9690eea7631b07117e46ae8b84889a2baa3eee7aeaPhil Burk 9790eea7631b07117e46ae8b84889a2baa3eee7aeaPhil Burk // Adjust for standby using HAL rate frames. 9890eea7631b07117e46ae8b84889a2baa3eee7aeaPhil Burk // Only apply this correction if the HAL is getting PCM frames. 99fdb3c07db5d44535eb8c3ec46dc78ad8446c01ebPhil Burk if (mHalFormatHasProportionalFrames) { 10090eea7631b07117e46ae8b84889a2baa3eee7aeaPhil Burk uint64_t adjustedPosition = (halPosition <= mFramesWrittenAtStandby) ? 10190eea7631b07117e46ae8b84889a2baa3eee7aeaPhil Burk 0 : (halPosition - mFramesWrittenAtStandby); 10290eea7631b07117e46ae8b84889a2baa3eee7aeaPhil Burk // Scale from HAL sample rate to application rate. 10390eea7631b07117e46ae8b84889a2baa3eee7aeaPhil Burk *frames = adjustedPosition / mRateMultiplier; 10490eea7631b07117e46ae8b84889a2baa3eee7aeaPhil Burk } else { 10590eea7631b07117e46ae8b84889a2baa3eee7aeaPhil Burk // For offloaded MP3 and other compressed formats. 10690eea7631b07117e46ae8b84889a2baa3eee7aeaPhil Burk *frames = halPosition; 10790eea7631b07117e46ae8b84889a2baa3eee7aeaPhil Burk } 10890eea7631b07117e46ae8b84889a2baa3eee7aeaPhil Burk 10990eea7631b07117e46ae8b84889a2baa3eee7aeaPhil Burk return status; 110062e67a26e0553dd142be622821f493df541f0c6Phil Burk} 111062e67a26e0553dd142be622821f493df541f0c6Phil Burk 112062e67a26e0553dd142be622821f493df541f0c6Phil Burkstatus_t AudioStreamOut::open( 113062e67a26e0553dd142be622821f493df541f0c6Phil Burk audio_io_handle_t handle, 114062e67a26e0553dd142be622821f493df541f0c6Phil Burk audio_devices_t devices, 115062e67a26e0553dd142be622821f493df541f0c6Phil Burk struct audio_config *config, 116062e67a26e0553dd142be622821f493df541f0c6Phil Burk const char *address) 117062e67a26e0553dd142be622821f493df541f0c6Phil Burk{ 11890eea7631b07117e46ae8b84889a2baa3eee7aeaPhil Burk audio_stream_out_t *outStream; 119fdb3c07db5d44535eb8c3ec46dc78ad8446c01ebPhil Burk 120fdb3c07db5d44535eb8c3ec46dc78ad8446c01ebPhil Burk audio_output_flags_t customFlags = (config->format == AUDIO_FORMAT_IEC61937) 121fdb3c07db5d44535eb8c3ec46dc78ad8446c01ebPhil Burk ? (audio_output_flags_t)(flags | AUDIO_OUTPUT_FLAG_IEC958_NONAUDIO) 122fdb3c07db5d44535eb8c3ec46dc78ad8446c01ebPhil Burk : flags; 123fdb3c07db5d44535eb8c3ec46dc78ad8446c01ebPhil Burk 124062e67a26e0553dd142be622821f493df541f0c6Phil Burk int status = hwDev()->open_output_stream( 125062e67a26e0553dd142be622821f493df541f0c6Phil Burk hwDev(), 126062e67a26e0553dd142be622821f493df541f0c6Phil Burk handle, 127062e67a26e0553dd142be622821f493df541f0c6Phil Burk devices, 128fdb3c07db5d44535eb8c3ec46dc78ad8446c01ebPhil Burk customFlags, 129062e67a26e0553dd142be622821f493df541f0c6Phil Burk config, 130062e67a26e0553dd142be622821f493df541f0c6Phil Burk &outStream, 131062e67a26e0553dd142be622821f493df541f0c6Phil Burk address); 132fdb3c07db5d44535eb8c3ec46dc78ad8446c01ebPhil Burk ALOGV("AudioStreamOut::open(), HAL returned " 133fdb3c07db5d44535eb8c3ec46dc78ad8446c01ebPhil Burk " stream %p, sampleRate %d, Format %#x, " 134062e67a26e0553dd142be622821f493df541f0c6Phil Burk "channelMask %#x, status %d", 135062e67a26e0553dd142be622821f493df541f0c6Phil Burk outStream, 136062e67a26e0553dd142be622821f493df541f0c6Phil Burk config->sample_rate, 137062e67a26e0553dd142be622821f493df541f0c6Phil Burk config->format, 138062e67a26e0553dd142be622821f493df541f0c6Phil Burk config->channel_mask, 139062e67a26e0553dd142be622821f493df541f0c6Phil Burk status); 140062e67a26e0553dd142be622821f493df541f0c6Phil Burk 141fdb3c07db5d44535eb8c3ec46dc78ad8446c01ebPhil Burk // Some HALs may not recognize AUDIO_FORMAT_IEC61937. But if we declare 142fdb3c07db5d44535eb8c3ec46dc78ad8446c01ebPhil Burk // it as PCM then it will probably work. 143fdb3c07db5d44535eb8c3ec46dc78ad8446c01ebPhil Burk if (status != NO_ERROR && config->format == AUDIO_FORMAT_IEC61937) { 144fdb3c07db5d44535eb8c3ec46dc78ad8446c01ebPhil Burk struct audio_config customConfig = *config; 145fdb3c07db5d44535eb8c3ec46dc78ad8446c01ebPhil Burk customConfig.format = AUDIO_FORMAT_PCM_16_BIT; 146fdb3c07db5d44535eb8c3ec46dc78ad8446c01ebPhil Burk 147fdb3c07db5d44535eb8c3ec46dc78ad8446c01ebPhil Burk status = hwDev()->open_output_stream( 148fdb3c07db5d44535eb8c3ec46dc78ad8446c01ebPhil Burk hwDev(), 149fdb3c07db5d44535eb8c3ec46dc78ad8446c01ebPhil Burk handle, 150fdb3c07db5d44535eb8c3ec46dc78ad8446c01ebPhil Burk devices, 151fdb3c07db5d44535eb8c3ec46dc78ad8446c01ebPhil Burk customFlags, 152fdb3c07db5d44535eb8c3ec46dc78ad8446c01ebPhil Burk &customConfig, 153fdb3c07db5d44535eb8c3ec46dc78ad8446c01ebPhil Burk &outStream, 154fdb3c07db5d44535eb8c3ec46dc78ad8446c01ebPhil Burk address); 155fdb3c07db5d44535eb8c3ec46dc78ad8446c01ebPhil Burk ALOGV("AudioStreamOut::open(), treat IEC61937 as PCM, status = %d", status); 156fdb3c07db5d44535eb8c3ec46dc78ad8446c01ebPhil Burk } 157fdb3c07db5d44535eb8c3ec46dc78ad8446c01ebPhil Burk 158062e67a26e0553dd142be622821f493df541f0c6Phil Burk if (status == NO_ERROR) { 159062e67a26e0553dd142be622821f493df541f0c6Phil Burk stream = outStream; 160fdb3c07db5d44535eb8c3ec46dc78ad8446c01ebPhil Burk mHalFormatHasProportionalFrames = audio_has_proportional_frames(config->format); 16190eea7631b07117e46ae8b84889a2baa3eee7aeaPhil Burk mHalFrameSize = audio_stream_out_frame_size(stream); 162062e67a26e0553dd142be622821f493df541f0c6Phil Burk } 163062e67a26e0553dd142be622821f493df541f0c6Phil Burk 164062e67a26e0553dd142be622821f493df541f0c6Phil Burk return status; 165062e67a26e0553dd142be622821f493df541f0c6Phil Burk} 166062e67a26e0553dd142be622821f493df541f0c6Phil Burk 167ca5e6143740299c877d69e97f7968cd04476d32cPhil Burkaudio_format_t AudioStreamOut::getFormat() const 168062e67a26e0553dd142be622821f493df541f0c6Phil Burk{ 169ca5e6143740299c877d69e97f7968cd04476d32cPhil Burk return stream->common.get_format(&stream->common); 170ca5e6143740299c877d69e97f7968cd04476d32cPhil Burk} 171ca5e6143740299c877d69e97f7968cd04476d32cPhil Burk 172ca5e6143740299c877d69e97f7968cd04476d32cPhil Burkuint32_t AudioStreamOut::getSampleRate() const 173ca5e6143740299c877d69e97f7968cd04476d32cPhil Burk{ 174ca5e6143740299c877d69e97f7968cd04476d32cPhil Burk return stream->common.get_sample_rate(&stream->common); 175ca5e6143740299c877d69e97f7968cd04476d32cPhil Burk} 176ca5e6143740299c877d69e97f7968cd04476d32cPhil Burk 177ca5e6143740299c877d69e97f7968cd04476d32cPhil Burkaudio_channel_mask_t AudioStreamOut::getChannelMask() const 178ca5e6143740299c877d69e97f7968cd04476d32cPhil Burk{ 179ca5e6143740299c877d69e97f7968cd04476d32cPhil Burk return stream->common.get_channels(&stream->common); 180062e67a26e0553dd142be622821f493df541f0c6Phil Burk} 181062e67a26e0553dd142be622821f493df541f0c6Phil Burk 182062e67a26e0553dd142be622821f493df541f0c6Phil Burkint AudioStreamOut::flush() 183062e67a26e0553dd142be622821f493df541f0c6Phil Burk{ 184062e67a26e0553dd142be622821f493df541f0c6Phil Burk ALOG_ASSERT(stream != NULL); 18590eea7631b07117e46ae8b84889a2baa3eee7aeaPhil Burk mRenderPosition = 0; 18690eea7631b07117e46ae8b84889a2baa3eee7aeaPhil Burk mFramesWritten = 0; 18790eea7631b07117e46ae8b84889a2baa3eee7aeaPhil Burk mFramesWrittenAtStandby = 0; 188062e67a26e0553dd142be622821f493df541f0c6Phil Burk if (stream->flush != NULL) { 189062e67a26e0553dd142be622821f493df541f0c6Phil Burk return stream->flush(stream); 190062e67a26e0553dd142be622821f493df541f0c6Phil Burk } 191062e67a26e0553dd142be622821f493df541f0c6Phil Burk return NO_ERROR; 192062e67a26e0553dd142be622821f493df541f0c6Phil Burk} 193062e67a26e0553dd142be622821f493df541f0c6Phil Burk 194062e67a26e0553dd142be622821f493df541f0c6Phil Burkint AudioStreamOut::standby() 195062e67a26e0553dd142be622821f493df541f0c6Phil Burk{ 196062e67a26e0553dd142be622821f493df541f0c6Phil Burk ALOG_ASSERT(stream != NULL); 19790eea7631b07117e46ae8b84889a2baa3eee7aeaPhil Burk mRenderPosition = 0; 19890eea7631b07117e46ae8b84889a2baa3eee7aeaPhil Burk mFramesWrittenAtStandby = mFramesWritten; 199062e67a26e0553dd142be622821f493df541f0c6Phil Burk return stream->common.standby(&stream->common); 200062e67a26e0553dd142be622821f493df541f0c6Phil Burk} 201062e67a26e0553dd142be622821f493df541f0c6Phil Burk 20290eea7631b07117e46ae8b84889a2baa3eee7aeaPhil Burkssize_t AudioStreamOut::write(const void *buffer, size_t numBytes) 203062e67a26e0553dd142be622821f493df541f0c6Phil Burk{ 204062e67a26e0553dd142be622821f493df541f0c6Phil Burk ALOG_ASSERT(stream != NULL); 20590eea7631b07117e46ae8b84889a2baa3eee7aeaPhil Burk ssize_t bytesWritten = stream->write(stream, buffer, numBytes); 20690eea7631b07117e46ae8b84889a2baa3eee7aeaPhil Burk if (bytesWritten > 0 && mHalFrameSize > 0) { 20790eea7631b07117e46ae8b84889a2baa3eee7aeaPhil Burk mFramesWritten += bytesWritten / mHalFrameSize; 20890eea7631b07117e46ae8b84889a2baa3eee7aeaPhil Burk } 20990eea7631b07117e46ae8b84889a2baa3eee7aeaPhil Burk return bytesWritten; 210062e67a26e0553dd142be622821f493df541f0c6Phil Burk} 211062e67a26e0553dd142be622821f493df541f0c6Phil Burk 212062e67a26e0553dd142be622821f493df541f0c6Phil Burk} // namespace android 213