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) 3890eea7631b07117e46ae8b84889a2baa3eee7aeaPhil Burk , mHalFormatIsLinearPcm(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. 9990eea7631b07117e46ae8b84889a2baa3eee7aeaPhil Burk if (mHalFormatIsLinearPcm) { 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; 119062e67a26e0553dd142be622821f493df541f0c6Phil Burk int status = hwDev()->open_output_stream( 120062e67a26e0553dd142be622821f493df541f0c6Phil Burk hwDev(), 121062e67a26e0553dd142be622821f493df541f0c6Phil Burk handle, 122062e67a26e0553dd142be622821f493df541f0c6Phil Burk devices, 123062e67a26e0553dd142be622821f493df541f0c6Phil Burk flags, 124062e67a26e0553dd142be622821f493df541f0c6Phil Burk config, 125062e67a26e0553dd142be622821f493df541f0c6Phil Burk &outStream, 126062e67a26e0553dd142be622821f493df541f0c6Phil Burk address); 127062e67a26e0553dd142be622821f493df541f0c6Phil Burk ALOGV("AudioStreamOut::open(), HAL open_output_stream returned " 128062e67a26e0553dd142be622821f493df541f0c6Phil Burk " %p, sampleRate %d, Format %#x, " 129062e67a26e0553dd142be622821f493df541f0c6Phil Burk "channelMask %#x, status %d", 130062e67a26e0553dd142be622821f493df541f0c6Phil Burk outStream, 131062e67a26e0553dd142be622821f493df541f0c6Phil Burk config->sample_rate, 132062e67a26e0553dd142be622821f493df541f0c6Phil Burk config->format, 133062e67a26e0553dd142be622821f493df541f0c6Phil Burk config->channel_mask, 134062e67a26e0553dd142be622821f493df541f0c6Phil Burk status); 135062e67a26e0553dd142be622821f493df541f0c6Phil Burk 136062e67a26e0553dd142be622821f493df541f0c6Phil Burk if (status == NO_ERROR) { 137062e67a26e0553dd142be622821f493df541f0c6Phil Burk stream = outStream; 13890eea7631b07117e46ae8b84889a2baa3eee7aeaPhil Burk mHalFormatIsLinearPcm = audio_is_linear_pcm(config->format); 13990eea7631b07117e46ae8b84889a2baa3eee7aeaPhil Burk ALOGI("AudioStreamOut::open(), mHalFormatIsLinearPcm = %d", (int)mHalFormatIsLinearPcm); 14090eea7631b07117e46ae8b84889a2baa3eee7aeaPhil Burk mHalFrameSize = audio_stream_out_frame_size(stream); 141062e67a26e0553dd142be622821f493df541f0c6Phil Burk } 142062e67a26e0553dd142be622821f493df541f0c6Phil Burk 143062e67a26e0553dd142be622821f493df541f0c6Phil Burk return status; 144062e67a26e0553dd142be622821f493df541f0c6Phil Burk} 145062e67a26e0553dd142be622821f493df541f0c6Phil Burk 146ca5e6143740299c877d69e97f7968cd04476d32cPhil Burkaudio_format_t AudioStreamOut::getFormat() const 147062e67a26e0553dd142be622821f493df541f0c6Phil Burk{ 148ca5e6143740299c877d69e97f7968cd04476d32cPhil Burk return stream->common.get_format(&stream->common); 149ca5e6143740299c877d69e97f7968cd04476d32cPhil Burk} 150ca5e6143740299c877d69e97f7968cd04476d32cPhil Burk 151ca5e6143740299c877d69e97f7968cd04476d32cPhil Burkuint32_t AudioStreamOut::getSampleRate() const 152ca5e6143740299c877d69e97f7968cd04476d32cPhil Burk{ 153ca5e6143740299c877d69e97f7968cd04476d32cPhil Burk return stream->common.get_sample_rate(&stream->common); 154ca5e6143740299c877d69e97f7968cd04476d32cPhil Burk} 155ca5e6143740299c877d69e97f7968cd04476d32cPhil Burk 156ca5e6143740299c877d69e97f7968cd04476d32cPhil Burkaudio_channel_mask_t AudioStreamOut::getChannelMask() const 157ca5e6143740299c877d69e97f7968cd04476d32cPhil Burk{ 158ca5e6143740299c877d69e97f7968cd04476d32cPhil Burk return stream->common.get_channels(&stream->common); 159062e67a26e0553dd142be622821f493df541f0c6Phil Burk} 160062e67a26e0553dd142be622821f493df541f0c6Phil Burk 161062e67a26e0553dd142be622821f493df541f0c6Phil Burkint AudioStreamOut::flush() 162062e67a26e0553dd142be622821f493df541f0c6Phil Burk{ 163062e67a26e0553dd142be622821f493df541f0c6Phil Burk ALOG_ASSERT(stream != NULL); 16490eea7631b07117e46ae8b84889a2baa3eee7aeaPhil Burk mRenderPosition = 0; 16590eea7631b07117e46ae8b84889a2baa3eee7aeaPhil Burk mFramesWritten = 0; 16690eea7631b07117e46ae8b84889a2baa3eee7aeaPhil Burk mFramesWrittenAtStandby = 0; 167062e67a26e0553dd142be622821f493df541f0c6Phil Burk if (stream->flush != NULL) { 168062e67a26e0553dd142be622821f493df541f0c6Phil Burk return stream->flush(stream); 169062e67a26e0553dd142be622821f493df541f0c6Phil Burk } 170062e67a26e0553dd142be622821f493df541f0c6Phil Burk return NO_ERROR; 171062e67a26e0553dd142be622821f493df541f0c6Phil Burk} 172062e67a26e0553dd142be622821f493df541f0c6Phil Burk 173062e67a26e0553dd142be622821f493df541f0c6Phil Burkint AudioStreamOut::standby() 174062e67a26e0553dd142be622821f493df541f0c6Phil Burk{ 175062e67a26e0553dd142be622821f493df541f0c6Phil Burk ALOG_ASSERT(stream != NULL); 17690eea7631b07117e46ae8b84889a2baa3eee7aeaPhil Burk mRenderPosition = 0; 17790eea7631b07117e46ae8b84889a2baa3eee7aeaPhil Burk mFramesWrittenAtStandby = mFramesWritten; 178062e67a26e0553dd142be622821f493df541f0c6Phil Burk return stream->common.standby(&stream->common); 179062e67a26e0553dd142be622821f493df541f0c6Phil Burk} 180062e67a26e0553dd142be622821f493df541f0c6Phil Burk 18190eea7631b07117e46ae8b84889a2baa3eee7aeaPhil Burkssize_t AudioStreamOut::write(const void *buffer, size_t numBytes) 182062e67a26e0553dd142be622821f493df541f0c6Phil Burk{ 183062e67a26e0553dd142be622821f493df541f0c6Phil Burk ALOG_ASSERT(stream != NULL); 18490eea7631b07117e46ae8b84889a2baa3eee7aeaPhil Burk ssize_t bytesWritten = stream->write(stream, buffer, numBytes); 18590eea7631b07117e46ae8b84889a2baa3eee7aeaPhil Burk if (bytesWritten > 0 && mHalFrameSize > 0) { 18690eea7631b07117e46ae8b84889a2baa3eee7aeaPhil Burk mFramesWritten += bytesWritten / mHalFrameSize; 18790eea7631b07117e46ae8b84889a2baa3eee7aeaPhil Burk } 18890eea7631b07117e46ae8b84889a2baa3eee7aeaPhil Burk return bytesWritten; 189062e67a26e0553dd142be622821f493df541f0c6Phil Burk} 190062e67a26e0553dd142be622821f493df541f0c6Phil Burk 191062e67a26e0553dd142be622821f493df541f0c6Phil Burk} // namespace android 192