Home | History | Annotate | Download | only in legacy
      1 /*
      2  * Copyright 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 "AudioStreamLegacy"
     18 //#define LOG_NDEBUG 0
     19 #include <utils/Log.h>
     20 
     21 #include <stdint.h>
     22 #include <utils/String16.h>
     23 #include <media/AudioTrack.h>
     24 #include <aaudio/AAudio.h>
     25 
     26 #include "core/AudioStream.h"
     27 #include "legacy/AudioStreamLegacy.h"
     28 
     29 using namespace android;
     30 using namespace aaudio;
     31 
     32 AudioStreamLegacy::AudioStreamLegacy()
     33         : AudioStream(), mDeviceCallback(new StreamDeviceCallback(this)) {
     34 }
     35 
     36 AudioStreamLegacy::~AudioStreamLegacy() {
     37 }
     38 
     39 // Called from AudioTrack.cpp or AudioRecord.cpp
     40 static void AudioStreamLegacy_callback(int event, void* userData, void *info) {
     41     AudioStreamLegacy *streamLegacy = (AudioStreamLegacy *) userData;
     42     streamLegacy->processCallback(event, info);
     43 }
     44 
     45 aaudio_legacy_callback_t AudioStreamLegacy::getLegacyCallback() {
     46     return AudioStreamLegacy_callback;
     47 }
     48 
     49 // Implement FixedBlockProcessor
     50 int32_t AudioStreamLegacy::onProcessFixedBlock(uint8_t *buffer, int32_t numBytes) {
     51     int32_t frameCount = numBytes / getBytesPerFrame();
     52     // Call using the AAudio callback interface.
     53     AAudioStream_dataCallback appCallback = getDataCallbackProc();
     54     return (*appCallback)(
     55             (AAudioStream *) this,
     56             getDataCallbackUserData(),
     57             buffer,
     58             frameCount);
     59 }
     60 
     61 void AudioStreamLegacy::processCallbackCommon(aaudio_callback_operation_t opcode, void *info) {
     62     aaudio_data_callback_result_t callbackResult;
     63 
     64     if (!mCallbackEnabled.load()) {
     65         return;
     66     }
     67 
     68     switch (opcode) {
     69         case AAUDIO_CALLBACK_OPERATION_PROCESS_DATA: {
     70             if (getState() != AAUDIO_STREAM_STATE_DISCONNECTED) {
     71                 // Note that this code assumes an AudioTrack::Buffer is the same as
     72                 // AudioRecord::Buffer
     73                 // TODO define our own AudioBuffer and pass it from the subclasses.
     74                 AudioTrack::Buffer *audioBuffer = static_cast<AudioTrack::Buffer *>(info);
     75                 if (audioBuffer->frameCount == 0) return;
     76 
     77                 // If the caller specified an exact size then use a block size adapter.
     78                 if (mBlockAdapter != nullptr) {
     79                     int32_t byteCount = audioBuffer->frameCount * getBytesPerFrame();
     80                     callbackResult = mBlockAdapter->processVariableBlock(
     81                             (uint8_t *) audioBuffer->raw, byteCount);
     82                 } else {
     83                     // Call using the AAudio callback interface.
     84                     callbackResult = (*getDataCallbackProc())(
     85                             (AAudioStream *) this,
     86                             getDataCallbackUserData(),
     87                             audioBuffer->raw,
     88                             audioBuffer->frameCount
     89                             );
     90                 }
     91                 if (callbackResult == AAUDIO_CALLBACK_RESULT_CONTINUE) {
     92                     audioBuffer->size = audioBuffer->frameCount * getBytesPerFrame();
     93                     incrementClientFrameCounter(audioBuffer->frameCount);
     94                 } else {
     95                     audioBuffer->size = 0;
     96                 }
     97                 break;
     98             }
     99         }
    100         /// FALL THROUGH
    101 
    102             // Stream got rerouted so we disconnect.
    103         case AAUDIO_CALLBACK_OPERATION_DISCONNECTED: {
    104             setState(AAUDIO_STREAM_STATE_DISCONNECTED);
    105             ALOGD("processCallbackCommon() stream disconnected");
    106             if (getErrorCallbackProc() != nullptr) {
    107                 (*getErrorCallbackProc())(
    108                         (AAudioStream *) this,
    109                         getErrorCallbackUserData(),
    110                         AAUDIO_ERROR_DISCONNECTED
    111                         );
    112             }
    113             mCallbackEnabled.store(false);
    114         }
    115             break;
    116 
    117         default:
    118             break;
    119     }
    120 }
    121 
    122 aaudio_result_t AudioStreamLegacy::getBestTimestamp(clockid_t clockId,
    123                                                    int64_t *framePosition,
    124                                                    int64_t *timeNanoseconds,
    125                                                    ExtendedTimestamp *extendedTimestamp) {
    126     int timebase;
    127     switch (clockId) {
    128         case CLOCK_BOOTTIME:
    129             timebase = ExtendedTimestamp::TIMEBASE_BOOTTIME;
    130             break;
    131         case CLOCK_MONOTONIC:
    132             timebase = ExtendedTimestamp::TIMEBASE_MONOTONIC;
    133             break;
    134         default:
    135             ALOGE("getTimestamp() - Unrecognized clock type %d", (int) clockId);
    136             return AAUDIO_ERROR_ILLEGAL_ARGUMENT;
    137             break;
    138     }
    139     status_t status = extendedTimestamp->getBestTimestamp(framePosition, timeNanoseconds, timebase);
    140     return AAudioConvert_androidToAAudioResult(status);
    141 }
    142 
    143 void AudioStreamLegacy::onAudioDeviceUpdate(audio_port_handle_t deviceId)
    144 {
    145     ALOGD("onAudioDeviceUpdate() deviceId %d", (int)deviceId);
    146     if (getDeviceId() != AAUDIO_UNSPECIFIED && getDeviceId() != deviceId &&
    147             getState() != AAUDIO_STREAM_STATE_DISCONNECTED) {
    148         setState(AAUDIO_STREAM_STATE_DISCONNECTED);
    149         // if we have a data callback and the stream is active, send the error callback from
    150         // data callback thread when it sees the DISCONNECTED state
    151         if (!isDataCallbackActive() && getErrorCallbackProc() != nullptr) {
    152             (*getErrorCallbackProc())(
    153                     (AAudioStream *) this,
    154                     getErrorCallbackUserData(),
    155                     AAUDIO_ERROR_DISCONNECTED
    156                     );
    157         }
    158     }
    159     setDeviceId(deviceId);
    160 }
    161