1 /* 2 ** 3 ** Copyright 2015, The Android Open Source Project 4 ** 5 ** Licensed under the Apache License, Version 2.0 (the "License"); 6 ** you may not use this file except in compliance with the License. 7 ** You may obtain a copy of the License at 8 ** 9 ** http://www.apache.org/licenses/LICENSE-2.0 10 ** 11 ** Unless required by applicable law or agreed to in writing, software 12 ** distributed under the License is distributed on an "AS IS" BASIS, 13 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 ** See the License for the specific language governing permissions and 15 ** limitations under the License. 16 */ 17 18 #define LOG_TAG "AudioFlinger" 19 //#define LOG_NDEBUG 0 20 21 #include <hardware/audio.h> 22 #include <utils/Log.h> 23 24 #include "AudioHwDevice.h" 25 #include "AudioStreamOut.h" 26 27 namespace android { 28 29 // ---------------------------------------------------------------------------- 30 AudioStreamOut::AudioStreamOut(AudioHwDevice *dev, audio_output_flags_t flags) 31 : audioHwDev(dev) 32 , stream(NULL) 33 , flags(flags) 34 , mFramesWritten(0) 35 , mFramesWrittenAtStandby(0) 36 , mRenderPosition(0) 37 , mRateMultiplier(1) 38 , mHalFormatIsLinearPcm(false) 39 , mHalFrameSize(0) 40 { 41 } 42 43 audio_hw_device_t *AudioStreamOut::hwDev() const 44 { 45 return audioHwDev->hwDevice(); 46 } 47 48 status_t AudioStreamOut::getRenderPosition(uint64_t *frames) 49 { 50 if (stream == NULL) { 51 return NO_INIT; 52 } 53 54 uint32_t halPosition = 0; 55 status_t status = stream->get_render_position(stream, &halPosition); 56 if (status != NO_ERROR) { 57 return status; 58 } 59 60 // Maintain a 64-bit render position using the 32-bit result from the HAL. 61 // This delta calculation relies on the arithmetic overflow behavior 62 // of integers. For example (100 - 0xFFFFFFF0) = 116. 63 uint32_t truncatedPosition = (uint32_t)mRenderPosition; 64 int32_t deltaHalPosition = (int32_t)(halPosition - truncatedPosition); 65 if (deltaHalPosition > 0) { 66 mRenderPosition += deltaHalPosition; 67 } 68 // Scale from HAL sample rate to application rate. 69 *frames = mRenderPosition / mRateMultiplier; 70 71 return status; 72 } 73 74 // return bottom 32-bits of the render position 75 status_t AudioStreamOut::getRenderPosition(uint32_t *frames) 76 { 77 uint64_t position64 = 0; 78 status_t status = getRenderPosition(&position64); 79 if (status == NO_ERROR) { 80 *frames = (uint32_t)position64; 81 } 82 return status; 83 } 84 85 status_t AudioStreamOut::getPresentationPosition(uint64_t *frames, struct timespec *timestamp) 86 { 87 if (stream == NULL) { 88 return NO_INIT; 89 } 90 91 uint64_t halPosition = 0; 92 status_t status = stream->get_presentation_position(stream, &halPosition, timestamp); 93 if (status != NO_ERROR) { 94 return status; 95 } 96 97 // Adjust for standby using HAL rate frames. 98 // Only apply this correction if the HAL is getting PCM frames. 99 if (mHalFormatIsLinearPcm) { 100 uint64_t adjustedPosition = (halPosition <= mFramesWrittenAtStandby) ? 101 0 : (halPosition - mFramesWrittenAtStandby); 102 // Scale from HAL sample rate to application rate. 103 *frames = adjustedPosition / mRateMultiplier; 104 } else { 105 // For offloaded MP3 and other compressed formats. 106 *frames = halPosition; 107 } 108 109 return status; 110 } 111 112 status_t AudioStreamOut::open( 113 audio_io_handle_t handle, 114 audio_devices_t devices, 115 struct audio_config *config, 116 const char *address) 117 { 118 audio_stream_out_t *outStream; 119 int status = hwDev()->open_output_stream( 120 hwDev(), 121 handle, 122 devices, 123 flags, 124 config, 125 &outStream, 126 address); 127 ALOGV("AudioStreamOut::open(), HAL open_output_stream returned " 128 " %p, sampleRate %d, Format %#x, " 129 "channelMask %#x, status %d", 130 outStream, 131 config->sample_rate, 132 config->format, 133 config->channel_mask, 134 status); 135 136 if (status == NO_ERROR) { 137 stream = outStream; 138 mHalFormatIsLinearPcm = audio_is_linear_pcm(config->format); 139 ALOGI("AudioStreamOut::open(), mHalFormatIsLinearPcm = %d", (int)mHalFormatIsLinearPcm); 140 mHalFrameSize = audio_stream_out_frame_size(stream); 141 } 142 143 return status; 144 } 145 146 audio_format_t AudioStreamOut::getFormat() const 147 { 148 return stream->common.get_format(&stream->common); 149 } 150 151 uint32_t AudioStreamOut::getSampleRate() const 152 { 153 return stream->common.get_sample_rate(&stream->common); 154 } 155 156 audio_channel_mask_t AudioStreamOut::getChannelMask() const 157 { 158 return stream->common.get_channels(&stream->common); 159 } 160 161 int AudioStreamOut::flush() 162 { 163 ALOG_ASSERT(stream != NULL); 164 mRenderPosition = 0; 165 mFramesWritten = 0; 166 mFramesWrittenAtStandby = 0; 167 if (stream->flush != NULL) { 168 return stream->flush(stream); 169 } 170 return NO_ERROR; 171 } 172 173 int AudioStreamOut::standby() 174 { 175 ALOG_ASSERT(stream != NULL); 176 mRenderPosition = 0; 177 mFramesWrittenAtStandby = mFramesWritten; 178 return stream->common.standby(&stream->common); 179 } 180 181 ssize_t AudioStreamOut::write(const void *buffer, size_t numBytes) 182 { 183 ALOG_ASSERT(stream != NULL); 184 ssize_t bytesWritten = stream->write(stream, buffer, numBytes); 185 if (bytesWritten > 0 && mHalFrameSize > 0) { 186 mFramesWritten += bytesWritten / mHalFrameSize; 187 } 188 return bytesWritten; 189 } 190 191 } // namespace android 192