1 /* 2 * Copyright (C) 2017 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #define LOG_TAG (mInService ? "AudioStreamInternalCapture_Service" \ 18 : "AudioStreamInternalCapture_Client") 19 //#define LOG_NDEBUG 0 20 #include <utils/Log.h> 21 22 #include <algorithm> 23 #include <audio_utils/primitives.h> 24 #include <aaudio/AAudio.h> 25 26 #include "client/AudioStreamInternalCapture.h" 27 #include "utility/AudioClock.h" 28 29 #define ATRACE_TAG ATRACE_TAG_AUDIO 30 #include <utils/Trace.h> 31 32 using android::WrappingBuffer; 33 34 using namespace aaudio; 35 36 AudioStreamInternalCapture::AudioStreamInternalCapture(AAudioServiceInterface &serviceInterface, 37 bool inService) 38 : AudioStreamInternal(serviceInterface, inService) { 39 40 } 41 42 AudioStreamInternalCapture::~AudioStreamInternalCapture() {} 43 44 void AudioStreamInternalCapture::advanceClientToMatchServerPosition() { 45 int64_t readCounter = mAudioEndpoint.getDataReadCounter(); 46 int64_t writeCounter = mAudioEndpoint.getDataWriteCounter(); 47 48 // Bump offset so caller does not see the retrograde motion in getFramesRead(). 49 int64_t offset = readCounter - writeCounter; 50 mFramesOffsetFromService += offset; 51 ALOGD("advanceClientToMatchServerPosition() readN = %lld, writeN = %lld, offset = %lld", 52 (long long)readCounter, (long long)writeCounter, (long long)mFramesOffsetFromService); 53 54 // Force readCounter to match writeCounter. 55 // This is because we cannot change the write counter in the hardware. 56 mAudioEndpoint.setDataReadCounter(writeCounter); 57 } 58 59 // Write the data, block if needed and timeoutMillis > 0 60 aaudio_result_t AudioStreamInternalCapture::read(void *buffer, int32_t numFrames, 61 int64_t timeoutNanoseconds) 62 { 63 return processData(buffer, numFrames, timeoutNanoseconds); 64 } 65 66 // Read as much data as we can without blocking. 67 aaudio_result_t AudioStreamInternalCapture::processDataNow(void *buffer, int32_t numFrames, 68 int64_t currentNanoTime, int64_t *wakeTimePtr) { 69 aaudio_result_t result = processCommands(); 70 if (result != AAUDIO_OK) { 71 return result; 72 } 73 74 const char *traceName = "aaRdNow"; 75 ATRACE_BEGIN(traceName); 76 77 if (mClockModel.isStarting()) { 78 // Still haven't got any timestamps from server. 79 // Keep waiting until we get some valid timestamps then start writing to the 80 // current buffer position. 81 ALOGD("processDataNow() wait for valid timestamps"); 82 // Sleep very briefly and hope we get a timestamp soon. 83 *wakeTimePtr = currentNanoTime + (2000 * AAUDIO_NANOS_PER_MICROSECOND); 84 ATRACE_END(); 85 return 0; 86 } 87 // If we have gotten this far then we have at least one timestamp from server. 88 89 if (mAudioEndpoint.isFreeRunning()) { 90 //ALOGD("AudioStreamInternalCapture::processDataNow() - update remote counter"); 91 // Update data queue based on the timing model. 92 int64_t estimatedRemoteCounter = mClockModel.convertTimeToPosition(currentNanoTime); 93 // TODO refactor, maybe use setRemoteCounter() 94 mAudioEndpoint.setDataWriteCounter(estimatedRemoteCounter); 95 } 96 97 // This code assumes that we have already received valid timestamps. 98 if (mNeedCatchUp.isRequested()) { 99 // Catch an MMAP pointer that is already advancing. 100 // This will avoid initial underruns caused by a slow cold start. 101 advanceClientToMatchServerPosition(); 102 mNeedCatchUp.acknowledge(); 103 } 104 105 // If the write index passed the read index then consider it an overrun. 106 // For shared streams, the xRunCount is passed up from the service. 107 if (mAudioEndpoint.isFreeRunning() && mAudioEndpoint.getEmptyFramesAvailable() < 0) { 108 mXRunCount++; 109 if (ATRACE_ENABLED()) { 110 ATRACE_INT("aaOverRuns", mXRunCount); 111 } 112 } 113 114 // Read some data from the buffer. 115 //ALOGD("AudioStreamInternalCapture::processDataNow() - readNowWithConversion(%d)", numFrames); 116 int32_t framesProcessed = readNowWithConversion(buffer, numFrames); 117 //ALOGD("AudioStreamInternalCapture::processDataNow() - tried to read %d frames, read %d", 118 // numFrames, framesProcessed); 119 if (ATRACE_ENABLED()) { 120 ATRACE_INT("aaRead", framesProcessed); 121 } 122 123 // Calculate an ideal time to wake up. 124 if (wakeTimePtr != nullptr && framesProcessed >= 0) { 125 // By default wake up a few milliseconds from now. // TODO review 126 int64_t wakeTime = currentNanoTime + (1 * AAUDIO_NANOS_PER_MILLISECOND); 127 aaudio_stream_state_t state = getState(); 128 //ALOGD("AudioStreamInternalCapture::processDataNow() - wakeTime based on %s", 129 // AAudio_convertStreamStateToText(state)); 130 switch (state) { 131 case AAUDIO_STREAM_STATE_OPEN: 132 case AAUDIO_STREAM_STATE_STARTING: 133 break; 134 case AAUDIO_STREAM_STATE_STARTED: 135 { 136 // When do we expect the next write burst to occur? 137 138 // Calculate frame position based off of the readCounter because 139 // the writeCounter might have just advanced in the background, 140 // causing us to sleep until a later burst. 141 int64_t nextPosition = mAudioEndpoint.getDataReadCounter() + mFramesPerBurst; 142 wakeTime = mClockModel.convertPositionToTime(nextPosition); 143 } 144 break; 145 default: 146 break; 147 } 148 *wakeTimePtr = wakeTime; 149 150 } 151 152 ATRACE_END(); 153 return framesProcessed; 154 } 155 156 aaudio_result_t AudioStreamInternalCapture::readNowWithConversion(void *buffer, 157 int32_t numFrames) { 158 // ALOGD("readNowWithConversion(%p, %d)", 159 // buffer, numFrames); 160 WrappingBuffer wrappingBuffer; 161 uint8_t *destination = (uint8_t *) buffer; 162 int32_t framesLeft = numFrames; 163 164 mAudioEndpoint.getFullFramesAvailable(&wrappingBuffer); 165 166 // Read data in one or two parts. 167 for (int partIndex = 0; framesLeft > 0 && partIndex < WrappingBuffer::SIZE; partIndex++) { 168 int32_t framesToProcess = framesLeft; 169 const int32_t framesAvailable = wrappingBuffer.numFrames[partIndex]; 170 if (framesAvailable <= 0) break; 171 172 if (framesToProcess > framesAvailable) { 173 framesToProcess = framesAvailable; 174 } 175 176 const int32_t numBytes = getBytesPerFrame() * framesToProcess; 177 const int32_t numSamples = framesToProcess * getSamplesPerFrame(); 178 179 const audio_format_t sourceFormat = getDeviceFormat(); 180 const audio_format_t destinationFormat = getFormat(); 181 // TODO factor this out into a utility function 182 if (sourceFormat == destinationFormat) { 183 memcpy(destination, wrappingBuffer.data[partIndex], numBytes); 184 } else if (sourceFormat == AUDIO_FORMAT_PCM_16_BIT 185 && destinationFormat == AUDIO_FORMAT_PCM_FLOAT) { 186 memcpy_to_float_from_i16( 187 (float *) destination, 188 (const int16_t *) wrappingBuffer.data[partIndex], 189 numSamples); 190 } else if (sourceFormat == AUDIO_FORMAT_PCM_FLOAT 191 && destinationFormat == AUDIO_FORMAT_PCM_16_BIT) { 192 memcpy_to_i16_from_float( 193 (int16_t *) destination, 194 (const float *) wrappingBuffer.data[partIndex], 195 numSamples); 196 } else { 197 ALOGE("%s() - Format conversion not supported! audio_format_t source = %u, dest = %u", 198 __func__, sourceFormat, destinationFormat); 199 return AAUDIO_ERROR_INVALID_FORMAT; 200 } 201 destination += numBytes; 202 framesLeft -= framesToProcess; 203 } 204 205 int32_t framesProcessed = numFrames - framesLeft; 206 mAudioEndpoint.advanceReadIndex(framesProcessed); 207 208 //ALOGD("readNowWithConversion() returns %d", framesProcessed); 209 return framesProcessed; 210 } 211 212 int64_t AudioStreamInternalCapture::getFramesWritten() { 213 const int64_t framesWrittenHardware = isClockModelInControl() 214 ? mClockModel.convertTimeToPosition(AudioClock::getNanoseconds()) 215 : mAudioEndpoint.getDataWriteCounter(); 216 // Add service offset and prevent retrograde motion. 217 mLastFramesWritten = std::max(mLastFramesWritten, 218 framesWrittenHardware + mFramesOffsetFromService); 219 return mLastFramesWritten; 220 } 221 222 int64_t AudioStreamInternalCapture::getFramesRead() { 223 int64_t frames = mAudioEndpoint.getDataReadCounter() + mFramesOffsetFromService; 224 //ALOGD("getFramesRead() returns %lld", (long long)frames); 225 return frames; 226 } 227 228 // Read data from the stream and pass it to the callback for processing. 229 void *AudioStreamInternalCapture::callbackLoop() { 230 aaudio_result_t result = AAUDIO_OK; 231 aaudio_data_callback_result_t callbackResult = AAUDIO_CALLBACK_RESULT_CONTINUE; 232 if (!isDataCallbackSet()) return NULL; 233 234 // result might be a frame count 235 while (mCallbackEnabled.load() && isActive() && (result >= 0)) { 236 237 // Read audio data from stream. 238 int64_t timeoutNanos = calculateReasonableTimeout(mCallbackFrames); 239 240 // This is a BLOCKING READ! 241 result = read(mCallbackBuffer, mCallbackFrames, timeoutNanos); 242 if ((result != mCallbackFrames)) { 243 ALOGE("callbackLoop: read() returned %d", result); 244 if (result >= 0) { 245 // Only read some of the frames requested. Must have timed out. 246 result = AAUDIO_ERROR_TIMEOUT; 247 } 248 maybeCallErrorCallback(result); 249 break; 250 } 251 252 // Call application using the AAudio callback interface. 253 callbackResult = maybeCallDataCallback(mCallbackBuffer, mCallbackFrames); 254 255 if (callbackResult == AAUDIO_CALLBACK_RESULT_STOP) { 256 ALOGD("%s(): callback returned AAUDIO_CALLBACK_RESULT_STOP", __func__); 257 result = systemStopFromCallback(); 258 break; 259 } 260 } 261 262 ALOGD("callbackLoop() exiting, result = %d, isActive() = %d", 263 result, (int) isActive()); 264 return NULL; 265 } 266