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