Home | History | Annotate | Download | only in libnbaio
      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 "SourceAudioBufferProvider"
     18 //#define LOG_NDEBUG 0
     19 
     20 #include <utils/Log.h>
     21 #include <media/nbaio/SourceAudioBufferProvider.h>
     22 
     23 namespace android {
     24 
     25 SourceAudioBufferProvider::SourceAudioBufferProvider(const sp<NBAIO_Source>& source) :
     26     mSource(source),
     27     // mFrameSize below
     28     mAllocated(NULL), mSize(0), mOffset(0), mRemaining(0), mGetCount(0), mFramesReleased(0)
     29 {
     30     ALOG_ASSERT(source != 0);
     31 
     32     // negotiate with source
     33     NBAIO_Format counterOffers[1];
     34     size_t numCounterOffers = 1;
     35     ssize_t index = source->negotiate(NULL, 0, counterOffers, numCounterOffers);
     36     ALOG_ASSERT(index == (ssize_t) NEGOTIATE && numCounterOffers > 0);
     37     numCounterOffers = 0;
     38     index = source->negotiate(counterOffers, 1, NULL, numCounterOffers);
     39     ALOG_ASSERT(index == 0);
     40     mFrameSize = Format_frameSize(source->format());
     41 }
     42 
     43 SourceAudioBufferProvider::~SourceAudioBufferProvider()
     44 {
     45     free(mAllocated);
     46 }
     47 
     48 status_t SourceAudioBufferProvider::getNextBuffer(Buffer *buffer)
     49 {
     50     ALOG_ASSERT(buffer != NULL && buffer->frameCount > 0 && mGetCount == 0);
     51     // any leftover data available?
     52     if (mRemaining > 0) {
     53         ALOG_ASSERT(mOffset + mRemaining <= mSize);
     54         if (mRemaining < buffer->frameCount) {
     55             buffer->frameCount = mRemaining;
     56         }
     57         buffer->raw = (char *) mAllocated + (mOffset * mFrameSize);
     58         mGetCount = buffer->frameCount;
     59         return OK;
     60     }
     61     // do we need to reallocate?
     62     if (buffer->frameCount > mSize) {
     63         free(mAllocated);
     64         // Android convention is to _not_ check the return value of malloc and friends.
     65         // But in this case the calloc() can also fail due to integer overflow,
     66         // so we check and recover.
     67         mAllocated = calloc(buffer->frameCount, mFrameSize);
     68         if (mAllocated == NULL) {
     69             mSize = 0;
     70             goto fail;
     71         }
     72         mSize = buffer->frameCount;
     73     }
     74     {
     75         // read from source
     76         ssize_t actual = mSource->read(mAllocated, buffer->frameCount);
     77         if (actual > 0) {
     78             ALOG_ASSERT((size_t) actual <= buffer->frameCount);
     79             mOffset = 0;
     80             mRemaining = actual;
     81             buffer->raw = mAllocated;
     82             buffer->frameCount = actual;
     83             mGetCount = actual;
     84             return OK;
     85         }
     86     }
     87 fail:
     88     buffer->raw = NULL;
     89     buffer->frameCount = 0;
     90     mGetCount = 0;
     91     return NOT_ENOUGH_DATA;
     92 }
     93 
     94 void SourceAudioBufferProvider::releaseBuffer(Buffer *buffer)
     95 {
     96     ALOG_ASSERT((buffer != NULL) &&
     97             (buffer->raw == (char *) mAllocated + (mOffset * mFrameSize)) &&
     98             (buffer->frameCount <= mGetCount) &&
     99             (mGetCount <= mRemaining) &&
    100             (mOffset + mRemaining <= mSize));
    101     mOffset += buffer->frameCount;
    102     mRemaining -= buffer->frameCount;
    103     mFramesReleased += buffer->frameCount;
    104     buffer->raw = NULL;
    105     buffer->frameCount = 0;
    106     mGetCount = 0;
    107 }
    108 
    109 size_t SourceAudioBufferProvider::framesReady() const
    110 {
    111     ssize_t avail = mSource->availableToRead();
    112     return avail < 0 ? 0 : (size_t) avail;
    113 }
    114 
    115 int64_t SourceAudioBufferProvider::framesReleased() const
    116 {
    117     return mFramesReleased;
    118 }
    119 
    120 void SourceAudioBufferProvider::onTimestamp(const ExtendedTimestamp &timestamp)
    121 {
    122     mSource->onTimestamp(timestamp);
    123 }
    124 
    125 }   // namespace android
    126