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