Home | History | Annotate | Download | only in audioflinger
      1 /*
      2  * Copyright (C) 2012 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 "AudioBufferProviderSource"
     18 //#define LOG_NDEBUG 0
     19 
     20 #include <cutils/compiler.h>
     21 #include <utils/Log.h>
     22 #include "AudioBufferProviderSource.h"
     23 
     24 namespace android {
     25 
     26 AudioBufferProviderSource::AudioBufferProviderSource(AudioBufferProvider *provider,
     27                                                      NBAIO_Format format) :
     28     NBAIO_Source(format), mProvider(provider), mConsumed(0)
     29 {
     30     ALOG_ASSERT(provider != NULL);
     31     ALOG_ASSERT(format != Format_Invalid);
     32 }
     33 
     34 AudioBufferProviderSource::~AudioBufferProviderSource()
     35 {
     36     if (mBuffer.raw != NULL) {
     37         mProvider->releaseBuffer(&mBuffer);
     38     }
     39 }
     40 
     41 ssize_t AudioBufferProviderSource::availableToRead()
     42 {
     43     if (CC_UNLIKELY(!mNegotiated)) {
     44         return NEGOTIATE;
     45     }
     46     return mBuffer.raw != NULL ? mBuffer.frameCount - mConsumed : 0;
     47 }
     48 
     49 ssize_t AudioBufferProviderSource::read(void *buffer, size_t count)
     50 {
     51     if (CC_UNLIKELY(!mNegotiated)) {
     52         return NEGOTIATE;
     53     }
     54     if (CC_UNLIKELY(mBuffer.raw == NULL)) {
     55         mBuffer.frameCount = count;
     56         status_t status = mProvider->getNextBuffer(&mBuffer, AudioBufferProvider::kInvalidPTS);
     57         if (status != OK) {
     58             return status == NOT_ENOUGH_DATA ? (ssize_t) WOULD_BLOCK : (ssize_t) status;
     59         }
     60         ALOG_ASSERT(mBuffer.raw != NULL);
     61         // mConsumed is 0 either from constructor or after releaseBuffer()
     62     }
     63     size_t available = mBuffer.frameCount - mConsumed;
     64     if (CC_UNLIKELY(count > available)) {
     65         count = available;
     66     }
     67     // count could be zero, either because count was zero on entry or
     68     // available is zero, but both are unlikely so don't check for that
     69     memcpy(buffer, (char *) mBuffer.raw + (mConsumed << mBitShift), count << mBitShift);
     70     if (CC_UNLIKELY((mConsumed += count) >= mBuffer.frameCount)) {
     71         mProvider->releaseBuffer(&mBuffer);
     72         mBuffer.raw = NULL;
     73         mConsumed = 0;
     74     }
     75     mFramesRead += count;
     76     // For better responsiveness with large values of count,
     77     // return a short count rather than continuing with next buffer.
     78     // This gives the caller a chance to interpolate other actions.
     79     return count;
     80 }
     81 
     82 ssize_t AudioBufferProviderSource::readVia(readVia_t via, size_t total, void *user, size_t block)
     83 {
     84     if (CC_UNLIKELY(!mNegotiated)) {
     85         return NEGOTIATE;
     86     }
     87     if (CC_UNLIKELY(block == 0)) {
     88         block = ~0;
     89     }
     90     for (size_t accumulator = 0; ; ) {
     91         ALOG_ASSERT(accumulator <= total);
     92         size_t count = total - accumulator;
     93         if (CC_UNLIKELY(count == 0)) {
     94             return accumulator;
     95         }
     96         if (CC_LIKELY(count > block)) {
     97             count = block;
     98         }
     99         // 1 <= count <= block
    100         if (CC_UNLIKELY(mBuffer.raw == NULL)) {
    101             mBuffer.frameCount = count;
    102             status_t status = mProvider->getNextBuffer(&mBuffer, AudioBufferProvider::kInvalidPTS);
    103             if (CC_LIKELY(status == OK)) {
    104                 ALOG_ASSERT(mBuffer.raw != NULL && mBuffer.frameCount <= count);
    105                 // mConsumed is 0 either from constructor or after releaseBuffer()
    106                 continue;
    107             }
    108             // FIXME simplify logic - does the initial count and block checks again for no reason;
    109             //       don't you just want to fall through to the size_t available line?
    110             if (CC_LIKELY(status == NOT_ENOUGH_DATA)) {
    111                 status = WOULD_BLOCK;
    112             }
    113             return accumulator > 0 ? accumulator : (ssize_t) status;
    114         }
    115         size_t available = mBuffer.frameCount - mConsumed;
    116         if (CC_UNLIKELY(count > available)) {
    117             count = available;
    118         }
    119         if (CC_LIKELY(count > 0)) {
    120             ssize_t ret = via(user, (char *) mBuffer.raw + (mConsumed << mBitShift), count);
    121             if (CC_UNLIKELY(ret <= 0)) {
    122                 if (CC_LIKELY(accumulator > 0)) {
    123                     return accumulator;
    124                 }
    125                 return ret;
    126             }
    127             ALOG_ASSERT((size_t) ret <= count);
    128             mFramesRead += ret;
    129             accumulator += ret;
    130             if (CC_LIKELY((mConsumed += ret) < mBuffer.frameCount)) {
    131                 continue;
    132             }
    133         }
    134         mProvider->releaseBuffer(&mBuffer);
    135         mBuffer.raw = NULL;
    136         mConsumed = 0;
    137         // don't get next buffer until we really need it
    138     }
    139 }
    140 
    141 }   // namespace android
    142