AudioStreamInternalCapture.cpp revision fd34a9310659aa53e9e10d6826651577a75f6447
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 ? "AAudioService" : "AAudio")
18//#define LOG_NDEBUG 0
19#include <utils/Log.h>
20
21#include <algorithm>
22#include <aaudio/AAudio.h>
23
24#include "client/AudioStreamInternalCapture.h"
25#include "utility/AudioClock.h"
26
27#define ATRACE_TAG ATRACE_TAG_AUDIO
28#include <utils/Trace.h>
29
30using android::WrappingBuffer;
31
32using namespace aaudio;
33
34AudioStreamInternalCapture::AudioStreamInternalCapture(AAudioServiceInterface  &serviceInterface,
35                                                 bool inService)
36    : AudioStreamInternal(serviceInterface, inService) {
37
38}
39
40AudioStreamInternalCapture::~AudioStreamInternalCapture() {}
41
42// Write the data, block if needed and timeoutMillis > 0
43aaudio_result_t AudioStreamInternalCapture::read(void *buffer, int32_t numFrames,
44                                               int64_t timeoutNanoseconds)
45{
46    return processData(buffer, numFrames, timeoutNanoseconds);
47}
48
49// Read as much data as we can without blocking.
50aaudio_result_t AudioStreamInternalCapture::processDataNow(void *buffer, int32_t numFrames,
51                                                  int64_t currentNanoTime, int64_t *wakeTimePtr) {
52    aaudio_result_t result = processCommands();
53    if (result != AAUDIO_OK) {
54        return result;
55    }
56
57    const char *traceName = "aaRdNow";
58    ATRACE_BEGIN(traceName);
59
60    if (mAudioEndpoint.isFreeRunning()) {
61        //ALOGD("AudioStreamInternalCapture::processDataNow() - update remote counter");
62        // Update data queue based on the timing model.
63        int64_t estimatedRemoteCounter = mClockModel.convertTimeToPosition(currentNanoTime);
64        // TODO refactor, maybe use setRemoteCounter()
65        mAudioEndpoint.setDataWriteCounter(estimatedRemoteCounter);
66    }
67
68    // If the write index passed the read index then consider it an overrun.
69    if (mAudioEndpoint.getEmptyFramesAvailable() < 0) {
70        mXRunCount++;
71        if (ATRACE_ENABLED()) {
72            ATRACE_INT("aaOverRuns", mXRunCount);
73        }
74    }
75
76    // Read some data from the buffer.
77    //ALOGD("AudioStreamInternalCapture::processDataNow() - readNowWithConversion(%d)", numFrames);
78    int32_t framesProcessed = readNowWithConversion(buffer, numFrames);
79    //ALOGD("AudioStreamInternalCapture::processDataNow() - tried to read %d frames, read %d",
80    //    numFrames, framesProcessed);
81    if (ATRACE_ENABLED()) {
82        ATRACE_INT("aaRead", framesProcessed);
83    }
84
85    // Calculate an ideal time to wake up.
86    if (wakeTimePtr != nullptr && framesProcessed >= 0) {
87        // By default wake up a few milliseconds from now.  // TODO review
88        int64_t wakeTime = currentNanoTime + (1 * AAUDIO_NANOS_PER_MILLISECOND);
89        aaudio_stream_state_t state = getState();
90        //ALOGD("AudioStreamInternalCapture::processDataNow() - wakeTime based on %s",
91        //      AAudio_convertStreamStateToText(state));
92        switch (state) {
93            case AAUDIO_STREAM_STATE_OPEN:
94            case AAUDIO_STREAM_STATE_STARTING:
95                break;
96            case AAUDIO_STREAM_STATE_STARTED:
97            {
98                // When do we expect the next write burst to occur?
99
100                // Calculate frame position based off of the readCounter because
101                // the writeCounter might have just advanced in the background,
102                // causing us to sleep until a later burst.
103                int64_t nextReadPosition = mAudioEndpoint.getDataReadCounter() + mFramesPerBurst;
104                wakeTime = mClockModel.convertPositionToTime(nextReadPosition);
105            }
106                break;
107            default:
108                break;
109        }
110        *wakeTimePtr = wakeTime;
111
112    }
113
114    ATRACE_END();
115    return framesProcessed;
116}
117
118aaudio_result_t AudioStreamInternalCapture::readNowWithConversion(void *buffer,
119                                                                int32_t numFrames) {
120    // ALOGD("AudioStreamInternalCapture::readNowWithConversion(%p, %d)",
121    //              buffer, numFrames);
122    WrappingBuffer wrappingBuffer;
123    uint8_t *destination = (uint8_t *) buffer;
124    int32_t framesLeft = numFrames;
125
126    mAudioEndpoint.getFullFramesAvailable(&wrappingBuffer);
127
128    // Read data in one or two parts.
129    for (int partIndex = 0; framesLeft > 0 && partIndex < WrappingBuffer::SIZE; partIndex++) {
130        int32_t framesToProcess = framesLeft;
131        int32_t framesAvailable = wrappingBuffer.numFrames[partIndex];
132        if (framesAvailable <= 0) break;
133
134        if (framesToProcess > framesAvailable) {
135            framesToProcess = framesAvailable;
136        }
137
138        int32_t numBytes = getBytesPerFrame() * framesToProcess;
139        int32_t numSamples = framesToProcess * getSamplesPerFrame();
140
141        // TODO factor this out into a utility function
142        if (mDeviceFormat == getFormat()) {
143            memcpy(destination, wrappingBuffer.data[partIndex], numBytes);
144        } else if (mDeviceFormat == AAUDIO_FORMAT_PCM_I16
145                   && getFormat() == AAUDIO_FORMAT_PCM_FLOAT) {
146            AAudioConvert_pcm16ToFloat(
147                    (const int16_t *) wrappingBuffer.data[partIndex],
148                    (float *) destination,
149                    numSamples,
150                    1.0f);
151        } else if (mDeviceFormat == AAUDIO_FORMAT_PCM_FLOAT
152                   && getFormat() == AAUDIO_FORMAT_PCM_I16) {
153            AAudioConvert_floatToPcm16(
154                    (const float *) wrappingBuffer.data[partIndex],
155                    (int16_t *) destination,
156                    numSamples,
157                    1.0f);
158        } else {
159            ALOGE("Format conversion not supported!");
160            return AAUDIO_ERROR_INVALID_FORMAT;
161        }
162        destination += numBytes;
163        framesLeft -= framesToProcess;
164    }
165
166    int32_t framesProcessed = numFrames - framesLeft;
167    mAudioEndpoint.advanceReadIndex(framesProcessed);
168
169    //ALOGD("AudioStreamInternalCapture::readNowWithConversion() returns %d", framesProcessed);
170    return framesProcessed;
171}
172
173int64_t AudioStreamInternalCapture::getFramesWritten() {
174    int64_t framesWrittenHardware;
175    if (isActive()) {
176        framesWrittenHardware = mClockModel.convertTimeToPosition(AudioClock::getNanoseconds());
177    } else {
178        framesWrittenHardware = mAudioEndpoint.getDataWriteCounter();
179    }
180    // Prevent retrograde motion.
181    mLastFramesWritten = std::max(mLastFramesWritten,
182                                  framesWrittenHardware + mFramesOffsetFromService);
183    //ALOGD("AudioStreamInternalCapture::getFramesWritten() returns %lld",
184    //      (long long)mLastFramesWritten);
185    return mLastFramesWritten;
186}
187
188int64_t AudioStreamInternalCapture::getFramesRead() {
189    int64_t frames = mAudioEndpoint.getDataWriteCounter()
190                               + mFramesOffsetFromService;
191    //ALOGD("AudioStreamInternalCapture::getFramesRead() returns %lld", (long long)frames);
192    return frames;
193}
194
195// Read data from the stream and pass it to the callback for processing.
196void *AudioStreamInternalCapture::callbackLoop() {
197    aaudio_result_t result = AAUDIO_OK;
198    aaudio_data_callback_result_t callbackResult = AAUDIO_CALLBACK_RESULT_CONTINUE;
199    AAudioStream_dataCallback appCallback = getDataCallbackProc();
200    if (appCallback == nullptr) return NULL;
201
202    // result might be a frame count
203    while (mCallbackEnabled.load() && isActive() && (result >= 0)) {
204
205        // Read audio data from stream.
206        int64_t timeoutNanos = calculateReasonableTimeout(mCallbackFrames);
207
208        // This is a BLOCKING READ!
209        result = read(mCallbackBuffer, mCallbackFrames, timeoutNanos);
210        if ((result != mCallbackFrames)) {
211            ALOGE("AudioStreamInternalCapture(): callbackLoop: read() returned %d", result);
212            if (result >= 0) {
213                // Only read some of the frames requested. Must have timed out.
214                result = AAUDIO_ERROR_TIMEOUT;
215            }
216            AAudioStream_errorCallback errorCallback = getErrorCallbackProc();
217            if (errorCallback != nullptr) {
218                (*errorCallback)(
219                        (AAudioStream *) this,
220                        getErrorCallbackUserData(),
221                        result);
222            }
223            break;
224        }
225
226        // Call application using the AAudio callback interface.
227        callbackResult = (*appCallback)(
228                (AAudioStream *) this,
229                getDataCallbackUserData(),
230                mCallbackBuffer,
231                mCallbackFrames);
232
233        if (callbackResult == AAUDIO_CALLBACK_RESULT_STOP) {
234            ALOGD("AudioStreamInternalCapture(): callback returned AAUDIO_CALLBACK_RESULT_STOP");
235            break;
236        }
237    }
238
239    ALOGD("AudioStreamInternalCapture(): callbackLoop() exiting, result = %d, isActive() = %d",
240          result, (int) isActive());
241    return NULL;
242}
243